usb: xhci: Add debugfs interface for xHCI driver
Subsystems (2)
PATCH v2 1/1 usb: xhci: Add debugfs interface for xHCI driver
This adds debugfs consumer for xHCI driver. The debugfs entries read all host registers, device/endpoint contexts, command ring, event ring and various endpoint rings. With these entries, users can check the registers and memory spaces used by a host during run time, or save all the information with a simple 'cp -r' for post-mortem programs.
The file hierarchy looks like this.
[root of debugfs]
|__usb |____[e,u,o]hci <---------[root for other HCIs] |____xhci <---------------[root for xHCI] |______0000:00:14.0 <--------------[xHCI host name] |________reg-cap <--------[capability registers] |________reg-op <-------[operational registers] |________reg-runtime <-----------[runtime registers] |________reg-ext-#cap_name <----[extended capability regs] |________command-ring <-------[root for command ring] |__________cycle <------------------[ring cycle] |__________dequeue <--------[ring dequeue pointer] |__________enqueue <--------[ring enqueue pointer] |__________trbs <-------------------[ring trbs] |________event-ring <---------[root for event ring] |__________cycle <------------------[ring cycle] |__________dequeue <--------[ring dequeue pointer] |__________enqueue <--------[ring enqueue pointer] |__________trbs <-------------------[ring trbs] |________devices <------------[root for devices] |__________#slot_id <-----------[root for a device] |____________name <-----------------[device name] |____________slot-context <----------------[slot context] |____________ep-context <-----------[endpoint contexts] |____________ep#ep_index <--------[root for an endpoint] |______________cycle <------------------[ring cycle] |______________dequeue <--------[ring dequeue pointer] |______________enqueue <--------[ring enqueue pointer] |______________trbs <-------------------[ring trbs]
Signed-off-by Lu Baolu <[email protected]>
---
Change log:v1->v2:
- No need to check return valuse of debugfs interfaces.
- Remove file entries when adding endpoint failed.
drivers/usb/host/Makefile | 4 + drivers/usb/host/xhci-debugfs.c | 526 ++++++++++++++++++++++++++++++++++++++++ drivers/usb/host/xhci-debugfs.h | 137 +++++++++++ drivers/usb/host/xhci-mem.c | 5 +- drivers/usb/host/xhci.c | 23 +- drivers/usb/host/xhci.h | 9 + 6 files changed, 700 insertions(+), 4 deletions(-) create mode 100644 drivers/usb/host/xhci-debugfs.c create mode 100644 drivers/usb/host/xhci-debugfs.h
drivers/usb/host/Makefile +4 -0
@@ -25,6 +25,10 @@ ifneq ($(CONFIG_USB_XHCI_RCAR), ) xhci-plat-hcd-y += xhci-rcar.o endif +ifneq ($(CONFIG_DEBUG_FS),) + xhci-hcd-y += xhci-debugfs.o +endif + obj-$(CONFIG_USB_WHCI_HCD) += whci/ obj-$(CONFIG_USB_PCI) += pci-quirks.o
drivers/usb/host/xhci-debugfs.c new file +526 -0
526 lines not on this page · raw message
drivers/usb/host/xhci-debugfs.h new file +137 -0
137 lines not on this page · raw message
drivers/usb/host/xhci-mem.c +2 -3
@@ -28,6 +28,7 @@#include "xhci.h" #include "xhci-trace.h" +#include "xhci-debugfs.h" /* * Allocates a generic ring segment from the ring pool, sets the dma address,
@@ -465,8 +466,6 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,return 0 ; } -#define CTX_SIZE (_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32) -static struct xhci_container_ctx *xhci_alloc_container_ctx (struct xhci_hcd *xhci,int type,gfp_t flags) {
@@ -961,6 +960,7 @@ void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_id) } }/* we are now at a leaf device */ +xhci_debugfs_remove_slot (xhci, slot_id);xhci_free_virt_device (xhci, slot_id); }
@@ -1496,7 +1496,6 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, ep_ctx->tx_info =cpu_to_le32 (EP_MAX_ESIT_PAYLOAD_LO (max_esit_payload) |EP_AVG_TRB_LENGTH (avg_trb_len)); -/* FIXME Debug endpoint context */ return 0 ; }
drivers/usb/host/xhci.c +22 -1
@@ -32,6 +32,7 @@#include "xhci.h" #include "xhci-trace.h" #include "xhci-mtk.h" +#include "xhci-debugfs.h" #define DRIVER_AUTHOR "Sarah Sharp"#define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver"
@@ -632,6 +633,9 @@ int xhci_run(struct usb_hcd *hcd) }xhci_dbg_trace (xhci, trace_xhci_dbg_init,"Finished xhci_run for USB2 roothub" ); + +xhci_debugfs_init (xhci); +return 0 ; }EXPORT_SYMBOL_GPL (xhci_run);
@@ -650,6 +654,8 @@ static void xhci_stop(struct usb_hcd *hcd)u32 temp;struct xhci_hcd *xhci =hcd_to_xhci (hcd); +xhci_debugfs_exit (xhci); +mutex_lock (&xhci->mutex);/* Only halt host and free memory after both hcds are removed */
@@ -1600,6 +1606,8 @@ static int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, ctrl_ctx->add_flags &=cpu_to_le32 (~drop_flag); new_add_flags =le32_to_cpu (ctrl_ctx->add_flags); +xhci_debugfs_remove_endpoint (xhci, xhci->devs[udev->slot_id], ep_index); +xhci_endpoint_zero (xhci, xhci->devs[udev->slot_id], ep);if (xhci->quirks &XHCI_MTK_HOST )
@@ -1722,6 +1730,8 @@ static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,/* Store the usb_device pointer for later use */ ep->hcpriv = udev; +xhci_debugfs_create_endpoint (xhci, virt_dev, ep_index); + xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n", (unsigned int) ep->desc.bEndpointAddress, udev->slot_id,
@@ -2772,6 +2782,7 @@ static void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)/* Free any rings allocated for added endpoints */ for (i =0 ; i <31 ; i++) {if (virt_dev->eps[i].new_ring) { +xhci_debugfs_remove_endpoint (xhci, virt_dev, i);xhci_ring_free (xhci, virt_dev->eps[i].new_ring); virt_dev->eps[i].new_ring =NULL ; }
@@ -3487,6 +3498,7 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd, }if (ep->ring) { +xhci_debugfs_remove_endpoint (xhci, virt_dev, i);xhci_free_endpoint_ring (xhci, virt_dev, i); last_freed_endpoint = i; }
@@ -3521,6 +3533,8 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)int i, ret;struct xhci_command *command; +xhci_debugfs_remove_slot (xhci, udev->slot_id); + command =xhci_alloc_command (xhci, false, false,GFP_KERNEL );if (!command)return ;
@@ -3693,6 +3707,8 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) udev->slot_id = slot_id; +xhci_debugfs_create_slot (xhci, slot_id); +#ifndef CONFIG_USB_DEFAULT_PERSIST /* * If resetting upon resume, we can't put the controller into runtime
@@ -5003,6 +5019,8 @@ static int __init xhci_hcd_init(void)if (usb_disabled ())return -ENODEV ; +xhci_debugfs_create_root (); +return 0 ; }
@@ -5010,7 +5028,10 @@ static int __init xhci_hcd_init(void)* If an init function is provided, an exit function must also be provided * to allow module unload. */ -static void __exit xhci_hcd_fini(void) { } +static void __exit xhci_hcd_fini(void) +{ +xhci_debugfs_remove_root (); +}module_init (xhci_hcd_init);module_exit (xhci_hcd_fini);
drivers/usb/host/xhci.h +9 -0
@@ -131,6 +131,8 @@ struct xhci_cap_regs {/* Extended Capabilities pointer from PCI base - section 5.3.6 */ #define HCC_EXT_CAPS (p) XHCI_HCC_EXT_CAPS(p) +#define CTX_SIZE (_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32) +/* db_off bitmask - bits 0:1 reserved */ #define DBOFF_MASK (~0x3)
@@ -998,6 +1000,8 @@ struct xhci_virt_device {struct xhci_tt_bw_info *tt_info;/* The current max exit latency for the enabled USB3 link states. */ u16 current_mel; +/* Used for the debugfs interfaces. */ +void *debugfs_private; };/*
@@ -1850,6 +1854,10 @@ struct xhci_hcd {/* Compliance Mode Timer Triggered every 2 seconds */ #define COMP_MODE_RCVRY_MSECS 2000 +struct dentry *debugfs_root; +struct dentry *debugfs_slots; +struct list_head regset_list; +/* platform-specific data -- must come last */ unsigned long priv[0 ]__aligned(sizeof(s64)) ; };
@@ -2098,6 +2106,7 @@ struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_containerstruct xhci_ring *xhci_triad_to_transfer_ring (struct xhci_hcd *xhci,unsigned int slot_id,unsigned int ep_index,unsigned int stream_id); +static inline struct xhci_ring *xhci_urb_to_transfer_ring (struct xhci_hcd *xhci,struct urb *urb) {
Signature · 1 line
2.7.4