]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.18.3/iwlwifi-dvm-fix-flush-support-for-old-firmware.patch
Fixes for 4.19
[thirdparty/kernel/stable-queue.git] / releases / 3.18.3 / iwlwifi-dvm-fix-flush-support-for-old-firmware.patch
1 From 5a12a07e4495d1e4d79382e05c9d6e8b4d9fa4ec Mon Sep 17 00:00:00 2001
2 From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
3 Date: Mon, 1 Dec 2014 09:34:13 +0200
4 Subject: iwlwifi: dvm: fix flush support for old firmware
5
6 From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
7
8 commit 5a12a07e4495d1e4d79382e05c9d6e8b4d9fa4ec upstream.
9
10 Since the commit below, iwldvm sends the FLUSH command to
11 the firmware. All the devices that use iwldvm have a
12 firmware that expects the _v3 version of this command,
13 besides 5150.
14 5150's latest available firmware still expects a _v2 version
15 of the FLUSH command.
16 This means that since the commit below, we had a mismatch for
17 this specific device only.
18 This mismatch led to the NMI below:
19
20 Loaded firmware version: 8.24.2.2
21 Start IWL Error Log Dump:
22 Status: 0x0000004C, count: 5
23 0x00000004 | NMI_INTERRUPT_WDG
24 0x000006F4 | uPc
25 0x000005BA | branchlink1
26 0x000006F8 | branchlink2
27 0x000008C2 | interruptlink1
28 0x00005B02 | interruptlink2
29 0x00000002 | data1
30 0x07030000 | data2
31 0x00000068 | line
32 0x3E80510C | beacon time
33 0x728A0EF4 | tsf low
34 0x0000002A | tsf hi
35 0x00000000 | time gp1
36 0x01BDC977 | time gp2
37 0x00000000 | time gp3
38 0x00010818 | uCode version
39 0x00000000 | hw version
40 0x00484704 | board version
41 0x00000002 | hcmd
42 0x2FF23080 | isr0
43 0x0103E000 | isr1
44 0x0000001A | isr2
45 0x1443FCC3 | isr3
46 0x11800112 | isr4
47 0x00000068 | isr_pref
48 0x000000D4 | wait_event
49 0x00000000 | l2p_control
50 0x00000007 | l2p_duration
51 0x00103040 | l2p_mhvalid
52 0x00000007 | l2p_addr_match
53 0x00000000 | lmpm_pmg_sel
54 0x00000000 | timestamp
55 0x00000200 | flow_handler
56
57 This was reported here:
58 https://bugzilla.kernel.org/show_bug.cgi?id=88961
59
60 Fixes: a0855054e59b ("iwlwifi: dvm: drop non VO frames when flushing")
61 Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
62 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
63
64 ---
65 drivers/net/wireless/iwlwifi/dvm/commands.h | 31 +++++++++++--------
66 drivers/net/wireless/iwlwifi/dvm/lib.c | 45 ++++++++++++++--------------
67 2 files changed, 41 insertions(+), 35 deletions(-)
68
69 --- a/drivers/net/wireless/iwlwifi/dvm/commands.h
70 +++ b/drivers/net/wireless/iwlwifi/dvm/commands.h
71 @@ -966,21 +966,21 @@ struct iwl_rem_sta_cmd {
72
73
74 /* WiFi queues mask */
75 -#define IWL_SCD_BK_MSK cpu_to_le32(BIT(0))
76 -#define IWL_SCD_BE_MSK cpu_to_le32(BIT(1))
77 -#define IWL_SCD_VI_MSK cpu_to_le32(BIT(2))
78 -#define IWL_SCD_VO_MSK cpu_to_le32(BIT(3))
79 -#define IWL_SCD_MGMT_MSK cpu_to_le32(BIT(3))
80 +#define IWL_SCD_BK_MSK BIT(0)
81 +#define IWL_SCD_BE_MSK BIT(1)
82 +#define IWL_SCD_VI_MSK BIT(2)
83 +#define IWL_SCD_VO_MSK BIT(3)
84 +#define IWL_SCD_MGMT_MSK BIT(3)
85
86 /* PAN queues mask */
87 -#define IWL_PAN_SCD_BK_MSK cpu_to_le32(BIT(4))
88 -#define IWL_PAN_SCD_BE_MSK cpu_to_le32(BIT(5))
89 -#define IWL_PAN_SCD_VI_MSK cpu_to_le32(BIT(6))
90 -#define IWL_PAN_SCD_VO_MSK cpu_to_le32(BIT(7))
91 -#define IWL_PAN_SCD_MGMT_MSK cpu_to_le32(BIT(7))
92 -#define IWL_PAN_SCD_MULTICAST_MSK cpu_to_le32(BIT(8))
93 +#define IWL_PAN_SCD_BK_MSK BIT(4)
94 +#define IWL_PAN_SCD_BE_MSK BIT(5)
95 +#define IWL_PAN_SCD_VI_MSK BIT(6)
96 +#define IWL_PAN_SCD_VO_MSK BIT(7)
97 +#define IWL_PAN_SCD_MGMT_MSK BIT(7)
98 +#define IWL_PAN_SCD_MULTICAST_MSK BIT(8)
99
100 -#define IWL_AGG_TX_QUEUE_MSK cpu_to_le32(0xffc00)
101 +#define IWL_AGG_TX_QUEUE_MSK 0xffc00
102
103 #define IWL_DROP_ALL BIT(1)
104
105 @@ -1005,12 +1005,17 @@ struct iwl_rem_sta_cmd {
106 * 1: Dump multiple MSDU according to PS, INVALID STA, TTL, TID disable.
107 * 2: Dump all FIFO
108 */
109 -struct iwl_txfifo_flush_cmd {
110 +struct iwl_txfifo_flush_cmd_v3 {
111 __le32 queue_control;
112 __le16 flush_control;
113 __le16 reserved;
114 } __packed;
115
116 +struct iwl_txfifo_flush_cmd_v2 {
117 + __le16 queue_control;
118 + __le16 flush_control;
119 +} __packed;
120 +
121 /*
122 * REPLY_WEP_KEY = 0x20
123 */
124 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c
125 +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
126 @@ -137,37 +137,38 @@ int iwlagn_manage_ibss_station(struct iw
127 */
128 int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk)
129 {
130 - struct iwl_txfifo_flush_cmd flush_cmd;
131 - struct iwl_host_cmd cmd = {
132 - .id = REPLY_TXFIFO_FLUSH,
133 - .len = { sizeof(struct iwl_txfifo_flush_cmd), },
134 - .data = { &flush_cmd, },
135 + struct iwl_txfifo_flush_cmd_v3 flush_cmd_v3 = {
136 + .flush_control = cpu_to_le16(IWL_DROP_ALL),
137 + };
138 + struct iwl_txfifo_flush_cmd_v2 flush_cmd_v2 = {
139 + .flush_control = cpu_to_le16(IWL_DROP_ALL),
140 };
141
142 - memset(&flush_cmd, 0, sizeof(flush_cmd));
143 + u32 queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
144 + IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | IWL_SCD_MGMT_MSK;
145
146 - flush_cmd.queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
147 - IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
148 - IWL_SCD_MGMT_MSK;
149 if ((priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
150 - flush_cmd.queue_control |= IWL_PAN_SCD_VO_MSK |
151 - IWL_PAN_SCD_VI_MSK |
152 - IWL_PAN_SCD_BE_MSK |
153 - IWL_PAN_SCD_BK_MSK |
154 - IWL_PAN_SCD_MGMT_MSK |
155 - IWL_PAN_SCD_MULTICAST_MSK;
156 + queue_control |= IWL_PAN_SCD_VO_MSK | IWL_PAN_SCD_VI_MSK |
157 + IWL_PAN_SCD_BE_MSK | IWL_PAN_SCD_BK_MSK |
158 + IWL_PAN_SCD_MGMT_MSK |
159 + IWL_PAN_SCD_MULTICAST_MSK;
160
161 if (priv->nvm_data->sku_cap_11n_enable)
162 - flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK;
163 + queue_control |= IWL_AGG_TX_QUEUE_MSK;
164
165 if (scd_q_msk)
166 - flush_cmd.queue_control = cpu_to_le32(scd_q_msk);
167 -
168 - IWL_DEBUG_INFO(priv, "queue control: 0x%x\n",
169 - flush_cmd.queue_control);
170 - flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL);
171 + queue_control = scd_q_msk;
172
173 - return iwl_dvm_send_cmd(priv, &cmd);
174 + IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", queue_control);
175 + flush_cmd_v3.queue_control = cpu_to_le32(queue_control);
176 + flush_cmd_v2.queue_control = cpu_to_le16((u16)queue_control);
177 +
178 + if (IWL_UCODE_API(priv->fw->ucode_ver) > 2)
179 + return iwl_dvm_send_cmd_pdu(priv, REPLY_TXFIFO_FLUSH, 0,
180 + sizeof(flush_cmd_v3),
181 + &flush_cmd_v3);
182 + return iwl_dvm_send_cmd_pdu(priv, REPLY_TXFIFO_FLUSH, 0,
183 + sizeof(flush_cmd_v2), &flush_cmd_v2);
184 }
185
186 void iwlagn_dev_txfifo_flush(struct iwl_priv *priv)