162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2014 Redpine Signals Inc. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 562306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 662306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 962306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1062306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1162306a36Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1262306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1362306a36Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1462306a36Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include "rsi_debugfs.h" 1862306a36Sopenharmony_ci#include "rsi_sdio.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/** 2162306a36Sopenharmony_ci * rsi_sdio_stats_read() - This function returns the sdio status of the driver. 2262306a36Sopenharmony_ci * @seq: Pointer to the sequence file structure. 2362306a36Sopenharmony_ci * @data: Pointer to the data. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * Return: 0 on success, -1 on failure. 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_cistatic int rsi_sdio_stats_read(struct seq_file *seq, void *data) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci struct rsi_common *common = seq->private; 3062306a36Sopenharmony_ci struct rsi_hw *adapter = common->priv; 3162306a36Sopenharmony_ci struct rsi_91x_sdiodev *dev = adapter->rsi_dev; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci seq_printf(seq, "total_sdio_interrupts: %d\n", 3462306a36Sopenharmony_ci dev->rx_info.sdio_int_counter); 3562306a36Sopenharmony_ci seq_printf(seq, "sdio_msdu_pending_intr_count: %d\n", 3662306a36Sopenharmony_ci dev->rx_info.total_sdio_msdu_pending_intr); 3762306a36Sopenharmony_ci seq_printf(seq, "sdio_buff_full_count : %d\n", 3862306a36Sopenharmony_ci dev->rx_info.buf_full_counter); 3962306a36Sopenharmony_ci seq_printf(seq, "sdio_buf_semi_full_count %d\n", 4062306a36Sopenharmony_ci dev->rx_info.buf_semi_full_counter); 4162306a36Sopenharmony_ci seq_printf(seq, "sdio_unknown_intr_count: %d\n", 4262306a36Sopenharmony_ci dev->rx_info.total_sdio_unknown_intr); 4362306a36Sopenharmony_ci /* RX Path Stats */ 4462306a36Sopenharmony_ci seq_printf(seq, "BUFFER FULL STATUS : %d\n", 4562306a36Sopenharmony_ci dev->rx_info.buffer_full); 4662306a36Sopenharmony_ci seq_printf(seq, "SEMI BUFFER FULL STATUS : %d\n", 4762306a36Sopenharmony_ci dev->rx_info.semi_buffer_full); 4862306a36Sopenharmony_ci seq_printf(seq, "MGMT BUFFER FULL STATUS : %d\n", 4962306a36Sopenharmony_ci dev->rx_info.mgmt_buffer_full); 5062306a36Sopenharmony_ci seq_printf(seq, "BUFFER FULL COUNTER : %d\n", 5162306a36Sopenharmony_ci dev->rx_info.buf_full_counter); 5262306a36Sopenharmony_ci seq_printf(seq, "BUFFER SEMI FULL COUNTER : %d\n", 5362306a36Sopenharmony_ci dev->rx_info.buf_semi_full_counter); 5462306a36Sopenharmony_ci seq_printf(seq, "MGMT BUFFER FULL COUNTER : %d\n", 5562306a36Sopenharmony_ci dev->rx_info.mgmt_buf_full_counter); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci return 0; 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/** 6162306a36Sopenharmony_ci * rsi_sdio_stats_open() - This function calls single open function of seq_file 6262306a36Sopenharmony_ci * to open file and read contents from it. 6362306a36Sopenharmony_ci * @inode: Pointer to the inode structure. 6462306a36Sopenharmony_ci * @file: Pointer to the file structure. 6562306a36Sopenharmony_ci * 6662306a36Sopenharmony_ci * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure. 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_cistatic int rsi_sdio_stats_open(struct inode *inode, 6962306a36Sopenharmony_ci struct file *file) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci return single_open(file, rsi_sdio_stats_read, inode->i_private); 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/** 7562306a36Sopenharmony_ci * rsi_version_read() - This function gives driver and firmware version number. 7662306a36Sopenharmony_ci * @seq: Pointer to the sequence file structure. 7762306a36Sopenharmony_ci * @data: Pointer to the data. 7862306a36Sopenharmony_ci * 7962306a36Sopenharmony_ci * Return: 0 on success, -1 on failure. 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_cistatic int rsi_version_read(struct seq_file *seq, void *data) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci struct rsi_common *common = seq->private; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci seq_printf(seq, "LMAC : %d.%d.%d.%d\n", 8662306a36Sopenharmony_ci common->lmac_ver.major, 8762306a36Sopenharmony_ci common->lmac_ver.minor, 8862306a36Sopenharmony_ci common->lmac_ver.release_num, 8962306a36Sopenharmony_ci common->lmac_ver.patch_num); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci return 0; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci/** 9562306a36Sopenharmony_ci * rsi_version_open() - This function calls single open function of seq_file to 9662306a36Sopenharmony_ci * open file and read contents from it. 9762306a36Sopenharmony_ci * @inode: Pointer to the inode structure. 9862306a36Sopenharmony_ci * @file: Pointer to the file structure. 9962306a36Sopenharmony_ci * 10062306a36Sopenharmony_ci * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure. 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_cistatic int rsi_version_open(struct inode *inode, 10362306a36Sopenharmony_ci struct file *file) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci return single_open(file, rsi_version_read, inode->i_private); 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/** 10962306a36Sopenharmony_ci * rsi_stats_read() - This function return the status of the driver. 11062306a36Sopenharmony_ci * @seq: Pointer to the sequence file structure. 11162306a36Sopenharmony_ci * @data: Pointer to the data. 11262306a36Sopenharmony_ci * 11362306a36Sopenharmony_ci * Return: 0 on success, -1 on failure. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_cistatic int rsi_stats_read(struct seq_file *seq, void *data) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci struct rsi_common *common = seq->private; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci static const unsigned char fsm_state[][32] = { 12062306a36Sopenharmony_ci "FSM_FW_NOT_LOADED", 12162306a36Sopenharmony_ci "FSM_CARD_NOT_READY", 12262306a36Sopenharmony_ci "FSM_COMMON_DEV_PARAMS_SENT", 12362306a36Sopenharmony_ci "FSM_BOOT_PARAMS_SENT", 12462306a36Sopenharmony_ci "FSM_EEPROM_READ_MAC_ADDR", 12562306a36Sopenharmony_ci "FSM_EEPROM_READ_RF_TYPE", 12662306a36Sopenharmony_ci "FSM_RESET_MAC_SENT", 12762306a36Sopenharmony_ci "FSM_RADIO_CAPS_SENT", 12862306a36Sopenharmony_ci "FSM_BB_RF_PROG_SENT", 12962306a36Sopenharmony_ci "FSM_MAC_INIT_DONE" 13062306a36Sopenharmony_ci }; 13162306a36Sopenharmony_ci seq_puts(seq, "==> RSI STA DRIVER STATUS <==\n"); 13262306a36Sopenharmony_ci seq_puts(seq, "DRIVER_FSM_STATE: "); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(fsm_state) != NUM_FSM_STATES); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (common->fsm_state <= FSM_MAC_INIT_DONE) 13762306a36Sopenharmony_ci seq_printf(seq, "%s", fsm_state[common->fsm_state]); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci seq_printf(seq, "(%d)\n\n", common->fsm_state); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci /* Mgmt TX Path Stats */ 14262306a36Sopenharmony_ci seq_printf(seq, "total_mgmt_pkt_send : %d\n", 14362306a36Sopenharmony_ci common->tx_stats.total_tx_pkt_send[MGMT_SOFT_Q]); 14462306a36Sopenharmony_ci seq_printf(seq, "total_mgmt_pkt_queued : %d\n", 14562306a36Sopenharmony_ci skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])); 14662306a36Sopenharmony_ci seq_printf(seq, "total_mgmt_pkt_freed : %d\n", 14762306a36Sopenharmony_ci common->tx_stats.total_tx_pkt_freed[MGMT_SOFT_Q]); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci /* Data TX Path Stats */ 15062306a36Sopenharmony_ci seq_printf(seq, "total_data_vo_pkt_send: %8d\t", 15162306a36Sopenharmony_ci common->tx_stats.total_tx_pkt_send[VO_Q]); 15262306a36Sopenharmony_ci seq_printf(seq, "total_data_vo_pkt_queued: %8d\t", 15362306a36Sopenharmony_ci skb_queue_len(&common->tx_queue[VO_Q])); 15462306a36Sopenharmony_ci seq_printf(seq, "total_vo_pkt_freed: %8d\n", 15562306a36Sopenharmony_ci common->tx_stats.total_tx_pkt_freed[VO_Q]); 15662306a36Sopenharmony_ci seq_printf(seq, "total_data_vi_pkt_send: %8d\t", 15762306a36Sopenharmony_ci common->tx_stats.total_tx_pkt_send[VI_Q]); 15862306a36Sopenharmony_ci seq_printf(seq, "total_data_vi_pkt_queued: %8d\t", 15962306a36Sopenharmony_ci skb_queue_len(&common->tx_queue[VI_Q])); 16062306a36Sopenharmony_ci seq_printf(seq, "total_vi_pkt_freed: %8d\n", 16162306a36Sopenharmony_ci common->tx_stats.total_tx_pkt_freed[VI_Q]); 16262306a36Sopenharmony_ci seq_printf(seq, "total_data_be_pkt_send: %8d\t", 16362306a36Sopenharmony_ci common->tx_stats.total_tx_pkt_send[BE_Q]); 16462306a36Sopenharmony_ci seq_printf(seq, "total_data_be_pkt_queued: %8d\t", 16562306a36Sopenharmony_ci skb_queue_len(&common->tx_queue[BE_Q])); 16662306a36Sopenharmony_ci seq_printf(seq, "total_be_pkt_freed: %8d\n", 16762306a36Sopenharmony_ci common->tx_stats.total_tx_pkt_freed[BE_Q]); 16862306a36Sopenharmony_ci seq_printf(seq, "total_data_bk_pkt_send: %8d\t", 16962306a36Sopenharmony_ci common->tx_stats.total_tx_pkt_send[BK_Q]); 17062306a36Sopenharmony_ci seq_printf(seq, "total_data_bk_pkt_queued: %8d\t", 17162306a36Sopenharmony_ci skb_queue_len(&common->tx_queue[BK_Q])); 17262306a36Sopenharmony_ci seq_printf(seq, "total_bk_pkt_freed: %8d\n", 17362306a36Sopenharmony_ci common->tx_stats.total_tx_pkt_freed[BK_Q]); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci seq_puts(seq, "\n"); 17662306a36Sopenharmony_ci return 0; 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci/** 18062306a36Sopenharmony_ci * rsi_stats_open() - This function calls single open function of seq_file to 18162306a36Sopenharmony_ci * open file and read contents from it. 18262306a36Sopenharmony_ci * @inode: Pointer to the inode structure. 18362306a36Sopenharmony_ci * @file: Pointer to the file structure. 18462306a36Sopenharmony_ci * 18562306a36Sopenharmony_ci * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure. 18662306a36Sopenharmony_ci */ 18762306a36Sopenharmony_cistatic int rsi_stats_open(struct inode *inode, 18862306a36Sopenharmony_ci struct file *file) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci return single_open(file, rsi_stats_read, inode->i_private); 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci/** 19462306a36Sopenharmony_ci * rsi_debug_zone_read() - This function display the currently enabled debug zones. 19562306a36Sopenharmony_ci * @seq: Pointer to the sequence file structure. 19662306a36Sopenharmony_ci * @data: Pointer to the data. 19762306a36Sopenharmony_ci * 19862306a36Sopenharmony_ci * Return: 0 on success, -1 on failure. 19962306a36Sopenharmony_ci */ 20062306a36Sopenharmony_cistatic int rsi_debug_zone_read(struct seq_file *seq, void *data) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci rsi_dbg(FSM_ZONE, "%x: rsi_enabled zone", rsi_zone_enabled); 20362306a36Sopenharmony_ci seq_printf(seq, "The zones available are %#x\n", 20462306a36Sopenharmony_ci rsi_zone_enabled); 20562306a36Sopenharmony_ci return 0; 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci/** 20962306a36Sopenharmony_ci * rsi_debug_read() - This function calls single open function of seq_file to 21062306a36Sopenharmony_ci * open file and read contents from it. 21162306a36Sopenharmony_ci * @inode: Pointer to the inode structure. 21262306a36Sopenharmony_ci * @file: Pointer to the file structure. 21362306a36Sopenharmony_ci * 21462306a36Sopenharmony_ci * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure. 21562306a36Sopenharmony_ci */ 21662306a36Sopenharmony_cistatic int rsi_debug_read(struct inode *inode, 21762306a36Sopenharmony_ci struct file *file) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci return single_open(file, rsi_debug_zone_read, inode->i_private); 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci/** 22362306a36Sopenharmony_ci * rsi_debug_zone_write() - This function writes into hal queues as per user 22462306a36Sopenharmony_ci * requirement. 22562306a36Sopenharmony_ci * @filp: Pointer to the file structure. 22662306a36Sopenharmony_ci * @buff: Pointer to the character buffer. 22762306a36Sopenharmony_ci * @len: Length of the data to be written into buffer. 22862306a36Sopenharmony_ci * @data: Pointer to the data. 22962306a36Sopenharmony_ci * 23062306a36Sopenharmony_ci * Return: len: Number of bytes read. 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_cistatic ssize_t rsi_debug_zone_write(struct file *filp, 23362306a36Sopenharmony_ci const char __user *buff, 23462306a36Sopenharmony_ci size_t len, 23562306a36Sopenharmony_ci loff_t *data) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci unsigned long dbg_zone; 23862306a36Sopenharmony_ci int ret; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci if (!len) 24162306a36Sopenharmony_ci return 0; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci ret = kstrtoul_from_user(buff, len, 16, &dbg_zone); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci if (ret) 24662306a36Sopenharmony_ci return ret; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci rsi_zone_enabled = dbg_zone; 24962306a36Sopenharmony_ci return len; 25062306a36Sopenharmony_ci} 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci#define FOPS(fopen) { \ 25362306a36Sopenharmony_ci .owner = THIS_MODULE, \ 25462306a36Sopenharmony_ci .open = (fopen), \ 25562306a36Sopenharmony_ci .read = seq_read, \ 25662306a36Sopenharmony_ci .llseek = seq_lseek, \ 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci#define FOPS_RW(fopen, fwrite) { \ 26062306a36Sopenharmony_ci .owner = THIS_MODULE, \ 26162306a36Sopenharmony_ci .open = (fopen), \ 26262306a36Sopenharmony_ci .read = seq_read, \ 26362306a36Sopenharmony_ci .llseek = seq_lseek, \ 26462306a36Sopenharmony_ci .write = (fwrite), \ 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cistatic const struct rsi_dbg_files dev_debugfs_files[] = { 26862306a36Sopenharmony_ci {"version", 0644, FOPS(rsi_version_open),}, 26962306a36Sopenharmony_ci {"stats", 0644, FOPS(rsi_stats_open),}, 27062306a36Sopenharmony_ci {"debug_zone", 0666, FOPS_RW(rsi_debug_read, rsi_debug_zone_write),}, 27162306a36Sopenharmony_ci {"sdio_stats", 0644, FOPS(rsi_sdio_stats_open),}, 27262306a36Sopenharmony_ci}; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci/** 27562306a36Sopenharmony_ci * rsi_init_dbgfs() - This function initializes the dbgfs entry. 27662306a36Sopenharmony_ci * @adapter: Pointer to the adapter structure. 27762306a36Sopenharmony_ci * 27862306a36Sopenharmony_ci * Return: 0 on success, -1 on failure. 27962306a36Sopenharmony_ci */ 28062306a36Sopenharmony_ciint rsi_init_dbgfs(struct rsi_hw *adapter) 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci struct rsi_common *common = adapter->priv; 28362306a36Sopenharmony_ci struct rsi_debugfs *dev_dbgfs; 28462306a36Sopenharmony_ci char devdir[6]; 28562306a36Sopenharmony_ci int ii; 28662306a36Sopenharmony_ci const struct rsi_dbg_files *files; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci dev_dbgfs = kzalloc(sizeof(*dev_dbgfs), GFP_KERNEL); 28962306a36Sopenharmony_ci if (!dev_dbgfs) 29062306a36Sopenharmony_ci return -ENOMEM; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci adapter->dfsentry = dev_dbgfs; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci snprintf(devdir, sizeof(devdir), "%s", 29562306a36Sopenharmony_ci wiphy_name(adapter->hw->wiphy)); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci dev_dbgfs->subdir = debugfs_create_dir(devdir, NULL); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci for (ii = 0; ii < adapter->num_debugfs_entries; ii++) { 30062306a36Sopenharmony_ci files = &dev_debugfs_files[ii]; 30162306a36Sopenharmony_ci dev_dbgfs->rsi_files[ii] = 30262306a36Sopenharmony_ci debugfs_create_file(files->name, 30362306a36Sopenharmony_ci files->perms, 30462306a36Sopenharmony_ci dev_dbgfs->subdir, 30562306a36Sopenharmony_ci common, 30662306a36Sopenharmony_ci &files->fops); 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci return 0; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rsi_init_dbgfs); 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci/** 31362306a36Sopenharmony_ci * rsi_remove_dbgfs() - Removes the previously created dbgfs file entries 31462306a36Sopenharmony_ci * in the reverse order of creation. 31562306a36Sopenharmony_ci * @adapter: Pointer to the adapter structure. 31662306a36Sopenharmony_ci * 31762306a36Sopenharmony_ci * Return: None. 31862306a36Sopenharmony_ci */ 31962306a36Sopenharmony_civoid rsi_remove_dbgfs(struct rsi_hw *adapter) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci struct rsi_debugfs *dev_dbgfs = adapter->dfsentry; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci if (!dev_dbgfs) 32462306a36Sopenharmony_ci return; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci debugfs_remove_recursive(dev_dbgfs->subdir); 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(rsi_remove_dbgfs); 329