Loading arch/arm/configs/vendor/sdxlemur.config +1 −0 Original line number Diff line number Diff line Loading @@ -179,6 +179,7 @@ CONFIG_QTI_TZ_LOG=y CONFIG_SLAB_FREELIST_RANDOM=y CONFIG_QCOM_SOCINFO=y CONFIG_USB_DWC3=y CONFIG_USB_FUNC_WAKEUP_SUPPORTED=y CONFIG_USB_DWC3_MSM=y CONFIG_USB_QCOM_EMU_PHY=y CONFIG_USB_MSM_SSPHY_QMP=y Loading drivers/usb/dwc3/core.c +1 −0 Original line number Diff line number Diff line Loading @@ -1622,6 +1622,7 @@ static int dwc3_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dwc); init_waitqueue_head(&dwc->wait_linkstate); spin_lock_init(&dwc->lock); pm_runtime_no_callbacks(dev); Loading drivers/usb/dwc3/core.h +4 −0 Original line number Diff line number Diff line Loading @@ -1151,6 +1151,8 @@ struct dwc3_scratchpad_array { * @bh_dbg_index: index for capturing bh_completion_time and bh_handled_evt_cnt * @last_run_stop: timestamp denoting the last run_stop update * @is_remote_wakeup_enabled: remote wakeup status from host perspective * @wait_linkstate: waitqueue for waiting LINK to move into required state * @remote_wakeup_work: use to perform remote wakeup from this context */ struct dwc3 { struct work_struct drd_work; Loading Loading @@ -1397,6 +1399,8 @@ struct dwc3 { u32 gen2_tx_de_emph3; ktime_t last_run_stop; bool is_remote_wakeup_enabled; wait_queue_head_t wait_linkstate; struct work_struct remote_wakeup_work; }; #define INCRX_BURST_MODE 0 Loading drivers/usb/dwc3/ep0.c +6 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep); static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, struct dwc3_ep *dep, struct dwc3_request *req); static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl); static void dwc3_ep0_prepare_one_trb(struct dwc3_ep *dep, dma_addr_t buf_dma, u32 len, u32 type, bool chain) Loading Loading @@ -352,7 +354,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc, * Function Remote Wake Capable D0 * Function Remote Wakeup D1 */ break; return dwc3_ep0_delegate_req(dwc, ctrl); case USB_RECIP_ENDPOINT: dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); Loading Loading @@ -507,6 +509,9 @@ static int dwc3_ep0_handle_intf(struct dwc3 *dwc, * For now, we're not doing anything, just making sure we return * 0 so USB Command Verifier tests pass without any errors. */ ret = dwc3_ep0_delegate_req(dwc, ctrl); if (ret) return ret; break; default: ret = -EINVAL; Loading drivers/usb/dwc3/gadget.c +166 −26 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc); static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc); static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, bool remote_wakeup); /** * dwc3_gadget_set_test_mode - enables usb2 test modes Loading Loading @@ -1924,15 +1925,17 @@ static int dwc3_gadget_get_frame(struct usb_gadget *g) return __dwc3_gadget_get_frame(dwc); } static int __dwc3_gadget_wakeup(struct dwc3 *dwc) static int dwc3_gadget_remote_wakeup(struct dwc3 *dwc) { int retries; int ret; int ret = 0; u32 reg; u8 link_state; unsigned long flags; bool link_recover_only = false; dev_dbg(dwc->dev, "%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 @@ -1942,21 +1945,45 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc) reg = dwc3_readl(dwc->regs, DWC3_DSTS); link_state = DWC3_DSTS_USBLNKST(reg); switch (link_state) { case DWC3_LINK_STATE_RESET: case DWC3_LINK_STATE_RX_DET: /* in HS, means Early Suspend */ case DWC3_LINK_STATE_U3: /* in HS, means SUSPEND */ case DWC3_LINK_STATE_RESUME: break; case DWC3_LINK_STATE_U1: if (dwc->gadget.speed != USB_SPEED_SUPER) { link_recover_only = true; break; } fallthrough; default: return -EINVAL; dev_dbg(dwc->dev, "can't wakeup from link state %d\n", link_state); ret = -EINVAL; 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"); return ret; /* 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; } /* Recent versions do this automatically */ Loading @@ -1967,30 +1994,115 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_DCTL, reg); } /* poll until Link State changes to ON */ retries = 20000; spin_unlock_irqrestore(&dwc->lock, flags); enable_irq(dwc->irq); while (retries--) { reg = dwc3_readl(dwc->regs, DWC3_DSTS); /* * Have bigger value (16 sec) for timeout since some host PCs driving * resume for very long time (e.g. 8 sec) */ 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(16000)); /* in HS, means ON */ if (DWC3_DSTS_USBLNKST(reg) == DWC3_LINK_STATE_U0) break; 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 (!ret) { dev_dbg(dwc->dev, "Timeout moving into state(%d)\n", dwc->link_state); ret = -EINVAL; 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; } if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U0) { dev_err(dwc->dev, "failed to send remote wakeup\n"); return -EINVAL; /* * According to DWC3 databook, the controller does not * trigger a wakeup event when remote-wakeup is used. * Hence, after remote-wakeup sequence is complete, and * the device is back at U0 state, it is required that * the resume sequence is initiated by SW. */ if (!link_recover_only) dwc3_gadget_wakeup_interrupt(dwc, true); spin_unlock_irqrestore(&dwc->lock, flags); dev_dbg(dwc->dev, "%s: Exit\n", __func__); return ret; out: spin_unlock_irqrestore(&dwc->lock, flags); enable_irq(dwc->irq); out1: return ret; } return 0; #define DWC3_PM_RESUME_RETRIES 20 /* Max Number of retries */ #define DWC3_PM_RESUME_DELAY 100 /* 100 msec */ static void dwc3_gadget_remote_wakeup_work(struct work_struct *w) { struct dwc3 *dwc; int ret; static int retry_count; dwc = container_of(w, struct dwc3, remote_wakeup_work); ret = pm_runtime_get_sync(dwc->dev); if (ret) { /* pm_runtime_get_sync returns -EACCES error between * late_suspend and early_resume, wait for system resume to * finish and queue work again */ dev_dbg(dwc->dev, "PM runtime get sync failed, ret %d\n", ret); if (ret == -EACCES) { pm_runtime_put_noidle(dwc->dev); if (retry_count == DWC3_PM_RESUME_RETRIES) { retry_count = 0; dev_err(dwc->dev, "pm_runtime_get_sync timed out\n"); return; } msleep(DWC3_PM_RESUME_DELAY); retry_count++; schedule_work(&dwc->remote_wakeup_work); return; } } retry_count = 0; dbg_event(0xFF, "Gdgwake gsyn", atomic_read(&dwc->dev->power.usage_count)); ret = dwc3_gadget_remote_wakeup(dwc); if (ret) dev_err(dwc->dev, "Remote wakeup failed. ret = %d\n", ret); pm_runtime_put_noidle(dwc->dev); dbg_event(0xFF, "Gdgwake put", atomic_read(&dwc->dev->power.usage_count)); } static int dwc3_gadget_wakeup(struct usb_gadget *g) { struct dwc3 *dwc = gadget_to_dwc(g); unsigned long flags; int ret; spin_lock_irqsave(&dwc->lock, flags); if (!dwc->is_remote_wakeup_enabled) { Loading @@ -1999,11 +2111,32 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) return -EINVAL; } ret = __dwc3_gadget_wakeup(dwc); spin_unlock_irqrestore(&dwc->lock, flags); schedule_work(&dwc->remote_wakeup_work); return 0; } #ifdef CONFIG_USB_FUNC_WAKEUP_SUPPORTED static int dwc_gadget_func_wakeup(struct usb_gadget *g, int interface_id) { int ret = 0; struct dwc3 *dwc = gadget_to_dwc(g); if (dwc3_gadget_is_suspended(dwc)) { dev_dbg(dwc->dev, "USB bus is suspended, scheduling wakeup\n"); dwc3_gadget_wakeup(&dwc->gadget); return -EAGAIN; } ret = dwc3_send_gadget_generic_command(dwc, DWC3_DGCMD_XMIT_DEV, 0x1 | (interface_id << 4)); if (ret) dev_err(dwc->dev, "Function wakeup HW command failed, ret %d\n", ret); return ret; } #endif static int dwc3_gadget_set_selfpowered(struct usb_gadget *g, int is_selfpowered) Loading Loading @@ -2659,6 +2792,9 @@ static void __maybe_unused dwc3_gadget_set_speed(struct usb_gadget *g, static const struct usb_gadget_ops dwc3_gadget_ops = { .get_frame = dwc3_gadget_get_frame, .wakeup = dwc3_gadget_wakeup, #ifdef CONFIG_USB_FUNC_WAKEUP_SUPPORTED .func_wakeup = dwc_gadget_func_wakeup, #endif .set_selfpowered = dwc3_gadget_set_selfpowered, .vbus_session = dwc3_gadget_vbus_session, .vbus_draw = dwc3_gadget_vbus_draw, Loading Loading @@ -3286,6 +3422,7 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) usb_gadget_set_state(&dwc->gadget, USB_STATE_NOTATTACHED); dwc->connected = false; wake_up_interruptible(&dwc->wait_linkstate); } static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) Loading Loading @@ -3371,6 +3508,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->link_state = DWC3_LINK_STATE_U0; dwc->is_remote_wakeup_enabled = false; wake_up_interruptible(&dwc->wait_linkstate); } static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) Loading Loading @@ -3503,7 +3641,7 @@ 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) { enum dwc3_link_state link_state = dwc->link_state; Loading @@ -3511,7 +3649,7 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc) dwc->link_state = DWC3_LINK_STATE_U0; /* For L1 resume case, don't perform resume */ if (link_state != DWC3_LINK_STATE_U3) if (!remote_wakeup && link_state != DWC3_LINK_STATE_U3) return; /* Handle bus resume case */ Loading Loading @@ -3617,7 +3755,9 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, } dev_dbg(dwc->dev, "Going from (%d)--->(%d)\n", dwc->link_state, next); dbg_log_string("link state from %d to %d", dwc->link_state, next); dwc->link_state = next; wake_up_interruptible(&dwc->wait_linkstate); } static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc, Loading Loading @@ -3694,7 +3834,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_HIBER_REQ: Loading Loading @@ -3982,7 +4122,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) } dwc->irq_gadget = irq; INIT_WORK(&dwc->remote_wakeup_work, dwc3_gadget_remote_wakeup_work); dwc->ep0_trb = dma_alloc_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, &dwc->ep0_trb_addr, GFP_KERNEL); Loading Loading
arch/arm/configs/vendor/sdxlemur.config +1 −0 Original line number Diff line number Diff line Loading @@ -179,6 +179,7 @@ CONFIG_QTI_TZ_LOG=y CONFIG_SLAB_FREELIST_RANDOM=y CONFIG_QCOM_SOCINFO=y CONFIG_USB_DWC3=y CONFIG_USB_FUNC_WAKEUP_SUPPORTED=y CONFIG_USB_DWC3_MSM=y CONFIG_USB_QCOM_EMU_PHY=y CONFIG_USB_MSM_SSPHY_QMP=y Loading
drivers/usb/dwc3/core.c +1 −0 Original line number Diff line number Diff line Loading @@ -1622,6 +1622,7 @@ static int dwc3_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dwc); init_waitqueue_head(&dwc->wait_linkstate); spin_lock_init(&dwc->lock); pm_runtime_no_callbacks(dev); Loading
drivers/usb/dwc3/core.h +4 −0 Original line number Diff line number Diff line Loading @@ -1151,6 +1151,8 @@ struct dwc3_scratchpad_array { * @bh_dbg_index: index for capturing bh_completion_time and bh_handled_evt_cnt * @last_run_stop: timestamp denoting the last run_stop update * @is_remote_wakeup_enabled: remote wakeup status from host perspective * @wait_linkstate: waitqueue for waiting LINK to move into required state * @remote_wakeup_work: use to perform remote wakeup from this context */ struct dwc3 { struct work_struct drd_work; Loading Loading @@ -1397,6 +1399,8 @@ struct dwc3 { u32 gen2_tx_de_emph3; ktime_t last_run_stop; bool is_remote_wakeup_enabled; wait_queue_head_t wait_linkstate; struct work_struct remote_wakeup_work; }; #define INCRX_BURST_MODE 0 Loading
drivers/usb/dwc3/ep0.c +6 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,8 @@ static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep); static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, struct dwc3_ep *dep, struct dwc3_request *req); static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl); static void dwc3_ep0_prepare_one_trb(struct dwc3_ep *dep, dma_addr_t buf_dma, u32 len, u32 type, bool chain) Loading Loading @@ -352,7 +354,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc, * Function Remote Wake Capable D0 * Function Remote Wakeup D1 */ break; return dwc3_ep0_delegate_req(dwc, ctrl); case USB_RECIP_ENDPOINT: dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); Loading Loading @@ -507,6 +509,9 @@ static int dwc3_ep0_handle_intf(struct dwc3 *dwc, * For now, we're not doing anything, just making sure we return * 0 so USB Command Verifier tests pass without any errors. */ ret = dwc3_ep0_delegate_req(dwc, ctrl); if (ret) return ret; break; default: ret = -EINVAL; Loading
drivers/usb/dwc3/gadget.c +166 −26 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc); static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc); static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, bool remote_wakeup); /** * dwc3_gadget_set_test_mode - enables usb2 test modes Loading Loading @@ -1924,15 +1925,17 @@ static int dwc3_gadget_get_frame(struct usb_gadget *g) return __dwc3_gadget_get_frame(dwc); } static int __dwc3_gadget_wakeup(struct dwc3 *dwc) static int dwc3_gadget_remote_wakeup(struct dwc3 *dwc) { int retries; int ret; int ret = 0; u32 reg; u8 link_state; unsigned long flags; bool link_recover_only = false; dev_dbg(dwc->dev, "%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 @@ -1942,21 +1945,45 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc) reg = dwc3_readl(dwc->regs, DWC3_DSTS); link_state = DWC3_DSTS_USBLNKST(reg); switch (link_state) { case DWC3_LINK_STATE_RESET: case DWC3_LINK_STATE_RX_DET: /* in HS, means Early Suspend */ case DWC3_LINK_STATE_U3: /* in HS, means SUSPEND */ case DWC3_LINK_STATE_RESUME: break; case DWC3_LINK_STATE_U1: if (dwc->gadget.speed != USB_SPEED_SUPER) { link_recover_only = true; break; } fallthrough; default: return -EINVAL; dev_dbg(dwc->dev, "can't wakeup from link state %d\n", link_state); ret = -EINVAL; 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"); return ret; /* 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; } /* Recent versions do this automatically */ Loading @@ -1967,30 +1994,115 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_DCTL, reg); } /* poll until Link State changes to ON */ retries = 20000; spin_unlock_irqrestore(&dwc->lock, flags); enable_irq(dwc->irq); while (retries--) { reg = dwc3_readl(dwc->regs, DWC3_DSTS); /* * Have bigger value (16 sec) for timeout since some host PCs driving * resume for very long time (e.g. 8 sec) */ 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(16000)); /* in HS, means ON */ if (DWC3_DSTS_USBLNKST(reg) == DWC3_LINK_STATE_U0) break; 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 (!ret) { dev_dbg(dwc->dev, "Timeout moving into state(%d)\n", dwc->link_state); ret = -EINVAL; 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; } if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U0) { dev_err(dwc->dev, "failed to send remote wakeup\n"); return -EINVAL; /* * According to DWC3 databook, the controller does not * trigger a wakeup event when remote-wakeup is used. * Hence, after remote-wakeup sequence is complete, and * the device is back at U0 state, it is required that * the resume sequence is initiated by SW. */ if (!link_recover_only) dwc3_gadget_wakeup_interrupt(dwc, true); spin_unlock_irqrestore(&dwc->lock, flags); dev_dbg(dwc->dev, "%s: Exit\n", __func__); return ret; out: spin_unlock_irqrestore(&dwc->lock, flags); enable_irq(dwc->irq); out1: return ret; } return 0; #define DWC3_PM_RESUME_RETRIES 20 /* Max Number of retries */ #define DWC3_PM_RESUME_DELAY 100 /* 100 msec */ static void dwc3_gadget_remote_wakeup_work(struct work_struct *w) { struct dwc3 *dwc; int ret; static int retry_count; dwc = container_of(w, struct dwc3, remote_wakeup_work); ret = pm_runtime_get_sync(dwc->dev); if (ret) { /* pm_runtime_get_sync returns -EACCES error between * late_suspend and early_resume, wait for system resume to * finish and queue work again */ dev_dbg(dwc->dev, "PM runtime get sync failed, ret %d\n", ret); if (ret == -EACCES) { pm_runtime_put_noidle(dwc->dev); if (retry_count == DWC3_PM_RESUME_RETRIES) { retry_count = 0; dev_err(dwc->dev, "pm_runtime_get_sync timed out\n"); return; } msleep(DWC3_PM_RESUME_DELAY); retry_count++; schedule_work(&dwc->remote_wakeup_work); return; } } retry_count = 0; dbg_event(0xFF, "Gdgwake gsyn", atomic_read(&dwc->dev->power.usage_count)); ret = dwc3_gadget_remote_wakeup(dwc); if (ret) dev_err(dwc->dev, "Remote wakeup failed. ret = %d\n", ret); pm_runtime_put_noidle(dwc->dev); dbg_event(0xFF, "Gdgwake put", atomic_read(&dwc->dev->power.usage_count)); } static int dwc3_gadget_wakeup(struct usb_gadget *g) { struct dwc3 *dwc = gadget_to_dwc(g); unsigned long flags; int ret; spin_lock_irqsave(&dwc->lock, flags); if (!dwc->is_remote_wakeup_enabled) { Loading @@ -1999,11 +2111,32 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) return -EINVAL; } ret = __dwc3_gadget_wakeup(dwc); spin_unlock_irqrestore(&dwc->lock, flags); schedule_work(&dwc->remote_wakeup_work); return 0; } #ifdef CONFIG_USB_FUNC_WAKEUP_SUPPORTED static int dwc_gadget_func_wakeup(struct usb_gadget *g, int interface_id) { int ret = 0; struct dwc3 *dwc = gadget_to_dwc(g); if (dwc3_gadget_is_suspended(dwc)) { dev_dbg(dwc->dev, "USB bus is suspended, scheduling wakeup\n"); dwc3_gadget_wakeup(&dwc->gadget); return -EAGAIN; } ret = dwc3_send_gadget_generic_command(dwc, DWC3_DGCMD_XMIT_DEV, 0x1 | (interface_id << 4)); if (ret) dev_err(dwc->dev, "Function wakeup HW command failed, ret %d\n", ret); return ret; } #endif static int dwc3_gadget_set_selfpowered(struct usb_gadget *g, int is_selfpowered) Loading Loading @@ -2659,6 +2792,9 @@ static void __maybe_unused dwc3_gadget_set_speed(struct usb_gadget *g, static const struct usb_gadget_ops dwc3_gadget_ops = { .get_frame = dwc3_gadget_get_frame, .wakeup = dwc3_gadget_wakeup, #ifdef CONFIG_USB_FUNC_WAKEUP_SUPPORTED .func_wakeup = dwc_gadget_func_wakeup, #endif .set_selfpowered = dwc3_gadget_set_selfpowered, .vbus_session = dwc3_gadget_vbus_session, .vbus_draw = dwc3_gadget_vbus_draw, Loading Loading @@ -3286,6 +3422,7 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) usb_gadget_set_state(&dwc->gadget, USB_STATE_NOTATTACHED); dwc->connected = false; wake_up_interruptible(&dwc->wait_linkstate); } static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) Loading Loading @@ -3371,6 +3508,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->link_state = DWC3_LINK_STATE_U0; dwc->is_remote_wakeup_enabled = false; wake_up_interruptible(&dwc->wait_linkstate); } static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) Loading Loading @@ -3503,7 +3641,7 @@ 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) { enum dwc3_link_state link_state = dwc->link_state; Loading @@ -3511,7 +3649,7 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc) dwc->link_state = DWC3_LINK_STATE_U0; /* For L1 resume case, don't perform resume */ if (link_state != DWC3_LINK_STATE_U3) if (!remote_wakeup && link_state != DWC3_LINK_STATE_U3) return; /* Handle bus resume case */ Loading Loading @@ -3617,7 +3755,9 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, } dev_dbg(dwc->dev, "Going from (%d)--->(%d)\n", dwc->link_state, next); dbg_log_string("link state from %d to %d", dwc->link_state, next); dwc->link_state = next; wake_up_interruptible(&dwc->wait_linkstate); } static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc, Loading Loading @@ -3694,7 +3834,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_HIBER_REQ: Loading Loading @@ -3982,7 +4122,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) } dwc->irq_gadget = irq; INIT_WORK(&dwc->remote_wakeup_work, dwc3_gadget_remote_wakeup_work); dwc->ep0_trb = dma_alloc_coherent(dwc->sysdev, sizeof(*dwc->ep0_trb) * 2, &dwc->ep0_trb_addr, GFP_KERNEL); Loading