diff options
Diffstat (limited to 'drivers/usb/host/xhci-debugfs.c')
-rw-r--r-- | drivers/usb/host/xhci-debugfs.c | 117 |
1 files changed, 112 insertions, 5 deletions
diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c index 92e25a62fdb5..2c0fda57869e 100644 --- a/drivers/usb/host/xhci-debugfs.c +++ b/drivers/usb/host/xhci-debugfs.c @@ -274,7 +274,7 @@ static int xhci_slot_context_show(struct seq_file *s, void *unused) static int xhci_endpoint_context_show(struct seq_file *s, void *unused) { - int dci; + int ep_index; dma_addr_t dma; struct xhci_hcd *xhci; struct xhci_ep_ctx *ep_ctx; @@ -283,9 +283,9 @@ static int xhci_endpoint_context_show(struct seq_file *s, void *unused) xhci = hcd_to_xhci(bus_to_hcd(dev->udev->bus)); - for (dci = 1; dci < 32; dci++) { - ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, dci); - dma = dev->out_ctx->dma + dci * CTX_SIZE(xhci->hcc_params); + for (ep_index = 0; ep_index < 31; ep_index++) { + ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index); + dma = dev->out_ctx->dma + (ep_index + 1) * CTX_SIZE(xhci->hcc_params); seq_printf(s, "%pad: %s\n", &dma, xhci_decode_ep_context(le32_to_cpu(ep_ctx->ep_info), le32_to_cpu(ep_ctx->ep_info2), @@ -451,9 +451,11 @@ void xhci_debugfs_create_endpoint(struct xhci_hcd *xhci, if (!epriv) return; + epriv->show_ring = dev->eps[ep_index].ring; + snprintf(epriv->name, sizeof(epriv->name), "ep%02d", ep_index); epriv->root = xhci_debugfs_create_ring_dir(xhci, - &dev->eps[ep_index].ring, + &epriv->show_ring, epriv->name, spriv->root); spriv->eps[ep_index] = epriv; @@ -475,6 +477,111 @@ void xhci_debugfs_remove_endpoint(struct xhci_hcd *xhci, kfree(epriv); } +static int xhci_stream_id_show(struct seq_file *s, void *unused) +{ + struct xhci_ep_priv *epriv = s->private; + + if (!epriv->stream_info) + return -EPERM; + + seq_printf(s, "Show stream ID %d trb ring, supported [1 - %d]\n", + epriv->stream_id, epriv->stream_info->num_streams - 1); + + return 0; +} + +static int xhci_stream_id_open(struct inode *inode, struct file *file) +{ + return single_open(file, xhci_stream_id_show, inode->i_private); +} + +static ssize_t xhci_stream_id_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct seq_file *s = file->private_data; + struct xhci_ep_priv *epriv = s->private; + int ret; + u16 stream_id; /* MaxPStreams + 1 <= 16 */ + + if (!epriv->stream_info) + return -EPERM; + + /* Decimal number */ + ret = kstrtou16_from_user(ubuf, count, 10, &stream_id); + if (ret) + return ret; + + if (stream_id == 0 || stream_id >= epriv->stream_info->num_streams) + return -EINVAL; + + epriv->stream_id = stream_id; + epriv->show_ring = epriv->stream_info->stream_rings[stream_id]; + + return count; +} + +static const struct file_operations stream_id_fops = { + .open = xhci_stream_id_open, + .write = xhci_stream_id_write, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int xhci_stream_context_array_show(struct seq_file *s, void *unused) +{ + struct xhci_ep_priv *epriv = s->private; + struct xhci_stream_ctx *stream_ctx; + dma_addr_t dma; + int id; + + if (!epriv->stream_info) + return -EPERM; + + seq_printf(s, "Allocated %d streams and %d stream context array entries\n", + epriv->stream_info->num_streams, + epriv->stream_info->num_stream_ctxs); + + for (id = 0; id < epriv->stream_info->num_stream_ctxs; id++) { + stream_ctx = epriv->stream_info->stream_ctx_array + id; + dma = epriv->stream_info->ctx_array_dma + id * 16; + if (id < epriv->stream_info->num_streams) + seq_printf(s, "%pad stream id %d deq %016llx\n", &dma, + id, le64_to_cpu(stream_ctx->stream_ring)); + else + seq_printf(s, "%pad stream context entry not used deq %016llx\n", + &dma, le64_to_cpu(stream_ctx->stream_ring)); + } + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(xhci_stream_context_array); + +void xhci_debugfs_create_stream_files(struct xhci_hcd *xhci, + struct xhci_virt_device *dev, + int ep_index) +{ + struct xhci_slot_priv *spriv = dev->debugfs_private; + struct xhci_ep_priv *epriv; + + if (!spriv || !spriv->eps[ep_index] || + !dev->eps[ep_index].stream_info) + return; + + epriv = spriv->eps[ep_index]; + epriv->stream_info = dev->eps[ep_index].stream_info; + + /* Show trb ring of stream ID 1 by default */ + epriv->stream_id = 1; + epriv->show_ring = epriv->stream_info->stream_rings[1]; + debugfs_create_file("stream_id", 0644, + epriv->root, epriv, + &stream_id_fops); + debugfs_create_file("stream_context_array", 0444, + epriv->root, epriv, + &xhci_stream_context_array_fops); +} + void xhci_debugfs_create_slot(struct xhci_hcd *xhci, int slot_id) { struct xhci_slot_priv *priv; |