commit 5ad4eee7a69f66ac8767ed1b919af78c76389101 Author: Jiri Slaby Date: Sat Jul 14 13:17:26 2007 +0200 hw wep diff --git a/ath/if_ath_pci.c b/ath/if_ath_pci.c index 90deebb..91e884f 100644 --- a/ath/if_ath_pci.c +++ b/ath/if_ath_pci.c @@ -282,6 +282,31 @@ static int ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf) return 0; } +static unsigned int ath_rx_decrypted(struct ath_softc *sc, + struct ath_desc *ds, struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr = (void *)skb->data; + unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb); + + if (!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) && + ds->ds_rxstat.rs_keyix != AR5K_RXKEYIX_INVALID) + return RX_FLAG_DECRYPTED; + + /* Apparently when a default key is used to decrypt the packet + the hal does not set the index used to decrypt. In such cases + get the index from the packet. */ + if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) && + !(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) && + skb->len >= hlen + 4) { + keyix = skb->data[hlen + 3] >> 6; + + if (test_bit(keyix, sc->keymap)) + return RX_FLAG_DECRYPTED; + } + + return 0; +} + static void ath_tasklet_rx(unsigned long data) { struct ieee80211_rx_status rxs = {}; @@ -381,7 +406,7 @@ accept: rxs.ssi = ds->ds_rxstat.rs_rssi; rxs.antenna = ds->ds_rxstat.rs_antenna; rxs.rate = ds->ds_rxstat.rs_rate; -// rxs.flag |= RX_FLAG_DECRYPTED; + rxs.flag |= ath_rx_decrypted(sc, ds, skb); // printk(KERN_DEBUG "stat: %x, dlen: %u (hdr: %u), rssi: %d, rate: %u\n", ds->ds_rxstat.rs_status, len, ieee80211_get_hdrlen_from_skb(skb), ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_rate); ath_dump_skb(skb, 1); @@ -862,7 +887,7 @@ static int ath_tx_bf(struct ath_softc *sc, struct ath_buf *bf, struct ath_txq *txq = sc->txq; struct ath_desc *ds = bf->desc; struct sk_buff *skb = bf->skb; - unsigned int hdrpad, pktlen, flags; + unsigned int hdrpad, pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID; int ret; flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; @@ -879,10 +904,15 @@ static int ath_tx_bf(struct ath_softc *sc, struct ath_buf *bf, hdrpad = 0; pktlen = skb->len - hdrpad + FCS_LEN; + + if (ctl->key_idx != HW_KEY_IDX_INVALID) { + keyidx = ctl->key_idx; + pktlen += ctl->icv_len; + } + ret = ah->ah_setup_tx_desc(ah, ds, pktlen, ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, - 0xffff, ctl->tx_rate, ctl->retry_limit, AR5K_TXKEYIX_INVALID, 0, - flags, 0, 0); + 0xffff, ctl->tx_rate, ctl->retry_limit, keyidx, 0, flags, 0, 0); if (ret) goto err_unmap; @@ -971,6 +1001,54 @@ static int ath_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) return ath_chan_set(sc, conf->chan); } +static int ath_set_key(struct ieee80211_hw *hw, set_key_cmd cmd, + u8 *addr, struct ieee80211_key_conf *key, int aid) +{ + struct ath_softc *sc = hw->priv; + int ret = 0; + + mutex_lock(&sc->lock); + + switch (cmd) { + case SET_KEY: + if (key->alg != ALG_WEP && key->alg != ALG_NONE && + key->alg != ALG_NULL) { + ret = -EINVAL; + goto unlock; + } + + ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, addr); + if (ret) { + printk(KERN_ERR "ath: can't set the key\n"); + goto unlock; + } + + set_bit(key->keyidx, sc->keymap); + key->hw_key_idx = key->keyidx; + key->flags &= ~IEEE80211_KEY_FORCE_SW_ENCRYPT; + break; + case DISABLE_KEY: + ath5k_hw_reset_key(sc->ah, key->keyidx); + clear_bit(key->keyidx, sc->keymap); + break; + case REMOVE_ALL_KEYS: { + unsigned int i; + for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) { + ath5k_hw_reset_key(sc->ah, i); + clear_bit(i, sc->keymap); + } + break; + } + default: + ret = -EINVAL; + goto unlock; + } + +unlock: + mutex_unlock(&sc->lock); + return ret; +} + static struct ieee80211_ops ath_hw_ops = { .tx = ath_tx, .reset = NULL, @@ -979,9 +1057,9 @@ static struct ieee80211_ops ath_hw_ops = { .add_interface = NULL, .remove_interface = NULL, .config = ath_config, -/* .config_interface = , - .set_key = , - .get_stats = , +/* .config_interface = ,*/ + .set_key = ath_set_key, +/* .get_stats = , .conf_tx = , .get_tx_stats = , .get_tsf = , @@ -1460,30 +1538,12 @@ static int ath_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) sc->mrretry = ah->ah_setup_xtx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); /* - * Get the hardware key cache size. - */ - sc->keymax = AR5K_KEYCACHE_SIZE; - - /* * Reset the key cache since some parts do not * reset the contents on initial power up. */ - for (i = 0; i < sc->keymax; i++) + for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) ath5k_hw_reset_key(ah, i); - /* - * Mark key cache slots associated with global keys - * as in use. If we knew TKIP was not to be used we - * could leave the +32, +64, and +32+64 slots free. - * XXX only for splitmic. - */ -#ifdef BLE - for (i = 0; i < IEEE80211_WEP_NKID; i++) { - setbit(sc->sc_keymap, i); - setbit(sc->sc_keymap, i+32); - setbit(sc->sc_keymap, i+64); - setbit(sc->sc_keymap, i+32+64); - } -#endif + /* * Collect the channel list using the default country * code and including outdoor channels. The 802.11 layer diff --git a/ath/if_athvar.h b/ath/if_athvar.h index 2f58793..92445c7 100644 --- a/ath/if_athvar.h +++ b/ath/if_athvar.h @@ -71,17 +71,6 @@ #define ATH_BEACON_CWMIN_DEFAULT 0 /* default cwmin for ap beacon q */ #define ATH_BEACON_CWMAX_DEFAULT 0 /* default cwmax for ap beacon q */ -/* - * The key cache is used for h/w cipher state and also for - * tracking station state such as the current tx antenna. - * We also setup a mapping table between key cache slot indices - * and station state to short-circuit node lookups on rx. - * Different parts have different size key caches. We handle - * up to ATH_KEYMAX entries (could dynamically allocate state). - */ -#define ATH_KEYMAX AR5K_KEYCACHE_SIZE /* max key cache size we handle */ -#define ATH_KEYBYTES (ATH_KEYMAX/NBBY) /* storage space in bytes */ - /* driver-specific node state */ struct ath_node { #ifdef BLE @@ -222,13 +211,11 @@ struct ath_softc { u_int sc_txantenna; /* tx antenna (fixed or auto) */ #endif enum ath5k_int imask; /* interrupt mask copy */ - u_int keymax; /* size of key cache */ -#ifdef BLE - u8 sc_keymap[ATH_KEYBYTES];/* key use bit map */ - struct ieee80211_node *sc_keyixmap[ATH_KEYMAX];/* key ix->node map */ -#endif + + DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */ + u8 bssidmask[ETH_ALEN]; - u_int ledpin; /* GPIO pin for driving LED */ + unsigned int ledpin; /* GPIO pin for driving LED */ #ifdef BLE u_int sc_ledon; /* pin setting for LED on */ u_int sc_ledidle; /* idle polling interval */ diff --git a/openhal/ath5k.h b/openhal/ath5k.h index 3ca9468..012bb46 100644 --- a/openhal/ath5k.h +++ b/openhal/ath5k.h @@ -693,30 +693,6 @@ struct ath5k_rate_table { * Crypto definitions */ -/* key types */ -enum ath5k_cipher { - AR5K_CIPHER_WEP = 0, - AR5K_CIPHER_AES_OCB = 1, - AR5K_CIPHER_AES_CCM = 2, - AR5K_CIPHER_CKIP = 3, - AR5K_CIPHER_TKIP = 4, - AR5K_CIPHER_CLR = 5, /* no encryption */ - AR5K_CIPHER_MIC = 127 /* used for Message - Integrity Code */ -}; - -#define AR5K_KEYVAL_LENGTH_40 5 -#define AR5K_KEYVAL_LENGTH_104 13 -#define AR5K_KEYVAL_LENGTH_128 16 -#define AR5K_KEYVAL_LENGTH_MAX AR5K_KEYVAL_LENGTH_128 - -struct ath5k_keyval { - int wk_len; /* key's length */ - u8 wk_key[AR5K_KEYVAL_LENGTH_MAX]; - u8 wk_type; /* see above */ - u8 wk_mic[8]; /* TKIP MIC key */ -}; - #define AR5K_KEYCACHE_SIZE 8 /***********************\ @@ -1059,7 +1035,7 @@ unsigned int ath5k_hw_get_cts_timeout(struct ath_hw *hal); /* Key table (WEP) functions */ int ath5k_hw_reset_key(struct ath_hw *hal, u16 entry); int ath5k_hw_is_key_valid(struct ath_hw *hal, u16 entry); -int ath5k_hw_set_key(struct ath_hw *hal, u16 entry, const struct ath5k_keyval *keyval, const u8 *mac); +int ath5k_hw_set_key(struct ath_hw *hal, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac); int ath5k_hw_set_key_lladdr(struct ath_hw *hal, u16 entry, const u8 *mac); /* Queue Control Unit, DFS Control Unit Functions */ int ath5k_hw_setup_tx_queue(struct ath_hw *hal, enum ath5k_tx_queue queue_type, struct ath5k_txq_info *queue_info); diff --git a/openhal/ath5k_hw.c b/openhal/ath5k_hw.c index dbee59a..5791170 100644 --- a/openhal/ath5k_hw.c +++ b/openhal/ath5k_hw.c @@ -3186,7 +3186,7 @@ int ath5k_hw_is_key_valid(struct ath_hw *hal, u16 entry) } int ath5k_hw_set_key(struct ath_hw *hal, u16 entry, - const struct ath5k_keyval *keyval, const u8 *mac) + const struct ieee80211_key_conf *key, const u8 *mac) { unsigned int i; u32 key_v[AR5K_KEYCACHE_SIZE - 2] = {}; @@ -3194,28 +3194,28 @@ int ath5k_hw_set_key(struct ath_hw *hal, u16 entry, AR5K_TRACE; AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); - switch (keyval->wk_len) { - case AR5K_KEYVAL_LENGTH_40: - memcpy(&key_v[0], keyval->wk_key, 4); - memcpy(&key_v[1], keyval->wk_key + 4, 1); + switch (key->keylen) { + case 40 / 8: + memcpy(&key_v[0], key->key, 4); + memcpy(&key_v[1], key->key + 4, 1); key_v[5] = AR5K_KEYTABLE_TYPE_40; break; - case AR5K_KEYVAL_LENGTH_104: - memcpy(&key_v[0], keyval->wk_key, 4); - memcpy(&key_v[1], keyval->wk_key + 4, 2); - memcpy(&key_v[2], keyval->wk_key + 6, 4); - memcpy(&key_v[3], keyval->wk_key + 10, 2); - memcpy(&key_v[4], keyval->wk_key + 12, 1); + case 104 / 8: + memcpy(&key_v[0], key->key, 4); + memcpy(&key_v[1], key->key + 4, 2); + memcpy(&key_v[2], key->key + 6, 4); + memcpy(&key_v[3], key->key + 10, 2); + memcpy(&key_v[4], key->key + 12, 1); key_v[5] = AR5K_KEYTABLE_TYPE_104; break; - case AR5K_KEYVAL_LENGTH_128: - memcpy(&key_v[0], keyval->wk_key, 4); - memcpy(&key_v[1], keyval->wk_key + 4, 2); - memcpy(&key_v[2], keyval->wk_key + 6, 4); - memcpy(&key_v[3], keyval->wk_key + 10, 2); - memcpy(&key_v[4], keyval->wk_key + 12, 4); + case 128 / 8: + memcpy(&key_v[0], key->key, 4); + memcpy(&key_v[1], key->key + 4, 2); + memcpy(&key_v[2], key->key + 6, 4); + memcpy(&key_v[3], key->key + 10, 2); + memcpy(&key_v[4], key->key + 12, 4); key_v[5] = AR5K_KEYTABLE_TYPE_128; break;