diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index bce34a0b6d0e..0763dd3ba8aa 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -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) @@ -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); @@ -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; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index b09e35cb206e..dc2b4cdd588a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2116,6 +2116,28 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g) 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) { @@ -2770,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,