aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intel/iwlwifi
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-11-27 20:26:59 -0500
committerDavid S. Miller <davem@davemloft.net>2016-11-27 20:26:59 -0500
commit33f8a0458b2ce4546b681c5fae04427e3077a543 (patch)
treedc7e9750666fa02b19e0dad4aa8b514403f5e4ae /drivers/net/wireless/intel/iwlwifi
parent5a717f4f8f2830f297b5511022481bdc27b9d576 (diff)
parent159a55a64d44acbbd6f0d8f3c082e628d6d75670 (diff)
Merge tag 'wireless-drivers-next-for-davem-2016-11-25' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says: ==================== wireless-drivers-next patches for 4.10 Major changes: iwlwifi * finalize and enable dynamic queue allocation * use dev_coredumpmsg() to prevent locking the driver * small fix to pass the AID to the FW * use FW PS decisions with multi-queue ath9k * add device tree bindings * switch to use mac80211 intermediate software queues to reduce latency and fix bufferbloat wl18xx * allow scanning in AP mode ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h26
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c100
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c24
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c86
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c37
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c29
12 files changed, 249 insertions, 75 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
index ceec5ca2b1ab..1ad0ec180d5d 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-fw-file.h
@@ -293,6 +293,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;
293 * is supported. 293 * is supported.
294 * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC 294 * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC
295 * @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan 295 * @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan
296 * @IWL_UCODE_TLV_CAPA_STA_PM_NOTIF: firmware will send STA PM notification
296 * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement 297 * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
297 * @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts 298 * @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
298 * @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT 299 * @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT
@@ -342,6 +343,7 @@ enum iwl_ucode_tlv_capa {
342 IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29, 343 IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29,
343 IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30, 344 IWL_UCODE_TLV_CAPA_BT_COEX_RRC = (__force iwl_ucode_tlv_capa_t)30,
344 IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, 345 IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31,
346 IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38,
345 IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, 347 IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
346 IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, 348 IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
347 IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67, 349 IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
index acc5cd53e4ba..b530fa47d68a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-rx.h
@@ -474,4 +474,30 @@ struct iwl_mvm_internal_rxq_notif {
474 u8 data[]; 474 u8 data[];
475} __packed; 475} __packed;
476 476
477/**
478 * enum iwl_mvm_pm_event - type of station PM event
479 * @IWL_MVM_PM_EVENT_AWAKE: station woke up
480 * @IWL_MVM_PM_EVENT_ASLEEP: station went to sleep
481 * @IWL_MVM_PM_EVENT_UAPSD: station sent uAPSD trigger
482 * @IWL_MVM_PM_EVENT_PS_POLL: station sent PS-Poll
483 */
484enum iwl_mvm_pm_event {
485 IWL_MVM_PM_EVENT_AWAKE,
486 IWL_MVM_PM_EVENT_ASLEEP,
487 IWL_MVM_PM_EVENT_UAPSD,
488 IWL_MVM_PM_EVENT_PS_POLL,
489}; /* PEER_PM_NTFY_API_E_VER_1 */
490
491/**
492 * struct iwl_mvm_pm_state_notification - station PM state notification
493 * @sta_id: station ID of the station changing state
494 * @type: the new powersave state, see IWL_MVM_PM_EVENT_ above
495 */
496struct iwl_mvm_pm_state_notification {
497 u8 sta_id;
498 u8 type;
499 /* private: */
500 u16 reserved;
501} __packed; /* PEER_PM_NTFY_API_S_VER_1 */
502
477#endif /* __fw_api_rx_h__ */ 503#endif /* __fw_api_rx_h__ */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
index 6c8e3ca79323..3b5150e9975d 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api-sta.h
@@ -179,7 +179,7 @@ enum iwl_sta_key_flag {
179 * enum iwl_sta_modify_flag - indicate to the fw what flag are being changed 179 * enum iwl_sta_modify_flag - indicate to the fw what flag are being changed
180 * @STA_MODIFY_QUEUE_REMOVAL: this command removes a queue 180 * @STA_MODIFY_QUEUE_REMOVAL: this command removes a queue
181 * @STA_MODIFY_TID_DISABLE_TX: this command modifies %tid_disable_tx 181 * @STA_MODIFY_TID_DISABLE_TX: this command modifies %tid_disable_tx
182 * @STA_MODIFY_TX_RATE: unused 182 * @STA_MODIFY_UAPSD_ACS: this command modifies %uapsd_trigger_acs
183 * @STA_MODIFY_ADD_BA_TID: this command modifies %add_immediate_ba_tid 183 * @STA_MODIFY_ADD_BA_TID: this command modifies %add_immediate_ba_tid
184 * @STA_MODIFY_REMOVE_BA_TID: this command modifies %remove_immediate_ba_tid 184 * @STA_MODIFY_REMOVE_BA_TID: this command modifies %remove_immediate_ba_tid
185 * @STA_MODIFY_SLEEPING_STA_TX_COUNT: this command modifies %sleep_tx_count 185 * @STA_MODIFY_SLEEPING_STA_TX_COUNT: this command modifies %sleep_tx_count
@@ -189,7 +189,7 @@ enum iwl_sta_key_flag {
189enum iwl_sta_modify_flag { 189enum iwl_sta_modify_flag {
190 STA_MODIFY_QUEUE_REMOVAL = BIT(0), 190 STA_MODIFY_QUEUE_REMOVAL = BIT(0),
191 STA_MODIFY_TID_DISABLE_TX = BIT(1), 191 STA_MODIFY_TID_DISABLE_TX = BIT(1),
192 STA_MODIFY_TX_RATE = BIT(2), 192 STA_MODIFY_UAPSD_ACS = BIT(2),
193 STA_MODIFY_ADD_BA_TID = BIT(3), 193 STA_MODIFY_ADD_BA_TID = BIT(3),
194 STA_MODIFY_REMOVE_BA_TID = BIT(4), 194 STA_MODIFY_REMOVE_BA_TID = BIT(4),
195 STA_MODIFY_SLEEPING_STA_TX_COUNT = BIT(5), 195 STA_MODIFY_SLEEPING_STA_TX_COUNT = BIT(5),
@@ -353,6 +353,8 @@ struct iwl_mvm_add_sta_cmd_v7 {
353 * @beamform_flags: beam forming controls 353 * @beamform_flags: beam forming controls
354 * @tfd_queue_msk: tfd queues used by this station 354 * @tfd_queue_msk: tfd queues used by this station
355 * @rx_ba_window: aggregation window size 355 * @rx_ba_window: aggregation window size
356 * @scd_queue_bank: queue bank in used. Each bank contains 32 queues. 0 means
357 * that the queues used by this station are in the first 32.
356 * 358 *
357 * The device contains an internal table of per-station information, with info 359 * The device contains an internal table of per-station information, with info
358 * on security keys, aggregation parameters, and Tx rates for initial Tx 360 * on security keys, aggregation parameters, and Tx rates for initial Tx
@@ -382,7 +384,8 @@ struct iwl_mvm_add_sta_cmd {
382 __le16 beamform_flags; 384 __le16 beamform_flags;
383 __le32 tfd_queue_msk; 385 __le32 tfd_queue_msk;
384 __le16 rx_ba_window; 386 __le16 rx_ba_window;
385 __le16 reserved; 387 u8 scd_queue_bank;
388 u8 uapsd_trigger_acs;
386} __packed; /* ADD_STA_CMD_API_S_VER_8 */ 389} __packed; /* ADD_STA_CMD_API_S_VER_8 */
387 390
388/** 391/**
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
index 97633690f3d5..ae12badc0c2a 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-api.h
@@ -332,6 +332,7 @@ enum iwl_data_path_subcmd_ids {
332 DQA_ENABLE_CMD = 0x0, 332 DQA_ENABLE_CMD = 0x0,
333 UPDATE_MU_GROUPS_CMD = 0x1, 333 UPDATE_MU_GROUPS_CMD = 0x1,
334 TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2, 334 TRIGGER_RX_QUEUES_NOTIF_CMD = 0x2,
335 STA_PM_NOTIF = 0xFD,
335 MU_GROUP_MGMT_NOTIF = 0xFE, 336 MU_GROUP_MGMT_NOTIF = 0xFE,
336 RX_QUEUES_NOTIFICATION = 0xFF, 337 RX_QUEUES_NOTIFICATION = 0xFF,
337}; 338};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
index d89d0a1fd34e..2e8e3e8e30a3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw-dbg.c
@@ -70,49 +70,6 @@
70#include "iwl-prph.h" 70#include "iwl-prph.h"
71#include "iwl-csr.h" 71#include "iwl-csr.h"
72 72
73static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count,
74 void *data, size_t datalen)
75{
76 const struct iwl_mvm_dump_ptrs *dump_ptrs = data;
77 ssize_t bytes_read;
78 ssize_t bytes_read_trans;
79
80 if (offset < dump_ptrs->op_mode_len) {
81 bytes_read = min_t(ssize_t, count,
82 dump_ptrs->op_mode_len - offset);
83 memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset,
84 bytes_read);
85 offset += bytes_read;
86 count -= bytes_read;
87
88 if (count == 0)
89 return bytes_read;
90 } else {
91 bytes_read = 0;
92 }
93
94 if (!dump_ptrs->trans_ptr)
95 return bytes_read;
96
97 offset -= dump_ptrs->op_mode_len;
98 bytes_read_trans = min_t(ssize_t, count,
99 dump_ptrs->trans_ptr->len - offset);
100 memcpy(buffer + bytes_read,
101 (u8 *)dump_ptrs->trans_ptr->data + offset,
102 bytes_read_trans);
103
104 return bytes_read + bytes_read_trans;
105}
106
107static void iwl_mvm_free_coredump(void *data)
108{
109 const struct iwl_mvm_dump_ptrs *fw_error_dump = data;
110
111 vfree(fw_error_dump->op_mode_ptr);
112 vfree(fw_error_dump->trans_ptr);
113 kfree(fw_error_dump);
114}
115
116#define RADIO_REG_MAX_READ 0x2ad 73#define RADIO_REG_MAX_READ 0x2ad
117static void iwl_mvm_read_radio_reg(struct iwl_mvm *mvm, 74static void iwl_mvm_read_radio_reg(struct iwl_mvm *mvm,
118 struct iwl_fw_error_dump_data **dump_data) 75 struct iwl_fw_error_dump_data **dump_data)
@@ -491,6 +448,43 @@ static u32 iwl_dump_prph(struct iwl_trans *trans,
491 return prph_len; 448 return prph_len;
492} 449}
493 450
451/*
452 * alloc_sgtable - allocates scallerlist table in the given size,
453 * fills it with pages and returns it
454 * @size: the size (in bytes) of the table
455*/
456static struct scatterlist *alloc_sgtable(int size)
457{
458 int alloc_size, nents, i;
459 struct page *new_page;
460 struct scatterlist *iter;
461 struct scatterlist *table;
462
463 nents = DIV_ROUND_UP(size, PAGE_SIZE);
464 table = kcalloc(nents, sizeof(*table), GFP_KERNEL);
465 if (!table)
466 return NULL;
467 sg_init_table(table, nents);
468 iter = table;
469 for_each_sg(table, iter, sg_nents(table), i) {
470 new_page = alloc_page(GFP_KERNEL);
471 if (!new_page) {
472 /* release all previous allocated pages in the table */
473 iter = table;
474 for_each_sg(table, iter, sg_nents(table), i) {
475 new_page = sg_page(iter);
476 if (new_page)
477 __free_page(new_page);
478 }
479 return NULL;
480 }
481 alloc_size = min_t(int, size, PAGE_SIZE);
482 size -= PAGE_SIZE;
483 sg_set_page(iter, new_page, alloc_size, 0);
484 }
485 return table;
486}
487
494void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) 488void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
495{ 489{
496 struct iwl_fw_error_dump_file *dump_file; 490 struct iwl_fw_error_dump_file *dump_file;
@@ -499,6 +493,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
499 struct iwl_fw_error_dump_mem *dump_mem; 493 struct iwl_fw_error_dump_mem *dump_mem;
500 struct iwl_fw_error_dump_trigger_desc *dump_trig; 494 struct iwl_fw_error_dump_trigger_desc *dump_trig;
501 struct iwl_mvm_dump_ptrs *fw_error_dump; 495 struct iwl_mvm_dump_ptrs *fw_error_dump;
496 struct scatterlist *sg_dump_data;
502 u32 sram_len, sram_ofs; 497 u32 sram_len, sram_ofs;
503 struct iwl_fw_dbg_mem_seg_tlv * const *fw_dbg_mem = 498 struct iwl_fw_dbg_mem_seg_tlv * const *fw_dbg_mem =
504 mvm->fw->dbg_mem_tlv; 499 mvm->fw->dbg_mem_tlv;
@@ -815,8 +810,23 @@ dump_trans_data:
815 file_len += fw_error_dump->trans_ptr->len; 810 file_len += fw_error_dump->trans_ptr->len;
816 dump_file->file_len = cpu_to_le32(file_len); 811 dump_file->file_len = cpu_to_le32(file_len);
817 812
818 dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0, 813 sg_dump_data = alloc_sgtable(file_len);
819 GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump); 814 if (sg_dump_data) {
815 sg_pcopy_from_buffer(sg_dump_data,
816 sg_nents(sg_dump_data),
817 fw_error_dump->op_mode_ptr,
818 fw_error_dump->op_mode_len, 0);
819 sg_pcopy_from_buffer(sg_dump_data,
820 sg_nents(sg_dump_data),
821 fw_error_dump->trans_ptr->data,
822 fw_error_dump->trans_ptr->len,
823 fw_error_dump->op_mode_len);
824 dev_coredumpsg(mvm->trans->dev, sg_dump_data, file_len,
825 GFP_KERNEL);
826 }
827 vfree(fw_error_dump->op_mode_ptr);
828 vfree(fw_error_dump->trans_ptr);
829 kfree(fw_error_dump);
820 830
821out: 831out:
822 iwl_mvm_free_fw_dump_desc(mvm); 832 iwl_mvm_free_fw_dump_desc(mvm);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 6b962d6b067a..4a0874e40731 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -499,23 +499,21 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
499 if (ret) 499 if (ret)
500 return ret; 500 return ret;
501 501
502 /* If DQA is supported - queues will be enabled when needed */
503 if (iwl_mvm_is_dqa_supported(mvm))
504 return 0;
505
502 switch (vif->type) { 506 switch (vif->type) {
503 case NL80211_IFTYPE_P2P_DEVICE: 507 case NL80211_IFTYPE_P2P_DEVICE:
504 if (!iwl_mvm_is_dqa_supported(mvm)) 508 iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE,
505 iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, 509 IWL_MVM_OFFCHANNEL_QUEUE,
506 IWL_MVM_OFFCHANNEL_QUEUE, 510 IWL_MVM_TX_FIFO_VO, 0, wdg_timeout);
507 IWL_MVM_TX_FIFO_VO, 0,
508 wdg_timeout);
509 break; 511 break;
510 case NL80211_IFTYPE_AP: 512 case NL80211_IFTYPE_AP:
511 iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, vif->cab_queue, 513 iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, vif->cab_queue,
512 IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout); 514 IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout);
513 /* fall through */ 515 /* fall through */
514 default: 516 default:
515 /* If DQA is supported - queues will be enabled when needed */
516 if (iwl_mvm_is_dqa_supported(mvm))
517 break;
518
519 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) 517 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
520 iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac], 518 iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac],
521 vif->hw_queue[ac], 519 vif->hw_queue[ac],
@@ -899,9 +897,11 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
899 897
900 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action); 898 iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
901 899
902 for (i = 0; i < IEEE80211_NUM_ACS; i++) 900 if (!iwl_mvm_is_dqa_supported(mvm)) {
903 if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE) 901 for (i = 0; i < IEEE80211_NUM_ACS; i++)
904 tfd_queue_msk |= BIT(vif->hw_queue[i]); 902 if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
903 tfd_queue_msk |= BIT(vif->hw_queue[i]);
904 }
905 905
906 cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC | 906 cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
907 MAC_FILTER_IN_CONTROL_AND_MGMT | 907 MAC_FILTER_IN_CONTROL_AND_MGMT |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 1db1dc13e988..45122dafe922 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -445,6 +445,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
445 ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); 445 ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR);
446 if (iwl_mvm_has_new_rx_api(mvm)) 446 if (iwl_mvm_has_new_rx_api(mvm))
447 ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER); 447 ieee80211_hw_set(hw, SUPPORTS_REORDERING_BUFFER);
448 if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_STA_PM_NOTIF))
449 ieee80211_hw_set(hw, AP_LINK_PS);
448 450
449 if (mvm->trans->num_rx_queues > 1) 451 if (mvm->trans->num_rx_queues > 1)
450 ieee80211_hw_set(hw, USES_RSS); 452 ieee80211_hw_set(hw, USES_RSS);
@@ -2097,6 +2099,22 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
2097 if (ret) 2099 if (ret)
2098 goto out_unbind; 2100 goto out_unbind;
2099 2101
2102 /* enable the multicast queue, now that we have a station for it */
2103 if (iwl_mvm_is_dqa_supported(mvm)) {
2104 unsigned int wdg_timeout =
2105 iwl_mvm_get_wd_timeout(mvm, vif, false, false);
2106 struct iwl_trans_txq_scd_cfg cfg = {
2107 .fifo = IWL_MVM_TX_FIFO_MCAST,
2108 .sta_id = mvmvif->bcast_sta.sta_id,
2109 .tid = IWL_MAX_TID_COUNT,
2110 .aggregate = false,
2111 .frame_limit = IWL_FRAME_LIMIT,
2112 };
2113
2114 iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
2115 &cfg, wdg_timeout);
2116 }
2117
2100 /* must be set before quota calculations */ 2118 /* must be set before quota calculations */
2101 mvmvif->ap_ibss_active = true; 2119 mvmvif->ap_ibss_active = true;
2102 2120
@@ -2318,10 +2336,9 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
2318 tids, more_data, true); 2336 tids, more_data, true);
2319} 2337}
2320 2338
2321static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, 2339static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
2322 struct ieee80211_vif *vif, 2340 enum sta_notify_cmd cmd,
2323 enum sta_notify_cmd cmd, 2341 struct ieee80211_sta *sta)
2324 struct ieee80211_sta *sta)
2325{ 2342{
2326 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 2343 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
2327 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); 2344 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
@@ -2374,6 +2391,67 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
2374 spin_unlock_bh(&mvmsta->lock); 2391 spin_unlock_bh(&mvmsta->lock);
2375} 2392}
2376 2393
2394static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
2395 struct ieee80211_vif *vif,
2396 enum sta_notify_cmd cmd,
2397 struct ieee80211_sta *sta)
2398{
2399 __iwl_mvm_mac_sta_notify(hw, cmd, sta);
2400}
2401
2402void iwl_mvm_sta_pm_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
2403{
2404 struct iwl_rx_packet *pkt = rxb_addr(rxb);
2405 struct iwl_mvm_pm_state_notification *notif = (void *)pkt->data;
2406 struct ieee80211_sta *sta;
2407 struct iwl_mvm_sta *mvmsta;
2408 bool sleeping = (notif->type != IWL_MVM_PM_EVENT_AWAKE);
2409
2410 if (WARN_ON(notif->sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id)))
2411 return;
2412
2413 rcu_read_lock();
2414 sta = mvm->fw_id_to_mac_id[notif->sta_id];
2415 if (WARN_ON(IS_ERR_OR_NULL(sta))) {
2416 rcu_read_unlock();
2417 return;
2418 }
2419
2420 mvmsta = iwl_mvm_sta_from_mac80211(sta);
2421
2422 if (!mvmsta->vif ||
2423 mvmsta->vif->type != NL80211_IFTYPE_AP) {
2424 rcu_read_unlock();
2425 return;
2426 }
2427
2428 if (mvmsta->sleeping != sleeping) {
2429 mvmsta->sleeping = sleeping;
2430 __iwl_mvm_mac_sta_notify(mvm->hw,
2431 sleeping ? STA_NOTIFY_SLEEP : STA_NOTIFY_AWAKE,
2432 sta);
2433 ieee80211_sta_ps_transition(sta, sleeping);
2434 }
2435
2436 if (sleeping) {
2437 switch (notif->type) {
2438 case IWL_MVM_PM_EVENT_AWAKE:
2439 case IWL_MVM_PM_EVENT_ASLEEP:
2440 break;
2441 case IWL_MVM_PM_EVENT_UAPSD:
2442 ieee80211_sta_uapsd_trigger(sta, IEEE80211_NUM_TIDS);
2443 break;
2444 case IWL_MVM_PM_EVENT_PS_POLL:
2445 ieee80211_sta_pspoll(sta);
2446 break;
2447 default:
2448 break;
2449 }
2450 }
2451
2452 rcu_read_unlock();
2453}
2454
2377static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, 2455static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
2378 struct ieee80211_vif *vif, 2456 struct ieee80211_vif *vif,
2379 struct ieee80211_sta *sta) 2457 struct ieee80211_sta *sta)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index c60703e0c246..4a9cb76b7611 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1112,9 +1112,8 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)
1112 1112
1113static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm) 1113static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm)
1114{ 1114{
1115 /* Make sure DQA isn't allowed in driver until feature is complete */ 1115 return fw_has_capa(&mvm->fw->ucode_capa,
1116 return false && fw_has_capa(&mvm->fw->ucode_capa, 1116 IWL_UCODE_TLV_CAPA_DQA_SUPPORT);
1117 IWL_UCODE_TLV_CAPA_DQA_SUPPORT);
1118} 1117}
1119 1118
1120static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm) 1119static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm)
@@ -1419,6 +1418,7 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
1419 struct iwl_rx_cmd_buffer *rxb); 1418 struct iwl_rx_cmd_buffer *rxb);
1420void iwl_mvm_mu_mimo_grp_notif(struct iwl_mvm *mvm, 1419void iwl_mvm_mu_mimo_grp_notif(struct iwl_mvm *mvm,
1421 struct iwl_rx_cmd_buffer *rxb); 1420 struct iwl_rx_cmd_buffer *rxb);
1421void iwl_mvm_sta_pm_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
1422void iwl_mvm_window_status_notif(struct iwl_mvm *mvm, 1422void iwl_mvm_window_status_notif(struct iwl_mvm *mvm,
1423 struct iwl_rx_cmd_buffer *rxb); 1423 struct iwl_rx_cmd_buffer *rxb);
1424void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, 1424void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 4d35deb628bc..f14aada390c5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -306,6 +306,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
306 iwl_mvm_rx_stored_beacon_notif, RX_HANDLER_SYNC), 306 iwl_mvm_rx_stored_beacon_notif, RX_HANDLER_SYNC),
307 RX_HANDLER_GRP(DATA_PATH_GROUP, MU_GROUP_MGMT_NOTIF, 307 RX_HANDLER_GRP(DATA_PATH_GROUP, MU_GROUP_MGMT_NOTIF,
308 iwl_mvm_mu_mimo_grp_notif, RX_HANDLER_SYNC), 308 iwl_mvm_mu_mimo_grp_notif, RX_HANDLER_SYNC),
309 RX_HANDLER_GRP(DATA_PATH_GROUP, STA_PM_NOTIF,
310 iwl_mvm_sta_pm_notif, RX_HANDLER_SYNC),
309}; 311};
310#undef RX_HANDLER 312#undef RX_HANDLER
311#undef RX_HANDLER_GRP 313#undef RX_HANDLER_GRP
@@ -452,6 +454,7 @@ static const struct iwl_hcmd_names iwl_mvm_phy_names[] = {
452static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = { 454static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
453 HCMD_NAME(UPDATE_MU_GROUPS_CMD), 455 HCMD_NAME(UPDATE_MU_GROUPS_CMD),
454 HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD), 456 HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD),
457 HCMD_NAME(STA_PM_NOTIF),
455 HCMD_NAME(MU_GROUP_MGMT_NOTIF), 458 HCMD_NAME(MU_GROUP_MGMT_NOTIF),
456 HCMD_NAME(RX_QUEUES_NOTIFICATION), 459 HCMD_NAME(RX_QUEUES_NOTIFICATION),
457}; 460};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index fc771885e383..636c8b03e318 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -202,6 +202,20 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
202 cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT); 202 cpu_to_le32(agg_size << STA_FLG_MAX_AGG_SIZE_SHIFT);
203 add_sta_cmd.station_flags |= 203 add_sta_cmd.station_flags |=
204 cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT); 204 cpu_to_le32(mpdu_dens << STA_FLG_AGG_MPDU_DENS_SHIFT);
205 add_sta_cmd.assoc_id = cpu_to_le16(sta->aid);
206
207 if (sta->wme) {
208 add_sta_cmd.modify_mask |= STA_MODIFY_UAPSD_ACS;
209
210 if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
211 add_sta_cmd.uapsd_trigger_acs |= BIT(AC_BK);
212 if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
213 add_sta_cmd.uapsd_trigger_acs |= BIT(AC_BE);
214 if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
215 add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VI);
216 if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
217 add_sta_cmd.uapsd_trigger_acs |= BIT(AC_VO);
218 }
205 219
206 status = ADD_STA_SUCCESS; 220 status = ADD_STA_SUCCESS;
207 ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, 221 ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA,
@@ -875,12 +889,17 @@ static void iwl_mvm_change_queue_owner(struct iwl_mvm *mvm, int queue)
875 cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]]; 889 cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]];
876 890
877 ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd); 891 ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd);
878 if (ret) 892 if (ret) {
879 IWL_ERR(mvm, "Failed to update owner of TXQ %d (ret=%d)\n", 893 IWL_ERR(mvm, "Failed to update owner of TXQ %d (ret=%d)\n",
880 queue, ret); 894 queue, ret);
881 else 895 return;
882 IWL_DEBUG_TX_QUEUES(mvm, "Changed TXQ %d ownership to tid %d\n", 896 }
883 queue, tid); 897
898 spin_lock_bh(&mvm->queue_info_lock);
899 mvm->queue_info[queue].txq_tid = tid;
900 spin_unlock_bh(&mvm->queue_info_lock);
901 IWL_DEBUG_TX_QUEUES(mvm, "Changed TXQ %d ownership to tid %d\n",
902 queue, tid);
884} 903}
885 904
886static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue) 905static void iwl_mvm_unshare_queue(struct iwl_mvm *mvm, int queue)
@@ -1010,6 +1029,7 @@ static void iwl_mvm_tx_deferred_stream(struct iwl_mvm *mvm,
1010 local_bh_disable(); 1029 local_bh_disable();
1011 spin_lock(&mvmsta->lock); 1030 spin_lock(&mvmsta->lock);
1012 skb_queue_splice_init(&tid_data->deferred_tx_frames, &deferred_tx); 1031 skb_queue_splice_init(&tid_data->deferred_tx_frames, &deferred_tx);
1032 mvmsta->deferred_traffic_tid_map &= ~BIT(tid);
1013 spin_unlock(&mvmsta->lock); 1033 spin_unlock(&mvmsta->lock);
1014 1034
1015 while ((skb = __skb_dequeue(&deferred_tx))) 1035 while ((skb = __skb_dequeue(&deferred_tx)))
@@ -1489,12 +1509,15 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
1489 ret = iwl_mvm_drain_sta(mvm, mvm_sta, false); 1509 ret = iwl_mvm_drain_sta(mvm, mvm_sta, false);
1490 1510
1491 /* If DQA is supported - the queues can be disabled now */ 1511 /* If DQA is supported - the queues can be disabled now */
1492 if (iwl_mvm_is_dqa_supported(mvm)) { 1512 if (iwl_mvm_is_dqa_supported(mvm))
1513 iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta);
1514
1515 /* If there is a TXQ still marked as reserved - free it */
1516 if (iwl_mvm_is_dqa_supported(mvm) &&
1517 mvm_sta->reserved_queue != IEEE80211_INVAL_HW_QUEUE) {
1493 u8 reserved_txq = mvm_sta->reserved_queue; 1518 u8 reserved_txq = mvm_sta->reserved_queue;
1494 enum iwl_mvm_queue_status *status; 1519 enum iwl_mvm_queue_status *status;
1495 1520
1496 iwl_mvm_disable_sta_queues(mvm, vif, mvm_sta);
1497
1498 /* 1521 /*
1499 * If no traffic has gone through the reserved TXQ - it 1522 * If no traffic has gone through the reserved TXQ - it
1500 * is still marked as IWL_MVM_QUEUE_RESERVED, and 1523 * is still marked as IWL_MVM_QUEUE_RESERVED, and
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index e068d5355865..b45c7b9937c8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -436,6 +436,7 @@ struct iwl_mvm_sta {
436 436
437 bool disable_tx; 437 bool disable_tx;
438 bool tlc_amsdu; 438 bool tlc_amsdu;
439 bool sleeping;
439 u8 agg_tids; 440 u8 agg_tids;
440 u8 sleep_tx_count; 441 u8 sleep_tx_count;
441 u8 avg_energy; 442 u8 avg_energy;
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index ae95533e587d..b10e3633df1a 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1598,6 +1598,29 @@ static void iwl_pcie_irq_set_affinity(struct iwl_trans *trans)
1598 } 1598 }
1599} 1599}
1600 1600
1601static const char *queue_name(struct device *dev,
1602 struct iwl_trans_pcie *trans_p, int i)
1603{
1604 if (trans_p->shared_vec_mask) {
1605 int vec = trans_p->shared_vec_mask &
1606 IWL_SHARED_IRQ_FIRST_RSS ? 1 : 0;
1607
1608 if (i == 0)
1609 return DRV_NAME ": shared IRQ";
1610
1611 return devm_kasprintf(dev, GFP_KERNEL,
1612 DRV_NAME ": queue %d", i + vec);
1613 }
1614 if (i == 0)
1615 return DRV_NAME ": default queue";
1616
1617 if (i == trans_p->alloc_vecs - 1)
1618 return DRV_NAME ": exception";
1619
1620 return devm_kasprintf(dev, GFP_KERNEL,
1621 DRV_NAME ": queue %d", i);
1622}
1623
1601static int iwl_pcie_init_msix_handler(struct pci_dev *pdev, 1624static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
1602 struct iwl_trans_pcie *trans_pcie) 1625 struct iwl_trans_pcie *trans_pcie)
1603{ 1626{
@@ -1606,6 +1629,10 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
1606 for (i = 0; i < trans_pcie->alloc_vecs; i++) { 1629 for (i = 0; i < trans_pcie->alloc_vecs; i++) {
1607 int ret; 1630 int ret;
1608 struct msix_entry *msix_entry; 1631 struct msix_entry *msix_entry;
1632 const char *qname = queue_name(&pdev->dev, trans_pcie, i);
1633
1634 if (!qname)
1635 return -ENOMEM;
1609 1636
1610 msix_entry = &trans_pcie->msix_entries[i]; 1637 msix_entry = &trans_pcie->msix_entries[i];
1611 ret = devm_request_threaded_irq(&pdev->dev, 1638 ret = devm_request_threaded_irq(&pdev->dev,
@@ -1615,7 +1642,7 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
1615 iwl_pcie_irq_msix_handler : 1642 iwl_pcie_irq_msix_handler :
1616 iwl_pcie_irq_rx_msix_handler, 1643 iwl_pcie_irq_rx_msix_handler,
1617 IRQF_SHARED, 1644 IRQF_SHARED,
1618 DRV_NAME, 1645 qname,
1619 msix_entry); 1646 msix_entry);
1620 if (ret) { 1647 if (ret) {
1621 IWL_ERR(trans_pcie->trans, 1648 IWL_ERR(trans_pcie->trans,