// SPDX-License-Identifier: GPL-2.0-only
/*
* NXP Wireless LAN device driver: debugfs
*
* Copyright 2011-2020 NXP
*/
#include <linux/debugfs.h>
#include "main.h"
#include "11n.h"
static struct dentry *mwifiex_dfs_dir;
static char *bss_modes[] = {
"UNSPECIFIED",
"ADHOC",
"STATION",
"AP",
"AP_VLAN",
"WDS",
"MONITOR",
"MESH_POINT",
"P2P_CLIENT",
"P2P_GO",
"P2P_DEVICE",
};
/*
* Proc info file read handler.
*
* This function is called when the 'info' file is opened for reading.
* It prints the following driver related information -
* - Driver name
* - Driver version
* - Driver extended version
* - Interface name
* - BSS mode
* - Media state (connected or disconnected)
* - MAC address
* - Total number of Tx bytes
* - Total number of Rx bytes
* - Total number of Tx packets
* - Total number of Rx packets
* - Total number of dropped Tx packets
* - Total number of dropped Rx packets
* - Total number of corrupted Tx packets
* - Total number of corrupted Rx packets
* - Carrier status (on or off)
* - Tx queue status (started or stopped)
*
* For STA mode drivers, it also prints the following extra -
* - ESSID
* - BSSID
* - Channel
* - Region code
* - Multicast count
* - Multicast addresses
*/
static ssize_t
mwifiex_info_read(struct file *file, char __user *ubuf,
size_t count, loff_t *ppos)
{
struct mwifiex_private *priv =
(struct mwifiex_private *) file->private_data;
struct net_device *netdev = priv->netdev;
struct netdev_hw_addr *ha;
struct netdev_queue *txq;
unsigned long page = get_zeroed_page(GFP_KERNEL);
char *p = (char *) page, fmt[64];
struct mwifiex_bss_info info;
ssize_t ret;
int i = 0;
if (!p)
return -ENOMEM;
memset(&info, 0, sizeof(info));
ret = mwifiex_get_bss_info(priv, &info);
if (ret)
goto free_and_exit;
mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1);
mwifiex_get_ver_ext(priv, 0);
p += sprintf(p, "driver_name = " "\"mwifiex\"\n");
p += sprintf(p, "driver_version = %s", fmt);
p += sprintf(p, "\nverext = %s", priv->version_str);
p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name);
if (info.bss_mode >= ARRAY_SIZE(bss_modes))
p += sprintf(p, "bss_mode=\"%d\"\n", info.bss_mode);
else
p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]);
p += sprintf(p, "media_state=\"%s\"\n",
(!priv->media_connected ? "Disconnected" : "Connected"));
p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr);
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
p += sprintf(p, "multicast_count=\"%d\"\n",
netdev_mc_count(netdev));
p += sprintf(p, "essid=\"%.*s\"\n", info.ssid.ssid_len,
info.ssid.ssid);
p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
p += sprintf(p, "country_code = \"%s\"\n", info.country_code);
p += sprintf(p, "region_code=\"0x%x\"\n",
priv->adapter->region_code);
netdev_for_each_mc_addr(ha, netdev)
p += sprintf(p, "multicast_address[%d]=\"%pM\"\n",
i++, ha->addr);
}
p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev))
? "on" : "off"));
p += sprintf(p, "tx queue");
for (i = 0; i < netdev->num_tx_queues; i++) {
txq = netdev_get_tx_queue(netdev, i);
p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ?
"stopped" : "started");
}
p += sprintf(p, "\n");
ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
(unsigned long) p - page);
free_and_exit:
free_page(page);
return ret