Merge tag 'usb-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
[linux-2.6-microblaze.git] / drivers / usb / host / xhci-debugfs.c
index c88bffd..dc832dd 100644 (file)
@@ -198,12 +198,13 @@ static void xhci_ring_dump_segment(struct seq_file *s,
        int                     i;
        dma_addr_t              dma;
        union xhci_trb          *trb;
+       char                    str[XHCI_MSG_MAX];
 
        for (i = 0; i < TRBS_PER_SEGMENT; i++) {
                trb = &seg->trbs[i];
                dma = seg->dma + i * sizeof(*trb);
                seq_printf(s, "%pad: %s\n", &dma,
-                          xhci_decode_trb(le32_to_cpu(trb->generic.field[0]),
+                          xhci_decode_trb(str, XHCI_MSG_MAX, le32_to_cpu(trb->generic.field[0]),
                                           le32_to_cpu(trb->generic.field[1]),
                                           le32_to_cpu(trb->generic.field[2]),
                                           le32_to_cpu(trb->generic.field[3])));
@@ -260,11 +261,13 @@ static int xhci_slot_context_show(struct seq_file *s, void *unused)
        struct xhci_slot_ctx    *slot_ctx;
        struct xhci_slot_priv   *priv = s->private;
        struct xhci_virt_device *dev = priv->dev;
+       char                    str[XHCI_MSG_MAX];
 
        xhci = hcd_to_xhci(bus_to_hcd(dev->udev->bus));
        slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
        seq_printf(s, "%pad: %s\n", &dev->out_ctx->dma,
-                  xhci_decode_slot_context(le32_to_cpu(slot_ctx->dev_info),
+                  xhci_decode_slot_context(str,
+                                           le32_to_cpu(slot_ctx->dev_info),
                                            le32_to_cpu(slot_ctx->dev_info2),
                                            le32_to_cpu(slot_ctx->tt_info),
                                            le32_to_cpu(slot_ctx->dev_state)));
@@ -280,6 +283,7 @@ static int xhci_endpoint_context_show(struct seq_file *s, void *unused)
        struct xhci_ep_ctx      *ep_ctx;
        struct xhci_slot_priv   *priv = s->private;
        struct xhci_virt_device *dev = priv->dev;
+       char                    str[XHCI_MSG_MAX];
 
        xhci = hcd_to_xhci(bus_to_hcd(dev->udev->bus));
 
@@ -287,7 +291,8 @@ static int xhci_endpoint_context_show(struct seq_file *s, void *unused)
                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),
+                          xhci_decode_ep_context(str,
+                                                 le32_to_cpu(ep_ctx->ep_info),
                                                  le32_to_cpu(ep_ctx->ep_info2),
                                                  le64_to_cpu(ep_ctx->deq),
                                                  le32_to_cpu(ep_ctx->tx_info)));
@@ -341,9 +346,10 @@ static int xhci_portsc_show(struct seq_file *s, void *unused)
 {
        struct xhci_port        *port = s->private;
        u32                     portsc;
+       char                    str[XHCI_MSG_MAX];
 
        portsc = readl(port->addr);
-       seq_printf(s, "%s\n", xhci_decode_portsc(portsc));
+       seq_printf(s, "%s\n", xhci_decode_portsc(str, portsc));
 
        return 0;
 }
@@ -451,9 +457,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 +483,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;