1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2/*
3 * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
4 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
5 * Copyright (C) 2016-2017 Intel Deutschland GmbH
6 */
7#include <linux/vmalloc.h>
8#include <linux/err.h>
9#include <linux/ieee80211.h>
10#include <linux/netdevice.h>
11#include <linux/dmi.h>
12
13#include "mvm.h"
14#include "sta.h"
15#include "iwl-io.h"
16#include "debugfs.h"
17#include "iwl-modparams.h"
18#include "iwl-drv.h"
19#include "fw/error-dump.h"
20#include "fw/api/phy-ctxt.h"
21
22static ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file,
23					  char __user *user_buf,
24					  size_t count, loff_t *ppos)
25{
26	struct iwl_mvm *mvm = file->private_data;
27	char buf[16];
28	int pos, budget;
29
30	if (!iwl_mvm_is_ctdp_supported(mvm))
31		return -EOPNOTSUPP;
32
33	if (!iwl_mvm_firmware_running(mvm) ||
34	    mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
35		return -EIO;
36
37	mutex_lock(&mvm->mutex);
38	budget = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_REPORT, 0);
39	mutex_unlock(&mvm->mutex);
40
41	if (budget < 0)
42		return budget;
43
44	pos = scnprintf(buf, sizeof(buf), "%d\n", budget);
45
46	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
47}
48
49static ssize_t iwl_dbgfs_stop_ctdp_write(struct iwl_mvm *mvm, char *buf,
50					 size_t count, loff_t *ppos)
51{
52	int ret;
53	bool force;
54
55	if (!kstrtobool(buf, &force))
56		IWL_DEBUG_INFO(mvm,
57			       "force start is %d [0=disabled, 1=enabled]\n",
58			       force);
59
60	/* we allow skipping cap support check and force stop ctdp
61	 * statistics collection and with guerantee that it is
62	 * safe to use.
63	 */
64	if (!force && !iwl_mvm_is_ctdp_supported(mvm))
65		return -EOPNOTSUPP;
66
67	if (!iwl_mvm_firmware_running(mvm) ||
68	    mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
69		return -EIO;
70
71	mutex_lock(&mvm->mutex);
72	ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_STOP, 0);
73	mutex_unlock(&mvm->mutex);
74
75	return ret ?: count;
76}
77
78static ssize_t iwl_dbgfs_start_ctdp_write(struct iwl_mvm *mvm,
79					  char *buf, size_t count,
80					  loff_t *ppos)
81{
82	int ret;
83	bool force;
84
85	if (!kstrtobool(buf, &force))
86		IWL_DEBUG_INFO(mvm,
87			       "force start is %d [0=disabled, 1=enabled]\n",
88			       force);
89
90	/* we allow skipping cap support check and force enable ctdp
91	 * for statistics collection and with guerantee that it is
92	 * safe to use.
93	 */
94	if (!force && !iwl_mvm_is_ctdp_supported(mvm))
95		return -EOPNOTSUPP;
96
97	if (!iwl_mvm_firmware_running(mvm) ||
98	    mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
99		return -EIO;
100
101	mutex_lock(&mvm->mutex);
102	ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_START, 0);
103	mutex_unlock(&mvm->mutex);
104
105	return ret ?: count;
106}
107
108static ssize_t iwl_dbgfs_force_ctkill_write(struct iwl_mvm *mvm, char *buf,
109					    size_t count, loff_t *ppos)
110{
111	if (!iwl_mvm_firmware_running(mvm) ||
112	    mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
113		return -EIO;
114
115	iwl_mvm_enter_ctkill(mvm);
116
117	return count;
118}
119
120static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
121					size_t count, loff_t *ppos)
122{
123	int ret;
124	u32 flush_arg;
125
126	if (!iwl_mvm_firmware_running(mvm) ||
127	    mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
128		return -EIO;
129
130	if (kstrtou32(buf, 0, &flush_arg))
131		return -EINVAL;
132
133	if (iwl_mvm_has_new_tx_api(mvm)) {
134		IWL_DEBUG_TX_QUEUES(mvm,
135				    "FLUSHING all tids queues on sta_id = %d\n",
136				    flush_arg);
137		mutex_lock(&mvm->mutex);
138		ret = iwl_mvm_flush_sta_tids(mvm, flush_arg, 0xFFFF)
139			? : count;
140		mutex_unlock(&mvm->mutex);
141		return ret;
142	}
143
144	IWL_DEBUG_TX_QUEUES(mvm, "FLUSHING queues mask to flush = 0x%x\n",
145			    flush_arg);
146
147	mutex_lock(&mvm->mutex);
148	ret =  iwl_mvm_flush_tx_path(mvm, flush_arg) ? : count;
149	mutex_unlock(&mvm->mutex);
150
151	return ret;
152}
153
154static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
155					 size_t count, loff_t *ppos)
156{
157	struct iwl_mvm_sta *mvmsta;
158	int sta_id, drain, ret;
159
160	if (!iwl_mvm_firmware_running(mvm) ||
161	    mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
162		return -EIO;
163
164	if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
165		return -EINVAL;
166	if (sta_id < 0 || sta_id >= mvm->fw->ucode_capa.num_stations)
167		return -EINVAL;
168	if (drain < 0 || drain > 1)
169		return -EINVAL;
170
171	mutex_lock(&mvm->mutex);
172
173	mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
174
175	if (!mvmsta)
176		ret = -ENOENT;
177	else
178		ret = iwl_mvm_drain_sta(mvm, mvmsta, drain) ? : count;
179
180	mutex_unlock(&mvm->mutex);
181
182	return ret;
183}
184
185static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
186				   size_t count, loff_t *ppos)
187{
188	struct iwl_mvm *mvm = file->private_data;
189	const struct fw_img *img;
190	unsigned int ofs, len;
191	size_t ret;
192	u8 *ptr;
193
194	if (!iwl_mvm_firmware_running(mvm))
195		return -EINVAL;
196
197	/* default is to dump the entire data segment */
198	img = &mvm->fw->img[mvm->fwrt.cur_fw_img];
199	ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
200	len = img->sec[IWL_UCODE_SECTION_DATA].len;
201
202	if (mvm->dbgfs_sram_len) {
203		ofs = mvm->dbgfs_sram_offset;
204		len = mvm->dbgfs_sram_len;
205	}
206
207	ptr = kzalloc(len, GFP_KERNEL);
208	if (!ptr)
209		return -ENOMEM;
210
211	iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len);
212
213	ret = simple_read_from_buffer(user_buf, count, ppos, ptr, len);
214
215	kfree(ptr);
216
217	return ret;
218}
219
220static ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
221				    size_t count, loff_t *ppos)
222{
223	const struct fw_img *img;
224	u32 offset, len;
225	u32 img_offset, img_len;
226
227	if (!iwl_mvm_firmware_running(mvm))
228		return -EINVAL;
229
230	img = &mvm->fw->img[mvm->fwrt.cur_fw_img];
231	img_offset = img->sec[IWL_UCODE_SECTION_DATA].offset;
232	img_len = img->sec[IWL_UCODE_SECTION_DATA].len;
233
234	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
235		if ((offset & 0x3) || (len & 0x3))
236			return -EINVAL;
237
238		if (offset + len > img_offset + img_len)
239			return -EINVAL;
240
241		mvm->dbgfs_sram_offset = offset;
242		mvm->dbgfs_sram_len = len;
243	} else {
244		mvm->dbgfs_sram_offset = 0;
245		mvm->dbgfs_sram_len = 0;
246	}
247
248	return count;
249}
250
251static ssize_t iwl_dbgfs_set_nic_temperature_read(struct file *file,
252						  char __user *user_buf,
253						  size_t count, loff_t *ppos)
254{
255	struct iwl_mvm *mvm = file->private_data;
256	char buf[16];
257	int pos;
258
259	if (!mvm->temperature_test)
260		pos = scnprintf(buf, sizeof(buf), "disabled\n");
261	else
262		pos = scnprintf(buf, sizeof(buf), "%d\n", mvm->temperature);
263
264	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
265}
266
267/*
268 * Set NIC Temperature
269 * Cause the driver to ignore the actual NIC temperature reported by the FW
270 * Enable: any value between IWL_MVM_DEBUG_SET_TEMPERATURE_MIN -
271 * IWL_MVM_DEBUG_SET_TEMPERATURE_MAX
272 * Disable: IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE
273 */
274static ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm,
275						   char *buf, size_t count,
276						   loff_t *ppos)
277{
278	int temperature;
279
280	if (!iwl_mvm_firmware_running(mvm) && !mvm->temperature_test)
281		return -EIO;
282
283	if (kstrtoint(buf, 10, &temperature))
284		return -EINVAL;
285	/* not a legal temperature */
286	if ((temperature > IWL_MVM_DEBUG_SET_TEMPERATURE_MAX &&
287	     temperature != IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) ||
288	    temperature < IWL_MVM_DEBUG_SET_TEMPERATURE_MIN)
289		return -EINVAL;
290
291	mutex_lock(&mvm->mutex);
292	if (temperature == IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) {
293		if (!mvm->temperature_test)
294			goto out;
295
296		mvm->temperature_test = false;
297		/* Since we can't read the temp while awake, just set
298		 * it to zero until we get the next RX stats from the
299		 * firmware.
300		 */
301		mvm->temperature = 0;
302	} else {
303		mvm->temperature_test = true;
304		mvm->temperature = temperature;
305	}
306	IWL_DEBUG_TEMP(mvm, "%sabling debug set temperature (temp = %d)\n",
307		       mvm->temperature_test ? "En" : "Dis",
308		       mvm->temperature);
309	/* handle the temperature change */
310	iwl_mvm_tt_handler(mvm);
311
312out:
313	mutex_unlock(&mvm->mutex);
314
315	return count;
316}
317
318static ssize_t iwl_dbgfs_nic_temp_read(struct file *file,
319				       char __user *user_buf,
320				       size_t count, loff_t *ppos)
321{
322	struct iwl_mvm *mvm = file->private_data;
323	char buf[16];
324	int pos, ret;
325	s32 temp;
326
327	if (!iwl_mvm_firmware_running(mvm))
328		return -EIO;
329
330	mutex_lock(&mvm->mutex);
331	ret = iwl_mvm_get_temp(mvm, &temp);
332	mutex_unlock(&mvm->mutex);
333
334	if (ret)
335		return -EIO;
336
337	pos = scnprintf(buf, sizeof(buf), "%d\n", temp);
338
339	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
340}
341
342#ifdef CONFIG_ACPI
343static ssize_t iwl_dbgfs_sar_geo_profile_read(struct file *file,
344					      char __user *user_buf,
345					      size_t count, loff_t *ppos)
346{
347	struct iwl_mvm *mvm = file->private_data;
348	char buf[256];
349	int pos = 0;
350	int bufsz = sizeof(buf);
351	int tbl_idx;
352
353	if (!iwl_mvm_firmware_running(mvm))
354		return -EIO;
355
356	mutex_lock(&mvm->mutex);
357	tbl_idx = iwl_mvm_get_sar_geo_profile(mvm);
358	if (tbl_idx < 0) {
359		mutex_unlock(&mvm->mutex);
360		return tbl_idx;
361	}
362
363	if (!tbl_idx) {
364		pos = scnprintf(buf, bufsz,
365				"SAR geographic profile disabled\n");
366	} else {
367		pos += scnprintf(buf + pos, bufsz - pos,
368				 "Use geographic profile %d\n", tbl_idx);
369		pos += scnprintf(buf + pos, bufsz - pos,
370				 "2.4GHz:\n\tChain A offset: %u dBm\n\tChain B offset: %u dBm\n\tmax tx power: %u dBm\n",
371				 mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].chains[0],
372				 mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].chains[1],
373				 mvm->fwrt.geo_profiles[tbl_idx - 1].bands[0].max);
374		pos += scnprintf(buf + pos, bufsz - pos,
375				 "5.2GHz:\n\tChain A offset: %u dBm\n\tChain B offset: %u dBm\n\tmax tx power: %u dBm\n",
376				 mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].chains[0],
377				 mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].chains[1],
378				 mvm->fwrt.geo_profiles[tbl_idx - 1].bands[1].max);
379	}
380	mutex_unlock(&mvm->mutex);
381
382	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
383}
384
385static ssize_t iwl_dbgfs_wifi_6e_enable_read(struct file *file,
386					     char __user *user_buf,
387					     size_t count, loff_t *ppos)
388{
389	struct iwl_mvm *mvm = file->private_data;
390	int err, pos;
391	char buf[12];
392	u32 value;
393
394	err = iwl_bios_get_dsm(&mvm->fwrt, DSM_FUNC_ENABLE_6E, &value);
395	if (err)
396		return err;
397
398	pos = sprintf(buf, "0x%08x\n", value);
399
400	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
401}
402#endif
403
404static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
405				       size_t count, loff_t *ppos)
406{
407	struct iwl_mvm *mvm = file->private_data;
408	struct ieee80211_sta *sta;
409	char buf[400];
410	int i, pos = 0, bufsz = sizeof(buf);
411
412	mutex_lock(&mvm->mutex);
413
414	for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
415		pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i);
416		sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
417						lockdep_is_held(&mvm->mutex));
418		if (!sta)
419			pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
420		else if (IS_ERR(sta))
421			pos += scnprintf(buf + pos, bufsz - pos, "%ld\n",
422					 PTR_ERR(sta));
423		else
424			pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
425					 sta->addr);
426	}
427
428	mutex_unlock(&mvm->mutex);
429
430	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
431}
432
433static ssize_t iwl_dbgfs_rs_data_read(struct ieee80211_link_sta *link_sta,
434				      struct iwl_mvm_sta *mvmsta,
435				      struct iwl_mvm *mvm,
436				      struct iwl_mvm_link_sta *mvm_link_sta,
437				      char __user *user_buf,
438				      size_t count, loff_t *ppos)
439{
440	struct iwl_lq_sta_rs_fw *lq_sta = &mvm_link_sta->lq_sta.rs_fw;
441	static const size_t bufsz = 2048;
442	char *buff;
443	int desc = 0;
444	ssize_t ret;
445
446	buff = kmalloc(bufsz, GFP_KERNEL);
447	if (!buff)
448		return -ENOMEM;
449
450	desc += scnprintf(buff + desc, bufsz - desc, "sta_id %d\n",
451			  lq_sta->pers.sta_id);
452	desc += scnprintf(buff + desc, bufsz - desc,
453			  "fixed rate 0x%X\n",
454			  lq_sta->pers.dbg_fixed_rate);
455	desc += scnprintf(buff + desc, bufsz - desc,
456			  "A-MPDU size limit %d\n",
457			  lq_sta->pers.dbg_agg_frame_count_lim);
458	desc += scnprintf(buff + desc, bufsz - desc,
459			  "valid_tx_ant %s%s\n",
460		(iwl_mvm_get_valid_tx_ant(mvm) & ANT_A) ? "ANT_A," : "",
461		(iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "");
462	desc += scnprintf(buff + desc, bufsz - desc,
463			  "last tx rate=0x%X ",
464			  lq_sta->last_rate_n_flags);
465
466	desc += rs_pretty_print_rate(buff + desc, bufsz - desc,
467				     lq_sta->last_rate_n_flags);
468	if (desc < bufsz - 1)
469		buff[desc++] = '\n';
470
471	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
472	kfree(buff);
473	return ret;
474}
475
476static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_link_sta *link_sta,
477					 struct iwl_mvm_sta *mvmsta,
478					 struct iwl_mvm *mvm,
479					 struct iwl_mvm_link_sta *mvm_link_sta,
480					 char *buf, size_t count,
481					 loff_t *ppos)
482{
483	int i;
484	u16 amsdu_len;
485
486	if (kstrtou16(buf, 0, &amsdu_len))
487		return -EINVAL;
488
489	/* only change from debug set <-> debug unset */
490	if (amsdu_len && mvm_link_sta->orig_amsdu_len)
491		return -EBUSY;
492
493	if (amsdu_len) {
494		mvm_link_sta->orig_amsdu_len = link_sta->agg.max_amsdu_len;
495		link_sta->agg.max_amsdu_len = amsdu_len;
496		link_sta->agg.max_amsdu_len = amsdu_len;
497		for (i = 0; i < ARRAY_SIZE(link_sta->agg.max_tid_amsdu_len); i++)
498			link_sta->agg.max_tid_amsdu_len[i] = amsdu_len;
499	} else {
500		link_sta->agg.max_amsdu_len = mvm_link_sta->orig_amsdu_len;
501		mvm_link_sta->orig_amsdu_len = 0;
502	}
503
504	ieee80211_sta_recalc_aggregates(link_sta->sta);
505
506	return count;
507}
508
509static ssize_t iwl_dbgfs_amsdu_len_read(struct ieee80211_link_sta *link_sta,
510					struct iwl_mvm_sta *mvmsta,
511					struct iwl_mvm *mvm,
512					struct iwl_mvm_link_sta *mvm_link_sta,
513					char __user *user_buf,
514					size_t count, loff_t *ppos)
515{
516	char buf[32];
517	int pos;
518
519	pos = scnprintf(buf, sizeof(buf), "current %d ",
520			link_sta->agg.max_amsdu_len);
521	pos += scnprintf(buf + pos, sizeof(buf) - pos, "stored %d\n",
522			 mvm_link_sta->orig_amsdu_len);
523
524	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
525}
526
527static ssize_t iwl_dbgfs_disable_power_off_read(struct file *file,
528						char __user *user_buf,
529						size_t count, loff_t *ppos)
530{
531	struct iwl_mvm *mvm = file->private_data;
532	char buf[64];
533	int bufsz = sizeof(buf);
534	int pos = 0;
535
536	pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d0=%d\n",
537			 mvm->disable_power_off);
538	pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d3=%d\n",
539			 mvm->disable_power_off_d3);
540
541	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
542}
543
544static ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
545						 size_t count, loff_t *ppos)
546{
547	int ret, val;
548
549	if (!iwl_mvm_firmware_running(mvm))
550		return -EIO;
551
552	if (!strncmp("disable_power_off_d0=", buf, 21)) {
553		if (sscanf(buf + 21, "%d", &val) != 1)
554			return -EINVAL;
555		mvm->disable_power_off = val;
556	} else if (!strncmp("disable_power_off_d3=", buf, 21)) {
557		if (sscanf(buf + 21, "%d", &val) != 1)
558			return -EINVAL;
559		mvm->disable_power_off_d3 = val;
560	} else {
561		return -EINVAL;
562	}
563
564	mutex_lock(&mvm->mutex);
565	ret = iwl_mvm_power_update_device(mvm);
566	mutex_unlock(&mvm->mutex);
567
568	return ret ?: count;
569}
570
571static
572int iwl_mvm_coex_dump_mbox(struct iwl_bt_coex_profile_notif *notif, char *buf,
573			   int pos, int bufsz)
574{
575	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
576
577	BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
578	BT_MBOX_PRINT(0, LE_PROF1, false);
579	BT_MBOX_PRINT(0, LE_PROF2, false);
580	BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
581	BT_MBOX_PRINT(0, CHL_SEQ_N, false);
582	BT_MBOX_PRINT(0, INBAND_S, false);
583	BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
584	BT_MBOX_PRINT(0, LE_SCAN, false);
585	BT_MBOX_PRINT(0, LE_ADV, false);
586	BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
587	BT_MBOX_PRINT(0, OPEN_CON_1, true);
588
589	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
590
591	BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
592	BT_MBOX_PRINT(1, IP_SR, false);
593	BT_MBOX_PRINT(1, LE_MSTR, false);
594	BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
595	BT_MBOX_PRINT(1, MSG_TYPE, false);
596	BT_MBOX_PRINT(1, SSN, true);
597
598	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
599
600	BT_MBOX_PRINT(2, SNIFF_ACT, false);
601	BT_MBOX_PRINT(2, PAG, false);
602	BT_MBOX_PRINT(2, INQUIRY, false);
603	BT_MBOX_PRINT(2, CONN, false);
604	BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
605	BT_MBOX_PRINT(2, DISC, false);
606	BT_MBOX_PRINT(2, SCO_TX_ACT, false);
607	BT_MBOX_PRINT(2, SCO_RX_ACT, false);
608	BT_MBOX_PRINT(2, ESCO_RE_TX, false);
609	BT_MBOX_PRINT(2, SCO_DURATION, true);
610
611	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
612
613	BT_MBOX_PRINT(3, SCO_STATE, false);
614	BT_MBOX_PRINT(3, SNIFF_STATE, false);
615	BT_MBOX_PRINT(3, A2DP_STATE, false);
616	BT_MBOX_PRINT(3, A2DP_SRC, false);
617	BT_MBOX_PRINT(3, ACL_STATE, false);
618	BT_MBOX_PRINT(3, MSTR_STATE, false);
619	BT_MBOX_PRINT(3, OBX_STATE, false);
620	BT_MBOX_PRINT(3, OPEN_CON_2, false);
621	BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
622	BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
623	BT_MBOX_PRINT(3, INBAND_P, false);
624	BT_MBOX_PRINT(3, MSG_TYPE_2, false);
625	BT_MBOX_PRINT(3, SSN_2, false);
626	BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
627
628	return pos;
629}
630
631static ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
632				       size_t count, loff_t *ppos)
633{
634	struct iwl_mvm *mvm = file->private_data;
635	struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
636	char *buf;
637	int ret, pos = 0, bufsz = sizeof(char) * 1024;
638
639	buf = kmalloc(bufsz, GFP_KERNEL);
640	if (!buf)
641		return -ENOMEM;
642
643	mutex_lock(&mvm->mutex);
644
645	pos += iwl_mvm_coex_dump_mbox(notif, buf, pos, bufsz);
646
647	pos += scnprintf(buf + pos, bufsz - pos, "bt_ci_compliance = %d\n",
648			 notif->bt_ci_compliance);
649	pos += scnprintf(buf + pos, bufsz - pos, "primary_ch_lut = %d\n",
650			 le32_to_cpu(notif->primary_ch_lut));
651	pos += scnprintf(buf + pos, bufsz - pos, "secondary_ch_lut = %d\n",
652			 le32_to_cpu(notif->secondary_ch_lut));
653	pos += scnprintf(buf + pos,
654			 bufsz - pos, "bt_activity_grading = %d\n",
655			 le32_to_cpu(notif->bt_activity_grading));
656	pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n",
657			 notif->rrc_status & 0xF);
658	pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n",
659			 notif->ttc_status & 0xF);
660
661	pos += scnprintf(buf + pos, bufsz - pos, "sync_sco = %d\n",
662			 IWL_MVM_BT_COEX_SYNC2SCO);
663	pos += scnprintf(buf + pos, bufsz - pos, "mplut = %d\n",
664			 IWL_MVM_BT_COEX_MPLUT);
665
666	mutex_unlock(&mvm->mutex);
667
668	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
669	kfree(buf);
670
671	return ret;
672}
673#undef BT_MBOX_PRINT
674
675static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
676				     size_t count, loff_t *ppos)
677{
678	struct iwl_mvm *mvm = file->private_data;
679	struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
680	char buf[256];
681	int bufsz = sizeof(buf);
682	int pos = 0;
683
684	mutex_lock(&mvm->mutex);
685
686	pos += scnprintf(buf + pos, bufsz - pos, "Channel inhibition CMD\n");
687	pos += scnprintf(buf + pos, bufsz - pos,
688			 "\tPrimary Channel Bitmap 0x%016llx\n",
689			 le64_to_cpu(cmd->bt_primary_ci));
690	pos += scnprintf(buf + pos, bufsz - pos,
691			 "\tSecondary Channel Bitmap 0x%016llx\n",
692			 le64_to_cpu(cmd->bt_secondary_ci));
693
694	mutex_unlock(&mvm->mutex);
695
696	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
697}
698
699static ssize_t
700iwl_dbgfs_bt_tx_prio_write(struct iwl_mvm *mvm, char *buf,
701			   size_t count, loff_t *ppos)
702{
703	u32 bt_tx_prio;
704
705	if (sscanf(buf, "%u", &bt_tx_prio) != 1)
706		return -EINVAL;
707	if (bt_tx_prio > 4)
708		return -EINVAL;
709
710	mvm->bt_tx_prio = bt_tx_prio;
711
712	return count;
713}
714
715static ssize_t
716iwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
717			     size_t count, loff_t *ppos)
718{
719	static const char * const modes_str[BT_FORCE_ANT_MAX] = {
720		[BT_FORCE_ANT_DIS] = "dis",
721		[BT_FORCE_ANT_AUTO] = "auto",
722		[BT_FORCE_ANT_BT] = "bt",
723		[BT_FORCE_ANT_WIFI] = "wifi",
724	};
725	int ret, bt_force_ant_mode;
726
727	ret = match_string(modes_str, ARRAY_SIZE(modes_str), buf);
728	if (ret < 0)
729		return ret;
730
731	bt_force_ant_mode = ret;
732	ret = 0;
733	mutex_lock(&mvm->mutex);
734	if (mvm->bt_force_ant_mode == bt_force_ant_mode)
735		goto out;
736
737	mvm->bt_force_ant_mode = bt_force_ant_mode;
738	IWL_DEBUG_COEX(mvm, "Force mode: %s\n",
739		       modes_str[mvm->bt_force_ant_mode]);
740
741	if (iwl_mvm_firmware_running(mvm))
742		ret = iwl_mvm_send_bt_init_conf(mvm);
743	else
744		ret = 0;
745
746out:
747	mutex_unlock(&mvm->mutex);
748	return ret ?: count;
749}
750
751static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,
752				     size_t count, loff_t *ppos)
753{
754	struct iwl_mvm *mvm = file->private_data;
755	char *buff, *pos, *endpos;
756	static const size_t bufsz = 1024;
757	char _fw_name_pre[FW_NAME_PRE_BUFSIZE];
758	int ret;
759
760	buff = kmalloc(bufsz, GFP_KERNEL);
761	if (!buff)
762		return -ENOMEM;
763
764	pos = buff;
765	endpos = pos + bufsz;
766
767	pos += scnprintf(pos, endpos - pos, "FW prefix: %s\n",
768			 iwl_drv_get_fwname_pre(mvm->trans, _fw_name_pre));
769	pos += scnprintf(pos, endpos - pos, "FW: %s\n",
770			 mvm->fwrt.fw->human_readable);
771	pos += scnprintf(pos, endpos - pos, "Device: %s\n",
772			 mvm->fwrt.trans->name);
773	pos += scnprintf(pos, endpos - pos, "Bus: %s\n",
774			 mvm->fwrt.dev->bus->name);
775
776	ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
777	kfree(buff);
778
779	return ret;
780}
781
782static ssize_t iwl_dbgfs_tas_get_status_read(struct file *file,
783					     char __user *user_buf,
784					     size_t count, loff_t *ppos)
785{
786	struct iwl_mvm *mvm = file->private_data;
787	struct iwl_mvm_tas_status_resp tas_rsp;
788	struct iwl_mvm_tas_status_resp *rsp = &tas_rsp;
789	static const size_t bufsz = 1024;
790	char *buff, *pos, *endpos;
791	const char * const tas_dis_reason[TAS_DISABLED_REASON_MAX] = {
792		[TAS_DISABLED_DUE_TO_BIOS] =
793			"Due To BIOS",
794		[TAS_DISABLED_DUE_TO_SAR_6DBM] =
795			"Due To SAR Limit Less Than 6 dBm",
796		[TAS_DISABLED_REASON_INVALID] =
797			"N/A",
798	};
799	const char * const tas_current_status[TAS_DYNA_STATUS_MAX] = {
800		[TAS_DYNA_INACTIVE] = "INACTIVE",
801		[TAS_DYNA_INACTIVE_MVM_MODE] =
802			"inactive due to mvm mode",
803		[TAS_DYNA_INACTIVE_TRIGGER_MODE] =
804			"inactive due to trigger mode",
805		[TAS_DYNA_INACTIVE_BLOCK_LISTED] =
806			"inactive due to block listed",
807		[TAS_DYNA_INACTIVE_UHB_NON_US] =
808			"inactive due to uhb non US",
809		[TAS_DYNA_ACTIVE] = "ACTIVE",
810	};
811	struct iwl_host_cmd hcmd = {
812		.id = WIDE_ID(DEBUG_GROUP, GET_TAS_STATUS),
813		.flags = CMD_WANT_SKB,
814		.len = { 0, },
815		.data = { NULL, },
816	};
817	int ret, i, tmp;
818	bool tas_enabled = false;
819	unsigned long dyn_status;
820
821	if (!iwl_mvm_firmware_running(mvm))
822		return -ENODEV;
823
824	mutex_lock(&mvm->mutex);
825	ret = iwl_mvm_send_cmd(mvm, &hcmd);
826	mutex_unlock(&mvm->mutex);
827	if (ret < 0)
828		return ret;
829
830	buff = kzalloc(bufsz, GFP_KERNEL);
831	if (!buff)
832		return -ENOMEM;
833	pos = buff;
834	endpos = pos + bufsz;
835
836	rsp = (void *)hcmd.resp_pkt->data;
837
838	pos += scnprintf(pos, endpos - pos, "TAS Conclusion:\n");
839	for (i = 0; i < rsp->in_dual_radio + 1; i++) {
840		if (rsp->tas_status_mac[i].band != TAS_LMAC_BAND_INVALID &&
841		    rsp->tas_status_mac[i].dynamic_status & BIT(TAS_DYNA_ACTIVE)) {
842			pos += scnprintf(pos, endpos - pos, "\tON for ");
843			switch (rsp->tas_status_mac[i].band) {
844			case TAS_LMAC_BAND_HB:
845				pos += scnprintf(pos, endpos - pos, "HB\n");
846				break;
847			case TAS_LMAC_BAND_LB:
848				pos += scnprintf(pos, endpos - pos, "LB\n");
849				break;
850			case TAS_LMAC_BAND_UHB:
851				pos += scnprintf(pos, endpos - pos, "UHB\n");
852				break;
853			case TAS_LMAC_BAND_INVALID:
854				pos += scnprintf(pos, endpos - pos,
855						 "INVALID BAND\n");
856				break;
857			default:
858				pos += scnprintf(pos, endpos - pos,
859						 "Unsupported band (%d)\n",
860						 rsp->tas_status_mac[i].band);
861				goto out;
862			}
863			tas_enabled = true;
864		}
865	}
866	if (!tas_enabled)
867		pos += scnprintf(pos, endpos - pos, "\tOFF\n");
868
869	pos += scnprintf(pos, endpos - pos, "TAS Report\n");
870	pos += scnprintf(pos, endpos - pos, "TAS FW version: %d\n",
871			 rsp->tas_fw_version);
872	pos += scnprintf(pos, endpos - pos, "Is UHB enabled for USA?: %s\n",
873			 rsp->is_uhb_for_usa_enable ? "True" : "False");
874	pos += scnprintf(pos, endpos - pos, "Current MCC: 0x%x\n",
875			 le16_to_cpu(rsp->curr_mcc));
876
877	pos += scnprintf(pos, endpos - pos, "Block list entries:");
878	for (i = 0; i < IWL_WTAS_BLACK_LIST_MAX; i++)
879		pos += scnprintf(pos, endpos - pos, " 0x%x",
880				 le16_to_cpu(rsp->block_list[i]));
881
882	pos += scnprintf(pos, endpos - pos, "\nOEM name: %s\n",
883			 dmi_get_system_info(DMI_SYS_VENDOR) ?: "<unknown>");
884	pos += scnprintf(pos, endpos - pos, "\tVendor In Approved List: %s\n",
885			 iwl_is_tas_approved() ? "YES" : "NO");
886	pos += scnprintf(pos, endpos - pos,
887			 "\tDo TAS Support Dual Radio?: %s\n",
888			 rsp->in_dual_radio ? "TRUE" : "FALSE");
889
890	for (i = 0; i < rsp->in_dual_radio + 1; i++) {
891		if (rsp->tas_status_mac[i].static_status == 0) {
892			pos += scnprintf(pos, endpos - pos,
893					 "Static status: disabled\n");
894			pos += scnprintf(pos, endpos - pos,
895					 "Static disabled reason: %s (0)\n",
896					 tas_dis_reason[0]);
897			goto out;
898		}
899
900		pos += scnprintf(pos, endpos - pos, "TAS status for ");
901		switch (rsp->tas_status_mac[i].band) {
902		case TAS_LMAC_BAND_HB:
903			pos += scnprintf(pos, endpos - pos, "High band\n");
904			break;
905		case TAS_LMAC_BAND_LB:
906			pos += scnprintf(pos, endpos - pos, "Low band\n");
907			break;
908		case TAS_LMAC_BAND_UHB:
909			pos += scnprintf(pos, endpos - pos,
910					 "Ultra high band\n");
911			break;
912		case TAS_LMAC_BAND_INVALID:
913			pos += scnprintf(pos, endpos - pos,
914					 "INVALID band\n");
915			break;
916		default:
917			pos += scnprintf(pos, endpos - pos,
918					 "Unsupported band (%d)\n",
919					 rsp->tas_status_mac[i].band);
920			goto out;
921		}
922		pos += scnprintf(pos, endpos - pos, "Static status: %sabled\n",
923				 rsp->tas_status_mac[i].static_status ?
924				 "En" : "Dis");
925		pos += scnprintf(pos, endpos - pos,
926				 "\tStatic Disabled Reason: ");
927		if (rsp->tas_status_mac[i].static_dis_reason < TAS_DISABLED_REASON_MAX)
928			pos += scnprintf(pos, endpos - pos, "%s (%d)\n",
929					 tas_dis_reason[rsp->tas_status_mac[i].static_dis_reason],
930					 rsp->tas_status_mac[i].static_dis_reason);
931		else
932			pos += scnprintf(pos, endpos - pos,
933					 "unsupported value (%d)\n",
934					 rsp->tas_status_mac[i].static_dis_reason);
935
936		pos += scnprintf(pos, endpos - pos, "Dynamic status:\n");
937		dyn_status = (rsp->tas_status_mac[i].dynamic_status);
938		for_each_set_bit(tmp, &dyn_status, sizeof(dyn_status)) {
939			if (tmp >= 0 && tmp < TAS_DYNA_STATUS_MAX)
940				pos += scnprintf(pos, endpos - pos,
941						 "\t%s (%d)\n",
942						 tas_current_status[tmp], tmp);
943		}
944
945		pos += scnprintf(pos, endpos - pos,
946				 "Is near disconnection?: %s\n",
947				 rsp->tas_status_mac[i].near_disconnection ?
948				 "True" : "False");
949		tmp = le16_to_cpu(rsp->tas_status_mac[i].max_reg_pwr_limit);
950		pos += scnprintf(pos, endpos - pos,
951				 "Max. regulatory pwr limit (dBm): %d.%03d\n",
952				 tmp / 8, 125 * (tmp % 8));
953		tmp = le16_to_cpu(rsp->tas_status_mac[i].sar_limit);
954		pos += scnprintf(pos, endpos - pos,
955				 "SAR limit (dBm): %d.%03d\n",
956				 tmp / 8, 125 * (tmp % 8));
957	}
958
959out:
960	ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
961	kfree(buff);
962	iwl_free_resp(&hcmd);
963	return ret;
964}
965
966static ssize_t iwl_dbgfs_phy_integration_ver_read(struct file *file,
967						  char __user *user_buf,
968						  size_t count, loff_t *ppos)
969{
970	struct iwl_mvm *mvm = file->private_data;
971	char *buf;
972	size_t bufsz;
973	int pos;
974	ssize_t ret;
975
976	bufsz = mvm->fw->phy_integration_ver_len + 2;
977	buf = kmalloc(bufsz, GFP_KERNEL);
978	if (!buf)
979		return -ENOMEM;
980
981	pos = scnprintf(buf, bufsz, "%.*s\n", mvm->fw->phy_integration_ver_len,
982			mvm->fw->phy_integration_ver);
983
984	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
985
986	kfree(buf);
987	return ret;
988}
989
990#define PRINT_STATS_LE32(_struct, _memb)				\
991			 pos += scnprintf(buf + pos, bufsz - pos,	\
992					  fmt_table, #_memb,		\
993					  le32_to_cpu(_struct->_memb))
994
995static ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
996					  char __user *user_buf, size_t count,
997					  loff_t *ppos)
998{
999	struct iwl_mvm *mvm = file->private_data;
1000	static const char *fmt_table = "\t%-30s %10u\n";
1001	static const char *fmt_header = "%-32s\n";
1002	int pos = 0;
1003	char *buf;
1004	int ret;
1005	size_t bufsz;
1006	u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
1007					   WIDE_ID(SYSTEM_GROUP,
1008						   SYSTEM_STATISTICS_CMD),
1009					   IWL_FW_CMD_VER_UNKNOWN);
1010
1011	if (cmd_ver != IWL_FW_CMD_VER_UNKNOWN)
1012		return -EOPNOTSUPP;
1013
1014	if (iwl_mvm_has_new_rx_stats_api(mvm))
1015		bufsz = ((sizeof(struct mvm_statistics_rx) /
1016			  sizeof(__le32)) * 43) + (4 * 33) + 1;
1017	else
1018		/* 43 = size of each data line; 33 = size of each header */
1019		bufsz = ((sizeof(struct mvm_statistics_rx_v3) /
1020			  sizeof(__le32)) * 43) + (4 * 33) + 1;
1021
1022	buf = kzalloc(bufsz, GFP_KERNEL);
1023	if (!buf)
1024		return -ENOMEM;
1025
1026	mutex_lock(&mvm->mutex);
1027
1028	if (iwl_mvm_firmware_running(mvm))
1029		iwl_mvm_request_statistics(mvm, false);
1030
1031	pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
1032			 "Statistics_Rx - OFDM");
1033	if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
1034		struct mvm_statistics_rx_phy_v2 *ofdm = &mvm->rx_stats_v3.ofdm;
1035
1036		PRINT_STATS_LE32(ofdm, ina_cnt);
1037		PRINT_STATS_LE32(ofdm, fina_cnt);
1038		PRINT_STATS_LE32(ofdm, plcp_err);
1039		PRINT_STATS_LE32(ofdm, crc32_err);
1040		PRINT_STATS_LE32(ofdm, overrun_err);
1041		PRINT_STATS_LE32(ofdm, early_overrun_err);
1042		PRINT_STATS_LE32(ofdm, crc32_good);
1043		PRINT_STATS_LE32(ofdm, false_alarm_cnt);
1044		PRINT_STATS_LE32(ofdm, fina_sync_err_cnt);
1045		PRINT_STATS_LE32(ofdm, sfd_timeout);
1046		PRINT_STATS_LE32(ofdm, fina_timeout);
1047		PRINT_STATS_LE32(ofdm, unresponded_rts);
1048		PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
1049		PRINT_STATS_LE32(ofdm, sent_ack_cnt);
1050		PRINT_STATS_LE32(ofdm, sent_cts_cnt);
1051		PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
1052		PRINT_STATS_LE32(ofdm, dsp_self_kill);
1053		PRINT_STATS_LE32(ofdm, mh_format_err);
1054		PRINT_STATS_LE32(ofdm, re_acq_main_rssi_sum);
1055		PRINT_STATS_LE32(ofdm, reserved);
1056	} else {
1057		struct mvm_statistics_rx_phy *ofdm = &mvm->rx_stats.ofdm;
1058
1059		PRINT_STATS_LE32(ofdm, unresponded_rts);
1060		PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
1061		PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
1062		PRINT_STATS_LE32(ofdm, dsp_self_kill);
1063		PRINT_STATS_LE32(ofdm, reserved);
1064	}
1065
1066	pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
1067			 "Statistics_Rx - CCK");
1068	if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
1069		struct mvm_statistics_rx_phy_v2 *cck = &mvm->rx_stats_v3.cck;
1070
1071		PRINT_STATS_LE32(cck, ina_cnt);
1072		PRINT_STATS_LE32(cck, fina_cnt);
1073		PRINT_STATS_LE32(cck, plcp_err);
1074		PRINT_STATS_LE32(cck, crc32_err);
1075		PRINT_STATS_LE32(cck, overrun_err);
1076		PRINT_STATS_LE32(cck, early_overrun_err);
1077		PRINT_STATS_LE32(cck, crc32_good);
1078		PRINT_STATS_LE32(cck, false_alarm_cnt);
1079		PRINT_STATS_LE32(cck, fina_sync_err_cnt);
1080		PRINT_STATS_LE32(cck, sfd_timeout);
1081		PRINT_STATS_LE32(cck, fina_timeout);
1082		PRINT_STATS_LE32(cck, unresponded_rts);
1083		PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
1084		PRINT_STATS_LE32(cck, sent_ack_cnt);
1085		PRINT_STATS_LE32(cck, sent_cts_cnt);
1086		PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
1087		PRINT_STATS_LE32(cck, dsp_self_kill);
1088		PRINT_STATS_LE32(cck, mh_format_err);
1089		PRINT_STATS_LE32(cck, re_acq_main_rssi_sum);
1090		PRINT_STATS_LE32(cck, reserved);
1091	} else {
1092		struct mvm_statistics_rx_phy *cck = &mvm->rx_stats.cck;
1093
1094		PRINT_STATS_LE32(cck, unresponded_rts);
1095		PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
1096		PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
1097		PRINT_STATS_LE32(cck, dsp_self_kill);
1098		PRINT_STATS_LE32(cck, reserved);
1099	}
1100
1101	pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
1102			 "Statistics_Rx - GENERAL");
1103	if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
1104		struct mvm_statistics_rx_non_phy_v3 *general =
1105			&mvm->rx_stats_v3.general;
1106
1107		PRINT_STATS_LE32(general, bogus_cts);
1108		PRINT_STATS_LE32(general, bogus_ack);
1109		PRINT_STATS_LE32(general, non_bssid_frames);
1110		PRINT_STATS_LE32(general, filtered_frames);
1111		PRINT_STATS_LE32(general, non_channel_beacons);
1112		PRINT_STATS_LE32(general, channel_beacons);
1113		PRINT_STATS_LE32(general, num_missed_bcon);
1114		PRINT_STATS_LE32(general, adc_rx_saturation_time);
1115		PRINT_STATS_LE32(general, ina_detection_search_time);
1116		PRINT_STATS_LE32(general, beacon_silence_rssi_a);
1117		PRINT_STATS_LE32(general, beacon_silence_rssi_b);
1118		PRINT_STATS_LE32(general, beacon_silence_rssi_c);
1119		PRINT_STATS_LE32(general, interference_data_flag);
1120		PRINT_STATS_LE32(general, channel_load);
1121		PRINT_STATS_LE32(general, dsp_false_alarms);
1122		PRINT_STATS_LE32(general, beacon_rssi_a);
1123		PRINT_STATS_LE32(general, beacon_rssi_b);
1124		PRINT_STATS_LE32(general, beacon_rssi_c);
1125		PRINT_STATS_LE32(general, beacon_energy_a);
1126		PRINT_STATS_LE32(general, beacon_energy_b);
1127		PRINT_STATS_LE32(general, beacon_energy_c);
1128		PRINT_STATS_LE32(general, num_bt_kills);
1129		PRINT_STATS_LE32(general, mac_id);
1130		PRINT_STATS_LE32(general, directed_data_mpdu);
1131	} else {
1132		struct mvm_statistics_rx_non_phy *general =
1133			&mvm->rx_stats.general;
1134
1135		PRINT_STATS_LE32(general, bogus_cts);
1136		PRINT_STATS_LE32(general, bogus_ack);
1137		PRINT_STATS_LE32(general, non_channel_beacons);
1138		PRINT_STATS_LE32(general, channel_beacons);
1139		PRINT_STATS_LE32(general, num_missed_bcon);
1140		PRINT_STATS_LE32(general, adc_rx_saturation_time);
1141		PRINT_STATS_LE32(general, ina_detection_search_time);
1142		PRINT_STATS_LE32(general, beacon_silence_rssi_a);
1143		PRINT_STATS_LE32(general, beacon_silence_rssi_b);
1144		PRINT_STATS_LE32(general, beacon_silence_rssi_c);
1145		PRINT_STATS_LE32(general, interference_data_flag);
1146		PRINT_STATS_LE32(general, channel_load);
1147		PRINT_STATS_LE32(general, beacon_rssi_a);
1148		PRINT_STATS_LE32(general, beacon_rssi_b);
1149		PRINT_STATS_LE32(general, beacon_rssi_c);
1150		PRINT_STATS_LE32(general, beacon_energy_a);
1151		PRINT_STATS_LE32(general, beacon_energy_b);
1152		PRINT_STATS_LE32(general, beacon_energy_c);
1153		PRINT_STATS_LE32(general, num_bt_kills);
1154		PRINT_STATS_LE32(general, mac_id);
1155	}
1156
1157	pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
1158			 "Statistics_Rx - HT");
1159	if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
1160		struct mvm_statistics_rx_ht_phy_v1 *ht =
1161			&mvm->rx_stats_v3.ofdm_ht;
1162
1163		PRINT_STATS_LE32(ht, plcp_err);
1164		PRINT_STATS_LE32(ht, overrun_err);
1165		PRINT_STATS_LE32(ht, early_overrun_err);
1166		PRINT_STATS_LE32(ht, crc32_good);
1167		PRINT_STATS_LE32(ht, crc32_err);
1168		PRINT_STATS_LE32(ht, mh_format_err);
1169		PRINT_STATS_LE32(ht, agg_crc32_good);
1170		PRINT_STATS_LE32(ht, agg_mpdu_cnt);
1171		PRINT_STATS_LE32(ht, agg_cnt);
1172		PRINT_STATS_LE32(ht, unsupport_mcs);
1173	} else {
1174		struct mvm_statistics_rx_ht_phy *ht =
1175			&mvm->rx_stats.ofdm_ht;
1176
1177		PRINT_STATS_LE32(ht, mh_format_err);
1178		PRINT_STATS_LE32(ht, agg_mpdu_cnt);
1179		PRINT_STATS_LE32(ht, agg_cnt);
1180		PRINT_STATS_LE32(ht, unsupport_mcs);
1181	}
1182
1183	mutex_unlock(&mvm->mutex);
1184
1185	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1186	kfree(buf);
1187
1188	return ret;
1189}
1190#undef PRINT_STAT_LE32
1191
1192static ssize_t iwl_dbgfs_fw_system_stats_read(struct file *file,
1193					      char __user *user_buf,
1194					      size_t count, loff_t *ppos)
1195{
1196	char *buff, *pos, *endpos;
1197	int ret;
1198	size_t bufsz;
1199	int i;
1200	struct iwl_mvm_vif *mvmvif;
1201	struct ieee80211_vif *vif;
1202	struct iwl_mvm *mvm = file->private_data;
1203	u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
1204					   WIDE_ID(SYSTEM_GROUP,
1205						   SYSTEM_STATISTICS_CMD),
1206					   IWL_FW_CMD_VER_UNKNOWN);
1207
1208	/* in case of a wrong cmd version, allocate buffer only for error msg */
1209	bufsz = (cmd_ver == 1) ? 4096 : 64;
1210
1211	buff = kzalloc(bufsz, GFP_KERNEL);
1212	if (!buff)
1213		return -ENOMEM;
1214
1215	pos = buff;
1216	endpos = pos + bufsz;
1217
1218	if (cmd_ver != 1) {
1219		pos += scnprintf(pos, endpos - pos,
1220				 "System stats not supported:%d\n", cmd_ver);
1221		goto send_out;
1222	}
1223
1224	mutex_lock(&mvm->mutex);
1225	if (iwl_mvm_firmware_running(mvm))
1226		iwl_mvm_request_statistics(mvm, false);
1227
1228	for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
1229		vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, false);
1230		if (!vif)
1231			continue;
1232
1233		if (vif->type == NL80211_IFTYPE_STATION)
1234			break;
1235	}
1236
1237	if (i == NUM_MAC_INDEX_DRIVER || !vif) {
1238		pos += scnprintf(pos, endpos - pos, "vif is NULL\n");
1239		goto release_send_out;
1240	}
1241
1242	mvmvif = iwl_mvm_vif_from_mac80211(vif);
1243	if (!mvmvif) {
1244		pos += scnprintf(pos, endpos - pos, "mvmvif is NULL\n");
1245		goto release_send_out;
1246	}
1247
1248	for_each_mvm_vif_valid_link(mvmvif, i) {
1249		struct iwl_mvm_vif_link_info *link_info = mvmvif->link[i];
1250
1251		pos += scnprintf(pos, endpos - pos,
1252				 "link_id %d", i);
1253		pos += scnprintf(pos, endpos - pos,
1254				 " num_beacons %d",
1255				 link_info->beacon_stats.num_beacons);
1256		pos += scnprintf(pos, endpos - pos,
1257				 " accu_num_beacons %d",
1258				 link_info->beacon_stats.accu_num_beacons);
1259		pos += scnprintf(pos, endpos - pos,
1260				 " avg_signal %d\n",
1261				 link_info->beacon_stats.avg_signal);
1262	}
1263
1264	pos += scnprintf(pos, endpos - pos,
1265			 "radio_stats.rx_time %lld\n",
1266			 mvm->radio_stats.rx_time);
1267	pos += scnprintf(pos, endpos - pos,
1268			 "radio_stats.tx_time %lld\n",
1269			 mvm->radio_stats.tx_time);
1270	pos += scnprintf(pos, endpos - pos,
1271			 "accu_radio_stats.rx_time %lld\n",
1272			 mvm->accu_radio_stats.rx_time);
1273	pos += scnprintf(pos, endpos - pos,
1274			 "accu_radio_stats.tx_time %lld\n",
1275			 mvm->accu_radio_stats.tx_time);
1276
1277release_send_out:
1278	mutex_unlock(&mvm->mutex);
1279
1280send_out:
1281	ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
1282	kfree(buff);
1283
1284	return ret;
1285}
1286
1287static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
1288					  char __user *user_buf, size_t count,
1289					  loff_t *ppos,
1290					  struct iwl_mvm_frame_stats *stats)
1291{
1292	char *buff, *pos, *endpos;
1293	int idx, i;
1294	int ret;
1295	static const size_t bufsz = 1024;
1296
1297	buff = kmalloc(bufsz, GFP_KERNEL);
1298	if (!buff)
1299		return -ENOMEM;
1300
1301	spin_lock_bh(&mvm->drv_stats_lock);
1302
1303	pos = buff;
1304	endpos = pos + bufsz;
1305
1306	pos += scnprintf(pos, endpos - pos,
1307			 "Legacy/HT/VHT\t:\t%d/%d/%d\n",
1308			 stats->legacy_frames,
1309			 stats->ht_frames,
1310			 stats->vht_frames);
1311	pos += scnprintf(pos, endpos - pos, "20/40/80\t:\t%d/%d/%d\n",
1312			 stats->bw_20_frames,
1313			 stats->bw_40_frames,
1314			 stats->bw_80_frames);
1315	pos += scnprintf(pos, endpos - pos, "NGI/SGI\t\t:\t%d/%d\n",
1316			 stats->ngi_frames,
1317			 stats->sgi_frames);
1318	pos += scnprintf(pos, endpos - pos, "SISO/MIMO2\t:\t%d/%d\n",
1319			 stats->siso_frames,
1320			 stats->mimo2_frames);
1321	pos += scnprintf(pos, endpos - pos, "FAIL/SCSS\t:\t%d/%d\n",
1322			 stats->fail_frames,
1323			 stats->success_frames);
1324	pos += scnprintf(pos, endpos - pos, "MPDUs agg\t:\t%d\n",
1325			 stats->agg_frames);
1326	pos += scnprintf(pos, endpos - pos, "A-MPDUs\t\t:\t%d\n",
1327			 stats->ampdu_count);
1328	pos += scnprintf(pos, endpos - pos, "Avg MPDUs/A-MPDU:\t%d\n",
1329			 stats->ampdu_count > 0 ?
1330			 (stats->agg_frames / stats->ampdu_count) : 0);
1331
1332	pos += scnprintf(pos, endpos - pos, "Last Rates\n");
1333
1334	idx = stats->last_frame_idx - 1;
1335	for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) {
1336		idx = (idx + 1) % ARRAY_SIZE(stats->last_rates);
1337		if (stats->last_rates[idx] == 0)
1338			continue;
1339		pos += scnprintf(pos, endpos - pos, "Rate[%d]: ",
1340				 (int)(ARRAY_SIZE(stats->last_rates) - i));
1341		pos += rs_pretty_print_rate_v1(pos, endpos - pos,
1342					       stats->last_rates[idx]);
1343		if (pos < endpos - 1)
1344			*pos++ = '\n';
1345	}
1346	spin_unlock_bh(&mvm->drv_stats_lock);
1347
1348	ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
1349	kfree(buff);
1350
1351	return ret;
1352}
1353
1354static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file,
1355					   char __user *user_buf, size_t count,
1356					   loff_t *ppos)
1357{
1358	struct iwl_mvm *mvm = file->private_data;
1359
1360	return iwl_dbgfs_frame_stats_read(mvm, user_buf, count, ppos,
1361					  &mvm->drv_rx_stats);
1362}
1363
1364static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
1365					  size_t count, loff_t *ppos)
1366{
1367	int __maybe_unused ret;
1368
1369	if (!iwl_mvm_firmware_running(mvm))
1370		return -EIO;
1371
1372	mutex_lock(&mvm->mutex);
1373
1374	/* allow one more restart that we're provoking here */
1375	if (mvm->fw_restart >= 0)
1376		mvm->fw_restart++;
1377
1378	if (count == 6 && !strcmp(buf, "nolog\n")) {
1379		set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
1380		set_bit(STATUS_SUPPRESS_CMD_ERROR_ONCE, &mvm->trans->status);
1381	}
1382
1383	/* take the return value to make compiler happy - it will fail anyway */
1384	ret = iwl_mvm_send_cmd_pdu(mvm,
1385				   WIDE_ID(LONG_GROUP, REPLY_ERROR),
1386				   0, 0, NULL);
1387
1388	mutex_unlock(&mvm->mutex);
1389
1390	return count;
1391}
1392
1393static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
1394				      size_t count, loff_t *ppos)
1395{
1396	if (!iwl_mvm_firmware_running(mvm))
1397		return -EIO;
1398
1399	if (count == 6 && !strcmp(buf, "nolog\n"))
1400		set_bit(IWL_MVM_STATUS_SUPPRESS_ERROR_LOG_ONCE, &mvm->status);
1401
1402	iwl_force_nmi(mvm->trans);
1403
1404	return count;
1405}
1406
1407static ssize_t
1408iwl_dbgfs_scan_ant_rxchain_read(struct file *file,
1409				char __user *user_buf,
1410				size_t count, loff_t *ppos)
1411{
1412	struct iwl_mvm *mvm = file->private_data;
1413	int pos = 0;
1414	char buf[32];
1415	const size_t bufsz = sizeof(buf);
1416
1417	/* print which antennas were set for the scan command by the user */
1418	pos += scnprintf(buf + pos, bufsz - pos, "Antennas for scan: ");
1419	if (mvm->scan_rx_ant & ANT_A)
1420		pos += scnprintf(buf + pos, bufsz - pos, "A");
1421	if (mvm->scan_rx_ant & ANT_B)
1422		pos += scnprintf(buf + pos, bufsz - pos, "B");
1423	pos += scnprintf(buf + pos, bufsz - pos, " (%x)\n", mvm->scan_rx_ant);
1424
1425	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1426}
1427
1428static ssize_t
1429iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
1430				 size_t count, loff_t *ppos)
1431{
1432	u8 scan_rx_ant;
1433
1434	if (!iwl_mvm_firmware_running(mvm))
1435		return -EIO;
1436
1437	if (sscanf(buf, "%hhx", &scan_rx_ant) != 1)
1438		return -EINVAL;
1439	if (scan_rx_ant > ANT_ABC)
1440		return -EINVAL;
1441	if (scan_rx_ant & ~(iwl_mvm_get_valid_rx_ant(mvm)))
1442		return -EINVAL;
1443
1444	if (mvm->scan_rx_ant != scan_rx_ant) {
1445		mvm->scan_rx_ant = scan_rx_ant;
1446		if (fw_has_capa(&mvm->fw->ucode_capa,
1447				IWL_UCODE_TLV_CAPA_UMAC_SCAN))
1448			iwl_mvm_config_scan(mvm);
1449	}
1450
1451	return count;
1452}
1453
1454static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm,
1455					       char *buf, size_t count,
1456					       loff_t *ppos)
1457{
1458	struct iwl_rss_config_cmd cmd = {
1459		.flags = cpu_to_le32(IWL_RSS_ENABLE),
1460		.hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP |
1461			     IWL_RSS_HASH_TYPE_IPV4_UDP |
1462			     IWL_RSS_HASH_TYPE_IPV4_PAYLOAD |
1463			     IWL_RSS_HASH_TYPE_IPV6_TCP |
1464			     IWL_RSS_HASH_TYPE_IPV6_UDP |
1465			     IWL_RSS_HASH_TYPE_IPV6_PAYLOAD,
1466	};
1467	int ret, i, num_repeats, nbytes = count / 2;
1468
1469	ret = hex2bin(cmd.indirection_table, buf, nbytes);
1470	if (ret)
1471		return ret;
1472
1473	/*
1474	 * The input is the redirection table, partial or full.
1475	 * Repeat the pattern if needed.
1476	 * For example, input of 01020F will be repeated 42 times,
1477	 * indirecting RSS hash results to queues 1, 2, 15 (skipping
1478	 * queues 3 - 14).
1479	 */
1480	num_repeats = ARRAY_SIZE(cmd.indirection_table) / nbytes;
1481	for (i = 1; i < num_repeats; i++)
1482		memcpy(&cmd.indirection_table[i * nbytes],
1483		       cmd.indirection_table, nbytes);
1484	/* handle cut in the middle pattern for the last places */
1485	memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table,
1486	       ARRAY_SIZE(cmd.indirection_table) % nbytes);
1487
1488	netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key));
1489
1490	mutex_lock(&mvm->mutex);
1491	if (iwl_mvm_firmware_running(mvm))
1492		ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0,
1493					   sizeof(cmd), &cmd);
1494	else
1495		ret = 0;
1496	mutex_unlock(&mvm->mutex);
1497
1498	return ret ?: count;
1499}
1500
1501static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
1502					     char *buf, size_t count,
1503					     loff_t *ppos)
1504{
1505	struct iwl_op_mode *opmode = container_of((void *)mvm,
1506						  struct iwl_op_mode,
1507						  op_mode_specific);
1508	struct iwl_rx_cmd_buffer rxb = {
1509		._rx_page_order = 0,
1510		.truesize = 0, /* not used */
1511		._offset = 0,
1512	};
1513	struct iwl_rx_packet *pkt;
1514	int bin_len = count / 2;
1515	int ret = -EINVAL;
1516
1517	if (!iwl_mvm_firmware_running(mvm))
1518		return -EIO;
1519
1520	/* supporting only MQ RX */
1521	if (!mvm->trans->trans_cfg->mq_rx_supported)
1522		return -EOPNOTSUPP;
1523
1524	rxb._page = alloc_pages(GFP_ATOMIC, 0);
1525	if (!rxb._page)
1526		return -ENOMEM;
1527	pkt = rxb_addr(&rxb);
1528
1529	ret = hex2bin(page_address(rxb._page), buf, bin_len);
1530	if (ret)
1531		goto out;
1532
1533	/* avoid invalid memory access and malformed packet */
1534	if (bin_len < sizeof(*pkt) ||
1535	    bin_len != sizeof(*pkt) + iwl_rx_packet_payload_len(pkt))
1536		goto out;
1537
1538	local_bh_disable();
1539	iwl_mvm_rx_mq(opmode, NULL, &rxb);
1540	local_bh_enable();
1541	ret = 0;
1542
1543out:
1544	iwl_free_rxb(&rxb);
1545
1546	return ret ?: count;
1547}
1548
1549static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
1550{
1551	struct ieee80211_vif *vif;
1552	struct iwl_mvm_vif *mvmvif;
1553	struct sk_buff *beacon;
1554	struct ieee80211_tx_info *info;
1555	struct iwl_mac_beacon_cmd beacon_cmd = {};
1556	unsigned int link_id;
1557	u8 rate;
1558	int i;
1559
1560	len /= 2;
1561
1562	/* Element len should be represented by u8 */
1563	if (len >= U8_MAX)
1564		return -EINVAL;
1565
1566	if (!iwl_mvm_firmware_running(mvm))
1567		return -EIO;
1568
1569	if (!iwl_mvm_has_new_tx_api(mvm) &&
1570	    !fw_has_api(&mvm->fw->ucode_capa,
1571			IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
1572		return -EINVAL;
1573
1574	mutex_lock(&mvm->mutex);
1575
1576	for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
1577		vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, false);
1578		if (!vif)
1579			continue;
1580
1581		if (vif->type == NL80211_IFTYPE_AP)
1582			break;
1583	}
1584
1585	if (i == NUM_MAC_INDEX_DRIVER || !vif)
1586		goto out_err;
1587
1588	mvm->hw->extra_beacon_tailroom = len;
1589
1590	beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL, 0);
1591	if (!beacon)
1592		goto out_err;
1593
1594	if (len && hex2bin(skb_put_zero(beacon, len), bin, len)) {
1595		dev_kfree_skb(beacon);
1596		goto out_err;
1597	}
1598
1599	mvm->beacon_inject_active = true;
1600
1601	mvmvif = iwl_mvm_vif_from_mac80211(vif);
1602	info = IEEE80211_SKB_CB(beacon);
1603	rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif);
1604
1605	for_each_mvm_vif_valid_link(mvmvif, link_id) {
1606		beacon_cmd.flags =
1607			cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw,
1608								      rate));
1609		beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
1610		if (iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) > 12)
1611			beacon_cmd.link_id =
1612				cpu_to_le32(mvmvif->link[link_id]->fw_link_id);
1613		else
1614			beacon_cmd.link_id = cpu_to_le32((u32)mvmvif->id);
1615
1616		iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
1617					 &beacon_cmd.tim_size,
1618					 beacon->data, beacon->len);
1619
1620		iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
1621						 sizeof(beacon_cmd));
1622	}
1623	mutex_unlock(&mvm->mutex);
1624
1625	dev_kfree_skb(beacon);
1626
1627	return 0;
1628
1629out_err:
1630	mutex_unlock(&mvm->mutex);
1631	return -EINVAL;
1632}
1633
1634static ssize_t iwl_dbgfs_inject_beacon_ie_write(struct iwl_mvm *mvm,
1635						char *buf, size_t count,
1636						loff_t *ppos)
1637{
1638	int ret = _iwl_dbgfs_inject_beacon_ie(mvm, buf, count);
1639
1640	mvm->hw->extra_beacon_tailroom = 0;
1641	return ret ?: count;
1642}
1643
1644static ssize_t iwl_dbgfs_inject_beacon_ie_restore_write(struct iwl_mvm *mvm,
1645							char *buf,
1646							size_t count,
1647							loff_t *ppos)
1648{
1649	int ret = _iwl_dbgfs_inject_beacon_ie(mvm, NULL, 0);
1650
1651	mvm->hw->extra_beacon_tailroom = 0;
1652	mvm->beacon_inject_active = false;
1653	return ret ?: count;
1654}
1655
1656static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
1657					  char __user *user_buf,
1658					  size_t count, loff_t *ppos)
1659{
1660	struct iwl_mvm *mvm = file->private_data;
1661	int conf;
1662	char buf[8];
1663	const size_t bufsz = sizeof(buf);
1664	int pos = 0;
1665
1666	mutex_lock(&mvm->mutex);
1667	conf = mvm->fwrt.dump.conf;
1668	mutex_unlock(&mvm->mutex);
1669
1670	pos += scnprintf(buf + pos, bufsz - pos, "%d\n", conf);
1671
1672	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1673}
1674
1675static ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm,
1676					   char *buf, size_t count,
1677					   loff_t *ppos)
1678{
1679	unsigned int conf_id;
1680	int ret;
1681
1682	if (!iwl_mvm_firmware_running(mvm))
1683		return -EIO;
1684
1685	ret = kstrtouint(buf, 0, &conf_id);
1686	if (ret)
1687		return ret;
1688
1689	if (WARN_ON(conf_id >= FW_DBG_CONF_MAX))
1690		return -EINVAL;
1691
1692	mutex_lock(&mvm->mutex);
1693	ret = iwl_fw_start_dbg_conf(&mvm->fwrt, conf_id);
1694	mutex_unlock(&mvm->mutex);
1695
1696	return ret ?: count;
1697}
1698
1699static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
1700					      char *buf, size_t count,
1701					      loff_t *ppos)
1702{
1703	if (count == 0)
1704		return 0;
1705
1706	iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER,
1707			       NULL);
1708
1709	iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf,
1710			   (count - 1), NULL);
1711
1712	return count;
1713}
1714
1715static ssize_t iwl_dbgfs_fw_dbg_clear_write(struct iwl_mvm *mvm,
1716					    char *buf, size_t count,
1717					    loff_t *ppos)
1718{
1719	if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
1720		return -EOPNOTSUPP;
1721
1722	mutex_lock(&mvm->mutex);
1723	iwl_fw_dbg_clear_monitor_buf(&mvm->fwrt);
1724	mutex_unlock(&mvm->mutex);
1725
1726	return count;
1727}
1728
1729static ssize_t iwl_dbgfs_dbg_time_point_write(struct iwl_mvm *mvm,
1730					      char *buf, size_t count,
1731					      loff_t *ppos)
1732{
1733	u32 timepoint;
1734
1735	if (kstrtou32(buf, 0, &timepoint))
1736		return -EINVAL;
1737
1738	if (timepoint == IWL_FW_INI_TIME_POINT_INVALID ||
1739	    timepoint >= IWL_FW_INI_TIME_POINT_NUM)
1740		return -EINVAL;
1741
1742	iwl_dbg_tlv_time_point(&mvm->fwrt, timepoint, NULL);
1743
1744	return count;
1745}
1746
1747#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
1748	_MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
1749#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
1750	_MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
1751#define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do {	\
1752		debugfs_create_file(alias, mode, parent, mvm,		\
1753				    &iwl_dbgfs_##name##_ops);		\
1754	} while (0)
1755#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
1756	MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
1757
1758static ssize_t
1759_iwl_dbgfs_link_sta_wrap_write(ssize_t (*real)(struct ieee80211_link_sta *,
1760					       struct iwl_mvm_sta *,
1761					       struct iwl_mvm *,
1762					       struct iwl_mvm_link_sta *,
1763					       char *,
1764					       size_t, loff_t *),
1765			   struct file *file,
1766			   char *buf, size_t buf_size, loff_t *ppos)
1767{
1768	struct ieee80211_link_sta *link_sta = file->private_data;
1769	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(link_sta->sta);
1770	struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(mvmsta->vif)->mvm;
1771	struct iwl_mvm_link_sta *mvm_link_sta;
1772	ssize_t ret;
1773
1774	mutex_lock(&mvm->mutex);
1775
1776	mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_sta->link_id],
1777						 lockdep_is_held(&mvm->mutex));
1778	if (WARN_ON(!mvm_link_sta)) {
1779		mutex_unlock(&mvm->mutex);
1780		return -ENODEV;
1781	}
1782
1783	ret = real(link_sta, mvmsta, mvm, mvm_link_sta, buf, buf_size, ppos);
1784
1785	mutex_unlock(&mvm->mutex);
1786
1787	return ret;
1788}
1789
1790static ssize_t
1791_iwl_dbgfs_link_sta_wrap_read(ssize_t (*real)(struct ieee80211_link_sta *,
1792					      struct iwl_mvm_sta *,
1793					      struct iwl_mvm *,
1794					      struct iwl_mvm_link_sta *,
1795					      char __user *,
1796					      size_t, loff_t *),
1797			   struct file *file,
1798			   char __user *user_buf, size_t count, loff_t *ppos)
1799{
1800	struct ieee80211_link_sta *link_sta = file->private_data;
1801	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(link_sta->sta);
1802	struct iwl_mvm *mvm = iwl_mvm_vif_from_mac80211(mvmsta->vif)->mvm;
1803	struct iwl_mvm_link_sta *mvm_link_sta;
1804	ssize_t ret;
1805
1806	mutex_lock(&mvm->mutex);
1807
1808	mvm_link_sta = rcu_dereference_protected(mvmsta->link[link_sta->link_id],
1809						 lockdep_is_held(&mvm->mutex));
1810	if (WARN_ON(!mvm_link_sta)) {
1811		mutex_unlock(&mvm->mutex);
1812		return -ENODEV;
1813	}
1814
1815	ret = real(link_sta, mvmsta, mvm, mvm_link_sta, user_buf, count, ppos);
1816
1817	mutex_unlock(&mvm->mutex);
1818
1819	return ret;
1820}
1821
1822#define MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, buflen)		\
1823static ssize_t _iwl_dbgfs_link_sta_##name##_write(struct file *file,	\
1824					 const char __user *user_buf,	\
1825					 size_t count, loff_t *ppos)	\
1826{									\
1827	char buf[buflen] = {};						\
1828	size_t buf_size = min(count, sizeof(buf) -  1);			\
1829									\
1830	if (copy_from_user(buf, user_buf, buf_size))			\
1831		return -EFAULT;						\
1832									\
1833	return _iwl_dbgfs_link_sta_wrap_write(iwl_dbgfs_##name##_write,	\
1834					      file,			\
1835					      buf, buf_size, ppos);	\
1836}									\
1837
1838#define MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name)		\
1839static ssize_t _iwl_dbgfs_link_sta_##name##_read(struct file *file,	\
1840					 char __user *user_buf,		\
1841					 size_t count, loff_t *ppos)	\
1842{									\
1843	return _iwl_dbgfs_link_sta_wrap_read(iwl_dbgfs_##name##_read,	\
1844					     file,			\
1845					     user_buf, count, ppos);	\
1846}									\
1847
1848#define MVM_DEBUGFS_WRITE_LINK_STA_FILE_OPS(name, bufsz)		\
1849MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, bufsz)				\
1850static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = {	\
1851	.write = _iwl_dbgfs_link_sta_##name##_write,			\
1852	.open = simple_open,						\
1853	.llseek = generic_file_llseek,					\
1854}
1855
1856#define MVM_DEBUGFS_READ_LINK_STA_FILE_OPS(name)			\
1857MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name)					\
1858static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = {	\
1859	.read = _iwl_dbgfs_link_sta_##name##_read,			\
1860	.open = simple_open,						\
1861	.llseek = generic_file_llseek,					\
1862}
1863
1864#define MVM_DEBUGFS_READ_WRITE_LINK_STA_FILE_OPS(name, bufsz)		\
1865MVM_DEBUGFS_LINK_STA_READ_WRAPPER(name)					\
1866MVM_DEBUGFS_LINK_STA_WRITE_WRAPPER(name, bufsz)				\
1867static const struct file_operations iwl_dbgfs_link_sta_##name##_ops = {	\
1868	.read = _iwl_dbgfs_link_sta_##name##_read,			\
1869	.write = _iwl_dbgfs_link_sta_##name##_write,			\
1870	.open = simple_open,						\
1871	.llseek = generic_file_llseek,					\
1872}
1873
1874#define MVM_DEBUGFS_ADD_LINK_STA_FILE_ALIAS(alias, name, parent, mode)	\
1875		debugfs_create_file(alias, mode, parent, link_sta,	\
1876				    &iwl_dbgfs_link_sta_##name##_ops)
1877#define MVM_DEBUGFS_ADD_LINK_STA_FILE(name, parent, mode) \
1878	MVM_DEBUGFS_ADD_LINK_STA_FILE_ALIAS(#name, name, parent, mode)
1879
1880static ssize_t
1881iwl_dbgfs_prph_reg_read(struct file *file,
1882			char __user *user_buf,
1883			size_t count, loff_t *ppos)
1884{
1885	struct iwl_mvm *mvm = file->private_data;
1886	int pos = 0;
1887	char buf[32];
1888	const size_t bufsz = sizeof(buf);
1889
1890	if (!mvm->dbgfs_prph_reg_addr)
1891		return -EINVAL;
1892
1893	pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
1894		mvm->dbgfs_prph_reg_addr,
1895		iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
1896
1897	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1898}
1899
1900static ssize_t
1901iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
1902			 size_t count, loff_t *ppos)
1903{
1904	u8 args;
1905	u32 value;
1906
1907	args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
1908	/* if we only want to set the reg address - nothing more to do */
1909	if (args == 1)
1910		goto out;
1911
1912	/* otherwise, make sure we have both address and value */
1913	if (args != 2)
1914		return -EINVAL;
1915
1916	iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
1917
1918out:
1919	return count;
1920}
1921
1922static ssize_t
1923iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf,
1924			      size_t count, loff_t *ppos)
1925{
1926	int ret;
1927
1928	if (!iwl_mvm_firmware_running(mvm))
1929		return -EIO;
1930
1931	mutex_lock(&mvm->mutex);
1932	ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL);
1933	mutex_unlock(&mvm->mutex);
1934
1935	return ret ?: count;
1936}
1937
1938struct iwl_mvm_sniffer_apply {
1939	struct iwl_mvm *mvm;
1940	u8 *bssid;
1941	u16 aid;
1942};
1943
1944static bool iwl_mvm_sniffer_apply(struct iwl_notif_wait_data *notif_data,
1945				  struct iwl_rx_packet *pkt, void *data)
1946{
1947	struct iwl_mvm_sniffer_apply *apply = data;
1948
1949	apply->mvm->cur_aid = cpu_to_le16(apply->aid);
1950	memcpy(apply->mvm->cur_bssid, apply->bssid,
1951	       sizeof(apply->mvm->cur_bssid));
1952
1953	return true;
1954}
1955
1956static ssize_t
1957iwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf,
1958				  size_t count, loff_t *ppos)
1959{
1960	struct iwl_notification_wait wait;
1961	struct iwl_he_monitor_cmd he_mon_cmd = {};
1962	struct iwl_mvm_sniffer_apply apply = {
1963		.mvm = mvm,
1964	};
1965	u16 wait_cmds[] = {
1966		WIDE_ID(DATA_PATH_GROUP, HE_AIR_SNIFFER_CONFIG_CMD),
1967	};
1968	u32 aid;
1969	int ret;
1970
1971	if (!iwl_mvm_firmware_running(mvm))
1972		return -EIO;
1973
1974	ret = sscanf(buf, "%x %2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx", &aid,
1975		     &he_mon_cmd.bssid[0], &he_mon_cmd.bssid[1],
1976		     &he_mon_cmd.bssid[2], &he_mon_cmd.bssid[3],
1977		     &he_mon_cmd.bssid[4], &he_mon_cmd.bssid[5]);
1978	if (ret != 7)
1979		return -EINVAL;
1980
1981	he_mon_cmd.aid = cpu_to_le16(aid);
1982
1983	apply.aid = aid;
1984	apply.bssid = (void *)he_mon_cmd.bssid;
1985
1986	mutex_lock(&mvm->mutex);
1987
1988	/*
1989	 * Use the notification waiter to get our function triggered
1990	 * in sequence with other RX. This ensures that frames we get
1991	 * on the RX queue _before_ the new configuration is applied
1992	 * still have mvm->cur_aid pointing to the old AID, and that
1993	 * frames on the RX queue _after_ the firmware processed the
1994	 * new configuration (and sent the response, synchronously)
1995	 * get mvm->cur_aid correctly set to the new AID.
1996	 */
1997	iwl_init_notification_wait(&mvm->notif_wait, &wait,
1998				   wait_cmds, ARRAY_SIZE(wait_cmds),
1999				   iwl_mvm_sniffer_apply, &apply);
2000
2001	ret = iwl_mvm_send_cmd_pdu(mvm,
2002				   WIDE_ID(DATA_PATH_GROUP, HE_AIR_SNIFFER_CONFIG_CMD),
2003				   0,
2004				   sizeof(he_mon_cmd), &he_mon_cmd);
2005
2006	/* no need to really wait, we already did anyway */
2007	iwl_remove_notification(&mvm->notif_wait, &wait);
2008
2009	mutex_unlock(&mvm->mutex);
2010
2011	return ret ?: count;
2012}
2013
2014static ssize_t
2015iwl_dbgfs_he_sniffer_params_read(struct file *file, char __user *user_buf,
2016				 size_t count, loff_t *ppos)
2017{
2018	struct iwl_mvm *mvm = file->private_data;
2019	u8 buf[32];
2020	int len;
2021
2022	len = scnprintf(buf, sizeof(buf),
2023			"%d %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
2024			le16_to_cpu(mvm->cur_aid), mvm->cur_bssid[0],
2025			mvm->cur_bssid[1], mvm->cur_bssid[2], mvm->cur_bssid[3],
2026			mvm->cur_bssid[4], mvm->cur_bssid[5]);
2027
2028	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
2029}
2030
2031static ssize_t
2032iwl_dbgfs_uapsd_noagg_bssids_read(struct file *file, char __user *user_buf,
2033				  size_t count, loff_t *ppos)
2034{
2035	struct iwl_mvm *mvm = file->private_data;
2036	u8 buf[IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM * ETH_ALEN * 3 + 1];
2037	unsigned int pos = 0;
2038	size_t bufsz = sizeof(buf);
2039	int i;
2040
2041	mutex_lock(&mvm->mutex);
2042
2043	for (i = 0; i < IWL_MVM_UAPSD_NOAGG_LIST_LEN; i++)
2044		pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
2045				 mvm->uapsd_noagg_bssids[i].addr);
2046
2047	mutex_unlock(&mvm->mutex);
2048
2049	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2050}
2051
2052static ssize_t
2053iwl_dbgfs_ltr_config_write(struct iwl_mvm *mvm,
2054			   char *buf, size_t count, loff_t *ppos)
2055{
2056	int ret;
2057	struct iwl_ltr_config_cmd ltr_config = {0};
2058
2059	if (!iwl_mvm_firmware_running(mvm))
2060		return -EIO;
2061
2062	if (sscanf(buf, "%x,%x,%x,%x,%x,%x,%x",
2063		   &ltr_config.flags,
2064		   &ltr_config.static_long,
2065		   &ltr_config.static_short,
2066		   &ltr_config.ltr_cfg_values[0],
2067		   &ltr_config.ltr_cfg_values[1],
2068		   &ltr_config.ltr_cfg_values[2],
2069		   &ltr_config.ltr_cfg_values[3]) != 7) {
2070		return -EINVAL;
2071	}
2072
2073	mutex_lock(&mvm->mutex);
2074	ret = iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, sizeof(ltr_config),
2075				   &ltr_config);
2076	mutex_unlock(&mvm->mutex);
2077
2078	if (ret)
2079		IWL_ERR(mvm, "failed to send ltr configuration cmd\n");
2080
2081	return ret ?: count;
2082}
2083
2084static ssize_t iwl_dbgfs_rfi_freq_table_write(struct iwl_mvm *mvm, char *buf,
2085					      size_t count, loff_t *ppos)
2086{
2087	int ret = 0;
2088	u16 op_id;
2089
2090	if (kstrtou16(buf, 10, &op_id))
2091		return -EINVAL;
2092
2093	/* value zero triggers re-sending the default table to the device */
2094	if (!op_id) {
2095		mutex_lock(&mvm->mutex);
2096		ret = iwl_rfi_send_config_cmd(mvm, NULL);
2097		mutex_unlock(&mvm->mutex);
2098	} else {
2099		ret = -EOPNOTSUPP; /* in the future a new table will be added */
2100	}
2101
2102	return ret ?: count;
2103}
2104
2105/* The size computation is as follows:
2106 * each number needs at most 3 characters, number of rows is the size of
2107 * the table; So, need 5 chars for the "freq: " part and each tuple afterwards
2108 * needs 6 characters for numbers and 5 for the punctuation around.
2109 */
2110#define IWL_RFI_BUF_SIZE (IWL_RFI_LUT_INSTALLED_SIZE *\
2111				(5 + IWL_RFI_LUT_ENTRY_CHANNELS_NUM * (6 + 5)))
2112
2113static ssize_t iwl_dbgfs_rfi_freq_table_read(struct file *file,
2114					     char __user *user_buf,
2115					     size_t count, loff_t *ppos)
2116{
2117	struct iwl_mvm *mvm = file->private_data;
2118	struct iwl_rfi_freq_table_resp_cmd *resp;
2119	u32 status;
2120	char buf[IWL_RFI_BUF_SIZE];
2121	int i, j, pos = 0;
2122
2123	resp = iwl_rfi_get_freq_table(mvm);
2124	if (IS_ERR(resp))
2125		return PTR_ERR(resp);
2126
2127	status = le32_to_cpu(resp->status);
2128	if (status != RFI_FREQ_TABLE_OK) {
2129		scnprintf(buf, IWL_RFI_BUF_SIZE, "status = %d\n", status);
2130		goto out;
2131	}
2132
2133	for (i = 0; i < ARRAY_SIZE(resp->table); i++) {
2134		pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos, "%d: ",
2135				 resp->table[i].freq);
2136
2137		for (j = 0; j < ARRAY_SIZE(resp->table[i].channels); j++)
2138			pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos,
2139					 "(%d, %d) ",
2140					 resp->table[i].channels[j],
2141					 resp->table[i].bands[j]);
2142		pos += scnprintf(buf + pos, IWL_RFI_BUF_SIZE - pos, "\n");
2143	}
2144
2145out:
2146	kfree(resp);
2147	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2148}
2149
2150MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
2151
2152/* Device wide debugfs entries */
2153MVM_DEBUGFS_READ_FILE_OPS(ctdp_budget);
2154MVM_DEBUGFS_WRITE_FILE_OPS(stop_ctdp, 8);
2155MVM_DEBUGFS_WRITE_FILE_OPS(start_ctdp, 8);
2156MVM_DEBUGFS_WRITE_FILE_OPS(force_ctkill, 8);
2157MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
2158MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
2159MVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8);
2160MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
2161MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64);
2162MVM_DEBUGFS_READ_FILE_OPS(nic_temp);
2163MVM_DEBUGFS_READ_FILE_OPS(stations);
2164MVM_DEBUGFS_READ_LINK_STA_FILE_OPS(rs_data);
2165MVM_DEBUGFS_READ_FILE_OPS(bt_notif);
2166MVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
2167MVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
2168MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
2169MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
2170MVM_DEBUGFS_READ_FILE_OPS(fw_system_stats);
2171MVM_DEBUGFS_READ_FILE_OPS(fw_ver);
2172MVM_DEBUGFS_READ_FILE_OPS(phy_integration_ver);
2173MVM_DEBUGFS_READ_FILE_OPS(tas_get_status);
2174MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
2175MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
2176MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
2177MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
2178MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
2179MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
2180MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
2181MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_clear, 64);
2182MVM_DEBUGFS_WRITE_FILE_OPS(dbg_time_point, 64);
2183MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
2184			   (IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
2185MVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
2186MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie, 512);
2187MVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie_restore, 512);
2188
2189MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids);
2190
2191#ifdef CONFIG_ACPI
2192MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
2193MVM_DEBUGFS_READ_FILE_OPS(wifi_6e_enable);
2194#endif
2195
2196MVM_DEBUGFS_READ_WRITE_LINK_STA_FILE_OPS(amsdu_len, 16);
2197
2198MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32);
2199
2200MVM_DEBUGFS_WRITE_FILE_OPS(ltr_config, 512);
2201MVM_DEBUGFS_READ_WRITE_FILE_OPS(rfi_freq_table, 16);
2202
2203static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
2204				  size_t count, loff_t *ppos)
2205{
2206	struct iwl_mvm *mvm = file->private_data;
2207	struct iwl_dbg_mem_access_cmd cmd = {};
2208	struct iwl_dbg_mem_access_rsp *rsp;
2209	struct iwl_host_cmd hcmd = {
2210		.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
2211		.data = { &cmd, },
2212		.len = { sizeof(cmd) },
2213	};
2214	size_t delta;
2215	ssize_t ret, len;
2216
2217	if (!iwl_mvm_firmware_running(mvm))
2218		return -EIO;
2219
2220	hcmd.id = WIDE_ID(DEBUG_GROUP, *ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR);
2221	cmd.op = cpu_to_le32(DEBUG_MEM_OP_READ);
2222
2223	/* Take care of alignment of both the position and the length */
2224	delta = *ppos & 0x3;
2225	cmd.addr = cpu_to_le32(*ppos - delta);
2226	cmd.len = cpu_to_le32(min(ALIGN(count + delta, 4) / 4,
2227				  (size_t)DEBUG_MEM_MAX_SIZE_DWORDS));
2228
2229	mutex_lock(&mvm->mutex);
2230	ret = iwl_mvm_send_cmd(mvm, &hcmd);
2231	mutex_unlock(&mvm->mutex);
2232
2233	if (ret < 0)
2234		return ret;
2235
2236	if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) {
2237		ret = -EIO;
2238		goto out;
2239	}
2240
2241	rsp = (void *)hcmd.resp_pkt->data;
2242	if (le32_to_cpu(rsp->status) != DEBUG_MEM_STATUS_SUCCESS) {
2243		ret = -ENXIO;
2244		goto out;
2245	}
2246
2247	len = min((size_t)le32_to_cpu(rsp->len) << 2,
2248		  iwl_rx_packet_payload_len(hcmd.resp_pkt) - sizeof(*rsp));
2249	len = min(len - delta, count);
2250	if (len < 0) {
2251		ret = -EFAULT;
2252		goto out;
2253	}
2254
2255	ret = len - copy_to_user(user_buf, (u8 *)rsp->data + delta, len);
2256	*ppos += ret;
2257
2258out:
2259	iwl_free_resp(&hcmd);
2260	return ret;
2261}
2262
2263static ssize_t iwl_dbgfs_mem_write(struct file *file,
2264				   const char __user *user_buf, size_t count,
2265				   loff_t *ppos)
2266{
2267	struct iwl_mvm *mvm = file->private_data;
2268	struct iwl_dbg_mem_access_cmd *cmd;
2269	struct iwl_dbg_mem_access_rsp *rsp;
2270	struct iwl_host_cmd hcmd = {};
2271	size_t cmd_size;
2272	size_t data_size;
2273	u32 op, len;
2274	ssize_t ret;
2275
2276	if (!iwl_mvm_firmware_running(mvm))
2277		return -EIO;
2278
2279	hcmd.id = WIDE_ID(DEBUG_GROUP, *ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR);
2280
2281	if (*ppos & 0x3 || count < 4) {
2282		op = DEBUG_MEM_OP_WRITE_BYTES;
2283		len = min(count, (size_t)(4 - (*ppos & 0x3)));
2284		data_size = len;
2285	} else {
2286		op = DEBUG_MEM_OP_WRITE;
2287		len = min(count >> 2, (size_t)DEBUG_MEM_MAX_SIZE_DWORDS);
2288		data_size = len << 2;
2289	}
2290
2291	cmd_size = sizeof(*cmd) + ALIGN(data_size, 4);
2292	cmd = kzalloc(cmd_size, GFP_KERNEL);
2293	if (!cmd)
2294		return -ENOMEM;
2295
2296	cmd->op = cpu_to_le32(op);
2297	cmd->len = cpu_to_le32(len);
2298	cmd->addr = cpu_to_le32(*ppos);
2299	if (copy_from_user((void *)cmd->data, user_buf, data_size)) {
2300		kfree(cmd);
2301		return -EFAULT;
2302	}
2303
2304	hcmd.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
2305	hcmd.data[0] = (void *)cmd;
2306	hcmd.len[0] = cmd_size;
2307
2308	mutex_lock(&mvm->mutex);
2309	ret = iwl_mvm_send_cmd(mvm, &hcmd);
2310	mutex_unlock(&mvm->mutex);
2311
2312	kfree(cmd);
2313
2314	if (ret < 0)
2315		return ret;
2316
2317	if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) {
2318		ret = -EIO;
2319		goto out;
2320	}
2321
2322	rsp = (void *)hcmd.resp_pkt->data;
2323	if (rsp->status != DEBUG_MEM_STATUS_SUCCESS) {
2324		ret = -ENXIO;
2325		goto out;
2326	}
2327
2328	ret = data_size;
2329	*ppos += ret;
2330
2331out:
2332	iwl_free_resp(&hcmd);
2333	return ret;
2334}
2335
2336static const struct file_operations iwl_dbgfs_mem_ops = {
2337	.read = iwl_dbgfs_mem_read,
2338	.write = iwl_dbgfs_mem_write,
2339	.open = simple_open,
2340	.llseek = default_llseek,
2341};
2342
2343void iwl_mvm_link_sta_add_debugfs(struct ieee80211_hw *hw,
2344				  struct ieee80211_vif *vif,
2345				  struct ieee80211_link_sta *link_sta,
2346				  struct dentry *dir)
2347{
2348	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
2349
2350	if (iwl_mvm_has_tlc_offload(mvm)) {
2351		MVM_DEBUGFS_ADD_LINK_STA_FILE(rs_data, dir, 0400);
2352	}
2353
2354	MVM_DEBUGFS_ADD_LINK_STA_FILE(amsdu_len, dir, 0600);
2355}
2356
2357void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)
2358{
2359	struct dentry *bcast_dir __maybe_unused;
2360
2361	spin_lock_init(&mvm->drv_stats_lock);
2362
2363	MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, 0200);
2364	MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, 0200);
2365	MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, 0600);
2366	MVM_DEBUGFS_ADD_FILE(set_nic_temperature, mvm->debugfs_dir, 0600);
2367	MVM_DEBUGFS_ADD_FILE(nic_temp, mvm->debugfs_dir, 0400);
2368	MVM_DEBUGFS_ADD_FILE(ctdp_budget, mvm->debugfs_dir, 0400);
2369	MVM_DEBUGFS_ADD_FILE(stop_ctdp, mvm->debugfs_dir, 0200);
2370	MVM_DEBUGFS_ADD_FILE(start_ctdp, mvm->debugfs_dir, 0200);
2371	MVM_DEBUGFS_ADD_FILE(force_ctkill, mvm->debugfs_dir, 0200);
2372	MVM_DEBUGFS_ADD_FILE(stations, mvm->debugfs_dir, 0400);
2373	MVM_DEBUGFS_ADD_FILE(bt_notif, mvm->debugfs_dir, 0400);
2374	MVM_DEBUGFS_ADD_FILE(bt_cmd, mvm->debugfs_dir, 0400);
2375	MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, 0600);
2376	MVM_DEBUGFS_ADD_FILE(fw_ver, mvm->debugfs_dir, 0400);
2377	MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, 0400);
2378	MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, 0400);
2379	MVM_DEBUGFS_ADD_FILE(fw_system_stats, mvm->debugfs_dir, 0400);
2380	MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, 0200);
2381	MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, 0200);
2382	MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, 0200);
2383	MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, 0200);
2384	MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, 0600);
2385	MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, 0600);
2386	MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, 0600);
2387	MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200);
2388	MVM_DEBUGFS_ADD_FILE(fw_dbg_clear, mvm->debugfs_dir, 0200);
2389	MVM_DEBUGFS_ADD_FILE(dbg_time_point, mvm->debugfs_dir, 0200);
2390	MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
2391	MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200);
2392	MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200);
2393	MVM_DEBUGFS_ADD_FILE(inject_beacon_ie, mvm->debugfs_dir, 0200);
2394	MVM_DEBUGFS_ADD_FILE(inject_beacon_ie_restore, mvm->debugfs_dir, 0200);
2395	MVM_DEBUGFS_ADD_FILE(rfi_freq_table, mvm->debugfs_dir, 0600);
2396
2397	if (mvm->fw->phy_integration_ver)
2398		MVM_DEBUGFS_ADD_FILE(phy_integration_ver, mvm->debugfs_dir, 0400);
2399	MVM_DEBUGFS_ADD_FILE(tas_get_status, mvm->debugfs_dir, 0400);
2400#ifdef CONFIG_ACPI
2401	MVM_DEBUGFS_ADD_FILE(sar_geo_profile, mvm->debugfs_dir, 0400);
2402	MVM_DEBUGFS_ADD_FILE(wifi_6e_enable, mvm->debugfs_dir, 0400);
2403#endif
2404	MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600);
2405
2406	if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_LTR_GEN2))
2407		MVM_DEBUGFS_ADD_FILE(ltr_config, mvm->debugfs_dir, 0200);
2408
2409	debugfs_create_bool("enable_scan_iteration_notif", 0600,
2410			    mvm->debugfs_dir, &mvm->scan_iter_notif_enabled);
2411	debugfs_create_bool("drop_bcn_ap_mode", 0600, mvm->debugfs_dir,
2412			    &mvm->drop_bcn_ap_mode);
2413
2414	MVM_DEBUGFS_ADD_FILE(uapsd_noagg_bssids, mvm->debugfs_dir, S_IRUSR);
2415
2416#ifdef CONFIG_PM_SLEEP
2417	MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400);
2418	debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir,
2419			    &mvm->d3_wake_sysassert);
2420	debugfs_create_u32("last_netdetect_scans", 0400, mvm->debugfs_dir,
2421			   &mvm->last_netdetect_scans);
2422#endif
2423
2424	debugfs_create_u8("ps_disabled", 0400, mvm->debugfs_dir,
2425			  &mvm->ps_disabled);
2426	debugfs_create_blob("nvm_hw", 0400, mvm->debugfs_dir,
2427			    &mvm->nvm_hw_blob);
2428	debugfs_create_blob("nvm_sw", 0400, mvm->debugfs_dir,
2429			    &mvm->nvm_sw_blob);
2430	debugfs_create_blob("nvm_calib", 0400, mvm->debugfs_dir,
2431			    &mvm->nvm_calib_blob);
2432	debugfs_create_blob("nvm_prod", 0400, mvm->debugfs_dir,
2433			    &mvm->nvm_prod_blob);
2434	debugfs_create_blob("nvm_phy_sku", 0400, mvm->debugfs_dir,
2435			    &mvm->nvm_phy_sku_blob);
2436	debugfs_create_blob("nvm_reg", S_IRUSR,
2437			    mvm->debugfs_dir, &mvm->nvm_reg_blob);
2438
2439	debugfs_create_file("mem", 0600, mvm->debugfs_dir, mvm,
2440			    &iwl_dbgfs_mem_ops);
2441
2442	/*
2443	 * Create a symlink with mac80211. It will be removed when mac80211
2444	 * exists (before the opmode exists which removes the target.)
2445	 */
2446	if (!IS_ERR(mvm->debugfs_dir)) {
2447		char buf[100];
2448
2449		snprintf(buf, 100, "../../%pd2", mvm->debugfs_dir->d_parent);
2450		debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir,
2451				       buf);
2452	}
2453}
2454