xhci: Add tracing for xhci doorbell register writes
authorMathias Nyman <mathias.nyman@linux.intel.com>
Fri, 15 Nov 2019 16:50:01 +0000 (18:50 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 16 Nov 2019 09:26:05 +0000 (10:26 +0100)
Trace when a register in the doorbell array is written,
both for host controller command doorbell and device doorbells,
including for which endpoint and stream

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/1573836603-10871-3-git-send-email-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci-trace.h
drivers/usb/host/xhci.h

index 55084ad..bfd4d34 100644 (file)
@@ -280,6 +280,9 @@ void xhci_ring_cmd_db(struct xhci_hcd *xhci)
                return;
 
        xhci_dbg(xhci, "// Ding dong!\n");
+
+       trace_xhci_ring_host_doorbell(0, DB_VALUE_HOST);
+
        writel(DB_VALUE_HOST, &xhci->dba->doorbell[0]);
        /* Flush PCI posted writes */
        readl(&xhci->dba->doorbell[0]);
@@ -401,6 +404,9 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
        if ((ep_state & EP_STOP_CMD_PENDING) || (ep_state & SET_DEQ_PENDING) ||
            (ep_state & EP_HALTED) || (ep_state & EP_CLEARING_TT))
                return;
+
+       trace_xhci_ring_ep_doorbell(slot_id, DB_VALUE(ep_index, stream_id));
+
        writel(DB_VALUE(ep_index, stream_id), db_addr);
        /* The CPU has better things to do at this point than wait for a
         * write-posting flush.  It'll get there soon enough.
index 052a269..56eb867 100644 (file)
@@ -560,6 +560,32 @@ DEFINE_EVENT(xhci_log_portsc, xhci_hub_status_data,
             TP_ARGS(portnum, portsc)
 );
 
+DECLARE_EVENT_CLASS(xhci_log_doorbell,
+       TP_PROTO(u32 slot, u32 doorbell),
+       TP_ARGS(slot, doorbell),
+       TP_STRUCT__entry(
+               __field(u32, slot)
+               __field(u32, doorbell)
+       ),
+       TP_fast_assign(
+               __entry->slot = slot;
+               __entry->doorbell = doorbell;
+       ),
+       TP_printk("Ring doorbell for %s",
+               xhci_decode_doorbell(__entry->slot, __entry->doorbell)
+       )
+);
+
+DEFINE_EVENT(xhci_log_doorbell, xhci_ring_ep_doorbell,
+            TP_PROTO(u32 slot, u32 doorbell),
+            TP_ARGS(slot, doorbell)
+);
+
+DEFINE_EVENT(xhci_log_doorbell, xhci_ring_host_doorbell,
+            TP_PROTO(u32 slot, u32 doorbell),
+            TP_ARGS(slot, doorbell)
+);
+
 DECLARE_EVENT_CLASS(xhci_dbc_log_request,
        TP_PROTO(struct dbc_request *req),
        TP_ARGS(req),
index f9f8862..dc6f62a 100644 (file)
@@ -2580,6 +2580,35 @@ static inline const char *xhci_decode_portsc(u32 portsc)
        return str;
 }
 
+static inline const char *xhci_decode_doorbell(u32 slot, u32 doorbell)
+{
+       static char str[256];
+       u8 ep;
+       u16 stream;
+       int ret;
+
+       ep = (doorbell & 0xff);
+       stream = doorbell >> 16;
+
+       if (slot == 0) {
+               sprintf(str, "Command Ring %d", doorbell);
+               return str;
+       }
+       ret = sprintf(str, "Slot %d ", slot);
+       if (ep > 0 && ep < 32)
+               ret = sprintf(str + ret, "ep%d%s",
+                             ep / 2,
+                             ep % 2 ? "in" : "out");
+       else if (ep == 0 || ep < 248)
+               ret = sprintf(str + ret, "Reserved %d", ep);
+       else
+               ret = sprintf(str + ret, "Vendor Defined %d", ep);
+       if (stream)
+               ret = sprintf(str + ret, " Stream %d", stream);
+
+       return str;
+}
+
 static inline const char *xhci_ep_state_string(u8 state)
 {
        switch (state) {