diff options
author | John W. Linville <linville@tuxdriver.com> | 2013-02-12 11:06:52 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-02-12 11:06:52 -0500 |
commit | 4fe0c75eedb15af13859ef123db17fefed5af7ae (patch) | |
tree | 6ed38d8e2e0ae457d10a2af2e496e9ecb4d34e08 | |
parent | 8457703f1e86aaf0f134402dd1e09e1f13e65222 (diff) | |
parent | 9c35d7d2368f54313b988a01c408e5cf863ffd9e (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
49 files changed, 720 insertions, 522 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 259c43332fb8..a29f04e30830 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -767,7 +767,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, | |||
767 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n", | 767 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n", |
768 | nw_type & ADHOC_CREATOR ? "creator" : "joiner"); | 768 | nw_type & ADHOC_CREATOR ? "creator" : "joiner"); |
769 | cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); | 769 | cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); |
770 | cfg80211_put_bss(bss); | 770 | cfg80211_put_bss(ar->wiphy, bss); |
771 | return; | 771 | return; |
772 | } | 772 | } |
773 | 773 | ||
@@ -778,7 +778,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, | |||
778 | assoc_req_ie, assoc_req_len, | 778 | assoc_req_ie, assoc_req_len, |
779 | assoc_resp_ie, assoc_resp_len, | 779 | assoc_resp_ie, assoc_resp_len, |
780 | WLAN_STATUS_SUCCESS, GFP_KERNEL); | 780 | WLAN_STATUS_SUCCESS, GFP_KERNEL); |
781 | cfg80211_put_bss(bss); | 781 | cfg80211_put_bss(ar->wiphy, bss); |
782 | } else if (vif->sme_state == SME_CONNECTED) { | 782 | } else if (vif->sme_state == SME_CONNECTED) { |
783 | /* inform roam event to cfg80211 */ | 783 | /* inform roam event to cfg80211 */ |
784 | cfg80211_roamed_bss(vif->ndev, bss, assoc_req_ie, assoc_req_len, | 784 | cfg80211_roamed_bss(vif->ndev, bss, assoc_req_ie, assoc_req_len, |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 998f8b0f62fd..d366cf105c7c 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -1108,7 +1108,7 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len, | |||
1108 | kfree(mgmt); | 1108 | kfree(mgmt); |
1109 | if (bss == NULL) | 1109 | if (bss == NULL) |
1110 | return -ENOMEM; | 1110 | return -ENOMEM; |
1111 | cfg80211_put_bss(bss); | 1111 | cfg80211_put_bss(ar->wiphy, bss); |
1112 | 1112 | ||
1113 | /* | 1113 | /* |
1114 | * Firmware doesn't return any event when scheduled scan has | 1114 | * Firmware doesn't return any event when scheduled scan has |
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 002851fceb2f..9ecc1968262c 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
@@ -341,7 +341,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, | |||
341 | } | 341 | } |
342 | 342 | ||
343 | out: | 343 | out: |
344 | cfg80211_put_bss(bss); | 344 | cfg80211_put_bss(wiphy, bss); |
345 | 345 | ||
346 | return rc; | 346 | return rc; |
347 | } | 347 | } |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 0b70e17cd1fb..79d608caa903 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -338,7 +338,7 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) | |||
338 | if (bss) { | 338 | if (bss) { |
339 | wil_dbg_wmi(wil, "Added BSS %pM\n", | 339 | wil_dbg_wmi(wil, "Added BSS %pM\n", |
340 | rx_mgmt_frame->bssid); | 340 | rx_mgmt_frame->bssid); |
341 | cfg80211_put_bss(bss); | 341 | cfg80211_put_bss(wiphy, bss); |
342 | } else { | 342 | } else { |
343 | wil_err(wil, "cfg80211_inform_bss() failed\n"); | 343 | wil_err(wil, "cfg80211_inform_bss() failed\n"); |
344 | } | 344 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 481f41ad7989..cecc3eff72e9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -2323,7 +2323,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, | |||
2323 | if (!bss) | 2323 | if (!bss) |
2324 | return -ENOMEM; | 2324 | return -ENOMEM; |
2325 | 2325 | ||
2326 | cfg80211_put_bss(bss); | 2326 | cfg80211_put_bss(wiphy, bss); |
2327 | 2327 | ||
2328 | return err; | 2328 | return err; |
2329 | } | 2329 | } |
@@ -2429,7 +2429,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg, | |||
2429 | goto CleanUp; | 2429 | goto CleanUp; |
2430 | } | 2430 | } |
2431 | 2431 | ||
2432 | cfg80211_put_bss(bss); | 2432 | cfg80211_put_bss(wiphy, bss); |
2433 | 2433 | ||
2434 | CleanUp: | 2434 | CleanUp: |
2435 | 2435 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 75f6f6cfdd47..0fccf725a2e6 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -151,8 +151,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
151 | IEEE80211_HW_QUEUE_CONTROL | | 151 | IEEE80211_HW_QUEUE_CONTROL | |
152 | IEEE80211_HW_SUPPORTS_PS | | 152 | IEEE80211_HW_SUPPORTS_PS | |
153 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | | 153 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | |
154 | IEEE80211_HW_WANT_MONITOR_VIF | | 154 | IEEE80211_HW_WANT_MONITOR_VIF; |
155 | IEEE80211_HW_SCAN_WHILE_IDLE; | ||
156 | 155 | ||
157 | hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE; | 156 | hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE; |
158 | hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FMT; | 157 | hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FMT; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index ce6127caabdf..bbb8a5b35662 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -113,7 +113,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
113 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | 113 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | |
114 | IEEE80211_HW_QUEUE_CONTROL | | 114 | IEEE80211_HW_QUEUE_CONTROL | |
115 | IEEE80211_HW_WANT_MONITOR_VIF | | 115 | IEEE80211_HW_WANT_MONITOR_VIF | |
116 | IEEE80211_HW_SCAN_WHILE_IDLE | | ||
117 | IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | | 116 | IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | |
118 | IEEE80211_HW_SUPPORTS_PS | | 117 | IEEE80211_HW_SUPPORTS_PS | |
119 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | | 118 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 230f8ebbe289..61735db3b051 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -657,7 +657,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | |||
657 | capa, intvl, ie, ielen, | 657 | capa, intvl, ie, ielen, |
658 | LBS_SCAN_RSSI_TO_MBM(rssi), | 658 | LBS_SCAN_RSSI_TO_MBM(rssi), |
659 | GFP_KERNEL); | 659 | GFP_KERNEL); |
660 | cfg80211_put_bss(bss); | 660 | cfg80211_put_bss(wiphy, bss); |
661 | } | 661 | } |
662 | } else | 662 | } else |
663 | lbs_deb_scan("scan response: missing BSS channel IE\n"); | 663 | lbs_deb_scan("scan response: missing BSS channel IE\n"); |
@@ -1444,7 +1444,7 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, | |||
1444 | 1444 | ||
1445 | done: | 1445 | done: |
1446 | if (bss) | 1446 | if (bss) |
1447 | cfg80211_put_bss(bss); | 1447 | cfg80211_put_bss(wiphy, bss); |
1448 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | 1448 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); |
1449 | return ret; | 1449 | return ret; |
1450 | } | 1450 | } |
@@ -1766,7 +1766,7 @@ static void lbs_join_post(struct lbs_private *priv, | |||
1766 | params->beacon_interval, | 1766 | params->beacon_interval, |
1767 | fake_ie, fake - fake_ie, | 1767 | fake_ie, fake - fake_ie, |
1768 | 0, GFP_KERNEL); | 1768 | 0, GFP_KERNEL); |
1769 | cfg80211_put_bss(bss); | 1769 | cfg80211_put_bss(priv->wdev->wiphy, bss); |
1770 | 1770 | ||
1771 | memcpy(priv->wdev->ssid, params->ssid, params->ssid_len); | 1771 | memcpy(priv->wdev->ssid, params->ssid, params->ssid_len); |
1772 | priv->wdev->ssid_len = params->ssid_len; | 1772 | priv->wdev->ssid_len = params->ssid_len; |
@@ -2011,7 +2011,7 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev, | |||
2011 | 2011 | ||
2012 | if (bss) { | 2012 | if (bss) { |
2013 | ret = lbs_ibss_join_existing(priv, params, bss); | 2013 | ret = lbs_ibss_join_existing(priv, params, bss); |
2014 | cfg80211_put_bss(bss); | 2014 | cfg80211_put_bss(wiphy, bss); |
2015 | } else | 2015 | } else |
2016 | ret = lbs_ibss_start_new(priv, params); | 2016 | ret = lbs_ibss_start_new(priv, params); |
2017 | 2017 | ||
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 3a004b85b99f..81c84a29308f 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1430,7 +1430,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) | |||
1430 | bss = cfg80211_inform_bss(priv->wdev->wiphy, chan, | 1430 | bss = cfg80211_inform_bss(priv->wdev->wiphy, chan, |
1431 | bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, | 1431 | bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, |
1432 | 0, ie_buf, ie_len, 0, GFP_KERNEL); | 1432 | 0, ie_buf, ie_len, 0, GFP_KERNEL); |
1433 | cfg80211_put_bss(bss); | 1433 | cfg80211_put_bss(priv->wdev->wiphy, bss); |
1434 | memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); | 1434 | memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); |
1435 | 1435 | ||
1436 | return 0; | 1436 | return 0; |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 9189a32b7844..232492487527 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1746,7 +1746,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1746 | .mac_address, ETH_ALEN)) | 1746 | .mac_address, ETH_ALEN)) |
1747 | mwifiex_update_curr_bss_params(priv, | 1747 | mwifiex_update_curr_bss_params(priv, |
1748 | bss); | 1748 | bss); |
1749 | cfg80211_put_bss(bss); | 1749 | cfg80211_put_bss(priv->wdev->wiphy, bss); |
1750 | } | 1750 | } |
1751 | } else { | 1751 | } else { |
1752 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); | 1752 | dev_dbg(adapter->dev, "missing BSS channel IE\n"); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index f542bb8ccbc8..0d018460daf9 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -162,13 +162,9 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | |||
162 | 162 | ||
163 | rcu_read_lock(); | 163 | rcu_read_lock(); |
164 | ies = rcu_dereference(bss->ies); | 164 | ies = rcu_dereference(bss->ies); |
165 | if (WARN_ON(!ies)) { | ||
166 | /* should never happen */ | ||
167 | rcu_read_unlock(); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC); | 165 | beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC); |
171 | beacon_ie_len = ies->len; | 166 | beacon_ie_len = ies->len; |
167 | bss_desc->timestamp = ies->tsf; | ||
172 | rcu_read_unlock(); | 168 | rcu_read_unlock(); |
173 | 169 | ||
174 | if (!beacon_ie) { | 170 | if (!beacon_ie) { |
@@ -184,7 +180,6 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, | |||
184 | bss_desc->cap_info_bitmap = bss->capability; | 180 | bss_desc->cap_info_bitmap = bss->capability; |
185 | bss_desc->bss_band = bss_priv->band; | 181 | bss_desc->bss_band = bss_priv->band; |
186 | bss_desc->fw_tsf = bss_priv->fw_tsf; | 182 | bss_desc->fw_tsf = bss_priv->fw_tsf; |
187 | bss_desc->timestamp = bss->tsf; | ||
188 | if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { | 183 | if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { |
189 | dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n"); | 184 | dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n"); |
190 | bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; | 185 | bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; |
@@ -324,7 +319,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
324 | } | 319 | } |
325 | 320 | ||
326 | if (bss) | 321 | if (bss) |
327 | cfg80211_put_bss(bss); | 322 | cfg80211_put_bss(priv->adapter->wiphy, bss); |
328 | } else { | 323 | } else { |
329 | /* Adhoc mode */ | 324 | /* Adhoc mode */ |
330 | /* If the requested SSID matches current SSID, return */ | 325 | /* If the requested SSID matches current SSID, return */ |
@@ -354,7 +349,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
354 | " list. Joining...\n"); | 349 | " list. Joining...\n"); |
355 | ret = mwifiex_adhoc_join(priv, bss_desc); | 350 | ret = mwifiex_adhoc_join(priv, bss_desc); |
356 | if (bss) | 351 | if (bss) |
357 | cfg80211_put_bss(bss); | 352 | cfg80211_put_bss(priv->adapter->wiphy, bss); |
358 | } else { | 353 | } else { |
359 | dev_dbg(adapter->dev, "info: Network not found in " | 354 | dev_dbg(adapter->dev, "info: Network not found in " |
360 | "the list, creating adhoc with ssid = %s\n", | 355 | "the list, creating adhoc with ssid = %s\n", |
diff --git a/drivers/net/wireless/orinoco/scan.c b/drivers/net/wireless/orinoco/scan.c index 96e39edfec77..e8c5714bfd11 100644 --- a/drivers/net/wireless/orinoco/scan.c +++ b/drivers/net/wireless/orinoco/scan.c | |||
@@ -125,7 +125,7 @@ static void orinoco_add_hostscan_result(struct orinoco_private *priv, | |||
125 | cbss = cfg80211_inform_bss(wiphy, channel, bss->a.bssid, timestamp, | 125 | cbss = cfg80211_inform_bss(wiphy, channel, bss->a.bssid, timestamp, |
126 | capability, beacon_interval, ie_buf, ie_len, | 126 | capability, beacon_interval, ie_buf, ie_len, |
127 | signal, GFP_KERNEL); | 127 | signal, GFP_KERNEL); |
128 | cfg80211_put_bss(cbss); | 128 | cfg80211_put_bss(wiphy, cbss); |
129 | } | 129 | } |
130 | 130 | ||
131 | void orinoco_add_extscan_result(struct orinoco_private *priv, | 131 | void orinoco_add_extscan_result(struct orinoco_private *priv, |
@@ -158,7 +158,7 @@ void orinoco_add_extscan_result(struct orinoco_private *priv, | |||
158 | cbss = cfg80211_inform_bss(wiphy, channel, bss->bssid, timestamp, | 158 | cbss = cfg80211_inform_bss(wiphy, channel, bss->bssid, timestamp, |
159 | capability, beacon_interval, ie, ie_len, | 159 | capability, beacon_interval, ie, ie_len, |
160 | signal, GFP_KERNEL); | 160 | signal, GFP_KERNEL); |
161 | cfg80211_put_bss(cbss); | 161 | cfg80211_put_bss(wiphy, cbss); |
162 | } | 162 | } |
163 | 163 | ||
164 | void orinoco_add_hostscan_results(struct orinoco_private *priv, | 164 | void orinoco_add_hostscan_results(struct orinoco_private *priv, |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index abe1d039be81..fe2f272689aa 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -2029,7 +2029,7 @@ static bool rndis_bss_info_update(struct usbnet *usbdev, | |||
2029 | bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid->mac, | 2029 | bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid->mac, |
2030 | timestamp, capability, beacon_interval, ie, ie_len, signal, | 2030 | timestamp, capability, beacon_interval, ie, ie_len, signal, |
2031 | GFP_KERNEL); | 2031 | GFP_KERNEL); |
2032 | cfg80211_put_bss(bss); | 2032 | cfg80211_put_bss(priv->wdev.wiphy, bss); |
2033 | 2033 | ||
2034 | return (bss != NULL); | 2034 | return (bss != NULL); |
2035 | } | 2035 | } |
@@ -2718,7 +2718,7 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, | |||
2718 | bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid, | 2718 | bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid, |
2719 | timestamp, capability, beacon_period, ie_buf, ie_len, | 2719 | timestamp, capability, beacon_period, ie_buf, ie_len, |
2720 | signal, GFP_KERNEL); | 2720 | signal, GFP_KERNEL); |
2721 | cfg80211_put_bss(bss); | 2721 | cfg80211_put_bss(priv->wdev.wiphy, bss); |
2722 | } | 2722 | } |
2723 | 2723 | ||
2724 | /* | 2724 | /* |
diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c index 5ec50a476a69..74ae8e1c2e33 100644 --- a/drivers/net/wireless/ti/wl1251/event.c +++ b/drivers/net/wireless/ti/wl1251/event.c | |||
@@ -29,6 +29,8 @@ | |||
29 | static int wl1251_event_scan_complete(struct wl1251 *wl, | 29 | static int wl1251_event_scan_complete(struct wl1251 *wl, |
30 | struct event_mailbox *mbox) | 30 | struct event_mailbox *mbox) |
31 | { | 31 | { |
32 | int ret = 0; | ||
33 | |||
32 | wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d", | 34 | wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d", |
33 | mbox->scheduled_scan_status, | 35 | mbox->scheduled_scan_status, |
34 | mbox->scheduled_scan_channels); | 36 | mbox->scheduled_scan_channels); |
@@ -37,9 +39,11 @@ static int wl1251_event_scan_complete(struct wl1251 *wl, | |||
37 | ieee80211_scan_completed(wl->hw, false); | 39 | ieee80211_scan_completed(wl->hw, false); |
38 | wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed"); | 40 | wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed"); |
39 | wl->scanning = false; | 41 | wl->scanning = false; |
42 | if (wl->hw->conf.flags & IEEE80211_CONF_IDLE) | ||
43 | ret = wl1251_ps_set_mode(wl, STATION_IDLE); | ||
40 | } | 44 | } |
41 | 45 | ||
42 | return 0; | 46 | return ret; |
43 | } | 47 | } |
44 | 48 | ||
45 | static void wl1251_event_mbox_dump(struct event_mailbox *mbox) | 49 | static void wl1251_event_mbox_dump(struct event_mailbox *mbox) |
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index f47e8b0482ad..bbbf68cf50a7 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c | |||
@@ -623,7 +623,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | |||
623 | } | 623 | } |
624 | } | 624 | } |
625 | 625 | ||
626 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 626 | if (changed & IEEE80211_CONF_CHANGE_IDLE && !wl->scanning) { |
627 | if (conf->flags & IEEE80211_CONF_IDLE) { | 627 | if (conf->flags & IEEE80211_CONF_IDLE) { |
628 | ret = wl1251_ps_set_mode(wl, STATION_IDLE); | 628 | ret = wl1251_ps_set_mode(wl, STATION_IDLE); |
629 | if (ret < 0) | 629 | if (ret < 0) |
@@ -895,11 +895,21 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, | |||
895 | if (ret < 0) | 895 | if (ret < 0) |
896 | goto out; | 896 | goto out; |
897 | 897 | ||
898 | if (hw->conf.flags & IEEE80211_CONF_IDLE) { | ||
899 | ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); | ||
900 | if (ret < 0) | ||
901 | goto out_sleep; | ||
902 | ret = wl1251_join(wl, wl->bss_type, wl->channel, | ||
903 | wl->beacon_int, wl->dtim_period); | ||
904 | if (ret < 0) | ||
905 | goto out_sleep; | ||
906 | } | ||
907 | |||
898 | skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, | 908 | skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, |
899 | req->ie_len); | 909 | req->ie_len); |
900 | if (!skb) { | 910 | if (!skb) { |
901 | ret = -ENOMEM; | 911 | ret = -ENOMEM; |
902 | goto out; | 912 | goto out_idle; |
903 | } | 913 | } |
904 | if (req->ie_len) | 914 | if (req->ie_len) |
905 | memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len); | 915 | memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len); |
@@ -908,11 +918,11 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, | |||
908 | skb->len); | 918 | skb->len); |
909 | dev_kfree_skb(skb); | 919 | dev_kfree_skb(skb); |
910 | if (ret < 0) | 920 | if (ret < 0) |
911 | goto out_sleep; | 921 | goto out_idle; |
912 | 922 | ||
913 | ret = wl1251_cmd_trigger_scan_to(wl, 0); | 923 | ret = wl1251_cmd_trigger_scan_to(wl, 0); |
914 | if (ret < 0) | 924 | if (ret < 0) |
915 | goto out_sleep; | 925 | goto out_idle; |
916 | 926 | ||
917 | wl->scanning = true; | 927 | wl->scanning = true; |
918 | 928 | ||
@@ -920,9 +930,13 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, | |||
920 | req->n_channels, WL1251_SCAN_NUM_PROBES); | 930 | req->n_channels, WL1251_SCAN_NUM_PROBES); |
921 | if (ret < 0) { | 931 | if (ret < 0) { |
922 | wl->scanning = false; | 932 | wl->scanning = false; |
923 | goto out_sleep; | 933 | goto out_idle; |
924 | } | 934 | } |
935 | goto out_sleep; | ||
925 | 936 | ||
937 | out_idle: | ||
938 | if (hw->conf.flags & IEEE80211_CONF_IDLE) | ||
939 | ret = wl1251_ps_set_mode(wl, STATION_IDLE); | ||
926 | out_sleep: | 940 | out_sleep: |
927 | wl1251_ps_elp_sleep(wl); | 941 | wl1251_ps_elp_sleep(wl); |
928 | 942 | ||
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 28a37576d568..2c2ff3e1f849 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -5636,7 +5636,6 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5636 | IEEE80211_HW_AP_LINK_PS | | 5636 | IEEE80211_HW_AP_LINK_PS | |
5637 | IEEE80211_HW_AMPDU_AGGREGATION | | 5637 | IEEE80211_HW_AMPDU_AGGREGATION | |
5638 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW | | 5638 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW | |
5639 | IEEE80211_HW_SCAN_WHILE_IDLE | | ||
5640 | IEEE80211_HW_QUEUE_CONTROL; | 5639 | IEEE80211_HW_QUEUE_CONTROL; |
5641 | 5640 | ||
5642 | wl->hw->wiphy->cipher_suites = cipher_suites; | 5641 | wl->hw->wiphy->cipher_suites = cipher_suites; |
diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 18c06a59c091..a233f64ca22f 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c | |||
@@ -424,7 +424,7 @@ int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) | |||
424 | goto exit; | 424 | goto exit; |
425 | } | 425 | } |
426 | 426 | ||
427 | cfg80211_put_bss(bss); | 427 | cfg80211_put_bss(wiphy, bss); |
428 | } | 428 | } |
429 | 429 | ||
430 | if (result) | 430 | if (result) |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 3ec70e1681d3..77686ca28948 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -535,7 +535,7 @@ struct mac_address { | |||
535 | * struct cfg80211_acl_data - Access control list data | 535 | * struct cfg80211_acl_data - Access control list data |
536 | * | 536 | * |
537 | * @acl_policy: ACL policy to be applied on the station's | 537 | * @acl_policy: ACL policy to be applied on the station's |
538 | entry specified by mac_addr | 538 | * entry specified by mac_addr |
539 | * @n_acl_entries: Number of MAC address entries passed | 539 | * @n_acl_entries: Number of MAC address entries passed |
540 | * @mac_addrs: List of MAC addresses of stations to be used for ACL | 540 | * @mac_addrs: List of MAC addresses of stations to be used for ACL |
541 | */ | 541 | */ |
@@ -666,6 +666,8 @@ struct station_parameters { | |||
666 | * @STATION_INFO_INACTIVE_TIME: @inactive_time filled | 666 | * @STATION_INFO_INACTIVE_TIME: @inactive_time filled |
667 | * @STATION_INFO_RX_BYTES: @rx_bytes filled | 667 | * @STATION_INFO_RX_BYTES: @rx_bytes filled |
668 | * @STATION_INFO_TX_BYTES: @tx_bytes filled | 668 | * @STATION_INFO_TX_BYTES: @tx_bytes filled |
669 | * @STATION_INFO_RX_BYTES64: @rx_bytes filled with 64-bit value | ||
670 | * @STATION_INFO_TX_BYTES64: @tx_bytes filled with 64-bit value | ||
669 | * @STATION_INFO_LLID: @llid filled | 671 | * @STATION_INFO_LLID: @llid filled |
670 | * @STATION_INFO_PLID: @plid filled | 672 | * @STATION_INFO_PLID: @plid filled |
671 | * @STATION_INFO_PLINK_STATE: @plink_state filled | 673 | * @STATION_INFO_PLINK_STATE: @plink_state filled |
@@ -674,8 +676,6 @@ struct station_parameters { | |||
674 | * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) | 676 | * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) |
675 | * @STATION_INFO_RX_PACKETS: @rx_packets filled with 32-bit value | 677 | * @STATION_INFO_RX_PACKETS: @rx_packets filled with 32-bit value |
676 | * @STATION_INFO_TX_PACKETS: @tx_packets filled with 32-bit value | 678 | * @STATION_INFO_TX_PACKETS: @tx_packets filled with 32-bit value |
677 | * @STATION_INFO_RX_PACKETS64: @rx_packets filled with 64-bit value | ||
678 | * @STATION_INFO_TX_PACKETS64: @tx_packets filled with 64-bit value | ||
679 | * @STATION_INFO_TX_RETRIES: @tx_retries filled | 679 | * @STATION_INFO_TX_RETRIES: @tx_retries filled |
680 | * @STATION_INFO_TX_FAILED: @tx_failed filled | 680 | * @STATION_INFO_TX_FAILED: @tx_failed filled |
681 | * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled | 681 | * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled |
@@ -1226,6 +1226,7 @@ struct cfg80211_match_set { | |||
1226 | * @n_match_sets: number of match sets | 1226 | * @n_match_sets: number of match sets |
1227 | * @wiphy: the wiphy this was for | 1227 | * @wiphy: the wiphy this was for |
1228 | * @dev: the interface | 1228 | * @dev: the interface |
1229 | * @scan_start: start time of the scheduled scan | ||
1229 | * @channels: channels to scan | 1230 | * @channels: channels to scan |
1230 | * @rssi_thold: don't report scan results below this threshold (in s32 dBm) | 1231 | * @rssi_thold: don't report scan results below this threshold (in s32 dBm) |
1231 | */ | 1232 | */ |
@@ -1265,11 +1266,13 @@ enum cfg80211_signal_type { | |||
1265 | 1266 | ||
1266 | /** | 1267 | /** |
1267 | * struct cfg80211_bss_ie_data - BSS entry IE data | 1268 | * struct cfg80211_bss_ie_data - BSS entry IE data |
1269 | * @tsf: TSF contained in the frame that carried these IEs | ||
1268 | * @rcu_head: internal use, for freeing | 1270 | * @rcu_head: internal use, for freeing |
1269 | * @len: length of the IEs | 1271 | * @len: length of the IEs |
1270 | * @data: IE data | 1272 | * @data: IE data |
1271 | */ | 1273 | */ |
1272 | struct cfg80211_bss_ies { | 1274 | struct cfg80211_bss_ies { |
1275 | u64 tsf; | ||
1273 | struct rcu_head rcu_head; | 1276 | struct rcu_head rcu_head; |
1274 | int len; | 1277 | int len; |
1275 | u8 data[]; | 1278 | u8 data[]; |
@@ -1283,27 +1286,33 @@ struct cfg80211_bss_ies { | |||
1283 | * | 1286 | * |
1284 | * @channel: channel this BSS is on | 1287 | * @channel: channel this BSS is on |
1285 | * @bssid: BSSID of the BSS | 1288 | * @bssid: BSSID of the BSS |
1286 | * @tsf: timestamp of last received update | ||
1287 | * @beacon_interval: the beacon interval as from the frame | 1289 | * @beacon_interval: the beacon interval as from the frame |
1288 | * @capability: the capability field in host byte order | 1290 | * @capability: the capability field in host byte order |
1289 | * @ies: the information elements (Note that there | 1291 | * @ies: the information elements (Note that there is no guarantee that these |
1290 | * is no guarantee that these are well-formed!); this is a pointer to | 1292 | * are well-formed!); this is a pointer to either the beacon_ies or |
1291 | * either the beacon_ies or proberesp_ies depending on whether Probe | 1293 | * proberesp_ies depending on whether Probe Response frame has been |
1292 | * Response frame has been received | 1294 | * received. It is always non-%NULL. |
1293 | * @beacon_ies: the information elements from the last Beacon frame | 1295 | * @beacon_ies: the information elements from the last Beacon frame |
1296 | * (implementation note: if @hidden_beacon_bss is set this struct doesn't | ||
1297 | * own the beacon_ies, but they're just pointers to the ones from the | ||
1298 | * @hidden_beacon_bss struct) | ||
1294 | * @proberesp_ies: the information elements from the last Probe Response frame | 1299 | * @proberesp_ies: the information elements from the last Probe Response frame |
1300 | * @hidden_beacon_bss: in case this BSS struct represents a probe response from | ||
1301 | * a BSS that hides the SSID in its beacon, this points to the BSS struct | ||
1302 | * that holds the beacon data. @beacon_ies is still valid, of course, and | ||
1303 | * points to the same data as hidden_beacon_bss->beacon_ies in that case. | ||
1295 | * @signal: signal strength value (type depends on the wiphy's signal_type) | 1304 | * @signal: signal strength value (type depends on the wiphy's signal_type) |
1296 | * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes | 1305 | * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes |
1297 | */ | 1306 | */ |
1298 | struct cfg80211_bss { | 1307 | struct cfg80211_bss { |
1299 | u64 tsf; | ||
1300 | |||
1301 | struct ieee80211_channel *channel; | 1308 | struct ieee80211_channel *channel; |
1302 | 1309 | ||
1303 | const struct cfg80211_bss_ies __rcu *ies; | 1310 | const struct cfg80211_bss_ies __rcu *ies; |
1304 | const struct cfg80211_bss_ies __rcu *beacon_ies; | 1311 | const struct cfg80211_bss_ies __rcu *beacon_ies; |
1305 | const struct cfg80211_bss_ies __rcu *proberesp_ies; | 1312 | const struct cfg80211_bss_ies __rcu *proberesp_ies; |
1306 | 1313 | ||
1314 | struct cfg80211_bss *hidden_beacon_bss; | ||
1315 | |||
1307 | s32 signal; | 1316 | s32 signal; |
1308 | 1317 | ||
1309 | u16 beacon_interval; | 1318 | u16 beacon_interval; |
@@ -1404,6 +1413,8 @@ struct cfg80211_assoc_request { | |||
1404 | * @ie: Extra IEs to add to Deauthentication frame or %NULL | 1413 | * @ie: Extra IEs to add to Deauthentication frame or %NULL |
1405 | * @ie_len: Length of ie buffer in octets | 1414 | * @ie_len: Length of ie buffer in octets |
1406 | * @reason_code: The reason code for the deauthentication | 1415 | * @reason_code: The reason code for the deauthentication |
1416 | * @local_state_change: if set, change local state only and | ||
1417 | * do not set a deauth frame | ||
1407 | */ | 1418 | */ |
1408 | struct cfg80211_deauth_request { | 1419 | struct cfg80211_deauth_request { |
1409 | const u8 *bssid; | 1420 | const u8 *bssid; |
@@ -2629,7 +2640,6 @@ struct cfg80211_cached_keys; | |||
2629 | * the user-set AP, monitor and WDS channel | 2640 | * the user-set AP, monitor and WDS channel |
2630 | * @preset_chan: (private) Used by the internal configuration code to | 2641 | * @preset_chan: (private) Used by the internal configuration code to |
2631 | * track the channel to be used for AP later | 2642 | * track the channel to be used for AP later |
2632 | * @preset_chantype: (private) the corresponding channel type | ||
2633 | * @bssid: (private) Used by the internal configuration code | 2643 | * @bssid: (private) Used by the internal configuration code |
2634 | * @ssid: (private) Used by the internal configuration code | 2644 | * @ssid: (private) Used by the internal configuration code |
2635 | * @ssid_len: (private) Used by the internal configuration code | 2645 | * @ssid_len: (private) Used by the internal configuration code |
@@ -3166,19 +3176,21 @@ cfg80211_get_ibss(struct wiphy *wiphy, | |||
3166 | 3176 | ||
3167 | /** | 3177 | /** |
3168 | * cfg80211_ref_bss - reference BSS struct | 3178 | * cfg80211_ref_bss - reference BSS struct |
3179 | * @wiphy: the wiphy this BSS struct belongs to | ||
3169 | * @bss: the BSS struct to reference | 3180 | * @bss: the BSS struct to reference |
3170 | * | 3181 | * |
3171 | * Increments the refcount of the given BSS struct. | 3182 | * Increments the refcount of the given BSS struct. |
3172 | */ | 3183 | */ |
3173 | void cfg80211_ref_bss(struct cfg80211_bss *bss); | 3184 | void cfg80211_ref_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); |
3174 | 3185 | ||
3175 | /** | 3186 | /** |
3176 | * cfg80211_put_bss - unref BSS struct | 3187 | * cfg80211_put_bss - unref BSS struct |
3188 | * @wiphy: the wiphy this BSS struct belongs to | ||
3177 | * @bss: the BSS struct | 3189 | * @bss: the BSS struct |
3178 | * | 3190 | * |
3179 | * Decrements the refcount of the given BSS struct. | 3191 | * Decrements the refcount of the given BSS struct. |
3180 | */ | 3192 | */ |
3181 | void cfg80211_put_bss(struct cfg80211_bss *bss); | 3193 | void cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); |
3182 | 3194 | ||
3183 | /** | 3195 | /** |
3184 | * cfg80211_unlink_bss - unlink BSS from internal data structures | 3196 | * cfg80211_unlink_bss - unlink BSS from internal data structures |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 7da11211825d..0eaa9092364b 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -277,9 +277,16 @@ enum ieee80211_rssi_event { | |||
277 | * valid in station mode only if after the driver was notified | 277 | * valid in station mode only if after the driver was notified |
278 | * with the %BSS_CHANGED_DTIM_PERIOD flag, will be non-zero then. | 278 | * with the %BSS_CHANGED_DTIM_PERIOD flag, will be non-zero then. |
279 | * @sync_tsf: last beacon's/probe response's TSF timestamp (could be old | 279 | * @sync_tsf: last beacon's/probe response's TSF timestamp (could be old |
280 | * as it may have been received during scanning long ago) | 280 | * as it may have been received during scanning long ago). If the |
281 | * HW flag %IEEE80211_HW_TIMING_BEACON_ONLY is set, then this can | ||
282 | * only come from a beacon, but might not become valid until after | ||
283 | * association when a beacon is received (which is notified with the | ||
284 | * %BSS_CHANGED_DTIM flag.) | ||
281 | * @sync_device_ts: the device timestamp corresponding to the sync_tsf, | 285 | * @sync_device_ts: the device timestamp corresponding to the sync_tsf, |
282 | * the driver/device can use this to calculate synchronisation | 286 | * the driver/device can use this to calculate synchronisation |
287 | * (see @sync_tsf) | ||
288 | * @sync_dtim_count: Only valid when %IEEE80211_HW_TIMING_BEACON_ONLY | ||
289 | * is requested, see @sync_tsf/@sync_device_ts. | ||
283 | * @beacon_int: beacon interval | 290 | * @beacon_int: beacon interval |
284 | * @assoc_capability: capabilities taken from assoc resp | 291 | * @assoc_capability: capabilities taken from assoc resp |
285 | * @basic_rates: bitmap of basic rates, each bit stands for an | 292 | * @basic_rates: bitmap of basic rates, each bit stands for an |
@@ -331,6 +338,7 @@ struct ieee80211_bss_conf { | |||
331 | u16 assoc_capability; | 338 | u16 assoc_capability; |
332 | u64 sync_tsf; | 339 | u64 sync_tsf; |
333 | u32 sync_device_ts; | 340 | u32 sync_device_ts; |
341 | u8 sync_dtim_count; | ||
334 | u32 basic_rates; | 342 | u32 basic_rates; |
335 | int mcast_rate[IEEE80211_NUM_BANDS]; | 343 | int mcast_rate[IEEE80211_NUM_BANDS]; |
336 | u16 ht_operation_mode; | 344 | u16 ht_operation_mode; |
@@ -391,6 +399,9 @@ struct ieee80211_bss_conf { | |||
391 | * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be | 399 | * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be |
392 | * set by rate control algorithms to indicate probe rate, will | 400 | * set by rate control algorithms to indicate probe rate, will |
393 | * be cleared for fragmented frames (except on the last fragment) | 401 | * be cleared for fragmented frames (except on the last fragment) |
402 | * @IEEE80211_TX_INTFL_OFFCHAN_TX_OK: Internal to mac80211. Used to indicate | ||
403 | * that a frame can be transmitted while the queues are stopped for | ||
404 | * off-channel operation. | ||
394 | * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211, | 405 | * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211, |
395 | * used to indicate that a pending frame requires TX processing before | 406 | * used to indicate that a pending frame requires TX processing before |
396 | * it can be sent out. | 407 | * it can be sent out. |
@@ -456,6 +467,7 @@ enum mac80211_tx_control_flags { | |||
456 | IEEE80211_TX_STAT_AMPDU = BIT(10), | 467 | IEEE80211_TX_STAT_AMPDU = BIT(10), |
457 | IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), | 468 | IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), |
458 | IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), | 469 | IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), |
470 | IEEE80211_TX_INTFL_OFFCHAN_TX_OK = BIT(13), | ||
459 | IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), | 471 | IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), |
460 | IEEE80211_TX_INTFL_RETRIED = BIT(15), | 472 | IEEE80211_TX_INTFL_RETRIED = BIT(15), |
461 | IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), | 473 | IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), |
@@ -1355,10 +1367,6 @@ struct ieee80211_tx_control { | |||
1355 | * setup strictly in HW. mac80211 should not attempt to do this in | 1367 | * setup strictly in HW. mac80211 should not attempt to do this in |
1356 | * software. | 1368 | * software. |
1357 | * | 1369 | * |
1358 | * @IEEE80211_HW_SCAN_WHILE_IDLE: The device can do hw scan while | ||
1359 | * being idle (i.e. mac80211 doesn't have to go idle-off during the | ||
1360 | * the scan). | ||
1361 | * | ||
1362 | * @IEEE80211_HW_WANT_MONITOR_VIF: The driver would like to be informed of | 1370 | * @IEEE80211_HW_WANT_MONITOR_VIF: The driver would like to be informed of |
1363 | * a virtual monitor interface when monitor interfaces are the only | 1371 | * a virtual monitor interface when monitor interfaces are the only |
1364 | * active interfaces. | 1372 | * active interfaces. |
@@ -1371,6 +1379,9 @@ struct ieee80211_tx_control { | |||
1371 | * @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any | 1379 | * @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any |
1372 | * P2P Interface. This will be honoured even if more than one interface | 1380 | * P2P Interface. This will be honoured even if more than one interface |
1373 | * is supported. | 1381 | * is supported. |
1382 | * | ||
1383 | * @IEEE80211_HW_TIMING_BEACON_ONLY: Use sync timing from beacon frames | ||
1384 | * only, to allow getting TBTT of a DTIM beacon. | ||
1374 | */ | 1385 | */ |
1375 | enum ieee80211_hw_flags { | 1386 | enum ieee80211_hw_flags { |
1376 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, | 1387 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, |
@@ -1397,8 +1408,8 @@ enum ieee80211_hw_flags { | |||
1397 | IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21, | 1408 | IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21, |
1398 | IEEE80211_HW_AP_LINK_PS = 1<<22, | 1409 | IEEE80211_HW_AP_LINK_PS = 1<<22, |
1399 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, | 1410 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, |
1400 | IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24, | ||
1401 | IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, | 1411 | IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, |
1412 | IEEE80211_HW_TIMING_BEACON_ONLY = 1<<26, | ||
1402 | }; | 1413 | }; |
1403 | 1414 | ||
1404 | /** | 1415 | /** |
@@ -1683,15 +1694,6 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
1683 | * dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS | 1694 | * dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS |
1684 | * enabled whenever user has enabled powersave. | 1695 | * enabled whenever user has enabled powersave. |
1685 | * | 1696 | * |
1686 | * Some hardware need to toggle a single shared antenna between WLAN and | ||
1687 | * Bluetooth to facilitate co-existence. These types of hardware set | ||
1688 | * limitations on the use of host controlled dynamic powersave whenever there | ||
1689 | * is simultaneous WLAN and Bluetooth traffic. For these types of hardware, the | ||
1690 | * driver may request temporarily going into full power save, in order to | ||
1691 | * enable toggling the antenna between BT and WLAN. If the driver requests | ||
1692 | * disabling dynamic powersave, the @dynamic_ps_timeout value will be | ||
1693 | * temporarily set to zero until the driver re-enables dynamic powersave. | ||
1694 | * | ||
1695 | * Driver informs U-APSD client support by enabling | 1697 | * Driver informs U-APSD client support by enabling |
1696 | * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the | 1698 | * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the |
1697 | * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS | 1699 | * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS |
@@ -2167,6 +2169,18 @@ enum ieee80211_rate_control_changed { | |||
2167 | * MAC address of the device going away. | 2169 | * MAC address of the device going away. |
2168 | * Hence, this callback must be implemented. It can sleep. | 2170 | * Hence, this callback must be implemented. It can sleep. |
2169 | * | 2171 | * |
2172 | * @add_interface_debugfs: Drivers can use this callback to add debugfs files | ||
2173 | * when a vif is added to mac80211. This callback and | ||
2174 | * @remove_interface_debugfs should be within a CONFIG_MAC80211_DEBUGFS | ||
2175 | * conditional. @remove_interface_debugfs must be provided for cleanup. | ||
2176 | * This callback can sleep. | ||
2177 | * | ||
2178 | * @remove_interface_debugfs: Remove the debugfs files which were added using | ||
2179 | * @add_interface_debugfs. This callback must remove all debugfs entries | ||
2180 | * that were added because mac80211 only removes interface debugfs when the | ||
2181 | * interface is destroyed, not when it is removed from the driver. | ||
2182 | * This callback can sleep. | ||
2183 | * | ||
2170 | * @config: Handler for configuration requests. IEEE 802.11 code calls this | 2184 | * @config: Handler for configuration requests. IEEE 802.11 code calls this |
2171 | * function to change hardware configuration, e.g., channel. | 2185 | * function to change hardware configuration, e.g., channel. |
2172 | * This function should never fail but returns a negative error code | 2186 | * This function should never fail but returns a negative error code |
@@ -2580,6 +2594,12 @@ struct ieee80211_ops { | |||
2580 | struct ieee80211_vif *vif, | 2594 | struct ieee80211_vif *vif, |
2581 | struct ieee80211_sta *sta, | 2595 | struct ieee80211_sta *sta, |
2582 | struct dentry *dir); | 2596 | struct dentry *dir); |
2597 | void (*add_interface_debugfs)(struct ieee80211_hw *hw, | ||
2598 | struct ieee80211_vif *vif, | ||
2599 | struct dentry *dir); | ||
2600 | void (*remove_interface_debugfs)(struct ieee80211_hw *hw, | ||
2601 | struct ieee80211_vif *vif, | ||
2602 | struct dentry *dir); | ||
2583 | #endif | 2603 | #endif |
2584 | void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 2604 | void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
2585 | enum sta_notify_cmd, struct ieee80211_sta *sta); | 2605 | enum sta_notify_cmd, struct ieee80211_sta *sta); |
@@ -3909,36 +3929,6 @@ void ieee80211_connection_loss(struct ieee80211_vif *vif); | |||
3909 | void ieee80211_resume_disconnect(struct ieee80211_vif *vif); | 3929 | void ieee80211_resume_disconnect(struct ieee80211_vif *vif); |
3910 | 3930 | ||
3911 | /** | 3931 | /** |
3912 | * ieee80211_disable_dyn_ps - force mac80211 to temporarily disable dynamic psm | ||
3913 | * | ||
3914 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | ||
3915 | * | ||
3916 | * Some hardware require full power save to manage simultaneous BT traffic | ||
3917 | * on the WLAN frequency. Full PSM is required periodically, whenever there are | ||
3918 | * burst of BT traffic. The hardware gets information of BT traffic via | ||
3919 | * hardware co-existence lines, and consequentially requests mac80211 to | ||
3920 | * (temporarily) enter full psm. | ||
3921 | * This function will only temporarily disable dynamic PS, not enable PSM if | ||
3922 | * it was not already enabled. | ||
3923 | * The driver must make sure to re-enable dynamic PS using | ||
3924 | * ieee80211_enable_dyn_ps() if the driver has disabled it. | ||
3925 | * | ||
3926 | */ | ||
3927 | void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif); | ||
3928 | |||
3929 | /** | ||
3930 | * ieee80211_enable_dyn_ps - restore dynamic psm after being disabled | ||
3931 | * | ||
3932 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | ||
3933 | * | ||
3934 | * This function restores dynamic PS after being temporarily disabled via | ||
3935 | * ieee80211_disable_dyn_ps(). Each ieee80211_disable_dyn_ps() call must | ||
3936 | * be coupled with an eventual call to this function. | ||
3937 | * | ||
3938 | */ | ||
3939 | void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif); | ||
3940 | |||
3941 | /** | ||
3942 | * ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring | 3932 | * ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring |
3943 | * rssi threshold triggered | 3933 | * rssi threshold triggered |
3944 | * | 3934 | * |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index f4f7e7691077..e3dec80cf617 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -933,6 +933,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
933 | IEEE80211_CHANCTX_SHARED); | 933 | IEEE80211_CHANCTX_SHARED); |
934 | if (err) | 934 | if (err) |
935 | return err; | 935 | return err; |
936 | ieee80211_vif_copy_chanctx_to_vlans(sdata, false); | ||
936 | 937 | ||
937 | /* | 938 | /* |
938 | * Apply control port protocol, this allows us to | 939 | * Apply control port protocol, this allows us to |
@@ -1047,6 +1048,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1047 | local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf); | 1048 | local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf); |
1048 | skb_queue_purge(&sdata->u.ap.ps.bc_buf); | 1049 | skb_queue_purge(&sdata->u.ap.ps.bc_buf); |
1049 | 1050 | ||
1051 | ieee80211_vif_copy_chanctx_to_vlans(sdata, true); | ||
1050 | ieee80211_vif_release_channel(sdata); | 1052 | ieee80211_vif_release_channel(sdata); |
1051 | 1053 | ||
1052 | return 0; | 1054 | return 0; |
@@ -2747,7 +2749,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2747 | goto out_unlock; | 2749 | goto out_unlock; |
2748 | } | 2750 | } |
2749 | 2751 | ||
2750 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; | 2752 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN | |
2753 | IEEE80211_TX_INTFL_OFFCHAN_TX_OK; | ||
2751 | if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) | 2754 | if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) |
2752 | IEEE80211_SKB_CB(skb)->hw_queue = | 2755 | IEEE80211_SKB_CB(skb)->hw_queue = |
2753 | local->hw.offchannel_tx_hw_queue; | 2756 | local->hw.offchannel_tx_hw_queue; |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 1bfe0a8b19d2..038f249966d6 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -91,6 +91,10 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
91 | 91 | ||
92 | list_add_rcu(&ctx->list, &local->chanctx_list); | 92 | list_add_rcu(&ctx->list, &local->chanctx_list); |
93 | 93 | ||
94 | mutex_lock(&local->mtx); | ||
95 | ieee80211_recalc_idle(local); | ||
96 | mutex_unlock(&local->mtx); | ||
97 | |||
94 | return ctx; | 98 | return ctx; |
95 | } | 99 | } |
96 | 100 | ||
@@ -110,6 +114,10 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local, | |||
110 | 114 | ||
111 | list_del_rcu(&ctx->list); | 115 | list_del_rcu(&ctx->list); |
112 | kfree_rcu(ctx, rcu_head); | 116 | kfree_rcu(ctx, rcu_head); |
117 | |||
118 | mutex_lock(&local->mtx); | ||
119 | ieee80211_recalc_idle(local); | ||
120 | mutex_unlock(&local->mtx); | ||
113 | } | 121 | } |
114 | 122 | ||
115 | static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, | 123 | static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, |
@@ -128,6 +136,8 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, | |||
128 | ctx->refcount++; | 136 | ctx->refcount++; |
129 | 137 | ||
130 | ieee80211_recalc_txpower(sdata); | 138 | ieee80211_recalc_txpower(sdata); |
139 | sdata->vif.bss_conf.idle = false; | ||
140 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | ||
131 | 141 | ||
132 | return 0; | 142 | return 0; |
133 | } | 143 | } |
@@ -175,6 +185,9 @@ static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata, | |||
175 | ctx->refcount--; | 185 | ctx->refcount--; |
176 | rcu_assign_pointer(sdata->vif.chanctx_conf, NULL); | 186 | rcu_assign_pointer(sdata->vif.chanctx_conf, NULL); |
177 | 187 | ||
188 | sdata->vif.bss_conf.idle = true; | ||
189 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | ||
190 | |||
178 | drv_unassign_vif_chanctx(local, sdata, ctx); | 191 | drv_unassign_vif_chanctx(local, sdata, ctx); |
179 | 192 | ||
180 | if (ctx->refcount > 0) { | 193 | if (ctx->refcount > 0) { |
@@ -198,15 +211,6 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) | |||
198 | 211 | ||
199 | ctx = container_of(conf, struct ieee80211_chanctx, conf); | 212 | ctx = container_of(conf, struct ieee80211_chanctx, conf); |
200 | 213 | ||
201 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
202 | struct ieee80211_sub_if_data *vlan; | ||
203 | |||
204 | /* for the VLAN list */ | ||
205 | ASSERT_RTNL(); | ||
206 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
207 | rcu_assign_pointer(vlan->vif.chanctx_conf, NULL); | ||
208 | } | ||
209 | |||
210 | ieee80211_unassign_vif_chanctx(sdata, ctx); | 214 | ieee80211_unassign_vif_chanctx(sdata, ctx); |
211 | if (ctx->refcount == 0) | 215 | if (ctx->refcount == 0) |
212 | ieee80211_free_chanctx(local, ctx); | 216 | ieee80211_free_chanctx(local, ctx); |
@@ -326,15 +330,6 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
326 | goto out; | 330 | goto out; |
327 | } | 331 | } |
328 | 332 | ||
329 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
330 | struct ieee80211_sub_if_data *vlan; | ||
331 | |||
332 | /* for the VLAN list */ | ||
333 | ASSERT_RTNL(); | ||
334 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
335 | rcu_assign_pointer(vlan->vif.chanctx_conf, &ctx->conf); | ||
336 | } | ||
337 | |||
338 | ieee80211_recalc_smps_chanctx(local, ctx); | 333 | ieee80211_recalc_smps_chanctx(local, ctx); |
339 | out: | 334 | out: |
340 | mutex_unlock(&local->chanctx_mtx); | 335 | mutex_unlock(&local->chanctx_mtx); |
@@ -369,6 +364,40 @@ void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata) | |||
369 | mutex_unlock(&local->chanctx_mtx); | 364 | mutex_unlock(&local->chanctx_mtx); |
370 | } | 365 | } |
371 | 366 | ||
367 | void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, | ||
368 | bool clear) | ||
369 | { | ||
370 | struct ieee80211_local *local = sdata->local; | ||
371 | struct ieee80211_sub_if_data *vlan; | ||
372 | struct ieee80211_chanctx_conf *conf; | ||
373 | |||
374 | ASSERT_RTNL(); | ||
375 | |||
376 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP)) | ||
377 | return; | ||
378 | |||
379 | mutex_lock(&local->chanctx_mtx); | ||
380 | |||
381 | /* | ||
382 | * Check that conf exists, even when clearing this function | ||
383 | * must be called with the AP's channel context still there | ||
384 | * as it would otherwise cause VLANs to have an invalid | ||
385 | * channel context pointer for a while, possibly pointing | ||
386 | * to a channel context that has already been freed. | ||
387 | */ | ||
388 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
389 | lockdep_is_held(&local->chanctx_mtx)); | ||
390 | WARN_ON(!conf); | ||
391 | |||
392 | if (clear) | ||
393 | conf = NULL; | ||
394 | |||
395 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
396 | rcu_assign_pointer(vlan->vif.chanctx_conf, conf); | ||
397 | |||
398 | mutex_unlock(&local->chanctx_mtx); | ||
399 | } | ||
400 | |||
372 | void ieee80211_iter_chan_contexts_atomic( | 401 | void ieee80211_iter_chan_contexts_atomic( |
373 | struct ieee80211_hw *hw, | 402 | struct ieee80211_hw *hw, |
374 | void (*iter)(struct ieee80211_hw *hw, | 403 | void (*iter)(struct ieee80211_hw *hw, |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 8e6040998ba6..b0e32d628114 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -151,8 +151,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, | |||
151 | sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); | 151 | sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); |
152 | if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW) | 152 | if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW) |
153 | sf += snprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n"); | 153 | sf += snprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n"); |
154 | if (local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE) | ||
155 | sf += snprintf(buf + sf, mxln - sf, "SCAN_WHILE_IDLE\n"); | ||
156 | 154 | ||
157 | rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | 155 | rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); |
158 | kfree(buf); | 156 | kfree(buf); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 434b3c4f31b5..2b08b9982d06 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -528,6 +528,43 @@ static inline void drv_sta_remove_debugfs(struct ieee80211_local *local, | |||
528 | local->ops->sta_remove_debugfs(&local->hw, &sdata->vif, | 528 | local->ops->sta_remove_debugfs(&local->hw, &sdata->vif, |
529 | sta, dir); | 529 | sta, dir); |
530 | } | 530 | } |
531 | |||
532 | static inline | ||
533 | void drv_add_interface_debugfs(struct ieee80211_local *local, | ||
534 | struct ieee80211_sub_if_data *sdata) | ||
535 | { | ||
536 | might_sleep(); | ||
537 | |||
538 | check_sdata_in_driver(sdata); | ||
539 | |||
540 | if (!local->ops->add_interface_debugfs) | ||
541 | return; | ||
542 | |||
543 | local->ops->add_interface_debugfs(&local->hw, &sdata->vif, | ||
544 | sdata->debugfs.dir); | ||
545 | } | ||
546 | |||
547 | static inline | ||
548 | void drv_remove_interface_debugfs(struct ieee80211_local *local, | ||
549 | struct ieee80211_sub_if_data *sdata) | ||
550 | { | ||
551 | might_sleep(); | ||
552 | |||
553 | check_sdata_in_driver(sdata); | ||
554 | |||
555 | if (!local->ops->remove_interface_debugfs) | ||
556 | return; | ||
557 | |||
558 | local->ops->remove_interface_debugfs(&local->hw, &sdata->vif, | ||
559 | sdata->debugfs.dir); | ||
560 | } | ||
561 | #else | ||
562 | static inline | ||
563 | void drv_add_interface_debugfs(struct ieee80211_local *local, | ||
564 | struct ieee80211_sub_if_data *sdata) {} | ||
565 | static inline | ||
566 | void drv_remove_interface_debugfs(struct ieee80211_local *local, | ||
567 | struct ieee80211_sub_if_data *sdata) {} | ||
531 | #endif | 568 | #endif |
532 | 569 | ||
533 | static inline __must_check | 570 | static inline __must_check |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index a54c8248e0e0..2db1f2b90bfe 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -228,7 +228,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
228 | 228 | ||
229 | bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan, | 229 | bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan, |
230 | mgmt, skb->len, 0, GFP_KERNEL); | 230 | mgmt, skb->len, 0, GFP_KERNEL); |
231 | cfg80211_put_bss(bss); | 231 | cfg80211_put_bss(local->hw.wiphy, bss); |
232 | netif_carrier_on(sdata->dev); | 232 | netif_carrier_on(sdata->dev); |
233 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); | 233 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); |
234 | } | 234 | } |
@@ -242,6 +242,8 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
242 | u32 basic_rates; | 242 | u32 basic_rates; |
243 | int i, j; | 243 | int i, j; |
244 | u16 beacon_int = cbss->beacon_interval; | 244 | u16 beacon_int = cbss->beacon_interval; |
245 | const struct cfg80211_bss_ies *ies; | ||
246 | u64 tsf; | ||
245 | 247 | ||
246 | lockdep_assert_held(&sdata->u.ibss.mtx); | 248 | lockdep_assert_held(&sdata->u.ibss.mtx); |
247 | 249 | ||
@@ -265,13 +267,17 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
265 | } | 267 | } |
266 | } | 268 | } |
267 | 269 | ||
270 | rcu_read_lock(); | ||
271 | ies = rcu_dereference(cbss->ies); | ||
272 | tsf = ies->tsf; | ||
273 | rcu_read_unlock(); | ||
274 | |||
268 | __ieee80211_sta_join_ibss(sdata, cbss->bssid, | 275 | __ieee80211_sta_join_ibss(sdata, cbss->bssid, |
269 | beacon_int, | 276 | beacon_int, |
270 | cbss->channel, | 277 | cbss->channel, |
271 | basic_rates, | 278 | basic_rates, |
272 | cbss->capability, | 279 | cbss->capability, |
273 | cbss->tsf, | 280 | tsf, false); |
274 | false); | ||
275 | } | 281 | } |
276 | 282 | ||
277 | static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, | 283 | static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, |
@@ -535,8 +541,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
535 | 541 | ||
536 | cbss = container_of((void *)bss, struct cfg80211_bss, priv); | 542 | cbss = container_of((void *)bss, struct cfg80211_bss, priv); |
537 | 543 | ||
538 | /* was just updated in ieee80211_bss_info_update */ | 544 | /* same for beacon and probe response */ |
539 | beacon_timestamp = cbss->tsf; | 545 | beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); |
540 | 546 | ||
541 | /* check if we need to merge IBSS */ | 547 | /* check if we need to merge IBSS */ |
542 | 548 | ||
@@ -1102,10 +1108,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1102 | 1108 | ||
1103 | mutex_unlock(&sdata->u.ibss.mtx); | 1109 | mutex_unlock(&sdata->u.ibss.mtx); |
1104 | 1110 | ||
1105 | mutex_lock(&sdata->local->mtx); | ||
1106 | ieee80211_recalc_idle(sdata->local); | ||
1107 | mutex_unlock(&sdata->local->mtx); | ||
1108 | |||
1109 | /* | 1111 | /* |
1110 | * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is | 1112 | * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is |
1111 | * reserved, but an HT STA shall protect HT transmissions as though | 1113 | * reserved, but an HT STA shall protect HT transmissions as though |
@@ -1159,7 +1161,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
1159 | 1161 | ||
1160 | if (cbss) { | 1162 | if (cbss) { |
1161 | cfg80211_unlink_bss(local->hw.wiphy, cbss); | 1163 | cfg80211_unlink_bss(local->hw.wiphy, cbss); |
1162 | cfg80211_put_bss(cbss); | 1164 | cfg80211_put_bss(local->hw.wiphy, cbss); |
1163 | } | 1165 | } |
1164 | } | 1166 | } |
1165 | 1167 | ||
@@ -1203,9 +1205,5 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
1203 | 1205 | ||
1204 | mutex_unlock(&sdata->u.ibss.mtx); | 1206 | mutex_unlock(&sdata->u.ibss.mtx); |
1205 | 1207 | ||
1206 | mutex_lock(&local->mtx); | ||
1207 | ieee80211_recalc_idle(sdata->local); | ||
1208 | mutex_unlock(&local->mtx); | ||
1209 | |||
1210 | return 0; | 1208 | return 0; |
1211 | } | 1209 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 5fe9db707880..76cdcfcd614c 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -86,7 +86,7 @@ struct ieee80211_fragment_entry { | |||
86 | 86 | ||
87 | 87 | ||
88 | struct ieee80211_bss { | 88 | struct ieee80211_bss { |
89 | u32 device_ts; | 89 | u32 device_ts_beacon, device_ts_presp; |
90 | 90 | ||
91 | bool wmm_used; | 91 | bool wmm_used; |
92 | bool uapsd_supported; | 92 | bool uapsd_supported; |
@@ -689,9 +689,6 @@ struct ieee80211_sub_if_data { | |||
689 | 689 | ||
690 | char name[IFNAMSIZ]; | 690 | char name[IFNAMSIZ]; |
691 | 691 | ||
692 | /* to detect idle changes */ | ||
693 | bool old_idle; | ||
694 | |||
695 | /* Fragment table for host-based reassembly */ | 692 | /* Fragment table for host-based reassembly */ |
696 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 693 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
697 | unsigned int fragment_next; | 694 | unsigned int fragment_next; |
@@ -812,6 +809,7 @@ enum queue_stop_reason { | |||
812 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, | 809 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, |
813 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, | 810 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
814 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, | 811 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
812 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, | ||
815 | }; | 813 | }; |
816 | 814 | ||
817 | #ifdef CONFIG_MAC80211_LEDS | 815 | #ifdef CONFIG_MAC80211_LEDS |
@@ -958,14 +956,7 @@ struct ieee80211_local { | |||
958 | struct sk_buff_head skb_queue; | 956 | struct sk_buff_head skb_queue; |
959 | struct sk_buff_head skb_queue_unreliable; | 957 | struct sk_buff_head skb_queue_unreliable; |
960 | 958 | ||
961 | /* | 959 | spinlock_t rx_path_lock; |
962 | * Internal FIFO queue which is shared between multiple rx path | ||
963 | * stages. Its main task is to provide a serialization mechanism, | ||
964 | * so all rx handlers can enjoy having exclusive access to their | ||
965 | * private data structures. | ||
966 | */ | ||
967 | struct sk_buff_head rx_skb_queue; | ||
968 | bool running_rx_handler; /* protected by rx_skb_queue.lock */ | ||
969 | 960 | ||
970 | /* Station data */ | 961 | /* Station data */ |
971 | /* | 962 | /* |
@@ -1106,8 +1097,6 @@ struct ieee80211_local { | |||
1106 | * this will override whatever chosen by mac80211 internally. | 1097 | * this will override whatever chosen by mac80211 internally. |
1107 | */ | 1098 | */ |
1108 | int dynamic_ps_forced_timeout; | 1099 | int dynamic_ps_forced_timeout; |
1109 | int dynamic_ps_user_timeout; | ||
1110 | bool disable_dynamic_ps; | ||
1111 | 1100 | ||
1112 | int user_power_level; /* in dBm, for all interfaces */ | 1101 | int user_power_level; /* in dBm, for all interfaces */ |
1113 | 1102 | ||
@@ -1612,6 +1601,8 @@ ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
1612 | enum ieee80211_chanctx_mode mode); | 1601 | enum ieee80211_chanctx_mode mode); |
1613 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); | 1602 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); |
1614 | void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); | 1603 | void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); |
1604 | void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, | ||
1605 | bool clear); | ||
1615 | 1606 | ||
1616 | void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, | 1607 | void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, |
1617 | struct ieee80211_chanctx *chanctx); | 1608 | struct ieee80211_chanctx *chanctx); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 0a36dc6346bb..40ff0307d089 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -78,8 +78,7 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) | |||
78 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); | 78 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); |
79 | } | 79 | } |
80 | 80 | ||
81 | static u32 ieee80211_idle_off(struct ieee80211_local *local, | 81 | static u32 ieee80211_idle_off(struct ieee80211_local *local) |
82 | const char *reason) | ||
83 | { | 82 | { |
84 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) | 83 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) |
85 | return 0; | 84 | return 0; |
@@ -99,110 +98,45 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) | |||
99 | return IEEE80211_CONF_CHANGE_IDLE; | 98 | return IEEE80211_CONF_CHANGE_IDLE; |
100 | } | 99 | } |
101 | 100 | ||
102 | static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | 101 | void ieee80211_recalc_idle(struct ieee80211_local *local) |
103 | { | 102 | { |
104 | struct ieee80211_sub_if_data *sdata; | 103 | bool working = false, scanning, active; |
105 | int count = 0; | ||
106 | bool working = false, scanning = false; | ||
107 | unsigned int led_trig_start = 0, led_trig_stop = 0; | 104 | unsigned int led_trig_start = 0, led_trig_stop = 0; |
108 | struct ieee80211_roc_work *roc; | 105 | struct ieee80211_roc_work *roc; |
106 | u32 change; | ||
109 | 107 | ||
110 | #ifdef CONFIG_PROVE_LOCKING | ||
111 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && | ||
112 | !lockdep_is_held(&local->iflist_mtx)); | ||
113 | #endif | ||
114 | lockdep_assert_held(&local->mtx); | 108 | lockdep_assert_held(&local->mtx); |
115 | 109 | ||
116 | list_for_each_entry(sdata, &local->interfaces, list) { | 110 | active = !list_empty(&local->chanctx_list); |
117 | if (!ieee80211_sdata_running(sdata)) { | ||
118 | sdata->vif.bss_conf.idle = true; | ||
119 | continue; | ||
120 | } | ||
121 | |||
122 | sdata->old_idle = sdata->vif.bss_conf.idle; | ||
123 | |||
124 | /* do not count disabled managed interfaces */ | ||
125 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
126 | !sdata->u.mgd.associated && | ||
127 | !sdata->u.mgd.auth_data && | ||
128 | !sdata->u.mgd.assoc_data) { | ||
129 | sdata->vif.bss_conf.idle = true; | ||
130 | continue; | ||
131 | } | ||
132 | /* do not count unused IBSS interfaces */ | ||
133 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
134 | !sdata->u.ibss.ssid_len) { | ||
135 | sdata->vif.bss_conf.idle = true; | ||
136 | continue; | ||
137 | } | ||
138 | |||
139 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
140 | continue; | ||
141 | |||
142 | /* count everything else */ | ||
143 | sdata->vif.bss_conf.idle = false; | ||
144 | count++; | ||
145 | } | ||
146 | 111 | ||
147 | if (!local->ops->remain_on_channel) { | 112 | if (!local->ops->remain_on_channel) { |
148 | list_for_each_entry(roc, &local->roc_list, list) { | 113 | list_for_each_entry(roc, &local->roc_list, list) { |
149 | working = true; | 114 | working = true; |
150 | roc->sdata->vif.bss_conf.idle = false; | 115 | break; |
151 | } | 116 | } |
152 | } | 117 | } |
153 | 118 | ||
154 | sdata = rcu_dereference_protected(local->scan_sdata, | 119 | scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) || |
155 | lockdep_is_held(&local->mtx)); | 120 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning); |
156 | if (sdata && !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { | ||
157 | scanning = true; | ||
158 | sdata->vif.bss_conf.idle = false; | ||
159 | } | ||
160 | |||
161 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
162 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | ||
163 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | ||
164 | sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
165 | continue; | ||
166 | if (sdata->old_idle == sdata->vif.bss_conf.idle) | ||
167 | continue; | ||
168 | if (!ieee80211_sdata_running(sdata)) | ||
169 | continue; | ||
170 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | ||
171 | } | ||
172 | 121 | ||
173 | if (working || scanning) | 122 | if (working || scanning) |
174 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; | 123 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; |
175 | else | 124 | else |
176 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; | 125 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; |
177 | 126 | ||
178 | if (count) | 127 | if (active) |
179 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | 128 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; |
180 | else | 129 | else |
181 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | 130 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; |
182 | 131 | ||
183 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); | 132 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); |
184 | 133 | ||
185 | if (working) | 134 | if (working || scanning || active) |
186 | return ieee80211_idle_off(local, "working"); | 135 | change = ieee80211_idle_off(local); |
187 | if (scanning) | ||
188 | return ieee80211_idle_off(local, "scanning"); | ||
189 | if (!count) | ||
190 | return ieee80211_idle_on(local); | ||
191 | else | 136 | else |
192 | return ieee80211_idle_off(local, "in use"); | 137 | change = ieee80211_idle_on(local); |
193 | 138 | if (change) | |
194 | return 0; | 139 | ieee80211_hw_config(local, change); |
195 | } | ||
196 | |||
197 | void ieee80211_recalc_idle(struct ieee80211_local *local) | ||
198 | { | ||
199 | u32 chg; | ||
200 | |||
201 | mutex_lock(&local->iflist_mtx); | ||
202 | chg = __ieee80211_recalc_idle(local); | ||
203 | mutex_unlock(&local->iflist_mtx); | ||
204 | if (chg) | ||
205 | ieee80211_hw_config(local, chg); | ||
206 | } | 140 | } |
207 | 141 | ||
208 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | 142 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) |
@@ -621,6 +555,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
621 | goto err_del_interface; | 555 | goto err_del_interface; |
622 | } | 556 | } |
623 | 557 | ||
558 | drv_add_interface_debugfs(local, sdata); | ||
559 | |||
624 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 560 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
625 | local->fif_pspoll++; | 561 | local->fif_pspoll++; |
626 | local->fif_probe_req++; | 562 | local->fif_probe_req++; |
@@ -694,10 +630,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
694 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | 630 | if (sdata->flags & IEEE80211_SDATA_PROMISC) |
695 | atomic_inc(&local->iff_promiscs); | 631 | atomic_inc(&local->iff_promiscs); |
696 | 632 | ||
697 | mutex_lock(&local->mtx); | ||
698 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | ||
699 | mutex_unlock(&local->mtx); | ||
700 | |||
701 | if (coming_up) | 633 | if (coming_up) |
702 | local->open_count++; | 634 | local->open_count++; |
703 | 635 | ||
@@ -882,16 +814,14 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
882 | */ | 814 | */ |
883 | ieee80211_free_keys(sdata); | 815 | ieee80211_free_keys(sdata); |
884 | 816 | ||
817 | drv_remove_interface_debugfs(local, sdata); | ||
818 | |||
885 | if (going_down) | 819 | if (going_down) |
886 | drv_remove_interface(local, sdata); | 820 | drv_remove_interface(local, sdata); |
887 | } | 821 | } |
888 | 822 | ||
889 | sdata->bss = NULL; | 823 | sdata->bss = NULL; |
890 | 824 | ||
891 | mutex_lock(&local->mtx); | ||
892 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | ||
893 | mutex_unlock(&local->mtx); | ||
894 | |||
895 | ieee80211_recalc_ps(local, -1); | 825 | ieee80211_recalc_ps(local, -1); |
896 | 826 | ||
897 | if (local->open_count == 0) { | 827 | if (local->open_count == 0) { |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 2bdd454e8bcf..38b3468bc515 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -34,8 +34,6 @@ | |||
34 | #include "cfg.h" | 34 | #include "cfg.h" |
35 | #include "debugfs.h" | 35 | #include "debugfs.h" |
36 | 36 | ||
37 | static struct lock_class_key ieee80211_rx_skb_queue_class; | ||
38 | |||
39 | void ieee80211_configure_filter(struct ieee80211_local *local) | 37 | void ieee80211_configure_filter(struct ieee80211_local *local) |
40 | { | 38 | { |
41 | u64 mc; | 39 | u64 mc; |
@@ -613,21 +611,12 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
613 | 611 | ||
614 | mutex_init(&local->key_mtx); | 612 | mutex_init(&local->key_mtx); |
615 | spin_lock_init(&local->filter_lock); | 613 | spin_lock_init(&local->filter_lock); |
614 | spin_lock_init(&local->rx_path_lock); | ||
616 | spin_lock_init(&local->queue_stop_reason_lock); | 615 | spin_lock_init(&local->queue_stop_reason_lock); |
617 | 616 | ||
618 | INIT_LIST_HEAD(&local->chanctx_list); | 617 | INIT_LIST_HEAD(&local->chanctx_list); |
619 | mutex_init(&local->chanctx_mtx); | 618 | mutex_init(&local->chanctx_mtx); |
620 | 619 | ||
621 | /* | ||
622 | * The rx_skb_queue is only accessed from tasklets, | ||
623 | * but other SKB queues are used from within IRQ | ||
624 | * context. Therefore, this one needs a different | ||
625 | * locking class so our direct, non-irq-safe use of | ||
626 | * the queue's lock doesn't throw lockdep warnings. | ||
627 | */ | ||
628 | skb_queue_head_init_class(&local->rx_skb_queue, | ||
629 | &ieee80211_rx_skb_queue_class); | ||
630 | |||
631 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); | 620 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
632 | 621 | ||
633 | INIT_WORK(&local->restart_work, ieee80211_restart_work); | 622 | INIT_WORK(&local->restart_work, ieee80211_restart_work); |
@@ -707,9 +696,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
707 | return -EINVAL; | 696 | return -EINVAL; |
708 | #endif | 697 | #endif |
709 | 698 | ||
710 | if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) | ||
711 | return -EINVAL; | ||
712 | |||
713 | if (!local->use_chanctx) { | 699 | if (!local->use_chanctx) { |
714 | for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) { | 700 | for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) { |
715 | const struct ieee80211_iface_combination *comb; | 701 | const struct ieee80211_iface_combination *comb; |
@@ -1089,7 +1075,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
1089 | wiphy_warn(local->hw.wiphy, "skb_queue not empty\n"); | 1075 | wiphy_warn(local->hw.wiphy, "skb_queue not empty\n"); |
1090 | skb_queue_purge(&local->skb_queue); | 1076 | skb_queue_purge(&local->skb_queue); |
1091 | skb_queue_purge(&local->skb_queue_unreliable); | 1077 | skb_queue_purge(&local->skb_queue_unreliable); |
1092 | skb_queue_purge(&local->rx_skb_queue); | ||
1093 | 1078 | ||
1094 | destroy_workqueue(local->workqueue); | 1079 | destroy_workqueue(local->workqueue); |
1095 | wiphy_unregister(local->hw.wiphy); | 1080 | wiphy_unregister(local->hw.wiphy); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 35ac38871420..2bf0158c3f82 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -149,6 +149,31 @@ u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) | |||
149 | return changed; | 149 | return changed; |
150 | } | 150 | } |
151 | 151 | ||
152 | /* | ||
153 | * mesh_sta_cleanup - clean up any mesh sta state | ||
154 | * | ||
155 | * @sta: mesh sta to clean up. | ||
156 | */ | ||
157 | void mesh_sta_cleanup(struct sta_info *sta) | ||
158 | { | ||
159 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
160 | u32 changed; | ||
161 | |||
162 | /* | ||
163 | * maybe userspace handles peer allocation and peering, but in either | ||
164 | * case the beacon is still generated by the kernel and we might need | ||
165 | * an update. | ||
166 | */ | ||
167 | changed = mesh_accept_plinks_update(sdata); | ||
168 | if (sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { | ||
169 | changed |= mesh_plink_deactivate(sta); | ||
170 | del_timer_sync(&sta->plink_timer); | ||
171 | } | ||
172 | |||
173 | if (changed) | ||
174 | ieee80211_bss_info_change_notify(sdata, changed); | ||
175 | } | ||
176 | |||
152 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) | 177 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) |
153 | { | 178 | { |
154 | int i; | 179 | int i; |
@@ -368,8 +393,6 @@ mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
368 | int mesh_add_ds_params_ie(struct sk_buff *skb, | 393 | int mesh_add_ds_params_ie(struct sk_buff *skb, |
369 | struct ieee80211_sub_if_data *sdata) | 394 | struct ieee80211_sub_if_data *sdata) |
370 | { | 395 | { |
371 | struct ieee80211_local *local = sdata->local; | ||
372 | struct ieee80211_supported_band *sband; | ||
373 | struct ieee80211_chanctx_conf *chanctx_conf; | 396 | struct ieee80211_chanctx_conf *chanctx_conf; |
374 | struct ieee80211_channel *chan; | 397 | struct ieee80211_channel *chan; |
375 | u8 *pos; | 398 | u8 *pos; |
@@ -386,13 +409,10 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, | |||
386 | chan = chanctx_conf->def.chan; | 409 | chan = chanctx_conf->def.chan; |
387 | rcu_read_unlock(); | 410 | rcu_read_unlock(); |
388 | 411 | ||
389 | sband = local->hw.wiphy->bands[chan->band]; | 412 | pos = skb_put(skb, 2 + 1); |
390 | if (sband->band == IEEE80211_BAND_2GHZ) { | 413 | *pos++ = WLAN_EID_DS_PARAMS; |
391 | pos = skb_put(skb, 2 + 1); | 414 | *pos++ = 1; |
392 | *pos++ = WLAN_EID_DS_PARAMS; | 415 | *pos++ = ieee80211_frequency_to_channel(chan->center_freq); |
393 | *pos++ = 1; | ||
394 | *pos++ = ieee80211_frequency_to_channel(chan->center_freq); | ||
395 | } | ||
396 | 416 | ||
397 | return 0; | 417 | return 0; |
398 | } | 418 | } |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index eb336253b6b3..3b9d862744ba 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -288,12 +288,13 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, | |||
288 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); | 288 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); |
289 | u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); | 289 | u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); |
290 | void mesh_plink_broken(struct sta_info *sta); | 290 | void mesh_plink_broken(struct sta_info *sta); |
291 | void mesh_plink_deactivate(struct sta_info *sta); | 291 | u32 mesh_plink_deactivate(struct sta_info *sta); |
292 | int mesh_plink_open(struct sta_info *sta); | 292 | int mesh_plink_open(struct sta_info *sta); |
293 | void mesh_plink_block(struct sta_info *sta); | 293 | void mesh_plink_block(struct sta_info *sta); |
294 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, | 294 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, |
295 | struct ieee80211_mgmt *mgmt, size_t len, | 295 | struct ieee80211_mgmt *mgmt, size_t len, |
296 | struct ieee80211_rx_status *rx_status); | 296 | struct ieee80211_rx_status *rx_status); |
297 | void mesh_sta_cleanup(struct sta_info *sta); | ||
297 | 298 | ||
298 | /* Private interfaces */ | 299 | /* Private interfaces */ |
299 | /* Mesh tables */ | 300 | /* Mesh tables */ |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index fe7c3334d6fe..56c9b318a97e 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -214,7 +214,7 @@ static u32 __mesh_plink_deactivate(struct sta_info *sta) | |||
214 | * | 214 | * |
215 | * All mesh paths with this peer as next hop will be flushed | 215 | * All mesh paths with this peer as next hop will be flushed |
216 | */ | 216 | */ |
217 | void mesh_plink_deactivate(struct sta_info *sta) | 217 | u32 mesh_plink_deactivate(struct sta_info *sta) |
218 | { | 218 | { |
219 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 219 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
220 | u32 changed; | 220 | u32 changed; |
@@ -227,7 +227,7 @@ void mesh_plink_deactivate(struct sta_info *sta) | |||
227 | sta->reason); | 227 | sta->reason); |
228 | spin_unlock_bh(&sta->lock); | 228 | spin_unlock_bh(&sta->lock); |
229 | 229 | ||
230 | ieee80211_bss_info_change_notify(sdata, changed); | 230 | return changed; |
231 | } | 231 | } |
232 | 232 | ||
233 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | 233 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, |
@@ -592,6 +592,13 @@ static void mesh_plink_timer(unsigned long data) | |||
592 | #ifdef CONFIG_PM | 592 | #ifdef CONFIG_PM |
593 | void mesh_plink_quiesce(struct sta_info *sta) | 593 | void mesh_plink_quiesce(struct sta_info *sta) |
594 | { | 594 | { |
595 | if (!ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
596 | return; | ||
597 | |||
598 | /* no kernel mesh sta timers have been initialized */ | ||
599 | if (sta->sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) | ||
600 | return; | ||
601 | |||
595 | if (del_timer_sync(&sta->plink_timer)) | 602 | if (del_timer_sync(&sta->plink_timer)) |
596 | sta->plink_timer_was_running = true; | 603 | sta->plink_timer_was_running = true; |
597 | } | 604 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 353b690900e9..efb22763d56d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -685,7 +685,8 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
685 | if (powersave) | 685 | if (powersave) |
686 | nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); | 686 | nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); |
687 | 687 | ||
688 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 688 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | |
689 | IEEE80211_TX_INTFL_OFFCHAN_TX_OK; | ||
689 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | 690 | if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | |
690 | IEEE80211_STA_CONNECTION_POLL)) | 691 | IEEE80211_STA_CONNECTION_POLL)) |
691 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE; | 692 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE; |
@@ -951,39 +952,6 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | |||
951 | return 0; | 952 | return 0; |
952 | } | 953 | } |
953 | 954 | ||
954 | void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) | ||
955 | { | ||
956 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
957 | struct ieee80211_local *local = sdata->local; | ||
958 | struct ieee80211_conf *conf = &local->hw.conf; | ||
959 | |||
960 | WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION || | ||
961 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) || | ||
962 | (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)); | ||
963 | |||
964 | local->disable_dynamic_ps = false; | ||
965 | conf->dynamic_ps_timeout = local->dynamic_ps_user_timeout; | ||
966 | } | ||
967 | EXPORT_SYMBOL(ieee80211_enable_dyn_ps); | ||
968 | |||
969 | void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif) | ||
970 | { | ||
971 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
972 | struct ieee80211_local *local = sdata->local; | ||
973 | struct ieee80211_conf *conf = &local->hw.conf; | ||
974 | |||
975 | WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION || | ||
976 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) || | ||
977 | (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)); | ||
978 | |||
979 | local->disable_dynamic_ps = true; | ||
980 | conf->dynamic_ps_timeout = 0; | ||
981 | del_timer_sync(&local->dynamic_ps_timer); | ||
982 | ieee80211_queue_work(&local->hw, | ||
983 | &local->dynamic_ps_enable_work); | ||
984 | } | ||
985 | EXPORT_SYMBOL(ieee80211_disable_dyn_ps); | ||
986 | |||
987 | /* powersave */ | 955 | /* powersave */ |
988 | static void ieee80211_enable_ps(struct ieee80211_local *local, | 956 | static void ieee80211_enable_ps(struct ieee80211_local *local, |
989 | struct ieee80211_sub_if_data *sdata) | 957 | struct ieee80211_sub_if_data *sdata) |
@@ -1086,7 +1054,6 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
1086 | } | 1054 | } |
1087 | 1055 | ||
1088 | if (count == 1 && ieee80211_powersave_allowed(found)) { | 1056 | if (count == 1 && ieee80211_powersave_allowed(found)) { |
1089 | struct ieee80211_conf *conf = &local->hw.conf; | ||
1090 | s32 beaconint_us; | 1057 | s32 beaconint_us; |
1091 | 1058 | ||
1092 | if (latency < 0) | 1059 | if (latency < 0) |
@@ -1110,10 +1077,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
1110 | else | 1077 | else |
1111 | timeout = 100; | 1078 | timeout = 100; |
1112 | } | 1079 | } |
1113 | local->dynamic_ps_user_timeout = timeout; | 1080 | local->hw.conf.dynamic_ps_timeout = timeout; |
1114 | if (!local->disable_dynamic_ps) | ||
1115 | conf->dynamic_ps_timeout = | ||
1116 | local->dynamic_ps_user_timeout; | ||
1117 | 1081 | ||
1118 | if (beaconint_us > latency) { | 1082 | if (beaconint_us > latency) { |
1119 | local->ps_sdata = NULL; | 1083 | local->ps_sdata = NULL; |
@@ -1183,8 +1147,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
1183 | if (local->hw.conf.flags & IEEE80211_CONF_PS) | 1147 | if (local->hw.conf.flags & IEEE80211_CONF_PS) |
1184 | return; | 1148 | return; |
1185 | 1149 | ||
1186 | if (!local->disable_dynamic_ps && | 1150 | if (local->hw.conf.dynamic_ps_timeout > 0) { |
1187 | local->hw.conf.dynamic_ps_timeout > 0) { | ||
1188 | /* don't enter PS if TX frames are pending */ | 1151 | /* don't enter PS if TX frames are pending */ |
1189 | if (drv_tx_frames_pending(local)) { | 1152 | if (drv_tx_frames_pending(local)) { |
1190 | mod_timer(&local->dynamic_ps_timer, jiffies + | 1153 | mod_timer(&local->dynamic_ps_timer, jiffies + |
@@ -1746,7 +1709,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
1746 | 1709 | ||
1747 | if (beacon) | 1710 | if (beacon) |
1748 | mlme_dbg_ratelimited(sdata, | 1711 | mlme_dbg_ratelimited(sdata, |
1749 | "detected beacon loss from AP - sending probe request\n"); | 1712 | "detected beacon loss from AP - probing\n"); |
1750 | 1713 | ||
1751 | ieee80211_cqm_rssi_notify(&sdata->vif, | 1714 | ieee80211_cqm_rssi_notify(&sdata->vif, |
1752 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, GFP_KERNEL); | 1715 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, GFP_KERNEL); |
@@ -1830,7 +1793,6 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get); | |||
1830 | static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) | 1793 | static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) |
1831 | { | 1794 | { |
1832 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1795 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1833 | struct ieee80211_local *local = sdata->local; | ||
1834 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | 1796 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
1835 | 1797 | ||
1836 | mutex_lock(&ifmgd->mtx); | 1798 | mutex_lock(&ifmgd->mtx); |
@@ -1850,10 +1812,6 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) | |||
1850 | * but that's not a problem. | 1812 | * but that's not a problem. |
1851 | */ | 1813 | */ |
1852 | cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); | 1814 | cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); |
1853 | |||
1854 | mutex_lock(&local->mtx); | ||
1855 | ieee80211_recalc_idle(local); | ||
1856 | mutex_unlock(&local->mtx); | ||
1857 | } | 1815 | } |
1858 | 1816 | ||
1859 | static void ieee80211_beacon_connection_loss_work(struct work_struct *work) | 1817 | static void ieee80211_beacon_connection_loss_work(struct work_struct *work) |
@@ -1934,7 +1892,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, | |||
1934 | ieee80211_vif_release_channel(sdata); | 1892 | ieee80211_vif_release_channel(sdata); |
1935 | } | 1893 | } |
1936 | 1894 | ||
1937 | cfg80211_put_bss(auth_data->bss); | 1895 | cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss); |
1938 | kfree(auth_data); | 1896 | kfree(auth_data); |
1939 | sdata->u.mgd.auth_data = NULL; | 1897 | sdata->u.mgd.auth_data = NULL; |
1940 | } | 1898 | } |
@@ -2086,10 +2044,6 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
2086 | 2044 | ||
2087 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); | 2045 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); |
2088 | 2046 | ||
2089 | mutex_lock(&sdata->local->mtx); | ||
2090 | ieee80211_recalc_idle(sdata->local); | ||
2091 | mutex_unlock(&sdata->local->mtx); | ||
2092 | |||
2093 | return RX_MGMT_CFG80211_DEAUTH; | 2047 | return RX_MGMT_CFG80211_DEAUTH; |
2094 | } | 2048 | } |
2095 | 2049 | ||
@@ -2117,10 +2071,6 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2117 | 2071 | ||
2118 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); | 2072 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); |
2119 | 2073 | ||
2120 | mutex_lock(&sdata->local->mtx); | ||
2121 | ieee80211_recalc_idle(sdata->local); | ||
2122 | mutex_unlock(&sdata->local->mtx); | ||
2123 | |||
2124 | return RX_MGMT_CFG80211_DISASSOC; | 2074 | return RX_MGMT_CFG80211_DISASSOC; |
2125 | } | 2075 | } |
2126 | 2076 | ||
@@ -2263,9 +2213,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2263 | if (elems.wmm_param) | 2213 | if (elems.wmm_param) |
2264 | set_sta_flag(sta, WLAN_STA_WME); | 2214 | set_sta_flag(sta, WLAN_STA_WME); |
2265 | 2215 | ||
2266 | err = sta_info_move_state(sta, IEEE80211_STA_AUTH); | 2216 | err = sta_info_move_state(sta, IEEE80211_STA_ASSOC); |
2267 | if (!err) | ||
2268 | err = sta_info_move_state(sta, IEEE80211_STA_ASSOC); | ||
2269 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | 2217 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) |
2270 | err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | 2218 | err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); |
2271 | if (err) { | 2219 | if (err) { |
@@ -2387,7 +2335,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2387 | if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { | 2335 | if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { |
2388 | /* oops -- internal error -- send timeout for now */ | 2336 | /* oops -- internal error -- send timeout for now */ |
2389 | ieee80211_destroy_assoc_data(sdata, false); | 2337 | ieee80211_destroy_assoc_data(sdata, false); |
2390 | cfg80211_put_bss(*bss); | 2338 | cfg80211_put_bss(sdata->local->hw.wiphy, *bss); |
2391 | return RX_MGMT_CFG80211_ASSOC_TIMEOUT; | 2339 | return RX_MGMT_CFG80211_ASSOC_TIMEOUT; |
2392 | } | 2340 | } |
2393 | sdata_info(sdata, "associated\n"); | 2341 | sdata_info(sdata, "associated\n"); |
@@ -2567,6 +2515,17 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2567 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); | 2515 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); |
2568 | ifmgd->assoc_data->have_beacon = true; | 2516 | ifmgd->assoc_data->have_beacon = true; |
2569 | ifmgd->assoc_data->need_beacon = false; | 2517 | ifmgd->assoc_data->need_beacon = false; |
2518 | if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) { | ||
2519 | sdata->vif.bss_conf.sync_tsf = | ||
2520 | le64_to_cpu(mgmt->u.beacon.timestamp); | ||
2521 | sdata->vif.bss_conf.sync_device_ts = | ||
2522 | rx_status->device_timestamp; | ||
2523 | if (elems.tim) | ||
2524 | sdata->vif.bss_conf.sync_dtim_count = | ||
2525 | elems.tim->dtim_count; | ||
2526 | else | ||
2527 | sdata->vif.bss_conf.sync_dtim_count = 0; | ||
2528 | } | ||
2570 | /* continue assoc process */ | 2529 | /* continue assoc process */ |
2571 | ifmgd->assoc_data->timeout = jiffies; | 2530 | ifmgd->assoc_data->timeout = jiffies; |
2572 | run_again(ifmgd, ifmgd->assoc_data->timeout); | 2531 | run_again(ifmgd, ifmgd->assoc_data->timeout); |
@@ -2641,7 +2600,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2641 | 2600 | ||
2642 | if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { | 2601 | if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { |
2643 | mlme_dbg_ratelimited(sdata, | 2602 | mlme_dbg_ratelimited(sdata, |
2644 | "cancelling probereq poll due to a received beacon\n"); | 2603 | "cancelling AP probe due to a received beacon\n"); |
2645 | mutex_lock(&local->mtx); | 2604 | mutex_lock(&local->mtx); |
2646 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; | 2605 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; |
2647 | ieee80211_run_deferred_scan(local); | 2606 | ieee80211_run_deferred_scan(local); |
@@ -2725,7 +2684,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2725 | 2684 | ||
2726 | /* | 2685 | /* |
2727 | * If we haven't had a beacon before, tell the driver about the | 2686 | * If we haven't had a beacon before, tell the driver about the |
2728 | * DTIM period now. | 2687 | * DTIM period (and beacon timing if desired) now. |
2729 | */ | 2688 | */ |
2730 | if (!bss_conf->dtim_period) { | 2689 | if (!bss_conf->dtim_period) { |
2731 | /* a few bogus AP send dtim_period = 0 or no TIM IE */ | 2690 | /* a few bogus AP send dtim_period = 0 or no TIM IE */ |
@@ -2733,6 +2692,19 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2733 | bss_conf->dtim_period = elems.tim->dtim_period ?: 1; | 2692 | bss_conf->dtim_period = elems.tim->dtim_period ?: 1; |
2734 | else | 2693 | else |
2735 | bss_conf->dtim_period = 1; | 2694 | bss_conf->dtim_period = 1; |
2695 | |||
2696 | if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) { | ||
2697 | sdata->vif.bss_conf.sync_tsf = | ||
2698 | le64_to_cpu(mgmt->u.beacon.timestamp); | ||
2699 | sdata->vif.bss_conf.sync_device_ts = | ||
2700 | rx_status->device_timestamp; | ||
2701 | if (elems.tim) | ||
2702 | sdata->vif.bss_conf.sync_dtim_count = | ||
2703 | elems.tim->dtim_count; | ||
2704 | else | ||
2705 | sdata->vif.bss_conf.sync_dtim_count = 0; | ||
2706 | } | ||
2707 | |||
2736 | changed |= BSS_CHANGED_DTIM_PERIOD; | 2708 | changed |= BSS_CHANGED_DTIM_PERIOD; |
2737 | } | 2709 | } |
2738 | 2710 | ||
@@ -2853,7 +2825,6 @@ static void ieee80211_sta_timer(unsigned long data) | |||
2853 | static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | 2825 | static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, |
2854 | u8 *bssid, u8 reason, bool tx) | 2826 | u8 *bssid, u8 reason, bool tx) |
2855 | { | 2827 | { |
2856 | struct ieee80211_local *local = sdata->local; | ||
2857 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2828 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2858 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | 2829 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
2859 | 2830 | ||
@@ -2867,10 +2838,6 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, | |||
2867 | */ | 2838 | */ |
2868 | cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); | 2839 | cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); |
2869 | 2840 | ||
2870 | mutex_lock(&local->mtx); | ||
2871 | ieee80211_recalc_idle(local); | ||
2872 | mutex_unlock(&local->mtx); | ||
2873 | |||
2874 | mutex_lock(&ifmgd->mtx); | 2841 | mutex_lock(&ifmgd->mtx); |
2875 | } | 2842 | } |
2876 | 2843 | ||
@@ -3141,10 +3108,6 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
3141 | } | 3108 | } |
3142 | 3109 | ||
3143 | mutex_unlock(&ifmgd->mtx); | 3110 | mutex_unlock(&ifmgd->mtx); |
3144 | |||
3145 | mutex_lock(&local->mtx); | ||
3146 | ieee80211_recalc_idle(local); | ||
3147 | mutex_unlock(&local->mtx); | ||
3148 | } | 3111 | } |
3149 | 3112 | ||
3150 | static void ieee80211_sta_bcn_mon_timer(unsigned long data) | 3113 | static void ieee80211_sta_bcn_mon_timer(unsigned long data) |
@@ -3658,15 +3621,12 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3658 | return -ENOMEM; | 3621 | return -ENOMEM; |
3659 | } | 3622 | } |
3660 | 3623 | ||
3661 | mutex_lock(&local->mtx); | ||
3662 | ieee80211_recalc_idle(sdata->local); | ||
3663 | mutex_unlock(&local->mtx); | ||
3664 | |||
3665 | if (new_sta) { | 3624 | if (new_sta) { |
3666 | u32 rates = 0, basic_rates = 0; | 3625 | u32 rates = 0, basic_rates = 0; |
3667 | bool have_higher_than_11mbit; | 3626 | bool have_higher_than_11mbit; |
3668 | int min_rate = INT_MAX, min_rate_index = -1; | 3627 | int min_rate = INT_MAX, min_rate_index = -1; |
3669 | struct ieee80211_supported_band *sband; | 3628 | struct ieee80211_supported_band *sband; |
3629 | const struct cfg80211_bss_ies *ies; | ||
3670 | 3630 | ||
3671 | sband = local->hw.wiphy->bands[cbss->channel->band]; | 3631 | sband = local->hw.wiphy->bands[cbss->channel->band]; |
3672 | 3632 | ||
@@ -3710,8 +3670,34 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3710 | 3670 | ||
3711 | /* set timing information */ | 3671 | /* set timing information */ |
3712 | sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; | 3672 | sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; |
3713 | sdata->vif.bss_conf.sync_tsf = cbss->tsf; | 3673 | rcu_read_lock(); |
3714 | sdata->vif.bss_conf.sync_device_ts = bss->device_ts; | 3674 | ies = rcu_dereference(cbss->beacon_ies); |
3675 | if (ies) { | ||
3676 | const u8 *tim_ie; | ||
3677 | |||
3678 | sdata->vif.bss_conf.sync_tsf = ies->tsf; | ||
3679 | sdata->vif.bss_conf.sync_device_ts = | ||
3680 | bss->device_ts_beacon; | ||
3681 | tim_ie = cfg80211_find_ie(WLAN_EID_TIM, | ||
3682 | ies->data, ies->len); | ||
3683 | if (tim_ie && tim_ie[1] >= 2) | ||
3684 | sdata->vif.bss_conf.sync_dtim_count = tim_ie[2]; | ||
3685 | else | ||
3686 | sdata->vif.bss_conf.sync_dtim_count = 0; | ||
3687 | } else if (!(local->hw.flags & | ||
3688 | IEEE80211_HW_TIMING_BEACON_ONLY)) { | ||
3689 | ies = rcu_dereference(cbss->proberesp_ies); | ||
3690 | /* must be non-NULL since beacon IEs were NULL */ | ||
3691 | sdata->vif.bss_conf.sync_tsf = ies->tsf; | ||
3692 | sdata->vif.bss_conf.sync_device_ts = | ||
3693 | bss->device_ts_presp; | ||
3694 | sdata->vif.bss_conf.sync_dtim_count = 0; | ||
3695 | } else { | ||
3696 | sdata->vif.bss_conf.sync_tsf = 0; | ||
3697 | sdata->vif.bss_conf.sync_device_ts = 0; | ||
3698 | sdata->vif.bss_conf.sync_dtim_count = 0; | ||
3699 | } | ||
3700 | rcu_read_unlock(); | ||
3715 | 3701 | ||
3716 | /* tell driver about BSSID, basic rates and timing */ | 3702 | /* tell driver about BSSID, basic rates and timing */ |
3717 | ieee80211_bss_info_change_notify(sdata, | 3703 | ieee80211_bss_info_change_notify(sdata, |
@@ -3831,7 +3817,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
3831 | } | 3817 | } |
3832 | 3818 | ||
3833 | /* hold our own reference */ | 3819 | /* hold our own reference */ |
3834 | cfg80211_ref_bss(auth_data->bss); | 3820 | cfg80211_ref_bss(local->hw.wiphy, auth_data->bss); |
3835 | err = 0; | 3821 | err = 0; |
3836 | goto out_unlock; | 3822 | goto out_unlock; |
3837 | 3823 | ||
@@ -4037,13 +4023,23 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4037 | const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, | 4023 | const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, |
4038 | beacon_ies->data, | 4024 | beacon_ies->data, |
4039 | beacon_ies->len); | 4025 | beacon_ies->len); |
4026 | u8 dtim_count = 0; | ||
4027 | |||
4040 | if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) { | 4028 | if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) { |
4041 | const struct ieee80211_tim_ie *tim; | 4029 | const struct ieee80211_tim_ie *tim; |
4042 | tim = (void *)(tim_ie + 2); | 4030 | tim = (void *)(tim_ie + 2); |
4043 | ifmgd->dtim_period = tim->dtim_period; | 4031 | ifmgd->dtim_period = tim->dtim_period; |
4032 | dtim_count = tim->dtim_count; | ||
4044 | } | 4033 | } |
4045 | assoc_data->have_beacon = true; | 4034 | assoc_data->have_beacon = true; |
4046 | assoc_data->timeout = jiffies; | 4035 | assoc_data->timeout = jiffies; |
4036 | |||
4037 | if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) { | ||
4038 | sdata->vif.bss_conf.sync_tsf = beacon_ies->tsf; | ||
4039 | sdata->vif.bss_conf.sync_device_ts = | ||
4040 | bss->device_ts_beacon; | ||
4041 | sdata->vif.bss_conf.sync_dtim_count = dtim_count; | ||
4042 | } | ||
4047 | } else { | 4043 | } else { |
4048 | assoc_data->timeout = jiffies; | 4044 | assoc_data->timeout = jiffies; |
4049 | } | 4045 | } |
@@ -4115,10 +4111,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
4115 | mutex_unlock(&ifmgd->mtx); | 4111 | mutex_unlock(&ifmgd->mtx); |
4116 | 4112 | ||
4117 | out: | 4113 | out: |
4118 | mutex_lock(&sdata->local->mtx); | ||
4119 | ieee80211_recalc_idle(sdata->local); | ||
4120 | mutex_unlock(&sdata->local->mtx); | ||
4121 | |||
4122 | if (sent_frame) | 4114 | if (sent_frame) |
4123 | __cfg80211_send_deauth(sdata->dev, frame_buf, | 4115 | __cfg80211_send_deauth(sdata->dev, frame_buf, |
4124 | IEEE80211_DEAUTH_FRAME_LEN); | 4116 | IEEE80211_DEAUTH_FRAME_LEN); |
@@ -4159,10 +4151,6 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
4159 | __cfg80211_send_disassoc(sdata->dev, frame_buf, | 4151 | __cfg80211_send_disassoc(sdata->dev, frame_buf, |
4160 | IEEE80211_DEAUTH_FRAME_LEN); | 4152 | IEEE80211_DEAUTH_FRAME_LEN); |
4161 | 4153 | ||
4162 | mutex_lock(&sdata->local->mtx); | ||
4163 | ieee80211_recalc_idle(sdata->local); | ||
4164 | mutex_unlock(&sdata->local->mtx); | ||
4165 | |||
4166 | return 0; | 4154 | return 0; |
4167 | } | 4155 | } |
4168 | 4156 | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 82baf5b6ecf4..cc79b4a2e821 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -113,6 +113,15 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) | |||
113 | * notify the AP about us leaving the channel and stop all | 113 | * notify the AP about us leaving the channel and stop all |
114 | * STA interfaces. | 114 | * STA interfaces. |
115 | */ | 115 | */ |
116 | |||
117 | /* | ||
118 | * Stop queues and transmit all frames queued by the driver | ||
119 | * before sending nullfunc to enable powersave at the AP. | ||
120 | */ | ||
121 | ieee80211_stop_queues_by_reason(&local->hw, | ||
122 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); | ||
123 | drv_flush(local, false); | ||
124 | |||
116 | mutex_lock(&local->iflist_mtx); | 125 | mutex_lock(&local->iflist_mtx); |
117 | list_for_each_entry(sdata, &local->interfaces, list) { | 126 | list_for_each_entry(sdata, &local->interfaces, list) { |
118 | if (!ieee80211_sdata_running(sdata)) | 127 | if (!ieee80211_sdata_running(sdata)) |
@@ -133,12 +142,9 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) | |||
133 | sdata, BSS_CHANGED_BEACON_ENABLED); | 142 | sdata, BSS_CHANGED_BEACON_ENABLED); |
134 | } | 143 | } |
135 | 144 | ||
136 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { | 145 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
137 | netif_tx_stop_all_queues(sdata->dev); | 146 | sdata->u.mgd.associated) |
138 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 147 | ieee80211_offchannel_ps_enable(sdata); |
139 | sdata->u.mgd.associated) | ||
140 | ieee80211_offchannel_ps_enable(sdata); | ||
141 | } | ||
142 | } | 148 | } |
143 | mutex_unlock(&local->iflist_mtx); | 149 | mutex_unlock(&local->iflist_mtx); |
144 | } | 150 | } |
@@ -166,20 +172,6 @@ void ieee80211_offchannel_return(struct ieee80211_local *local) | |||
166 | sdata->u.mgd.associated) | 172 | sdata->u.mgd.associated) |
167 | ieee80211_offchannel_ps_disable(sdata); | 173 | ieee80211_offchannel_ps_disable(sdata); |
168 | 174 | ||
169 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { | ||
170 | /* | ||
171 | * This may wake up queues even though the driver | ||
172 | * currently has them stopped. This is not very | ||
173 | * likely, since the driver won't have gotten any | ||
174 | * (or hardly any) new packets while we weren't | ||
175 | * on the right channel, and even if it happens | ||
176 | * it will at most lead to queueing up one more | ||
177 | * packet per queue in mac80211 rather than on | ||
178 | * the interface qdisc. | ||
179 | */ | ||
180 | netif_tx_wake_all_queues(sdata->dev); | ||
181 | } | ||
182 | |||
183 | if (test_and_clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, | 175 | if (test_and_clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, |
184 | &sdata->state)) { | 176 | &sdata->state)) { |
185 | sdata->vif.bss_conf.enable_beacon = true; | 177 | sdata->vif.bss_conf.enable_beacon = true; |
@@ -188,6 +180,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local) | |||
188 | } | 180 | } |
189 | } | 181 | } |
190 | mutex_unlock(&local->iflist_mtx); | 182 | mutex_unlock(&local->iflist_mtx); |
183 | |||
184 | ieee80211_wake_queues_by_reason(&local->hw, | ||
185 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); | ||
191 | } | 186 | } |
192 | 187 | ||
193 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) | 188 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 9f9c453bc45d..5bb316aff21a 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -231,10 +231,6 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
231 | if (!mr->cur_tp) | 231 | if (!mr->cur_tp) |
232 | continue; | 232 | continue; |
233 | 233 | ||
234 | /* ignore the lowest rate of each single-stream group */ | ||
235 | if (!i && minstrel_mcs_groups[group].streams == 1) | ||
236 | continue; | ||
237 | |||
238 | if ((mr->cur_tp > cur_prob_tp && mr->probability > | 234 | if ((mr->cur_tp > cur_prob_tp && mr->probability > |
239 | MINSTREL_FRAC(3, 4)) || mr->probability > cur_prob) { | 235 | MINSTREL_FRAC(3, 4)) || mr->probability > cur_prob) { |
240 | mg->max_prob_rate = index; | 236 | mg->max_prob_rate = index; |
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c index e788f76a1dfe..f2b7d26370f0 100644 --- a/net/mac80211/rc80211_minstrel_ht_debugfs.c +++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c | |||
@@ -38,8 +38,8 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file) | |||
38 | 38 | ||
39 | file->private_data = ms; | 39 | file->private_data = ms; |
40 | p = ms->buf; | 40 | p = ms->buf; |
41 | p += sprintf(p, "type rate throughput ewma prob this prob " | 41 | p += sprintf(p, "type rate throughput ewma prob this prob " |
42 | "this succ/attempt success attempts\n"); | 42 | "retry this succ/attempt success attempts\n"); |
43 | for (i = 0; i < MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS; i++) { | 43 | for (i = 0; i < MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS; i++) { |
44 | char htmode = '2'; | 44 | char htmode = '2'; |
45 | char gimode = 'L'; | 45 | char gimode = 'L'; |
@@ -64,18 +64,19 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file) | |||
64 | *(p++) = (idx == mi->max_tp_rate) ? 'T' : ' '; | 64 | *(p++) = (idx == mi->max_tp_rate) ? 'T' : ' '; |
65 | *(p++) = (idx == mi->max_tp_rate2) ? 't' : ' '; | 65 | *(p++) = (idx == mi->max_tp_rate2) ? 't' : ' '; |
66 | *(p++) = (idx == mi->max_prob_rate) ? 'P' : ' '; | 66 | *(p++) = (idx == mi->max_prob_rate) ? 'P' : ' '; |
67 | p += sprintf(p, "MCS%-2u", (minstrel_mcs_groups[i].streams - 1) * | 67 | p += sprintf(p, " MCS%-2u", (minstrel_mcs_groups[i].streams - 1) * |
68 | MCS_GROUP_RATES + j); | 68 | MCS_GROUP_RATES + j); |
69 | 69 | ||
70 | tp = mr->cur_tp / 10; | 70 | tp = mr->cur_tp / 10; |
71 | prob = MINSTREL_TRUNC(mr->cur_prob * 1000); | 71 | prob = MINSTREL_TRUNC(mr->cur_prob * 1000); |
72 | eprob = MINSTREL_TRUNC(mr->probability * 1000); | 72 | eprob = MINSTREL_TRUNC(mr->probability * 1000); |
73 | 73 | ||
74 | p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " | 74 | p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " |
75 | "%3u(%3u) %8llu %8llu\n", | 75 | "%3u %3u(%3u) %8llu %8llu\n", |
76 | tp / 10, tp % 10, | 76 | tp / 10, tp % 10, |
77 | eprob / 10, eprob % 10, | 77 | eprob / 10, eprob % 10, |
78 | prob / 10, prob % 10, | 78 | prob / 10, prob % 10, |
79 | mr->retry_count, | ||
79 | mr->last_success, | 80 | mr->last_success, |
80 | mr->last_attempts, | 81 | mr->last_attempts, |
81 | (unsigned long long)mr->succ_hist, | 82 | (unsigned long long)mr->succ_hist, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c98be0593756..b5f1bba7ffe1 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -668,9 +668,9 @@ static inline u16 seq_sub(u16 sq1, u16 sq2) | |||
668 | 668 | ||
669 | static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, | 669 | static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, |
670 | struct tid_ampdu_rx *tid_agg_rx, | 670 | struct tid_ampdu_rx *tid_agg_rx, |
671 | int index) | 671 | int index, |
672 | struct sk_buff_head *frames) | ||
672 | { | 673 | { |
673 | struct ieee80211_local *local = sdata->local; | ||
674 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; | 674 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; |
675 | struct ieee80211_rx_status *status; | 675 | struct ieee80211_rx_status *status; |
676 | 676 | ||
@@ -684,7 +684,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, | |||
684 | tid_agg_rx->reorder_buf[index] = NULL; | 684 | tid_agg_rx->reorder_buf[index] = NULL; |
685 | status = IEEE80211_SKB_RXCB(skb); | 685 | status = IEEE80211_SKB_RXCB(skb); |
686 | status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE; | 686 | status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE; |
687 | skb_queue_tail(&local->rx_skb_queue, skb); | 687 | __skb_queue_tail(frames, skb); |
688 | 688 | ||
689 | no_frame: | 689 | no_frame: |
690 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 690 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); |
@@ -692,7 +692,8 @@ no_frame: | |||
692 | 692 | ||
693 | static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata, | 693 | static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata, |
694 | struct tid_ampdu_rx *tid_agg_rx, | 694 | struct tid_ampdu_rx *tid_agg_rx, |
695 | u16 head_seq_num) | 695 | u16 head_seq_num, |
696 | struct sk_buff_head *frames) | ||
696 | { | 697 | { |
697 | int index; | 698 | int index; |
698 | 699 | ||
@@ -701,7 +702,8 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata | |||
701 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { | 702 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { |
702 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 703 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
703 | tid_agg_rx->buf_size; | 704 | tid_agg_rx->buf_size; |
704 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index); | 705 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, |
706 | frames); | ||
705 | } | 707 | } |
706 | } | 708 | } |
707 | 709 | ||
@@ -717,7 +719,8 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata | |||
717 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) | 719 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) |
718 | 720 | ||
719 | static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | 721 | static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, |
720 | struct tid_ampdu_rx *tid_agg_rx) | 722 | struct tid_ampdu_rx *tid_agg_rx, |
723 | struct sk_buff_head *frames) | ||
721 | { | 724 | { |
722 | int index, j; | 725 | int index, j; |
723 | 726 | ||
@@ -746,7 +749,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
746 | 749 | ||
747 | ht_dbg_ratelimited(sdata, | 750 | ht_dbg_ratelimited(sdata, |
748 | "release an RX reorder frame due to timeout on earlier frames\n"); | 751 | "release an RX reorder frame due to timeout on earlier frames\n"); |
749 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, j); | 752 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, j, |
753 | frames); | ||
750 | 754 | ||
751 | /* | 755 | /* |
752 | * Increment the head seq# also for the skipped slots. | 756 | * Increment the head seq# also for the skipped slots. |
@@ -756,7 +760,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
756 | skipped = 0; | 760 | skipped = 0; |
757 | } | 761 | } |
758 | } else while (tid_agg_rx->reorder_buf[index]) { | 762 | } else while (tid_agg_rx->reorder_buf[index]) { |
759 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index); | 763 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, |
764 | frames); | ||
760 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 765 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
761 | tid_agg_rx->buf_size; | 766 | tid_agg_rx->buf_size; |
762 | } | 767 | } |
@@ -788,7 +793,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
788 | */ | 793 | */ |
789 | static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata, | 794 | static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata, |
790 | struct tid_ampdu_rx *tid_agg_rx, | 795 | struct tid_ampdu_rx *tid_agg_rx, |
791 | struct sk_buff *skb) | 796 | struct sk_buff *skb, |
797 | struct sk_buff_head *frames) | ||
792 | { | 798 | { |
793 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 799 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
794 | u16 sc = le16_to_cpu(hdr->seq_ctrl); | 800 | u16 sc = le16_to_cpu(hdr->seq_ctrl); |
@@ -816,7 +822,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
816 | head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); | 822 | head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); |
817 | /* release stored frames up to new head to stack */ | 823 | /* release stored frames up to new head to stack */ |
818 | ieee80211_release_reorder_frames(sdata, tid_agg_rx, | 824 | ieee80211_release_reorder_frames(sdata, tid_agg_rx, |
819 | head_seq_num); | 825 | head_seq_num, frames); |
820 | } | 826 | } |
821 | 827 | ||
822 | /* Now the new frame is always in the range of the reordering buffer */ | 828 | /* Now the new frame is always in the range of the reordering buffer */ |
@@ -846,7 +852,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
846 | tid_agg_rx->reorder_buf[index] = skb; | 852 | tid_agg_rx->reorder_buf[index] = skb; |
847 | tid_agg_rx->reorder_time[index] = jiffies; | 853 | tid_agg_rx->reorder_time[index] = jiffies; |
848 | tid_agg_rx->stored_mpdu_num++; | 854 | tid_agg_rx->stored_mpdu_num++; |
849 | ieee80211_sta_reorder_release(sdata, tid_agg_rx); | 855 | ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames); |
850 | 856 | ||
851 | out: | 857 | out: |
852 | spin_unlock(&tid_agg_rx->reorder_lock); | 858 | spin_unlock(&tid_agg_rx->reorder_lock); |
@@ -857,7 +863,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
857 | * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns | 863 | * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns |
858 | * true if the MPDU was buffered, false if it should be processed. | 864 | * true if the MPDU was buffered, false if it should be processed. |
859 | */ | 865 | */ |
860 | static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) | 866 | static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, |
867 | struct sk_buff_head *frames) | ||
861 | { | 868 | { |
862 | struct sk_buff *skb = rx->skb; | 869 | struct sk_buff *skb = rx->skb; |
863 | struct ieee80211_local *local = rx->local; | 870 | struct ieee80211_local *local = rx->local; |
@@ -922,11 +929,12 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) | |||
922 | * sure that we cannot get to it any more before doing | 929 | * sure that we cannot get to it any more before doing |
923 | * anything with it. | 930 | * anything with it. |
924 | */ | 931 | */ |
925 | if (ieee80211_sta_manage_reorder_buf(rx->sdata, tid_agg_rx, skb)) | 932 | if (ieee80211_sta_manage_reorder_buf(rx->sdata, tid_agg_rx, skb, |
933 | frames)) | ||
926 | return; | 934 | return; |
927 | 935 | ||
928 | dont_reorder: | 936 | dont_reorder: |
929 | skb_queue_tail(&local->rx_skb_queue, skb); | 937 | __skb_queue_tail(frames, skb); |
930 | } | 938 | } |
931 | 939 | ||
932 | static ieee80211_rx_result debug_noinline | 940 | static ieee80211_rx_result debug_noinline |
@@ -2184,7 +2192,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
2184 | } | 2192 | } |
2185 | 2193 | ||
2186 | static ieee80211_rx_result debug_noinline | 2194 | static ieee80211_rx_result debug_noinline |
2187 | ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | 2195 | ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) |
2188 | { | 2196 | { |
2189 | struct sk_buff *skb = rx->skb; | 2197 | struct sk_buff *skb = rx->skb; |
2190 | struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; | 2198 | struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; |
@@ -2223,7 +2231,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | |||
2223 | spin_lock(&tid_agg_rx->reorder_lock); | 2231 | spin_lock(&tid_agg_rx->reorder_lock); |
2224 | /* release stored frames up to start of BAR */ | 2232 | /* release stored frames up to start of BAR */ |
2225 | ieee80211_release_reorder_frames(rx->sdata, tid_agg_rx, | 2233 | ieee80211_release_reorder_frames(rx->sdata, tid_agg_rx, |
2226 | start_seq_num); | 2234 | start_seq_num, frames); |
2227 | spin_unlock(&tid_agg_rx->reorder_lock); | 2235 | spin_unlock(&tid_agg_rx->reorder_lock); |
2228 | 2236 | ||
2229 | kfree_skb(skb); | 2237 | kfree_skb(skb); |
@@ -2808,7 +2816,8 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, | |||
2808 | } | 2816 | } |
2809 | } | 2817 | } |
2810 | 2818 | ||
2811 | static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) | 2819 | static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, |
2820 | struct sk_buff_head *frames) | ||
2812 | { | 2821 | { |
2813 | ieee80211_rx_result res = RX_DROP_MONITOR; | 2822 | ieee80211_rx_result res = RX_DROP_MONITOR; |
2814 | struct sk_buff *skb; | 2823 | struct sk_buff *skb; |
@@ -2820,15 +2829,9 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) | |||
2820 | goto rxh_next; \ | 2829 | goto rxh_next; \ |
2821 | } while (0); | 2830 | } while (0); |
2822 | 2831 | ||
2823 | spin_lock(&rx->local->rx_skb_queue.lock); | 2832 | spin_lock_bh(&rx->local->rx_path_lock); |
2824 | if (rx->local->running_rx_handler) | ||
2825 | goto unlock; | ||
2826 | |||
2827 | rx->local->running_rx_handler = true; | ||
2828 | |||
2829 | while ((skb = __skb_dequeue(&rx->local->rx_skb_queue))) { | ||
2830 | spin_unlock(&rx->local->rx_skb_queue.lock); | ||
2831 | 2833 | ||
2834 | while ((skb = __skb_dequeue(frames))) { | ||
2832 | /* | 2835 | /* |
2833 | * all the other fields are valid across frames | 2836 | * all the other fields are valid across frames |
2834 | * that belong to an aMPDU since they are on the | 2837 | * that belong to an aMPDU since they are on the |
@@ -2849,7 +2852,12 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) | |||
2849 | #endif | 2852 | #endif |
2850 | CALL_RXH(ieee80211_rx_h_amsdu) | 2853 | CALL_RXH(ieee80211_rx_h_amsdu) |
2851 | CALL_RXH(ieee80211_rx_h_data) | 2854 | CALL_RXH(ieee80211_rx_h_data) |
2852 | CALL_RXH(ieee80211_rx_h_ctrl); | 2855 | |
2856 | /* special treatment -- needs the queue */ | ||
2857 | res = ieee80211_rx_h_ctrl(rx, frames); | ||
2858 | if (res != RX_CONTINUE) | ||
2859 | goto rxh_next; | ||
2860 | |||
2853 | CALL_RXH(ieee80211_rx_h_mgmt_check) | 2861 | CALL_RXH(ieee80211_rx_h_mgmt_check) |
2854 | CALL_RXH(ieee80211_rx_h_action) | 2862 | CALL_RXH(ieee80211_rx_h_action) |
2855 | CALL_RXH(ieee80211_rx_h_userspace_mgmt) | 2863 | CALL_RXH(ieee80211_rx_h_userspace_mgmt) |
@@ -2858,20 +2866,20 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) | |||
2858 | 2866 | ||
2859 | rxh_next: | 2867 | rxh_next: |
2860 | ieee80211_rx_handlers_result(rx, res); | 2868 | ieee80211_rx_handlers_result(rx, res); |
2861 | spin_lock(&rx->local->rx_skb_queue.lock); | 2869 | |
2862 | #undef CALL_RXH | 2870 | #undef CALL_RXH |
2863 | } | 2871 | } |
2864 | 2872 | ||
2865 | rx->local->running_rx_handler = false; | 2873 | spin_unlock_bh(&rx->local->rx_path_lock); |
2866 | |||
2867 | unlock: | ||
2868 | spin_unlock(&rx->local->rx_skb_queue.lock); | ||
2869 | } | 2874 | } |
2870 | 2875 | ||
2871 | static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | 2876 | static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) |
2872 | { | 2877 | { |
2878 | struct sk_buff_head reorder_release; | ||
2873 | ieee80211_rx_result res = RX_DROP_MONITOR; | 2879 | ieee80211_rx_result res = RX_DROP_MONITOR; |
2874 | 2880 | ||
2881 | __skb_queue_head_init(&reorder_release); | ||
2882 | |||
2875 | #define CALL_RXH(rxh) \ | 2883 | #define CALL_RXH(rxh) \ |
2876 | do { \ | 2884 | do { \ |
2877 | res = rxh(rx); \ | 2885 | res = rxh(rx); \ |
@@ -2881,9 +2889,9 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | |||
2881 | 2889 | ||
2882 | CALL_RXH(ieee80211_rx_h_check) | 2890 | CALL_RXH(ieee80211_rx_h_check) |
2883 | 2891 | ||
2884 | ieee80211_rx_reorder_ampdu(rx); | 2892 | ieee80211_rx_reorder_ampdu(rx, &reorder_release); |
2885 | 2893 | ||
2886 | ieee80211_rx_handlers(rx); | 2894 | ieee80211_rx_handlers(rx, &reorder_release); |
2887 | return; | 2895 | return; |
2888 | 2896 | ||
2889 | rxh_next: | 2897 | rxh_next: |
@@ -2898,6 +2906,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | |||
2898 | */ | 2906 | */ |
2899 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | 2907 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) |
2900 | { | 2908 | { |
2909 | struct sk_buff_head frames; | ||
2901 | struct ieee80211_rx_data rx = { | 2910 | struct ieee80211_rx_data rx = { |
2902 | .sta = sta, | 2911 | .sta = sta, |
2903 | .sdata = sta->sdata, | 2912 | .sdata = sta->sdata, |
@@ -2913,11 +2922,13 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | |||
2913 | if (!tid_agg_rx) | 2922 | if (!tid_agg_rx) |
2914 | return; | 2923 | return; |
2915 | 2924 | ||
2925 | __skb_queue_head_init(&frames); | ||
2926 | |||
2916 | spin_lock(&tid_agg_rx->reorder_lock); | 2927 | spin_lock(&tid_agg_rx->reorder_lock); |
2917 | ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx); | 2928 | ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx, &frames); |
2918 | spin_unlock(&tid_agg_rx->reorder_lock); | 2929 | spin_unlock(&tid_agg_rx->reorder_lock); |
2919 | 2930 | ||
2920 | ieee80211_rx_handlers(&rx); | 2931 | ieee80211_rx_handlers(&rx, &frames); |
2921 | } | 2932 | } |
2922 | 2933 | ||
2923 | /* main receive path */ | 2934 | /* main receive path */ |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 7f80f0a5026e..6d0b89e4aa31 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -34,7 +34,8 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local, | |||
34 | { | 34 | { |
35 | if (!bss) | 35 | if (!bss) |
36 | return; | 36 | return; |
37 | cfg80211_put_bss(container_of((void *)bss, struct cfg80211_bss, priv)); | 37 | cfg80211_put_bss(local->hw.wiphy, |
38 | container_of((void *)bss, struct cfg80211_bss, priv)); | ||
38 | } | 39 | } |
39 | 40 | ||
40 | static bool is_uapsd_supported(struct ieee802_11_elems *elems) | 41 | static bool is_uapsd_supported(struct ieee802_11_elems *elems) |
@@ -79,7 +80,10 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
79 | 80 | ||
80 | bss = (void *)cbss->priv; | 81 | bss = (void *)cbss->priv; |
81 | 82 | ||
82 | bss->device_ts = rx_status->device_timestamp; | 83 | if (beacon) |
84 | bss->device_ts_beacon = rx_status->device_timestamp; | ||
85 | else | ||
86 | bss->device_ts_presp = rx_status->device_timestamp; | ||
83 | 87 | ||
84 | if (elems->parse_error) { | 88 | if (elems->parse_error) { |
85 | if (beacon) | 89 | if (beacon) |
@@ -330,6 +334,9 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
330 | 334 | ||
331 | ieee80211_offchannel_stop_vifs(local); | 335 | ieee80211_offchannel_stop_vifs(local); |
332 | 336 | ||
337 | /* ensure nullfunc is transmitted before leaving operating channel */ | ||
338 | drv_flush(local, false); | ||
339 | |||
333 | ieee80211_configure_filter(local); | 340 | ieee80211_configure_filter(local); |
334 | 341 | ||
335 | /* We need to set power level at maximum rate for scanning. */ | 342 | /* We need to set power level at maximum rate for scanning. */ |
@@ -378,6 +385,11 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
378 | int i; | 385 | int i; |
379 | struct ieee80211_sub_if_data *sdata; | 386 | struct ieee80211_sub_if_data *sdata; |
380 | enum ieee80211_band band = local->hw.conf.channel->band; | 387 | enum ieee80211_band band = local->hw.conf.channel->band; |
388 | u32 tx_flags; | ||
389 | |||
390 | tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK; | ||
391 | if (local->scan_req->no_cck) | ||
392 | tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | ||
381 | 393 | ||
382 | sdata = rcu_dereference_protected(local->scan_sdata, | 394 | sdata = rcu_dereference_protected(local->scan_sdata, |
383 | lockdep_is_held(&local->mtx)); | 395 | lockdep_is_held(&local->mtx)); |
@@ -389,9 +401,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
389 | local->scan_req->ssids[i].ssid_len, | 401 | local->scan_req->ssids[i].ssid_len, |
390 | local->scan_req->ie, local->scan_req->ie_len, | 402 | local->scan_req->ie, local->scan_req->ie_len, |
391 | local->scan_req->rates[band], false, | 403 | local->scan_req->rates[band], false, |
392 | local->scan_req->no_cck ? | 404 | tx_flags, local->hw.conf.channel, true); |
393 | IEEE80211_TX_CTL_NO_CCK_RATE : 0, | ||
394 | local->hw.conf.channel, true); | ||
395 | 405 | ||
396 | /* | 406 | /* |
397 | * After sending probe requests, wait for probe responses | 407 | * After sending probe requests, wait for probe responses |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 47a0f0601768..19db20a58e23 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -137,13 +137,8 @@ static void cleanup_single_sta(struct sta_info *sta) | |||
137 | ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]); | 137 | ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]); |
138 | } | 138 | } |
139 | 139 | ||
140 | #ifdef CONFIG_MAC80211_MESH | 140 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
141 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 141 | mesh_sta_cleanup(sta); |
142 | mesh_accept_plinks_update(sdata); | ||
143 | mesh_plink_deactivate(sta); | ||
144 | del_timer_sync(&sta->plink_timer); | ||
145 | } | ||
146 | #endif | ||
147 | 142 | ||
148 | cancel_work_sync(&sta->drv_unblock_wk); | 143 | cancel_work_sync(&sta->drv_unblock_wk); |
149 | 144 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 5a1deba2c645..350578c396c0 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -298,6 +298,7 @@ struct sta_ampdu_mlme { | |||
298 | * @beacon_loss_count: number of times beacon loss has triggered | 298 | * @beacon_loss_count: number of times beacon loss has triggered |
299 | * @supports_40mhz: tracks whether the station advertised 40 MHz support | 299 | * @supports_40mhz: tracks whether the station advertised 40 MHz support |
300 | * as we overwrite its HT parameters with the currently used value | 300 | * as we overwrite its HT parameters with the currently used value |
301 | * @rcu_head: RCU head used for freeing this station struct | ||
301 | */ | 302 | */ |
302 | struct sta_info { | 303 | struct sta_info { |
303 | /* General information, mostly static */ | 304 | /* General information, mostly static */ |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 6ca53d64cb28..0bdd7aeb8958 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -36,7 +36,7 @@ | |||
36 | __entry->control_freq = (c)->chan->center_freq; \ | 36 | __entry->control_freq = (c)->chan->center_freq; \ |
37 | __entry->chan_width = (c)->width; \ | 37 | __entry->chan_width = (c)->width; \ |
38 | __entry->center_freq1 = (c)->center_freq1; \ | 38 | __entry->center_freq1 = (c)->center_freq1; \ |
39 | __entry->center_freq1 = (c)->center_freq2; | 39 | __entry->center_freq2 = (c)->center_freq2; |
40 | #define CHANDEF_PR_FMT " control:%d MHz width:%d center: %d/%d MHz" | 40 | #define CHANDEF_PR_FMT " control:%d MHz width:%d center: %d/%d MHz" |
41 | #define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \ | 41 | #define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \ |
42 | __entry->center_freq1, __entry->center_freq2 | 42 | __entry->center_freq1, __entry->center_freq2 |
@@ -340,6 +340,7 @@ TRACE_EVENT(drv_bss_info_changed, | |||
340 | __field(u16, assoc_cap) | 340 | __field(u16, assoc_cap) |
341 | __field(u64, sync_tsf) | 341 | __field(u64, sync_tsf) |
342 | __field(u32, sync_device_ts) | 342 | __field(u32, sync_device_ts) |
343 | __field(u8, sync_dtim_count) | ||
343 | __field(u32, basic_rates) | 344 | __field(u32, basic_rates) |
344 | __array(int, mcast_rate, IEEE80211_NUM_BANDS) | 345 | __array(int, mcast_rate, IEEE80211_NUM_BANDS) |
345 | __field(u16, ht_operation_mode) | 346 | __field(u16, ht_operation_mode) |
@@ -379,6 +380,7 @@ TRACE_EVENT(drv_bss_info_changed, | |||
379 | __entry->assoc_cap = info->assoc_capability; | 380 | __entry->assoc_cap = info->assoc_capability; |
380 | __entry->sync_tsf = info->sync_tsf; | 381 | __entry->sync_tsf = info->sync_tsf; |
381 | __entry->sync_device_ts = info->sync_device_ts; | 382 | __entry->sync_device_ts = info->sync_device_ts; |
383 | __entry->sync_dtim_count = info->sync_dtim_count; | ||
382 | __entry->basic_rates = info->basic_rates; | 384 | __entry->basic_rates = info->basic_rates; |
383 | memcpy(__entry->mcast_rate, info->mcast_rate, | 385 | memcpy(__entry->mcast_rate, info->mcast_rate, |
384 | sizeof(__entry->mcast_rate)); | 386 | sizeof(__entry->mcast_rate)); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 2ef0e19b06bb..f476aa6a771d 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1230,6 +1230,21 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, | |||
1230 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 1230 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
1231 | if (local->queue_stop_reasons[q] || | 1231 | if (local->queue_stop_reasons[q] || |
1232 | (!txpending && !skb_queue_empty(&local->pending[q]))) { | 1232 | (!txpending && !skb_queue_empty(&local->pending[q]))) { |
1233 | if (unlikely(info->flags & | ||
1234 | IEEE80211_TX_INTFL_OFFCHAN_TX_OK && | ||
1235 | local->queue_stop_reasons[q] & | ||
1236 | ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) { | ||
1237 | /* | ||
1238 | * Drop off-channel frames if queues are stopped | ||
1239 | * for any reason other than off-channel | ||
1240 | * operation. Never queue them. | ||
1241 | */ | ||
1242 | spin_unlock_irqrestore( | ||
1243 | &local->queue_stop_reason_lock, flags); | ||
1244 | ieee80211_purge_tx_queue(&local->hw, skbs); | ||
1245 | return true; | ||
1246 | } | ||
1247 | |||
1233 | /* | 1248 | /* |
1234 | * Since queue is stopped, queue up frames for later | 1249 | * Since queue is stopped, queue up frames for later |
1235 | * transmission from the tx-pending tasklet when the | 1250 | * transmission from the tx-pending tasklet when the |
diff --git a/net/wireless/core.c b/net/wireless/core.c index ce827242f390..f0a1bbe95cff 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -715,7 +715,7 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) | |||
715 | kfree(reg); | 715 | kfree(reg); |
716 | } | 716 | } |
717 | list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) | 717 | list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) |
718 | cfg80211_put_bss(&scan->pub); | 718 | cfg80211_put_bss(&rdev->wiphy, &scan->pub); |
719 | kfree(rdev); | 719 | kfree(rdev); |
720 | } | 720 | } |
721 | 721 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index 8396f7671c8d..37d70dc2fe82 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -8,7 +8,6 @@ | |||
8 | #include <linux/mutex.h> | 8 | #include <linux/mutex.h> |
9 | #include <linux/list.h> | 9 | #include <linux/list.h> |
10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
11 | #include <linux/kref.h> | ||
12 | #include <linux/rbtree.h> | 11 | #include <linux/rbtree.h> |
13 | #include <linux/debugfs.h> | 12 | #include <linux/debugfs.h> |
14 | #include <linux/rfkill.h> | 13 | #include <linux/rfkill.h> |
@@ -124,9 +123,10 @@ static inline void assert_cfg80211_lock(void) | |||
124 | 123 | ||
125 | struct cfg80211_internal_bss { | 124 | struct cfg80211_internal_bss { |
126 | struct list_head list; | 125 | struct list_head list; |
126 | struct list_head hidden_list; | ||
127 | struct rb_node rbn; | 127 | struct rb_node rbn; |
128 | unsigned long ts; | 128 | unsigned long ts; |
129 | struct kref ref; | 129 | unsigned long refcount; |
130 | atomic_t hold; | 130 | atomic_t hold; |
131 | 131 | ||
132 | /* must be last because of priv member */ | 132 | /* must be last because of priv member */ |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 9b9551e4a6f9..d80e47194d49 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -37,7 +37,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) | |||
37 | 37 | ||
38 | if (wdev->current_bss) { | 38 | if (wdev->current_bss) { |
39 | cfg80211_unhold_bss(wdev->current_bss); | 39 | cfg80211_unhold_bss(wdev->current_bss); |
40 | cfg80211_put_bss(&wdev->current_bss->pub); | 40 | cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); |
41 | } | 41 | } |
42 | 42 | ||
43 | cfg80211_hold_bss(bss_from_pub(bss)); | 43 | cfg80211_hold_bss(bss_from_pub(bss)); |
@@ -182,7 +182,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) | |||
182 | 182 | ||
183 | if (wdev->current_bss) { | 183 | if (wdev->current_bss) { |
184 | cfg80211_unhold_bss(wdev->current_bss); | 184 | cfg80211_unhold_bss(wdev->current_bss); |
185 | cfg80211_put_bss(&wdev->current_bss->pub); | 185 | cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); |
186 | } | 186 | } |
187 | 187 | ||
188 | wdev->current_bss = NULL; | 188 | wdev->current_bss = NULL; |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index fee9bf70efcf..8e6920728c43 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -58,7 +58,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, | |||
58 | */ | 58 | */ |
59 | if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && | 59 | if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && |
60 | cfg80211_sme_failed_reassoc(wdev)) { | 60 | cfg80211_sme_failed_reassoc(wdev)) { |
61 | cfg80211_put_bss(bss); | 61 | cfg80211_put_bss(wiphy, bss); |
62 | goto out; | 62 | goto out; |
63 | } | 63 | } |
64 | 64 | ||
@@ -70,7 +70,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, | |||
70 | * do not call connect_result() now because the | 70 | * do not call connect_result() now because the |
71 | * sme will schedule work that does it later. | 71 | * sme will schedule work that does it later. |
72 | */ | 72 | */ |
73 | cfg80211_put_bss(bss); | 73 | cfg80211_put_bss(wiphy, bss); |
74 | goto out; | 74 | goto out; |
75 | } | 75 | } |
76 | 76 | ||
@@ -108,7 +108,7 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
108 | if (wdev->current_bss && | 108 | if (wdev->current_bss && |
109 | ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { | 109 | ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { |
110 | cfg80211_unhold_bss(wdev->current_bss); | 110 | cfg80211_unhold_bss(wdev->current_bss); |
111 | cfg80211_put_bss(&wdev->current_bss->pub); | 111 | cfg80211_put_bss(wiphy, &wdev->current_bss->pub); |
112 | wdev->current_bss = NULL; | 112 | wdev->current_bss = NULL; |
113 | was_current = true; | 113 | was_current = true; |
114 | } | 114 | } |
@@ -164,7 +164,7 @@ void __cfg80211_send_disassoc(struct net_device *dev, | |||
164 | ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { | 164 | ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { |
165 | cfg80211_sme_disassoc(dev, wdev->current_bss); | 165 | cfg80211_sme_disassoc(dev, wdev->current_bss); |
166 | cfg80211_unhold_bss(wdev->current_bss); | 166 | cfg80211_unhold_bss(wdev->current_bss); |
167 | cfg80211_put_bss(&wdev->current_bss->pub); | 167 | cfg80211_put_bss(wiphy, &wdev->current_bss->pub); |
168 | wdev->current_bss = NULL; | 168 | wdev->current_bss = NULL; |
169 | } else | 169 | } else |
170 | WARN_ON(1); | 170 | WARN_ON(1); |
@@ -324,7 +324,7 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
324 | err = rdev_auth(rdev, dev, &req); | 324 | err = rdev_auth(rdev, dev, &req); |
325 | 325 | ||
326 | out: | 326 | out: |
327 | cfg80211_put_bss(req.bss); | 327 | cfg80211_put_bss(&rdev->wiphy, req.bss); |
328 | return err; | 328 | return err; |
329 | } | 329 | } |
330 | 330 | ||
@@ -432,7 +432,7 @@ out: | |||
432 | if (err) { | 432 | if (err) { |
433 | if (was_connected) | 433 | if (was_connected) |
434 | wdev->sme_state = CFG80211_SME_CONNECTED; | 434 | wdev->sme_state = CFG80211_SME_CONNECTED; |
435 | cfg80211_put_bss(req.bss); | 435 | cfg80211_put_bss(&rdev->wiphy, req.bss); |
436 | } | 436 | } |
437 | 437 | ||
438 | return err; | 438 | return err; |
@@ -572,7 +572,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
572 | 572 | ||
573 | if (wdev->current_bss) { | 573 | if (wdev->current_bss) { |
574 | cfg80211_unhold_bss(wdev->current_bss); | 574 | cfg80211_unhold_bss(wdev->current_bss); |
575 | cfg80211_put_bss(&wdev->current_bss->pub); | 575 | cfg80211_put_bss(&rdev->wiphy, &wdev->current_bss->pub); |
576 | wdev->current_bss = NULL; | 576 | wdev->current_bss = NULL; |
577 | } | 577 | } |
578 | } | 578 | } |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 807d448e702e..93bc63eae076 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -4997,6 +4997,7 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, | |||
4997 | const struct cfg80211_bss_ies *ies; | 4997 | const struct cfg80211_bss_ies *ies; |
4998 | void *hdr; | 4998 | void *hdr; |
4999 | struct nlattr *bss; | 4999 | struct nlattr *bss; |
5000 | bool tsf = false; | ||
5000 | 5001 | ||
5001 | ASSERT_WDEV_LOCK(wdev); | 5002 | ASSERT_WDEV_LOCK(wdev); |
5002 | 5003 | ||
@@ -5020,22 +5021,24 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, | |||
5020 | 5021 | ||
5021 | rcu_read_lock(); | 5022 | rcu_read_lock(); |
5022 | ies = rcu_dereference(res->ies); | 5023 | ies = rcu_dereference(res->ies); |
5023 | if (ies && ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS, | 5024 | if (ies) { |
5024 | ies->len, ies->data)) { | 5025 | if (nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf)) |
5025 | rcu_read_unlock(); | 5026 | goto fail_unlock_rcu; |
5026 | goto nla_put_failure; | 5027 | tsf = true; |
5028 | if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS, | ||
5029 | ies->len, ies->data)) | ||
5030 | goto fail_unlock_rcu; | ||
5027 | } | 5031 | } |
5028 | ies = rcu_dereference(res->beacon_ies); | 5032 | ies = rcu_dereference(res->beacon_ies); |
5029 | if (ies && ies->len && nla_put(msg, NL80211_BSS_BEACON_IES, | 5033 | if (ies) { |
5030 | ies->len, ies->data)) { | 5034 | if (!tsf && nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf)) |
5031 | rcu_read_unlock(); | 5035 | goto fail_unlock_rcu; |
5032 | goto nla_put_failure; | 5036 | if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES, |
5037 | ies->len, ies->data)) | ||
5038 | goto fail_unlock_rcu; | ||
5033 | } | 5039 | } |
5034 | rcu_read_unlock(); | 5040 | rcu_read_unlock(); |
5035 | 5041 | ||
5036 | if (res->tsf && | ||
5037 | nla_put_u64(msg, NL80211_BSS_TSF, res->tsf)) | ||
5038 | goto nla_put_failure; | ||
5039 | if (res->beacon_interval && | 5042 | if (res->beacon_interval && |
5040 | nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval)) | 5043 | nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval)) |
5041 | goto nla_put_failure; | 5044 | goto nla_put_failure; |
@@ -5080,6 +5083,8 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, | |||
5080 | 5083 | ||
5081 | return genlmsg_end(msg, hdr); | 5084 | return genlmsg_end(msg, hdr); |
5082 | 5085 | ||
5086 | fail_unlock_rcu: | ||
5087 | rcu_read_unlock(); | ||
5083 | nla_put_failure: | 5088 | nla_put_failure: |
5084 | genlmsg_cancel(msg, hdr); | 5089 | genlmsg_cancel(msg, hdr); |
5085 | return -EMSGSIZE; | 5090 | return -EMSGSIZE; |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 6ea626b30a2a..08d3da2c70ab 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -2189,10 +2189,15 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
2189 | * However if a driver requested this specific regulatory | 2189 | * However if a driver requested this specific regulatory |
2190 | * domain we keep it for its private use | 2190 | * domain we keep it for its private use |
2191 | */ | 2191 | */ |
2192 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER) | 2192 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER) { |
2193 | const struct ieee80211_regdomain *tmp; | ||
2194 | |||
2195 | tmp = get_wiphy_regdom(request_wiphy); | ||
2193 | rcu_assign_pointer(request_wiphy->regd, rd); | 2196 | rcu_assign_pointer(request_wiphy->regd, rd); |
2194 | else | 2197 | rcu_free_regdom(tmp); |
2198 | } else { | ||
2195 | kfree(rd); | 2199 | kfree(rd); |
2200 | } | ||
2196 | 2201 | ||
2197 | rd = NULL; | 2202 | rd = NULL; |
2198 | 2203 | ||
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 36daacb31788..b7a167984986 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -19,46 +19,124 @@ | |||
19 | #include "wext-compat.h" | 19 | #include "wext-compat.h" |
20 | #include "rdev-ops.h" | 20 | #include "rdev-ops.h" |
21 | 21 | ||
22 | /** | ||
23 | * DOC: BSS tree/list structure | ||
24 | * | ||
25 | * At the top level, the BSS list is kept in both a list in each | ||
26 | * registered device (@bss_list) as well as an RB-tree for faster | ||
27 | * lookup. In the RB-tree, entries can be looked up using their | ||
28 | * channel, MESHID, MESHCONF (for MBSSes) or channel, BSSID, SSID | ||
29 | * for other BSSes. | ||
30 | * | ||
31 | * Due to the possibility of hidden SSIDs, there's a second level | ||
32 | * structure, the "hidden_list" and "hidden_beacon_bss" pointer. | ||
33 | * The hidden_list connects all BSSes belonging to a single AP | ||
34 | * that has a hidden SSID, and connects beacon and probe response | ||
35 | * entries. For a probe response entry for a hidden SSID, the | ||
36 | * hidden_beacon_bss pointer points to the BSS struct holding the | ||
37 | * beacon's information. | ||
38 | * | ||
39 | * Reference counting is done for all these references except for | ||
40 | * the hidden_list, so that a beacon BSS struct that is otherwise | ||
41 | * not referenced has one reference for being on the bss_list and | ||
42 | * one for each probe response entry that points to it using the | ||
43 | * hidden_beacon_bss pointer. When a BSS struct that has such a | ||
44 | * pointer is get/put, the refcount update is also propagated to | ||
45 | * the referenced struct, this ensure that it cannot get removed | ||
46 | * while somebody is using the probe response version. | ||
47 | * | ||
48 | * Note that the hidden_beacon_bss pointer never changes, due to | ||
49 | * the reference counting. Therefore, no locking is needed for | ||
50 | * it. | ||
51 | * | ||
52 | * Also note that the hidden_beacon_bss pointer is only relevant | ||
53 | * if the driver uses something other than the IEs, e.g. private | ||
54 | * data stored stored in the BSS struct, since the beacon IEs are | ||
55 | * also linked into the probe response struct. | ||
56 | */ | ||
57 | |||
22 | #define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ) | 58 | #define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ) |
23 | 59 | ||
24 | static void bss_release(struct kref *ref) | 60 | static void bss_free(struct cfg80211_internal_bss *bss) |
25 | { | 61 | { |
26 | struct cfg80211_bss_ies *ies; | 62 | struct cfg80211_bss_ies *ies; |
27 | struct cfg80211_internal_bss *bss; | ||
28 | |||
29 | bss = container_of(ref, struct cfg80211_internal_bss, ref); | ||
30 | 63 | ||
31 | if (WARN_ON(atomic_read(&bss->hold))) | 64 | if (WARN_ON(atomic_read(&bss->hold))) |
32 | return; | 65 | return; |
33 | 66 | ||
34 | ies = (void *)rcu_access_pointer(bss->pub.beacon_ies); | 67 | ies = (void *)rcu_access_pointer(bss->pub.beacon_ies); |
35 | if (ies) | 68 | if (ies && !bss->pub.hidden_beacon_bss) |
36 | kfree_rcu(ies, rcu_head); | 69 | kfree_rcu(ies, rcu_head); |
37 | ies = (void *)rcu_access_pointer(bss->pub.proberesp_ies); | 70 | ies = (void *)rcu_access_pointer(bss->pub.proberesp_ies); |
38 | if (ies) | 71 | if (ies) |
39 | kfree_rcu(ies, rcu_head); | 72 | kfree_rcu(ies, rcu_head); |
40 | 73 | ||
74 | /* | ||
75 | * This happens when the module is removed, it doesn't | ||
76 | * really matter any more save for completeness | ||
77 | */ | ||
78 | if (!list_empty(&bss->hidden_list)) | ||
79 | list_del(&bss->hidden_list); | ||
80 | |||
41 | kfree(bss); | 81 | kfree(bss); |
42 | } | 82 | } |
43 | 83 | ||
44 | static inline void bss_ref_get(struct cfg80211_internal_bss *bss) | 84 | static inline void bss_ref_get(struct cfg80211_registered_device *dev, |
85 | struct cfg80211_internal_bss *bss) | ||
45 | { | 86 | { |
46 | kref_get(&bss->ref); | 87 | lockdep_assert_held(&dev->bss_lock); |
88 | |||
89 | bss->refcount++; | ||
90 | if (bss->pub.hidden_beacon_bss) { | ||
91 | bss = container_of(bss->pub.hidden_beacon_bss, | ||
92 | struct cfg80211_internal_bss, | ||
93 | pub); | ||
94 | bss->refcount++; | ||
95 | } | ||
47 | } | 96 | } |
48 | 97 | ||
49 | static inline void bss_ref_put(struct cfg80211_internal_bss *bss) | 98 | static inline void bss_ref_put(struct cfg80211_registered_device *dev, |
99 | struct cfg80211_internal_bss *bss) | ||
50 | { | 100 | { |
51 | kref_put(&bss->ref, bss_release); | 101 | lockdep_assert_held(&dev->bss_lock); |
102 | |||
103 | if (bss->pub.hidden_beacon_bss) { | ||
104 | struct cfg80211_internal_bss *hbss; | ||
105 | hbss = container_of(bss->pub.hidden_beacon_bss, | ||
106 | struct cfg80211_internal_bss, | ||
107 | pub); | ||
108 | hbss->refcount--; | ||
109 | if (hbss->refcount == 0) | ||
110 | bss_free(hbss); | ||
111 | } | ||
112 | bss->refcount--; | ||
113 | if (bss->refcount == 0) | ||
114 | bss_free(bss); | ||
52 | } | 115 | } |
53 | 116 | ||
54 | static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev, | 117 | static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *dev, |
55 | struct cfg80211_internal_bss *bss) | 118 | struct cfg80211_internal_bss *bss) |
56 | { | 119 | { |
57 | lockdep_assert_held(&dev->bss_lock); | 120 | lockdep_assert_held(&dev->bss_lock); |
58 | 121 | ||
122 | if (!list_empty(&bss->hidden_list)) { | ||
123 | /* | ||
124 | * don't remove the beacon entry if it has | ||
125 | * probe responses associated with it | ||
126 | */ | ||
127 | if (!bss->pub.hidden_beacon_bss) | ||
128 | return false; | ||
129 | /* | ||
130 | * if it's a probe response entry break its | ||
131 | * link to the other entries in the group | ||
132 | */ | ||
133 | list_del_init(&bss->hidden_list); | ||
134 | } | ||
135 | |||
59 | list_del_init(&bss->list); | 136 | list_del_init(&bss->list); |
60 | rb_erase(&bss->rbn, &dev->bss_tree); | 137 | rb_erase(&bss->rbn, &dev->bss_tree); |
61 | bss_ref_put(bss); | 138 | bss_ref_put(dev, bss); |
139 | return true; | ||
62 | } | 140 | } |
63 | 141 | ||
64 | static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev, | 142 | static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev, |
@@ -75,8 +153,8 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev, | |||
75 | if (!time_after(expire_time, bss->ts)) | 153 | if (!time_after(expire_time, bss->ts)) |
76 | continue; | 154 | continue; |
77 | 155 | ||
78 | __cfg80211_unlink_bss(dev, bss); | 156 | if (__cfg80211_unlink_bss(dev, bss)) |
79 | expired = true; | 157 | expired = true; |
80 | } | 158 | } |
81 | 159 | ||
82 | if (expired) | 160 | if (expired) |
@@ -466,7 +544,7 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, | |||
466 | continue; | 544 | continue; |
467 | if (is_bss(&bss->pub, bssid, ssid, ssid_len)) { | 545 | if (is_bss(&bss->pub, bssid, ssid, ssid_len)) { |
468 | res = bss; | 546 | res = bss; |
469 | bss_ref_get(res); | 547 | bss_ref_get(dev, res); |
470 | break; | 548 | break; |
471 | } | 549 | } |
472 | } | 550 | } |
@@ -532,23 +610,67 @@ rb_find_bss(struct cfg80211_registered_device *dev, | |||
532 | return NULL; | 610 | return NULL; |
533 | } | 611 | } |
534 | 612 | ||
535 | static void | 613 | static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev, |
536 | copy_hidden_ies(struct cfg80211_internal_bss *res, | 614 | struct cfg80211_internal_bss *new) |
537 | struct cfg80211_internal_bss *hidden) | ||
538 | { | 615 | { |
539 | const struct cfg80211_bss_ies *ies; | 616 | const struct cfg80211_bss_ies *ies; |
617 | struct cfg80211_internal_bss *bss; | ||
618 | const u8 *ie; | ||
619 | int i, ssidlen; | ||
620 | u8 fold = 0; | ||
540 | 621 | ||
541 | if (rcu_access_pointer(res->pub.beacon_ies)) | 622 | ies = rcu_access_pointer(new->pub.beacon_ies); |
542 | return; | ||
543 | |||
544 | ies = rcu_access_pointer(hidden->pub.beacon_ies); | ||
545 | if (WARN_ON(!ies)) | 623 | if (WARN_ON(!ies)) |
546 | return; | 624 | return false; |
547 | 625 | ||
548 | ies = kmemdup(ies, sizeof(*ies) + ies->len, GFP_ATOMIC); | 626 | ie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len); |
549 | if (unlikely(!ies)) | 627 | if (!ie) { |
550 | return; | 628 | /* nothing to do */ |
551 | rcu_assign_pointer(res->pub.beacon_ies, ies); | 629 | return true; |
630 | } | ||
631 | |||
632 | ssidlen = ie[1]; | ||
633 | for (i = 0; i < ssidlen; i++) | ||
634 | fold |= ie[2 + i]; | ||
635 | |||
636 | if (fold) { | ||
637 | /* not a hidden SSID */ | ||
638 | return true; | ||
639 | } | ||
640 | |||
641 | /* This is the bad part ... */ | ||
642 | |||
643 | list_for_each_entry(bss, &dev->bss_list, list) { | ||
644 | if (!ether_addr_equal(bss->pub.bssid, new->pub.bssid)) | ||
645 | continue; | ||
646 | if (bss->pub.channel != new->pub.channel) | ||
647 | continue; | ||
648 | if (rcu_access_pointer(bss->pub.beacon_ies)) | ||
649 | continue; | ||
650 | ies = rcu_access_pointer(bss->pub.ies); | ||
651 | if (!ies) | ||
652 | continue; | ||
653 | ie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len); | ||
654 | if (!ie) | ||
655 | continue; | ||
656 | if (ssidlen && ie[1] != ssidlen) | ||
657 | continue; | ||
658 | /* that would be odd ... */ | ||
659 | if (bss->pub.beacon_ies) | ||
660 | continue; | ||
661 | if (WARN_ON_ONCE(bss->pub.hidden_beacon_bss)) | ||
662 | continue; | ||
663 | if (WARN_ON_ONCE(!list_empty(&bss->hidden_list))) | ||
664 | list_del(&bss->hidden_list); | ||
665 | /* combine them */ | ||
666 | list_add(&bss->hidden_list, &new->hidden_list); | ||
667 | bss->pub.hidden_beacon_bss = &new->pub; | ||
668 | new->refcount += bss->refcount; | ||
669 | rcu_assign_pointer(bss->pub.beacon_ies, | ||
670 | new->pub.beacon_ies); | ||
671 | } | ||
672 | |||
673 | return true; | ||
552 | } | 674 | } |
553 | 675 | ||
554 | static struct cfg80211_internal_bss * | 676 | static struct cfg80211_internal_bss * |
@@ -573,7 +695,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
573 | 695 | ||
574 | if (found) { | 696 | if (found) { |
575 | found->pub.beacon_interval = tmp->pub.beacon_interval; | 697 | found->pub.beacon_interval = tmp->pub.beacon_interval; |
576 | found->pub.tsf = tmp->pub.tsf; | ||
577 | found->pub.signal = tmp->pub.signal; | 698 | found->pub.signal = tmp->pub.signal; |
578 | found->pub.capability = tmp->pub.capability; | 699 | found->pub.capability = tmp->pub.capability; |
579 | found->ts = tmp->ts; | 700 | found->ts = tmp->ts; |
@@ -594,6 +715,21 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
594 | rcu_head); | 715 | rcu_head); |
595 | } else if (rcu_access_pointer(tmp->pub.beacon_ies)) { | 716 | } else if (rcu_access_pointer(tmp->pub.beacon_ies)) { |
596 | const struct cfg80211_bss_ies *old; | 717 | const struct cfg80211_bss_ies *old; |
718 | struct cfg80211_internal_bss *bss; | ||
719 | |||
720 | if (found->pub.hidden_beacon_bss && | ||
721 | !list_empty(&found->hidden_list)) { | ||
722 | /* | ||
723 | * The found BSS struct is one of the probe | ||
724 | * response members of a group, but we're | ||
725 | * receiving a beacon (beacon_ies in the tmp | ||
726 | * bss is used). This can only mean that the | ||
727 | * AP changed its beacon from not having an | ||
728 | * SSID to showing it, which is confusing so | ||
729 | * drop this information. | ||
730 | */ | ||
731 | goto drop; | ||
732 | } | ||
597 | 733 | ||
598 | old = rcu_access_pointer(found->pub.beacon_ies); | 734 | old = rcu_access_pointer(found->pub.beacon_ies); |
599 | 735 | ||
@@ -605,6 +741,18 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
605 | rcu_assign_pointer(found->pub.ies, | 741 | rcu_assign_pointer(found->pub.ies, |
606 | tmp->pub.beacon_ies); | 742 | tmp->pub.beacon_ies); |
607 | 743 | ||
744 | /* Assign beacon IEs to all sub entries */ | ||
745 | list_for_each_entry(bss, &found->hidden_list, | ||
746 | hidden_list) { | ||
747 | const struct cfg80211_bss_ies *ies; | ||
748 | |||
749 | ies = rcu_access_pointer(bss->pub.beacon_ies); | ||
750 | WARN_ON(ies != old); | ||
751 | |||
752 | rcu_assign_pointer(bss->pub.beacon_ies, | ||
753 | tmp->pub.beacon_ies); | ||
754 | } | ||
755 | |||
608 | if (old) | 756 | if (old) |
609 | kfree_rcu((struct cfg80211_bss_ies *)old, | 757 | kfree_rcu((struct cfg80211_bss_ies *)old, |
610 | rcu_head); | 758 | rcu_head); |
@@ -614,24 +762,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
614 | struct cfg80211_internal_bss *hidden; | 762 | struct cfg80211_internal_bss *hidden; |
615 | struct cfg80211_bss_ies *ies; | 763 | struct cfg80211_bss_ies *ies; |
616 | 764 | ||
617 | /* First check if the beacon is a probe response from | ||
618 | * a hidden bss. If so, copy beacon ies (with nullified | ||
619 | * ssid) into the probe response bss entry (with real ssid). | ||
620 | * It is required basically for PSM implementation | ||
621 | * (probe responses do not contain tim ie) */ | ||
622 | |||
623 | /* TODO: The code is not trying to update existing probe | ||
624 | * response bss entries when beacon ies are | ||
625 | * getting changed. */ | ||
626 | hidden = rb_find_bss(dev, tmp, BSS_CMP_HIDE_ZLEN); | ||
627 | if (hidden) { | ||
628 | copy_hidden_ies(tmp, hidden); | ||
629 | } else { | ||
630 | hidden = rb_find_bss(dev, tmp, BSS_CMP_HIDE_NUL); | ||
631 | if (hidden) | ||
632 | copy_hidden_ies(tmp, hidden); | ||
633 | } | ||
634 | |||
635 | /* | 765 | /* |
636 | * create a copy -- the "res" variable that is passed in | 766 | * create a copy -- the "res" variable that is passed in |
637 | * is allocated on the stack since it's not needed in the | 767 | * is allocated on the stack since it's not needed in the |
@@ -646,21 +776,51 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
646 | ies = (void *)rcu_dereference(tmp->pub.proberesp_ies); | 776 | ies = (void *)rcu_dereference(tmp->pub.proberesp_ies); |
647 | if (ies) | 777 | if (ies) |
648 | kfree_rcu(ies, rcu_head); | 778 | kfree_rcu(ies, rcu_head); |
649 | spin_unlock_bh(&dev->bss_lock); | 779 | goto drop; |
650 | return NULL; | ||
651 | } | 780 | } |
652 | memcpy(new, tmp, sizeof(*new)); | 781 | memcpy(new, tmp, sizeof(*new)); |
653 | kref_init(&new->ref); | 782 | new->refcount = 1; |
783 | INIT_LIST_HEAD(&new->hidden_list); | ||
784 | |||
785 | if (rcu_access_pointer(tmp->pub.proberesp_ies)) { | ||
786 | hidden = rb_find_bss(dev, tmp, BSS_CMP_HIDE_ZLEN); | ||
787 | if (!hidden) | ||
788 | hidden = rb_find_bss(dev, tmp, | ||
789 | BSS_CMP_HIDE_NUL); | ||
790 | if (hidden) { | ||
791 | new->pub.hidden_beacon_bss = &hidden->pub; | ||
792 | list_add(&new->hidden_list, | ||
793 | &hidden->hidden_list); | ||
794 | hidden->refcount++; | ||
795 | rcu_assign_pointer(new->pub.beacon_ies, | ||
796 | hidden->pub.beacon_ies); | ||
797 | } | ||
798 | } else { | ||
799 | /* | ||
800 | * Ok so we found a beacon, and don't have an entry. If | ||
801 | * it's a beacon with hidden SSID, we might be in for an | ||
802 | * expensive search for any probe responses that should | ||
803 | * be grouped with this beacon for updates ... | ||
804 | */ | ||
805 | if (!cfg80211_combine_bsses(dev, new)) { | ||
806 | kfree(new); | ||
807 | goto drop; | ||
808 | } | ||
809 | } | ||
810 | |||
654 | list_add_tail(&new->list, &dev->bss_list); | 811 | list_add_tail(&new->list, &dev->bss_list); |
655 | rb_insert_bss(dev, new); | 812 | rb_insert_bss(dev, new); |
656 | found = new; | 813 | found = new; |
657 | } | 814 | } |
658 | 815 | ||
659 | dev->bss_generation++; | 816 | dev->bss_generation++; |
817 | bss_ref_get(dev, found); | ||
660 | spin_unlock_bh(&dev->bss_lock); | 818 | spin_unlock_bh(&dev->bss_lock); |
661 | 819 | ||
662 | bss_ref_get(found); | ||
663 | return found; | 820 | return found; |
821 | drop: | ||
822 | spin_unlock_bh(&dev->bss_lock); | ||
823 | return NULL; | ||
664 | } | 824 | } |
665 | 825 | ||
666 | static struct ieee80211_channel * | 826 | static struct ieee80211_channel * |
@@ -719,7 +879,6 @@ cfg80211_inform_bss(struct wiphy *wiphy, | |||
719 | memcpy(tmp.pub.bssid, bssid, ETH_ALEN); | 879 | memcpy(tmp.pub.bssid, bssid, ETH_ALEN); |
720 | tmp.pub.channel = channel; | 880 | tmp.pub.channel = channel; |
721 | tmp.pub.signal = signal; | 881 | tmp.pub.signal = signal; |
722 | tmp.pub.tsf = tsf; | ||
723 | tmp.pub.beacon_interval = beacon_interval; | 882 | tmp.pub.beacon_interval = beacon_interval; |
724 | tmp.pub.capability = capability; | 883 | tmp.pub.capability = capability; |
725 | /* | 884 | /* |
@@ -734,6 +893,7 @@ cfg80211_inform_bss(struct wiphy *wiphy, | |||
734 | if (!ies) | 893 | if (!ies) |
735 | return NULL; | 894 | return NULL; |
736 | ies->len = ielen; | 895 | ies->len = ielen; |
896 | ies->tsf = tsf; | ||
737 | memcpy(ies->data, ie, ielen); | 897 | memcpy(ies->data, ie, ielen); |
738 | 898 | ||
739 | rcu_assign_pointer(tmp.pub.beacon_ies, ies); | 899 | rcu_assign_pointer(tmp.pub.beacon_ies, ies); |
@@ -790,6 +950,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
790 | if (!ies) | 950 | if (!ies) |
791 | return NULL; | 951 | return NULL; |
792 | ies->len = ielen; | 952 | ies->len = ielen; |
953 | ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); | ||
793 | memcpy(ies->data, mgmt->u.probe_resp.variable, ielen); | 954 | memcpy(ies->data, mgmt->u.probe_resp.variable, ielen); |
794 | 955 | ||
795 | if (ieee80211_is_probe_resp(mgmt->frame_control)) | 956 | if (ieee80211_is_probe_resp(mgmt->frame_control)) |
@@ -801,7 +962,6 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
801 | memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN); | 962 | memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN); |
802 | tmp.pub.channel = channel; | 963 | tmp.pub.channel = channel; |
803 | tmp.pub.signal = signal; | 964 | tmp.pub.signal = signal; |
804 | tmp.pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); | ||
805 | tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); | 965 | tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); |
806 | tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); | 966 | tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); |
807 | 967 | ||
@@ -818,27 +978,35 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
818 | } | 978 | } |
819 | EXPORT_SYMBOL(cfg80211_inform_bss_frame); | 979 | EXPORT_SYMBOL(cfg80211_inform_bss_frame); |
820 | 980 | ||
821 | void cfg80211_ref_bss(struct cfg80211_bss *pub) | 981 | void cfg80211_ref_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) |
822 | { | 982 | { |
983 | struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); | ||
823 | struct cfg80211_internal_bss *bss; | 984 | struct cfg80211_internal_bss *bss; |
824 | 985 | ||
825 | if (!pub) | 986 | if (!pub) |
826 | return; | 987 | return; |
827 | 988 | ||
828 | bss = container_of(pub, struct cfg80211_internal_bss, pub); | 989 | bss = container_of(pub, struct cfg80211_internal_bss, pub); |
829 | bss_ref_get(bss); | 990 | |
991 | spin_lock_bh(&dev->bss_lock); | ||
992 | bss_ref_get(dev, bss); | ||
993 | spin_unlock_bh(&dev->bss_lock); | ||
830 | } | 994 | } |
831 | EXPORT_SYMBOL(cfg80211_ref_bss); | 995 | EXPORT_SYMBOL(cfg80211_ref_bss); |
832 | 996 | ||
833 | void cfg80211_put_bss(struct cfg80211_bss *pub) | 997 | void cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) |
834 | { | 998 | { |
999 | struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); | ||
835 | struct cfg80211_internal_bss *bss; | 1000 | struct cfg80211_internal_bss *bss; |
836 | 1001 | ||
837 | if (!pub) | 1002 | if (!pub) |
838 | return; | 1003 | return; |
839 | 1004 | ||
840 | bss = container_of(pub, struct cfg80211_internal_bss, pub); | 1005 | bss = container_of(pub, struct cfg80211_internal_bss, pub); |
841 | bss_ref_put(bss); | 1006 | |
1007 | spin_lock_bh(&dev->bss_lock); | ||
1008 | bss_ref_put(dev, bss); | ||
1009 | spin_unlock_bh(&dev->bss_lock); | ||
842 | } | 1010 | } |
843 | EXPORT_SYMBOL(cfg80211_put_bss); | 1011 | EXPORT_SYMBOL(cfg80211_put_bss); |
844 | 1012 | ||
@@ -854,8 +1022,8 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) | |||
854 | 1022 | ||
855 | spin_lock_bh(&dev->bss_lock); | 1023 | spin_lock_bh(&dev->bss_lock); |
856 | if (!list_empty(&bss->list)) { | 1024 | if (!list_empty(&bss->list)) { |
857 | __cfg80211_unlink_bss(dev, bss); | 1025 | if (__cfg80211_unlink_bss(dev, bss)) |
858 | dev->bss_generation++; | 1026 | dev->bss_generation++; |
859 | } | 1027 | } |
860 | spin_unlock_bh(&dev->bss_lock); | 1028 | spin_unlock_bh(&dev->bss_lock); |
861 | } | 1029 | } |
@@ -1124,15 +1292,10 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1124 | 1292 | ||
1125 | rcu_read_lock(); | 1293 | rcu_read_lock(); |
1126 | ies = rcu_dereference(bss->pub.ies); | 1294 | ies = rcu_dereference(bss->pub.ies); |
1127 | if (ies) { | 1295 | rem = ies->len; |
1128 | rem = ies->len; | 1296 | ie = ies->data; |
1129 | ie = ies->data; | ||
1130 | } else { | ||
1131 | rem = 0; | ||
1132 | ie = NULL; | ||
1133 | } | ||
1134 | 1297 | ||
1135 | while (ies && rem >= 2) { | 1298 | while (rem >= 2) { |
1136 | /* invalid data */ | 1299 | /* invalid data */ |
1137 | if (ie[1] > rem - 2) | 1300 | if (ie[1] > rem - 2) |
1138 | break; | 1301 | break; |
@@ -1245,7 +1408,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
1245 | if (buf) { | 1408 | if (buf) { |
1246 | memset(&iwe, 0, sizeof(iwe)); | 1409 | memset(&iwe, 0, sizeof(iwe)); |
1247 | iwe.cmd = IWEVCUSTOM; | 1410 | iwe.cmd = IWEVCUSTOM; |
1248 | sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->pub.tsf)); | 1411 | sprintf(buf, "tsf=%016llx", (unsigned long long)(ies->tsf)); |
1249 | iwe.u.data.length = strlen(buf); | 1412 | iwe.u.data.length = strlen(buf); |
1250 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | 1413 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
1251 | &iwe, buf); | 1414 | &iwe, buf); |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index a825dfe12cf7..f432bd3755b1 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -301,7 +301,7 @@ static void __cfg80211_sme_scan_done(struct net_device *dev) | |||
301 | 301 | ||
302 | bss = cfg80211_get_conn_bss(wdev); | 302 | bss = cfg80211_get_conn_bss(wdev); |
303 | if (bss) { | 303 | if (bss) { |
304 | cfg80211_put_bss(bss); | 304 | cfg80211_put_bss(&rdev->wiphy, bss); |
305 | } else { | 305 | } else { |
306 | /* not found */ | 306 | /* not found */ |
307 | if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN) | 307 | if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN) |
@@ -464,7 +464,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
464 | 464 | ||
465 | if (wdev->current_bss) { | 465 | if (wdev->current_bss) { |
466 | cfg80211_unhold_bss(wdev->current_bss); | 466 | cfg80211_unhold_bss(wdev->current_bss); |
467 | cfg80211_put_bss(&wdev->current_bss->pub); | 467 | cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); |
468 | wdev->current_bss = NULL; | 468 | wdev->current_bss = NULL; |
469 | } | 469 | } |
470 | 470 | ||
@@ -480,7 +480,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
480 | kfree(wdev->connect_keys); | 480 | kfree(wdev->connect_keys); |
481 | wdev->connect_keys = NULL; | 481 | wdev->connect_keys = NULL; |
482 | wdev->ssid_len = 0; | 482 | wdev->ssid_len = 0; |
483 | cfg80211_put_bss(bss); | 483 | cfg80211_put_bss(wdev->wiphy, bss); |
484 | return; | 484 | return; |
485 | } | 485 | } |
486 | 486 | ||
@@ -586,7 +586,7 @@ void __cfg80211_roamed(struct wireless_dev *wdev, | |||
586 | } | 586 | } |
587 | 587 | ||
588 | cfg80211_unhold_bss(wdev->current_bss); | 588 | cfg80211_unhold_bss(wdev->current_bss); |
589 | cfg80211_put_bss(&wdev->current_bss->pub); | 589 | cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); |
590 | wdev->current_bss = NULL; | 590 | wdev->current_bss = NULL; |
591 | 591 | ||
592 | cfg80211_hold_bss(bss_from_pub(bss)); | 592 | cfg80211_hold_bss(bss_from_pub(bss)); |
@@ -621,7 +621,7 @@ void __cfg80211_roamed(struct wireless_dev *wdev, | |||
621 | 621 | ||
622 | return; | 622 | return; |
623 | out: | 623 | out: |
624 | cfg80211_put_bss(bss); | 624 | cfg80211_put_bss(wdev->wiphy, bss); |
625 | } | 625 | } |
626 | 626 | ||
627 | void cfg80211_roamed(struct net_device *dev, | 627 | void cfg80211_roamed(struct net_device *dev, |
@@ -663,7 +663,7 @@ void cfg80211_roamed_bss(struct net_device *dev, | |||
663 | 663 | ||
664 | ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); | 664 | ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); |
665 | if (!ev) { | 665 | if (!ev) { |
666 | cfg80211_put_bss(bss); | 666 | cfg80211_put_bss(wdev->wiphy, bss); |
667 | return; | 667 | return; |
668 | } | 668 | } |
669 | 669 | ||
@@ -704,7 +704,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
704 | 704 | ||
705 | if (wdev->current_bss) { | 705 | if (wdev->current_bss) { |
706 | cfg80211_unhold_bss(wdev->current_bss); | 706 | cfg80211_unhold_bss(wdev->current_bss); |
707 | cfg80211_put_bss(&wdev->current_bss->pub); | 707 | cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); |
708 | } | 708 | } |
709 | 709 | ||
710 | wdev->current_bss = NULL; | 710 | wdev->current_bss = NULL; |
@@ -875,7 +875,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
875 | if (bss) { | 875 | if (bss) { |
876 | wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; | 876 | wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; |
877 | err = cfg80211_conn_do_work(wdev); | 877 | err = cfg80211_conn_do_work(wdev); |
878 | cfg80211_put_bss(bss); | 878 | cfg80211_put_bss(wdev->wiphy, bss); |
879 | } else { | 879 | } else { |
880 | /* otherwise we'll need to scan for the AP first */ | 880 | /* otherwise we'll need to scan for the AP first */ |
881 | err = cfg80211_conn_scan(wdev); | 881 | err = cfg80211_conn_scan(wdev); |
diff --git a/net/wireless/util.c b/net/wireless/util.c index d7873c7ae0ec..37a56ee1e1ed 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -1217,10 +1217,10 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1217 | break; | 1217 | break; |
1218 | case NL80211_IFTYPE_P2P_CLIENT: | 1218 | case NL80211_IFTYPE_P2P_CLIENT: |
1219 | case NL80211_IFTYPE_STATION: | 1219 | case NL80211_IFTYPE_STATION: |
1220 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1220 | case NL80211_IFTYPE_MONITOR: | 1221 | case NL80211_IFTYPE_MONITOR: |
1221 | radar_required = false; | 1222 | radar_required = false; |
1222 | break; | 1223 | break; |
1223 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1224 | case NUM_NL80211_IFTYPES: | 1224 | case NUM_NL80211_IFTYPES: |
1225 | case NL80211_IFTYPE_UNSPECIFIED: | 1225 | case NL80211_IFTYPE_UNSPECIFIED: |
1226 | default: | 1226 | default: |