All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
To: Elson Roy Serrao <quic_eserrao@quicinc.com>,
	"balbi@kernel.org" <balbi@kernel.org>,
	"gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>
Cc: "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
	"quic_wcheng@quicinc.com" <quic_wcheng@quicinc.com>,
	"quic_jackp@quicinc.com" <quic_jackp@quicinc.com>,
	"quic_mrana@quicinc.com" <quic_mrana@quicinc.com>,
	Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Subject: Re: [PATCH 1/5] usb: dwc3: Add remote wakeup handling
Date: Wed, 3 Aug 2022 00:01:14 +0000	[thread overview]
Message-ID: <910da314-f00f-2fa0-c35d-fd176d63f18b@synopsys.com> (raw)
In-Reply-To: <1659467920-9095-2-git-send-email-quic_eserrao@quicinc.com>

On 8/2/2022, Elson Roy Serrao wrote:
> An usb device can initate a remote wakeup and bring the link out of
> suspend as dictated by the DEVICE_REMOTE_WAKEUP feature selector.
> Add support to handle this packet and set the remote wakeup capability
> accordingly.
>
> Some hosts may take longer time to initiate the resume
> signaling after device triggers a remote wakeup. So improve the
> gadget_wakeup op to interrupt based rather than polling based by
> enabling link status change events.
>
> Signed-off-by: Elson Roy Serrao <quic_eserrao@quicinc.com>
> ---
>   drivers/usb/dwc3/core.h   |  4 +++
>   drivers/usb/dwc3/ep0.c    |  4 +++
>   drivers/usb/dwc3/gadget.c | 69 ++++++++++++++++++++++++++++++++++++++++++++---
>   3 files changed, 74 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 4fe4287..3306b1c 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -1113,6 +1113,8 @@ struct dwc3_scratchpad_array {
>    *		     address.
>    * @num_ep_resized: carries the current number endpoints which have had its tx
>    *		    fifo resized.
> + * @is_remote_wakeup_enabled: remote wakeup status from host perspective
> + * @is_gadget_wakeup: remote wakeup requested via gadget op.
>    */
>   struct dwc3 {
>   	struct work_struct	drd_work;
> @@ -1326,6 +1328,8 @@ struct dwc3 {
>   	int			max_cfg_eps;
>   	int			last_fifo_depth;
>   	int			num_ep_resized;
> +	bool			is_remote_wakeup_enabled;
> +	bool			is_gadget_wakeup;
>   };
>   
>   #define INCRX_BURST_MODE 0
> diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
> index 197af63..4cc3d3a 100644
> --- a/drivers/usb/dwc3/ep0.c
> +++ b/drivers/usb/dwc3/ep0.c
> @@ -353,6 +353,9 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
>   				usb_status |= 1 << USB_DEV_STAT_U1_ENABLED;
>   			if (reg & DWC3_DCTL_INITU2ENA)
>   				usb_status |= 1 << USB_DEV_STAT_U2_ENABLED;
> +		} else {
> +			usb_status |= dwc->is_remote_wakeup_enabled <<
> +						USB_DEVICE_REMOTE_WAKEUP;

You need to create a new macro for function remote enabled. Name it 
something like USB_DEV_STAT_FUNC_RW_ENABLED to match with others in ch9.h

>   		}
>   
>   		break;
> @@ -473,6 +476,7 @@ static int dwc3_ep0_handle_device(struct dwc3 *dwc,
>   
>   	switch (wValue) {
>   	case USB_DEVICE_REMOTE_WAKEUP:
> +		dwc->is_remote_wakeup_enabled = set;
>   		break;
>   	/*
>   	 * 9.4.1 says only for SS, in AddressState only for
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 4366c45..d6697da 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -2232,6 +2232,22 @@ static const struct usb_ep_ops dwc3_gadget_ep_ops = {
>   
>   /* -------------------------------------------------------------------------- */
>   
> +static void linksts_change_events_set(struct dwc3 *dwc, bool set)

It should be named something that's consistent with the other functions. 
Something like dwc3_gadget_enable_linkstate_change_event()

> +{
> +	u32 reg;
> +
> +	reg = dwc3_readl(dwc->regs, DWC3_DEVTEN);
> +	if (set)
> +		reg |= DWC3_DEVTEN_ULSTCNGEN;
> +	else
> +		reg &= ~DWC3_DEVTEN_ULSTCNGEN;
> +
> +	dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
> +
> +	/* Required to complete this operation before returning */
> +	mb();

Why do we need memory barrier here? It's just register write, and we 
already have io barrier for that.

> +}
> +
>   static int dwc3_gadget_get_frame(struct usb_gadget *g)
>   {
>   	struct dwc3		*dwc = gadget_to_dwc(g);
> @@ -2270,9 +2286,13 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc)
>   		return -EINVAL;
>   	}
>   
> +	linksts_change_events_set(dwc, true);
> +
>   	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");
> +		linksts_change_events_set(dwc, false);
> +		dwc->is_gadget_wakeup = false;
>   		return ret;
>   	}
>   
> @@ -2284,9 +2304,15 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc)
>   		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
>   	}
>   
> +	/* If remote wakeup is triggered from function driver, bail out.

Follow this type of doc

/*
  * xxxx
  * yyyy
  */

