Commit 58b9d71a authored by Mathias Nyman's avatar Mathias Nyman Committed by Greg Kroah-Hartman

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: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/1573836603-10871-3-git-send-email-mathias.nyman@linux.intel.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent dc0ffbea
...@@ -280,6 +280,9 @@ void xhci_ring_cmd_db(struct xhci_hcd *xhci) ...@@ -280,6 +280,9 @@ void xhci_ring_cmd_db(struct xhci_hcd *xhci)
return; return;
xhci_dbg(xhci, "// Ding dong!\n"); xhci_dbg(xhci, "// Ding dong!\n");
trace_xhci_ring_host_doorbell(0, DB_VALUE_HOST);
writel(DB_VALUE_HOST, &xhci->dba->doorbell[0]); writel(DB_VALUE_HOST, &xhci->dba->doorbell[0]);
/* Flush PCI posted writes */ /* Flush PCI posted writes */
readl(&xhci->dba->doorbell[0]); readl(&xhci->dba->doorbell[0]);
...@@ -401,6 +404,9 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, ...@@ -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) || if ((ep_state & EP_STOP_CMD_PENDING) || (ep_state & SET_DEQ_PENDING) ||
(ep_state & EP_HALTED) || (ep_state & EP_CLEARING_TT)) (ep_state & EP_HALTED) || (ep_state & EP_CLEARING_TT))
return; return;
trace_xhci_ring_ep_doorbell(slot_id, DB_VALUE(ep_index, stream_id));
writel(DB_VALUE(ep_index, stream_id), db_addr); writel(DB_VALUE(ep_index, stream_id), db_addr);
/* The CPU has better things to do at this point than wait for a /* The CPU has better things to do at this point than wait for a
* write-posting flush. It'll get there soon enough. * write-posting flush. It'll get there soon enough.
......
...@@ -560,6 +560,32 @@ DEFINE_EVENT(xhci_log_portsc, xhci_hub_status_data, ...@@ -560,6 +560,32 @@ DEFINE_EVENT(xhci_log_portsc, xhci_hub_status_data,
TP_ARGS(portnum, portsc) 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, DECLARE_EVENT_CLASS(xhci_dbc_log_request,
TP_PROTO(struct dbc_request *req), TP_PROTO(struct dbc_request *req),
TP_ARGS(req), TP_ARGS(req),
......
...@@ -2580,6 +2580,35 @@ static inline const char *xhci_decode_portsc(u32 portsc) ...@@ -2580,6 +2580,35 @@ static inline const char *xhci_decode_portsc(u32 portsc)
return str; 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) static inline const char *xhci_ep_state_string(u8 state)
{ {
switch (state) { switch (state) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment