Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/iwlwifi/mvm/power.c
48287 views
1
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2
/*
3
* Copyright (C) 2012-2014, 2018-2019, 2021-2025 Intel Corporation
4
* Copyright (C) 2013-2014 Intel Mobile Communications GmbH
5
* Copyright (C) 2015-2017 Intel Deutschland GmbH
6
*/
7
#include <linux/kernel.h>
8
#include <linux/module.h>
9
#include <linux/slab.h>
10
#include <linux/etherdevice.h>
11
12
#include <net/mac80211.h>
13
14
#include "iwl-debug.h"
15
#include "mvm.h"
16
#include "iwl-modparams.h"
17
#include "fw/api/power.h"
18
19
#define POWER_KEEP_ALIVE_PERIOD_SEC 25
20
21
static
22
int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
23
struct iwl_beacon_filter_cmd *cmd)
24
{
25
u16 len;
26
27
IWL_DEBUG_POWER(mvm, "ba_enable_beacon_abort is: %d\n",
28
le32_to_cpu(cmd->ba_enable_beacon_abort));
29
IWL_DEBUG_POWER(mvm, "ba_escape_timer is: %d\n",
30
le32_to_cpu(cmd->ba_escape_timer));
31
IWL_DEBUG_POWER(mvm, "bf_debug_flag is: %d\n",
32
le32_to_cpu(cmd->bf_debug_flag));
33
IWL_DEBUG_POWER(mvm, "bf_enable_beacon_filter is: %d\n",
34
le32_to_cpu(cmd->bf_enable_beacon_filter));
35
IWL_DEBUG_POWER(mvm, "bf_energy_delta is: %d\n",
36
le32_to_cpu(cmd->bf_energy_delta));
37
IWL_DEBUG_POWER(mvm, "bf_escape_timer is: %d\n",
38
le32_to_cpu(cmd->bf_escape_timer));
39
IWL_DEBUG_POWER(mvm, "bf_roaming_energy_delta is: %d\n",
40
le32_to_cpu(cmd->bf_roaming_energy_delta));
41
IWL_DEBUG_POWER(mvm, "bf_roaming_state is: %d\n",
42
le32_to_cpu(cmd->bf_roaming_state));
43
IWL_DEBUG_POWER(mvm, "bf_temp_threshold is: %d\n",
44
le32_to_cpu(cmd->bf_temp_threshold));
45
IWL_DEBUG_POWER(mvm, "bf_temp_fast_filter is: %d\n",
46
le32_to_cpu(cmd->bf_temp_fast_filter));
47
IWL_DEBUG_POWER(mvm, "bf_temp_slow_filter is: %d\n",
48
le32_to_cpu(cmd->bf_temp_slow_filter));
49
IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_low is: %d, %d\n",
50
le32_to_cpu(cmd->bf_threshold_absolute_low[0]),
51
le32_to_cpu(cmd->bf_threshold_absolute_low[1]));
52
53
IWL_DEBUG_POWER(mvm, "bf_threshold_absolute_high is: %d, %d\n",
54
le32_to_cpu(cmd->bf_threshold_absolute_high[0]),
55
le32_to_cpu(cmd->bf_threshold_absolute_high[1]));
56
57
if (fw_has_api(&mvm->fw->ucode_capa,
58
IWL_UCODE_TLV_API_BEACON_FILTER_V4))
59
len = sizeof(struct iwl_beacon_filter_cmd);
60
else
61
len = offsetof(struct iwl_beacon_filter_cmd,
62
bf_threshold_absolute_low);
63
64
return iwl_mvm_send_cmd_pdu(mvm, REPLY_BEACON_FILTERING_CMD, 0,
65
len, cmd);
66
}
67
68
static
69
void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm,
70
struct ieee80211_vif *vif,
71
struct iwl_beacon_filter_cmd *cmd)
72
{
73
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
74
75
if (vif->bss_conf.cqm_rssi_thold) {
76
cmd->bf_energy_delta =
77
cpu_to_le32(vif->bss_conf.cqm_rssi_hyst);
78
/* fw uses an absolute value for this */
79
cmd->bf_roaming_state =
80
cpu_to_le32(-vif->bss_conf.cqm_rssi_thold);
81
}
82
cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->ba_enabled);
83
}
84
85
static void iwl_mvm_power_log(struct iwl_mvm *mvm,
86
struct iwl_mac_power_cmd *cmd)
87
{
88
IWL_DEBUG_POWER(mvm,
89
"Sending power table command on mac id 0x%X for power level %d, flags = 0x%X\n",
90
cmd->id_and_color, iwlmvm_mod_params.power_scheme,
91
le16_to_cpu(cmd->flags));
92
IWL_DEBUG_POWER(mvm, "Keep alive = %u sec\n",
93
le16_to_cpu(cmd->keep_alive_seconds));
94
95
if (!(cmd->flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK))) {
96
IWL_DEBUG_POWER(mvm, "Disable power management\n");
97
return;
98
}
99
100
IWL_DEBUG_POWER(mvm, "Rx timeout = %u usec\n",
101
le32_to_cpu(cmd->rx_data_timeout));
102
IWL_DEBUG_POWER(mvm, "Tx timeout = %u usec\n",
103
le32_to_cpu(cmd->tx_data_timeout));
104
if (cmd->flags & cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK))
105
IWL_DEBUG_POWER(mvm, "DTIM periods to skip = %u\n",
106
cmd->skip_dtim_periods);
107
if (cmd->flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
108
IWL_DEBUG_POWER(mvm, "LP RX RSSI threshold = %u\n",
109
cmd->lprx_rssi_threshold);
110
if (cmd->flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)) {
111
IWL_DEBUG_POWER(mvm, "uAPSD enabled\n");
112
IWL_DEBUG_POWER(mvm, "Rx timeout (uAPSD) = %u usec\n",
113
le32_to_cpu(cmd->rx_data_timeout_uapsd));
114
IWL_DEBUG_POWER(mvm, "Tx timeout (uAPSD) = %u usec\n",
115
le32_to_cpu(cmd->tx_data_timeout_uapsd));
116
IWL_DEBUG_POWER(mvm, "QNDP TID = %d\n", cmd->qndp_tid);
117
IWL_DEBUG_POWER(mvm, "ACs flags = 0x%x\n", cmd->uapsd_ac_flags);
118
IWL_DEBUG_POWER(mvm, "Max SP = %d\n", cmd->uapsd_max_sp);
119
}
120
}
121
122
static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
123
struct ieee80211_vif *vif,
124
struct iwl_mac_power_cmd *cmd)
125
{
126
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
127
enum ieee80211_ac_numbers ac;
128
bool tid_found = false;
129
130
if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ||
131
cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
132
cmd->rx_data_timeout_uapsd =
133
cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
134
cmd->tx_data_timeout_uapsd =
135
cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
136
} else {
137
cmd->rx_data_timeout_uapsd =
138
cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
139
cmd->tx_data_timeout_uapsd =
140
cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
141
}
142
143
#ifdef CONFIG_IWLWIFI_DEBUGFS
144
/* set advanced pm flag with no uapsd ACs to enable ps-poll */
145
if (mvmvif->dbgfs_pm.use_ps_poll) {
146
cmd->flags |= cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
147
return;
148
}
149
#endif
150
151
for (ac = IEEE80211_AC_VO; ac <= IEEE80211_AC_BK; ac++) {
152
if (!mvmvif->deflink.queue_params[ac].uapsd)
153
continue;
154
155
if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
156
cmd->flags |=
157
cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK);
158
159
cmd->uapsd_ac_flags |= BIT(ac);
160
161
/* QNDP TID - the highest TID with no admission control */
162
if (!tid_found && !mvmvif->deflink.queue_params[ac].acm) {
163
tid_found = true;
164
switch (ac) {
165
case IEEE80211_AC_VO:
166
cmd->qndp_tid = 6;
167
break;
168
case IEEE80211_AC_VI:
169
cmd->qndp_tid = 5;
170
break;
171
case IEEE80211_AC_BE:
172
cmd->qndp_tid = 0;
173
break;
174
case IEEE80211_AC_BK:
175
cmd->qndp_tid = 1;
176
break;
177
}
178
}
179
}
180
181
cmd->flags |= cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK);
182
183
if (cmd->uapsd_ac_flags == (BIT(IEEE80211_AC_VO) |
184
BIT(IEEE80211_AC_VI) |
185
BIT(IEEE80211_AC_BE) |
186
BIT(IEEE80211_AC_BK))) {
187
cmd->flags |= cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
188
cmd->snooze_interval = cpu_to_le16(IWL_MVM_PS_SNOOZE_INTERVAL);
189
cmd->snooze_window =
190
test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ?
191
cpu_to_le16(IWL_MVM_WOWLAN_PS_SNOOZE_WINDOW) :
192
cpu_to_le16(IWL_MVM_PS_SNOOZE_WINDOW);
193
}
194
195
cmd->uapsd_max_sp = mvm->hw->uapsd_max_sp_len;
196
197
if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
198
cmd->heavy_tx_thld_packets =
199
IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS;
200
cmd->heavy_rx_thld_packets =
201
IWL_MVM_PS_SNOOZE_HEAVY_RX_THLD_PACKETS;
202
} else {
203
cmd->heavy_tx_thld_packets =
204
IWL_MVM_PS_HEAVY_TX_THLD_PACKETS;
205
cmd->heavy_rx_thld_packets =
206
IWL_MVM_PS_HEAVY_RX_THLD_PACKETS;
207
}
208
cmd->heavy_tx_thld_percentage =
209
IWL_MVM_PS_HEAVY_TX_THLD_PERCENT;
210
cmd->heavy_rx_thld_percentage =
211
IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
212
}
213
214
struct iwl_allow_uapsd_iface_iterator_data {
215
struct ieee80211_vif *current_vif;
216
bool allow_uapsd;
217
};
218
219
static void iwl_mvm_allow_uapsd_iterator(void *_data, u8 *mac,
220
struct ieee80211_vif *vif)
221
{
222
struct iwl_allow_uapsd_iface_iterator_data *data = _data;
223
struct iwl_mvm_vif *other_mvmvif = iwl_mvm_vif_from_mac80211(vif);
224
struct iwl_mvm_vif *curr_mvmvif =
225
iwl_mvm_vif_from_mac80211(data->current_vif);
226
227
/* exclude the given vif */
228
if (vif == data->current_vif)
229
return;
230
231
switch (vif->type) {
232
case NL80211_IFTYPE_AP:
233
case NL80211_IFTYPE_ADHOC:
234
data->allow_uapsd = false;
235
break;
236
case NL80211_IFTYPE_STATION:
237
/* allow UAPSD if P2P interface and BSS station interface share
238
* the same channel.
239
*/
240
if (vif->cfg.assoc && other_mvmvif->deflink.phy_ctxt &&
241
curr_mvmvif->deflink.phy_ctxt &&
242
other_mvmvif->deflink.phy_ctxt->id != curr_mvmvif->deflink.phy_ctxt->id)
243
data->allow_uapsd = false;
244
break;
245
246
default:
247
break;
248
}
249
}
250
251
static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
252
struct ieee80211_vif *vif)
253
{
254
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
255
struct iwl_allow_uapsd_iface_iterator_data data = {
256
.current_vif = vif,
257
.allow_uapsd = true,
258
};
259
260
if (ether_addr_equal(mvmvif->uapsd_misbehaving_ap_addr,
261
vif->cfg.ap_addr))
262
return false;
263
264
/*
265
* Avoid using uAPSD if P2P client is associated to GO that uses
266
* opportunistic power save. This is due to current FW limitation.
267
*/
268
if (vif->p2p &&
269
(vif->bss_conf.p2p_noa_attr.oppps_ctwindow &
270
IEEE80211_P2P_OPPPS_ENABLE_BIT))
271
return false;
272
273
if (vif->p2p && !iwl_mvm_is_p2p_scm_uapsd_supported(mvm))
274
return false;
275
276
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
277
IEEE80211_IFACE_ITER_NORMAL,
278
iwl_mvm_allow_uapsd_iterator,
279
&data);
280
281
return data.allow_uapsd;
282
}
283
284
static bool iwl_mvm_power_is_radar(struct ieee80211_bss_conf *link_conf)
285
{
286
struct ieee80211_chanctx_conf *chanctx_conf;
287
288
chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
289
290
/* this happens on link switching, just ignore inactive ones */
291
if (!chanctx_conf)
292
return false;
293
294
return chanctx_conf->def.chan->flags & IEEE80211_CHAN_RADAR;
295
}
296
297
static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm,
298
struct ieee80211_vif *vif,
299
struct iwl_mac_power_cmd *cmd)
300
{
301
struct ieee80211_bss_conf *link_conf;
302
unsigned int min_link_skip = ~0;
303
unsigned int link_id;
304
305
/* disable, in case we're supposed to override */
306
cmd->skip_dtim_periods = 0;
307
cmd->flags &= ~cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
308
309
if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) {
310
if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP)
311
return;
312
cmd->skip_dtim_periods = 2;
313
cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
314
return;
315
}
316
317
rcu_read_lock();
318
for_each_vif_active_link(vif, link_conf, link_id) {
319
unsigned int dtimper = link_conf->dtim_period ?: 1;
320
unsigned int dtimper_tu = dtimper * link_conf->beacon_int;
321
unsigned int skip;
322
323
if (dtimper >= 10 || iwl_mvm_power_is_radar(link_conf)) {
324
rcu_read_unlock();
325
return;
326
}
327
328
if (WARN_ON(!dtimper_tu))
329
continue;
330
331
/* configure skip over dtim up to 900 TU DTIM interval */
332
skip = max_t(int, 1, 900 / dtimper_tu);
333
min_link_skip = min(min_link_skip, skip);
334
}
335
rcu_read_unlock();
336
337
/* no WARN_ON, can only happen with WARN_ON above */
338
if (min_link_skip == ~0)
339
return;
340
341
cmd->skip_dtim_periods = min_link_skip;
342
cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
343
}
344
345
static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm,
346
struct ieee80211_vif *vif,
347
struct iwl_mac_power_cmd *cmd)
348
{
349
int dtimper, bi;
350
int keep_alive;
351
struct iwl_mvm_vif *mvmvif __maybe_unused =
352
iwl_mvm_vif_from_mac80211(vif);
353
354
cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
355
mvmvif->color));
356
dtimper = vif->bss_conf.dtim_period;
357
bi = vif->bss_conf.beacon_int;
358
359
/*
360
* Regardless of power management state the driver must set
361
* keep alive period. FW will use it for sending keep alive NDPs
362
* immediately after association. Check that keep alive period
363
* is at least 3 * DTIM
364
*/
365
keep_alive = DIV_ROUND_UP(ieee80211_tu_to_usec(3 * dtimper * bi),
366
USEC_PER_SEC);
367
keep_alive = max(keep_alive, POWER_KEEP_ALIVE_PERIOD_SEC);
368
cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
369
370
if (mvm->ps_disabled)
371
return;
372
373
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK);
374
375
if (!vif->cfg.ps || !mvmvif->pm_enabled)
376
return;
377
378
if (iwl_fw_lookup_cmd_ver(mvm->fw, MAC_PM_POWER_TABLE, 0) >= 2)
379
cmd->flags |= cpu_to_le16(POWER_FLAGS_ENABLE_SMPS_MSK);
380
381
if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
382
(!fw_has_capa(&mvm->fw->ucode_capa,
383
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) ||
384
!IWL_MVM_P2P_LOWLATENCY_PS_ENABLE))
385
return;
386
387
cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK);
388
389
if (vif->bss_conf.beacon_rate &&
390
(vif->bss_conf.beacon_rate->bitrate == 10 ||
391
vif->bss_conf.beacon_rate->bitrate == 60)) {
392
cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
393
cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD;
394
}
395
396
iwl_mvm_power_config_skip_dtim(mvm, vif, cmd);
397
398
if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) {
399
cmd->rx_data_timeout =
400
cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
401
cmd->tx_data_timeout =
402
cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
403
} else if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p &&
404
fw_has_capa(&mvm->fw->ucode_capa,
405
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS)) {
406
cmd->tx_data_timeout =
407
cpu_to_le32(IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT);
408
cmd->rx_data_timeout =
409
cpu_to_le32(IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT);
410
} else {
411
cmd->rx_data_timeout =
412
cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT);
413
cmd->tx_data_timeout =
414
cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT);
415
}
416
417
if (iwl_mvm_power_allow_uapsd(mvm, vif))
418
iwl_mvm_power_configure_uapsd(mvm, vif, cmd);
419
420
#ifdef CONFIG_IWLWIFI_DEBUGFS
421
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_KEEP_ALIVE)
422
cmd->keep_alive_seconds =
423
cpu_to_le16(mvmvif->dbgfs_pm.keep_alive_seconds);
424
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_OVER_DTIM) {
425
if (mvmvif->dbgfs_pm.skip_over_dtim)
426
cmd->flags |=
427
cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
428
else
429
cmd->flags &=
430
cpu_to_le16(~POWER_FLAGS_SKIP_OVER_DTIM_MSK);
431
}
432
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_RX_DATA_TIMEOUT)
433
cmd->rx_data_timeout =
434
cpu_to_le32(mvmvif->dbgfs_pm.rx_data_timeout);
435
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_TX_DATA_TIMEOUT)
436
cmd->tx_data_timeout =
437
cpu_to_le32(mvmvif->dbgfs_pm.tx_data_timeout);
438
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS)
439
cmd->skip_dtim_periods = mvmvif->dbgfs_pm.skip_dtim_periods;
440
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_ENA) {
441
if (mvmvif->dbgfs_pm.lprx_ena)
442
cmd->flags |= cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK);
443
else
444
cmd->flags &= cpu_to_le16(~POWER_FLAGS_LPRX_ENA_MSK);
445
}
446
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD)
447
cmd->lprx_rssi_threshold = mvmvif->dbgfs_pm.lprx_rssi_threshold;
448
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_SNOOZE_ENABLE) {
449
if (mvmvif->dbgfs_pm.snooze_ena)
450
cmd->flags |=
451
cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK);
452
else
453
cmd->flags &=
454
cpu_to_le16(~POWER_FLAGS_SNOOZE_ENA_MSK);
455
}
456
if (mvmvif->dbgfs_pm.mask & MVM_DEBUGFS_PM_UAPSD_MISBEHAVING) {
457
u16 flag = POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK;
458
if (mvmvif->dbgfs_pm.uapsd_misbehaving)
459
cmd->flags |= cpu_to_le16(flag);
460
else
461
cmd->flags &= cpu_to_le16(flag);
462
}
463
#endif /* CONFIG_IWLWIFI_DEBUGFS */
464
}
465
466
static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
467
struct ieee80211_vif *vif)
468
{
469
struct iwl_mac_power_cmd cmd = {};
470
471
iwl_mvm_power_build_cmd(mvm, vif, &cmd);
472
iwl_mvm_power_log(mvm, &cmd);
473
#ifdef CONFIG_IWLWIFI_DEBUGFS
474
memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd));
475
#endif
476
477
return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, 0,
478
sizeof(cmd), &cmd);
479
}
480
481
int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
482
{
483
struct iwl_device_power_cmd cmd = {
484
.flags = 0,
485
};
486
487
if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM)
488
mvm->ps_disabled = true;
489
490
if (!mvm->ps_disabled)
491
cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
492
493
#ifdef CONFIG_IWLWIFI_DEBUGFS
494
if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ?
495
mvm->disable_power_off_d3 : mvm->disable_power_off)
496
cmd.flags &=
497
cpu_to_le16(~DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK);
498
#endif
499
if (mvm->ext_clock_valid)
500
cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_32K_CLK_VALID_MSK);
501
502
if (iwl_fw_lookup_cmd_ver(mvm->fw, POWER_TABLE_CMD, 0) >= 7 &&
503
test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
504
cmd.flags |=
505
cpu_to_le16(DEVICE_POWER_FLAGS_NO_SLEEP_TILL_D3_MSK);
506
507
IWL_DEBUG_POWER(mvm,
508
"Sending device power command with flags = 0x%X\n",
509
cmd.flags);
510
511
return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, 0, sizeof(cmd),
512
&cmd);
513
}
514
515
void iwl_mvm_power_vif_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
516
{
517
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
518
519
if (!ether_addr_equal(mvmvif->uapsd_misbehaving_ap_addr,
520
vif->cfg.ap_addr))
521
eth_zero_addr(mvmvif->uapsd_misbehaving_ap_addr);
522
}
523
524
static void iwl_mvm_power_uapsd_misbehav_ap_iterator(void *_data, u8 *mac,
525
struct ieee80211_vif *vif)
526
{
527
u8 *ap_sta_id = _data;
528
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
529
struct ieee80211_bss_conf *link_conf;
530
unsigned int link_id;
531
532
rcu_read_lock();
533
for_each_vif_active_link(vif, link_conf, link_id) {
534
struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id];
535
536
/* The ap_sta_id is not expected to change during current
537
* association so no explicit protection is needed
538
*/
539
if (link_info->ap_sta_id == *ap_sta_id) {
540
ether_addr_copy(mvmvif->uapsd_misbehaving_ap_addr,
541
vif->cfg.ap_addr);
542
break;
543
}
544
}
545
rcu_read_unlock();
546
}
547
548
void iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
549
struct iwl_rx_cmd_buffer *rxb)
550
{
551
struct iwl_rx_packet *pkt = rxb_addr(rxb);
552
struct iwl_uapsd_misbehaving_ap_notif *notif = (void *)pkt->data;
553
u8 ap_sta_id = le32_to_cpu(notif->sta_id);
554
555
ieee80211_iterate_active_interfaces_atomic(
556
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
557
iwl_mvm_power_uapsd_misbehav_ap_iterator, &ap_sta_id);
558
}
559
560
struct iwl_power_vifs {
561
struct iwl_mvm *mvm;
562
struct ieee80211_vif *bss_vif;
563
struct ieee80211_vif *p2p_vif;
564
struct ieee80211_vif *ap_vif;
565
struct ieee80211_vif *monitor_vif;
566
bool p2p_active;
567
bool bss_active;
568
bool ap_active;
569
bool monitor_active;
570
};
571
572
static void iwl_mvm_power_disable_pm_iterator(void *_data, u8 *mac,
573
struct ieee80211_vif *vif)
574
{
575
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
576
577
mvmvif->pm_enabled = false;
578
}
579
580
static void iwl_mvm_power_ps_disabled_iterator(void *_data, u8 *mac,
581
struct ieee80211_vif *vif)
582
{
583
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
584
bool *disable_ps = _data;
585
586
if (iwl_mvm_vif_is_active(mvmvif))
587
*disable_ps |= mvmvif->ps_disabled;
588
}
589
590
static void iwl_mvm_power_get_vifs_iterator(void *_data, u8 *mac,
591
struct ieee80211_vif *vif)
592
{
593
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
594
struct iwl_power_vifs *power_iterator = _data;
595
bool active;
596
597
if (!mvmvif->uploaded)
598
return;
599
600
active = iwl_mvm_vif_is_active(mvmvif);
601
602
switch (ieee80211_vif_type_p2p(vif)) {
603
case NL80211_IFTYPE_P2P_DEVICE:
604
break;
605
606
case NL80211_IFTYPE_P2P_GO:
607
case NL80211_IFTYPE_AP:
608
/* only a single MAC of the same type */
609
WARN_ON(power_iterator->ap_vif);
610
power_iterator->ap_vif = vif;
611
if (active)
612
power_iterator->ap_active = true;
613
break;
614
615
case NL80211_IFTYPE_MONITOR:
616
/* only a single MAC of the same type */
617
WARN_ON(power_iterator->monitor_vif);
618
power_iterator->monitor_vif = vif;
619
if (active)
620
power_iterator->monitor_active = true;
621
break;
622
623
case NL80211_IFTYPE_P2P_CLIENT:
624
/* only a single MAC of the same type */
625
WARN_ON(power_iterator->p2p_vif);
626
power_iterator->p2p_vif = vif;
627
if (active)
628
power_iterator->p2p_active = true;
629
break;
630
631
case NL80211_IFTYPE_STATION:
632
power_iterator->bss_vif = vif;
633
if (active)
634
power_iterator->bss_active = true;
635
break;
636
637
default:
638
break;
639
}
640
}
641
642
static void iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
643
struct iwl_power_vifs *vifs)
644
{
645
struct iwl_mvm_vif *bss_mvmvif = NULL;
646
struct iwl_mvm_vif *p2p_mvmvif = NULL;
647
struct iwl_mvm_vif *ap_mvmvif = NULL;
648
bool client_same_channel = false;
649
bool ap_same_channel = false;
650
651
lockdep_assert_held(&mvm->mutex);
652
653
/* set pm_enable to false */
654
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
655
IEEE80211_IFACE_ITER_NORMAL,
656
iwl_mvm_power_disable_pm_iterator,
657
NULL);
658
659
if (vifs->bss_vif)
660
bss_mvmvif = iwl_mvm_vif_from_mac80211(vifs->bss_vif);
661
662
if (vifs->p2p_vif)
663
p2p_mvmvif = iwl_mvm_vif_from_mac80211(vifs->p2p_vif);
664
665
if (vifs->ap_vif)
666
ap_mvmvif = iwl_mvm_vif_from_mac80211(vifs->ap_vif);
667
668
/* don't allow PM if any TDLS stations exist */
669
if (iwl_mvm_tdls_sta_count(mvm, NULL))
670
return;
671
672
/* enable PM on bss if bss stand alone */
673
if (bss_mvmvif && vifs->bss_active && !vifs->p2p_active &&
674
!vifs->ap_active) {
675
bss_mvmvif->pm_enabled = true;
676
return;
677
}
678
679
/* enable PM on p2p if p2p stand alone */
680
if (p2p_mvmvif && vifs->p2p_active && !vifs->bss_active &&
681
!vifs->ap_active) {
682
p2p_mvmvif->pm_enabled = true;
683
return;
684
}
685
686
if (p2p_mvmvif && bss_mvmvif && vifs->bss_active && vifs->p2p_active)
687
client_same_channel =
688
iwl_mvm_have_links_same_channel(bss_mvmvif, p2p_mvmvif);
689
690
if (bss_mvmvif && ap_mvmvif && vifs->bss_active && vifs->ap_active)
691
ap_same_channel =
692
iwl_mvm_have_links_same_channel(bss_mvmvif, ap_mvmvif);
693
694
/* clients are not stand alone: enable PM if DCM */
695
if (!(client_same_channel || ap_same_channel)) {
696
if (bss_mvmvif && vifs->bss_active)
697
bss_mvmvif->pm_enabled = true;
698
if (p2p_mvmvif && vifs->p2p_active)
699
p2p_mvmvif->pm_enabled = true;
700
return;
701
}
702
703
/*
704
* There is only one channel in the system and there are only
705
* bss and p2p clients that share it
706
*/
707
if (client_same_channel && !vifs->ap_active) {
708
/* share same channel*/
709
bss_mvmvif->pm_enabled = true;
710
p2p_mvmvif->pm_enabled = true;
711
}
712
}
713
714
#ifdef CONFIG_IWLWIFI_DEBUGFS
715
int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
716
struct ieee80211_vif *vif, char *buf,
717
int bufsz)
718
{
719
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
720
struct iwl_mac_power_cmd cmd = {};
721
int pos = 0;
722
723
mutex_lock(&mvm->mutex);
724
memcpy(&cmd, &mvmvif->mac_pwr_cmd, sizeof(cmd));
725
mutex_unlock(&mvm->mutex);
726
727
pos += scnprintf(buf+pos, bufsz-pos, "power_scheme = %d\n",
728
iwlmvm_mod_params.power_scheme);
729
pos += scnprintf(buf+pos, bufsz-pos, "flags = 0x%x\n",
730
le16_to_cpu(cmd.flags));
731
pos += scnprintf(buf+pos, bufsz-pos, "keep_alive = %d\n",
732
le16_to_cpu(cmd.keep_alive_seconds));
733
734
if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK)))
735
return pos;
736
737
pos += scnprintf(buf+pos, bufsz-pos, "skip_over_dtim = %d\n",
738
(cmd.flags &
739
cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK)) ? 1 : 0);
740
pos += scnprintf(buf+pos, bufsz-pos, "skip_dtim_periods = %d\n",
741
cmd.skip_dtim_periods);
742
if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK))) {
743
pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout = %d\n",
744
le32_to_cpu(cmd.rx_data_timeout));
745
pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout = %d\n",
746
le32_to_cpu(cmd.tx_data_timeout));
747
}
748
if (cmd.flags & cpu_to_le16(POWER_FLAGS_LPRX_ENA_MSK))
749
pos += scnprintf(buf+pos, bufsz-pos,
750
"lprx_rssi_threshold = %d\n",
751
cmd.lprx_rssi_threshold);
752
753
if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_ADVANCE_PM_ENA_MSK)))
754
return pos;
755
756
pos += scnprintf(buf+pos, bufsz-pos, "rx_data_timeout_uapsd = %d\n",
757
le32_to_cpu(cmd.rx_data_timeout_uapsd));
758
pos += scnprintf(buf+pos, bufsz-pos, "tx_data_timeout_uapsd = %d\n",
759
le32_to_cpu(cmd.tx_data_timeout_uapsd));
760
pos += scnprintf(buf+pos, bufsz-pos, "qndp_tid = %d\n", cmd.qndp_tid);
761
pos += scnprintf(buf+pos, bufsz-pos, "uapsd_ac_flags = 0x%x\n",
762
cmd.uapsd_ac_flags);
763
pos += scnprintf(buf+pos, bufsz-pos, "uapsd_max_sp = %d\n",
764
cmd.uapsd_max_sp);
765
pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_packets = %d\n",
766
cmd.heavy_tx_thld_packets);
767
pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_packets = %d\n",
768
cmd.heavy_rx_thld_packets);
769
pos += scnprintf(buf+pos, bufsz-pos, "heavy_tx_thld_percentage = %d\n",
770
cmd.heavy_tx_thld_percentage);
771
pos += scnprintf(buf+pos, bufsz-pos, "heavy_rx_thld_percentage = %d\n",
772
cmd.heavy_rx_thld_percentage);
773
pos += scnprintf(buf+pos, bufsz-pos, "uapsd_misbehaving_enable = %d\n",
774
(cmd.flags &
775
cpu_to_le16(POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK)) ?
776
1 : 0);
777
778
if (!(cmd.flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)))
779
return pos;
780
781
pos += scnprintf(buf+pos, bufsz-pos, "snooze_interval = %d\n",
782
cmd.snooze_interval);
783
pos += scnprintf(buf+pos, bufsz-pos, "snooze_window = %d\n",
784
cmd.snooze_window);
785
786
return pos;
787
}
788
789
void
790
iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
791
struct iwl_beacon_filter_cmd *cmd)
792
{
793
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
794
struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
795
796
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ENERGY_DELTA)
797
cmd->bf_energy_delta = cpu_to_le32(dbgfs_bf->bf_energy_delta);
798
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA)
799
cmd->bf_roaming_energy_delta =
800
cpu_to_le32(dbgfs_bf->bf_roaming_energy_delta);
801
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ROAMING_STATE)
802
cmd->bf_roaming_state = cpu_to_le32(dbgfs_bf->bf_roaming_state);
803
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_THRESHOLD)
804
cmd->bf_temp_threshold =
805
cpu_to_le32(dbgfs_bf->bf_temp_threshold);
806
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_FAST_FILTER)
807
cmd->bf_temp_fast_filter =
808
cpu_to_le32(dbgfs_bf->bf_temp_fast_filter);
809
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_TEMP_SLOW_FILTER)
810
cmd->bf_temp_slow_filter =
811
cpu_to_le32(dbgfs_bf->bf_temp_slow_filter);
812
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_DEBUG_FLAG)
813
cmd->bf_debug_flag = cpu_to_le32(dbgfs_bf->bf_debug_flag);
814
if (dbgfs_bf->mask & MVM_DEBUGFS_BF_ESCAPE_TIMER)
815
cmd->bf_escape_timer = cpu_to_le32(dbgfs_bf->bf_escape_timer);
816
if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ESCAPE_TIMER)
817
cmd->ba_escape_timer = cpu_to_le32(dbgfs_bf->ba_escape_timer);
818
if (dbgfs_bf->mask & MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT)
819
cmd->ba_enable_beacon_abort =
820
cpu_to_le32(dbgfs_bf->ba_enable_beacon_abort);
821
}
822
#endif
823
824
static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
825
struct ieee80211_vif *vif,
826
struct iwl_beacon_filter_cmd *cmd)
827
{
828
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
829
int ret;
830
831
if (mvmvif != mvm->bf_allowed_vif || !vif->bss_conf.dtim_period ||
832
vif->type != NL80211_IFTYPE_STATION || vif->p2p)
833
return 0;
834
835
iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd);
836
iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
837
ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd);
838
839
if (!ret)
840
mvmvif->bf_enabled = true;
841
842
return ret;
843
}
844
845
int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
846
struct ieee80211_vif *vif)
847
{
848
struct iwl_beacon_filter_cmd cmd = {
849
IWL_BF_CMD_CONFIG_DEFAULTS,
850
.bf_enable_beacon_filter = cpu_to_le32(1),
851
};
852
853
return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd);
854
}
855
856
static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
857
struct ieee80211_vif *vif)
858
{
859
struct iwl_beacon_filter_cmd cmd = {};
860
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
861
int ret;
862
863
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
864
return 0;
865
866
ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd);
867
868
if (!ret)
869
mvmvif->bf_enabled = false;
870
871
return ret;
872
}
873
874
int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
875
struct ieee80211_vif *vif)
876
{
877
return _iwl_mvm_disable_beacon_filter(mvm, vif);
878
}
879
880
static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm)
881
{
882
bool disable_ps;
883
int ret;
884
885
/* disable PS if CAM */
886
disable_ps = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM);
887
/* ...or if any of the vifs require PS to be off */
888
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
889
IEEE80211_IFACE_ITER_NORMAL,
890
iwl_mvm_power_ps_disabled_iterator,
891
&disable_ps);
892
893
/* update device power state if it has changed */
894
if (mvm->ps_disabled != disable_ps) {
895
bool old_ps_disabled = mvm->ps_disabled;
896
897
mvm->ps_disabled = disable_ps;
898
ret = iwl_mvm_power_update_device(mvm);
899
if (ret) {
900
mvm->ps_disabled = old_ps_disabled;
901
return ret;
902
}
903
}
904
905
return 0;
906
}
907
908
static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm,
909
struct ieee80211_vif *vif)
910
{
911
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
912
struct iwl_beacon_filter_cmd cmd = {
913
IWL_BF_CMD_CONFIG_DEFAULTS,
914
.bf_enable_beacon_filter = cpu_to_le32(1),
915
};
916
917
if (!mvmvif->bf_enabled)
918
return 0;
919
920
if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))
921
cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
922
923
mvmvif->ba_enabled = !(!mvmvif->pm_enabled ||
924
mvm->ps_disabled ||
925
!vif->cfg.ps ||
926
iwl_mvm_vif_low_latency(mvmvif));
927
928
return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd);
929
}
930
931
int iwl_mvm_power_update_ps(struct iwl_mvm *mvm)
932
{
933
struct iwl_power_vifs vifs = {
934
.mvm = mvm,
935
};
936
int ret;
937
938
lockdep_assert_held(&mvm->mutex);
939
940
/* get vifs info */
941
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
942
IEEE80211_IFACE_ITER_NORMAL,
943
iwl_mvm_power_get_vifs_iterator, &vifs);
944
945
ret = iwl_mvm_power_set_ps(mvm);
946
if (ret)
947
return ret;
948
949
if (vifs.bss_vif)
950
return iwl_mvm_power_set_ba(mvm, vifs.bss_vif);
951
952
return 0;
953
}
954
955
int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
956
{
957
struct iwl_power_vifs vifs = {
958
.mvm = mvm,
959
};
960
int ret;
961
962
lockdep_assert_held(&mvm->mutex);
963
964
/* get vifs info */
965
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
966
IEEE80211_IFACE_ITER_NORMAL,
967
iwl_mvm_power_get_vifs_iterator, &vifs);
968
969
iwl_mvm_power_set_pm(mvm, &vifs);
970
971
ret = iwl_mvm_power_set_ps(mvm);
972
if (ret)
973
return ret;
974
975
if (vifs.bss_vif) {
976
ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif);
977
if (ret)
978
return ret;
979
}
980
981
if (vifs.p2p_vif) {
982
ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif);
983
if (ret)
984
return ret;
985
}
986
987
if (vifs.bss_vif)
988
return iwl_mvm_power_set_ba(mvm, vifs.bss_vif);
989
990
return 0;
991
}
992
993