xref: /linux/drivers/net/wireless/intel/iwlwifi/mld/mld.c (revision a40ad60a47f7c904b75a9ff83b39edebf3961c85)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /*
3  * Copyright (C) 2024-2026 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(REPLY_ERROR),
151 	HCMD_NAME(INIT_COMPLETE_NOTIF),
152 	HCMD_NAME(PHY_CONTEXT_CMD),
153 	HCMD_NAME(SCAN_CFG_CMD),
154 	HCMD_NAME(SCAN_REQ_UMAC),
155 	HCMD_NAME(SCAN_ABORT_UMAC),
156 	HCMD_NAME(SCAN_COMPLETE_UMAC),
157 	HCMD_NAME(TX_CMD),
158 	HCMD_NAME(TXPATH_FLUSH),
159 	HCMD_NAME(LEDS_CMD),
160 	HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_NOTIFICATION),
161 	HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_CONFIRM_NOTIFICATION),
162 	HCMD_NAME(PHY_CONFIGURATION_CMD),
163 	HCMD_NAME(SCAN_OFFLOAD_UPDATE_PROFILES_CMD),
164 	HCMD_NAME(POWER_TABLE_CMD),
165 	HCMD_NAME(BEACON_NOTIFICATION),
166 	HCMD_NAME(BEACON_TEMPLATE_CMD),
167 	HCMD_NAME(TX_ANT_CONFIGURATION_CMD),
168 	HCMD_NAME(BT_CONFIG),
169 	HCMD_NAME(REDUCE_TX_POWER_CMD),
170 	HCMD_NAME(MISSED_BEACONS_NOTIFICATION),
171 	HCMD_NAME(MAC_PM_POWER_TABLE),
172 	HCMD_NAME(MFUART_LOAD_NOTIFICATION),
173 	HCMD_NAME(SCAN_START_NOTIFICATION_UMAC),
174 	HCMD_NAME(RSS_CONFIG_CMD),
175 	HCMD_NAME(SCAN_ITERATION_COMPLETE_UMAC),
176 	HCMD_NAME(REPLY_RX_MPDU_CMD),
177 	HCMD_NAME(BA_NOTIF),
178 	HCMD_NAME(MCC_UPDATE_CMD),
179 	HCMD_NAME(MCC_CHUB_UPDATE_CMD),
180 	HCMD_NAME(MCAST_FILTER_CMD),
181 	HCMD_NAME(REPLY_BEACON_FILTERING_CMD),
182 	HCMD_NAME(PROT_OFFLOAD_CONFIG_CMD),
183 	HCMD_NAME(MATCH_FOUND_NOTIFICATION),
184 	HCMD_NAME(WOWLAN_PATTERNS),
185 	HCMD_NAME(WOWLAN_CONFIGURATION),
186 	HCMD_NAME(WOWLAN_TSC_RSC_PARAM),
187 	HCMD_NAME(WOWLAN_KEK_KCK_MATERIAL),
188 	HCMD_NAME(DEBUG_HOST_COMMAND),
189 	HCMD_NAME(LDBG_CONFIG_CMD),
190 };
191 
192 /* Please keep this array *SORTED* by hex value.
193  * Access is done through binary search
194  */
195 static const struct iwl_hcmd_names iwl_mld_system_names[] = {
196 	HCMD_NAME(SHARED_MEM_CFG_CMD),
197 	HCMD_NAME(SOC_CONFIGURATION_CMD),
198 	HCMD_NAME(INIT_EXTENDED_CFG_CMD),
199 	HCMD_NAME(FW_ERROR_RECOVERY_CMD),
200 	HCMD_NAME(RFI_CONFIG_CMD),
201 	HCMD_NAME(RFI_GET_FREQ_TABLE_CMD),
202 	HCMD_NAME(SYSTEM_STATISTICS_CMD),
203 	HCMD_NAME(SYSTEM_STATISTICS_END_NOTIF),
204 };
205 
206 /* Please keep this array *SORTED* by hex value.
207  * Access is done through binary search
208  */
209 static const struct iwl_hcmd_names iwl_mld_reg_and_nvm_names[] = {
210 	HCMD_NAME(LARI_CONFIG_CHANGE),
211 	HCMD_NAME(NVM_GET_INFO),
212 	HCMD_NAME(TAS_CONFIG),
213 	HCMD_NAME(SAR_OFFSET_MAPPING_TABLE_CMD),
214 	HCMD_NAME(MCC_ALLOWED_AP_TYPE_CMD),
215 };
216 
217 /* Please keep this array *SORTED* by hex value.
218  * Access is done through binary search
219  */
220 static const struct iwl_hcmd_names iwl_mld_debug_names[] = {
221 	HCMD_NAME(HOST_EVENT_CFG),
222 	HCMD_NAME(DBGC_SUSPEND_RESUME),
223 };
224 
225 /* Please keep this array *SORTED* by hex value.
226  * Access is done through binary search
227  */
228 static const struct iwl_hcmd_names iwl_mld_mac_conf_names[] = {
229 	HCMD_NAME(LOW_LATENCY_CMD),
230 	HCMD_NAME(SESSION_PROTECTION_CMD),
231 	HCMD_NAME(MAC_CONFIG_CMD),
232 	HCMD_NAME(LINK_CONFIG_CMD),
233 	HCMD_NAME(STA_CONFIG_CMD),
234 	HCMD_NAME(AUX_STA_CMD),
235 	HCMD_NAME(STA_REMOVE_CMD),
236 	HCMD_NAME(ROC_CMD),
237 	HCMD_NAME(NAN_CFG_CMD),
238 	HCMD_NAME(NAN_SCHEDULE_CMD),
239 	HCMD_NAME(NAN_PEER_CMD),
240 	HCMD_NAME(NAN_ULW_ATTR_NOTIF),
241 	HCMD_NAME(NAN_SCHED_UPDATE_COMPLETED_NOTIF),
242 	HCMD_NAME(NAN_DW_END_NOTIF),
243 	HCMD_NAME(NAN_JOINED_CLUSTER_NOTIF),
244 	HCMD_NAME(MISSED_BEACONS_NOTIF),
245 	HCMD_NAME(EMLSR_TRANS_FAIL_NOTIF),
246 	HCMD_NAME(ROC_NOTIF),
247 	HCMD_NAME(CHANNEL_SWITCH_ERROR_NOTIF),
248 	HCMD_NAME(SESSION_PROTECTION_NOTIF),
249 	HCMD_NAME(PROBE_RESPONSE_DATA_NOTIF),
250 	HCMD_NAME(CHANNEL_SWITCH_START_NOTIF),
251 };
252 
253 /* Please keep this array *SORTED* by hex value.
254  * Access is done through binary search
255  */
256 static const struct iwl_hcmd_names iwl_mld_data_path_names[] = {
257 	HCMD_NAME(TRIGGER_RX_QUEUES_NOTIF_CMD),
258 	HCMD_NAME(WNM_PLATFORM_PTM_REQUEST_CMD),
259 	HCMD_NAME(WNM_80211V_TIMING_MEASUREMENT_CONFIG_CMD),
260 	HCMD_NAME(RFH_QUEUE_CONFIG_CMD),
261 	HCMD_NAME(TLC_MNG_CONFIG_CMD),
262 	HCMD_NAME(RX_BAID_ALLOCATION_CONFIG_CMD),
263 	HCMD_NAME(SCD_QUEUE_CONFIG_CMD),
264 	HCMD_NAME(SEC_KEY_CMD),
265 	HCMD_NAME(RSC_NOTIF),
266 	HCMD_NAME(ESR_MODE_NOTIF),
267 	HCMD_NAME(MONITOR_NOTIF),
268 	HCMD_NAME(TLC_MNG_UPDATE_NOTIF),
269 	HCMD_NAME(BEACON_FILTER_IN_NOTIF),
270 	HCMD_NAME(PHY_AIR_SNIFFER_NOTIF),
271 	HCMD_NAME(MU_GROUP_MGMT_NOTIF),
272 };
273 
274 /* Please keep this array *SORTED* by hex value.
275  * Access is done through binary search
276  */
277 static const struct iwl_hcmd_names iwl_mld_scan_names[] = {
278 	HCMD_NAME(CHANNEL_SURVEY_NOTIF),
279 };
280 
281 /* Please keep this array *SORTED* by hex value.
282  * Access is done through binary search
283  */
284 static const struct iwl_hcmd_names iwl_mld_location_names[] = {
285 	HCMD_NAME(TOF_RANGE_REQ_CMD),
286 	HCMD_NAME(TOF_RANGE_RESPONSE_NOTIF),
287 };
288 
289 /* Please keep this array *SORTED* by hex value.
290  * Access is done through binary search
291  */
292 static const struct iwl_hcmd_names iwl_mld_phy_names[] = {
293 	HCMD_NAME(CMD_DTS_MEASUREMENT_TRIGGER_WIDE),
294 	HCMD_NAME(CTDP_CONFIG_CMD),
295 	HCMD_NAME(TEMP_REPORTING_THRESHOLDS_CMD),
296 	HCMD_NAME(PER_CHAIN_LIMIT_OFFSET_CMD),
297 	HCMD_NAME(CT_KILL_NOTIFICATION),
298 	HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE),
299 };
300 
301 /* Please keep this array *SORTED* by hex value.
302  * Access is done through binary search
303  */
304 static const struct iwl_hcmd_names iwl_mld_statistics_names[] = {
305 	HCMD_NAME(STATISTICS_OPER_NOTIF),
306 	HCMD_NAME(STATISTICS_OPER_PART1_NOTIF),
307 };
308 
309 /* Please keep this array *SORTED* by hex value.
310  * Access is done through binary search
311  */
312 static const struct iwl_hcmd_names iwl_mld_prot_offload_names[] = {
313 	HCMD_NAME(WOWLAN_WAKE_PKT_NOTIFICATION),
314 	HCMD_NAME(WOWLAN_INFO_NOTIFICATION),
315 	HCMD_NAME(D3_END_NOTIFICATION),
316 };
317 
318 /* Please keep this array *SORTED* by hex value.
319  * Access is done through binary search
320  */
321 static const struct iwl_hcmd_names iwl_mld_coex_names[] = {
322 	HCMD_NAME(PROFILE_NOTIF),
323 };
324 
325 VISIBLE_IF_IWLWIFI_KUNIT
326 const struct iwl_hcmd_arr iwl_mld_groups[] = {
327 	[LEGACY_GROUP] = HCMD_ARR(iwl_mld_legacy_names),
328 	[LONG_GROUP] = HCMD_ARR(iwl_mld_legacy_names),
329 	[SYSTEM_GROUP] = HCMD_ARR(iwl_mld_system_names),
330 	[MAC_CONF_GROUP] = HCMD_ARR(iwl_mld_mac_conf_names),
331 	[DATA_PATH_GROUP] = HCMD_ARR(iwl_mld_data_path_names),
332 	[SCAN_GROUP] = HCMD_ARR(iwl_mld_scan_names),
333 	[LOCATION_GROUP] = HCMD_ARR(iwl_mld_location_names),
334 	[REGULATORY_AND_NVM_GROUP] = HCMD_ARR(iwl_mld_reg_and_nvm_names),
335 	[DEBUG_GROUP] = HCMD_ARR(iwl_mld_debug_names),
336 	[PHY_OPS_GROUP] = HCMD_ARR(iwl_mld_phy_names),
337 	[STATISTICS_GROUP] = HCMD_ARR(iwl_mld_statistics_names),
338 	[PROT_OFFLOAD_GROUP] = HCMD_ARR(iwl_mld_prot_offload_names),
339 	[BT_COEX_GROUP] = HCMD_ARR(iwl_mld_coex_names),
340 };
341 EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_groups);
342 
343 #if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
344 const unsigned int global_iwl_mld_goups_size = ARRAY_SIZE(iwl_mld_groups);
345 EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(global_iwl_mld_goups_size);
346 #endif
347 
348 static void
349 iwl_mld_configure_trans(struct iwl_op_mode *op_mode)
350 {
351 	struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
352 	static const u8 no_reclaim_cmds[] = {TX_CMD};
353 	struct iwl_trans *trans = mld->trans;
354 	u32 eckv_value;
355 
356 	iwl_bios_setup_step(trans, &mld->fwrt);
357 	iwl_uefi_get_step_table(trans);
358 
359 	if (iwl_bios_get_eckv(&mld->fwrt, &eckv_value))
360 		IWL_DEBUG_RADIO(mld, "ECKV table doesn't exist in BIOS\n");
361 	else
362 		trans->conf.ext_32khz_clock_valid = !!eckv_value;
363 
364 	trans->conf.rx_buf_size = iwl_amsdu_size_to_rxb_size();
365 	trans->conf.command_groups = iwl_mld_groups;
366 	trans->conf.command_groups_size = ARRAY_SIZE(iwl_mld_groups);
367 	trans->conf.fw_reset_handshake = true;
368 	trans->conf.queue_alloc_cmd_ver =
369 		iwl_fw_lookup_cmd_ver(mld->fw, WIDE_ID(DATA_PATH_GROUP,
370 						       SCD_QUEUE_CONFIG_CMD),
371 				      0);
372 	trans->conf.cb_data_offs = offsetof(struct ieee80211_tx_info,
373 					    driver_data[2]);
374 	BUILD_BUG_ON(sizeof(no_reclaim_cmds) >
375 		     sizeof(trans->conf.no_reclaim_cmds));
376 	memcpy(trans->conf.no_reclaim_cmds, no_reclaim_cmds,
377 	       sizeof(no_reclaim_cmds));
378 	trans->conf.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
379 
380 	trans->conf.rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
381 	trans->conf.rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_desc);
382 	trans->conf.wide_cmd_header = true;
383 
384 	iwl_trans_op_mode_enter(trans, op_mode);
385 }
386 
387 /*
388  *****************************************************
389  * op mode ops functions
390  *****************************************************
391  */
392 
393 #define NUM_FW_LOAD_RETRIES	3
394 static struct iwl_op_mode *
395 iwl_op_mode_mld_start(struct iwl_trans *trans, const struct iwl_rf_cfg *cfg,
396 		      const struct iwl_fw *fw, struct dentry *dbgfs_dir)
397 {
398 	struct ieee80211_hw *hw;
399 	struct iwl_op_mode *op_mode;
400 	struct iwl_mld *mld;
401 	int ret;
402 
403 	/* Allocate and initialize a new hardware device */
404 	hw = ieee80211_alloc_hw(sizeof(struct iwl_op_mode) +
405 				sizeof(struct iwl_mld),
406 				&iwl_mld_hw_ops);
407 	if (!hw)
408 		return ERR_PTR(-ENOMEM);
409 
410 	op_mode = hw->priv;
411 
412 	op_mode->ops = &iwl_mld_ops;
413 
414 	mld = IWL_OP_MODE_GET_MLD(op_mode);
415 
416 	iwl_construct_mld(mld, trans, cfg, fw, hw, dbgfs_dir);
417 
418 	iwl_mld_construct_fw_runtime(mld, trans, fw, dbgfs_dir);
419 
420 	iwl_mld_get_bios_tables(mld);
421 	iwl_uefi_get_sgom_table(trans, &mld->fwrt);
422 	mld->bios_enable_puncturing = iwl_uefi_get_puncturing(&mld->fwrt);
423 
424 	iwl_mld_hw_set_regulatory(mld);
425 
426 	/* Configure transport layer with the opmode specific params */
427 	iwl_mld_configure_trans(op_mode);
428 
429 	/* needed for regulatory init */
430 	rtnl_lock();
431 	/* Needed for sending commands */
432 	wiphy_lock(mld->wiphy);
433 
434 	for (int i = 0; i < NUM_FW_LOAD_RETRIES; i++) {
435 		ret = iwl_mld_load_fw(mld);
436 		if (!ret)
437 			break;
438 	}
439 
440 	if (!ret) {
441 		mld->nvm_data = iwl_get_nvm(mld->trans, mld->fw, 0, 0);
442 		if (IS_ERR(mld->nvm_data)) {
443 			IWL_ERR(mld, "Failed to read NVM: %d\n", ret);
444 			ret = PTR_ERR(mld->nvm_data);
445 		}
446 	}
447 
448 	if (ret) {
449 		wiphy_unlock(mld->wiphy);
450 		rtnl_unlock();
451 		goto err;
452 	}
453 
454 	/* We are about to stop the FW. Notifications may require an
455 	 * operational FW, so handle them all here before we stop.
456 	 */
457 	wiphy_work_flush(mld->wiphy, &mld->async_handlers_wk);
458 
459 	iwl_mld_stop_fw(mld);
460 
461 	wiphy_unlock(mld->wiphy);
462 	rtnl_unlock();
463 
464 	ret = iwl_mld_leds_init(mld);
465 	if (ret)
466 		goto free_nvm;
467 
468 	ret = iwl_mld_alloc_scan_cmd(mld);
469 	if (ret)
470 		goto leds_exit;
471 
472 	ret = iwl_mld_low_latency_init(mld);
473 	if (ret)
474 		goto free_scan_cmd;
475 
476 	ret = iwl_mld_register_hw(mld);
477 	if (ret)
478 		goto low_latency_free;
479 
480 	iwl_mld_toggle_tx_ant(mld, &mld->mgmt_tx_ant);
481 
482 	iwl_mld_add_debugfs_files(mld, dbgfs_dir);
483 	iwl_mld_thermal_initialize(mld);
484 
485 	iwl_mld_ptp_init(mld);
486 
487 	return op_mode;
488 
489 low_latency_free:
490 	iwl_mld_low_latency_free(mld);
491 free_scan_cmd:
492 	kfree(mld->scan.cmd);
493 leds_exit:
494 	iwl_mld_leds_exit(mld);
495 free_nvm:
496 	kfree(mld->nvm_data);
497 err:
498 	iwl_trans_op_mode_leave(mld->trans);
499 	ieee80211_free_hw(mld->hw);
500 	return ERR_PTR(ret);
501 }
502 
503 static void
504 iwl_op_mode_mld_stop(struct iwl_op_mode *op_mode)
505 {
506 	struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
507 
508 	iwl_mld_ptp_remove(mld);
509 	iwl_mld_leds_exit(mld);
510 
511 	iwl_mld_thermal_exit(mld);
512 
513 	wiphy_lock(mld->wiphy);
514 	iwl_mld_low_latency_stop(mld);
515 	iwl_mld_deinit_time_sync(mld);
516 	wiphy_unlock(mld->wiphy);
517 
518 	ieee80211_unregister_hw(mld->hw);
519 
520 	iwl_fw_runtime_free(&mld->fwrt);
521 	iwl_mld_low_latency_free(mld);
522 
523 	iwl_trans_op_mode_leave(mld->trans);
524 
525 	kfree(mld->nvm_data);
526 	kfree(mld->scan.cmd);
527 	kfree(mld->channel_survey);
528 	kfree(mld->error_recovery_buf);
529 	kfree(mld->mcast_filter_cmd);
530 
531 	ieee80211_free_hw(mld->hw);
532 }
533 
534 static void iwl_mld_queue_state_change(struct iwl_op_mode *op_mode,
535 				       int hw_queue, bool queue_full)
536 {
537 	struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
538 	struct ieee80211_txq *txq;
539 	struct iwl_mld_sta *mld_sta;
540 	struct iwl_mld_txq *mld_txq;
541 
542 	rcu_read_lock();
543 
544 	txq = rcu_dereference(mld->fw_id_to_txq[hw_queue]);
545 	if (!txq) {
546 		rcu_read_unlock();
547 
548 		if (queue_full) {
549 			/* An internal queue is not expected to become full */
550 			IWL_WARN(mld,
551 				 "Internal hw_queue %d is full! stopping all queues\n",
552 				 hw_queue);
553 			/* Stop all queues, as an internal queue is not
554 			 * mapped to a mac80211 one
555 			 */
556 			ieee80211_stop_queues(mld->hw);
557 		} else {
558 			ieee80211_wake_queues(mld->hw);
559 		}
560 
561 		return;
562 	}
563 
564 	mld_txq = iwl_mld_txq_from_mac80211(txq);
565 	mld_sta = txq->sta ? iwl_mld_sta_from_mac80211(txq->sta) : NULL;
566 
567 	mld_txq->status.stop_full = queue_full;
568 
569 	if (!queue_full && mld_sta &&
570 	    mld_sta->sta_state != IEEE80211_STA_NOTEXIST) {
571 		local_bh_disable();
572 		iwl_mld_tx_from_txq(mld, txq);
573 		local_bh_enable();
574 	}
575 
576 	rcu_read_unlock();
577 }
578 
579 static void
580 iwl_mld_queue_full(struct iwl_op_mode *op_mode, int hw_queue)
581 {
582 	iwl_mld_queue_state_change(op_mode, hw_queue, true);
583 }
584 
585 static void
586 iwl_mld_queue_not_full(struct iwl_op_mode *op_mode, int hw_queue)
587 {
588 	iwl_mld_queue_state_change(op_mode, hw_queue, false);
589 }
590 
591 static bool
592 iwl_mld_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
593 {
594 	struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
595 
596 	iwl_mld_set_hwkill(mld, state);
597 
598 	return false;
599 }
600 
601 static void
602 iwl_mld_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
603 {
604 	struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
605 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
606 
607 	iwl_trans_free_tx_cmd(mld->trans, info->driver_data[1]);
608 	ieee80211_free_txskb(mld->hw, skb);
609 }
610 
611 static void iwl_mld_read_error_recovery_buffer(struct iwl_mld *mld)
612 {
613 	u32 src_size = mld->fw->ucode_capa.error_log_size;
614 	u32 src_addr = mld->fw->ucode_capa.error_log_addr;
615 	u8 *recovery_buf;
616 	int ret;
617 
618 	/* no recovery buffer size defined in a TLV */
619 	if (!src_size)
620 		return;
621 
622 	recovery_buf = kzalloc(src_size, GFP_ATOMIC);
623 	if (!recovery_buf)
624 		return;
625 
626 	ret = iwl_trans_read_mem_bytes(mld->trans, src_addr,
627 				       recovery_buf, src_size);
628 	if (ret) {
629 		IWL_ERR(mld, "Failed to read error recovery buffer (%d)\n",
630 			ret);
631 		kfree(recovery_buf);
632 		return;
633 	}
634 
635 	mld->error_recovery_buf = recovery_buf;
636 }
637 
638 static void iwl_mld_restart_nic(struct iwl_mld *mld)
639 {
640 	iwl_mld_read_error_recovery_buffer(mld);
641 
642 	mld->fwrt.trans->dbg.restart_required = false;
643 
644 	ieee80211_restart_hw(mld->hw);
645 }
646 
647 static void
648 iwl_mld_nic_error(struct iwl_op_mode *op_mode,
649 		  enum iwl_fw_error_type type)
650 {
651 	struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
652 	bool trans_dead = iwl_trans_is_dead(mld->trans);
653 
654 	if (type == IWL_ERR_TYPE_CMD_QUEUE_FULL)
655 		IWL_ERR(mld, "Command queue full!\n");
656 	else if (!trans_dead && !mld->fw_status.do_not_dump_once)
657 		iwl_fwrt_dump_error_logs(&mld->fwrt);
658 
659 	mld->fw_status.do_not_dump_once = false;
660 
661 	/* It is necessary to abort any os scan here because mac80211 requires
662 	 * having the scan cleared before restarting.
663 	 * We'll reset the scan_status to NONE in restart cleanup in
664 	 * the next drv_start() call from mac80211. If ieee80211_hw_restart
665 	 * isn't called scan status will stay busy.
666 	 */
667 	iwl_mld_report_scan_aborted(mld);
668 
669 	/*
670 	 * This should be first thing before trying to collect any
671 	 * data to avoid endless loops if any HW error happens while
672 	 * collecting debug data.
673 	 * It might not actually be true that we'll restart, but the
674 	 * setting doesn't matter if we're going to be unbound either.
675 	 */
676 	if (type != IWL_ERR_TYPE_RESET_HS_TIMEOUT &&
677 	    mld->fw_status.running)
678 		mld->fw_status.in_hw_restart = true;
679 
680 	/* FW is dead. We don't want to process its notifications.
681 	 * Right, we cancel them also in iwl_mld_stop_fw, but
682 	 * iwl_mld_async_handlers_wk might be executed before
683 	 * ieee80211_restart_work.
684 	 * In addition, in case of an error during recovery,
685 	 * iwl_mld_stop_fw might be too late.
686 	 */
687 	iwl_mld_cancel_async_notifications(mld);
688 }
689 
690 static void iwl_mld_dump_error(struct iwl_op_mode *op_mode,
691 			       struct iwl_fw_error_dump_mode *mode)
692 {
693 	struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
694 
695 	/* if we come in from opmode we have the mutex held */
696 	if (mode->context == IWL_ERR_CONTEXT_FROM_OPMODE) {
697 		lockdep_assert_wiphy(mld->wiphy);
698 		iwl_fw_error_collect(&mld->fwrt);
699 	} else {
700 		wiphy_lock(mld->wiphy);
701 		if (mode->context != IWL_ERR_CONTEXT_ABORT)
702 			iwl_fw_error_collect(&mld->fwrt);
703 		wiphy_unlock(mld->wiphy);
704 	}
705 }
706 
707 static bool iwl_mld_sw_reset(struct iwl_op_mode *op_mode,
708 			     enum iwl_fw_error_type type)
709 {
710 	struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
711 
712 	/* SW reset can happen for TOP error w/o NIC error, so
713 	 * also abort scan here and set in_hw_restart, when we
714 	 * had a NIC error both were already done.
715 	 */
716 	iwl_mld_report_scan_aborted(mld);
717 	mld->fw_status.in_hw_restart = true;
718 
719 	/* Do restart only in the following conditions are met:
720 	 * - we consider the FW as running
721 	 * - The trigger that brought us here is defined as one that requires
722 	 *   a restart (in the debug TLVs)
723 	 */
724 	if (!mld->fw_status.running || !mld->fwrt.trans->dbg.restart_required)
725 		return false;
726 
727 	iwl_mld_restart_nic(mld);
728 	return true;
729 }
730 
731 static void
732 iwl_mld_time_point(struct iwl_op_mode *op_mode,
733 		   enum iwl_fw_ini_time_point tp_id,
734 		   union iwl_dbg_tlv_tp_data *tp_data)
735 {
736 	struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
737 
738 	iwl_dbg_tlv_time_point(&mld->fwrt, tp_id, tp_data);
739 }
740 
741 #ifdef CONFIG_PM_SLEEP
742 static void iwl_mld_device_powered_off(struct iwl_op_mode *op_mode)
743 {
744 	struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
745 
746 	wiphy_lock(mld->wiphy);
747 	iwl_mld_stop_fw(mld);
748 	mld->fw_status.in_d3 = false;
749 	wiphy_unlock(mld->wiphy);
750 }
751 #else
752 static void iwl_mld_device_powered_off(struct iwl_op_mode *op_mode)
753 {}
754 #endif
755 
756 static void iwl_mld_dump(struct iwl_op_mode *op_mode)
757 {
758 	struct iwl_mld *mld = IWL_OP_MODE_GET_MLD(op_mode);
759 	struct iwl_fw_runtime *fwrt = &mld->fwrt;
760 
761 	if (!iwl_trans_fw_running(fwrt->trans))
762 		return;
763 
764 	iwl_dbg_tlv_time_point(fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER, NULL);
765 }
766 
767 static const struct iwl_op_mode_ops iwl_mld_ops = {
768 	.start = iwl_op_mode_mld_start,
769 	.stop = iwl_op_mode_mld_stop,
770 	.rx = iwl_mld_rx,
771 	.rx_rss = iwl_mld_rx_rss,
772 	.queue_full = iwl_mld_queue_full,
773 	.queue_not_full = iwl_mld_queue_not_full,
774 	.hw_rf_kill = iwl_mld_set_hw_rfkill_state,
775 	.free_skb = iwl_mld_free_skb,
776 	.nic_error = iwl_mld_nic_error,
777 	.dump_error = iwl_mld_dump_error,
778 	.sw_reset = iwl_mld_sw_reset,
779 	.time_point = iwl_mld_time_point,
780 	.device_powered_off = pm_sleep_ptr(iwl_mld_device_powered_off),
781 	.dump = iwl_mld_dump,
782 };
783 
784 struct iwl_mld_mod_params iwlmld_mod_params = {
785 	.power_scheme = IWL_POWER_SCHEME_BPS,
786 };
787 
788 module_param_named(power_scheme, iwlmld_mod_params.power_scheme, int, 0444);
789 MODULE_PARM_DESC(power_scheme,
790 		 "power management scheme: 1-active, 2-balanced, default: 2");
791