Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/iwlwifi/mld/mld.c
48287 views
1
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2
/*
3
* Copyright (C) 2024-2025 Intel Corporation
4
*/
5
#include <linux/rtnetlink.h>
6
#include <net/mac80211.h>
7
8
#include "fw/api/rx.h"
9
#include "fw/api/datapath.h"
10
#include "fw/api/commands.h"
11
#include "fw/api/offload.h"
12
#include "fw/api/coex.h"
13
#include "fw/dbg.h"
14
#include "fw/uefi.h"
15
16
#include "mld.h"
17
#include "mlo.h"
18
#include "mac80211.h"
19
#include "led.h"
20
#include "scan.h"
21
#include "tx.h"
22
#include "sta.h"
23
#include "regulatory.h"
24
#include "thermal.h"
25
#include "low_latency.h"
26
#include "hcmd.h"
27
#include "fw/api/location.h"
28
29
#include "iwl-nvm-parse.h"
30
31
#define DRV_DESCRIPTION "Intel(R) MLD wireless driver for Linux"
32
MODULE_DESCRIPTION(DRV_DESCRIPTION);
33
MODULE_LICENSE("GPL");
34
MODULE_IMPORT_NS("IWLWIFI");
35
36
static const struct iwl_op_mode_ops iwl_mld_ops;
37
38
static int __init iwl_mld_init(void)
39
{
40
int ret = iwl_opmode_register("iwlmld", &iwl_mld_ops);
41
42
if (ret)
43
pr_err("Unable to register MLD op_mode: %d\n", ret);
44
45
return ret;
46
}
47
module_init(iwl_mld_init);
48
49
static void __exit iwl_mld_exit(void)
50
{
51
iwl_opmode_deregister("iwlmld");
52
}
53
module_exit(iwl_mld_exit);
54
55
static void iwl_mld_hw_set_regulatory(struct iwl_mld *mld)
56
{
57
struct wiphy *wiphy = mld->wiphy;
58
59
wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
60
wiphy->regulatory_flags |= REGULATORY_ENABLE_RELAX_NO_IR;
61
}
62
63
VISIBLE_IF_IWLWIFI_KUNIT
64
void iwl_construct_mld(struct iwl_mld *mld, struct iwl_trans *trans,
65
const struct iwl_rf_cfg *cfg, const struct iwl_fw *fw,
66
struct ieee80211_hw *hw, struct dentry *dbgfs_dir)
67
{
68
mld->dev = trans->dev;
69
mld->trans = trans;
70
mld->cfg = cfg;
71
mld->fw = fw;
72
mld->hw = hw;
73
mld->wiphy = hw->wiphy;
74
mld->debugfs_dir = dbgfs_dir;
75
76
iwl_notification_wait_init(&mld->notif_wait);
77
78
/* Setup async RX handling */
79
spin_lock_init(&mld->async_handlers_lock);
80
INIT_LIST_HEAD(&mld->async_handlers_list);
81
wiphy_work_init(&mld->async_handlers_wk,
82
iwl_mld_async_handlers_wk);
83
84
/* Dynamic Queue Allocation */
85
spin_lock_init(&mld->add_txqs_lock);
86
INIT_LIST_HEAD(&mld->txqs_to_add);
87
wiphy_work_init(&mld->add_txqs_wk, iwl_mld_add_txqs_wk);
88
89
/* Setup RX queues sync wait queue */
90
init_waitqueue_head(&mld->rxq_sync.waitq);
91
}
92
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_construct_mld);
93
94
static void __acquires(&mld->wiphy->mtx)
95
iwl_mld_fwrt_dump_start(void *ctx)
96
{
97
struct iwl_mld *mld = ctx;
98
99
wiphy_lock(mld->wiphy);
100
}
101
102
static void __releases(&mld->wiphy->mtx)
103
iwl_mld_fwrt_dump_end(void *ctx)
104
{
105
struct iwl_mld *mld = ctx;
106
107
wiphy_unlock(mld->wiphy);
108
}
109
110
static bool iwl_mld_d3_debug_enable(void *ctx)
111
{
112
return IWL_MLD_D3_DEBUG;
113
}
114
115
static int iwl_mld_fwrt_send_hcmd(void *ctx, struct iwl_host_cmd *host_cmd)
116
{
117
struct iwl_mld *mld = (struct iwl_mld *)ctx;
118
int ret;
119
120
wiphy_lock(mld->wiphy);
121
ret = iwl_mld_send_cmd(mld, host_cmd);
122
wiphy_unlock(mld->wiphy);
123
124
return ret;
125
}
126
127
static const struct iwl_fw_runtime_ops iwl_mld_fwrt_ops = {
128
.dump_start = iwl_mld_fwrt_dump_start,
129
.dump_end = iwl_mld_fwrt_dump_end,
130
.send_hcmd = iwl_mld_fwrt_send_hcmd,
131
.d3_debug_enable = iwl_mld_d3_debug_enable,
132
};
133
134
static void
135
iwl_mld_construct_fw_runtime(struct iwl_mld *mld, struct iwl_trans *trans,
136
const struct iwl_fw *fw,
137
struct dentry *debugfs_dir)
138
{
139
iwl_fw_runtime_init(&mld->fwrt, trans, fw, &iwl_mld_fwrt_ops, mld,
140
NULL, NULL, debugfs_dir);
141
142
iwl_fw_set_current_image(&mld->fwrt, IWL_UCODE_REGULAR);
143
}
144
145
/* Please keep this array *SORTED* by hex value.
146
* Access is done through binary search
147
*/
148
static const struct iwl_hcmd_names iwl_mld_legacy_names[] = {
149
HCMD_NAME(UCODE_ALIVE_NTFY),
150
HCMD_NAME(INIT_COMPLETE_NOTIF),
151
HCMD_NAME(PHY_CONTEXT_CMD),
152
HCMD_NAME(SCAN_CFG_CMD),
153
HCMD_NAME(SCAN_REQ_UMAC),
154
HCMD_NAME(SCAN_ABORT_UMAC),
155
HCMD_NAME(SCAN_COMPLETE_UMAC),
156
HCMD_NAME(TX_CMD),
157
HCMD_NAME(TXPATH_FLUSH),
158
HCMD_NAME(LEDS_CMD),
159
HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_NOTIFICATION),
160
HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION),
161
HCMD_NAME(SCAN_OFFLOAD_UPDATE_PROFILES_CMD),
162
HCMD_NAME(POWER_TABLE_CMD),
163
HCMD_NAME(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION),
164
HCMD_NAME(BEACON_NOTIFICATION),
165
HCMD_NAME(BEACON_TEMPLATE_CMD),
166
HCMD_NAME(TX_ANT_CONFIGURATION_CMD),
167
HCMD_NAME(REDUCE_TX_POWER_CMD),
168
HCMD_NAME(MISSED_BEACONS_NOTIFICATION),
169
HCMD_NAME(MAC_PM_POWER_TABLE),
170
HCMD_NAME(MFUART_LOAD_NOTIFICATION),
171
HCMD_NAME(RSS_CONFIG_CMD),
172
HCMD_NAME(SCAN_ITERATION_COMPLETE_UMAC),
173
HCMD_NAME(REPLY_RX_MPDU_CMD),
174
HCMD_NAME(BA_NOTIF),
175
HCMD_NAME(MCC_UPDATE_CMD),
176
HCMD_NAME(MCC_CHUB_UPDATE_CMD),
177
HCMD_NAME(MCAST_FILTER_CMD),
178
HCMD_NAME(REPLY_BEACON_FILTERING_CMD),
179
HCMD_NAME(PROT_OFFLOAD_CONFIG_CMD),
180
HCMD_NAME(MATCH_FOUND_NOTIFICATION),
181
HCMD_NAME(WOWLAN_PATTERNS),
182
HCMD_NAME(WOWLAN_CONFIGURATION),
183
HCMD_NAME(WOWLAN_TSC_RSC_PARAM),
184
HCMD_NAME(WOWLAN_KEK_KCK_MATERIAL),
185
HCMD_NAME(DEBUG_HOST_COMMAND),
186
HCMD_NAME(LDBG_CONFIG_CMD),
187
};
188
189
/* Please keep this array *SORTED* by hex value.
190
* Access is done through binary search
191
*/
192
static const struct iwl_hcmd_names iwl_mld_system_names[] = {
193
HCMD_NAME(SHARED_MEM_CFG_CMD),
194
HCMD_NAME(SOC_CONFIGURATION_CMD),
195
HCMD_NAME(INIT_EXTENDED_CFG_CMD),
196
HCMD_NAME(FW_ERROR_RECOVERY_CMD),
197
HCMD_NAME(RFI_CONFIG_CMD),
198
HCMD_NAME(RFI_GET_FREQ_TABLE_CMD),
199
HCMD_NAME(SYSTEM_STATISTICS_CMD),
200
HCMD_NAME(SYSTEM_STATISTICS_END_NOTIF),
201
};
202
203
/* Please keep this array *SORTED* by hex value.
204
* Access is done through binary search
205
*/
206
static const struct iwl_hcmd_names iwl_mld_reg_and_nvm_names[] = {
207
HCMD_NAME(LARI_CONFIG_CHANGE),
208
HCMD_NAME(NVM_GET_INFO),
209
HCMD_NAME(TAS_CONFIG),
210
HCMD_NAME(SAR_OFFSET_MAPPING_TABLE_CMD),
211
HCMD_NAME(MCC_ALLOWED_AP_TYPE_CMD),
212
};
213
214
/* Please keep this array *SORTED* by hex value.
215
* Access is done through binary search
216
*/
217
static const struct iwl_hcmd_names iwl_mld_debug_names[] = {
218
HCMD_NAME(HOST_EVENT_CFG),
219
HCMD_NAME(DBGC_SUSPEND_RESUME),
220
};
221
222
/* Please keep this array *SORTED* by hex value.
223
* Access is done through binary search
224
*/
225
static const struct iwl_hcmd_names iwl_mld_mac_conf_names[] = {
226
HCMD_NAME(LOW_LATENCY_CMD),
227
HCMD_NAME(SESSION_PROTECTION_CMD),
228
HCMD_NAME(MAC_CONFIG_CMD),
229
HCMD_NAME(LINK_CONFIG_CMD),
230
HCMD_NAME(STA_CONFIG_CMD),
231
HCMD_NAME(AUX_STA_CMD),
232
HCMD_NAME(STA_REMOVE_CMD),
233
HCMD_NAME(ROC_CMD),
234
HCMD_NAME(MISSED_BEACONS_NOTIF),
235
HCMD_NAME(EMLSR_TRANS_FAIL_NOTIF),
236
HCMD_NAME(ROC_NOTIF),
237
HCMD_NAME(CHANNEL_SWITCH_ERROR_NOTIF),
238
HCMD_NAME(SESSION_PROTECTION_NOTIF),
239
HCMD_NAME(PROBE_RESPONSE_DATA_NOTIF),
240
HCMD_NAME(CHANNEL_SWITCH_START_NOTIF),
241
};
242
243
/* Please keep this array *SORTED* by hex value.
244
* Access is done through binary search
245
*/
246
static const struct iwl_hcmd_names iwl_mld_data_path_names[] = {
247
HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD),
248
HCMD_NAME(WNM_PLATFORM_PTM_REQUEST_CMD),
249
HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_CONFIG_CMD),
250
HCMD_NAME(RFH_QUEUE_CONFIG_CMD),
251
HCMD_NAME(TLC_MNG_CONFIG_CMD),
252
HCMD_NAME(RX_BAID_ALLOCATION_CONFIG_CMD),
253
HCMD_NAME(SCD_QUEUE_CONFIG_CMD),
254
HCMD_NAME(ESR_MODE_NOTIF),
255
HCMD_NAME(MONITOR_NOTIF),
256
HCMD_NAME(TLC_MNG_UPDATE_NOTIF),
257
HCMD_NAME(BEACON_FILTER_IN_NOTIF),
258
HCMD_NAME(MU_GROUP_MGMT_NOTIF),
259
};
260
261
/* Please keep this array *SORTED* by hex value.
262
* Access is done through binary search
263
*/
264
static const struct iwl_hcmd_names iwl_mld_scan_names[] = {
265
HCMD_NAME(CHANNEL_SURVEY_NOTIF),
266
};
267
268
/* Please keep this array *SORTED* by hex value.
269
* Access is done through binary search
270
*/
271
static const struct iwl_hcmd_names iwl_mld_location_names[] = {
272
HCMD_NAME(TOF_RANGE_REQ_CMD),
273
HCMD_NAME(TOF_RANGE_RESPONSE_NOTIF),
274
};
275
276
/* Please keep this array *SORTED* by hex value.
277
* Access is done through binary search
278
*/
279
static const struct iwl_hcmd_names iwl_mld_phy_names[] = {
280
HCMD_NAME(CMD_DTS_MEASUREMENT_TRIGGER_WIDE),
281
HCMD_NAME(CTDP_CONFIG_CMD),
282
HCMD_NAME(TEMP_REPORTING_THRESHOLDS_CMD),
283
HCMD_NAME(PER_CHAIN_LIMIT_OFFSET_CMD),
284
HCMD_NAME(CT_KILL_NOTIFICATION),
285
HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE),
286
};
287
288
/* Please keep this array *SORTED* by hex value.
289
* Access is done through binary search
290
*/
291
static const struct iwl_hcmd_names iwl_mld_statistics_names[] = {
292
HCMD_NAME(STATISTICS_OPER_NOTIF),
293
HCMD_NAME(STATISTICS_OPER_PART1_NOTIF),
294
};
295
296
/* Please keep this array *SORTED* by hex value.
297
* Access is done through binary search
298
*/
299
static const struct iwl_hcmd_names iwl_mld_prot_offload_names[] = {
300
HCMD_NAME(WOWLAN_WAKE_PKT_NOTIFICATION),
301
HCMD_NAME(WOWLAN_INFO_NOTIFICATION),
302
HCMD_NAME(D3_END_NOTIFICATION),
303
};
304
305
/* Please keep this array *SORTED* by hex value.
306
* Access is done through binary search
307
*/
308
static const struct iwl_hcmd_names iwl_mld_coex_names[] = {
309
HCMD_NAME(PROFILE_NOTIF),
310
};
311
312
VISIBLE_IF_IWLWIFI_KUNIT
313
const struct iwl_hcmd_arr iwl_mld_groups[] = {
314
[LEGACY_GROUP] = HCMD_ARR(iwl_mld_legacy_names),
315
[LONG_GROUP] = HCMD_ARR(iwl_mld_legacy_names),
316
[SYSTEM_GROUP] = HCMD_ARR(iwl_mld_system_names),
317
[MAC_CONF_GROUP] = HCMD_ARR(iwl_mld_mac_conf_names),
318
[DATA_PATH_GROUP] = HCMD_ARR(iwl_mld_data_path_names),
319
[SCAN_GROUP] = HCMD_ARR(iwl_mld_scan_names),
320
[LOCATION_GROUP] = HCMD_ARR(iwl_mld_location_names),
321
[REGULATORY_AND_NVM_GROUP] = HCMD_ARR(iwl_mld_reg_and_nvm_names),
322
[DEBUG_GROUP] = HCMD_ARR(iwl_mld_debug_names),
323
[PHY_OPS_GROUP] = HCMD_ARR(iwl_mld_phy_names),
324
[STATISTICS_GROUP] = HCMD_ARR(iwl_mld_statistics_names),
325
[PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mld_prot_offload_names),
326
[BT_COEX_GROUP] = HCMD_ARR(iwl_mld_coex_names),
327
};
328
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_groups);
329
330
#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
331
const unsigned int global_iwl_mld_goups_size = ARRAY_SIZE(iwl_mld_groups);
332
EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(global_iwl_mld_goups_size);
333
#endif
334
335
static void
336
iwl_mld_configure_trans(struct iwl_op_mode *op_mode)
337
{
338
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
339
static const u8 no_reclaim_cmds[] = {TX_CMD};
340
struct iwl_trans *trans = mld->trans;
341
u32 eckv_value;
342
343
iwl_bios_setup_step(trans, &mld->fwrt);
344
iwl_uefi_get_step_table(trans);
345
346
if (iwl_bios_get_eckv(&mld->fwrt, &eckv_value))
347
IWL_DEBUG_RADIO(mld, "ECKV table doesn't exist in BIOS\n");
348
else
349
trans->conf.ext_32khz_clock_valid = !!eckv_value;
350
351
trans->conf.rx_buf_size = iwl_amsdu_size_to_rxb_size();
352
trans->conf.command_groups = iwl_mld_groups;
353
trans->conf.command_groups_size = ARRAY_SIZE(iwl_mld_groups);
354
trans->conf.fw_reset_handshake = true;
355
trans->conf.queue_alloc_cmd_ver =
356
iwl_fw_lookup_cmd_ver(mld->fw, WIDE_ID(DATA_PATH_GROUP,
357
SCD_QUEUE_CONFIG_CMD),
358
0);
359
trans->conf.cb_data_offs = offsetof(struct ieee80211_tx_info,
360
driver_data[2]);
361
BUILD_BUG_ON(sizeof(no_reclaim_cmds) >
362
sizeof(trans->conf.no_reclaim_cmds));
363
memcpy(trans->conf.no_reclaim_cmds, no_reclaim_cmds,
364
sizeof(no_reclaim_cmds));
365
trans->conf.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
366
367
trans->conf.rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
368
trans->conf.rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_desc);
369
trans->conf.wide_cmd_header = true;
370
371
iwl_trans_op_mode_enter(trans, op_mode);
372
}
373
374
/*
375
*****************************************************
376
* op mode ops functions
377
*****************************************************
378
*/
379
380
#define NUM_FW_LOAD_RETRIES 3
381
static struct iwl_op_mode *
382
iwl_op_mode_mld_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
383
const struct iwl_fw *fw, struct dentry *dbgfs_dir)
384
{
385
struct ieee80211_hw *hw;
386
struct iwl_op_mode *op_mode;
387
struct iwl_mld *mld;
388
int ret;
389
390
/* Allocate and initialize a new hardware device */
391
hw = ieee80211_alloc_hw(sizeof(struct iwl_op_mode) +
392
sizeof(struct iwl_mld),
393
&iwl_mld_hw_ops);
394
if (!hw)
395
return ERR_PTR(-ENOMEM);
396
397
op_mode = hw->priv;
398
399
op_mode->ops = &iwl_mld_ops;
400
401
mld = IWL_OP_MODE_GET_MLD(op_mode);
402
403
iwl_construct_mld(mld, trans, cfg, fw, hw, dbgfs_dir);
404
405
/* we'll verify later it matches between commands */
406
mld->fw_rates_ver_3 = iwl_fw_lookup_cmd_ver(mld->fw, TX_CMD, 0) >= 11;
407
408
iwl_mld_construct_fw_runtime(mld, trans, fw, dbgfs_dir);
409
410
iwl_mld_get_bios_tables(mld);
411
iwl_uefi_get_sgom_table(trans, &mld->fwrt);
412
mld->bios_enable_puncturing = iwl_uefi_get_puncturing(&mld->fwrt);
413
414
iwl_mld_hw_set_regulatory(mld);
415
416
/* Configure transport layer with the opmode specific params */
417
iwl_mld_configure_trans(op_mode);
418
419
/* needed for regulatory init */
420
rtnl_lock();
421
/* Needed for sending commands */
422
wiphy_lock(mld->wiphy);
423
424
for (int i = 0; i < NUM_FW_LOAD_RETRIES; i++) {
425
ret = iwl_mld_load_fw(mld);
426
if (!ret)
427
break;
428
}
429
430
if (!ret) {
431
mld->nvm_data = iwl_get_nvm(mld->trans, mld->fw, 0, 0);
432
if (IS_ERR(mld->nvm_data)) {
433
IWL_ERR(mld, "Failed to read NVM: %d\n", ret);
434
ret = PTR_ERR(mld->nvm_data);
435
}
436
}
437
438
if (ret) {
439
wiphy_unlock(mld->wiphy);
440
rtnl_unlock();
441
goto err;
442
}
443
444
/* We are about to stop the FW. Notifications may require an
445
* operational FW, so handle them all here before we stop.
446
*/
447
wiphy_work_flush(mld->wiphy, &mld->async_handlers_wk);
448
449
iwl_mld_stop_fw(mld);
450
451
wiphy_unlock(mld->wiphy);
452
rtnl_unlock();
453
454
ret = iwl_mld_leds_init(mld);
455
if (ret)
456
goto free_nvm;
457
458
ret = iwl_mld_alloc_scan_cmd(mld);
459
if (ret)
460
goto leds_exit;
461
462
ret = iwl_mld_low_latency_init(mld);
463
if (ret)
464
goto free_scan_cmd;
465
466
ret = iwl_mld_register_hw(mld);
467
if (ret)
468
goto low_latency_free;
469
470
iwl_mld_toggle_tx_ant(mld, &mld->mgmt_tx_ant);
471
472
iwl_mld_add_debugfs_files(mld, dbgfs_dir);
473
iwl_mld_thermal_initialize(mld);
474
475
iwl_mld_ptp_init(mld);
476
477
return op_mode;
478
479
low_latency_free:
480
iwl_mld_low_latency_free(mld);
481
free_scan_cmd:
482
kfree(mld->scan.cmd);
483
leds_exit:
484
iwl_mld_leds_exit(mld);
485
free_nvm:
486
kfree(mld->nvm_data);
487
err:
488
iwl_trans_op_mode_leave(mld->trans);
489
ieee80211_free_hw(mld->hw);
490
return ERR_PTR(ret);
491
}
492
493
static void
494
iwl_op_mode_mld_stop(struct iwl_op_mode *op_mode)
495
{
496
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
497
498
iwl_mld_ptp_remove(mld);
499
iwl_mld_leds_exit(mld);
500
501
iwl_mld_thermal_exit(mld);
502
503
wiphy_lock(mld->wiphy);
504
iwl_mld_low_latency_stop(mld);
505
iwl_mld_deinit_time_sync(mld);
506
wiphy_unlock(mld->wiphy);
507
508
ieee80211_unregister_hw(mld->hw);
509
510
iwl_fw_runtime_free(&mld->fwrt);
511
iwl_mld_low_latency_free(mld);
512
513
iwl_trans_op_mode_leave(mld->trans);
514
515
kfree(mld->nvm_data);
516
kfree(mld->scan.cmd);
517
kfree(mld->channel_survey);
518
kfree(mld->error_recovery_buf);
519
kfree(mld->mcast_filter_cmd);
520
521
ieee80211_free_hw(mld->hw);
522
}
523
524
static void iwl_mld_queue_state_change(struct iwl_op_mode *op_mode,
525
int hw_queue, bool queue_full)
526
{
527
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
528
struct ieee80211_txq *txq;
529
struct iwl_mld_sta *mld_sta;
530
struct iwl_mld_txq *mld_txq;
531
532
rcu_read_lock();
533
534
txq = rcu_dereference(mld->fw_id_to_txq[hw_queue]);
535
if (!txq) {
536
rcu_read_unlock();
537
538
if (queue_full) {
539
/* An internal queue is not expected to become full */
540
IWL_WARN(mld,
541
"Internal hw_queue %d is full! stopping all queues\n",
542
hw_queue);
543
/* Stop all queues, as an internal queue is not
544
* mapped to a mac80211 one
545
*/
546
ieee80211_stop_queues(mld->hw);
547
} else {
548
ieee80211_wake_queues(mld->hw);
549
}
550
551
return;
552
}
553
554
mld_txq = iwl_mld_txq_from_mac80211(txq);
555
mld_sta = txq->sta ? iwl_mld_sta_from_mac80211(txq->sta) : NULL;
556
557
mld_txq->status.stop_full = queue_full;
558
559
if (!queue_full && mld_sta &&
560
mld_sta->sta_state != IEEE80211_STA_NOTEXIST) {
561
local_bh_disable();
562
iwl_mld_tx_from_txq(mld, txq);
563
local_bh_enable();
564
}
565
566
rcu_read_unlock();
567
}
568
569
static void
570
iwl_mld_queue_full(struct iwl_op_mode *op_mode, int hw_queue)
571
{
572
iwl_mld_queue_state_change(op_mode, hw_queue, true);
573
}
574
575
static void
576
iwl_mld_queue_not_full(struct iwl_op_mode *op_mode, int hw_queue)
577
{
578
iwl_mld_queue_state_change(op_mode, hw_queue, false);
579
}
580
581
static bool
582
iwl_mld_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
583
{
584
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
585
586
iwl_mld_set_hwkill(mld, state);
587
588
return false;
589
}
590
591
static void
592
iwl_mld_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
593
{
594
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
595
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
596
597
iwl_trans_free_tx_cmd(mld->trans, info->driver_data[1]);
598
ieee80211_free_txskb(mld->hw, skb);
599
}
600
601
static void iwl_mld_read_error_recovery_buffer(struct iwl_mld *mld)
602
{
603
u32 src_size = mld->fw->ucode_capa.error_log_size;
604
u32 src_addr = mld->fw->ucode_capa.error_log_addr;
605
u8 *recovery_buf;
606
int ret;
607
608
/* no recovery buffer size defined in a TLV */
609
if (!src_size)
610
return;
611
612
recovery_buf = kzalloc(src_size, GFP_ATOMIC);
613
if (!recovery_buf)
614
return;
615
616
ret = iwl_trans_read_mem_bytes(mld->trans, src_addr,
617
recovery_buf, src_size);
618
if (ret) {
619
IWL_ERR(mld, "Failed to read error recovery buffer (%d)\n",
620
ret);
621
kfree(recovery_buf);
622
return;
623
}
624
625
mld->error_recovery_buf = recovery_buf;
626
}
627
628
static void iwl_mld_restart_nic(struct iwl_mld *mld)
629
{
630
iwl_mld_read_error_recovery_buffer(mld);
631
632
mld->fwrt.trans->dbg.restart_required = false;
633
634
ieee80211_restart_hw(mld->hw);
635
}
636
637
static void
638
iwl_mld_nic_error(struct iwl_op_mode *op_mode,
639
enum iwl_fw_error_type type)
640
{
641
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
642
bool trans_dead = iwl_trans_is_dead(mld->trans);
643
644
if (type == IWL_ERR_TYPE_CMD_QUEUE_FULL)
645
IWL_ERR(mld, "Command queue full!\n");
646
else if (!trans_dead && !mld->fw_status.do_not_dump_once)
647
iwl_fwrt_dump_error_logs(&mld->fwrt);
648
649
mld->fw_status.do_not_dump_once = false;
650
651
/* It is necessary to abort any os scan here because mac80211 requires
652
* having the scan cleared before restarting.
653
* We'll reset the scan_status to NONE in restart cleanup in
654
* the next drv_start() call from mac80211. If ieee80211_hw_restart
655
* isn't called scan status will stay busy.
656
*/
657
iwl_mld_report_scan_aborted(mld);
658
659
/*
660
* This should be first thing before trying to collect any
661
* data to avoid endless loops if any HW error happens while
662
* collecting debug data.
663
* It might not actually be true that we'll restart, but the
664
* setting doesn't matter if we're going to be unbound either.
665
*/
666
if (type != IWL_ERR_TYPE_RESET_HS_TIMEOUT &&
667
mld->fw_status.running)
668
mld->fw_status.in_hw_restart = true;
669
}
670
671
static void iwl_mld_dump_error(struct iwl_op_mode *op_mode,
672
struct iwl_fw_error_dump_mode *mode)
673
{
674
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
675
676
/* if we come in from opmode we have the mutex held */
677
if (mode->context == IWL_ERR_CONTEXT_FROM_OPMODE) {
678
lockdep_assert_wiphy(mld->wiphy);
679
iwl_fw_error_collect(&mld->fwrt);
680
} else {
681
wiphy_lock(mld->wiphy);
682
if (mode->context != IWL_ERR_CONTEXT_ABORT)
683
iwl_fw_error_collect(&mld->fwrt);
684
wiphy_unlock(mld->wiphy);
685
}
686
}
687
688
static bool iwl_mld_sw_reset(struct iwl_op_mode *op_mode,
689
enum iwl_fw_error_type type)
690
{
691
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
692
693
/* SW reset can happen for TOP error w/o NIC error, so
694
* also abort scan here and set in_hw_restart, when we
695
* had a NIC error both were already done.
696
*/
697
iwl_mld_report_scan_aborted(mld);
698
mld->fw_status.in_hw_restart = true;
699
700
/* Do restart only in the following conditions are met:
701
* - we consider the FW as running
702
* - The trigger that brought us here is defined as one that requires
703
* a restart (in the debug TLVs)
704
*/
705
if (!mld->fw_status.running || !mld->fwrt.trans->dbg.restart_required)
706
return false;
707
708
iwl_mld_restart_nic(mld);
709
return true;
710
}
711
712
static void
713
iwl_mld_time_point(struct iwl_op_mode *op_mode,
714
enum iwl_fw_ini_time_point tp_id,
715
union iwl_dbg_tlv_tp_data *tp_data)
716
{
717
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
718
719
iwl_dbg_tlv_time_point(&mld->fwrt, tp_id, tp_data);
720
}
721
722
#ifdef CONFIG_PM_SLEEP
723
static void iwl_mld_device_powered_off(struct iwl_op_mode *op_mode)
724
{
725
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
726
727
wiphy_lock(mld->wiphy);
728
iwl_mld_stop_fw(mld);
729
mld->fw_status.in_d3 = false;
730
wiphy_unlock(mld->wiphy);
731
}
732
#else
733
static void iwl_mld_device_powered_off(struct iwl_op_mode *op_mode)
734
{}
735
#endif
736
737
static void iwl_mld_dump(struct iwl_op_mode *op_mode)
738
{
739
struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
740
struct iwl_fw_runtime *fwrt = &mld->fwrt;
741
742
if (!iwl_trans_fw_running(fwrt->trans))
743
return;
744
745
iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER, NULL);
746
}
747
748
static const struct iwl_op_mode_ops iwl_mld_ops = {
749
.start = iwl_op_mode_mld_start,
750
.stop = iwl_op_mode_mld_stop,
751
.rx = iwl_mld_rx,
752
.rx_rss = iwl_mld_rx_rss,
753
.queue_full = iwl_mld_queue_full,
754
.queue_not_full = iwl_mld_queue_not_full,
755
.hw_rf_kill = iwl_mld_set_hw_rfkill_state,
756
.free_skb = iwl_mld_free_skb,
757
.nic_error = iwl_mld_nic_error,
758
.dump_error = iwl_mld_dump_error,
759
.sw_reset = iwl_mld_sw_reset,
760
.time_point = iwl_mld_time_point,
761
.device_powered_off = pm_sleep_ptr(iwl_mld_device_powered_off),
762
.dump = iwl_mld_dump,
763
};
764
765
struct iwl_mld_mod_params iwlmld_mod_params = {
766
.power_scheme = IWL_POWER_SCHEME_BPS,
767
};
768
769
module_param_named(power_scheme, iwlmld_mod_params.power_scheme, int, 0444);
770
MODULE_PARM_DESC(power_scheme,
771
"power management scheme: 1-active, 2-balanced, default: 2");
772
773