1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* Copyright(c) 2023 Advanced Micro Devices, Inc */ |
3 | |
4 | #include <linux/pci.h> |
5 | #include <linux/vdpa.h> |
6 | |
7 | #include <linux/pds/pds_common.h> |
8 | #include <linux/pds/pds_core_if.h> |
9 | #include <linux/pds/pds_adminq.h> |
10 | #include <linux/pds/pds_auxbus.h> |
11 | |
12 | #include "aux_drv.h" |
13 | #include "vdpa_dev.h" |
14 | #include "debugfs.h" |
15 | |
16 | static struct dentry *dbfs_dir; |
17 | |
18 | void pds_vdpa_debugfs_create(void) |
19 | { |
20 | dbfs_dir = debugfs_create_dir(PDS_VDPA_DRV_NAME, NULL); |
21 | } |
22 | |
23 | void pds_vdpa_debugfs_destroy(void) |
24 | { |
25 | debugfs_remove_recursive(dentry: dbfs_dir); |
26 | dbfs_dir = NULL; |
27 | } |
28 | |
29 | #define PRINT_SBIT_NAME(__seq, __f, __name) \ |
30 | do { \ |
31 | if ((__f) & (__name)) \ |
32 | seq_printf(__seq, " %s", &#__name[16]); \ |
33 | } while (0) |
34 | |
35 | static void print_status_bits(struct seq_file *seq, u8 status) |
36 | { |
37 | seq_puts(m: seq, s: "status:" ); |
38 | PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_ACKNOWLEDGE); |
39 | PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_DRIVER); |
40 | PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_DRIVER_OK); |
41 | PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_FEATURES_OK); |
42 | PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_NEEDS_RESET); |
43 | PRINT_SBIT_NAME(seq, status, VIRTIO_CONFIG_S_FAILED); |
44 | seq_puts(m: seq, s: "\n" ); |
45 | } |
46 | |
47 | static void print_feature_bits_all(struct seq_file *seq, u64 features) |
48 | { |
49 | int i; |
50 | |
51 | seq_puts(m: seq, s: "features:" ); |
52 | |
53 | for (i = 0; i < (sizeof(u64) * 8); i++) { |
54 | u64 mask = BIT_ULL(i); |
55 | |
56 | switch (features & mask) { |
57 | case BIT_ULL(VIRTIO_NET_F_CSUM): |
58 | seq_puts(m: seq, s: " VIRTIO_NET_F_CSUM" ); |
59 | break; |
60 | case BIT_ULL(VIRTIO_NET_F_GUEST_CSUM): |
61 | seq_puts(m: seq, s: " VIRTIO_NET_F_GUEST_CSUM" ); |
62 | break; |
63 | case BIT_ULL(VIRTIO_NET_F_CTRL_GUEST_OFFLOADS): |
64 | seq_puts(m: seq, s: " VIRTIO_NET_F_CTRL_GUEST_OFFLOADS" ); |
65 | break; |
66 | case BIT_ULL(VIRTIO_NET_F_MTU): |
67 | seq_puts(m: seq, s: " VIRTIO_NET_F_MTU" ); |
68 | break; |
69 | case BIT_ULL(VIRTIO_NET_F_MAC): |
70 | seq_puts(m: seq, s: " VIRTIO_NET_F_MAC" ); |
71 | break; |
72 | case BIT_ULL(VIRTIO_NET_F_GUEST_TSO4): |
73 | seq_puts(m: seq, s: " VIRTIO_NET_F_GUEST_TSO4" ); |
74 | break; |
75 | case BIT_ULL(VIRTIO_NET_F_GUEST_TSO6): |
76 | seq_puts(m: seq, s: " VIRTIO_NET_F_GUEST_TSO6" ); |
77 | break; |
78 | case BIT_ULL(VIRTIO_NET_F_GUEST_ECN): |
79 | seq_puts(m: seq, s: " VIRTIO_NET_F_GUEST_ECN" ); |
80 | break; |
81 | case BIT_ULL(VIRTIO_NET_F_GUEST_UFO): |
82 | seq_puts(m: seq, s: " VIRTIO_NET_F_GUEST_UFO" ); |
83 | break; |
84 | case BIT_ULL(VIRTIO_NET_F_HOST_TSO4): |
85 | seq_puts(m: seq, s: " VIRTIO_NET_F_HOST_TSO4" ); |
86 | break; |
87 | case BIT_ULL(VIRTIO_NET_F_HOST_TSO6): |
88 | seq_puts(m: seq, s: " VIRTIO_NET_F_HOST_TSO6" ); |
89 | break; |
90 | case BIT_ULL(VIRTIO_NET_F_HOST_ECN): |
91 | seq_puts(m: seq, s: " VIRTIO_NET_F_HOST_ECN" ); |
92 | break; |
93 | case BIT_ULL(VIRTIO_NET_F_HOST_UFO): |
94 | seq_puts(m: seq, s: " VIRTIO_NET_F_HOST_UFO" ); |
95 | break; |
96 | case BIT_ULL(VIRTIO_NET_F_MRG_RXBUF): |
97 | seq_puts(m: seq, s: " VIRTIO_NET_F_MRG_RXBUF" ); |
98 | break; |
99 | case BIT_ULL(VIRTIO_NET_F_STATUS): |
100 | seq_puts(m: seq, s: " VIRTIO_NET_F_STATUS" ); |
101 | break; |
102 | case BIT_ULL(VIRTIO_NET_F_CTRL_VQ): |
103 | seq_puts(m: seq, s: " VIRTIO_NET_F_CTRL_VQ" ); |
104 | break; |
105 | case BIT_ULL(VIRTIO_NET_F_CTRL_RX): |
106 | seq_puts(m: seq, s: " VIRTIO_NET_F_CTRL_RX" ); |
107 | break; |
108 | case BIT_ULL(VIRTIO_NET_F_CTRL_VLAN): |
109 | seq_puts(m: seq, s: " VIRTIO_NET_F_CTRL_VLAN" ); |
110 | break; |
111 | case BIT_ULL(VIRTIO_NET_F_CTRL_RX_EXTRA): |
112 | seq_puts(m: seq, s: " VIRTIO_NET_F_CTRL_RX_EXTRA" ); |
113 | break; |
114 | case BIT_ULL(VIRTIO_NET_F_GUEST_ANNOUNCE): |
115 | seq_puts(m: seq, s: " VIRTIO_NET_F_GUEST_ANNOUNCE" ); |
116 | break; |
117 | case BIT_ULL(VIRTIO_NET_F_MQ): |
118 | seq_puts(m: seq, s: " VIRTIO_NET_F_MQ" ); |
119 | break; |
120 | case BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR): |
121 | seq_puts(m: seq, s: " VIRTIO_NET_F_CTRL_MAC_ADDR" ); |
122 | break; |
123 | case BIT_ULL(VIRTIO_NET_F_HASH_REPORT): |
124 | seq_puts(m: seq, s: " VIRTIO_NET_F_HASH_REPORT" ); |
125 | break; |
126 | case BIT_ULL(VIRTIO_NET_F_RSS): |
127 | seq_puts(m: seq, s: " VIRTIO_NET_F_RSS" ); |
128 | break; |
129 | case BIT_ULL(VIRTIO_NET_F_RSC_EXT): |
130 | seq_puts(m: seq, s: " VIRTIO_NET_F_RSC_EXT" ); |
131 | break; |
132 | case BIT_ULL(VIRTIO_NET_F_STANDBY): |
133 | seq_puts(m: seq, s: " VIRTIO_NET_F_STANDBY" ); |
134 | break; |
135 | case BIT_ULL(VIRTIO_NET_F_SPEED_DUPLEX): |
136 | seq_puts(m: seq, s: " VIRTIO_NET_F_SPEED_DUPLEX" ); |
137 | break; |
138 | case BIT_ULL(VIRTIO_F_NOTIFY_ON_EMPTY): |
139 | seq_puts(m: seq, s: " VIRTIO_F_NOTIFY_ON_EMPTY" ); |
140 | break; |
141 | case BIT_ULL(VIRTIO_F_ANY_LAYOUT): |
142 | seq_puts(m: seq, s: " VIRTIO_F_ANY_LAYOUT" ); |
143 | break; |
144 | case BIT_ULL(VIRTIO_F_VERSION_1): |
145 | seq_puts(m: seq, s: " VIRTIO_F_VERSION_1" ); |
146 | break; |
147 | case BIT_ULL(VIRTIO_F_ACCESS_PLATFORM): |
148 | seq_puts(m: seq, s: " VIRTIO_F_ACCESS_PLATFORM" ); |
149 | break; |
150 | case BIT_ULL(VIRTIO_F_RING_PACKED): |
151 | seq_puts(m: seq, s: " VIRTIO_F_RING_PACKED" ); |
152 | break; |
153 | case BIT_ULL(VIRTIO_F_ORDER_PLATFORM): |
154 | seq_puts(m: seq, s: " VIRTIO_F_ORDER_PLATFORM" ); |
155 | break; |
156 | case BIT_ULL(VIRTIO_F_SR_IOV): |
157 | seq_puts(m: seq, s: " VIRTIO_F_SR_IOV" ); |
158 | break; |
159 | case 0: |
160 | break; |
161 | default: |
162 | seq_printf(m: seq, fmt: " bit_%d" , i); |
163 | break; |
164 | } |
165 | } |
166 | |
167 | seq_puts(m: seq, s: "\n" ); |
168 | } |
169 | |
170 | void pds_vdpa_debugfs_add_pcidev(struct pds_vdpa_aux *vdpa_aux) |
171 | { |
172 | vdpa_aux->dentry = debugfs_create_dir(name: pci_name(pdev: vdpa_aux->padev->vf_pdev), parent: dbfs_dir); |
173 | } |
174 | |
175 | static int identity_show(struct seq_file *seq, void *v) |
176 | { |
177 | struct pds_vdpa_aux *vdpa_aux = seq->private; |
178 | struct vdpa_mgmt_dev *mgmt; |
179 | u64 hw_features; |
180 | |
181 | seq_printf(m: seq, fmt: "aux_dev: %s\n" , |
182 | dev_name(dev: &vdpa_aux->padev->aux_dev.dev)); |
183 | |
184 | mgmt = &vdpa_aux->vdpa_mdev; |
185 | seq_printf(m: seq, fmt: "max_vqs: %d\n" , mgmt->max_supported_vqs); |
186 | seq_printf(m: seq, fmt: "config_attr_mask: %#llx\n" , mgmt->config_attr_mask); |
187 | hw_features = le64_to_cpu(vdpa_aux->ident.hw_features); |
188 | seq_printf(m: seq, fmt: "hw_features: %#llx\n" , hw_features); |
189 | print_feature_bits_all(seq, features: hw_features); |
190 | |
191 | return 0; |
192 | } |
193 | DEFINE_SHOW_ATTRIBUTE(identity); |
194 | |
195 | void pds_vdpa_debugfs_add_ident(struct pds_vdpa_aux *vdpa_aux) |
196 | { |
197 | debugfs_create_file(name: "identity" , mode: 0400, parent: vdpa_aux->dentry, |
198 | data: vdpa_aux, fops: &identity_fops); |
199 | } |
200 | |
201 | static int config_show(struct seq_file *seq, void *v) |
202 | { |
203 | struct pds_vdpa_device *pdsv = seq->private; |
204 | struct virtio_net_config vc; |
205 | u8 status; |
206 | |
207 | memcpy_fromio(&vc, pdsv->vdpa_aux->vd_mdev.device, |
208 | sizeof(struct virtio_net_config)); |
209 | |
210 | seq_printf(m: seq, fmt: "mac: %pM\n" , vc.mac); |
211 | seq_printf(m: seq, fmt: "max_virtqueue_pairs: %d\n" , |
212 | __virtio16_to_cpu(little_endian: true, val: vc.max_virtqueue_pairs)); |
213 | seq_printf(m: seq, fmt: "mtu: %d\n" , __virtio16_to_cpu(little_endian: true, val: vc.mtu)); |
214 | seq_printf(m: seq, fmt: "speed: %d\n" , le32_to_cpu(vc.speed)); |
215 | seq_printf(m: seq, fmt: "duplex: %d\n" , vc.duplex); |
216 | seq_printf(m: seq, fmt: "rss_max_key_size: %d\n" , vc.rss_max_key_size); |
217 | seq_printf(m: seq, fmt: "rss_max_indirection_table_length: %d\n" , |
218 | le16_to_cpu(vc.rss_max_indirection_table_length)); |
219 | seq_printf(m: seq, fmt: "supported_hash_types: %#x\n" , |
220 | le32_to_cpu(vc.supported_hash_types)); |
221 | seq_printf(m: seq, fmt: "vn_status: %#x\n" , |
222 | __virtio16_to_cpu(little_endian: true, val: vc.status)); |
223 | |
224 | status = vp_modern_get_status(mdev: &pdsv->vdpa_aux->vd_mdev); |
225 | seq_printf(m: seq, fmt: "dev_status: %#x\n" , status); |
226 | print_status_bits(seq, status); |
227 | seq_printf(m: seq, fmt: "negotiated_features: %#llx\n" , pdsv->negotiated_features); |
228 | print_feature_bits_all(seq, features: pdsv->negotiated_features); |
229 | seq_printf(m: seq, fmt: "vdpa_index: %d\n" , pdsv->vdpa_index); |
230 | seq_printf(m: seq, fmt: "num_vqs: %d\n" , pdsv->num_vqs); |
231 | |
232 | return 0; |
233 | } |
234 | DEFINE_SHOW_ATTRIBUTE(config); |
235 | |
236 | static int vq_show(struct seq_file *seq, void *v) |
237 | { |
238 | struct pds_vdpa_vq_info *vq = seq->private; |
239 | |
240 | seq_printf(m: seq, fmt: "ready: %d\n" , vq->ready); |
241 | seq_printf(m: seq, fmt: "desc_addr: %#llx\n" , vq->desc_addr); |
242 | seq_printf(m: seq, fmt: "avail_addr: %#llx\n" , vq->avail_addr); |
243 | seq_printf(m: seq, fmt: "used_addr: %#llx\n" , vq->used_addr); |
244 | seq_printf(m: seq, fmt: "q_len: %d\n" , vq->q_len); |
245 | seq_printf(m: seq, fmt: "qid: %d\n" , vq->qid); |
246 | |
247 | seq_printf(m: seq, fmt: "doorbell: %#llx\n" , vq->doorbell); |
248 | seq_printf(m: seq, fmt: "avail_idx: %d\n" , vq->avail_idx); |
249 | seq_printf(m: seq, fmt: "used_idx: %d\n" , vq->used_idx); |
250 | seq_printf(m: seq, fmt: "irq: %d\n" , vq->irq); |
251 | seq_printf(m: seq, fmt: "irq-name: %s\n" , vq->irq_name); |
252 | |
253 | return 0; |
254 | } |
255 | DEFINE_SHOW_ATTRIBUTE(vq); |
256 | |
257 | void pds_vdpa_debugfs_add_vdpadev(struct pds_vdpa_aux *vdpa_aux) |
258 | { |
259 | int i; |
260 | |
261 | debugfs_create_file(name: "config" , mode: 0400, parent: vdpa_aux->dentry, data: vdpa_aux->pdsv, fops: &config_fops); |
262 | |
263 | for (i = 0; i < vdpa_aux->pdsv->num_vqs; i++) { |
264 | char name[16]; |
265 | |
266 | snprintf(buf: name, size: sizeof(name), fmt: "vq%02d" , i); |
267 | debugfs_create_file(name, mode: 0400, parent: vdpa_aux->dentry, |
268 | data: &vdpa_aux->pdsv->vqs[i], fops: &vq_fops); |
269 | } |
270 | } |
271 | |
272 | void pds_vdpa_debugfs_del_vdpadev(struct pds_vdpa_aux *vdpa_aux) |
273 | { |
274 | debugfs_remove_recursive(dentry: vdpa_aux->dentry); |
275 | vdpa_aux->dentry = NULL; |
276 | } |
277 | |
278 | void pds_vdpa_debugfs_reset_vdpadev(struct pds_vdpa_aux *vdpa_aux) |
279 | { |
280 | /* we don't keep track of the entries, so remove it all |
281 | * then rebuild the basics |
282 | */ |
283 | pds_vdpa_debugfs_del_vdpadev(vdpa_aux); |
284 | pds_vdpa_debugfs_add_pcidev(vdpa_aux); |
285 | pds_vdpa_debugfs_add_ident(vdpa_aux); |
286 | } |
287 | |