diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/mac.c')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 97d7111..bc0e17b 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -1239,7 +1239,7 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw, /* FIXME: why don't we print error if wmi call fails? */ ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); - arvif->def_wep_key_index = 0; + arvif->def_wep_key_idx = 0; } static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, @@ -1467,6 +1467,30 @@ static void ath10k_tx_h_qos_workaround(struct ieee80211_hw *hw, skb_pull(skb, IEEE80211_QOS_CTL_LEN); } +static void ath10k_tx_wep_key_work(struct work_struct *work) +{ + struct ath10k_vif *arvif = container_of(work, struct ath10k_vif, + wep_key_work); + int ret, keyidx = arvif->def_wep_key_newidx; + + if (arvif->def_wep_key_idx == keyidx) + return; + + ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d set keyidx %d\n", + arvif->vdev_id, keyidx); + + ret = ath10k_wmi_vdev_set_param(arvif->ar, + arvif->vdev_id, + arvif->ar->wmi.vdev_param->def_keyid, + keyidx); + if (ret) { + ath10k_warn("could not update wep keyidx (%d)\n", ret); + return; + } + + arvif->def_wep_key_idx = keyidx; +} + static void ath10k_tx_h_update_wep_key(struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); @@ -1475,8 +1499,6 @@ static void ath10k_tx_h_update_wep_key(struct sk_buff *skb) struct ath10k *ar = arvif->ar; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_key_conf *key = info->control.hw_key; - u32 vdev_param; - int ret; if (!ieee80211_has_protected(hdr->frame_control)) return; @@ -1488,21 +1510,14 @@ static void ath10k_tx_h_update_wep_key(struct sk_buff *skb) key->cipher != WLAN_CIPHER_SUITE_WEP104) return; - if (key->keyidx == arvif->def_wep_key_index) - return; - - ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d keyidx %d\n", - arvif->vdev_id, key->keyidx); - - vdev_param = ar->wmi.vdev_param->def_keyid; - ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, - key->keyidx); - if (ret) { - ath10k_warn("could not update wep keyidx (%d)\n", ret); + if (key->keyidx == arvif->def_wep_key_idx) return; - } - arvif->def_wep_key_index = key->keyidx; + /* FIXME: Most likely a few frames will be TXed with an old key. Simply + * queueing frames until key index is updated is not an option because + * sk_buff may need more processing to be done, e.g. offchannel */ + arvif->def_wep_key_newidx = key->keyidx; + ieee80211_queue_work(ar->hw, &arvif->wep_key_work); } static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb) @@ -2023,6 +2038,8 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, arvif->ar = ar; arvif->vif = vif; + INIT_WORK(&arvif->wep_key_work, ath10k_tx_wep_key_work); + if ((vif->type == NL80211_IFTYPE_MONITOR) && ar->monitor_present) { ath10k_warn("Only one monitor interface allowed\n"); ret = -EBUSY; @@ -2078,7 +2095,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, vdev_param = ar->wmi.vdev_param->def_keyid; ret = ath10k_wmi_vdev_set_param(ar, 0, vdev_param, - arvif->def_wep_key_index); + arvif->def_wep_key_idx); if (ret) ath10k_warn("Failed to set default keyid: %d\n", ret); @@ -2147,6 +2164,8 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); + cancel_work_sync(&arvif->wep_key_work); + spin_lock_bh(&ar->data_lock); if (arvif->beacon) { dev_kfree_skb_any(arvif->beacon); |