xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/huawei/hinic/hinic_debugfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /* Huawei HiNIC PCI Express Linux driver
3*4882a593Smuzhiyun  * Copyright(c) 2017 Huawei Technologies Co., Ltd
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <linux/debugfs.h>
7*4882a593Smuzhiyun #include <linux/device.h>
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include "hinic_debugfs.h"
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun static struct dentry *hinic_dbgfs_root;
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun enum sq_dbg_info {
14*4882a593Smuzhiyun 	GLB_SQ_ID,
15*4882a593Smuzhiyun 	SQ_PI,
16*4882a593Smuzhiyun 	SQ_CI,
17*4882a593Smuzhiyun 	SQ_FI,
18*4882a593Smuzhiyun 	SQ_MSIX_ENTRY,
19*4882a593Smuzhiyun };
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun static char *sq_fields[] = {"glb_sq_id", "sq_pi", "sq_ci", "sq_fi", "sq_msix_entry"};
22*4882a593Smuzhiyun 
hinic_dbg_get_sq_info(struct hinic_dev * nic_dev,struct hinic_sq * sq,int idx)23*4882a593Smuzhiyun static u64 hinic_dbg_get_sq_info(struct hinic_dev *nic_dev, struct hinic_sq *sq, int idx)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun 	struct hinic_wq *wq = sq->wq;
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun 	switch (idx) {
28*4882a593Smuzhiyun 	case GLB_SQ_ID:
29*4882a593Smuzhiyun 		return nic_dev->hwdev->func_to_io.global_qpn + sq->qid;
30*4882a593Smuzhiyun 	case SQ_PI:
31*4882a593Smuzhiyun 		return atomic_read(&wq->prod_idx) & wq->mask;
32*4882a593Smuzhiyun 	case SQ_CI:
33*4882a593Smuzhiyun 		return atomic_read(&wq->cons_idx) & wq->mask;
34*4882a593Smuzhiyun 	case SQ_FI:
35*4882a593Smuzhiyun 		return be16_to_cpu(*(__be16 *)(sq->hw_ci_addr)) & wq->mask;
36*4882a593Smuzhiyun 	case SQ_MSIX_ENTRY:
37*4882a593Smuzhiyun 		return sq->msix_entry;
38*4882a593Smuzhiyun 	}
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	return 0;
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun enum rq_dbg_info {
44*4882a593Smuzhiyun 	GLB_RQ_ID,
45*4882a593Smuzhiyun 	RQ_HW_PI,
46*4882a593Smuzhiyun 	RQ_SW_CI,
47*4882a593Smuzhiyun 	RQ_SW_PI,
48*4882a593Smuzhiyun 	RQ_MSIX_ENTRY,
49*4882a593Smuzhiyun };
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun static char *rq_fields[] = {"glb_rq_id", "rq_hw_pi", "rq_sw_ci", "rq_sw_pi", "rq_msix_entry"};
52*4882a593Smuzhiyun 
hinic_dbg_get_rq_info(struct hinic_dev * nic_dev,struct hinic_rq * rq,int idx)53*4882a593Smuzhiyun static u64 hinic_dbg_get_rq_info(struct hinic_dev *nic_dev, struct hinic_rq *rq, int idx)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	struct hinic_wq *wq = rq->wq;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	switch (idx) {
58*4882a593Smuzhiyun 	case GLB_RQ_ID:
59*4882a593Smuzhiyun 		return nic_dev->hwdev->func_to_io.global_qpn + rq->qid;
60*4882a593Smuzhiyun 	case RQ_HW_PI:
61*4882a593Smuzhiyun 		return be16_to_cpu(*(__be16 *)(rq->pi_virt_addr)) & wq->mask;
62*4882a593Smuzhiyun 	case RQ_SW_CI:
63*4882a593Smuzhiyun 		return atomic_read(&wq->cons_idx) & wq->mask;
64*4882a593Smuzhiyun 	case RQ_SW_PI:
65*4882a593Smuzhiyun 		return atomic_read(&wq->prod_idx) & wq->mask;
66*4882a593Smuzhiyun 	case RQ_MSIX_ENTRY:
67*4882a593Smuzhiyun 		return rq->msix_entry;
68*4882a593Smuzhiyun 	}
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	return 0;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun enum func_tbl_info {
74*4882a593Smuzhiyun 	VALID,
75*4882a593Smuzhiyun 	RX_MODE,
76*4882a593Smuzhiyun 	MTU,
77*4882a593Smuzhiyun 	RQ_DEPTH,
78*4882a593Smuzhiyun 	QUEUE_NUM,
79*4882a593Smuzhiyun };
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun static char *func_table_fields[] = {"valid", "rx_mode", "mtu", "rq_depth", "cfg_q_num"};
82*4882a593Smuzhiyun 
hinic_dbg_get_func_table(struct hinic_dev * nic_dev,int idx)83*4882a593Smuzhiyun static int hinic_dbg_get_func_table(struct hinic_dev *nic_dev, int idx)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	struct tag_sml_funcfg_tbl *funcfg_table_elem;
86*4882a593Smuzhiyun 	struct hinic_cmd_lt_rd *read_data;
87*4882a593Smuzhiyun 	u16 out_size = sizeof(*read_data);
88*4882a593Smuzhiyun 	int ret = ~0;
89*4882a593Smuzhiyun 	int err;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	read_data = kzalloc(sizeof(*read_data), GFP_KERNEL);
92*4882a593Smuzhiyun 	if (!read_data)
93*4882a593Smuzhiyun 		return ~0;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	read_data->node = TBL_ID_FUNC_CFG_SM_NODE;
96*4882a593Smuzhiyun 	read_data->inst = TBL_ID_FUNC_CFG_SM_INST;
97*4882a593Smuzhiyun 	read_data->entry_size = HINIC_FUNCTION_CONFIGURE_TABLE_SIZE;
98*4882a593Smuzhiyun 	read_data->lt_index = HINIC_HWIF_FUNC_IDX(nic_dev->hwdev->hwif);
99*4882a593Smuzhiyun 	read_data->len = HINIC_FUNCTION_CONFIGURE_TABLE_SIZE;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	err = hinic_port_msg_cmd(nic_dev->hwdev, HINIC_PORT_CMD_RD_LINE_TBL, read_data,
102*4882a593Smuzhiyun 				 sizeof(*read_data), read_data, &out_size);
103*4882a593Smuzhiyun 	if (err || out_size != sizeof(*read_data) || read_data->status) {
104*4882a593Smuzhiyun 		netif_err(nic_dev, drv, nic_dev->netdev,
105*4882a593Smuzhiyun 			  "Failed to get func table, err: %d, status: 0x%x, out size: 0x%x\n",
106*4882a593Smuzhiyun 			  err, read_data->status, out_size);
107*4882a593Smuzhiyun 		kfree(read_data);
108*4882a593Smuzhiyun 		return ~0;
109*4882a593Smuzhiyun 	}
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	funcfg_table_elem = (struct tag_sml_funcfg_tbl *)read_data->data;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	switch (idx) {
114*4882a593Smuzhiyun 	case VALID:
115*4882a593Smuzhiyun 		ret = funcfg_table_elem->dw0.bs.valid;
116*4882a593Smuzhiyun 		break;
117*4882a593Smuzhiyun 	case RX_MODE:
118*4882a593Smuzhiyun 		ret = funcfg_table_elem->dw0.bs.nic_rx_mode;
119*4882a593Smuzhiyun 		break;
120*4882a593Smuzhiyun 	case MTU:
121*4882a593Smuzhiyun 		ret = funcfg_table_elem->dw1.bs.mtu;
122*4882a593Smuzhiyun 		break;
123*4882a593Smuzhiyun 	case RQ_DEPTH:
124*4882a593Smuzhiyun 		ret = funcfg_table_elem->dw13.bs.cfg_rq_depth;
125*4882a593Smuzhiyun 		break;
126*4882a593Smuzhiyun 	case QUEUE_NUM:
127*4882a593Smuzhiyun 		ret = funcfg_table_elem->dw13.bs.cfg_q_num;
128*4882a593Smuzhiyun 		break;
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	kfree(read_data);
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	return ret;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun 
hinic_dbg_cmd_read(struct file * filp,char __user * buffer,size_t count,loff_t * ppos)136*4882a593Smuzhiyun static ssize_t hinic_dbg_cmd_read(struct file *filp, char __user *buffer, size_t count,
137*4882a593Smuzhiyun 				  loff_t *ppos)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun 	struct hinic_debug_priv *dbg;
140*4882a593Smuzhiyun 	char ret_buf[20];
141*4882a593Smuzhiyun 	int *desc;
142*4882a593Smuzhiyun 	u64 out;
143*4882a593Smuzhiyun 	int ret;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	desc = filp->private_data;
146*4882a593Smuzhiyun 	dbg = container_of(desc, struct hinic_debug_priv, field_id[*desc]);
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	switch (dbg->type) {
149*4882a593Smuzhiyun 	case HINIC_DBG_SQ_INFO:
150*4882a593Smuzhiyun 		out = hinic_dbg_get_sq_info(dbg->dev, dbg->object, *desc);
151*4882a593Smuzhiyun 		break;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	case HINIC_DBG_RQ_INFO:
154*4882a593Smuzhiyun 		out = hinic_dbg_get_rq_info(dbg->dev, dbg->object, *desc);
155*4882a593Smuzhiyun 		break;
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	case HINIC_DBG_FUNC_TABLE:
158*4882a593Smuzhiyun 		out = hinic_dbg_get_func_table(dbg->dev, *desc);
159*4882a593Smuzhiyun 		break;
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	default:
162*4882a593Smuzhiyun 		netif_warn(dbg->dev, drv, dbg->dev->netdev, "Invalid hinic debug cmd: %d\n",
163*4882a593Smuzhiyun 			   dbg->type);
164*4882a593Smuzhiyun 		return -EINVAL;
165*4882a593Smuzhiyun 	}
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	ret = snprintf(ret_buf, sizeof(ret_buf), "0x%llx\n", out);
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	return simple_read_from_buffer(buffer, count, ppos, ret_buf, ret);
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun static const struct file_operations hinic_dbg_cmd_fops = {
173*4882a593Smuzhiyun 	.owner = THIS_MODULE,
174*4882a593Smuzhiyun 	.open  = simple_open,
175*4882a593Smuzhiyun 	.read  = hinic_dbg_cmd_read,
176*4882a593Smuzhiyun };
177*4882a593Smuzhiyun 
create_dbg_files(struct hinic_dev * dev,enum hinic_dbg_type type,void * data,struct dentry * root,struct hinic_debug_priv ** dbg,char ** field,int nfile)178*4882a593Smuzhiyun static int create_dbg_files(struct hinic_dev *dev, enum hinic_dbg_type type, void *data,
179*4882a593Smuzhiyun 			    struct dentry *root, struct hinic_debug_priv **dbg, char **field,
180*4882a593Smuzhiyun 			    int nfile)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun 	struct hinic_debug_priv *tmp;
183*4882a593Smuzhiyun 	int i;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
186*4882a593Smuzhiyun 	if (!tmp)
187*4882a593Smuzhiyun 		return -ENOMEM;
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	tmp->dev = dev;
190*4882a593Smuzhiyun 	tmp->object = data;
191*4882a593Smuzhiyun 	tmp->type = type;
192*4882a593Smuzhiyun 	tmp->root = root;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	for (i = 0; i < nfile; i++) {
195*4882a593Smuzhiyun 		tmp->field_id[i] = i;
196*4882a593Smuzhiyun 		debugfs_create_file(field[i], 0400, root, &tmp->field_id[i], &hinic_dbg_cmd_fops);
197*4882a593Smuzhiyun 	}
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	*dbg = tmp;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	return 0;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun 
rem_dbg_files(struct hinic_debug_priv * dbg)204*4882a593Smuzhiyun static void rem_dbg_files(struct hinic_debug_priv *dbg)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun 	if (dbg->type != HINIC_DBG_FUNC_TABLE)
207*4882a593Smuzhiyun 		debugfs_remove_recursive(dbg->root);
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	kfree(dbg);
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
hinic_sq_debug_add(struct hinic_dev * dev,u16 sq_id)212*4882a593Smuzhiyun int hinic_sq_debug_add(struct hinic_dev *dev, u16 sq_id)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	struct hinic_sq *sq;
215*4882a593Smuzhiyun 	struct dentry *root;
216*4882a593Smuzhiyun 	char sub_dir[16];
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	sq = dev->txqs[sq_id].sq;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	sprintf(sub_dir, "0x%x", sq_id);
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	root = debugfs_create_dir(sub_dir, dev->sq_dbgfs);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	return create_dbg_files(dev, HINIC_DBG_SQ_INFO, sq, root, &sq->dbg, sq_fields,
225*4882a593Smuzhiyun 				ARRAY_SIZE(sq_fields));
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun 
hinic_sq_debug_rem(struct hinic_sq * sq)228*4882a593Smuzhiyun void hinic_sq_debug_rem(struct hinic_sq *sq)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun 	if (sq->dbg)
231*4882a593Smuzhiyun 		rem_dbg_files(sq->dbg);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
hinic_rq_debug_add(struct hinic_dev * dev,u16 rq_id)234*4882a593Smuzhiyun int hinic_rq_debug_add(struct hinic_dev *dev, u16 rq_id)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun 	struct hinic_rq *rq;
237*4882a593Smuzhiyun 	struct dentry *root;
238*4882a593Smuzhiyun 	char sub_dir[16];
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	rq = dev->rxqs[rq_id].rq;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	sprintf(sub_dir, "0x%x", rq_id);
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	root = debugfs_create_dir(sub_dir, dev->rq_dbgfs);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	return create_dbg_files(dev, HINIC_DBG_RQ_INFO, rq, root, &rq->dbg, rq_fields,
247*4882a593Smuzhiyun 				ARRAY_SIZE(rq_fields));
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun 
hinic_rq_debug_rem(struct hinic_rq * rq)250*4882a593Smuzhiyun void hinic_rq_debug_rem(struct hinic_rq *rq)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun 	if (rq->dbg)
253*4882a593Smuzhiyun 		rem_dbg_files(rq->dbg);
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun 
hinic_func_table_debug_add(struct hinic_dev * dev)256*4882a593Smuzhiyun int hinic_func_table_debug_add(struct hinic_dev *dev)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun 	if (HINIC_IS_VF(dev->hwdev->hwif))
259*4882a593Smuzhiyun 		return 0;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	return create_dbg_files(dev, HINIC_DBG_FUNC_TABLE, dev, dev->func_tbl_dbgfs, &dev->dbg,
262*4882a593Smuzhiyun 				func_table_fields, ARRAY_SIZE(func_table_fields));
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
hinic_func_table_debug_rem(struct hinic_dev * dev)265*4882a593Smuzhiyun void hinic_func_table_debug_rem(struct hinic_dev *dev)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun 	if (!HINIC_IS_VF(dev->hwdev->hwif) && dev->dbg)
268*4882a593Smuzhiyun 		rem_dbg_files(dev->dbg);
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
hinic_sq_dbgfs_init(struct hinic_dev * nic_dev)271*4882a593Smuzhiyun void hinic_sq_dbgfs_init(struct hinic_dev *nic_dev)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun 	nic_dev->sq_dbgfs = debugfs_create_dir("SQs", nic_dev->dbgfs_root);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
hinic_sq_dbgfs_uninit(struct hinic_dev * nic_dev)276*4882a593Smuzhiyun void hinic_sq_dbgfs_uninit(struct hinic_dev *nic_dev)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun 	debugfs_remove_recursive(nic_dev->sq_dbgfs);
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun 
hinic_rq_dbgfs_init(struct hinic_dev * nic_dev)281*4882a593Smuzhiyun void hinic_rq_dbgfs_init(struct hinic_dev *nic_dev)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun 	nic_dev->rq_dbgfs = debugfs_create_dir("RQs", nic_dev->dbgfs_root);
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
hinic_rq_dbgfs_uninit(struct hinic_dev * nic_dev)286*4882a593Smuzhiyun void hinic_rq_dbgfs_uninit(struct hinic_dev *nic_dev)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun 	debugfs_remove_recursive(nic_dev->rq_dbgfs);
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
hinic_func_tbl_dbgfs_init(struct hinic_dev * nic_dev)291*4882a593Smuzhiyun void hinic_func_tbl_dbgfs_init(struct hinic_dev *nic_dev)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun 	if (!HINIC_IS_VF(nic_dev->hwdev->hwif))
294*4882a593Smuzhiyun 		nic_dev->func_tbl_dbgfs = debugfs_create_dir("func_table", nic_dev->dbgfs_root);
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
hinic_func_tbl_dbgfs_uninit(struct hinic_dev * nic_dev)297*4882a593Smuzhiyun void hinic_func_tbl_dbgfs_uninit(struct hinic_dev *nic_dev)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun 	if (!HINIC_IS_VF(nic_dev->hwdev->hwif))
300*4882a593Smuzhiyun 		debugfs_remove_recursive(nic_dev->func_tbl_dbgfs);
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun 
hinic_dbg_init(struct hinic_dev * nic_dev)303*4882a593Smuzhiyun void hinic_dbg_init(struct hinic_dev *nic_dev)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun 	nic_dev->dbgfs_root = debugfs_create_dir(pci_name(nic_dev->hwdev->hwif->pdev),
306*4882a593Smuzhiyun 						 hinic_dbgfs_root);
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun 
hinic_dbg_uninit(struct hinic_dev * nic_dev)309*4882a593Smuzhiyun void hinic_dbg_uninit(struct hinic_dev *nic_dev)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun 	debugfs_remove_recursive(nic_dev->dbgfs_root);
312*4882a593Smuzhiyun 	nic_dev->dbgfs_root = NULL;
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun 
hinic_dbg_register_debugfs(const char * debugfs_dir_name)315*4882a593Smuzhiyun void hinic_dbg_register_debugfs(const char *debugfs_dir_name)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun 	hinic_dbgfs_root = debugfs_create_dir(debugfs_dir_name, NULL);
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun 
hinic_dbg_unregister_debugfs(void)320*4882a593Smuzhiyun void hinic_dbg_unregister_debugfs(void)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun 	debugfs_remove_recursive(hinic_dbgfs_root);
323*4882a593Smuzhiyun 	hinic_dbgfs_root = NULL;
324*4882a593Smuzhiyun }
325