aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c1
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c8
-rw-r--r--drivers/net/wireless/cw1200/txrx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/main.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c6
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c23
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h1
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c10
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c23
-rw-r--r--drivers/net/wireless/mwifiex/init.c10
-rw-r--r--drivers/net/wireless/mwifiex/main.c13
-rw-r--r--drivers/net/wireless/mwifiex/main.h1
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c91
-rw-r--r--drivers/net/wireless/mwifiex/sdio.h3
-rw-r--r--net/mac80211/cfg.c2
-rw-r--r--net/mac80211/rc80211_minstrel.c3
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c10
-rw-r--r--net/mac80211/rx.c10
-rw-r--r--net/wireless/nl80211.c11
-rw-r--r--net/wireless/reg.c2
-rw-r--r--net/wireless/sme.c29
24 files changed, 184 insertions, 87 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 2469db5a5bb1..5205a3625e84 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -1295,7 +1295,9 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
1295 1295
1296 usb_set_intfdata(interface, NULL); 1296 usb_set_intfdata(interface, NULL);
1297 1297
1298 if (!unplugged && (hif_dev->flags & HIF_USB_START)) 1298 /* If firmware was loaded we should drop it
1299 * go back to first stage bootloader. */
1300 if (!unplugged && (hif_dev->flags & HIF_USB_READY))
1299 ath9k_hif_usb_reboot(udev); 1301 ath9k_hif_usb_reboot(udev);
1300 1302
1301 kfree(hif_dev); 1303 kfree(hif_dev);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 71a183ffc77f..c3676bf1d6c4 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -861,6 +861,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
861 if (error != 0) 861 if (error != 0)
862 goto err_rx; 862 goto err_rx;
863 863
864 ath9k_hw_disable(priv->ah);
864#ifdef CONFIG_MAC80211_LEDS 865#ifdef CONFIG_MAC80211_LEDS
865 /* must be initialized before ieee80211_register_hw */ 866 /* must be initialized before ieee80211_register_hw */
866 priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw, 867 priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw,
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index e8308ec30970..ab636767fbde 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -145,7 +145,7 @@ static void wil_print_ring(struct seq_file *s, const char *prefix,
145 le16_to_cpu(hdr.type), hdr.flags); 145 le16_to_cpu(hdr.type), hdr.flags);
146 if (len <= MAX_MBOXITEM_SIZE) { 146 if (len <= MAX_MBOXITEM_SIZE) {
147 int n = 0; 147 int n = 0;
148 unsigned char printbuf[16 * 3 + 2]; 148 char printbuf[16 * 3 + 2];
149 unsigned char databuf[MAX_MBOXITEM_SIZE]; 149 unsigned char databuf[MAX_MBOXITEM_SIZE];
150 void __iomem *src = wmi_buffer(wil, d.addr) + 150 void __iomem *src = wmi_buffer(wil, d.addr) +
151 sizeof(struct wil6210_mbox_hdr); 151 sizeof(struct wil6210_mbox_hdr);
@@ -416,7 +416,7 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
416 seq_printf(s, " SKB = %p\n", skb); 416 seq_printf(s, " SKB = %p\n", skb);
417 417
418 if (skb) { 418 if (skb) {
419 unsigned char printbuf[16 * 3 + 2]; 419 char printbuf[16 * 3 + 2];
420 int i = 0; 420 int i = 0;
421 int len = le16_to_cpu(d->dma.length); 421 int len = le16_to_cpu(d->dma.length);
422 void *p = skb->data; 422 void *p = skb->data;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 8e8975562ec3..80099016d21f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -242,7 +242,7 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp,
242{ 242{
243 unsigned long flags; 243 unsigned long flags;
244 244
245 if (!ifp) 245 if (!ifp || !ifp->ndev)
246 return; 246 return;
247 247
248 brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n", 248 brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n",
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index f0d9f7f6c83d..29b1f24c2d0f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -1744,13 +1744,14 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
1744 ulong flags; 1744 ulong flags;
1745 int fifo = BRCMF_FWS_FIFO_BCMC; 1745 int fifo = BRCMF_FWS_FIFO_BCMC;
1746 bool multicast = is_multicast_ether_addr(eh->h_dest); 1746 bool multicast = is_multicast_ether_addr(eh->h_dest);
1747 bool pae = eh->h_proto == htons(ETH_P_PAE);
1747 1748
1748 /* determine the priority */ 1749 /* determine the priority */
1749 if (!skb->priority) 1750 if (!skb->priority)
1750 skb->priority = cfg80211_classify8021d(skb); 1751 skb->priority = cfg80211_classify8021d(skb);
1751 1752
1752 drvr->tx_multicast += !!multicast; 1753 drvr->tx_multicast += !!multicast;
1753 if (ntohs(eh->h_proto) == ETH_P_PAE) 1754 if (pae)
1754 atomic_inc(&ifp->pend_8021x_cnt); 1755 atomic_inc(&ifp->pend_8021x_cnt);
1755 1756
1756 if (!brcmf_fws_fc_active(fws)) { 1757 if (!brcmf_fws_fc_active(fws)) {
@@ -1781,6 +1782,11 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
1781 brcmf_fws_schedule_deq(fws); 1782 brcmf_fws_schedule_deq(fws);
1782 } else { 1783 } else {
1783 brcmf_err("drop skb: no hanger slot\n"); 1784 brcmf_err("drop skb: no hanger slot\n");
1785 if (pae) {
1786 atomic_dec(&ifp->pend_8021x_cnt);
1787 if (waitqueue_active(&ifp->pend_8021x_wait))
1788 wake_up(&ifp->pend_8021x_wait);
1789 }
1784 brcmu_pkt_buf_free_skb(skb); 1790 brcmu_pkt_buf_free_skb(skb);
1785 } 1791 }
1786 brcmf_fws_unlock(drvr, flags); 1792 brcmf_fws_unlock(drvr, flags);
diff --git a/drivers/net/wireless/cw1200/txrx.c b/drivers/net/wireless/cw1200/txrx.c
index 5862c373d714..e824d4d4a18d 100644
--- a/drivers/net/wireless/cw1200/txrx.c
+++ b/drivers/net/wireless/cw1200/txrx.c
@@ -1165,7 +1165,7 @@ void cw1200_rx_cb(struct cw1200_common *priv,
1165 if (cw1200_handle_action_rx(priv, skb)) 1165 if (cw1200_handle_action_rx(priv, skb))
1166 return; 1166 return;
1167 } else if (ieee80211_is_beacon(frame->frame_control) && 1167 } else if (ieee80211_is_beacon(frame->frame_control) &&
1168 !arg->status && 1168 !arg->status && priv->vif &&
1169 !memcmp(ieee80211_get_SA(frame), priv->vif->bss_conf.bssid, 1169 !memcmp(ieee80211_get_SA(frame), priv->vif->bss_conf.bssid,
1170 ETH_ALEN)) { 1170 ETH_ALEN)) {
1171 const u8 *tim_ie; 1171 const u8 *tim_ie;
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 3952ddf2ddb2..1531a4fc0960 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -758,7 +758,7 @@ int iwl_alive_start(struct iwl_priv *priv)
758 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); 758 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
759 if (ret) 759 if (ret)
760 return ret; 760 return ret;
761 } else { 761 } else if (priv->lib->bt_params) {
762 /* 762 /*
763 * default is 2-wire BT coexexistence support 763 * default is 2-wire BT coexexistence support
764 */ 764 */
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index e56ed2a84888..c24a744910ac 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -988,7 +988,11 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
988 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 988 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
989 char buf[100]; 989 char buf[100];
990 990
991 if (!dbgfs_dir) 991 /*
992 * Check if debugfs directory already exist before creating it.
993 * This may happen when, for example, resetting hw or suspend-resume
994 */
995 if (!dbgfs_dir || mvmvif->dbgfs_dir)
992 return; 996 return;
993 997
994 mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir); 998 mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index e08683b20531..1eedc424051c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -257,7 +257,11 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
257 if (ret) 257 if (ret)
258 return ret; 258 return ret;
259 259
260 return ieee80211_register_hw(mvm->hw); 260 ret = ieee80211_register_hw(mvm->hw);
261 if (ret)
262 iwl_mvm_leds_exit(mvm);
263
264 return ret;
261} 265}
262 266
263static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, 267static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
@@ -385,6 +389,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
385 ieee80211_wake_queues(mvm->hw); 389 ieee80211_wake_queues(mvm->hw);
386 390
387 mvm->vif_count = 0; 391 mvm->vif_count = 0;
392 mvm->rx_ba_sessions = 0;
388} 393}
389 394
390static int iwl_mvm_mac_start(struct ieee80211_hw *hw) 395static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
@@ -1006,6 +1011,21 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
1006 mutex_lock(&mvm->mutex); 1011 mutex_lock(&mvm->mutex);
1007 if (old_state == IEEE80211_STA_NOTEXIST && 1012 if (old_state == IEEE80211_STA_NOTEXIST &&
1008 new_state == IEEE80211_STA_NONE) { 1013 new_state == IEEE80211_STA_NONE) {
1014 /*
1015 * Firmware bug - it'll crash if the beacon interval is less
1016 * than 16. We can't avoid connecting at all, so refuse the
1017 * station state change, this will cause mac80211 to abandon
1018 * attempts to connect to this AP, and eventually wpa_s will
1019 * blacklist the AP...
1020 */
1021 if (vif->type == NL80211_IFTYPE_STATION &&
1022 vif->bss_conf.beacon_int < 16) {
1023 IWL_ERR(mvm,
1024 "AP %pM beacon interval is %d, refusing due to firmware bug!\n",
1025 sta->addr, vif->bss_conf.beacon_int);
1026 ret = -EINVAL;
1027 goto out_unlock;
1028 }
1009 ret = iwl_mvm_add_sta(mvm, vif, sta); 1029 ret = iwl_mvm_add_sta(mvm, vif, sta);
1010 } else if (old_state == IEEE80211_STA_NONE && 1030 } else if (old_state == IEEE80211_STA_NONE &&
1011 new_state == IEEE80211_STA_AUTH) { 1031 new_state == IEEE80211_STA_AUTH) {
@@ -1038,6 +1058,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
1038 } else { 1058 } else {
1039 ret = -EIO; 1059 ret = -EIO;
1040 } 1060 }
1061 out_unlock:
1041 mutex_unlock(&mvm->mutex); 1062 mutex_unlock(&mvm->mutex);
1042 1063
1043 return ret; 1064 return ret;
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index d40d7db185d6..420e82d379d9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -419,6 +419,7 @@ struct iwl_mvm {
419 struct work_struct sta_drained_wk; 419 struct work_struct sta_drained_wk;
420 unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)]; 420 unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)];
421 atomic_t pending_frames[IWL_MVM_STATION_COUNT]; 421 atomic_t pending_frames[IWL_MVM_STATION_COUNT];
422 u8 rx_ba_sessions;
422 423
423 /* configured by mac80211 */ 424 /* configured by mac80211 */
424 u32 rts_threshold; 425 u32 rts_threshold;
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index 2157b0f8ced5..268f027b45b0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -137,8 +137,8 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd,
137{ 137{
138 int fw_idx, req_idx; 138 int fw_idx, req_idx;
139 139
140 fw_idx = 0; 140 for (req_idx = req->n_ssids - 1, fw_idx = 0; req_idx > 0;
141 for (req_idx = req->n_ssids - 1; req_idx > 0; req_idx--) { 141 req_idx--, fw_idx++) {
142 cmd->direct_scan[fw_idx].id = WLAN_EID_SSID; 142 cmd->direct_scan[fw_idx].id = WLAN_EID_SSID;
143 cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len; 143 cmd->direct_scan[fw_idx].len = req->ssids[req_idx].ssid_len;
144 memcpy(cmd->direct_scan[fw_idx].ssid, 144 memcpy(cmd->direct_scan[fw_idx].ssid,
@@ -153,7 +153,9 @@ static void iwl_mvm_scan_fill_ssids(struct iwl_scan_cmd *cmd,
153 * just to notify that this scan is active and not passive. 153 * just to notify that this scan is active and not passive.
154 * In order to notify the FW of the number of SSIDs we wish to scan (including 154 * In order to notify the FW of the number of SSIDs we wish to scan (including
155 * the zero-length one), we need to set the corresponding bits in chan->type, 155 * the zero-length one), we need to set the corresponding bits in chan->type,
156 * one for each SSID, and set the active bit (first). 156 * one for each SSID, and set the active bit (first). The first SSID is already
157 * included in the probe template, so we need to set only req->n_ssids - 1 bits
158 * in addition to the first bit.
157 */ 159 */
158static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids) 160static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids)
159{ 161{
@@ -179,7 +181,7 @@ static void iwl_mvm_scan_fill_channels(struct iwl_scan_cmd *cmd,
179 __le32 chan_type_value; 181 __le32 chan_type_value;
180 182
181 if (req->n_ssids > 0) 183 if (req->n_ssids > 0)
182 chan_type_value = cpu_to_le32(BIT(req->n_ssids + 1) - 1); 184 chan_type_value = cpu_to_le32(BIT(req->n_ssids) - 1);
183 else 185 else
184 chan_type_value = SCAN_CHANNEL_TYPE_PASSIVE; 186 chan_type_value = SCAN_CHANNEL_TYPE_PASSIVE;
185 187
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 62fe5209093b..85d4bbe52157 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -608,6 +608,8 @@ int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *bsta)
608 return ret; 608 return ret;
609} 609}
610 610
611#define IWL_MAX_RX_BA_SESSIONS 16
612
611int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, 613int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
612 int tid, u16 ssn, bool start) 614 int tid, u16 ssn, bool start)
613{ 615{
@@ -618,11 +620,20 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
618 620
619 lockdep_assert_held(&mvm->mutex); 621 lockdep_assert_held(&mvm->mutex);
620 622
623 if (start && mvm->rx_ba_sessions >= IWL_MAX_RX_BA_SESSIONS) {
624 IWL_WARN(mvm, "Not enough RX BA SESSIONS\n");
625 return -ENOSPC;
626 }
627
621 cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color); 628 cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
622 cmd.sta_id = mvm_sta->sta_id; 629 cmd.sta_id = mvm_sta->sta_id;
623 cmd.add_modify = STA_MODE_MODIFY; 630 cmd.add_modify = STA_MODE_MODIFY;
624 cmd.add_immediate_ba_tid = (u8) tid; 631 if (start) {
625 cmd.add_immediate_ba_ssn = cpu_to_le16(ssn); 632 cmd.add_immediate_ba_tid = (u8) tid;
633 cmd.add_immediate_ba_ssn = cpu_to_le16(ssn);
634 } else {
635 cmd.remove_immediate_ba_tid = (u8) tid;
636 }
626 cmd.modify_mask = start ? STA_MODIFY_ADD_BA_TID : 637 cmd.modify_mask = start ? STA_MODIFY_ADD_BA_TID :
627 STA_MODIFY_REMOVE_BA_TID; 638 STA_MODIFY_REMOVE_BA_TID;
628 639
@@ -648,6 +659,14 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
648 break; 659 break;
649 } 660 }
650 661
662 if (!ret) {
663 if (start)
664 mvm->rx_ba_sessions++;
665 else if (mvm->rx_ba_sessions > 0)
666 /* check that restart flow didn't zero the counter */
667 mvm->rx_ba_sessions--;
668 }
669
651 return ret; 670 return ret;
652} 671}
653 672
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index caaf4bd56b30..2cf8b964e966 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -693,7 +693,7 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
693 if (!ret) { 693 if (!ret) {
694 dev_notice(adapter->dev, 694 dev_notice(adapter->dev,
695 "WLAN FW already running! Skip FW dnld\n"); 695 "WLAN FW already running! Skip FW dnld\n");
696 goto done; 696 return 0;
697 } 697 }
698 698
699 poll_num = MAX_FIRMWARE_POLL_TRIES; 699 poll_num = MAX_FIRMWARE_POLL_TRIES;
@@ -719,14 +719,8 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *adapter,
719poll_fw: 719poll_fw:
720 /* Check if the firmware is downloaded successfully or not */ 720 /* Check if the firmware is downloaded successfully or not */
721 ret = adapter->if_ops.check_fw_status(adapter, poll_num); 721 ret = adapter->if_ops.check_fw_status(adapter, poll_num);
722 if (ret) { 722 if (ret)
723 dev_err(adapter->dev, "FW failed to be active in time\n"); 723 dev_err(adapter->dev, "FW failed to be active in time\n");
724 return -1;
725 }
726done:
727 /* re-enable host interrupt for mwifiex after fw dnld is successful */
728 if (adapter->if_ops.enable_int)
729 adapter->if_ops.enable_int(adapter);
730 724
731 return ret; 725 return ret;
732} 726}
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index e15ab72fb03d..1753431de361 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -427,6 +427,10 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
427 "Cal data request_firmware() failed\n"); 427 "Cal data request_firmware() failed\n");
428 } 428 }
429 429
430 /* enable host interrupt after fw dnld is successful */
431 if (adapter->if_ops.enable_int)
432 adapter->if_ops.enable_int(adapter);
433
430 adapter->init_wait_q_woken = false; 434 adapter->init_wait_q_woken = false;
431 ret = mwifiex_init_fw(adapter); 435 ret = mwifiex_init_fw(adapter);
432 if (ret == -1) { 436 if (ret == -1) {
@@ -478,6 +482,8 @@ err_add_intf:
478 mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev); 482 mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
479 rtnl_unlock(); 483 rtnl_unlock();
480err_init_fw: 484err_init_fw:
485 if (adapter->if_ops.disable_int)
486 adapter->if_ops.disable_int(adapter);
481 pr_debug("info: %s: unregister device\n", __func__); 487 pr_debug("info: %s: unregister device\n", __func__);
482 adapter->if_ops.unregister_dev(adapter); 488 adapter->if_ops.unregister_dev(adapter);
483done: 489done:
@@ -855,7 +861,7 @@ mwifiex_add_card(void *card, struct semaphore *sem,
855 INIT_WORK(&adapter->main_work, mwifiex_main_work_queue); 861 INIT_WORK(&adapter->main_work, mwifiex_main_work_queue);
856 862
857 /* Register the device. Fill up the private data structure with relevant 863 /* Register the device. Fill up the private data structure with relevant
858 information from the card and request for the required IRQ. */ 864 information from the card. */
859 if (adapter->if_ops.register_dev(adapter)) { 865 if (adapter->if_ops.register_dev(adapter)) {
860 pr_err("%s: failed to register mwifiex device\n", __func__); 866 pr_err("%s: failed to register mwifiex device\n", __func__);
861 goto err_registerdev; 867 goto err_registerdev;
@@ -919,6 +925,11 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
919 if (!adapter) 925 if (!adapter)
920 goto exit_remove; 926 goto exit_remove;
921 927
928 /* We can no longer handle interrupts once we start doing the teardown
929 * below. */
930 if (adapter->if_ops.disable_int)
931 adapter->if_ops.disable_int(adapter);
932
922 adapter->surprise_removed = true; 933 adapter->surprise_removed = true;
923 934
924 /* Stop data */ 935 /* Stop data */
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 3da73d36acdf..253e0bd38e25 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -601,6 +601,7 @@ struct mwifiex_if_ops {
601 int (*register_dev) (struct mwifiex_adapter *); 601 int (*register_dev) (struct mwifiex_adapter *);
602 void (*unregister_dev) (struct mwifiex_adapter *); 602 void (*unregister_dev) (struct mwifiex_adapter *);
603 int (*enable_int) (struct mwifiex_adapter *); 603 int (*enable_int) (struct mwifiex_adapter *);
604 void (*disable_int) (struct mwifiex_adapter *);
604 int (*process_int_status) (struct mwifiex_adapter *); 605 int (*process_int_status) (struct mwifiex_adapter *);
605 int (*host_to_card) (struct mwifiex_adapter *, u8, struct sk_buff *, 606 int (*host_to_card) (struct mwifiex_adapter *, u8, struct sk_buff *,
606 struct mwifiex_tx_param *); 607 struct mwifiex_tx_param *);
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index 5ee5ed02eccd..5ef49f2e375a 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -51,6 +51,7 @@ static struct mwifiex_if_ops sdio_ops;
51static struct semaphore add_remove_card_sem; 51static struct semaphore add_remove_card_sem;
52 52
53static int mwifiex_sdio_resume(struct device *dev); 53static int mwifiex_sdio_resume(struct device *dev);
54static void mwifiex_sdio_interrupt(struct sdio_func *func);
54 55
55/* 56/*
56 * SDIO probe. 57 * SDIO probe.
@@ -296,6 +297,15 @@ static struct sdio_driver mwifiex_sdio = {
296 } 297 }
297}; 298};
298 299
300/* Write data into SDIO card register. Caller claims SDIO device. */
301static int
302mwifiex_write_reg_locked(struct sdio_func *func, u32 reg, u8 data)
303{
304 int ret = -1;
305 sdio_writeb(func, data, reg, &ret);
306 return ret;
307}
308
299/* 309/*
300 * This function writes data into SDIO card register. 310 * This function writes data into SDIO card register.
301 */ 311 */
@@ -303,10 +313,10 @@ static int
303mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u8 data) 313mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u8 data)
304{ 314{
305 struct sdio_mmc_card *card = adapter->card; 315 struct sdio_mmc_card *card = adapter->card;
306 int ret = -1; 316 int ret;
307 317
308 sdio_claim_host(card->func); 318 sdio_claim_host(card->func);
309 sdio_writeb(card->func, data, reg, &ret); 319 ret = mwifiex_write_reg_locked(card->func, reg, data);
310 sdio_release_host(card->func); 320 sdio_release_host(card->func);
311 321
312 return ret; 322 return ret;
@@ -685,23 +695,15 @@ mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat)
685 * The host interrupt mask is read, the disable bit is reset and 695 * The host interrupt mask is read, the disable bit is reset and
686 * written back to the card host interrupt mask register. 696 * written back to the card host interrupt mask register.
687 */ 697 */
688static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) 698static void mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter)
689{ 699{
690 u8 host_int_mask, host_int_disable = HOST_INT_DISABLE; 700 struct sdio_mmc_card *card = adapter->card;
691 701 struct sdio_func *func = card->func;
692 /* Read back the host_int_mask register */
693 if (mwifiex_read_reg(adapter, HOST_INT_MASK_REG, &host_int_mask))
694 return -1;
695
696 /* Update with the mask and write back to the register */
697 host_int_mask &= ~host_int_disable;
698
699 if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, host_int_mask)) {
700 dev_err(adapter->dev, "disable host interrupt failed\n");
701 return -1;
702 }
703 702
704 return 0; 703 sdio_claim_host(func);
704 mwifiex_write_reg_locked(func, HOST_INT_MASK_REG, 0);
705 sdio_release_irq(func);
706 sdio_release_host(func);
705} 707}
706 708
707/* 709/*
@@ -713,14 +715,29 @@ static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter)
713static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter) 715static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter)
714{ 716{
715 struct sdio_mmc_card *card = adapter->card; 717 struct sdio_mmc_card *card = adapter->card;
718 struct sdio_func *func = card->func;
719 int ret;
720
721 sdio_claim_host(func);
722
723 /* Request the SDIO IRQ */
724 ret = sdio_claim_irq(func, mwifiex_sdio_interrupt);
725 if (ret) {
726 dev_err(adapter->dev, "claim irq failed: ret=%d\n", ret);
727 goto out;
728 }
716 729
717 /* Simply write the mask to the register */ 730 /* Simply write the mask to the register */
718 if (mwifiex_write_reg(adapter, HOST_INT_MASK_REG, 731 ret = mwifiex_write_reg_locked(func, HOST_INT_MASK_REG,
719 card->reg->host_int_enable)) { 732 card->reg->host_int_enable);
733 if (ret) {
720 dev_err(adapter->dev, "enable host interrupt failed\n"); 734 dev_err(adapter->dev, "enable host interrupt failed\n");
721 return -1; 735 sdio_release_irq(func);
722 } 736 }
723 return 0; 737
738out:
739 sdio_release_host(func);
740 return ret;
724} 741}
725 742
726/* 743/*
@@ -997,9 +1014,6 @@ mwifiex_sdio_interrupt(struct sdio_func *func)
997 } 1014 }
998 adapter = card->adapter; 1015 adapter = card->adapter;
999 1016
1000 if (adapter->surprise_removed)
1001 return;
1002
1003 if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP) 1017 if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP)
1004 adapter->ps_state = PS_STATE_AWAKE; 1018 adapter->ps_state = PS_STATE_AWAKE;
1005 1019
@@ -1728,9 +1742,7 @@ mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
1728 struct sdio_mmc_card *card = adapter->card; 1742 struct sdio_mmc_card *card = adapter->card;
1729 1743
1730 if (adapter->card) { 1744 if (adapter->card) {
1731 /* Release the SDIO IRQ */
1732 sdio_claim_host(card->func); 1745 sdio_claim_host(card->func);
1733 sdio_release_irq(card->func);
1734 sdio_disable_func(card->func); 1746 sdio_disable_func(card->func);
1735 sdio_release_host(card->func); 1747 sdio_release_host(card->func);
1736 sdio_set_drvdata(card->func, NULL); 1748 sdio_set_drvdata(card->func, NULL);
@@ -1744,7 +1756,7 @@ mwifiex_unregister_dev(struct mwifiex_adapter *adapter)
1744 */ 1756 */
1745static int mwifiex_register_dev(struct mwifiex_adapter *adapter) 1757static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
1746{ 1758{
1747 int ret = 0; 1759 int ret;
1748 struct sdio_mmc_card *card = adapter->card; 1760 struct sdio_mmc_card *card = adapter->card;
1749 struct sdio_func *func = card->func; 1761 struct sdio_func *func = card->func;
1750 1762
@@ -1753,22 +1765,14 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
1753 1765
1754 sdio_claim_host(func); 1766 sdio_claim_host(func);
1755 1767
1756 /* Request the SDIO IRQ */
1757 ret = sdio_claim_irq(func, mwifiex_sdio_interrupt);
1758 if (ret) {
1759 pr_err("claim irq failed: ret=%d\n", ret);
1760 goto disable_func;
1761 }
1762
1763 /* Set block size */ 1768 /* Set block size */
1764 ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE); 1769 ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE);
1770 sdio_release_host(func);
1765 if (ret) { 1771 if (ret) {
1766 pr_err("cannot set SDIO block size\n"); 1772 pr_err("cannot set SDIO block size\n");
1767 ret = -1; 1773 return ret;
1768 goto release_irq;
1769 } 1774 }
1770 1775
1771 sdio_release_host(func);
1772 sdio_set_drvdata(func, card); 1776 sdio_set_drvdata(func, card);
1773 1777
1774 adapter->dev = &func->dev; 1778 adapter->dev = &func->dev;
@@ -1776,15 +1780,6 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
1776 strcpy(adapter->fw_name, card->firmware); 1780 strcpy(adapter->fw_name, card->firmware);
1777 1781
1778 return 0; 1782 return 0;
1779
1780release_irq:
1781 sdio_release_irq(func);
1782disable_func:
1783 sdio_disable_func(func);
1784 sdio_release_host(func);
1785 adapter->card = NULL;
1786
1787 return -1;
1788} 1783}
1789 1784
1790/* 1785/*
@@ -1813,9 +1808,6 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
1813 */ 1808 */
1814 mwifiex_read_reg(adapter, HOST_INTSTATUS_REG, &sdio_ireg); 1809 mwifiex_read_reg(adapter, HOST_INTSTATUS_REG, &sdio_ireg);
1815 1810
1816 /* Disable host interrupt mask register for SDIO */
1817 mwifiex_sdio_disable_host_int(adapter);
1818
1819 /* Get SDIO ioport */ 1811 /* Get SDIO ioport */
1820 mwifiex_init_sdio_ioport(adapter); 1812 mwifiex_init_sdio_ioport(adapter);
1821 1813
@@ -1957,6 +1949,7 @@ static struct mwifiex_if_ops sdio_ops = {
1957 .register_dev = mwifiex_register_dev, 1949 .register_dev = mwifiex_register_dev,
1958 .unregister_dev = mwifiex_unregister_dev, 1950 .unregister_dev = mwifiex_unregister_dev,
1959 .enable_int = mwifiex_sdio_enable_host_int, 1951 .enable_int = mwifiex_sdio_enable_host_int,
1952 .disable_int = mwifiex_sdio_disable_host_int,
1960 .process_int_status = mwifiex_process_int_status, 1953 .process_int_status = mwifiex_process_int_status,
1961 .host_to_card = mwifiex_sdio_host_to_card, 1954 .host_to_card = mwifiex_sdio_host_to_card,
1962 .wakeup = mwifiex_pm_wakeup_card, 1955 .wakeup = mwifiex_pm_wakeup_card,
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 6d51dfdd8251..532ae0ac4dfb 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -92,9 +92,6 @@
92/* Host Control Registers : Download host interrupt mask */ 92/* Host Control Registers : Download host interrupt mask */
93#define DN_LD_HOST_INT_MASK (0x2U) 93#define DN_LD_HOST_INT_MASK (0x2U)
94 94
95/* Disable Host interrupt mask */
96#define HOST_INT_DISABLE 0xff
97
98/* Host Control Registers : Host interrupt status */ 95/* Host Control Registers : Host interrupt status */
99#define HOST_INTSTATUS_REG 0x03 96#define HOST_INTSTATUS_REG 0x03
100/* Host Control Registers : Upload host interrupt status */ 97/* Host Control Registers : Upload host interrupt status */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 8184d121ff09..43dd7525bfcb 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -666,6 +666,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
666 if (sta->sdata->dev != dev) 666 if (sta->sdata->dev != dev)
667 continue; 667 continue;
668 668
669 sinfo.filled = 0;
670 sta_set_sinfo(sta, &sinfo);
669 i = 0; 671 i = 0;
670 ADD_STA_STATS(sta); 672 ADD_STA_STATS(sta);
671 } 673 }
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index ac7ef5414bde..e6512e2ffd20 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -290,7 +290,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
290 struct minstrel_rate *msr, *mr; 290 struct minstrel_rate *msr, *mr;
291 unsigned int ndx; 291 unsigned int ndx;
292 bool mrr_capable; 292 bool mrr_capable;
293 bool prev_sample = mi->prev_sample; 293 bool prev_sample;
294 int delta; 294 int delta;
295 int sampling_ratio; 295 int sampling_ratio;
296 296
@@ -314,6 +314,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta,
314 (mi->sample_count + mi->sample_deferred / 2); 314 (mi->sample_count + mi->sample_deferred / 2);
315 315
316 /* delta < 0: no sampling required */ 316 /* delta < 0: no sampling required */
317 prev_sample = mi->prev_sample;
317 mi->prev_sample = false; 318 mi->prev_sample = false;
318 if (delta < 0 || (!mrr_capable && prev_sample)) 319 if (delta < 0 || (!mrr_capable && prev_sample))
319 return; 320 return;
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 5b2d3012b983..f5aed963b22e 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -804,10 +804,18 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
804 804
805 sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES]; 805 sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
806 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; 806 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
807 rate->count = 1;
808
809 if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
810 int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);
811 rate->idx = mp->cck_rates[idx];
812 rate->flags = 0;
813 return;
814 }
815
807 rate->idx = sample_idx % MCS_GROUP_RATES + 816 rate->idx = sample_idx % MCS_GROUP_RATES +
808 (sample_group->streams - 1) * MCS_GROUP_RATES; 817 (sample_group->streams - 1) * MCS_GROUP_RATES;
809 rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags; 818 rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
810 rate->count = 1;
811} 819}
812 820
813static void 821static void
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 23dbcfc69b3b..2c5a79bd3777 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -936,8 +936,14 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
936 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 936 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
937 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); 937 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
938 938
939 /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ 939 /*
940 if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { 940 * Drop duplicate 802.11 retransmissions
941 * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
942 */
943 if (rx->skb->len >= 24 && rx->sta &&
944 !ieee80211_is_ctl(hdr->frame_control) &&
945 !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
946 !is_multicast_ether_addr(hdr->addr1)) {
941 if (unlikely(ieee80211_has_retry(hdr->frame_control) && 947 if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
942 rx->sta->last_seq_ctrl[rx->seqno_idx] == 948 rx->sta->last_seq_ctrl[rx->seqno_idx] ==
943 hdr->seq_ctrl)) { 949 hdr->seq_ctrl)) {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 1cc47aca7f05..25d217d90807 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4770,9 +4770,9 @@ do { \
4770 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1, 4770 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1,
4771 mask, NL80211_MESHCONF_FORWARDING, 4771 mask, NL80211_MESHCONF_FORWARDING,
4772 nla_get_u8); 4772 nla_get_u8);
4773 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, 1, 255, 4773 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0,
4774 mask, NL80211_MESHCONF_RSSI_THRESHOLD, 4774 mask, NL80211_MESHCONF_RSSI_THRESHOLD,
4775 nla_get_u32); 4775 nla_get_s32);
4776 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16, 4776 FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16,
4777 mask, NL80211_MESHCONF_HT_OPMODE, 4777 mask, NL80211_MESHCONF_HT_OPMODE,
4778 nla_get_u16); 4778 nla_get_u16);
@@ -6613,12 +6613,14 @@ EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb);
6613 6613
6614void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) 6614void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
6615{ 6615{
6616 struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
6616 void *hdr = ((void **)skb->cb)[1]; 6617 void *hdr = ((void **)skb->cb)[1];
6617 struct nlattr *data = ((void **)skb->cb)[2]; 6618 struct nlattr *data = ((void **)skb->cb)[2];
6618 6619
6619 nla_nest_end(skb, data); 6620 nla_nest_end(skb, data);
6620 genlmsg_end(skb, hdr); 6621 genlmsg_end(skb, hdr);
6621 genlmsg_multicast(skb, 0, nl80211_testmode_mcgrp.id, gfp); 6622 genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), skb, 0,
6623 nl80211_testmode_mcgrp.id, gfp);
6622} 6624}
6623EXPORT_SYMBOL(cfg80211_testmode_event); 6625EXPORT_SYMBOL(cfg80211_testmode_event);
6624#endif 6626#endif
@@ -10064,7 +10066,8 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
10064 10066
10065 genlmsg_end(msg, hdr); 10067 genlmsg_end(msg, hdr);
10066 10068
10067 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); 10069 genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
10070 nl80211_mlme_mcgrp.id, gfp);
10068 return; 10071 return;
10069 10072
10070 nla_put_failure: 10073 nla_put_failure:
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 5a24c986f34b..5a950f36bae4 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -2279,7 +2279,9 @@ void wiphy_regulatory_deregister(struct wiphy *wiphy)
2279static void reg_timeout_work(struct work_struct *work) 2279static void reg_timeout_work(struct work_struct *work)
2280{ 2280{
2281 REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n"); 2281 REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n");
2282 rtnl_lock();
2282 restore_regulatory_settings(true); 2283 restore_regulatory_settings(true);
2284 rtnl_unlock();
2283} 2285}
2284 2286
2285int __init regulatory_init(void) 2287int __init regulatory_init(void)
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 1d3cfb1a3f28..81c8a10d743c 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -34,8 +34,10 @@ struct cfg80211_conn {
34 CFG80211_CONN_SCAN_AGAIN, 34 CFG80211_CONN_SCAN_AGAIN,
35 CFG80211_CONN_AUTHENTICATE_NEXT, 35 CFG80211_CONN_AUTHENTICATE_NEXT,
36 CFG80211_CONN_AUTHENTICATING, 36 CFG80211_CONN_AUTHENTICATING,
37 CFG80211_CONN_AUTH_FAILED,
37 CFG80211_CONN_ASSOCIATE_NEXT, 38 CFG80211_CONN_ASSOCIATE_NEXT,
38 CFG80211_CONN_ASSOCIATING, 39 CFG80211_CONN_ASSOCIATING,
40 CFG80211_CONN_ASSOC_FAILED,
39 CFG80211_CONN_DEAUTH, 41 CFG80211_CONN_DEAUTH,
40 CFG80211_CONN_CONNECTED, 42 CFG80211_CONN_CONNECTED,
41 } state; 43 } state;
@@ -164,6 +166,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
164 NULL, 0, 166 NULL, 0,
165 params->key, params->key_len, 167 params->key, params->key_len,
166 params->key_idx, NULL, 0); 168 params->key_idx, NULL, 0);
169 case CFG80211_CONN_AUTH_FAILED:
170 return -ENOTCONN;
167 case CFG80211_CONN_ASSOCIATE_NEXT: 171 case CFG80211_CONN_ASSOCIATE_NEXT:
168 BUG_ON(!rdev->ops->assoc); 172 BUG_ON(!rdev->ops->assoc);
169 wdev->conn->state = CFG80211_CONN_ASSOCIATING; 173 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
@@ -188,10 +192,17 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
188 WLAN_REASON_DEAUTH_LEAVING, 192 WLAN_REASON_DEAUTH_LEAVING,
189 false); 193 false);
190 return err; 194 return err;
195 case CFG80211_CONN_ASSOC_FAILED:
196 cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
197 NULL, 0,
198 WLAN_REASON_DEAUTH_LEAVING, false);
199 return -ENOTCONN;
191 case CFG80211_CONN_DEAUTH: 200 case CFG80211_CONN_DEAUTH:
192 cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, 201 cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
193 NULL, 0, 202 NULL, 0,
194 WLAN_REASON_DEAUTH_LEAVING, false); 203 WLAN_REASON_DEAUTH_LEAVING, false);
204 /* free directly, disconnected event already sent */
205 cfg80211_sme_free(wdev);
195 return 0; 206 return 0;
196 default: 207 default:
197 return 0; 208 return 0;
@@ -371,7 +382,7 @@ bool cfg80211_sme_rx_assoc_resp(struct wireless_dev *wdev, u16 status)
371 return true; 382 return true;
372 } 383 }
373 384
374 wdev->conn->state = CFG80211_CONN_DEAUTH; 385 wdev->conn->state = CFG80211_CONN_ASSOC_FAILED;
375 schedule_work(&rdev->conn_work); 386 schedule_work(&rdev->conn_work);
376 return false; 387 return false;
377} 388}
@@ -383,7 +394,13 @@ void cfg80211_sme_deauth(struct wireless_dev *wdev)
383 394
384void cfg80211_sme_auth_timeout(struct wireless_dev *wdev) 395void cfg80211_sme_auth_timeout(struct wireless_dev *wdev)
385{ 396{
386 cfg80211_sme_free(wdev); 397 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
398
399 if (!wdev->conn)
400 return;
401
402 wdev->conn->state = CFG80211_CONN_AUTH_FAILED;
403 schedule_work(&rdev->conn_work);
387} 404}
388 405
389void cfg80211_sme_disassoc(struct wireless_dev *wdev) 406void cfg80211_sme_disassoc(struct wireless_dev *wdev)
@@ -399,7 +416,13 @@ void cfg80211_sme_disassoc(struct wireless_dev *wdev)
399 416
400void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev) 417void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev)
401{ 418{
402 cfg80211_sme_disassoc(wdev); 419 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
420
421 if (!wdev->conn)
422 return;
423
424 wdev->conn->state = CFG80211_CONN_ASSOC_FAILED;
425 schedule_work(&rdev->conn_work);
403} 426}
404 427
405static int cfg80211_sme_connect(struct wireless_dev *wdev, 428static int cfg80211_sme_connect(struct wireless_dev *wdev,