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