Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2014 Redpine Signals Inc.
0003  *
0004  * Permission to use, copy, modify, and/or distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 
0017 #include "rsi_debugfs.h"
0018 #include "rsi_sdio.h"
0019 
0020 /**
0021  * rsi_sdio_stats_read() - This function returns the sdio status of the driver.
0022  * @seq: Pointer to the sequence file structure.
0023  * @data: Pointer to the data.
0024  *
0025  * Return: 0 on success, -1 on failure.
0026  */
0027 static int rsi_sdio_stats_read(struct seq_file *seq, void *data)
0028 {
0029     struct rsi_common *common = seq->private;
0030     struct rsi_hw *adapter = common->priv;
0031     struct rsi_91x_sdiodev *dev =
0032         (struct rsi_91x_sdiodev *)adapter->rsi_dev;
0033 
0034     seq_printf(seq, "total_sdio_interrupts: %d\n",
0035            dev->rx_info.sdio_int_counter);
0036     seq_printf(seq, "sdio_msdu_pending_intr_count: %d\n",
0037            dev->rx_info.total_sdio_msdu_pending_intr);
0038     seq_printf(seq, "sdio_buff_full_count : %d\n",
0039            dev->rx_info.buf_full_counter);
0040     seq_printf(seq, "sdio_buf_semi_full_count %d\n",
0041            dev->rx_info.buf_semi_full_counter);
0042     seq_printf(seq, "sdio_unknown_intr_count: %d\n",
0043            dev->rx_info.total_sdio_unknown_intr);
0044     /* RX Path Stats */
0045     seq_printf(seq, "BUFFER FULL STATUS  : %d\n",
0046            dev->rx_info.buffer_full);
0047     seq_printf(seq, "SEMI BUFFER FULL STATUS  : %d\n",
0048            dev->rx_info.semi_buffer_full);
0049     seq_printf(seq, "MGMT BUFFER FULL STATUS  : %d\n",
0050            dev->rx_info.mgmt_buffer_full);
0051     seq_printf(seq, "BUFFER FULL COUNTER  : %d\n",
0052            dev->rx_info.buf_full_counter);
0053     seq_printf(seq, "BUFFER SEMI FULL COUNTER  : %d\n",
0054            dev->rx_info.buf_semi_full_counter);
0055     seq_printf(seq, "MGMT BUFFER FULL COUNTER  : %d\n",
0056            dev->rx_info.mgmt_buf_full_counter);
0057 
0058     return 0;
0059 }
0060 
0061 /**
0062  * rsi_sdio_stats_open() - This function calls single open function of seq_file
0063  *             to open file and read contents from it.
0064  * @inode: Pointer to the inode structure.
0065  * @file: Pointer to the file structure.
0066  *
0067  * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
0068  */
0069 static int rsi_sdio_stats_open(struct inode *inode,
0070                    struct file *file)
0071 {
0072     return single_open(file, rsi_sdio_stats_read, inode->i_private);
0073 }
0074 
0075 /**
0076  * rsi_version_read() - This function gives driver and firmware version number.
0077  * @seq: Pointer to the sequence file structure.
0078  * @data: Pointer to the data.
0079  *
0080  * Return: 0 on success, -1 on failure.
0081  */
0082 static int rsi_version_read(struct seq_file *seq, void *data)
0083 {
0084     struct rsi_common *common = seq->private;
0085 
0086     seq_printf(seq, "LMAC   : %d.%d.%d.%d\n",
0087            common->lmac_ver.major,
0088            common->lmac_ver.minor,
0089            common->lmac_ver.release_num,
0090            common->lmac_ver.patch_num);
0091 
0092     return 0;
0093 }
0094 
0095 /**
0096  * rsi_version_open() - This function calls single open function of seq_file to
0097  *          open file and read contents from it.
0098  * @inode: Pointer to the inode structure.
0099  * @file: Pointer to the file structure.
0100  *
0101  * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
0102  */
0103 static int rsi_version_open(struct inode *inode,
0104                  struct file *file)
0105 {
0106     return single_open(file, rsi_version_read, inode->i_private);
0107 }
0108 
0109 /**
0110  * rsi_stats_read() - This function return the status of the driver.
0111  * @seq: Pointer to the sequence file structure.
0112  * @data: Pointer to the data.
0113  *
0114  * Return: 0 on success, -1 on failure.
0115  */
0116 static int rsi_stats_read(struct seq_file *seq, void *data)
0117 {
0118     struct rsi_common *common = seq->private;
0119 
0120     static const unsigned char fsm_state[][32] = {
0121         "FSM_FW_NOT_LOADED",
0122         "FSM_CARD_NOT_READY",
0123         "FSM_COMMON_DEV_PARAMS_SENT",
0124         "FSM_BOOT_PARAMS_SENT",
0125         "FSM_EEPROM_READ_MAC_ADDR",
0126         "FSM_EEPROM_READ_RF_TYPE",
0127         "FSM_RESET_MAC_SENT",
0128         "FSM_RADIO_CAPS_SENT",
0129         "FSM_BB_RF_PROG_SENT",
0130         "FSM_MAC_INIT_DONE"
0131     };
0132     seq_puts(seq, "==> RSI STA DRIVER STATUS <==\n");
0133     seq_puts(seq, "DRIVER_FSM_STATE: ");
0134 
0135     BUILD_BUG_ON(ARRAY_SIZE(fsm_state) != NUM_FSM_STATES);
0136 
0137     if (common->fsm_state <= FSM_MAC_INIT_DONE)
0138         seq_printf(seq, "%s", fsm_state[common->fsm_state]);
0139 
0140     seq_printf(seq, "(%d)\n\n", common->fsm_state);
0141 
0142     /* Mgmt TX Path Stats */
0143     seq_printf(seq, "total_mgmt_pkt_send : %d\n",
0144            common->tx_stats.total_tx_pkt_send[MGMT_SOFT_Q]);
0145     seq_printf(seq, "total_mgmt_pkt_queued : %d\n",
0146            skb_queue_len(&common->tx_queue[MGMT_SOFT_Q]));
0147     seq_printf(seq, "total_mgmt_pkt_freed  : %d\n",
0148            common->tx_stats.total_tx_pkt_freed[MGMT_SOFT_Q]);
0149 
0150     /* Data TX Path Stats */
0151     seq_printf(seq, "total_data_vo_pkt_send: %8d\t",
0152            common->tx_stats.total_tx_pkt_send[VO_Q]);
0153     seq_printf(seq, "total_data_vo_pkt_queued:  %8d\t",
0154            skb_queue_len(&common->tx_queue[VO_Q]));
0155     seq_printf(seq, "total_vo_pkt_freed: %8d\n",
0156            common->tx_stats.total_tx_pkt_freed[VO_Q]);
0157     seq_printf(seq, "total_data_vi_pkt_send: %8d\t",
0158            common->tx_stats.total_tx_pkt_send[VI_Q]);
0159     seq_printf(seq, "total_data_vi_pkt_queued:  %8d\t",
0160            skb_queue_len(&common->tx_queue[VI_Q]));
0161     seq_printf(seq, "total_vi_pkt_freed: %8d\n",
0162            common->tx_stats.total_tx_pkt_freed[VI_Q]);
0163     seq_printf(seq,  "total_data_be_pkt_send: %8d\t",
0164            common->tx_stats.total_tx_pkt_send[BE_Q]);
0165     seq_printf(seq, "total_data_be_pkt_queued:  %8d\t",
0166            skb_queue_len(&common->tx_queue[BE_Q]));
0167     seq_printf(seq, "total_be_pkt_freed: %8d\n",
0168            common->tx_stats.total_tx_pkt_freed[BE_Q]);
0169     seq_printf(seq, "total_data_bk_pkt_send: %8d\t",
0170            common->tx_stats.total_tx_pkt_send[BK_Q]);
0171     seq_printf(seq, "total_data_bk_pkt_queued:  %8d\t",
0172            skb_queue_len(&common->tx_queue[BK_Q]));
0173     seq_printf(seq, "total_bk_pkt_freed: %8d\n",
0174            common->tx_stats.total_tx_pkt_freed[BK_Q]);
0175 
0176     seq_puts(seq, "\n");
0177     return 0;
0178 }
0179 
0180 /**
0181  * rsi_stats_open() - This function calls single open function of seq_file to
0182  *            open file and read contents from it.
0183  * @inode: Pointer to the inode structure.
0184  * @file: Pointer to the file structure.
0185  *
0186  * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
0187  */
0188 static int rsi_stats_open(struct inode *inode,
0189               struct file *file)
0190 {
0191     return single_open(file, rsi_stats_read, inode->i_private);
0192 }
0193 
0194 /**
0195  * rsi_debug_zone_read() - This function display the currently enabled debug zones.
0196  * @seq: Pointer to the sequence file structure.
0197  * @data: Pointer to the data.
0198  *
0199  * Return: 0 on success, -1 on failure.
0200  */
0201 static int rsi_debug_zone_read(struct seq_file *seq, void *data)
0202 {
0203     rsi_dbg(FSM_ZONE, "%x: rsi_enabled zone", rsi_zone_enabled);
0204     seq_printf(seq, "The zones available are %#x\n",
0205            rsi_zone_enabled);
0206     return 0;
0207 }
0208 
0209 /**
0210  * rsi_debug_read() - This function calls single open function of seq_file to
0211  *            open file and read contents from it.
0212  * @inode: Pointer to the inode structure.
0213  * @file: Pointer to the file structure.
0214  *
0215  * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
0216  */
0217 static int rsi_debug_read(struct inode *inode,
0218               struct file *file)
0219 {
0220     return single_open(file, rsi_debug_zone_read, inode->i_private);
0221 }
0222 
0223 /**
0224  * rsi_debug_zone_write() - This function writes into hal queues as per user
0225  *              requirement.
0226  * @filp: Pointer to the file structure.
0227  * @buff: Pointer to the character buffer.
0228  * @len: Length of the data to be written into buffer.
0229  * @data: Pointer to the data.
0230  *
0231  * Return: len: Number of bytes read.
0232  */
0233 static ssize_t rsi_debug_zone_write(struct file *filp,
0234                     const char __user *buff,
0235                     size_t len,
0236                     loff_t *data)
0237 {
0238     unsigned long dbg_zone;
0239     int ret;
0240 
0241     if (!len)
0242         return 0;
0243 
0244     ret = kstrtoul_from_user(buff, len, 16, &dbg_zone);
0245 
0246     if (ret)
0247         return ret;
0248 
0249     rsi_zone_enabled = dbg_zone;
0250     return len;
0251 }
0252 
0253 #define FOPS(fopen) { \
0254     .owner = THIS_MODULE, \
0255     .open = (fopen), \
0256     .read = seq_read, \
0257     .llseek = seq_lseek, \
0258 }
0259 
0260 #define FOPS_RW(fopen, fwrite) { \
0261     .owner = THIS_MODULE, \
0262     .open = (fopen), \
0263     .read = seq_read, \
0264     .llseek = seq_lseek, \
0265     .write = (fwrite), \
0266 }
0267 
0268 static const struct rsi_dbg_files dev_debugfs_files[] = {
0269     {"version", 0644, FOPS(rsi_version_open),},
0270     {"stats", 0644, FOPS(rsi_stats_open),},
0271     {"debug_zone", 0666, FOPS_RW(rsi_debug_read, rsi_debug_zone_write),},
0272     {"sdio_stats", 0644, FOPS(rsi_sdio_stats_open),},
0273 };
0274 
0275 /**
0276  * rsi_init_dbgfs() - This function initializes the dbgfs entry.
0277  * @adapter: Pointer to the adapter structure.
0278  *
0279  * Return: 0 on success, -1 on failure.
0280  */
0281 int rsi_init_dbgfs(struct rsi_hw *adapter)
0282 {
0283     struct rsi_common *common = adapter->priv;
0284     struct rsi_debugfs *dev_dbgfs;
0285     char devdir[6];
0286     int ii;
0287     const struct rsi_dbg_files *files;
0288 
0289     dev_dbgfs = kzalloc(sizeof(*dev_dbgfs), GFP_KERNEL);
0290     if (!dev_dbgfs)
0291         return -ENOMEM;
0292 
0293     adapter->dfsentry = dev_dbgfs;
0294 
0295     snprintf(devdir, sizeof(devdir), "%s",
0296          wiphy_name(adapter->hw->wiphy));
0297 
0298     dev_dbgfs->subdir = debugfs_create_dir(devdir, NULL);
0299 
0300     for (ii = 0; ii < adapter->num_debugfs_entries; ii++) {
0301         files = &dev_debugfs_files[ii];
0302         dev_dbgfs->rsi_files[ii] =
0303         debugfs_create_file(files->name,
0304                     files->perms,
0305                     dev_dbgfs->subdir,
0306                     common,
0307                     &files->fops);
0308     }
0309     return 0;
0310 }
0311 EXPORT_SYMBOL_GPL(rsi_init_dbgfs);
0312 
0313 /**
0314  * rsi_remove_dbgfs() - Removes the previously created dbgfs file entries
0315  *          in the reverse order of creation.
0316  * @adapter: Pointer to the adapter structure.
0317  *
0318  * Return: None.
0319  */
0320 void rsi_remove_dbgfs(struct rsi_hw *adapter)
0321 {
0322     struct rsi_debugfs *dev_dbgfs = adapter->dfsentry;
0323 
0324     if (!dev_dbgfs)
0325         return;
0326 
0327     debugfs_remove_recursive(dev_dbgfs->subdir);
0328 }
0329 EXPORT_SYMBOL_GPL(rsi_remove_dbgfs);