linux/drivers/net/wireless/rsi/rsi_91x_debugfs.c
<<
>>
Prefs
   1/**
   2 * Copyright (c) 2014 Redpine Signals Inc.
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17#include "rsi_debugfs.h"
  18#include "rsi_sdio.h"
  19
  20/**
  21 * rsi_sdio_stats_read() - This function returns the sdio status of the driver.
  22 * @seq: Pointer to the sequence file structure.
  23 * @data: Pointer to the data.
  24 *
  25 * Return: 0 on success, -1 on failure.
  26 */
  27static int rsi_sdio_stats_read(struct seq_file *seq, void *data)
  28{
  29        struct rsi_common *common = seq->private;
  30        struct rsi_hw *adapter = common->priv;
  31        struct rsi_91x_sdiodev *dev =
  32                (struct rsi_91x_sdiodev *)adapter->rsi_dev;
  33
  34        seq_printf(seq, "total_sdio_interrupts: %d\n",
  35                   dev->rx_info.sdio_int_counter);
  36        seq_printf(seq, "sdio_msdu_pending_intr_count: %d\n",
  37                   dev->rx_info.total_sdio_msdu_pending_intr);
  38        seq_printf(seq, "sdio_buff_full_count : %d\n",
  39                   dev->rx_info.buf_full_counter);
  40        seq_printf(seq, "sdio_buf_semi_full_count %d\n",
  41                   dev->rx_info.buf_semi_full_counter);
  42        seq_printf(seq, "sdio_unknown_intr_count: %d\n",
  43                   dev->rx_info.total_sdio_unknown_intr);
  44        /* RX Path Stats */
  45        seq_printf(seq, "BUFFER FULL STATUS  : %d\n",
  46                   dev->rx_info.buffer_full);
  47        seq_printf(seq, "SEMI BUFFER FULL STATUS  : %d\n",
  48                   dev->rx_info.semi_buffer_full);
  49        seq_printf(seq, "MGMT BUFFER FULL STATUS  : %d\n",
  50                   dev->rx_info.mgmt_buffer_full);
  51        seq_printf(seq, "BUFFER FULL COUNTER  : %d\n",
  52                   dev->rx_info.buf_full_counter);
  53        seq_printf(seq, "BUFFER SEMI FULL COUNTER  : %d\n",
  54                   dev->rx_info.buf_semi_full_counter);
  55        seq_printf(seq, "MGMT BUFFER FULL COUNTER  : %d\n",
  56                   dev->rx_info.mgmt_buf_full_counter);
  57
  58        return 0;
  59}
  60
  61/**
  62 * rsi_sdio_stats_open() - This funtion calls single open function of seq_file
  63 *                         to open file and read contents from it.
  64 * @inode: Pointer to the inode structure.
  65 * @file: Pointer to the file structure.
  66 *
  67 * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
  68 */
  69static int rsi_sdio_stats_open(struct inode *inode,
  70                               struct file *file)
  71{
  72        return single_open(file, rsi_sdio_stats_read, inode->i_private);
  73}
  74
  75/**
  76 * rsi_version_read() - This function gives driver and firmware version number.
  77 * @seq: Pointer to the sequence file structure.
  78 * @data: Pointer to the data.
  79 *
  80 * Return: 0 on success, -1 on failure.
  81 */
  82static int rsi_version_read(struct seq_file *seq, void *data)
  83{
  84        struct rsi_common *common = seq->private;
  85
  86        common->driver_ver.major = 0;
  87        common->driver_ver.minor = 1;
  88        common->driver_ver.release_num = 0;
  89        common->driver_ver.patch_num = 0;
  90        seq_printf(seq, "Driver : %x.%d.%d.%d\nLMAC   : %d.%d.%d.%d\n",
  91                   common->driver_ver.major,
  92                   common->driver_ver.minor,
  93                   common->driver_ver.release_num,
  94                   common->driver_ver.patch_num,
  95                   common->fw_ver.major,
  96                   common->fw_ver.minor,
  97                   common->fw_ver.release_num,
  98                   common->fw_ver.patch_num);
  99        return 0;
 100}
 101
 102/**
 103 * rsi_version_open() - This funtion calls single open function of seq_file to
 104 *                      open file and read contents from it.
 105 * @inode: Pointer to the inode structure.
 106 * @file: Pointer to the file structure.
 107 *
 108 * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
 109 */
 110static int rsi_version_open(struct inode *inode,
 111                                 struct file *file)
 112{
 113        return single_open(file, rsi_version_read, inode->i_private);
 114}
 115
 116/**
 117 * rsi_stats_read() - This function return the status of the driver.
 118 * @seq: Pointer to the sequence file structure.
 119 * @data: Pointer to the data.
 120 *
 121 * Return: 0 on success, -1 on failure.
 122 */
 123static int rsi_stats_read(struct seq_file *seq, void *data)
 124{
 125        struct rsi_common *common = seq->private;
 126
 127        unsigned char fsm_state[][32] = {
 128                "FSM_FW_NOT_LOADED",
 129                "FSM_CARD_NOT_READY",
 130                "FSM_COMMON_DEV_PARAMS_SENT",
 131                "FSM_BOOT_PARAMS_SENT",
 132                "FSM_EEPROM_READ_MAC_ADDR",
 133                "FSM_RESET_MAC_SENT",
 134                "FSM_RADIO_CAPS_SENT",
 135                "FSM_BB_RF_PROG_SENT",
 136                "FSM_MAC_INIT_DONE"
 137        };
 138        seq_puts(seq, "==> RSI STA DRIVER STATUS <==\n");
 139        seq_puts(seq, "DRIVER_FSM_STATE: ");
 140
 141        if (common->fsm_state <= FSM_MAC_INIT_DONE)
 142                seq_printf(seq, "%s", fsm_state[common->fsm_state]);
 143
 144        seq_printf(seq, "(%d)\n\n", common->fsm_state);
 145
 146        /* Mgmt TX Path Stats */
 147        seq_printf(seq, "total_mgmt_pkt_send : %d\n",
 148                   common->tx_stats.total_tx_pkt_send[MGMT_SOFT_Q]);
 149        seq_printf(seq, "total_mgmt_pkt_queued : %d\n",
 150                   skb_queue_len(&common->tx_queue[MGMT_SOFT_Q]));
 151        seq_printf(seq, "total_mgmt_pkt_freed  : %d\n",
 152                   common->tx_stats.total_tx_pkt_freed[MGMT_SOFT_Q]);
 153
 154        /* Data TX Path Stats */
 155        seq_printf(seq, "total_data_vo_pkt_send: %8d\t",
 156                   common->tx_stats.total_tx_pkt_send[VO_Q]);
 157        seq_printf(seq, "total_data_vo_pkt_queued:  %8d\t",
 158                   skb_queue_len(&common->tx_queue[VO_Q]));
 159        seq_printf(seq, "total_vo_pkt_freed: %8d\n",
 160                   common->tx_stats.total_tx_pkt_freed[VO_Q]);
 161        seq_printf(seq, "total_data_vi_pkt_send: %8d\t",
 162                   common->tx_stats.total_tx_pkt_send[VI_Q]);
 163        seq_printf(seq, "total_data_vi_pkt_queued:  %8d\t",
 164                   skb_queue_len(&common->tx_queue[VI_Q]));
 165        seq_printf(seq, "total_vi_pkt_freed: %8d\n",
 166                   common->tx_stats.total_tx_pkt_freed[VI_Q]);
 167        seq_printf(seq,  "total_data_be_pkt_send: %8d\t",
 168                   common->tx_stats.total_tx_pkt_send[BE_Q]);
 169        seq_printf(seq, "total_data_be_pkt_queued:  %8d\t",
 170                   skb_queue_len(&common->tx_queue[BE_Q]));
 171        seq_printf(seq, "total_be_pkt_freed: %8d\n",
 172                   common->tx_stats.total_tx_pkt_freed[BE_Q]);
 173        seq_printf(seq, "total_data_bk_pkt_send: %8d\t",
 174                   common->tx_stats.total_tx_pkt_send[BK_Q]);
 175        seq_printf(seq, "total_data_bk_pkt_queued:  %8d\t",
 176                   skb_queue_len(&common->tx_queue[BK_Q]));
 177        seq_printf(seq, "total_bk_pkt_freed: %8d\n",
 178                   common->tx_stats.total_tx_pkt_freed[BK_Q]);
 179
 180        seq_puts(seq, "\n");
 181        return 0;
 182}
 183
 184/**
 185 * rsi_stats_open() - This funtion calls single open function of seq_file to
 186 *                    open file and read contents from it.
 187 * @inode: Pointer to the inode structure.
 188 * @file: Pointer to the file structure.
 189 *
 190 * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
 191 */
 192static int rsi_stats_open(struct inode *inode,
 193                          struct file *file)
 194{
 195        return single_open(file, rsi_stats_read, inode->i_private);
 196}
 197
 198/**
 199 * rsi_debug_zone_read() - This function display the currently enabled debug zones.
 200 * @seq: Pointer to the sequence file structure.
 201 * @data: Pointer to the data.
 202 *
 203 * Return: 0 on success, -1 on failure.
 204 */
 205static int rsi_debug_zone_read(struct seq_file *seq, void *data)
 206{
 207        rsi_dbg(FSM_ZONE, "%x: rsi_enabled zone", rsi_zone_enabled);
 208        seq_printf(seq, "The zones available are %#x\n",
 209                   rsi_zone_enabled);
 210        return 0;
 211}
 212
 213/**
 214 * rsi_debug_read() - This funtion calls single open function of seq_file to
 215 *                    open file and read contents from it.
 216 * @inode: Pointer to the inode structure.
 217 * @file: Pointer to the file structure.
 218 *
 219 * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
 220 */
 221static int rsi_debug_read(struct inode *inode,
 222                          struct file *file)
 223{
 224        return single_open(file, rsi_debug_zone_read, inode->i_private);
 225}
 226
 227/**
 228 * rsi_debug_zone_write() - This function writes into hal queues as per user
 229 *                          requirement.
 230 * @filp: Pointer to the file structure.
 231 * @buff: Pointer to the character buffer.
 232 * @len: Length of the data to be written into buffer.
 233 * @data: Pointer to the data.
 234 *
 235 * Return: len: Number of bytes read.
 236 */
 237static ssize_t rsi_debug_zone_write(struct file *filp,
 238                                    const char __user *buff,
 239                                    size_t len,
 240                                    loff_t *data)
 241{
 242        unsigned long dbg_zone;
 243        int ret;
 244
 245        if (!len)
 246                return 0;
 247
 248        ret = kstrtoul_from_user(buff, len, 16, &dbg_zone);
 249
 250        if (ret)
 251                return ret;
 252
 253        rsi_zone_enabled = dbg_zone;
 254        return len;
 255}
 256
 257#define FOPS(fopen) { \
 258        .owner = THIS_MODULE, \
 259        .open = (fopen), \
 260        .read = seq_read, \
 261        .llseek = seq_lseek, \
 262}
 263
 264#define FOPS_RW(fopen, fwrite) { \
 265        .owner = THIS_MODULE, \
 266        .open = (fopen), \
 267        .read = seq_read, \
 268        .llseek = seq_lseek, \
 269        .write = (fwrite), \
 270}
 271
 272static const struct rsi_dbg_files dev_debugfs_files[] = {
 273        {"version", 0644, FOPS(rsi_version_open),},
 274        {"stats", 0644, FOPS(rsi_stats_open),},
 275        {"debug_zone", 0666, FOPS_RW(rsi_debug_read, rsi_debug_zone_write),},
 276        {"sdio_stats", 0644, FOPS(rsi_sdio_stats_open),},
 277};
 278
 279/**
 280 * rsi_init_dbgfs() - This function initializes the dbgfs entry.
 281 * @adapter: Pointer to the adapter structure.
 282 *
 283 * Return: 0 on success, -1 on failure.
 284 */
 285int rsi_init_dbgfs(struct rsi_hw *adapter)
 286{
 287        struct rsi_common *common = adapter->priv;
 288        struct rsi_debugfs *dev_dbgfs;
 289        char devdir[6];
 290        int ii;
 291        const struct rsi_dbg_files *files;
 292
 293        dev_dbgfs = kzalloc(sizeof(*dev_dbgfs), GFP_KERNEL);
 294        if (!dev_dbgfs)
 295                return -ENOMEM;
 296
 297        adapter->dfsentry = dev_dbgfs;
 298
 299        snprintf(devdir, sizeof(devdir), "%s",
 300                 wiphy_name(adapter->hw->wiphy));
 301
 302        dev_dbgfs->subdir = debugfs_create_dir(devdir, NULL);
 303
 304        if (!dev_dbgfs->subdir) {
 305                kfree(dev_dbgfs);
 306                return -ENOMEM;
 307        }
 308
 309        for (ii = 0; ii < adapter->num_debugfs_entries; ii++) {
 310                files = &dev_debugfs_files[ii];
 311                dev_dbgfs->rsi_files[ii] =
 312                debugfs_create_file(files->name,
 313                                    files->perms,
 314                                    dev_dbgfs->subdir,
 315                                    common,
 316                                    &files->fops);
 317        }
 318        return 0;
 319}
 320EXPORT_SYMBOL_GPL(rsi_init_dbgfs);
 321
 322/**
 323 * rsi_remove_dbgfs() - Removes the previously created dbgfs file entries
 324 *                      in the reverse order of creation.
 325 * @adapter: Pointer to the adapter structure.
 326 *
 327 * Return: None.
 328 */
 329void rsi_remove_dbgfs(struct rsi_hw *adapter)
 330{
 331        struct rsi_debugfs *dev_dbgfs = adapter->dfsentry;
 332
 333        if (!dev_dbgfs)
 334                return;
 335
 336        debugfs_remove_recursive(dev_dbgfs->subdir);
 337}
 338EXPORT_SYMBOL_GPL(rsi_remove_dbgfs);
 339