Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * xhci-debugfs.c - xHCI debugfs interface
4 : : *
5 : : * Copyright (C) 2017 Intel Corporation
6 : : *
7 : : * Author: Lu Baolu <baolu.lu@linux.intel.com>
8 : : */
9 : :
10 : : #include <linux/slab.h>
11 : : #include <linux/uaccess.h>
12 : :
13 : : #include "xhci.h"
14 : : #include "xhci-debugfs.h"
15 : :
16 : : static const struct debugfs_reg32 xhci_cap_regs[] = {
17 : : dump_register(CAPLENGTH),
18 : : dump_register(HCSPARAMS1),
19 : : dump_register(HCSPARAMS2),
20 : : dump_register(HCSPARAMS3),
21 : : dump_register(HCCPARAMS1),
22 : : dump_register(DOORBELLOFF),
23 : : dump_register(RUNTIMEOFF),
24 : : dump_register(HCCPARAMS2),
25 : : };
26 : :
27 : : static const struct debugfs_reg32 xhci_op_regs[] = {
28 : : dump_register(USBCMD),
29 : : dump_register(USBSTS),
30 : : dump_register(PAGESIZE),
31 : : dump_register(DNCTRL),
32 : : dump_register(CRCR),
33 : : dump_register(DCBAAP_LOW),
34 : : dump_register(DCBAAP_HIGH),
35 : : dump_register(CONFIG),
36 : : };
37 : :
38 : : static const struct debugfs_reg32 xhci_runtime_regs[] = {
39 : : dump_register(MFINDEX),
40 : : dump_register(IR0_IMAN),
41 : : dump_register(IR0_IMOD),
42 : : dump_register(IR0_ERSTSZ),
43 : : dump_register(IR0_ERSTBA_LOW),
44 : : dump_register(IR0_ERSTBA_HIGH),
45 : : dump_register(IR0_ERDP_LOW),
46 : : dump_register(IR0_ERDP_HIGH),
47 : : };
48 : :
49 : : static const struct debugfs_reg32 xhci_extcap_legsup[] = {
50 : : dump_register(EXTCAP_USBLEGSUP),
51 : : dump_register(EXTCAP_USBLEGCTLSTS),
52 : : };
53 : :
54 : : static const struct debugfs_reg32 xhci_extcap_protocol[] = {
55 : : dump_register(EXTCAP_REVISION),
56 : : dump_register(EXTCAP_NAME),
57 : : dump_register(EXTCAP_PORTINFO),
58 : : dump_register(EXTCAP_PORTTYPE),
59 : : dump_register(EXTCAP_MANTISSA1),
60 : : dump_register(EXTCAP_MANTISSA2),
61 : : dump_register(EXTCAP_MANTISSA3),
62 : : dump_register(EXTCAP_MANTISSA4),
63 : : dump_register(EXTCAP_MANTISSA5),
64 : : dump_register(EXTCAP_MANTISSA6),
65 : : };
66 : :
67 : : static const struct debugfs_reg32 xhci_extcap_dbc[] = {
68 : : dump_register(EXTCAP_DBC_CAPABILITY),
69 : : dump_register(EXTCAP_DBC_DOORBELL),
70 : : dump_register(EXTCAP_DBC_ERSTSIZE),
71 : : dump_register(EXTCAP_DBC_ERST_LOW),
72 : : dump_register(EXTCAP_DBC_ERST_HIGH),
73 : : dump_register(EXTCAP_DBC_ERDP_LOW),
74 : : dump_register(EXTCAP_DBC_ERDP_HIGH),
75 : : dump_register(EXTCAP_DBC_CONTROL),
76 : : dump_register(EXTCAP_DBC_STATUS),
77 : : dump_register(EXTCAP_DBC_PORTSC),
78 : : dump_register(EXTCAP_DBC_CONT_LOW),
79 : : dump_register(EXTCAP_DBC_CONT_HIGH),
80 : : dump_register(EXTCAP_DBC_DEVINFO1),
81 : : dump_register(EXTCAP_DBC_DEVINFO2),
82 : : };
83 : :
84 : : static struct dentry *xhci_debugfs_root;
85 : :
86 : 0 : static struct xhci_regset *xhci_debugfs_alloc_regset(struct xhci_hcd *xhci)
87 : : {
88 : 0 : struct xhci_regset *regset;
89 : :
90 : 0 : regset = kzalloc(sizeof(*regset), GFP_KERNEL);
91 [ # # ]: 0 : if (!regset)
92 : : return NULL;
93 : :
94 : : /*
95 : : * The allocation and free of regset are executed in order.
96 : : * We needn't a lock here.
97 : : */
98 : 0 : INIT_LIST_HEAD(®set->list);
99 : 0 : list_add_tail(®set->list, &xhci->regset_list);
100 : :
101 : 0 : return regset;
102 : : }
103 : :
104 : 0 : static void xhci_debugfs_free_regset(struct xhci_regset *regset)
105 : : {
106 : 0 : if (!regset)
107 : : return;
108 : :
109 : 0 : list_del(®set->list);
110 : 0 : kfree(regset);
111 : : }
112 : :
113 : 0 : static void xhci_debugfs_regset(struct xhci_hcd *xhci, u32 base,
114 : : const struct debugfs_reg32 *regs,
115 : : size_t nregs, struct dentry *parent,
116 : : const char *fmt, ...)
117 : : {
118 : 0 : struct xhci_regset *rgs;
119 : 0 : va_list args;
120 : 0 : struct debugfs_regset32 *regset;
121 : 0 : struct usb_hcd *hcd = xhci_to_hcd(xhci);
122 : :
123 : 0 : rgs = xhci_debugfs_alloc_regset(xhci);
124 [ # # ]: 0 : if (!rgs)
125 : 0 : return;
126 : :
127 : 0 : va_start(args, fmt);
128 : 0 : vsnprintf(rgs->name, sizeof(rgs->name), fmt, args);
129 : 0 : va_end(args);
130 : :
131 : 0 : regset = &rgs->regset;
132 : 0 : regset->regs = regs;
133 : 0 : regset->nregs = nregs;
134 : 0 : regset->base = hcd->regs + base;
135 : :
136 : 0 : debugfs_create_regset32((const char *)rgs->name, 0444, parent, regset);
137 : : }
138 : :
139 : 0 : static void xhci_debugfs_extcap_regset(struct xhci_hcd *xhci, int cap_id,
140 : : const struct debugfs_reg32 *regs,
141 : : size_t n, const char *cap_name)
142 : : {
143 : 0 : u32 offset;
144 : 0 : int index = 0;
145 : 0 : size_t psic, nregs = n;
146 : 0 : void __iomem *base = &xhci->cap_regs->hc_capbase;
147 : :
148 : 0 : offset = xhci_find_next_ext_cap(base, 0, cap_id);
149 [ # # ]: 0 : while (offset) {
150 [ # # ]: 0 : if (cap_id == XHCI_EXT_CAPS_PROTOCOL) {
151 : 0 : psic = XHCI_EXT_PORT_PSIC(readl(base + offset + 8));
152 : 0 : nregs = min(4 + psic, n);
153 : : }
154 : :
155 : 0 : xhci_debugfs_regset(xhci, offset, regs, nregs,
156 : : xhci->debugfs_root, "%s:%02d",
157 : : cap_name, index);
158 : 0 : offset = xhci_find_next_ext_cap(base, offset, cap_id);
159 : 0 : index++;
160 : : }
161 : 0 : }
162 : :
163 : 0 : static int xhci_ring_enqueue_show(struct seq_file *s, void *unused)
164 : : {
165 : 0 : dma_addr_t dma;
166 : 0 : struct xhci_ring *ring = *(struct xhci_ring **)s->private;
167 : :
168 : 0 : dma = xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue);
169 : 0 : seq_printf(s, "%pad\n", &dma);
170 : :
171 : 0 : return 0;
172 : : }
173 : :
174 : 0 : static int xhci_ring_dequeue_show(struct seq_file *s, void *unused)
175 : : {
176 : 0 : dma_addr_t dma;
177 : 0 : struct xhci_ring *ring = *(struct xhci_ring **)s->private;
178 : :
179 : 0 : dma = xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue);
180 : 0 : seq_printf(s, "%pad\n", &dma);
181 : :
182 : 0 : return 0;
183 : : }
184 : :
185 : 0 : static int xhci_ring_cycle_show(struct seq_file *s, void *unused)
186 : : {
187 : 0 : struct xhci_ring *ring = *(struct xhci_ring **)s->private;
188 : :
189 : 0 : seq_printf(s, "%d\n", ring->cycle_state);
190 : :
191 : 0 : return 0;
192 : : }
193 : :
194 : : static void xhci_ring_dump_segment(struct seq_file *s,
195 : : struct xhci_segment *seg)
196 : : {
197 : : int i;
198 : : dma_addr_t dma;
199 : : union xhci_trb *trb;
200 : :
201 : : for (i = 0; i < TRBS_PER_SEGMENT; i++) {
202 : : trb = &seg->trbs[i];
203 : : dma = seg->dma + i * sizeof(*trb);
204 : : seq_printf(s, "%pad: %s\n", &dma,
205 : : xhci_decode_trb(le32_to_cpu(trb->generic.field[0]),
206 : : le32_to_cpu(trb->generic.field[1]),
207 : : le32_to_cpu(trb->generic.field[2]),
208 : : le32_to_cpu(trb->generic.field[3])));
209 : : }
210 : : }
211 : :
212 : 0 : static int xhci_ring_trb_show(struct seq_file *s, void *unused)
213 : : {
214 : 0 : int i;
215 : 0 : struct xhci_ring *ring = *(struct xhci_ring **)s->private;
216 : 0 : struct xhci_segment *seg = ring->first_seg;
217 : :
218 [ # # ]: 0 : for (i = 0; i < ring->num_segs; i++) {
219 : 0 : xhci_ring_dump_segment(s, seg);
220 : 0 : seg = seg->next;
221 : : }
222 : :
223 : 0 : return 0;
224 : : }
225 : :
226 : : static struct xhci_file_map ring_files[] = {
227 : : {"enqueue", xhci_ring_enqueue_show, },
228 : : {"dequeue", xhci_ring_dequeue_show, },
229 : : {"cycle", xhci_ring_cycle_show, },
230 : : {"trbs", xhci_ring_trb_show, },
231 : : };
232 : :
233 : 0 : static int xhci_ring_open(struct inode *inode, struct file *file)
234 : : {
235 : 0 : int i;
236 : 0 : struct xhci_file_map *f_map;
237 [ # # ]: 0 : const char *file_name = file_dentry(file)->d_iname;
238 : :
239 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(ring_files); i++) {
240 : 0 : f_map = &ring_files[i];
241 : :
242 [ # # ]: 0 : if (strcmp(f_map->name, file_name) == 0)
243 : : break;
244 : : }
245 : :
246 : 0 : return single_open(file, f_map->show, inode->i_private);
247 : : }
248 : :
249 : : static const struct file_operations xhci_ring_fops = {
250 : : .open = xhci_ring_open,
251 : : .read = seq_read,
252 : : .llseek = seq_lseek,
253 : : .release = single_release,
254 : : };
255 : :
256 : 0 : static int xhci_slot_context_show(struct seq_file *s, void *unused)
257 : : {
258 : 0 : struct xhci_hcd *xhci;
259 : 0 : struct xhci_slot_ctx *slot_ctx;
260 : 0 : struct xhci_slot_priv *priv = s->private;
261 : 0 : struct xhci_virt_device *dev = priv->dev;
262 : :
263 : 0 : xhci = hcd_to_xhci(bus_to_hcd(dev->udev->bus));
264 : 0 : slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
265 : 0 : seq_printf(s, "%pad: %s\n", &dev->out_ctx->dma,
266 : 0 : xhci_decode_slot_context(le32_to_cpu(slot_ctx->dev_info),
267 : 0 : le32_to_cpu(slot_ctx->dev_info2),
268 : 0 : le32_to_cpu(slot_ctx->tt_info),
269 : 0 : le32_to_cpu(slot_ctx->dev_state)));
270 : :
271 : 0 : return 0;
272 : : }
273 : :
274 : 0 : static int xhci_endpoint_context_show(struct seq_file *s, void *unused)
275 : : {
276 : 0 : int dci;
277 : 0 : dma_addr_t dma;
278 : 0 : struct xhci_hcd *xhci;
279 : 0 : struct xhci_ep_ctx *ep_ctx;
280 : 0 : struct xhci_slot_priv *priv = s->private;
281 : 0 : struct xhci_virt_device *dev = priv->dev;
282 : :
283 : 0 : xhci = hcd_to_xhci(bus_to_hcd(dev->udev->bus));
284 : :
285 [ # # ]: 0 : for (dci = 1; dci < 32; dci++) {
286 : 0 : ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, dci);
287 [ # # ]: 0 : dma = dev->out_ctx->dma + dci * CTX_SIZE(xhci->hcc_params);
288 : 0 : seq_printf(s, "%pad: %s\n", &dma,
289 : 0 : xhci_decode_ep_context(le32_to_cpu(ep_ctx->ep_info),
290 : 0 : le32_to_cpu(ep_ctx->ep_info2),
291 : 0 : le64_to_cpu(ep_ctx->deq),
292 : 0 : le32_to_cpu(ep_ctx->tx_info)));
293 : : }
294 : :
295 : 0 : return 0;
296 : : }
297 : :
298 : 0 : static int xhci_device_name_show(struct seq_file *s, void *unused)
299 : : {
300 : 0 : struct xhci_slot_priv *priv = s->private;
301 : 0 : struct xhci_virt_device *dev = priv->dev;
302 : :
303 [ # # ]: 0 : seq_printf(s, "%s\n", dev_name(&dev->udev->dev));
304 : :
305 : 0 : return 0;
306 : : }
307 : :
308 : : static struct xhci_file_map context_files[] = {
309 : : {"name", xhci_device_name_show, },
310 : : {"slot-context", xhci_slot_context_show, },
311 : : {"ep-context", xhci_endpoint_context_show, },
312 : : };
313 : :
314 : 0 : static int xhci_context_open(struct inode *inode, struct file *file)
315 : : {
316 : 0 : int i;
317 : 0 : struct xhci_file_map *f_map;
318 [ # # ]: 0 : const char *file_name = file_dentry(file)->d_iname;
319 : :
320 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(context_files); i++) {
321 : 0 : f_map = &context_files[i];
322 : :
323 [ # # ]: 0 : if (strcmp(f_map->name, file_name) == 0)
324 : : break;
325 : : }
326 : :
327 : 0 : return single_open(file, f_map->show, inode->i_private);
328 : : }
329 : :
330 : : static const struct file_operations xhci_context_fops = {
331 : : .open = xhci_context_open,
332 : : .read = seq_read,
333 : : .llseek = seq_lseek,
334 : : .release = single_release,
335 : : };
336 : :
337 : :
338 : :
339 : 0 : static int xhci_portsc_show(struct seq_file *s, void *unused)
340 : : {
341 : 0 : struct xhci_port *port = s->private;
342 : 0 : u32 portsc;
343 : :
344 : 0 : portsc = readl(port->addr);
345 : 0 : seq_printf(s, "%s\n", xhci_decode_portsc(portsc));
346 : :
347 : 0 : return 0;
348 : : }
349 : :
350 : 0 : static int xhci_port_open(struct inode *inode, struct file *file)
351 : : {
352 : 0 : return single_open(file, xhci_portsc_show, inode->i_private);
353 : : }
354 : :
355 : 0 : static ssize_t xhci_port_write(struct file *file, const char __user *ubuf,
356 : : size_t count, loff_t *ppos)
357 : : {
358 : 0 : struct seq_file *s = file->private_data;
359 : 0 : struct xhci_port *port = s->private;
360 : 0 : struct xhci_hcd *xhci = hcd_to_xhci(port->rhub->hcd);
361 : 0 : char buf[32];
362 : 0 : u32 portsc;
363 : 0 : unsigned long flags;
364 : :
365 [ # # ]: 0 : if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
366 : : return -EFAULT;
367 : :
368 [ # # ]: 0 : if (!strncmp(buf, "compliance", 10)) {
369 : : /* If CTC is clear, compliance is enabled by default */
370 [ # # ]: 0 : if (!HCC2_CTC(xhci->hcc_params2))
371 : 0 : return count;
372 : 0 : spin_lock_irqsave(&xhci->lock, flags);
373 : : /* compliance mode can only be enabled on ports in RxDetect */
374 : 0 : portsc = readl(port->addr);
375 [ # # ]: 0 : if ((portsc & PORT_PLS_MASK) != XDEV_RXDETECT) {
376 : 0 : spin_unlock_irqrestore(&xhci->lock, flags);
377 : 0 : return -EPERM;
378 : : }
379 : 0 : portsc = xhci_port_state_to_neutral(portsc);
380 : 0 : portsc &= ~PORT_PLS_MASK;
381 : 0 : portsc |= PORT_LINK_STROBE | XDEV_COMP_MODE;
382 : 0 : writel(portsc, port->addr);
383 : 0 : spin_unlock_irqrestore(&xhci->lock, flags);
384 : : } else {
385 : : return -EINVAL;
386 : : }
387 : 0 : return count;
388 : : }
389 : :
390 : : static const struct file_operations port_fops = {
391 : : .open = xhci_port_open,
392 : : .write = xhci_port_write,
393 : : .read = seq_read,
394 : : .llseek = seq_lseek,
395 : : .release = single_release,
396 : : };
397 : :
398 : 0 : static void xhci_debugfs_create_files(struct xhci_hcd *xhci,
399 : : struct xhci_file_map *files,
400 : : size_t nentries, void *data,
401 : : struct dentry *parent,
402 : : const struct file_operations *fops)
403 : : {
404 : : int i;
405 : :
406 [ # # ]: 0 : for (i = 0; i < nentries; i++)
407 : 0 : debugfs_create_file(files[i].name, 0444, parent, data, fops);
408 : : }
409 : :
410 : : static struct dentry *xhci_debugfs_create_ring_dir(struct xhci_hcd *xhci,
411 : : struct xhci_ring **ring,
412 : : const char *name,
413 : : struct dentry *parent)
414 : : {
415 : : struct dentry *dir;
416 : :
417 : : dir = debugfs_create_dir(name, parent);
418 : : xhci_debugfs_create_files(xhci, ring_files, ARRAY_SIZE(ring_files),
419 : : ring, dir, &xhci_ring_fops);
420 : :
421 : : return dir;
422 : : }
423 : :
424 : 0 : static void xhci_debugfs_create_context_files(struct xhci_hcd *xhci,
425 : : struct dentry *parent,
426 : : int slot_id)
427 : : {
428 : 0 : struct xhci_virt_device *dev = xhci->devs[slot_id];
429 : :
430 : 0 : xhci_debugfs_create_files(xhci, context_files,
431 : : ARRAY_SIZE(context_files),
432 : : dev->debugfs_private,
433 : : parent, &xhci_context_fops);
434 : 0 : }
435 : :
436 : 0 : void xhci_debugfs_create_endpoint(struct xhci_hcd *xhci,
437 : : struct xhci_virt_device *dev,
438 : : int ep_index)
439 : : {
440 : 0 : struct xhci_ep_priv *epriv;
441 : 0 : struct xhci_slot_priv *spriv = dev->debugfs_private;
442 : :
443 [ # # ]: 0 : if (!spriv)
444 : : return;
445 : :
446 [ # # ]: 0 : if (spriv->eps[ep_index])
447 : : return;
448 : :
449 : 0 : epriv = kzalloc(sizeof(*epriv), GFP_KERNEL);
450 [ # # ]: 0 : if (!epriv)
451 : : return;
452 : :
453 : 0 : snprintf(epriv->name, sizeof(epriv->name), "ep%02d", ep_index);
454 : 0 : epriv->root = xhci_debugfs_create_ring_dir(xhci,
455 : : &dev->eps[ep_index].ring,
456 : : epriv->name,
457 : : spriv->root);
458 : 0 : spriv->eps[ep_index] = epriv;
459 : : }
460 : :
461 : 0 : void xhci_debugfs_remove_endpoint(struct xhci_hcd *xhci,
462 : : struct xhci_virt_device *dev,
463 : : int ep_index)
464 : : {
465 : 0 : struct xhci_ep_priv *epriv;
466 : 0 : struct xhci_slot_priv *spriv = dev->debugfs_private;
467 : :
468 [ # # # # ]: 0 : if (!spriv || !spriv->eps[ep_index])
469 : : return;
470 : :
471 : 0 : epriv = spriv->eps[ep_index];
472 : 0 : debugfs_remove_recursive(epriv->root);
473 : 0 : spriv->eps[ep_index] = NULL;
474 : 0 : kfree(epriv);
475 : : }
476 : :
477 : 0 : void xhci_debugfs_create_slot(struct xhci_hcd *xhci, int slot_id)
478 : : {
479 : 0 : struct xhci_slot_priv *priv;
480 : 0 : struct xhci_virt_device *dev = xhci->devs[slot_id];
481 : :
482 : 0 : priv = kzalloc(sizeof(*priv), GFP_KERNEL);
483 [ # # ]: 0 : if (!priv)
484 : : return;
485 : :
486 : 0 : snprintf(priv->name, sizeof(priv->name), "%02d", slot_id);
487 : 0 : priv->root = debugfs_create_dir(priv->name, xhci->debugfs_slots);
488 : 0 : priv->dev = dev;
489 : 0 : dev->debugfs_private = priv;
490 : :
491 : 0 : xhci_debugfs_create_ring_dir(xhci, &dev->eps[0].ring,
492 : : "ep00", priv->root);
493 : :
494 : 0 : xhci_debugfs_create_context_files(xhci, priv->root, slot_id);
495 : : }
496 : :
497 : 0 : void xhci_debugfs_remove_slot(struct xhci_hcd *xhci, int slot_id)
498 : : {
499 : 0 : int i;
500 : 0 : struct xhci_slot_priv *priv;
501 : 0 : struct xhci_virt_device *dev = xhci->devs[slot_id];
502 : :
503 [ # # # # ]: 0 : if (!dev || !dev->debugfs_private)
504 : : return;
505 : :
506 : 0 : priv = dev->debugfs_private;
507 : :
508 : 0 : debugfs_remove_recursive(priv->root);
509 : :
510 [ # # ]: 0 : for (i = 0; i < 31; i++)
511 : 0 : kfree(priv->eps[i]);
512 : :
513 : 0 : kfree(priv);
514 : 0 : dev->debugfs_private = NULL;
515 : : }
516 : :
517 : : static void xhci_debugfs_create_ports(struct xhci_hcd *xhci,
518 : : struct dentry *parent)
519 : : {
520 : : unsigned int num_ports;
521 : : char port_name[8];
522 : : struct xhci_port *port;
523 : : struct dentry *dir;
524 : :
525 : : num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
526 : :
527 : : parent = debugfs_create_dir("ports", parent);
528 : :
529 : : while (num_ports--) {
530 : : scnprintf(port_name, sizeof(port_name), "port%02d",
531 : : num_ports + 1);
532 : : dir = debugfs_create_dir(port_name, parent);
533 : : port = &xhci->hw_ports[num_ports];
534 : : debugfs_create_file("portsc", 0644, dir, port, &port_fops);
535 : : }
536 : : }
537 : :
538 : 0 : void xhci_debugfs_init(struct xhci_hcd *xhci)
539 : : {
540 [ # # ]: 0 : struct device *dev = xhci_to_hcd(xhci)->self.controller;
541 : :
542 [ # # ]: 0 : xhci->debugfs_root = debugfs_create_dir(dev_name(dev),
543 : : xhci_debugfs_root);
544 : :
545 : 0 : INIT_LIST_HEAD(&xhci->regset_list);
546 : :
547 : 0 : xhci_debugfs_regset(xhci,
548 : : 0,
549 : : xhci_cap_regs, ARRAY_SIZE(xhci_cap_regs),
550 : : xhci->debugfs_root, "reg-cap");
551 : :
552 : 0 : xhci_debugfs_regset(xhci,
553 : 0 : HC_LENGTH(readl(&xhci->cap_regs->hc_capbase)),
554 : : xhci_op_regs, ARRAY_SIZE(xhci_op_regs),
555 : : xhci->debugfs_root, "reg-op");
556 : :
557 : 0 : xhci_debugfs_regset(xhci,
558 : 0 : readl(&xhci->cap_regs->run_regs_off) & RTSOFF_MASK,
559 : : xhci_runtime_regs, ARRAY_SIZE(xhci_runtime_regs),
560 : : xhci->debugfs_root, "reg-runtime");
561 : :
562 : 0 : xhci_debugfs_extcap_regset(xhci, XHCI_EXT_CAPS_LEGACY,
563 : : xhci_extcap_legsup,
564 : : ARRAY_SIZE(xhci_extcap_legsup),
565 : : "reg-ext-legsup");
566 : :
567 : 0 : xhci_debugfs_extcap_regset(xhci, XHCI_EXT_CAPS_PROTOCOL,
568 : : xhci_extcap_protocol,
569 : : ARRAY_SIZE(xhci_extcap_protocol),
570 : : "reg-ext-protocol");
571 : :
572 : 0 : xhci_debugfs_extcap_regset(xhci, XHCI_EXT_CAPS_DEBUG,
573 : : xhci_extcap_dbc,
574 : : ARRAY_SIZE(xhci_extcap_dbc),
575 : : "reg-ext-dbc");
576 : :
577 : 0 : xhci_debugfs_create_ring_dir(xhci, &xhci->cmd_ring,
578 : : "command-ring",
579 : : xhci->debugfs_root);
580 : :
581 : 0 : xhci_debugfs_create_ring_dir(xhci, &xhci->event_ring,
582 : : "event-ring",
583 : : xhci->debugfs_root);
584 : :
585 : 0 : xhci->debugfs_slots = debugfs_create_dir("devices", xhci->debugfs_root);
586 : :
587 : 0 : xhci_debugfs_create_ports(xhci, xhci->debugfs_root);
588 : 0 : }
589 : :
590 : 0 : void xhci_debugfs_exit(struct xhci_hcd *xhci)
591 : : {
592 : 0 : struct xhci_regset *rgs, *tmp;
593 : :
594 : 0 : debugfs_remove_recursive(xhci->debugfs_root);
595 : 0 : xhci->debugfs_root = NULL;
596 : 0 : xhci->debugfs_slots = NULL;
597 : :
598 [ # # ]: 0 : list_for_each_entry_safe(rgs, tmp, &xhci->regset_list, list)
599 [ # # ]: 0 : xhci_debugfs_free_regset(rgs);
600 : 0 : }
601 : :
602 : 78 : void __init xhci_debugfs_create_root(void)
603 : : {
604 : 78 : xhci_debugfs_root = debugfs_create_dir("xhci", usb_debug_root);
605 : 78 : }
606 : :
607 : 0 : void __exit xhci_debugfs_remove_root(void)
608 : : {
609 : 0 : debugfs_remove_recursive(xhci_debugfs_root);
610 : 0 : xhci_debugfs_root = NULL;
611 : 0 : }
|