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 <r_config.flags, 17848c2ecf20Sopenharmony_ci <r_config.static_long, 17858c2ecf20Sopenharmony_ci <r_config.static_short, 17868c2ecf20Sopenharmony_ci <r_config.ltr_cfg_values[0], 17878c2ecf20Sopenharmony_ci <r_config.ltr_cfg_values[1], 17888c2ecf20Sopenharmony_ci <r_config.ltr_cfg_values[2], 17898c2ecf20Sopenharmony_ci <r_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 <r_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