From 58b9d71a0f55e2514211875553dd092f74dc2cbc Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Fri, 15 Nov 2019 18:50:01 +0200 Subject: xhci: Add tracing for xhci doorbell register writes 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 Link: https://lore.kernel.org/r/1573836603-10871-3-git-send-email-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 6 ++++++ drivers/usb/host/xhci-trace.h | 26 ++++++++++++++++++++++++++ drivers/usb/host/xhci.h | 29 +++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 55084adf1faf..bfd4d34c2535 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -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. diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h index 052a269d86f2..56eb867803a6 100644 --- a/drivers/usb/host/xhci-trace.h +++ b/drivers/usb/host/xhci-trace.h @@ -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), diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f9f88626a57a..dc6f62a4b197 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -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) { -- cgit v1.2.3