aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath5k/base.c9
-rw-r--r--drivers/net/wireless/ath5k/pcu.c2
-rw-r--r--drivers/net/wireless/ath9k/main.c18
-rw-r--r--drivers/net/wireless/b43/main.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c12
-rw-r--r--drivers/net/wireless/p54/p54common.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c29
-rw-r--r--include/net/mac80211.h20
-rw-r--r--net/mac80211/key.c51
11 files changed, 89 insertions, 83 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 8ef87356e083..88618645a7e4 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -232,7 +232,7 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
232 int mc_count, struct dev_mc_list *mclist); 232 int mc_count, struct dev_mc_list *mclist);
233static int ath5k_set_key(struct ieee80211_hw *hw, 233static int ath5k_set_key(struct ieee80211_hw *hw,
234 enum set_key_cmd cmd, 234 enum set_key_cmd cmd,
235 const u8 *local_addr, const u8 *addr, 235 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
236 struct ieee80211_key_conf *key); 236 struct ieee80211_key_conf *key);
237static int ath5k_get_stats(struct ieee80211_hw *hw, 237static int ath5k_get_stats(struct ieee80211_hw *hw,
238 struct ieee80211_low_level_stats *stats); 238 struct ieee80211_low_level_stats *stats);
@@ -2991,8 +2991,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
2991 2991
2992static int 2992static int
2993ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 2993ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
2994 const u8 *local_addr, const u8 *addr, 2994 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
2995 struct ieee80211_key_conf *key) 2995 struct ieee80211_key_conf *key)
2996{ 2996{
2997 struct ath5k_softc *sc = hw->priv; 2997 struct ath5k_softc *sc = hw->priv;
2998 int ret = 0; 2998 int ret = 0;
@@ -3015,7 +3015,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3015 3015
3016 switch (cmd) { 3016 switch (cmd) {
3017 case SET_KEY: 3017 case SET_KEY:
3018 ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, addr); 3018 ret = ath5k_hw_set_key(sc->ah, key->keyidx, key,
3019 sta ? sta->addr : NULL);
3019 if (ret) { 3020 if (ret) {
3020 ATH5K_ERR(sc, "can't set the key\n"); 3021 ATH5K_ERR(sc, "can't set the key\n");
3021 goto unlock; 3022 goto unlock;
diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c
index 75eb9f43c741..5b416ed65299 100644
--- a/drivers/net/wireless/ath5k/pcu.c
+++ b/drivers/net/wireless/ath5k/pcu.c
@@ -1139,7 +1139,7 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
1139 1139
1140 /* MAC may be NULL if it's a broadcast key. In this case no need to 1140 /* MAC may be NULL if it's a broadcast key. In this case no need to
1141 * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ 1141 * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */
1142 if (unlikely(mac == NULL)) { 1142 if (!mac) {
1143 low_id = 0xffffffff; 1143 low_id = 0xffffffff;
1144 high_id = 0xffff | AR5K_KEYTABLE_VALID; 1144 high_id = 0xffff | AR5K_KEYTABLE_VALID;
1145 } else { 1145 } else {
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index 5cbda9245560..a4046a97c016 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -794,7 +794,7 @@ static int ath_reserve_key_cache_slot(struct ath_softc *sc)
794} 794}
795 795
796static int ath_key_config(struct ath_softc *sc, 796static int ath_key_config(struct ath_softc *sc,
797 const u8 *addr, 797 struct ieee80211_sta *sta,
798 struct ieee80211_key_conf *key) 798 struct ieee80211_key_conf *key)
799{ 799{
800 struct ath9k_keyval hk; 800 struct ath9k_keyval hk;
@@ -828,7 +828,10 @@ static int ath_key_config(struct ath_softc *sc,
828 } else if (key->keyidx) { 828 } else if (key->keyidx) {
829 struct ieee80211_vif *vif; 829 struct ieee80211_vif *vif;
830 830
831 mac = addr; 831 if (WARN_ON(!sta))
832 return -EOPNOTSUPP;
833 mac = sta->addr;
834
832 vif = sc->sc_vaps[0]; 835 vif = sc->sc_vaps[0];
833 if (vif->type != NL80211_IFTYPE_AP) { 836 if (vif->type != NL80211_IFTYPE_AP) {
834 /* Only keyidx 0 should be used with unicast key, but 837 /* Only keyidx 0 should be used with unicast key, but
@@ -837,7 +840,10 @@ static int ath_key_config(struct ath_softc *sc,
837 } else 840 } else
838 return -EIO; 841 return -EIO;
839 } else { 842 } else {
840 mac = addr; 843 if (WARN_ON(!sta))
844 return -EOPNOTSUPP;
845 mac = sta->addr;
846
841 if (key->alg == ALG_TKIP) 847 if (key->alg == ALG_TKIP)
842 idx = ath_reserve_key_cache_slot_tkip(sc); 848 idx = ath_reserve_key_cache_slot_tkip(sc);
843 else 849 else
@@ -2320,8 +2326,8 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw,
2320 2326
2321static int ath9k_set_key(struct ieee80211_hw *hw, 2327static int ath9k_set_key(struct ieee80211_hw *hw,
2322 enum set_key_cmd cmd, 2328 enum set_key_cmd cmd,
2323 const u8 *local_addr, 2329 struct ieee80211_vif *vif,
2324 const u8 *addr, 2330 struct ieee80211_sta *sta,
2325 struct ieee80211_key_conf *key) 2331 struct ieee80211_key_conf *key)
2326{ 2332{
2327 struct ath_softc *sc = hw->priv; 2333 struct ath_softc *sc = hw->priv;
@@ -2331,7 +2337,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
2331 2337
2332 switch (cmd) { 2338 switch (cmd) {
2333 case SET_KEY: 2339 case SET_KEY:
2334 ret = ath_key_config(sc, addr, key); 2340 ret = ath_key_config(sc, sta, key);
2335 if (ret >= 0) { 2341 if (ret >= 0) {
2336 key->hw_key_idx = ret; 2342 key->hw_key_idx = ret;
2337 /* push IV and Michael MIC generation to stack */ 2343 /* push IV and Michael MIC generation to stack */
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 5ca55dcd0345..19ad5164fce7 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3476,8 +3476,8 @@ out_unlock_mutex:
3476} 3476}
3477 3477
3478static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 3478static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3479 const u8 *local_addr, const u8 *addr, 3479 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
3480 struct ieee80211_key_conf *key) 3480 struct ieee80211_key_conf *key)
3481{ 3481{
3482 struct b43_wl *wl = hw_to_b43_wl(hw); 3482 struct b43_wl *wl = hw_to_b43_wl(hw);
3483 struct b43_wldev *dev; 3483 struct b43_wldev *dev;
@@ -3542,9 +3542,14 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3542 } 3542 }
3543 3543
3544 if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { 3544 if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
3545 if (WARN_ON(!sta)) {
3546 err = -EOPNOTSUPP;
3547 goto out_unlock;
3548 }
3545 /* Pairwise key with an assigned MAC address. */ 3549 /* Pairwise key with an assigned MAC address. */
3546 err = b43_key_write(dev, -1, algorithm, 3550 err = b43_key_write(dev, -1, algorithm,
3547 key->key, key->keylen, addr, key); 3551 key->key, key->keylen,
3552 sta->addr, key);
3548 } else { 3553 } else {
3549 /* Group key */ 3554 /* Group key */
3550 err = b43_key_write(dev, index, algorithm, 3555 err = b43_key_write(dev, index, algorithm,
@@ -3577,7 +3582,7 @@ out_unlock:
3577 b43dbg(wl, "%s hardware based encryption for keyidx: %d, " 3582 b43dbg(wl, "%s hardware based encryption for keyidx: %d, "
3578 "mac: %pM\n", 3583 "mac: %pM\n",
3579 cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, 3584 cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
3580 addr); 3585 sta ? sta->addr : "<group key>");
3581 b43_dump_keymemory(dev); 3586 b43_dump_keymemory(dev);
3582 } 3587 }
3583 write_unlock(&wl->tx_lock); 3588 write_unlock(&wl->tx_lock);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index f3f6dba7a673..dbfee28107a5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3021,13 +3021,17 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
3021} 3021}
3022 3022
3023static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 3023static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3024 const u8 *local_addr, const u8 *addr, 3024 struct ieee80211_vif *vif,
3025 struct ieee80211_sta *sta,
3025 struct ieee80211_key_conf *key) 3026 struct ieee80211_key_conf *key)
3026{ 3027{
3027 struct iwl_priv *priv = hw->priv; 3028 struct iwl_priv *priv = hw->priv;
3028 int ret = 0; 3029 int ret = 0;
3029 u8 sta_id = IWL_INVALID_STATION; 3030 u8 sta_id = IWL_INVALID_STATION;
3030 u8 is_default_wep_key = 0; 3031 u8 is_default_wep_key = 0;
3032 static const u8 bcast_addr[ETH_ALEN] =
3033 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
3034 static const u8 *addr;
3031 3035
3032 IWL_DEBUG_MAC80211("enter\n"); 3036 IWL_DEBUG_MAC80211("enter\n");
3033 3037
@@ -3036,9 +3040,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3036 return -EOPNOTSUPP; 3040 return -EOPNOTSUPP;
3037 } 3041 }
3038 3042
3039 if (is_zero_ether_addr(addr)) 3043 addr = sta ? sta->addr : bcast_addr;
3040 /* only support pairwise keys */
3041 return -EOPNOTSUPP;
3042 3044
3043 sta_id = iwl_find_station(priv, addr); 3045 sta_id = iwl_find_station(priv, addr);
3044 if (sta_id == IWL_INVALID_STATION) { 3046 if (sta_id == IWL_INVALID_STATION) {
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index a176f42fd7cf..43cfc6ec5163 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -6546,12 +6546,16 @@ out_unlock:
6546} 6546}
6547 6547
6548static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 6548static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
6549 const u8 *local_addr, const u8 *addr, 6549 struct ieee80211_vif *vif,
6550 struct ieee80211_key_conf *key) 6550 struct ieee80211_sta *sta,
6551 struct ieee80211_key_conf *key)
6551{ 6552{
6552 struct iwl_priv *priv = hw->priv; 6553 struct iwl_priv *priv = hw->priv;
6554 const u8 *addr;
6553 int rc = 0; 6555 int rc = 0;
6554 u8 sta_id; 6556 u8 sta_id;
6557 static const u8 bcast_addr[ETH_ALEN] =
6558 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
6555 6559
6556 IWL_DEBUG_MAC80211("enter\n"); 6560 IWL_DEBUG_MAC80211("enter\n");
6557 6561
@@ -6560,9 +6564,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
6560 return -EOPNOTSUPP; 6564 return -EOPNOTSUPP;
6561 } 6565 }
6562 6566
6563 if (is_zero_ether_addr(addr)) 6567 addr = sta ? sta->addr : bcast_addr;
6564 /* only support pairwise keys */
6565 return -EOPNOTSUPP;
6566 6568
6567 sta_id = iwl3945_hw_find_station(priv, addr); 6569 sta_id = iwl3945_hw_find_station(priv, addr);
6568 if (sta_id == IWL_INVALID_STATION) { 6570 if (sta_id == IWL_INVALID_STATION) {
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index 8d2df5b6ecbf..0907e6f246e6 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -2127,7 +2127,7 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev,
2127} 2127}
2128 2128
2129static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, 2129static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
2130 const u8 *local_address, const u8 *address, 2130 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
2131 struct ieee80211_key_conf *key) 2131 struct ieee80211_key_conf *key)
2132{ 2132{
2133 struct p54_common *priv = dev->priv; 2133 struct p54_common *priv = dev->priv;
@@ -2191,8 +2191,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
2191 rxkey->entry = key->keyidx; 2191 rxkey->entry = key->keyidx;
2192 rxkey->key_id = key->keyidx; 2192 rxkey->key_id = key->keyidx;
2193 rxkey->key_type = algo; 2193 rxkey->key_type = algo;
2194 if (address) 2194 if (sta)
2195 memcpy(rxkey->mac, address, ETH_ALEN); 2195 memcpy(rxkey->mac, sta->addr, ETH_ALEN);
2196 else 2196 else
2197 memset(rxkey->mac, ~0, ETH_ALEN); 2197 memset(rxkey->mac, ~0, ETH_ALEN);
2198 if (key->alg != ALG_TKIP) { 2198 if (key->alg != ALG_TKIP) {
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 1ef3434a2bae..890c7216cf38 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -931,7 +931,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
931 int mc_count, struct dev_addr_list *mc_list); 931 int mc_count, struct dev_addr_list *mc_list);
932#ifdef CONFIG_RT2X00_LIB_CRYPTO 932#ifdef CONFIG_RT2X00_LIB_CRYPTO
933int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 933int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
934 const u8 *local_address, const u8 *address, 934 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
935 struct ieee80211_key_conf *key); 935 struct ieee80211_key_conf *key);
936#else 936#else
937#define rt2x00mac_set_key NULL 937#define rt2x00mac_set_key NULL
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index bf7755a21645..3e204406f44f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -502,15 +502,17 @@ static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len)
502} 502}
503 503
504int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, 504int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
505 const u8 *local_address, const u8 *address, 505 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
506 struct ieee80211_key_conf *key) 506 struct ieee80211_key_conf *key)
507{ 507{
508 struct rt2x00_dev *rt2x00dev = hw->priv; 508 struct rt2x00_dev *rt2x00dev = hw->priv;
509 struct ieee80211_sta *sta; 509 struct rt2x00_intf *intf = vif_to_intf(vif);
510 int (*set_key) (struct rt2x00_dev *rt2x00dev, 510 int (*set_key) (struct rt2x00_dev *rt2x00dev,
511 struct rt2x00lib_crypto *crypto, 511 struct rt2x00lib_crypto *crypto,
512 struct ieee80211_key_conf *key); 512 struct ieee80211_key_conf *key);
513 struct rt2x00lib_crypto crypto; 513 struct rt2x00lib_crypto crypto;
514 static const u8 bcast_addr[ETH_ALEN] =
515 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
514 516
515 if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) 517 if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
516 return 0; 518 return 0;
@@ -528,32 +530,25 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
528 if (rt2x00dev->intf_sta_count) 530 if (rt2x00dev->intf_sta_count)
529 crypto.bssidx = 0; 531 crypto.bssidx = 0;
530 else 532 else
531 crypto.bssidx = 533 crypto.bssidx = intf->mac[5] & (rt2x00dev->ops->max_ap_intf - 1);
532 local_address[5] & (rt2x00dev->ops->max_ap_intf - 1);
533 534
534 crypto.cipher = rt2x00crypto_key_to_cipher(key); 535 crypto.cipher = rt2x00crypto_key_to_cipher(key);
535 if (crypto.cipher == CIPHER_NONE) 536 if (crypto.cipher == CIPHER_NONE)
536 return -EOPNOTSUPP; 537 return -EOPNOTSUPP;
537 538
538 crypto.cmd = cmd; 539 crypto.cmd = cmd;
539 crypto.address = address; 540
541 if (sta) {
542 /* some drivers need the AID */
543 crypto.aid = sta->aid;
544 crypto.address = sta->addr;
545 } else
546 crypto.address = bcast_addr;
540 547
541 if (crypto.cipher == CIPHER_TKIP) 548 if (crypto.cipher == CIPHER_TKIP)
542 memcpy_tkip(&crypto, &key->key[0], key->keylen); 549 memcpy_tkip(&crypto, &key->key[0], key->keylen);
543 else 550 else
544 memcpy(&crypto.key, &key->key[0], key->keylen); 551 memcpy(&crypto.key, &key->key[0], key->keylen);
545
546 /*
547 * Discover the Association ID from mac80211.
548 * Some drivers need this information when updating the
549 * hardware key (either adding or removing).
550 */
551 rcu_read_lock();
552 sta = ieee80211_find_sta(hw, address);
553 if (sta)
554 crypto.aid = sta->aid;
555 rcu_read_unlock();
556
557 /* 552 /*
558 * Each BSS has a maximum of 4 shared keys. 553 * Each BSS has a maximum of 4 shared keys.
559 * Shared key index values: 554 * Shared key index values:
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index ffcbd12775a4..9215b1ec90ec 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -715,8 +715,8 @@ enum ieee80211_key_flags {
715 * - Temporal Encryption Key (128 bits) 715 * - Temporal Encryption Key (128 bits)
716 * - Temporal Authenticator Tx MIC Key (64 bits) 716 * - Temporal Authenticator Tx MIC Key (64 bits)
717 * - Temporal Authenticator Rx MIC Key (64 bits) 717 * - Temporal Authenticator Rx MIC Key (64 bits)
718 * @icv_len: FIXME 718 * @icv_len: The ICV length for this key type
719 * @iv_len: FIXME 719 * @iv_len: The IV length for this key type
720 */ 720 */
721struct ieee80211_key_conf { 721struct ieee80211_key_conf {
722 enum ieee80211_key_alg alg; 722 enum ieee80211_key_alg alg;
@@ -1019,16 +1019,12 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
1019 * 1019 *
1020 * The set_key() callback in the &struct ieee80211_ops for a given 1020 * The set_key() callback in the &struct ieee80211_ops for a given
1021 * device is called to enable hardware acceleration of encryption and 1021 * device is called to enable hardware acceleration of encryption and
1022 * decryption. The callback takes an @address parameter that will be 1022 * decryption. The callback takes a @sta parameter that will be NULL
1023 * the broadcast address for default keys, the other station's hardware 1023 * for default keys or keys used for transmission only, or point to
1024 * address for individual keys or the zero address for keys that will 1024 * the station information for the peer for individual keys.
1025 * be used only for transmission.
1026 * Multiple transmission keys with the same key index may be used when 1025 * Multiple transmission keys with the same key index may be used when
1027 * VLANs are configured for an access point. 1026 * VLANs are configured for an access point.
1028 * 1027 *
1029 * The @local_address parameter will always be set to our own address,
1030 * this is only relevant if you support multiple local addresses.
1031 *
1032 * When transmitting, the TX control data will use the @hw_key_idx 1028 * When transmitting, the TX control data will use the @hw_key_idx
1033 * selected by the driver by modifying the &struct ieee80211_key_conf 1029 * selected by the driver by modifying the &struct ieee80211_key_conf
1034 * pointed to by the @key parameter to the set_key() function. 1030 * pointed to by the @key parameter to the set_key() function.
@@ -1233,8 +1229,8 @@ enum ieee80211_ampdu_mlme_action {
1233 * 1229 *
1234 * @set_key: See the section "Hardware crypto acceleration" 1230 * @set_key: See the section "Hardware crypto acceleration"
1235 * This callback can sleep, and is only called between add_interface 1231 * This callback can sleep, and is only called between add_interface
1236 * and remove_interface calls, i.e. while the interface with the 1232 * and remove_interface calls, i.e. while the given virtual interface
1237 * given local_address is enabled. 1233 * is enabled.
1238 * 1234 *
1239 * @update_tkip_key: See the section "Hardware crypto acceleration" 1235 * @update_tkip_key: See the section "Hardware crypto acceleration"
1240 * This callback will be called in the context of Rx. Called for drivers 1236 * This callback will be called in the context of Rx. Called for drivers
@@ -1311,7 +1307,7 @@ struct ieee80211_ops {
1311 int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, 1307 int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
1312 bool set); 1308 bool set);
1313 int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, 1309 int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
1314 const u8 *local_address, const u8 *address, 1310 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
1315 struct ieee80211_key_conf *key); 1311 struct ieee80211_key_conf *key);
1316 void (*update_tkip_key)(struct ieee80211_hw *hw, 1312 void (*update_tkip_key)(struct ieee80211_hw *hw,
1317 struct ieee80211_key_conf *conf, const u8 *address, 1313 struct ieee80211_key_conf *conf, const u8 *address,
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 999f7aa42326..b0a025c9b615 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -47,7 +47,6 @@
47 */ 47 */
48 48
49static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 49static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
50static const u8 zero_addr[ETH_ALEN];
51 50
52/* key mutex: used to synchronise todo runners */ 51/* key mutex: used to synchronise todo runners */
53static DEFINE_MUTEX(key_mutex); 52static DEFINE_MUTEX(key_mutex);
@@ -108,29 +107,18 @@ static void assert_key_lock(void)
108 WARN_ON(!mutex_is_locked(&key_mutex)); 107 WARN_ON(!mutex_is_locked(&key_mutex));
109} 108}
110 109
111static const u8 *get_mac_for_key(struct ieee80211_key *key) 110static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
112{ 111{
113 const u8 *addr = bcast_addr;
114
115 /*
116 * If we're an AP we won't ever receive frames with a non-WEP
117 * group key so we tell the driver that by using the zero MAC
118 * address to indicate a transmit-only key.
119 */
120 if (key->conf.alg != ALG_WEP &&
121 (key->sdata->vif.type == NL80211_IFTYPE_AP ||
122 key->sdata->vif.type == NL80211_IFTYPE_AP_VLAN))
123 addr = zero_addr;
124
125 if (key->sta) 112 if (key->sta)
126 addr = key->sta->sta.addr; 113 return &key->sta->sta;
127 114
128 return addr; 115 return NULL;
129} 116}
130 117
131static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key) 118static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
132{ 119{
133 const u8 *addr; 120 struct ieee80211_sub_if_data *sdata;
121 struct ieee80211_sta *sta;
134 int ret; 122 int ret;
135 123
136 assert_key_lock(); 124 assert_key_lock();
@@ -139,11 +127,16 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
139 if (!key->local->ops->set_key) 127 if (!key->local->ops->set_key)
140 return; 128 return;
141 129
142 addr = get_mac_for_key(key); 130 sta = get_sta_for_key(key);
131
132 sdata = key->sdata;
133 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
134 sdata = container_of(sdata->bss,
135 struct ieee80211_sub_if_data,
136 u.ap);
143 137
144 ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY, 138 ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY,
145 key->sdata->dev->dev_addr, addr, 139 &sdata->vif, sta, &key->conf);
146 &key->conf);
147 140
148 if (!ret) { 141 if (!ret) {
149 spin_lock(&todo_lock); 142 spin_lock(&todo_lock);
@@ -155,12 +148,13 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
155 printk(KERN_ERR "mac80211-%s: failed to set key " 148 printk(KERN_ERR "mac80211-%s: failed to set key "
156 "(%d, %pM) to hardware (%d)\n", 149 "(%d, %pM) to hardware (%d)\n",
157 wiphy_name(key->local->hw.wiphy), 150 wiphy_name(key->local->hw.wiphy),
158 key->conf.keyidx, addr, ret); 151 key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
159} 152}
160 153
161static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key) 154static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
162{ 155{
163 const u8 *addr; 156 struct ieee80211_sub_if_data *sdata;
157 struct ieee80211_sta *sta;
164 int ret; 158 int ret;
165 159
166 assert_key_lock(); 160 assert_key_lock();
@@ -176,17 +170,22 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
176 } 170 }
177 spin_unlock(&todo_lock); 171 spin_unlock(&todo_lock);
178 172
179 addr = get_mac_for_key(key); 173 sta = get_sta_for_key(key);
174 sdata = key->sdata;
175
176 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
177 sdata = container_of(sdata->bss,
178 struct ieee80211_sub_if_data,
179 u.ap);
180 180
181 ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY, 181 ret = key->local->ops->set_key(local_to_hw(key->local), DISABLE_KEY,
182 key->sdata->dev->dev_addr, addr, 182 &sdata->vif, sta, &key->conf);
183 &key->conf);
184 183
185 if (ret) 184 if (ret)
186 printk(KERN_ERR "mac80211-%s: failed to remove key " 185 printk(KERN_ERR "mac80211-%s: failed to remove key "
187 "(%d, %pM) from hardware (%d)\n", 186 "(%d, %pM) from hardware (%d)\n",
188 wiphy_name(key->local->hw.wiphy), 187 wiphy_name(key->local->hw.wiphy),
189 key->conf.keyidx, addr, ret); 188 key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
190 189
191 spin_lock(&todo_lock); 190 spin_lock(&todo_lock);
192 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; 191 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;