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