17453645fSAndriy Voskoboinyk /* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ 27453645fSAndriy Voskoboinyk 37453645fSAndriy Voskoboinyk /*- 47453645fSAndriy Voskoboinyk * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr> 57453645fSAndriy Voskoboinyk * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org> 67453645fSAndriy Voskoboinyk * Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org> 77453645fSAndriy Voskoboinyk * 87453645fSAndriy Voskoboinyk * Permission to use, copy, modify, and distribute this software for any 97453645fSAndriy Voskoboinyk * purpose with or without fee is hereby granted, provided that the above 107453645fSAndriy Voskoboinyk * copyright notice and this permission notice appear in all copies. 117453645fSAndriy Voskoboinyk * 127453645fSAndriy Voskoboinyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 137453645fSAndriy Voskoboinyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 147453645fSAndriy Voskoboinyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 157453645fSAndriy Voskoboinyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 167453645fSAndriy Voskoboinyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 177453645fSAndriy Voskoboinyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 187453645fSAndriy Voskoboinyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 197453645fSAndriy Voskoboinyk */ 207453645fSAndriy Voskoboinyk 217453645fSAndriy Voskoboinyk #include <sys/cdefs.h> 227453645fSAndriy Voskoboinyk #include "opt_wlan.h" 237453645fSAndriy Voskoboinyk 247453645fSAndriy Voskoboinyk #include <sys/param.h> 257453645fSAndriy Voskoboinyk #include <sys/lock.h> 267453645fSAndriy Voskoboinyk #include <sys/mutex.h> 277453645fSAndriy Voskoboinyk #include <sys/mbuf.h> 287453645fSAndriy Voskoboinyk #include <sys/kernel.h> 297453645fSAndriy Voskoboinyk #include <sys/socket.h> 307453645fSAndriy Voskoboinyk #include <sys/systm.h> 317453645fSAndriy Voskoboinyk #include <sys/malloc.h> 327453645fSAndriy Voskoboinyk #include <sys/queue.h> 337453645fSAndriy Voskoboinyk #include <sys/taskqueue.h> 347453645fSAndriy Voskoboinyk #include <sys/bus.h> 357453645fSAndriy Voskoboinyk #include <sys/endian.h> 367453645fSAndriy Voskoboinyk 377453645fSAndriy Voskoboinyk #include <net/if.h> 387453645fSAndriy Voskoboinyk #include <net/ethernet.h> 397453645fSAndriy Voskoboinyk #include <net/if_media.h> 407453645fSAndriy Voskoboinyk 417453645fSAndriy Voskoboinyk #include <net80211/ieee80211_var.h> 427453645fSAndriy Voskoboinyk #include <net80211/ieee80211_radiotap.h> 437453645fSAndriy Voskoboinyk 447453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwnreg.h> 457453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwnvar.h> 467453645fSAndriy Voskoboinyk 477453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwn_cam.h> 487453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwn_debug.h> 497453645fSAndriy Voskoboinyk #include <dev/rtwn/if_rtwn_task.h> 507453645fSAndriy Voskoboinyk 517453645fSAndriy Voskoboinyk #include <dev/rtwn/rtl8192c/r92c_reg.h> 527453645fSAndriy Voskoboinyk 537453645fSAndriy Voskoboinyk void 547453645fSAndriy Voskoboinyk rtwn_init_cam(struct rtwn_softc *sc) 557453645fSAndriy Voskoboinyk { 567453645fSAndriy Voskoboinyk /* Invalidate all CAM entries. */ 577453645fSAndriy Voskoboinyk rtwn_write_4(sc, R92C_CAMCMD, 587453645fSAndriy Voskoboinyk R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR); 597453645fSAndriy Voskoboinyk } 607453645fSAndriy Voskoboinyk 617453645fSAndriy Voskoboinyk static int 627453645fSAndriy Voskoboinyk rtwn_cam_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data) 637453645fSAndriy Voskoboinyk { 647453645fSAndriy Voskoboinyk int error; 657453645fSAndriy Voskoboinyk 667453645fSAndriy Voskoboinyk error = rtwn_write_4(sc, R92C_CAMWRITE, data); 677453645fSAndriy Voskoboinyk if (error != 0) 687453645fSAndriy Voskoboinyk return (error); 697453645fSAndriy Voskoboinyk error = rtwn_write_4(sc, R92C_CAMCMD, 707453645fSAndriy Voskoboinyk R92C_CAMCMD_POLLING | R92C_CAMCMD_WRITE | 717453645fSAndriy Voskoboinyk SM(R92C_CAMCMD_ADDR, addr)); 727453645fSAndriy Voskoboinyk 737453645fSAndriy Voskoboinyk return (error); 747453645fSAndriy Voskoboinyk } 757453645fSAndriy Voskoboinyk 767453645fSAndriy Voskoboinyk void 777453645fSAndriy Voskoboinyk rtwn_init_seccfg(struct rtwn_softc *sc) 787453645fSAndriy Voskoboinyk { 797453645fSAndriy Voskoboinyk uint16_t seccfg; 807453645fSAndriy Voskoboinyk 817453645fSAndriy Voskoboinyk /* Select decryption / encryption flags. */ 827453645fSAndriy Voskoboinyk seccfg = 0; 837453645fSAndriy Voskoboinyk switch (sc->sc_hwcrypto) { 847453645fSAndriy Voskoboinyk case RTWN_CRYPTO_SW: 857453645fSAndriy Voskoboinyk break; /* nothing to do */ 867453645fSAndriy Voskoboinyk case RTWN_CRYPTO_PAIR: 877453645fSAndriy Voskoboinyk /* NB: TXUCKEY_DEF / RXUCKEY_DEF are required for RTL8192C */ 887453645fSAndriy Voskoboinyk seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF | 897453645fSAndriy Voskoboinyk R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA | 907453645fSAndriy Voskoboinyk R92C_SECCFG_MC_SRCH_DIS; 917453645fSAndriy Voskoboinyk break; 927453645fSAndriy Voskoboinyk case RTWN_CRYPTO_FULL: 937453645fSAndriy Voskoboinyk seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF | 947453645fSAndriy Voskoboinyk R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA | 957453645fSAndriy Voskoboinyk R92C_SECCFG_TXBCKEY_DEF | R92C_SECCFG_RXBCKEY_DEF; 967453645fSAndriy Voskoboinyk break; 977453645fSAndriy Voskoboinyk default: 987453645fSAndriy Voskoboinyk KASSERT(0, ("%s: case %d was not handled\n", __func__, 997453645fSAndriy Voskoboinyk sc->sc_hwcrypto)); 1007453645fSAndriy Voskoboinyk break; 1017453645fSAndriy Voskoboinyk } 1027453645fSAndriy Voskoboinyk 1037453645fSAndriy Voskoboinyk RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, "%s: seccfg %04X, hwcrypto %d\n", 1047453645fSAndriy Voskoboinyk __func__, seccfg, sc->sc_hwcrypto); 1057453645fSAndriy Voskoboinyk 1067453645fSAndriy Voskoboinyk rtwn_write_2(sc, R92C_SECCFG, seccfg); 1077453645fSAndriy Voskoboinyk } 1087453645fSAndriy Voskoboinyk 1097453645fSAndriy Voskoboinyk int 1107453645fSAndriy Voskoboinyk rtwn_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k, 1117453645fSAndriy Voskoboinyk ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) 1127453645fSAndriy Voskoboinyk { 1137453645fSAndriy Voskoboinyk struct rtwn_softc *sc = vap->iv_ic->ic_softc; 1147453645fSAndriy Voskoboinyk int i, start; 1157453645fSAndriy Voskoboinyk 116*2589197aSAdrian Chadd if (ieee80211_is_key_global(vap, k)) { 1174a19d712SAndriy Voskoboinyk *keyix = ieee80211_crypto_get_key_wepidx(vap, k); 1187453645fSAndriy Voskoboinyk if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) 1197453645fSAndriy Voskoboinyk k->wk_flags |= IEEE80211_KEY_SWCRYPT; 1207453645fSAndriy Voskoboinyk else { 1217453645fSAndriy Voskoboinyk RTWN_LOCK(sc); 1227453645fSAndriy Voskoboinyk if (isset(sc->keys_bmap, *keyix)) { 1237453645fSAndriy Voskoboinyk device_printf(sc->sc_dev, 1247453645fSAndriy Voskoboinyk "%s: group key slot %d is already used!\n", 1257453645fSAndriy Voskoboinyk __func__, *keyix); 1267453645fSAndriy Voskoboinyk /* XXX recover? */ 1277453645fSAndriy Voskoboinyk RTWN_UNLOCK(sc); 1287453645fSAndriy Voskoboinyk return (0); 1297453645fSAndriy Voskoboinyk } 1307453645fSAndriy Voskoboinyk 1317453645fSAndriy Voskoboinyk setbit(sc->keys_bmap, *keyix); 1327453645fSAndriy Voskoboinyk RTWN_UNLOCK(sc); 1337453645fSAndriy Voskoboinyk } 1347453645fSAndriy Voskoboinyk 1357453645fSAndriy Voskoboinyk goto end; 1367453645fSAndriy Voskoboinyk } 1377453645fSAndriy Voskoboinyk 1387453645fSAndriy Voskoboinyk start = sc->cam_entry_limit; 1397453645fSAndriy Voskoboinyk switch (sc->sc_hwcrypto) { 1407453645fSAndriy Voskoboinyk case RTWN_CRYPTO_SW: 1417453645fSAndriy Voskoboinyk k->wk_flags |= IEEE80211_KEY_SWCRYPT; 1427453645fSAndriy Voskoboinyk *keyix = 0; 1437453645fSAndriy Voskoboinyk goto end; 1447453645fSAndriy Voskoboinyk case RTWN_CRYPTO_PAIR: 1457453645fSAndriy Voskoboinyk /* all slots for pairwise keys. */ 1467453645fSAndriy Voskoboinyk start = 0; 1477453645fSAndriy Voskoboinyk RTWN_LOCK(sc); 1487453645fSAndriy Voskoboinyk if (sc->sc_flags & RTWN_FLAG_CAM_FIXED) 1497453645fSAndriy Voskoboinyk start = 4; 1507453645fSAndriy Voskoboinyk RTWN_UNLOCK(sc); 1517453645fSAndriy Voskoboinyk break; 1527453645fSAndriy Voskoboinyk case RTWN_CRYPTO_FULL: 1537453645fSAndriy Voskoboinyk /* first 4 - for group keys, others for pairwise. */ 1547453645fSAndriy Voskoboinyk start = 4; 1557453645fSAndriy Voskoboinyk break; 1567453645fSAndriy Voskoboinyk default: 1577453645fSAndriy Voskoboinyk KASSERT(0, ("%s: case %d was not handled!\n", 1587453645fSAndriy Voskoboinyk __func__, sc->sc_hwcrypto)); 1597453645fSAndriy Voskoboinyk break; 1607453645fSAndriy Voskoboinyk } 1617453645fSAndriy Voskoboinyk 1627453645fSAndriy Voskoboinyk RTWN_LOCK(sc); 1637453645fSAndriy Voskoboinyk for (i = start; i < sc->cam_entry_limit; i++) { 1647453645fSAndriy Voskoboinyk if (isclr(sc->keys_bmap, i)) { 1657453645fSAndriy Voskoboinyk setbit(sc->keys_bmap, i); 1667453645fSAndriy Voskoboinyk *keyix = i; 1677453645fSAndriy Voskoboinyk break; 1687453645fSAndriy Voskoboinyk } 1697453645fSAndriy Voskoboinyk } 1707453645fSAndriy Voskoboinyk RTWN_UNLOCK(sc); 1717453645fSAndriy Voskoboinyk if (i == sc->cam_entry_limit) { 1727453645fSAndriy Voskoboinyk /* XXX check and remove keys with the same MAC address */ 1737453645fSAndriy Voskoboinyk k->wk_flags |= IEEE80211_KEY_SWCRYPT; 1747453645fSAndriy Voskoboinyk *keyix = 0; 1757453645fSAndriy Voskoboinyk } 1767453645fSAndriy Voskoboinyk 1777453645fSAndriy Voskoboinyk end: 1787453645fSAndriy Voskoboinyk *rxkeyix = *keyix; 1797453645fSAndriy Voskoboinyk return (1); 1807453645fSAndriy Voskoboinyk } 1817453645fSAndriy Voskoboinyk 1827453645fSAndriy Voskoboinyk static int 1837453645fSAndriy Voskoboinyk rtwn_key_set_cb0(struct rtwn_softc *sc, const struct ieee80211_key *k) 1847453645fSAndriy Voskoboinyk { 1857453645fSAndriy Voskoboinyk uint8_t algo, keyid; 1867453645fSAndriy Voskoboinyk int i, error; 1877453645fSAndriy Voskoboinyk 1887453645fSAndriy Voskoboinyk if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL && 1897453645fSAndriy Voskoboinyk k->wk_keyix < IEEE80211_WEP_NKID) 1907453645fSAndriy Voskoboinyk keyid = k->wk_keyix; 1917453645fSAndriy Voskoboinyk else 1927453645fSAndriy Voskoboinyk keyid = 0; 1937453645fSAndriy Voskoboinyk 1947453645fSAndriy Voskoboinyk /* Map net80211 cipher to HW crypto algorithm. */ 1957453645fSAndriy Voskoboinyk switch (k->wk_cipher->ic_cipher) { 1967453645fSAndriy Voskoboinyk case IEEE80211_CIPHER_WEP: 1977453645fSAndriy Voskoboinyk if (k->wk_keylen < 8) 1987453645fSAndriy Voskoboinyk algo = R92C_CAM_ALGO_WEP40; 1997453645fSAndriy Voskoboinyk else 2007453645fSAndriy Voskoboinyk algo = R92C_CAM_ALGO_WEP104; 2017453645fSAndriy Voskoboinyk break; 2027453645fSAndriy Voskoboinyk case IEEE80211_CIPHER_TKIP: 2037453645fSAndriy Voskoboinyk algo = R92C_CAM_ALGO_TKIP; 2047453645fSAndriy Voskoboinyk break; 2057453645fSAndriy Voskoboinyk case IEEE80211_CIPHER_AES_CCM: 2067453645fSAndriy Voskoboinyk algo = R92C_CAM_ALGO_AES; 2077453645fSAndriy Voskoboinyk break; 2087453645fSAndriy Voskoboinyk default: 2097453645fSAndriy Voskoboinyk device_printf(sc->sc_dev, "%s: unknown cipher %u\n", 2107453645fSAndriy Voskoboinyk __func__, k->wk_cipher->ic_cipher); 2117453645fSAndriy Voskoboinyk return (EINVAL); 2127453645fSAndriy Voskoboinyk } 2137453645fSAndriy Voskoboinyk 2147453645fSAndriy Voskoboinyk RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, 2157453645fSAndriy Voskoboinyk "%s: keyix %u, keyid %u, algo %u/%u, flags %04X, len %u, " 2167453645fSAndriy Voskoboinyk "macaddr %s\n", __func__, k->wk_keyix, keyid, 2177453645fSAndriy Voskoboinyk k->wk_cipher->ic_cipher, algo, k->wk_flags, k->wk_keylen, 2187453645fSAndriy Voskoboinyk ether_sprintf(k->wk_macaddr)); 2197453645fSAndriy Voskoboinyk 2207453645fSAndriy Voskoboinyk /* Clear high bits. */ 2217453645fSAndriy Voskoboinyk rtwn_cam_write(sc, R92C_CAM_CTL6(k->wk_keyix), 0); 2227453645fSAndriy Voskoboinyk rtwn_cam_write(sc, R92C_CAM_CTL7(k->wk_keyix), 0); 2237453645fSAndriy Voskoboinyk 2247453645fSAndriy Voskoboinyk /* Write key. */ 2257453645fSAndriy Voskoboinyk for (i = 0; i < 4; i++) { 2267453645fSAndriy Voskoboinyk error = rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), 2277453645fSAndriy Voskoboinyk le32dec(&k->wk_key[i * 4])); 2287453645fSAndriy Voskoboinyk if (error != 0) 2297453645fSAndriy Voskoboinyk goto fail; 2307453645fSAndriy Voskoboinyk } 2317453645fSAndriy Voskoboinyk 2327453645fSAndriy Voskoboinyk /* Write CTL0 last since that will validate the CAM entry. */ 2337453645fSAndriy Voskoboinyk error = rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), 2347453645fSAndriy Voskoboinyk le32dec(&k->wk_macaddr[2])); 2357453645fSAndriy Voskoboinyk if (error != 0) 2367453645fSAndriy Voskoboinyk goto fail; 2377453645fSAndriy Voskoboinyk error = rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), 2387453645fSAndriy Voskoboinyk SM(R92C_CAM_ALGO, algo) | 2397453645fSAndriy Voskoboinyk SM(R92C_CAM_KEYID, keyid) | 2407453645fSAndriy Voskoboinyk SM(R92C_CAM_MACLO, le16dec(&k->wk_macaddr[0])) | 2417453645fSAndriy Voskoboinyk R92C_CAM_VALID); 2427453645fSAndriy Voskoboinyk if (error != 0) 2437453645fSAndriy Voskoboinyk goto fail; 2447453645fSAndriy Voskoboinyk 2457453645fSAndriy Voskoboinyk return (0); 2467453645fSAndriy Voskoboinyk 2477453645fSAndriy Voskoboinyk fail: 2487453645fSAndriy Voskoboinyk device_printf(sc->sc_dev, "%s fails, error %d\n", __func__, error); 2497453645fSAndriy Voskoboinyk return (error); 2507453645fSAndriy Voskoboinyk } 2517453645fSAndriy Voskoboinyk 2527453645fSAndriy Voskoboinyk static void 2537453645fSAndriy Voskoboinyk rtwn_key_set_cb(struct rtwn_softc *sc, union sec_param *data) 2547453645fSAndriy Voskoboinyk { 2557453645fSAndriy Voskoboinyk const struct ieee80211_key *k = &data->key; 2567453645fSAndriy Voskoboinyk 2577453645fSAndriy Voskoboinyk (void) rtwn_key_set_cb0(sc, k); 2587453645fSAndriy Voskoboinyk } 2597453645fSAndriy Voskoboinyk 2607453645fSAndriy Voskoboinyk int 2617453645fSAndriy Voskoboinyk rtwn_init_static_keys(struct rtwn_softc *sc, struct rtwn_vap *rvp) 2627453645fSAndriy Voskoboinyk { 2637453645fSAndriy Voskoboinyk int i, error; 2647453645fSAndriy Voskoboinyk 2657453645fSAndriy Voskoboinyk if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) 2667453645fSAndriy Voskoboinyk return (0); /* nothing to do */ 2677453645fSAndriy Voskoboinyk 2687453645fSAndriy Voskoboinyk for (i = 0; i < IEEE80211_WEP_NKID; i++) { 2697453645fSAndriy Voskoboinyk const struct ieee80211_key *k = rvp->keys[i]; 2707453645fSAndriy Voskoboinyk if (k != NULL) { 2717453645fSAndriy Voskoboinyk error = rtwn_key_set_cb0(sc, k); 2727453645fSAndriy Voskoboinyk if (error != 0) 2737453645fSAndriy Voskoboinyk return (error); 2747453645fSAndriy Voskoboinyk } 2757453645fSAndriy Voskoboinyk } 2767453645fSAndriy Voskoboinyk 2777453645fSAndriy Voskoboinyk return (0); 2787453645fSAndriy Voskoboinyk } 2797453645fSAndriy Voskoboinyk 2807453645fSAndriy Voskoboinyk static void 2817453645fSAndriy Voskoboinyk rtwn_key_del_cb(struct rtwn_softc *sc, union sec_param *data) 2827453645fSAndriy Voskoboinyk { 2837453645fSAndriy Voskoboinyk struct ieee80211_key *k = &data->key; 2847453645fSAndriy Voskoboinyk int i; 2857453645fSAndriy Voskoboinyk 2867453645fSAndriy Voskoboinyk RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, 2877453645fSAndriy Voskoboinyk "%s: keyix %u, flags %04X, macaddr %s\n", __func__, 2887453645fSAndriy Voskoboinyk k->wk_keyix, k->wk_flags, ether_sprintf(k->wk_macaddr)); 2897453645fSAndriy Voskoboinyk 2907453645fSAndriy Voskoboinyk rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), 0); 2917453645fSAndriy Voskoboinyk rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), 0); 2927453645fSAndriy Voskoboinyk 2937453645fSAndriy Voskoboinyk /* Clear key. */ 2947453645fSAndriy Voskoboinyk for (i = 0; i < 4; i++) 2957453645fSAndriy Voskoboinyk rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), 0); 2967453645fSAndriy Voskoboinyk clrbit(sc->keys_bmap, k->wk_keyix); 2977453645fSAndriy Voskoboinyk } 2987453645fSAndriy Voskoboinyk 2997453645fSAndriy Voskoboinyk static int 3007453645fSAndriy Voskoboinyk rtwn_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k, 3017453645fSAndriy Voskoboinyk int set) 3027453645fSAndriy Voskoboinyk { 3037453645fSAndriy Voskoboinyk struct rtwn_softc *sc = vap->iv_ic->ic_softc; 3047453645fSAndriy Voskoboinyk 3057453645fSAndriy Voskoboinyk if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { 3067453645fSAndriy Voskoboinyk /* Not for us. */ 3077453645fSAndriy Voskoboinyk return (1); 3087453645fSAndriy Voskoboinyk } 3097453645fSAndriy Voskoboinyk 310*2589197aSAdrian Chadd if (ieee80211_is_key_global(vap, k)) { 3117453645fSAndriy Voskoboinyk if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL) { 3127453645fSAndriy Voskoboinyk struct rtwn_vap *rvp = RTWN_VAP(vap); 3137453645fSAndriy Voskoboinyk 3147453645fSAndriy Voskoboinyk RTWN_LOCK(sc); 3157453645fSAndriy Voskoboinyk rvp->keys[k->wk_keyix] = (set ? k : NULL); 3167453645fSAndriy Voskoboinyk if ((sc->sc_flags & RTWN_RUNNING) == 0) { 3177453645fSAndriy Voskoboinyk if (!set) 3187453645fSAndriy Voskoboinyk clrbit(sc->keys_bmap, k->wk_keyix); 3197453645fSAndriy Voskoboinyk RTWN_UNLOCK(sc); 3207453645fSAndriy Voskoboinyk return (1); 3217453645fSAndriy Voskoboinyk } 3227453645fSAndriy Voskoboinyk RTWN_UNLOCK(sc); 3237453645fSAndriy Voskoboinyk } 3247453645fSAndriy Voskoboinyk } 3257453645fSAndriy Voskoboinyk 3267453645fSAndriy Voskoboinyk return (!rtwn_cmd_sleepable(sc, k, sizeof(*k), 3277453645fSAndriy Voskoboinyk set ? rtwn_key_set_cb : rtwn_key_del_cb)); 3287453645fSAndriy Voskoboinyk } 3297453645fSAndriy Voskoboinyk 3307453645fSAndriy Voskoboinyk int 3317453645fSAndriy Voskoboinyk rtwn_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k) 3327453645fSAndriy Voskoboinyk { 3337453645fSAndriy Voskoboinyk return (rtwn_process_key(vap, k, 1)); 3347453645fSAndriy Voskoboinyk } 3357453645fSAndriy Voskoboinyk 3367453645fSAndriy Voskoboinyk int 3377453645fSAndriy Voskoboinyk rtwn_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) 3387453645fSAndriy Voskoboinyk { 3397453645fSAndriy Voskoboinyk return (rtwn_process_key(vap, k, 0)); 3407453645fSAndriy Voskoboinyk } 341