aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-11-27 11:09:42 -0500
committerDavid S. Miller <davem@davemloft.net>2017-11-27 11:09:42 -0500
commitd3fe1e0185cffabc9b6f73f246a5552b46af7131 (patch)
treea2a897425ab99d849b095ed8764f669e282ccc1e
parent6b56b1a255bda11fcec0b5f4f8ac7dcec43808af (diff)
parent72e2c3438ba3bd2ed640b6b5ea9e58993dd9ab7f (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.c2
-rw-r--r--drivers/net/wireless/st/cw1200/sta.c4
-rw-r--r--drivers/net/wireless/ti/wl1251/main.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.c5
-rw-r--r--include/net/mac80211.h8
-rw-r--r--net/mac80211/ht.c4
-rw-r--r--net/mac80211/mesh_hwmp.c15
-rw-r--r--net/mac80211/mlme.c2
-rw-r--r--net/mac80211/tx.c29
-rw-r--r--net/wireless/Kconfig7
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 */
4483struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, 4488struct 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,
4438EXPORT_SYMBOL(ieee80211_pspoll_get); 4438EXPORT_SYMBOL(ieee80211_pspoll_get);
4439 4439
4440struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, 4440struct 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
116config CFG80211_REG_CELLULAR_HINTS 123config 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