diff options
-rw-r--r-- | drivers/bcma/driver_pci_host.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/common.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 18 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-devtrace.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-phy-db.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/d3.c | 104 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/internal.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/tx.c | 75 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_sdio.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/pcie.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 8 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 12 | ||||
-rw-r--r-- | net/mac80211/iface.c | 2 | ||||
-rw-r--r-- | net/mac80211/tx.c | 77 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 61 |
19 files changed, 258 insertions, 174 deletions
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index d3bde6cec927..30629a3d44cc 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c | |||
@@ -404,6 +404,8 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | |||
404 | return; | 404 | return; |
405 | } | 405 | } |
406 | 406 | ||
407 | spin_lock_init(&pc_host->cfgspace_lock); | ||
408 | |||
407 | pc->host_controller = pc_host; | 409 | pc->host_controller = pc_host; |
408 | pc_host->pci_controller.io_resource = &pc_host->io_resource; | 410 | pc_host->pci_controller.io_resource = &pc_host->io_resource; |
409 | pc_host->pci_controller.mem_resource = &pc_host->mem_resource; | 411 | pc_host->pci_controller.mem_resource = &pc_host->mem_resource; |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 5f845beeb18b..050ca4a4850d 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -27,7 +27,7 @@ | |||
27 | #define WME_MAX_BA WME_BA_BMP_SIZE | 27 | #define WME_MAX_BA WME_BA_BMP_SIZE |
28 | #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) | 28 | #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) |
29 | 29 | ||
30 | #define ATH_RSSI_DUMMY_MARKER 0x127 | 30 | #define ATH_RSSI_DUMMY_MARKER 127 |
31 | #define ATH_RSSI_LPF_LEN 10 | 31 | #define ATH_RSSI_LPF_LEN 10 |
32 | #define RSSI_LPF_THRESHOLD -20 | 32 | #define RSSI_LPF_THRESHOLD -20 |
33 | #define ATH_RSSI_EP_MULTIPLIER (1<<7) | 33 | #define ATH_RSSI_EP_MULTIPLIER (1<<7) |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 96bfb18078fa..d3b099d7898b 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/firmware.h> | 22 | #include <linux/firmware.h> |
23 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
24 | #include <linux/netdevice.h> | 24 | #include <linux/netdevice.h> |
25 | #include <linux/etherdevice.h> | ||
25 | #include <linux/leds.h> | 26 | #include <linux/leds.h> |
26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
27 | #include <net/mac80211.h> | 28 | #include <net/mac80211.h> |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 3ad1fd05c5e7..bd8251c1c749 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -1067,15 +1067,19 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
1067 | 1067 | ||
1068 | last_rssi = priv->rx.last_rssi; | 1068 | last_rssi = priv->rx.last_rssi; |
1069 | 1069 | ||
1070 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | 1070 | if (ieee80211_is_beacon(hdr->frame_control) && |
1071 | rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi, | 1071 | !is_zero_ether_addr(common->curbssid) && |
1072 | ATH_RSSI_EP_MULTIPLIER); | 1072 | ether_addr_equal(hdr->addr3, common->curbssid)) { |
1073 | s8 rssi = rxbuf->rxstatus.rs_rssi; | ||
1073 | 1074 | ||
1074 | if (rxbuf->rxstatus.rs_rssi < 0) | 1075 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) |
1075 | rxbuf->rxstatus.rs_rssi = 0; | 1076 | rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); |
1076 | 1077 | ||
1077 | if (ieee80211_is_beacon(fc)) | 1078 | if (rssi < 0) |
1078 | priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; | 1079 | rssi = 0; |
1080 | |||
1081 | priv->ah->stats.avgbrssi = rssi; | ||
1082 | } | ||
1079 | 1083 | ||
1080 | rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); | 1084 | rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); |
1081 | rx_status->band = hw->conf.channel->band; | 1085 | rx_status->band = hw->conf.channel->band; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2a2ae403e0e5..07e25260c31d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1463,7 +1463,9 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah, | |||
1463 | reset_type = ATH9K_RESET_POWER_ON; | 1463 | reset_type = ATH9K_RESET_POWER_ON; |
1464 | else | 1464 | else |
1465 | reset_type = ATH9K_RESET_COLD; | 1465 | reset_type = ATH9K_RESET_COLD; |
1466 | } | 1466 | } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) || |
1467 | (REG_READ(ah, AR_CR) & AR_CR_RXE)) | ||
1468 | reset_type = ATH9K_RESET_COLD; | ||
1467 | 1469 | ||
1468 | if (!ath9k_hw_set_reset_reg(ah, reset_type)) | 1470 | if (!ath9k_hw_set_reset_reg(ah, reset_type)) |
1469 | return false; | 1471 | return false; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 9a0f45ec9e01..10f01793d7a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -349,25 +349,23 @@ TRACE_EVENT(iwlwifi_dev_rx_data, | |||
349 | TRACE_EVENT(iwlwifi_dev_hcmd, | 349 | TRACE_EVENT(iwlwifi_dev_hcmd, |
350 | TP_PROTO(const struct device *dev, | 350 | TP_PROTO(const struct device *dev, |
351 | struct iwl_host_cmd *cmd, u16 total_size, | 351 | struct iwl_host_cmd *cmd, u16 total_size, |
352 | const void *hdr, size_t hdr_len), | 352 | struct iwl_cmd_header *hdr), |
353 | TP_ARGS(dev, cmd, total_size, hdr, hdr_len), | 353 | TP_ARGS(dev, cmd, total_size, hdr), |
354 | TP_STRUCT__entry( | 354 | TP_STRUCT__entry( |
355 | DEV_ENTRY | 355 | DEV_ENTRY |
356 | __dynamic_array(u8, hcmd, total_size) | 356 | __dynamic_array(u8, hcmd, total_size) |
357 | __field(u32, flags) | 357 | __field(u32, flags) |
358 | ), | 358 | ), |
359 | TP_fast_assign( | 359 | TP_fast_assign( |
360 | int i, offset = hdr_len; | 360 | int i, offset = sizeof(*hdr); |
361 | 361 | ||
362 | DEV_ASSIGN; | 362 | DEV_ASSIGN; |
363 | __entry->flags = cmd->flags; | 363 | __entry->flags = cmd->flags; |
364 | memcpy(__get_dynamic_array(hcmd), hdr, hdr_len); | 364 | memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr)); |
365 | 365 | ||
366 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | 366 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { |
367 | if (!cmd->len[i]) | 367 | if (!cmd->len[i]) |
368 | continue; | 368 | continue; |
369 | if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) | ||
370 | continue; | ||
371 | memcpy((u8 *)__get_dynamic_array(hcmd) + offset, | 369 | memcpy((u8 *)__get_dynamic_array(hcmd) + offset, |
372 | cmd->data[i], cmd->len[i]); | 370 | cmd->data[i], cmd->len[i]); |
373 | offset += cmd->len[i]; | 371 | offset += cmd->len[i]; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c index 14fc8d39fc28..3392011a8768 100644 --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c | |||
@@ -136,12 +136,6 @@ struct iwl_calib_res_notif_phy_db { | |||
136 | u8 data[]; | 136 | u8 data[]; |
137 | } __packed; | 137 | } __packed; |
138 | 138 | ||
139 | #define IWL_PHY_DB_STATIC_PIC cpu_to_le32(0x21436587) | ||
140 | static inline void iwl_phy_db_test_pic(__le32 pic) | ||
141 | { | ||
142 | WARN_ON(IWL_PHY_DB_STATIC_PIC != pic); | ||
143 | } | ||
144 | |||
145 | struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans) | 139 | struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans) |
146 | { | 140 | { |
147 | struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db), | 141 | struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db), |
@@ -260,11 +254,6 @@ int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt, | |||
260 | (size - CHANNEL_NUM_SIZE) / phy_db->channel_num; | 254 | (size - CHANNEL_NUM_SIZE) / phy_db->channel_num; |
261 | } | 255 | } |
262 | 256 | ||
263 | /* Test PIC */ | ||
264 | if (type != IWL_PHY_DB_CFG) | ||
265 | iwl_phy_db_test_pic(*(((__le32 *)phy_db_notif->data) + | ||
266 | (size / sizeof(__le32)) - 1)); | ||
267 | |||
268 | IWL_DEBUG_INFO(phy_db->trans, | 257 | IWL_DEBUG_INFO(phy_db->trans, |
269 | "%s(%d): [PHYDB]SET: Type %d , Size: %d\n", | 258 | "%s(%d): [PHYDB]SET: Type %d , Size: %d\n", |
270 | __func__, __LINE__, type, size); | 259 | __func__, __LINE__, type, size); |
@@ -372,11 +361,6 @@ int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db, | |||
372 | *size = entry->size; | 361 | *size = entry->size; |
373 | } | 362 | } |
374 | 363 | ||
375 | /* Test PIC */ | ||
376 | if (type != IWL_PHY_DB_CFG) | ||
377 | iwl_phy_db_test_pic(*(((__le32 *)*data) + | ||
378 | (*size / sizeof(__le32)) - 1)); | ||
379 | |||
380 | IWL_DEBUG_INFO(phy_db->trans, | 364 | IWL_DEBUG_INFO(phy_db->trans, |
381 | "%s(%d): [PHYDB] GET: Type %d , Size: %d\n", | 365 | "%s(%d): [PHYDB] GET: Type %d , Size: %d\n", |
382 | __func__, __LINE__, type, *size); | 366 | __func__, __LINE__, type, *size); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index c64d864799cd..994c8c263dc0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -61,6 +61,7 @@ | |||
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | 63 | ||
64 | #include <linux/etherdevice.h> | ||
64 | #include <net/cfg80211.h> | 65 | #include <net/cfg80211.h> |
65 | #include <net/ipv6.h> | 66 | #include <net/ipv6.h> |
66 | #include "iwl-modparams.h" | 67 | #include "iwl-modparams.h" |
@@ -192,6 +193,11 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, | |||
192 | sizeof(wkc), &wkc); | 193 | sizeof(wkc), &wkc); |
193 | data->error = ret != 0; | 194 | data->error = ret != 0; |
194 | 195 | ||
196 | mvm->ptk_ivlen = key->iv_len; | ||
197 | mvm->ptk_icvlen = key->icv_len; | ||
198 | mvm->gtk_ivlen = key->iv_len; | ||
199 | mvm->gtk_icvlen = key->icv_len; | ||
200 | |||
195 | /* don't upload key again */ | 201 | /* don't upload key again */ |
196 | goto out_unlock; | 202 | goto out_unlock; |
197 | } | 203 | } |
@@ -304,9 +310,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, | |||
304 | */ | 310 | */ |
305 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { | 311 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { |
306 | key->hw_key_idx = 0; | 312 | key->hw_key_idx = 0; |
313 | mvm->ptk_ivlen = key->iv_len; | ||
314 | mvm->ptk_icvlen = key->icv_len; | ||
307 | } else { | 315 | } else { |
308 | data->gtk_key_idx++; | 316 | data->gtk_key_idx++; |
309 | key->hw_key_idx = data->gtk_key_idx; | 317 | key->hw_key_idx = data->gtk_key_idx; |
318 | mvm->gtk_ivlen = key->iv_len; | ||
319 | mvm->gtk_icvlen = key->icv_len; | ||
310 | } | 320 | } |
311 | 321 | ||
312 | ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true); | 322 | ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true); |
@@ -649,6 +659,11 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
649 | /* We reprogram keys and shouldn't allocate new key indices */ | 659 | /* We reprogram keys and shouldn't allocate new key indices */ |
650 | memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); | 660 | memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); |
651 | 661 | ||
662 | mvm->ptk_ivlen = 0; | ||
663 | mvm->ptk_icvlen = 0; | ||
664 | mvm->ptk_ivlen = 0; | ||
665 | mvm->ptk_icvlen = 0; | ||
666 | |||
652 | /* | 667 | /* |
653 | * The D3 firmware still hardcodes the AP station ID for the | 668 | * The D3 firmware still hardcodes the AP station ID for the |
654 | * BSS we're associated with as 0. As a result, we have to move | 669 | * BSS we're associated with as 0. As a result, we have to move |
@@ -783,7 +798,6 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
783 | struct iwl_wowlan_status *status; | 798 | struct iwl_wowlan_status *status; |
784 | u32 reasons; | 799 | u32 reasons; |
785 | int ret, len; | 800 | int ret, len; |
786 | bool pkt8023 = false; | ||
787 | struct sk_buff *pkt = NULL; | 801 | struct sk_buff *pkt = NULL; |
788 | 802 | ||
789 | iwl_trans_read_mem_bytes(mvm->trans, base, | 803 | iwl_trans_read_mem_bytes(mvm->trans, base, |
@@ -824,7 +838,8 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
824 | status = (void *)cmd.resp_pkt->data; | 838 | status = (void *)cmd.resp_pkt->data; |
825 | 839 | ||
826 | if (len - sizeof(struct iwl_cmd_header) != | 840 | if (len - sizeof(struct iwl_cmd_header) != |
827 | sizeof(*status) + le32_to_cpu(status->wake_packet_bufsize)) { | 841 | sizeof(*status) + |
842 | ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) { | ||
828 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 843 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
829 | goto out; | 844 | goto out; |
830 | } | 845 | } |
@@ -836,61 +851,96 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
836 | goto report; | 851 | goto report; |
837 | } | 852 | } |
838 | 853 | ||
839 | if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) { | 854 | if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) |
840 | wakeup.magic_pkt = true; | 855 | wakeup.magic_pkt = true; |
841 | pkt8023 = true; | ||
842 | } | ||
843 | 856 | ||
844 | if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) { | 857 | if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) |
845 | wakeup.pattern_idx = | 858 | wakeup.pattern_idx = |
846 | le16_to_cpu(status->pattern_number); | 859 | le16_to_cpu(status->pattern_number); |
847 | pkt8023 = true; | ||
848 | } | ||
849 | 860 | ||
850 | if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON | | 861 | if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON | |
851 | IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)) | 862 | IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)) |
852 | wakeup.disconnect = true; | 863 | wakeup.disconnect = true; |
853 | 864 | ||
854 | if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) { | 865 | if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) |
855 | wakeup.gtk_rekey_failure = true; | 866 | wakeup.gtk_rekey_failure = true; |
856 | pkt8023 = true; | ||
857 | } | ||
858 | 867 | ||
859 | if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) { | 868 | if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) |
860 | wakeup.rfkill_release = true; | 869 | wakeup.rfkill_release = true; |
861 | pkt8023 = true; | ||
862 | } | ||
863 | 870 | ||
864 | if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) { | 871 | if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) |
865 | wakeup.eap_identity_req = true; | 872 | wakeup.eap_identity_req = true; |
866 | pkt8023 = true; | ||
867 | } | ||
868 | 873 | ||
869 | if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) { | 874 | if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) |
870 | wakeup.four_way_handshake = true; | 875 | wakeup.four_way_handshake = true; |
871 | pkt8023 = true; | ||
872 | } | ||
873 | 876 | ||
874 | if (status->wake_packet_bufsize) { | 877 | if (status->wake_packet_bufsize) { |
875 | u32 pktsize = le32_to_cpu(status->wake_packet_bufsize); | 878 | int pktsize = le32_to_cpu(status->wake_packet_bufsize); |
876 | u32 pktlen = le32_to_cpu(status->wake_packet_length); | 879 | int pktlen = le32_to_cpu(status->wake_packet_length); |
880 | const u8 *pktdata = status->wake_packet; | ||
881 | struct ieee80211_hdr *hdr = (void *)pktdata; | ||
882 | int truncated = pktlen - pktsize; | ||
883 | |||
884 | /* this would be a firmware bug */ | ||
885 | if (WARN_ON_ONCE(truncated < 0)) | ||
886 | truncated = 0; | ||
887 | |||
888 | if (ieee80211_is_data(hdr->frame_control)) { | ||
889 | int hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
890 | int ivlen = 0, icvlen = 4; /* also FCS */ | ||
877 | 891 | ||
878 | if (pkt8023) { | ||
879 | pkt = alloc_skb(pktsize, GFP_KERNEL); | 892 | pkt = alloc_skb(pktsize, GFP_KERNEL); |
880 | if (!pkt) | 893 | if (!pkt) |
881 | goto report; | 894 | goto report; |
882 | memcpy(skb_put(pkt, pktsize), status->wake_packet, | 895 | |
883 | pktsize); | 896 | memcpy(skb_put(pkt, hdrlen), pktdata, hdrlen); |
897 | pktdata += hdrlen; | ||
898 | pktsize -= hdrlen; | ||
899 | |||
900 | if (ieee80211_has_protected(hdr->frame_control)) { | ||
901 | if (is_multicast_ether_addr(hdr->addr1)) { | ||
902 | ivlen = mvm->gtk_ivlen; | ||
903 | icvlen += mvm->gtk_icvlen; | ||
904 | } else { | ||
905 | ivlen = mvm->ptk_ivlen; | ||
906 | icvlen += mvm->ptk_icvlen; | ||
907 | } | ||
908 | } | ||
909 | |||
910 | /* if truncated, FCS/ICV is (partially) gone */ | ||
911 | if (truncated >= icvlen) { | ||
912 | icvlen = 0; | ||
913 | truncated -= icvlen; | ||
914 | } else { | ||
915 | icvlen -= truncated; | ||
916 | truncated = 0; | ||
917 | } | ||
918 | |||
919 | pktsize -= ivlen + icvlen; | ||
920 | pktdata += ivlen; | ||
921 | |||
922 | memcpy(skb_put(pkt, pktsize), pktdata, pktsize); | ||
923 | |||
884 | if (ieee80211_data_to_8023(pkt, vif->addr, vif->type)) | 924 | if (ieee80211_data_to_8023(pkt, vif->addr, vif->type)) |
885 | goto report; | 925 | goto report; |
886 | wakeup.packet = pkt->data; | 926 | wakeup.packet = pkt->data; |
887 | wakeup.packet_present_len = pkt->len; | 927 | wakeup.packet_present_len = pkt->len; |
888 | wakeup.packet_len = pkt->len - (pktlen - pktsize); | 928 | wakeup.packet_len = pkt->len - truncated; |
889 | wakeup.packet_80211 = false; | 929 | wakeup.packet_80211 = false; |
890 | } else { | 930 | } else { |
931 | int fcslen = 4; | ||
932 | |||
933 | if (truncated >= 4) { | ||
934 | truncated -= 4; | ||
935 | fcslen = 0; | ||
936 | } else { | ||
937 | fcslen -= truncated; | ||
938 | truncated = 0; | ||
939 | } | ||
940 | pktsize -= fcslen; | ||
891 | wakeup.packet = status->wake_packet; | 941 | wakeup.packet = status->wake_packet; |
892 | wakeup.packet_present_len = pktsize; | 942 | wakeup.packet_present_len = pktsize; |
893 | wakeup.packet_len = pktlen; | 943 | wakeup.packet_len = pktlen - truncated; |
894 | wakeup.packet_80211 = true; | 944 | wakeup.packet_80211 = true; |
895 | } | 945 | } |
896 | } | 946 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index e8264e11b12d..7e169b085afe 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -557,11 +557,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
557 | return ret; | 557 | return ret; |
558 | } | 558 | } |
559 | 559 | ||
560 | static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | 560 | static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, |
561 | struct ieee80211_vif *vif) | 561 | struct ieee80211_vif *vif) |
562 | { | 562 | { |
563 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
564 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
565 | u32 tfd_msk = 0, ac; | 563 | u32 tfd_msk = 0, ac; |
566 | 564 | ||
567 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 565 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
@@ -594,12 +592,21 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | |||
594 | */ | 592 | */ |
595 | flush_work(&mvm->sta_drained_wk); | 593 | flush_work(&mvm->sta_drained_wk); |
596 | } | 594 | } |
595 | } | ||
596 | |||
597 | static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | ||
598 | struct ieee80211_vif *vif) | ||
599 | { | ||
600 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
601 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
602 | |||
603 | iwl_mvm_prepare_mac_removal(mvm, vif); | ||
597 | 604 | ||
598 | mutex_lock(&mvm->mutex); | 605 | mutex_lock(&mvm->mutex); |
599 | 606 | ||
600 | /* | 607 | /* |
601 | * For AP/GO interface, the tear down of the resources allocated to the | 608 | * For AP/GO interface, the tear down of the resources allocated to the |
602 | * interface should be handled as part of the bss_info_changed flow. | 609 | * interface is be handled as part of the stop_ap flow. |
603 | */ | 610 | */ |
604 | if (vif->type == NL80211_IFTYPE_AP) { | 611 | if (vif->type == NL80211_IFTYPE_AP) { |
605 | iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); | 612 | iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); |
@@ -763,6 +770,8 @@ static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
763 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 770 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
764 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 771 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
765 | 772 | ||
773 | iwl_mvm_prepare_mac_removal(mvm, vif); | ||
774 | |||
766 | mutex_lock(&mvm->mutex); | 775 | mutex_lock(&mvm->mutex); |
767 | 776 | ||
768 | mvmvif->ap_active = false; | 777 | mvmvif->ap_active = false; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 4e339ccfa800..537711b10478 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -327,6 +327,10 @@ struct iwl_mvm { | |||
327 | struct led_classdev led; | 327 | struct led_classdev led; |
328 | 328 | ||
329 | struct ieee80211_vif *p2p_device_vif; | 329 | struct ieee80211_vif *p2p_device_vif; |
330 | |||
331 | #ifdef CONFIG_PM_SLEEP | ||
332 | int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; | ||
333 | #endif | ||
330 | }; | 334 | }; |
331 | 335 | ||
332 | /* Extract MVM priv from op_mode and _hw */ | 336 | /* Extract MVM priv from op_mode and _hw */ |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index aa2a39a637dd..3d62e8055352 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -182,6 +182,15 @@ struct iwl_queue { | |||
182 | #define TFD_TX_CMD_SLOTS 256 | 182 | #define TFD_TX_CMD_SLOTS 256 |
183 | #define TFD_CMD_SLOTS 32 | 183 | #define TFD_CMD_SLOTS 32 |
184 | 184 | ||
185 | /* | ||
186 | * The FH will write back to the first TB only, so we need | ||
187 | * to copy some data into the buffer regardless of whether | ||
188 | * it should be mapped or not. This indicates how much to | ||
189 | * copy, even for HCMDs it must be big enough to fit the | ||
190 | * DRAM scratch from the TX cmd, at least 16 bytes. | ||
191 | */ | ||
192 | #define IWL_HCMD_MIN_COPY_SIZE 16 | ||
193 | |||
185 | struct iwl_pcie_txq_entry { | 194 | struct iwl_pcie_txq_entry { |
186 | struct iwl_device_cmd *cmd; | 195 | struct iwl_device_cmd *cmd; |
187 | struct iwl_device_cmd *copy_cmd; | 196 | struct iwl_device_cmd *copy_cmd; |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 8e9e3212fe78..8b625a7f5685 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -1152,10 +1152,12 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1152 | void *dup_buf = NULL; | 1152 | void *dup_buf = NULL; |
1153 | dma_addr_t phys_addr; | 1153 | dma_addr_t phys_addr; |
1154 | int idx; | 1154 | int idx; |
1155 | u16 copy_size, cmd_size; | 1155 | u16 copy_size, cmd_size, dma_size; |
1156 | bool had_nocopy = false; | 1156 | bool had_nocopy = false; |
1157 | int i; | 1157 | int i; |
1158 | u32 cmd_pos; | 1158 | u32 cmd_pos; |
1159 | const u8 *cmddata[IWL_MAX_CMD_TFDS]; | ||
1160 | u16 cmdlen[IWL_MAX_CMD_TFDS]; | ||
1159 | 1161 | ||
1160 | copy_size = sizeof(out_cmd->hdr); | 1162 | copy_size = sizeof(out_cmd->hdr); |
1161 | cmd_size = sizeof(out_cmd->hdr); | 1163 | cmd_size = sizeof(out_cmd->hdr); |
@@ -1164,8 +1166,23 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1164 | BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1); | 1166 | BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1); |
1165 | 1167 | ||
1166 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | 1168 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { |
1169 | cmddata[i] = cmd->data[i]; | ||
1170 | cmdlen[i] = cmd->len[i]; | ||
1171 | |||
1167 | if (!cmd->len[i]) | 1172 | if (!cmd->len[i]) |
1168 | continue; | 1173 | continue; |
1174 | |||
1175 | /* need at least IWL_HCMD_MIN_COPY_SIZE copied */ | ||
1176 | if (copy_size < IWL_HCMD_MIN_COPY_SIZE) { | ||
1177 | int copy = IWL_HCMD_MIN_COPY_SIZE - copy_size; | ||
1178 | |||
1179 | if (copy > cmdlen[i]) | ||
1180 | copy = cmdlen[i]; | ||
1181 | cmdlen[i] -= copy; | ||
1182 | cmddata[i] += copy; | ||
1183 | copy_size += copy; | ||
1184 | } | ||
1185 | |||
1169 | if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { | 1186 | if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { |
1170 | had_nocopy = true; | 1187 | had_nocopy = true; |
1171 | if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) { | 1188 | if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) { |
@@ -1185,7 +1202,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1185 | goto free_dup_buf; | 1202 | goto free_dup_buf; |
1186 | } | 1203 | } |
1187 | 1204 | ||
1188 | dup_buf = kmemdup(cmd->data[i], cmd->len[i], | 1205 | dup_buf = kmemdup(cmddata[i], cmdlen[i], |
1189 | GFP_ATOMIC); | 1206 | GFP_ATOMIC); |
1190 | if (!dup_buf) | 1207 | if (!dup_buf) |
1191 | return -ENOMEM; | 1208 | return -ENOMEM; |
@@ -1195,7 +1212,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1195 | idx = -EINVAL; | 1212 | idx = -EINVAL; |
1196 | goto free_dup_buf; | 1213 | goto free_dup_buf; |
1197 | } | 1214 | } |
1198 | copy_size += cmd->len[i]; | 1215 | copy_size += cmdlen[i]; |
1199 | } | 1216 | } |
1200 | cmd_size += cmd->len[i]; | 1217 | cmd_size += cmd->len[i]; |
1201 | } | 1218 | } |
@@ -1242,14 +1259,31 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1242 | 1259 | ||
1243 | /* and copy the data that needs to be copied */ | 1260 | /* and copy the data that needs to be copied */ |
1244 | cmd_pos = offsetof(struct iwl_device_cmd, payload); | 1261 | cmd_pos = offsetof(struct iwl_device_cmd, payload); |
1262 | copy_size = sizeof(out_cmd->hdr); | ||
1245 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | 1263 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { |
1246 | if (!cmd->len[i]) | 1264 | int copy = 0; |
1265 | |||
1266 | if (!cmd->len) | ||
1247 | continue; | 1267 | continue; |
1248 | if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | | 1268 | |
1249 | IWL_HCMD_DFL_DUP)) | 1269 | /* need at least IWL_HCMD_MIN_COPY_SIZE copied */ |
1250 | break; | 1270 | if (copy_size < IWL_HCMD_MIN_COPY_SIZE) { |
1251 | memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]); | 1271 | copy = IWL_HCMD_MIN_COPY_SIZE - copy_size; |
1252 | cmd_pos += cmd->len[i]; | 1272 | |
1273 | if (copy > cmd->len[i]) | ||
1274 | copy = cmd->len[i]; | ||
1275 | } | ||
1276 | |||
1277 | /* copy everything if not nocopy/dup */ | ||
1278 | if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | | ||
1279 | IWL_HCMD_DFL_DUP))) | ||
1280 | copy = cmd->len[i]; | ||
1281 | |||
1282 | if (copy) { | ||
1283 | memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy); | ||
1284 | cmd_pos += copy; | ||
1285 | copy_size += copy; | ||
1286 | } | ||
1253 | } | 1287 | } |
1254 | 1288 | ||
1255 | WARN_ON_ONCE(txq->entries[idx].copy_cmd); | 1289 | WARN_ON_ONCE(txq->entries[idx].copy_cmd); |
@@ -1275,7 +1309,14 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1275 | out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), | 1309 | out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), |
1276 | cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue); | 1310 | cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue); |
1277 | 1311 | ||
1278 | phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size, | 1312 | /* |
1313 | * If the entire command is smaller than IWL_HCMD_MIN_COPY_SIZE, we must | ||
1314 | * still map at least that many bytes for the hardware to write back to. | ||
1315 | * We have enough space, so that's not a problem. | ||
1316 | */ | ||
1317 | dma_size = max_t(u16, copy_size, IWL_HCMD_MIN_COPY_SIZE); | ||
1318 | |||
1319 | phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, dma_size, | ||
1279 | DMA_BIDIRECTIONAL); | 1320 | DMA_BIDIRECTIONAL); |
1280 | if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { | 1321 | if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { |
1281 | idx = -ENOMEM; | 1322 | idx = -ENOMEM; |
@@ -1283,14 +1324,15 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1283 | } | 1324 | } |
1284 | 1325 | ||
1285 | dma_unmap_addr_set(out_meta, mapping, phys_addr); | 1326 | dma_unmap_addr_set(out_meta, mapping, phys_addr); |
1286 | dma_unmap_len_set(out_meta, len, copy_size); | 1327 | dma_unmap_len_set(out_meta, len, dma_size); |
1287 | 1328 | ||
1288 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1); | 1329 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1); |
1289 | 1330 | ||
1331 | /* map the remaining (adjusted) nocopy/dup fragments */ | ||
1290 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | 1332 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { |
1291 | const void *data = cmd->data[i]; | 1333 | const void *data = cmddata[i]; |
1292 | 1334 | ||
1293 | if (!cmd->len[i]) | 1335 | if (!cmdlen[i]) |
1294 | continue; | 1336 | continue; |
1295 | if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | | 1337 | if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | |
1296 | IWL_HCMD_DFL_DUP))) | 1338 | IWL_HCMD_DFL_DUP))) |
@@ -1298,7 +1340,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1298 | if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) | 1340 | if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) |
1299 | data = dup_buf; | 1341 | data = dup_buf; |
1300 | phys_addr = dma_map_single(trans->dev, (void *)data, | 1342 | phys_addr = dma_map_single(trans->dev, (void *)data, |
1301 | cmd->len[i], DMA_BIDIRECTIONAL); | 1343 | cmdlen[i], DMA_BIDIRECTIONAL); |
1302 | if (dma_mapping_error(trans->dev, phys_addr)) { | 1344 | if (dma_mapping_error(trans->dev, phys_addr)) { |
1303 | iwl_pcie_tfd_unmap(trans, out_meta, | 1345 | iwl_pcie_tfd_unmap(trans, out_meta, |
1304 | &txq->tfds[q->write_ptr], | 1346 | &txq->tfds[q->write_ptr], |
@@ -1307,7 +1349,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1307 | goto out; | 1349 | goto out; |
1308 | } | 1350 | } |
1309 | 1351 | ||
1310 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0); | 1352 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0); |
1311 | } | 1353 | } |
1312 | 1354 | ||
1313 | out_meta->flags = cmd->flags; | 1355 | out_meta->flags = cmd->flags; |
@@ -1317,8 +1359,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1317 | 1359 | ||
1318 | txq->need_update = 1; | 1360 | txq->need_update = 1; |
1319 | 1361 | ||
1320 | trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, | 1362 | trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr); |
1321 | &out_cmd->hdr, copy_size); | ||
1322 | 1363 | ||
1323 | /* start timer if queue currently empty */ | 1364 | /* start timer if queue currently empty */ |
1324 | if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) | 1365 | if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 739309e70d8b..45578335e420 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -825,6 +825,11 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card) | |||
825 | 825 | ||
826 | sdio_release_host(func); | 826 | sdio_release_host(func); |
827 | 827 | ||
828 | /* Set fw_ready before queuing any commands so that | ||
829 | * lbs_thread won't block from sending them to firmware. | ||
830 | */ | ||
831 | priv->fw_ready = 1; | ||
832 | |||
828 | /* | 833 | /* |
829 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions | 834 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions |
830 | */ | 835 | */ |
@@ -839,7 +844,6 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card) | |||
839 | netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n"); | 844 | netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n"); |
840 | } | 845 | } |
841 | 846 | ||
842 | priv->fw_ready = 1; | ||
843 | wake_up(&card->pwron_waitq); | 847 | wake_up(&card->pwron_waitq); |
844 | 848 | ||
845 | if (!card->started) { | 849 | if (!card->started) { |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 35c79722c361..5c395e2e6a2b 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -302,7 +302,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | |||
302 | i++; | 302 | i++; |
303 | usleep_range(10, 20); | 303 | usleep_range(10, 20); |
304 | /* 50ms max wait */ | 304 | /* 50ms max wait */ |
305 | if (i == 50000) | 305 | if (i == 5000) |
306 | break; | 306 | break; |
307 | } | 307 | } |
308 | 308 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 1031db66474a..189744db65e0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -1236,8 +1236,10 @@ static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev) | |||
1236 | */ | 1236 | */ |
1237 | if_limit = &rt2x00dev->if_limits_ap; | 1237 | if_limit = &rt2x00dev->if_limits_ap; |
1238 | if_limit->max = rt2x00dev->ops->max_ap_intf; | 1238 | if_limit->max = rt2x00dev->ops->max_ap_intf; |
1239 | if_limit->types = BIT(NL80211_IFTYPE_AP) | | 1239 | if_limit->types = BIT(NL80211_IFTYPE_AP); |
1240 | BIT(NL80211_IFTYPE_MESH_POINT); | 1240 | #ifdef CONFIG_MAC80211_MESH |
1241 | if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT); | ||
1242 | #endif | ||
1241 | 1243 | ||
1242 | /* | 1244 | /* |
1243 | * Build up AP interface combinations structure. | 1245 | * Build up AP interface combinations structure. |
@@ -1309,7 +1311,9 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
1309 | rt2x00dev->hw->wiphy->interface_modes |= | 1311 | rt2x00dev->hw->wiphy->interface_modes |= |
1310 | BIT(NL80211_IFTYPE_ADHOC) | | 1312 | BIT(NL80211_IFTYPE_ADHOC) | |
1311 | BIT(NL80211_IFTYPE_AP) | | 1313 | BIT(NL80211_IFTYPE_AP) | |
1314 | #ifdef CONFIG_MAC80211_MESH | ||
1312 | BIT(NL80211_IFTYPE_MESH_POINT) | | 1315 | BIT(NL80211_IFTYPE_MESH_POINT) | |
1316 | #endif | ||
1313 | BIT(NL80211_IFTYPE_WDS); | 1317 | BIT(NL80211_IFTYPE_WDS); |
1314 | 1318 | ||
1315 | rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 1319 | rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 09d96a8f6c2c..808f5fcd1ced 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -3285,13 +3285,19 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy, | |||
3285 | struct cfg80211_chan_def *chandef) | 3285 | struct cfg80211_chan_def *chandef) |
3286 | { | 3286 | { |
3287 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | 3287 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
3288 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
3288 | struct ieee80211_chanctx_conf *chanctx_conf; | 3289 | struct ieee80211_chanctx_conf *chanctx_conf; |
3289 | int ret = -ENODATA; | 3290 | int ret = -ENODATA; |
3290 | 3291 | ||
3291 | rcu_read_lock(); | 3292 | rcu_read_lock(); |
3292 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 3293 | if (local->use_chanctx) { |
3293 | if (chanctx_conf) { | 3294 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
3294 | *chandef = chanctx_conf->def; | 3295 | if (chanctx_conf) { |
3296 | *chandef = chanctx_conf->def; | ||
3297 | ret = 0; | ||
3298 | } | ||
3299 | } else if (local->open_count == local->monitors) { | ||
3300 | *chandef = local->monitor_chandef; | ||
3295 | ret = 0; | 3301 | ret = 0; |
3296 | } | 3302 | } |
3297 | rcu_read_unlock(); | 3303 | rcu_read_unlock(); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 2c059e54e885..640afab304d7 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -107,7 +107,7 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) | |||
107 | 107 | ||
108 | lockdep_assert_held(&local->mtx); | 108 | lockdep_assert_held(&local->mtx); |
109 | 109 | ||
110 | active = !list_empty(&local->chanctx_list); | 110 | active = !list_empty(&local->chanctx_list) || local->monitors; |
111 | 111 | ||
112 | if (!local->ops->remain_on_channel) { | 112 | if (!local->ops->remain_on_channel) { |
113 | list_for_each_entry(roc, &local->roc_list, list) { | 113 | list_for_each_entry(roc, &local->roc_list, list) { |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 5b9602b62405..c592a413bad9 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1231,34 +1231,40 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, | |||
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 & | 1233 | if (unlikely(info->flags & |
1234 | IEEE80211_TX_INTFL_OFFCHAN_TX_OK && | 1234 | IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) { |
1235 | local->queue_stop_reasons[q] & | 1235 | if (local->queue_stop_reasons[q] & |
1236 | ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) { | 1236 | ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) { |
1237 | /* | ||
1238 | * Drop off-channel frames if queues | ||
1239 | * are stopped for any reason other | ||
1240 | * than off-channel operation. Never | ||
1241 | * queue them. | ||
1242 | */ | ||
1243 | spin_unlock_irqrestore( | ||
1244 | &local->queue_stop_reason_lock, | ||
1245 | flags); | ||
1246 | ieee80211_purge_tx_queue(&local->hw, | ||
1247 | skbs); | ||
1248 | return true; | ||
1249 | } | ||
1250 | } else { | ||
1251 | |||
1237 | /* | 1252 | /* |
1238 | * Drop off-channel frames if queues are stopped | 1253 | * Since queue is stopped, queue up frames for |
1239 | * for any reason other than off-channel | 1254 | * later transmission from the tx-pending |
1240 | * operation. Never queue them. | 1255 | * tasklet when the queue is woken again. |
1241 | */ | 1256 | */ |
1242 | spin_unlock_irqrestore( | 1257 | if (txpending) |
1243 | &local->queue_stop_reason_lock, flags); | 1258 | skb_queue_splice_init(skbs, |
1244 | ieee80211_purge_tx_queue(&local->hw, skbs); | 1259 | &local->pending[q]); |
1245 | return true; | 1260 | else |
1261 | skb_queue_splice_tail_init(skbs, | ||
1262 | &local->pending[q]); | ||
1263 | |||
1264 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | ||
1265 | flags); | ||
1266 | return false; | ||
1246 | } | 1267 | } |
1247 | |||
1248 | /* | ||
1249 | * Since queue is stopped, queue up frames for later | ||
1250 | * transmission from the tx-pending tasklet when the | ||
1251 | * queue is woken again. | ||
1252 | */ | ||
1253 | if (txpending) | ||
1254 | skb_queue_splice_init(skbs, &local->pending[q]); | ||
1255 | else | ||
1256 | skb_queue_splice_tail_init(skbs, | ||
1257 | &local->pending[q]); | ||
1258 | |||
1259 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | ||
1260 | flags); | ||
1261 | return false; | ||
1262 | } | 1268 | } |
1263 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 1269 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
1264 | 1270 | ||
@@ -1844,9 +1850,24 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1844 | } | 1850 | } |
1845 | 1851 | ||
1846 | if (!is_multicast_ether_addr(skb->data)) { | 1852 | if (!is_multicast_ether_addr(skb->data)) { |
1853 | struct sta_info *next_hop; | ||
1854 | bool mpp_lookup = true; | ||
1855 | |||
1847 | mpath = mesh_path_lookup(sdata, skb->data); | 1856 | mpath = mesh_path_lookup(sdata, skb->data); |
1848 | if (!mpath) | 1857 | if (mpath) { |
1858 | mpp_lookup = false; | ||
1859 | next_hop = rcu_dereference(mpath->next_hop); | ||
1860 | if (!next_hop || | ||
1861 | !(mpath->flags & (MESH_PATH_ACTIVE | | ||
1862 | MESH_PATH_RESOLVING))) | ||
1863 | mpp_lookup = true; | ||
1864 | } | ||
1865 | |||
1866 | if (mpp_lookup) | ||
1849 | mppath = mpp_path_lookup(sdata, skb->data); | 1867 | mppath = mpp_path_lookup(sdata, skb->data); |
1868 | |||
1869 | if (mppath && mpath) | ||
1870 | mesh_path_del(mpath->sdata, mpath->dst); | ||
1850 | } | 1871 | } |
1851 | 1872 | ||
1852 | /* | 1873 | /* |
@@ -2360,9 +2381,9 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | |||
2360 | if (local->tim_in_locked_section) { | 2381 | if (local->tim_in_locked_section) { |
2361 | __ieee80211_beacon_add_tim(sdata, ps, skb); | 2382 | __ieee80211_beacon_add_tim(sdata, ps, skb); |
2362 | } else { | 2383 | } else { |
2363 | spin_lock(&local->tim_lock); | 2384 | spin_lock_bh(&local->tim_lock); |
2364 | __ieee80211_beacon_add_tim(sdata, ps, skb); | 2385 | __ieee80211_beacon_add_tim(sdata, ps, skb); |
2365 | spin_unlock(&local->tim_lock); | 2386 | spin_unlock_bh(&local->tim_lock); |
2366 | } | 2387 | } |
2367 | 2388 | ||
2368 | return 0; | 2389 | return 0; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 35545ccc30fd..e652d05ff712 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -554,16 +554,9 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, | |||
554 | if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && | 554 | if ((chan->flags & IEEE80211_CHAN_NO_IBSS) && |
555 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) | 555 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS)) |
556 | goto nla_put_failure; | 556 | goto nla_put_failure; |
557 | if (chan->flags & IEEE80211_CHAN_RADAR) { | 557 | if ((chan->flags & IEEE80211_CHAN_RADAR) && |
558 | u32 time = elapsed_jiffies_msecs(chan->dfs_state_entered); | 558 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) |
559 | if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) | 559 | goto nla_put_failure; |
560 | goto nla_put_failure; | ||
561 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE, | ||
562 | chan->dfs_state)) | ||
563 | goto nla_put_failure; | ||
564 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, time)) | ||
565 | goto nla_put_failure; | ||
566 | } | ||
567 | if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) && | 560 | if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) && |
568 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS)) | 561 | nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS)) |
569 | goto nla_put_failure; | 562 | goto nla_put_failure; |
@@ -900,9 +893,6 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy, | |||
900 | nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, | 893 | nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM, |
901 | c->max_interfaces)) | 894 | c->max_interfaces)) |
902 | goto nla_put_failure; | 895 | goto nla_put_failure; |
903 | if (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, | ||
904 | c->radar_detect_widths)) | ||
905 | goto nla_put_failure; | ||
906 | 896 | ||
907 | nla_nest_end(msg, nl_combi); | 897 | nla_nest_end(msg, nl_combi); |
908 | } | 898 | } |
@@ -914,48 +904,6 @@ nla_put_failure: | |||
914 | return -ENOBUFS; | 904 | return -ENOBUFS; |
915 | } | 905 | } |
916 | 906 | ||
917 | #ifdef CONFIG_PM | ||
918 | static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev, | ||
919 | struct sk_buff *msg) | ||
920 | { | ||
921 | const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan.tcp; | ||
922 | struct nlattr *nl_tcp; | ||
923 | |||
924 | if (!tcp) | ||
925 | return 0; | ||
926 | |||
927 | nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION); | ||
928 | if (!nl_tcp) | ||
929 | return -ENOBUFS; | ||
930 | |||
931 | if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD, | ||
932 | tcp->data_payload_max)) | ||
933 | return -ENOBUFS; | ||
934 | |||
935 | if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD, | ||
936 | tcp->data_payload_max)) | ||
937 | return -ENOBUFS; | ||
938 | |||
939 | if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ)) | ||
940 | return -ENOBUFS; | ||
941 | |||
942 | if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN, | ||
943 | sizeof(*tcp->tok), tcp->tok)) | ||
944 | return -ENOBUFS; | ||
945 | |||
946 | if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL, | ||
947 | tcp->data_interval_max)) | ||
948 | return -ENOBUFS; | ||
949 | |||
950 | if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD, | ||
951 | tcp->wake_payload_max)) | ||
952 | return -ENOBUFS; | ||
953 | |||
954 | nla_nest_end(msg, nl_tcp); | ||
955 | return 0; | ||
956 | } | ||
957 | #endif | ||
958 | |||
959 | static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags, | 907 | static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags, |
960 | struct cfg80211_registered_device *dev) | 908 | struct cfg80211_registered_device *dev) |
961 | { | 909 | { |
@@ -1330,9 +1278,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag | |||
1330 | goto nla_put_failure; | 1278 | goto nla_put_failure; |
1331 | } | 1279 | } |
1332 | 1280 | ||
1333 | if (nl80211_send_wowlan_tcp_caps(dev, msg)) | ||
1334 | goto nla_put_failure; | ||
1335 | |||
1336 | nla_nest_end(msg, nl_wowlan); | 1281 | nla_nest_end(msg, nl_wowlan); |
1337 | } | 1282 | } |
1338 | #endif | 1283 | #endif |