18c2ecf20Sopenharmony_ci/******************************************************************************
28c2ecf20Sopenharmony_ci *
38c2ecf20Sopenharmony_ci * This file is provided under a dual BSD/GPLv2 license.  When using or
48c2ecf20Sopenharmony_ci * redistributing this file, you may do so under either license.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * GPL LICENSE SUMMARY
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
98c2ecf20Sopenharmony_ci * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
108c2ecf20Sopenharmony_ci * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or modify
138c2ecf20Sopenharmony_ci * it under the terms of version 2 of the GNU General Public License as
148c2ecf20Sopenharmony_ci * published by the Free Software Foundation.
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, but
178c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
188c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
198c2ecf20Sopenharmony_ci * General Public License for more details.
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * The full GNU General Public License is included in this distribution
228c2ecf20Sopenharmony_ci * in the file called COPYING.
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * Contact Information:
258c2ecf20Sopenharmony_ci *  Intel Linux Wireless <linuxwifi@intel.com>
268c2ecf20Sopenharmony_ci * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
278c2ecf20Sopenharmony_ci *
288c2ecf20Sopenharmony_ci * BSD LICENSE
298c2ecf20Sopenharmony_ci *
308c2ecf20Sopenharmony_ci * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
318c2ecf20Sopenharmony_ci * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
328c2ecf20Sopenharmony_ci * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
338c2ecf20Sopenharmony_ci * All rights reserved.
348c2ecf20Sopenharmony_ci *
358c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
368c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
378c2ecf20Sopenharmony_ci * are met:
388c2ecf20Sopenharmony_ci *
398c2ecf20Sopenharmony_ci *  * Redistributions of source code must retain the above copyright
408c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
418c2ecf20Sopenharmony_ci *  * Redistributions in binary form must reproduce the above copyright
428c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in
438c2ecf20Sopenharmony_ci *    the documentation and/or other materials provided with the
448c2ecf20Sopenharmony_ci *    distribution.
458c2ecf20Sopenharmony_ci *  * Neither the name Intel Corporation nor the names of its
468c2ecf20Sopenharmony_ci *    contributors may be used to endorse or promote products derived
478c2ecf20Sopenharmony_ci *    from this software without specific prior written permission.
488c2ecf20Sopenharmony_ci *
498c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
508c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
518c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
528c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
538c2ecf20Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
548c2ecf20Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
558c2ecf20Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
568c2ecf20Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
578c2ecf20Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
588c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
598c2ecf20Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
608c2ecf20Sopenharmony_ci *
618c2ecf20Sopenharmony_ci *****************************************************************************/
628c2ecf20Sopenharmony_ci#include <linux/vmalloc.h>
638c2ecf20Sopenharmony_ci#include <linux/ieee80211.h>
648c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci#include "mvm.h"
678c2ecf20Sopenharmony_ci#include "sta.h"
688c2ecf20Sopenharmony_ci#include "iwl-io.h"
698c2ecf20Sopenharmony_ci#include "debugfs.h"
708c2ecf20Sopenharmony_ci#include "iwl-modparams.h"
718c2ecf20Sopenharmony_ci#include "fw/error-dump.h"
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file,
748c2ecf20Sopenharmony_ci					  char __user *user_buf,
758c2ecf20Sopenharmony_ci					  size_t count, loff_t *ppos)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
788c2ecf20Sopenharmony_ci	char buf[16];
798c2ecf20Sopenharmony_ci	int pos, budget;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	if (!iwl_mvm_is_ctdp_supported(mvm))
828c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm) ||
858c2ecf20Sopenharmony_ci	    mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
868c2ecf20Sopenharmony_ci		return -EIO;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
898c2ecf20Sopenharmony_ci	budget = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_REPORT, 0);
908c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	if (budget < 0)
938c2ecf20Sopenharmony_ci		return budget;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	pos = scnprintf(buf, sizeof(buf), "%d\n", budget);
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
988c2ecf20Sopenharmony_ci}
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_stop_ctdp_write(struct iwl_mvm *mvm, char *buf,
1018c2ecf20Sopenharmony_ci					 size_t count, loff_t *ppos)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	int ret;
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	if (!iwl_mvm_is_ctdp_supported(mvm))
1068c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm) ||
1098c2ecf20Sopenharmony_ci	    mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
1108c2ecf20Sopenharmony_ci		return -EIO;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
1138c2ecf20Sopenharmony_ci	ret = iwl_mvm_ctdp_command(mvm, CTDP_CMD_OPERATION_STOP, 0);
1148c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	return ret ?: count;
1178c2ecf20Sopenharmony_ci}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_force_ctkill_write(struct iwl_mvm *mvm, char *buf,
1208c2ecf20Sopenharmony_ci					    size_t count, loff_t *ppos)
1218c2ecf20Sopenharmony_ci{
1228c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm) ||
1238c2ecf20Sopenharmony_ci	    mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
1248c2ecf20Sopenharmony_ci		return -EIO;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	iwl_mvm_enter_ctkill(mvm);
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	return count;
1298c2ecf20Sopenharmony_ci}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
1328c2ecf20Sopenharmony_ci					size_t count, loff_t *ppos)
1338c2ecf20Sopenharmony_ci{
1348c2ecf20Sopenharmony_ci	int ret;
1358c2ecf20Sopenharmony_ci	u32 flush_arg;
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm) ||
1388c2ecf20Sopenharmony_ci	    mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
1398c2ecf20Sopenharmony_ci		return -EIO;
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	if (kstrtou32(buf, 0, &flush_arg))
1428c2ecf20Sopenharmony_ci		return -EINVAL;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	if (iwl_mvm_has_new_tx_api(mvm)) {
1458c2ecf20Sopenharmony_ci		IWL_DEBUG_TX_QUEUES(mvm,
1468c2ecf20Sopenharmony_ci				    "FLUSHING all tids queues on sta_id = %d\n",
1478c2ecf20Sopenharmony_ci				    flush_arg);
1488c2ecf20Sopenharmony_ci		mutex_lock(&mvm->mutex);
1498c2ecf20Sopenharmony_ci		ret = iwl_mvm_flush_sta_tids(mvm, flush_arg, 0xFFFF, 0)
1508c2ecf20Sopenharmony_ci			? : count;
1518c2ecf20Sopenharmony_ci		mutex_unlock(&mvm->mutex);
1528c2ecf20Sopenharmony_ci		return ret;
1538c2ecf20Sopenharmony_ci	}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	IWL_DEBUG_TX_QUEUES(mvm, "FLUSHING queues mask to flush = 0x%x\n",
1568c2ecf20Sopenharmony_ci			    flush_arg);
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
1598c2ecf20Sopenharmony_ci	ret =  iwl_mvm_flush_tx_path(mvm, flush_arg, 0) ? : count;
1608c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	return ret;
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
1668c2ecf20Sopenharmony_ci					 size_t count, loff_t *ppos)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct iwl_mvm_sta *mvmsta;
1698c2ecf20Sopenharmony_ci	int sta_id, drain, ret;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm) ||
1728c2ecf20Sopenharmony_ci	    mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR)
1738c2ecf20Sopenharmony_ci		return -EIO;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	if (sscanf(buf, "%d %d", &sta_id, &drain) != 2)
1768c2ecf20Sopenharmony_ci		return -EINVAL;
1778c2ecf20Sopenharmony_ci	if (sta_id < 0 || sta_id >= mvm->fw->ucode_capa.num_stations)
1788c2ecf20Sopenharmony_ci		return -EINVAL;
1798c2ecf20Sopenharmony_ci	if (drain < 0 || drain > 1)
1808c2ecf20Sopenharmony_ci		return -EINVAL;
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	if (!mvmsta)
1878c2ecf20Sopenharmony_ci		ret = -ENOENT;
1888c2ecf20Sopenharmony_ci	else
1898c2ecf20Sopenharmony_ci		ret = iwl_mvm_drain_sta(mvm, mvmsta, drain) ? : count;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	return ret;
1948c2ecf20Sopenharmony_ci}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
1978c2ecf20Sopenharmony_ci				   size_t count, loff_t *ppos)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
2008c2ecf20Sopenharmony_ci	const struct fw_img *img;
2018c2ecf20Sopenharmony_ci	unsigned int ofs, len;
2028c2ecf20Sopenharmony_ci	size_t ret;
2038c2ecf20Sopenharmony_ci	u8 *ptr;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
2068c2ecf20Sopenharmony_ci		return -EINVAL;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	/* default is to dump the entire data segment */
2098c2ecf20Sopenharmony_ci	img = &mvm->fw->img[mvm->fwrt.cur_fw_img];
2108c2ecf20Sopenharmony_ci	ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
2118c2ecf20Sopenharmony_ci	len = img->sec[IWL_UCODE_SECTION_DATA].len;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	if (mvm->dbgfs_sram_len) {
2148c2ecf20Sopenharmony_ci		ofs = mvm->dbgfs_sram_offset;
2158c2ecf20Sopenharmony_ci		len = mvm->dbgfs_sram_len;
2168c2ecf20Sopenharmony_ci	}
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	ptr = kzalloc(len, GFP_KERNEL);
2198c2ecf20Sopenharmony_ci	if (!ptr)
2208c2ecf20Sopenharmony_ci		return -ENOMEM;
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	iwl_trans_read_mem_bytes(mvm->trans, ofs, ptr, len);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	ret = simple_read_from_buffer(user_buf, count, ppos, ptr, len);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	kfree(ptr);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	return ret;
2298c2ecf20Sopenharmony_ci}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_sram_write(struct iwl_mvm *mvm, char *buf,
2328c2ecf20Sopenharmony_ci				    size_t count, loff_t *ppos)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	const struct fw_img *img;
2358c2ecf20Sopenharmony_ci	u32 offset, len;
2368c2ecf20Sopenharmony_ci	u32 img_offset, img_len;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
2398c2ecf20Sopenharmony_ci		return -EINVAL;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	img = &mvm->fw->img[mvm->fwrt.cur_fw_img];
2428c2ecf20Sopenharmony_ci	img_offset = img->sec[IWL_UCODE_SECTION_DATA].offset;
2438c2ecf20Sopenharmony_ci	img_len = img->sec[IWL_UCODE_SECTION_DATA].len;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
2468c2ecf20Sopenharmony_ci		if ((offset & 0x3) || (len & 0x3))
2478c2ecf20Sopenharmony_ci			return -EINVAL;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci		if (offset + len > img_offset + img_len)
2508c2ecf20Sopenharmony_ci			return -EINVAL;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci		mvm->dbgfs_sram_offset = offset;
2538c2ecf20Sopenharmony_ci		mvm->dbgfs_sram_len = len;
2548c2ecf20Sopenharmony_ci	} else {
2558c2ecf20Sopenharmony_ci		mvm->dbgfs_sram_offset = 0;
2568c2ecf20Sopenharmony_ci		mvm->dbgfs_sram_len = 0;
2578c2ecf20Sopenharmony_ci	}
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	return count;
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_set_nic_temperature_read(struct file *file,
2638c2ecf20Sopenharmony_ci						  char __user *user_buf,
2648c2ecf20Sopenharmony_ci						  size_t count, loff_t *ppos)
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
2678c2ecf20Sopenharmony_ci	char buf[16];
2688c2ecf20Sopenharmony_ci	int pos;
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	if (!mvm->temperature_test)
2718c2ecf20Sopenharmony_ci		pos = scnprintf(buf , sizeof(buf), "disabled\n");
2728c2ecf20Sopenharmony_ci	else
2738c2ecf20Sopenharmony_ci		pos = scnprintf(buf , sizeof(buf), "%d\n", mvm->temperature);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2768c2ecf20Sopenharmony_ci}
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci/*
2798c2ecf20Sopenharmony_ci * Set NIC Temperature
2808c2ecf20Sopenharmony_ci * Cause the driver to ignore the actual NIC temperature reported by the FW
2818c2ecf20Sopenharmony_ci * Enable: any value between IWL_MVM_DEBUG_SET_TEMPERATURE_MIN -
2828c2ecf20Sopenharmony_ci * IWL_MVM_DEBUG_SET_TEMPERATURE_MAX
2838c2ecf20Sopenharmony_ci * Disable: IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE
2848c2ecf20Sopenharmony_ci */
2858c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm,
2868c2ecf20Sopenharmony_ci						   char *buf, size_t count,
2878c2ecf20Sopenharmony_ci						   loff_t *ppos)
2888c2ecf20Sopenharmony_ci{
2898c2ecf20Sopenharmony_ci	int temperature;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm) && !mvm->temperature_test)
2928c2ecf20Sopenharmony_ci		return -EIO;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	if (kstrtoint(buf, 10, &temperature))
2958c2ecf20Sopenharmony_ci		return -EINVAL;
2968c2ecf20Sopenharmony_ci	/* not a legal temperature */
2978c2ecf20Sopenharmony_ci	if ((temperature > IWL_MVM_DEBUG_SET_TEMPERATURE_MAX &&
2988c2ecf20Sopenharmony_ci	     temperature != IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) ||
2998c2ecf20Sopenharmony_ci	    temperature < IWL_MVM_DEBUG_SET_TEMPERATURE_MIN)
3008c2ecf20Sopenharmony_ci		return -EINVAL;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
3038c2ecf20Sopenharmony_ci	if (temperature == IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE) {
3048c2ecf20Sopenharmony_ci		if (!mvm->temperature_test)
3058c2ecf20Sopenharmony_ci			goto out;
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci		mvm->temperature_test = false;
3088c2ecf20Sopenharmony_ci		/* Since we can't read the temp while awake, just set
3098c2ecf20Sopenharmony_ci		 * it to zero until we get the next RX stats from the
3108c2ecf20Sopenharmony_ci		 * firmware.
3118c2ecf20Sopenharmony_ci		 */
3128c2ecf20Sopenharmony_ci		mvm->temperature = 0;
3138c2ecf20Sopenharmony_ci	} else {
3148c2ecf20Sopenharmony_ci		mvm->temperature_test = true;
3158c2ecf20Sopenharmony_ci		mvm->temperature = temperature;
3168c2ecf20Sopenharmony_ci	}
3178c2ecf20Sopenharmony_ci	IWL_DEBUG_TEMP(mvm, "%sabling debug set temperature (temp = %d)\n",
3188c2ecf20Sopenharmony_ci		       mvm->temperature_test ? "En" : "Dis" ,
3198c2ecf20Sopenharmony_ci		       mvm->temperature);
3208c2ecf20Sopenharmony_ci	/* handle the temperature change */
3218c2ecf20Sopenharmony_ci	iwl_mvm_tt_handler(mvm);
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ciout:
3248c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	return count;
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_nic_temp_read(struct file *file,
3308c2ecf20Sopenharmony_ci				       char __user *user_buf,
3318c2ecf20Sopenharmony_ci				       size_t count, loff_t *ppos)
3328c2ecf20Sopenharmony_ci{
3338c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
3348c2ecf20Sopenharmony_ci	char buf[16];
3358c2ecf20Sopenharmony_ci	int pos, ret;
3368c2ecf20Sopenharmony_ci	s32 temp;
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
3398c2ecf20Sopenharmony_ci		return -EIO;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
3428c2ecf20Sopenharmony_ci	ret = iwl_mvm_get_temp(mvm, &temp);
3438c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	if (ret)
3468c2ecf20Sopenharmony_ci		return -EIO;
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	pos = scnprintf(buf , sizeof(buf), "%d\n", temp);
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
3518c2ecf20Sopenharmony_ci}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI
3548c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_sar_geo_profile_read(struct file *file,
3558c2ecf20Sopenharmony_ci					      char __user *user_buf,
3568c2ecf20Sopenharmony_ci					      size_t count, loff_t *ppos)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
3598c2ecf20Sopenharmony_ci	char buf[256];
3608c2ecf20Sopenharmony_ci	int pos = 0;
3618c2ecf20Sopenharmony_ci	int bufsz = sizeof(buf);
3628c2ecf20Sopenharmony_ci	int tbl_idx;
3638c2ecf20Sopenharmony_ci	u8 *value;
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
3668c2ecf20Sopenharmony_ci		return -EIO;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
3698c2ecf20Sopenharmony_ci	tbl_idx = iwl_mvm_get_sar_geo_profile(mvm);
3708c2ecf20Sopenharmony_ci	if (tbl_idx < 0) {
3718c2ecf20Sopenharmony_ci		mutex_unlock(&mvm->mutex);
3728c2ecf20Sopenharmony_ci		return tbl_idx;
3738c2ecf20Sopenharmony_ci	}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	if (!tbl_idx) {
3768c2ecf20Sopenharmony_ci		pos = scnprintf(buf, bufsz,
3778c2ecf20Sopenharmony_ci				"SAR geographic profile disabled\n");
3788c2ecf20Sopenharmony_ci	} else {
3798c2ecf20Sopenharmony_ci		value = &mvm->fwrt.geo_profiles[tbl_idx - 1].values[0];
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci		pos += scnprintf(buf + pos, bufsz - pos,
3828c2ecf20Sopenharmony_ci				 "Use geographic profile %d\n", tbl_idx);
3838c2ecf20Sopenharmony_ci		pos += scnprintf(buf + pos, bufsz - pos,
3848c2ecf20Sopenharmony_ci				 "2.4GHz:\n\tChain A offset: %hhd dBm\n\tChain B offset: %hhd dBm\n\tmax tx power: %hhd dBm\n",
3858c2ecf20Sopenharmony_ci				 value[1], value[2], value[0]);
3868c2ecf20Sopenharmony_ci		pos += scnprintf(buf + pos, bufsz - pos,
3878c2ecf20Sopenharmony_ci				 "5.2GHz:\n\tChain A offset: %hhd dBm\n\tChain B offset: %hhd dBm\n\tmax tx power: %hhd dBm\n",
3888c2ecf20Sopenharmony_ci				 value[4], value[5], value[3]);
3898c2ecf20Sopenharmony_ci	}
3908c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
3938c2ecf20Sopenharmony_ci}
3948c2ecf20Sopenharmony_ci#endif
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
3978c2ecf20Sopenharmony_ci				       size_t count, loff_t *ppos)
3988c2ecf20Sopenharmony_ci{
3998c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
4008c2ecf20Sopenharmony_ci	struct ieee80211_sta *sta;
4018c2ecf20Sopenharmony_ci	char buf[400];
4028c2ecf20Sopenharmony_ci	int i, pos = 0, bufsz = sizeof(buf);
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	for (i = 0; i < mvm->fw->ucode_capa.num_stations; i++) {
4078c2ecf20Sopenharmony_ci		pos += scnprintf(buf + pos, bufsz - pos, "%.2d: ", i);
4088c2ecf20Sopenharmony_ci		sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
4098c2ecf20Sopenharmony_ci						lockdep_is_held(&mvm->mutex));
4108c2ecf20Sopenharmony_ci		if (!sta)
4118c2ecf20Sopenharmony_ci			pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
4128c2ecf20Sopenharmony_ci		else if (IS_ERR(sta))
4138c2ecf20Sopenharmony_ci			pos += scnprintf(buf + pos, bufsz - pos, "%ld\n",
4148c2ecf20Sopenharmony_ci					 PTR_ERR(sta));
4158c2ecf20Sopenharmony_ci		else
4168c2ecf20Sopenharmony_ci			pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
4178c2ecf20Sopenharmony_ci					 sta->addr);
4188c2ecf20Sopenharmony_ci	}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
4238c2ecf20Sopenharmony_ci}
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
4268c2ecf20Sopenharmony_ci				      size_t count, loff_t *ppos)
4278c2ecf20Sopenharmony_ci{
4288c2ecf20Sopenharmony_ci	struct ieee80211_sta *sta = file->private_data;
4298c2ecf20Sopenharmony_ci	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
4308c2ecf20Sopenharmony_ci	struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw;
4318c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = lq_sta->pers.drv;
4328c2ecf20Sopenharmony_ci	static const size_t bufsz = 2048;
4338c2ecf20Sopenharmony_ci	char *buff;
4348c2ecf20Sopenharmony_ci	int desc = 0;
4358c2ecf20Sopenharmony_ci	ssize_t ret;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	buff = kmalloc(bufsz, GFP_KERNEL);
4388c2ecf20Sopenharmony_ci	if (!buff)
4398c2ecf20Sopenharmony_ci		return -ENOMEM;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci	desc += scnprintf(buff + desc, bufsz - desc, "sta_id %d\n",
4448c2ecf20Sopenharmony_ci			  lq_sta->pers.sta_id);
4458c2ecf20Sopenharmony_ci	desc += scnprintf(buff + desc, bufsz - desc,
4468c2ecf20Sopenharmony_ci			  "fixed rate 0x%X\n",
4478c2ecf20Sopenharmony_ci			  lq_sta->pers.dbg_fixed_rate);
4488c2ecf20Sopenharmony_ci	desc += scnprintf(buff + desc, bufsz - desc,
4498c2ecf20Sopenharmony_ci			  "A-MPDU size limit %d\n",
4508c2ecf20Sopenharmony_ci			  lq_sta->pers.dbg_agg_frame_count_lim);
4518c2ecf20Sopenharmony_ci	desc += scnprintf(buff + desc, bufsz - desc,
4528c2ecf20Sopenharmony_ci			  "valid_tx_ant %s%s%s\n",
4538c2ecf20Sopenharmony_ci		(iwl_mvm_get_valid_tx_ant(mvm) & ANT_A) ? "ANT_A," : "",
4548c2ecf20Sopenharmony_ci		(iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "",
4558c2ecf20Sopenharmony_ci		(iwl_mvm_get_valid_tx_ant(mvm) & ANT_C) ? "ANT_C" : "");
4568c2ecf20Sopenharmony_ci	desc += scnprintf(buff + desc, bufsz - desc,
4578c2ecf20Sopenharmony_ci			  "last tx rate=0x%X ",
4588c2ecf20Sopenharmony_ci			  lq_sta->last_rate_n_flags);
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	desc += rs_pretty_print_rate(buff + desc, bufsz - desc,
4618c2ecf20Sopenharmony_ci				     lq_sta->last_rate_n_flags);
4628c2ecf20Sopenharmony_ci	if (desc < bufsz - 1)
4638c2ecf20Sopenharmony_ci		buff[desc++] = '\n';
4648c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
4678c2ecf20Sopenharmony_ci	kfree(buff);
4688c2ecf20Sopenharmony_ci	return ret;
4698c2ecf20Sopenharmony_ci}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta,
4728c2ecf20Sopenharmony_ci					 char *buf, size_t count,
4738c2ecf20Sopenharmony_ci					 loff_t *ppos)
4748c2ecf20Sopenharmony_ci{
4758c2ecf20Sopenharmony_ci	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
4768c2ecf20Sopenharmony_ci	int i;
4778c2ecf20Sopenharmony_ci	u16 amsdu_len;
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	if (kstrtou16(buf, 0, &amsdu_len))
4808c2ecf20Sopenharmony_ci		return -EINVAL;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	/* only change from debug set <-> debug unset */
4838c2ecf20Sopenharmony_ci	if ((amsdu_len && mvmsta->orig_amsdu_len) ||
4848c2ecf20Sopenharmony_ci	    (!!amsdu_len && mvmsta->orig_amsdu_len))
4858c2ecf20Sopenharmony_ci		return -EBUSY;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	if (amsdu_len) {
4888c2ecf20Sopenharmony_ci		mvmsta->orig_amsdu_len = sta->max_amsdu_len;
4898c2ecf20Sopenharmony_ci		sta->max_amsdu_len = amsdu_len;
4908c2ecf20Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(sta->max_tid_amsdu_len); i++)
4918c2ecf20Sopenharmony_ci			sta->max_tid_amsdu_len[i] = amsdu_len;
4928c2ecf20Sopenharmony_ci	} else {
4938c2ecf20Sopenharmony_ci		sta->max_amsdu_len = mvmsta->orig_amsdu_len;
4948c2ecf20Sopenharmony_ci		mvmsta->orig_amsdu_len = 0;
4958c2ecf20Sopenharmony_ci	}
4968c2ecf20Sopenharmony_ci	return count;
4978c2ecf20Sopenharmony_ci}
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_amsdu_len_read(struct file *file,
5008c2ecf20Sopenharmony_ci					char __user *user_buf,
5018c2ecf20Sopenharmony_ci					size_t count, loff_t *ppos)
5028c2ecf20Sopenharmony_ci{
5038c2ecf20Sopenharmony_ci	struct ieee80211_sta *sta = file->private_data;
5048c2ecf20Sopenharmony_ci	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	char buf[32];
5078c2ecf20Sopenharmony_ci	int pos;
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	pos = scnprintf(buf, sizeof(buf), "current %d ", sta->max_amsdu_len);
5108c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, sizeof(buf) - pos, "stored %d\n",
5118c2ecf20Sopenharmony_ci			 mvmsta->orig_amsdu_len);
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
5148c2ecf20Sopenharmony_ci}
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_disable_power_off_read(struct file *file,
5178c2ecf20Sopenharmony_ci						char __user *user_buf,
5188c2ecf20Sopenharmony_ci						size_t count, loff_t *ppos)
5198c2ecf20Sopenharmony_ci{
5208c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
5218c2ecf20Sopenharmony_ci	char buf[64];
5228c2ecf20Sopenharmony_ci	int bufsz = sizeof(buf);
5238c2ecf20Sopenharmony_ci	int pos = 0;
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d0=%d\n",
5268c2ecf20Sopenharmony_ci			 mvm->disable_power_off);
5278c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "disable_power_off_d3=%d\n",
5288c2ecf20Sopenharmony_ci			 mvm->disable_power_off_d3);
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
5318c2ecf20Sopenharmony_ci}
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_disable_power_off_write(struct iwl_mvm *mvm, char *buf,
5348c2ecf20Sopenharmony_ci						 size_t count, loff_t *ppos)
5358c2ecf20Sopenharmony_ci{
5368c2ecf20Sopenharmony_ci	int ret, val;
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
5398c2ecf20Sopenharmony_ci		return -EIO;
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	if (!strncmp("disable_power_off_d0=", buf, 21)) {
5428c2ecf20Sopenharmony_ci		if (sscanf(buf + 21, "%d", &val) != 1)
5438c2ecf20Sopenharmony_ci			return -EINVAL;
5448c2ecf20Sopenharmony_ci		mvm->disable_power_off = val;
5458c2ecf20Sopenharmony_ci	} else if (!strncmp("disable_power_off_d3=", buf, 21)) {
5468c2ecf20Sopenharmony_ci		if (sscanf(buf + 21, "%d", &val) != 1)
5478c2ecf20Sopenharmony_ci			return -EINVAL;
5488c2ecf20Sopenharmony_ci		mvm->disable_power_off_d3 = val;
5498c2ecf20Sopenharmony_ci	} else {
5508c2ecf20Sopenharmony_ci		return -EINVAL;
5518c2ecf20Sopenharmony_ci	}
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
5548c2ecf20Sopenharmony_ci	ret = iwl_mvm_power_update_device(mvm);
5558c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	return ret ?: count;
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_cistatic
5618c2ecf20Sopenharmony_ciint iwl_mvm_coex_dump_mbox(struct iwl_bt_coex_profile_notif *notif, char *buf,
5628c2ecf20Sopenharmony_ci			   int pos, int bufsz)
5638c2ecf20Sopenharmony_ci{
5648c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw0:\n");
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(0, LE_SLAVE_LAT, false);
5678c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(0, LE_PROF1, false);
5688c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(0, LE_PROF2, false);
5698c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(0, LE_PROF_OTHER, false);
5708c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(0, CHL_SEQ_N, false);
5718c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(0, INBAND_S, false);
5728c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(0, LE_MIN_RSSI, false);
5738c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(0, LE_SCAN, false);
5748c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(0, LE_ADV, false);
5758c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(0, LE_MAX_TX_POWER, false);
5768c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(0, OPEN_CON_1, true);
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw1:\n");
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(1, BR_MAX_TX_POWER, false);
5818c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(1, IP_SR, false);
5828c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(1, LE_MSTR, false);
5838c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(1, AGGR_TRFC_LD, false);
5848c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(1, MSG_TYPE, false);
5858c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(1, SSN, true);
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw2:\n");
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(2, SNIFF_ACT, false);
5908c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(2, PAG, false);
5918c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(2, INQUIRY, false);
5928c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(2, CONN, false);
5938c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(2, SNIFF_INTERVAL, false);
5948c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(2, DISC, false);
5958c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(2, SCO_TX_ACT, false);
5968c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(2, SCO_RX_ACT, false);
5978c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(2, ESCO_RE_TX, false);
5988c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(2, SCO_DURATION, true);
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "MBOX dw3:\n");
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, SCO_STATE, false);
6038c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, SNIFF_STATE, false);
6048c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, A2DP_STATE, false);
6058c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, A2DP_SRC, false);
6068c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, ACL_STATE, false);
6078c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, MSTR_STATE, false);
6088c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, OBX_STATE, false);
6098c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, OPEN_CON_2, false);
6108c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, TRAFFIC_LOAD, false);
6118c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, CHL_SEQN_LSB, false);
6128c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, INBAND_P, false);
6138c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, MSG_TYPE_2, false);
6148c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, SSN_2, false);
6158c2ecf20Sopenharmony_ci	BT_MBOX_PRINT(3, UPDATE_REQUEST, true);
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	return pos;
6188c2ecf20Sopenharmony_ci}
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_bt_notif_read(struct file *file, char __user *user_buf,
6218c2ecf20Sopenharmony_ci				       size_t count, loff_t *ppos)
6228c2ecf20Sopenharmony_ci{
6238c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
6248c2ecf20Sopenharmony_ci	struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
6258c2ecf20Sopenharmony_ci	char *buf;
6268c2ecf20Sopenharmony_ci	int ret, pos = 0, bufsz = sizeof(char) * 1024;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	buf = kmalloc(bufsz, GFP_KERNEL);
6298c2ecf20Sopenharmony_ci	if (!buf)
6308c2ecf20Sopenharmony_ci		return -ENOMEM;
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	pos += iwl_mvm_coex_dump_mbox(notif, buf, pos, bufsz);
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, "bt_ci_compliance = %d\n",
6378c2ecf20Sopenharmony_ci			 notif->bt_ci_compliance);
6388c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, "primary_ch_lut = %d\n",
6398c2ecf20Sopenharmony_ci			 le32_to_cpu(notif->primary_ch_lut));
6408c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, "secondary_ch_lut = %d\n",
6418c2ecf20Sopenharmony_ci			 le32_to_cpu(notif->secondary_ch_lut));
6428c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos,
6438c2ecf20Sopenharmony_ci			 bufsz - pos, "bt_activity_grading = %d\n",
6448c2ecf20Sopenharmony_ci			 le32_to_cpu(notif->bt_activity_grading));
6458c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, "bt_rrc = %d\n",
6468c2ecf20Sopenharmony_ci			 notif->rrc_status & 0xF);
6478c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, "bt_ttc = %d\n",
6488c2ecf20Sopenharmony_ci			 notif->ttc_status & 0xF);
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, "sync_sco = %d\n",
6518c2ecf20Sopenharmony_ci			 IWL_MVM_BT_COEX_SYNC2SCO);
6528c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, "mplut = %d\n",
6538c2ecf20Sopenharmony_ci			 IWL_MVM_BT_COEX_MPLUT);
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
6588c2ecf20Sopenharmony_ci	kfree(buf);
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	return ret;
6618c2ecf20Sopenharmony_ci}
6628c2ecf20Sopenharmony_ci#undef BT_MBOX_PRINT
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
6658c2ecf20Sopenharmony_ci				     size_t count, loff_t *ppos)
6668c2ecf20Sopenharmony_ci{
6678c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
6688c2ecf20Sopenharmony_ci	struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
6698c2ecf20Sopenharmony_ci	char buf[256];
6708c2ecf20Sopenharmony_ci	int bufsz = sizeof(buf);
6718c2ecf20Sopenharmony_ci	int pos = 0;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, "Channel inhibition CMD\n");
6768c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos,
6778c2ecf20Sopenharmony_ci			 "\tPrimary Channel Bitmap 0x%016llx\n",
6788c2ecf20Sopenharmony_ci			 le64_to_cpu(cmd->bt_primary_ci));
6798c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos,
6808c2ecf20Sopenharmony_ci			 "\tSecondary Channel Bitmap 0x%016llx\n",
6818c2ecf20Sopenharmony_ci			 le64_to_cpu(cmd->bt_secondary_ci));
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
6868c2ecf20Sopenharmony_ci}
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_cistatic ssize_t
6898c2ecf20Sopenharmony_ciiwl_dbgfs_bt_tx_prio_write(struct iwl_mvm *mvm, char *buf,
6908c2ecf20Sopenharmony_ci			   size_t count, loff_t *ppos)
6918c2ecf20Sopenharmony_ci{
6928c2ecf20Sopenharmony_ci	u32 bt_tx_prio;
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	if (sscanf(buf, "%u", &bt_tx_prio) != 1)
6958c2ecf20Sopenharmony_ci		return -EINVAL;
6968c2ecf20Sopenharmony_ci	if (bt_tx_prio > 4)
6978c2ecf20Sopenharmony_ci		return -EINVAL;
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	mvm->bt_tx_prio = bt_tx_prio;
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_ci	return count;
7028c2ecf20Sopenharmony_ci}
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_cistatic ssize_t
7058c2ecf20Sopenharmony_ciiwl_dbgfs_bt_force_ant_write(struct iwl_mvm *mvm, char *buf,
7068c2ecf20Sopenharmony_ci			     size_t count, loff_t *ppos)
7078c2ecf20Sopenharmony_ci{
7088c2ecf20Sopenharmony_ci	static const char * const modes_str[BT_FORCE_ANT_MAX] = {
7098c2ecf20Sopenharmony_ci		[BT_FORCE_ANT_DIS] = "dis",
7108c2ecf20Sopenharmony_ci		[BT_FORCE_ANT_AUTO] = "auto",
7118c2ecf20Sopenharmony_ci		[BT_FORCE_ANT_BT] = "bt",
7128c2ecf20Sopenharmony_ci		[BT_FORCE_ANT_WIFI] = "wifi",
7138c2ecf20Sopenharmony_ci	};
7148c2ecf20Sopenharmony_ci	int ret, bt_force_ant_mode;
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	ret = match_string(modes_str, ARRAY_SIZE(modes_str), buf);
7178c2ecf20Sopenharmony_ci	if (ret < 0)
7188c2ecf20Sopenharmony_ci		return ret;
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	bt_force_ant_mode = ret;
7218c2ecf20Sopenharmony_ci	ret = 0;
7228c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
7238c2ecf20Sopenharmony_ci	if (mvm->bt_force_ant_mode == bt_force_ant_mode)
7248c2ecf20Sopenharmony_ci		goto out;
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	mvm->bt_force_ant_mode = bt_force_ant_mode;
7278c2ecf20Sopenharmony_ci	IWL_DEBUG_COEX(mvm, "Force mode: %s\n",
7288c2ecf20Sopenharmony_ci		       modes_str[mvm->bt_force_ant_mode]);
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci	if (iwl_mvm_firmware_running(mvm))
7318c2ecf20Sopenharmony_ci		ret = iwl_mvm_send_bt_init_conf(mvm);
7328c2ecf20Sopenharmony_ci	else
7338c2ecf20Sopenharmony_ci		ret = 0;
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ciout:
7368c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
7378c2ecf20Sopenharmony_ci	return ret ?: count;
7388c2ecf20Sopenharmony_ci}
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,
7418c2ecf20Sopenharmony_ci				     size_t count, loff_t *ppos)
7428c2ecf20Sopenharmony_ci{
7438c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
7448c2ecf20Sopenharmony_ci	char *buff, *pos, *endpos;
7458c2ecf20Sopenharmony_ci	static const size_t bufsz = 1024;
7468c2ecf20Sopenharmony_ci	int ret;
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	buff = kmalloc(bufsz, GFP_KERNEL);
7498c2ecf20Sopenharmony_ci	if (!buff)
7508c2ecf20Sopenharmony_ci		return -ENOMEM;
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	pos = buff;
7538c2ecf20Sopenharmony_ci	endpos = pos + bufsz;
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci	pos += scnprintf(pos, endpos - pos, "FW prefix: %s\n",
7568c2ecf20Sopenharmony_ci			 mvm->trans->cfg->fw_name_pre);
7578c2ecf20Sopenharmony_ci	pos += scnprintf(pos, endpos - pos, "FW: %s\n",
7588c2ecf20Sopenharmony_ci			 mvm->fwrt.fw->human_readable);
7598c2ecf20Sopenharmony_ci	pos += scnprintf(pos, endpos - pos, "Device: %s\n",
7608c2ecf20Sopenharmony_ci			 mvm->fwrt.trans->name);
7618c2ecf20Sopenharmony_ci	pos += scnprintf(pos, endpos - pos, "Bus: %s\n",
7628c2ecf20Sopenharmony_ci			 mvm->fwrt.dev->bus->name);
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci	ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
7658c2ecf20Sopenharmony_ci	kfree(buff);
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	return ret;
7688c2ecf20Sopenharmony_ci}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci#define PRINT_STATS_LE32(_struct, _memb)				\
7718c2ecf20Sopenharmony_ci			 pos += scnprintf(buf + pos, bufsz - pos,	\
7728c2ecf20Sopenharmony_ci					  fmt_table, #_memb,		\
7738c2ecf20Sopenharmony_ci					  le32_to_cpu(_struct->_memb))
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_fw_rx_stats_read(struct file *file,
7768c2ecf20Sopenharmony_ci					  char __user *user_buf, size_t count,
7778c2ecf20Sopenharmony_ci					  loff_t *ppos)
7788c2ecf20Sopenharmony_ci{
7798c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
7808c2ecf20Sopenharmony_ci	static const char *fmt_table = "\t%-30s %10u\n";
7818c2ecf20Sopenharmony_ci	static const char *fmt_header = "%-32s\n";
7828c2ecf20Sopenharmony_ci	int pos = 0;
7838c2ecf20Sopenharmony_ci	char *buf;
7848c2ecf20Sopenharmony_ci	int ret;
7858c2ecf20Sopenharmony_ci	size_t bufsz;
7868c2ecf20Sopenharmony_ci
7878c2ecf20Sopenharmony_ci	if (iwl_mvm_has_new_rx_stats_api(mvm))
7888c2ecf20Sopenharmony_ci		bufsz = ((sizeof(struct mvm_statistics_rx) /
7898c2ecf20Sopenharmony_ci			  sizeof(__le32)) * 43) + (4 * 33) + 1;
7908c2ecf20Sopenharmony_ci	else
7918c2ecf20Sopenharmony_ci		/* 43 = size of each data line; 33 = size of each header */
7928c2ecf20Sopenharmony_ci		bufsz = ((sizeof(struct mvm_statistics_rx_v3) /
7938c2ecf20Sopenharmony_ci			  sizeof(__le32)) * 43) + (4 * 33) + 1;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci	buf = kzalloc(bufsz, GFP_KERNEL);
7968c2ecf20Sopenharmony_ci	if (!buf)
7978c2ecf20Sopenharmony_ci		return -ENOMEM;
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	if (iwl_mvm_firmware_running(mvm))
8028c2ecf20Sopenharmony_ci		iwl_mvm_request_statistics(mvm, false);
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
8058c2ecf20Sopenharmony_ci			 "Statistics_Rx - OFDM");
8068c2ecf20Sopenharmony_ci	if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
8078c2ecf20Sopenharmony_ci		struct mvm_statistics_rx_phy_v2 *ofdm = &mvm->rx_stats_v3.ofdm;
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, ina_cnt);
8108c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, fina_cnt);
8118c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, plcp_err);
8128c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, crc32_err);
8138c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, overrun_err);
8148c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, early_overrun_err);
8158c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, crc32_good);
8168c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, false_alarm_cnt);
8178c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, fina_sync_err_cnt);
8188c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, sfd_timeout);
8198c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, fina_timeout);
8208c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, unresponded_rts);
8218c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
8228c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, sent_ack_cnt);
8238c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, sent_cts_cnt);
8248c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
8258c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, dsp_self_kill);
8268c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, mh_format_err);
8278c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, re_acq_main_rssi_sum);
8288c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, reserved);
8298c2ecf20Sopenharmony_ci	} else {
8308c2ecf20Sopenharmony_ci		struct mvm_statistics_rx_phy *ofdm = &mvm->rx_stats.ofdm;
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, unresponded_rts);
8338c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, rxe_frame_lmt_overrun);
8348c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, sent_ba_rsp_cnt);
8358c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, dsp_self_kill);
8368c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ofdm, reserved);
8378c2ecf20Sopenharmony_ci	}
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
8408c2ecf20Sopenharmony_ci			 "Statistics_Rx - CCK");
8418c2ecf20Sopenharmony_ci	if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
8428c2ecf20Sopenharmony_ci		struct mvm_statistics_rx_phy_v2 *cck = &mvm->rx_stats_v3.cck;
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, ina_cnt);
8458c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, fina_cnt);
8468c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, plcp_err);
8478c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, crc32_err);
8488c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, overrun_err);
8498c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, early_overrun_err);
8508c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, crc32_good);
8518c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, false_alarm_cnt);
8528c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, fina_sync_err_cnt);
8538c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, sfd_timeout);
8548c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, fina_timeout);
8558c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, unresponded_rts);
8568c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
8578c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, sent_ack_cnt);
8588c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, sent_cts_cnt);
8598c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
8608c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, dsp_self_kill);
8618c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, mh_format_err);
8628c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, re_acq_main_rssi_sum);
8638c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, reserved);
8648c2ecf20Sopenharmony_ci	} else {
8658c2ecf20Sopenharmony_ci		struct mvm_statistics_rx_phy *cck = &mvm->rx_stats.cck;
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, unresponded_rts);
8688c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, rxe_frame_lmt_overrun);
8698c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, sent_ba_rsp_cnt);
8708c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, dsp_self_kill);
8718c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(cck, reserved);
8728c2ecf20Sopenharmony_ci	}
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
8758c2ecf20Sopenharmony_ci			 "Statistics_Rx - GENERAL");
8768c2ecf20Sopenharmony_ci	if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
8778c2ecf20Sopenharmony_ci		struct mvm_statistics_rx_non_phy_v3 *general =
8788c2ecf20Sopenharmony_ci			&mvm->rx_stats_v3.general;
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, bogus_cts);
8818c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, bogus_ack);
8828c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, non_bssid_frames);
8838c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, filtered_frames);
8848c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, non_channel_beacons);
8858c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, channel_beacons);
8868c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, num_missed_bcon);
8878c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, adc_rx_saturation_time);
8888c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, ina_detection_search_time);
8898c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_silence_rssi_a);
8908c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_silence_rssi_b);
8918c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_silence_rssi_c);
8928c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, interference_data_flag);
8938c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, channel_load);
8948c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, dsp_false_alarms);
8958c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_rssi_a);
8968c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_rssi_b);
8978c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_rssi_c);
8988c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_energy_a);
8998c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_energy_b);
9008c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_energy_c);
9018c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, num_bt_kills);
9028c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, mac_id);
9038c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, directed_data_mpdu);
9048c2ecf20Sopenharmony_ci	} else {
9058c2ecf20Sopenharmony_ci		struct mvm_statistics_rx_non_phy *general =
9068c2ecf20Sopenharmony_ci			&mvm->rx_stats.general;
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, bogus_cts);
9098c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, bogus_ack);
9108c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, non_channel_beacons);
9118c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, channel_beacons);
9128c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, num_missed_bcon);
9138c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, adc_rx_saturation_time);
9148c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, ina_detection_search_time);
9158c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_silence_rssi_a);
9168c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_silence_rssi_b);
9178c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_silence_rssi_c);
9188c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, interference_data_flag);
9198c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, channel_load);
9208c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_rssi_a);
9218c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_rssi_b);
9228c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_rssi_c);
9238c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_energy_a);
9248c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_energy_b);
9258c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, beacon_energy_c);
9268c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, num_bt_kills);
9278c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(general, mac_id);
9288c2ecf20Sopenharmony_ci	}
9298c2ecf20Sopenharmony_ci
9308c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, fmt_header,
9318c2ecf20Sopenharmony_ci			 "Statistics_Rx - HT");
9328c2ecf20Sopenharmony_ci	if (!iwl_mvm_has_new_rx_stats_api(mvm)) {
9338c2ecf20Sopenharmony_ci		struct mvm_statistics_rx_ht_phy_v1 *ht =
9348c2ecf20Sopenharmony_ci			&mvm->rx_stats_v3.ofdm_ht;
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, plcp_err);
9378c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, overrun_err);
9388c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, early_overrun_err);
9398c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, crc32_good);
9408c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, crc32_err);
9418c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, mh_format_err);
9428c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, agg_crc32_good);
9438c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, agg_mpdu_cnt);
9448c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, agg_cnt);
9458c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, unsupport_mcs);
9468c2ecf20Sopenharmony_ci	} else {
9478c2ecf20Sopenharmony_ci		struct mvm_statistics_rx_ht_phy *ht =
9488c2ecf20Sopenharmony_ci			&mvm->rx_stats.ofdm_ht;
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, mh_format_err);
9518c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, agg_mpdu_cnt);
9528c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, agg_cnt);
9538c2ecf20Sopenharmony_ci		PRINT_STATS_LE32(ht, unsupport_mcs);
9548c2ecf20Sopenharmony_ci	}
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
9598c2ecf20Sopenharmony_ci	kfree(buf);
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_ci	return ret;
9628c2ecf20Sopenharmony_ci}
9638c2ecf20Sopenharmony_ci#undef PRINT_STAT_LE32
9648c2ecf20Sopenharmony_ci
9658c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
9668c2ecf20Sopenharmony_ci					  char __user *user_buf, size_t count,
9678c2ecf20Sopenharmony_ci					  loff_t *ppos,
9688c2ecf20Sopenharmony_ci					  struct iwl_mvm_frame_stats *stats)
9698c2ecf20Sopenharmony_ci{
9708c2ecf20Sopenharmony_ci	char *buff, *pos, *endpos;
9718c2ecf20Sopenharmony_ci	int idx, i;
9728c2ecf20Sopenharmony_ci	int ret;
9738c2ecf20Sopenharmony_ci	static const size_t bufsz = 1024;
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	buff = kmalloc(bufsz, GFP_KERNEL);
9768c2ecf20Sopenharmony_ci	if (!buff)
9778c2ecf20Sopenharmony_ci		return -ENOMEM;
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci	spin_lock_bh(&mvm->drv_stats_lock);
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	pos = buff;
9828c2ecf20Sopenharmony_ci	endpos = pos + bufsz;
9838c2ecf20Sopenharmony_ci
9848c2ecf20Sopenharmony_ci	pos += scnprintf(pos, endpos - pos,
9858c2ecf20Sopenharmony_ci			 "Legacy/HT/VHT\t:\t%d/%d/%d\n",
9868c2ecf20Sopenharmony_ci			 stats->legacy_frames,
9878c2ecf20Sopenharmony_ci			 stats->ht_frames,
9888c2ecf20Sopenharmony_ci			 stats->vht_frames);
9898c2ecf20Sopenharmony_ci	pos += scnprintf(pos, endpos - pos, "20/40/80\t:\t%d/%d/%d\n",
9908c2ecf20Sopenharmony_ci			 stats->bw_20_frames,
9918c2ecf20Sopenharmony_ci			 stats->bw_40_frames,
9928c2ecf20Sopenharmony_ci			 stats->bw_80_frames);
9938c2ecf20Sopenharmony_ci	pos += scnprintf(pos, endpos - pos, "NGI/SGI\t\t:\t%d/%d\n",
9948c2ecf20Sopenharmony_ci			 stats->ngi_frames,
9958c2ecf20Sopenharmony_ci			 stats->sgi_frames);
9968c2ecf20Sopenharmony_ci	pos += scnprintf(pos, endpos - pos, "SISO/MIMO2\t:\t%d/%d\n",
9978c2ecf20Sopenharmony_ci			 stats->siso_frames,
9988c2ecf20Sopenharmony_ci			 stats->mimo2_frames);
9998c2ecf20Sopenharmony_ci	pos += scnprintf(pos, endpos - pos, "FAIL/SCSS\t:\t%d/%d\n",
10008c2ecf20Sopenharmony_ci			 stats->fail_frames,
10018c2ecf20Sopenharmony_ci			 stats->success_frames);
10028c2ecf20Sopenharmony_ci	pos += scnprintf(pos, endpos - pos, "MPDUs agg\t:\t%d\n",
10038c2ecf20Sopenharmony_ci			 stats->agg_frames);
10048c2ecf20Sopenharmony_ci	pos += scnprintf(pos, endpos - pos, "A-MPDUs\t\t:\t%d\n",
10058c2ecf20Sopenharmony_ci			 stats->ampdu_count);
10068c2ecf20Sopenharmony_ci	pos += scnprintf(pos, endpos - pos, "Avg MPDUs/A-MPDU:\t%d\n",
10078c2ecf20Sopenharmony_ci			 stats->ampdu_count > 0 ?
10088c2ecf20Sopenharmony_ci			 (stats->agg_frames / stats->ampdu_count) : 0);
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	pos += scnprintf(pos, endpos - pos, "Last Rates\n");
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	idx = stats->last_frame_idx - 1;
10138c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(stats->last_rates); i++) {
10148c2ecf20Sopenharmony_ci		idx = (idx + 1) % ARRAY_SIZE(stats->last_rates);
10158c2ecf20Sopenharmony_ci		if (stats->last_rates[idx] == 0)
10168c2ecf20Sopenharmony_ci			continue;
10178c2ecf20Sopenharmony_ci		pos += scnprintf(pos, endpos - pos, "Rate[%d]: ",
10188c2ecf20Sopenharmony_ci				 (int)(ARRAY_SIZE(stats->last_rates) - i));
10198c2ecf20Sopenharmony_ci		pos += rs_pretty_print_rate(pos, endpos - pos,
10208c2ecf20Sopenharmony_ci					    stats->last_rates[idx]);
10218c2ecf20Sopenharmony_ci		if (pos < endpos - 1)
10228c2ecf20Sopenharmony_ci			*pos++ = '\n';
10238c2ecf20Sopenharmony_ci	}
10248c2ecf20Sopenharmony_ci	spin_unlock_bh(&mvm->drv_stats_lock);
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ci	ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff);
10278c2ecf20Sopenharmony_ci	kfree(buff);
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	return ret;
10308c2ecf20Sopenharmony_ci}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file,
10338c2ecf20Sopenharmony_ci					   char __user *user_buf, size_t count,
10348c2ecf20Sopenharmony_ci					   loff_t *ppos)
10358c2ecf20Sopenharmony_ci{
10368c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	return iwl_dbgfs_frame_stats_read(mvm, user_buf, count, ppos,
10398c2ecf20Sopenharmony_ci					  &mvm->drv_rx_stats);
10408c2ecf20Sopenharmony_ci}
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
10438c2ecf20Sopenharmony_ci					  size_t count, loff_t *ppos)
10448c2ecf20Sopenharmony_ci{
10458c2ecf20Sopenharmony_ci	int __maybe_unused ret;
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
10488c2ecf20Sopenharmony_ci		return -EIO;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci	/* allow one more restart that we're provoking here */
10538c2ecf20Sopenharmony_ci	if (mvm->fw_restart >= 0)
10548c2ecf20Sopenharmony_ci		mvm->fw_restart++;
10558c2ecf20Sopenharmony_ci
10568c2ecf20Sopenharmony_ci	/* take the return value to make compiler happy - it will fail anyway */
10578c2ecf20Sopenharmony_ci	ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, 0, 0, NULL);
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	return count;
10628c2ecf20Sopenharmony_ci}
10638c2ecf20Sopenharmony_ci
10648c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
10658c2ecf20Sopenharmony_ci				      size_t count, loff_t *ppos)
10668c2ecf20Sopenharmony_ci{
10678c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
10688c2ecf20Sopenharmony_ci		return -EIO;
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_ci	iwl_force_nmi(mvm->trans);
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci	return count;
10738c2ecf20Sopenharmony_ci}
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_cistatic ssize_t
10768c2ecf20Sopenharmony_ciiwl_dbgfs_scan_ant_rxchain_read(struct file *file,
10778c2ecf20Sopenharmony_ci				char __user *user_buf,
10788c2ecf20Sopenharmony_ci				size_t count, loff_t *ppos)
10798c2ecf20Sopenharmony_ci{
10808c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
10818c2ecf20Sopenharmony_ci	int pos = 0;
10828c2ecf20Sopenharmony_ci	char buf[32];
10838c2ecf20Sopenharmony_ci	const size_t bufsz = sizeof(buf);
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci	/* print which antennas were set for the scan command by the user */
10868c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, "Antennas for scan: ");
10878c2ecf20Sopenharmony_ci	if (mvm->scan_rx_ant & ANT_A)
10888c2ecf20Sopenharmony_ci		pos += scnprintf(buf + pos, bufsz - pos, "A");
10898c2ecf20Sopenharmony_ci	if (mvm->scan_rx_ant & ANT_B)
10908c2ecf20Sopenharmony_ci		pos += scnprintf(buf + pos, bufsz - pos, "B");
10918c2ecf20Sopenharmony_ci	if (mvm->scan_rx_ant & ANT_C)
10928c2ecf20Sopenharmony_ci		pos += scnprintf(buf + pos, bufsz - pos, "C");
10938c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, " (%hhx)\n", mvm->scan_rx_ant);
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
10968c2ecf20Sopenharmony_ci}
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_cistatic ssize_t
10998c2ecf20Sopenharmony_ciiwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
11008c2ecf20Sopenharmony_ci				 size_t count, loff_t *ppos)
11018c2ecf20Sopenharmony_ci{
11028c2ecf20Sopenharmony_ci	u8 scan_rx_ant;
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
11058c2ecf20Sopenharmony_ci		return -EIO;
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	if (sscanf(buf, "%hhx", &scan_rx_ant) != 1)
11088c2ecf20Sopenharmony_ci		return -EINVAL;
11098c2ecf20Sopenharmony_ci	if (scan_rx_ant > ANT_ABC)
11108c2ecf20Sopenharmony_ci		return -EINVAL;
11118c2ecf20Sopenharmony_ci	if (scan_rx_ant & ~(iwl_mvm_get_valid_rx_ant(mvm)))
11128c2ecf20Sopenharmony_ci		return -EINVAL;
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_ci	if (mvm->scan_rx_ant != scan_rx_ant) {
11158c2ecf20Sopenharmony_ci		mvm->scan_rx_ant = scan_rx_ant;
11168c2ecf20Sopenharmony_ci		if (fw_has_capa(&mvm->fw->ucode_capa,
11178c2ecf20Sopenharmony_ci				IWL_UCODE_TLV_CAPA_UMAC_SCAN))
11188c2ecf20Sopenharmony_ci			iwl_mvm_config_scan(mvm);
11198c2ecf20Sopenharmony_ci	}
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_ci	return count;
11228c2ecf20Sopenharmony_ci}
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm,
11258c2ecf20Sopenharmony_ci					       char *buf, size_t count,
11268c2ecf20Sopenharmony_ci					       loff_t *ppos)
11278c2ecf20Sopenharmony_ci{
11288c2ecf20Sopenharmony_ci	struct iwl_rss_config_cmd cmd = {
11298c2ecf20Sopenharmony_ci		.flags = cpu_to_le32(IWL_RSS_ENABLE),
11308c2ecf20Sopenharmony_ci		.hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP |
11318c2ecf20Sopenharmony_ci			     IWL_RSS_HASH_TYPE_IPV4_UDP |
11328c2ecf20Sopenharmony_ci			     IWL_RSS_HASH_TYPE_IPV4_PAYLOAD |
11338c2ecf20Sopenharmony_ci			     IWL_RSS_HASH_TYPE_IPV6_TCP |
11348c2ecf20Sopenharmony_ci			     IWL_RSS_HASH_TYPE_IPV6_UDP |
11358c2ecf20Sopenharmony_ci			     IWL_RSS_HASH_TYPE_IPV6_PAYLOAD,
11368c2ecf20Sopenharmony_ci	};
11378c2ecf20Sopenharmony_ci	int ret, i, num_repeats, nbytes = count / 2;
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci	ret = hex2bin(cmd.indirection_table, buf, nbytes);
11408c2ecf20Sopenharmony_ci	if (ret)
11418c2ecf20Sopenharmony_ci		return ret;
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci	/*
11448c2ecf20Sopenharmony_ci	 * The input is the redirection table, partial or full.
11458c2ecf20Sopenharmony_ci	 * Repeat the pattern if needed.
11468c2ecf20Sopenharmony_ci	 * For example, input of 01020F will be repeated 42 times,
11478c2ecf20Sopenharmony_ci	 * indirecting RSS hash results to queues 1, 2, 15 (skipping
11488c2ecf20Sopenharmony_ci	 * queues 3 - 14).
11498c2ecf20Sopenharmony_ci	 */
11508c2ecf20Sopenharmony_ci	num_repeats = ARRAY_SIZE(cmd.indirection_table) / nbytes;
11518c2ecf20Sopenharmony_ci	for (i = 1; i < num_repeats; i++)
11528c2ecf20Sopenharmony_ci		memcpy(&cmd.indirection_table[i * nbytes],
11538c2ecf20Sopenharmony_ci		       cmd.indirection_table, nbytes);
11548c2ecf20Sopenharmony_ci	/* handle cut in the middle pattern for the last places */
11558c2ecf20Sopenharmony_ci	memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table,
11568c2ecf20Sopenharmony_ci	       ARRAY_SIZE(cmd.indirection_table) % nbytes);
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	netdev_rss_key_fill(cmd.secret_key, sizeof(cmd.secret_key));
11598c2ecf20Sopenharmony_ci
11608c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
11618c2ecf20Sopenharmony_ci	if (iwl_mvm_firmware_running(mvm))
11628c2ecf20Sopenharmony_ci		ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0,
11638c2ecf20Sopenharmony_ci					   sizeof(cmd), &cmd);
11648c2ecf20Sopenharmony_ci	else
11658c2ecf20Sopenharmony_ci		ret = 0;
11668c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
11678c2ecf20Sopenharmony_ci
11688c2ecf20Sopenharmony_ci	return ret ?: count;
11698c2ecf20Sopenharmony_ci}
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
11728c2ecf20Sopenharmony_ci					     char *buf, size_t count,
11738c2ecf20Sopenharmony_ci					     loff_t *ppos)
11748c2ecf20Sopenharmony_ci{
11758c2ecf20Sopenharmony_ci	struct iwl_rx_cmd_buffer rxb = {
11768c2ecf20Sopenharmony_ci		._rx_page_order = 0,
11778c2ecf20Sopenharmony_ci		.truesize = 0, /* not used */
11788c2ecf20Sopenharmony_ci		._offset = 0,
11798c2ecf20Sopenharmony_ci	};
11808c2ecf20Sopenharmony_ci	struct iwl_rx_packet *pkt;
11818c2ecf20Sopenharmony_ci	struct iwl_rx_mpdu_desc *desc;
11828c2ecf20Sopenharmony_ci	int bin_len = count / 2;
11838c2ecf20Sopenharmony_ci	int ret = -EINVAL;
11848c2ecf20Sopenharmony_ci	size_t mpdu_cmd_hdr_size = (mvm->trans->trans_cfg->device_family >=
11858c2ecf20Sopenharmony_ci				    IWL_DEVICE_FAMILY_AX210) ?
11868c2ecf20Sopenharmony_ci		sizeof(struct iwl_rx_mpdu_desc) :
11878c2ecf20Sopenharmony_ci		IWL_RX_DESC_SIZE_V1;
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
11908c2ecf20Sopenharmony_ci		return -EIO;
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	/* supporting only 9000 descriptor */
11938c2ecf20Sopenharmony_ci	if (!mvm->trans->trans_cfg->mq_rx_supported)
11948c2ecf20Sopenharmony_ci		return -ENOTSUPP;
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci	rxb._page = alloc_pages(GFP_ATOMIC, 0);
11978c2ecf20Sopenharmony_ci	if (!rxb._page)
11988c2ecf20Sopenharmony_ci		return -ENOMEM;
11998c2ecf20Sopenharmony_ci	pkt = rxb_addr(&rxb);
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	ret = hex2bin(page_address(rxb._page), buf, bin_len);
12028c2ecf20Sopenharmony_ci	if (ret)
12038c2ecf20Sopenharmony_ci		goto out;
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	/* avoid invalid memory access */
12068c2ecf20Sopenharmony_ci	if (bin_len < sizeof(*pkt) + mpdu_cmd_hdr_size)
12078c2ecf20Sopenharmony_ci		goto out;
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	/* check this is RX packet */
12108c2ecf20Sopenharmony_ci	if (WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd) !=
12118c2ecf20Sopenharmony_ci	    WIDE_ID(LEGACY_GROUP, REPLY_RX_MPDU_CMD))
12128c2ecf20Sopenharmony_ci		goto out;
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	/* check the length in metadata matches actual received length */
12158c2ecf20Sopenharmony_ci	desc = (void *)pkt->data;
12168c2ecf20Sopenharmony_ci	if (le16_to_cpu(desc->mpdu_len) !=
12178c2ecf20Sopenharmony_ci	    (bin_len - mpdu_cmd_hdr_size - sizeof(*pkt)))
12188c2ecf20Sopenharmony_ci		goto out;
12198c2ecf20Sopenharmony_ci
12208c2ecf20Sopenharmony_ci	local_bh_disable();
12218c2ecf20Sopenharmony_ci	iwl_mvm_rx_mpdu_mq(mvm, NULL, &rxb, 0);
12228c2ecf20Sopenharmony_ci	local_bh_enable();
12238c2ecf20Sopenharmony_ci	ret = 0;
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ciout:
12268c2ecf20Sopenharmony_ci	iwl_free_rxb(&rxb);
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	return ret ?: count;
12298c2ecf20Sopenharmony_ci}
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_cistatic int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
12328c2ecf20Sopenharmony_ci{
12338c2ecf20Sopenharmony_ci	struct ieee80211_vif *vif;
12348c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif;
12358c2ecf20Sopenharmony_ci	struct sk_buff *beacon;
12368c2ecf20Sopenharmony_ci	struct ieee80211_tx_info *info;
12378c2ecf20Sopenharmony_ci	struct iwl_mac_beacon_cmd beacon_cmd = {};
12388c2ecf20Sopenharmony_ci	u8 rate;
12398c2ecf20Sopenharmony_ci	u16 flags;
12408c2ecf20Sopenharmony_ci	int i;
12418c2ecf20Sopenharmony_ci
12428c2ecf20Sopenharmony_ci	len /= 2;
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	/* Element len should be represented by u8 */
12458c2ecf20Sopenharmony_ci	if (len >= U8_MAX)
12468c2ecf20Sopenharmony_ci		return -EINVAL;
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
12498c2ecf20Sopenharmony_ci		return -EIO;
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	if (!iwl_mvm_has_new_tx_api(mvm) &&
12528c2ecf20Sopenharmony_ci	    !fw_has_api(&mvm->fw->ucode_capa,
12538c2ecf20Sopenharmony_ci			IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE))
12548c2ecf20Sopenharmony_ci		return -EINVAL;
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	rcu_read_lock();
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	for (i = 0; i < NUM_MAC_INDEX_DRIVER; i++) {
12598c2ecf20Sopenharmony_ci		vif = iwl_mvm_rcu_dereference_vif_id(mvm, i, true);
12608c2ecf20Sopenharmony_ci		if (!vif)
12618c2ecf20Sopenharmony_ci			continue;
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci		if (vif->type == NL80211_IFTYPE_AP)
12648c2ecf20Sopenharmony_ci			break;
12658c2ecf20Sopenharmony_ci	}
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci	if (i == NUM_MAC_INDEX_DRIVER || !vif)
12688c2ecf20Sopenharmony_ci		goto out_err;
12698c2ecf20Sopenharmony_ci
12708c2ecf20Sopenharmony_ci	mvm->hw->extra_beacon_tailroom = len;
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ci	beacon = ieee80211_beacon_get_template(mvm->hw, vif, NULL);
12738c2ecf20Sopenharmony_ci	if (!beacon)
12748c2ecf20Sopenharmony_ci		goto out_err;
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_ci	if (len && hex2bin(skb_put_zero(beacon, len), bin, len)) {
12778c2ecf20Sopenharmony_ci		dev_kfree_skb(beacon);
12788c2ecf20Sopenharmony_ci		goto out_err;
12798c2ecf20Sopenharmony_ci	}
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	mvm->beacon_inject_active = true;
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	mvmvif = iwl_mvm_vif_from_mac80211(vif);
12848c2ecf20Sopenharmony_ci	info = IEEE80211_SKB_CB(beacon);
12858c2ecf20Sopenharmony_ci	rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
12868c2ecf20Sopenharmony_ci	flags = iwl_mvm_mac80211_idx_to_hwrate(rate);
12878c2ecf20Sopenharmony_ci
12888c2ecf20Sopenharmony_ci	if (rate == IWL_FIRST_CCK_RATE)
12898c2ecf20Sopenharmony_ci		flags |= IWL_MAC_BEACON_CCK;
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_ci	beacon_cmd.flags = cpu_to_le16(flags);
12928c2ecf20Sopenharmony_ci	beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
12938c2ecf20Sopenharmony_ci	beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
12948c2ecf20Sopenharmony_ci
12958c2ecf20Sopenharmony_ci	iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx,
12968c2ecf20Sopenharmony_ci				 &beacon_cmd.tim_size,
12978c2ecf20Sopenharmony_ci				 beacon->data, beacon->len);
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
13008c2ecf20Sopenharmony_ci	iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd,
13018c2ecf20Sopenharmony_ci					 sizeof(beacon_cmd));
13028c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci	dev_kfree_skb(beacon);
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_ci	rcu_read_unlock();
13078c2ecf20Sopenharmony_ci	return 0;
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_ciout_err:
13108c2ecf20Sopenharmony_ci	rcu_read_unlock();
13118c2ecf20Sopenharmony_ci	return -EINVAL;
13128c2ecf20Sopenharmony_ci}
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_inject_beacon_ie_write(struct iwl_mvm *mvm,
13158c2ecf20Sopenharmony_ci						char *buf, size_t count,
13168c2ecf20Sopenharmony_ci						loff_t *ppos)
13178c2ecf20Sopenharmony_ci{
13188c2ecf20Sopenharmony_ci	int ret = _iwl_dbgfs_inject_beacon_ie(mvm, buf, count);
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci	mvm->hw->extra_beacon_tailroom = 0;
13218c2ecf20Sopenharmony_ci	return ret ?: count;
13228c2ecf20Sopenharmony_ci}
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_inject_beacon_ie_restore_write(struct iwl_mvm *mvm,
13258c2ecf20Sopenharmony_ci							char *buf,
13268c2ecf20Sopenharmony_ci							size_t count,
13278c2ecf20Sopenharmony_ci							loff_t *ppos)
13288c2ecf20Sopenharmony_ci{
13298c2ecf20Sopenharmony_ci	int ret = _iwl_dbgfs_inject_beacon_ie(mvm, NULL, 0);
13308c2ecf20Sopenharmony_ci
13318c2ecf20Sopenharmony_ci	mvm->hw->extra_beacon_tailroom = 0;
13328c2ecf20Sopenharmony_ci	mvm->beacon_inject_active = false;
13338c2ecf20Sopenharmony_ci	return ret ?: count;
13348c2ecf20Sopenharmony_ci}
13358c2ecf20Sopenharmony_ci
13368c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
13378c2ecf20Sopenharmony_ci					  char __user *user_buf,
13388c2ecf20Sopenharmony_ci					  size_t count, loff_t *ppos)
13398c2ecf20Sopenharmony_ci{
13408c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
13418c2ecf20Sopenharmony_ci	int conf;
13428c2ecf20Sopenharmony_ci	char buf[8];
13438c2ecf20Sopenharmony_ci	const size_t bufsz = sizeof(buf);
13448c2ecf20Sopenharmony_ci	int pos = 0;
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
13478c2ecf20Sopenharmony_ci	conf = mvm->fwrt.dump.conf;
13488c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, "%d\n", conf);
13518c2ecf20Sopenharmony_ci
13528c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
13538c2ecf20Sopenharmony_ci}
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_fw_dbg_conf_write(struct iwl_mvm *mvm,
13568c2ecf20Sopenharmony_ci					   char *buf, size_t count,
13578c2ecf20Sopenharmony_ci					   loff_t *ppos)
13588c2ecf20Sopenharmony_ci{
13598c2ecf20Sopenharmony_ci	unsigned int conf_id;
13608c2ecf20Sopenharmony_ci	int ret;
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
13638c2ecf20Sopenharmony_ci		return -EIO;
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci	ret = kstrtouint(buf, 0, &conf_id);
13668c2ecf20Sopenharmony_ci	if (ret)
13678c2ecf20Sopenharmony_ci		return ret;
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci	if (WARN_ON(conf_id >= FW_DBG_CONF_MAX))
13708c2ecf20Sopenharmony_ci		return -EINVAL;
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
13738c2ecf20Sopenharmony_ci	ret = iwl_fw_start_dbg_conf(&mvm->fwrt, conf_id);
13748c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	return ret ?: count;
13778c2ecf20Sopenharmony_ci}
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
13808c2ecf20Sopenharmony_ci					      char *buf, size_t count,
13818c2ecf20Sopenharmony_ci					      loff_t *ppos)
13828c2ecf20Sopenharmony_ci{
13838c2ecf20Sopenharmony_ci	if (count == 0)
13848c2ecf20Sopenharmony_ci		return 0;
13858c2ecf20Sopenharmony_ci
13868c2ecf20Sopenharmony_ci	iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_USER_TRIGGER,
13878c2ecf20Sopenharmony_ci			       NULL);
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci	iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf,
13908c2ecf20Sopenharmony_ci			   (count - 1), NULL);
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_ci	return count;
13938c2ecf20Sopenharmony_ci}
13948c2ecf20Sopenharmony_ci
13958c2ecf20Sopenharmony_ci#define ADD_TEXT(...) pos += scnprintf(buf + pos, bufsz - pos, __VA_ARGS__)
13968c2ecf20Sopenharmony_ci#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
13978c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_bcast_filters_read(struct file *file,
13988c2ecf20Sopenharmony_ci					    char __user *user_buf,
13998c2ecf20Sopenharmony_ci					    size_t count, loff_t *ppos)
14008c2ecf20Sopenharmony_ci{
14018c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
14028c2ecf20Sopenharmony_ci	struct iwl_bcast_filter_cmd cmd;
14038c2ecf20Sopenharmony_ci	const struct iwl_fw_bcast_filter *filter;
14048c2ecf20Sopenharmony_ci	char *buf;
14058c2ecf20Sopenharmony_ci	int bufsz = 1024;
14068c2ecf20Sopenharmony_ci	int i, j, pos = 0;
14078c2ecf20Sopenharmony_ci	ssize_t ret;
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_ci	buf = kzalloc(bufsz, GFP_KERNEL);
14108c2ecf20Sopenharmony_ci	if (!buf)
14118c2ecf20Sopenharmony_ci		return -ENOMEM;
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
14148c2ecf20Sopenharmony_ci	if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) {
14158c2ecf20Sopenharmony_ci		ADD_TEXT("None\n");
14168c2ecf20Sopenharmony_ci		mutex_unlock(&mvm->mutex);
14178c2ecf20Sopenharmony_ci		goto out;
14188c2ecf20Sopenharmony_ci	}
14198c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci	for (i = 0; cmd.filters[i].attrs[0].mask; i++) {
14228c2ecf20Sopenharmony_ci		filter = &cmd.filters[i];
14238c2ecf20Sopenharmony_ci
14248c2ecf20Sopenharmony_ci		ADD_TEXT("Filter [%d]:\n", i);
14258c2ecf20Sopenharmony_ci		ADD_TEXT("\tDiscard=%d\n", filter->discard);
14268c2ecf20Sopenharmony_ci		ADD_TEXT("\tFrame Type: %s\n",
14278c2ecf20Sopenharmony_ci			 filter->frame_type ? "IPv4" : "Generic");
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ci		for (j = 0; j < ARRAY_SIZE(filter->attrs); j++) {
14308c2ecf20Sopenharmony_ci			const struct iwl_fw_bcast_filter_attr *attr;
14318c2ecf20Sopenharmony_ci
14328c2ecf20Sopenharmony_ci			attr = &filter->attrs[j];
14338c2ecf20Sopenharmony_ci			if (!attr->mask)
14348c2ecf20Sopenharmony_ci				break;
14358c2ecf20Sopenharmony_ci
14368c2ecf20Sopenharmony_ci			ADD_TEXT("\tAttr [%d]: offset=%d (from %s), mask=0x%x, value=0x%x reserved=0x%x\n",
14378c2ecf20Sopenharmony_ci				 j, attr->offset,
14388c2ecf20Sopenharmony_ci				 attr->offset_type ? "IP End" :
14398c2ecf20Sopenharmony_ci						     "Payload Start",
14408c2ecf20Sopenharmony_ci				 be32_to_cpu(attr->mask),
14418c2ecf20Sopenharmony_ci				 be32_to_cpu(attr->val),
14428c2ecf20Sopenharmony_ci				 le16_to_cpu(attr->reserved1));
14438c2ecf20Sopenharmony_ci		}
14448c2ecf20Sopenharmony_ci	}
14458c2ecf20Sopenharmony_ciout:
14468c2ecf20Sopenharmony_ci	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
14478c2ecf20Sopenharmony_ci	kfree(buf);
14488c2ecf20Sopenharmony_ci	return ret;
14498c2ecf20Sopenharmony_ci}
14508c2ecf20Sopenharmony_ci
14518c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_bcast_filters_write(struct iwl_mvm *mvm, char *buf,
14528c2ecf20Sopenharmony_ci					     size_t count, loff_t *ppos)
14538c2ecf20Sopenharmony_ci{
14548c2ecf20Sopenharmony_ci	int pos, next_pos;
14558c2ecf20Sopenharmony_ci	struct iwl_fw_bcast_filter filter = {};
14568c2ecf20Sopenharmony_ci	struct iwl_bcast_filter_cmd cmd;
14578c2ecf20Sopenharmony_ci	u32 filter_id, attr_id, mask, value;
14588c2ecf20Sopenharmony_ci	int err = 0;
14598c2ecf20Sopenharmony_ci
14608c2ecf20Sopenharmony_ci	if (sscanf(buf, "%d %hhi %hhi %n", &filter_id, &filter.discard,
14618c2ecf20Sopenharmony_ci		   &filter.frame_type, &pos) != 3)
14628c2ecf20Sopenharmony_ci		return -EINVAL;
14638c2ecf20Sopenharmony_ci
14648c2ecf20Sopenharmony_ci	if (filter_id >= ARRAY_SIZE(mvm->dbgfs_bcast_filtering.cmd.filters) ||
14658c2ecf20Sopenharmony_ci	    filter.frame_type > BCAST_FILTER_FRAME_TYPE_IPV4)
14668c2ecf20Sopenharmony_ci		return -EINVAL;
14678c2ecf20Sopenharmony_ci
14688c2ecf20Sopenharmony_ci	for (attr_id = 0; attr_id < ARRAY_SIZE(filter.attrs);
14698c2ecf20Sopenharmony_ci	     attr_id++) {
14708c2ecf20Sopenharmony_ci		struct iwl_fw_bcast_filter_attr *attr =
14718c2ecf20Sopenharmony_ci				&filter.attrs[attr_id];
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_ci		if (pos >= count)
14748c2ecf20Sopenharmony_ci			break;
14758c2ecf20Sopenharmony_ci
14768c2ecf20Sopenharmony_ci		if (sscanf(&buf[pos], "%hhi %hhi %i %i %n",
14778c2ecf20Sopenharmony_ci			   &attr->offset, &attr->offset_type,
14788c2ecf20Sopenharmony_ci			   &mask, &value, &next_pos) != 4)
14798c2ecf20Sopenharmony_ci			return -EINVAL;
14808c2ecf20Sopenharmony_ci
14818c2ecf20Sopenharmony_ci		attr->mask = cpu_to_be32(mask);
14828c2ecf20Sopenharmony_ci		attr->val = cpu_to_be32(value);
14838c2ecf20Sopenharmony_ci		if (mask)
14848c2ecf20Sopenharmony_ci			filter.num_attrs++;
14858c2ecf20Sopenharmony_ci
14868c2ecf20Sopenharmony_ci		pos += next_pos;
14878c2ecf20Sopenharmony_ci	}
14888c2ecf20Sopenharmony_ci
14898c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
14908c2ecf20Sopenharmony_ci	memcpy(&mvm->dbgfs_bcast_filtering.cmd.filters[filter_id],
14918c2ecf20Sopenharmony_ci	       &filter, sizeof(filter));
14928c2ecf20Sopenharmony_ci
14938c2ecf20Sopenharmony_ci	/* send updated bcast filtering configuration */
14948c2ecf20Sopenharmony_ci	if (iwl_mvm_firmware_running(mvm) &&
14958c2ecf20Sopenharmony_ci	    mvm->dbgfs_bcast_filtering.override &&
14968c2ecf20Sopenharmony_ci	    iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
14978c2ecf20Sopenharmony_ci		err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,
14988c2ecf20Sopenharmony_ci					   sizeof(cmd), &cmd);
14998c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
15008c2ecf20Sopenharmony_ci
15018c2ecf20Sopenharmony_ci	return err ?: count;
15028c2ecf20Sopenharmony_ci}
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_bcast_filters_macs_read(struct file *file,
15058c2ecf20Sopenharmony_ci						 char __user *user_buf,
15068c2ecf20Sopenharmony_ci						 size_t count, loff_t *ppos)
15078c2ecf20Sopenharmony_ci{
15088c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
15098c2ecf20Sopenharmony_ci	struct iwl_bcast_filter_cmd cmd;
15108c2ecf20Sopenharmony_ci	char *buf;
15118c2ecf20Sopenharmony_ci	int bufsz = 1024;
15128c2ecf20Sopenharmony_ci	int i, pos = 0;
15138c2ecf20Sopenharmony_ci	ssize_t ret;
15148c2ecf20Sopenharmony_ci
15158c2ecf20Sopenharmony_ci	buf = kzalloc(bufsz, GFP_KERNEL);
15168c2ecf20Sopenharmony_ci	if (!buf)
15178c2ecf20Sopenharmony_ci		return -ENOMEM;
15188c2ecf20Sopenharmony_ci
15198c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
15208c2ecf20Sopenharmony_ci	if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd)) {
15218c2ecf20Sopenharmony_ci		ADD_TEXT("None\n");
15228c2ecf20Sopenharmony_ci		mutex_unlock(&mvm->mutex);
15238c2ecf20Sopenharmony_ci		goto out;
15248c2ecf20Sopenharmony_ci	}
15258c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(cmd.macs); i++) {
15288c2ecf20Sopenharmony_ci		const struct iwl_fw_bcast_mac *mac = &cmd.macs[i];
15298c2ecf20Sopenharmony_ci
15308c2ecf20Sopenharmony_ci		ADD_TEXT("Mac [%d]: discard=%d attached_filters=0x%x\n",
15318c2ecf20Sopenharmony_ci			 i, mac->default_discard, mac->attached_filters);
15328c2ecf20Sopenharmony_ci	}
15338c2ecf20Sopenharmony_ciout:
15348c2ecf20Sopenharmony_ci	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
15358c2ecf20Sopenharmony_ci	kfree(buf);
15368c2ecf20Sopenharmony_ci	return ret;
15378c2ecf20Sopenharmony_ci}
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
15408c2ecf20Sopenharmony_ci						  char *buf, size_t count,
15418c2ecf20Sopenharmony_ci						  loff_t *ppos)
15428c2ecf20Sopenharmony_ci{
15438c2ecf20Sopenharmony_ci	struct iwl_bcast_filter_cmd cmd;
15448c2ecf20Sopenharmony_ci	struct iwl_fw_bcast_mac mac = {};
15458c2ecf20Sopenharmony_ci	u32 mac_id, attached_filters;
15468c2ecf20Sopenharmony_ci	int err = 0;
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci	if (!mvm->bcast_filters)
15498c2ecf20Sopenharmony_ci		return -ENOENT;
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci	if (sscanf(buf, "%d %hhi %i", &mac_id, &mac.default_discard,
15528c2ecf20Sopenharmony_ci		   &attached_filters) != 3)
15538c2ecf20Sopenharmony_ci		return -EINVAL;
15548c2ecf20Sopenharmony_ci
15558c2ecf20Sopenharmony_ci	if (mac_id >= ARRAY_SIZE(cmd.macs) ||
15568c2ecf20Sopenharmony_ci	    mac.default_discard > 1 ||
15578c2ecf20Sopenharmony_ci	    attached_filters >= BIT(ARRAY_SIZE(cmd.filters)))
15588c2ecf20Sopenharmony_ci		return -EINVAL;
15598c2ecf20Sopenharmony_ci
15608c2ecf20Sopenharmony_ci	mac.attached_filters = cpu_to_le16(attached_filters);
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
15638c2ecf20Sopenharmony_ci	memcpy(&mvm->dbgfs_bcast_filtering.cmd.macs[mac_id],
15648c2ecf20Sopenharmony_ci	       &mac, sizeof(mac));
15658c2ecf20Sopenharmony_ci
15668c2ecf20Sopenharmony_ci	/* send updated bcast filtering configuration */
15678c2ecf20Sopenharmony_ci	if (iwl_mvm_firmware_running(mvm) &&
15688c2ecf20Sopenharmony_ci	    mvm->dbgfs_bcast_filtering.override &&
15698c2ecf20Sopenharmony_ci	    iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
15708c2ecf20Sopenharmony_ci		err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,
15718c2ecf20Sopenharmony_ci					   sizeof(cmd), &cmd);
15728c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
15738c2ecf20Sopenharmony_ci
15748c2ecf20Sopenharmony_ci	return err ?: count;
15758c2ecf20Sopenharmony_ci}
15768c2ecf20Sopenharmony_ci#endif
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
15798c2ecf20Sopenharmony_ci	_MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
15808c2ecf20Sopenharmony_ci#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
15818c2ecf20Sopenharmony_ci	_MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
15828c2ecf20Sopenharmony_ci#define MVM_DEBUGFS_ADD_FILE_ALIAS(alias, name, parent, mode) do {	\
15838c2ecf20Sopenharmony_ci		debugfs_create_file(alias, mode, parent, mvm,		\
15848c2ecf20Sopenharmony_ci				    &iwl_dbgfs_##name##_ops);		\
15858c2ecf20Sopenharmony_ci	} while (0)
15868c2ecf20Sopenharmony_ci#define MVM_DEBUGFS_ADD_FILE(name, parent, mode) \
15878c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE_ALIAS(#name, name, parent, mode)
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci#define MVM_DEBUGFS_WRITE_STA_FILE_OPS(name, bufsz) \
15908c2ecf20Sopenharmony_ci	_MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta)
15918c2ecf20Sopenharmony_ci#define MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(name, bufsz) \
15928c2ecf20Sopenharmony_ci	_MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_sta)
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_ci#define MVM_DEBUGFS_ADD_STA_FILE_ALIAS(alias, name, parent, mode) do {	\
15958c2ecf20Sopenharmony_ci		debugfs_create_file(alias, mode, parent, sta,		\
15968c2ecf20Sopenharmony_ci				    &iwl_dbgfs_##name##_ops);		\
15978c2ecf20Sopenharmony_ci	} while (0)
15988c2ecf20Sopenharmony_ci#define MVM_DEBUGFS_ADD_STA_FILE(name, parent, mode) \
15998c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_STA_FILE_ALIAS(#name, name, parent, mode)
16008c2ecf20Sopenharmony_ci
16018c2ecf20Sopenharmony_cistatic ssize_t
16028c2ecf20Sopenharmony_ciiwl_dbgfs_prph_reg_read(struct file *file,
16038c2ecf20Sopenharmony_ci			char __user *user_buf,
16048c2ecf20Sopenharmony_ci			size_t count, loff_t *ppos)
16058c2ecf20Sopenharmony_ci{
16068c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
16078c2ecf20Sopenharmony_ci	int pos = 0;
16088c2ecf20Sopenharmony_ci	char buf[32];
16098c2ecf20Sopenharmony_ci	const size_t bufsz = sizeof(buf);
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_ci	if (!mvm->dbgfs_prph_reg_addr)
16128c2ecf20Sopenharmony_ci		return -EINVAL;
16138c2ecf20Sopenharmony_ci
16148c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
16158c2ecf20Sopenharmony_ci		mvm->dbgfs_prph_reg_addr,
16168c2ecf20Sopenharmony_ci		iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
16198c2ecf20Sopenharmony_ci}
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_cistatic ssize_t
16228c2ecf20Sopenharmony_ciiwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
16238c2ecf20Sopenharmony_ci			 size_t count, loff_t *ppos)
16248c2ecf20Sopenharmony_ci{
16258c2ecf20Sopenharmony_ci	u8 args;
16268c2ecf20Sopenharmony_ci	u32 value;
16278c2ecf20Sopenharmony_ci
16288c2ecf20Sopenharmony_ci	args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
16298c2ecf20Sopenharmony_ci	/* if we only want to set the reg address - nothing more to do */
16308c2ecf20Sopenharmony_ci	if (args == 1)
16318c2ecf20Sopenharmony_ci		goto out;
16328c2ecf20Sopenharmony_ci
16338c2ecf20Sopenharmony_ci	/* otherwise, make sure we have both address and value */
16348c2ecf20Sopenharmony_ci	if (args != 2)
16358c2ecf20Sopenharmony_ci		return -EINVAL;
16368c2ecf20Sopenharmony_ci
16378c2ecf20Sopenharmony_ci	iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ciout:
16408c2ecf20Sopenharmony_ci	return count;
16418c2ecf20Sopenharmony_ci}
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_cistatic ssize_t
16448c2ecf20Sopenharmony_ciiwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf,
16458c2ecf20Sopenharmony_ci			      size_t count, loff_t *ppos)
16468c2ecf20Sopenharmony_ci{
16478c2ecf20Sopenharmony_ci	int ret;
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
16508c2ecf20Sopenharmony_ci		return -EIO;
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
16538c2ecf20Sopenharmony_ci	ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL);
16548c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
16558c2ecf20Sopenharmony_ci
16568c2ecf20Sopenharmony_ci	return ret ?: count;
16578c2ecf20Sopenharmony_ci}
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_cistruct iwl_mvm_sniffer_apply {
16608c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm;
16618c2ecf20Sopenharmony_ci	u8 *bssid;
16628c2ecf20Sopenharmony_ci	u16 aid;
16638c2ecf20Sopenharmony_ci};
16648c2ecf20Sopenharmony_ci
16658c2ecf20Sopenharmony_cistatic bool iwl_mvm_sniffer_apply(struct iwl_notif_wait_data *notif_data,
16668c2ecf20Sopenharmony_ci				  struct iwl_rx_packet *pkt, void *data)
16678c2ecf20Sopenharmony_ci{
16688c2ecf20Sopenharmony_ci	struct iwl_mvm_sniffer_apply *apply = data;
16698c2ecf20Sopenharmony_ci
16708c2ecf20Sopenharmony_ci	apply->mvm->cur_aid = cpu_to_le16(apply->aid);
16718c2ecf20Sopenharmony_ci	memcpy(apply->mvm->cur_bssid, apply->bssid,
16728c2ecf20Sopenharmony_ci	       sizeof(apply->mvm->cur_bssid));
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci	return true;
16758c2ecf20Sopenharmony_ci}
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_cistatic ssize_t
16788c2ecf20Sopenharmony_ciiwl_dbgfs_he_sniffer_params_write(struct iwl_mvm *mvm, char *buf,
16798c2ecf20Sopenharmony_ci				  size_t count, loff_t *ppos)
16808c2ecf20Sopenharmony_ci{
16818c2ecf20Sopenharmony_ci	struct iwl_notification_wait wait;
16828c2ecf20Sopenharmony_ci	struct iwl_he_monitor_cmd he_mon_cmd = {};
16838c2ecf20Sopenharmony_ci	struct iwl_mvm_sniffer_apply apply = {
16848c2ecf20Sopenharmony_ci		.mvm = mvm,
16858c2ecf20Sopenharmony_ci	};
16868c2ecf20Sopenharmony_ci	u16 wait_cmds[] = {
16878c2ecf20Sopenharmony_ci		iwl_cmd_id(HE_AIR_SNIFFER_CONFIG_CMD, DATA_PATH_GROUP, 0),
16888c2ecf20Sopenharmony_ci	};
16898c2ecf20Sopenharmony_ci	u32 aid;
16908c2ecf20Sopenharmony_ci	int ret;
16918c2ecf20Sopenharmony_ci
16928c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
16938c2ecf20Sopenharmony_ci		return -EIO;
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_ci	ret = sscanf(buf, "%x %2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx", &aid,
16968c2ecf20Sopenharmony_ci		     &he_mon_cmd.bssid[0], &he_mon_cmd.bssid[1],
16978c2ecf20Sopenharmony_ci		     &he_mon_cmd.bssid[2], &he_mon_cmd.bssid[3],
16988c2ecf20Sopenharmony_ci		     &he_mon_cmd.bssid[4], &he_mon_cmd.bssid[5]);
16998c2ecf20Sopenharmony_ci	if (ret != 7)
17008c2ecf20Sopenharmony_ci		return -EINVAL;
17018c2ecf20Sopenharmony_ci
17028c2ecf20Sopenharmony_ci	he_mon_cmd.aid = cpu_to_le16(aid);
17038c2ecf20Sopenharmony_ci
17048c2ecf20Sopenharmony_ci	apply.aid = aid;
17058c2ecf20Sopenharmony_ci	apply.bssid = (void *)he_mon_cmd.bssid;
17068c2ecf20Sopenharmony_ci
17078c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
17088c2ecf20Sopenharmony_ci
17098c2ecf20Sopenharmony_ci	/*
17108c2ecf20Sopenharmony_ci	 * Use the notification waiter to get our function triggered
17118c2ecf20Sopenharmony_ci	 * in sequence with other RX. This ensures that frames we get
17128c2ecf20Sopenharmony_ci	 * on the RX queue _before_ the new configuration is applied
17138c2ecf20Sopenharmony_ci	 * still have mvm->cur_aid pointing to the old AID, and that
17148c2ecf20Sopenharmony_ci	 * frames on the RX queue _after_ the firmware processed the
17158c2ecf20Sopenharmony_ci	 * new configuration (and sent the response, synchronously)
17168c2ecf20Sopenharmony_ci	 * get mvm->cur_aid correctly set to the new AID.
17178c2ecf20Sopenharmony_ci	 */
17188c2ecf20Sopenharmony_ci	iwl_init_notification_wait(&mvm->notif_wait, &wait,
17198c2ecf20Sopenharmony_ci				   wait_cmds, ARRAY_SIZE(wait_cmds),
17208c2ecf20Sopenharmony_ci				   iwl_mvm_sniffer_apply, &apply);
17218c2ecf20Sopenharmony_ci
17228c2ecf20Sopenharmony_ci	ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(HE_AIR_SNIFFER_CONFIG_CMD,
17238c2ecf20Sopenharmony_ci						   DATA_PATH_GROUP, 0), 0,
17248c2ecf20Sopenharmony_ci				   sizeof(he_mon_cmd), &he_mon_cmd);
17258c2ecf20Sopenharmony_ci
17268c2ecf20Sopenharmony_ci	/* no need to really wait, we already did anyway */
17278c2ecf20Sopenharmony_ci	iwl_remove_notification(&mvm->notif_wait, &wait);
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
17308c2ecf20Sopenharmony_ci
17318c2ecf20Sopenharmony_ci	return ret ?: count;
17328c2ecf20Sopenharmony_ci}
17338c2ecf20Sopenharmony_ci
17348c2ecf20Sopenharmony_cistatic ssize_t
17358c2ecf20Sopenharmony_ciiwl_dbgfs_he_sniffer_params_read(struct file *file, char __user *user_buf,
17368c2ecf20Sopenharmony_ci				 size_t count, loff_t *ppos)
17378c2ecf20Sopenharmony_ci{
17388c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
17398c2ecf20Sopenharmony_ci	u8 buf[32];
17408c2ecf20Sopenharmony_ci	int len;
17418c2ecf20Sopenharmony_ci
17428c2ecf20Sopenharmony_ci	len = scnprintf(buf, sizeof(buf),
17438c2ecf20Sopenharmony_ci			"%d %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
17448c2ecf20Sopenharmony_ci			le16_to_cpu(mvm->cur_aid), mvm->cur_bssid[0],
17458c2ecf20Sopenharmony_ci			mvm->cur_bssid[1], mvm->cur_bssid[2], mvm->cur_bssid[3],
17468c2ecf20Sopenharmony_ci			mvm->cur_bssid[4], mvm->cur_bssid[5]);
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
17498c2ecf20Sopenharmony_ci}
17508c2ecf20Sopenharmony_ci
17518c2ecf20Sopenharmony_cistatic ssize_t
17528c2ecf20Sopenharmony_ciiwl_dbgfs_uapsd_noagg_bssids_read(struct file *file, char __user *user_buf,
17538c2ecf20Sopenharmony_ci				  size_t count, loff_t *ppos)
17548c2ecf20Sopenharmony_ci{
17558c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
17568c2ecf20Sopenharmony_ci	u8 buf[IWL_MVM_UAPSD_NOAGG_BSSIDS_NUM * ETH_ALEN * 3 + 1];
17578c2ecf20Sopenharmony_ci	unsigned int pos = 0;
17588c2ecf20Sopenharmony_ci	size_t bufsz = sizeof(buf);
17598c2ecf20Sopenharmony_ci	int i;
17608c2ecf20Sopenharmony_ci
17618c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_ci	for (i = 0; i < IWL_MVM_UAPSD_NOAGG_LIST_LEN; i++)
17648c2ecf20Sopenharmony_ci		pos += scnprintf(buf + pos, bufsz - pos, "%pM\n",
17658c2ecf20Sopenharmony_ci				 mvm->uapsd_noagg_bssids[i].addr);
17668c2ecf20Sopenharmony_ci
17678c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
17688c2ecf20Sopenharmony_ci
17698c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
17708c2ecf20Sopenharmony_ci}
17718c2ecf20Sopenharmony_ci
17728c2ecf20Sopenharmony_cistatic ssize_t
17738c2ecf20Sopenharmony_ciiwl_dbgfs_ltr_config_write(struct iwl_mvm *mvm,
17748c2ecf20Sopenharmony_ci			   char *buf, size_t count, loff_t *ppos)
17758c2ecf20Sopenharmony_ci{
17768c2ecf20Sopenharmony_ci	int ret;
17778c2ecf20Sopenharmony_ci	struct iwl_ltr_config_cmd ltr_config = {0};
17788c2ecf20Sopenharmony_ci
17798c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
17808c2ecf20Sopenharmony_ci		return -EIO;
17818c2ecf20Sopenharmony_ci
17828c2ecf20Sopenharmony_ci	if (sscanf(buf, "%x,%x,%x,%x,%x,%x,%x",
17838c2ecf20Sopenharmony_ci		   &ltr_config.flags,
17848c2ecf20Sopenharmony_ci		   &ltr_config.static_long,
17858c2ecf20Sopenharmony_ci		   &ltr_config.static_short,
17868c2ecf20Sopenharmony_ci		   &ltr_config.ltr_cfg_values[0],
17878c2ecf20Sopenharmony_ci		   &ltr_config.ltr_cfg_values[1],
17888c2ecf20Sopenharmony_ci		   &ltr_config.ltr_cfg_values[2],
17898c2ecf20Sopenharmony_ci		   &ltr_config.ltr_cfg_values[3]) != 7) {
17908c2ecf20Sopenharmony_ci		return -EINVAL;
17918c2ecf20Sopenharmony_ci	}
17928c2ecf20Sopenharmony_ci
17938c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
17948c2ecf20Sopenharmony_ci	ret = iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, sizeof(ltr_config),
17958c2ecf20Sopenharmony_ci				   &ltr_config);
17968c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
17978c2ecf20Sopenharmony_ci
17988c2ecf20Sopenharmony_ci	if (ret)
17998c2ecf20Sopenharmony_ci		IWL_ERR(mvm, "failed to send ltr configuration cmd\n");
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci	return ret ?: count;
18028c2ecf20Sopenharmony_ci}
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
18058c2ecf20Sopenharmony_ci
18068c2ecf20Sopenharmony_ci/* Device wide debugfs entries */
18078c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(ctdp_budget);
18088c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(stop_ctdp, 8);
18098c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(force_ctkill, 8);
18108c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16);
18118c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8);
18128c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8);
18138c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64);
18148c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64);
18158c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(nic_temp);
18168c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(stations);
18178c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(rs_data);
18188c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(bt_notif);
18198c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(bt_cmd);
18208c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(disable_power_off, 64);
18218c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);
18228c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);
18238c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(fw_ver);
18248c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);
18258c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
18268c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
18278c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
18288c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
18298c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
18308c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
18318c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
18328c2ecf20Sopenharmony_ci			   (IWL_RSS_INDIRECTION_TABLE_SIZE * 2));
18338c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(inject_packet, 512);
18348c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie, 512);
18358c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(inject_beacon_ie_restore, 512);
18368c2ecf20Sopenharmony_ci
18378c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids);
18388c2ecf20Sopenharmony_ci
18398c2ecf20Sopenharmony_ci#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
18408c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
18418c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
18428c2ecf20Sopenharmony_ci#endif
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI
18458c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile);
18468c2ecf20Sopenharmony_ci#endif
18478c2ecf20Sopenharmony_ci
18488c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(amsdu_len, 16);
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32);
18518c2ecf20Sopenharmony_ci
18528c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(ltr_config, 512);
18538c2ecf20Sopenharmony_ci
18548c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
18558c2ecf20Sopenharmony_ci				  size_t count, loff_t *ppos)
18568c2ecf20Sopenharmony_ci{
18578c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
18588c2ecf20Sopenharmony_ci	struct iwl_dbg_mem_access_cmd cmd = {};
18598c2ecf20Sopenharmony_ci	struct iwl_dbg_mem_access_rsp *rsp;
18608c2ecf20Sopenharmony_ci	struct iwl_host_cmd hcmd = {
18618c2ecf20Sopenharmony_ci		.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
18628c2ecf20Sopenharmony_ci		.data = { &cmd, },
18638c2ecf20Sopenharmony_ci		.len = { sizeof(cmd) },
18648c2ecf20Sopenharmony_ci	};
18658c2ecf20Sopenharmony_ci	size_t delta;
18668c2ecf20Sopenharmony_ci	ssize_t ret, len;
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
18698c2ecf20Sopenharmony_ci		return -EIO;
18708c2ecf20Sopenharmony_ci
18718c2ecf20Sopenharmony_ci	hcmd.id = iwl_cmd_id(*ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR,
18728c2ecf20Sopenharmony_ci			     DEBUG_GROUP, 0);
18738c2ecf20Sopenharmony_ci	cmd.op = cpu_to_le32(DEBUG_MEM_OP_READ);
18748c2ecf20Sopenharmony_ci
18758c2ecf20Sopenharmony_ci	/* Take care of alignment of both the position and the length */
18768c2ecf20Sopenharmony_ci	delta = *ppos & 0x3;
18778c2ecf20Sopenharmony_ci	cmd.addr = cpu_to_le32(*ppos - delta);
18788c2ecf20Sopenharmony_ci	cmd.len = cpu_to_le32(min(ALIGN(count + delta, 4) / 4,
18798c2ecf20Sopenharmony_ci				  (size_t)DEBUG_MEM_MAX_SIZE_DWORDS));
18808c2ecf20Sopenharmony_ci
18818c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
18828c2ecf20Sopenharmony_ci	ret = iwl_mvm_send_cmd(mvm, &hcmd);
18838c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
18848c2ecf20Sopenharmony_ci
18858c2ecf20Sopenharmony_ci	if (ret < 0)
18868c2ecf20Sopenharmony_ci		return ret;
18878c2ecf20Sopenharmony_ci
18888c2ecf20Sopenharmony_ci	if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) {
18898c2ecf20Sopenharmony_ci		ret = -EIO;
18908c2ecf20Sopenharmony_ci		goto out;
18918c2ecf20Sopenharmony_ci	}
18928c2ecf20Sopenharmony_ci
18938c2ecf20Sopenharmony_ci	rsp = (void *)hcmd.resp_pkt->data;
18948c2ecf20Sopenharmony_ci	if (le32_to_cpu(rsp->status) != DEBUG_MEM_STATUS_SUCCESS) {
18958c2ecf20Sopenharmony_ci		ret = -ENXIO;
18968c2ecf20Sopenharmony_ci		goto out;
18978c2ecf20Sopenharmony_ci	}
18988c2ecf20Sopenharmony_ci
18998c2ecf20Sopenharmony_ci	len = min((size_t)le32_to_cpu(rsp->len) << 2,
19008c2ecf20Sopenharmony_ci		  iwl_rx_packet_payload_len(hcmd.resp_pkt) - sizeof(*rsp));
19018c2ecf20Sopenharmony_ci	len = min(len - delta, count);
19028c2ecf20Sopenharmony_ci	if (len < 0) {
19038c2ecf20Sopenharmony_ci		ret = -EFAULT;
19048c2ecf20Sopenharmony_ci		goto out;
19058c2ecf20Sopenharmony_ci	}
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci	ret = len - copy_to_user(user_buf, (void *)rsp->data + delta, len);
19088c2ecf20Sopenharmony_ci	*ppos += ret;
19098c2ecf20Sopenharmony_ci
19108c2ecf20Sopenharmony_ciout:
19118c2ecf20Sopenharmony_ci	iwl_free_resp(&hcmd);
19128c2ecf20Sopenharmony_ci	return ret;
19138c2ecf20Sopenharmony_ci}
19148c2ecf20Sopenharmony_ci
19158c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_mem_write(struct file *file,
19168c2ecf20Sopenharmony_ci				   const char __user *user_buf, size_t count,
19178c2ecf20Sopenharmony_ci				   loff_t *ppos)
19188c2ecf20Sopenharmony_ci{
19198c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = file->private_data;
19208c2ecf20Sopenharmony_ci	struct iwl_dbg_mem_access_cmd *cmd;
19218c2ecf20Sopenharmony_ci	struct iwl_dbg_mem_access_rsp *rsp;
19228c2ecf20Sopenharmony_ci	struct iwl_host_cmd hcmd = {};
19238c2ecf20Sopenharmony_ci	size_t cmd_size;
19248c2ecf20Sopenharmony_ci	size_t data_size;
19258c2ecf20Sopenharmony_ci	u32 op, len;
19268c2ecf20Sopenharmony_ci	ssize_t ret;
19278c2ecf20Sopenharmony_ci
19288c2ecf20Sopenharmony_ci	if (!iwl_mvm_firmware_running(mvm))
19298c2ecf20Sopenharmony_ci		return -EIO;
19308c2ecf20Sopenharmony_ci
19318c2ecf20Sopenharmony_ci	hcmd.id = iwl_cmd_id(*ppos >> 24 ? UMAC_RD_WR : LMAC_RD_WR,
19328c2ecf20Sopenharmony_ci			     DEBUG_GROUP, 0);
19338c2ecf20Sopenharmony_ci
19348c2ecf20Sopenharmony_ci	if (*ppos & 0x3 || count < 4) {
19358c2ecf20Sopenharmony_ci		op = DEBUG_MEM_OP_WRITE_BYTES;
19368c2ecf20Sopenharmony_ci		len = min(count, (size_t)(4 - (*ppos & 0x3)));
19378c2ecf20Sopenharmony_ci		data_size = len;
19388c2ecf20Sopenharmony_ci	} else {
19398c2ecf20Sopenharmony_ci		op = DEBUG_MEM_OP_WRITE;
19408c2ecf20Sopenharmony_ci		len = min(count >> 2, (size_t)DEBUG_MEM_MAX_SIZE_DWORDS);
19418c2ecf20Sopenharmony_ci		data_size = len << 2;
19428c2ecf20Sopenharmony_ci	}
19438c2ecf20Sopenharmony_ci
19448c2ecf20Sopenharmony_ci	cmd_size = sizeof(*cmd) + ALIGN(data_size, 4);
19458c2ecf20Sopenharmony_ci	cmd = kzalloc(cmd_size, GFP_KERNEL);
19468c2ecf20Sopenharmony_ci	if (!cmd)
19478c2ecf20Sopenharmony_ci		return -ENOMEM;
19488c2ecf20Sopenharmony_ci
19498c2ecf20Sopenharmony_ci	cmd->op = cpu_to_le32(op);
19508c2ecf20Sopenharmony_ci	cmd->len = cpu_to_le32(len);
19518c2ecf20Sopenharmony_ci	cmd->addr = cpu_to_le32(*ppos);
19528c2ecf20Sopenharmony_ci	if (copy_from_user((void *)cmd->data, user_buf, data_size)) {
19538c2ecf20Sopenharmony_ci		kfree(cmd);
19548c2ecf20Sopenharmony_ci		return -EFAULT;
19558c2ecf20Sopenharmony_ci	}
19568c2ecf20Sopenharmony_ci
19578c2ecf20Sopenharmony_ci	hcmd.flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
19588c2ecf20Sopenharmony_ci	hcmd.data[0] = (void *)cmd;
19598c2ecf20Sopenharmony_ci	hcmd.len[0] = cmd_size;
19608c2ecf20Sopenharmony_ci
19618c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
19628c2ecf20Sopenharmony_ci	ret = iwl_mvm_send_cmd(mvm, &hcmd);
19638c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_ci	kfree(cmd);
19668c2ecf20Sopenharmony_ci
19678c2ecf20Sopenharmony_ci	if (ret < 0)
19688c2ecf20Sopenharmony_ci		return ret;
19698c2ecf20Sopenharmony_ci
19708c2ecf20Sopenharmony_ci	if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) {
19718c2ecf20Sopenharmony_ci		ret = -EIO;
19728c2ecf20Sopenharmony_ci		goto out;
19738c2ecf20Sopenharmony_ci	}
19748c2ecf20Sopenharmony_ci
19758c2ecf20Sopenharmony_ci	rsp = (void *)hcmd.resp_pkt->data;
19768c2ecf20Sopenharmony_ci	if (rsp->status != DEBUG_MEM_STATUS_SUCCESS) {
19778c2ecf20Sopenharmony_ci		ret = -ENXIO;
19788c2ecf20Sopenharmony_ci		goto out;
19798c2ecf20Sopenharmony_ci	}
19808c2ecf20Sopenharmony_ci
19818c2ecf20Sopenharmony_ci	ret = data_size;
19828c2ecf20Sopenharmony_ci	*ppos += ret;
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ciout:
19858c2ecf20Sopenharmony_ci	iwl_free_resp(&hcmd);
19868c2ecf20Sopenharmony_ci	return ret;
19878c2ecf20Sopenharmony_ci}
19888c2ecf20Sopenharmony_ci
19898c2ecf20Sopenharmony_cistatic const struct file_operations iwl_dbgfs_mem_ops = {
19908c2ecf20Sopenharmony_ci	.read = iwl_dbgfs_mem_read,
19918c2ecf20Sopenharmony_ci	.write = iwl_dbgfs_mem_write,
19928c2ecf20Sopenharmony_ci	.open = simple_open,
19938c2ecf20Sopenharmony_ci	.llseek = default_llseek,
19948c2ecf20Sopenharmony_ci};
19958c2ecf20Sopenharmony_ci
19968c2ecf20Sopenharmony_civoid iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
19978c2ecf20Sopenharmony_ci			     struct ieee80211_vif *vif,
19988c2ecf20Sopenharmony_ci			     struct ieee80211_sta *sta,
19998c2ecf20Sopenharmony_ci			     struct dentry *dir)
20008c2ecf20Sopenharmony_ci{
20018c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
20028c2ecf20Sopenharmony_ci
20038c2ecf20Sopenharmony_ci	if (iwl_mvm_has_tlc_offload(mvm)) {
20048c2ecf20Sopenharmony_ci		MVM_DEBUGFS_ADD_STA_FILE(rs_data, dir, 0400);
20058c2ecf20Sopenharmony_ci	}
20068c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_STA_FILE(amsdu_len, dir, 0600);
20078c2ecf20Sopenharmony_ci}
20088c2ecf20Sopenharmony_ci
20098c2ecf20Sopenharmony_civoid iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
20108c2ecf20Sopenharmony_ci{
20118c2ecf20Sopenharmony_ci	struct dentry *bcast_dir __maybe_unused;
20128c2ecf20Sopenharmony_ci	char buf[100];
20138c2ecf20Sopenharmony_ci
20148c2ecf20Sopenharmony_ci	spin_lock_init(&mvm->drv_stats_lock);
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_ci	mvm->debugfs_dir = dbgfs_dir;
20178c2ecf20Sopenharmony_ci
20188c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(tx_flush, mvm->debugfs_dir, 0200);
20198c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(sta_drain, mvm->debugfs_dir, 0200);
20208c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(sram, mvm->debugfs_dir, 0600);
20218c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(set_nic_temperature, mvm->debugfs_dir, 0600);
20228c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, 0400);
20238c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(ctdp_budget, dbgfs_dir, 0400);
20248c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(stop_ctdp, dbgfs_dir, 0200);
20258c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(force_ctkill, dbgfs_dir, 0200);
20268c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, 0400);
20278c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, 0400);
20288c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, 0400);
20298c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, 0600);
20308c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(fw_ver, mvm->debugfs_dir, 0400);
20318c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(fw_rx_stats, mvm->debugfs_dir, 0400);
20328c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(drv_rx_stats, mvm->debugfs_dir, 0400);
20338c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(fw_restart, mvm->debugfs_dir, 0200);
20348c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(fw_nmi, mvm->debugfs_dir, 0200);
20358c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(bt_tx_prio, mvm->debugfs_dir, 0200);
20368c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, 0200);
20378c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, 0600);
20388c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, 0600);
20398c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, 0600);
20408c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200);
20418c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
20428c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, 0200);
20438c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(inject_packet, mvm->debugfs_dir, 0200);
20448c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(inject_beacon_ie, mvm->debugfs_dir, 0200);
20458c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(inject_beacon_ie_restore, mvm->debugfs_dir, 0200);
20468c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI
20478c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(sar_geo_profile, dbgfs_dir, 0400);
20488c2ecf20Sopenharmony_ci#endif
20498c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600);
20508c2ecf20Sopenharmony_ci
20518c2ecf20Sopenharmony_ci	if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_LTR_GEN2))
20528c2ecf20Sopenharmony_ci		MVM_DEBUGFS_ADD_FILE(ltr_config, mvm->debugfs_dir, 0200);
20538c2ecf20Sopenharmony_ci
20548c2ecf20Sopenharmony_ci	debugfs_create_bool("enable_scan_iteration_notif", 0600,
20558c2ecf20Sopenharmony_ci			    mvm->debugfs_dir, &mvm->scan_iter_notif_enabled);
20568c2ecf20Sopenharmony_ci	debugfs_create_bool("drop_bcn_ap_mode", 0600, mvm->debugfs_dir,
20578c2ecf20Sopenharmony_ci			    &mvm->drop_bcn_ap_mode);
20588c2ecf20Sopenharmony_ci
20598c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(uapsd_noagg_bssids, mvm->debugfs_dir, S_IRUSR);
20608c2ecf20Sopenharmony_ci
20618c2ecf20Sopenharmony_ci#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
20628c2ecf20Sopenharmony_ci	if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING) {
20638c2ecf20Sopenharmony_ci		bcast_dir = debugfs_create_dir("bcast_filtering",
20648c2ecf20Sopenharmony_ci					       mvm->debugfs_dir);
20658c2ecf20Sopenharmony_ci
20668c2ecf20Sopenharmony_ci		debugfs_create_bool("override", 0600, bcast_dir,
20678c2ecf20Sopenharmony_ci				    &mvm->dbgfs_bcast_filtering.override);
20688c2ecf20Sopenharmony_ci
20698c2ecf20Sopenharmony_ci		MVM_DEBUGFS_ADD_FILE_ALIAS("filters", bcast_filters,
20708c2ecf20Sopenharmony_ci					   bcast_dir, 0600);
20718c2ecf20Sopenharmony_ci		MVM_DEBUGFS_ADD_FILE_ALIAS("macs", bcast_filters_macs,
20728c2ecf20Sopenharmony_ci					   bcast_dir, 0600);
20738c2ecf20Sopenharmony_ci	}
20748c2ecf20Sopenharmony_ci#endif
20758c2ecf20Sopenharmony_ci
20768c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
20778c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE(d3_test, mvm->debugfs_dir, 0400);
20788c2ecf20Sopenharmony_ci	debugfs_create_bool("d3_wake_sysassert", 0600, mvm->debugfs_dir,
20798c2ecf20Sopenharmony_ci			    &mvm->d3_wake_sysassert);
20808c2ecf20Sopenharmony_ci	debugfs_create_u32("last_netdetect_scans", 0400, mvm->debugfs_dir,
20818c2ecf20Sopenharmony_ci			   &mvm->last_netdetect_scans);
20828c2ecf20Sopenharmony_ci#endif
20838c2ecf20Sopenharmony_ci
20848c2ecf20Sopenharmony_ci	debugfs_create_u8("ps_disabled", 0400, mvm->debugfs_dir,
20858c2ecf20Sopenharmony_ci			  &mvm->ps_disabled);
20868c2ecf20Sopenharmony_ci	debugfs_create_blob("nvm_hw", 0400, mvm->debugfs_dir,
20878c2ecf20Sopenharmony_ci			    &mvm->nvm_hw_blob);
20888c2ecf20Sopenharmony_ci	debugfs_create_blob("nvm_sw", 0400, mvm->debugfs_dir,
20898c2ecf20Sopenharmony_ci			    &mvm->nvm_sw_blob);
20908c2ecf20Sopenharmony_ci	debugfs_create_blob("nvm_calib", 0400, mvm->debugfs_dir,
20918c2ecf20Sopenharmony_ci			    &mvm->nvm_calib_blob);
20928c2ecf20Sopenharmony_ci	debugfs_create_blob("nvm_prod", 0400, mvm->debugfs_dir,
20938c2ecf20Sopenharmony_ci			    &mvm->nvm_prod_blob);
20948c2ecf20Sopenharmony_ci	debugfs_create_blob("nvm_phy_sku", 0400, mvm->debugfs_dir,
20958c2ecf20Sopenharmony_ci			    &mvm->nvm_phy_sku_blob);
20968c2ecf20Sopenharmony_ci	debugfs_create_blob("nvm_reg", S_IRUSR,
20978c2ecf20Sopenharmony_ci			    mvm->debugfs_dir, &mvm->nvm_reg_blob);
20988c2ecf20Sopenharmony_ci
20998c2ecf20Sopenharmony_ci	debugfs_create_file("mem", 0600, dbgfs_dir, mvm, &iwl_dbgfs_mem_ops);
21008c2ecf20Sopenharmony_ci
21018c2ecf20Sopenharmony_ci	/*
21028c2ecf20Sopenharmony_ci	 * Create a symlink with mac80211. It will be removed when mac80211
21038c2ecf20Sopenharmony_ci	 * exists (before the opmode exists which removes the target.)
21048c2ecf20Sopenharmony_ci	 */
21058c2ecf20Sopenharmony_ci	snprintf(buf, 100, "../../%pd2", dbgfs_dir->d_parent);
21068c2ecf20Sopenharmony_ci	debugfs_create_symlink("iwlwifi", mvm->hw->wiphy->debugfsdir, buf);
21078c2ecf20Sopenharmony_ci}
2108