Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: xhci: add debugfs support for ep with stream

To show the trb ring of streams, use the exsiting ring files of bulk ep
to show trb ring of one specific stream ID, which stream ID's trb ring
will be shown, is controlled by a new debugfs file stream_id, this is to
avoid to create a large number of dir for every allocate stream IDs,
another debugfs file stream_context_array is created to show all the
allocated stream context array entries.

Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20200918131752.16488-11-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Li Jun and committed by
Greg Kroah-Hartman
673d7468 167657a1

+119 -1
+108 -1
drivers/usb/host/xhci-debugfs.c
··· 451 451 if (!epriv) 452 452 return; 453 453 454 + epriv->show_ring = dev->eps[ep_index].ring; 455 + 454 456 snprintf(epriv->name, sizeof(epriv->name), "ep%02d", ep_index); 455 457 epriv->root = xhci_debugfs_create_ring_dir(xhci, 456 - &dev->eps[ep_index].ring, 458 + &epriv->show_ring, 457 459 epriv->name, 458 460 spriv->root); 459 461 spriv->eps[ep_index] = epriv; ··· 475 473 debugfs_remove_recursive(epriv->root); 476 474 spriv->eps[ep_index] = NULL; 477 475 kfree(epriv); 476 + } 477 + 478 + static int xhci_stream_id_show(struct seq_file *s, void *unused) 479 + { 480 + struct xhci_ep_priv *epriv = s->private; 481 + 482 + if (!epriv->stream_info) 483 + return -EPERM; 484 + 485 + seq_printf(s, "Show stream ID %d trb ring, supported [1 - %d]\n", 486 + epriv->stream_id, epriv->stream_info->num_streams - 1); 487 + 488 + return 0; 489 + } 490 + 491 + static int xhci_stream_id_open(struct inode *inode, struct file *file) 492 + { 493 + return single_open(file, xhci_stream_id_show, inode->i_private); 494 + } 495 + 496 + static ssize_t xhci_stream_id_write(struct file *file, const char __user *ubuf, 497 + size_t count, loff_t *ppos) 498 + { 499 + struct seq_file *s = file->private_data; 500 + struct xhci_ep_priv *epriv = s->private; 501 + int ret; 502 + u16 stream_id; /* MaxPStreams + 1 <= 16 */ 503 + 504 + if (!epriv->stream_info) 505 + return -EPERM; 506 + 507 + /* Decimal number */ 508 + ret = kstrtou16_from_user(ubuf, count, 10, &stream_id); 509 + if (ret) 510 + return ret; 511 + 512 + if (stream_id == 0 || stream_id >= epriv->stream_info->num_streams) 513 + return -EINVAL; 514 + 515 + epriv->stream_id = stream_id; 516 + epriv->show_ring = epriv->stream_info->stream_rings[stream_id]; 517 + 518 + return count; 519 + } 520 + 521 + static const struct file_operations stream_id_fops = { 522 + .open = xhci_stream_id_open, 523 + .write = xhci_stream_id_write, 524 + .read = seq_read, 525 + .llseek = seq_lseek, 526 + .release = single_release, 527 + }; 528 + 529 + static int xhci_stream_context_array_show(struct seq_file *s, void *unused) 530 + { 531 + struct xhci_ep_priv *epriv = s->private; 532 + struct xhci_stream_ctx *stream_ctx; 533 + dma_addr_t dma; 534 + int id; 535 + 536 + if (!epriv->stream_info) 537 + return -EPERM; 538 + 539 + seq_printf(s, "Allocated %d streams and %d stream context array entries\n", 540 + epriv->stream_info->num_streams, 541 + epriv->stream_info->num_stream_ctxs); 542 + 543 + for (id = 0; id < epriv->stream_info->num_stream_ctxs; id++) { 544 + stream_ctx = epriv->stream_info->stream_ctx_array + id; 545 + dma = epriv->stream_info->ctx_array_dma + id * 16; 546 + if (id < epriv->stream_info->num_streams) 547 + seq_printf(s, "%pad stream id %d deq %016llx\n", &dma, 548 + id, le64_to_cpu(stream_ctx->stream_ring)); 549 + else 550 + seq_printf(s, "%pad stream context entry not used deq %016llx\n", 551 + &dma, le64_to_cpu(stream_ctx->stream_ring)); 552 + } 553 + 554 + return 0; 555 + } 556 + DEFINE_SHOW_ATTRIBUTE(xhci_stream_context_array); 557 + 558 + void xhci_debugfs_create_stream_files(struct xhci_hcd *xhci, 559 + struct xhci_virt_device *dev, 560 + int ep_index) 561 + { 562 + struct xhci_slot_priv *spriv = dev->debugfs_private; 563 + struct xhci_ep_priv *epriv; 564 + 565 + if (!spriv || !spriv->eps[ep_index] || 566 + !dev->eps[ep_index].stream_info) 567 + return; 568 + 569 + epriv = spriv->eps[ep_index]; 570 + epriv->stream_info = dev->eps[ep_index].stream_info; 571 + 572 + /* Show trb ring of stream ID 1 by default */ 573 + epriv->stream_id = 1; 574 + epriv->show_ring = epriv->stream_info->stream_rings[1]; 575 + debugfs_create_file("stream_id", 0644, 576 + epriv->root, epriv, 577 + &stream_id_fops); 578 + debugfs_create_file("stream_context_array", 0444, 579 + epriv->root, epriv, 580 + &xhci_stream_context_array_fops); 478 581 } 479 582 480 583 void xhci_debugfs_create_slot(struct xhci_hcd *xhci, int slot_id)
+10
drivers/usb/host/xhci-debugfs.h
··· 91 91 struct xhci_ep_priv { 92 92 char name[DEBUGFS_NAMELEN]; 93 93 struct dentry *root; 94 + struct xhci_stream_info *stream_info; 95 + struct xhci_ring *show_ring; 96 + unsigned int stream_id; 94 97 }; 95 98 96 99 struct xhci_slot_priv { ··· 116 113 void xhci_debugfs_remove_endpoint(struct xhci_hcd *xhci, 117 114 struct xhci_virt_device *virt_dev, 118 115 int ep_index); 116 + void xhci_debugfs_create_stream_files(struct xhci_hcd *xhci, 117 + struct xhci_virt_device *virt_dev, 118 + int ep_index); 119 119 #else 120 120 static inline void xhci_debugfs_init(struct xhci_hcd *xhci) { } 121 121 static inline void xhci_debugfs_exit(struct xhci_hcd *xhci) { } ··· 134 128 xhci_debugfs_remove_endpoint(struct xhci_hcd *xhci, 135 129 struct xhci_virt_device *virt_dev, 136 130 int ep_index) { } 131 + static inline void 132 + xhci_debugfs_create_stream_files(struct xhci_hcd *xhci, 133 + struct xhci_virt_device *virt_dev, 134 + int ep_index) { } 137 135 #endif /* CONFIG_DEBUG_FS */ 138 136 139 137 #endif /* __LINUX_XHCI_DEBUGFS_H */
+1
drivers/usb/host/xhci.c
··· 3533 3533 xhci_dbg(xhci, "Slot %u ep ctx %u now has streams.\n", 3534 3534 udev->slot_id, ep_index); 3535 3535 vdev->eps[ep_index].ep_state |= EP_HAS_STREAMS; 3536 + xhci_debugfs_create_stream_files(xhci, vdev, ep_index); 3536 3537 } 3537 3538 xhci_free_command(xhci, config_cmd); 3538 3539 spin_unlock_irqrestore(&xhci->lock, flags);