diff options
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 | ||
263 | static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, | 267 | static 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 | ||
390 | static int iwl_mvm_mac_start(struct ieee80211_hw *hw) | 395 | static 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 | */ |
158 | static u16 iwl_mvm_get_active_dwell(enum ieee80211_band band, int n_ssids) | 160 | static 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 | |||
611 | int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | 613 | int 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, | |||
719 | poll_fw: | 719 | poll_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 | } | ||
726 | done: | ||
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(); |
480 | err_init_fw: | 484 | err_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); |
483 | done: | 489 | done: |
@@ -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; | |||
51 | static struct semaphore add_remove_card_sem; | 51 | static struct semaphore add_remove_card_sem; |
52 | 52 | ||
53 | static int mwifiex_sdio_resume(struct device *dev); | 53 | static int mwifiex_sdio_resume(struct device *dev); |
54 | static 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. */ | ||
301 | static int | ||
302 | mwifiex_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 | |||
303 | mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u8 data) | 313 | mwifiex_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 | */ |
688 | static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) | 698 | static 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) | |||
713 | static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter) | 715 | static 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 | |
738 | out: | ||
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 | */ |
1745 | static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | 1757 | static 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 | |||
1780 | release_irq: | ||
1781 | sdio_release_irq(func); | ||
1782 | disable_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 | ||
813 | static void | 821 | static 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 | ||
6614 | void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) | 6614 | void 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 | } |
6623 | EXPORT_SYMBOL(cfg80211_testmode_event); | 6625 | EXPORT_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) | |||
2279 | static void reg_timeout_work(struct work_struct *work) | 2279 | static 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 | ||
2285 | int __init regulatory_init(void) | 2287 | int __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 | ||
384 | void cfg80211_sme_auth_timeout(struct wireless_dev *wdev) | 395 | void 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 | ||
389 | void cfg80211_sme_disassoc(struct wireless_dev *wdev) | 406 | void cfg80211_sme_disassoc(struct wireless_dev *wdev) |
@@ -399,7 +416,13 @@ void cfg80211_sme_disassoc(struct wireless_dev *wdev) | |||
399 | 416 | ||
400 | void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev) | 417 | void 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 | ||
405 | static int cfg80211_sme_connect(struct wireless_dev *wdev, | 428 | static int cfg80211_sme_connect(struct wireless_dev *wdev, |