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.lu@xxxxxxxxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html