diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c')
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 258 | 
1 files changed, 243 insertions, 15 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 85b99316d029..84a488538427 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1,6 +1,6 @@  // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause  /* - * Copyright (C) 2012-2014, 2018-2022 Intel Corporation + * Copyright (C) 2012-2014, 2018-2023 Intel Corporation   * Copyright (C) 2013-2015 Intel Mobile Communications GmbH   * Copyright (C) 2016-2017 Intel Deutschland GmbH   */ @@ -8,6 +8,7 @@  #include <linux/err.h>  #include <linux/ieee80211.h>  #include <linux/netdevice.h> +#include <linux/dmi.h>  #include "mvm.h"  #include "sta.h" @@ -15,6 +16,7 @@  #include "debugfs.h"  #include "iwl-modparams.h"  #include "fw/error-dump.h" +#include "fw/api/phy-ctxt.h"  static ssize_t iwl_dbgfs_ctdp_budget_read(struct file *file,  					  char __user *user_buf, @@ -214,9 +216,9 @@ static ssize_t iwl_dbgfs_set_nic_temperature_read(struct file *file,  	int pos;  	if (!mvm->temperature_test) -		pos = scnprintf(buf , sizeof(buf), "disabled\n"); +		pos = scnprintf(buf, sizeof(buf), "disabled\n");  	else -		pos = scnprintf(buf , sizeof(buf), "%d\n", mvm->temperature); +		pos = scnprintf(buf, sizeof(buf), "%d\n", mvm->temperature);  	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);  } @@ -261,7 +263,7 @@ static ssize_t iwl_dbgfs_set_nic_temperature_write(struct iwl_mvm *mvm,  		mvm->temperature = temperature;  	}  	IWL_DEBUG_TEMP(mvm, "%sabling debug set temperature (temp = %d)\n", -		       mvm->temperature_test ? "En" : "Dis" , +		       mvm->temperature_test ? "En" : "Dis",  		       mvm->temperature);  	/* handle the temperature change */  	iwl_mvm_tt_handler(mvm); @@ -291,7 +293,7 @@ static ssize_t iwl_dbgfs_nic_temp_read(struct file *file,  	if (ret)  		return -EIO; -	pos = scnprintf(buf , sizeof(buf), "%d\n", temp); +	pos = scnprintf(buf, sizeof(buf), "%d\n", temp);  	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);  } @@ -338,6 +340,26 @@ static ssize_t iwl_dbgfs_sar_geo_profile_read(struct file *file,  	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);  } + +static ssize_t iwl_dbgfs_wifi_6e_enable_read(struct file *file, +					     char __user *user_buf, +					     size_t count, loff_t *ppos) +{ +	struct iwl_mvm *mvm = file->private_data; +	int err, pos; +	char buf[12]; +	u32 value; + +	err = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0, +				   DSM_FUNC_ENABLE_6E, +				   &iwl_guid, &value); +	if (err) +		return err; + +	pos = sprintf(buf, "0x%08x\n", value); + +	return simple_read_from_buffer(user_buf, count, ppos, buf, pos); +}  #endif  static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, @@ -374,7 +396,7 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,  {  	struct ieee80211_sta *sta = file->private_data;  	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); -	struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->lq_sta.rs_fw; +	struct iwl_lq_sta_rs_fw *lq_sta = &mvmsta->deflink.lq_sta.rs_fw;  	struct iwl_mvm *mvm = lq_sta->pers.drv;  	static const size_t bufsz = 2048;  	char *buff; @@ -714,6 +736,190 @@ static ssize_t iwl_dbgfs_fw_ver_read(struct file *file, char __user *user_buf,  	return ret;  } +static ssize_t iwl_dbgfs_tas_get_status_read(struct file *file, +					     char __user *user_buf, +					     size_t count, loff_t *ppos) +{ +	struct iwl_mvm *mvm = file->private_data; +	struct iwl_mvm_tas_status_resp tas_rsp; +	struct iwl_mvm_tas_status_resp *rsp = &tas_rsp; +	static const size_t bufsz = 1024; +	char *buff, *pos, *endpos; +	const char * const tas_dis_reason[TAS_DISABLED_REASON_MAX] = { +		[TAS_DISABLED_DUE_TO_BIOS] = +			"Due To BIOS", +		[TAS_DISABLED_DUE_TO_SAR_6DBM] = +			"Due To SAR Limit Less Than 6 dBm", +		[TAS_DISABLED_REASON_INVALID] = +			"N/A", +	}; +	const char * const tas_current_status[TAS_DYNA_STATUS_MAX] = { +		[TAS_DYNA_INACTIVE] = "INACTIVE", +		[TAS_DYNA_INACTIVE_MVM_MODE] = +			"inactive due to mvm mode", +		[TAS_DYNA_INACTIVE_TRIGGER_MODE] = +			"inactive due to trigger mode", +		[TAS_DYNA_INACTIVE_BLOCK_LISTED] = +			"inactive due to block listed", +		[TAS_DYNA_INACTIVE_UHB_NON_US] = +			"inactive due to uhb non US", +		[TAS_DYNA_ACTIVE] = "ACTIVE", +	}; +	struct iwl_host_cmd hcmd = { +		.id = WIDE_ID(DEBUG_GROUP, GET_TAS_STATUS), +		.flags = CMD_WANT_SKB, +		.len = { 0, }, +		.data = { NULL, }, +	}; +	int ret, i, tmp; +	bool tas_enabled = false; +	unsigned long dyn_status; + +	if (!iwl_mvm_firmware_running(mvm)) +		return -ENODEV; + +	mutex_lock(&mvm->mutex); +	ret = iwl_mvm_send_cmd(mvm, &hcmd); +	mutex_unlock(&mvm->mutex); +	if (ret < 0) +		return ret; + +	buff = kzalloc(bufsz, GFP_KERNEL); +	if (!buff) +		return -ENOMEM; +	pos = buff; +	endpos = pos + bufsz; + +	rsp = (void *)hcmd.resp_pkt->data; + +	pos += scnprintf(pos, endpos - pos, "TAS Conclusion:\n"); +	for (i = 0; i < rsp->in_dual_radio + 1; i++) { +		if (rsp->tas_status_mac[i].band != TAS_LMAC_BAND_INVALID && +		    rsp->tas_status_mac[i].dynamic_status & BIT(TAS_DYNA_ACTIVE)) { +			pos += scnprintf(pos, endpos - pos, "\tON for "); +			switch (rsp->tas_status_mac[i].band) { +			case TAS_LMAC_BAND_HB: +				pos += scnprintf(pos, endpos - pos, "HB\n"); +				break; +			case TAS_LMAC_BAND_LB: +				pos += scnprintf(pos, endpos - pos, "LB\n"); +				break; +			case TAS_LMAC_BAND_UHB: +				pos += scnprintf(pos, endpos - pos, "UHB\n"); +				break; +			case TAS_LMAC_BAND_INVALID: +				pos += scnprintf(pos, endpos - pos, +						 "INVALID BAND\n"); +				break; +			default: +				pos += scnprintf(pos, endpos - pos, +						 "Unsupported band (%d)\n", +						 rsp->tas_status_mac[i].band); +				goto out; +			} +			tas_enabled = true; +		} +	} +	if (!tas_enabled) +		pos += scnprintf(pos, endpos - pos, "\tOFF\n"); + +	pos += scnprintf(pos, endpos - pos, "TAS Report\n"); +	pos += scnprintf(pos, endpos - pos, "TAS FW version: %d\n", +			 rsp->tas_fw_version); +	pos += scnprintf(pos, endpos - pos, "Is UHB enabled for USA?: %s\n", +			 rsp->is_uhb_for_usa_enable ? "True" : "False"); +	pos += scnprintf(pos, endpos - pos, "Current MCC: 0x%x\n", +			 le16_to_cpu(rsp->curr_mcc)); + +	pos += scnprintf(pos, endpos - pos, "Block list entries:"); +	for (i = 0; i < APCI_WTAS_BLACK_LIST_MAX; i++) +		pos += scnprintf(pos, endpos - pos, " 0x%x", +				 le16_to_cpu(rsp->block_list[i])); + +	pos += scnprintf(pos, endpos - pos, "\nOEM name: %s\n", +			 dmi_get_system_info(DMI_SYS_VENDOR)); +	pos += scnprintf(pos, endpos - pos, "\tVendor In Approved List: %s\n", +			 iwl_mvm_is_vendor_in_approved_list() ? "YES" : "NO"); +	pos += scnprintf(pos, endpos - pos, +			 "\tDo TAS Support Dual Radio?: %s\n", +			 rsp->in_dual_radio ? "TRUE" : "FALSE"); + +	for (i = 0; i < rsp->in_dual_radio + 1; i++) { +		if (rsp->tas_status_mac[i].static_status == 0) { +			pos += scnprintf(pos, endpos - pos, +					 "Static status: disabled\n"); +			pos += scnprintf(pos, endpos - pos, +					 "Static disabled reason: %s (0)\n", +					 tas_dis_reason[0]); +			goto out; +		} + +		pos += scnprintf(pos, endpos - pos, "TAS status for "); +		switch (rsp->tas_status_mac[i].band) { +		case TAS_LMAC_BAND_HB: +			pos += scnprintf(pos, endpos - pos, "High band\n"); +			break; +		case TAS_LMAC_BAND_LB: +			pos += scnprintf(pos, endpos - pos, "Low band\n"); +			break; +		case TAS_LMAC_BAND_UHB: +			pos += scnprintf(pos, endpos - pos, +					 "Ultra high band\n"); +			break; +		case TAS_LMAC_BAND_INVALID: +			pos += scnprintf(pos, endpos - pos, +					 "INVALID band\n"); +			break; +		default: +			pos += scnprintf(pos, endpos - pos, +					 "Unsupported band (%d)\n", +					 rsp->tas_status_mac[i].band); +			goto out; +		} +		pos += scnprintf(pos, endpos - pos, "Static status: %sabled\n", +				 rsp->tas_status_mac[i].static_status ? +				 "En" : "Dis"); +		pos += scnprintf(pos, endpos - pos, +				 "\tStatic Disabled Reason: "); +		if (rsp->tas_status_mac[i].static_dis_reason < TAS_DISABLED_REASON_MAX) +			pos += scnprintf(pos, endpos - pos, "%s (%d)\n", +					 tas_dis_reason[rsp->tas_status_mac[i].static_dis_reason], +					 rsp->tas_status_mac[i].static_dis_reason); +		else +			pos += scnprintf(pos, endpos - pos, +					 "unsupported value (%d)\n", +					 rsp->tas_status_mac[i].static_dis_reason); + +		pos += scnprintf(pos, endpos - pos, "Dynamic status:\n"); +		dyn_status = (rsp->tas_status_mac[i].dynamic_status); +		for_each_set_bit(tmp, &dyn_status, sizeof(dyn_status)) { +			if (tmp >= 0 && tmp < TAS_DYNA_STATUS_MAX) +				pos += scnprintf(pos, endpos - pos, +						 "\t%s (%d)\n", +						 tas_current_status[tmp], tmp); +		} + +		pos += scnprintf(pos, endpos - pos, +				 "Is near disconnection?: %s\n", +				 rsp->tas_status_mac[i].near_disconnection ? +				 "True" : "False"); +		tmp = le16_to_cpu(rsp->tas_status_mac[i].max_reg_pwr_limit); +		pos += scnprintf(pos, endpos - pos, +				 "Max. regulatory pwr limit (dBm): %d.%03d\n", +				 tmp / 8, 125 * (tmp % 8)); +		tmp = le16_to_cpu(rsp->tas_status_mac[i].sar_limit); +		pos += scnprintf(pos, endpos - pos, +				 "SAR limit (dBm): %d.%03d\n", +				 tmp / 8, 125 * (tmp % 8)); +	} + +out: +	ret = simple_read_from_buffer(user_buf, count, ppos, buff, pos - buff); +	kfree(buff); +	iwl_free_resp(&hcmd); +	return ret; +} +  static ssize_t iwl_dbgfs_phy_integration_ver_read(struct file *file,  						  char __user *user_buf,  						  size_t count, loff_t *ppos) @@ -1202,6 +1408,7 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)  	struct sk_buff *beacon;  	struct ieee80211_tx_info *info;  	struct iwl_mac_beacon_cmd beacon_cmd = {}; +	unsigned int link_id;  	u8 rate;  	int i; @@ -1250,17 +1457,24 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)  	info = IEEE80211_SKB_CB(beacon);  	rate = iwl_mvm_mac_ctxt_get_beacon_rate(mvm, info, vif); -	beacon_cmd.flags = -		cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate)); -	beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len); -	beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id); +	for_each_mvm_vif_valid_link(mvmvif, link_id) { +		beacon_cmd.flags = +			cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, +								      rate)); +		beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len); +		if (iwl_fw_lookup_cmd_ver(mvm->fw, BEACON_TEMPLATE_CMD, 0) > 12) +			beacon_cmd.link_id = +				cpu_to_le32(mvmvif->link[link_id]->fw_link_id); +		else +			beacon_cmd.link_id = cpu_to_le32((u32)mvmvif->id); -	iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx, -				 &beacon_cmd.tim_size, -				 beacon->data, beacon->len); +		iwl_mvm_mac_ctxt_set_tim(mvm, &beacon_cmd.tim_idx, +					 &beacon_cmd.tim_size, +					 beacon->data, beacon->len); -	iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd, -					 sizeof(beacon_cmd)); +		iwl_mvm_mac_ctxt_send_beacon_cmd(mvm, beacon, &beacon_cmd, +						 sizeof(beacon_cmd)); +	}  	mutex_unlock(&mvm->mutex);  	dev_kfree_skb(beacon); @@ -1685,6 +1899,7 @@ MVM_DEBUGFS_READ_FILE_OPS(fw_rx_stats);  MVM_DEBUGFS_READ_FILE_OPS(drv_rx_stats);  MVM_DEBUGFS_READ_FILE_OPS(fw_ver);  MVM_DEBUGFS_READ_FILE_OPS(phy_integration_ver); +MVM_DEBUGFS_READ_FILE_OPS(tas_get_status);  MVM_DEBUGFS_WRITE_FILE_OPS(fw_restart, 10);  MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);  MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10); @@ -1703,6 +1918,7 @@ MVM_DEBUGFS_READ_FILE_OPS(uapsd_noagg_bssids);  #ifdef CONFIG_ACPI  MVM_DEBUGFS_READ_FILE_OPS(sar_geo_profile); +MVM_DEBUGFS_READ_FILE_OPS(wifi_6e_enable);  #endif  MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(amsdu_len, 16); @@ -1745,6 +1961,11 @@ static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,  	if (ret < 0)  		return ret; +	if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) { +		ret = -EIO; +		goto out; +	} +  	rsp = (void *)hcmd.resp_pkt->data;  	if (le32_to_cpu(rsp->status) != DEBUG_MEM_STATUS_SUCCESS) {  		ret = -ENXIO; @@ -1821,6 +2042,11 @@ static ssize_t iwl_dbgfs_mem_write(struct file *file,  	if (ret < 0)  		return ret; +	if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) { +		ret = -EIO; +		goto out; +	} +  	rsp = (void *)hcmd.resp_pkt->data;  	if (rsp->status != DEBUG_MEM_STATUS_SUCCESS) {  		ret = -ENXIO; @@ -1894,8 +2120,10 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm)  	if (mvm->fw->phy_integration_ver)  		MVM_DEBUGFS_ADD_FILE(phy_integration_ver, mvm->debugfs_dir, 0400); +	MVM_DEBUGFS_ADD_FILE(tas_get_status, mvm->debugfs_dir, 0400);  #ifdef CONFIG_ACPI  	MVM_DEBUGFS_ADD_FILE(sar_geo_profile, mvm->debugfs_dir, 0400); +	MVM_DEBUGFS_ADD_FILE(wifi_6e_enable, mvm->debugfs_dir, 0400);  #endif  	MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600);  |