diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/bt-coex.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/bt-coex.c | 638 |
1 files changed, 475 insertions, 163 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c index 0fad98b85f60..5d066cbc5ac7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/bt-coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/bt-coex.c | |||
@@ -98,126 +98,258 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { | |||
98 | 98 | ||
99 | #undef EVENT_PRIO_ANT | 99 | #undef EVENT_PRIO_ANT |
100 | 100 | ||
101 | /* BT Antenna Coupling Threshold (dB) */ | ||
102 | #define IWL_BT_ANTENNA_COUPLING_THRESHOLD (35) | ||
103 | #define IWL_BT_LOAD_FORCE_SISO_THRESHOLD (3) | ||
104 | |||
105 | #define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62) | 101 | #define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62) |
106 | #define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65) | 102 | #define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65) |
107 | #define BT_REDUCED_TX_POWER_BIT BIT(7) | 103 | #define BT_ANTENNA_COUPLING_THRESHOLD (30) |
108 | |||
109 | static inline bool is_loose_coex(void) | ||
110 | { | ||
111 | return iwlwifi_mod_params.ant_coupling > | ||
112 | IWL_BT_ANTENNA_COUPLING_THRESHOLD; | ||
113 | } | ||
114 | 104 | ||
115 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) | 105 | int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) |
116 | { | 106 | { |
107 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) | ||
108 | return 0; | ||
109 | |||
117 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC, | 110 | return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC, |
118 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), | 111 | sizeof(struct iwl_bt_coex_prio_tbl_cmd), |
119 | &iwl_bt_prio_tbl); | 112 | &iwl_bt_prio_tbl); |
120 | } | 113 | } |
121 | 114 | ||
122 | static int iwl_send_bt_env(struct iwl_mvm *mvm, u8 action, u8 type) | 115 | const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { |
123 | { | ||
124 | struct iwl_bt_coex_prot_env_cmd env_cmd; | ||
125 | int ret; | ||
126 | |||
127 | env_cmd.action = action; | ||
128 | env_cmd.type = type; | ||
129 | ret = iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PROT_ENV, CMD_SYNC, | ||
130 | sizeof(env_cmd), &env_cmd); | ||
131 | if (ret) | ||
132 | IWL_ERR(mvm, "failed to send BT env command\n"); | ||
133 | return ret; | ||
134 | } | ||
135 | |||
136 | enum iwl_bt_kill_msk { | ||
137 | BT_KILL_MSK_DEFAULT, | ||
138 | BT_KILL_MSK_SCO_HID_A2DP, | ||
139 | BT_KILL_MSK_REDUCED_TXPOW, | ||
140 | BT_KILL_MSK_MAX, | ||
141 | }; | ||
142 | |||
143 | static const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = { | ||
144 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, | 116 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, |
145 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, | 117 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, |
146 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, | 118 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, |
147 | }; | 119 | }; |
148 | 120 | ||
149 | static const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { | 121 | const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = { |
150 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, | 122 | [BT_KILL_MSK_DEFAULT] = 0xffff0000, |
151 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, | 123 | [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff, |
152 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, | 124 | [BT_KILL_MSK_REDUCED_TXPOW] = 0, |
153 | }; | 125 | }; |
154 | 126 | ||
155 | #define IWL_BT_DEFAULT_BOOST (0xf0f0f0f0) | 127 | static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = { |
156 | 128 | cpu_to_le32(0xf0f0f0f0), | |
157 | /* Tight Coex */ | 129 | cpu_to_le32(0xc0c0c0c0), |
158 | static const __le32 iwl_tight_lookup[BT_COEX_LUT_SIZE] = { | 130 | cpu_to_le32(0xfcfcfcfc), |
159 | cpu_to_le32(0xaaaaaaaa), | 131 | cpu_to_le32(0xff00ff00), |
160 | cpu_to_le32(0xaaaaaaaa), | ||
161 | cpu_to_le32(0xaeaaaaaa), | ||
162 | cpu_to_le32(0xaaaaaaaa), | ||
163 | cpu_to_le32(0xcc00ff28), | ||
164 | cpu_to_le32(0x0000aaaa), | ||
165 | cpu_to_le32(0xcc00aaaa), | ||
166 | cpu_to_le32(0x0000aaaa), | ||
167 | cpu_to_le32(0xc0004000), | ||
168 | cpu_to_le32(0x00000000), | ||
169 | cpu_to_le32(0xf0005000), | ||
170 | cpu_to_le32(0xf0005000), | ||
171 | }; | 132 | }; |
172 | 133 | ||
173 | /* Loose Coex */ | 134 | static const __le32 iwl_single_shared_ant[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { |
174 | static const __le32 iwl_loose_lookup[BT_COEX_LUT_SIZE] = { | 135 | { |
175 | cpu_to_le32(0xaaaaaaaa), | 136 | cpu_to_le32(0x40000000), |
176 | cpu_to_le32(0xaaaaaaaa), | 137 | cpu_to_le32(0x00000000), |
177 | cpu_to_le32(0xaaaaaaaa), | 138 | cpu_to_le32(0x44000000), |
178 | cpu_to_le32(0xaaaaaaaa), | 139 | cpu_to_le32(0x00000000), |
179 | cpu_to_le32(0xcc00ff28), | 140 | cpu_to_le32(0x40000000), |
180 | cpu_to_le32(0x0000aaaa), | 141 | cpu_to_le32(0x00000000), |
181 | cpu_to_le32(0xcc00aaaa), | 142 | cpu_to_le32(0x44000000), |
182 | cpu_to_le32(0x0000aaaa), | 143 | cpu_to_le32(0x00000000), |
183 | cpu_to_le32(0x00000000), | 144 | cpu_to_le32(0xc0004000), |
184 | cpu_to_le32(0x00000000), | 145 | cpu_to_le32(0xf0005000), |
185 | cpu_to_le32(0xf0005000), | 146 | cpu_to_le32(0xc0004000), |
186 | cpu_to_le32(0xf0005000), | 147 | cpu_to_le32(0xf0005000), |
148 | }, | ||
149 | { | ||
150 | cpu_to_le32(0x40000000), | ||
151 | cpu_to_le32(0x00000000), | ||
152 | cpu_to_le32(0x44000000), | ||
153 | cpu_to_le32(0x00000000), | ||
154 | cpu_to_le32(0x40000000), | ||
155 | cpu_to_le32(0x00000000), | ||
156 | cpu_to_le32(0x44000000), | ||
157 | cpu_to_le32(0x00000000), | ||
158 | cpu_to_le32(0xc0004000), | ||
159 | cpu_to_le32(0xf0005000), | ||
160 | cpu_to_le32(0xc0004000), | ||
161 | cpu_to_le32(0xf0005000), | ||
162 | }, | ||
163 | { | ||
164 | cpu_to_le32(0x40000000), | ||
165 | cpu_to_le32(0x00000000), | ||
166 | cpu_to_le32(0x44000000), | ||
167 | cpu_to_le32(0x00000000), | ||
168 | cpu_to_le32(0x40000000), | ||
169 | cpu_to_le32(0x00000000), | ||
170 | cpu_to_le32(0x44000000), | ||
171 | cpu_to_le32(0x00000000), | ||
172 | cpu_to_le32(0xc0004000), | ||
173 | cpu_to_le32(0xf0005000), | ||
174 | cpu_to_le32(0xc0004000), | ||
175 | cpu_to_le32(0xf0005000), | ||
176 | }, | ||
187 | }; | 177 | }; |
188 | 178 | ||
189 | /* Full concurrency */ | 179 | static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { |
190 | static const __le32 iwl_concurrent_lookup[BT_COEX_LUT_SIZE] = { | 180 | { |
191 | cpu_to_le32(0xaaaaaaaa), | 181 | /* Tight */ |
192 | cpu_to_le32(0xaaaaaaaa), | 182 | cpu_to_le32(0xaaaaaaaa), |
193 | cpu_to_le32(0xaaaaaaaa), | 183 | cpu_to_le32(0xaaaaaaaa), |
194 | cpu_to_le32(0xaaaaaaaa), | 184 | cpu_to_le32(0xaeaaaaaa), |
195 | cpu_to_le32(0xaaaaaaaa), | 185 | cpu_to_le32(0xaaaaaaaa), |
196 | cpu_to_le32(0xaaaaaaaa), | 186 | cpu_to_le32(0xcc00ff28), |
197 | cpu_to_le32(0xaaaaaaaa), | 187 | cpu_to_le32(0x0000aaaa), |
198 | cpu_to_le32(0xaaaaaaaa), | 188 | cpu_to_le32(0xcc00aaaa), |
199 | cpu_to_le32(0x00000000), | 189 | cpu_to_le32(0x0000aaaa), |
200 | cpu_to_le32(0x00000000), | 190 | cpu_to_le32(0xc0004000), |
201 | cpu_to_le32(0x00000000), | 191 | cpu_to_le32(0x00000000), |
202 | cpu_to_le32(0x00000000), | 192 | cpu_to_le32(0xf0005000), |
193 | cpu_to_le32(0xf0005000), | ||
194 | }, | ||
195 | { | ||
196 | /* Loose */ | ||
197 | cpu_to_le32(0xaaaaaaaa), | ||
198 | cpu_to_le32(0xaaaaaaaa), | ||
199 | cpu_to_le32(0xaaaaaaaa), | ||
200 | cpu_to_le32(0xaaaaaaaa), | ||
201 | cpu_to_le32(0xcc00ff28), | ||
202 | cpu_to_le32(0x0000aaaa), | ||
203 | cpu_to_le32(0xcc00aaaa), | ||
204 | cpu_to_le32(0x0000aaaa), | ||
205 | cpu_to_le32(0x00000000), | ||
206 | cpu_to_le32(0x00000000), | ||
207 | cpu_to_le32(0xf0005000), | ||
208 | cpu_to_le32(0xf0005000), | ||
209 | }, | ||
210 | { | ||
211 | /* Tx Tx disabled */ | ||
212 | cpu_to_le32(0xaaaaaaaa), | ||
213 | cpu_to_le32(0xaaaaaaaa), | ||
214 | cpu_to_le32(0xaaaaaaaa), | ||
215 | cpu_to_le32(0xaaaaaaaa), | ||
216 | cpu_to_le32(0xcc00ff28), | ||
217 | cpu_to_le32(0x0000aaaa), | ||
218 | cpu_to_le32(0xcc00aaaa), | ||
219 | cpu_to_le32(0x0000aaaa), | ||
220 | cpu_to_le32(0xC0004000), | ||
221 | cpu_to_le32(0xC0004000), | ||
222 | cpu_to_le32(0xF0005000), | ||
223 | cpu_to_le32(0xF0005000), | ||
224 | }, | ||
203 | }; | 225 | }; |
204 | 226 | ||
205 | /* single shared antenna */ | 227 | /* 20MHz / 40MHz below / 40Mhz above*/ |
206 | static const __le32 iwl_single_shared_ant_lookup[BT_COEX_LUT_SIZE] = { | 228 | static const __le64 iwl_ci_mask[][3] = { |
207 | cpu_to_le32(0x40000000), | 229 | /* dummy entry for channel 0 */ |
208 | cpu_to_le32(0x00000000), | 230 | {cpu_to_le64(0), cpu_to_le64(0), cpu_to_le64(0)}, |
209 | cpu_to_le32(0x44000000), | 231 | { |
210 | cpu_to_le32(0x00000000), | 232 | cpu_to_le64(0x0000001FFFULL), |
211 | cpu_to_le32(0x40000000), | 233 | cpu_to_le64(0x0ULL), |
212 | cpu_to_le32(0x00000000), | 234 | cpu_to_le64(0x00007FFFFFULL), |
213 | cpu_to_le32(0x44000000), | 235 | }, |
214 | cpu_to_le32(0x00000000), | 236 | { |
215 | cpu_to_le32(0xC0004000), | 237 | cpu_to_le64(0x000000FFFFULL), |
216 | cpu_to_le32(0xF0005000), | 238 | cpu_to_le64(0x0ULL), |
217 | cpu_to_le32(0xC0004000), | 239 | cpu_to_le64(0x0003FFFFFFULL), |
218 | cpu_to_le32(0xF0005000), | 240 | }, |
241 | { | ||
242 | cpu_to_le64(0x000003FFFCULL), | ||
243 | cpu_to_le64(0x0ULL), | ||
244 | cpu_to_le64(0x000FFFFFFCULL), | ||
245 | }, | ||
246 | { | ||
247 | cpu_to_le64(0x00001FFFE0ULL), | ||
248 | cpu_to_le64(0x0ULL), | ||
249 | cpu_to_le64(0x007FFFFFE0ULL), | ||
250 | }, | ||
251 | { | ||
252 | cpu_to_le64(0x00007FFF80ULL), | ||
253 | cpu_to_le64(0x00007FFFFFULL), | ||
254 | cpu_to_le64(0x01FFFFFF80ULL), | ||
255 | }, | ||
256 | { | ||
257 | cpu_to_le64(0x0003FFFC00ULL), | ||
258 | cpu_to_le64(0x0003FFFFFFULL), | ||
259 | cpu_to_le64(0x0FFFFFFC00ULL), | ||
260 | }, | ||
261 | { | ||
262 | cpu_to_le64(0x000FFFF000ULL), | ||
263 | cpu_to_le64(0x000FFFFFFCULL), | ||
264 | cpu_to_le64(0x3FFFFFF000ULL), | ||
265 | }, | ||
266 | { | ||
267 | cpu_to_le64(0x007FFF8000ULL), | ||
268 | cpu_to_le64(0x007FFFFFE0ULL), | ||
269 | cpu_to_le64(0xFFFFFF8000ULL), | ||
270 | }, | ||
271 | { | ||
272 | cpu_to_le64(0x01FFFE0000ULL), | ||
273 | cpu_to_le64(0x01FFFFFF80ULL), | ||
274 | cpu_to_le64(0xFFFFFE0000ULL), | ||
275 | }, | ||
276 | { | ||
277 | cpu_to_le64(0x0FFFF00000ULL), | ||
278 | cpu_to_le64(0x0FFFFFFC00ULL), | ||
279 | cpu_to_le64(0x0ULL), | ||
280 | }, | ||
281 | { | ||
282 | cpu_to_le64(0x3FFFC00000ULL), | ||
283 | cpu_to_le64(0x3FFFFFF000ULL), | ||
284 | cpu_to_le64(0x0) | ||
285 | }, | ||
286 | { | ||
287 | cpu_to_le64(0xFFFE000000ULL), | ||
288 | cpu_to_le64(0xFFFFFF8000ULL), | ||
289 | cpu_to_le64(0x0) | ||
290 | }, | ||
291 | { | ||
292 | cpu_to_le64(0xFFF8000000ULL), | ||
293 | cpu_to_le64(0xFFFFFE0000ULL), | ||
294 | cpu_to_le64(0x0) | ||
295 | }, | ||
296 | { | ||
297 | cpu_to_le64(0xFE00000000ULL), | ||
298 | cpu_to_le64(0x0ULL), | ||
299 | cpu_to_le64(0x0) | ||
300 | }, | ||
219 | }; | 301 | }; |
220 | 302 | ||
303 | static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = { | ||
304 | cpu_to_le32(0x22002200), | ||
305 | cpu_to_le32(0x33113311), | ||
306 | }; | ||
307 | |||
308 | static enum iwl_bt_coex_lut_type | ||
309 | iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif) | ||
310 | { | ||
311 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
312 | enum iwl_bt_coex_lut_type ret; | ||
313 | u16 phy_ctx_id; | ||
314 | |||
315 | /* | ||
316 | * Checking that we hold mvm->mutex is a good idea, but the rate | ||
317 | * control can't acquire the mutex since it runs in Tx path. | ||
318 | * So this is racy in that case, but in the worst case, the AMPDU | ||
319 | * size limit will be wrong for a short time which is not a big | ||
320 | * issue. | ||
321 | */ | ||
322 | |||
323 | rcu_read_lock(); | ||
324 | |||
325 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
326 | |||
327 | if (!chanctx_conf || | ||
328 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) { | ||
329 | rcu_read_unlock(); | ||
330 | return BT_COEX_LOOSE_LUT; | ||
331 | } | ||
332 | |||
333 | ret = BT_COEX_TX_DIS_LUT; | ||
334 | |||
335 | if (mvm->cfg->bt_shared_single_ant) { | ||
336 | rcu_read_unlock(); | ||
337 | return ret; | ||
338 | } | ||
339 | |||
340 | phy_ctx_id = *((u16 *)chanctx_conf->drv_priv); | ||
341 | |||
342 | if (mvm->last_bt_ci_cmd.primary_ch_phy_id == phy_ctx_id) | ||
343 | ret = le32_to_cpu(mvm->last_bt_notif.primary_ch_lut); | ||
344 | else if (mvm->last_bt_ci_cmd.secondary_ch_phy_id == phy_ctx_id) | ||
345 | ret = le32_to_cpu(mvm->last_bt_notif.secondary_ch_lut); | ||
346 | /* else - default = TX TX disallowed */ | ||
347 | |||
348 | rcu_read_unlock(); | ||
349 | |||
350 | return ret; | ||
351 | } | ||
352 | |||
221 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | 353 | int iwl_send_bt_init_conf(struct iwl_mvm *mvm) |
222 | { | 354 | { |
223 | struct iwl_bt_coex_cmd *bt_cmd; | 355 | struct iwl_bt_coex_cmd *bt_cmd; |
@@ -228,17 +360,10 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
228 | .flags = CMD_SYNC, | 360 | .flags = CMD_SYNC, |
229 | }; | 361 | }; |
230 | int ret; | 362 | int ret; |
363 | u32 flags; | ||
231 | 364 | ||
232 | /* go to CALIB state in internal BT-Coex state machine */ | 365 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) |
233 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_OPEN, | 366 | return 0; |
234 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
235 | if (ret) | ||
236 | return ret; | ||
237 | |||
238 | ret = iwl_send_bt_env(mvm, BT_COEX_ENV_CLOSE, | ||
239 | BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); | ||
240 | if (ret) | ||
241 | return ret; | ||
242 | 367 | ||
243 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); | 368 | bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL); |
244 | if (!bt_cmd) | 369 | if (!bt_cmd) |
@@ -246,40 +371,52 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
246 | cmd.data[0] = bt_cmd; | 371 | cmd.data[0] = bt_cmd; |
247 | 372 | ||
248 | bt_cmd->max_kill = 5; | 373 | bt_cmd->max_kill = 5; |
249 | bt_cmd->bt3_time_t7_value = 1; | 374 | bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD, |
250 | bt_cmd->bt3_prio_sample_time = 2; | 375 | bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling, |
251 | bt_cmd->bt3_timer_t2_value = 0xc; | 376 | bt_cmd->bt4_tx_tx_delta_freq_thr = 15, |
377 | bt_cmd->bt4_tx_rx_max_freq0 = 15, | ||
252 | 378 | ||
253 | bt_cmd->flags = iwlwifi_mod_params.bt_coex_active ? | 379 | flags = iwlwifi_mod_params.bt_coex_active ? |
254 | BT_COEX_NW : BT_COEX_DISABLE; | 380 | BT_COEX_NW : BT_COEX_DISABLE; |
255 | bt_cmd->flags |= BT_CH_PRIMARY_EN | BT_SYNC_2_BT_DISABLE; | 381 | flags |= BT_CH_PRIMARY_EN | BT_CH_SECONDARY_EN | BT_SYNC_2_BT_DISABLE; |
382 | bt_cmd->flags = cpu_to_le32(flags); | ||
256 | 383 | ||
257 | bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_ENABLE | | 384 | bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE | |
258 | BT_VALID_BT_PRIO_BOOST | | 385 | BT_VALID_BT_PRIO_BOOST | |
259 | BT_VALID_MAX_KILL | | 386 | BT_VALID_MAX_KILL | |
260 | BT_VALID_3W_TMRS | | 387 | BT_VALID_3W_TMRS | |
261 | BT_VALID_KILL_ACK | | 388 | BT_VALID_KILL_ACK | |
262 | BT_VALID_KILL_CTS | | 389 | BT_VALID_KILL_CTS | |
263 | BT_VALID_REDUCED_TX_POWER | | 390 | BT_VALID_REDUCED_TX_POWER | |
264 | BT_VALID_LUT); | 391 | BT_VALID_LUT | |
392 | BT_VALID_WIFI_RX_SW_PRIO_BOOST | | ||
393 | BT_VALID_WIFI_TX_SW_PRIO_BOOST | | ||
394 | BT_VALID_MULTI_PRIO_LUT | | ||
395 | BT_VALID_CORUN_LUT_20 | | ||
396 | BT_VALID_CORUN_LUT_40 | | ||
397 | BT_VALID_ANT_ISOLATION | | ||
398 | BT_VALID_ANT_ISOLATION_THRS | | ||
399 | BT_VALID_TXTX_DELTA_FREQ_THRS | | ||
400 | BT_VALID_TXRX_MAX_FREQ_0); | ||
265 | 401 | ||
266 | if (mvm->cfg->bt_shared_single_ant) | 402 | if (mvm->cfg->bt_shared_single_ant) |
267 | memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant_lookup, | 403 | memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant, |
268 | sizeof(iwl_single_shared_ant_lookup)); | 404 | sizeof(iwl_single_shared_ant)); |
269 | else if (is_loose_coex()) | ||
270 | memcpy(&bt_cmd->decision_lut, iwl_loose_lookup, | ||
271 | sizeof(iwl_tight_lookup)); | ||
272 | else | 405 | else |
273 | memcpy(&bt_cmd->decision_lut, iwl_tight_lookup, | 406 | memcpy(&bt_cmd->decision_lut, iwl_combined_lookup, |
274 | sizeof(iwl_tight_lookup)); | 407 | sizeof(iwl_combined_lookup)); |
275 | 408 | ||
276 | bt_cmd->bt_prio_boost = cpu_to_le32(IWL_BT_DEFAULT_BOOST); | 409 | memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost, |
410 | sizeof(iwl_bt_prio_boost)); | ||
411 | memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut, | ||
412 | sizeof(iwl_bt_mprio_lut)); | ||
277 | bt_cmd->kill_ack_msk = | 413 | bt_cmd->kill_ack_msk = |
278 | cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); | 414 | cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]); |
279 | bt_cmd->kill_cts_msk = | 415 | bt_cmd->kill_cts_msk = |
280 | cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); | 416 | cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]); |
281 | 417 | ||
282 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); | 418 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); |
419 | memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd)); | ||
283 | 420 | ||
284 | ret = iwl_mvm_send_cmd(mvm, &cmd); | 421 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
285 | 422 | ||
@@ -334,13 +471,17 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm, | |||
334 | if (!bt_cmd) | 471 | if (!bt_cmd) |
335 | return -ENOMEM; | 472 | return -ENOMEM; |
336 | cmd.data[0] = bt_cmd; | 473 | cmd.data[0] = bt_cmd; |
474 | bt_cmd->flags = cpu_to_le32(BT_COEX_NW); | ||
337 | 475 | ||
338 | bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); | 476 | bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]); |
339 | bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); | 477 | bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]); |
340 | bt_cmd->valid_bit_msk = | 478 | bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE | |
341 | cpu_to_le16(BT_VALID_KILL_ACK | BT_VALID_KILL_CTS); | 479 | BT_VALID_KILL_ACK | |
480 | BT_VALID_KILL_CTS); | ||
342 | 481 | ||
343 | IWL_DEBUG_COEX(mvm, "bt_kill_msk = %d\n", bt_kill_msk); | 482 | IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n", |
483 | iwl_bt_ack_kill_msk[bt_kill_msk], | ||
484 | iwl_bt_cts_kill_msk[bt_kill_msk]); | ||
344 | 485 | ||
345 | ret = iwl_mvm_send_cmd(mvm, &cmd); | 486 | ret = iwl_mvm_send_cmd(mvm, &cmd); |
346 | 487 | ||
@@ -364,12 +505,16 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | |||
364 | struct iwl_mvm_sta *mvmsta; | 505 | struct iwl_mvm_sta *mvmsta; |
365 | int ret; | 506 | int ret; |
366 | 507 | ||
367 | /* This can happen if the station has been removed right now */ | ||
368 | if (sta_id == IWL_MVM_STATION_COUNT) | 508 | if (sta_id == IWL_MVM_STATION_COUNT) |
369 | return 0; | 509 | return 0; |
370 | 510 | ||
371 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], | 511 | sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], |
372 | lockdep_is_held(&mvm->mutex)); | 512 | lockdep_is_held(&mvm->mutex)); |
513 | |||
514 | /* This can happen if the station has been removed right now */ | ||
515 | if (IS_ERR_OR_NULL(sta)) | ||
516 | return 0; | ||
517 | |||
373 | mvmsta = (void *)sta->drv_priv; | 518 | mvmsta = (void *)sta->drv_priv; |
374 | 519 | ||
375 | /* nothing to do */ | 520 | /* nothing to do */ |
@@ -380,8 +525,10 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, | |||
380 | if (!bt_cmd) | 525 | if (!bt_cmd) |
381 | return -ENOMEM; | 526 | return -ENOMEM; |
382 | cmd.data[0] = bt_cmd; | 527 | cmd.data[0] = bt_cmd; |
528 | bt_cmd->flags = cpu_to_le32(BT_COEX_NW); | ||
383 | 529 | ||
384 | bt_cmd->valid_bit_msk = cpu_to_le16(BT_VALID_REDUCED_TX_POWER), | 530 | bt_cmd->valid_bit_msk = |
531 | cpu_to_le32(BT_VALID_ENABLE | BT_VALID_REDUCED_TX_POWER); | ||
385 | bt_cmd->bt_reduced_tx_power = sta_id; | 532 | bt_cmd->bt_reduced_tx_power = sta_id; |
386 | 533 | ||
387 | if (enable) | 534 | if (enable) |
@@ -403,8 +550,25 @@ struct iwl_bt_iterator_data { | |||
403 | struct iwl_mvm *mvm; | 550 | struct iwl_mvm *mvm; |
404 | u32 num_bss_ifaces; | 551 | u32 num_bss_ifaces; |
405 | bool reduced_tx_power; | 552 | bool reduced_tx_power; |
553 | struct ieee80211_chanctx_conf *primary; | ||
554 | struct ieee80211_chanctx_conf *secondary; | ||
406 | }; | 555 | }; |
407 | 556 | ||
557 | static inline | ||
558 | void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm, | ||
559 | struct ieee80211_vif *vif, | ||
560 | bool enable, int rssi) | ||
561 | { | ||
562 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
563 | |||
564 | mvmvif->bf_data.last_bt_coex_event = rssi; | ||
565 | mvmvif->bf_data.bt_coex_max_thold = | ||
566 | enable ? BT_ENABLE_REDUCED_TXPOWER_THRESHOLD : 0; | ||
567 | mvmvif->bf_data.bt_coex_min_thold = | ||
568 | enable ? BT_DISABLE_REDUCED_TXPOWER_THRESHOLD : 0; | ||
569 | } | ||
570 | |||
571 | /* must be called under rcu_read_lock */ | ||
408 | static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | 572 | static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, |
409 | struct ieee80211_vif *vif) | 573 | struct ieee80211_vif *vif) |
410 | { | 574 | { |
@@ -413,65 +577,94 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
413 | struct iwl_mvm *mvm = data->mvm; | 577 | struct iwl_mvm *mvm = data->mvm; |
414 | struct ieee80211_chanctx_conf *chanctx_conf; | 578 | struct ieee80211_chanctx_conf *chanctx_conf; |
415 | enum ieee80211_smps_mode smps_mode; | 579 | enum ieee80211_smps_mode smps_mode; |
416 | enum ieee80211_band band; | ||
417 | int ave_rssi; | 580 | int ave_rssi; |
418 | 581 | ||
419 | lockdep_assert_held(&mvm->mutex); | 582 | lockdep_assert_held(&mvm->mutex); |
420 | if (vif->type != NL80211_IFTYPE_STATION) | ||
421 | return; | ||
422 | 583 | ||
423 | rcu_read_lock(); | 584 | if (vif->type != NL80211_IFTYPE_STATION && |
424 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | 585 | vif->type != NL80211_IFTYPE_AP) |
425 | if (chanctx_conf && chanctx_conf->def.chan) | 586 | return; |
426 | band = chanctx_conf->def.chan->band; | ||
427 | else | ||
428 | band = -1; | ||
429 | rcu_read_unlock(); | ||
430 | 587 | ||
431 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | 588 | smps_mode = IEEE80211_SMPS_AUTOMATIC; |
432 | 589 | ||
433 | /* non associated BSSes aren't to be considered */ | 590 | chanctx_conf = rcu_dereference(vif->chanctx_conf); |
434 | if (!vif->bss_conf.assoc) | 591 | |
592 | /* If channel context is invalid or not on 2.4GHz .. */ | ||
593 | if ((!chanctx_conf || | ||
594 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) { | ||
595 | /* ... and it is an associated STATION, relax constraints */ | ||
596 | if (vif->type == NL80211_IFTYPE_STATION && vif->bss_conf.assoc) | ||
597 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | ||
598 | smps_mode); | ||
599 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); | ||
435 | return; | 600 | return; |
601 | } | ||
602 | |||
603 | /* SoftAP / GO will always be primary */ | ||
604 | if (vif->type == NL80211_IFTYPE_AP) { | ||
605 | if (!mvmvif->ap_ibss_active) | ||
606 | return; | ||
436 | 607 | ||
437 | if (band != IEEE80211_BAND_2GHZ) { | 608 | /* the Ack / Cts kill mask must be default if AP / GO */ |
438 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, | 609 | data->reduced_tx_power = false; |
439 | smps_mode); | 610 | |
611 | if (chanctx_conf == data->primary) | ||
612 | return; | ||
613 | |||
614 | /* downgrade the current primary no matter what its type is */ | ||
615 | data->secondary = data->primary; | ||
616 | data->primary = chanctx_conf; | ||
440 | return; | 617 | return; |
441 | } | 618 | } |
442 | 619 | ||
443 | if (data->notif->bt_status) | 620 | data->num_bss_ifaces++; |
444 | smps_mode = IEEE80211_SMPS_DYNAMIC; | 621 | |
622 | /* we are now a STA / P2P Client, and take associated ones only */ | ||
623 | if (!vif->bss_conf.assoc) | ||
624 | return; | ||
625 | |||
626 | /* STA / P2P Client, try to be primary if first vif */ | ||
627 | if (!data->primary || data->primary == chanctx_conf) | ||
628 | data->primary = chanctx_conf; | ||
629 | else if (!data->secondary) | ||
630 | /* if secondary is not NULL, it might be a GO */ | ||
631 | data->secondary = chanctx_conf; | ||
445 | 632 | ||
446 | if (data->notif->bt_traffic_load >= IWL_BT_LOAD_FORCE_SISO_THRESHOLD) | 633 | if (le32_to_cpu(data->notif->bt_activity_grading) >= BT_HIGH_TRAFFIC) |
447 | smps_mode = IEEE80211_SMPS_STATIC; | 634 | smps_mode = IEEE80211_SMPS_STATIC; |
635 | else if (le32_to_cpu(data->notif->bt_activity_grading) >= | ||
636 | BT_LOW_TRAFFIC) | ||
637 | smps_mode = IEEE80211_SMPS_DYNAMIC; | ||
448 | 638 | ||
449 | IWL_DEBUG_COEX(data->mvm, | 639 | IWL_DEBUG_COEX(data->mvm, |
450 | "mac %d: bt_status %d traffic_load %d smps_req %d\n", | 640 | "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n", |
451 | mvmvif->id, data->notif->bt_status, | 641 | mvmvif->id, data->notif->bt_status, |
452 | data->notif->bt_traffic_load, smps_mode); | 642 | data->notif->bt_activity_grading, smps_mode); |
453 | 643 | ||
454 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); | 644 | iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode); |
455 | 645 | ||
456 | /* don't reduce the Tx power if in loose scheme */ | 646 | /* don't reduce the Tx power if in loose scheme */ |
457 | if (is_loose_coex()) | 647 | if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT || |
648 | mvm->cfg->bt_shared_single_ant) { | ||
649 | data->reduced_tx_power = false; | ||
650 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); | ||
458 | return; | 651 | return; |
652 | } | ||
459 | 653 | ||
460 | data->num_bss_ifaces++; | 654 | /* reduced Txpower only if BT is on, so ...*/ |
461 | 655 | if (!data->notif->bt_status) { | |
462 | /* reduced Txpower only if there are open BT connections, so ...*/ | ||
463 | if (!BT_MBOX_MSG(data->notif, 3, OPEN_CON_2)) { | ||
464 | /* ... cancel reduced Tx power ... */ | 656 | /* ... cancel reduced Tx power ... */ |
465 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) | 657 | if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false)) |
466 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); | 658 | IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n"); |
467 | data->reduced_tx_power = false; | 659 | data->reduced_tx_power = false; |
468 | 660 | ||
469 | /* ... and there is no need to get reports on RSSI any more. */ | 661 | /* ... and there is no need to get reports on RSSI any more. */ |
470 | ieee80211_disable_rssi_reports(vif); | 662 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0); |
471 | return; | 663 | return; |
472 | } | 664 | } |
473 | 665 | ||
474 | ave_rssi = ieee80211_ave_rssi(vif); | 666 | /* try to get the avg rssi from fw */ |
667 | ave_rssi = mvmvif->bf_data.ave_beacon_signal; | ||
475 | 668 | ||
476 | /* if the RSSI isn't valid, fake it is very low */ | 669 | /* if the RSSI isn't valid, fake it is very low */ |
477 | if (!ave_rssi) | 670 | if (!ave_rssi) |
@@ -499,8 +692,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, | |||
499 | } | 692 | } |
500 | 693 | ||
501 | /* Begin to monitor the RSSI: it may influence the reduced Tx power */ | 694 | /* Begin to monitor the RSSI: it may influence the reduced Tx power */ |
502 | ieee80211_enable_rssi_reports(vif, BT_DISABLE_REDUCED_TXPOWER_THRESHOLD, | 695 | iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi); |
503 | BT_ENABLE_REDUCED_TXPOWER_THRESHOLD); | ||
504 | } | 696 | } |
505 | 697 | ||
506 | static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | 698 | static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) |
@@ -510,11 +702,72 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm) | |||
510 | .notif = &mvm->last_bt_notif, | 702 | .notif = &mvm->last_bt_notif, |
511 | .reduced_tx_power = true, | 703 | .reduced_tx_power = true, |
512 | }; | 704 | }; |
705 | struct iwl_bt_coex_ci_cmd cmd = {}; | ||
706 | u8 ci_bw_idx; | ||
513 | 707 | ||
708 | rcu_read_lock(); | ||
514 | ieee80211_iterate_active_interfaces_atomic( | 709 | ieee80211_iterate_active_interfaces_atomic( |
515 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | 710 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, |
516 | iwl_mvm_bt_notif_iterator, &data); | 711 | iwl_mvm_bt_notif_iterator, &data); |
517 | 712 | ||
713 | if (data.primary) { | ||
714 | struct ieee80211_chanctx_conf *chan = data.primary; | ||
715 | if (WARN_ON(!chan->def.chan)) { | ||
716 | rcu_read_unlock(); | ||
717 | return; | ||
718 | } | ||
719 | |||
720 | if (chan->def.width < NL80211_CHAN_WIDTH_40) { | ||
721 | ci_bw_idx = 0; | ||
722 | cmd.co_run_bw_primary = 0; | ||
723 | } else { | ||
724 | cmd.co_run_bw_primary = 1; | ||
725 | if (chan->def.center_freq1 > | ||
726 | chan->def.chan->center_freq) | ||
727 | ci_bw_idx = 2; | ||
728 | else | ||
729 | ci_bw_idx = 1; | ||
730 | } | ||
731 | |||
732 | cmd.bt_primary_ci = | ||
733 | iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx]; | ||
734 | cmd.primary_ch_phy_id = *((u16 *)data.primary->drv_priv); | ||
735 | } | ||
736 | |||
737 | if (data.secondary) { | ||
738 | struct ieee80211_chanctx_conf *chan = data.secondary; | ||
739 | if (WARN_ON(!data.secondary->def.chan)) { | ||
740 | rcu_read_unlock(); | ||
741 | return; | ||
742 | } | ||
743 | |||
744 | if (chan->def.width < NL80211_CHAN_WIDTH_40) { | ||
745 | ci_bw_idx = 0; | ||
746 | cmd.co_run_bw_secondary = 0; | ||
747 | } else { | ||
748 | cmd.co_run_bw_secondary = 1; | ||
749 | if (chan->def.center_freq1 > | ||
750 | chan->def.chan->center_freq) | ||
751 | ci_bw_idx = 2; | ||
752 | else | ||
753 | ci_bw_idx = 1; | ||
754 | } | ||
755 | |||
756 | cmd.bt_secondary_ci = | ||
757 | iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx]; | ||
758 | cmd.secondary_ch_phy_id = *((u16 *)data.secondary->drv_priv); | ||
759 | } | ||
760 | |||
761 | rcu_read_unlock(); | ||
762 | |||
763 | /* Don't spam the fw with the same command over and over */ | ||
764 | if (memcmp(&cmd, &mvm->last_bt_ci_cmd, sizeof(cmd))) { | ||
765 | if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, CMD_SYNC, | ||
766 | sizeof(cmd), &cmd)) | ||
767 | IWL_ERR(mvm, "Failed to send BT_CI cmd"); | ||
768 | memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd)); | ||
769 | } | ||
770 | |||
518 | /* | 771 | /* |
519 | * If there are no BSS / P2P client interfaces, reduced Tx Power is | 772 | * If there are no BSS / P2P client interfaces, reduced Tx Power is |
520 | * irrelevant since it is based on the RSSI coming from the beacon. | 773 | * irrelevant since it is based on the RSSI coming from the beacon. |
@@ -536,12 +789,18 @@ int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm, | |||
536 | 789 | ||
537 | 790 | ||
538 | IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n"); | 791 | IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n"); |
539 | IWL_DEBUG_COEX(mvm, "\tBT %salive\n", notif->bt_status ? "" : "not "); | 792 | IWL_DEBUG_COEX(mvm, "\tBT status: %s\n", |
793 | notif->bt_status ? "ON" : "OFF"); | ||
540 | IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn); | 794 | IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn); |
541 | IWL_DEBUG_COEX(mvm, "\tBT traffic load %d\n", notif->bt_traffic_load); | 795 | IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance); |
796 | IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n", | ||
797 | le32_to_cpu(notif->primary_ch_lut)); | ||
798 | IWL_DEBUG_COEX(mvm, "\tBT secondary_ch_lut %d\n", | ||
799 | le32_to_cpu(notif->secondary_ch_lut)); | ||
800 | IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n", | ||
801 | le32_to_cpu(notif->bt_activity_grading)); | ||
542 | IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n", | 802 | IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n", |
543 | notif->bt_agg_traffic_load); | 803 | notif->bt_agg_traffic_load); |
544 | IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance); | ||
545 | 804 | ||
546 | /* remember this notification for future use: rssi fluctuations */ | 805 | /* remember this notification for future use: rssi fluctuations */ |
547 | memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif)); | 806 | memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif)); |
@@ -565,6 +824,18 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac, | |||
565 | struct ieee80211_sta *sta; | 824 | struct ieee80211_sta *sta; |
566 | struct iwl_mvm_sta *mvmsta; | 825 | struct iwl_mvm_sta *mvmsta; |
567 | 826 | ||
827 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
828 | |||
829 | rcu_read_lock(); | ||
830 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
831 | /* If channel context is invalid or not on 2.4GHz - don't count it */ | ||
832 | if (!chanctx_conf || | ||
833 | chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) { | ||
834 | rcu_read_unlock(); | ||
835 | return; | ||
836 | } | ||
837 | rcu_read_unlock(); | ||
838 | |||
568 | if (vif->type != NL80211_IFTYPE_STATION || | 839 | if (vif->type != NL80211_IFTYPE_STATION || |
569 | mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) | 840 | mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) |
570 | return; | 841 | return; |
@@ -594,15 +865,15 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
594 | }; | 865 | }; |
595 | int ret; | 866 | int ret; |
596 | 867 | ||
597 | mutex_lock(&mvm->mutex); | 868 | lockdep_assert_held(&mvm->mutex); |
598 | 869 | ||
599 | /* Rssi update while not associated ?! */ | 870 | /* Rssi update while not associated ?! */ |
600 | if (WARN_ON_ONCE(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)) | 871 | if (WARN_ON_ONCE(mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)) |
601 | goto out_unlock; | 872 | return; |
602 | 873 | ||
603 | /* No open connection - reports should be disabled */ | 874 | /* No BT - reports should be disabled */ |
604 | if (!BT_MBOX_MSG(&mvm->last_bt_notif, 3, OPEN_CON_2)) | 875 | if (!mvm->last_bt_notif.bt_status) |
605 | goto out_unlock; | 876 | return; |
606 | 877 | ||
607 | IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid, | 878 | IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid, |
608 | rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW"); | 879 | rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW"); |
@@ -611,7 +882,8 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
611 | * Check if rssi is good enough for reduced Tx power, but not in loose | 882 | * Check if rssi is good enough for reduced Tx power, but not in loose |
612 | * scheme. | 883 | * scheme. |
613 | */ | 884 | */ |
614 | if (rssi_event == RSSI_EVENT_LOW || is_loose_coex()) | 885 | if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant || |
886 | iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT) | ||
615 | ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, | 887 | ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, |
616 | false); | 888 | false); |
617 | else | 889 | else |
@@ -633,12 +905,52 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
633 | 905 | ||
634 | if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power)) | 906 | if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power)) |
635 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); | 907 | IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n"); |
908 | } | ||
636 | 909 | ||
637 | out_unlock: | 910 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) |
638 | mutex_unlock(&mvm->mutex); | 911 | #define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT (1200) |
912 | |||
913 | u16 iwl_mvm_bt_coex_agg_time_limit(struct iwl_mvm *mvm, | ||
914 | struct ieee80211_sta *sta) | ||
915 | { | ||
916 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | ||
917 | enum iwl_bt_coex_lut_type lut_type; | ||
918 | |||
919 | if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < | ||
920 | BT_LOW_TRAFFIC) | ||
921 | return LINK_QUAL_AGG_TIME_LIMIT_DEF; | ||
922 | |||
923 | lut_type = iwl_get_coex_type(mvm, mvmsta->vif); | ||
924 | |||
925 | if (lut_type == BT_COEX_LOOSE_LUT) | ||
926 | return LINK_QUAL_AGG_TIME_LIMIT_DEF; | ||
927 | |||
928 | /* tight coex, high bt traffic, reduce AGG time limit */ | ||
929 | return LINK_QUAL_AGG_TIME_LIMIT_BT_ACT; | ||
639 | } | 930 | } |
640 | 931 | ||
641 | void iwl_mvm_bt_coex_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | 932 | bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm, |
933 | struct ieee80211_sta *sta) | ||
642 | { | 934 | { |
935 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | ||
936 | |||
937 | if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) < | ||
938 | BT_HIGH_TRAFFIC) | ||
939 | return true; | ||
940 | |||
941 | /* | ||
942 | * In Tight, BT can't Rx while we Tx, so use both antennas since BT is | ||
943 | * already killed. | ||
944 | * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while we | ||
945 | * Tx. | ||
946 | */ | ||
947 | return iwl_get_coex_type(mvm, mvmsta->vif) == BT_COEX_TIGHT_LUT; | ||
948 | } | ||
949 | |||
950 | void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm) | ||
951 | { | ||
952 | if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX)) | ||
953 | return; | ||
954 | |||
643 | iwl_mvm_bt_coex_notif_handle(mvm); | 955 | iwl_mvm_bt_coex_notif_handle(mvm); |
644 | } | 956 | } |