This patch creates a new event class called xhci_log_cmd, and
defines the events used for tracing the life cycle of commands
issued for various purposes.

This info can be used, later, to print, in a human readable way,
the life cycle of an xHCI command using the trace-cmd tool and
the appropriate plugin.

Signed-off-by: Lu Baolu <baolu...@linux.intel.com>
---
 drivers/usb/host/xhci-hub.c   |  2 +
 drivers/usb/host/xhci-ring.c  | 13 +++++--
 drivers/usb/host/xhci-trace.h | 90 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/host/xhci.c       |  7 ++++
 4 files changed, 108 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 3bddeaa..2c3f77f 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -411,9 +411,11 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int 
slot_id, int suspend)
                        }
                        xhci_queue_stop_endpoint(xhci, command, slot_id, i,
                                                 suspend);
+                       trace_cmd_xhci_stop_device(command);
                }
        }
        xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend);
+       trace_cmd_xhci_stop_device(cmd);
        xhci_ring_cmd_db(xhci);
        spin_unlock_irqrestore(&xhci->lock, flags);
 
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index d9936c7..4cdcd71 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1124,6 +1124,7 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd 
*xhci, int slot_id,
                xhci_queue_configure_endpoint(xhci, command,
                                xhci->devs[slot_id]->in_ctx->dma, slot_id,
                                false);
+               trace_cmd_xhci_handle_cmd_reset_ep(command);
                xhci_ring_cmd_db(xhci);
        } else {
                /* Clear our internal halted state */
@@ -1231,13 +1232,13 @@ static void xhci_handle_cmd_nec_get_fw(struct xhci_hcd 
*xhci,
 static void xhci_complete_del_and_free_cmd(struct xhci_command *cmd, u32 
status)
 {
        list_del(&cmd->cmd_list);
+       cmd->status = status;
+       trace_cmd_xhci_complete_del_and_free_cmd(cmd);
 
-       if (cmd->completion) {
-               cmd->status = status;
+       if (cmd->completion)
                complete(cmd->completion);
-       } else {
+       else
                kfree(cmd);
-       }
 }
 
 void xhci_cleanup_command_queue(struct xhci_hcd *xhci)
@@ -1268,6 +1269,7 @@ void xhci_handle_command_timeout(struct work_struct *work)
        }
        /* mark this command to be cancelled */
        xhci->current_cmd->status = COMP_COMMAND_ABORTED;
+       trace_cmd_xhci_handle_command_timeout(xhci->current_cmd);
 
        /* Make sure command ring is running before aborting it */
        hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
@@ -1432,6 +1434,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
        }
 
 event_handled:
+       trace_cmd_handle_cmd_completion(cmd);
        xhci_complete_del_and_free_cmd(cmd, cmd_comp_code);
 
        inc_deq(xhci, xhci->cmd_ring);
@@ -1773,6 +1776,7 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd 
*xhci,
        ep->stopped_stream = stream_id;
 
        xhci_queue_reset_ep(xhci, command, slot_id, ep_index);
+       trace_cmd_xhci_cleanup_halted_endpoint(command);
        xhci_cleanup_stalled_ring(xhci, ep_index, td);
 
        ep->stopped_stream = 0;
@@ -3956,6 +3960,7 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
                xhci_free_command(xhci, cmd);
                return;
        }
