diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c index da528d07b815..b4f12013d487 100644 --- a/drivers/usb/host/xhci-debugfs.c +++ b/drivers/usb/host/xhci-debugfs.c @@ -779,6 +779,78 @@ static void xhci_debugfs_create_bandwidth(struct xhci_hcd *xhci, parent, &bw_fops); } +static void list_ring_segments(struct seq_file *s, struct xhci_ring *ring) +{ + struct xhci_segment *seg; + + xhci_for_each_ring_seg(ring->first_seg, seg) + seq_printf(s, "%.3x: %pad\n", seg->num, &seg->dma); +} + +static void list_event_ring_segments(struct seq_file *s, struct xhci_interrupter *ir) +{ + struct xhci_segment *seg; + + seq_printf(s, "IR%d ERST: %pad\n", ir->intr_num, &ir->erst.erst_dma_addr); + xhci_for_each_ring_seg(ir->event_ring->first_seg, seg) + seq_printf(s, "%.3x: %pad %c= %.16llx %.8x\n", seg->num, &seg->dma, + ir->erst.entries[seg->num].seg_addr == seg->dma ? '=' : '!', + ir->erst.entries[seg->num].seg_addr, + ir->erst.entries[seg->num].seg_size); + seq_putc(s, '\n'); +} + +static int xhci_memory_show(struct seq_file *s, void *unused) +{ + struct xhci_hcd *xhci = (struct xhci_hcd *)s->private; + int num_sp = HCS_MAX_SCRATCHPAD(xhci->hcs_params2); + + if (!xhci) + return -EFAULT; + + seq_puts(s, "CR:\n"); + list_ring_segments(s, xhci->cmd_ring); + seq_putc(s, '\n'); + + for (int i = 0; i < 1; i++) + if (xhci->interrupters[i]) + list_event_ring_segments(s, xhci->interrupters[i]); + + seq_printf(s, "DCBAA: %pad\n", &xhci->dcbaa->dma); + for (int i = 0; i < MAX_HC_SLOTS; i++) + seq_printf(s, "%.3x: %pad\n", i, xhci->dcbaa->dev_context_ptrs + i); + seq_putc(s, '\n'); + + if (xhci->scratchpad) { + seq_printf(s, "SBA: %pad\n", &xhci->scratchpad->sp_dma); + for (int i = 0; i < num_sp; i++) + seq_printf(s, "%.3x: %pad\n", i, xhci->scratchpad->sp_array + i); + seq_putc(s, '\n'); + } + + for (int d = 1; d < MAX_HC_SLOTS; d++) + for (int e = 0; e < EP_CTX_PER_DEV; e++) + if (xhci->devs[d] && xhci->devs[d]->eps[e].ring) { + seq_printf(s, "DEV %d EP %d:\n", d, e); + list_ring_segments(s, xhci->devs[d]->eps[e].ring); + seq_putc(s, '\n'); + } + + return 0; +} + +static int memory_open(struct inode *inode, struct file *file) +{ + return single_open(file, xhci_memory_show, inode->i_private); +} + +static const struct file_operations memory_fops = { + .open = memory_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + void xhci_debugfs_init(struct xhci_hcd *xhci) { struct device *dev = xhci_to_hcd(xhci)->self.controller; @@ -831,6 +903,8 @@ void xhci_debugfs_init(struct xhci_hcd *xhci) xhci_debugfs_create_ports(xhci, xhci->debugfs_root); xhci_debugfs_create_bandwidth(xhci, xhci->debugfs_root); + + debugfs_create_file("memory", 0444, xhci->debugfs_root, xhci, &memory_fops); } void xhci_debugfs_exit(struct xhci_hcd *xhci)