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