> +	 * Since link status change events are enabled we would receive
> +	 * an U0 event when wakeup is successful.
> +	 */
> +	if (dwc->is_gadget_wakeup)
> +		return -EAGAIN;
> +
>   	/* poll until Link State changes to ON */
>   	retries = 20000;
> -
>   	while (retries--) {
>   		reg = dwc3_readl(dwc->regs, DWC3_DSTS);
>   
> @@ -2295,6 +2321,8 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc)
>   			break;
>   	}
>   
> +	linksts_change_events_set(dwc, false);
> +
>   	if (DWC3_DSTS_USBLNKST(reg) != DWC3_LINK_STATE_U0) {
>   		dev_err(dwc->dev, "failed to send remote wakeup\n");
>   		return -EINVAL;
> @@ -2310,7 +2338,20 @@ static int dwc3_gadget_wakeup(struct usb_gadget *g)
>   	int			ret;
>   
>   	spin_lock_irqsave(&dwc->lock, flags);
> +	if (g->speed < USB_SPEED_SUPER && !dwc->is_remote_wakeup_enabled) {
> +		dev_err(dwc->dev, "%s:remote wakeup not supported\n", __func__);
> +		ret =  -EPERM;
> +		goto out;
> +	}
> +	if (dwc->is_gadget_wakeup) {
> +		dev_err(dwc->dev, "%s: remote wakeup in progress\n", __func__);
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +	dwc->is_gadget_wakeup = true;
>   	ret = __dwc3_gadget_wakeup(dwc);
> +
> +out:
>   	spin_unlock_irqrestore(&dwc->lock, flags);
>   
>   	return ret;
> @@ -2766,6 +2807,9 @@ static int dwc3_gadget_start(struct usb_gadget *g,
>   
>   	spin_lock_irqsave(&dwc->lock, flags);
>   	dwc->gadget_driver	= driver;
> +	linksts_change_events_set(dwc, false);
> +	dwc->is_remote_wakeup_enabled = false;
> +	dwc->is_gadget_wakeup = false;
>   	spin_unlock_irqrestore(&dwc->lock, flags);
>   
>   	return 0;
> @@ -2785,6 +2829,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
>   
>   	spin_lock_irqsave(&dwc->lock, flags);
>   	dwc->gadget_driver	= NULL;
> +	linksts_change_events_set(dwc, false);
> +	dwc->is_remote_wakeup_enabled = false;
> +	dwc->is_gadget_wakeup = false;
>   	dwc->max_cfg_eps = 0;
>   	spin_unlock_irqrestore(&dwc->lock, flags);
>   
> @@ -3768,6 +3815,8 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
>   	usb_gadget_set_state(dwc->gadget, USB_STATE_NOTATTACHED);
>   
>   	dwc->connected = false;
> +	linksts_change_events_set(dwc, false);
> +	dwc->is_gadget_wakeup = false;
>   }
>   
>   static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
> @@ -3855,6 +3904,10 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
>   	reg = dwc3_readl(dwc->regs, DWC3_DCFG);
>   	reg &= ~(DWC3_DCFG_DEVADDR_MASK);
>   	dwc3_writel(dwc->regs, DWC3_DCFG, reg);
> +
> +	dwc->is_remote_wakeup_enabled = false;
> +	linksts_change_events_set(dwc, false);
> +	dwc->is_gadget_wakeup = false;
>   }
>   
>   static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
> @@ -3998,8 +4051,9 @@ 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, unsigned int evtinfo)
>   {
> +	enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK;
>   	/*
>   	 * TODO take core out of low power mode when that's
>   	 * implemented.
> @@ -4010,6 +4064,8 @@ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc)
>   		dwc->gadget_driver->resume(dwc->gadget);
>   		spin_lock(&dwc->lock);
>   	}
> +
> +	dwc->link_state = next;
>   }
>   
>   static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
> @@ -4091,6 +4147,13 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
>   	}
>   
>   	switch (next) {
> +	case DWC3_LINK_STATE_U0:
> +		if (dwc->is_gadget_wakeup) {
> +			linksts_change_events_set(dwc, false);
> +			dwc3_resume_gadget(dwc);
> +			dwc->is_gadget_wakeup = false;
> +		}
> +		break;
>   	case DWC3_LINK_STATE_U1:
>   		if (dwc->speed == USB_SPEED_SUPER)
>   			dwc3_suspend_gadget(dwc);
> @@ -4159,7 +4222,7 @@ static void dwc3_gadget_interrupt(struct dwc3 *dwc,
>   		dwc3_gadget_conndone_interrupt(dwc);
>   		break;
>   	case DWC3_DEVICE_EVENT_WAKEUP:
> -		dwc3_gadget_wakeup_interrupt(dwc);
> +		dwc3_gadget_wakeup_interrupt(dwc, event->event_info);
>   		break;
>   	case DWC3_DEVICE_EVENT_HIBER_REQ:
>   		if (dev_WARN_ONCE(dwc->dev, !dwc->has_hibernation,


  reply	other threads:[~2022-08-03  0:01 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-02 19:18 [PATCH 0/5] Add function suspend/resume and remote wakeup support Elson Roy Serrao
2022-08-02 19:18 ` [PATCH 1/5] usb: dwc3: Add remote wakeup handling Elson Roy Serrao
2022-08-03  0:01   ` Thinh Nguyen [this message]
2022-08-02 19:18 ` [PATCH 2/5] usb: gadget: Add function wakeup support Elson Roy Serrao
2022-08-02 23:51   ` Thinh Nguyen
2022-08-04 21:42     ` Elson Serrao
2022-08-05  1:26       ` Thinh Nguyen
2022-08-09 19:42         ` Elson Serrao
2022-08-10  1:08           ` Thinh Nguyen
2022-08-11 20:31             ` Elson Serrao
2022-08-12  2:00               ` Thinh Nguyen
2022-08-12  2:19                 ` Thinh Nguyen
2022-08-13  0:46                   ` Thinh Nguyen
2022-08-16 19:57                     ` Elson Serrao
2022-08-16 23:51                       ` Thinh Nguyen
2022-08-18 18:17                         ` Elson Serrao
2022-08-18 19:41                           ` Elson Serrao
2022-08-23  1:01                           ` Thinh Nguyen
2022-08-23 22:06                             ` Elson Serrao
2022-08-26  1:30                               ` Thinh Nguyen
2022-09-13 20:13                                 ` Elson Serrao
2022-09-15  2:06                                   ` Thinh Nguyen
2022-08-11 21:03             ` Elson Serrao
2022-08-12  2:07               ` Thinh Nguyen
2022-08-02 19:18 ` [PATCH 3/5] usb: dwc3: Add function suspend and " Elson Roy Serrao
2022-08-02 23:44   ` Thinh Nguyen
2022-08-02 19:18 ` [PATCH 4/5] usb: gadget: f_ecm: Add suspend/resume and remote " Elson Roy Serrao
2022-08-02 19:18 ` [PATCH 5/5] usb: gadget: f_ecm: Add function suspend and " Elson Roy Serrao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=910da314-f00f-2fa0-c35d-fd176d63f18b@synopsys.com \
    --to=thinh.nguyen@synopsys.com \
    --cc=balbi@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=quic_eserrao@quicinc.com \
    --cc=quic_jackp@quicinc.com \
    --cc=quic_mrana@quicinc.com \
    --cc=quic_wcheng@quicinc.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.