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) 2012 - 2014 Intel Corporation. All rights reserved.
98c2ecf20Sopenharmony_ci * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
108c2ecf20Sopenharmony_ci * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
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) 2012 - 2014 Intel Corporation. All rights reserved.
318c2ecf20Sopenharmony_ci * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
328c2ecf20Sopenharmony_ci * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
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 "mvm.h"
638c2ecf20Sopenharmony_ci#include "debugfs.h"
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic void iwl_dbgfs_update_pm(struct iwl_mvm *mvm,
668c2ecf20Sopenharmony_ci				 struct ieee80211_vif *vif,
678c2ecf20Sopenharmony_ci				 enum iwl_dbgfs_pm_mask param, int val)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
708c2ecf20Sopenharmony_ci	struct iwl_dbgfs_pm *dbgfs_pm = &mvmvif->dbgfs_pm;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	dbgfs_pm->mask |= param;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	switch (param) {
758c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_PM_KEEP_ALIVE: {
768c2ecf20Sopenharmony_ci		int dtimper = vif->bss_conf.dtim_period ?: 1;
778c2ecf20Sopenharmony_ci		int dtimper_msec = dtimper * vif->bss_conf.beacon_int;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci		IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val);
808c2ecf20Sopenharmony_ci		if (val * MSEC_PER_SEC < 3 * dtimper_msec)
818c2ecf20Sopenharmony_ci			IWL_WARN(mvm,
828c2ecf20Sopenharmony_ci				 "debugfs: keep alive period (%ld msec) is less than minimum required (%d msec)\n",
838c2ecf20Sopenharmony_ci				 val * MSEC_PER_SEC, 3 * dtimper_msec);
848c2ecf20Sopenharmony_ci		dbgfs_pm->keep_alive_seconds = val;
858c2ecf20Sopenharmony_ci		break;
868c2ecf20Sopenharmony_ci	}
878c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_PM_SKIP_OVER_DTIM:
888c2ecf20Sopenharmony_ci		IWL_DEBUG_POWER(mvm, "skip_over_dtim %s\n",
898c2ecf20Sopenharmony_ci				val ? "enabled" : "disabled");
908c2ecf20Sopenharmony_ci		dbgfs_pm->skip_over_dtim = val;
918c2ecf20Sopenharmony_ci		break;
928c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS:
938c2ecf20Sopenharmony_ci		IWL_DEBUG_POWER(mvm, "skip_dtim_periods=%d\n", val);
948c2ecf20Sopenharmony_ci		dbgfs_pm->skip_dtim_periods = val;
958c2ecf20Sopenharmony_ci		break;
968c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_PM_RX_DATA_TIMEOUT:
978c2ecf20Sopenharmony_ci		IWL_DEBUG_POWER(mvm, "rx_data_timeout=%d\n", val);
988c2ecf20Sopenharmony_ci		dbgfs_pm->rx_data_timeout = val;
998c2ecf20Sopenharmony_ci		break;
1008c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_PM_TX_DATA_TIMEOUT:
1018c2ecf20Sopenharmony_ci		IWL_DEBUG_POWER(mvm, "tx_data_timeout=%d\n", val);
1028c2ecf20Sopenharmony_ci		dbgfs_pm->tx_data_timeout = val;
1038c2ecf20Sopenharmony_ci		break;
1048c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_PM_LPRX_ENA:
1058c2ecf20Sopenharmony_ci		IWL_DEBUG_POWER(mvm, "lprx %s\n", val ? "enabled" : "disabled");
1068c2ecf20Sopenharmony_ci		dbgfs_pm->lprx_ena = val;
1078c2ecf20Sopenharmony_ci		break;
1088c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD:
1098c2ecf20Sopenharmony_ci		IWL_DEBUG_POWER(mvm, "lprx_rssi_threshold=%d\n", val);
1108c2ecf20Sopenharmony_ci		dbgfs_pm->lprx_rssi_threshold = val;
1118c2ecf20Sopenharmony_ci		break;
1128c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_PM_SNOOZE_ENABLE:
1138c2ecf20Sopenharmony_ci		IWL_DEBUG_POWER(mvm, "snooze_enable=%d\n", val);
1148c2ecf20Sopenharmony_ci		dbgfs_pm->snooze_ena = val;
1158c2ecf20Sopenharmony_ci		break;
1168c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_PM_UAPSD_MISBEHAVING:
1178c2ecf20Sopenharmony_ci		IWL_DEBUG_POWER(mvm, "uapsd_misbehaving_enable=%d\n", val);
1188c2ecf20Sopenharmony_ci		dbgfs_pm->uapsd_misbehaving = val;
1198c2ecf20Sopenharmony_ci		break;
1208c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_PM_USE_PS_POLL:
1218c2ecf20Sopenharmony_ci		IWL_DEBUG_POWER(mvm, "use_ps_poll=%d\n", val);
1228c2ecf20Sopenharmony_ci		dbgfs_pm->use_ps_poll = val;
1238c2ecf20Sopenharmony_ci		break;
1248c2ecf20Sopenharmony_ci	}
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf,
1288c2ecf20Sopenharmony_ci					 size_t count, loff_t *ppos)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
1318c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = mvmvif->mvm;
1328c2ecf20Sopenharmony_ci	enum iwl_dbgfs_pm_mask param;
1338c2ecf20Sopenharmony_ci	int val, ret;
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci	if (!strncmp("keep_alive=", buf, 11)) {
1368c2ecf20Sopenharmony_ci		if (sscanf(buf + 11, "%d", &val) != 1)
1378c2ecf20Sopenharmony_ci			return -EINVAL;
1388c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_PM_KEEP_ALIVE;
1398c2ecf20Sopenharmony_ci	} else if (!strncmp("skip_over_dtim=", buf, 15)) {
1408c2ecf20Sopenharmony_ci		if (sscanf(buf + 15, "%d", &val) != 1)
1418c2ecf20Sopenharmony_ci			return -EINVAL;
1428c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_PM_SKIP_OVER_DTIM;
1438c2ecf20Sopenharmony_ci	} else if (!strncmp("skip_dtim_periods=", buf, 18)) {
1448c2ecf20Sopenharmony_ci		if (sscanf(buf + 18, "%d", &val) != 1)
1458c2ecf20Sopenharmony_ci			return -EINVAL;
1468c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_PM_SKIP_DTIM_PERIODS;
1478c2ecf20Sopenharmony_ci	} else if (!strncmp("rx_data_timeout=", buf, 16)) {
1488c2ecf20Sopenharmony_ci		if (sscanf(buf + 16, "%d", &val) != 1)
1498c2ecf20Sopenharmony_ci			return -EINVAL;
1508c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_PM_RX_DATA_TIMEOUT;
1518c2ecf20Sopenharmony_ci	} else if (!strncmp("tx_data_timeout=", buf, 16)) {
1528c2ecf20Sopenharmony_ci		if (sscanf(buf + 16, "%d", &val) != 1)
1538c2ecf20Sopenharmony_ci			return -EINVAL;
1548c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_PM_TX_DATA_TIMEOUT;
1558c2ecf20Sopenharmony_ci	} else if (!strncmp("lprx=", buf, 5)) {
1568c2ecf20Sopenharmony_ci		if (sscanf(buf + 5, "%d", &val) != 1)
1578c2ecf20Sopenharmony_ci			return -EINVAL;
1588c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_PM_LPRX_ENA;
1598c2ecf20Sopenharmony_ci	} else if (!strncmp("lprx_rssi_threshold=", buf, 20)) {
1608c2ecf20Sopenharmony_ci		if (sscanf(buf + 20, "%d", &val) != 1)
1618c2ecf20Sopenharmony_ci			return -EINVAL;
1628c2ecf20Sopenharmony_ci		if (val > POWER_LPRX_RSSI_THRESHOLD_MAX || val <
1638c2ecf20Sopenharmony_ci		    POWER_LPRX_RSSI_THRESHOLD_MIN)
1648c2ecf20Sopenharmony_ci			return -EINVAL;
1658c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_PM_LPRX_RSSI_THRESHOLD;
1668c2ecf20Sopenharmony_ci	} else if (!strncmp("snooze_enable=", buf, 14)) {
1678c2ecf20Sopenharmony_ci		if (sscanf(buf + 14, "%d", &val) != 1)
1688c2ecf20Sopenharmony_ci			return -EINVAL;
1698c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_PM_SNOOZE_ENABLE;
1708c2ecf20Sopenharmony_ci	} else if (!strncmp("uapsd_misbehaving=", buf, 18)) {
1718c2ecf20Sopenharmony_ci		if (sscanf(buf + 18, "%d", &val) != 1)
1728c2ecf20Sopenharmony_ci			return -EINVAL;
1738c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_PM_UAPSD_MISBEHAVING;
1748c2ecf20Sopenharmony_ci	} else if (!strncmp("use_ps_poll=", buf, 12)) {
1758c2ecf20Sopenharmony_ci		if (sscanf(buf + 12, "%d", &val) != 1)
1768c2ecf20Sopenharmony_ci			return -EINVAL;
1778c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_PM_USE_PS_POLL;
1788c2ecf20Sopenharmony_ci	} else {
1798c2ecf20Sopenharmony_ci		return -EINVAL;
1808c2ecf20Sopenharmony_ci	}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
1838c2ecf20Sopenharmony_ci	iwl_dbgfs_update_pm(mvm, vif, param, val);
1848c2ecf20Sopenharmony_ci	ret = iwl_mvm_power_update_mac(mvm);
1858c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	return ret ?: count;
1888c2ecf20Sopenharmony_ci}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_tx_pwr_lmt_read(struct file *file,
1918c2ecf20Sopenharmony_ci					 char __user *user_buf,
1928c2ecf20Sopenharmony_ci					 size_t count, loff_t *ppos)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	struct ieee80211_vif *vif = file->private_data;
1958c2ecf20Sopenharmony_ci	char buf[64];
1968c2ecf20Sopenharmony_ci	int bufsz = sizeof(buf);
1978c2ecf20Sopenharmony_ci	int pos;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	pos = scnprintf(buf, bufsz, "bss limit = %d\n",
2008c2ecf20Sopenharmony_ci			vif->bss_conf.txpower);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2038c2ecf20Sopenharmony_ci}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_pm_params_read(struct file *file,
2068c2ecf20Sopenharmony_ci					char __user *user_buf,
2078c2ecf20Sopenharmony_ci					size_t count, loff_t *ppos)
2088c2ecf20Sopenharmony_ci{
2098c2ecf20Sopenharmony_ci	struct ieee80211_vif *vif = file->private_data;
2108c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
2118c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = mvmvif->mvm;
2128c2ecf20Sopenharmony_ci	char buf[512];
2138c2ecf20Sopenharmony_ci	int bufsz = sizeof(buf);
2148c2ecf20Sopenharmony_ci	int pos;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	pos = iwl_mvm_power_mac_dbgfs_read(mvm, vif, buf, bufsz);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
2198c2ecf20Sopenharmony_ci}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_mac_params_read(struct file *file,
2228c2ecf20Sopenharmony_ci					 char __user *user_buf,
2238c2ecf20Sopenharmony_ci					 size_t count, loff_t *ppos)
2248c2ecf20Sopenharmony_ci{
2258c2ecf20Sopenharmony_ci	struct ieee80211_vif *vif = file->private_data;
2268c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
2278c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = mvmvif->mvm;
2288c2ecf20Sopenharmony_ci	u8 ap_sta_id;
2298c2ecf20Sopenharmony_ci	struct ieee80211_chanctx_conf *chanctx_conf;
2308c2ecf20Sopenharmony_ci	char buf[512];
2318c2ecf20Sopenharmony_ci	int bufsz = sizeof(buf);
2328c2ecf20Sopenharmony_ci	int pos = 0;
2338c2ecf20Sopenharmony_ci	int i;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci	ap_sta_id = mvmvif->ap_sta_id;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	switch (ieee80211_vif_type_p2p(vif)) {
2408c2ecf20Sopenharmony_ci	case NL80211_IFTYPE_ADHOC:
2418c2ecf20Sopenharmony_ci		pos += scnprintf(buf+pos, bufsz-pos, "type: ibss\n");
2428c2ecf20Sopenharmony_ci		break;
2438c2ecf20Sopenharmony_ci	case NL80211_IFTYPE_STATION:
2448c2ecf20Sopenharmony_ci		pos += scnprintf(buf+pos, bufsz-pos, "type: bss\n");
2458c2ecf20Sopenharmony_ci		break;
2468c2ecf20Sopenharmony_ci	case NL80211_IFTYPE_AP:
2478c2ecf20Sopenharmony_ci		pos += scnprintf(buf+pos, bufsz-pos, "type: ap\n");
2488c2ecf20Sopenharmony_ci		break;
2498c2ecf20Sopenharmony_ci	case NL80211_IFTYPE_P2P_CLIENT:
2508c2ecf20Sopenharmony_ci		pos += scnprintf(buf+pos, bufsz-pos, "type: p2p client\n");
2518c2ecf20Sopenharmony_ci		break;
2528c2ecf20Sopenharmony_ci	case NL80211_IFTYPE_P2P_GO:
2538c2ecf20Sopenharmony_ci		pos += scnprintf(buf+pos, bufsz-pos, "type: p2p go\n");
2548c2ecf20Sopenharmony_ci		break;
2558c2ecf20Sopenharmony_ci	case NL80211_IFTYPE_P2P_DEVICE:
2568c2ecf20Sopenharmony_ci		pos += scnprintf(buf+pos, bufsz-pos, "type: p2p dev\n");
2578c2ecf20Sopenharmony_ci		break;
2588c2ecf20Sopenharmony_ci	default:
2598c2ecf20Sopenharmony_ci		break;
2608c2ecf20Sopenharmony_ci	}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "mac id/color: %d / %d\n",
2638c2ecf20Sopenharmony_ci			 mvmvif->id, mvmvif->color);
2648c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "bssid: %pM\n",
2658c2ecf20Sopenharmony_ci			 vif->bss_conf.bssid);
2668c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "Load: %d\n",
2678c2ecf20Sopenharmony_ci			 mvm->tcm.result.load[mvmvif->id]);
2688c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "QoS:\n");
2698c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(mvmvif->queue_params); i++)
2708c2ecf20Sopenharmony_ci		pos += scnprintf(buf+pos, bufsz-pos,
2718c2ecf20Sopenharmony_ci				 "\t%d: txop:%d - cw_min:%d - cw_max = %d - aifs = %d upasd = %d\n",
2728c2ecf20Sopenharmony_ci				 i, mvmvif->queue_params[i].txop,
2738c2ecf20Sopenharmony_ci				 mvmvif->queue_params[i].cw_min,
2748c2ecf20Sopenharmony_ci				 mvmvif->queue_params[i].cw_max,
2758c2ecf20Sopenharmony_ci				 mvmvif->queue_params[i].aifs,
2768c2ecf20Sopenharmony_ci				 mvmvif->queue_params[i].uapsd);
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	if (vif->type == NL80211_IFTYPE_STATION &&
2798c2ecf20Sopenharmony_ci	    ap_sta_id != IWL_MVM_INVALID_STA) {
2808c2ecf20Sopenharmony_ci		struct iwl_mvm_sta *mvm_sta;
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci		mvm_sta = iwl_mvm_sta_from_staid_protected(mvm, ap_sta_id);
2838c2ecf20Sopenharmony_ci		if (mvm_sta) {
2848c2ecf20Sopenharmony_ci			pos += scnprintf(buf+pos, bufsz-pos,
2858c2ecf20Sopenharmony_ci					 "ap_sta_id %d - reduced Tx power %d\n",
2868c2ecf20Sopenharmony_ci					 ap_sta_id,
2878c2ecf20Sopenharmony_ci					 mvm_sta->bt_reduced_txpower);
2888c2ecf20Sopenharmony_ci		}
2898c2ecf20Sopenharmony_ci	}
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	rcu_read_lock();
2928c2ecf20Sopenharmony_ci	chanctx_conf = rcu_dereference(vif->chanctx_conf);
2938c2ecf20Sopenharmony_ci	if (chanctx_conf)
2948c2ecf20Sopenharmony_ci		pos += scnprintf(buf+pos, bufsz-pos,
2958c2ecf20Sopenharmony_ci				 "idle rx chains %d, active rx chains: %d\n",
2968c2ecf20Sopenharmony_ci				 chanctx_conf->rx_chains_static,
2978c2ecf20Sopenharmony_ci				 chanctx_conf->rx_chains_dynamic);
2988c2ecf20Sopenharmony_ci	rcu_read_unlock();
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
3038c2ecf20Sopenharmony_ci}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
3068c2ecf20Sopenharmony_ci				enum iwl_dbgfs_bf_mask param, int value)
3078c2ecf20Sopenharmony_ci{
3088c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
3098c2ecf20Sopenharmony_ci	struct iwl_dbgfs_bf *dbgfs_bf = &mvmvif->dbgfs_bf;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	dbgfs_bf->mask |= param;
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_ci	switch (param) {
3148c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_BF_ENERGY_DELTA:
3158c2ecf20Sopenharmony_ci		dbgfs_bf->bf_energy_delta = value;
3168c2ecf20Sopenharmony_ci		break;
3178c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA:
3188c2ecf20Sopenharmony_ci		dbgfs_bf->bf_roaming_energy_delta = value;
3198c2ecf20Sopenharmony_ci		break;
3208c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_BF_ROAMING_STATE:
3218c2ecf20Sopenharmony_ci		dbgfs_bf->bf_roaming_state = value;
3228c2ecf20Sopenharmony_ci		break;
3238c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_BF_TEMP_THRESHOLD:
3248c2ecf20Sopenharmony_ci		dbgfs_bf->bf_temp_threshold = value;
3258c2ecf20Sopenharmony_ci		break;
3268c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_BF_TEMP_FAST_FILTER:
3278c2ecf20Sopenharmony_ci		dbgfs_bf->bf_temp_fast_filter = value;
3288c2ecf20Sopenharmony_ci		break;
3298c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_BF_TEMP_SLOW_FILTER:
3308c2ecf20Sopenharmony_ci		dbgfs_bf->bf_temp_slow_filter = value;
3318c2ecf20Sopenharmony_ci		break;
3328c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER:
3338c2ecf20Sopenharmony_ci		dbgfs_bf->bf_enable_beacon_filter = value;
3348c2ecf20Sopenharmony_ci		break;
3358c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_BF_DEBUG_FLAG:
3368c2ecf20Sopenharmony_ci		dbgfs_bf->bf_debug_flag = value;
3378c2ecf20Sopenharmony_ci		break;
3388c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_BF_ESCAPE_TIMER:
3398c2ecf20Sopenharmony_ci		dbgfs_bf->bf_escape_timer = value;
3408c2ecf20Sopenharmony_ci		break;
3418c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT:
3428c2ecf20Sopenharmony_ci		dbgfs_bf->ba_enable_beacon_abort = value;
3438c2ecf20Sopenharmony_ci		break;
3448c2ecf20Sopenharmony_ci	case MVM_DEBUGFS_BA_ESCAPE_TIMER:
3458c2ecf20Sopenharmony_ci		dbgfs_bf->ba_escape_timer = value;
3468c2ecf20Sopenharmony_ci		break;
3478c2ecf20Sopenharmony_ci	}
3488c2ecf20Sopenharmony_ci}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_bf_params_write(struct ieee80211_vif *vif, char *buf,
3518c2ecf20Sopenharmony_ci					 size_t count, loff_t *ppos)
3528c2ecf20Sopenharmony_ci{
3538c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
3548c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = mvmvif->mvm;
3558c2ecf20Sopenharmony_ci	enum iwl_dbgfs_bf_mask param;
3568c2ecf20Sopenharmony_ci	int value, ret = 0;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	if (!strncmp("bf_energy_delta=", buf, 16)) {
3598c2ecf20Sopenharmony_ci		if (sscanf(buf+16, "%d", &value) != 1)
3608c2ecf20Sopenharmony_ci			return -EINVAL;
3618c2ecf20Sopenharmony_ci		if (value < IWL_BF_ENERGY_DELTA_MIN ||
3628c2ecf20Sopenharmony_ci		    value > IWL_BF_ENERGY_DELTA_MAX)
3638c2ecf20Sopenharmony_ci			return -EINVAL;
3648c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_BF_ENERGY_DELTA;
3658c2ecf20Sopenharmony_ci	} else if (!strncmp("bf_roaming_energy_delta=", buf, 24)) {
3668c2ecf20Sopenharmony_ci		if (sscanf(buf+24, "%d", &value) != 1)
3678c2ecf20Sopenharmony_ci			return -EINVAL;
3688c2ecf20Sopenharmony_ci		if (value < IWL_BF_ROAMING_ENERGY_DELTA_MIN ||
3698c2ecf20Sopenharmony_ci		    value > IWL_BF_ROAMING_ENERGY_DELTA_MAX)
3708c2ecf20Sopenharmony_ci			return -EINVAL;
3718c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_BF_ROAMING_ENERGY_DELTA;
3728c2ecf20Sopenharmony_ci	} else if (!strncmp("bf_roaming_state=", buf, 17)) {
3738c2ecf20Sopenharmony_ci		if (sscanf(buf+17, "%d", &value) != 1)
3748c2ecf20Sopenharmony_ci			return -EINVAL;
3758c2ecf20Sopenharmony_ci		if (value < IWL_BF_ROAMING_STATE_MIN ||
3768c2ecf20Sopenharmony_ci		    value > IWL_BF_ROAMING_STATE_MAX)
3778c2ecf20Sopenharmony_ci			return -EINVAL;
3788c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_BF_ROAMING_STATE;
3798c2ecf20Sopenharmony_ci	} else if (!strncmp("bf_temp_threshold=", buf, 18)) {
3808c2ecf20Sopenharmony_ci		if (sscanf(buf+18, "%d", &value) != 1)
3818c2ecf20Sopenharmony_ci			return -EINVAL;
3828c2ecf20Sopenharmony_ci		if (value < IWL_BF_TEMP_THRESHOLD_MIN ||
3838c2ecf20Sopenharmony_ci		    value > IWL_BF_TEMP_THRESHOLD_MAX)
3848c2ecf20Sopenharmony_ci			return -EINVAL;
3858c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_BF_TEMP_THRESHOLD;
3868c2ecf20Sopenharmony_ci	} else if (!strncmp("bf_temp_fast_filter=", buf, 20)) {
3878c2ecf20Sopenharmony_ci		if (sscanf(buf+20, "%d", &value) != 1)
3888c2ecf20Sopenharmony_ci			return -EINVAL;
3898c2ecf20Sopenharmony_ci		if (value < IWL_BF_TEMP_FAST_FILTER_MIN ||
3908c2ecf20Sopenharmony_ci		    value > IWL_BF_TEMP_FAST_FILTER_MAX)
3918c2ecf20Sopenharmony_ci			return -EINVAL;
3928c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_BF_TEMP_FAST_FILTER;
3938c2ecf20Sopenharmony_ci	} else if (!strncmp("bf_temp_slow_filter=", buf, 20)) {
3948c2ecf20Sopenharmony_ci		if (sscanf(buf+20, "%d", &value) != 1)
3958c2ecf20Sopenharmony_ci			return -EINVAL;
3968c2ecf20Sopenharmony_ci		if (value < IWL_BF_TEMP_SLOW_FILTER_MIN ||
3978c2ecf20Sopenharmony_ci		    value > IWL_BF_TEMP_SLOW_FILTER_MAX)
3988c2ecf20Sopenharmony_ci			return -EINVAL;
3998c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_BF_TEMP_SLOW_FILTER;
4008c2ecf20Sopenharmony_ci	} else if (!strncmp("bf_enable_beacon_filter=", buf, 24)) {
4018c2ecf20Sopenharmony_ci		if (sscanf(buf+24, "%d", &value) != 1)
4028c2ecf20Sopenharmony_ci			return -EINVAL;
4038c2ecf20Sopenharmony_ci		if (value < 0 || value > 1)
4048c2ecf20Sopenharmony_ci			return -EINVAL;
4058c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER;
4068c2ecf20Sopenharmony_ci	} else if (!strncmp("bf_debug_flag=", buf, 14)) {
4078c2ecf20Sopenharmony_ci		if (sscanf(buf+14, "%d", &value) != 1)
4088c2ecf20Sopenharmony_ci			return -EINVAL;
4098c2ecf20Sopenharmony_ci		if (value < 0 || value > 1)
4108c2ecf20Sopenharmony_ci			return -EINVAL;
4118c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_BF_DEBUG_FLAG;
4128c2ecf20Sopenharmony_ci	} else if (!strncmp("bf_escape_timer=", buf, 16)) {
4138c2ecf20Sopenharmony_ci		if (sscanf(buf+16, "%d", &value) != 1)
4148c2ecf20Sopenharmony_ci			return -EINVAL;
4158c2ecf20Sopenharmony_ci		if (value < IWL_BF_ESCAPE_TIMER_MIN ||
4168c2ecf20Sopenharmony_ci		    value > IWL_BF_ESCAPE_TIMER_MAX)
4178c2ecf20Sopenharmony_ci			return -EINVAL;
4188c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_BF_ESCAPE_TIMER;
4198c2ecf20Sopenharmony_ci	} else if (!strncmp("ba_escape_timer=", buf, 16)) {
4208c2ecf20Sopenharmony_ci		if (sscanf(buf+16, "%d", &value) != 1)
4218c2ecf20Sopenharmony_ci			return -EINVAL;
4228c2ecf20Sopenharmony_ci		if (value < IWL_BA_ESCAPE_TIMER_MIN ||
4238c2ecf20Sopenharmony_ci		    value > IWL_BA_ESCAPE_TIMER_MAX)
4248c2ecf20Sopenharmony_ci			return -EINVAL;
4258c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_BA_ESCAPE_TIMER;
4268c2ecf20Sopenharmony_ci	} else if (!strncmp("ba_enable_beacon_abort=", buf, 23)) {
4278c2ecf20Sopenharmony_ci		if (sscanf(buf+23, "%d", &value) != 1)
4288c2ecf20Sopenharmony_ci			return -EINVAL;
4298c2ecf20Sopenharmony_ci		if (value < 0 || value > 1)
4308c2ecf20Sopenharmony_ci			return -EINVAL;
4318c2ecf20Sopenharmony_ci		param = MVM_DEBUGFS_BA_ENABLE_BEACON_ABORT;
4328c2ecf20Sopenharmony_ci	} else {
4338c2ecf20Sopenharmony_ci		return -EINVAL;
4348c2ecf20Sopenharmony_ci	}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
4378c2ecf20Sopenharmony_ci	iwl_dbgfs_update_bf(vif, param, value);
4388c2ecf20Sopenharmony_ci	if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value)
4398c2ecf20Sopenharmony_ci		ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
4408c2ecf20Sopenharmony_ci	else
4418c2ecf20Sopenharmony_ci		ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
4428c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	return ret ?: count;
4458c2ecf20Sopenharmony_ci}
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_bf_params_read(struct file *file,
4488c2ecf20Sopenharmony_ci					char __user *user_buf,
4498c2ecf20Sopenharmony_ci					size_t count, loff_t *ppos)
4508c2ecf20Sopenharmony_ci{
4518c2ecf20Sopenharmony_ci	struct ieee80211_vif *vif = file->private_data;
4528c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
4538c2ecf20Sopenharmony_ci	char buf[256];
4548c2ecf20Sopenharmony_ci	int pos = 0;
4558c2ecf20Sopenharmony_ci	const size_t bufsz = sizeof(buf);
4568c2ecf20Sopenharmony_ci	struct iwl_beacon_filter_cmd cmd = {
4578c2ecf20Sopenharmony_ci		IWL_BF_CMD_CONFIG_DEFAULTS,
4588c2ecf20Sopenharmony_ci		.bf_enable_beacon_filter =
4598c2ecf20Sopenharmony_ci			cpu_to_le32(IWL_BF_ENABLE_BEACON_FILTER_DEFAULT),
4608c2ecf20Sopenharmony_ci		.ba_enable_beacon_abort =
4618c2ecf20Sopenharmony_ci			cpu_to_le32(IWL_BA_ENABLE_BEACON_ABORT_DEFAULT),
4628c2ecf20Sopenharmony_ci	};
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
4658c2ecf20Sopenharmony_ci	if (mvmvif->bf_data.bf_enabled)
4668c2ecf20Sopenharmony_ci		cmd.bf_enable_beacon_filter = cpu_to_le32(1);
4678c2ecf20Sopenharmony_ci	else
4688c2ecf20Sopenharmony_ci		cmd.bf_enable_beacon_filter = 0;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "bf_energy_delta = %d\n",
4718c2ecf20Sopenharmony_ci			 le32_to_cpu(cmd.bf_energy_delta));
4728c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_energy_delta = %d\n",
4738c2ecf20Sopenharmony_ci			 le32_to_cpu(cmd.bf_roaming_energy_delta));
4748c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "bf_roaming_state = %d\n",
4758c2ecf20Sopenharmony_ci			 le32_to_cpu(cmd.bf_roaming_state));
4768c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_threshold = %d\n",
4778c2ecf20Sopenharmony_ci			 le32_to_cpu(cmd.bf_temp_threshold));
4788c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_fast_filter = %d\n",
4798c2ecf20Sopenharmony_ci			 le32_to_cpu(cmd.bf_temp_fast_filter));
4808c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "bf_temp_slow_filter = %d\n",
4818c2ecf20Sopenharmony_ci			 le32_to_cpu(cmd.bf_temp_slow_filter));
4828c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "bf_enable_beacon_filter = %d\n",
4838c2ecf20Sopenharmony_ci			 le32_to_cpu(cmd.bf_enable_beacon_filter));
4848c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "bf_debug_flag = %d\n",
4858c2ecf20Sopenharmony_ci			 le32_to_cpu(cmd.bf_debug_flag));
4868c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "bf_escape_timer = %d\n",
4878c2ecf20Sopenharmony_ci			 le32_to_cpu(cmd.bf_escape_timer));
4888c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "ba_escape_timer = %d\n",
4898c2ecf20Sopenharmony_ci			 le32_to_cpu(cmd.ba_escape_timer));
4908c2ecf20Sopenharmony_ci	pos += scnprintf(buf+pos, bufsz-pos, "ba_enable_beacon_abort = %d\n",
4918c2ecf20Sopenharmony_ci			 le32_to_cpu(cmd.ba_enable_beacon_abort));
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic inline char *iwl_dbgfs_is_match(char *name, char *buf)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	int len = strlen(name);
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	return !strncmp(name, buf, len) ? buf + len : NULL;
5018c2ecf20Sopenharmony_ci}
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_os_device_timediff_read(struct file *file,
5048c2ecf20Sopenharmony_ci						 char __user *user_buf,
5058c2ecf20Sopenharmony_ci						 size_t count, loff_t *ppos)
5068c2ecf20Sopenharmony_ci{
5078c2ecf20Sopenharmony_ci	struct ieee80211_vif *vif = file->private_data;
5088c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
5098c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = mvmvif->mvm;
5108c2ecf20Sopenharmony_ci	u32 curr_gp2;
5118c2ecf20Sopenharmony_ci	u64 curr_os;
5128c2ecf20Sopenharmony_ci	s64 diff;
5138c2ecf20Sopenharmony_ci	char buf[64];
5148c2ecf20Sopenharmony_ci	const size_t bufsz = sizeof(buf);
5158c2ecf20Sopenharmony_ci	int pos = 0;
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
5188c2ecf20Sopenharmony_ci	iwl_mvm_get_sync_time(mvm, &curr_gp2, &curr_os);
5198c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	do_div(curr_os, NSEC_PER_USEC);
5228c2ecf20Sopenharmony_ci	diff = curr_os - curr_gp2;
5238c2ecf20Sopenharmony_ci	pos += scnprintf(buf + pos, bufsz - pos, "diff=%lld\n", diff);
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
5268c2ecf20Sopenharmony_ci}
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf,
5298c2ecf20Sopenharmony_ci					   size_t count, loff_t *ppos)
5308c2ecf20Sopenharmony_ci{
5318c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
5328c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = mvmvif->mvm;
5338c2ecf20Sopenharmony_ci	u8 value;
5348c2ecf20Sopenharmony_ci	int ret;
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	ret = kstrtou8(buf, 0, &value);
5378c2ecf20Sopenharmony_ci	if (ret)
5388c2ecf20Sopenharmony_ci		return ret;
5398c2ecf20Sopenharmony_ci	if (value > 1)
5408c2ecf20Sopenharmony_ci		return -EINVAL;
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
5438c2ecf20Sopenharmony_ci	iwl_mvm_update_low_latency(mvm, vif, value, LOW_LATENCY_DEBUGFS);
5448c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	return count;
5478c2ecf20Sopenharmony_ci}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_cistatic ssize_t
5508c2ecf20Sopenharmony_ciiwl_dbgfs_low_latency_force_write(struct ieee80211_vif *vif, char *buf,
5518c2ecf20Sopenharmony_ci				  size_t count, loff_t *ppos)
5528c2ecf20Sopenharmony_ci{
5538c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
5548c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = mvmvif->mvm;
5558c2ecf20Sopenharmony_ci	u8 value;
5568c2ecf20Sopenharmony_ci	int ret;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	ret = kstrtou8(buf, 0, &value);
5598c2ecf20Sopenharmony_ci	if (ret)
5608c2ecf20Sopenharmony_ci		return ret;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	if (value > NUM_LOW_LATENCY_FORCE)
5638c2ecf20Sopenharmony_ci		return -EINVAL;
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
5668c2ecf20Sopenharmony_ci	if (value == LOW_LATENCY_FORCE_UNSET) {
5678c2ecf20Sopenharmony_ci		iwl_mvm_update_low_latency(mvm, vif, false,
5688c2ecf20Sopenharmony_ci					   LOW_LATENCY_DEBUGFS_FORCE);
5698c2ecf20Sopenharmony_ci		iwl_mvm_update_low_latency(mvm, vif, false,
5708c2ecf20Sopenharmony_ci					   LOW_LATENCY_DEBUGFS_FORCE_ENABLE);
5718c2ecf20Sopenharmony_ci	} else {
5728c2ecf20Sopenharmony_ci		iwl_mvm_update_low_latency(mvm, vif,
5738c2ecf20Sopenharmony_ci					   value == LOW_LATENCY_FORCE_ON,
5748c2ecf20Sopenharmony_ci					   LOW_LATENCY_DEBUGFS_FORCE);
5758c2ecf20Sopenharmony_ci		iwl_mvm_update_low_latency(mvm, vif, true,
5768c2ecf20Sopenharmony_ci					   LOW_LATENCY_DEBUGFS_FORCE_ENABLE);
5778c2ecf20Sopenharmony_ci	}
5788c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
5798c2ecf20Sopenharmony_ci	return count;
5808c2ecf20Sopenharmony_ci}
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_low_latency_read(struct file *file,
5838c2ecf20Sopenharmony_ci					  char __user *user_buf,
5848c2ecf20Sopenharmony_ci					  size_t count, loff_t *ppos)
5858c2ecf20Sopenharmony_ci{
5868c2ecf20Sopenharmony_ci	struct ieee80211_vif *vif = file->private_data;
5878c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
5888c2ecf20Sopenharmony_ci	char format[] = "traffic=%d\ndbgfs=%d\nvcmd=%d\nvif_type=%d\n"
5898c2ecf20Sopenharmony_ci			"dbgfs_force_enable=%d\ndbgfs_force=%d\nactual=%d\n";
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	/*
5928c2ecf20Sopenharmony_ci	 * all values in format are boolean so the size of format is enough
5938c2ecf20Sopenharmony_ci	 * for holding the result string
5948c2ecf20Sopenharmony_ci	 */
5958c2ecf20Sopenharmony_ci	char buf[sizeof(format) + 1] = {};
5968c2ecf20Sopenharmony_ci	int len;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	len = scnprintf(buf, sizeof(buf) - 1, format,
5998c2ecf20Sopenharmony_ci			!!(mvmvif->low_latency & LOW_LATENCY_TRAFFIC),
6008c2ecf20Sopenharmony_ci			!!(mvmvif->low_latency & LOW_LATENCY_DEBUGFS),
6018c2ecf20Sopenharmony_ci			!!(mvmvif->low_latency & LOW_LATENCY_VCMD),
6028c2ecf20Sopenharmony_ci			!!(mvmvif->low_latency & LOW_LATENCY_VIF_TYPE),
6038c2ecf20Sopenharmony_ci			!!(mvmvif->low_latency &
6048c2ecf20Sopenharmony_ci			   LOW_LATENCY_DEBUGFS_FORCE_ENABLE),
6058c2ecf20Sopenharmony_ci			!!(mvmvif->low_latency & LOW_LATENCY_DEBUGFS_FORCE),
6068c2ecf20Sopenharmony_ci			!!(mvmvif->low_latency_actual));
6078c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
6088c2ecf20Sopenharmony_ci}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_uapsd_misbehaving_read(struct file *file,
6118c2ecf20Sopenharmony_ci						char __user *user_buf,
6128c2ecf20Sopenharmony_ci						size_t count, loff_t *ppos)
6138c2ecf20Sopenharmony_ci{
6148c2ecf20Sopenharmony_ci	struct ieee80211_vif *vif = file->private_data;
6158c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
6168c2ecf20Sopenharmony_ci	char buf[20];
6178c2ecf20Sopenharmony_ci	int len;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	len = sprintf(buf, "%pM\n", mvmvif->uapsd_misbehaving_bssid);
6208c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
6218c2ecf20Sopenharmony_ci}
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_uapsd_misbehaving_write(struct ieee80211_vif *vif,
6248c2ecf20Sopenharmony_ci						 char *buf, size_t count,
6258c2ecf20Sopenharmony_ci						 loff_t *ppos)
6268c2ecf20Sopenharmony_ci{
6278c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
6288c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = mvmvif->mvm;
6298c2ecf20Sopenharmony_ci	bool ret;
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
6328c2ecf20Sopenharmony_ci	ret = mac_pton(buf, mvmvif->uapsd_misbehaving_bssid);
6338c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	return ret ? count : -EINVAL;
6368c2ecf20Sopenharmony_ci}
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_rx_phyinfo_write(struct ieee80211_vif *vif, char *buf,
6398c2ecf20Sopenharmony_ci					  size_t count, loff_t *ppos)
6408c2ecf20Sopenharmony_ci{
6418c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
6428c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = mvmvif->mvm;
6438c2ecf20Sopenharmony_ci	struct ieee80211_chanctx_conf *chanctx_conf;
6448c2ecf20Sopenharmony_ci	struct iwl_mvm_phy_ctxt *phy_ctxt;
6458c2ecf20Sopenharmony_ci	u16 value;
6468c2ecf20Sopenharmony_ci	int ret;
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	ret = kstrtou16(buf, 0, &value);
6498c2ecf20Sopenharmony_ci	if (ret)
6508c2ecf20Sopenharmony_ci		return ret;
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
6538c2ecf20Sopenharmony_ci	rcu_read_lock();
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	chanctx_conf = rcu_dereference(vif->chanctx_conf);
6568c2ecf20Sopenharmony_ci	/* make sure the channel context is assigned */
6578c2ecf20Sopenharmony_ci	if (!chanctx_conf) {
6588c2ecf20Sopenharmony_ci		rcu_read_unlock();
6598c2ecf20Sopenharmony_ci		mutex_unlock(&mvm->mutex);
6608c2ecf20Sopenharmony_ci		return -EINVAL;
6618c2ecf20Sopenharmony_ci	}
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	phy_ctxt = &mvm->phy_ctxts[*(u16 *)chanctx_conf->drv_priv];
6648c2ecf20Sopenharmony_ci	rcu_read_unlock();
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	mvm->dbgfs_rx_phyinfo = value;
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &chanctx_conf->min_def,
6698c2ecf20Sopenharmony_ci				       chanctx_conf->rx_chains_static,
6708c2ecf20Sopenharmony_ci				       chanctx_conf->rx_chains_dynamic);
6718c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	return ret ?: count;
6748c2ecf20Sopenharmony_ci}
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_rx_phyinfo_read(struct file *file,
6778c2ecf20Sopenharmony_ci					 char __user *user_buf,
6788c2ecf20Sopenharmony_ci					 size_t count, loff_t *ppos)
6798c2ecf20Sopenharmony_ci{
6808c2ecf20Sopenharmony_ci	struct ieee80211_vif *vif = file->private_data;
6818c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
6828c2ecf20Sopenharmony_ci	char buf[8];
6838c2ecf20Sopenharmony_ci	int len;
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	len = scnprintf(buf, sizeof(buf), "0x%04x\n",
6868c2ecf20Sopenharmony_ci			mvmvif->mvm->dbgfs_rx_phyinfo);
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
6898c2ecf20Sopenharmony_ci}
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_cistatic void iwl_dbgfs_quota_check(void *data, u8 *mac,
6928c2ecf20Sopenharmony_ci				  struct ieee80211_vif *vif)
6938c2ecf20Sopenharmony_ci{
6948c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
6958c2ecf20Sopenharmony_ci	int *ret = data;
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	if (mvmvif->dbgfs_quota_min)
6988c2ecf20Sopenharmony_ci		*ret = -EINVAL;
6998c2ecf20Sopenharmony_ci}
7008c2ecf20Sopenharmony_ci
7018c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_quota_min_write(struct ieee80211_vif *vif, char *buf,
7028c2ecf20Sopenharmony_ci					 size_t count, loff_t *ppos)
7038c2ecf20Sopenharmony_ci{
7048c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
7058c2ecf20Sopenharmony_ci	struct iwl_mvm *mvm = mvmvif->mvm;
7068c2ecf20Sopenharmony_ci	u16 value;
7078c2ecf20Sopenharmony_ci	int ret;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	ret = kstrtou16(buf, 0, &value);
7108c2ecf20Sopenharmony_ci	if (ret)
7118c2ecf20Sopenharmony_ci		return ret;
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_ci	if (value > 95)
7148c2ecf20Sopenharmony_ci		return -EINVAL;
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	mutex_lock(&mvm->mutex);
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	mvmvif->dbgfs_quota_min = 0;
7198c2ecf20Sopenharmony_ci	ieee80211_iterate_interfaces(mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
7208c2ecf20Sopenharmony_ci				     iwl_dbgfs_quota_check, &ret);
7218c2ecf20Sopenharmony_ci	if (ret == 0) {
7228c2ecf20Sopenharmony_ci		mvmvif->dbgfs_quota_min = value;
7238c2ecf20Sopenharmony_ci		iwl_mvm_update_quotas(mvm, false, NULL);
7248c2ecf20Sopenharmony_ci	}
7258c2ecf20Sopenharmony_ci	mutex_unlock(&mvm->mutex);
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	return ret ?: count;
7288c2ecf20Sopenharmony_ci}
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_cistatic ssize_t iwl_dbgfs_quota_min_read(struct file *file,
7318c2ecf20Sopenharmony_ci					char __user *user_buf,
7328c2ecf20Sopenharmony_ci					size_t count, loff_t *ppos)
7338c2ecf20Sopenharmony_ci{
7348c2ecf20Sopenharmony_ci	struct ieee80211_vif *vif = file->private_data;
7358c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
7368c2ecf20Sopenharmony_ci	char buf[10];
7378c2ecf20Sopenharmony_ci	int len;
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci	len = scnprintf(buf, sizeof(buf), "%d\n", mvmvif->dbgfs_quota_min);
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
7428c2ecf20Sopenharmony_ci}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
7458c2ecf20Sopenharmony_ci	_MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
7468c2ecf20Sopenharmony_ci#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
7478c2ecf20Sopenharmony_ci	_MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz, struct ieee80211_vif)
7488c2ecf20Sopenharmony_ci#define MVM_DEBUGFS_ADD_FILE_VIF(name, parent, mode) do {		\
7498c2ecf20Sopenharmony_ci		debugfs_create_file(#name, mode, parent, vif,		\
7508c2ecf20Sopenharmony_ci				    &iwl_dbgfs_##name##_ops);		\
7518c2ecf20Sopenharmony_ci	} while (0)
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(mac_params);
7548c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(tx_pwr_lmt);
7558c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32);
7568c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256);
7578c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10);
7588c2ecf20Sopenharmony_ciMVM_DEBUGFS_WRITE_FILE_OPS(low_latency_force, 10);
7598c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(uapsd_misbehaving, 20);
7608c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(rx_phyinfo, 10);
7618c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_WRITE_FILE_OPS(quota_min, 32);
7628c2ecf20Sopenharmony_ciMVM_DEBUGFS_READ_FILE_OPS(os_device_timediff);
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_civoid iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
7668c2ecf20Sopenharmony_ci{
7678c2ecf20Sopenharmony_ci	struct dentry *dbgfs_dir = vif->debugfs_dir;
7688c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
7698c2ecf20Sopenharmony_ci	char buf[100];
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	/*
7728c2ecf20Sopenharmony_ci	 * Check if debugfs directory already exist before creating it.
7738c2ecf20Sopenharmony_ci	 * This may happen when, for example, resetting hw or suspend-resume
7748c2ecf20Sopenharmony_ci	 */
7758c2ecf20Sopenharmony_ci	if (!dbgfs_dir || mvmvif->dbgfs_dir)
7768c2ecf20Sopenharmony_ci		return;
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	mvmvif->dbgfs_dir = debugfs_create_dir("iwlmvm", dbgfs_dir);
7798c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(mvmvif->dbgfs_dir)) {
7808c2ecf20Sopenharmony_ci		IWL_ERR(mvm, "Failed to create debugfs directory under %pd\n",
7818c2ecf20Sopenharmony_ci			dbgfs_dir);
7828c2ecf20Sopenharmony_ci		return;
7838c2ecf20Sopenharmony_ci	}
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci	if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM &&
7868c2ecf20Sopenharmony_ci	    ((vif->type == NL80211_IFTYPE_STATION && !vif->p2p) ||
7878c2ecf20Sopenharmony_ci	     (vif->type == NL80211_IFTYPE_STATION && vif->p2p)))
7888c2ecf20Sopenharmony_ci		MVM_DEBUGFS_ADD_FILE_VIF(pm_params, mvmvif->dbgfs_dir, 0600);
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE_VIF(tx_pwr_lmt, mvmvif->dbgfs_dir, 0400);
7918c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, 0400);
7928c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir, 0600);
7938c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE_VIF(low_latency_force, mvmvif->dbgfs_dir, 0600);
7948c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE_VIF(uapsd_misbehaving, mvmvif->dbgfs_dir, 0600);
7958c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE_VIF(rx_phyinfo, mvmvif->dbgfs_dir, 0600);
7968c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE_VIF(quota_min, mvmvif->dbgfs_dir, 0600);
7978c2ecf20Sopenharmony_ci	MVM_DEBUGFS_ADD_FILE_VIF(os_device_timediff, mvmvif->dbgfs_dir, 0400);
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p &&
8008c2ecf20Sopenharmony_ci	    mvmvif == mvm->bf_allowed_vif)
8018c2ecf20Sopenharmony_ci		MVM_DEBUGFS_ADD_FILE_VIF(bf_params, mvmvif->dbgfs_dir, 0600);
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	/*
8048c2ecf20Sopenharmony_ci	 * Create symlink for convenience pointing to interface specific
8058c2ecf20Sopenharmony_ci	 * debugfs entries for the driver. For example, under
8068c2ecf20Sopenharmony_ci	 * /sys/kernel/debug/iwlwifi/0000\:02\:00.0/iwlmvm/
8078c2ecf20Sopenharmony_ci	 * find
8088c2ecf20Sopenharmony_ci	 * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
8098c2ecf20Sopenharmony_ci	 */
8108c2ecf20Sopenharmony_ci	snprintf(buf, 100, "../../../%pd3/%pd",
8118c2ecf20Sopenharmony_ci		 dbgfs_dir,
8128c2ecf20Sopenharmony_ci		 mvmvif->dbgfs_dir);
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
8158c2ecf20Sopenharmony_ci						     mvm->debugfs_dir, buf);
8168c2ecf20Sopenharmony_ci}
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_civoid iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
8198c2ecf20Sopenharmony_ci{
8208c2ecf20Sopenharmony_ci	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	debugfs_remove(mvmvif->dbgfs_slink);
8238c2ecf20Sopenharmony_ci	mvmvif->dbgfs_slink = NULL;
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	debugfs_remove_recursive(mvmvif->dbgfs_dir);
8268c2ecf20Sopenharmony_ci	mvmvif->dbgfs_dir = NULL;
8278c2ecf20Sopenharmony_ci}
828