]>
Commit | Line | Data |
---|---|---|
fbfb8031 SN |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright(c) 2017 - 2019 Pensando Systems, Inc */ | |
3 | ||
1a58e196 | 4 | #include <linux/pci.h> |
fbfb8031 SN |
5 | #include <linux/netdevice.h> |
6 | ||
7 | #include "ionic.h" | |
8 | #include "ionic_bus.h" | |
1a58e196 | 9 | #include "ionic_lif.h" |
fbfb8031 SN |
10 | #include "ionic_debugfs.h" |
11 | ||
12 | #ifdef CONFIG_DEBUG_FS | |
13 | ||
14 | static struct dentry *ionic_dir; | |
15 | ||
16 | void ionic_debugfs_create(void) | |
17 | { | |
18 | ionic_dir = debugfs_create_dir(IONIC_DRV_NAME, NULL); | |
19 | } | |
20 | ||
21 | void ionic_debugfs_destroy(void) | |
22 | { | |
23 | debugfs_remove_recursive(ionic_dir); | |
24 | } | |
25 | ||
26 | void ionic_debugfs_add_dev(struct ionic *ionic) | |
27 | { | |
28 | ionic->dentry = debugfs_create_dir(ionic_bus_info(ionic), ionic_dir); | |
29 | } | |
30 | ||
31 | void ionic_debugfs_del_dev(struct ionic *ionic) | |
32 | { | |
33 | debugfs_remove_recursive(ionic->dentry); | |
34 | ionic->dentry = NULL; | |
35 | } | |
36 | ||
37 | static int identity_show(struct seq_file *seq, void *v) | |
38 | { | |
39 | struct ionic *ionic = seq->private; | |
40 | struct ionic_identity *ident; | |
41 | ||
42 | ident = &ionic->ident; | |
43 | ||
44 | seq_printf(seq, "nlifs: %d\n", ident->dev.nlifs); | |
45 | seq_printf(seq, "nintrs: %d\n", ident->dev.nintrs); | |
46 | seq_printf(seq, "ndbpgs_per_lif: %d\n", ident->dev.ndbpgs_per_lif); | |
47 | seq_printf(seq, "intr_coal_mult: %d\n", ident->dev.intr_coal_mult); | |
48 | seq_printf(seq, "intr_coal_div: %d\n", ident->dev.intr_coal_div); | |
49 | ||
50 | seq_printf(seq, "max_ucast_filters: %d\n", ident->lif.eth.max_ucast_filters); | |
51 | seq_printf(seq, "max_mcast_filters: %d\n", ident->lif.eth.max_mcast_filters); | |
52 | ||
53 | return 0; | |
54 | } | |
55 | DEFINE_SHOW_ATTRIBUTE(identity); | |
56 | ||
57 | void ionic_debugfs_add_ident(struct ionic *ionic) | |
58 | { | |
59 | debugfs_create_file("identity", 0400, ionic->dentry, | |
b47bea2b | 60 | ionic, &identity_fops); |
fbfb8031 SN |
61 | } |
62 | ||
1a58e196 SN |
63 | void ionic_debugfs_add_sizes(struct ionic *ionic) |
64 | { | |
65 | debugfs_create_u32("nlifs", 0400, ionic->dentry, | |
66 | (u32 *)&ionic->ident.dev.nlifs); | |
67 | debugfs_create_u32("nintrs", 0400, ionic->dentry, &ionic->nintrs); | |
68 | ||
69 | debugfs_create_u32("ntxqs_per_lif", 0400, ionic->dentry, | |
70 | (u32 *)&ionic->ident.lif.eth.config.queue_count[IONIC_QTYPE_TXQ]); | |
71 | debugfs_create_u32("nrxqs_per_lif", 0400, ionic->dentry, | |
72 | (u32 *)&ionic->ident.lif.eth.config.queue_count[IONIC_QTYPE_RXQ]); | |
73 | } | |
74 | ||
1d062b7b SN |
75 | static int q_tail_show(struct seq_file *seq, void *v) |
76 | { | |
77 | struct ionic_queue *q = seq->private; | |
78 | ||
79 | seq_printf(seq, "%d\n", q->tail->index); | |
80 | ||
81 | return 0; | |
82 | } | |
83 | DEFINE_SHOW_ATTRIBUTE(q_tail); | |
84 | ||
85 | static int q_head_show(struct seq_file *seq, void *v) | |
86 | { | |
87 | struct ionic_queue *q = seq->private; | |
88 | ||
89 | seq_printf(seq, "%d\n", q->head->index); | |
90 | ||
91 | return 0; | |
92 | } | |
93 | DEFINE_SHOW_ATTRIBUTE(q_head); | |
94 | ||
95 | static int cq_tail_show(struct seq_file *seq, void *v) | |
96 | { | |
97 | struct ionic_cq *cq = seq->private; | |
98 | ||
99 | seq_printf(seq, "%d\n", cq->tail->index); | |
100 | ||
101 | return 0; | |
102 | } | |
103 | DEFINE_SHOW_ATTRIBUTE(cq_tail); | |
104 | ||
105 | static const struct debugfs_reg32 intr_ctrl_regs[] = { | |
106 | { .name = "coal_init", .offset = 0, }, | |
107 | { .name = "mask", .offset = 4, }, | |
108 | { .name = "credits", .offset = 8, }, | |
109 | { .name = "mask_on_assert", .offset = 12, }, | |
110 | { .name = "coal_timer", .offset = 16, }, | |
111 | }; | |
112 | ||
113 | void ionic_debugfs_add_qcq(struct ionic_lif *lif, struct ionic_qcq *qcq) | |
114 | { | |
77ceb68e | 115 | struct dentry *q_dentry, *cq_dentry, *intr_dentry, *stats_dentry; |
1d062b7b SN |
116 | struct ionic_dev *idev = &lif->ionic->idev; |
117 | struct debugfs_regset32 *intr_ctrl_regset; | |
118 | struct ionic_intr_info *intr = &qcq->intr; | |
119 | struct debugfs_blob_wrapper *desc_blob; | |
120 | struct device *dev = lif->ionic->dev; | |
121 | struct ionic_queue *q = &qcq->q; | |
122 | struct ionic_cq *cq = &qcq->cq; | |
123 | ||
124 | qcq->dentry = debugfs_create_dir(q->name, lif->dentry); | |
125 | ||
126 | debugfs_create_x32("total_size", 0400, qcq->dentry, &qcq->total_size); | |
127 | debugfs_create_x64("base_pa", 0400, qcq->dentry, &qcq->base_pa); | |
128 | ||
129 | q_dentry = debugfs_create_dir("q", qcq->dentry); | |
130 | ||
131 | debugfs_create_u32("index", 0400, q_dentry, &q->index); | |
132 | debugfs_create_x64("base_pa", 0400, q_dentry, &q->base_pa); | |
133 | if (qcq->flags & IONIC_QCQ_F_SG) { | |
134 | debugfs_create_x64("sg_base_pa", 0400, q_dentry, | |
135 | &q->sg_base_pa); | |
136 | debugfs_create_u32("sg_desc_size", 0400, q_dentry, | |
137 | &q->sg_desc_size); | |
138 | } | |
139 | debugfs_create_u32("num_descs", 0400, q_dentry, &q->num_descs); | |
140 | debugfs_create_u32("desc_size", 0400, q_dentry, &q->desc_size); | |
141 | debugfs_create_u32("pid", 0400, q_dentry, &q->pid); | |
142 | debugfs_create_u32("qid", 0400, q_dentry, &q->hw_index); | |
143 | debugfs_create_u32("qtype", 0400, q_dentry, &q->hw_type); | |
144 | debugfs_create_u64("drop", 0400, q_dentry, &q->drop); | |
145 | debugfs_create_u64("stop", 0400, q_dentry, &q->stop); | |
146 | debugfs_create_u64("wake", 0400, q_dentry, &q->wake); | |
147 | ||
148 | debugfs_create_file("tail", 0400, q_dentry, q, &q_tail_fops); | |
149 | debugfs_create_file("head", 0400, q_dentry, q, &q_head_fops); | |
150 | ||
151 | desc_blob = devm_kzalloc(dev, sizeof(*desc_blob), GFP_KERNEL); | |
152 | if (!desc_blob) | |
153 | return; | |
154 | desc_blob->data = q->base; | |
155 | desc_blob->size = (unsigned long)q->num_descs * q->desc_size; | |
156 | debugfs_create_blob("desc_blob", 0400, q_dentry, desc_blob); | |
157 | ||
158 | if (qcq->flags & IONIC_QCQ_F_SG) { | |
159 | desc_blob = devm_kzalloc(dev, sizeof(*desc_blob), GFP_KERNEL); | |
160 | if (!desc_blob) | |
161 | return; | |
162 | desc_blob->data = q->sg_base; | |
163 | desc_blob->size = (unsigned long)q->num_descs * q->sg_desc_size; | |
164 | debugfs_create_blob("sg_desc_blob", 0400, q_dentry, | |
165 | desc_blob); | |
166 | } | |
167 | ||
168 | cq_dentry = debugfs_create_dir("cq", qcq->dentry); | |
169 | ||
170 | debugfs_create_x64("base_pa", 0400, cq_dentry, &cq->base_pa); | |
171 | debugfs_create_u32("num_descs", 0400, cq_dentry, &cq->num_descs); | |
172 | debugfs_create_u32("desc_size", 0400, cq_dentry, &cq->desc_size); | |
0735ccc9 | 173 | debugfs_create_bool("done_color", 0400, cq_dentry, &cq->done_color); |
1d062b7b SN |
174 | |
175 | debugfs_create_file("tail", 0400, cq_dentry, cq, &cq_tail_fops); | |
176 | ||
177 | desc_blob = devm_kzalloc(dev, sizeof(*desc_blob), GFP_KERNEL); | |
178 | if (!desc_blob) | |
179 | return; | |
180 | desc_blob->data = cq->base; | |
181 | desc_blob->size = (unsigned long)cq->num_descs * cq->desc_size; | |
182 | debugfs_create_blob("desc_blob", 0400, cq_dentry, desc_blob); | |
183 | ||
184 | if (qcq->flags & IONIC_QCQ_F_INTR) { | |
185 | intr_dentry = debugfs_create_dir("intr", qcq->dentry); | |
186 | ||
187 | debugfs_create_u32("index", 0400, intr_dentry, | |
188 | &intr->index); | |
189 | debugfs_create_u32("vector", 0400, intr_dentry, | |
190 | &intr->vector); | |
191 | ||
192 | intr_ctrl_regset = devm_kzalloc(dev, sizeof(*intr_ctrl_regset), | |
193 | GFP_KERNEL); | |
194 | if (!intr_ctrl_regset) | |
195 | return; | |
196 | intr_ctrl_regset->regs = intr_ctrl_regs; | |
197 | intr_ctrl_regset->nregs = ARRAY_SIZE(intr_ctrl_regs); | |
198 | intr_ctrl_regset->base = &idev->intr_ctrl[intr->index]; | |
199 | ||
200 | debugfs_create_regset32("intr_ctrl", 0400, intr_dentry, | |
201 | intr_ctrl_regset); | |
202 | } | |
77ceb68e SN |
203 | |
204 | if (qcq->flags & IONIC_QCQ_F_NOTIFYQ) { | |
205 | stats_dentry = debugfs_create_dir("notifyblock", qcq->dentry); | |
206 | ||
207 | debugfs_create_u64("eid", 0400, stats_dentry, | |
208 | (u64 *)&lif->info->status.eid); | |
209 | debugfs_create_u16("link_status", 0400, stats_dentry, | |
210 | (u16 *)&lif->info->status.link_status); | |
211 | debugfs_create_u32("link_speed", 0400, stats_dentry, | |
212 | (u32 *)&lif->info->status.link_speed); | |
213 | debugfs_create_u16("link_down_count", 0400, stats_dentry, | |
214 | (u16 *)&lif->info->status.link_down_count); | |
215 | } | |
1d062b7b SN |
216 | } |
217 | ||
1a58e196 SN |
218 | static int netdev_show(struct seq_file *seq, void *v) |
219 | { | |
220 | struct net_device *netdev = seq->private; | |
221 | ||
222 | seq_printf(seq, "%s\n", netdev->name); | |
223 | ||
224 | return 0; | |
225 | } | |
226 | DEFINE_SHOW_ATTRIBUTE(netdev); | |
227 | ||
228 | void ionic_debugfs_add_lif(struct ionic_lif *lif) | |
229 | { | |
0e1825f4 SN |
230 | struct dentry *lif_dentry; |
231 | ||
232 | lif_dentry = debugfs_create_dir(lif->name, lif->ionic->dentry); | |
233 | if (IS_ERR_OR_NULL(lif_dentry)) | |
234 | return; | |
235 | lif->dentry = lif_dentry; | |
236 | ||
1a58e196 SN |
237 | debugfs_create_file("netdev", 0400, lif->dentry, |
238 | lif->netdev, &netdev_fops); | |
239 | } | |
240 | ||
241 | void ionic_debugfs_del_lif(struct ionic_lif *lif) | |
242 | { | |
243 | debugfs_remove_recursive(lif->dentry); | |
244 | lif->dentry = NULL; | |
245 | } | |
1d062b7b SN |
246 | |
247 | void ionic_debugfs_del_qcq(struct ionic_qcq *qcq) | |
248 | { | |
249 | debugfs_remove_recursive(qcq->dentry); | |
250 | qcq->dentry = NULL; | |
251 | } | |
252 | ||
fbfb8031 | 253 | #endif |