+       trace_cmd_xhci_queue_new_dequeue_state(cmd);
 
        /* Stop the TD queueing code from ringing the doorbell until
         * this command completes.  The HC won't set the dequeue pointer
diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
index 1ac2cdf..c31eeaf 100644
--- a/drivers/usb/host/xhci-trace.h
+++ b/drivers/usb/host/xhci-trace.h
@@ -285,6 +285,96 @@ DEFINE_EVENT(xhci_log_urb, xhci_urb_dequeue,
        TP_ARGS(urb)
 );
 
+DECLARE_EVENT_CLASS(xhci_log_cmd,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd),
+       TP_STRUCT__entry(
+               __field(struct xhci_command *, cmd)
+               __field(struct xhci_container_ctx *, in_ctx)
+               __field(union xhci_trb *, cmd_trb)
+               __field(int, slot_id)
+               __field(int, status)
+               __field(int, type)
+       ),
+       TP_fast_assign(
+               __entry->cmd = cmd;
+               __entry->in_ctx = cmd->in_ctx;
+               __entry->cmd_trb = cmd->command_trb;
+               __entry->slot_id = cmd->slot_id;
+               __entry->status = cmd->status;
+               __entry->type = 
TRB_FIELD_TO_TYPE(le32_to_cpu(cmd->command_trb->generic.field[3]))
+       ),
+       TP_printk("cmd @%p: %s: in_ctx=@%p, slot_id=%d, cmd_trb=@%p, status=%d",
+               __entry->cmd, xhci_trb_type_string(__entry->type),
+               __entry->in_ctx, __entry->slot_id, __entry->cmd_trb,
+               __entry->status
+       )
+);
+
+DEFINE_EVENT(xhci_log_cmd, cmd_xhci_stop_device,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd)
+);
+
+DEFINE_EVENT(xhci_log_cmd, cmd_xhci_handle_cmd_reset_ep,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd)
+);
+
+DEFINE_EVENT(xhci_log_cmd, cmd_xhci_cleanup_halted_endpoint,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd)
+);
+
+DEFINE_EVENT(xhci_log_cmd, cmd_xhci_queue_new_dequeue_state,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd)
+);
+
+DEFINE_EVENT(xhci_log_cmd, cmd_xhci_urb_dequeue,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd)
+);
+
+DEFINE_EVENT(xhci_log_cmd, cmd_xhci_configure_endpoint,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd)
+);
+
+DEFINE_EVENT(xhci_log_cmd, cmd_xhci_discover_or_reset_device,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd)
+);
+
+DEFINE_EVENT(xhci_log_cmd, cmd_xhci_free_dev,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd)
+);
+
+DEFINE_EVENT(xhci_log_cmd, cmd_xhci_alloc_dev,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd)
+);
+
+DEFINE_EVENT(xhci_log_cmd, cmd_xhci_setup_device,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd)
+);
+
+DEFINE_EVENT(xhci_log_cmd, cmd_handle_cmd_completion,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd)
+);
+
+DEFINE_EVENT(xhci_log_cmd, cmd_xhci_handle_command_timeout,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd)
+);
+
+DEFINE_EVENT(xhci_log_cmd, cmd_xhci_complete_del_and_free_cmd,
+       TP_PROTO(struct xhci_command *cmd),
+       TP_ARGS(cmd)
+);
 #endif /* __XHCI_TRACE_H */
 
 /* this part must be outside header guard */
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index b3f7766..dff912e 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1549,6 +1549,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb 
*urb, int status)
                add_timer(&ep->stop_cmd_timer);
                xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id,
                                         ep_index, 0);
+               trace_cmd_xhci_urb_dequeue(command);
                xhci_ring_cmd_db(xhci);
        }
 done:
@@ -2631,6 +2632,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
                                "FIXME allocate a new ring segment");
                return -ENOMEM;
        }
+       trace_cmd_xhci_configure_endpoint(command);
        xhci_ring_cmd_db(xhci);
        spin_unlock_irqrestore(&xhci->lock, flags);
 
@@ -3458,6 +3460,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, 
struct usb_device *udev)
                spin_unlock_irqrestore(&xhci->lock, flags);
                goto command_cleanup;
        }
+       trace_cmd_xhci_discover_or_reset_device(reset_device_cmd);
        xhci_ring_cmd_db(xhci);
        spin_unlock_irqrestore(&xhci->lock, flags);
 
@@ -3604,6 +3607,7 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device 
*udev)
                xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
                return;
        }
+       trace_cmd_xhci_free_dev(command);
        xhci_ring_cmd_db(xhci);
        spin_unlock_irqrestore(&xhci->lock, flags);
 
@@ -3662,6 +3666,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device 
*udev)
                xhci_free_command(xhci, command);
                return 0;
        }
+       trace_cmd_xhci_alloc_dev(command);
        xhci_ring_cmd_db(xhci);
        spin_unlock_irqrestore(&xhci->lock, flags);
 
@@ -3724,6 +3729,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device 
*udev)
        if (!xhci_queue_slot_control(xhci, command, TRB_DISABLE_SLOT,
                                     udev->slot_id))
                xhci_ring_cmd_db(xhci);
+       trace_cmd_xhci_alloc_dev(command);
        spin_unlock_irqrestore(&xhci->lock, flags);
        return 0;
 }
@@ -3826,6 +3832,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct 
usb_device *udev,
                                "FIXME: allocate a command ring segment");
                goto out;
        }
+       trace_cmd_xhci_setup_device(command);
        xhci_ring_cmd_db(xhci);
        spin_unlock_irqrestore(&xhci->lock, flags);
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to