Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142776431
D8706.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D8706.diff
View Options
Index: head/sys/dev/usb/wlan/if_rsu.c
===================================================================
--- head/sys/dev/usb/wlan/if_rsu.c
+++ head/sys/dev/usb/wlan/if_rsu.c
@@ -22,8 +22,8 @@
* Driver for Realtek RTL8188SU/RTL8191SU/RTL8192SU.
*
* TODO:
- * o h/w crypto
- * o hostap / ibss / mesh
+ * o tx a-mpdu
+ * o monitor / hostap / ibss / mesh
* o power-save operation
*/
@@ -102,6 +102,7 @@
#define RSU_DEBUG_FW 0x00000100
#define RSU_DEBUG_FWDBG 0x00000200
#define RSU_DEBUG_AMPDU 0x00000400
+#define RSU_DEBUG_KEY 0x00000800
static const STRUCT_USB_HOST_ID rsu_devs[] = {
#define RSU_HT_NOT_SUPPORTED 0
@@ -202,10 +203,25 @@
static void rsu_calib_task(void *, int);
static void rsu_tx_task(void *, int);
static int rsu_newstate(struct ieee80211vap *, enum ieee80211_state, int);
-#ifdef notyet
-static void rsu_set_key(struct rsu_softc *, const struct ieee80211_key *);
-static void rsu_delete_key(struct rsu_softc *, const struct ieee80211_key *);
-#endif
+static int rsu_key_alloc(struct ieee80211vap *, struct ieee80211_key *,
+ ieee80211_keyix *, ieee80211_keyix *);
+static int rsu_process_key(struct ieee80211vap *,
+ const struct ieee80211_key *, int);
+static int rsu_key_set(struct ieee80211vap *,
+ const struct ieee80211_key *);
+static int rsu_key_delete(struct ieee80211vap *,
+ const struct ieee80211_key *);
+static int rsu_cam_read(struct rsu_softc *, uint8_t, uint32_t *);
+static void rsu_cam_write(struct rsu_softc *, uint8_t, uint32_t);
+static int rsu_key_check(struct rsu_softc *, ieee80211_keyix, int);
+static uint8_t rsu_crypto_mode(struct rsu_softc *, u_int, int);
+static int rsu_set_key_group(struct rsu_softc *,
+ const struct ieee80211_key *);
+static int rsu_set_key_pair(struct rsu_softc *,
+ const struct ieee80211_key *);
+static int rsu_reinit_static_keys(struct rsu_softc *);
+static int rsu_delete_key(struct rsu_softc *sc, ieee80211_keyix);
+static void rsu_delete_key_pair_cb(void *, int);
static int rsu_site_survey(struct rsu_softc *,
struct ieee80211_scan_ssid *);
static int rsu_join_bss(struct rsu_softc *, struct ieee80211_node *);
@@ -437,8 +453,10 @@
mtx_init(&sc->sc_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK,
MTX_DEF);
+ RSU_DELKEY_BMAP_LOCK_INIT(sc);
TIMEOUT_TASK_INIT(taskqueue_thread, &sc->calib_task, 0,
rsu_calib_task, sc);
+ TASK_INIT(&sc->del_key_task, 0, rsu_delete_key_pair_cb, sc);
TASK_INIT(&sc->tx_task, 0, rsu_tx_task, sc);
mbufq_init(&sc->sc_snd, ifqmaxlen);
@@ -524,6 +542,11 @@
IEEE80211_C_SHSLOT | /* Short slot time supported. */
IEEE80211_C_WPA; /* WPA/RSN. */
+ ic->ic_cryptocaps =
+ IEEE80211_CRYPTO_WEP |
+ IEEE80211_CRYPTO_TKIP |
+ IEEE80211_CRYPTO_AES_CCM;
+
/* Check if HT support is present. */
if (sc->sc_ht) {
device_printf(sc->sc_dev, "%s: enabling 11n\n", __func__);
@@ -608,8 +631,10 @@
ieee80211_ifdetach(ic);
taskqueue_drain_timeout(taskqueue_thread, &sc->calib_task);
+ taskqueue_drain(taskqueue_thread, &sc->del_key_task);
taskqueue_drain(taskqueue_thread, &sc->tx_task);
+ RSU_DELKEY_BMAP_LOCK_DESTROY(sc);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -662,6 +687,9 @@
/* override state transition machine */
uvp->newstate = vap->iv_newstate;
vap->iv_newstate = rsu_newstate;
+ vap->iv_key_alloc = rsu_key_alloc;
+ vap->iv_key_set = rsu_key_set;
+ vap->iv_key_delete = rsu_key_delete;
/* Limits from the r92su driver */
vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_16;
@@ -1335,12 +1363,20 @@
RSU_LOCK(sc);
/* Stop calibration. */
sc->sc_calibrating = 0;
+
+ /* Pause Tx for AC queues. */
+ rsu_write_1(sc, R92S_TXPAUSE, R92S_TXPAUSE_AC);
+ usb_pause_mtx(&sc->sc_mtx, USB_MS_TO_TICKS(10));
+
RSU_UNLOCK(sc);
taskqueue_drain_timeout(taskqueue_thread, &sc->calib_task);
taskqueue_drain(taskqueue_thread, &sc->tx_task);
- /* Disassociate from our current BSS. */
RSU_LOCK(sc);
+ /* Disassociate from our current BSS. */
rsu_disconnect(sc);
+ /* Reinstall static keys. */
+ if (sc->sc_running)
+ rsu_reinit_static_keys(sc);
} else
RSU_LOCK(sc);
switch (nstate) {
@@ -1358,6 +1394,9 @@
}
break;
case IEEE80211_S_RUN:
+ /* Flush all AC queues. */
+ rsu_write_1(sc, R92S_TXPAUSE, 0);
+
ni = ieee80211_ref_node(vap->iv_bss);
rs = &ni->ni_rates;
/* Indicate highest supported rate. */
@@ -1380,46 +1419,365 @@
return (uvp->newstate(vap, nstate, arg));
}
-#ifdef notyet
+static int
+rsu_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
+ ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
+{
+ struct rsu_softc *sc = vap->iv_ic->ic_softc;
+ int is_checked = 0;
+
+ if (&vap->iv_nw_keys[0] <= k &&
+ k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
+ *keyix = k - vap->iv_nw_keys;
+ } else {
+ if (vap->iv_opmode != IEEE80211_M_STA) {
+ *keyix = 0;
+ /* TODO: obtain keyix from node id */
+ is_checked = 1;
+ k->wk_flags |= IEEE80211_KEY_SWCRYPT;
+ } else
+ *keyix = R92S_MACID_BSS;
+ }
+
+ if (!is_checked) {
+ RSU_LOCK(sc);
+ if (isset(sc->keys_bmap, *keyix)) {
+ device_printf(sc->sc_dev,
+ "%s: key slot %d is already used!\n",
+ __func__, *keyix);
+ RSU_UNLOCK(sc);
+ return (0);
+ }
+ setbit(sc->keys_bmap, *keyix);
+ RSU_UNLOCK(sc);
+ }
+
+ *rxkeyix = *keyix;
+
+ return (1);
+}
+
+static int
+rsu_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k,
+ int set)
+{
+ struct rsu_softc *sc = vap->iv_ic->ic_softc;
+ int ret;
+
+ if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
+ /* Not for us. */
+ return (1);
+ }
+
+ /* Handle group keys. */
+ if (&vap->iv_nw_keys[0] <= k &&
+ k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
+ KASSERT(k->wk_keyix < nitems(sc->group_keys),
+ ("keyix %d > %d\n", k->wk_keyix, nitems(sc->group_keys)));
+
+ RSU_LOCK(sc);
+ sc->group_keys[k->wk_keyix] = (set ? k : NULL);
+ if (!sc->sc_running) {
+ /* Static keys will be set during device startup. */
+ RSU_UNLOCK(sc);
+ return (1);
+ }
+
+ if (set)
+ ret = rsu_set_key_group(sc, k);
+ else
+ ret = rsu_delete_key(sc, k->wk_keyix);
+ RSU_UNLOCK(sc);
+
+ return (!ret);
+ }
+
+ if (set) {
+ /* wait for pending key removal */
+ taskqueue_drain(taskqueue_thread, &sc->del_key_task);
+
+ RSU_LOCK(sc);
+ ret = rsu_set_key_pair(sc, k);
+ RSU_UNLOCK(sc);
+ } else {
+ RSU_DELKEY_BMAP_LOCK(sc);
+ setbit(sc->free_keys_bmap, k->wk_keyix);
+ RSU_DELKEY_BMAP_UNLOCK(sc);
+
+ /* workaround ieee80211_node_delucastkey() locking */
+ taskqueue_enqueue(taskqueue_thread, &sc->del_key_task);
+ ret = 0; /* fake success */
+ }
+
+ return (!ret);
+}
+
+static int
+rsu_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
+{
+ return (rsu_process_key(vap, k, 1));
+}
+
+static int
+rsu_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
+{
+ return (rsu_process_key(vap, k, 0));
+}
+
+static int
+rsu_cam_read(struct rsu_softc *sc, uint8_t addr, uint32_t *val)
+{
+ int ntries;
+
+ rsu_write_4(sc, R92S_CAMCMD,
+ R92S_CAMCMD_POLLING | SM(R92S_CAMCMD_ADDR, addr));
+ for (ntries = 0; ntries < 10; ntries++) {
+ if (!(rsu_read_4(sc, R92S_CAMCMD) & R92S_CAMCMD_POLLING))
+ break;
+
+ usb_pause_mtx(&sc->sc_mtx, USB_MS_TO_TICKS(1));
+ }
+ if (ntries == 10) {
+ device_printf(sc->sc_dev,
+ "%s: cannot read CAM entry at address %02X\n",
+ __func__, addr);
+ return (ETIMEDOUT);
+ }
+
+ *val = rsu_read_4(sc, R92S_CAMREAD);
+
+ return (0);
+}
+
static void
-rsu_set_key(struct rsu_softc *sc, const struct ieee80211_key *k)
+rsu_cam_write(struct rsu_softc *sc, uint8_t addr, uint32_t data)
{
- struct r92s_fw_cmd_set_key key;
- memset(&key, 0, sizeof(key));
- /* Map net80211 cipher to HW crypto algorithm. */
- switch (k->wk_cipher->ic_cipher) {
+ rsu_write_4(sc, R92S_CAMWRITE, data);
+ rsu_write_4(sc, R92S_CAMCMD,
+ R92S_CAMCMD_POLLING | R92S_CAMCMD_WRITE |
+ SM(R92S_CAMCMD_ADDR, addr));
+}
+
+static int
+rsu_key_check(struct rsu_softc *sc, ieee80211_keyix keyix, int is_valid)
+{
+ uint32_t val;
+ int error, ntries;
+
+ for (ntries = 0; ntries < 20; ntries++) {
+ usb_pause_mtx(&sc->sc_mtx, USB_MS_TO_TICKS(1));
+
+ error = rsu_cam_read(sc, R92S_CAM_CTL0(keyix), &val);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: cannot check key status!\n", __func__);
+ return (error);
+ }
+ if (((val & R92S_CAM_VALID) == 0) ^ is_valid)
+ break;
+ }
+ if (ntries == 20) {
+ device_printf(sc->sc_dev,
+ "%s: key %d is %s marked as valid, rejecting request\n",
+ __func__, keyix, is_valid ? "not" : "still");
+ return (EIO);
+ }
+
+ return (0);
+}
+
+/*
+ * Map net80211 cipher to RTL8712 security mode.
+ */
+static uint8_t
+rsu_crypto_mode(struct rsu_softc *sc, u_int cipher, int keylen)
+{
+ switch (cipher) {
case IEEE80211_CIPHER_WEP:
- if (k->wk_keylen < 8)
- key.algo = R92S_KEY_ALGO_WEP40;
- else
- key.algo = R92S_KEY_ALGO_WEP104;
- break;
+ return keylen < 8 ? R92S_KEY_ALGO_WEP40 : R92S_KEY_ALGO_WEP104;
case IEEE80211_CIPHER_TKIP:
- key.algo = R92S_KEY_ALGO_TKIP;
- break;
+ return R92S_KEY_ALGO_TKIP;
case IEEE80211_CIPHER_AES_CCM:
- key.algo = R92S_KEY_ALGO_AES;
- break;
+ return R92S_KEY_ALGO_AES;
default:
- return;
+ device_printf(sc->sc_dev, "unknown cipher %d\n", cipher);
+ return R92S_KEY_ALGO_INVALID;
}
- key.id = k->wk_keyix;
+}
+
+static int
+rsu_set_key_group(struct rsu_softc *sc, const struct ieee80211_key *k)
+{
+ struct r92s_fw_cmd_set_key key;
+ uint8_t algo;
+ int error;
+
+ RSU_ASSERT_LOCKED(sc);
+
+ /* Map net80211 cipher to HW crypto algorithm. */
+ algo = rsu_crypto_mode(sc, k->wk_cipher->ic_cipher, k->wk_keylen);
+ if (algo == R92S_KEY_ALGO_INVALID)
+ return (EINVAL);
+
+ memset(&key, 0, sizeof(key));
+ key.algo = algo;
+ key.cam_id = k->wk_keyix;
key.grpkey = (k->wk_flags & IEEE80211_KEY_GROUP) != 0;
memcpy(key.key, k->wk_key, MIN(k->wk_keylen, sizeof(key.key)));
- (void)rsu_fw_cmd(sc, R92S_CMD_SET_KEY, &key, sizeof(key));
+
+ RSU_DPRINTF(sc, RSU_DEBUG_KEY | RSU_DEBUG_FWCMD,
+ "%s: keyix %u, group %u, algo %u/%u, flags %04X, len %u, "
+ "macaddr %s\n", __func__, key.cam_id, key.grpkey,
+ k->wk_cipher->ic_cipher, key.algo, k->wk_flags, k->wk_keylen,
+ ether_sprintf(k->wk_macaddr));
+
+ error = rsu_fw_cmd(sc, R92S_CMD_SET_KEY, &key, sizeof(key));
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: cannot send firmware command, error %d\n",
+ __func__, error);
+ return (error);
+ }
+
+ return (rsu_key_check(sc, k->wk_keyix, 1));
}
-static void
-rsu_delete_key(struct rsu_softc *sc, const struct ieee80211_key *k)
+static int
+rsu_set_key_pair(struct rsu_softc *sc, const struct ieee80211_key *k)
+{
+ struct r92s_fw_cmd_set_key_mac key;
+ uint8_t algo;
+ int error;
+
+ RSU_ASSERT_LOCKED(sc);
+
+ if (!sc->sc_running)
+ return (ESHUTDOWN);
+
+ /* Map net80211 cipher to HW crypto algorithm. */
+ algo = rsu_crypto_mode(sc, k->wk_cipher->ic_cipher, k->wk_keylen);
+ if (algo == R92S_KEY_ALGO_INVALID)
+ return (EINVAL);
+
+ memset(&key, 0, sizeof(key));
+ key.algo = algo;
+ memcpy(key.macaddr, k->wk_macaddr, sizeof(key.macaddr));
+ memcpy(key.key, k->wk_key, MIN(k->wk_keylen, sizeof(key.key)));
+
+ RSU_DPRINTF(sc, RSU_DEBUG_KEY | RSU_DEBUG_FWCMD,
+ "%s: keyix %u, algo %u/%u, flags %04X, len %u, macaddr %s\n",
+ __func__, k->wk_keyix, k->wk_cipher->ic_cipher, key.algo,
+ k->wk_flags, k->wk_keylen, ether_sprintf(key.macaddr));
+
+ error = rsu_fw_cmd(sc, R92S_CMD_SET_STA_KEY, &key, sizeof(key));
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: cannot send firmware command, error %d\n",
+ __func__, error);
+ return (error);
+ }
+
+ return (rsu_key_check(sc, k->wk_keyix, 1));
+}
+
+static int
+rsu_reinit_static_keys(struct rsu_softc *sc)
+{
+ int i, error;
+
+ for (i = 0; i < nitems(sc->group_keys); i++) {
+ if (sc->group_keys[i] != NULL) {
+ error = rsu_set_key_group(sc, sc->group_keys[i]);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: failed to set static key %d, "
+ "error %d\n", __func__, i, error);
+ return (error);
+ }
+ }
+ }
+
+ return (0);
+}
+
+static int
+rsu_delete_key(struct rsu_softc *sc, ieee80211_keyix keyix)
{
struct r92s_fw_cmd_set_key key;
+ uint32_t val;
+ int error;
+
+ RSU_ASSERT_LOCKED(sc);
+
+ if (!sc->sc_running)
+ return (0);
+
+ /* check if it was automatically removed by firmware */
+ error = rsu_cam_read(sc, R92S_CAM_CTL0(keyix), &val);
+ if (error == 0 && (val & R92S_CAM_VALID) == 0) {
+ RSU_DPRINTF(sc, RSU_DEBUG_KEY,
+ "%s: key %u does not exist\n", __func__, keyix);
+ clrbit(sc->keys_bmap, keyix);
+ return (0);
+ }
memset(&key, 0, sizeof(key));
- key.id = k->wk_keyix;
- (void)rsu_fw_cmd(sc, R92S_CMD_SET_KEY, &key, sizeof(key));
+ key.cam_id = keyix;
+
+ RSU_DPRINTF(sc, RSU_DEBUG_KEY | RSU_DEBUG_FWCMD,
+ "%s: removing key %u\n", __func__, key.cam_id);
+
+ error = rsu_fw_cmd(sc, R92S_CMD_SET_KEY, &key, sizeof(key));
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: cannot send firmware command, error %d\n",
+ __func__, error);
+ goto finish;
+ }
+
+ usb_pause_mtx(&sc->sc_mtx, USB_MS_TO_TICKS(5));
+
+ /*
+ * Clear 'valid' bit manually (cannot be done via firmware command).
+ * Used for key check + when firmware command cannot be sent.
+ */
+finish:
+ rsu_cam_write(sc, R92S_CAM_CTL0(keyix), 0);
+
+ clrbit(sc->keys_bmap, keyix);
+
+ return (rsu_key_check(sc, keyix, 0));
+}
+
+static void
+rsu_delete_key_pair_cb(void *arg, int pending __unused)
+{
+ struct rsu_softc *sc = arg;
+ int i;
+
+ RSU_DELKEY_BMAP_LOCK(sc);
+ for (i = IEEE80211_WEP_NKID; i < R92S_CAM_ENTRY_LIMIT; i++) {
+ if (isset(sc->free_keys_bmap, i)) {
+ RSU_DELKEY_BMAP_UNLOCK(sc);
+
+ RSU_LOCK(sc);
+ RSU_DPRINTF(sc, RSU_DEBUG_KEY,
+ "%s: calling rsu_delete_key() with keyix = %d\n",
+ __func__, i);
+ (void) rsu_delete_key(sc, i);
+ RSU_UNLOCK(sc);
+
+ RSU_DELKEY_BMAP_LOCK(sc);
+ clrbit(sc->free_keys_bmap, i);
+
+ /* bmap can be changed */
+ i = IEEE80211_WEP_NKID - 1;
+ continue;
+ }
+ }
+ RSU_DELKEY_BMAP_UNLOCK(sc);
}
-#endif
static int
rsu_site_survey(struct rsu_softc *sc, struct ieee80211_scan_ssid *ssid)
@@ -1834,9 +2192,10 @@
int pktlen;
rxdw0 = le32toh(stat->rxdw0);
- if (__predict_false(rxdw0 & R92S_RXDW0_CRCERR)) {
+ if (__predict_false(rxdw0 & (R92S_RXDW0_CRCERR | R92S_RXDW0_ICVERR))) {
RSU_DPRINTF(sc, RSU_DEBUG_RX,
- "%s: RX flags error (CRC)\n", __func__);
+ "%s: RX flags error (%s)\n", __func__,
+ rxdw0 & R92S_RXDW0_CRCERR ? "CRC" : "ICV");
goto fail;
}
@@ -1871,7 +2230,7 @@
struct ieee80211_frame_min *wh;
struct r92s_rx_stat *stat;
uint32_t rxdw0, rxdw3;
- uint8_t rate;
+ uint8_t cipher, rate;
int infosz;
stat = mtod(m, struct r92s_rx_stat *);
@@ -1879,6 +2238,7 @@
rxdw3 = le32toh(stat->rxdw3);
rate = MS(rxdw3, R92S_RXDW3_RATE);
+ cipher = MS(rxdw0, R92S_RXDW0_CIPHER);
infosz = MS(rxdw0, R92S_RXDW0_INFOSZ) * 8;
/* Get RSSI from PHY status descriptor if present. */
@@ -1930,6 +2290,10 @@
/* Drop descriptor. */
m_adj(m, sizeof(*stat) + infosz);
wh = mtod(m, struct ieee80211_frame_min *);
+ if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
+ cipher != R92S_KEY_ALGO_NONE) {
+ m->m_flags |= M_WEP;
+ }
RSU_DPRINTF(sc, RSU_DEBUG_RX,
"%s: Rx frame len %d, rate %d, infosz %d\n",
@@ -2225,7 +2589,7 @@
struct ieee80211_frame *wh;
struct ieee80211_key *k = NULL;
struct r92s_tx_desc *txd;
- uint8_t type;
+ uint8_t type, cipher;
int prio = 0;
uint8_t which;
int hasqos;
@@ -2298,8 +2662,7 @@
SM(R92S_TXDW1_MACID, R92S_MACID_BSS) | SM(R92S_TXDW1_QSEL, qid));
if (!hasqos)
txd->txdw1 |= htole32(R92S_TXDW1_NONQOS);
-#ifdef notyet
- if (k != NULL) {
+ if (k != NULL && !(k->wk_flags & IEEE80211_KEY_SWENCRYPT)) {
switch (k->wk_cipher->ic_cipher) {
case IEEE80211_CIPHER_WEP:
cipher = R92S_TXDW1_CIPHER_WEP;
@@ -2315,9 +2678,8 @@
}
txd->txdw1 |= htole32(
SM(R92S_TXDW1_CIPHER, cipher) |
- SM(R92S_TXDW1_KEYIDX, k->k_id));
+ SM(R92S_TXDW1_KEYIDX, k->wk_keyix));
}
-#endif
/* XXX todo: set AGGEN bit if appropriate? */
txd->txdw2 |= htole32(R92S_TXDW2_BK);
if (IEEE80211_IS_MULTICAST(wh->i_addr1))
@@ -3021,12 +3383,16 @@
/* Set PS mode fully active */
error = rsu_set_fw_power_state(sc, RSU_PWR_ACTIVE);
-
if (error != 0) {
device_printf(sc->sc_dev, "could not set PS mode\n");
goto fail;
}
+ /* Install static keys (if any). */
+ error = rsu_reinit_static_keys(sc);
+ if (error != 0)
+ goto fail;
+
sc->sc_extra_scan = 0;
usbd_transfer_start(sc->sc_xfer[RSU_BULK_RX]);
@@ -3054,6 +3420,13 @@
/* Power off adapter. */
rsu_power_off(sc);
+ /*
+ * CAM is not accessible after shutdown;
+ * all entries are marked (by firmware?) as invalid.
+ */
+ memset(sc->free_keys_bmap, 0, sizeof(sc->free_keys_bmap));
+ memset(sc->keys_bmap, 0, sizeof(sc->keys_bmap));
+
for (i = 0; i < RSU_N_TRANSFER; i++)
usbd_transfer_stop(sc->sc_xfer[i]);
Index: head/sys/dev/usb/wlan/if_rsureg.h
===================================================================
--- head/sys/dev/usb/wlan/if_rsureg.h
+++ head/sys/dev/usb/wlan/if_rsureg.h
@@ -43,6 +43,7 @@
#define R92S_CMDCTRL 0x0040
#define R92S_CR (R92S_CMDCTRL + 0x000)
+#define R92S_TXPAUSE (R92S_CMDCTRL + 0x002)
#define R92S_TCR (R92S_CMDCTRL + 0x004)
#define R92S_RCR (R92S_CMDCTRL + 0x008)
@@ -55,6 +56,11 @@
#define R92S_GPIO_IO_SEL (R92S_GP + 0x00e)
#define R92S_MAC_PINMUX_CTRL (R92S_GP + 0x011)
+#define R92S_SECURITY 0x0240
+#define R92S_CAMCMD (R92S_SECURITY + 0x000)
+#define R92S_CAMWRITE (R92S_SECURITY + 0x004)
+#define R92S_CAMREAD (R92S_SECURITY + 0x008)
+
#define R92S_IOCMD_CTRL 0x0370
#define R92S_IOCMD_DATA 0x0374
@@ -105,6 +111,24 @@
/* Bits for R92S_CR. */
#define R92S_CR_TXDMA_EN 0x10
+/* Bits for R92S_TXPAUSE. */
+#define R92S_TXPAUSE_VO 0x01
+#define R92S_TXPAUSE_VI 0x02
+#define R92S_TXPAUSE_BE 0x04
+#define R92S_TXPAUSE_BK 0x08
+#define R92S_TXPAUSE_MGT 0x10
+#define R92S_TXPAUSE_HIGH 0x20
+#define R92S_TXPAUSE_HCCA 0x40
+
+/* Shortcuts. */
+#define R92S_TXPAUSE_AC \
+ (R92S_TXPAUSE_VO | R92S_TXPAUSE_VI | \
+ R92S_TXPAUSE_BE | R92S_TXPAUSE_BK)
+
+#define R92S_TXPAUSE_ALL \
+ (R92S_TXPAUSE_AC | R92S_TXPAUSE_MGT | \
+ R92S_TXPAUSE_HIGH | R92S_TXPAUSE_HCCA | 0x80)
+
/* Bits for R92S_TCR. */
#define R92S_TCR_IMEM_CODE_DONE 0x01
#define R92S_TCR_IMEM_CHK_RPT 0x02
@@ -126,6 +150,32 @@
#define R92S_GPIOSEL_GPIO_WLANDBG 3
#define R92S_GPIOMUX_EN 0x08
+/* Bits for R92S_CAMCMD. */
+#define R92S_CAMCMD_ADDR_M 0x000000ff
+#define R92S_CAMCMD_ADDR_S 0
+#define R92S_CAMCMD_READ 0x00000000
+#define R92S_CAMCMD_WRITE 0x00010000
+#define R92S_CAMCMD_POLLING 0x80000000
+
+/*
+ * CAM entries.
+ */
+#define R92S_CAM_ENTRY_LIMIT 32
+#define R92S_CAM_ENTRY_BYTES howmany(R92S_CAM_ENTRY_LIMIT, NBBY)
+
+#define R92S_CAM_CTL0(entry) ((entry) * 8 + 0)
+#define R92S_CAM_CTL1(entry) ((entry) * 8 + 1)
+#define R92S_CAM_KEY(entry, i) ((entry) * 8 + 2 + (i))
+
+/* Bits for R92S_CAM_CTL0(i). */
+#define R92S_CAM_KEYID_M 0x00000003
+#define R92S_CAM_KEYID_S 0
+#define R92S_CAM_ALGO_M 0x0000001c
+#define R92S_CAM_ALGO_S 2
+#define R92S_CAM_VALID 0x00008000
+#define R92S_CAM_MACLO_M 0xffff0000
+#define R92S_CAM_MACLO_S 16
+
/* Bits for R92S_IOCMD_CTRL. */
#define R92S_IOCMD_CLASS_M 0xff000000
#define R92S_IOCMD_CLASS_S 24
@@ -391,10 +441,18 @@
#define R92S_KEY_ALGO_TKIP_MMIC 3
#define R92S_KEY_ALGO_AES 4
#define R92S_KEY_ALGO_WEP104 5
+#define R92S_KEY_ALGO_INVALID 0xff /* for rsu_crypto_mode() only */
- uint8_t id;
+ uint8_t cam_id;
uint8_t grpkey;
- uint8_t key[16];
+ uint8_t key[IEEE80211_KEYBUF_SIZE];
+} __packed;
+
+/* Structure for R92S_CMD_SET_STA_KEY. */
+struct r92s_fw_cmd_set_key_mac {
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
+ uint8_t algo;
+ uint8_t key[IEEE80211_KEYBUF_SIZE];
} __packed;
/* Structures for R92S_EVENT_SURVEY/R92S_CMD_JOIN_BSS. */
@@ -497,7 +555,7 @@
struct ndis_wlan_bssid_ex bss;
} __packed;
-#define R92S_MACID_BSS 5
+#define R92S_MACID_BSS 5 /* XXX hardcoded somewhere */
/* Rx MAC descriptor. */
struct r92s_rx_stat {
@@ -505,8 +563,11 @@
#define R92S_RXDW0_PKTLEN_M 0x00003fff
#define R92S_RXDW0_PKTLEN_S 0
#define R92S_RXDW0_CRCERR 0x00004000
+#define R92S_RXDW0_ICVERR 0x00008000
#define R92S_RXDW0_INFOSZ_M 0x000f0000
#define R92S_RXDW0_INFOSZ_S 16
+#define R92S_RXDW0_CIPHER_M 0x00700000
+#define R92S_RXDW0_CIPHER_S 20
#define R92S_RXDW0_QOS 0x00800000
#define R92S_RXDW0_SHIFT_M 0x03000000
#define R92S_RXDW0_SHIFT_S 24
@@ -581,6 +642,7 @@
#define R92S_TXDW1_KEYIDX_S 17
#define R92S_TXDW1_CIPHER_M 0x00c00000
#define R92S_TXDW1_CIPHER_S 22
+#define R92S_TXDW1_CIPHER_NONE 0
#define R92S_TXDW1_CIPHER_WEP 1
#define R92S_TXDW1_CIPHER_TKIP 2
#define R92S_TXDW1_CIPHER_AES 3
@@ -728,6 +790,13 @@
#define RSU_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
#define RSU_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
+#define RSU_DELKEY_BMAP_LOCK_INIT(_sc) \
+ mtx_init(&(_sc)->free_keys_bmap_mtx, "bmap lock", NULL, MTX_DEF)
+#define RSU_DELKEY_BMAP_LOCK(_sc) mtx_lock(&(_sc)->free_keys_bmap_mtx)
+#define RSU_DELKEY_BMAP_UNLOCK(_sc) mtx_unlock(&(_sc)->free_keys_bmap_mtx)
+#define RSU_DELKEY_BMAP_LOCK_DESTROY(_sc) \
+ mtx_destroy(&(_sc)->free_keys_bmap_mtx)
+
struct rsu_softc {
struct ieee80211com sc_ic;
struct mbufq sc_snd;
@@ -762,6 +831,13 @@
STAILQ_HEAD(, rsu_data) sc_tx_inactive;
STAILQ_HEAD(, rsu_data) sc_tx_pending[RSU_N_TRANSFER];
+ struct task del_key_task;
+ uint8_t keys_bmap[R92S_CAM_ENTRY_BYTES];
+ const struct ieee80211_key *group_keys[IEEE80211_WEP_NKID];
+
+ struct mtx free_keys_bmap_mtx;
+ uint8_t free_keys_bmap[R92S_CAM_ENTRY_BYTES];
+
union {
struct rsu_rx_radiotap_header th;
uint8_t pad[64];
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jan 24, 11:34 AM (7 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27896469
Default Alt Text
D8706.diff (21 KB)
Attached To
Mode
D8706: rsu: add hardware crypto support (WEP, TKIP and CCMP)
Attached
Detach File
Event Timeline
Log In to Comment