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