diff options
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/core.h | 4 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 161 |
2 files changed, 72 insertions, 93 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index abb32037c3f7..a47b41dd966f 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
| @@ -285,10 +285,8 @@ struct ath10k_vif { | |||
| 285 | u32 aid; | 285 | u32 aid; |
| 286 | u8 bssid[ETH_ALEN]; | 286 | u8 bssid[ETH_ALEN]; |
| 287 | 287 | ||
| 288 | struct work_struct wep_key_work; | ||
| 289 | struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1]; | 288 | struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1]; |
| 290 | u8 def_wep_key_idx; | 289 | s8 def_wep_key_idx; |
| 291 | u8 def_wep_key_newidx; | ||
| 292 | 290 | ||
| 293 | u16 tx_seq_no; | 291 | u16 tx_seq_no; |
| 294 | 292 | ||
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index f9440deffa26..d3fe1a378e8b 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
| @@ -37,7 +37,7 @@ | |||
| 37 | static int ath10k_send_key(struct ath10k_vif *arvif, | 37 | static int ath10k_send_key(struct ath10k_vif *arvif, |
| 38 | struct ieee80211_key_conf *key, | 38 | struct ieee80211_key_conf *key, |
| 39 | enum set_key_cmd cmd, | 39 | enum set_key_cmd cmd, |
| 40 | const u8 *macaddr) | 40 | const u8 *macaddr, bool def_idx) |
| 41 | { | 41 | { |
| 42 | struct ath10k *ar = arvif->ar; | 42 | struct ath10k *ar = arvif->ar; |
| 43 | struct wmi_vdev_install_key_arg arg = { | 43 | struct wmi_vdev_install_key_arg arg = { |
| @@ -72,6 +72,9 @@ static int ath10k_send_key(struct ath10k_vif *arvif, | |||
| 72 | * Otherwise pairwise key must be set */ | 72 | * Otherwise pairwise key must be set */ |
| 73 | if (memcmp(macaddr, arvif->vif->addr, ETH_ALEN)) | 73 | if (memcmp(macaddr, arvif->vif->addr, ETH_ALEN)) |
| 74 | arg.key_flags = WMI_KEY_PAIRWISE; | 74 | arg.key_flags = WMI_KEY_PAIRWISE; |
| 75 | |||
| 76 | if (def_idx) | ||
| 77 | arg.key_flags |= WMI_KEY_TX_USAGE; | ||
| 75 | break; | 78 | break; |
| 76 | default: | 79 | default: |
| 77 | ath10k_warn(ar, "cipher %d is not supported\n", key->cipher); | 80 | ath10k_warn(ar, "cipher %d is not supported\n", key->cipher); |
| @@ -89,7 +92,7 @@ static int ath10k_send_key(struct ath10k_vif *arvif, | |||
| 89 | static int ath10k_install_key(struct ath10k_vif *arvif, | 92 | static int ath10k_install_key(struct ath10k_vif *arvif, |
| 90 | struct ieee80211_key_conf *key, | 93 | struct ieee80211_key_conf *key, |
| 91 | enum set_key_cmd cmd, | 94 | enum set_key_cmd cmd, |
| 92 | const u8 *macaddr) | 95 | const u8 *macaddr, bool def_idx) |
| 93 | { | 96 | { |
| 94 | struct ath10k *ar = arvif->ar; | 97 | struct ath10k *ar = arvif->ar; |
| 95 | int ret; | 98 | int ret; |
| @@ -98,7 +101,7 @@ static int ath10k_install_key(struct ath10k_vif *arvif, | |||
| 98 | 101 | ||
| 99 | reinit_completion(&ar->install_key_done); | 102 | reinit_completion(&ar->install_key_done); |
| 100 | 103 | ||
| 101 | ret = ath10k_send_key(arvif, key, cmd, macaddr); | 104 | ret = ath10k_send_key(arvif, key, cmd, macaddr, def_idx); |
| 102 | if (ret) | 105 | if (ret) |
| 103 | return ret; | 106 | return ret; |
| 104 | 107 | ||
| @@ -116,6 +119,7 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif, | |||
| 116 | struct ath10k_peer *peer; | 119 | struct ath10k_peer *peer; |
| 117 | int ret; | 120 | int ret; |
| 118 | int i; | 121 | int i; |
| 122 | bool def_idx; | ||
| 119 | 123 | ||
| 120 | lockdep_assert_held(&ar->conf_mutex); | 124 | lockdep_assert_held(&ar->conf_mutex); |
| 121 | 125 | ||
| @@ -129,9 +133,14 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif, | |||
| 129 | for (i = 0; i < ARRAY_SIZE(arvif->wep_keys); i++) { | 133 | for (i = 0; i < ARRAY_SIZE(arvif->wep_keys); i++) { |
| 130 | if (arvif->wep_keys[i] == NULL) | 134 | if (arvif->wep_keys[i] == NULL) |
| 131 | continue; | 135 | continue; |
| 136 | /* set TX_USAGE flag for default key id */ | ||
| 137 | if (arvif->def_wep_key_idx == i) | ||
| 138 | def_idx = true; | ||
| 139 | else | ||
| 140 | def_idx = false; | ||
| 132 | 141 | ||
| 133 | ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY, | 142 | ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY, |
| 134 | addr); | 143 | addr, def_idx); |
| 135 | if (ret) | 144 | if (ret) |
| 136 | return ret; | 145 | return ret; |
| 137 | 146 | ||
| @@ -165,8 +174,9 @@ static int ath10k_clear_peer_keys(struct ath10k_vif *arvif, | |||
| 165 | if (peer->keys[i] == NULL) | 174 | if (peer->keys[i] == NULL) |
| 166 | continue; | 175 | continue; |
| 167 | 176 | ||
| 177 | /* key flags are not required to delete the key */ | ||
| 168 | ret = ath10k_install_key(arvif, peer->keys[i], | 178 | ret = ath10k_install_key(arvif, peer->keys[i], |
| 169 | DISABLE_KEY, addr); | 179 | DISABLE_KEY, addr, false); |
| 170 | if (ret && first_errno == 0) | 180 | if (ret && first_errno == 0) |
| 171 | first_errno = ret; | 181 | first_errno = ret; |
| 172 | 182 | ||
| @@ -240,8 +250,8 @@ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif, | |||
| 240 | 250 | ||
| 241 | if (i == ARRAY_SIZE(peer->keys)) | 251 | if (i == ARRAY_SIZE(peer->keys)) |
| 242 | break; | 252 | break; |
| 243 | 253 | /* key flags are not required to delete the key */ | |
| 244 | ret = ath10k_install_key(arvif, key, DISABLE_KEY, addr); | 254 | ret = ath10k_install_key(arvif, key, DISABLE_KEY, addr, false); |
| 245 | if (ret && first_errno == 0) | 255 | if (ret && first_errno == 0) |
| 246 | first_errno = ret; | 256 | first_errno = ret; |
| 247 | 257 | ||
| @@ -1855,7 +1865,8 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw, | |||
| 1855 | ath10k_warn(ar, "faield to down vdev %i: %d\n", | 1865 | ath10k_warn(ar, "faield to down vdev %i: %d\n", |
| 1856 | arvif->vdev_id, ret); | 1866 | arvif->vdev_id, ret); |
| 1857 | 1867 | ||
| 1858 | arvif->def_wep_key_idx = 0; | 1868 | arvif->def_wep_key_idx = -1; |
| 1869 | |||
| 1859 | arvif->is_up = false; | 1870 | arvif->is_up = false; |
| 1860 | } | 1871 | } |
| 1861 | 1872 | ||
| @@ -1914,11 +1925,14 @@ static int ath10k_station_assoc(struct ath10k *ar, | |||
| 1914 | } | 1925 | } |
| 1915 | } | 1926 | } |
| 1916 | 1927 | ||
| 1917 | ret = ath10k_install_peer_wep_keys(arvif, sta->addr); | 1928 | /* Plumb cached keys only for static WEP */ |
| 1918 | if (ret) { | 1929 | if (arvif->def_wep_key_idx != -1) { |
| 1919 | ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n", | 1930 | ret = ath10k_install_peer_wep_keys(arvif, sta->addr); |
| 1920 | arvif->vdev_id, ret); | 1931 | if (ret) { |
| 1921 | return ret; | 1932 | ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n", |
| 1933 | arvif->vdev_id, ret); | ||
| 1934 | return ret; | ||
| 1935 | } | ||
| 1922 | } | 1936 | } |
| 1923 | } | 1937 | } |
| 1924 | 1938 | ||
| @@ -2190,69 +2204,6 @@ static void ath10k_tx_h_nwifi(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
| 2190 | } | 2204 | } |
| 2191 | } | 2205 | } |
| 2192 | 2206 | ||
| 2193 | static void ath10k_tx_wep_key_work(struct work_struct *work) | ||
| 2194 | { | ||
| 2195 | struct ath10k_vif *arvif = container_of(work, struct ath10k_vif, | ||
| 2196 | wep_key_work); | ||
| 2197 | struct ath10k *ar = arvif->ar; | ||
| 2198 | int ret, keyidx = arvif->def_wep_key_newidx; | ||
| 2199 | |||
| 2200 | mutex_lock(&arvif->ar->conf_mutex); | ||
| 2201 | |||
| 2202 | if (arvif->ar->state != ATH10K_STATE_ON) | ||
| 2203 | goto unlock; | ||
| 2204 | |||
| 2205 | if (arvif->def_wep_key_idx == keyidx) | ||
| 2206 | goto unlock; | ||
| 2207 | |||
| 2208 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d set keyidx %d\n", | ||
| 2209 | arvif->vdev_id, keyidx); | ||
| 2210 | |||
| 2211 | ret = ath10k_wmi_vdev_set_param(arvif->ar, | ||
| 2212 | arvif->vdev_id, | ||
| 2213 | arvif->ar->wmi.vdev_param->def_keyid, | ||
| 2214 | keyidx); | ||
| 2215 | if (ret) { | ||
| 2216 | ath10k_warn(ar, "failed to update wep key index for vdev %d: %d\n", | ||
| 2217 | arvif->vdev_id, | ||
| 2218 | ret); | ||
| 2219 | goto unlock; | ||
| 2220 | } | ||
| 2221 | |||
| 2222 | arvif->def_wep_key_idx = keyidx; | ||
| 2223 | |||
| 2224 | unlock: | ||
| 2225 | mutex_unlock(&arvif->ar->conf_mutex); | ||
| 2226 | } | ||
| 2227 | |||
| 2228 | static void ath10k_tx_h_update_wep_key(struct ieee80211_vif *vif, | ||
| 2229 | struct ieee80211_key_conf *key, | ||
| 2230 | struct sk_buff *skb) | ||
| 2231 | { | ||
| 2232 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
| 2233 | struct ath10k *ar = arvif->ar; | ||
| 2234 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
| 2235 | |||
| 2236 | if (!ieee80211_has_protected(hdr->frame_control)) | ||
| 2237 | return; | ||
| 2238 | |||
| 2239 | if (!key) | ||
| 2240 | return; | ||
| 2241 | |||
| 2242 | if (key->cipher != WLAN_CIPHER_SUITE_WEP40 && | ||
| 2243 | key->cipher != WLAN_CIPHER_SUITE_WEP104) | ||
| 2244 | return; | ||
| 2245 | |||
| 2246 | if (key->keyidx == arvif->def_wep_key_idx) | ||
| 2247 | return; | ||
| 2248 | |||
| 2249 | /* FIXME: Most likely a few frames will be TXed with an old key. Simply | ||
| 2250 | * queueing frames until key index is updated is not an option because | ||
| 2251 | * sk_buff may need more processing to be done, e.g. offchannel */ | ||
| 2252 | arvif->def_wep_key_newidx = key->keyidx; | ||
| 2253 | ieee80211_queue_work(ar->hw, &arvif->wep_key_work); | ||
| 2254 | } | ||
| 2255 | |||
| 2256 | static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, | 2207 | static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, |
| 2257 | struct ieee80211_vif *vif, | 2208 | struct ieee80211_vif *vif, |
| 2258 | struct sk_buff *skb) | 2209 | struct sk_buff *skb) |
| @@ -2613,7 +2564,6 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
| 2613 | struct ath10k *ar = hw->priv; | 2564 | struct ath10k *ar = hw->priv; |
| 2614 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2565 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
| 2615 | struct ieee80211_vif *vif = info->control.vif; | 2566 | struct ieee80211_vif *vif = info->control.vif; |
| 2616 | struct ieee80211_key_conf *key = info->control.hw_key; | ||
| 2617 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 2567 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| 2618 | 2568 | ||
| 2619 | /* We should disable CCK RATE due to P2P */ | 2569 | /* We should disable CCK RATE due to P2P */ |
| @@ -2627,7 +2577,6 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
| 2627 | /* it makes no sense to process injected frames like that */ | 2577 | /* it makes no sense to process injected frames like that */ |
| 2628 | if (vif && vif->type != NL80211_IFTYPE_MONITOR) { | 2578 | if (vif && vif->type != NL80211_IFTYPE_MONITOR) { |
| 2629 | ath10k_tx_h_nwifi(hw, skb); | 2579 | ath10k_tx_h_nwifi(hw, skb); |
| 2630 | ath10k_tx_h_update_wep_key(vif, key, skb); | ||
| 2631 | ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb); | 2580 | ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb); |
| 2632 | ath10k_tx_h_seq_no(vif, skb); | 2581 | ath10k_tx_h_seq_no(vif, skb); |
| 2633 | } | 2582 | } |
| @@ -3132,7 +3081,6 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
| 3132 | arvif->ar = ar; | 3081 | arvif->ar = ar; |
| 3133 | arvif->vif = vif; | 3082 | arvif->vif = vif; |
| 3134 | 3083 | ||
| 3135 | INIT_WORK(&arvif->wep_key_work, ath10k_tx_wep_key_work); | ||
| 3136 | INIT_LIST_HEAD(&arvif->list); | 3084 | INIT_LIST_HEAD(&arvif->list); |
| 3137 | 3085 | ||
| 3138 | if (ar->free_vdev_map == 0) { | 3086 | if (ar->free_vdev_map == 0) { |
| @@ -3231,14 +3179,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
| 3231 | goto err_vdev_delete; | 3179 | goto err_vdev_delete; |
| 3232 | } | 3180 | } |
| 3233 | 3181 | ||
| 3234 | vdev_param = ar->wmi.vdev_param->def_keyid; | 3182 | arvif->def_wep_key_idx = -1; |
| 3235 | ret = ath10k_wmi_vdev_set_param(ar, 0, vdev_param, | ||
| 3236 | arvif->def_wep_key_idx); | ||
| 3237 | if (ret) { | ||
| 3238 | ath10k_warn(ar, "failed to set vdev %i default key id: %d\n", | ||
| 3239 | arvif->vdev_id, ret); | ||
| 3240 | goto err_vdev_delete; | ||
| 3241 | } | ||
| 3242 | 3183 | ||
| 3243 | vdev_param = ar->wmi.vdev_param->tx_encap_type; | 3184 | vdev_param = ar->wmi.vdev_param->tx_encap_type; |
| 3244 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, | 3185 | ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
| @@ -3358,8 +3299,6 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, | |||
| 3358 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | 3299 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); |
| 3359 | int ret; | 3300 | int ret; |
| 3360 | 3301 | ||
| 3361 | cancel_work_sync(&arvif->wep_key_work); | ||
| 3362 | |||
| 3363 | mutex_lock(&ar->conf_mutex); | 3302 | mutex_lock(&ar->conf_mutex); |
| 3364 | 3303 | ||
| 3365 | spin_lock_bh(&ar->data_lock); | 3304 | spin_lock_bh(&ar->data_lock); |
| @@ -3731,6 +3670,7 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
| 3731 | const u8 *peer_addr; | 3670 | const u8 *peer_addr; |
| 3732 | bool is_wep = key->cipher == WLAN_CIPHER_SUITE_WEP40 || | 3671 | bool is_wep = key->cipher == WLAN_CIPHER_SUITE_WEP40 || |
| 3733 | key->cipher == WLAN_CIPHER_SUITE_WEP104; | 3672 | key->cipher == WLAN_CIPHER_SUITE_WEP104; |
| 3673 | bool def_idx = false; | ||
| 3734 | int ret = 0; | 3674 | int ret = 0; |
| 3735 | 3675 | ||
| 3736 | if (key->keyidx > WMI_MAX_KEY_INDEX) | 3676 | if (key->keyidx > WMI_MAX_KEY_INDEX) |
| @@ -3776,7 +3716,14 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
| 3776 | ath10k_clear_vdev_key(arvif, key); | 3716 | ath10k_clear_vdev_key(arvif, key); |
| 3777 | } | 3717 | } |
| 3778 | 3718 | ||
| 3779 | ret = ath10k_install_key(arvif, key, cmd, peer_addr); | 3719 | /* set TX_USAGE flag for all the keys incase of dot1x-WEP. For |
| 3720 | * static WEP, do not set this flag for the keys whose key id | ||
| 3721 | * is greater than default key id. | ||
| 3722 | */ | ||
| 3723 | if (arvif->def_wep_key_idx == -1) | ||
| 3724 | def_idx = true; | ||
| 3725 | |||
| 3726 | ret = ath10k_install_key(arvif, key, cmd, peer_addr, def_idx); | ||
| 3780 | if (ret) { | 3727 | if (ret) { |
| 3781 | ath10k_warn(ar, "failed to install key for vdev %i peer %pM: %d\n", | 3728 | ath10k_warn(ar, "failed to install key for vdev %i peer %pM: %d\n", |
| 3782 | arvif->vdev_id, peer_addr, ret); | 3729 | arvif->vdev_id, peer_addr, ret); |
| @@ -3801,6 +3748,39 @@ exit: | |||
| 3801 | return ret; | 3748 | return ret; |
| 3802 | } | 3749 | } |
| 3803 | 3750 | ||
| 3751 | static void ath10k_set_default_unicast_key(struct ieee80211_hw *hw, | ||
| 3752 | struct ieee80211_vif *vif, | ||
| 3753 | int keyidx) | ||
| 3754 | { | ||
| 3755 | struct ath10k *ar = hw->priv; | ||
| 3756 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
| 3757 | int ret; | ||
| 3758 | |||
| 3759 | mutex_lock(&arvif->ar->conf_mutex); | ||
| 3760 | |||
| 3761 | if (arvif->ar->state != ATH10K_STATE_ON) | ||
| 3762 | goto unlock; | ||
| 3763 | |||
| 3764 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d set keyidx %d\n", | ||
| 3765 | arvif->vdev_id, keyidx); | ||
| 3766 | |||
| 3767 | ret = ath10k_wmi_vdev_set_param(arvif->ar, | ||
| 3768 | arvif->vdev_id, | ||
| 3769 | arvif->ar->wmi.vdev_param->def_keyid, | ||
| 3770 | keyidx); | ||
| 3771 | |||
| 3772 | if (ret) { | ||
| 3773 | ath10k_warn(ar, "failed to update wep key index for vdev %d: %d\n", | ||
| 3774 | arvif->vdev_id, | ||
| 3775 | ret); | ||
| 3776 | goto unlock; | ||
| 3777 | } | ||
| 3778 | |||
| 3779 | arvif->def_wep_key_idx = keyidx; | ||
| 3780 | unlock: | ||
| 3781 | mutex_unlock(&arvif->ar->conf_mutex); | ||
| 3782 | } | ||
| 3783 | |||
| 3804 | static void ath10k_sta_rc_update_wk(struct work_struct *wk) | 3784 | static void ath10k_sta_rc_update_wk(struct work_struct *wk) |
| 3805 | { | 3785 | { |
| 3806 | struct ath10k *ar; | 3786 | struct ath10k *ar; |
| @@ -4966,6 +4946,7 @@ static const struct ieee80211_ops ath10k_ops = { | |||
| 4966 | .hw_scan = ath10k_hw_scan, | 4946 | .hw_scan = ath10k_hw_scan, |
| 4967 | .cancel_hw_scan = ath10k_cancel_hw_scan, | 4947 | .cancel_hw_scan = ath10k_cancel_hw_scan, |
| 4968 | .set_key = ath10k_set_key, | 4948 | .set_key = ath10k_set_key, |
| 4949 | .set_default_unicast_key = ath10k_set_default_unicast_key, | ||
| 4969 | .sta_state = ath10k_sta_state, | 4950 | .sta_state = ath10k_sta_state, |
| 4970 | .conf_tx = ath10k_conf_tx, | 4951 | .conf_tx = ath10k_conf_tx, |
| 4971 | .remain_on_channel = ath10k_remain_on_channel, | 4952 | .remain_on_channel = ath10k_remain_on_channel, |
