Loading drivers/usb/host/xhci-msm-hsic.c +45 −0 Original line number Diff line number Diff line Loading @@ -1025,6 +1025,50 @@ void mxhci_hsic_udev_enum_done(struct usb_hcd *hcd) } } /* * When stop ep command times out due to controller halt failure * no point waiting till XHCI_STOP_EP_CMD_TIMEOUT to giveback urbs. * Kick stop ep command watchdog to finish endpoint related cleanup * as early as possible. */ static void mxhci_hsic_ep_cleanup(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_virt_ep *temp_ep; int i, j; unsigned long flags; int locked; bool kick_wdog = false; locked = spin_trylock_irqsave(&xhci->lock, flags); if (xhci->xhc_state & XHCI_STATE_DYING) goto unlock; for (i = 0; i < MAX_HC_SLOTS; i++) { if (!xhci->devs[i]) continue; for (j = 0; j < 31; j++) { temp_ep = &xhci->devs[i]->eps[j]; /* find first ep with pending stop ep cmd */ if (temp_ep->stop_cmds_pending) { kick_wdog = true; /* kick stop ep cmd watchdog asap */ mod_timer(&temp_ep->stop_cmd_timer, jiffies); goto unlock; } } } unlock: /* * if no stop ep cmd pending set xhci state to halted so that * xhci_urb_dequeue() gives back urb right away. */ if (!kick_wdog) xhci->xhc_state |= XHCI_STATE_HALTED; if (locked) spin_unlock_irqrestore(&xhci->lock, flags); } static struct hc_driver mxhci_hsic_hc_driver = { .description = "xhci-hcd", .product_desc = "Qualcomm xHCI Host Controller using HSIC", Loading Loading @@ -1060,6 +1104,7 @@ static struct hc_driver mxhci_hsic_hc_driver = { .address_device = xhci_address_device, .update_hub_device = xhci_update_hub_device, .reset_device = xhci_discover_or_reset_device, .halt_failed_cleanup = mxhci_hsic_ep_cleanup, /* * scheduling support Loading drivers/usb/host/xhci.c +8 −1 Original line number Diff line number Diff line Loading @@ -101,6 +101,8 @@ void xhci_quiesce(struct xhci_hcd *xhci) int xhci_halt(struct xhci_hcd *xhci) { int ret; struct usb_hcd *hcd = xhci_to_hcd(xhci); xhci_dbg(xhci, "// Halt the HC\n"); xhci_quiesce(xhci); Loading @@ -109,9 +111,14 @@ int xhci_halt(struct xhci_hcd *xhci) if (!ret) { xhci->xhc_state |= XHCI_STATE_HALTED; xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; } else } else { xhci_warn(xhci, "Host not halted after %u microseconds.\n", XHCI_MAX_HALT_USEC); if (hcd->driver->halt_failed_cleanup) hcd->driver->halt_failed_cleanup(hcd); } return ret; } Loading include/linux/usb/hcd.h +2 −0 Original line number Diff line number Diff line Loading @@ -360,6 +360,8 @@ struct hc_driver { int (*disable_usb3_lpm_timeout)(struct usb_hcd *, struct usb_device *, enum usb3_link_state state); int (*find_raw_port_number)(struct usb_hcd *, int); /* if hcd needs to finish ep cleanup asap after HC halt failiure */ void (*halt_failed_cleanup)(struct usb_hcd *); /* to log submission/completion events*/ void (*log_urb)(struct urb *urb, char *event, unsigned extra); Loading Loading
drivers/usb/host/xhci-msm-hsic.c +45 −0 Original line number Diff line number Diff line Loading @@ -1025,6 +1025,50 @@ void mxhci_hsic_udev_enum_done(struct usb_hcd *hcd) } } /* * When stop ep command times out due to controller halt failure * no point waiting till XHCI_STOP_EP_CMD_TIMEOUT to giveback urbs. * Kick stop ep command watchdog to finish endpoint related cleanup * as early as possible. */ static void mxhci_hsic_ep_cleanup(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_virt_ep *temp_ep; int i, j; unsigned long flags; int locked; bool kick_wdog = false; locked = spin_trylock_irqsave(&xhci->lock, flags); if (xhci->xhc_state & XHCI_STATE_DYING) goto unlock; for (i = 0; i < MAX_HC_SLOTS; i++) { if (!xhci->devs[i]) continue; for (j = 0; j < 31; j++) { temp_ep = &xhci->devs[i]->eps[j]; /* find first ep with pending stop ep cmd */ if (temp_ep->stop_cmds_pending) { kick_wdog = true; /* kick stop ep cmd watchdog asap */ mod_timer(&temp_ep->stop_cmd_timer, jiffies); goto unlock; } } } unlock: /* * if no stop ep cmd pending set xhci state to halted so that * xhci_urb_dequeue() gives back urb right away. */ if (!kick_wdog) xhci->xhc_state |= XHCI_STATE_HALTED; if (locked) spin_unlock_irqrestore(&xhci->lock, flags); } static struct hc_driver mxhci_hsic_hc_driver = { .description = "xhci-hcd", .product_desc = "Qualcomm xHCI Host Controller using HSIC", Loading Loading @@ -1060,6 +1104,7 @@ static struct hc_driver mxhci_hsic_hc_driver = { .address_device = xhci_address_device, .update_hub_device = xhci_update_hub_device, .reset_device = xhci_discover_or_reset_device, .halt_failed_cleanup = mxhci_hsic_ep_cleanup, /* * scheduling support Loading
drivers/usb/host/xhci.c +8 −1 Original line number Diff line number Diff line Loading @@ -101,6 +101,8 @@ void xhci_quiesce(struct xhci_hcd *xhci) int xhci_halt(struct xhci_hcd *xhci) { int ret; struct usb_hcd *hcd = xhci_to_hcd(xhci); xhci_dbg(xhci, "// Halt the HC\n"); xhci_quiesce(xhci); Loading @@ -109,9 +111,14 @@ int xhci_halt(struct xhci_hcd *xhci) if (!ret) { xhci->xhc_state |= XHCI_STATE_HALTED; xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; } else } else { xhci_warn(xhci, "Host not halted after %u microseconds.\n", XHCI_MAX_HALT_USEC); if (hcd->driver->halt_failed_cleanup) hcd->driver->halt_failed_cleanup(hcd); } return ret; } Loading
include/linux/usb/hcd.h +2 −0 Original line number Diff line number Diff line Loading @@ -360,6 +360,8 @@ struct hc_driver { int (*disable_usb3_lpm_timeout)(struct usb_hcd *, struct usb_device *, enum usb3_link_state state); int (*find_raw_port_number)(struct usb_hcd *, int); /* if hcd needs to finish ep cleanup asap after HC halt failiure */ void (*halt_failed_cleanup)(struct usb_hcd *); /* to log submission/completion events*/ void (*log_urb)(struct urb *urb, char *event, unsigned extra); Loading