Loading drivers/usb/dwc3/core.h +3 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ #include <linux/mm.h> #include <linux/debugfs.h> #include <linux/hrtimer.h> #include <linux/wait.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> Loading Loading @@ -799,6 +800,7 @@ struct dwc3_scratchpad_array { * @bh_completion_time: time taken for taklet completion * @bh_handled_evt_cnt: no. of events handled by tasklet per interrupt * @bh_dbg_index: index for capturing bh_completion_time and bh_handled_evt_cnt * @wait_linkstate: waitqueue for waiting LINK to move into required state */ struct dwc3 { struct usb_ctrlrequest *ctrl_req; Loading Loading @@ -926,6 +928,7 @@ struct dwc3 { unsigned irq_completion_time[MAX_INTR_STATS]; unsigned irq_event_count[MAX_INTR_STATS]; unsigned irq_dbg_index; wait_queue_head_t wait_linkstate; }; /* -------------------------------------------------------------------------- */ Loading drivers/usb/dwc3/gadget.c +80 −28 Original line number Diff line number Diff line Loading @@ -64,7 +64,7 @@ static int bulk_ep_xfer_timeout_ms; module_param(bulk_ep_xfer_timeout_ms, int, S_IRUGO | S_IWUSR); #define bulk_ep_xfer_timeout_ns (bulk_ep_xfer_timeout_ms * NSEC_PER_MSEC) static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc); static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, bool remote_wakeup); static int dwc3_gadget_wakeup_int(struct dwc3 *dwc); static void dwc3_restart_hrtimer(struct dwc3 *dwc); Loading Loading @@ -1673,20 +1673,14 @@ static void dwc3_gadget_wakeup_work(struct work_struct *w) { struct dwc3_usb_gadget *dwc3_gadget; struct dwc3 *dwc; unsigned long flags; int ret; dwc3_gadget = container_of(w, struct dwc3_usb_gadget, wakeup_work); dwc = dwc3_gadget->dwc; spin_lock_irqsave(&dwc->lock, flags); if (atomic_read(&dwc->in_lpm)) { spin_unlock_irqrestore(&dwc->lock, flags); dbg_event(0xFF, "Gdgwake gsyn", 0); pm_runtime_get_sync(dwc->dev); spin_lock_irqsave(&dwc->lock, flags); } ret = dwc3_gadget_wakeup_int(dwc); Loading @@ -1695,19 +1689,20 @@ static void dwc3_gadget_wakeup_work(struct work_struct *w) pr_err("Remote wakeup failed. ret = %d.\n", ret); else pr_debug("Remote wakeup succeeded.\n"); spin_unlock_irqrestore(&dwc->lock, flags); } static int dwc3_gadget_wakeup_int(struct dwc3 *dwc) { u32 timeout = 0; bool link_recover_only = false; u32 reg; int ret = 0; u8 link_state; unsigned long flags; pr_debug("%s(): Entry\n", __func__); disable_irq(dwc->irq); spin_lock_irqsave(&dwc->lock, flags); /* * According to the Databook Remote wakeup request should * be issued only when the device is in early suspend state. Loading @@ -1733,9 +1728,25 @@ static int dwc3_gadget_wakeup_int(struct dwc3 *dwc) goto out; } /* Enable LINK STATUS change event */ reg = dwc3_readl(dwc->regs, DWC3_DEVTEN); reg |= DWC3_DEVTEN_ULSTCNGEN; dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); /* * memory barrier is required to make sure that required events * with core is enabled before performing RECOVERY mechnism. */ mb(); ret = dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RECOV); if (ret < 0) { dev_err(dwc->dev, "failed to put link in Recovery\n"); /* Disable LINK STATUS change */ reg = dwc3_readl(dwc->regs, DWC3_DEVTEN); reg &= ~DWC3_DEVTEN_ULSTCNGEN; dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); /* Required to complete this operation before returning */ mb(); goto out; } Loading @@ -1747,22 +1758,39 @@ static int dwc3_gadget_wakeup_int(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_DCTL, reg); } /* poll until Link State changes to ON */ do { reg = dwc3_readl(dwc->regs, DWC3_DSTS); spin_unlock_irqrestore(&dwc->lock, flags); enable_irq(dwc->irq); ret = wait_event_interruptible_timeout(dwc->wait_linkstate, (dwc->link_state < DWC3_LINK_STATE_U3) || (dwc->link_state == DWC3_LINK_STATE_SS_DIS), msecs_to_jiffies(3000)); /* 3 seconds */ /* in HS, means ON */ if (DWC3_DSTS_USBLNKST(reg) == DWC3_LINK_STATE_U0) break; udelay(10); timeout++; } while (timeout < 10000); spin_lock_irqsave(&dwc->lock, flags); /* Disable link status change event */ reg = dwc3_readl(dwc->regs, DWC3_DEVTEN); reg &= ~DWC3_DEVTEN_ULSTCNGEN; dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); /* * Complete this write before we go ahead and perform resume * as we don't need link status change notificaiton anymore. */ mb(); if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U0) { dev_err(dwc->dev, "failed to send remote wakeup\n"); if (!ret) { dev_dbg(dwc->dev, "Timeout moving into state(%d)\n", dwc->link_state); ret = -EINVAL; goto out; spin_unlock_irqrestore(&dwc->lock, flags); goto out1; } else { ret = 0; /* * If USB is disconnected OR received RESET from host, * don't perform resume */ if (dwc->link_state == DWC3_LINK_STATE_SS_DIS || dwc->gadget.state == USB_STATE_DEFAULT) link_recover_only = true; } /* Loading @@ -1773,8 +1801,17 @@ static int dwc3_gadget_wakeup_int(struct dwc3 *dwc) * the resume sequence is initiated by SW. */ if (!link_recover_only) dwc3_gadget_wakeup_interrupt(dwc); dwc3_gadget_wakeup_interrupt(dwc, true); spin_unlock_irqrestore(&dwc->lock, flags); pr_debug("%s: Exit\n", __func__); return ret; out: spin_unlock_irqrestore(&dwc->lock, flags); enable_irq(dwc->irq); out1: return ret; } Loading Loading @@ -2197,6 +2234,7 @@ static int dwc3_gadget_start(struct usb_gadget *g, } spin_unlock_irqrestore(&dwc->lock, flags); init_waitqueue_head(&dwc->wait_linkstate); pm_runtime_put(dwc->dev); dbg_event(0xFF, "GdgStrt End", 0); Loading Loading @@ -2891,6 +2929,7 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->setup_packet_pending = false; dwc->link_state = DWC3_LINK_STATE_SS_DIS; wake_up_interruptible(&dwc->wait_linkstate); } void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend) Loading Loading @@ -2979,6 +3018,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_DCFG, reg); dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->link_state = DWC3_LINK_STATE_U0; wake_up_interruptible(&dwc->wait_linkstate); } static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed) Loading Loading @@ -3114,12 +3154,23 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) */ } static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc) static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, bool remote_wakeup) { bool perform_resume = true; dev_dbg(dwc->dev, "%s\n", __func__); /* * Identify if it is called from wakeup_interrupt() context for bus * resume or as part of remote wakeup. And based on that check for * U3 state. as we need to handle case of L1 resume i.e. where we * don't want to perform resume. */ if (!remote_wakeup && dwc->link_state != DWC3_LINK_STATE_U3) perform_resume = false; /* Only perform resume from L2 or Early Suspend states */ if (dwc->link_state == DWC3_LINK_STATE_U3) { if (perform_resume) { dbg_event(0xFF, "WAKEUP", 0); /* Clear OTG suspend state */ Loading Loading @@ -3229,8 +3280,9 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, } } dev_dbg(dwc->dev, "Going from (%d)--->(%d)\n", dwc->link_state, next); dwc->link_state = next; wake_up_interruptible(&dwc->wait_linkstate); dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state); } Loading Loading @@ -3322,7 +3374,7 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc, dwc->dbg_gadget_events.connect++; break; case DWC3_DEVICE_EVENT_WAKEUP: dwc3_gadget_wakeup_interrupt(dwc); dwc3_gadget_wakeup_interrupt(dwc, false); dwc->dbg_gadget_events.wakeup++; break; case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE: Loading drivers/usb/gadget/composite.c +6 −21 Original line number Diff line number Diff line Loading @@ -363,8 +363,7 @@ int usb_get_func_interface_id(struct usb_function *func) return -ENODEV; } static int usb_func_wakeup_int(struct usb_function *func, bool use_pending_flag) static int usb_func_wakeup_int(struct usb_function *func) { int ret; int interface_id; Loading @@ -372,13 +371,14 @@ static int usb_func_wakeup_int(struct usb_function *func, struct usb_gadget *gadget; struct usb_composite_dev *cdev; pr_debug("%s - %s function wakeup, use pending: %u\n", __func__, func->name ? func->name : "", use_pending_flag); if (!func || !func->config || !func->config->cdev || !func->config->cdev->gadget) return -EINVAL; pr_debug("%s - %s function wakeup\n", __func__, func->name ? func->name : ""); gadget = func->config->cdev->gadget; if ((gadget->speed != USB_SPEED_SUPER) || !func->func_wakeup_allowed) { DBG(func->config->cdev, Loading @@ -391,13 +391,6 @@ static int usb_func_wakeup_int(struct usb_function *func, cdev = get_gadget_data(gadget); spin_lock_irqsave(&cdev->lock, flags); if (use_pending_flag && !func->func_wakeup_pending) { pr_debug("Pending flag is cleared - Function wakeup is cancelled.\n"); spin_unlock_irqrestore(&cdev->lock, flags); return 0; } ret = usb_get_func_interface_id(func); if (ret < 0) { ERROR(func->config->cdev, Loading @@ -410,14 +403,6 @@ static int usb_func_wakeup_int(struct usb_function *func, interface_id = ret; ret = usb_gadget_func_wakeup(gadget, interface_id); if (use_pending_flag) { func->func_wakeup_pending = false; } else { if (ret == -EAGAIN) func->func_wakeup_pending = true; } spin_unlock_irqrestore(&cdev->lock, flags); return ret; Loading @@ -430,7 +415,7 @@ int usb_func_wakeup(struct usb_function *func) pr_debug("%s function wakeup\n", func->name ? func->name : ""); ret = usb_func_wakeup_int(func, false); ret = usb_func_wakeup_int(func); if (ret == -EAGAIN) { DBG(func->config->cdev, "Function wakeup for %s could not complete due to suspend state. Delayed until after bus resume.\n", Loading Loading @@ -1914,7 +1899,7 @@ composite_resume(struct usb_gadget *gadget) if (cdev->config) { list_for_each_entry(f, &cdev->config->functions, list) { ret = usb_func_wakeup_int(f, true); ret = usb_func_wakeup_int(f); if (ret) { if (ret == -EAGAIN) { ERROR(f->config->cdev, Loading Loading
drivers/usb/dwc3/core.h +3 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ #include <linux/mm.h> #include <linux/debugfs.h> #include <linux/hrtimer.h> #include <linux/wait.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> Loading Loading @@ -799,6 +800,7 @@ struct dwc3_scratchpad_array { * @bh_completion_time: time taken for taklet completion * @bh_handled_evt_cnt: no. of events handled by tasklet per interrupt * @bh_dbg_index: index for capturing bh_completion_time and bh_handled_evt_cnt * @wait_linkstate: waitqueue for waiting LINK to move into required state */ struct dwc3 { struct usb_ctrlrequest *ctrl_req; Loading Loading @@ -926,6 +928,7 @@ struct dwc3 { unsigned irq_completion_time[MAX_INTR_STATS]; unsigned irq_event_count[MAX_INTR_STATS]; unsigned irq_dbg_index; wait_queue_head_t wait_linkstate; }; /* -------------------------------------------------------------------------- */ Loading
drivers/usb/dwc3/gadget.c +80 −28 Original line number Diff line number Diff line Loading @@ -64,7 +64,7 @@ static int bulk_ep_xfer_timeout_ms; module_param(bulk_ep_xfer_timeout_ms, int, S_IRUGO | S_IWUSR); #define bulk_ep_xfer_timeout_ns (bulk_ep_xfer_timeout_ms * NSEC_PER_MSEC) static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc); static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, bool remote_wakeup); static int dwc3_gadget_wakeup_int(struct dwc3 *dwc); static void dwc3_restart_hrtimer(struct dwc3 *dwc); Loading Loading @@ -1673,20 +1673,14 @@ static void dwc3_gadget_wakeup_work(struct work_struct *w) { struct dwc3_usb_gadget *dwc3_gadget; struct dwc3 *dwc; unsigned long flags; int ret; dwc3_gadget = container_of(w, struct dwc3_usb_gadget, wakeup_work); dwc = dwc3_gadget->dwc; spin_lock_irqsave(&dwc->lock, flags); if (atomic_read(&dwc->in_lpm)) { spin_unlock_irqrestore(&dwc->lock, flags); dbg_event(0xFF, "Gdgwake gsyn", 0); pm_runtime_get_sync(dwc->dev); spin_lock_irqsave(&dwc->lock, flags); } ret = dwc3_gadget_wakeup_int(dwc); Loading @@ -1695,19 +1689,20 @@ static void dwc3_gadget_wakeup_work(struct work_struct *w) pr_err("Remote wakeup failed. ret = %d.\n", ret); else pr_debug("Remote wakeup succeeded.\n"); spin_unlock_irqrestore(&dwc->lock, flags); } static int dwc3_gadget_wakeup_int(struct dwc3 *dwc) { u32 timeout = 0; bool link_recover_only = false; u32 reg; int ret = 0; u8 link_state; unsigned long flags; pr_debug("%s(): Entry\n", __func__); disable_irq(dwc->irq); spin_lock_irqsave(&dwc->lock, flags); /* * According to the Databook Remote wakeup request should * be issued only when the device is in early suspend state. Loading @@ -1733,9 +1728,25 @@ static int dwc3_gadget_wakeup_int(struct dwc3 *dwc) goto out; } /* Enable LINK STATUS change event */ reg = dwc3_readl(dwc->regs, DWC3_DEVTEN); reg |= DWC3_DEVTEN_ULSTCNGEN; dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); /* * memory barrier is required to make sure that required events * with core is enabled before performing RECOVERY mechnism. */ mb(); ret = dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RECOV); if (ret < 0) { dev_err(dwc->dev, "failed to put link in Recovery\n"); /* Disable LINK STATUS change */ reg = dwc3_readl(dwc->regs, DWC3_DEVTEN); reg &= ~DWC3_DEVTEN_ULSTCNGEN; dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); /* Required to complete this operation before returning */ mb(); goto out; } Loading @@ -1747,22 +1758,39 @@ static int dwc3_gadget_wakeup_int(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_DCTL, reg); } /* poll until Link State changes to ON */ do { reg = dwc3_readl(dwc->regs, DWC3_DSTS); spin_unlock_irqrestore(&dwc->lock, flags); enable_irq(dwc->irq); ret = wait_event_interruptible_timeout(dwc->wait_linkstate, (dwc->link_state < DWC3_LINK_STATE_U3) || (dwc->link_state == DWC3_LINK_STATE_SS_DIS), msecs_to_jiffies(3000)); /* 3 seconds */ /* in HS, means ON */ if (DWC3_DSTS_USBLNKST(reg) == DWC3_LINK_STATE_U0) break; udelay(10); timeout++; } while (timeout < 10000); spin_lock_irqsave(&dwc->lock, flags); /* Disable link status change event */ reg = dwc3_readl(dwc->regs, DWC3_DEVTEN); reg &= ~DWC3_DEVTEN_ULSTCNGEN; dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); /* * Complete this write before we go ahead and perform resume * as we don't need link status change notificaiton anymore. */ mb(); if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U0) { dev_err(dwc->dev, "failed to send remote wakeup\n"); if (!ret) { dev_dbg(dwc->dev, "Timeout moving into state(%d)\n", dwc->link_state); ret = -EINVAL; goto out; spin_unlock_irqrestore(&dwc->lock, flags); goto out1; } else { ret = 0; /* * If USB is disconnected OR received RESET from host, * don't perform resume */ if (dwc->link_state == DWC3_LINK_STATE_SS_DIS || dwc->gadget.state == USB_STATE_DEFAULT) link_recover_only = true; } /* Loading @@ -1773,8 +1801,17 @@ static int dwc3_gadget_wakeup_int(struct dwc3 *dwc) * the resume sequence is initiated by SW. */ if (!link_recover_only) dwc3_gadget_wakeup_interrupt(dwc); dwc3_gadget_wakeup_interrupt(dwc, true); spin_unlock_irqrestore(&dwc->lock, flags); pr_debug("%s: Exit\n", __func__); return ret; out: spin_unlock_irqrestore(&dwc->lock, flags); enable_irq(dwc->irq); out1: return ret; } Loading Loading @@ -2197,6 +2234,7 @@ static int dwc3_gadget_start(struct usb_gadget *g, } spin_unlock_irqrestore(&dwc->lock, flags); init_waitqueue_head(&dwc->wait_linkstate); pm_runtime_put(dwc->dev); dbg_event(0xFF, "GdgStrt End", 0); Loading Loading @@ -2891,6 +2929,7 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->setup_packet_pending = false; dwc->link_state = DWC3_LINK_STATE_SS_DIS; wake_up_interruptible(&dwc->wait_linkstate); } void dwc3_gadget_usb3_phy_suspend(struct dwc3 *dwc, int suspend) Loading Loading @@ -2979,6 +3018,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_DCFG, reg); dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->link_state = DWC3_LINK_STATE_U0; wake_up_interruptible(&dwc->wait_linkstate); } static void dwc3_update_ram_clk_sel(struct dwc3 *dwc, u32 speed) Loading Loading @@ -3114,12 +3154,23 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) */ } static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc) static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, bool remote_wakeup) { bool perform_resume = true; dev_dbg(dwc->dev, "%s\n", __func__); /* * Identify if it is called from wakeup_interrupt() context for bus * resume or as part of remote wakeup. And based on that check for * U3 state. as we need to handle case of L1 resume i.e. where we * don't want to perform resume. */ if (!remote_wakeup && dwc->link_state != DWC3_LINK_STATE_U3) perform_resume = false; /* Only perform resume from L2 or Early Suspend states */ if (dwc->link_state == DWC3_LINK_STATE_U3) { if (perform_resume) { dbg_event(0xFF, "WAKEUP", 0); /* Clear OTG suspend state */ Loading Loading @@ -3229,8 +3280,9 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, } } dev_dbg(dwc->dev, "Going from (%d)--->(%d)\n", dwc->link_state, next); dwc->link_state = next; wake_up_interruptible(&dwc->wait_linkstate); dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state); } Loading Loading @@ -3322,7 +3374,7 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc, dwc->dbg_gadget_events.connect++; break; case DWC3_DEVICE_EVENT_WAKEUP: dwc3_gadget_wakeup_interrupt(dwc); dwc3_gadget_wakeup_interrupt(dwc, false); dwc->dbg_gadget_events.wakeup++; break; case DWC3_DEVICE_EVENT_LINK_STATUS_CHANGE: Loading
drivers/usb/gadget/composite.c +6 −21 Original line number Diff line number Diff line Loading @@ -363,8 +363,7 @@ int usb_get_func_interface_id(struct usb_function *func) return -ENODEV; } static int usb_func_wakeup_int(struct usb_function *func, bool use_pending_flag) static int usb_func_wakeup_int(struct usb_function *func) { int ret; int interface_id; Loading @@ -372,13 +371,14 @@ static int usb_func_wakeup_int(struct usb_function *func, struct usb_gadget *gadget; struct usb_composite_dev *cdev; pr_debug("%s - %s function wakeup, use pending: %u\n", __func__, func->name ? func->name : "", use_pending_flag); if (!func || !func->config || !func->config->cdev || !func->config->cdev->gadget) return -EINVAL; pr_debug("%s - %s function wakeup\n", __func__, func->name ? func->name : ""); gadget = func->config->cdev->gadget; if ((gadget->speed != USB_SPEED_SUPER) || !func->func_wakeup_allowed) { DBG(func->config->cdev, Loading @@ -391,13 +391,6 @@ static int usb_func_wakeup_int(struct usb_function *func, cdev = get_gadget_data(gadget); spin_lock_irqsave(&cdev->lock, flags); if (use_pending_flag && !func->func_wakeup_pending) { pr_debug("Pending flag is cleared - Function wakeup is cancelled.\n"); spin_unlock_irqrestore(&cdev->lock, flags); return 0; } ret = usb_get_func_interface_id(func); if (ret < 0) { ERROR(func->config->cdev, Loading @@ -410,14 +403,6 @@ static int usb_func_wakeup_int(struct usb_function *func, interface_id = ret; ret = usb_gadget_func_wakeup(gadget, interface_id); if (use_pending_flag) { func->func_wakeup_pending = false; } else { if (ret == -EAGAIN) func->func_wakeup_pending = true; } spin_unlock_irqrestore(&cdev->lock, flags); return ret; Loading @@ -430,7 +415,7 @@ int usb_func_wakeup(struct usb_function *func) pr_debug("%s function wakeup\n", func->name ? func->name : ""); ret = usb_func_wakeup_int(func, false); ret = usb_func_wakeup_int(func); if (ret == -EAGAIN) { DBG(func->config->cdev, "Function wakeup for %s could not complete due to suspend state. Delayed until after bus resume.\n", Loading Loading @@ -1914,7 +1899,7 @@ composite_resume(struct usb_gadget *gadget) if (cdev->config) { list_for_each_entry(f, &cdev->config->functions, list) { ret = usb_func_wakeup_int(f, true); ret = usb_func_wakeup_int(f); if (ret) { if (ret == -EAGAIN) { ERROR(f->config->cdev, Loading