diff options
author | David S. Miller <davem@davemloft.net> | 2017-11-27 11:09:42 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-11-27 11:09:42 -0500 |
commit | d3fe1e0185cffabc9b6f73f246a5552b46af7131 (patch) | |
tree | a2a897425ab99d849b095ed8764f669e282ccc1e | |
parent | 6b56b1a255bda11fcec0b5f4f8ac7dcec43808af (diff) | |
parent | 72e2c3438ba3bd2ed640b6b5ea9e58993dd9ab7f (diff) |
Merge tag 'mac80211-for-davem-2017-11-27' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211
Johannes Berg says:
====================
Four fixes:
* CRYPTO_SHA256 is needed for regdb validation
* mac80211: mesh path metric was wrong in some frames
* mac80211: use QoS null-data packets on QoS connections
* mac80211: tear down RX aggregation sessions first to
drop fewer packets in HW restart scenarios
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/channel.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/st/cw1200/sta.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl1251/main.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/cmd.c | 5 | ||||
-rw-r--r-- | include/net/mac80211.h | 8 | ||||
-rw-r--r-- | net/mac80211/ht.c | 4 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 15 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 2 | ||||
-rw-r--r-- | net/mac80211/tx.c | 29 | ||||
-rw-r--r-- | net/wireless/Kconfig | 7 |
10 files changed, 61 insertions, 17 deletions
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index dfb26f03c1a2..1b05b5d7a038 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c | |||
@@ -1113,7 +1113,7 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp, | |||
1113 | if (!avp->assoc) | 1113 | if (!avp->assoc) |
1114 | return false; | 1114 | return false; |
1115 | 1115 | ||
1116 | skb = ieee80211_nullfunc_get(sc->hw, vif); | 1116 | skb = ieee80211_nullfunc_get(sc->hw, vif, false); |
1117 | if (!skb) | 1117 | if (!skb) |
1118 | return false; | 1118 | return false; |
1119 | 1119 | ||
diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c index 03687a80d6e9..38678e9a0562 100644 --- a/drivers/net/wireless/st/cw1200/sta.c +++ b/drivers/net/wireless/st/cw1200/sta.c | |||
@@ -198,7 +198,7 @@ void __cw1200_cqm_bssloss_sm(struct cw1200_common *priv, | |||
198 | 198 | ||
199 | priv->bss_loss_state++; | 199 | priv->bss_loss_state++; |
200 | 200 | ||
201 | skb = ieee80211_nullfunc_get(priv->hw, priv->vif); | 201 | skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false); |
202 | WARN_ON(!skb); | 202 | WARN_ON(!skb); |
203 | if (skb) | 203 | if (skb) |
204 | cw1200_tx(priv->hw, NULL, skb); | 204 | cw1200_tx(priv->hw, NULL, skb); |
@@ -2265,7 +2265,7 @@ static int cw1200_upload_null(struct cw1200_common *priv) | |||
2265 | .rate = 0xFF, | 2265 | .rate = 0xFF, |
2266 | }; | 2266 | }; |
2267 | 2267 | ||
2268 | frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif); | 2268 | frame.skb = ieee80211_nullfunc_get(priv->hw, priv->vif, false); |
2269 | if (!frame.skb) | 2269 | if (!frame.skb) |
2270 | return -ENOMEM; | 2270 | return -ENOMEM; |
2271 | 2271 | ||
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index 9915d83a4a30..6d02c660b4ab 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c | |||
@@ -566,7 +566,7 @@ static int wl1251_build_null_data(struct wl1251 *wl) | |||
566 | size = sizeof(struct wl12xx_null_data_template); | 566 | size = sizeof(struct wl12xx_null_data_template); |
567 | ptr = NULL; | 567 | ptr = NULL; |
568 | } else { | 568 | } else { |
569 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif); | 569 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif, false); |
570 | if (!skb) | 570 | if (!skb) |
571 | goto out; | 571 | goto out; |
572 | size = skb->len; | 572 | size = skb->len; |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 2bfc12fdc929..761cf8573a80 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -1069,7 +1069,8 @@ int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
1069 | ptr = NULL; | 1069 | ptr = NULL; |
1070 | } else { | 1070 | } else { |
1071 | skb = ieee80211_nullfunc_get(wl->hw, | 1071 | skb = ieee80211_nullfunc_get(wl->hw, |
1072 | wl12xx_wlvif_to_vif(wlvif)); | 1072 | wl12xx_wlvif_to_vif(wlvif), |
1073 | false); | ||
1073 | if (!skb) | 1074 | if (!skb) |
1074 | goto out; | 1075 | goto out; |
1075 | size = skb->len; | 1076 | size = skb->len; |
@@ -1096,7 +1097,7 @@ int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, | |||
1096 | struct sk_buff *skb = NULL; | 1097 | struct sk_buff *skb = NULL; |
1097 | int ret = -ENOMEM; | 1098 | int ret = -ENOMEM; |
1098 | 1099 | ||
1099 | skb = ieee80211_nullfunc_get(wl->hw, vif); | 1100 | skb = ieee80211_nullfunc_get(wl->hw, vif, false); |
1100 | if (!skb) | 1101 | if (!skb) |
1101 | goto out; | 1102 | goto out; |
1102 | 1103 | ||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index cc9073e45be9..eec143cca1c0 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -4470,18 +4470,24 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, | |||
4470 | * ieee80211_nullfunc_get - retrieve a nullfunc template | 4470 | * ieee80211_nullfunc_get - retrieve a nullfunc template |
4471 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 4471 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
4472 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | 4472 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
4473 | * @qos_ok: QoS NDP is acceptable to the caller, this should be set | ||
4474 | * if at all possible | ||
4473 | * | 4475 | * |
4474 | * Creates a Nullfunc template which can, for example, uploaded to | 4476 | * Creates a Nullfunc template which can, for example, uploaded to |
4475 | * hardware. The template must be updated after association so that correct | 4477 | * hardware. The template must be updated after association so that correct |
4476 | * BSSID and address is used. | 4478 | * BSSID and address is used. |
4477 | * | 4479 | * |
4480 | * If @qos_ndp is set and the association is to an AP with QoS/WMM, the | ||
4481 | * returned packet will be QoS NDP. | ||
4482 | * | ||
4478 | * Note: Caller (or hardware) is responsible for setting the | 4483 | * Note: Caller (or hardware) is responsible for setting the |
4479 | * &IEEE80211_FCTL_PM bit as well as Duration and Sequence Control fields. | 4484 | * &IEEE80211_FCTL_PM bit as well as Duration and Sequence Control fields. |
4480 | * | 4485 | * |
4481 | * Return: The nullfunc template. %NULL on error. | 4486 | * Return: The nullfunc template. %NULL on error. |
4482 | */ | 4487 | */ |
4483 | struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, | 4488 | struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, |
4484 | struct ieee80211_vif *vif); | 4489 | struct ieee80211_vif *vif, |
4490 | bool qos_ok); | ||
4485 | 4491 | ||
4486 | /** | 4492 | /** |
4487 | * ieee80211_probereq_get - retrieve a Probe Request template | 4493 | * ieee80211_probereq_get - retrieve a Probe Request template |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 41f5e48f8021..167f83b853e6 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -292,7 +292,6 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, | |||
292 | 292 | ||
293 | mutex_lock(&sta->ampdu_mlme.mtx); | 293 | mutex_lock(&sta->ampdu_mlme.mtx); |
294 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { | 294 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { |
295 | ___ieee80211_stop_tx_ba_session(sta, i, reason); | ||
296 | ___ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, | 295 | ___ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, |
297 | WLAN_REASON_QSTA_LEAVE_QBSS, | 296 | WLAN_REASON_QSTA_LEAVE_QBSS, |
298 | reason != AGG_STOP_DESTROY_STA && | 297 | reason != AGG_STOP_DESTROY_STA && |
@@ -300,6 +299,9 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, | |||
300 | } | 299 | } |
301 | mutex_unlock(&sta->ampdu_mlme.mtx); | 300 | mutex_unlock(&sta->ampdu_mlme.mtx); |
302 | 301 | ||
302 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) | ||
303 | ___ieee80211_stop_tx_ba_session(sta, i, reason); | ||
304 | |||
303 | /* stopping might queue the work again - so cancel only afterwards */ | 305 | /* stopping might queue the work again - so cancel only afterwards */ |
304 | cancel_work_sync(&sta->ampdu_mlme.work); | 306 | cancel_work_sync(&sta->ampdu_mlme.work); |
305 | 307 | ||
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 4f7826d7b47c..4394463a0c2e 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -797,7 +797,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
797 | struct mesh_path *mpath; | 797 | struct mesh_path *mpath; |
798 | u8 ttl, flags, hopcount; | 798 | u8 ttl, flags, hopcount; |
799 | const u8 *orig_addr; | 799 | const u8 *orig_addr; |
800 | u32 orig_sn, metric, metric_txsta, interval; | 800 | u32 orig_sn, new_metric, orig_metric, last_hop_metric, interval; |
801 | bool root_is_gate; | 801 | bool root_is_gate; |
802 | 802 | ||
803 | ttl = rann->rann_ttl; | 803 | ttl = rann->rann_ttl; |
@@ -808,7 +808,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
808 | interval = le32_to_cpu(rann->rann_interval); | 808 | interval = le32_to_cpu(rann->rann_interval); |
809 | hopcount = rann->rann_hopcount; | 809 | hopcount = rann->rann_hopcount; |
810 | hopcount++; | 810 | hopcount++; |
811 | metric = le32_to_cpu(rann->rann_metric); | 811 | orig_metric = le32_to_cpu(rann->rann_metric); |
812 | 812 | ||
813 | /* Ignore our own RANNs */ | 813 | /* Ignore our own RANNs */ |
814 | if (ether_addr_equal(orig_addr, sdata->vif.addr)) | 814 | if (ether_addr_equal(orig_addr, sdata->vif.addr)) |
@@ -825,7 +825,10 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
825 | return; | 825 | return; |
826 | } | 826 | } |
827 | 827 | ||
828 | metric_txsta = airtime_link_metric_get(local, sta); | 828 | last_hop_metric = airtime_link_metric_get(local, sta); |
829 | new_metric = orig_metric + last_hop_metric; | ||
830 | if (new_metric < orig_metric) | ||
831 | new_metric = MAX_METRIC; | ||
829 | 832 | ||
830 | mpath = mesh_path_lookup(sdata, orig_addr); | 833 | mpath = mesh_path_lookup(sdata, orig_addr); |
831 | if (!mpath) { | 834 | if (!mpath) { |
@@ -838,7 +841,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
838 | } | 841 | } |
839 | 842 | ||
840 | if (!(SN_LT(mpath->sn, orig_sn)) && | 843 | if (!(SN_LT(mpath->sn, orig_sn)) && |
841 | !(mpath->sn == orig_sn && metric < mpath->rann_metric)) { | 844 | !(mpath->sn == orig_sn && new_metric < mpath->rann_metric)) { |
842 | rcu_read_unlock(); | 845 | rcu_read_unlock(); |
843 | return; | 846 | return; |
844 | } | 847 | } |
@@ -856,7 +859,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
856 | } | 859 | } |
857 | 860 | ||
858 | mpath->sn = orig_sn; | 861 | mpath->sn = orig_sn; |
859 | mpath->rann_metric = metric + metric_txsta; | 862 | mpath->rann_metric = new_metric; |
860 | mpath->is_root = true; | 863 | mpath->is_root = true; |
861 | /* Recording RANNs sender address to send individually | 864 | /* Recording RANNs sender address to send individually |
862 | * addressed PREQs destined for root mesh STA */ | 865 | * addressed PREQs destined for root mesh STA */ |
@@ -876,7 +879,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
876 | mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, | 879 | mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, |
877 | orig_sn, 0, NULL, 0, broadcast_addr, | 880 | orig_sn, 0, NULL, 0, broadcast_addr, |
878 | hopcount, ttl, interval, | 881 | hopcount, ttl, interval, |
879 | metric + metric_txsta, 0, sdata); | 882 | new_metric, 0, sdata); |
880 | } | 883 | } |
881 | 884 | ||
882 | rcu_read_unlock(); | 885 | rcu_read_unlock(); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 04460440d731..c244691deab9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -895,7 +895,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
895 | struct ieee80211_hdr_3addr *nullfunc; | 895 | struct ieee80211_hdr_3addr *nullfunc; |
896 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 896 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
897 | 897 | ||
898 | skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif); | 898 | skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif, true); |
899 | if (!skb) | 899 | if (!skb) |
900 | return; | 900 | return; |
901 | 901 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 7b8154474b9e..3160954fc406 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -4438,13 +4438,15 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw, | |||
4438 | EXPORT_SYMBOL(ieee80211_pspoll_get); | 4438 | EXPORT_SYMBOL(ieee80211_pspoll_get); |
4439 | 4439 | ||
4440 | struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, | 4440 | struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, |
4441 | struct ieee80211_vif *vif) | 4441 | struct ieee80211_vif *vif, |
4442 | bool qos_ok) | ||
4442 | { | 4443 | { |
4443 | struct ieee80211_hdr_3addr *nullfunc; | 4444 | struct ieee80211_hdr_3addr *nullfunc; |
4444 | struct ieee80211_sub_if_data *sdata; | 4445 | struct ieee80211_sub_if_data *sdata; |
4445 | struct ieee80211_if_managed *ifmgd; | 4446 | struct ieee80211_if_managed *ifmgd; |
4446 | struct ieee80211_local *local; | 4447 | struct ieee80211_local *local; |
4447 | struct sk_buff *skb; | 4448 | struct sk_buff *skb; |
4449 | bool qos = false; | ||
4448 | 4450 | ||
4449 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) | 4451 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) |
4450 | return NULL; | 4452 | return NULL; |
@@ -4453,7 +4455,17 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, | |||
4453 | ifmgd = &sdata->u.mgd; | 4455 | ifmgd = &sdata->u.mgd; |
4454 | local = sdata->local; | 4456 | local = sdata->local; |
4455 | 4457 | ||
4456 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*nullfunc)); | 4458 | if (qos_ok) { |
4459 | struct sta_info *sta; | ||
4460 | |||
4461 | rcu_read_lock(); | ||
4462 | sta = sta_info_get(sdata, ifmgd->bssid); | ||
4463 | qos = sta && sta->sta.wme; | ||
4464 | rcu_read_unlock(); | ||
4465 | } | ||
4466 | |||
4467 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
4468 | sizeof(*nullfunc) + 2); | ||
4457 | if (!skb) | 4469 | if (!skb) |
4458 | return NULL; | 4470 | return NULL; |
4459 | 4471 | ||
@@ -4463,6 +4475,19 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, | |||
4463 | nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | | 4475 | nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | |
4464 | IEEE80211_STYPE_NULLFUNC | | 4476 | IEEE80211_STYPE_NULLFUNC | |
4465 | IEEE80211_FCTL_TODS); | 4477 | IEEE80211_FCTL_TODS); |
4478 | if (qos) { | ||
4479 | __le16 qos = cpu_to_le16(7); | ||
4480 | |||
4481 | BUILD_BUG_ON((IEEE80211_STYPE_QOS_NULLFUNC | | ||
4482 | IEEE80211_STYPE_NULLFUNC) != | ||
4483 | IEEE80211_STYPE_QOS_NULLFUNC); | ||
4484 | nullfunc->frame_control |= | ||
4485 | cpu_to_le16(IEEE80211_STYPE_QOS_NULLFUNC); | ||
4486 | skb->priority = 7; | ||
4487 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); | ||
4488 | skb_put_data(skb, &qos, sizeof(qos)); | ||
4489 | } | ||
4490 | |||
4466 | memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN); | 4491 | memcpy(nullfunc->addr1, ifmgd->bssid, ETH_ALEN); |
4467 | memcpy(nullfunc->addr2, vif->addr, ETH_ALEN); | 4492 | memcpy(nullfunc->addr2, vif->addr, ETH_ALEN); |
4468 | memcpy(nullfunc->addr3, ifmgd->bssid, ETH_ALEN); | 4493 | memcpy(nullfunc->addr3, ifmgd->bssid, ETH_ALEN); |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index da91bb547db3..1abcc4fc4df1 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -20,6 +20,10 @@ config CFG80211 | |||
20 | tristate "cfg80211 - wireless configuration API" | 20 | tristate "cfg80211 - wireless configuration API" |
21 | depends on RFKILL || !RFKILL | 21 | depends on RFKILL || !RFKILL |
22 | select FW_LOADER | 22 | select FW_LOADER |
23 | # may need to update this when certificates are changed and are | ||
24 | # using a different algorithm, though right now they shouldn't | ||
25 | # (this is here rather than below to allow it to be a module) | ||
26 | select CRYPTO_SHA256 if CFG80211_USE_KERNEL_REGDB_KEYS | ||
23 | ---help--- | 27 | ---help--- |
24 | cfg80211 is the Linux wireless LAN (802.11) configuration API. | 28 | cfg80211 is the Linux wireless LAN (802.11) configuration API. |
25 | Enable this if you have a wireless device. | 29 | Enable this if you have a wireless device. |
@@ -113,6 +117,9 @@ config CFG80211_EXTRA_REGDB_KEYDIR | |||
113 | certificates like in the kernel sources (net/wireless/certs/) | 117 | certificates like in the kernel sources (net/wireless/certs/) |
114 | that shall be accepted for a signed regulatory database. | 118 | that shall be accepted for a signed regulatory database. |
115 | 119 | ||
120 | Note that you need to also select the correct CRYPTO_<hash> modules | ||
121 | for your certificates, and if cfg80211 is built-in they also must be. | ||
122 | |||
116 | config CFG80211_REG_CELLULAR_HINTS | 123 | config CFG80211_REG_CELLULAR_HINTS |
117 | bool "cfg80211 regulatory support for cellular base station hints" | 124 | bool "cfg80211 regulatory support for cellular base station hints" |
118 | depends on CFG80211_CERTIFICATION_ONUS | 125 | depends on CFG80211_CERTIFICATION_ONUS |