18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * NXP Wireless LAN device driver: debugfs 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright 2011-2020 NXP 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This software file (the "File") is distributed by NXP 78c2ecf20Sopenharmony_ci * under the terms of the GNU General Public License Version 2, June 1991 88c2ecf20Sopenharmony_ci * (the "License"). You may use, redistribute and/or modify this File in 98c2ecf20Sopenharmony_ci * accordance with the terms and conditions of the License, a copy of which 108c2ecf20Sopenharmony_ci * is available by writing to the Free Software Foundation, Inc., 118c2ecf20Sopenharmony_ci * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the 128c2ecf20Sopenharmony_ci * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 158c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 168c2ecf20Sopenharmony_ci * ARE EXPRESSLY DISCLAIMED. The License provides additional details about 178c2ecf20Sopenharmony_ci * this warranty disclaimer. 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include <linux/debugfs.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "main.h" 238c2ecf20Sopenharmony_ci#include "11n.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic struct dentry *mwifiex_dfs_dir; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic char *bss_modes[] = { 298c2ecf20Sopenharmony_ci "UNSPECIFIED", 308c2ecf20Sopenharmony_ci "ADHOC", 318c2ecf20Sopenharmony_ci "STATION", 328c2ecf20Sopenharmony_ci "AP", 338c2ecf20Sopenharmony_ci "AP_VLAN", 348c2ecf20Sopenharmony_ci "WDS", 358c2ecf20Sopenharmony_ci "MONITOR", 368c2ecf20Sopenharmony_ci "MESH_POINT", 378c2ecf20Sopenharmony_ci "P2P_CLIENT", 388c2ecf20Sopenharmony_ci "P2P_GO", 398c2ecf20Sopenharmony_ci "P2P_DEVICE", 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* 438c2ecf20Sopenharmony_ci * Proc info file read handler. 448c2ecf20Sopenharmony_ci * 458c2ecf20Sopenharmony_ci * This function is called when the 'info' file is opened for reading. 468c2ecf20Sopenharmony_ci * It prints the following driver related information - 478c2ecf20Sopenharmony_ci * - Driver name 488c2ecf20Sopenharmony_ci * - Driver version 498c2ecf20Sopenharmony_ci * - Driver extended version 508c2ecf20Sopenharmony_ci * - Interface name 518c2ecf20Sopenharmony_ci * - BSS mode 528c2ecf20Sopenharmony_ci * - Media state (connected or disconnected) 538c2ecf20Sopenharmony_ci * - MAC address 548c2ecf20Sopenharmony_ci * - Total number of Tx bytes 558c2ecf20Sopenharmony_ci * - Total number of Rx bytes 568c2ecf20Sopenharmony_ci * - Total number of Tx packets 578c2ecf20Sopenharmony_ci * - Total number of Rx packets 588c2ecf20Sopenharmony_ci * - Total number of dropped Tx packets 598c2ecf20Sopenharmony_ci * - Total number of dropped Rx packets 608c2ecf20Sopenharmony_ci * - Total number of corrupted Tx packets 618c2ecf20Sopenharmony_ci * - Total number of corrupted Rx packets 628c2ecf20Sopenharmony_ci * - Carrier status (on or off) 638c2ecf20Sopenharmony_ci * - Tx queue status (started or stopped) 648c2ecf20Sopenharmony_ci * 658c2ecf20Sopenharmony_ci * For STA mode drivers, it also prints the following extra - 668c2ecf20Sopenharmony_ci * - ESSID 678c2ecf20Sopenharmony_ci * - BSSID 688c2ecf20Sopenharmony_ci * - Channel 698c2ecf20Sopenharmony_ci * - Region code 708c2ecf20Sopenharmony_ci * - Multicast count 718c2ecf20Sopenharmony_ci * - Multicast addresses 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_cistatic ssize_t 748c2ecf20Sopenharmony_cimwifiex_info_read(struct file *file, char __user *ubuf, 758c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci struct mwifiex_private *priv = 788c2ecf20Sopenharmony_ci (struct mwifiex_private *) file->private_data; 798c2ecf20Sopenharmony_ci struct net_device *netdev = priv->netdev; 808c2ecf20Sopenharmony_ci struct netdev_hw_addr *ha; 818c2ecf20Sopenharmony_ci struct netdev_queue *txq; 828c2ecf20Sopenharmony_ci unsigned long page = get_zeroed_page(GFP_KERNEL); 838c2ecf20Sopenharmony_ci char *p = (char *) page, fmt[64]; 848c2ecf20Sopenharmony_ci struct mwifiex_bss_info info; 858c2ecf20Sopenharmony_ci ssize_t ret; 868c2ecf20Sopenharmony_ci int i = 0; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci if (!p) 898c2ecf20Sopenharmony_ci return -ENOMEM; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci memset(&info, 0, sizeof(info)); 928c2ecf20Sopenharmony_ci ret = mwifiex_get_bss_info(priv, &info); 938c2ecf20Sopenharmony_ci if (ret) 948c2ecf20Sopenharmony_ci goto free_and_exit; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci mwifiex_get_ver_ext(priv, 0); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci p += sprintf(p, "driver_name = " "\"mwifiex\"\n"); 1018c2ecf20Sopenharmony_ci p += sprintf(p, "driver_version = %s", fmt); 1028c2ecf20Sopenharmony_ci p += sprintf(p, "\nverext = %s", priv->version_str); 1038c2ecf20Sopenharmony_ci p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci if (info.bss_mode >= ARRAY_SIZE(bss_modes)) 1068c2ecf20Sopenharmony_ci p += sprintf(p, "bss_mode=\"%d\"\n", info.bss_mode); 1078c2ecf20Sopenharmony_ci else 1088c2ecf20Sopenharmony_ci p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci p += sprintf(p, "media_state=\"%s\"\n", 1118c2ecf20Sopenharmony_ci (!priv->media_connected ? "Disconnected" : "Connected")); 1128c2ecf20Sopenharmony_ci p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { 1158c2ecf20Sopenharmony_ci p += sprintf(p, "multicast_count=\"%d\"\n", 1168c2ecf20Sopenharmony_ci netdev_mc_count(netdev)); 1178c2ecf20Sopenharmony_ci p += sprintf(p, "essid=\"%.*s\"\n", info.ssid.ssid_len, 1188c2ecf20Sopenharmony_ci info.ssid.ssid); 1198c2ecf20Sopenharmony_ci p += sprintf(p, "bssid=\"%pM\"\n", info.bssid); 1208c2ecf20Sopenharmony_ci p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); 1218c2ecf20Sopenharmony_ci p += sprintf(p, "country_code = \"%s\"\n", info.country_code); 1228c2ecf20Sopenharmony_ci p += sprintf(p, "region_code=\"0x%x\"\n", 1238c2ecf20Sopenharmony_ci priv->adapter->region_code); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci netdev_for_each_mc_addr(ha, netdev) 1268c2ecf20Sopenharmony_ci p += sprintf(p, "multicast_address[%d]=\"%pM\"\n", 1278c2ecf20Sopenharmony_ci i++, ha->addr); 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); 1318c2ecf20Sopenharmony_ci p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes); 1328c2ecf20Sopenharmony_ci p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets); 1338c2ecf20Sopenharmony_ci p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets); 1348c2ecf20Sopenharmony_ci p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped); 1358c2ecf20Sopenharmony_ci p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped); 1368c2ecf20Sopenharmony_ci p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors); 1378c2ecf20Sopenharmony_ci p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); 1388c2ecf20Sopenharmony_ci p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) 1398c2ecf20Sopenharmony_ci ? "on" : "off")); 1408c2ecf20Sopenharmony_ci p += sprintf(p, "tx queue"); 1418c2ecf20Sopenharmony_ci for (i = 0; i < netdev->num_tx_queues; i++) { 1428c2ecf20Sopenharmony_ci txq = netdev_get_tx_queue(netdev, i); 1438c2ecf20Sopenharmony_ci p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ? 1448c2ecf20Sopenharmony_ci "stopped" : "started"); 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci p += sprintf(p, "\n"); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, 1498c2ecf20Sopenharmony_ci (unsigned long) p - page); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cifree_and_exit: 1528c2ecf20Sopenharmony_ci free_page(page); 1538c2ecf20Sopenharmony_ci return ret; 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci/* 1578c2ecf20Sopenharmony_ci * Proc getlog file read handler. 1588c2ecf20Sopenharmony_ci * 1598c2ecf20Sopenharmony_ci * This function is called when the 'getlog' file is opened for reading 1608c2ecf20Sopenharmony_ci * It prints the following log information - 1618c2ecf20Sopenharmony_ci * - Number of multicast Tx frames 1628c2ecf20Sopenharmony_ci * - Number of failed packets 1638c2ecf20Sopenharmony_ci * - Number of Tx retries 1648c2ecf20Sopenharmony_ci * - Number of multicast Tx retries 1658c2ecf20Sopenharmony_ci * - Number of duplicate frames 1668c2ecf20Sopenharmony_ci * - Number of RTS successes 1678c2ecf20Sopenharmony_ci * - Number of RTS failures 1688c2ecf20Sopenharmony_ci * - Number of ACK failures 1698c2ecf20Sopenharmony_ci * - Number of fragmented Rx frames 1708c2ecf20Sopenharmony_ci * - Number of multicast Rx frames 1718c2ecf20Sopenharmony_ci * - Number of FCS errors 1728c2ecf20Sopenharmony_ci * - Number of Tx frames 1738c2ecf20Sopenharmony_ci * - WEP ICV error counts 1748c2ecf20Sopenharmony_ci * - Number of received beacons 1758c2ecf20Sopenharmony_ci * - Number of missed beacons 1768c2ecf20Sopenharmony_ci */ 1778c2ecf20Sopenharmony_cistatic ssize_t 1788c2ecf20Sopenharmony_cimwifiex_getlog_read(struct file *file, char __user *ubuf, 1798c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci struct mwifiex_private *priv = 1828c2ecf20Sopenharmony_ci (struct mwifiex_private *) file->private_data; 1838c2ecf20Sopenharmony_ci unsigned long page = get_zeroed_page(GFP_KERNEL); 1848c2ecf20Sopenharmony_ci char *p = (char *) page; 1858c2ecf20Sopenharmony_ci ssize_t ret; 1868c2ecf20Sopenharmony_ci struct mwifiex_ds_get_stats stats; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (!p) 1898c2ecf20Sopenharmony_ci return -ENOMEM; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci memset(&stats, 0, sizeof(stats)); 1928c2ecf20Sopenharmony_ci ret = mwifiex_get_stats_info(priv, &stats); 1938c2ecf20Sopenharmony_ci if (ret) 1948c2ecf20Sopenharmony_ci goto free_and_exit; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci p += sprintf(p, "\n" 1978c2ecf20Sopenharmony_ci "mcasttxframe %u\n" 1988c2ecf20Sopenharmony_ci "failed %u\n" 1998c2ecf20Sopenharmony_ci "retry %u\n" 2008c2ecf20Sopenharmony_ci "multiretry %u\n" 2018c2ecf20Sopenharmony_ci "framedup %u\n" 2028c2ecf20Sopenharmony_ci "rtssuccess %u\n" 2038c2ecf20Sopenharmony_ci "rtsfailure %u\n" 2048c2ecf20Sopenharmony_ci "ackfailure %u\n" 2058c2ecf20Sopenharmony_ci "rxfrag %u\n" 2068c2ecf20Sopenharmony_ci "mcastrxframe %u\n" 2078c2ecf20Sopenharmony_ci "fcserror %u\n" 2088c2ecf20Sopenharmony_ci "txframe %u\n" 2098c2ecf20Sopenharmony_ci "wepicverrcnt-1 %u\n" 2108c2ecf20Sopenharmony_ci "wepicverrcnt-2 %u\n" 2118c2ecf20Sopenharmony_ci "wepicverrcnt-3 %u\n" 2128c2ecf20Sopenharmony_ci "wepicverrcnt-4 %u\n" 2138c2ecf20Sopenharmony_ci "bcn_rcv_cnt %u\n" 2148c2ecf20Sopenharmony_ci "bcn_miss_cnt %u\n", 2158c2ecf20Sopenharmony_ci stats.mcast_tx_frame, 2168c2ecf20Sopenharmony_ci stats.failed, 2178c2ecf20Sopenharmony_ci stats.retry, 2188c2ecf20Sopenharmony_ci stats.multi_retry, 2198c2ecf20Sopenharmony_ci stats.frame_dup, 2208c2ecf20Sopenharmony_ci stats.rts_success, 2218c2ecf20Sopenharmony_ci stats.rts_failure, 2228c2ecf20Sopenharmony_ci stats.ack_failure, 2238c2ecf20Sopenharmony_ci stats.rx_frag, 2248c2ecf20Sopenharmony_ci stats.mcast_rx_frame, 2258c2ecf20Sopenharmony_ci stats.fcs_error, 2268c2ecf20Sopenharmony_ci stats.tx_frame, 2278c2ecf20Sopenharmony_ci stats.wep_icv_error[0], 2288c2ecf20Sopenharmony_ci stats.wep_icv_error[1], 2298c2ecf20Sopenharmony_ci stats.wep_icv_error[2], 2308c2ecf20Sopenharmony_ci stats.wep_icv_error[3], 2318c2ecf20Sopenharmony_ci stats.bcn_rcv_cnt, 2328c2ecf20Sopenharmony_ci stats.bcn_miss_cnt); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, 2368c2ecf20Sopenharmony_ci (unsigned long) p - page); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cifree_and_exit: 2398c2ecf20Sopenharmony_ci free_page(page); 2408c2ecf20Sopenharmony_ci return ret; 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci/* Sysfs histogram file read handler. 2448c2ecf20Sopenharmony_ci * 2458c2ecf20Sopenharmony_ci * This function is called when the 'histogram' file is opened for reading 2468c2ecf20Sopenharmony_ci * It prints the following histogram information - 2478c2ecf20Sopenharmony_ci * - Number of histogram samples 2488c2ecf20Sopenharmony_ci * - Receive packet number of each rx_rate 2498c2ecf20Sopenharmony_ci * - Receive packet number of each snr 2508c2ecf20Sopenharmony_ci * - Receive packet number of each nosie_flr 2518c2ecf20Sopenharmony_ci * - Receive packet number of each signal streath 2528c2ecf20Sopenharmony_ci */ 2538c2ecf20Sopenharmony_cistatic ssize_t 2548c2ecf20Sopenharmony_cimwifiex_histogram_read(struct file *file, char __user *ubuf, 2558c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci struct mwifiex_private *priv = 2588c2ecf20Sopenharmony_ci (struct mwifiex_private *)file->private_data; 2598c2ecf20Sopenharmony_ci ssize_t ret; 2608c2ecf20Sopenharmony_ci struct mwifiex_histogram_data *phist_data; 2618c2ecf20Sopenharmony_ci int i, value; 2628c2ecf20Sopenharmony_ci unsigned long page = get_zeroed_page(GFP_KERNEL); 2638c2ecf20Sopenharmony_ci char *p = (char *)page; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci if (!p) 2668c2ecf20Sopenharmony_ci return -ENOMEM; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci if (!priv || !priv->hist_data) { 2698c2ecf20Sopenharmony_ci ret = -EFAULT; 2708c2ecf20Sopenharmony_ci goto free_and_exit; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci phist_data = priv->hist_data; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci p += sprintf(p, "\n" 2768c2ecf20Sopenharmony_ci "total samples = %d\n", 2778c2ecf20Sopenharmony_ci atomic_read(&phist_data->num_samples)); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci p += sprintf(p, 2808c2ecf20Sopenharmony_ci "rx rates (in Mbps): 0=1M 1=2M 2=5.5M 3=11M 4=6M 5=9M 6=12M\n" 2818c2ecf20Sopenharmony_ci "7=18M 8=24M 9=36M 10=48M 11=54M 12-27=MCS0-15(BW20) 28-43=MCS0-15(BW40)\n"); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) { 2848c2ecf20Sopenharmony_ci p += sprintf(p, 2858c2ecf20Sopenharmony_ci "44-53=MCS0-9(VHT:BW20) 54-63=MCS0-9(VHT:BW40) 64-73=MCS0-9(VHT:BW80)\n\n"); 2868c2ecf20Sopenharmony_ci } else { 2878c2ecf20Sopenharmony_ci p += sprintf(p, "\n"); 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci for (i = 0; i < MWIFIEX_MAX_RX_RATES; i++) { 2918c2ecf20Sopenharmony_ci value = atomic_read(&phist_data->rx_rate[i]); 2928c2ecf20Sopenharmony_ci if (value) 2938c2ecf20Sopenharmony_ci p += sprintf(p, "rx_rate[%02d] = %d\n", i, value); 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) { 2978c2ecf20Sopenharmony_ci for (i = MWIFIEX_MAX_RX_RATES; i < MWIFIEX_MAX_AC_RX_RATES; 2988c2ecf20Sopenharmony_ci i++) { 2998c2ecf20Sopenharmony_ci value = atomic_read(&phist_data->rx_rate[i]); 3008c2ecf20Sopenharmony_ci if (value) 3018c2ecf20Sopenharmony_ci p += sprintf(p, "rx_rate[%02d] = %d\n", 3028c2ecf20Sopenharmony_ci i, value); 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci } 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci for (i = 0; i < MWIFIEX_MAX_SNR; i++) { 3078c2ecf20Sopenharmony_ci value = atomic_read(&phist_data->snr[i]); 3088c2ecf20Sopenharmony_ci if (value) 3098c2ecf20Sopenharmony_ci p += sprintf(p, "snr[%02ddB] = %d\n", i, value); 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci for (i = 0; i < MWIFIEX_MAX_NOISE_FLR; i++) { 3128c2ecf20Sopenharmony_ci value = atomic_read(&phist_data->noise_flr[i]); 3138c2ecf20Sopenharmony_ci if (value) 3148c2ecf20Sopenharmony_ci p += sprintf(p, "noise_flr[%02ddBm] = %d\n", 3158c2ecf20Sopenharmony_ci (int)(i-128), value); 3168c2ecf20Sopenharmony_ci } 3178c2ecf20Sopenharmony_ci for (i = 0; i < MWIFIEX_MAX_SIG_STRENGTH; i++) { 3188c2ecf20Sopenharmony_ci value = atomic_read(&phist_data->sig_str[i]); 3198c2ecf20Sopenharmony_ci if (value) 3208c2ecf20Sopenharmony_ci p += sprintf(p, "sig_strength[-%02ddBm] = %d\n", 3218c2ecf20Sopenharmony_ci i, value); 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci ret = simple_read_from_buffer(ubuf, count, ppos, (char *)page, 3258c2ecf20Sopenharmony_ci (unsigned long)p - page); 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cifree_and_exit: 3288c2ecf20Sopenharmony_ci free_page(page); 3298c2ecf20Sopenharmony_ci return ret; 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic ssize_t 3338c2ecf20Sopenharmony_cimwifiex_histogram_write(struct file *file, const char __user *ubuf, 3348c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci struct mwifiex_private *priv = (void *)file->private_data; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci if (priv && priv->hist_data) 3398c2ecf20Sopenharmony_ci mwifiex_hist_data_reset(priv); 3408c2ecf20Sopenharmony_ci return 0; 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_cistatic struct mwifiex_debug_info info; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci/* 3468c2ecf20Sopenharmony_ci * Proc debug file read handler. 3478c2ecf20Sopenharmony_ci * 3488c2ecf20Sopenharmony_ci * This function is called when the 'debug' file is opened for reading 3498c2ecf20Sopenharmony_ci * It prints the following log information - 3508c2ecf20Sopenharmony_ci * - Interrupt count 3518c2ecf20Sopenharmony_ci * - WMM AC VO packets count 3528c2ecf20Sopenharmony_ci * - WMM AC VI packets count 3538c2ecf20Sopenharmony_ci * - WMM AC BE packets count 3548c2ecf20Sopenharmony_ci * - WMM AC BK packets count 3558c2ecf20Sopenharmony_ci * - Maximum Tx buffer size 3568c2ecf20Sopenharmony_ci * - Tx buffer size 3578c2ecf20Sopenharmony_ci * - Current Tx buffer size 3588c2ecf20Sopenharmony_ci * - Power Save mode 3598c2ecf20Sopenharmony_ci * - Power Save state 3608c2ecf20Sopenharmony_ci * - Deep Sleep status 3618c2ecf20Sopenharmony_ci * - Device wakeup required status 3628c2ecf20Sopenharmony_ci * - Number of wakeup tries 3638c2ecf20Sopenharmony_ci * - Host Sleep configured status 3648c2ecf20Sopenharmony_ci * - Host Sleep activated status 3658c2ecf20Sopenharmony_ci * - Number of Tx timeouts 3668c2ecf20Sopenharmony_ci * - Number of command timeouts 3678c2ecf20Sopenharmony_ci * - Last timed out command ID 3688c2ecf20Sopenharmony_ci * - Last timed out command action 3698c2ecf20Sopenharmony_ci * - Last command ID 3708c2ecf20Sopenharmony_ci * - Last command action 3718c2ecf20Sopenharmony_ci * - Last command index 3728c2ecf20Sopenharmony_ci * - Last command response ID 3738c2ecf20Sopenharmony_ci * - Last command response index 3748c2ecf20Sopenharmony_ci * - Last event 3758c2ecf20Sopenharmony_ci * - Last event index 3768c2ecf20Sopenharmony_ci * - Number of host to card command failures 3778c2ecf20Sopenharmony_ci * - Number of sleep confirm command failures 3788c2ecf20Sopenharmony_ci * - Number of host to card data failure 3798c2ecf20Sopenharmony_ci * - Number of deauthentication events 3808c2ecf20Sopenharmony_ci * - Number of disassociation events 3818c2ecf20Sopenharmony_ci * - Number of link lost events 3828c2ecf20Sopenharmony_ci * - Number of deauthentication commands 3838c2ecf20Sopenharmony_ci * - Number of association success commands 3848c2ecf20Sopenharmony_ci * - Number of association failure commands 3858c2ecf20Sopenharmony_ci * - Number of commands sent 3868c2ecf20Sopenharmony_ci * - Number of data packets sent 3878c2ecf20Sopenharmony_ci * - Number of command responses received 3888c2ecf20Sopenharmony_ci * - Number of events received 3898c2ecf20Sopenharmony_ci * - Tx BA stream table (TID, RA) 3908c2ecf20Sopenharmony_ci * - Rx reorder table (TID, TA, Start window, Window size, Buffer) 3918c2ecf20Sopenharmony_ci */ 3928c2ecf20Sopenharmony_cistatic ssize_t 3938c2ecf20Sopenharmony_cimwifiex_debug_read(struct file *file, char __user *ubuf, 3948c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci struct mwifiex_private *priv = 3978c2ecf20Sopenharmony_ci (struct mwifiex_private *) file->private_data; 3988c2ecf20Sopenharmony_ci unsigned long page = get_zeroed_page(GFP_KERNEL); 3998c2ecf20Sopenharmony_ci char *p = (char *) page; 4008c2ecf20Sopenharmony_ci ssize_t ret; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci if (!p) 4038c2ecf20Sopenharmony_ci return -ENOMEM; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci ret = mwifiex_get_debug_info(priv, &info); 4068c2ecf20Sopenharmony_ci if (ret) 4078c2ecf20Sopenharmony_ci goto free_and_exit; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci p += mwifiex_debug_info_to_buffer(priv, p, &info); 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, 4128c2ecf20Sopenharmony_ci (unsigned long) p - page); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_cifree_and_exit: 4158c2ecf20Sopenharmony_ci free_page(page); 4168c2ecf20Sopenharmony_ci return ret; 4178c2ecf20Sopenharmony_ci} 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_cistatic u32 saved_reg_type, saved_reg_offset, saved_reg_value; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci/* 4228c2ecf20Sopenharmony_ci * Proc regrdwr file write handler. 4238c2ecf20Sopenharmony_ci * 4248c2ecf20Sopenharmony_ci * This function is called when the 'regrdwr' file is opened for writing 4258c2ecf20Sopenharmony_ci * 4268c2ecf20Sopenharmony_ci * This function can be used to write to a register. 4278c2ecf20Sopenharmony_ci */ 4288c2ecf20Sopenharmony_cistatic ssize_t 4298c2ecf20Sopenharmony_cimwifiex_regrdwr_write(struct file *file, 4308c2ecf20Sopenharmony_ci const char __user *ubuf, size_t count, loff_t *ppos) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci char *buf; 4338c2ecf20Sopenharmony_ci int ret; 4348c2ecf20Sopenharmony_ci u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); 4378c2ecf20Sopenharmony_ci if (IS_ERR(buf)) 4388c2ecf20Sopenharmony_ci return PTR_ERR(buf); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci sscanf(buf, "%u %x %x", ®_type, ®_offset, ®_value); 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci if (reg_type == 0 || reg_offset == 0) { 4438c2ecf20Sopenharmony_ci ret = -EINVAL; 4448c2ecf20Sopenharmony_ci goto done; 4458c2ecf20Sopenharmony_ci } else { 4468c2ecf20Sopenharmony_ci saved_reg_type = reg_type; 4478c2ecf20Sopenharmony_ci saved_reg_offset = reg_offset; 4488c2ecf20Sopenharmony_ci saved_reg_value = reg_value; 4498c2ecf20Sopenharmony_ci ret = count; 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_cidone: 4528c2ecf20Sopenharmony_ci kfree(buf); 4538c2ecf20Sopenharmony_ci return ret; 4548c2ecf20Sopenharmony_ci} 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci/* 4578c2ecf20Sopenharmony_ci * Proc regrdwr file read handler. 4588c2ecf20Sopenharmony_ci * 4598c2ecf20Sopenharmony_ci * This function is called when the 'regrdwr' file is opened for reading 4608c2ecf20Sopenharmony_ci * 4618c2ecf20Sopenharmony_ci * This function can be used to read from a register. 4628c2ecf20Sopenharmony_ci */ 4638c2ecf20Sopenharmony_cistatic ssize_t 4648c2ecf20Sopenharmony_cimwifiex_regrdwr_read(struct file *file, char __user *ubuf, 4658c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 4668c2ecf20Sopenharmony_ci{ 4678c2ecf20Sopenharmony_ci struct mwifiex_private *priv = 4688c2ecf20Sopenharmony_ci (struct mwifiex_private *) file->private_data; 4698c2ecf20Sopenharmony_ci unsigned long addr = get_zeroed_page(GFP_KERNEL); 4708c2ecf20Sopenharmony_ci char *buf = (char *) addr; 4718c2ecf20Sopenharmony_ci int pos = 0, ret = 0; 4728c2ecf20Sopenharmony_ci u32 reg_value; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci if (!buf) 4758c2ecf20Sopenharmony_ci return -ENOMEM; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci if (!saved_reg_type) { 4788c2ecf20Sopenharmony_ci /* No command has been given */ 4798c2ecf20Sopenharmony_ci pos += snprintf(buf, PAGE_SIZE, "0"); 4808c2ecf20Sopenharmony_ci goto done; 4818c2ecf20Sopenharmony_ci } 4828c2ecf20Sopenharmony_ci /* Set command has been given */ 4838c2ecf20Sopenharmony_ci if (saved_reg_value != UINT_MAX) { 4848c2ecf20Sopenharmony_ci ret = mwifiex_reg_write(priv, saved_reg_type, saved_reg_offset, 4858c2ecf20Sopenharmony_ci saved_reg_value); 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", 4888c2ecf20Sopenharmony_ci saved_reg_type, saved_reg_offset, 4898c2ecf20Sopenharmony_ci saved_reg_value); 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci goto done; 4948c2ecf20Sopenharmony_ci } 4958c2ecf20Sopenharmony_ci /* Get command has been given */ 4968c2ecf20Sopenharmony_ci ret = mwifiex_reg_read(priv, saved_reg_type, 4978c2ecf20Sopenharmony_ci saved_reg_offset, ®_value); 4988c2ecf20Sopenharmony_ci if (ret) { 4998c2ecf20Sopenharmony_ci ret = -EINVAL; 5008c2ecf20Sopenharmony_ci goto done; 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", saved_reg_type, 5048c2ecf20Sopenharmony_ci saved_reg_offset, reg_value); 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_cidone: 5098c2ecf20Sopenharmony_ci free_page(addr); 5108c2ecf20Sopenharmony_ci return ret; 5118c2ecf20Sopenharmony_ci} 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci/* Proc debug_mask file read handler. 5148c2ecf20Sopenharmony_ci * This function is called when the 'debug_mask' file is opened for reading 5158c2ecf20Sopenharmony_ci * This function can be used read driver debugging mask value. 5168c2ecf20Sopenharmony_ci */ 5178c2ecf20Sopenharmony_cistatic ssize_t 5188c2ecf20Sopenharmony_cimwifiex_debug_mask_read(struct file *file, char __user *ubuf, 5198c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 5208c2ecf20Sopenharmony_ci{ 5218c2ecf20Sopenharmony_ci struct mwifiex_private *priv = 5228c2ecf20Sopenharmony_ci (struct mwifiex_private *)file->private_data; 5238c2ecf20Sopenharmony_ci unsigned long page = get_zeroed_page(GFP_KERNEL); 5248c2ecf20Sopenharmony_ci char *buf = (char *)page; 5258c2ecf20Sopenharmony_ci size_t ret = 0; 5268c2ecf20Sopenharmony_ci int pos = 0; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci if (!buf) 5298c2ecf20Sopenharmony_ci return -ENOMEM; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci pos += snprintf(buf, PAGE_SIZE, "debug mask=0x%08x\n", 5328c2ecf20Sopenharmony_ci priv->adapter->debug_mask); 5338c2ecf20Sopenharmony_ci ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci free_page(page); 5368c2ecf20Sopenharmony_ci return ret; 5378c2ecf20Sopenharmony_ci} 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci/* Proc debug_mask file read handler. 5408c2ecf20Sopenharmony_ci * This function is called when the 'debug_mask' file is opened for reading 5418c2ecf20Sopenharmony_ci * This function can be used read driver debugging mask value. 5428c2ecf20Sopenharmony_ci */ 5438c2ecf20Sopenharmony_cistatic ssize_t 5448c2ecf20Sopenharmony_cimwifiex_debug_mask_write(struct file *file, const char __user *ubuf, 5458c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 5468c2ecf20Sopenharmony_ci{ 5478c2ecf20Sopenharmony_ci int ret; 5488c2ecf20Sopenharmony_ci unsigned long debug_mask; 5498c2ecf20Sopenharmony_ci struct mwifiex_private *priv = (void *)file->private_data; 5508c2ecf20Sopenharmony_ci char *buf; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); 5538c2ecf20Sopenharmony_ci if (IS_ERR(buf)) 5548c2ecf20Sopenharmony_ci return PTR_ERR(buf); 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci if (kstrtoul(buf, 0, &debug_mask)) { 5578c2ecf20Sopenharmony_ci ret = -EINVAL; 5588c2ecf20Sopenharmony_ci goto done; 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci priv->adapter->debug_mask = debug_mask; 5628c2ecf20Sopenharmony_ci ret = count; 5638c2ecf20Sopenharmony_cidone: 5648c2ecf20Sopenharmony_ci kfree(buf); 5658c2ecf20Sopenharmony_ci return ret; 5668c2ecf20Sopenharmony_ci} 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci/* debugfs verext file write handler. 5698c2ecf20Sopenharmony_ci * This function is called when the 'verext' file is opened for write 5708c2ecf20Sopenharmony_ci */ 5718c2ecf20Sopenharmony_cistatic ssize_t 5728c2ecf20Sopenharmony_cimwifiex_verext_write(struct file *file, const char __user *ubuf, 5738c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 5748c2ecf20Sopenharmony_ci{ 5758c2ecf20Sopenharmony_ci int ret; 5768c2ecf20Sopenharmony_ci u32 versionstrsel; 5778c2ecf20Sopenharmony_ci struct mwifiex_private *priv = (void *)file->private_data; 5788c2ecf20Sopenharmony_ci char buf[16]; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci memset(buf, 0, sizeof(buf)); 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) 5838c2ecf20Sopenharmony_ci return -EFAULT; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci ret = kstrtou32(buf, 10, &versionstrsel); 5868c2ecf20Sopenharmony_ci if (ret) 5878c2ecf20Sopenharmony_ci return ret; 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci priv->versionstrsel = versionstrsel; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci return count; 5928c2ecf20Sopenharmony_ci} 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci/* Proc verext file read handler. 5958c2ecf20Sopenharmony_ci * This function is called when the 'verext' file is opened for reading 5968c2ecf20Sopenharmony_ci * This function can be used read driver exteneed verion string. 5978c2ecf20Sopenharmony_ci */ 5988c2ecf20Sopenharmony_cistatic ssize_t 5998c2ecf20Sopenharmony_cimwifiex_verext_read(struct file *file, char __user *ubuf, 6008c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 6018c2ecf20Sopenharmony_ci{ 6028c2ecf20Sopenharmony_ci struct mwifiex_private *priv = 6038c2ecf20Sopenharmony_ci (struct mwifiex_private *)file->private_data; 6048c2ecf20Sopenharmony_ci char buf[256]; 6058c2ecf20Sopenharmony_ci int ret; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci mwifiex_get_ver_ext(priv, priv->versionstrsel); 6088c2ecf20Sopenharmony_ci ret = snprintf(buf, sizeof(buf), "version string: %s\n", 6098c2ecf20Sopenharmony_ci priv->version_str); 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci return simple_read_from_buffer(ubuf, count, ppos, buf, ret); 6128c2ecf20Sopenharmony_ci} 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci/* Proc memrw file write handler. 6158c2ecf20Sopenharmony_ci * This function is called when the 'memrw' file is opened for writing 6168c2ecf20Sopenharmony_ci * This function can be used to write to a memory location. 6178c2ecf20Sopenharmony_ci */ 6188c2ecf20Sopenharmony_cistatic ssize_t 6198c2ecf20Sopenharmony_cimwifiex_memrw_write(struct file *file, const char __user *ubuf, size_t count, 6208c2ecf20Sopenharmony_ci loff_t *ppos) 6218c2ecf20Sopenharmony_ci{ 6228c2ecf20Sopenharmony_ci int ret; 6238c2ecf20Sopenharmony_ci char cmd; 6248c2ecf20Sopenharmony_ci struct mwifiex_ds_mem_rw mem_rw; 6258c2ecf20Sopenharmony_ci u16 cmd_action; 6268c2ecf20Sopenharmony_ci struct mwifiex_private *priv = (void *)file->private_data; 6278c2ecf20Sopenharmony_ci char *buf; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); 6308c2ecf20Sopenharmony_ci if (IS_ERR(buf)) 6318c2ecf20Sopenharmony_ci return PTR_ERR(buf); 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci ret = sscanf(buf, "%c %x %x", &cmd, &mem_rw.addr, &mem_rw.value); 6348c2ecf20Sopenharmony_ci if (ret != 3) { 6358c2ecf20Sopenharmony_ci ret = -EINVAL; 6368c2ecf20Sopenharmony_ci goto done; 6378c2ecf20Sopenharmony_ci } 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci if ((cmd == 'r') || (cmd == 'R')) { 6408c2ecf20Sopenharmony_ci cmd_action = HostCmd_ACT_GEN_GET; 6418c2ecf20Sopenharmony_ci mem_rw.value = 0; 6428c2ecf20Sopenharmony_ci } else if ((cmd == 'w') || (cmd == 'W')) { 6438c2ecf20Sopenharmony_ci cmd_action = HostCmd_ACT_GEN_SET; 6448c2ecf20Sopenharmony_ci } else { 6458c2ecf20Sopenharmony_ci ret = -EINVAL; 6468c2ecf20Sopenharmony_ci goto done; 6478c2ecf20Sopenharmony_ci } 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci memcpy(&priv->mem_rw, &mem_rw, sizeof(mem_rw)); 6508c2ecf20Sopenharmony_ci if (mwifiex_send_cmd(priv, HostCmd_CMD_MEM_ACCESS, cmd_action, 0, 6518c2ecf20Sopenharmony_ci &mem_rw, true)) 6528c2ecf20Sopenharmony_ci ret = -1; 6538c2ecf20Sopenharmony_ci else 6548c2ecf20Sopenharmony_ci ret = count; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_cidone: 6578c2ecf20Sopenharmony_ci kfree(buf); 6588c2ecf20Sopenharmony_ci return ret; 6598c2ecf20Sopenharmony_ci} 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci/* Proc memrw file read handler. 6628c2ecf20Sopenharmony_ci * This function is called when the 'memrw' file is opened for reading 6638c2ecf20Sopenharmony_ci * This function can be used to read from a memory location. 6648c2ecf20Sopenharmony_ci */ 6658c2ecf20Sopenharmony_cistatic ssize_t 6668c2ecf20Sopenharmony_cimwifiex_memrw_read(struct file *file, char __user *ubuf, 6678c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 6688c2ecf20Sopenharmony_ci{ 6698c2ecf20Sopenharmony_ci struct mwifiex_private *priv = (void *)file->private_data; 6708c2ecf20Sopenharmony_ci unsigned long addr = get_zeroed_page(GFP_KERNEL); 6718c2ecf20Sopenharmony_ci char *buf = (char *)addr; 6728c2ecf20Sopenharmony_ci int ret, pos = 0; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci if (!buf) 6758c2ecf20Sopenharmony_ci return -ENOMEM; 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci pos += snprintf(buf, PAGE_SIZE, "0x%x 0x%x\n", priv->mem_rw.addr, 6788c2ecf20Sopenharmony_ci priv->mem_rw.value); 6798c2ecf20Sopenharmony_ci ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci free_page(addr); 6828c2ecf20Sopenharmony_ci return ret; 6838c2ecf20Sopenharmony_ci} 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_cistatic u32 saved_offset = -1, saved_bytes = -1; 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci/* 6888c2ecf20Sopenharmony_ci * Proc rdeeprom file write handler. 6898c2ecf20Sopenharmony_ci * 6908c2ecf20Sopenharmony_ci * This function is called when the 'rdeeprom' file is opened for writing 6918c2ecf20Sopenharmony_ci * 6928c2ecf20Sopenharmony_ci * This function can be used to write to a RDEEPROM location. 6938c2ecf20Sopenharmony_ci */ 6948c2ecf20Sopenharmony_cistatic ssize_t 6958c2ecf20Sopenharmony_cimwifiex_rdeeprom_write(struct file *file, 6968c2ecf20Sopenharmony_ci const char __user *ubuf, size_t count, loff_t *ppos) 6978c2ecf20Sopenharmony_ci{ 6988c2ecf20Sopenharmony_ci char *buf; 6998c2ecf20Sopenharmony_ci int ret = 0; 7008c2ecf20Sopenharmony_ci int offset = -1, bytes = -1; 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); 7038c2ecf20Sopenharmony_ci if (IS_ERR(buf)) 7048c2ecf20Sopenharmony_ci return PTR_ERR(buf); 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci sscanf(buf, "%d %d", &offset, &bytes); 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci if (offset == -1 || bytes == -1) { 7098c2ecf20Sopenharmony_ci ret = -EINVAL; 7108c2ecf20Sopenharmony_ci goto done; 7118c2ecf20Sopenharmony_ci } else { 7128c2ecf20Sopenharmony_ci saved_offset = offset; 7138c2ecf20Sopenharmony_ci saved_bytes = bytes; 7148c2ecf20Sopenharmony_ci ret = count; 7158c2ecf20Sopenharmony_ci } 7168c2ecf20Sopenharmony_cidone: 7178c2ecf20Sopenharmony_ci kfree(buf); 7188c2ecf20Sopenharmony_ci return ret; 7198c2ecf20Sopenharmony_ci} 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci/* 7228c2ecf20Sopenharmony_ci * Proc rdeeprom read write handler. 7238c2ecf20Sopenharmony_ci * 7248c2ecf20Sopenharmony_ci * This function is called when the 'rdeeprom' file is opened for reading 7258c2ecf20Sopenharmony_ci * 7268c2ecf20Sopenharmony_ci * This function can be used to read from a RDEEPROM location. 7278c2ecf20Sopenharmony_ci */ 7288c2ecf20Sopenharmony_cistatic ssize_t 7298c2ecf20Sopenharmony_cimwifiex_rdeeprom_read(struct file *file, char __user *ubuf, 7308c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 7318c2ecf20Sopenharmony_ci{ 7328c2ecf20Sopenharmony_ci struct mwifiex_private *priv = 7338c2ecf20Sopenharmony_ci (struct mwifiex_private *) file->private_data; 7348c2ecf20Sopenharmony_ci unsigned long addr = get_zeroed_page(GFP_KERNEL); 7358c2ecf20Sopenharmony_ci char *buf = (char *) addr; 7368c2ecf20Sopenharmony_ci int pos, ret, i; 7378c2ecf20Sopenharmony_ci u8 value[MAX_EEPROM_DATA]; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci if (!buf) 7408c2ecf20Sopenharmony_ci return -ENOMEM; 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci if (saved_offset == -1) { 7438c2ecf20Sopenharmony_ci /* No command has been given */ 7448c2ecf20Sopenharmony_ci pos = snprintf(buf, PAGE_SIZE, "0"); 7458c2ecf20Sopenharmony_ci goto done; 7468c2ecf20Sopenharmony_ci } 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci /* Get command has been given */ 7498c2ecf20Sopenharmony_ci ret = mwifiex_eeprom_read(priv, (u16) saved_offset, 7508c2ecf20Sopenharmony_ci (u16) saved_bytes, value); 7518c2ecf20Sopenharmony_ci if (ret) { 7528c2ecf20Sopenharmony_ci ret = -EINVAL; 7538c2ecf20Sopenharmony_ci goto out_free; 7548c2ecf20Sopenharmony_ci } 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci pos = snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes); 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci for (i = 0; i < saved_bytes; i++) 7598c2ecf20Sopenharmony_ci pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]); 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_cidone: 7628c2ecf20Sopenharmony_ci ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); 7638c2ecf20Sopenharmony_ciout_free: 7648c2ecf20Sopenharmony_ci free_page(addr); 7658c2ecf20Sopenharmony_ci return ret; 7668c2ecf20Sopenharmony_ci} 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci/* Proc hscfg file write handler 7698c2ecf20Sopenharmony_ci * This function can be used to configure the host sleep parameters. 7708c2ecf20Sopenharmony_ci */ 7718c2ecf20Sopenharmony_cistatic ssize_t 7728c2ecf20Sopenharmony_cimwifiex_hscfg_write(struct file *file, const char __user *ubuf, 7738c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 7748c2ecf20Sopenharmony_ci{ 7758c2ecf20Sopenharmony_ci struct mwifiex_private *priv = (void *)file->private_data; 7768c2ecf20Sopenharmony_ci char *buf; 7778c2ecf20Sopenharmony_ci int ret, arg_num; 7788c2ecf20Sopenharmony_ci struct mwifiex_ds_hs_cfg hscfg; 7798c2ecf20Sopenharmony_ci int conditions = HS_CFG_COND_DEF; 7808c2ecf20Sopenharmony_ci u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF; 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci buf = memdup_user_nul(ubuf, min(count, (size_t)(PAGE_SIZE - 1))); 7838c2ecf20Sopenharmony_ci if (IS_ERR(buf)) 7848c2ecf20Sopenharmony_ci return PTR_ERR(buf); 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap); 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg)); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci if (arg_num > 3) { 7918c2ecf20Sopenharmony_ci mwifiex_dbg(priv->adapter, ERROR, 7928c2ecf20Sopenharmony_ci "Too many arguments\n"); 7938c2ecf20Sopenharmony_ci ret = -EINVAL; 7948c2ecf20Sopenharmony_ci goto done; 7958c2ecf20Sopenharmony_ci } 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci if (arg_num >= 1 && arg_num < 3) 7988c2ecf20Sopenharmony_ci mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET, 7998c2ecf20Sopenharmony_ci MWIFIEX_SYNC_CMD, &hscfg); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci if (arg_num) { 8028c2ecf20Sopenharmony_ci if (conditions == HS_CFG_CANCEL) { 8038c2ecf20Sopenharmony_ci mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD); 8048c2ecf20Sopenharmony_ci ret = count; 8058c2ecf20Sopenharmony_ci goto done; 8068c2ecf20Sopenharmony_ci } 8078c2ecf20Sopenharmony_ci hscfg.conditions = conditions; 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci if (arg_num >= 2) 8108c2ecf20Sopenharmony_ci hscfg.gpio = gpio; 8118c2ecf20Sopenharmony_ci if (arg_num == 3) 8128c2ecf20Sopenharmony_ci hscfg.gap = gap; 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci hscfg.is_invoke_hostcmd = false; 8158c2ecf20Sopenharmony_ci mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, 8168c2ecf20Sopenharmony_ci MWIFIEX_SYNC_CMD, &hscfg); 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci mwifiex_enable_hs(priv->adapter); 8198c2ecf20Sopenharmony_ci clear_bit(MWIFIEX_IS_HS_ENABLING, &priv->adapter->work_flags); 8208c2ecf20Sopenharmony_ci ret = count; 8218c2ecf20Sopenharmony_cidone: 8228c2ecf20Sopenharmony_ci kfree(buf); 8238c2ecf20Sopenharmony_ci return ret; 8248c2ecf20Sopenharmony_ci} 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci/* Proc hscfg file read handler 8278c2ecf20Sopenharmony_ci * This function can be used to read host sleep configuration 8288c2ecf20Sopenharmony_ci * parameters from driver. 8298c2ecf20Sopenharmony_ci */ 8308c2ecf20Sopenharmony_cistatic ssize_t 8318c2ecf20Sopenharmony_cimwifiex_hscfg_read(struct file *file, char __user *ubuf, 8328c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 8338c2ecf20Sopenharmony_ci{ 8348c2ecf20Sopenharmony_ci struct mwifiex_private *priv = (void *)file->private_data; 8358c2ecf20Sopenharmony_ci unsigned long addr = get_zeroed_page(GFP_KERNEL); 8368c2ecf20Sopenharmony_ci char *buf = (char *)addr; 8378c2ecf20Sopenharmony_ci int pos, ret; 8388c2ecf20Sopenharmony_ci struct mwifiex_ds_hs_cfg hscfg; 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci if (!buf) 8418c2ecf20Sopenharmony_ci return -ENOMEM; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET, 8448c2ecf20Sopenharmony_ci MWIFIEX_SYNC_CMD, &hscfg); 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci pos = snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", hscfg.conditions, 8478c2ecf20Sopenharmony_ci hscfg.gpio, hscfg.gap); 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci free_page(addr); 8528c2ecf20Sopenharmony_ci return ret; 8538c2ecf20Sopenharmony_ci} 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_cistatic ssize_t 8568c2ecf20Sopenharmony_cimwifiex_timeshare_coex_read(struct file *file, char __user *ubuf, 8578c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 8588c2ecf20Sopenharmony_ci{ 8598c2ecf20Sopenharmony_ci struct mwifiex_private *priv = file->private_data; 8608c2ecf20Sopenharmony_ci char buf[3]; 8618c2ecf20Sopenharmony_ci bool timeshare_coex; 8628c2ecf20Sopenharmony_ci int ret; 8638c2ecf20Sopenharmony_ci unsigned int len; 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15) 8668c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX, 8698c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_GET, 0, ×hare_coex, true); 8708c2ecf20Sopenharmony_ci if (ret) 8718c2ecf20Sopenharmony_ci return ret; 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci len = sprintf(buf, "%d\n", timeshare_coex); 8748c2ecf20Sopenharmony_ci return simple_read_from_buffer(ubuf, count, ppos, buf, len); 8758c2ecf20Sopenharmony_ci} 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_cistatic ssize_t 8788c2ecf20Sopenharmony_cimwifiex_timeshare_coex_write(struct file *file, const char __user *ubuf, 8798c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 8808c2ecf20Sopenharmony_ci{ 8818c2ecf20Sopenharmony_ci bool timeshare_coex; 8828c2ecf20Sopenharmony_ci struct mwifiex_private *priv = file->private_data; 8838c2ecf20Sopenharmony_ci char kbuf[16]; 8848c2ecf20Sopenharmony_ci int ret; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15) 8878c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci memset(kbuf, 0, sizeof(kbuf)); 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci if (copy_from_user(&kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, count))) 8928c2ecf20Sopenharmony_ci return -EFAULT; 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci if (strtobool(kbuf, ×hare_coex)) 8958c2ecf20Sopenharmony_ci return -EINVAL; 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX, 8988c2ecf20Sopenharmony_ci HostCmd_ACT_GEN_SET, 0, ×hare_coex, true); 8998c2ecf20Sopenharmony_ci if (ret) 9008c2ecf20Sopenharmony_ci return ret; 9018c2ecf20Sopenharmony_ci else 9028c2ecf20Sopenharmony_ci return count; 9038c2ecf20Sopenharmony_ci} 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_cistatic ssize_t 9068c2ecf20Sopenharmony_cimwifiex_reset_write(struct file *file, 9078c2ecf20Sopenharmony_ci const char __user *ubuf, size_t count, loff_t *ppos) 9088c2ecf20Sopenharmony_ci{ 9098c2ecf20Sopenharmony_ci struct mwifiex_private *priv = file->private_data; 9108c2ecf20Sopenharmony_ci struct mwifiex_adapter *adapter = priv->adapter; 9118c2ecf20Sopenharmony_ci bool result; 9128c2ecf20Sopenharmony_ci int rc; 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci rc = kstrtobool_from_user(ubuf, count, &result); 9158c2ecf20Sopenharmony_ci if (rc) 9168c2ecf20Sopenharmony_ci return rc; 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci if (!result) 9198c2ecf20Sopenharmony_ci return -EINVAL; 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci if (adapter->if_ops.card_reset) { 9228c2ecf20Sopenharmony_ci dev_info(adapter->dev, "Resetting per request\n"); 9238c2ecf20Sopenharmony_ci adapter->if_ops.card_reset(adapter); 9248c2ecf20Sopenharmony_ci } 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci return count; 9278c2ecf20Sopenharmony_ci} 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci#define MWIFIEX_DFS_ADD_FILE(name) do { \ 9308c2ecf20Sopenharmony_ci debugfs_create_file(#name, 0644, priv->dfs_dev_dir, priv, \ 9318c2ecf20Sopenharmony_ci &mwifiex_dfs_##name##_fops); \ 9328c2ecf20Sopenharmony_ci} while (0); 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci#define MWIFIEX_DFS_FILE_OPS(name) \ 9358c2ecf20Sopenharmony_cistatic const struct file_operations mwifiex_dfs_##name##_fops = { \ 9368c2ecf20Sopenharmony_ci .read = mwifiex_##name##_read, \ 9378c2ecf20Sopenharmony_ci .write = mwifiex_##name##_write, \ 9388c2ecf20Sopenharmony_ci .open = simple_open, \ 9398c2ecf20Sopenharmony_ci}; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci#define MWIFIEX_DFS_FILE_READ_OPS(name) \ 9428c2ecf20Sopenharmony_cistatic const struct file_operations mwifiex_dfs_##name##_fops = { \ 9438c2ecf20Sopenharmony_ci .read = mwifiex_##name##_read, \ 9448c2ecf20Sopenharmony_ci .open = simple_open, \ 9458c2ecf20Sopenharmony_ci}; 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci#define MWIFIEX_DFS_FILE_WRITE_OPS(name) \ 9488c2ecf20Sopenharmony_cistatic const struct file_operations mwifiex_dfs_##name##_fops = { \ 9498c2ecf20Sopenharmony_ci .write = mwifiex_##name##_write, \ 9508c2ecf20Sopenharmony_ci .open = simple_open, \ 9518c2ecf20Sopenharmony_ci}; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_ciMWIFIEX_DFS_FILE_READ_OPS(info); 9558c2ecf20Sopenharmony_ciMWIFIEX_DFS_FILE_READ_OPS(debug); 9568c2ecf20Sopenharmony_ciMWIFIEX_DFS_FILE_READ_OPS(getlog); 9578c2ecf20Sopenharmony_ciMWIFIEX_DFS_FILE_OPS(regrdwr); 9588c2ecf20Sopenharmony_ciMWIFIEX_DFS_FILE_OPS(rdeeprom); 9598c2ecf20Sopenharmony_ciMWIFIEX_DFS_FILE_OPS(memrw); 9608c2ecf20Sopenharmony_ciMWIFIEX_DFS_FILE_OPS(hscfg); 9618c2ecf20Sopenharmony_ciMWIFIEX_DFS_FILE_OPS(histogram); 9628c2ecf20Sopenharmony_ciMWIFIEX_DFS_FILE_OPS(debug_mask); 9638c2ecf20Sopenharmony_ciMWIFIEX_DFS_FILE_OPS(timeshare_coex); 9648c2ecf20Sopenharmony_ciMWIFIEX_DFS_FILE_WRITE_OPS(reset); 9658c2ecf20Sopenharmony_ciMWIFIEX_DFS_FILE_OPS(verext); 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci/* 9688c2ecf20Sopenharmony_ci * This function creates the debug FS directory structure and the files. 9698c2ecf20Sopenharmony_ci */ 9708c2ecf20Sopenharmony_civoid 9718c2ecf20Sopenharmony_cimwifiex_dev_debugfs_init(struct mwifiex_private *priv) 9728c2ecf20Sopenharmony_ci{ 9738c2ecf20Sopenharmony_ci if (!mwifiex_dfs_dir || !priv) 9748c2ecf20Sopenharmony_ci return; 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci priv->dfs_dev_dir = debugfs_create_dir(priv->netdev->name, 9778c2ecf20Sopenharmony_ci mwifiex_dfs_dir); 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ci if (!priv->dfs_dev_dir) 9808c2ecf20Sopenharmony_ci return; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci MWIFIEX_DFS_ADD_FILE(info); 9838c2ecf20Sopenharmony_ci MWIFIEX_DFS_ADD_FILE(debug); 9848c2ecf20Sopenharmony_ci MWIFIEX_DFS_ADD_FILE(getlog); 9858c2ecf20Sopenharmony_ci MWIFIEX_DFS_ADD_FILE(regrdwr); 9868c2ecf20Sopenharmony_ci MWIFIEX_DFS_ADD_FILE(rdeeprom); 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci MWIFIEX_DFS_ADD_FILE(memrw); 9898c2ecf20Sopenharmony_ci MWIFIEX_DFS_ADD_FILE(hscfg); 9908c2ecf20Sopenharmony_ci MWIFIEX_DFS_ADD_FILE(histogram); 9918c2ecf20Sopenharmony_ci MWIFIEX_DFS_ADD_FILE(debug_mask); 9928c2ecf20Sopenharmony_ci MWIFIEX_DFS_ADD_FILE(timeshare_coex); 9938c2ecf20Sopenharmony_ci MWIFIEX_DFS_ADD_FILE(reset); 9948c2ecf20Sopenharmony_ci MWIFIEX_DFS_ADD_FILE(verext); 9958c2ecf20Sopenharmony_ci} 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci/* 9988c2ecf20Sopenharmony_ci * This function removes the debug FS directory structure and the files. 9998c2ecf20Sopenharmony_ci */ 10008c2ecf20Sopenharmony_civoid 10018c2ecf20Sopenharmony_cimwifiex_dev_debugfs_remove(struct mwifiex_private *priv) 10028c2ecf20Sopenharmony_ci{ 10038c2ecf20Sopenharmony_ci if (!priv) 10048c2ecf20Sopenharmony_ci return; 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci debugfs_remove_recursive(priv->dfs_dev_dir); 10078c2ecf20Sopenharmony_ci} 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci/* 10108c2ecf20Sopenharmony_ci * This function creates the top level proc directory. 10118c2ecf20Sopenharmony_ci */ 10128c2ecf20Sopenharmony_civoid 10138c2ecf20Sopenharmony_cimwifiex_debugfs_init(void) 10148c2ecf20Sopenharmony_ci{ 10158c2ecf20Sopenharmony_ci if (!mwifiex_dfs_dir) 10168c2ecf20Sopenharmony_ci mwifiex_dfs_dir = debugfs_create_dir("mwifiex", NULL); 10178c2ecf20Sopenharmony_ci} 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci/* 10208c2ecf20Sopenharmony_ci * This function removes the top level proc directory. 10218c2ecf20Sopenharmony_ci */ 10228c2ecf20Sopenharmony_civoid 10238c2ecf20Sopenharmony_cimwifiex_debugfs_remove(void) 10248c2ecf20Sopenharmony_ci{ 10258c2ecf20Sopenharmony_ci debugfs_remove(mwifiex_dfs_dir); 10268c2ecf20Sopenharmony_ci} 1027