[PATCH] usb: gadget: Fix double free of device descriptor pointers

2021-04-19 Thread Wesley Cheng
From: Hemant Kumar 

Upon driver unbind usb_free_all_descriptors() function frees all
speed descriptor pointers without setting them to NULL. In case
gadget speed changes (i.e from super speed plus to super speed)
after driver unbind only upto super speed descriptor pointers get
populated. Super speed plus desc still holds the stale (already
freed) pointer. Fix this issue by setting all descriptor pointers
to NULL after freeing them in usb_free_all_descriptors().

Signed-off-by: Hemant Kumar 
Signed-off-by: Wesley Cheng 
---
 drivers/usb/gadget/config.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index 2d11535..8bb2577 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -194,9 +194,13 @@ EXPORT_SYMBOL_GPL(usb_assign_descriptors);
 void usb_free_all_descriptors(struct usb_function *f)
 {
usb_free_descriptors(f->fs_descriptors);
+   f->fs_descriptors = NULL;
usb_free_descriptors(f->hs_descriptors);
+   f->hs_descriptors = NULL;
usb_free_descriptors(f->ss_descriptors);
+   f->ss_descriptors = NULL;
usb_free_descriptors(f->ssp_descriptors);
+   f->ssp_descriptors = NULL;
 }
 EXPORT_SYMBOL_GPL(usb_free_all_descriptors);
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH] usb: dwc3: gadget: Avoid canceling current request for queuing error

2021-04-19 Thread Wesley Cheng



On 4/15/2021 12:28 PM, Thinh Nguyen wrote:
> Thinh Nguyen wrote:
>> Wesley Cheng wrote:
>>>
>>>
>>> On 4/14/2021 11:26 PM, Felipe Balbi wrote:
>>>> Wesley Cheng  writes:
>>>>
>>>>> If an error is received when issuing a start or update transfer
>>>>> command, the error handler will stop all active requests (including
>>>>> the current USB request), and call dwc3_gadget_giveback() to notify
>>>>> function drivers of the requests which have been stopped.  Avoid
>>>>> having to cancel the current request which is trying to be queued, as
>>>>> the function driver will handle the EP queue error accordingly.
>>>>> Simply unmap the request as it was done before, and allow previously
>>>>> started transfers to be cleaned up.
>>>>>
>>>>> Signed-off-by: Wesley Cheng 
>>>>> ---
>>>>>  drivers/usb/dwc3/gadget.c | 5 +
>>>>>  1 file changed, 5 insertions(+)
>>>>>
>>>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>>>> index e1b04c97..4200775 100644
>>>>> --- a/drivers/usb/dwc3/gadget.c
>>>>> +++ b/drivers/usb/dwc3/gadget.c
>>>>> @@ -1399,6 +1399,11 @@ static int __dwc3_gadget_kick_transfer(struct 
>>>>> dwc3_ep *dep)
>>>>>   if (ret == -EAGAIN)
>>>>>   return ret;
>>>>>  
>>>>> + /* Avoid canceling current request, as it has not been started 
>>>>> */
>>>>> + if (req->trb)
>>>>> + memset(req->trb, 0, sizeof(struct dwc3_trb));
>>>>
>>>> we don't need a full memset. I think ensuring HWO bit is zero is enough.
>>>>
>>> Hi Felipe,
>>>
>>> Thanks for the input/review, will make this change to just clear the HWO.
>>>
>>
>> Make sure to increment the dequeue pointer also. I think you can use
>> dwc3_gadget_ep_skip_trbs().
>>
> 
> Nevermind. There maybe a problem with using dwc3_gadget_ep_skip_trbs().
> 
> Thinh
> 
Hi Thinh,

Thank you for your input.  In this case (if kick transfer fails w/ an
error), would we still need to mess with the enqueue/dequeue pointers?
Not sure if my assumption is correct, but the TRB wouldn't have been
started, so we can use the same (failed) TRB for future requests, right?

I think one thing I will need to update is to loop through num_trbs and
clear all HWO bits if the above is not needed.

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH] usb: dwc3: gadget: Avoid canceling current request for queuing error

2021-04-15 Thread Wesley Cheng



On 4/14/2021 11:26 PM, Felipe Balbi wrote:
> Wesley Cheng  writes:
> 
>> If an error is received when issuing a start or update transfer
>> command, the error handler will stop all active requests (including
>> the current USB request), and call dwc3_gadget_giveback() to notify
>> function drivers of the requests which have been stopped.  Avoid
>> having to cancel the current request which is trying to be queued, as
>> the function driver will handle the EP queue error accordingly.
>> Simply unmap the request as it was done before, and allow previously
>> started transfers to be cleaned up.
>>
>> Signed-off-by: Wesley Cheng 
>> ---
>>  drivers/usb/dwc3/gadget.c | 5 +
>>  1 file changed, 5 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index e1b04c97..4200775 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -1399,6 +1399,11 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep 
>> *dep)
>>  if (ret == -EAGAIN)
>>  return ret;
>>  
>> +/* Avoid canceling current request, as it has not been started 
>> */
>> +if (req->trb)
>> +memset(req->trb, 0, sizeof(struct dwc3_trb));
> 
> we don't need a full memset. I think ensuring HWO bit is zero is enough.
> 
Hi Felipe,

Thanks for the input/review, will make this change to just clear the HWO.

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH] usb: dwc3: gadget: Avoid canceling current request for queuing error

2021-04-14 Thread Wesley Cheng
If an error is received when issuing a start or update transfer
command, the error handler will stop all active requests (including
the current USB request), and call dwc3_gadget_giveback() to notify
function drivers of the requests which have been stopped.  Avoid
having to cancel the current request which is trying to be queued, as
the function driver will handle the EP queue error accordingly.
Simply unmap the request as it was done before, and allow previously
started transfers to be cleaned up.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/gadget.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index e1b04c97..4200775 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1399,6 +1399,11 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep 
*dep)
if (ret == -EAGAIN)
return ret;
 
+   /* Avoid canceling current request, as it has not been started 
*/
+   if (req->trb)
+   memset(req->trb, 0, sizeof(struct dwc3_trb));
+   dwc3_gadget_del_and_unmap_request(dep, req, ret);
+
dwc3_stop_active_transfer(dep, true, true);
 
list_for_each_entry_safe(req, tmp, >started_list, list)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH] Revert "usb: dwc3: gadget: Prevent EP queuing while stopping transfers"

2021-04-01 Thread Wesley Cheng


On 4/1/2021 4:55 AM, Martin Kepplinger wrote:
> This reverts commit 9de47c3737e0c0207beb03615b320cabe495.
> 
> Signed-off-by: Martin Kepplinger 
> ---
> 
> I more or less blindly report:
> commit 9de47c ("usb: dwc3: gadget: Prevent EP queuing while stopping
> transfers") results in the below error every time I connect the type-c
> connector to the dwc3, configured with serial and ethernet gadgets.
> 
> fyi, I apply the following to dwc3 on this port:
> dr_mode = "otg";
> snps,dis_u3_susphy_quirk;   
> hnp-disable;
> srp-disable;
> adp-disable;
> usb-role-switch;
> 
> v5.12-rc5 does not have this error so I'm not sure whether it's
> more appropriate to add something to dwc3 than reverting. I hope usb
> people to know better and maybe even see the problem.
> 
> thanks,
>martin
> 
Hi Martin,

This has been fixed with the below:
https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git/commit/?h=usb-linus=5aef629704ad4d983ecf5c8a25840f16e45b6d59

Can you pull that in and give it a try?

Thanks
Wesley Cheng

> 
> 
> 
> [   51.148220] [ cut here ]
> [   51.148241] dwc3 3810.usb: No resource for ep2in
> [   51.148376] WARNING: CPU: 0 PID: 299 at drivers/usb/dwc3/gadget.c:360 
> dwc3_send_gadget_ep_cmd+0x570/0x740 [dwc3]
> [   51.148431] Modules linked in: aes_ce_ccm rfcomm algif_hash algif_skcipher 
> af_alg bnep qmi_wwan cdc_wdm usbnet mii option usb_wwan usbserial caam_jr 
> caamhash_desc caamalg_desc crypto_engine mousedev redpine_sdio redpine_91x 
> bluetooth uas usb_storage mac80211 st_lsm6dsx_spi aes_ce_blk crypto_simd 
> crct10dif_ce cfg80211 ghash_ce sha2_ce sha1_ce bq25890_charger s5k3l6xx 
> snd_soc_wm8962 hi846 vcnl4000 leds_lm3560 edt_ft5x06 ofpart 
> industrialio_triggered_buffer tps6598x st_lsm6dsx_i2c st_lsm6dsx kfifo_buf 
> gnss_mtk typec mxc_mipi_csi2_yav gnss_serial mx6s_capture gnss 
> videobuf2_dma_contig videobuf2_memops spi_nor v4l2_fwnode videobuf2_v4l2 
> videobuf2_common snd_soc_gtm601 snd_soc_simple_card videodev mtd 
> snd_soc_simple_card_utils mc snd_soc_fsl_sai imx_pcm_dma caam error 
> snvs_pwrkey imx_sdma virt_dma snd_soc_core imx2_wdt snd_pcm_dmaengine snd_pcm 
> watchdog snd_timer snd soundcore pwm_vibra rfkill_hks rfkill ledtrig_timer 
> usb_f_acm u_serial usb_f_rndis g_multi usb_f_mass_storage u_ether
> [   51.148759]  libcomposite ledtrig_pattern fuse ip_tables x_tables ipv6 
> xhci_plat_hcd xhci_hcd usbcore dwc3 cdns_mhdp_imx ulpi cdns_mhdp_drmcore 
> udc_core imx_dcss roles usb_common phy_fsl_imx8mq_usb clk_bd718x7
> [   51.148837] CPU: 0 PID: 299 Comm: irq/64-dwc3 Not tainted 
> 5.11.11-librem5-00334-ge4c4ff3624e9 #218
> [   51.148848] Hardware name: Purism Librem 5r4 (DT)
> [   51.148854] pstate: 6085 (nZCv daIf -PAN -UAO -TCO BTYPE=--)
> [   51.148863] pc : dwc3_send_gadget_ep_cmd+0x570/0x740 [dwc3]
> [   51.148894] lr : dwc3_send_gadget_ep_cmd+0x570/0x740 [dwc3]
> [   51.148924] sp : 800011cb3ac0
> [   51.148929] x29: 800011cb3ac0 x28: 032a7b00 
> [   51.148942] x27: 0327da00 x26:  
> [   51.148954] x25: ffea x24: 0006 
> [   51.148967] x23: bee1c080 x22: 800011cb3b7c 
> [   51.148979] x21: 0406 x20: bf17 
> [   51.148992] x19: 0001 x18:  
> [   51.149004] x17:  x16:  
> [   51.149016] x15:  x14: 8000114512c0 
> [   51.149028] x13: 1698 x12: 0040 
> [   51.149040] x11: 80001151a6f8 x10: e000 
> [   51.149052] x9 : 8000100b2b7c x8 : 80001146a6f8 
> [   51.149065] x7 : 80001151a6f8 x6 :  
> [   51.149077] x5 : bf939948 x4 :  
> [   51.149089] x3 : 0027 x2 :  
> [   51.149101] x1 :  x0 : 049ae040 
> [   51.149114] Call trace:
> [   51.149120]  dwc3_send_gadget_ep_cmd+0x570/0x740 [dwc3]
> [   51.149150]  __dwc3_gadget_ep_enable+0x288/0x4fc [dwc3]
> [   51.149179]  dwc3_gadget_ep_enable+0x6c/0x15c [dwc3]
> [   51.149209]  usb_ep_enable+0x48/0x110 [udc_core]
> [   51.149251]  rndis_set_alt+0x138/0x1c0 [usb_f_rndis]
> [   51.149276]  composite_setup+0x674/0x194c [libcomposite]
> [   51.149314]  dwc3_ep0_interrupt+0x9c4/0xb9c [dwc3]
> [   51.149344]  dwc3_thread_interrupt+0x8bc/0xe74 [dwc3]
> [   51.149374]  irq_thread_fn+0x38/0xb0
> [   51.1

Re: [PATCH v3 2/2] usb: dwc3: Fix DRD mode change sequence following programming guide

2021-03-30 Thread Wesley Cheng



On 3/29/2021 6:19 PM, Thinh Nguyen wrote:
> Wesley Cheng wrote:
>>
>>
>> On 3/6/2021 3:39 PM, Thinh Nguyen wrote:
>>> Wesley Cheng wrote:
>>>>
>>>> On 1/7/2021 5:51 PM, John Stultz wrote:
>>>>> In reviewing the previous patch, Thinh Nguyen pointed out that
>>>>> the DRD mode change sequence should be like the following when
>>>>> switching from host -> device according to the programming guide
>>>>> (for all DRD IPs):
>>>>> 1. Reset controller with GCTL.CoreSoftReset
>>>>> 2. Set GCTL.PrtCapDir(device)
>>>>> 3. Soft reset with DCTL.CSftRst
>>>>> 4. Then follow up with the initializing registers sequence
>>>>>
>>>>> The current code does:
>>>>> a. Soft reset with DCTL.CSftRst on driver probe
>>>>> b. Reset controller with GCTL.CoreSoftReset (added in previous
>>>>>patch)
>>>>> c. Set GCTL.PrtCapDir(device)
>>>>> d. < missing DCTL.CSftRst >
>>>>> e. Then follow up with initializing registers sequence
>>>>>
>>>>> So this patch adds the DCTL.CSftRst soft reset that was currently
>>>>> missing from the dwc3 mode switching.
>>>>>
>>>>> Cc: Felipe Balbi 
>>>>> Cc: Tejas Joglekar 
>>>>> Cc: Yang Fei 
>>>>> Cc: YongQin Liu 
>>>>> Cc: Andrzej Pietrasiewicz 
>>>>> Cc: Thinh Nguyen 
>>>>> Cc: Jun Li 
>>>>> Cc: Mauro Carvalho Chehab 
>>>>> Cc: Greg Kroah-Hartman 
>>>>> Cc: linux-...@vger.kernel.org
>>>>> Signed-off-by: John Stultz 
>>>>> ---
>>>>> Feedback would be appreciated. I'm a little worried I should be
>>>>> conditionalizing the DCTL.CSftRst on DRD mode controllers, but
>>>>> I'm really not sure what the right thing to do is for non-DRD
>>>>> mode controllers.
>>>>> ---
>>>>>  drivers/usb/dwc3/core.c | 3 +++
>>>>>  1 file changed, 3 insertions(+)
>>>>>
>>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>>> index b6a6b90eb2d5..71f8b07ecb99 100644
>>>>> --- a/drivers/usb/dwc3/core.c
>>>>> +++ b/drivers/usb/dwc3/core.c
>>>>> @@ -40,6 +40,8 @@
>>>>>  
>>>>>  #define DWC3_DEFAULT_AUTOSUSPEND_DELAY   5000 /* ms */
>>>>>  
>>>>> +static int dwc3_core_soft_reset(struct dwc3 *dwc);
>>>>> +
>>>>>  /**
>>>>>   * dwc3_get_dr_mode - Validates and sets dr_mode
>>>>>   * @dwc: pointer to our context structure
>>>>> @@ -177,6 +179,7 @@ static void __dwc3_set_mode(struct work_struct *work)
>>>>>  
>>>>>   dwc3_set_prtcap(dwc, dwc->desired_dr_role);
>>>>>  
>>>>> + dwc3_core_soft_reset(dwc);
>>>> Hi John/Thinh/Felipe,
>>>>
>>>> I actually added this change into my local branch, because we were
>>>> seeing an issue when switching from host mode --> peripheral mode.  What
>>>> was happening was that the RXFIFO register did not update back to the
>>>> expected value for peripheral mode by the time
>>>> dwc3_gadget_init_out_endpoint() was executed.  With the logic to
>>>> calculate the EP max packet limit based on RXFIFO reg, this caused all
>>>> EPs to be set with an EP max limit of 0.
>>>>
>>>> With this change, it seemed to help with the above issue.  However, can
>>>> we consider moving the core soft reset outside the spinlock?  At least
>>>> with our PHY init routines, we have some msleep() calls for waiting for
>>>> the PHYs to be ready, which will end up as a sleeping while atomic bug.
>>>> (not sure if PHY init is required to be called in atomic context)
>>>>
>>>> Thanks
>>>> Wesley Cheng
>>>
>>> Hi Wesley,
>>>
>>> Thanks for letting us know the issue you're having also.
>>>
>>> Yes, you need to wait a certain amount of time to synchronize with the
>>> PHY (at least 50ms for dwc_usb32 and dwc_usb31 v1.80a and above, and
>>> less for older versions). When removing the spinlock to use msleep(),
>>> just make sure that there's no race issue. BTW, how long does your setup
>>> need to msleep()?
>>>
>> Hi Thinh,
>>
>> Sorry for the late response.  My mist

Re: [PATCH v3 1/2] usb: dwc3: Trigger a GCTL soft reset when switching modes in DRD

2021-03-29 Thread Wesley Cheng



On 3/29/2021 3:20 PM, John Stultz wrote:
> On Mon, Mar 29, 2021 at 3:15 PM Wesley Cheng  wrote:
>>
>>
>>
>> On 3/19/2021 4:09 PM, Thinh Nguyen wrote:
>>> Wesley Cheng wrote:
>>>>
>>>>
>>>> On 3/8/2021 10:33 PM, Wesley Cheng wrote:
>>>>>
>>>>>
>>>>> On 3/8/2021 7:05 PM, Thinh Nguyen wrote:
>>>>>> Wesley Cheng wrote:
>>>>>>>
>>>>>>> On 3/6/2021 3:41 PM, Thinh Nguyen wrote:
>>>>>>>> Wesley Cheng wrote:
>>>>>>>>> On 1/8/2021 4:44 PM, Thinh Nguyen wrote:
>>>>>>>>>> Hi,
>>>>>>>>>>
>>>>>>>>>> John Stultz wrote:
>>>>>>>>>>> On Fri, Jan 8, 2021 at 4:26 AM Felipe Balbi  
>>>>>>>>>>> wrote:
>>>>>>>>>>>> Hi,
>>>>>>>>>>>>
>>>>>>>>>>>> John Stultz  writes:
>>>>>>>>>>>>> From: Yu Chen 
>>>>>>>>>>>>>
>>>>>>>>>>>>> Just resending this, as discussion died out a bit and I'm not
>>>>>>>>>>>>> sure how to make further progress. See here for debug data that
>>>>>>>>>>>>> was requested last time around:
>>>>>>>>>>>>>   
>>>>>>>>>>>>> https://urldefense.com/v3/__https://lore.kernel.org/lkml/calaqxlxdnaufjkx0an9xwwtfwvjmwigppy2aqsnj56yvnbu...@mail.gmail.com/__;!!A4F2R9G_pg!LNzuprAeg-O80SgolYkIkW4-ne-M-yLWCDUY9MygAIrQC398Z6gRJ9wnsnlqd3w$
>>>>>>>>>>>>>
>>>>>>>>>>>>> With the current dwc3 code on the HiKey960 we often see the
>>>>>>>>>>>>> COREIDLE flag get stuck off in __dwc3_gadget_start(), which
>>>>>>>>>>>>> seems to prevent the reset irq and causes the USB gadget to
>>>>>>>>>>>>> fail to initialize.
>>>>>>>>>>>>>
>>>>>>>>>>>>> We had seen occasional initialization failures with older
>>>>>>>>>>>>> kernels but with recent 5.x era kernels it seemed to be becoming
>>>>>>>>>>>>> much more common, so I dug back through some older trees and
>>>>>>>>>>>>> realized I dropped this quirk from Yu Chen during upstreaming
>>>>>>>>>>>>> as I couldn't provide a proper rational for it and it didn't
>>>>>>>>>>>>> seem to be necessary. I now realize I was wrong.
>>>>>>>>>>>>>
>>>>>>>>>>>>> After resubmitting the quirk, Thinh Nguyen pointed out that it
>>>>>>>>>>>>> shouldn't be a quirk at all and it is actually mentioned in the
>>>>>>>>>>>>> programming guide that it should be done when switching modes
>>>>>>>>>>>>> in DRD.
>>>>>>>>>>>>>
>>>>>>>>>>>>> So, to avoid these !COREIDLE lockups seen on HiKey960, this
>>>>>>>>>>>>> patch issues GCTL soft reset when switching modes if the
>>>>>>>>>>>>> controller is in DRD mode.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Cc: Felipe Balbi 
>>>>>>>>>>>>> Cc: Tejas Joglekar 
>>>>>>>>>>>>> Cc: Yang Fei 
>>>>>>>>>>>>> Cc: YongQin Liu 
>>>>>>>>>>>>> Cc: Andrzej Pietrasiewicz 
>>>>>>>>>>>>> Cc: Thinh Nguyen 
>>>>>>>>>>>>> Cc: Jun Li 
>>>>>>>>>>>>> Cc: Mauro Carvalho Chehab 
>>>>>>>>>>>>> Cc: Greg Kroah-Hartman 
>>>>>>>>>>>>> Cc: linux-...@vger.kernel.org
>>>>>>>>>>>>> Signed-off-by: Yu Chen 
>>>>>>>>>>>>> Signed-off-by: John Stultz 
>>>>>>>>>>>>> ---
>>>>>>>>>>>>> v2:
>>>>>&g

Re: [PATCH v3 2/2] usb: dwc3: Fix DRD mode change sequence following programming guide

2021-03-29 Thread Wesley Cheng



On 3/6/2021 3:39 PM, Thinh Nguyen wrote:
> Wesley Cheng wrote:
>>
>> On 1/7/2021 5:51 PM, John Stultz wrote:
>>> In reviewing the previous patch, Thinh Nguyen pointed out that
>>> the DRD mode change sequence should be like the following when
>>> switching from host -> device according to the programming guide
>>> (for all DRD IPs):
>>> 1. Reset controller with GCTL.CoreSoftReset
>>> 2. Set GCTL.PrtCapDir(device)
>>> 3. Soft reset with DCTL.CSftRst
>>> 4. Then follow up with the initializing registers sequence
>>>
>>> The current code does:
>>> a. Soft reset with DCTL.CSftRst on driver probe
>>> b. Reset controller with GCTL.CoreSoftReset (added in previous
>>>patch)
>>> c. Set GCTL.PrtCapDir(device)
>>> d. < missing DCTL.CSftRst >
>>> e. Then follow up with initializing registers sequence
>>>
>>> So this patch adds the DCTL.CSftRst soft reset that was currently
>>> missing from the dwc3 mode switching.
>>>
>>> Cc: Felipe Balbi 
>>> Cc: Tejas Joglekar 
>>> Cc: Yang Fei 
>>> Cc: YongQin Liu 
>>> Cc: Andrzej Pietrasiewicz 
>>> Cc: Thinh Nguyen 
>>> Cc: Jun Li 
>>> Cc: Mauro Carvalho Chehab 
>>> Cc: Greg Kroah-Hartman 
>>> Cc: linux-...@vger.kernel.org
>>> Signed-off-by: John Stultz 
>>> ---
>>> Feedback would be appreciated. I'm a little worried I should be
>>> conditionalizing the DCTL.CSftRst on DRD mode controllers, but
>>> I'm really not sure what the right thing to do is for non-DRD
>>> mode controllers.
>>> ---
>>>  drivers/usb/dwc3/core.c | 3 +++
>>>  1 file changed, 3 insertions(+)
>>>
>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>> index b6a6b90eb2d5..71f8b07ecb99 100644
>>> --- a/drivers/usb/dwc3/core.c
>>> +++ b/drivers/usb/dwc3/core.c
>>> @@ -40,6 +40,8 @@
>>>  
>>>  #define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */
>>>  
>>> +static int dwc3_core_soft_reset(struct dwc3 *dwc);
>>> +
>>>  /**
>>>   * dwc3_get_dr_mode - Validates and sets dr_mode
>>>   * @dwc: pointer to our context structure
>>> @@ -177,6 +179,7 @@ static void __dwc3_set_mode(struct work_struct *work)
>>>  
>>> dwc3_set_prtcap(dwc, dwc->desired_dr_role);
>>>  
>>> +   dwc3_core_soft_reset(dwc);
>> Hi John/Thinh/Felipe,
>>
>> I actually added this change into my local branch, because we were
>> seeing an issue when switching from host mode --> peripheral mode.  What
>> was happening was that the RXFIFO register did not update back to the
>> expected value for peripheral mode by the time
>> dwc3_gadget_init_out_endpoint() was executed.  With the logic to
>> calculate the EP max packet limit based on RXFIFO reg, this caused all
>> EPs to be set with an EP max limit of 0.
>>
>> With this change, it seemed to help with the above issue.  However, can
>> we consider moving the core soft reset outside the spinlock?  At least
>> with our PHY init routines, we have some msleep() calls for waiting for
>> the PHYs to be ready, which will end up as a sleeping while atomic bug.
>> (not sure if PHY init is required to be called in atomic context)
>>
>> Thanks
>> Wesley Cheng
> 
> Hi Wesley,
> 
> Thanks for letting us know the issue you're having also.
> 
> Yes, you need to wait a certain amount of time to synchronize with the
> PHY (at least 50ms for dwc_usb32 and dwc_usb31 v1.80a and above, and
> less for older versions). When removing the spinlock to use msleep(),
> just make sure that there's no race issue. BTW, how long does your setup
> need to msleep()?
> 
Hi Thinh,

Sorry for the late response.  My mistake, its actually just a usleep()
for a less than 100uS (polling for a status bit change, so it will exit
early if possible).  For this change, can we just move the
dwc3_core_soft_reset() outside of the spinlock?

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v3 1/2] usb: dwc3: Trigger a GCTL soft reset when switching modes in DRD

2021-03-29 Thread Wesley Cheng



On 3/19/2021 4:09 PM, Thinh Nguyen wrote:
> Wesley Cheng wrote:
>>
>>
>> On 3/8/2021 10:33 PM, Wesley Cheng wrote:
>>>
>>>
>>> On 3/8/2021 7:05 PM, Thinh Nguyen wrote:
>>>> Wesley Cheng wrote:
>>>>>
>>>>> On 3/6/2021 3:41 PM, Thinh Nguyen wrote:
>>>>>> Wesley Cheng wrote:
>>>>>>> On 1/8/2021 4:44 PM, Thinh Nguyen wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> John Stultz wrote:
>>>>>>>>> On Fri, Jan 8, 2021 at 4:26 AM Felipe Balbi  wrote:
>>>>>>>>>> Hi,
>>>>>>>>>>
>>>>>>>>>> John Stultz  writes:
>>>>>>>>>>> From: Yu Chen 
>>>>>>>>>>>
>>>>>>>>>>> Just resending this, as discussion died out a bit and I'm not
>>>>>>>>>>> sure how to make further progress. See here for debug data that
>>>>>>>>>>> was requested last time around:
>>>>>>>>>>>   
>>>>>>>>>>> https://urldefense.com/v3/__https://lore.kernel.org/lkml/calaqxlxdnaufjkx0an9xwwtfwvjmwigppy2aqsnj56yvnbu...@mail.gmail.com/__;!!A4F2R9G_pg!LNzuprAeg-O80SgolYkIkW4-ne-M-yLWCDUY9MygAIrQC398Z6gRJ9wnsnlqd3w$
>>>>>>>>>>>  
>>>>>>>>>>>
>>>>>>>>>>> With the current dwc3 code on the HiKey960 we often see the
>>>>>>>>>>> COREIDLE flag get stuck off in __dwc3_gadget_start(), which
>>>>>>>>>>> seems to prevent the reset irq and causes the USB gadget to
>>>>>>>>>>> fail to initialize.
>>>>>>>>>>>
>>>>>>>>>>> We had seen occasional initialization failures with older
>>>>>>>>>>> kernels but with recent 5.x era kernels it seemed to be becoming
>>>>>>>>>>> much more common, so I dug back through some older trees and
>>>>>>>>>>> realized I dropped this quirk from Yu Chen during upstreaming
>>>>>>>>>>> as I couldn't provide a proper rational for it and it didn't
>>>>>>>>>>> seem to be necessary. I now realize I was wrong.
>>>>>>>>>>>
>>>>>>>>>>> After resubmitting the quirk, Thinh Nguyen pointed out that it
>>>>>>>>>>> shouldn't be a quirk at all and it is actually mentioned in the
>>>>>>>>>>> programming guide that it should be done when switching modes
>>>>>>>>>>> in DRD.
>>>>>>>>>>>
>>>>>>>>>>> So, to avoid these !COREIDLE lockups seen on HiKey960, this
>>>>>>>>>>> patch issues GCTL soft reset when switching modes if the
>>>>>>>>>>> controller is in DRD mode.
>>>>>>>>>>>
>>>>>>>>>>> Cc: Felipe Balbi 
>>>>>>>>>>> Cc: Tejas Joglekar 
>>>>>>>>>>> Cc: Yang Fei 
>>>>>>>>>>> Cc: YongQin Liu 
>>>>>>>>>>> Cc: Andrzej Pietrasiewicz 
>>>>>>>>>>> Cc: Thinh Nguyen 
>>>>>>>>>>> Cc: Jun Li 
>>>>>>>>>>> Cc: Mauro Carvalho Chehab 
>>>>>>>>>>> Cc: Greg Kroah-Hartman 
>>>>>>>>>>> Cc: linux-...@vger.kernel.org
>>>>>>>>>>> Signed-off-by: Yu Chen 
>>>>>>>>>>> Signed-off-by: John Stultz 
>>>>>>>>>>> ---
>>>>>>>>>>> v2:
>>>>>>>>>>> * Rework to always call the GCTL soft reset in DRD mode,
>>>>>>>>>>>   rather then using a quirk as suggested by Thinh Nguyen
>>>>>>>>>>>
>>>>>>>>>>> v3:
>>>>>>>>>>> * Move GCTL soft reset under the spinlock as suggested by
>>>>>>>>>>>   Thinh Nguyen
>>>>>>>>>> Because this is such an invasive change, I would prefer that we get
>>>>>>>>>> Tested-By tags from a good fraction of 

[PATCH] usb: dwc3: gadget: Clear DEP flags after stop transfers in ep disable

2021-03-24 Thread Wesley Cheng
Ensure that dep->flags are cleared until after stop active transfers
is completed.  Otherwise, the ENDXFER command will not be executed
during ep disable.

Fixes: f09ddcfcb8c5 ("usb: dwc3: gadget: Prevent EP queuing while stopping 
transfers")
Reported-and-tested-by: Andy Shevchenko 
Tested-by: Marek Szyprowski 
Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/gadget.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index e1442fc..2c4d201 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -791,10 +791,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
reg &= ~DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
 
-   dep->stream_capable = false;
-   dep->type = 0;
-   dep->flags = 0;
-
/* Clear out the ep descriptors for non-ep0 */
if (dep->number > 1) {
dep->endpoint.comp_desc = NULL;
@@ -803,6 +799,10 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
 
dwc3_remove_requests(dwc, dep);
 
+   dep->stream_capable = false;
+   dep->type = 0;
+   dep->flags = 0;
+
return 0;
 }
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH v3] usb: dwc3: gadget: Prevent EP queuing while stopping transfers

2021-03-23 Thread Wesley Cheng



On 3/23/2021 10:27 AM, Andy Shevchenko wrote:
> On Tue, Mar 23, 2021 at 1:19 AM Wesley Cheng  wrote:
>>
>> Hi Andy,
>>
>> On 3/22/2021 2:14 PM, Andy Shevchenko wrote:
>>> On Mon, Mar 22, 2021 at 10:06 PM Wesley Cheng  wrote:
>>>>
>>>> Hi Andy,
>>>>
>>>> On 3/22/2021 12:34 PM, Andy Shevchenko wrote:
>>>>> On Mon, Mar 22, 2021 at 8:49 PM Wesley Cheng  
>>>>> wrote:
>>>>>>
>>>>>> Hi Andy,
>>>>>>
>>>>>> On 3/22/2021 5:48 AM, Andy Shevchenko wrote:
>>>>>>> On Fri, Mar 12, 2021 at 2:01 AM Wesley Cheng  
>>>>>>> wrote:
>>>>>>>>
>>>>>>>> In the situations where the DWC3 gadget stops active transfers, once
>>>>>>>> calling the dwc3_gadget_giveback(), there is a chance where a function
>>>>>>>> driver can queue a new USB request in between the time where the dwc3
>>>>>>>> lock has been released and re-aquired.  This occurs after we've already
>>>>>>>> issued an ENDXFER command.  When the stop active transfers continues
>>>>>>>> to remove USB requests from all dep lists, the newly added request will
>>>>>>>> also be removed, while controller still has an active TRB for it.
>>>>>>>> This can lead to the controller accessing an unmapped memory address.
>>>>>>>>
>>>>>>>> Fix this by ensuring parameters to prevent EP queuing are set before
>>>>>>>> calling the stop active transfers API.
>>>>>>>
>>>>>>>
>>>>>>> commit f09ddcfcb8c569675066337adac2ac205113471f
>>>>>>> Author: Wesley Cheng 
>>>>>>> Date:   Thu Mar 11 15:59:02 2021 -0800
>>>>>>>
>>>>>>>usb: dwc3: gadget: Prevent EP queuing while stopping transfers
>>>>>>>
>>>>>>> effectively broke my gadget setup.
>>>>>>>
>>>>>>> The output of the kernel (followed by non responsive state of USB 
>>>>>>> controller):
>>>>>>>
>>>>>>> [  195.228586] using random self ethernet address
>>>>>>> [  195.233104] using random host ethernet address
>>>>>>> [  195.245306] usb0: HOST MAC aa:bb:cc:dd:ee:f2
>>>>>>> [  195.249732] usb0: MAC aa:bb:cc:dd:ee:f1
>>>>>>> # [  195.773594] IPv6: ADDRCONF(NETDEV_CHANGE): usb0: link becomes ready
>>>>>>> [  195.780585] [ cut here ]
>>>>>>> [  195.785217] dwc3 dwc3.0.auto: No resource for ep2in
>>>>>>> [  195.790162] WARNING: CPU: 0 PID: 217 at
>>>>>>> drivers/usb/dwc3/gadget.c:360 dwc3_send_gadget_ep_cmd+0x4b9/0x670
>>>>>>> [  195.799760] Modules linked in: usb_f_eem u_ether libcomposite
>>>>>>> brcmfmac brcmutil mmc_block pwm_lpss_pci pwm_lps
>>>>>>> s snd_sof_pci_intel_tng snd_sof_pci snd_sof_acpi_intel_byt
>>>>>>> snd_sof_intel_ipc snd_sof_acpi snd_sof snd_sof_nocodec
>>>>>>> spi_pxa2xx_platform snd_sof_xtensa_dsp spi_pxa2xx_pci
>>>>>>> extcon_intel_mrfld intel_mrfld_adc sdhci_pci cqhci sdhci m
>>>>>>> mc_core intel_mrfld_pwrbtn intel_soc_pmic_mrfld hci_uart btbcm btintel
>>>>>>> [  195.835604] CPU: 0 PID: 217 Comm: irq/16-dwc3 Not tainted 
>>>>>>> 5.12.0-rc4+ #60
>>>>>>> [  195.842403] Hardware name: Intel Corporation Merrifield/BODEGA BAY,
>>>>>>> BIOS 542 2015.01.21:18.19.48
>>>>>>> [  195.851191] RIP: 0010:dwc3_send_gadget_ep_cmd+0x4b9/0x670
>>>>>>> [  195.856608] Code: cd 00 00 00 44 89 44 24 20 48 89 4c 24 18 e8 ee
>>>>>>> f7 e4 ff 48 8b 4c 24 18 4c 89 f2 48 c7 c7 b9
>>>>>>> ed 4f a0 48 89 c6 e8 ef 24 43 00 <0f> 0b 41 be ea ff ff ff 44 8b 44 24
>>>>>>> 20 e9 80 fc ff ff 41 83 fe 92
>>>>>>> [  195.875381] RSP: :a53c00373ba8 EFLAGS: 00010086
>>>>>>> [  195.880617] RAX:  RBX: 1387 RCX: 
>>>>>>> dfff
>>>>>>> [  195.887755] RDX: dfff RSI: ffea RDI: 
>>>>>>> 
>>>>>>> [  195.894893] RBP: 9ce8c8f2b028

Re: [PATCH v3] usb: dwc3: gadget: Prevent EP queuing while stopping transfers

2021-03-23 Thread Wesley Cheng



On 3/23/2021 10:27 AM, Andy Shevchenko wrote:
> On Tue, Mar 23, 2021 at 1:19 AM Wesley Cheng  wrote:
>>
>> Hi Andy,
>>
>> On 3/22/2021 2:14 PM, Andy Shevchenko wrote:
>>> On Mon, Mar 22, 2021 at 10:06 PM Wesley Cheng  wrote:
>>>>
>>>> Hi Andy,
>>>>
>>>> On 3/22/2021 12:34 PM, Andy Shevchenko wrote:
>>>>> On Mon, Mar 22, 2021 at 8:49 PM Wesley Cheng  
>>>>> wrote:
>>>>>>
>>>>>> Hi Andy,
>>>>>>
>>>>>> On 3/22/2021 5:48 AM, Andy Shevchenko wrote:
>>>>>>> On Fri, Mar 12, 2021 at 2:01 AM Wesley Cheng  
>>>>>>> wrote:
>>>>>>>>
>>>>>>>> In the situations where the DWC3 gadget stops active transfers, once
>>>>>>>> calling the dwc3_gadget_giveback(), there is a chance where a function
>>>>>>>> driver can queue a new USB request in between the time where the dwc3
>>>>>>>> lock has been released and re-aquired.  This occurs after we've already
>>>>>>>> issued an ENDXFER command.  When the stop active transfers continues
>>>>>>>> to remove USB requests from all dep lists, the newly added request will
>>>>>>>> also be removed, while controller still has an active TRB for it.
>>>>>>>> This can lead to the controller accessing an unmapped memory address.
>>>>>>>>
>>>>>>>> Fix this by ensuring parameters to prevent EP queuing are set before
>>>>>>>> calling the stop active transfers API.
>>>>>>>
>>>>>>>
>>>>>>> commit f09ddcfcb8c569675066337adac2ac205113471f
>>>>>>> Author: Wesley Cheng 
>>>>>>> Date:   Thu Mar 11 15:59:02 2021 -0800
>>>>>>>
>>>>>>>usb: dwc3: gadget: Prevent EP queuing while stopping transfers
>>>>>>>
>>>>>>> effectively broke my gadget setup.
>>>>>>>
>>>>>>> The output of the kernel (followed by non responsive state of USB 
>>>>>>> controller):
>>>>>>>
>>>>>>> [  195.228586] using random self ethernet address
>>>>>>> [  195.233104] using random host ethernet address
>>>>>>> [  195.245306] usb0: HOST MAC aa:bb:cc:dd:ee:f2
>>>>>>> [  195.249732] usb0: MAC aa:bb:cc:dd:ee:f1
>>>>>>> # [  195.773594] IPv6: ADDRCONF(NETDEV_CHANGE): usb0: link becomes ready
>>>>>>> [  195.780585] [ cut here ]
>>>>>>> [  195.785217] dwc3 dwc3.0.auto: No resource for ep2in
>>>>>>> [  195.790162] WARNING: CPU: 0 PID: 217 at
>>>>>>> drivers/usb/dwc3/gadget.c:360 dwc3_send_gadget_ep_cmd+0x4b9/0x670
>>>>>>> [  195.799760] Modules linked in: usb_f_eem u_ether libcomposite
>>>>>>> brcmfmac brcmutil mmc_block pwm_lpss_pci pwm_lps
>>>>>>> s snd_sof_pci_intel_tng snd_sof_pci snd_sof_acpi_intel_byt
>>>>>>> snd_sof_intel_ipc snd_sof_acpi snd_sof snd_sof_nocodec
>>>>>>> spi_pxa2xx_platform snd_sof_xtensa_dsp spi_pxa2xx_pci
>>>>>>> extcon_intel_mrfld intel_mrfld_adc sdhci_pci cqhci sdhci m
>>>>>>> mc_core intel_mrfld_pwrbtn intel_soc_pmic_mrfld hci_uart btbcm btintel
>>>>>>> [  195.835604] CPU: 0 PID: 217 Comm: irq/16-dwc3 Not tainted 
>>>>>>> 5.12.0-rc4+ #60
>>>>>>> [  195.842403] Hardware name: Intel Corporation Merrifield/BODEGA BAY,
>>>>>>> BIOS 542 2015.01.21:18.19.48
>>>>>>> [  195.851191] RIP: 0010:dwc3_send_gadget_ep_cmd+0x4b9/0x670
>>>>>>> [  195.856608] Code: cd 00 00 00 44 89 44 24 20 48 89 4c 24 18 e8 ee
>>>>>>> f7 e4 ff 48 8b 4c 24 18 4c 89 f2 48 c7 c7 b9
>>>>>>> ed 4f a0 48 89 c6 e8 ef 24 43 00 <0f> 0b 41 be ea ff ff ff 44 8b 44 24
>>>>>>> 20 e9 80 fc ff ff 41 83 fe 92
>>>>>>> [  195.875381] RSP: :a53c00373ba8 EFLAGS: 00010086
>>>>>>> [  195.880617] RAX:  RBX: 1387 RCX: 
>>>>>>> dfff
>>>>>>> [  195.887755] RDX: dfff RSI: ffea RDI: 
>>>>>>> 
>>>>>>> [  195.894893] RBP: 9ce8c8f2b028

Re: [PATCH] usb: gadget: Stall OS descriptor request for unsupported functions

2021-03-23 Thread Wesley Cheng



On 3/22/2021 11:25 PM, Jack Pham wrote:
> Hi Wesley,
> 
> On Mon, Mar 22, 2021 at 06:50:17PM -0700, Wesley Cheng wrote:
>> From: Chandana Kishori Chiluveru 
>>
>> Hosts which request "OS descriptors" from gadgets do so during
>> the enumeration phase and before the configuration is set with
>> SET_CONFIGURATION. Composite driver supports OS descriptor
>> handling in composite_setup function. This requires to pass
>> signature field, vendor code, compatibleID and subCompatibleID
>> from user space.
>>
>> For USB compositions that contain functions which don't implement os
>> descriptors, Windows is sending vendor specific requests for os
>> descriptors and composite driver handling this request with invalid
>> data. With this invalid info host resetting the bus and never
>> selecting the configuration and leading enumeration issue.
>>
>> Fix this by bailing out from the OS descriptor setup request
>> handling if the functions does not have OS descriptors compatibleID.
>>
>> Signed-off-by: Chandana Kishori Chiluveru 
>> Signed-off-by: Wesley Cheng 
>> ---
>>  drivers/usb/gadget/composite.c | 6 ++
>>  1 file changed, 6 insertions(+)
>>
>> diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
>> index 72a9797..473edda6 100644
>> --- a/drivers/usb/gadget/composite.c
>> +++ b/drivers/usb/gadget/composite.c
>> @@ -1945,6 +1945,12 @@ composite_setup(struct usb_gadget *gadget, const 
>> struct usb_ctrlrequest *ctrl)
>>  buf[6] = w_index;
>>  /* Number of ext compat interfaces */
>>  count = count_ext_compat(os_desc_cfg);
>> +/*
>> + * Bailout if device does not
>> + * have ext_compat interfaces.
>> + */
>> +if (count == 0)
>> +break;
>>  buf[8] = count;
>>  count *= 24; /* 24 B/ext compat desc */
>>  count += 16; /* header */
> 
> Do we still need this fix? IIRC we had this change in our downstream
> kernel to fix the case when dynamically re-configuring ConfigFS, i.e.
> changing the composition of functions wherein none of the interfaces
> support OS Descriptors, so this causes count_ext_compat() to return
> 0 and results in the issue described in $SUBJECT.
> 
Hi Jack,

You're correct.  We can address this as well in the userspace perspective.

> But I think this is more of a problem of an improperly configured
> ConfigFS gadget. If userspace instead removes the config from the
> gadget's os_desc subdirectory that should cause cdev->os_desc_config to
> be set to NULL and hence composite_setup() should never enter this
> handling at all, right?

Sure, I'll go with fixing it in the userspace, since the support to
stall the OS desc is already present in the composite driver as you
mentioned.  Thanks for the input.

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH] usb: gadget: Stall OS descriptor request for unsupported functions

2021-03-22 Thread Wesley Cheng
From: Chandana Kishori Chiluveru 

Hosts which request "OS descriptors" from gadgets do so during
the enumeration phase and before the configuration is set with
SET_CONFIGURATION. Composite driver supports OS descriptor
handling in composite_setup function. This requires to pass
signature field, vendor code, compatibleID and subCompatibleID
from user space.

For USB compositions that contain functions which don't implement os
descriptors, Windows is sending vendor specific requests for os
descriptors and composite driver handling this request with invalid
data. With this invalid info host resetting the bus and never
selecting the configuration and leading enumeration issue.

Fix this by bailing out from the OS descriptor setup request
handling if the functions does not have OS descriptors compatibleID.

Signed-off-by: Chandana Kishori Chiluveru 
Signed-off-by: Wesley Cheng 
---
 drivers/usb/gadget/composite.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 72a9797..473edda6 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1945,6 +1945,12 @@ composite_setup(struct usb_gadget *gadget, const struct 
usb_ctrlrequest *ctrl)
buf[6] = w_index;
/* Number of ext compat interfaces */
count = count_ext_compat(os_desc_cfg);
+   /*
+* Bailout if device does not
+* have ext_compat interfaces.
+*/
+   if (count == 0)
+   break;
buf[8] = count;
count *= 24; /* 24 B/ext compat desc */
count += 16; /* header */
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH v3] usb: dwc3: gadget: Prevent EP queuing while stopping transfers

2021-03-22 Thread Wesley Cheng
Hi Andy,

On 3/22/2021 2:14 PM, Andy Shevchenko wrote:
> On Mon, Mar 22, 2021 at 10:06 PM Wesley Cheng  wrote:
>>
>> Hi Andy,
>>
>> On 3/22/2021 12:34 PM, Andy Shevchenko wrote:
>>> On Mon, Mar 22, 2021 at 8:49 PM Wesley Cheng  wrote:
>>>>
>>>> Hi Andy,
>>>>
>>>> On 3/22/2021 5:48 AM, Andy Shevchenko wrote:
>>>>> On Fri, Mar 12, 2021 at 2:01 AM Wesley Cheng  
>>>>> wrote:
>>>>>>
>>>>>> In the situations where the DWC3 gadget stops active transfers, once
>>>>>> calling the dwc3_gadget_giveback(), there is a chance where a function
>>>>>> driver can queue a new USB request in between the time where the dwc3
>>>>>> lock has been released and re-aquired.  This occurs after we've already
>>>>>> issued an ENDXFER command.  When the stop active transfers continues
>>>>>> to remove USB requests from all dep lists, the newly added request will
>>>>>> also be removed, while controller still has an active TRB for it.
>>>>>> This can lead to the controller accessing an unmapped memory address.
>>>>>>
>>>>>> Fix this by ensuring parameters to prevent EP queuing are set before
>>>>>> calling the stop active transfers API.
>>>>>
>>>>>
>>>>> commit f09ddcfcb8c569675066337adac2ac205113471f
>>>>> Author: Wesley Cheng 
>>>>> Date:   Thu Mar 11 15:59:02 2021 -0800
>>>>>
>>>>>usb: dwc3: gadget: Prevent EP queuing while stopping transfers
>>>>>
>>>>> effectively broke my gadget setup.
>>>>>
>>>>> The output of the kernel (followed by non responsive state of USB 
>>>>> controller):
>>>>>
>>>>> [  195.228586] using random self ethernet address
>>>>> [  195.233104] using random host ethernet address
>>>>> [  195.245306] usb0: HOST MAC aa:bb:cc:dd:ee:f2
>>>>> [  195.249732] usb0: MAC aa:bb:cc:dd:ee:f1
>>>>> # [  195.773594] IPv6: ADDRCONF(NETDEV_CHANGE): usb0: link becomes ready
>>>>> [  195.780585] [ cut here ]
>>>>> [  195.785217] dwc3 dwc3.0.auto: No resource for ep2in
>>>>> [  195.790162] WARNING: CPU: 0 PID: 217 at
>>>>> drivers/usb/dwc3/gadget.c:360 dwc3_send_gadget_ep_cmd+0x4b9/0x670
>>>>> [  195.799760] Modules linked in: usb_f_eem u_ether libcomposite
>>>>> brcmfmac brcmutil mmc_block pwm_lpss_pci pwm_lps
>>>>> s snd_sof_pci_intel_tng snd_sof_pci snd_sof_acpi_intel_byt
>>>>> snd_sof_intel_ipc snd_sof_acpi snd_sof snd_sof_nocodec
>>>>> spi_pxa2xx_platform snd_sof_xtensa_dsp spi_pxa2xx_pci
>>>>> extcon_intel_mrfld intel_mrfld_adc sdhci_pci cqhci sdhci m
>>>>> mc_core intel_mrfld_pwrbtn intel_soc_pmic_mrfld hci_uart btbcm btintel
>>>>> [  195.835604] CPU: 0 PID: 217 Comm: irq/16-dwc3 Not tainted 5.12.0-rc4+ 
>>>>> #60
>>>>> [  195.842403] Hardware name: Intel Corporation Merrifield/BODEGA BAY,
>>>>> BIOS 542 2015.01.21:18.19.48
>>>>> [  195.851191] RIP: 0010:dwc3_send_gadget_ep_cmd+0x4b9/0x670
>>>>> [  195.856608] Code: cd 00 00 00 44 89 44 24 20 48 89 4c 24 18 e8 ee
>>>>> f7 e4 ff 48 8b 4c 24 18 4c 89 f2 48 c7 c7 b9
>>>>> ed 4f a0 48 89 c6 e8 ef 24 43 00 <0f> 0b 41 be ea ff ff ff 44 8b 44 24
>>>>> 20 e9 80 fc ff ff 41 83 fe 92
>>>>> [  195.875381] RSP: :a53c00373ba8 EFLAGS: 00010086
>>>>> [  195.880617] RAX:  RBX: 1387 RCX: 
>>>>> dfff
>>>>> [  195.887755] RDX: dfff RSI: ffea RDI: 
>>>>> 
>>>>> [  195.894893] RBP: 9ce8c8f2b028 R08: a0732288 R09: 
>>>>> 9ffb
>>>>> [  195.902034] R10: e000 R11: 3fff R12: 
>>>>> 00041006
>>>>> [  195.909170] R13: a53c00373c24 R14: 9ce8c11dadb0 R15: 
>>>>> 9ce8c2861700
>>>>> [  195.916310] FS:  () GS:9ce8fe20()
>>>>> knlGS:
>>>>> [  195.924409] CS:  0010 DS:  ES:  CR0: 80050033
>>>>> [  195.930161] CR2: f7f694a0 CR3: 38e0c000 CR4: 
>>>>> 001006f0
>>>>> [  195.937300] Call Trace:
>>&g

Re: [PATCH v3] usb: dwc3: gadget: Prevent EP queuing while stopping transfers

2021-03-22 Thread Wesley Cheng
Hi Andy,

On 3/22/2021 12:34 PM, Andy Shevchenko wrote:
> On Mon, Mar 22, 2021 at 8:49 PM Wesley Cheng  wrote:
>>
>> Hi Andy,
>>
>> On 3/22/2021 5:48 AM, Andy Shevchenko wrote:
>>> On Fri, Mar 12, 2021 at 2:01 AM Wesley Cheng  wrote:
>>>>
>>>> In the situations where the DWC3 gadget stops active transfers, once
>>>> calling the dwc3_gadget_giveback(), there is a chance where a function
>>>> driver can queue a new USB request in between the time where the dwc3
>>>> lock has been released and re-aquired.  This occurs after we've already
>>>> issued an ENDXFER command.  When the stop active transfers continues
>>>> to remove USB requests from all dep lists, the newly added request will
>>>> also be removed, while controller still has an active TRB for it.
>>>> This can lead to the controller accessing an unmapped memory address.
>>>>
>>>> Fix this by ensuring parameters to prevent EP queuing are set before
>>>> calling the stop active transfers API.
>>>
>>>
>>> commit f09ddcfcb8c569675066337adac2ac205113471f
>>> Author: Wesley Cheng 
>>> Date:   Thu Mar 11 15:59:02 2021 -0800
>>>
>>>usb: dwc3: gadget: Prevent EP queuing while stopping transfers
>>>
>>> effectively broke my gadget setup.
>>>
>>> The output of the kernel (followed by non responsive state of USB 
>>> controller):
>>>
>>> [  195.228586] using random self ethernet address
>>> [  195.233104] using random host ethernet address
>>> [  195.245306] usb0: HOST MAC aa:bb:cc:dd:ee:f2
>>> [  195.249732] usb0: MAC aa:bb:cc:dd:ee:f1
>>> # [  195.773594] IPv6: ADDRCONF(NETDEV_CHANGE): usb0: link becomes ready
>>> [  195.780585] [ cut here ]
>>> [  195.785217] dwc3 dwc3.0.auto: No resource for ep2in
>>> [  195.790162] WARNING: CPU: 0 PID: 217 at
>>> drivers/usb/dwc3/gadget.c:360 dwc3_send_gadget_ep_cmd+0x4b9/0x670
>>> [  195.799760] Modules linked in: usb_f_eem u_ether libcomposite
>>> brcmfmac brcmutil mmc_block pwm_lpss_pci pwm_lps
>>> s snd_sof_pci_intel_tng snd_sof_pci snd_sof_acpi_intel_byt
>>> snd_sof_intel_ipc snd_sof_acpi snd_sof snd_sof_nocodec
>>> spi_pxa2xx_platform snd_sof_xtensa_dsp spi_pxa2xx_pci
>>> extcon_intel_mrfld intel_mrfld_adc sdhci_pci cqhci sdhci m
>>> mc_core intel_mrfld_pwrbtn intel_soc_pmic_mrfld hci_uart btbcm btintel
>>> [  195.835604] CPU: 0 PID: 217 Comm: irq/16-dwc3 Not tainted 5.12.0-rc4+ #60
>>> [  195.842403] Hardware name: Intel Corporation Merrifield/BODEGA BAY,
>>> BIOS 542 2015.01.21:18.19.48
>>> [  195.851191] RIP: 0010:dwc3_send_gadget_ep_cmd+0x4b9/0x670
>>> [  195.856608] Code: cd 00 00 00 44 89 44 24 20 48 89 4c 24 18 e8 ee
>>> f7 e4 ff 48 8b 4c 24 18 4c 89 f2 48 c7 c7 b9
>>> ed 4f a0 48 89 c6 e8 ef 24 43 00 <0f> 0b 41 be ea ff ff ff 44 8b 44 24
>>> 20 e9 80 fc ff ff 41 83 fe 92
>>> [  195.875381] RSP: :a53c00373ba8 EFLAGS: 00010086
>>> [  195.880617] RAX:  RBX: 1387 RCX: 
>>> dfff
>>> [  195.887755] RDX: dfff RSI: ffea RDI: 
>>> 
>>> [  195.894893] RBP: 9ce8c8f2b028 R08: a0732288 R09: 
>>> 9ffb
>>> [  195.902034] R10: e000 R11: 3fff R12: 
>>> 00041006
>>> [  195.909170] R13: a53c00373c24 R14: 9ce8c11dadb0 R15: 
>>> 9ce8c2861700
>>> [  195.916310] FS:  () GS:9ce8fe20()
>>> knlGS:
>>> [  195.924409] CS:  0010 DS:  ES:  CR0: 80050033
>>> [  195.930161] CR2: f7f694a0 CR3: 38e0c000 CR4: 
>>> 001006f0
>>> [  195.937300] Call Trace:
>>> [  195.939755]  __dwc3_gadget_ep_enable+0x2d4/0x4e0
>>> [  195.944393]  ? dwc3_remove_requests.constprop.0+0x86/0x170
>>
>> Odd that this change would affect the USB enablment path, as they were
>> focused on the pullup disable path.  Would you happen to have any
>> downstream changes on top of v5.12-rc4 we could review to see if they
>> are still required? (ie where is the dwc3_remove_requests() coming from
>> during ep enable)
> 
> You may check my branch [1] on GH. Basically you may be interested in
> the commit:
> 0f86df1294ee7523060cc16eafaf4898c693eab0 REVERTME: usb: dwc3: gadget:
> skip endpoints ep[18]{in,out}
> Otherwise it's a clean v5.12-rc4 with a revert and another USB PHY
> sus

Re: [PATCH v3] usb: dwc3: gadget: Prevent EP queuing while stopping transfers

2021-03-22 Thread Wesley Cheng
Hi Andy,

On 3/22/2021 5:48 AM, Andy Shevchenko wrote:
> On Fri, Mar 12, 2021 at 2:01 AM Wesley Cheng  wrote:
>>
>> In the situations where the DWC3 gadget stops active transfers, once
>> calling the dwc3_gadget_giveback(), there is a chance where a function
>> driver can queue a new USB request in between the time where the dwc3
>> lock has been released and re-aquired.  This occurs after we've already
>> issued an ENDXFER command.  When the stop active transfers continues
>> to remove USB requests from all dep lists, the newly added request will
>> also be removed, while controller still has an active TRB for it.
>> This can lead to the controller accessing an unmapped memory address.
>>
>> Fix this by ensuring parameters to prevent EP queuing are set before
>> calling the stop active transfers API.
> 
> 
> commit f09ddcfcb8c569675066337adac2ac205113471f
> Author: Wesley Cheng 
> Date:   Thu Mar 11 15:59:02 2021 -0800
> 
>usb: dwc3: gadget: Prevent EP queuing while stopping transfers
> 
> effectively broke my gadget setup.
> 
> The output of the kernel (followed by non responsive state of USB controller):
> 
> [  195.228586] using random self ethernet address
> [  195.233104] using random host ethernet address
> [  195.245306] usb0: HOST MAC aa:bb:cc:dd:ee:f2
> [  195.249732] usb0: MAC aa:bb:cc:dd:ee:f1
> # [  195.773594] IPv6: ADDRCONF(NETDEV_CHANGE): usb0: link becomes ready
> [  195.780585] [ cut here ]
> [  195.785217] dwc3 dwc3.0.auto: No resource for ep2in
> [  195.790162] WARNING: CPU: 0 PID: 217 at
> drivers/usb/dwc3/gadget.c:360 dwc3_send_gadget_ep_cmd+0x4b9/0x670
> [  195.799760] Modules linked in: usb_f_eem u_ether libcomposite
> brcmfmac brcmutil mmc_block pwm_lpss_pci pwm_lps
> s snd_sof_pci_intel_tng snd_sof_pci snd_sof_acpi_intel_byt
> snd_sof_intel_ipc snd_sof_acpi snd_sof snd_sof_nocodec
> spi_pxa2xx_platform snd_sof_xtensa_dsp spi_pxa2xx_pci
> extcon_intel_mrfld intel_mrfld_adc sdhci_pci cqhci sdhci m
> mc_core intel_mrfld_pwrbtn intel_soc_pmic_mrfld hci_uart btbcm btintel
> [  195.835604] CPU: 0 PID: 217 Comm: irq/16-dwc3 Not tainted 5.12.0-rc4+ #60
> [  195.842403] Hardware name: Intel Corporation Merrifield/BODEGA BAY,
> BIOS 542 2015.01.21:18.19.48
> [  195.851191] RIP: 0010:dwc3_send_gadget_ep_cmd+0x4b9/0x670
> [  195.856608] Code: cd 00 00 00 44 89 44 24 20 48 89 4c 24 18 e8 ee
> f7 e4 ff 48 8b 4c 24 18 4c 89 f2 48 c7 c7 b9
> ed 4f a0 48 89 c6 e8 ef 24 43 00 <0f> 0b 41 be ea ff ff ff 44 8b 44 24
> 20 e9 80 fc ff ff 41 83 fe 92
> [  195.875381] RSP: :a53c00373ba8 EFLAGS: 00010086
> [  195.880617] RAX:  RBX: 1387 RCX: 
> dfff
> [  195.887755] RDX: dfff RSI: ffea RDI: 
> 
> [  195.894893] RBP: 9ce8c8f2b028 R08: a0732288 R09: 
> 9ffb
> [  195.902034] R10: e000 R11: 3fff R12: 
> 00041006
> [  195.909170] R13: a53c00373c24 R14: 9ce8c11dadb0 R15: 
> 9ce8c2861700
> [  195.916310] FS:  () GS:9ce8fe20()
> knlGS:
> [  195.924409] CS:  0010 DS:  ES:  CR0: 80050033
> [  195.930161] CR2: f7f694a0 CR3: 38e0c000 CR4: 
> 001006f0
> [  195.937300] Call Trace:
> [  195.939755]  __dwc3_gadget_ep_enable+0x2d4/0x4e0
> [  195.944393]  ? dwc3_remove_requests.constprop.0+0x86/0x170

Odd that this change would affect the USB enablment path, as they were
focused on the pullup disable path.  Would you happen to have any
downstream changes on top of v5.12-rc4 we could review to see if they
are still required? (ie where is the dwc3_remove_requests() coming from
during ep enable)

> [  195.949897]  dwc3_gadget_ep_enable+0x5d/0x120
> [  195.954274]  usb_ep_enable+0x27/0x80
> [  195.957869]  gether_connect+0x32/0x1f0 [u_ether]
> [  195.962512]  eem_set_alt+0x6d/0x140 [usb_f_eem]
> [  195.967061]  composite_setup+0x224/0x1ba0 [libcomposite]
> [  195.972405]  ? debug_dma_unmap_page+0x79/0x80
> [  195.976782]  ? configfs_composite_setup+0x6b/0x90 [libcomposite]
> [  195.982811]  configfs_composite_setup+0x6b/0x90 [libcomposite]
> [  195.988668]  dwc3_ep0_interrupt+0x459/0xa50
> [  195.992869]  dwc3_thread_interrupt+0x8e2/0xee0
> [  195.997327]  ? __schedule+0x237/0x6d0
> [  196.001005]  ? disable_irq_nosync+0x10/0x10
> [  196.005200]  irq_thread_fn+0x1b/0x60
> [  196.008789]  irq_thread+0xd6/0x170
> [  196.012202]  ? irq_thread_check_affinity+0x70/0x70
> [  196.017004]  ? irq_forced_thread_fn+0x70/0x70
> [  196.021373]  kthread+0x116/0x130
> [  196.024617]  ? kthread_create_worker_on_cpu+0x60/0x60
> [  196.029680]  ret_from_fork+0x22/0x30
> [  1

Re: [PATCH 2/2] usb: dwc3: gadget: Ignore EP queue requests during bus reset

2021-03-19 Thread Wesley Cheng
Hi Thinh,


On 3/19/2021 7:01 PM, Thinh Nguyen wrote:
> Wesley Cheng wrote:
>>
>>
>> On 3/19/2021 5:40 PM, Thinh Nguyen wrote:
>>> Hi,
>>>
>>> Wesley Cheng wrote:
>>>> The current dwc3_gadget_reset_interrupt() will stop any active
>>>> transfers, but only addresses blocking of EP queuing for while we are
>>>> coming from a disconnected scenario, i.e. after receiving the disconnect
>>>> event.  If the host decides to issue a bus reset on the device, the
>>>> connected parameter will still be set to true, allowing for EP queuing
>>>> to continue while we are disabling the functions.  To avoid this, set the
>>>> connected flag to false until the stop active transfers is complete.
>>>>
>>>> Signed-off-by: Wesley Cheng 
>>>> ---
>>>>  drivers/usb/dwc3/gadget.c | 9 +
>>>>  1 file changed, 9 insertions(+)
>>>>
>>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>>> index 6e14fdc..d5ed0f69 100644
>>>> --- a/drivers/usb/dwc3/gadget.c
>>>> +++ b/drivers/usb/dwc3/gadget.c
>>>> @@ -3327,6 +3327,15 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 
>>>> *dwc)
>>>>u32 reg;
>>>>  
>>>>/*
>>>> +   * Ideally, dwc3_reset_gadget() would trigger the function
>>>> +   * drivers to stop any active transfers through ep disable.
>>>> +   * However, for functions which defer ep disable, such as mass
>>>> +   * storage, we will need to rely on the call to stop active
>>>> +   * transfers here, and avoid allowing of request queuing.
>>>> +   */
>>>> +  dwc->connected = false;
>>>> +
>>>> +  /*
>>>> * WORKAROUND: DWC3 revisions <1.88a have an issue which
>>>> * would cause a missing Disconnect Event if there's a
>>>> * pending Setup Packet in the FIFO.
>>>>
>>>
>>> This doesn't look right. Did you have rebase issue with your local
>>> change again?
>>>
>>> BR,
>>> Thinh
>>>
>> Hi Thinh,
>>
>> This was rebased on Greg's usb-linus branch, which has commit
>> f09ddcfcb8c5 ("usb: dwc3: gadget: Prevent EP queuing while stopping
>> transfers") merged.
> 
> Ah I see.
> 
>>
>> commit f09ddcfcb8c5  moved the dwc->connected = true to after we have
>> finished stop active transfers.  However, this change will also ensure
>> that the connected flag is set to false to ensure that when we call stop
>> active transfers, nothing can prepare TRBs.  (previous commit only
>> addresses the case where we get the reset interrupt when coming from a
>> disconnected state)
>>
> 
> That still doesn't address this issue.
> 
> Because:
> 1) We're still protected by the spin_lock_irq*(), so this change doesn't
> make any difference while handling an event.

Thank you for the feedback.  So it is true that we lock dwc->lock while
handling EP/device events, but what these changes are trying to address
is that during dwc3_stop_active_transfers() we will eventually call
dwc3_gadget_giveback() to call the complete() functions registered by
the function driver.  Before we call the complete() callbacks, we unlock
dwc->lock, so we are no longer protected, and if there was a pending ep
queue from a function driver, that would allow it to acquire the lock
and continue preparing the TRBs.

> 2) We don't enable the interrupt for END_TRANSFER command completion
> when doing dwc3_stop_active_transfers(), the
> DWC3_EP_END_TRANSFER_PENDING flag will not be set to prevent preparing
> new requests.
> 
Agreed.  That is the reason for adding the check to dwc->connected in
__dwc3_gadget_ep_queue()

if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) {
dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
    dep->name);
return -ESHUTDOWN;

> We should do dwc->connected = true when we handle connection_done
> interrupt instead. The END_TRANSFER command should complete before this.
> 
So how this change will address the issue is:

1.  IRQ handler will acquire dwc->lock
2.  dwc3_gadget_reset_handler() sets dwc->connected = false
3.  Call to dwc3_stop_active_transfers()
---> dwc3_gadget_giveback() releases dwc->lock
4.  If there was a pending ep queue (waiting for dwc->lock) it can
continue here
5.  __dwc3_gadget_ep_queue() exits early due to dwc->connected = false
6.  dwc3_gadget_giveback() re-acquires dwc->lock and continues

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH 2/2] usb: dwc3: gadget: Ignore EP queue requests during bus reset

2021-03-19 Thread Wesley Cheng



On 3/19/2021 5:40 PM, Thinh Nguyen wrote:
> Hi,
> 
> Wesley Cheng wrote:
>> The current dwc3_gadget_reset_interrupt() will stop any active
>> transfers, but only addresses blocking of EP queuing for while we are
>> coming from a disconnected scenario, i.e. after receiving the disconnect
>> event.  If the host decides to issue a bus reset on the device, the
>> connected parameter will still be set to true, allowing for EP queuing
>> to continue while we are disabling the functions.  To avoid this, set the
>> connected flag to false until the stop active transfers is complete.
>>
>> Signed-off-by: Wesley Cheng 
>> ---
>>  drivers/usb/dwc3/gadget.c | 9 +
>>  1 file changed, 9 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index 6e14fdc..d5ed0f69 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -3327,6 +3327,15 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 
>> *dwc)
>>  u32 reg;
>>  
>>  /*
>> + * Ideally, dwc3_reset_gadget() would trigger the function
>> + * drivers to stop any active transfers through ep disable.
>> + * However, for functions which defer ep disable, such as mass
>> + * storage, we will need to rely on the call to stop active
>> + * transfers here, and avoid allowing of request queuing.
>> + */
>> +dwc->connected = false;
>> +
>> +/*
>>   * WORKAROUND: DWC3 revisions <1.88a have an issue which
>>   * would cause a missing Disconnect Event if there's a
>>   * pending Setup Packet in the FIFO.
>>
> 
> This doesn't look right. Did you have rebase issue with your local
> change again?
> 
> BR,
> Thinh
> 
Hi Thinh,

This was rebased on Greg's usb-linus branch, which has commit
f09ddcfcb8c5 ("usb: dwc3: gadget: Prevent EP queuing while stopping
transfers") merged.

commit f09ddcfcb8c5  moved the dwc->connected = true to after we have
finished stop active transfers.  However, this change will also ensure
that the connected flag is set to false to ensure that when we call stop
active transfers, nothing can prepare TRBs.  (previous commit only
addresses the case where we get the reset interrupt when coming from a
disconnected state)

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v3 1/2] usb: dwc3: Trigger a GCTL soft reset when switching modes in DRD

2021-03-19 Thread Wesley Cheng



On 3/8/2021 10:33 PM, Wesley Cheng wrote:
> 
> 
> On 3/8/2021 7:05 PM, Thinh Nguyen wrote:
>> Wesley Cheng wrote:
>>>
>>> On 3/6/2021 3:41 PM, Thinh Nguyen wrote:
>>>> Wesley Cheng wrote:
>>>>> On 1/8/2021 4:44 PM, Thinh Nguyen wrote:
>>>>>> Hi,
>>>>>>
>>>>>> John Stultz wrote:
>>>>>>> On Fri, Jan 8, 2021 at 4:26 AM Felipe Balbi  wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> John Stultz  writes:
>>>>>>>>> From: Yu Chen 
>>>>>>>>>
>>>>>>>>> Just resending this, as discussion died out a bit and I'm not
>>>>>>>>> sure how to make further progress. See here for debug data that
>>>>>>>>> was requested last time around:
>>>>>>>>>   
>>>>>>>>> https://urldefense.com/v3/__https://lore.kernel.org/lkml/calaqxlxdnaufjkx0an9xwwtfwvjmwigppy2aqsnj56yvnbu...@mail.gmail.com/__;!!A4F2R9G_pg!LNzuprAeg-O80SgolYkIkW4-ne-M-yLWCDUY9MygAIrQC398Z6gRJ9wnsnlqd3w$
>>>>>>>>>  
>>>>>>>>>
>>>>>>>>> With the current dwc3 code on the HiKey960 we often see the
>>>>>>>>> COREIDLE flag get stuck off in __dwc3_gadget_start(), which
>>>>>>>>> seems to prevent the reset irq and causes the USB gadget to
>>>>>>>>> fail to initialize.
>>>>>>>>>
>>>>>>>>> We had seen occasional initialization failures with older
>>>>>>>>> kernels but with recent 5.x era kernels it seemed to be becoming
>>>>>>>>> much more common, so I dug back through some older trees and
>>>>>>>>> realized I dropped this quirk from Yu Chen during upstreaming
>>>>>>>>> as I couldn't provide a proper rational for it and it didn't
>>>>>>>>> seem to be necessary. I now realize I was wrong.
>>>>>>>>>
>>>>>>>>> After resubmitting the quirk, Thinh Nguyen pointed out that it
>>>>>>>>> shouldn't be a quirk at all and it is actually mentioned in the
>>>>>>>>> programming guide that it should be done when switching modes
>>>>>>>>> in DRD.
>>>>>>>>>
>>>>>>>>> So, to avoid these !COREIDLE lockups seen on HiKey960, this
>>>>>>>>> patch issues GCTL soft reset when switching modes if the
>>>>>>>>> controller is in DRD mode.
>>>>>>>>>
>>>>>>>>> Cc: Felipe Balbi 
>>>>>>>>> Cc: Tejas Joglekar 
>>>>>>>>> Cc: Yang Fei 
>>>>>>>>> Cc: YongQin Liu 
>>>>>>>>> Cc: Andrzej Pietrasiewicz 
>>>>>>>>> Cc: Thinh Nguyen 
>>>>>>>>> Cc: Jun Li 
>>>>>>>>> Cc: Mauro Carvalho Chehab 
>>>>>>>>> Cc: Greg Kroah-Hartman 
>>>>>>>>> Cc: linux-...@vger.kernel.org
>>>>>>>>> Signed-off-by: Yu Chen 
>>>>>>>>> Signed-off-by: John Stultz 
>>>>>>>>> ---
>>>>>>>>> v2:
>>>>>>>>> * Rework to always call the GCTL soft reset in DRD mode,
>>>>>>>>>   rather then using a quirk as suggested by Thinh Nguyen
>>>>>>>>>
>>>>>>>>> v3:
>>>>>>>>> * Move GCTL soft reset under the spinlock as suggested by
>>>>>>>>>   Thinh Nguyen
>>>>>>>> Because this is such an invasive change, I would prefer that we get
>>>>>>>> Tested-By tags from a good fraction of the users before applying these
>>>>>>>> two changes.
>>>>>>> I'm happy to reach out to folks to try to get that. Though I'm
>>>>>>> wondering if it would be better to put it behind a dts quirk flag, as
>>>>>>> originally proposed?
>>>>>>>
>>>>>>> https://urldefense.com/v3/__https://lore.kernel.org/lkml/20201021181803.79650-1-john.stu...@linaro.org/__;!!A4F2R9G_pg!LNzuprAeg-O80SgolYkIkW4-ne-M-yLWCDUY9MygAIrQC398Z6gRJ9wnRWITZfc$
>>>>>>>  
>>>>>>>
>

[PATCH 1/2] usb: dwc3: gadget: Avoid continuing preparing TRBs during teardown

2021-03-19 Thread Wesley Cheng
Add checks similar to dwc3_gadget_ep_queue() before kicking off
transfers after getting an endpoint completion event.   Since cleaning
up completed requests will momentarily unlock dwc->lock, there is a
chance for a sequence like pullup disable to be executed.  This can
lead to preparing a TRB, which will be removed by the pullup disable
routine.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/gadget.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 4a337f3..6e14fdc 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2912,6 +2912,11 @@ static void 
dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep,
 static bool dwc3_gadget_ep_should_continue(struct dwc3_ep *dep)
 {
struct dwc3_request *req;
+   struct dwc3 *dwc = dep->dwc;
+
+   if (!dep->endpoint.desc || !dwc->pullups_connected ||
+   !dwc->connected)
+   return false;
 
if (!list_empty(>pending_list))
return true;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 0/2] Fix allowing of ep queuing while stopping transfers

2021-03-19 Thread Wesley Cheng
commit f09ddcfcb8c5 ("usb: dwc3: gadget: Prevent EP queuing while stopping
transfers") addressed an issue where the DWC3 gadget was still allowing EP
queuing to occur while the pullup disable routine was executing.  This led to
a situation where the controller prepares a TRB, which will be unmapped by the
stop active transfer call.

In addition to the above, there are a few other places in the DWC3 gadget where
we need to block preparing of TRBs:

 1. While the DWC3 gadget cleans up completed TRBs (during
dwc3_gadget_endpoint_trbs_complete()), DWC3 gadget giveback is utilized and
will release the dwc->lock.  If a pullup disable call occurs while the
cleanup is happening, then there is a chance dwc3_gadget_ep_should_continue
will prepare a TRB, which will later on be unmapped by the stop active
transfer in the pullup disable path.

 2. If we are in the CONFIGURED state and the host issues a bus RESET.  In this
situation, the connected flag is still set to true while we stop active
transfers, which can lead to the same initial problem.  Ideally, function
drivers would stop any pending usb requests through dwc3_reset_gadget()
using the EP disable call, but for some function drivers, this does not
occur synchronously in their disable() callback.  These functions would rely
on the stop active transfers in the reset handler to issue the endxfer cmd.

Wesley Cheng (2):
  usb: dwc3: gadget: Avoid continuing preparing TRBs during teardown
  usb: dwc3: gadget: Ignore EP queue requests during bus reset

 drivers/usb/dwc3/gadget.c | 14 ++
 1 file changed, 14 insertions(+)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 2/2] usb: dwc3: gadget: Ignore EP queue requests during bus reset

2021-03-19 Thread Wesley Cheng
The current dwc3_gadget_reset_interrupt() will stop any active
transfers, but only addresses blocking of EP queuing for while we are
coming from a disconnected scenario, i.e. after receiving the disconnect
event.  If the host decides to issue a bus reset on the device, the
connected parameter will still be set to true, allowing for EP queuing
to continue while we are disabling the functions.  To avoid this, set the
connected flag to false until the stop active transfers is complete.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/gadget.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 6e14fdc..d5ed0f69 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -3327,6 +3327,15 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
u32 reg;
 
/*
+* Ideally, dwc3_reset_gadget() would trigger the function
+* drivers to stop any active transfers through ep disable.
+* However, for functions which defer ep disable, such as mass
+* storage, we will need to rely on the call to stop active
+* transfers here, and avoid allowing of request queuing.
+*/
+   dwc->connected = false;
+
+   /*
 * WORKAROUND: DWC3 revisions <1.88a have an issue which
 * would cause a missing Disconnect Event if there's a
 * pending Setup Packet in the FIFO.
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v3] usb: dwc3: gadget: Prevent EP queuing while stopping transfers

2021-03-11 Thread Wesley Cheng
In the situations where the DWC3 gadget stops active transfers, once
calling the dwc3_gadget_giveback(), there is a chance where a function
driver can queue a new USB request in between the time where the dwc3
lock has been released and re-aquired.  This occurs after we've already
issued an ENDXFER command.  When the stop active transfers continues
to remove USB requests from all dep lists, the newly added request will
also be removed, while controller still has an active TRB for it.
This can lead to the controller accessing an unmapped memory address.

Fix this by ensuring parameters to prevent EP queuing are set before
calling the stop active transfers API.

Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the 
controller")
Signed-off-by: Wesley Cheng 
---
Changes since V2:
 - Removed duplicate dwc->connected = false setting in pullup routine

Changes since V1:
 - Added Fixes tag to point to the commit this is addressing

 drivers/usb/dwc3/gadget.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 4780983..2c94cc9 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -783,8 +783,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
 
trace_dwc3_gadget_ep_disable(dep);
 
-   dwc3_remove_requests(dwc, dep);
-
/* make sure HW endpoint isn't stalled */
if (dep->flags & DWC3_EP_STALL)
__dwc3_gadget_ep_set_halt(dep, 0, false);
@@ -803,6 +801,8 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->endpoint.desc = NULL;
}
 
+   dwc3_remove_requests(dwc, dep);
+
return 0;
 }
 
@@ -1617,7 +1617,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, 
struct dwc3_request *req)
 {
struct dwc3 *dwc = dep->dwc;
 
-   if (!dep->endpoint.desc || !dwc->pullups_connected) {
+   if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) {
dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
dep->name);
return -ESHUTDOWN;
@@ -2247,6 +2247,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
if (!is_on) {
u32 count;
 
+   dwc->connected = false;
/*
 * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
 * Section 4.1.8 Table 4-7, it states that for a 
device-initiated
@@ -2271,7 +2272,6 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
dwc->ev_buf->length;
}
-   dwc->connected = false;
} else {
__dwc3_gadget_start(dwc);
}
@@ -3329,8 +3329,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 {
u32 reg;
 
-   dwc->connected = true;
-
/*
 * WORKAROUND: DWC3 revisions <1.88a have an issue which
 * would cause a missing Disconnect Event if there's a
@@ -3370,6 +3368,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 * transfers."
 */
dwc3_stop_active_transfers(dwc);
+   dwc->connected = true;
 
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg &= ~DWC3_DCTL_TSTCTRL_MASK;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH v2] usb: dwc3: gadget: Prevent EP queuing while stopping transfers

2021-03-11 Thread Wesley Cheng



On 3/11/2021 3:18 PM, Thinh Nguyen wrote:
> Wesley Cheng wrote:
>> In the situations where the DWC3 gadget stops active transfers, once
>> calling the dwc3_gadget_giveback(), there is a chance where a function
>> driver can queue a new USB request in between the time where the dwc3
>> lock has been released and re-aquired.  This occurs after we've already
>> issued an ENDXFER command.  When the stop active transfers continues
>> to remove USB requests from all dep lists, the newly added request will
>> also be removed, while controller still has an active TRB for it.
>> This can lead to the controller accessing an unmapped memory address.
>>
>> Fix this by ensuring parameters to prevent EP queuing are set before
>> calling the stop active transfers API.
>>
>> Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the 
>> controller")
>> Signed-off-by: Wesley Cheng 
>> ---
>> Changes since V1:
>>  - Added Fixes tag to point to the commit this is addressing
>>
>>  drivers/usb/dwc3/gadget.c | 10 +-
>>  1 file changed, 5 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index 4780983..4d98fbf 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -783,8 +783,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
>>  
>>  trace_dwc3_gadget_ep_disable(dep);
>>  
>> -dwc3_remove_requests(dwc, dep);
>> -
>>  /* make sure HW endpoint isn't stalled */
>>  if (dep->flags & DWC3_EP_STALL)
>>  __dwc3_gadget_ep_set_halt(dep, 0, false);
>> @@ -803,6 +801,8 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
>>  dep->endpoint.desc = NULL;
>>  }
>>  
>> +dwc3_remove_requests(dwc, dep);
>> +
>>  return 0;
>>  }
>>  
>> @@ -1617,7 +1617,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, 
>> struct dwc3_request *req)
>>  {
>>  struct dwc3 *dwc = dep->dwc;
>>  
>> -if (!dep->endpoint.desc || !dwc->pullups_connected) {
>> +if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) {
>>  dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
>>  dep->name);
>>  return -ESHUTDOWN;
>> @@ -2247,6 +2247,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, 
>> int is_on)
>>  if (!is_on) {
>>  u32 count;
>>  
>> +dwc->connected = false;
> 
> 
> You want to set this before __dwc3_gadget_stop() right? Then you may
> want to remove this same setting few lines below this. Otherwise, this
> looks good.
> 
> Thanks,
> Thinh
> 
Hi Thinh,

Ah, good catch, must've missed that while porting this over from my
local branch.  Will remove that connected false setting a few lines down.

Thanks
Wesley Cheng

> 
>>  /*
>>   * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
>>   * Section 4.1.8 Table 4-7, it states that for a 
>> device-initiated
>> @@ -3329,8 +3330,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 
>> *dwc)
>>  {
>>  u32 reg;
>>  
>> -dwc->connected = true;
>> -
>>  /*
>>   * WORKAROUND: DWC3 revisions <1.88a have an issue which
>>   * would cause a missing Disconnect Event if there's a
>> @@ -3370,6 +3369,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 
>> *dwc)
>>   * transfers."
>>   */
>>  dwc3_stop_active_transfers(dwc);
>> +dwc->connected = true;
>>  
>>  reg = dwc3_readl(dwc->regs, DWC3_DCTL);
>>  reg &= ~DWC3_DCTL_TSTCTRL_MASK;
>>
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH v2] usb: dwc3: gadget: Prevent EP queuing while stopping transfers

2021-03-11 Thread Wesley Cheng
In the situations where the DWC3 gadget stops active transfers, once
calling the dwc3_gadget_giveback(), there is a chance where a function
driver can queue a new USB request in between the time where the dwc3
lock has been released and re-aquired.  This occurs after we've already
issued an ENDXFER command.  When the stop active transfers continues
to remove USB requests from all dep lists, the newly added request will
also be removed, while controller still has an active TRB for it.
This can lead to the controller accessing an unmapped memory address.

Fix this by ensuring parameters to prevent EP queuing are set before
calling the stop active transfers API.

Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the 
controller")
Signed-off-by: Wesley Cheng 
---
Changes since V1:
 - Added Fixes tag to point to the commit this is addressing

 drivers/usb/dwc3/gadget.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 4780983..4d98fbf 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -783,8 +783,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
 
trace_dwc3_gadget_ep_disable(dep);
 
-   dwc3_remove_requests(dwc, dep);
-
/* make sure HW endpoint isn't stalled */
if (dep->flags & DWC3_EP_STALL)
__dwc3_gadget_ep_set_halt(dep, 0, false);
@@ -803,6 +801,8 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->endpoint.desc = NULL;
}
 
+   dwc3_remove_requests(dwc, dep);
+
return 0;
 }
 
@@ -1617,7 +1617,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, 
struct dwc3_request *req)
 {
struct dwc3 *dwc = dep->dwc;
 
-   if (!dep->endpoint.desc || !dwc->pullups_connected) {
+   if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) {
dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
dep->name);
return -ESHUTDOWN;
@@ -2247,6 +2247,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
if (!is_on) {
u32 count;
 
+   dwc->connected = false;
/*
 * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
 * Section 4.1.8 Table 4-7, it states that for a 
device-initiated
@@ -3329,8 +3330,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 {
u32 reg;
 
-   dwc->connected = true;
-
/*
 * WORKAROUND: DWC3 revisions <1.88a have an issue which
 * would cause a missing Disconnect Event if there's a
@@ -3370,6 +3369,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 * transfers."
 */
dwc3_stop_active_transfers(dwc);
+   dwc->connected = true;
 
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg &= ~DWC3_DCTL_TSTCTRL_MASK;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] usb: dwc3: gadget: Prevent EP queuing while stopping transfers

2021-03-10 Thread Wesley Cheng
In the situations where the DWC3 gadget stops active transfers, once
calling the dwc3_gadget_giveback(), there is a chance where a function
driver can queue a new USB request in between the time where the dwc3
lock has been released and re-aquired.  This occurs after we've already
issued an ENDXFER command.  When the stop active transfers continues
to remove USB requests from all dep lists, the newly added request will
also be removed, while controller still has an active TRB for it.
This can lead to the controller accessing an unmapped memory address.

Fix this by ensuring parameters to prevent EP queuing are set before
calling the stop active transfers API.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/gadget.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 4780983..4d98fbf 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -783,8 +783,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
 
trace_dwc3_gadget_ep_disable(dep);
 
-   dwc3_remove_requests(dwc, dep);
-
/* make sure HW endpoint isn't stalled */
if (dep->flags & DWC3_EP_STALL)
__dwc3_gadget_ep_set_halt(dep, 0, false);
@@ -803,6 +801,8 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dep->endpoint.desc = NULL;
}
 
+   dwc3_remove_requests(dwc, dep);
+
return 0;
 }
 
@@ -1617,7 +1617,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, 
struct dwc3_request *req)
 {
struct dwc3 *dwc = dep->dwc;
 
-   if (!dep->endpoint.desc || !dwc->pullups_connected) {
+   if (!dep->endpoint.desc || !dwc->pullups_connected || !dwc->connected) {
dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
dep->name);
return -ESHUTDOWN;
@@ -2247,6 +2247,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
if (!is_on) {
u32 count;
 
+   dwc->connected = false;
/*
 * In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
 * Section 4.1.8 Table 4-7, it states that for a 
device-initiated
@@ -3329,8 +3330,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 {
u32 reg;
 
-   dwc->connected = true;
-
/*
 * WORKAROUND: DWC3 revisions <1.88a have an issue which
 * would cause a missing Disconnect Event if there's a
@@ -3370,6 +3369,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 * transfers."
 */
dwc3_stop_active_transfers(dwc);
+   dwc->connected = true;
 
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
reg &= ~DWC3_DCTL_TSTCTRL_MASK;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH v3 1/2] usb: dwc3: Trigger a GCTL soft reset when switching modes in DRD

2021-03-08 Thread Wesley Cheng



On 3/8/2021 7:05 PM, Thinh Nguyen wrote:
> Wesley Cheng wrote:
>>
>> On 3/6/2021 3:41 PM, Thinh Nguyen wrote:
>>> Wesley Cheng wrote:
>>>> On 1/8/2021 4:44 PM, Thinh Nguyen wrote:
>>>>> Hi,
>>>>>
>>>>> John Stultz wrote:
>>>>>> On Fri, Jan 8, 2021 at 4:26 AM Felipe Balbi  wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> John Stultz  writes:
>>>>>>>> From: Yu Chen 
>>>>>>>>
>>>>>>>> Just resending this, as discussion died out a bit and I'm not
>>>>>>>> sure how to make further progress. See here for debug data that
>>>>>>>> was requested last time around:
>>>>>>>>   
>>>>>>>> https://urldefense.com/v3/__https://lore.kernel.org/lkml/calaqxlxdnaufjkx0an9xwwtfwvjmwigppy2aqsnj56yvnbu...@mail.gmail.com/__;!!A4F2R9G_pg!LNzuprAeg-O80SgolYkIkW4-ne-M-yLWCDUY9MygAIrQC398Z6gRJ9wnsnlqd3w$
>>>>>>>>  
>>>>>>>>
>>>>>>>> With the current dwc3 code on the HiKey960 we often see the
>>>>>>>> COREIDLE flag get stuck off in __dwc3_gadget_start(), which
>>>>>>>> seems to prevent the reset irq and causes the USB gadget to
>>>>>>>> fail to initialize.
>>>>>>>>
>>>>>>>> We had seen occasional initialization failures with older
>>>>>>>> kernels but with recent 5.x era kernels it seemed to be becoming
>>>>>>>> much more common, so I dug back through some older trees and
>>>>>>>> realized I dropped this quirk from Yu Chen during upstreaming
>>>>>>>> as I couldn't provide a proper rational for it and it didn't
>>>>>>>> seem to be necessary. I now realize I was wrong.
>>>>>>>>
>>>>>>>> After resubmitting the quirk, Thinh Nguyen pointed out that it
>>>>>>>> shouldn't be a quirk at all and it is actually mentioned in the
>>>>>>>> programming guide that it should be done when switching modes
>>>>>>>> in DRD.
>>>>>>>>
>>>>>>>> So, to avoid these !COREIDLE lockups seen on HiKey960, this
>>>>>>>> patch issues GCTL soft reset when switching modes if the
>>>>>>>> controller is in DRD mode.
>>>>>>>>
>>>>>>>> Cc: Felipe Balbi 
>>>>>>>> Cc: Tejas Joglekar 
>>>>>>>> Cc: Yang Fei 
>>>>>>>> Cc: YongQin Liu 
>>>>>>>> Cc: Andrzej Pietrasiewicz 
>>>>>>>> Cc: Thinh Nguyen 
>>>>>>>> Cc: Jun Li 
>>>>>>>> Cc: Mauro Carvalho Chehab 
>>>>>>>> Cc: Greg Kroah-Hartman 
>>>>>>>> Cc: linux-...@vger.kernel.org
>>>>>>>> Signed-off-by: Yu Chen 
>>>>>>>> Signed-off-by: John Stultz 
>>>>>>>> ---
>>>>>>>> v2:
>>>>>>>> * Rework to always call the GCTL soft reset in DRD mode,
>>>>>>>>   rather then using a quirk as suggested by Thinh Nguyen
>>>>>>>>
>>>>>>>> v3:
>>>>>>>> * Move GCTL soft reset under the spinlock as suggested by
>>>>>>>>   Thinh Nguyen
>>>>>>> Because this is such an invasive change, I would prefer that we get
>>>>>>> Tested-By tags from a good fraction of the users before applying these
>>>>>>> two changes.
>>>>>> I'm happy to reach out to folks to try to get that. Though I'm
>>>>>> wondering if it would be better to put it behind a dts quirk flag, as
>>>>>> originally proposed?
>>>>>>
>>>>>> https://urldefense.com/v3/__https://lore.kernel.org/lkml/20201021181803.79650-1-john.stu...@linaro.org/__;!!A4F2R9G_pg!LNzuprAeg-O80SgolYkIkW4-ne-M-yLWCDUY9MygAIrQC398Z6gRJ9wnRWITZfc$
>>>>>>  
>>>>>>
>>>>>> That way folks can enable it for devices as they need?
>>>>>>
>>>>>> Again, I'm not trying to force this in as-is, just mostly sending it
>>>>>> out again for discussion to understand what other approach might work.
>>>>>>
>>>>>> thanks
>>>>>> -john
>>>>> A quirk would imply something is broken/diverged from the design right?
>>>>> But it's not the case here, and at least this is needed for HiKey960.
>>>>> Also, I think Rob will be ok with not adding 1 more quirk to the dwc3
>>>>> devicetree. :)
>>>>>
>>>>> BR,
>>>>> Thinh
>>>>>
>>>> Hi All,
>>>>
>>>> Sorry for jumping in, but I checked the SNPS v1.90a databook, and that
>>>> seemed to remove the requirement for the GCTL.softreset before writing
>>>> to PRTCAPDIR.  Should we consider adding a controller version/IP check?
>>>>
>>> Hi Wesley,
>>>
>>> From what I see in the v1.90a databook and others, the flow remains the
>>> same. I need to check internally, but I'm not aware of the change.
>>>
>> Hi Thinh,
>>
>> Hmmm, can you help check the register description for the PRTCAPDIR on
>> your v1.90a databook?  (Table 1-19 Fields for Register: GCTL (Continued)
>> Pg73)  When we compared the sequence in the description there to the
>> previous versions it removed the GCTL.softreset.  If it still shows up
>> on yours, then maybe my v1.90a isn't the final version?
>>
>> Thanks
>> Wesley Cheng
>>
> 
> Hi Wesley,
> 
> Actually your IP version type may use the newer flow. Can you print your
> DWC3_VER_TYPE? I still need to verify internally to know which versions
> need the update if any.
> 
> Thanks,
> Thinh
> 
Hi Thinh,

Sure, my DWC3_VER_TYPE output = 0x67612A2A

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v3 1/2] usb: dwc3: Trigger a GCTL soft reset when switching modes in DRD

2021-03-07 Thread Wesley Cheng



On 3/6/2021 3:41 PM, Thinh Nguyen wrote:
> Wesley Cheng wrote:
>>
>> On 1/8/2021 4:44 PM, Thinh Nguyen wrote:
>>> Hi,
>>>
>>> John Stultz wrote:
>>>> On Fri, Jan 8, 2021 at 4:26 AM Felipe Balbi  wrote:
>>>>> Hi,
>>>>>
>>>>> John Stultz  writes:
>>>>>> From: Yu Chen 
>>>>>>
>>>>>> Just resending this, as discussion died out a bit and I'm not
>>>>>> sure how to make further progress. See here for debug data that
>>>>>> was requested last time around:
>>>>>>   
>>>>>> https://urldefense.com/v3/__https://lore.kernel.org/lkml/calaqxlxdnaufjkx0an9xwwtfwvjmwigppy2aqsnj56yvnbu...@mail.gmail.com/__;!!A4F2R9G_pg!LNzuprAeg-O80SgolYkIkW4-ne-M-yLWCDUY9MygAIrQC398Z6gRJ9wnsnlqd3w$
>>>>>>  
>>>>>>
>>>>>> With the current dwc3 code on the HiKey960 we often see the
>>>>>> COREIDLE flag get stuck off in __dwc3_gadget_start(), which
>>>>>> seems to prevent the reset irq and causes the USB gadget to
>>>>>> fail to initialize.
>>>>>>
>>>>>> We had seen occasional initialization failures with older
>>>>>> kernels but with recent 5.x era kernels it seemed to be becoming
>>>>>> much more common, so I dug back through some older trees and
>>>>>> realized I dropped this quirk from Yu Chen during upstreaming
>>>>>> as I couldn't provide a proper rational for it and it didn't
>>>>>> seem to be necessary. I now realize I was wrong.
>>>>>>
>>>>>> After resubmitting the quirk, Thinh Nguyen pointed out that it
>>>>>> shouldn't be a quirk at all and it is actually mentioned in the
>>>>>> programming guide that it should be done when switching modes
>>>>>> in DRD.
>>>>>>
>>>>>> So, to avoid these !COREIDLE lockups seen on HiKey960, this
>>>>>> patch issues GCTL soft reset when switching modes if the
>>>>>> controller is in DRD mode.
>>>>>>
>>>>>> Cc: Felipe Balbi 
>>>>>> Cc: Tejas Joglekar 
>>>>>> Cc: Yang Fei 
>>>>>> Cc: YongQin Liu 
>>>>>> Cc: Andrzej Pietrasiewicz 
>>>>>> Cc: Thinh Nguyen 
>>>>>> Cc: Jun Li 
>>>>>> Cc: Mauro Carvalho Chehab 
>>>>>> Cc: Greg Kroah-Hartman 
>>>>>> Cc: linux-...@vger.kernel.org
>>>>>> Signed-off-by: Yu Chen 
>>>>>> Signed-off-by: John Stultz 
>>>>>> ---
>>>>>> v2:
>>>>>> * Rework to always call the GCTL soft reset in DRD mode,
>>>>>>   rather then using a quirk as suggested by Thinh Nguyen
>>>>>>
>>>>>> v3:
>>>>>> * Move GCTL soft reset under the spinlock as suggested by
>>>>>>   Thinh Nguyen
>>>>> Because this is such an invasive change, I would prefer that we get
>>>>> Tested-By tags from a good fraction of the users before applying these
>>>>> two changes.
>>>> I'm happy to reach out to folks to try to get that. Though I'm
>>>> wondering if it would be better to put it behind a dts quirk flag, as
>>>> originally proposed?
>>>>
>>>> https://urldefense.com/v3/__https://lore.kernel.org/lkml/20201021181803.79650-1-john.stu...@linaro.org/__;!!A4F2R9G_pg!LNzuprAeg-O80SgolYkIkW4-ne-M-yLWCDUY9MygAIrQC398Z6gRJ9wnRWITZfc$
>>>>  
>>>>
>>>> That way folks can enable it for devices as they need?
>>>>
>>>> Again, I'm not trying to force this in as-is, just mostly sending it
>>>> out again for discussion to understand what other approach might work.
>>>>
>>>> thanks
>>>> -john
>>> A quirk would imply something is broken/diverged from the design right?
>>> But it's not the case here, and at least this is needed for HiKey960.
>>> Also, I think Rob will be ok with not adding 1 more quirk to the dwc3
>>> devicetree. :)
>>>
>>> BR,
>>> Thinh
>>>
>> Hi All,
>>
>> Sorry for jumping in, but I checked the SNPS v1.90a databook, and that
>> seemed to remove the requirement for the GCTL.softreset before writing
>> to PRTCAPDIR.  Should we consider adding a controller version/IP check?
>>
> 
> Hi Wesley,
> 
> From what I see in the v1.90a databook and others, the flow remains the
> same. I need to check internally, but I'm not aware of the change.
> 
Hi Thinh,

Hmmm, can you help check the register description for the PRTCAPDIR on
your v1.90a databook?  (Table 1-19 Fields for Register: GCTL (Continued)
Pg73)  When we compared the sequence in the description there to the
previous versions it removed the GCTL.softreset.  If it still shows up
on yours, then maybe my v1.90a isn't the final version?

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v3 1/2] usb: dwc3: Trigger a GCTL soft reset when switching modes in DRD

2021-03-06 Thread Wesley Cheng



On 1/8/2021 4:44 PM, Thinh Nguyen wrote:
> Hi,
> 
> John Stultz wrote:
>> On Fri, Jan 8, 2021 at 4:26 AM Felipe Balbi  wrote:
>>>
>>> Hi,
>>>
>>> John Stultz  writes:
>>>> From: Yu Chen 
>>>>
>>>> Just resending this, as discussion died out a bit and I'm not
>>>> sure how to make further progress. See here for debug data that
>>>> was requested last time around:
>>>>   
>>>> https://urldefense.com/v3/__https://lore.kernel.org/lkml/calaqxlxdnaufjkx0an9xwwtfwvjmwigppy2aqsnj56yvnbu...@mail.gmail.com/__;!!A4F2R9G_pg!LNzuprAeg-O80SgolYkIkW4-ne-M-yLWCDUY9MygAIrQC398Z6gRJ9wnsnlqd3w$
>>>>  
>>>>
>>>> With the current dwc3 code on the HiKey960 we often see the
>>>> COREIDLE flag get stuck off in __dwc3_gadget_start(), which
>>>> seems to prevent the reset irq and causes the USB gadget to
>>>> fail to initialize.
>>>>
>>>> We had seen occasional initialization failures with older
>>>> kernels but with recent 5.x era kernels it seemed to be becoming
>>>> much more common, so I dug back through some older trees and
>>>> realized I dropped this quirk from Yu Chen during upstreaming
>>>> as I couldn't provide a proper rational for it and it didn't
>>>> seem to be necessary. I now realize I was wrong.
>>>>
>>>> After resubmitting the quirk, Thinh Nguyen pointed out that it
>>>> shouldn't be a quirk at all and it is actually mentioned in the
>>>> programming guide that it should be done when switching modes
>>>> in DRD.
>>>>
>>>> So, to avoid these !COREIDLE lockups seen on HiKey960, this
>>>> patch issues GCTL soft reset when switching modes if the
>>>> controller is in DRD mode.
>>>>
>>>> Cc: Felipe Balbi 
>>>> Cc: Tejas Joglekar 
>>>> Cc: Yang Fei 
>>>> Cc: YongQin Liu 
>>>> Cc: Andrzej Pietrasiewicz 
>>>> Cc: Thinh Nguyen 
>>>> Cc: Jun Li 
>>>> Cc: Mauro Carvalho Chehab 
>>>> Cc: Greg Kroah-Hartman 
>>>> Cc: linux-...@vger.kernel.org
>>>> Signed-off-by: Yu Chen 
>>>> Signed-off-by: John Stultz 
>>>> ---
>>>> v2:
>>>> * Rework to always call the GCTL soft reset in DRD mode,
>>>>   rather then using a quirk as suggested by Thinh Nguyen
>>>>
>>>> v3:
>>>> * Move GCTL soft reset under the spinlock as suggested by
>>>>   Thinh Nguyen
>>> Because this is such an invasive change, I would prefer that we get
>>> Tested-By tags from a good fraction of the users before applying these
>>> two changes.
>> I'm happy to reach out to folks to try to get that. Though I'm
>> wondering if it would be better to put it behind a dts quirk flag, as
>> originally proposed?
>>
>> https://urldefense.com/v3/__https://lore.kernel.org/lkml/20201021181803.79650-1-john.stu...@linaro.org/__;!!A4F2R9G_pg!LNzuprAeg-O80SgolYkIkW4-ne-M-yLWCDUY9MygAIrQC398Z6gRJ9wnRWITZfc$
>>  
>>
>> That way folks can enable it for devices as they need?
>>
>> Again, I'm not trying to force this in as-is, just mostly sending it
>> out again for discussion to understand what other approach might work.
>>
>> thanks
>> -john
> 
> A quirk would imply something is broken/diverged from the design right?
> But it's not the case here, and at least this is needed for HiKey960.
> Also, I think Rob will be ok with not adding 1 more quirk to the dwc3
> devicetree. :)
> 
> BR,
> Thinh
> 

Hi All,

Sorry for jumping in, but I checked the SNPS v1.90a databook, and that
seemed to remove the requirement for the GCTL.softreset before writing
to PRTCAPDIR.  Should we consider adding a controller version/IP check?

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v3 2/2] usb: dwc3: Fix DRD mode change sequence following programming guide

2021-03-06 Thread Wesley Cheng



On 1/7/2021 5:51 PM, John Stultz wrote:
> In reviewing the previous patch, Thinh Nguyen pointed out that
> the DRD mode change sequence should be like the following when
> switching from host -> device according to the programming guide
> (for all DRD IPs):
> 1. Reset controller with GCTL.CoreSoftReset
> 2. Set GCTL.PrtCapDir(device)
> 3. Soft reset with DCTL.CSftRst
> 4. Then follow up with the initializing registers sequence
> 
> The current code does:
> a. Soft reset with DCTL.CSftRst on driver probe
> b. Reset controller with GCTL.CoreSoftReset (added in previous
>patch)
> c. Set GCTL.PrtCapDir(device)
> d. < missing DCTL.CSftRst >
> e. Then follow up with initializing registers sequence
> 
> So this patch adds the DCTL.CSftRst soft reset that was currently
> missing from the dwc3 mode switching.
> 
> Cc: Felipe Balbi 
> Cc: Tejas Joglekar 
> Cc: Yang Fei 
> Cc: YongQin Liu 
> Cc: Andrzej Pietrasiewicz 
> Cc: Thinh Nguyen 
> Cc: Jun Li 
> Cc: Mauro Carvalho Chehab 
> Cc: Greg Kroah-Hartman 
> Cc: linux-...@vger.kernel.org
> Signed-off-by: John Stultz 
> ---
> Feedback would be appreciated. I'm a little worried I should be
> conditionalizing the DCTL.CSftRst on DRD mode controllers, but
> I'm really not sure what the right thing to do is for non-DRD
> mode controllers.
> ---
>  drivers/usb/dwc3/core.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index b6a6b90eb2d5..71f8b07ecb99 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -40,6 +40,8 @@
>  
>  #define DWC3_DEFAULT_AUTOSUSPEND_DELAY   5000 /* ms */
>  
> +static int dwc3_core_soft_reset(struct dwc3 *dwc);
> +
>  /**
>   * dwc3_get_dr_mode - Validates and sets dr_mode
>   * @dwc: pointer to our context structure
> @@ -177,6 +179,7 @@ static void __dwc3_set_mode(struct work_struct *work)
>  
>   dwc3_set_prtcap(dwc, dwc->desired_dr_role);
>  
> + dwc3_core_soft_reset(dwc);

Hi John/Thinh/Felipe,

I actually added this change into my local branch, because we were
seeing an issue when switching from host mode --> peripheral mode.  What
was happening was that the RXFIFO register did not update back to the
expected value for peripheral mode by the time
dwc3_gadget_init_out_endpoint() was executed.  With the logic to
calculate the EP max packet limit based on RXFIFO reg, this caused all
EPs to be set with an EP max limit of 0.

With this change, it seemed to help with the above issue.  However, can
we consider moving the core soft reset outside the spinlock?  At least
with our PHY init routines, we have some msleep() calls for waiting for
the PHYs to be ready, which will end up as a sleeping while atomic bug.
(not sure if PHY init is required to be called in atomic context)

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v7 4/5] usb: dwc3: dwc3-qcom: Enable tx-fifo-resize property by default

2021-02-17 Thread Wesley Cheng



On 2/2/2021 8:23 AM, Bjorn Andersson wrote:
> On Thu 28 Jan 22:46 CST 2021, Wesley Cheng wrote:
> 
>> In order to take advantage of the TX fifo resizing logic, manually add
>> these properties to the DWC3 child node by default.  This will allow
>> the DWC3 gadget to resize the TX fifos for the IN endpoints, which
>> help with performance.
>>
>> Signed-off-by: Wesley Cheng 
>> ---
>>  drivers/usb/dwc3/dwc3-qcom.c | 10 ++
>>  1 file changed, 10 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
>> index d803ee9..4ea6be3 100644
>> --- a/drivers/usb/dwc3/dwc3-qcom.c
>> +++ b/drivers/usb/dwc3/dwc3-qcom.c
>> @@ -564,6 +564,7 @@ static int dwc3_qcom_clk_init(struct dwc3_qcom *qcom, 
>> int count)
>>  
>>  static const struct property_entry dwc3_qcom_acpi_properties[] = {
>>  PROPERTY_ENTRY_STRING("dr_mode", "host"),
>> +PROPERTY_ENTRY_BOOL("tx-fifo-resize"),
> 
> I checked the ACPI tables for Lenovo Miix 630, Yoga C630 and Flex 5G and
> neither one has this property specified. So while we could just add this
> here, it would have to be done in collaboration with the people who
> actually define these. And as said before, I believe we want this to
> always be enabled.
> 
>>  {}
>>  };
>>  
>> @@ -634,6 +635,7 @@ static int dwc3_qcom_of_register_core(struct 
>> platform_device *pdev)
>>  struct dwc3_qcom*qcom = platform_get_drvdata(pdev);
>>  struct device_node  *np = pdev->dev.of_node, *dwc3_np;
>>  struct device   *dev = >dev;
>> +struct property *prop;
>>  int ret;
>>  
>>  dwc3_np = of_get_child_by_name(np, "dwc3");
>> @@ -642,6 +644,14 @@ static int dwc3_qcom_of_register_core(struct 
>> platform_device *pdev)
>>  return -ENODEV;
>>  }
>>  
>> +prop = kzalloc(sizeof(*prop), GFP_KERNEL);
>> +if (prop) {
>> +prop->name = "tx-fifo-resize";
>> +ret = of_add_property(dwc3_np, prop);
> 
> Can't we come up with a way where the platform driver enables this on
> the core driver without modifying DT?
> 
> Regards,
> Bjorn

Hi Bjorn,

Sorry for the late response.  As you know, its a little difficult to
access the DWC3 core device during DWC3 qcom probe time, as the DWC3
core will likely return deferred probe due to the PHY devices not being
ready.

This is why I went with the approach to modify the DWC3 node here, so
that when the DWC3 core is eventually probed, it wouldn't miss this
property setting.  If I tried to set this dynamically, say in
dwc3_qcom_vbus_override() (with proper NULL checks), then I'd miss this
setting for the first enumeration, but if cable plug out/in logic is
present, the setting would kick in on subsequent cable events.

Thanks
Wesley Cheng

> 
>> +if (ret < 0)
>> +dev_info(dev, "unable to add tx-fifo-resize prop\n");
>> +}
>> +
>>  ret = of_platform_populate(np, NULL, NULL, dev);
>>  if (ret) {
>>  dev_err(dev, "failed to register dwc3 core - %d\n", ret);
>> -- 
>> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
>> a Linux Foundation Collaborative Project
>>

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: usb: dwc3: gadget: Change runtime pm function for DWC3 runtime suspend

2021-02-16 Thread Wesley Cheng



On 2/15/2021 5:30 PM, Jung Daehwan wrote:
> Hello, Alan
> 
> On Mon, Feb 15, 2021 at 12:41:45PM -0500, Alan Stern wrote:
>> On Mon, Feb 15, 2021 at 11:38:58AM +0900, Daehwan Jung wrote:
>>> It seems pm_runtime_put calls runtime_idle callback not runtime_suspend 
>>> callback.
>>
>> How is this fact related to your patch?
> 
> I think we should cause dwc3_runtime_suspend at the time.
> That's why I use pm_runtime_put_sync_suspend.
> 
>>
>>> It's better to use pm_runtime_put_sync_suspend to allow DWC3 runtime 
>>> suspend.
>>
>> Why do you think it is better?  The advantage of pm_runtime_put is that 
>> it allows the suspend to occur at a later time in a workqueue thread, so 
>> the caller doesn't have to wait for the device to go into suspend.
>>
> 
> We can assume DWC3 was already in suspend state if pm_runtime_get_sync
> returns 0. DWC3 resumes due to pm_rumtime_get_sync but it doesn't
> re-enter runtime_suspend but runtime_idle. pm_runtime_put decreases
> usage_count but doesn't cause runtime_suspend.
> 
> 1. USB disconnected
> 2. UDC unbinded
> 3. DWC3 runtime suspend
> 4. UDC binded unexpectedly
> 5. DWC3 runtime resume (pm_runtime_get_sync)
> 6. DWC3 runtime idle (pm_runtime_put)
>-> DWC3 runtime suspend again (pm_runtime_put_sync_suspend)
> 
> I've talked with Wesley in other patch.
> 
> usbb: dwc3: gadget: skip pullup and set_speed after suspend
> patchwork.kernel.org/project/linux-usb/patch/163968-102424-1-git-send-email-dh10.j...@samsung.com
> 
> @ Wesley
> 
> I think We should guarantee DWC3 enters suspend again at the time.
> How do you think?
> 
Hi Daehwan,

Even if we call runtime idle versus suspend, if the device is still in
the disconnected state, it should call the runtime PM suspend routine
after the autosuspend timer expires.  As Alan mentioned already, this
allows not blocking the caller for the entire DWC3 suspend sequence to
execute. (DWC3 core will suspend other components as well, such as PHYs)

Also, for legitimate cases where pullup is actually called to start
enumeration from a suspended state, I'm not sure if the short duration
between RS set and re-suspend (due to your patch) is enough time for the
host to actually detect the device connected.

Thanks
Wesley Cheng

> Best Regards,
> Jung Daehwan
> 
>> Alan Stern
>>
> 
> 
>>> Signed-off-by: Daehwan Jung 
>>> ---
>>>  drivers/usb/dwc3/gadget.c | 2 +-
>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>> index aebcf8e..4a4b93b 100644
>>> --- a/drivers/usb/dwc3/gadget.c
>>> +++ b/drivers/usb/dwc3/gadget.c
>>> @@ -2229,7 +2229,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, 
>>> int is_on)
>>>  */
>>> ret = pm_runtime_get_sync(dwc->dev);
>>> if (!ret || ret < 0) {
>>> -   pm_runtime_put(dwc->dev);
>>> +   pm_runtime_put_sync_suspend(dwc->dev);
>>> return 0;
>>> }
>>>  
>>> -- 
>>> 2.7.4
>>>
>>
>>

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v7 4/5] usb: dwc3: dwc3-qcom: Enable tx-fifo-resize property by default

2021-01-29 Thread Wesley Cheng



On 1/29/2021 1:24 AM, Jack Pham wrote:
> Hi Wesley,
> 
> On Thu, Jan 28, 2021 at 08:46:43PM -0800, Wesley Cheng wrote:
>> In order to take advantage of the TX fifo resizing logic, manually add
>> these properties to the DWC3 child node by default.  This will allow
>> the DWC3 gadget to resize the TX fifos for the IN endpoints, which
>> help with performance.
>>
>> Signed-off-by: Wesley Cheng 
>> ---
>>  drivers/usb/dwc3/dwc3-qcom.c | 10 ++
>>  1 file changed, 10 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
>> index d803ee9..4ea6be3 100644
>> --- a/drivers/usb/dwc3/dwc3-qcom.c
>> +++ b/drivers/usb/dwc3/dwc3-qcom.c
>> @@ -564,6 +564,7 @@ static int dwc3_qcom_clk_init(struct dwc3_qcom *qcom, 
>> int count)
>>  
>>  static const struct property_entry dwc3_qcom_acpi_properties[] = {
>>  PROPERTY_ENTRY_STRING("dr_mode", "host"),
>> +PROPERTY_ENTRY_BOOL("tx-fifo-resize"),
>>  {}
>>  };
>>  
>> @@ -634,6 +635,7 @@ static int dwc3_qcom_of_register_core(struct 
>> platform_device *pdev)
>>  struct dwc3_qcom*qcom = platform_get_drvdata(pdev);
>>  struct device_node  *np = pdev->dev.of_node, *dwc3_np;
>>  struct device   *dev = >dev;
>> +struct property *prop;
>>  int ret;
>>  
>>  dwc3_np = of_get_child_by_name(np, "dwc3");
>> @@ -642,6 +644,14 @@ static int dwc3_qcom_of_register_core(struct 
>> platform_device *pdev)
>>  return -ENODEV;
>>  }
>>  
>> +prop = kzalloc(sizeof(*prop), GFP_KERNEL);
>> +if (prop) {
>> +prop->name = "tx-fifo-resize";
>> +ret = of_add_property(dwc3_np, prop);
>> +if (ret < 0)
>> +dev_info(dev, "unable to add tx-fifo-resize prop\n");
> 
> You'll need to kfree(prop) both in case of error here as well as in the
> driver's .remove() callback. Maybe easier to devm_kzalloc()?

Hi Jack,

Thanks for the catch, will fix this with the devm variant.

Hi Bjorn,

Just wanted to see what you thought about this approach?  This way we
can just keep the dt binding w/o having to re-add it in the future, as
well as not needing to enable this property on every qcom platform with
dwc3.

Tested on my set up, and removed the change which added the property
from the DTSI node.

Thanks
Wesley Cheng

> 
> Jack
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH v7 5/5] dt-bindings: usb: dwc3: Update dwc3 TX fifo properties

2021-01-28 Thread Wesley Cheng
Update the tx-fifo-resize property with a better description, while
adding the tx-fifo-max-num, which is a new parameter allowing
adjustments for the maximum number of packets the txfifo resizing logic
can account for while resizing the endpoints.

Signed-off-by: Wesley Cheng 
---
 Documentation/devicetree/bindings/usb/snps,dwc3.yaml | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml 
b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
index 2247da7..652b246 100644
--- a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
@@ -283,10 +283,21 @@ properties:
 maximum: 16
 
   tx-fifo-resize:
-description: Determines if the FIFO *has* to be reallocated
-deprecated: true
+description: Determines if the TX fifos can be dynamically resized 
depending
+  on the number of IN endpoints used and if bursting is supported.  This
+  may help improve bandwidth on platforms with higher system latencies, as
+  increased fifo space allows for the controller to prefetch data into its
+  internal memory.
 type: boolean
 
+  tx-fifo-max-num:
+description: Specifies the max number of packets the txfifo resizing logic
+  can account for when higher endpoint bursting is used. (bMaxBurst > 6) 
The
+  higher the number, the more fifo space the txfifo resizing logic will
+  allocate for that endpoint.
+$ref: /schemas/types.yaml#/definitions/uint8
+minimum: 3
+
   snps,incr-burst-type-adjustment:
 description:
   Value for INCR burst type of GSBUSCFG0 register, undefined length INCR
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v7 2/5] usb: gadget: configfs: Check USB configuration before adding

2021-01-28 Thread Wesley Cheng
Ensure that the USB gadget is able to support the configuration being
added based on the number of endpoints required from all interfaces.  This
is for accounting for any bandwidth or space limitations.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/gadget/configfs.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 0d56f33..e6de3ca5 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1368,6 +1368,7 @@ static int configfs_composite_bind(struct usb_gadget 
*gadget,
struct usb_function *f;
struct usb_function *tmp;
struct gadget_config_name *cn;
+   unsigned long ep_map = 0;
 
if (gadget_is_otg(gadget))
c->descriptors = otg_desc;
@@ -1397,7 +1398,28 @@ static int configfs_composite_bind(struct usb_gadget 
*gadget,
list_add(>list, >func_list);
goto err_purge_funcs;
}
+   if (f->fs_descriptors) {
+   struct usb_descriptor_header **d;
+
+   d = f->fs_descriptors;
+   for (; *d; ++d) {
+   struct usb_endpoint_descriptor *ep;
+   int addr;
+
+   if ((*d)->bDescriptorType != 
USB_DT_ENDPOINT)
+   continue;
+
+   ep = (struct usb_endpoint_descriptor 
*)*d;
+   addr = ((ep->bEndpointAddress & 0x80) 
>> 3) |
+   (ep->bEndpointAddress & 0x0f);
+   set_bit(addr, _map);
+   }
+   }
}
+   ret = usb_gadget_check_config(cdev->gadget, ep_map);
+   if (ret)
+   goto err_purge_funcs;
+
usb_ep_autoconfig_reset(cdev->gadget);
}
if (cdev->use_os_string) {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v7 4/5] usb: dwc3: dwc3-qcom: Enable tx-fifo-resize property by default

2021-01-28 Thread Wesley Cheng
In order to take advantage of the TX fifo resizing logic, manually add
these properties to the DWC3 child node by default.  This will allow
the DWC3 gadget to resize the TX fifos for the IN endpoints, which
help with performance.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/dwc3-qcom.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index d803ee9..4ea6be3 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -564,6 +564,7 @@ static int dwc3_qcom_clk_init(struct dwc3_qcom *qcom, int 
count)
 
 static const struct property_entry dwc3_qcom_acpi_properties[] = {
PROPERTY_ENTRY_STRING("dr_mode", "host"),
+   PROPERTY_ENTRY_BOOL("tx-fifo-resize"),
{}
 };
 
@@ -634,6 +635,7 @@ static int dwc3_qcom_of_register_core(struct 
platform_device *pdev)
struct dwc3_qcom*qcom = platform_get_drvdata(pdev);
struct device_node  *np = pdev->dev.of_node, *dwc3_np;
struct device   *dev = >dev;
+   struct property *prop;
int ret;
 
dwc3_np = of_get_child_by_name(np, "dwc3");
@@ -642,6 +644,14 @@ static int dwc3_qcom_of_register_core(struct 
platform_device *pdev)
return -ENODEV;
}
 
+   prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+   if (prop) {
+   prop->name = "tx-fifo-resize";
+   ret = of_add_property(dwc3_np, prop);
+   if (ret < 0)
+   dev_info(dev, "unable to add tx-fifo-resize prop\n");
+   }
+
ret = of_platform_populate(np, NULL, NULL, dev);
if (ret) {
dev_err(dev, "failed to register dwc3 core - %d\n", ret);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v7 3/5] usb: dwc3: Resize TX FIFOs to meet EP bursting requirements

2021-01-28 Thread Wesley Cheng
Some devices have USB compositions which may require multiple endpoints
that support EP bursting.  HW defined TX FIFO sizes may not always be
sufficient for these compositions.  By utilizing flexible TX FIFO
allocation, this allows for endpoints to request the required FIFO depth to
achieve higher bandwidth.  With some higher bMaxBurst configurations, using
a larger TX FIFO size results in better TX throughput.

By introducing the check_config() callback, the resizing logic can fetch
the maximum number of endpoints used in the USB composition (can contain
multiple configurations), which helps ensure that the resizing logic can
fulfill the configuration(s), or return an error to the gadget layer
otherwise during bind time.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/core.c   |   9 ++
 drivers/usb/dwc3/core.h   |  15 
 drivers/usb/dwc3/ep0.c|   2 +
 drivers/usb/dwc3/gadget.c | 214 ++
 4 files changed, 240 insertions(+)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 6969196..4f78370 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1238,6 +1238,7 @@ static void dwc3_get_properties(struct dwc3 *dwc)
u8  rx_max_burst_prd;
u8  tx_thr_num_pkt_prd;
u8  tx_max_burst_prd;
+   u8  tx_fifo_resize_max_num;
 
/* default to highest possible threshold */
lpm_nyet_threshold = 0xf;
@@ -1251,6 +1252,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
 */
hird_threshold = 12;
 
+   tx_fifo_resize_max_num = 6;
+
dwc->maximum_speed = usb_get_maximum_speed(dev);
dwc->dr_mode = usb_get_dr_mode(dev);
dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node);
@@ -1284,6 +1287,10 @@ static void dwc3_get_properties(struct dwc3 *dwc)
_thr_num_pkt_prd);
device_property_read_u8(dev, "snps,tx-max-burst-prd",
_max_burst_prd);
+   dwc->do_fifo_resize = device_property_read_bool(dev,
+   "tx-fifo-resize");
+   device_property_read_u8(dev, "tx-fifo-max-num",
+   _fifo_resize_max_num);
 
dwc->disable_scramble_quirk = device_property_read_bool(dev,
"snps,disable_scramble_quirk");
@@ -1349,6 +1356,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
dwc->tx_max_burst_prd = tx_max_burst_prd;
 
dwc->imod_interval = 0;
+
+   dwc->tx_fifo_resize_max_num = tx_fifo_resize_max_num;
 }
 
 /* check whether the core supports IMOD */
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index eec1cf4..411b904 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1007,6 +1007,7 @@ struct dwc3_scratchpad_array {
  * @rx_max_burst_prd: max periodic ESS receive burst size
  * @tx_thr_num_pkt_prd: periodic ESS transmit packet count
  * @tx_max_burst_prd: max periodic ESS transmit burst size
+ * @tx_fifo_resize_max_num: max number of fifos allocated during txfifo resize
  * @hsphy_interface: "utmi" or "ulpi"
  * @connected: true when we're connected to a host, false otherwise
  * @delayed_status: true when gadget driver asks for delayed status
@@ -1062,6 +1063,11 @@ struct dwc3_scratchpad_array {
  * @dis_split_quirk: set to disable split boundary.
  * @imod_interval: set the interrupt moderation interval in 250ns
  * increments or 0 to disable.
+ * @max_cfg_eps: current max number of IN eps used across all USB configs.
+ * @last_fifo_depth: last fifo depth used to determine next fifo ram start
+ *  address.
+ * @num_ep_resized: carries the current number endpoints which have had its tx
+ * fifo resized.
  */
 struct dwc3 {
struct work_struct  drd_work;
@@ -1210,6 +1216,7 @@ struct dwc3 {
u8  rx_max_burst_prd;
u8  tx_thr_num_pkt_prd;
u8  tx_max_burst_prd;
+   u8  tx_fifo_resize_max_num;
 
const char  *hsphy_interface;
 
@@ -1223,6 +1230,7 @@ struct dwc3 {
unsignedis_utmi_l1_suspend:1;
unsignedis_fpga:1;
unsignedpending_events:1;
+   unsigneddo_fifo_resize:1;
unsignedpullups_connected:1;
unsignedsetup_packet_pending:1;
unsignedthree_stage_setup:1;
@@ -1257,6 +1265,10 @@ struct dwc3 {
unsigneddis_split_quirk:1;
 
u16 imod_interval;
+
+   int max_cfg_eps;
+   int last_fifo_depth;
+   int num_ep_resiz

[PATCH v7 1/5] usb: gadget: udc: core: Introduce check_config to verify USB configuration

2021-01-28 Thread Wesley Cheng
Some UDCs may have constraints on how many high bandwidth endpoints it can
support in a certain configuration.  This API allows for the composite
driver to pass down the total number of endpoints to the UDC so it can verify
it has the required resources to support the configuration.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/gadget/udc/core.c | 25 +
 include/linux/usb/gadget.h|  5 +
 2 files changed, 30 insertions(+)

diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 4173acd..81252e5 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -1003,6 +1003,31 @@ int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
 }
 EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc);
 
+/**
+ * usb_gadget_check_config - checks if the UDC can support the number of eps
+ * @gadget: controller to check the USB configuration
+ * @ep_map: bitmap of endpoints being requested by a USB configuration
+ *
+ * Ensure that a UDC is able to support the number of endpoints within a USB
+ * configuration, and that there are no resource limitations to support all
+ * requested eps.
+ *
+ * Returns zero on success, else a negative errno.
+ */
+int usb_gadget_check_config(struct usb_gadget *gadget, unsigned long ep_map)
+{
+   int ret = 0;
+
+   if (!gadget->ops->check_config)
+   goto out;
+
+   ret = gadget->ops->check_config(gadget, ep_map);
+
+out:
+   return ret;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_check_config);
+
 /* - */
 
 static void usb_gadget_state_work(struct work_struct *work)
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index ee04ef2..9fb69eb 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -328,6 +328,7 @@ struct usb_gadget_ops {
struct usb_ep *(*match_ep)(struct usb_gadget *,
struct usb_endpoint_descriptor *,
struct usb_ss_ep_comp_descriptor *);
+   int (*check_config)(struct usb_gadget *gadget, unsigned long 
ep_map);
 };
 
 /**
@@ -607,6 +608,7 @@ int usb_gadget_connect(struct usb_gadget *gadget);
 int usb_gadget_disconnect(struct usb_gadget *gadget);
 int usb_gadget_deactivate(struct usb_gadget *gadget);
 int usb_gadget_activate(struct usb_gadget *gadget);
+int usb_gadget_check_config(struct usb_gadget *gadget, unsigned long ep_map);
 #else
 static inline int usb_gadget_frame_number(struct usb_gadget *gadget)
 { return 0; }
@@ -630,6 +632,9 @@ static inline int usb_gadget_deactivate(struct usb_gadget 
*gadget)
 { return 0; }
 static inline int usb_gadget_activate(struct usb_gadget *gadget)
 { return 0; }
+static inline int usb_gadget_check_config(struct usb_gadget *gadget,
+ unsigned long ep_map)
+{ return 0; }
 #endif /* CONFIG_USB_GADGET */
 
 /*-*/
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v7 0/5] Re-introduce TX FIFO resize for larger EP bursting

2021-01-28 Thread Wesley Cheng
Changes in V7:
 - Added a new property tx-fifo-max-num for limiting how much fifo space the
   resizing logic can allocate for endpoints with large burst values.  This
   can differ across platforms, and tie in closely with overall system latency.
 - Added recommended checks for DWC32.
 - Added changes to set the tx-fifo-resize property from dwc3-qcom by default
   instead of modifying the current DTSI files.
 - Added comments on all APIs/variables introduced.
 - Updated the DWC3 YAML to include a better description of the tx-fifo-resize
   property and added an entry for tx-fifo-max-num.

Changes in V6:
 - Rebased patches to usb-testing.
 - Renamed to PATCH series instead of RFC.
 - Checking for fs_descriptors instead of ss_descriptors for determining the
   endpoint count for a particular configuration.
 - Re-ordered patch series to fix patch dependencies.

Changes in V5:
 - Added check_config() logic, which is used to communicate the number of EPs
   used in a particular configuration.  Based on this, the DWC3 gadget driver
   has the ability to know the maximum number of eps utilized in all configs.
   This helps reduce unnecessary allocation to unused eps, and will catch fifo
   allocation issues at bind() time.
 - Fixed variable declaration to single line per variable, and reverse xmas.
 - Created a helper for fifo clearing, which is used by ep0.c

Changes in V4:
 - Removed struct dwc3* as an argument for dwc3_gadget_resize_tx_fifos()
 - Removed WARN_ON(1) in case we run out of fifo space
 
Changes in V3:
 - Removed "Reviewed-by" tags
 - Renamed series back to RFC
 - Modified logic to ensure that fifo_size is reset if we pass the minimum
   threshold.  Tested with binding multiple FDs requesting 6 FIFOs.

Changes in V2:
 - Modified TXFIFO resizing logic to ensure that each EP is reserved a
   FIFO.
 - Removed dev_dbg() prints and fixed typos from patches
 - Added some more description on the dt-bindings commit message

Currently, there is no functionality to allow for resizing the TXFIFOs, and
relying on the HW default setting for the TXFIFO depth.  In most cases, the
HW default is probably sufficient, but for USB compositions that contain
multiple functions that require EP bursting, the default settings
might not be enough.  Also to note, the current SW will assign an EP to a
function driver w/o checking to see if the TXFIFO size for that particular
EP is large enough. (this is a problem if there are multiple HW defined
values for the TXFIFO size)

It is mentioned in the SNPS databook that a minimum of TX FIFO depth = 3
is required for an EP that supports bursting.  Otherwise, there may be
frequent occurences of bursts ending.  For high bandwidth functions,
such as data tethering (protocols that support data aggregation), mass
storage, and media transfer protocol (over FFS), the bMaxBurst value can be
large, and a bigger TXFIFO depth may prove to be beneficial in terms of USB
throughput. (which can be associated to system access latency, etc...)  It
allows for a more consistent burst of traffic, w/o any interruptions, as
data is readily available in the FIFO.

With testing done using the mass storage function driver, the results show
that with a larger TXFIFO depth, the bandwidth increased significantly.

Test Parameters:
 - Platform: Qualcomm SM8150
 - bMaxBurst = 6
 - USB req size = 256kB
 - Num of USB reqs = 16
 - USB Speed = Super-Speed
 - Function Driver: Mass Storage (w/ ramdisk)
 - Test Application: CrystalDiskMark

Results:

TXFIFO Depth = 3 max packets

Test Case | Data Size | AVG tput (in MB/s)
---
Sequential|1 GB x | 
Read  |9 loops| 193.60
  |   | 195.86
  |   | 184.77
  |   | 193.60
---

TXFIFO Depth = 6 max packets

Test Case | Data Size | AVG tput (in MB/s)
---
Sequential|1 GB x | 
Read  |9 loops| 287.35
  |   | 304.94
  |   | 289.64
  |   | 293.61
-------

Wesley Cheng (5):
  usb: gadget: udc: core: Introduce check_config to verify USB
configuration
  usb: gadget: configfs: Check USB configuration before adding
  usb: dwc3: Resize TX FIFOs to meet EP bursting requirements
  usb: dwc3: dwc3-qcom: Enable tx-fifo-resize property by default
  dt-bindings: usb: dwc3: Update dwc3 TX fifo properties

 .../devicetree/bindings/usb/snps,dwc3.yaml |  15 +-
 drivers/usb/dwc3/core.c|   9 +
 drivers/usb/dwc3/core.h|  15 ++
 drivers/usb/dwc3/dwc3-qcom.c   |  10 +
 drivers/usb/dwc3/ep0.c |   2 +
 drivers/usb/dwc3/gadget.c  | 214 +
 drivers/usb/gadget/configfs.c  |  22 +++
 drivers/usb/gadget/udc/core.c  |  25 +++
 include

Re: [PATCH v6 3/4] usb: dwc3: Resize TX FIFOs to meet EP bursting requirements

2021-01-28 Thread Wesley Cheng



On 1/25/2021 9:15 PM, Bjorn Andersson wrote:
> On Mon 25 Jan 22:32 CST 2021, Wesley Cheng wrote:
>> On 1/25/2021 5:55 PM, Bjorn Andersson wrote:
>>> On Mon 25 Jan 19:14 CST 2021, Wesley Cheng wrote:
>>>
>>>>
>>>>
>>>> On 1/22/2021 9:12 AM, Bjorn Andersson wrote:
>>>>> On Thu 21 Jan 22:01 CST 2021, Wesley Cheng wrote:
>>>>>
>>>>
>>>> Hi Bjorn,
>>>>>
>>>>> Under what circumstances should we specify this? And in particular are
>>>>> there scenarios (in the Qualcomm platforms) where this must not be set?
>>>>> The TXFIFO dynamic allocation is actually a feature within the DWC3
>>>> controller, and isn't specifically for QCOM based platforms.  It won't
>>>> do any harm functionally if this flag is not set, as this is meant for
>>>> enhancing performance/bandwidth.
>>>>
>>>>> In particular, the composition can be changed in runtime, so should we
>>>>> set this for all Qualcomm platforms?
>>>>>
>>>> Ideally yes, if we want to increase bandwith for situations where SS
>>>> endpoint bursting is set to a higher value.
>>>>
>>>>> And if that's the case, can we not just set it from the qcom driver?
>>>>>
>>>> Since this is a common DWC3 core feature, I think it would make more
>>>> sense to have it in DWC3 core instead of a vendor's DWC3 glue driver.
>>>>
>>>
>>> I don't have any objections to implementing it in the core driver, but
>>> my question is can we just skip the DT binding and just enable it from
>>> the vendor driver?
>>>
>>> Regards,
>>> Bjorn
>>>
>>
>> Hi Bjorn,
>>
>> I see.  I think there are some designs which don't have a DWC3 glue
>> driver, so assuming there may be other platforms using this, there may
>> not always be a vendor driver to set this.
>>
> 
> You mean that there are implementations of dwc3 without an associated
> glue driver that haven't yet realized that they need this feature?
> 
> I would suggest then that we implement the core code necessary, we
> enable it from the Qualcomm glue layer and when someone realize that
> they need this without a glue driver it's going to be trivial to add the
> DT binding.
>>
> The alternative is that we're lugging around a requirement to specify
> this property in all past, present and future Qualcomm dts files - and
> then we'll need to hard code it for ACPI anyways.
> 
Hi Bjorn,

Can we utilize the of_add_property() call to add the "tx-fifo-resize"
property from the dwc3_qcom_register_core() API?  That way at least the
above concern would be addressed.

I'm not too familiar with the ACPI design, but I do see that the
dwc3-qcom does have an array carrying some DWC3 core properties.  Looks
like we can add the tx-fifo-resize property here too.

static const struct property_entry dwc3_qcom_acpi_properties[] = {
PROPERTY_ENTRY_STRING("dr_mode", "host"),
{}
};


Thanks
Wesley Cheng

> Regards,
> Bjorn
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v6 3/4] usb: dwc3: Resize TX FIFOs to meet EP bursting requirements

2021-01-26 Thread Wesley Cheng



On 1/26/2021 12:43 PM, Thinh Nguyen wrote:
> Wesley Cheng wrote:
>>
>> On 1/22/2021 4:15 PM, Thinh Nguyen wrote:
>>> Hi,
>>>
>>> Wesley Cheng wrote:
>>>> Some devices have USB compositions which may require multiple endpoints
>>>> that support EP bursting.  HW defined TX FIFO sizes may not always be
>>>> sufficient for these compositions.  By utilizing flexible TX FIFO
>>>> allocation, this allows for endpoints to request the required FIFO depth to
>>>> achieve higher bandwidth.  With some higher bMaxBurst configurations, using
>>>> a larger TX FIFO size results in better TX throughput.
>>>>
>>>> By introducing the check_config() callback, the resizing logic can fetch
>>>> the maximum number of endpoints used in the USB composition (can contain
>>>> multiple configurations), which helps ensure that the resizing logic can
>>>> fulfill the configuration(s), or return an error to the gadget layer
>>>> otherwise during bind time.
>>>>
>>>> Signed-off-by: Wesley Cheng 
>>>> ---
>>>>  drivers/usb/dwc3/core.c   |   2 +
>>>>  drivers/usb/dwc3/core.h   |   8 ++
>>>>  drivers/usb/dwc3/ep0.c|   2 +
>>>>  drivers/usb/dwc3/gadget.c | 194 
>>>> ++
>>>>  4 files changed, 206 insertions(+)
>>>>
>>>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>>>> index 6969196..e7fa6af 100644
>>>> --- a/drivers/usb/dwc3/core.c
>>>> +++ b/drivers/usb/dwc3/core.c
>>>> @@ -1284,6 +1284,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
>>>>_thr_num_pkt_prd);
>>>>device_property_read_u8(dev, "snps,tx-max-burst-prd",
>>>>_max_burst_prd);
>>>> +  dwc->needs_fifo_resize = device_property_read_bool(dev,
>>>> + "tx-fifo-resize");
>>>>  
>>>>dwc->disable_scramble_quirk = device_property_read_bool(dev,
>>>>"snps,disable_scramble_quirk");
>>>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>>>> index eec1cf4..983b2fd4 100644
>>>> --- a/drivers/usb/dwc3/core.h
>>>> +++ b/drivers/usb/dwc3/core.h
>>>> @@ -1223,6 +1223,7 @@ struct dwc3 {
>>>>unsignedis_utmi_l1_suspend:1;
>>>>unsignedis_fpga:1;
>>>>unsignedpending_events:1;
>>>> +  unsignedneeds_fifo_resize:1;
>>> The prefix "need" sounds like a requirement, but I don't think it is the
>>> case here. I think "do" would be a better prefix here.
>>>
>> Hi Thinh,
>>
>> Sure, that is true, since this may be an optional flag for certain
>> platforms.
>>
>>>>unsignedpullups_connected:1;
>>>>unsignedsetup_packet_pending:1;
>>>>unsignedthree_stage_setup:1;
>>>> @@ -1257,6 +1258,10 @@ struct dwc3 {
>>>>unsigneddis_split_quirk:1;
>>>>  
>>>>u16 imod_interval;
>>>> +
>>>> +  int max_cfg_eps;
>>>> +  int last_fifo_depth;
>>>> +  int num_ep_resized;
>>>>  };
>>> Please document these new fields.
>>>
>> Will do.
>>
>>>>  
>>>>  #define INCRX_BURST_MODE 0
>>>> @@ -1471,6 +1476,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, 
>>>> unsigned int cmd,
>>>>struct dwc3_gadget_ep_cmd_params *params);
>>>>  int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd,
>>>>u32 param);
>>>> +void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc);
>>>>  #else
>>>>  static inline int dwc3_gadget_init(struct dwc3 *dwc)
>>>>  { return 0; }
>>>> @@ -1490,6 +1496,8 @@ static inline int dwc3_send_gadget_ep_cmd(struct 
>>>> dwc3_ep *dep, unsigned int cmd,
>>>>  static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc,
>>>>int cmd, u32 param)
>>>>  { return 0; }
>>>> +static inline void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc)
>>>> +{ }
>>>>  #

Re: usb: dwc3: gadget: skip pullup and set_speed after suspend

2021-01-26 Thread Wesley Cheng



On 1/21/2021 11:15 PM, Jung Daehwan wrote:
> On Fri, Jan 22, 2021 03:32, Wesley cheng wrote:
>> Hi Daehwan,
>>
>> If this is an unexpected event where userspace initiates the UDC bind
>> sequence, then after the above sequence occurs, the DWC3 device should
>> still be able to re-enter runtime suspend after the autosuspend timer
>> expires.  Since the cable is disconnected, the dwc->connected flag would
>> still be false.  Is this not happening in your situation?
>>
>> I'm just trying to understand what issue you're seeing other than the
>> momentary transition from runtime suspend (due to cable disconnect)
>> -->runtime resume (due to unexpected UDC bind) --> runtime  suspend (due
>> to nothing connected).
>>
>> Thanks
>> Wesley cheng
> 
> Hi Wesley,
> 
> I don't know why but DWC3 device is not re-entering runtime-suspend in
> my situation. I'm still debugging it.
> Even if DWC3 re-enter runtime-suspend but it doesn't mean stopping gadget.
> Are you stopping gadget manually in this case?

Hi Daehwan,

Sorry for the late response.  So during the DWC3 runtime suspend path,
we will execute dwc3_gadget_suspend() which should disable the gadget
events and disable ep0 then clear RS bit.  Then on runtime resume, the
DWC3 will be re-enabled, and the RS bit set again.

Thanks
Wesley Cheng

> 
> Best Regards,
> Jung Daehwan
> 
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v6 3/4] usb: dwc3: Resize TX FIFOs to meet EP bursting requirements

2021-01-26 Thread Wesley Cheng



On 1/22/2021 4:15 PM, Thinh Nguyen wrote:
> Hi,
> 
> Wesley Cheng wrote:
>> Some devices have USB compositions which may require multiple endpoints
>> that support EP bursting.  HW defined TX FIFO sizes may not always be
>> sufficient for these compositions.  By utilizing flexible TX FIFO
>> allocation, this allows for endpoints to request the required FIFO depth to
>> achieve higher bandwidth.  With some higher bMaxBurst configurations, using
>> a larger TX FIFO size results in better TX throughput.
>>
>> By introducing the check_config() callback, the resizing logic can fetch
>> the maximum number of endpoints used in the USB composition (can contain
>> multiple configurations), which helps ensure that the resizing logic can
>> fulfill the configuration(s), or return an error to the gadget layer
>> otherwise during bind time.
>>
>> Signed-off-by: Wesley Cheng 
>> ---
>>  drivers/usb/dwc3/core.c   |   2 +
>>  drivers/usb/dwc3/core.h   |   8 ++
>>  drivers/usb/dwc3/ep0.c|   2 +
>>  drivers/usb/dwc3/gadget.c | 194 
>> ++
>>  4 files changed, 206 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index 6969196..e7fa6af 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -1284,6 +1284,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
>>  _thr_num_pkt_prd);
>>  device_property_read_u8(dev, "snps,tx-max-burst-prd",
>>  _max_burst_prd);
>> +dwc->needs_fifo_resize = device_property_read_bool(dev,
>> +   "tx-fifo-resize");
>>  
>>  dwc->disable_scramble_quirk = device_property_read_bool(dev,
>>  "snps,disable_scramble_quirk");
>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>> index eec1cf4..983b2fd4 100644
>> --- a/drivers/usb/dwc3/core.h
>> +++ b/drivers/usb/dwc3/core.h
>> @@ -1223,6 +1223,7 @@ struct dwc3 {
>>  unsignedis_utmi_l1_suspend:1;
>>  unsignedis_fpga:1;
>>  unsignedpending_events:1;
>> +unsignedneeds_fifo_resize:1;
> 
> The prefix "need" sounds like a requirement, but I don't think it is the
> case here. I think "do" would be a better prefix here.
> 
Hi Thinh,

Sure, that is true, since this may be an optional flag for certain
platforms.

>>  unsignedpullups_connected:1;
>>  unsignedsetup_packet_pending:1;
>>  unsignedthree_stage_setup:1;
>> @@ -1257,6 +1258,10 @@ struct dwc3 {
>>  unsigneddis_split_quirk:1;
>>  
>>  u16 imod_interval;
>> +
>> +int max_cfg_eps;
>> +int last_fifo_depth;
>> +int num_ep_resized;
>>  };
> 
> Please document these new fields.
> 
Will do.

>>  
>>  #define INCRX_BURST_MODE 0
>> @@ -1471,6 +1476,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, 
>> unsigned int cmd,
>>  struct dwc3_gadget_ep_cmd_params *params);
>>  int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd,
>>  u32 param);
>> +void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc);
>>  #else
>>  static inline int dwc3_gadget_init(struct dwc3 *dwc)
>>  { return 0; }
>> @@ -1490,6 +1496,8 @@ static inline int dwc3_send_gadget_ep_cmd(struct 
>> dwc3_ep *dep, unsigned int cmd,
>>  static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc,
>>  int cmd, u32 param)
>>  { return 0; }
>> +static inline void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc)
>> +{ }
>>  #endif
>>  
>>  #if IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
>> diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
>> index 8b668ef..4f216bd 100644
>> --- a/drivers/usb/dwc3/ep0.c
>> +++ b/drivers/usb/dwc3/ep0.c
>> @@ -616,6 +616,8 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct 
>> usb_ctrlrequest *ctrl)
>>  return -EINVAL;
>>  
>>  case USB_STATE_ADDRESS:
>> +dwc3_gadget_clear_tx_fifos(dwc);
>> +
>>  ret = dwc3_ep0_delegate_req(dwc, ctrl);
>>  /* if the cfg matches and the cfg is non zero */
>>  if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
>&g

Re: [PATCH v6 3/4] usb: dwc3: Resize TX FIFOs to meet EP bursting requirements

2021-01-26 Thread Wesley Cheng



On 1/25/2021 5:55 PM, Bjorn Andersson wrote:
> On Mon 25 Jan 19:14 CST 2021, Wesley Cheng wrote:
> 
>>
>>
>> On 1/22/2021 9:12 AM, Bjorn Andersson wrote:
>>> On Thu 21 Jan 22:01 CST 2021, Wesley Cheng wrote:
>>>
>>
>> Hi Bjorn,
>>>
>>> Under what circumstances should we specify this? And in particular are
>>> there scenarios (in the Qualcomm platforms) where this must not be set?
>>> The TXFIFO dynamic allocation is actually a feature within the DWC3
>> controller, and isn't specifically for QCOM based platforms.  It won't
>> do any harm functionally if this flag is not set, as this is meant for
>> enhancing performance/bandwidth.
>>
>>> In particular, the composition can be changed in runtime, so should we
>>> set this for all Qualcomm platforms?
>>>
>> Ideally yes, if we want to increase bandwith for situations where SS
>> endpoint bursting is set to a higher value.
>>
>>> And if that's the case, can we not just set it from the qcom driver?
>>>
>> Since this is a common DWC3 core feature, I think it would make more
>> sense to have it in DWC3 core instead of a vendor's DWC3 glue driver.
>>
> 
> I don't have any objections to implementing it in the core driver, but
> my question is can we just skip the DT binding and just enable it from
> the vendor driver?
> 
> Regards,
> Bjorn
> 

Hi Bjorn,

I see.  I think there are some designs which don't have a DWC3 glue
driver, so assuming there may be other platforms using this, there may
not always be a vendor driver to set this.

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v6 1/4] usb: gadget: udc: core: Introduce check_config to verify USB configuration

2021-01-26 Thread Wesley Cheng



On 1/21/2021 9:17 PM, Jack Pham wrote:
> Hi Wesley,
> 
> On Thu, Jan 21, 2021 at 08:01:37PM -0800, Wesley Cheng wrote:
>> Some UDCs may have constraints on how many high bandwidth endpoints it can
>> support in a certain configuration.  This API allows for the composite
>> driver to pass down the total number of endpoints to the UDC so it can verify
>> it has the required resources to support the configuration.
>>
>> Signed-off-by: Wesley Cheng 
>> ---
>>  drivers/usb/gadget/udc/core.c | 9 +
>>  include/linux/usb/gadget.h| 2 ++
>>  2 files changed, 11 insertions(+)
>>
>> diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
>> index 4173acd..469962f 100644
>> --- a/drivers/usb/gadget/udc/core.c
>> +++ b/drivers/usb/gadget/udc/core.c
>> @@ -1003,6 +1003,15 @@ int usb_gadget_ep_match_desc(struct usb_gadget 
>> *gadget,
>>  }
>>  EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc);
>>  
>> +int usb_gadget_check_config(struct usb_gadget *gadget, unsigned long ep_map)
> 
> You should probably add a kernel-doc for this function.
> 
> Jack
> 
Hi Jack,

Sure, I'll update a bit more about how this API can be used.

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v6 3/4] usb: dwc3: Resize TX FIFOs to meet EP bursting requirements

2021-01-26 Thread Wesley Cheng



On 1/22/2021 9:12 AM, Bjorn Andersson wrote:
> On Thu 21 Jan 22:01 CST 2021, Wesley Cheng wrote:
> 

Hi Bjorn,
> 
> Under what circumstances should we specify this? And in particular are
> there scenarios (in the Qualcomm platforms) where this must not be set?
>The TXFIFO dynamic allocation is actually a feature within the DWC3
controller, and isn't specifically for QCOM based platforms.  It won't
do any harm functionally if this flag is not set, as this is meant for
enhancing performance/bandwidth.

> In particular, the composition can be changed in runtime, so should we
> set this for all Qualcomm platforms?
> 
Ideally yes, if we want to increase bandwith for situations where SS
endpoint bursting is set to a higher value.

> And if that's the case, can we not just set it from the qcom driver?
> 
Since this is a common DWC3 core feature, I think it would make more
sense to have it in DWC3 core instead of a vendor's DWC3 glue driver.

Thanks
Wesley Cheng

> Regards,
> Bjorn


-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v6 1/4] usb: gadget: udc: core: Introduce check_config to verify USB configuration

2021-01-26 Thread Wesley Cheng



On 1/22/2021 8:24 AM, Alan Stern wrote:
> On Thu, Jan 21, 2021 at 08:01:37PM -0800, Wesley Cheng wrote:
>> Some UDCs may have constraints on how many high bandwidth endpoints it can
>> support in a certain configuration.  This API allows for the composite
>> driver to pass down the total number of endpoints to the UDC so it can verify
>> it has the required resources to support the configuration.
>>
>> Signed-off-by: Wesley Cheng 
> 
> 
>> --- a/include/linux/usb/gadget.h
>> +++ b/include/linux/usb/gadget.h
>> @@ -328,6 +328,7 @@ struct usb_gadget_ops {
>>  struct usb_ep *(*match_ep)(struct usb_gadget *,
>>  struct usb_endpoint_descriptor *,
>>  struct usb_ss_ep_comp_descriptor *);
>> +int (*check_config)(struct usb_gadget *gadget, unsigned long 
>> ep_map);
>>  };
>>  
>>  /**
>> @@ -607,6 +608,7 @@ int usb_gadget_connect(struct usb_gadget *gadget);
>>  int usb_gadget_disconnect(struct usb_gadget *gadget);
>>  int usb_gadget_deactivate(struct usb_gadget *gadget);
>>  int usb_gadget_activate(struct usb_gadget *gadget);
>> +int usb_gadget_check_config(struct usb_gadget *gadget, unsigned long 
>> ep_map);
>>  #else
>>  static inline int usb_gadget_frame_number(struct usb_gadget *gadget)
>>  { return 0; }
> 
> Don't you also need an entry for the case where CONFIG_USB_GADGET isn't 
> enabled?
> 
> Alan Stern
> 
Hi Alan,

Thanks for pointing that out.  I missed that, and will add it to the
next rev.

Thanks
Wesley Cheng


-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH v6 0/4] Re-introduce TX FIFO resize for larger EP bursting

2021-01-21 Thread Wesley Cheng
Changes in V6:
 - Rebased patches to usb-testing.
 - Renamed to PATCH series instead of RFC.
 - Checking for fs_descriptors instead of ss_descriptors for determining the
   endpoint count for a particular configuration.
 - Re-ordered patch series to fix patch dependencies.

Changes in V5:
 - Added check_config() logic, which is used to communicate the number of EPs
   used in a particular configuration.  Based on this, the DWC3 gadget driver
   has the ability to know the maximum number of eps utilized in all configs.
   This helps reduce unnecessary allocation to unused eps, and will catch fifo
   allocation issues at bind() time.
 - Fixed variable declaration to single line per variable, and reverse xmas.
 - Created a helper for fifo clearing, which is used by ep0.c

Changes in V4:
 - Removed struct dwc3* as an argument for dwc3_gadget_resize_tx_fifos()
 - Removed WARN_ON(1) in case we run out of fifo space
 
Changes in V3:
 - Removed "Reviewed-by" tags
 - Renamed series back to RFC
 - Modified logic to ensure that fifo_size is reset if we pass the minimum
   threshold.  Tested with binding multiple FDs requesting 6 FIFOs.

Changes in V2:
 - Modified TXFIFO resizing logic to ensure that each EP is reserved a
   FIFO.
 - Removed dev_dbg() prints and fixed typos from patches
 - Added some more description on the dt-bindings commit message

Currently, there is no functionality to allow for resizing the TXFIFOs, and
relying on the HW default setting for the TXFIFO depth.  In most cases, the
HW default is probably sufficient, but for USB compositions that contain
multiple functions that require EP bursting, the default settings
might not be enough.  Also to note, the current SW will assign an EP to a
function driver w/o checking to see if the TXFIFO size for that particular
EP is large enough. (this is a problem if there are multiple HW defined
values for the TXFIFO size)

It is mentioned in the SNPS databook that a minimum of TX FIFO depth = 3
is required for an EP that supports bursting.  Otherwise, there may be
frequent occurences of bursts ending.  For high bandwidth functions,
such as data tethering (protocols that support data aggregation), mass
storage, and media transfer protocol (over FFS), the bMaxBurst value can be
large, and a bigger TXFIFO depth may prove to be beneficial in terms of USB
throughput. (which can be associated to system access latency, etc...)  It
allows for a more consistent burst of traffic, w/o any interruptions, as
data is readily available in the FIFO.

With testing done using the mass storage function driver, the results show
that with a larger TXFIFO depth, the bandwidth increased significantly.

Test Parameters:
 - Platform: Qualcomm SM8150
 - bMaxBurst = 6
 - USB req size = 256kB
 - Num of USB reqs = 16
 - USB Speed = Super-Speed
 - Function Driver: Mass Storage (w/ ramdisk)
 - Test Application: CrystalDiskMark

Results:

TXFIFO Depth = 3 max packets

Test Case | Data Size | AVG tput (in MB/s)
---
Sequential|1 GB x | 
Read  |9 loops| 193.60
  |   | 195.86
  |   | 184.77
  |   | 193.60
---

TXFIFO Depth = 6 max packets

Test Case | Data Size | AVG tput (in MB/s)
---
Sequential|1 GB x | 
Read  |9 loops| 287.35
  |   | 304.94
  |   | 289.64
  |   | 293.61
-------
Wesley Cheng (4):
  usb: gadget: udc: core: Introduce check_config to verify USB
configuration
  usb: gadget: configfs: Check USB configuration before adding
  usb: dwc3: Resize TX FIFOs to meet EP bursting requirements
  arm64: boot: dts: qcom: sm8150: Enable dynamic TX FIFO resize logic

 arch/arm64/boot/dts/qcom/sm8150.dtsi |   1 +
 drivers/usb/dwc3/core.c  |   2 +
 drivers/usb/dwc3/core.h  |   8 ++
 drivers/usb/dwc3/ep0.c   |   2 +
 drivers/usb/dwc3/gadget.c| 194 +++
 drivers/usb/gadget/configfs.c|  22 
 drivers/usb/gadget/udc/core.c|   9 ++
 include/linux/usb/gadget.h   |   2 +
 8 files changed, 240 insertions(+)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v6 1/4] usb: gadget: udc: core: Introduce check_config to verify USB configuration

2021-01-21 Thread Wesley Cheng
Some UDCs may have constraints on how many high bandwidth endpoints it can
support in a certain configuration.  This API allows for the composite
driver to pass down the total number of endpoints to the UDC so it can verify
it has the required resources to support the configuration.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/gadget/udc/core.c | 9 +
 include/linux/usb/gadget.h| 2 ++
 2 files changed, 11 insertions(+)

diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 4173acd..469962f 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -1003,6 +1003,15 @@ int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
 }
 EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc);
 
+int usb_gadget_check_config(struct usb_gadget *gadget, unsigned long ep_map)
+{
+   if (!gadget->ops->check_config)
+   return 0;
+
+   return gadget->ops->check_config(gadget, ep_map);
+}
+EXPORT_SYMBOL_GPL(usb_gadget_check_config);
+
 /* - */
 
 static void usb_gadget_state_work(struct work_struct *work)
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index ee04ef2..8393fa8 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -328,6 +328,7 @@ struct usb_gadget_ops {
struct usb_ep *(*match_ep)(struct usb_gadget *,
struct usb_endpoint_descriptor *,
struct usb_ss_ep_comp_descriptor *);
+   int (*check_config)(struct usb_gadget *gadget, unsigned long 
ep_map);
 };
 
 /**
@@ -607,6 +608,7 @@ int usb_gadget_connect(struct usb_gadget *gadget);
 int usb_gadget_disconnect(struct usb_gadget *gadget);
 int usb_gadget_deactivate(struct usb_gadget *gadget);
 int usb_gadget_activate(struct usb_gadget *gadget);
+int usb_gadget_check_config(struct usb_gadget *gadget, unsigned long ep_map);
 #else
 static inline int usb_gadget_frame_number(struct usb_gadget *gadget)
 { return 0; }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v6 2/4] usb: gadget: configfs: Check USB configuration before adding

2021-01-21 Thread Wesley Cheng
Ensure that the USB gadget is able to support the configuration being
added based on the number of endpoints required from all interfaces.  This
is for accounting for any bandwidth or space limitations.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/gadget/configfs.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 0d56f33..e6de3ca5 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1368,6 +1368,7 @@ static int configfs_composite_bind(struct usb_gadget 
*gadget,
struct usb_function *f;
struct usb_function *tmp;
struct gadget_config_name *cn;
+   unsigned long ep_map = 0;
 
if (gadget_is_otg(gadget))
c->descriptors = otg_desc;
@@ -1397,7 +1398,28 @@ static int configfs_composite_bind(struct usb_gadget 
*gadget,
list_add(>list, >func_list);
goto err_purge_funcs;
}
+   if (f->fs_descriptors) {
+   struct usb_descriptor_header **d;
+
+   d = f->fs_descriptors;
+   for (; *d; ++d) {
+   struct usb_endpoint_descriptor *ep;
+   int addr;
+
+   if ((*d)->bDescriptorType != 
USB_DT_ENDPOINT)
+   continue;
+
+   ep = (struct usb_endpoint_descriptor 
*)*d;
+   addr = ((ep->bEndpointAddress & 0x80) 
>> 3) |
+   (ep->bEndpointAddress & 0x0f);
+   set_bit(addr, _map);
+   }
+   }
}
+   ret = usb_gadget_check_config(cdev->gadget, ep_map);
+   if (ret)
+   goto err_purge_funcs;
+
usb_ep_autoconfig_reset(cdev->gadget);
}
if (cdev->use_os_string) {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v6 3/4] usb: dwc3: Resize TX FIFOs to meet EP bursting requirements

2021-01-21 Thread Wesley Cheng
Some devices have USB compositions which may require multiple endpoints
that support EP bursting.  HW defined TX FIFO sizes may not always be
sufficient for these compositions.  By utilizing flexible TX FIFO
allocation, this allows for endpoints to request the required FIFO depth to
achieve higher bandwidth.  With some higher bMaxBurst configurations, using
a larger TX FIFO size results in better TX throughput.

By introducing the check_config() callback, the resizing logic can fetch
the maximum number of endpoints used in the USB composition (can contain
multiple configurations), which helps ensure that the resizing logic can
fulfill the configuration(s), or return an error to the gadget layer
otherwise during bind time.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/core.c   |   2 +
 drivers/usb/dwc3/core.h   |   8 ++
 drivers/usb/dwc3/ep0.c|   2 +
 drivers/usb/dwc3/gadget.c | 194 ++
 4 files changed, 206 insertions(+)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 6969196..e7fa6af 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1284,6 +1284,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
_thr_num_pkt_prd);
device_property_read_u8(dev, "snps,tx-max-burst-prd",
_max_burst_prd);
+   dwc->needs_fifo_resize = device_property_read_bool(dev,
+  "tx-fifo-resize");
 
dwc->disable_scramble_quirk = device_property_read_bool(dev,
"snps,disable_scramble_quirk");
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index eec1cf4..983b2fd4 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1223,6 +1223,7 @@ struct dwc3 {
unsignedis_utmi_l1_suspend:1;
unsignedis_fpga:1;
unsignedpending_events:1;
+   unsignedneeds_fifo_resize:1;
unsignedpullups_connected:1;
unsignedsetup_packet_pending:1;
unsignedthree_stage_setup:1;
@@ -1257,6 +1258,10 @@ struct dwc3 {
unsigneddis_split_quirk:1;
 
u16 imod_interval;
+
+   int max_cfg_eps;
+   int last_fifo_depth;
+   int num_ep_resized;
 };
 
 #define INCRX_BURST_MODE 0
@@ -1471,6 +1476,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned 
int cmd,
struct dwc3_gadget_ep_cmd_params *params);
 int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd,
u32 param);
+void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc);
 #else
 static inline int dwc3_gadget_init(struct dwc3 *dwc)
 { return 0; }
@@ -1490,6 +1496,8 @@ static inline int dwc3_send_gadget_ep_cmd(struct dwc3_ep 
*dep, unsigned int cmd,
 static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc,
int cmd, u32 param)
 { return 0; }
+static inline void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc)
+{ }
 #endif
 
 #if IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 8b668ef..4f216bd 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -616,6 +616,8 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct 
usb_ctrlrequest *ctrl)
return -EINVAL;
 
case USB_STATE_ADDRESS:
+   dwc3_gadget_clear_tx_fifos(dwc);
+
ret = dwc3_ep0_delegate_req(dwc, ctrl);
/* if the cfg matches and the cfg is non zero */
if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 86f257f..26f9d64 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -615,6 +615,161 @@ static int dwc3_gadget_set_ep_config(struct dwc3_ep *dep, 
unsigned int action)
 static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
bool interrupt);
 
+static int dwc3_gadget_calc_tx_fifo_size(struct dwc3 *dwc, int mult)
+{
+   int max_packet = 1024;
+   int fifo_size;
+   int mdwidth;
+
+   mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
+   /* MDWIDTH is represented in bits, we need it in bytes */
+   mdwidth >>= 3;
+
+   fifo_size = mult * ((max_packet + mdwidth) / mdwidth) + 1;
+   return fifo_size;
+}
+
+void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc)
+{
+   struct dwc3_ep *dep;
+   int fifo_depth;
+   int size;
+   int num;
+
+   if (!dwc->needs_fifo_resize)
+   return;
+
+   /* Read ep0IN related TXFIFO size */
+   dep = dwc->eps[1];
+   size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
+   if (DWC3_IP_I

[PATCH v6 4/4] arm64: boot: dts: qcom: sm8150: Enable dynamic TX FIFO resize logic

2021-01-21 Thread Wesley Cheng
Enable the flexible TX FIFO resize logic on SM8150.  Using a larger TX FIFO
SZ can help account for situations when system latency is greater than the
USB bus transmission latency.

Signed-off-by: Wesley Cheng 
---
 arch/arm64/boot/dts/qcom/sm8150.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi 
b/arch/arm64/boot/dts/qcom/sm8150.dtsi
index 5270bda..c7706f4 100644
--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -1569,6 +1569,7 @@
iommus = <_smmu 0x140 0>;
snps,dis_u2_susphy_quirk;
snps,dis_enblslpm_quirk;
+   tx-fifo-resize;
phys = <_1_hsphy>, <_1_ssphy>;
phy-names = "usb2-phy", "usb3-phy";
};
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: usb: dwc3: gadget: skip pullup and set_speed after suspend

2021-01-21 Thread Wesley Cheng



On 1/21/2021 12:13 AM, Jung Daehwan wrote:
> On Wed, Jan 20, 2021 at 11:44:05PM -0800, Wesley Cheng wrote:
>>
>>
>> On 1/20/2021 10:49 PM, Jung Daehwan wrote:
>>> Hi,
>>>
>>> On Thu, Jan 21, 2021 at 01:00:32AM +, Thinh Nguyen wrote:
>>>> Hi,
>>>>
>>>> Daehwan Jung wrote:
>>>>> Sometimes dwc3_gadget_pullup and dwc3_gadget_set_speed are called after
>>>>> entering suspend. That's why it needs to check whether suspend
>>>>>
>>>>> 1. dwc3 sends disconnect uevent and turn off. (suspend)
>>>>> 2. Platform side causes pullup or set_speed(e.g., adbd closes ffs node)
>>>>> 3. It causes unexpected behavior like ITMON error.
>>>>>
>>>>> Signed-off-by: Daehwan Jung 
>>>>> ---
>>>>>  drivers/usb/dwc3/gadget.c | 6 ++
>>>>>  1 file changed, 6 insertions(+)
>>>>>
>>>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>>>> index ee44321..d7d4202 100644
>>>>> --- a/drivers/usb/dwc3/gadget.c
>>>>> +++ b/drivers/usb/dwc3/gadget.c
>>>>> @@ -2093,6 +2093,9 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, 
>>>>> int is_on)
>>>>>   unsigned long   flags;
>>>>>   int ret;
>>>>>  
>>>>> + if (pm_runtime_suspended(dwc->dev))
>>>>> + return 0;
>>>>> +
>>>>>   is_on = !!is_on;
>>>>>  
>>>>>   /*
>>>>> @@ -2403,6 +2406,9 @@ static void dwc3_gadget_set_speed(struct usb_gadget 
>>>>> *g,
>>>>>   unsigned long   flags;
>>>>>   u32 reg;
>>>>>  
>>>>> + if (pm_runtime_suspended(dwc->dev))
>>>>> + return;
>>>>> +
>>>>>   spin_lock_irqsave(>lock, flags);
>>>>>   reg = dwc3_readl(dwc->regs, DWC3_DCFG);
>>>>>   reg &= ~(DWC3_DCFG_SPEED_MASK);
>>>>
>>>> This is already addressed in Wesley Cheng's patches. Can you try the
>>>> latest changes of DWC3 in Greg's usb-next branch?
>>>>
>>>> Thanks,
>>>> Thinh
>>>
>>> I checked Wesly Cheng's pathces but it's not same.
>>> What I want to do for this patch is to avoid pullup from platform side.
>>> (android in my case)
>>>
>>> It's possible that platform side tries to pullup by UDC_Store after usb is 
>>> already disconnected.
>>> It can finally run controller and enable irq.
>>>
>>> I think we have to avoid it and other possible things related to platform 
>>> side.
>>>
>>>
>>
>> Hi Daehwan,
>>
>> I think what you're trying to do is to avoid the unnecessary runtime
>> resume if the cable is disconnected and userspace attempts to
>> bind/unbind the UDC.
>>
>> I'm not exactly sure what patches you've pulled in, but assuming you
>> didn't pull in any of the recent suspend changes:
>>
>> usb: dwc3: gadget: Allow runtime suspend if UDC unbinded
>> usb: dwc3: gadget: Preserve UDC max speed setting
>>
>> Please consider the following scenario:
>> 1.  USB connected
>> 2.  UDC unbinded
>> 3.  DWC3 will continue to stay in runtime active, since dwc->connected =
>> true
>>
>> In this scenario, we should allow the DWC3 to enter runtime suspend,
>> since runstop has been disabled.
>>
>> If you have pulled in the above changes, and adding your changes on top
>> of it, then consider the following:
>> 1.  USB connected
>> 2.  UDC unbinded
>> 3.  DWC enters runtime suspend (due to the above changes)
>> 4.  UDC binded
>>
>> The check for pm_runtime_suspended() will block step#4 from re-enabling
>> the runstop bit even if the USB cable is connected.
>>
>> Thanks
>> Wesley Cheng
>>
>> -- 
>> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
>> a Linux Foundation Collaborative Project
>>
> 
> Hi Wesley
> 
> The check for runtime_suspended() will block re-enabling the runstop bit as
> you said after pulling your patches in.
> 
> UDC is contolled by userspace and it's possible UDC can be binded
> unexpectedly. That's why I think it needs to handle it even if the
> problem is from userspace.
> 
> Below is an example in my environment.
> 
> 1. USB disconnected
> 2. UDC unbind

Re: usb: dwc3: gadget: skip pullup and set_speed after suspend

2021-01-20 Thread Wesley Cheng



On 1/20/2021 10:49 PM, Jung Daehwan wrote:
> Hi,
> 
> On Thu, Jan 21, 2021 at 01:00:32AM +, Thinh Nguyen wrote:
>> Hi,
>>
>> Daehwan Jung wrote:
>>> Sometimes dwc3_gadget_pullup and dwc3_gadget_set_speed are called after
>>> entering suspend. That's why it needs to check whether suspend
>>>
>>> 1. dwc3 sends disconnect uevent and turn off. (suspend)
>>> 2. Platform side causes pullup or set_speed(e.g., adbd closes ffs node)
>>> 3. It causes unexpected behavior like ITMON error.
>>>
>>> Signed-off-by: Daehwan Jung 
>>> ---
>>>  drivers/usb/dwc3/gadget.c | 6 ++
>>>  1 file changed, 6 insertions(+)
>>>
>>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>>> index ee44321..d7d4202 100644
>>> --- a/drivers/usb/dwc3/gadget.c
>>> +++ b/drivers/usb/dwc3/gadget.c
>>> @@ -2093,6 +2093,9 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, 
>>> int is_on)
>>> unsigned long   flags;
>>> int ret;
>>>  
>>> +   if (pm_runtime_suspended(dwc->dev))
>>> +   return 0;
>>> +
>>> is_on = !!is_on;
>>>  
>>> /*
>>> @@ -2403,6 +2406,9 @@ static void dwc3_gadget_set_speed(struct usb_gadget 
>>> *g,
>>> unsigned long   flags;
>>> u32 reg;
>>>  
>>> +   if (pm_runtime_suspended(dwc->dev))
>>> +   return;
>>> +
>>> spin_lock_irqsave(>lock, flags);
>>> reg = dwc3_readl(dwc->regs, DWC3_DCFG);
>>> reg &= ~(DWC3_DCFG_SPEED_MASK);
>>
>> This is already addressed in Wesley Cheng's patches. Can you try the
>> latest changes of DWC3 in Greg's usb-next branch?
>>
>> Thanks,
>> Thinh
> 
> I checked Wesly Cheng's pathces but it's not same.
> What I want to do for this patch is to avoid pullup from platform side.
> (android in my case)
> 
> It's possible that platform side tries to pullup by UDC_Store after usb is 
> already disconnected.
> It can finally run controller and enable irq.
> 
> I think we have to avoid it and other possible things related to platform 
> side.
> 
> 

Hi Daehwan,

I think what you're trying to do is to avoid the unnecessary runtime
resume if the cable is disconnected and userspace attempts to
bind/unbind the UDC.

I'm not exactly sure what patches you've pulled in, but assuming you
didn't pull in any of the recent suspend changes:

usb: dwc3: gadget: Allow runtime suspend if UDC unbinded
usb: dwc3: gadget: Preserve UDC max speed setting

Please consider the following scenario:
1.  USB connected
2.  UDC unbinded
3.  DWC3 will continue to stay in runtime active, since dwc->connected =
true

In this scenario, we should allow the DWC3 to enter runtime suspend,
since runstop has been disabled.

If you have pulled in the above changes, and adding your changes on top
of it, then consider the following:
1.  USB connected
2.  UDC unbinded
3.  DWC enters runtime suspend (due to the above changes)
4.  UDC binded

The check for pm_runtime_suspended() will block step#4 from re-enabling
the runstop bit even if the USB cable is connected.

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH 3/3] usb: gadget: configfs: Add a specific configFS reset callback

2021-01-04 Thread Wesley Cheng



On 1/4/2021 7:45 AM, Greg KH wrote:
> On Tue, Dec 29, 2020 at 03:03:31PM -0800, Wesley Cheng wrote:
>> In order for configFS based USB gadgets to set the proper charge current
>> for bus reset scenarios, expose a separate reset callback to set the
>> current to 100mA based on the USB battery charging specification.
>>
>> Reviewed-by: Peter Chen 
>> Signed-off-by: Wesley Cheng 
>> ---
>>  drivers/usb/gadget/configfs.c | 24 +++-
>>  1 file changed, 23 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
>> index 56051bb97349..80ca7ff2fb97 100644
>> --- a/drivers/usb/gadget/configfs.c
>> +++ b/drivers/usb/gadget/configfs.c
>> @@ -1481,6 +1481,28 @@ static void configfs_composite_disconnect(struct 
>> usb_gadget *gadget)
>>  spin_unlock_irqrestore(>spinlock, flags);
>>  }
>>  
>> +static void configfs_composite_reset(struct usb_gadget *gadget)
>> +{
>> +struct usb_composite_dev *cdev;
>> +struct gadget_info *gi;
>> +unsigned long flags;
>> +
>> +cdev = get_gadget_data(gadget);
>> +if (!cdev)
>> +return;
>> +
>> +gi = container_of(cdev, struct gadget_info, cdev);
>> +spin_lock_irqsave(>spinlock, flags);
>> +cdev = get_gadget_data(gadget);
>> +if (!cdev || gi->unbind) {
>> +spin_unlock_irqrestore(>spinlock, flags);
>> +return;
>> +}
>> +
>> +composite_reset(gadget);
>> +spin_unlock_irqrestore(>spinlock, flags);
>> +}
>> +
>>  static void configfs_composite_suspend(struct usb_gadget *gadget)
>>  {
>>  struct usb_composite_dev *cdev;
>> @@ -1530,7 +1552,7 @@ static const struct usb_gadget_driver 
>> configfs_driver_template = {
>>  .unbind = configfs_composite_unbind,
>>  
>>  .setup  = configfs_composite_setup,
>> -.reset  = configfs_composite_disconnect,
>> +.reset  = configfs_composite_reset,
>>  .disconnect = configfs_composite_disconnect,
>>  
>>  .suspend= configfs_composite_suspend,
>> -- 
>> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
>> a Linux Foundation Collaborative Project
>>
> 
> So this changes the existing userspace functionality?  What will break
> because of this now unexpected change?
> 
> thanks,
> 
> greg k-h
> 

Hi Greg,

Happy new years!  This wouldn't affect the userspace interaction with
configFS, as this is modifying the reset callback for the UDC core.  The
reset callback is only executed during usb_gadget_udc_reset(), which is
specifically run when vendor UDC drivers (i.e. DWC3 gadget) receive a
USB bus reset interrupt.  This is similar to the composite.c patch,
because for configFS based gadgets, they do not directly register the
USB composite ops and have their own routines.

Thanks
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH v2 0/2] Allow DWC3 runtime suspend if UDC is unbinded

2020-12-29 Thread Wesley Cheng
Changes in v2:
 - Modified logic for executing the runtime PM resume.  Using a sychronous get
   call to avoid race conditions.

During the following scenario, the DWC3 runtime suspend routine is blocked as
the connected flag is still true:

1.  Enumerate device w/ host.
2.  Gadget is unbinded
- echo "" > /sys/kernel/config/usb_gadget/g1/UDC
3.  Disconnect the USB cable (VBUS low)
4.  No dwc3_gadget_disconnect_interrupt() seen (since controller is
   halted from step#1)
5.  Runtime PM autosuspend fails due to "dwc->connected" being true
(cleared in dwc3_gadget_disconnect_interrupt())
6.  Gadget binded
- echo udc_name > /sys/kernel/config/usb_gadget/g1/UDC
7.  No runtime suspend until cable is plugged in and out

Technically, for device initiated disconnects, there is no active session/link
with the host, so the DWC3 controller should be allowed to go into a low power
state.  Also, we need to now consider when re-binding the UDC,
dwc3_gadget_set_speed() is executed before dwc3_gadget_pullup(), so if the DWC3
controller is suspended/disabled, while accessing the DCFG, that could result in
bus timeouts, etc...  Change the dwc3_gadget_set_speed() to save the speed
being requested, and program it during dwc3_gadget_run_stop(), which is executed
during PM runtime resume.  If not, previous setting will be overridden as we
execute a DWC3 controller reset during PM runtime resume. 

Wesley Cheng (2):
  usb: dwc3: gadget: Allow runtime suspend if UDC unbinded
  usb: dwc3: gadget: Preserve UDC max speed setting

 drivers/usb/dwc3/core.h   |   1 +
 drivers/usb/dwc3/gadget.c | 121 ++
 2 files changed, 71 insertions(+), 51 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v2 2/2] usb: dwc3: gadget: Preserve UDC max speed setting

2020-12-29 Thread Wesley Cheng
The USB gadget/UDC driver can restrict the DWC3 controller speed using
dwc3_gadget_set_speed().  Store this setting into a variable, in order for
this setting to persist across controller resets due to runtime PM.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/core.h   |   1 +
 drivers/usb/dwc3/gadget.c | 108 --
 2 files changed, 58 insertions(+), 51 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 2f04b3e42bf1..390d3deef0ba 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1119,6 +1119,7 @@ struct dwc3 {
u32 nr_scratch;
u32 u1u2;
u32 maximum_speed;
+   u32 gadget_max_speed;
 
u32 ip;
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index babf977cadc0..c145da1d8ba5 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1941,6 +1941,61 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
}
 }
 
+static void __dwc3_gadget_set_speed(struct dwc3 *dwc)
+{
+   u32 reg;
+
+   reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+   reg &= ~(DWC3_DCFG_SPEED_MASK);
+
+   /*
+* WORKAROUND: DWC3 revision < 2.20a have an issue
+* which would cause metastability state on Run/Stop
+* bit if we try to force the IP to USB2-only mode.
+*
+* Because of that, we cannot configure the IP to any
+* speed other than the SuperSpeed
+*
+* Refers to:
+*
+* STAR#9000525659: Clock Domain Crossing on DCTL in
+* USB 2.0 Mode
+*/
+   if (DWC3_VER_IS_PRIOR(DWC3, 220A) &&
+   !dwc->dis_metastability_quirk) {
+   reg |= DWC3_DCFG_SUPERSPEED;
+   } else {
+   switch (dwc->gadget_max_speed) {
+   case USB_SPEED_LOW:
+   reg |= DWC3_DCFG_LOWSPEED;
+   break;
+   case USB_SPEED_FULL:
+   reg |= DWC3_DCFG_FULLSPEED;
+   break;
+   case USB_SPEED_HIGH:
+   reg |= DWC3_DCFG_HIGHSPEED;
+   break;
+   case USB_SPEED_SUPER:
+   reg |= DWC3_DCFG_SUPERSPEED;
+   break;
+   case USB_SPEED_SUPER_PLUS:
+   if (DWC3_IP_IS(DWC3))
+   reg |= DWC3_DCFG_SUPERSPEED;
+   else
+   reg |= DWC3_DCFG_SUPERSPEED_PLUS;
+   break;
+   default:
+   dev_err(dwc->dev, "invalid speed (%d)\n", 
dwc->gadget_max_speed);
+
+   if (DWC3_IP_IS(DWC3))
+   reg |= DWC3_DCFG_SUPERSPEED;
+   else
+   reg |= DWC3_DCFG_SUPERSPEED_PLUS;
+   }
+   }
+   dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+}
+
 static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
 {
u32 reg;
@@ -1963,6 +2018,7 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int 
is_on, int suspend)
if (dwc->has_hibernation)
reg |= DWC3_DCTL_KEEP_CONNECT;
 
+   __dwc3_gadget_set_speed(dwc);
dwc->pullups_connected = true;
} else {
reg &= ~DWC3_DCTL_RUN_STOP;
@@ -2325,59 +2381,9 @@ static void dwc3_gadget_set_speed(struct usb_gadget *g,
 {
struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long   flags;
-   u32 reg;
 
spin_lock_irqsave(>lock, flags);
-   reg = dwc3_readl(dwc->regs, DWC3_DCFG);
-   reg &= ~(DWC3_DCFG_SPEED_MASK);
-
-   /*
-* WORKAROUND: DWC3 revision < 2.20a have an issue
-* which would cause metastability state on Run/Stop
-* bit if we try to force the IP to USB2-only mode.
-*
-* Because of that, we cannot configure the IP to any
-* speed other than the SuperSpeed
-*
-* Refers to:
-*
-* STAR#9000525659: Clock Domain Crossing on DCTL in
-* USB 2.0 Mode
-*/
-   if (DWC3_VER_IS_PRIOR(DWC3, 220A) &&
-   !dwc->dis_metastability_quirk) {
-   reg |= DWC3_DCFG_SUPERSPEED;
-   } else {
-   switch (speed) {
-   case USB_SPEED_LOW:
-   reg |= DWC3_DCFG_LOWSPEED;
-   break;
-   case USB_SPEED_FULL:
-   reg |= DWC3_DCFG_FULLSPEED;
-   break;
-   case USB_SPEED_HIGH:
-   reg |= DWC3_DCFG_HIGHSPEED;
-   break;
-   

[PATCH 3/3] usb: gadget: configfs: Add a specific configFS reset callback

2020-12-29 Thread Wesley Cheng
In order for configFS based USB gadgets to set the proper charge current
for bus reset scenarios, expose a separate reset callback to set the
current to 100mA based on the USB battery charging specification.

Reviewed-by: Peter Chen 
Signed-off-by: Wesley Cheng 
---
 drivers/usb/gadget/configfs.c | 24 +++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 56051bb97349..80ca7ff2fb97 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1481,6 +1481,28 @@ static void configfs_composite_disconnect(struct 
usb_gadget *gadget)
spin_unlock_irqrestore(>spinlock, flags);
 }
 
+static void configfs_composite_reset(struct usb_gadget *gadget)
+{
+   struct usb_composite_dev *cdev;
+   struct gadget_info *gi;
+   unsigned long flags;
+
+   cdev = get_gadget_data(gadget);
+   if (!cdev)
+   return;
+
+   gi = container_of(cdev, struct gadget_info, cdev);
+   spin_lock_irqsave(>spinlock, flags);
+   cdev = get_gadget_data(gadget);
+   if (!cdev || gi->unbind) {
+   spin_unlock_irqrestore(>spinlock, flags);
+   return;
+   }
+
+   composite_reset(gadget);
+   spin_unlock_irqrestore(>spinlock, flags);
+}
+
 static void configfs_composite_suspend(struct usb_gadget *gadget)
 {
struct usb_composite_dev *cdev;
@@ -1530,7 +1552,7 @@ static const struct usb_gadget_driver 
configfs_driver_template = {
.unbind = configfs_composite_unbind,
 
.setup  = configfs_composite_setup,
-   .reset  = configfs_composite_disconnect,
+   .reset  = configfs_composite_reset,
.disconnect = configfs_composite_disconnect,
 
.suspend= configfs_composite_suspend,
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v2 1/2] usb: dwc3: gadget: Allow runtime suspend if UDC unbinded

2020-12-29 Thread Wesley Cheng
The DWC3 runtime suspend routine checks for the USB connected parameter to
determine if the controller can enter into a low power state.  The
connected state is only set to false after receiving a disconnect event.
However, in the case of a device initiated disconnect (i.e. UDC unbind),
the controller is halted and a disconnect event is never generated.  Set
the connected flag to false if issuing a device initiated disconnect to
allow the controller to be suspended.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/gadget.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 5d879b7606d5..babf977cadc0 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2012,6 +2012,17 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
}
}
 
+   /*
+* Check the return value for successful resume, or error.  For a
+* successful resume, the DWC3 runtime PM resume routine will handle
+* the run stop sequence, so avoid duplicate operations here.
+*/
+   ret = pm_runtime_get_sync(dwc->dev);
+   if (!ret || ret < 0) {
+   pm_runtime_put(dwc->dev);
+   return 0;
+   }
+
/*
 * Synchronize any pending event handling before executing the 
controller
 * halt routine.
@@ -2050,10 +2061,12 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
dwc->ev_buf->length;
}
+   dwc->connected = false;
}
 
ret = dwc3_gadget_run_stop(dwc, is_on, false);
spin_unlock_irqrestore(>lock, flags);
+   pm_runtime_put(dwc->dev);
 
return ret;
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 1/3] usb: dwc3: gadget: Introduce a DWC3 VBUS draw callback

2020-12-29 Thread Wesley Cheng
Some devices support charging while in device mode.  In these situations,
the USB gadget will notify the DWC3 gadget driver to modify the current
based on the enumeration and device state.  The usb_phy_set_power() API
will allow external charger entities to adjust the charge current through
the notifier block.

Reviewed-by: Peter Chen 
Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/gadget.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index c145da1d8ba5..69122f66978e 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2387,6 +2387,16 @@ static void dwc3_gadget_set_speed(struct usb_gadget *g,
spin_unlock_irqrestore(>lock, flags);
 }
 
+static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA)
+{
+   struct dwc3 *dwc = gadget_to_dwc(g);
+
+   if (dwc->usb2_phy)
+   return usb_phy_set_power(dwc->usb2_phy, mA);
+
+   return 0;
+}
+
 static const struct usb_gadget_ops dwc3_gadget_ops = {
.get_frame  = dwc3_gadget_get_frame,
.wakeup = dwc3_gadget_wakeup,
@@ -2396,6 +2406,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
.udc_stop   = dwc3_gadget_stop,
.udc_set_speed  = dwc3_gadget_set_speed,
.get_config_params  = dwc3_gadget_config_params,
+   .vbus_draw  = dwc3_gadget_vbus_draw,
 };
 
 /* -- 
*/
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 2/3] usb: gadget: composite: Split composite reset and disconnect

2020-12-29 Thread Wesley Cheng
Add a specific composite reset API to differentiate between disconnect and
reset events.  This is needed for adjusting the current draw accordingly
based on the USB battery charging specification.  The device is only allowed
to draw the 500/900 mA (HS/SS) while in the CONFIGURED state, and only 100 mA
in the connected and UNCONFIGURED state.

Reviewed-by: Peter Chen 
Signed-off-by: Wesley Cheng 
---
 drivers/usb/gadget/composite.c | 21 +++--
 include/linux/usb/composite.h  |  2 ++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 05b176c82cc5..a41f7fe4b518 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -2036,7 +2036,7 @@ composite_setup(struct usb_gadget *gadget, const struct 
usb_ctrlrequest *ctrl)
return value;
 }
 
-void composite_disconnect(struct usb_gadget *gadget)
+static void __composite_disconnect(struct usb_gadget *gadget)
 {
struct usb_composite_dev*cdev = get_gadget_data(gadget);
unsigned long   flags;
@@ -2053,6 +2053,23 @@ void composite_disconnect(struct usb_gadget *gadget)
spin_unlock_irqrestore(>lock, flags);
 }
 
+void composite_disconnect(struct usb_gadget *gadget)
+{
+   usb_gadget_vbus_draw(gadget, 0);
+   __composite_disconnect(gadget);
+}
+
+void composite_reset(struct usb_gadget *gadget)
+{
+   /*
+* Section 1.4.13 Standard Downstream Port of the USB battery charging
+* specification v1.2 states that a device connected on a SDP shall only
+* draw at max 100mA while in a connected, but unconfigured state.
+*/
+   usb_gadget_vbus_draw(gadget, 100);
+   __composite_disconnect(gadget);
+}
+
 /*-*/
 
 static ssize_t suspended_show(struct device *dev, struct device_attribute 
*attr,
@@ -2373,7 +2390,7 @@ static const struct usb_gadget_driver 
composite_driver_template = {
.unbind = composite_unbind,
 
.setup  = composite_setup,
-   .reset  = composite_disconnect,
+   .reset  = composite_reset,
.disconnect = composite_disconnect,
 
.suspend= composite_suspend,
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 2040696d75b6..0d8a71471512 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -525,6 +525,8 @@ extern struct usb_string *usb_gstrings_attach(struct 
usb_composite_dev *cdev,
 extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n);
 
 extern void composite_disconnect(struct usb_gadget *gadget);
+extern void composite_reset(struct usb_gadget *gadget);
+
 extern int composite_setup(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl);
 extern void composite_suspend(struct usb_gadget *gadget);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 0/3] Add vbus draw support to DWC3

2020-12-29 Thread Wesley Cheng
Some devices are connected to standard downstream ports (SDP) and draw current
from them.  The current rates are defined in the BC1.2 specification, and
highlights the different charge rates depending on the device state.  The DWC3
gadget does not currently have a mechanism to notify external drivers about
how much current can be drawn.

The current rates are notified by the USB gadget layer, and the DWC3 gadget will
propagate this potentially to external charger drivers.  Also, the USB gadget
needs to be fixed to only allow 100mA current draw when receiving a bus reset
from the host, as the BC1.2 specification states that this is the max current
draw possible when in the connected and unconfigured state.

Wesley Cheng (3):
  usb: dwc3: gadget: Introduce a DWC3 VBUS draw callback
  usb: gadget: composite: Split composite reset and disconnect
  usb: gadget: configfs: Add a specific configFS reset callback

 drivers/usb/dwc3/gadget.c  | 11 +++
 drivers/usb/gadget/composite.c | 21 +++--
 drivers/usb/gadget/configfs.c  | 24 +++-
 include/linux/usb/composite.h  |  2 ++
 4 files changed, 55 insertions(+), 3 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] usb: dwc3: gadget: Restart DWC3 gadget when enabling pullup

2020-12-29 Thread Wesley Cheng
usb_gadget_deactivate/usb_gadget_activate does not execute the UDC start
operation, which may leave EP0 disabled and event IRQs disabled when
re-activating the function. Move the enabling/disabling of USB EP0 and
device event IRQs to be performed in the pullup routine.

Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the
controller")

Tested-by: Michael Tretter 
Reported-by: Michael Tretter 
Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/gadget.c | 14 +++---
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 5d879b7606d5..922c8b76e534 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1988,6 +1988,7 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int 
is_on, int suspend)
 
 static void dwc3_gadget_disable_irq(struct dwc3 *dwc);
 static void __dwc3_gadget_stop(struct dwc3 *dwc);
+static int __dwc3_gadget_start(struct dwc3 *dwc);
 
 static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 {
@@ -2050,6 +2051,8 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
dwc->ev_buf->length;
}
+   } else {
+   __dwc3_gadget_start(dwc);
}
 
ret = dwc3_gadget_run_stop(dwc, is_on, false);
@@ -2224,10 +2227,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
}
 
dwc->gadget_driver  = driver;
-
-   if (pm_runtime_active(dwc->dev))
-   __dwc3_gadget_start(dwc);
-
spin_unlock_irqrestore(>lock, flags);
 
return 0;
@@ -2253,13 +2252,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
unsigned long   flags;
 
spin_lock_irqsave(>lock, flags);
-
-   if (pm_runtime_suspended(dwc->dev))
-   goto out;
-
-   __dwc3_gadget_stop(dwc);
-
-out:
dwc->gadget_driver  = NULL;
spin_unlock_irqrestore(>lock, flags);
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] usb: dwc3: gadget: Restart DWC3 gadget when enabling pullup

2020-11-19 Thread Wesley Cheng
usb_gadget_deactivate/usb_gadget_activate does not execute the UDC start
operation, which may leave EP0 disabled and event IRQs disabled when
re-activating the function. Move the enabling/disabling of USB EP0 and
device event IRQs to be performed in the pullup routine.

Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the
controller")

Reported-by: Michael Tretter 
Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/gadget.c | 14 +++---
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 5d879b7606d5..922c8b76e534 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1988,6 +1988,7 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int 
is_on, int suspend)
 
 static void dwc3_gadget_disable_irq(struct dwc3 *dwc);
 static void __dwc3_gadget_stop(struct dwc3 *dwc);
+static int __dwc3_gadget_start(struct dwc3 *dwc);
 
 static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 {
@@ -2050,6 +2051,8 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
dwc->ev_buf->length;
}
+   } else {
+   __dwc3_gadget_start(dwc);
}
 
ret = dwc3_gadget_run_stop(dwc, is_on, false);
@@ -2224,10 +2227,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
}
 
dwc->gadget_driver  = driver;
-
-   if (pm_runtime_active(dwc->dev))
-   __dwc3_gadget_start(dwc);
-
spin_unlock_irqrestore(>lock, flags);
 
return 0;
@@ -2253,13 +2252,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
unsigned long   flags;
 
spin_lock_irqsave(>lock, flags);
-
-   if (pm_runtime_suspended(dwc->dev))
-   goto out;
-
-   __dwc3_gadget_stop(dwc);
-
-out:
dwc->gadget_driver  = NULL;
spin_unlock_irqrestore(>lock, flags);
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH v4] usb: dwc3: Stop active transfers before halting the controller

2020-11-18 Thread Wesley Cheng



On 11/18/2020 2:14 AM, Michael Tretter wrote:
> Hello,
> 
> On Mon, 28 Sep 2020 17:20:59 -0700, Wesley Cheng wrote:
>> In the DWC3 databook, for a device initiated disconnect or bus reset, the
>> driver is required to send dependxfer commands for any pending transfers.
>> In addition, before the controller can move to the halted state, the SW
>> needs to acknowledge any pending events.  If the controller is not halted
>> properly, there is a chance the controller will continue accessing stale or
>> freed TRBs and buffers.
> 
> This patch causes a regression when using the uvc gadget with the dwc3 gadget
> driver, which causes host to not be able to enumerate the USB device.
> 
> The regression can be reproduced as follows:
> 
> Configure the uvc gadget via configfs, which in the end binds to the driver
> and calls dwc3_gadget_start. Start the uvc-gadget user space application,
> which activates the function and the gadget and calls pullup enable. The UVC
> Device is now detected by a USB host.
> 
> Stop the uvc gadget application, which deactivates the gadget, calls pullup
> disable and, thus, stops the dwc3 gadget.
> 
Hi Michael,

Thanks for the analysis.  I think specifically, the f_uvc will use the
usb_function_deactivate() API to disable the pullup (w/o calling
udc_stop()) and using usb_function_activate() to do the opposite.  These
are triggered when an application opens/closes the V4L2 device. (your
application)

> Restart the uvc gadget application; the gadget is activated and pullup enable
> is called, but the dwc3 gadget is not started.
> 

Seems like the deactivate/activate calls avoid any UDC start stop
operations, and only use the pullup executions to issue a soft disconnect.

> The USB Host shows the following error messages and the USB device cannot be
> enumerated.
> 
>   usb 3-1.1: Device not responding to setup address.
>   usb 3-1.1: Device not responding to setup address.
>   usb 3-1.1: device not accepting address 10, error -71
>   usb 3-1.1: Device not responding to setup address.
>   usb 3-1.1: Device not responding to setup address.
>   usb 3-1.1: device not accepting address 11, error -71
>   usb 3-1-port1: unable to enumerate USB device
> 
>>
>> Signed-off-by: Wesley Cheng 
>> Reviewed-by: Thinh Nguyen 
>>
>> ---
>> Changes in v4:
>>  - Updated comments to reference DWC3 databook sections and added direct
>>quotes.
>>  - Changed the stop active transfer EP loop to use dwc->num_eps.
>>  - Moved to using dwc3_gadget_disable_irq/synchronize_irq instead of
>>enable_irq/disable_irq for ensuring the interrupt handler is not pending.
>>
>> Changes in v3:
>>  - Removed DWC3_EP_ENABLED check from dwc3_gadget_stop_active_transfers()
>>as dwc3_stop_active_transfer() has a check already in place.
>>  - Calling __dwc3_gadget_stop() which ensures that DWC3 interrupt events
>>are cleared, and ep0 eps are cleared for the pullup disabled case.  Not
>>required to call __dwc3_gadget_start() on pullup enable, as the
>>composite driver will execute udc_start() before calling pullup().
> 
> This change seems to be related to the regression. Maybe it is required to
> call __dwc3_gadget_start() on pullup enable, but I am not sure, how this
> should be handled.
> 
> Michael
> 

Definitely, in this situation, we would not call the udc_start()
callback, which will affect the functionality after re-enabling the
device.  I wonder why the deactivate/activate routines don't explicitly
need to start/stop the UDC?

Thanks
Wesley Cheng

>>
>> Changes in v2:
>>  - Moved cleanup code to the pullup() API to differentiate between device
>>disconnect and hibernation.
>>  - Added cleanup code to the bus reset case as well.
>>  - Verified the move to pullup() did not reproduce the problen using the
>>same test sequence.
>>
>> Verified fix by adding a check for ETIMEDOUT during the run stop call.
>> Shell script writing to the configfs UDC file to trigger disconnect and
>> connect.  Batch script to have PC execute data transfers over adb (ie adb
>> push)  After a few iterations, we'd run into a scenario where the
>> controller wasn't halted.  With the following change, no failed halts after
>> many iterations.
>> ---
>>  drivers/usb/dwc3/ep0.c|  2 +-
>>  drivers/usb/dwc3/gadget.c | 66 ++-
>>  2 files changed, 66 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
>> index 59f2e8c31bd1..456aa87e8778 100644
>> --- a/drivers/usb/dwc3/ep0.c
>> +++ b/drivers/usb/dwc3/ep0.c
&

[PATCH 3/3] usb: gadget: configfs: Add a specific configFS reset callback

2020-11-14 Thread Wesley Cheng
In order for configFS based USB gadgets to set the proper charge current
for bus reset scenarios, expose a separate reset callback to set the
current to 100mA based on the USB battery charging specification.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/gadget/configfs.c | 24 +++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 56051bb97349..80ca7ff2fb97 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1481,6 +1481,28 @@ static void configfs_composite_disconnect(struct 
usb_gadget *gadget)
spin_unlock_irqrestore(>spinlock, flags);
 }
 
+static void configfs_composite_reset(struct usb_gadget *gadget)
+{
+   struct usb_composite_dev *cdev;
+   struct gadget_info *gi;
+   unsigned long flags;
+
+   cdev = get_gadget_data(gadget);
+   if (!cdev)
+   return;
+
+   gi = container_of(cdev, struct gadget_info, cdev);
+   spin_lock_irqsave(>spinlock, flags);
+   cdev = get_gadget_data(gadget);
+   if (!cdev || gi->unbind) {
+   spin_unlock_irqrestore(>spinlock, flags);
+   return;
+   }
+
+   composite_reset(gadget);
+   spin_unlock_irqrestore(>spinlock, flags);
+}
+
 static void configfs_composite_suspend(struct usb_gadget *gadget)
 {
struct usb_composite_dev *cdev;
@@ -1530,7 +1552,7 @@ static const struct usb_gadget_driver 
configfs_driver_template = {
.unbind = configfs_composite_unbind,
 
.setup  = configfs_composite_setup,
-   .reset  = configfs_composite_disconnect,
+   .reset  = configfs_composite_reset,
.disconnect = configfs_composite_disconnect,
 
.suspend= configfs_composite_suspend,
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 0/3] Add vbus draw support to DWC3

2020-11-14 Thread Wesley Cheng
Some devices are connected to standard downstream ports (SDP) and draw current
from them.  The current rates are defined in the BC1.2 specification, and
highlights the different charge rates depending on the device state.  The DWC3
gadget does not currently have a mechanism to notify external drivers about
how much current can be drawn.

The current rates are notified by the USB gadget layer, and the DWC3 gadget will
propagate this potentially to external charger drivers.  Also, the USB gadget
needs to be fixed to only allow 100mA current draw when receiving a bus reset
from the host, as the BC1.2 specification states that this is the max current
draw possible when in the connected and unconfigured state.

Wesley Cheng (3):
  usb: dwc3: gadget: Introduce a DWC3 VBUS draw callback
  usb: gadget: composite: Split composite reset and disconnect
  usb: gadget: configfs: Add a specific configFS reset callback

 drivers/usb/dwc3/gadget.c  | 11 +++
 drivers/usb/gadget/composite.c | 21 +++--
 drivers/usb/gadget/configfs.c  | 24 +++-
 include/linux/usb/composite.h  |  2 ++
 4 files changed, 55 insertions(+), 3 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 1/3] usb: dwc3: gadget: Introduce a DWC3 VBUS draw callback

2020-11-14 Thread Wesley Cheng
Some devices support charging while in device mode.  In these situations,
the USB gadget will notify the DWC3 gadget driver to modify the current
based on the enumeration and device state.  The usb_phy_set_power() API
will allow external charger entities to adjust the charge current through
the notifier block.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/gadget.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index c145da1d8ba5..69122f66978e 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2387,6 +2387,16 @@ static void dwc3_gadget_set_speed(struct usb_gadget *g,
spin_unlock_irqrestore(>lock, flags);
 }
 
+static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA)
+{
+   struct dwc3 *dwc = gadget_to_dwc(g);
+
+   if (dwc->usb2_phy)
+   return usb_phy_set_power(dwc->usb2_phy, mA);
+
+   return 0;
+}
+
 static const struct usb_gadget_ops dwc3_gadget_ops = {
.get_frame  = dwc3_gadget_get_frame,
.wakeup = dwc3_gadget_wakeup,
@@ -2396,6 +2406,7 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
.udc_stop   = dwc3_gadget_stop,
.udc_set_speed  = dwc3_gadget_set_speed,
.get_config_params  = dwc3_gadget_config_params,
+   .vbus_draw  = dwc3_gadget_vbus_draw,
 };
 
 /* -- 
*/
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 2/3] usb: gadget: composite: Split composite reset and disconnect

2020-11-14 Thread Wesley Cheng
Add a specific composite reset API to differentiate between disconnect and
reset events.  This is needed for adjusting the current draw accordingly
based on the USB battery charging specification.  The device is only allowed
to draw the 500/900 mA (HS/SS) while in the CONFIGURED state, and only 100 mA
in the connected and UNCONFIGURED state.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/gadget/composite.c | 21 +++--
 include/linux/usb/composite.h  |  2 ++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 05b176c82cc5..a41f7fe4b518 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -2036,7 +2036,7 @@ composite_setup(struct usb_gadget *gadget, const struct 
usb_ctrlrequest *ctrl)
return value;
 }
 
-void composite_disconnect(struct usb_gadget *gadget)
+static void __composite_disconnect(struct usb_gadget *gadget)
 {
struct usb_composite_dev*cdev = get_gadget_data(gadget);
unsigned long   flags;
@@ -2053,6 +2053,23 @@ void composite_disconnect(struct usb_gadget *gadget)
spin_unlock_irqrestore(>lock, flags);
 }
 
+void composite_disconnect(struct usb_gadget *gadget)
+{
+   usb_gadget_vbus_draw(gadget, 0);
+   __composite_disconnect(gadget);
+}
+
+void composite_reset(struct usb_gadget *gadget)
+{
+   /*
+* Section 1.4.13 Standard Downstream Port of the USB battery charging
+* specification v1.2 states that a device connected on a SDP shall only
+* draw at max 100mA while in a connected, but unconfigured state.
+*/
+   usb_gadget_vbus_draw(gadget, 100);
+   __composite_disconnect(gadget);
+}
+
 /*-*/
 
 static ssize_t suspended_show(struct device *dev, struct device_attribute 
*attr,
@@ -2373,7 +2390,7 @@ static const struct usb_gadget_driver 
composite_driver_template = {
.unbind = composite_unbind,
 
.setup  = composite_setup,
-   .reset  = composite_disconnect,
+   .reset  = composite_reset,
.disconnect = composite_disconnect,
 
.suspend= composite_suspend,
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 2040696d75b6..0d8a71471512 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -525,6 +525,8 @@ extern struct usb_string *usb_gstrings_attach(struct 
usb_composite_dev *cdev,
 extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n);
 
 extern void composite_disconnect(struct usb_gadget *gadget);
+extern void composite_reset(struct usb_gadget *gadget);
+
 extern int composite_setup(struct usb_gadget *gadget,
const struct usb_ctrlrequest *ctrl);
 extern void composite_suspend(struct usb_gadget *gadget);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v2 2/2] usb: dwc3: gadget: Preserve UDC max speed setting

2020-11-05 Thread Wesley Cheng
The USB gadget/UDC driver can restrict the DWC3 controller speed using
dwc3_gadget_set_speed().  Store this setting into a variable, in order for
this setting to persist across controller resets due to runtime PM.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/core.h   |   1 +
 drivers/usb/dwc3/gadget.c | 108 --
 2 files changed, 58 insertions(+), 51 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 2f04b3e42bf1..390d3deef0ba 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1119,6 +1119,7 @@ struct dwc3 {
u32 nr_scratch;
u32 u1u2;
u32 maximum_speed;
+   u32 gadget_max_speed;
 
u32 ip;
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index babf977cadc0..c145da1d8ba5 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1941,6 +1941,61 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
}
 }
 
+static void __dwc3_gadget_set_speed(struct dwc3 *dwc)
+{
+   u32 reg;
+
+   reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+   reg &= ~(DWC3_DCFG_SPEED_MASK);
+
+   /*
+* WORKAROUND: DWC3 revision < 2.20a have an issue
+* which would cause metastability state on Run/Stop
+* bit if we try to force the IP to USB2-only mode.
+*
+* Because of that, we cannot configure the IP to any
+* speed other than the SuperSpeed
+*
+* Refers to:
+*
+* STAR#9000525659: Clock Domain Crossing on DCTL in
+* USB 2.0 Mode
+*/
+   if (DWC3_VER_IS_PRIOR(DWC3, 220A) &&
+   !dwc->dis_metastability_quirk) {
+   reg |= DWC3_DCFG_SUPERSPEED;
+   } else {
+   switch (dwc->gadget_max_speed) {
+   case USB_SPEED_LOW:
+   reg |= DWC3_DCFG_LOWSPEED;
+   break;
+   case USB_SPEED_FULL:
+   reg |= DWC3_DCFG_FULLSPEED;
+   break;
+   case USB_SPEED_HIGH:
+   reg |= DWC3_DCFG_HIGHSPEED;
+   break;
+   case USB_SPEED_SUPER:
+   reg |= DWC3_DCFG_SUPERSPEED;
+   break;
+   case USB_SPEED_SUPER_PLUS:
+   if (DWC3_IP_IS(DWC3))
+   reg |= DWC3_DCFG_SUPERSPEED;
+   else
+   reg |= DWC3_DCFG_SUPERSPEED_PLUS;
+   break;
+   default:
+   dev_err(dwc->dev, "invalid speed (%d)\n", 
dwc->gadget_max_speed);
+
+   if (DWC3_IP_IS(DWC3))
+   reg |= DWC3_DCFG_SUPERSPEED;
+   else
+   reg |= DWC3_DCFG_SUPERSPEED_PLUS;
+   }
+   }
+   dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+}
+
 static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
 {
u32 reg;
@@ -1963,6 +2018,7 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int 
is_on, int suspend)
if (dwc->has_hibernation)
reg |= DWC3_DCTL_KEEP_CONNECT;
 
+   __dwc3_gadget_set_speed(dwc);
dwc->pullups_connected = true;
} else {
reg &= ~DWC3_DCTL_RUN_STOP;
@@ -2325,59 +2381,9 @@ static void dwc3_gadget_set_speed(struct usb_gadget *g,
 {
struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long   flags;
-   u32 reg;
 
spin_lock_irqsave(>lock, flags);
-   reg = dwc3_readl(dwc->regs, DWC3_DCFG);
-   reg &= ~(DWC3_DCFG_SPEED_MASK);
-
-   /*
-* WORKAROUND: DWC3 revision < 2.20a have an issue
-* which would cause metastability state on Run/Stop
-* bit if we try to force the IP to USB2-only mode.
-*
-* Because of that, we cannot configure the IP to any
-* speed other than the SuperSpeed
-*
-* Refers to:
-*
-* STAR#9000525659: Clock Domain Crossing on DCTL in
-* USB 2.0 Mode
-*/
-   if (DWC3_VER_IS_PRIOR(DWC3, 220A) &&
-   !dwc->dis_metastability_quirk) {
-   reg |= DWC3_DCFG_SUPERSPEED;
-   } else {
-   switch (speed) {
-   case USB_SPEED_LOW:
-   reg |= DWC3_DCFG_LOWSPEED;
-   break;
-   case USB_SPEED_FULL:
-   reg |= DWC3_DCFG_FULLSPEED;
-   break;
-   case USB_SPEED_HIGH:
-   reg |= DWC3_DCFG_HIGHSPEED;
-   break;
-   

[PATCH v2 1/2] usb: dwc3: gadget: Allow runtime suspend if UDC unbinded

2020-11-05 Thread Wesley Cheng
The DWC3 runtime suspend routine checks for the USB connected parameter to
determine if the controller can enter into a low power state.  The
connected state is only set to false after receiving a disconnect event.
However, in the case of a device initiated disconnect (i.e. UDC unbind),
the controller is halted and a disconnect event is never generated.  Set
the connected flag to false if issuing a device initiated disconnect to
allow the controller to be suspended.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/gadget.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 5d879b7606d5..babf977cadc0 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2012,6 +2012,17 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
}
}
 
+   /*
+* Check the return value for successful resume, or error.  For a
+* successful resume, the DWC3 runtime PM resume routine will handle
+* the run stop sequence, so avoid duplicate operations here.
+*/
+   ret = pm_runtime_get_sync(dwc->dev);
+   if (!ret || ret < 0) {
+   pm_runtime_put(dwc->dev);
+   return 0;
+   }
+
/*
 * Synchronize any pending event handling before executing the 
controller
 * halt routine.
@@ -2050,10 +2061,12 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
dwc->ev_buf->length;
}
+   dwc->connected = false;
}
 
ret = dwc3_gadget_run_stop(dwc, is_on, false);
spin_unlock_irqrestore(>lock, flags);
+   pm_runtime_put(dwc->dev);
 
return ret;
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v2 0/2] Allow DWC3 runtime suspend if UDC is unbinded

2020-11-05 Thread Wesley Cheng
Changes in v2:
 - Modified logic for executing the runtime PM resume.  Using a sychronous get
   call to avoid race conditions.

During the following scenario, the DWC3 runtime suspend routine is blocked as
the connected flag is still true:

1.  Enumerate device w/ host.
2.  Gadget is unbinded
- echo "" > /sys/kernel/config/usb_gadget/g1/UDC
3.  Disconnect the USB cable (VBUS low)
4.  No dwc3_gadget_disconnect_interrupt() seen (since controller is
   halted from step#1)
5.  Runtime PM autosuspend fails due to "dwc->connected" being true
(cleared in dwc3_gadget_disconnect_interrupt())
6.  Gadget binded
- echo udc_name > /sys/kernel/config/usb_gadget/g1/UDC
7.  No runtime suspend until cable is plugged in and out

Technically, for device initiated disconnects, there is no active session/link
with the host, so the DWC3 controller should be allowed to go into a low power
state.  Also, we need to now consider when re-binding the UDC,
dwc3_gadget_set_speed() is executed before dwc3_gadget_pullup(), so if the DWC3
controller is suspended/disabled, while accessing the DCFG, that could result in
bus timeouts, etc...  Change the dwc3_gadget_set_speed() to save the speed
being requested, and program it during dwc3_gadget_run_stop(), which is executed
during PM runtime resume.  If not, previous setting will be overridden as we
execute a DWC3 controller reset during PM runtime resume. 

Wesley Cheng (2):
  usb: dwc3: gadget: Allow runtime suspend if UDC unbinded
  usb: dwc3: gadget: Preserve UDC max speed setting

 drivers/usb/dwc3/core.h   |   1 +
 drivers/usb/dwc3/gadget.c | 121 ++
 2 files changed, 71 insertions(+), 51 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH 1/2] usb: dwc3: gadget: Allow runtime suspend if UDC unbinded

2020-11-03 Thread Wesley Cheng



On 11/3/2020 12:07 PM, Alan Stern wrote:
> On Tue, Nov 03, 2020 at 11:02:25AM -0800, Wesley Cheng wrote:
>>
>>
>> On 10/28/2020 6:07 PM, Alan Stern wrote:
>>>> --- a/drivers/usb/dwc3/gadget.c
>>>> +++ b/drivers/usb/dwc3/gadget.c
>>>> @@ -1995,6 +1995,11 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, 
>>>> int is_on)
>>>>unsigned long   flags;
>>>>int ret;
>>>>  
>>>> +  if (pm_runtime_suspended(dwc->dev)) {
>>>> +  pm_request_resume(dwc->dev);
>>>> +  return 0;
>>>> +  }
>>>
>>> Isn't this racy?  What happens if the controller was active but a 
>>> runtime suspend occurs right here?
>>>
>>> Alan Stern
>>>
>>
>> Hi Alan,
>>
>> Ah, yes you're right.  I was hoping that the PM runtime layer would be
>> utilizing the spinlock when reading out the runtime status, but even
>> then, we wouldn't be able to catch intermediate states with this API
>> (i.e. RPM_RESUMING or RPM_SUSPENDING)
>>
>> Tried a few different approaches, and came up with something like the
>> following:
>>
>> static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
>> {
>> ...
>>  ret = pm_runtime_get_sync(dwc->dev);
>>  if (!ret) {
>>  pm_runtime_put(dwc->dev);
>>  return 0;
>>  }
>>  ...
>>  pm_runtime_put(dwc->dev);
>>
>>  return 0;
>> }
>>
>> I think this should be good to address your concern.  The only way we
>> would be able to ensure that the runtime PM state doesn't enter
>> idle/suspend is if we increment the usage count for the duration we're
>> accessing the DWC3 registers.  With the synchronous PM runtime resume
>> call, we can also ensure that no pending runtime suspends are executing
>> in parallel while running this code.
> 
> That's correct.
> 
>> The check for the zero return value would be for avoiding running the
>> DWC3 run stop sequence for the case where we executed the runtime PM
>> resume, as the DWC3 runtime PM resume routine will set the run stop bit
>> in there.
> 
> If you need to add an explanation of this subtle point in your email 
> message, then you should add a similar explanation as a comment in the 
> code.  And don't forget to check for ret < 0 (i.e., a resume error).
> 

Hi Alan,

Got it, will do.  Yes, I'll include the error conditions as well in the
actual change.  Thanks again!

Thanks

Regards,
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH 1/2] usb: dwc3: gadget: Allow runtime suspend if UDC unbinded

2020-11-03 Thread Wesley Cheng



On 10/28/2020 6:07 PM, Alan Stern wrote:
> On Wed, Oct 28, 2020 at 04:43:10PM -0700, Wesley Cheng wrote:
>> The DWC3 runtime suspend routine checks for the USB connected parameter to
>> determine if the controller can enter into a low power state.  The
>> connected state is only set to false after receiving a disconnect event.
>> However, in the case of a device initiated disconnect (i.e. UDC unbind),
>> the controller is halted and a disconnect event is never generated.  Set
>> the connected flag to false if issuing a device initiated disconnect to
>> allow the controller to be suspended.
>>
>> Signed-off-by: Wesley Cheng 
>> ---
>>  drivers/usb/dwc3/gadget.c | 6 ++
>>  1 file changed, 6 insertions(+)
>>
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index 5d879b7606d5..6364429b2122 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -1995,6 +1995,11 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, 
>> int is_on)
>>  unsigned long   flags;
>>  int ret;
>>  
>> +if (pm_runtime_suspended(dwc->dev)) {
>> +pm_request_resume(dwc->dev);
>> +return 0;
>> +}
> 
> Isn't this racy?  What happens if the controller was active but a 
> runtime suspend occurs right here?
> 
> Alan Stern
> 

Hi Alan,

Ah, yes you're right.  I was hoping that the PM runtime layer would be
utilizing the spinlock when reading out the runtime status, but even
then, we wouldn't be able to catch intermediate states with this API
(i.e. RPM_RESUMING or RPM_SUSPENDING)

Tried a few different approaches, and came up with something like the
following:

static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
{
...
ret = pm_runtime_get_sync(dwc->dev);
if (!ret) {
pm_runtime_put(dwc->dev);
return 0;
}
...
pm_runtime_put(dwc->dev);

return 0;
}

I think this should be good to address your concern.  The only way we
would be able to ensure that the runtime PM state doesn't enter
idle/suspend is if we increment the usage count for the duration we're
accessing the DWC3 registers.  With the synchronous PM runtime resume
call, we can also ensure that no pending runtime suspends are executing
in parallel while running this code.

The check for the zero return value would be for avoiding running the
DWC3 run stop sequence for the case where we executed the runtime PM
resume, as the DWC3 runtime PM resume routine will set the run stop bit
in there.

Thanks

Regards,
Wesley Cheng
>> +
>>  is_on = !!is_on;
>>  
>>  /*
>> @@ -2050,6 +2055,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, 
>> int is_on)
>>  dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
>>  dwc->ev_buf->length;
>>  }
>> +dwc->connected = false;
>>  }
>>  
>>  ret = dwc3_gadget_run_stop(dwc, is_on, false);
>> -- 
>> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
>> a Linux Foundation Collaborative Project

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH 2/2] usb: dwc3: gadget: Preserve UDC max speed setting

2020-10-28 Thread Wesley Cheng



On 10/28/2020 5:43 PM, Thinh Nguyen wrote:
> Hi,
> 
> Wesley Cheng wrote:
>> The USB gadget/UDC driver can restrict the DWC3 controller speed using
>> dwc3_gadget_set_speed().  Store this setting into a variable, in order for
>> this setting to persist across controller resets due to runtime PM.
> 
> Why do we need to do this? DCFG should persist unless we overwrite it.
> The current PM shouldn't update the current speed setting.
> 
> BR,
> Thinh
> 

Hi Thinh,

During runtime PM suspend, the dwc3_suspend_common() will call
dwc3_core_exit().  On some platforms they register the DWC3 reset
control to the DWC3 core driver (otherwise could be handled in the DWC3
glue drivers), which will be asserted here:

static void dwc3_core_exit(struct dwc3 *dwc)
{
...
reset_control_assert(dwc->reset);

>From the SNPS databook (Table 2-2 Resets for Registers) it mentions that
assertion of the reset signal will reset the DCFG register.

In addition to the above, with the change to allow runtime PM suspend
during UDC unbind, we need a way to avoid writing to the DCFG during the
UDC bind path. (if we entered suspend before re-binding the UDC)  If we
add an early exit based on the PM state (in
dwc3_gadget_set_udc_speed()), then we basically ignore the max speed
request from the UDC/gadget layer.

Since it looks like the DWC3 gadget driver doesn't like using
synchronous PM runtime resumes, by going this route, we can allow the
async runtime resume handler to do everything, such as writing the speed
config and re-enabling the controller.

Thanks

Regards,
Wesley Cheng
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH 1/2] usb: dwc3: gadget: Allow runtime suspend if UDC unbinded

2020-10-28 Thread Wesley Cheng
The DWC3 runtime suspend routine checks for the USB connected parameter to
determine if the controller can enter into a low power state.  The
connected state is only set to false after receiving a disconnect event.
However, in the case of a device initiated disconnect (i.e. UDC unbind),
the controller is halted and a disconnect event is never generated.  Set
the connected flag to false if issuing a device initiated disconnect to
allow the controller to be suspended.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/gadget.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 5d879b7606d5..6364429b2122 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1995,6 +1995,11 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
unsigned long   flags;
int ret;
 
+   if (pm_runtime_suspended(dwc->dev)) {
+   pm_request_resume(dwc->dev);
+   return 0;
+   }
+
is_on = !!is_on;
 
/*
@@ -2050,6 +2055,7 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
dwc->ev_buf->length;
}
+   dwc->connected = false;
}
 
ret = dwc3_gadget_run_stop(dwc, is_on, false);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 0/2] Allow DWC3 runtime suspend if UDC is unbinded

2020-10-28 Thread Wesley Cheng
During the following scenario, the DWC3 runtime suspend routine is blocked as
the connected flag is still true:

1.  Enumerate device w/ host.
2.  Gadget is unbinded
- echo "" > /sys/kernel/config/usb_gadget/g1/UDC
3.  Disconnect the USB cable (VBUS low)
4.  No dwc3_gadget_disconnect_interrupt() seen (since controller is
   halted from step#1)
5.  Runtime PM autosuspend fails due to "dwc->connected" being true
(cleared in dwc3_gadget_disconnect_interrupt())
6.  Gadget binded
- echo udc_name > /sys/kernel/config/usb_gadget/g1/UDC
7.  No runtime suspend until cable is plugged in and out

Technically, for device initiated disconnects, there is no active session/link
with the host, so the DWC3 controller should be allowed to go into a low power
state.  Also, we need to now consider when re-binding the UDC,
dwc3_gadget_set_speed() is executed before dwc3_gadget_pullup(), so if the DWC3
controller is suspended/disabled, while accessing the DCFG, that could result in
bus timeouts, etc...  Change the dwc3_gadget_set_speed() to save the speed
being requested, and program it during dwc3_gadget_run_stop(), which is executed
during PM runtime resume.  If not, previous setting will be overridden as we
execute a DWC3 controller reset during PM runtime resume. 

Wesley Cheng (2):
  usb: dwc3: gadget: Allow runtime suspend if UDC unbinded
  usb: dwc3: gadget: Preserve UDC max speed setting

 drivers/usb/dwc3/core.h   |   1 +
 drivers/usb/dwc3/gadget.c | 114 +-
 2 files changed, 64 insertions(+), 51 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH 2/2] usb: dwc3: gadget: Preserve UDC max speed setting

2020-10-28 Thread Wesley Cheng
The USB gadget/UDC driver can restrict the DWC3 controller speed using
dwc3_gadget_set_speed().  Store this setting into a variable, in order for
this setting to persist across controller resets due to runtime PM.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/core.h   |   1 +
 drivers/usb/dwc3/gadget.c | 108 --
 2 files changed, 58 insertions(+), 51 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 2f04b3e42bf1..390d3deef0ba 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -1119,6 +1119,7 @@ struct dwc3 {
u32 nr_scratch;
u32 u1u2;
u32 maximum_speed;
+   u32 gadget_max_speed;
 
u32 ip;
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 6364429b2122..1a93b92a5e6f 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1941,6 +1941,61 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
}
 }
 
+static void __dwc3_gadget_set_speed(struct dwc3 *dwc)
+{
+   u32 reg;
+
+   reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+   reg &= ~(DWC3_DCFG_SPEED_MASK);
+
+   /*
+* WORKAROUND: DWC3 revision < 2.20a have an issue
+* which would cause metastability state on Run/Stop
+* bit if we try to force the IP to USB2-only mode.
+*
+* Because of that, we cannot configure the IP to any
+* speed other than the SuperSpeed
+*
+* Refers to:
+*
+* STAR#9000525659: Clock Domain Crossing on DCTL in
+* USB 2.0 Mode
+*/
+   if (DWC3_VER_IS_PRIOR(DWC3, 220A) &&
+   !dwc->dis_metastability_quirk) {
+   reg |= DWC3_DCFG_SUPERSPEED;
+   } else {
+   switch (dwc->gadget_max_speed) {
+   case USB_SPEED_LOW:
+   reg |= DWC3_DCFG_LOWSPEED;
+   break;
+   case USB_SPEED_FULL:
+   reg |= DWC3_DCFG_FULLSPEED;
+   break;
+   case USB_SPEED_HIGH:
+   reg |= DWC3_DCFG_HIGHSPEED;
+   break;
+   case USB_SPEED_SUPER:
+   reg |= DWC3_DCFG_SUPERSPEED;
+   break;
+   case USB_SPEED_SUPER_PLUS:
+   if (DWC3_IP_IS(DWC3))
+   reg |= DWC3_DCFG_SUPERSPEED;
+   else
+   reg |= DWC3_DCFG_SUPERSPEED_PLUS;
+   break;
+   default:
+   dev_err(dwc->dev, "invalid speed (%d)\n", 
dwc->gadget_max_speed);
+
+   if (DWC3_IP_IS(DWC3))
+   reg |= DWC3_DCFG_SUPERSPEED;
+   else
+   reg |= DWC3_DCFG_SUPERSPEED_PLUS;
+   }
+   }
+   dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+}
+
 static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
 {
u32 reg;
@@ -1963,6 +2018,7 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int 
is_on, int suspend)
if (dwc->has_hibernation)
reg |= DWC3_DCTL_KEEP_CONNECT;
 
+   __dwc3_gadget_set_speed(dwc);
dwc->pullups_connected = true;
} else {
reg &= ~DWC3_DCTL_RUN_STOP;
@@ -2318,59 +2374,9 @@ static void dwc3_gadget_set_speed(struct usb_gadget *g,
 {
struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long   flags;
-   u32 reg;
 
spin_lock_irqsave(>lock, flags);
-   reg = dwc3_readl(dwc->regs, DWC3_DCFG);
-   reg &= ~(DWC3_DCFG_SPEED_MASK);
-
-   /*
-* WORKAROUND: DWC3 revision < 2.20a have an issue
-* which would cause metastability state on Run/Stop
-* bit if we try to force the IP to USB2-only mode.
-*
-* Because of that, we cannot configure the IP to any
-* speed other than the SuperSpeed
-*
-* Refers to:
-*
-* STAR#9000525659: Clock Domain Crossing on DCTL in
-* USB 2.0 Mode
-*/
-   if (DWC3_VER_IS_PRIOR(DWC3, 220A) &&
-   !dwc->dis_metastability_quirk) {
-   reg |= DWC3_DCFG_SUPERSPEED;
-   } else {
-   switch (speed) {
-   case USB_SPEED_LOW:
-   reg |= DWC3_DCFG_LOWSPEED;
-   break;
-   case USB_SPEED_FULL:
-   reg |= DWC3_DCFG_FULLSPEED;
-   break;
-   case USB_SPEED_HIGH:
-   reg |= DWC3_DCFG_HIGHSPEED;
-   break;
-   

Re: [PATCH v10 4/4] arm64: boot: dts: qcom: pm8150b: Add DTS node for PMIC VBUS booster

2020-10-14 Thread Wesley Cheng



On 10/13/2020 8:03 AM, Rob Herring wrote:
> On Thu, Oct 08, 2020 at 04:59:34PM -0700, Wesley Cheng wrote:
>> Add the required DTS node for the USB VBUS output regulator, which is
>> available on PM8150B.  This will provide the VBUS source to connected
>> peripherals.
>>
>> Signed-off-by: Wesley Cheng 
>> ---
>>  arch/arm64/boot/dts/qcom/pm8150b.dtsi   | 6 ++
>>  arch/arm64/boot/dts/qcom/sm8150-mtp.dts | 4 
>>  2 files changed, 10 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi 
>> b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
>> index 2bf385f5a55a..49ea597cc0c5 100644
>> --- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi
>> +++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
>> @@ -53,6 +53,12 @@ power-on@800 {
>>  status = "disabled";
>>  };
>>  
>> +pm8150b_vbus: regulator@1100 {
>> +compatible = "qcom,pm8150b-vbus-reg";
>> +status = "disabled";
>> +reg = <0x1100>;
>> +};
>> +
>>  pm8150b_typec: usb-typec@1500 {
>>  compatible = "qcom,pm8150b-usb-typec";
>>  status = "disabled";
>> diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts 
>> b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
>> index 6c6325c3af59..ba3b5b802954 100644
>> --- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
>> +++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
>> @@ -409,6 +409,10 @@ _mem_phy {
>>  vdda-pll-max-microamp = <19000>;
>>  };
>>  
>> +_vbus {
>> +status = "okay";
>> +};
> 
> Why aren't you enabling the TypeC node and providing a complete example?
> 

Hi Rob,

I have another patch series which enables the type C node and adds QMP
PHY driver changes for setting the SS lane select MUX.

https://patchwork.kernel.org/project/linux-arm-msm/list/?series=361971

Just wanted to work on getting a PMIC based type C driver out there,
which can be utilized in designs where the QMP PHY lane select mux is
not going to be used. (ie using a FUSB340 as a lane select mux instead
of the QMP PHY mux)

Thanks

Regards,
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v10 2/4] dt-bindings: usb: Add Qualcomm PMIC type C controller dt-binding

2020-10-14 Thread Wesley Cheng



On 10/13/2020 8:00 AM, Rob Herring wrote:
> On Thu, Oct 08, 2020 at 04:59:32PM -0700, Wesley Cheng wrote:
>> Introduce the dt-binding for enabling USB type C orientation and role
>> detection using the PM8150B.  The driver will be responsible for receiving
>> the interrupt at a state change on the CC lines, reading the
>> orientation/role, and communicating this information to the remote
>> clients, which can include a role switch node and a type C switch.
>>
>> Signed-off-by: Wesley Cheng 
>> ---
>>  .../bindings/usb/qcom,pmic-typec.yaml | 115 ++
>>  1 file changed, 115 insertions(+)
>>  create mode 100644 
>> Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml 
>> b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
>> new file mode 100644
>> index ..40e0a296f922
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
>> @@ -0,0 +1,115 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: "http://devicetree.org/schemas/usb/qcom,pmic-typec.yaml#;
>> +$schema: "http://devicetree.org/meta-schemas/core.yaml#;
>> +
>> +title: Qualcomm PMIC based USB type C Detection Driver
>> +
>> +maintainers:
>> +  - Wesley Cheng 
>> +
>> +description: |
>> +  Qualcomm PMIC Type C Detect
>> +
>> +properties:
>> +  compatible:
>> +enum:
>> +  - qcom,pm8150b-usb-typec
>> +
>> +  reg:
>> +maxItems: 1
>> +description: Type C base address
>> +
>> +  interrupts:
>> +maxItems: 1
>> +description: CC change interrupt from PMIC
>> +
>> +  port:
>> +description: Remote endpoint connection to the DRD switch
>> +type: object
> 
> I don't understand what this is supposed to be. You'll have to expand 
> the example or provide a block diagram of what the connections/routing 
> looks like.
> 

Hi Rob,

The "port" node is going to be the connection to the usb role switch
device, which will be listening for the USB type C port change events.
(i.e handling USB role events, etc...)  In previous patches, this was
part of the connector node, which may not have made much sense, as the
connector model is used to describe the HW connections within a design.
 The role switch endpoint is more of a SW interaction between drivers,
thus the motivation to remove it from the connector node.

I think the current usb-connector design is OK as it is, since the only
component essentially involved in the SS path is the SS MUX that we've
been discussing, and this is true among designs that are supporting SSUSB.


Thanks

Regards,
Wesley Cheng

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


[PATCH v2 0/4] Enable USB type C support on SM8150

2020-10-09 Thread Wesley Cheng
Changes in v2:
 - Added patch to fix a typo in dwc3_qcom_vbus_override_enable()
 - Modified dwc3_qcom_find_usb_connector_match() to search the child nodes for
   the connector device as well
 - Moved out the DRD switch remote endpoint from the connector node in the
   pm8150b_typec device

This series adds support for setting of the orientation multiplexor within the
QMP PHY based on the detection output from the PM8150B.  It will also introduce
a role switch in DWC3 QCOM, which is used so that the DWC3 QCOM glue can receive
role switch change events, and set the vbus override accordingly.  This event
will then be propagated down to the DWC3 core driver, by the DWC3 QCOM getting a
handle to the DWC3 core's role switch.

Wesley Cheng (4):
  arm64: boot: dts: qcom: sm8150: Add nodes for PMIC based typec
detection
  phy: qcom-qmp: Register as a typec switch for orientation detection
  usb: dwc3: dwc3-qcom: Find USB connector and register role switch
  usb: dwc3: dwc3-qcom: Fix typo in the dwc3 vbus override API

 arch/arm64/boot/dts/qcom/sm8150-mtp.dts |  40 +++-
 drivers/phy/qualcomm/Kconfig|  11 ++
 drivers/phy/qualcomm/phy-qcom-qmp.c |  70 -
 drivers/usb/dwc3/dwc3-qcom.c| 128 ++--
 4 files changed, 239 insertions(+), 10 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v2 4/4] usb: dwc3: dwc3-qcom: Fix typo in the dwc3 vbus override API

2020-10-09 Thread Wesley Cheng
There was an extra character in the dwc3_qcom_vbus_override_enable()
function.  Removed the extra character.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/dwc3-qcom.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index 340760ef0e01..236afbfe01d9 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -107,7 +107,7 @@ static inline void dwc3_qcom_clrbits(void __iomem *base, 
u32 offset, u32 val)
readl(base + offset);
 }
 
-static void dwc3_qcom_vbus_overrride_enable(struct dwc3_qcom *qcom, bool 
enable)
+static void dwc3_qcom_vbus_override_enable(struct dwc3_qcom *qcom, bool enable)
 {
if (enable) {
dwc3_qcom_setbits(qcom->qscratch_base, QSCRATCH_SS_PHY_CTRL,
@@ -128,7 +128,7 @@ static int dwc3_qcom_vbus_notifier(struct notifier_block 
*nb,
struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, vbus_nb);
 
/* enable vbus override for device mode */
-   dwc3_qcom_vbus_overrride_enable(qcom, event);
+   dwc3_qcom_vbus_override_enable(qcom, event);
qcom->mode = event ? USB_DR_MODE_PERIPHERAL : USB_DR_MODE_HOST;
 
return NOTIFY_DONE;
@@ -140,7 +140,7 @@ static int dwc3_qcom_host_notifier(struct notifier_block 
*nb,
struct dwc3_qcom *qcom = container_of(nb, struct dwc3_qcom, host_nb);
 
/* disable vbus override in host mode */
-   dwc3_qcom_vbus_overrride_enable(qcom, !event);
+   dwc3_qcom_vbus_override_enable(qcom, !event);
qcom->mode = event ? USB_DR_MODE_HOST : USB_DR_MODE_PERIPHERAL;
 
return NOTIFY_DONE;
@@ -223,7 +223,7 @@ static int dwc3_qcom_usb_role_switch_set(struct 
usb_role_switch *sw,
 
qcom->mode = (role == USB_ROLE_HOST) ? USB_DR_MODE_HOST :
   USB_DR_MODE_PERIPHERAL;
-   dwc3_qcom_vbus_overrride_enable(qcom, enable);
+   dwc3_qcom_vbus_override_enable(qcom, enable);
return 0;
 }
 
@@ -750,7 +750,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev)
 
/* enable vbus override for device mode */
if (qcom->mode == USB_DR_MODE_PERIPHERAL)
-   dwc3_qcom_vbus_overrride_enable(qcom, true);
+   dwc3_qcom_vbus_override_enable(qcom, true);
 
if (dwc3_qcom_find_usb_connector(pdev)) {
ret = dwc3_qcom_setup_role_switch(qcom);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v2 2/4] phy: qcom-qmp: Register as a typec switch for orientation detection

2020-10-09 Thread Wesley Cheng
The lane select switch for USB typec orientation is within the USB QMP PHY.
the current device.  It could be connected through an endpoint, to an
independent device handling the typec detection, ie the QCOM SPMI typec
driver.

Signed-off-by: Wesley Cheng 
---
 drivers/phy/qualcomm/Kconfig| 11 +
 drivers/phy/qualcomm/phy-qcom-qmp.c | 70 +++--
 2 files changed, 78 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
index 928db510b86c..43f46a1b3db1 100644
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -48,6 +48,17 @@ config PHY_QCOM_QMP
  Enable this to support the QMP PHY transceiver that is used
  with controllers such as PCIe, UFS, and USB on Qualcomm chips.
 
+if PHY_QCOM_QMP
+config PHY_QCOM_QMP_TYPEC
+   bool "Enable QCOM QMP PHY Type C Switch Support"
+   depends on PHY_QCOM_QMP=y && TYPEC=y || PHY_QCOM_QMP=m && TYPEC
+   help
+ Register a type C switch from the QMP PHY driver for type C
+ orientation support.  This has dependencies with if the type C kernel
+ configuration is enabled or not.  This support will not be present if
+ USB type C is disabled.
+endif
+
 config PHY_QCOM_QUSB2
tristate "Qualcomm QUSB2 PHY Driver"
depends on OF && (ARCH_QCOM || COMPILE_TEST)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c 
b/drivers/phy/qualcomm/phy-qcom-qmp.c
index 562053ce9455..29d8a3570328 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -66,6 +67,9 @@
 /* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
 #define CLAMP_EN   BIT(0) /* enables i/o clamp_n */
 
+#define SW_PORTSELECT_VAL  BIT(0)
+#define SW_PORTSELECT_MUX  BIT(1)
+
 #define PHY_INIT_COMPLETE_TIMEOUT  1
 #define POWER_DOWN_DELAY_US_MIN10
 #define POWER_DOWN_DELAY_US_MAX11
@@ -1845,6 +1849,8 @@ struct qmp_phy {
  * @phy_initialized: indicate if PHY has been initialized
  * @mode: current PHY mode
  * @ufs_reset: optional UFS PHY reset handle
+ * @sw: typec switch for receiving orientation changes
+ * @orientation: carries current CC orientation
  */
 struct qcom_qmp {
struct device *dev;
@@ -1864,6 +1870,8 @@ struct qcom_qmp {
enum phy_mode mode;
 
struct reset_control *ufs_reset;
+   struct typec_switch *sw;
+   enum typec_orientation orientation;
 };
 
 static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
@@ -2485,6 +2493,7 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy)
void __iomem *pcs = qphy->pcs;
void __iomem *dp_com = qmp->dp_com;
int ret, i;
+   unsigned int val;
 
mutex_lock(>phy_mutex);
if (qmp->init_count++) {
@@ -2534,6 +2543,13 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy)
qphy_setbits(dp_com, QPHY_V3_DP_COM_PHY_MODE_CTRL,
 USB3_MODE | DP_MODE);
 
+   if (cfg->is_dual_lane_phy) {
+   val = SW_PORTSELECT_MUX;
+   if (qmp->orientation == TYPEC_ORIENTATION_REVERSE)
+   val |= SW_PORTSELECT_VAL;
+   qphy_setbits(dp_com, QPHY_V3_DP_COM_TYPEC_CTRL, val);
+   }
+
/* bring both QMP USB and QMP DP PHYs PCS block out of reset */
qphy_clrbits(dp_com, QPHY_V3_DP_COM_RESET_OVRD_CTRL,
 SW_DPPHY_RESET_MUX | SW_DPPHY_RESET |
@@ -2559,7 +2575,7 @@ static int qcom_qmp_phy_com_init(struct qmp_phy *qphy)
 
if (cfg->has_phy_com_ctrl) {
void __iomem *status;
-   unsigned int mask, val;
+   unsigned int mask;
 
qphy_clrbits(serdes, cfg->regs[QPHY_COM_SW_RESET], SW_RESET);
qphy_setbits(serdes, cfg->regs[QPHY_COM_START_CONTROL],
@@ -3242,6 +3258,47 @@ static const struct dev_pm_ops qcom_qmp_phy_pm_ops = {
   qcom_qmp_phy_runtime_resume, NULL)
 };
 
+#if IS_ENABLED(CONFIG_PHY_QCOM_QMP_TYPEC)
+static int qcom_qmp_phy_typec_switch_set(struct typec_switch *sw,
+enum typec_orientation orientation)
+{
+   struct qcom_qmp *qmp = typec_switch_get_drvdata(sw);
+   struct qmp_phy *qphy = qmp->phys[0];
+
+   qmp->orientation = orientation;
+   if (qmp->phy_initialized) {
+   qcom_qmp_phy_disable(qphy->phy);
+   qcom_qmp_phy_enable(qphy->phy);
+   }
+
+   return 0;
+}
+
+static int qcom_qmp_phy_typec_switch_register(struct qcom_qmp *qmp)
+{
+   struct typec_switch_desc sw_desc;
+   struct device *dev = qmp-&

[PATCH v2 1/4] arm64: boot: dts: qcom: sm8150: Add nodes for PMIC based typec detection

2020-10-09 Thread Wesley Cheng
Introduce required child nodes to enable the PMIC based USB type C driver.
This consits of connector and endpoint nodes to drivers, which manage the
type C mux and the USB role switch.

Signed-off-by: Wesley Cheng 
---
 arch/arm64/boot/dts/qcom/sm8150-mtp.dts | 40 -
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts 
b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
index ba3b5b802954..06ad01dde080 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
@@ -413,6 +413,31 @@ _vbus {
status = "okay";
 };
 
+_typec {
+   status = "okay";
+   connector {
+   compatible = "usb-c-connector";
+   power-role = "dual";
+   data-role = "dual";
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   port@1 {
+   reg = <1>;
+   usb3_data_ss: endpoint@0 {
+   remote-endpoint = <_ss_mux>;
+   };
+   };
+   };
+   };
+
+   port {
+   usb3_role: endpoint {
+   remote-endpoint = <_drd_switch>;
+   };
+   };
+};
+
 _1_hsphy {
status = "okay";
vdda-pll-supply = <_usb_hs_core>;
@@ -424,12 +449,25 @@ _1_qmpphy {
status = "okay";
vdda-phy-supply = <_l3c_1p2>;
vdda-pll-supply = <_usb_ss_dp_core_1>;
+   orientation-switch;
+   port {
+   qmp_ss_mux: endpoint@0 {
+   remote-endpoint = <_data_ss>;
+   };
+   };
 };
 
 _1 {
status = "okay";
+   usb-role-switch;
+   port {
+   dwc3_drd_switch: endpoint@0 {
+   remote-endpoint = <_role>;
+   };
+   };
 };
 
 _1_dwc3 {
-   dr_mode = "peripheral";
+   dr_mode = "otg";
+   usb-role-switch;
 };
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v2 3/4] usb: dwc3: dwc3-qcom: Find USB connector and register role switch

2020-10-09 Thread Wesley Cheng
If registering a USB typeC connector, the connector node may not be a child
of the DWC3 QCOM device.  Utilize devcon graph search to lookup if any
remote endpoints contain the connector.  If a connector is present, the
DWC3 QCOM will register a USB role switch to receive role change events, as
well as attain a reference to the DWC3 core role switch to pass the event
down.

Signed-off-by: Wesley Cheng 
---
 drivers/usb/dwc3/dwc3-qcom.c | 120 ++-
 1 file changed, 118 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index e1e78e9824b1..340760ef0e01 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -19,6 +19,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "core.h"
 
@@ -71,6 +73,9 @@ struct dwc3_qcom {
struct notifier_block   vbus_nb;
struct notifier_block   host_nb;
 
+   struct usb_role_switch *role_sw;
+   struct usb_role_switch *dwc3_drd_sw;
+
const struct dwc3_acpi_pdata *acpi_pdata;
 
enum usb_dr_modemode;
@@ -190,6 +195,73 @@ static int dwc3_qcom_register_extcon(struct dwc3_qcom 
*qcom)
return 0;
 }
 
+static int dwc3_qcom_usb_role_switch_set(struct usb_role_switch *sw,
+enum usb_role role)
+{
+   struct dwc3_qcom *qcom = usb_role_switch_get_drvdata(sw);
+   struct fwnode_handle *child;
+   bool enable = false;
+
+   if (!qcom->dwc3_drd_sw) {
+   child = device_get_next_child_node(qcom->dev, NULL);
+   if (child) {
+   qcom->dwc3_drd_sw = 
usb_role_switch_find_by_fwnode(child);
+   fwnode_handle_put(child);
+   if (IS_ERR(qcom->dwc3_drd_sw)) {
+   qcom->dwc3_drd_sw = NULL;
+   return 0;
+   }
+   }
+   }
+
+   usb_role_switch_set_role(qcom->dwc3_drd_sw, role);
+
+   if (role == USB_ROLE_DEVICE)
+   enable = true;
+   else
+   enable = false;
+
+   qcom->mode = (role == USB_ROLE_HOST) ? USB_DR_MODE_HOST :
+  USB_DR_MODE_PERIPHERAL;
+   dwc3_qcom_vbus_overrride_enable(qcom, enable);
+   return 0;
+}
+
+static enum usb_role dwc3_qcom_usb_role_switch_get(struct usb_role_switch *sw)
+{
+   struct dwc3_qcom *qcom = usb_role_switch_get_drvdata(sw);
+   enum usb_role role;
+
+   switch (qcom->mode) {
+   case USB_DR_MODE_HOST:
+   role = USB_ROLE_HOST;
+   break;
+   case USB_DR_MODE_PERIPHERAL:
+   role = USB_ROLE_DEVICE;
+   break;
+   default:
+   role = USB_ROLE_DEVICE;
+   break;
+   }
+
+   return role;
+}
+
+static int dwc3_qcom_setup_role_switch(struct dwc3_qcom *qcom)
+{
+   struct usb_role_switch_desc dwc3_role_switch = {NULL};
+
+   dwc3_role_switch.fwnode = dev_fwnode(qcom->dev);
+   dwc3_role_switch.set = dwc3_qcom_usb_role_switch_set;
+   dwc3_role_switch.get = dwc3_qcom_usb_role_switch_get;
+   dwc3_role_switch.driver_data = qcom;
+   qcom->role_sw = usb_role_switch_register(qcom->dev, _role_switch);
+   if (IS_ERR(qcom->role_sw))
+   return PTR_ERR(qcom->role_sw);
+
+   return 0;
+}
+
 static void dwc3_qcom_disable_interrupts(struct dwc3_qcom *qcom)
 {
if (qcom->hs_phy_irq) {
@@ -540,6 +612,42 @@ static int dwc3_qcom_of_register_core(struct 
platform_device *pdev)
return 0;
 }
 
+static int dwc3_qcom_connector_check(struct fwnode_handle *fwnode)
+{
+   if (fwnode && (!fwnode_property_match_string(fwnode, "compatible",
+"gpio-usb-b-connector") ||
+   !fwnode_property_match_string(fwnode, "compatible",
+ "usb-c-connector")))
+   return 1;
+
+   return 0;
+}
+
+static void *dwc3_qcom_find_usb_connector_match(struct device_connection *con,
+   int ep, void *data)
+{
+   struct fwnode_handle *fwnode;
+
+   /* Check if the "connector" node is the parent of the remote endpoint */
+   if (dwc3_qcom_connector_check(con->fwnode))
+   return fwnode;
+
+   /* else, check if it is a child node */
+   fwnode = fwnode_get_named_child_node(con->fwnode, "connector");
+   if (dwc3_qcom_connector_check(fwnode))
+   return fwnode;
+
+   return 0;
+}
+
+static bool dwc3_qcom_find_usb_connector(struct platform_device *pdev)
+{
+   struct fwnode_handle *fwnode = pdev->dev.fwnode;
+
+   return fwnode_connection_find_match(fwnode, "connector", NULL,
+ 

[PATCH v10 2/4] dt-bindings: usb: Add Qualcomm PMIC type C controller dt-binding

2020-10-08 Thread Wesley Cheng
Introduce the dt-binding for enabling USB type C orientation and role
detection using the PM8150B.  The driver will be responsible for receiving
the interrupt at a state change on the CC lines, reading the
orientation/role, and communicating this information to the remote
clients, which can include a role switch node and a type C switch.

Signed-off-by: Wesley Cheng 
---
 .../bindings/usb/qcom,pmic-typec.yaml | 115 ++
 1 file changed, 115 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml

diff --git a/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml 
b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
new file mode 100644
index ..40e0a296f922
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
@@ -0,0 +1,115 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/usb/qcom,pmic-typec.yaml#;
+$schema: "http://devicetree.org/meta-schemas/core.yaml#;
+
+title: Qualcomm PMIC based USB type C Detection Driver
+
+maintainers:
+  - Wesley Cheng 
+
+description: |
+  Qualcomm PMIC Type C Detect
+
+properties:
+  compatible:
+enum:
+  - qcom,pm8150b-usb-typec
+
+  reg:
+maxItems: 1
+description: Type C base address
+
+  interrupts:
+maxItems: 1
+description: CC change interrupt from PMIC
+
+  port:
+description: Remote endpoint connection to the DRD switch
+type: object
+
+properties:
+  endpoint:
+description: Connection to the DRD switch being used
+type: object
+
+  connector:
+$ref: /connector/usb-connector.yaml#
+description: Connector type for remote endpoints
+type: object
+
+properties:
+  compatible:
+enum:
+  - usb-c-connector
+
+  power-role: true
+  data-role: true
+
+  ports:
+description: Remote endpoint connections for type C paths
+type: object
+
+properties:
+  port@1:
+description: Remote endpoints for the Super Speed path
+type: object
+
+properties:
+  endpoint:
+description: Connection to USB type C mux node
+type: object
+
+required:
+  - compatible
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - connector
+  - port
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+pm8150b {
+#address-cells = <1>;
+#size-cells = <0>;
+pm8150b_typec: usb-typec@1500 {
+compatible = "qcom,pm8150b-usb-typec";
+reg = <0x1500>;
+interrupts = <0x2 0x15 0x5 IRQ_TYPE_EDGE_RISING>;
+
+port {
+usb3_role: endpoint {
+remote-endpoint = <_drd_switch>;
+};
+};
+
+connector {
+compatible = "usb-c-connector";
+power-role = "dual";
+data-role = "dual";
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+};
+port@1 {
+reg = <1>;
+#address-cells = <1>;
+#size-cells = <0>;
+usb3_data_ss: endpoint {
+remote-endpoint = <_ss_mux>;
+};
+};
+};
+};
+};
+};
+...
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v10 1/4] usb: typec: Add QCOM PMIC typec detection driver

2020-10-08 Thread Wesley Cheng
The QCOM SPMI typec driver handles the role and orientation detection, and
notifies client drivers using the USB role switch framework.   It registers
as a typec port, so orientation can be communicated using the typec switch
APIs.  The driver also attains a handle to the VBUS output regulator, so it
can enable/disable the VBUS source when acting as a host/device.

Signed-off-by: Wesley Cheng 
Acked-by: Heikki Krogerus 
Reviewed-by: Stephen Boyd 
---
 drivers/usb/typec/Kconfig   |  12 ++
 drivers/usb/typec/Makefile  |   1 +
 drivers/usb/typec/qcom-pmic-typec.c | 262 
 3 files changed, 275 insertions(+)
 create mode 100644 drivers/usb/typec/qcom-pmic-typec.c

diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
index 559dd06117e7..63789cf88fce 100644
--- a/drivers/usb/typec/Kconfig
+++ b/drivers/usb/typec/Kconfig
@@ -73,6 +73,18 @@ config TYPEC_TPS6598X
  If you choose to build this driver as a dynamically linked module, the
  module will be called tps6598x.ko.
 
+config TYPEC_QCOM_PMIC
+   tristate "Qualcomm PMIC USB Type-C driver"
+   depends on ARCH_QCOM || COMPILE_TEST
+   help
+ Driver for supporting role switch over the Qualcomm PMIC.  This will
+ handle the USB Type-C role and orientation detection reported by the
+ QCOM PMIC if the PMIC has the capability to handle USB Type-C
+ detection.
+
+ It will also enable the VBUS output to connected devices when a
+ DFP connection is made.
+
 source "drivers/usb/typec/mux/Kconfig"
 
 source "drivers/usb/typec/altmodes/Kconfig"
diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index 7753a5c3cd46..cceffd987643 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_TYPEC_TCPM)+= tcpm/
 obj-$(CONFIG_TYPEC_UCSI)   += ucsi/
 obj-$(CONFIG_TYPEC_HD3SS3220)  += hd3ss3220.o
 obj-$(CONFIG_TYPEC_TPS6598X)   += tps6598x.o
+obj-$(CONFIG_TYPEC_QCOM_PMIC)  += qcom-pmic-typec.o
 obj-$(CONFIG_TYPEC)+= mux/
diff --git a/drivers/usb/typec/qcom-pmic-typec.c 
b/drivers/usb/typec/qcom-pmic-typec.c
new file mode 100644
index ..a0454a80c4a2
--- /dev/null
+++ b/drivers/usb/typec/qcom-pmic-typec.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define TYPEC_MISC_STATUS  0xb
+#define CC_ATTACHEDBIT(0)
+#define CC_ORIENTATION BIT(1)
+#define SNK_SRC_MODE   BIT(6)
+#define TYPEC_MODE_CFG 0x44
+#define TYPEC_DISABLE_CMD  BIT(0)
+#define EN_SNK_ONLYBIT(1)
+#define EN_SRC_ONLYBIT(2)
+#define TYPEC_VCONN_CONTROL0x46
+#define VCONN_EN_SRC   BIT(0)
+#define VCONN_EN_VAL   BIT(1)
+#define TYPEC_EXIT_STATE_CFG   0x50
+#define SEL_SRC_UPPER_REF  BIT(2)
+#define TYPEC_INTR_EN_CFG_10x5e
+#define TYPEC_INTR_EN_CFG_1_MASK   GENMASK(7, 0)
+
+struct qcom_pmic_typec {
+   struct device   *dev;
+   struct regmap   *regmap;
+   u32 base;
+
+   struct typec_port   *port;
+   struct usb_role_switch *role_sw;
+
+   struct regulator*vbus_reg;
+   boolvbus_enabled;
+};
+
+static void qcom_pmic_typec_enable_vbus_regulator(struct qcom_pmic_typec
+   *qcom_usb, bool enable)
+{
+   int ret;
+
+   if (enable == qcom_usb->vbus_enabled)
+   return;
+
+   if (enable) {
+   ret = regulator_enable(qcom_usb->vbus_reg);
+   if (ret)
+   return;
+   } else {
+   ret = regulator_disable(qcom_usb->vbus_reg);
+   if (ret)
+   return;
+   }
+   qcom_usb->vbus_enabled = enable;
+}
+
+static void qcom_pmic_typec_check_connection(struct qcom_pmic_typec *qcom_usb)
+{
+   enum typec_orientation orientation;
+   enum usb_role role;
+   unsigned int stat;
+   bool enable_vbus;
+
+   regmap_read(qcom_usb->regmap, qcom_usb->base + TYPEC_MISC_STATUS,
+   );
+
+   if (stat & CC_ATTACHED) {
+   orientation = (stat & CC_ORIENTATION) ?
+   TYPEC_ORIENTATION_REVERSE :
+   TYPEC_ORIENTATION_NORMAL;
+   typec_set_orientation(qcom_usb->port, orientation);
+
+   role = (stat & SNK_SRC_MODE) ? USB_ROLE_HOST : USB_ROLE_DEVICE;
+   if (role == USB_ROLE_HOST)
+   enable_vbus = true;
+   e

[PATCH v10 4/4] arm64: boot: dts: qcom: pm8150b: Add DTS node for PMIC VBUS booster

2020-10-08 Thread Wesley Cheng
Add the required DTS node for the USB VBUS output regulator, which is
available on PM8150B.  This will provide the VBUS source to connected
peripherals.

Signed-off-by: Wesley Cheng 
---
 arch/arm64/boot/dts/qcom/pm8150b.dtsi   | 6 ++
 arch/arm64/boot/dts/qcom/sm8150-mtp.dts | 4 
 2 files changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi 
b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
index 2bf385f5a55a..49ea597cc0c5 100644
--- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
@@ -53,6 +53,12 @@ power-on@800 {
status = "disabled";
};
 
+   pm8150b_vbus: regulator@1100 {
+   compatible = "qcom,pm8150b-vbus-reg";
+   status = "disabled";
+   reg = <0x1100>;
+   };
+
pm8150b_typec: usb-typec@1500 {
compatible = "qcom,pm8150b-usb-typec";
status = "disabled";
diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts 
b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
index 6c6325c3af59..ba3b5b802954 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
@@ -409,6 +409,10 @@ _mem_phy {
vdda-pll-max-microamp = <19000>;
 };
 
+_vbus {
+   status = "okay";
+};
+
 _1_hsphy {
status = "okay";
vdda-pll-supply = <_usb_hs_core>;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v10 0/4] Introduce PMIC based USB type C detection

2020-10-08 Thread Wesley Cheng
Changes in v10:
 - Modified the type c dt-binding to remove the DRD switch node outside of the
   connector, as it is more of a SW entity, whereas the USB connector model
   focuses more on how the connector pins are connected in the HW design.  The
   binding now matches what is specified in the usb-connector binding.
 - Change the fwnode to search for the remote endpoint referencing the usb role
   switch device in qcom-pmic-typec
 - Rename typec node from "typec" to "usb-typec"

Changes in v9:
 - Fixed dt-binding to reference usb-connector from the 'connector' node,
   removed properties that didn't have further constraints (than specified in
   usb-connector.yaml), and make 'reg' a required property.
 - Moved vbus_reg get call into probe(), and will fail if the regulator is not
   available.
 - Removed some references from qcom_pmic_typec, as they were not needed after
   probe().
 - Moved interrupt registration until after all used variables were initialized.

Changes in v8:
 - Simplified some property definitions, and corrected the
   connector reference in the dt binding.

Changes in v7:
 - Fixups in qcom-pmic-typec.c to remove uncesscary includes, printk formatting,
   and revising some logic operations. 

Changes in v6:
 - Removed qcom_usb_vbus-regulator.c and qcom,usb-vbus-regulator.yaml from the
   series as they have been merged on regulator.git
 - Added separate references to the usb-connector.yaml in qcom,pmic-typec.yaml
   instead of referencing the entire schema.

Changes in v5:
 - Fix dt_binding_check warning/error in qcom,pmic-typec.yaml

Changes in v4:
 - Modified qcom,pmic-typec binding to include the SS mux and the DRD remote
   endpoint nodes underneath port@1, which is assigned to the SSUSB path
   according to usb-connector
 - Added usb-connector reference to the typec dt-binding
 - Added tags to the usb type c and vbus nodes
 - Removed "qcom" tags from type c and vbus nodes
 - Modified Kconfig module name, and removed module alias from the typec driver
 
Changes in v3:
 - Fix driver reference to match driver name in Kconfig for
   qcom_usb_vbus-regulator.c
 - Utilize regulator bitmap helpers for enable, disable and is enabled calls in
   qcom_usb_vbus-regulator.c
 - Use of_get_regulator_init_data() to initialize regulator init data, and to
   set constraints in qcom_usb_vbus-regulator.c
 - Remove the need for a local device structure in the vbus regulator driver
 
Changes in v2:
 - Use devm_kzalloc() in qcom_pmic_typec_probe()
 - Add checks to make sure return value of typec_find_port_power_role() is
   valid
 - Added a VBUS output regulator driver, which will be used by the PMIC USB
   type c driver to enable/disable the source
 - Added logic to control vbus source from the PMIC type c driver when
   UFP/DFP is detected
 - Added dt-binding for this new regulator driver
 - Fixed Kconfig typec notation to match others
 - Leave type C block disabled until enabled by a platform DTS

Add the required drivers for implementing type C orientation and role
detection using the Qualcomm PMIC.  Currently, PMICs such as the PM8150B
have an integrated type C block, which can be utilized for this.  This
series adds the dt-binding, PMIC type C driver, and DTS nodes.

The PMIC type C driver will register itself as a type C port w/ a
registered type C switch for orientation, and will fetch a USB role switch
handle for the role notifications.  It will also have the ability to enable
the VBUS output to any connected devices based on if the device is behaving
as a UFP or DFP.

Wesley Cheng (4):
  usb: typec: Add QCOM PMIC typec detection driver
  dt-bindings: usb: Add Qualcomm PMIC type C controller dt-binding
  arm64: boot: dts: qcom: pm8150b: Add node for USB type C block
  arm64: boot: dts: qcom: pm8150b: Add DTS node for PMIC VBUS booster

 .../bindings/usb/qcom,pmic-typec.yaml | 115 
 arch/arm64/boot/dts/qcom/pm8150b.dtsi |  13 +
 arch/arm64/boot/dts/qcom/sm8150-mtp.dts   |   4 +
 drivers/usb/typec/Kconfig |  12 +
 drivers/usb/typec/Makefile|   1 +
 drivers/usb/typec/qcom-pmic-typec.c   | 262 ++
 6 files changed, 407 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
 create mode 100644 drivers/usb/typec/qcom-pmic-typec.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v10 3/4] arm64: boot: dts: qcom: pm8150b: Add node for USB type C block

2020-10-08 Thread Wesley Cheng
The PM8150B has a dedicated USB type C block, which can be used for type C
orientation and role detection.  Create the reference node to this type C
block for further use.

Signed-off-by: Wesley Cheng 
Reviewed-by: Bjorn Andersson 
---
 arch/arm64/boot/dts/qcom/pm8150b.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi 
b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
index e112e8876db6..2bf385f5a55a 100644
--- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
@@ -53,6 +53,13 @@ power-on@800 {
status = "disabled";
};
 
+   pm8150b_typec: usb-typec@1500 {
+   compatible = "qcom,pm8150b-usb-typec";
+   status = "disabled";
+   reg = <0x1500>;
+   interrupts = <0x2 0x15 0x5 IRQ_TYPE_EDGE_RISING>;
+   };
+
pm8150b_temp: temp-alarm@2400 {
compatible = "qcom,spmi-temp-alarm";
reg = <0x2400>;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v4] usb: dwc3: Stop active transfers before halting the controller

2020-09-28 Thread Wesley Cheng
In the DWC3 databook, for a device initiated disconnect or bus reset, the
driver is required to send dependxfer commands for any pending transfers.
In addition, before the controller can move to the halted state, the SW
needs to acknowledge any pending events.  If the controller is not halted
properly, there is a chance the controller will continue accessing stale or
freed TRBs and buffers.

Signed-off-by: Wesley Cheng 
Reviewed-by: Thinh Nguyen 

---
Changes in v4:
 - Updated comments to reference DWC3 databook sections and added direct
   quotes.
 - Changed the stop active transfer EP loop to use dwc->num_eps.
 - Moved to using dwc3_gadget_disable_irq/synchronize_irq instead of
   enable_irq/disable_irq for ensuring the interrupt handler is not pending.

Changes in v3:
 - Removed DWC3_EP_ENABLED check from dwc3_gadget_stop_active_transfers()
   as dwc3_stop_active_transfer() has a check already in place.
 - Calling __dwc3_gadget_stop() which ensures that DWC3 interrupt events
   are cleared, and ep0 eps are cleared for the pullup disabled case.  Not
   required to call __dwc3_gadget_start() on pullup enable, as the
   composite driver will execute udc_start() before calling pullup().

Changes in v2:
 - Moved cleanup code to the pullup() API to differentiate between device
   disconnect and hibernation.
 - Added cleanup code to the bus reset case as well.
 - Verified the move to pullup() did not reproduce the problen using the
   same test sequence.

Verified fix by adding a check for ETIMEDOUT during the run stop call.
Shell script writing to the configfs UDC file to trigger disconnect and
connect.  Batch script to have PC execute data transfers over adb (ie adb
push)  After a few iterations, we'd run into a scenario where the
controller wasn't halted.  With the following change, no failed halts after
many iterations.
---
 drivers/usb/dwc3/ep0.c|  2 +-
 drivers/usb/dwc3/gadget.c | 66 ++-
 2 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 59f2e8c31bd1..456aa87e8778 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -197,7 +197,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct 
usb_request *request,
int ret;
 
spin_lock_irqsave(>lock, flags);
-   if (!dep->endpoint.desc) {
+   if (!dep->endpoint.desc || !dwc->pullups_connected) {
dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
dep->name);
ret = -ESHUTDOWN;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 3ab6f118c508..5d879b7606d5 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1516,7 +1516,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, 
struct dwc3_request *req)
 {
struct dwc3 *dwc = dep->dwc;
 
-   if (!dep->endpoint.desc) {
+   if (!dep->endpoint.desc || !dwc->pullups_connected) {
dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
dep->name);
return -ESHUTDOWN;
@@ -1926,6 +1926,21 @@ static int dwc3_gadget_set_selfpowered(struct usb_gadget 
*g,
return 0;
 }
 
+static void dwc3_stop_active_transfers(struct dwc3 *dwc)
+{
+   u32 epnum;
+
+   for (epnum = 2; epnum < dwc->num_eps; epnum++) {
+   struct dwc3_ep *dep;
+
+   dep = dwc->eps[epnum];
+   if (!dep)
+   continue;
+
+   dwc3_remove_requests(dwc, dep);
+   }
+}
+
 static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend)
 {
u32 reg;
@@ -1971,6 +1986,9 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int 
is_on, int suspend)
return 0;
 }
 
+static void dwc3_gadget_disable_irq(struct dwc3 *dwc);
+static void __dwc3_gadget_stop(struct dwc3 *dwc);
+
 static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 {
struct dwc3 *dwc = gadget_to_dwc(g);
@@ -1994,7 +2012,46 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int 
is_on)
}
}
 
+   /*
+* Synchronize any pending event handling before executing the 
controller
+* halt routine.
+*/
+   if (!is_on) {
+   dwc3_gadget_disable_irq(dwc);
+   synchronize_irq(dwc->irq_gadget);
+   }
+
spin_lock_irqsave(>lock, flags);
+
+   if (!is_on) {
+   u32 count;
+
+   /*
+* In the Synopsis DesignWare Cores USB3 Databook Rev. 3.30a
+* Section 4.1.8 Table 4-7, it states that for a 
device-initiated
+* disconnect, the SW needs to ensure that it sends "a 
DEPENDXFER
+* comma

Re: [PATCH v3] usb: dwc3: Stop active transfers before halting the controller

2020-09-25 Thread Wesley Cheng



On 9/24/2020 11:06 PM, Felipe Balbi wrote:
> 
> Hi,
> 
> Alan Stern  writes:
>>>> Hence, the reason if there was already a pending IRQ triggered, the
>>>> dwc3_gadget_disable_irq() won't ensure the IRQ is handled.  We can do
>>>> something like:
>>>> if (!is_on)
>>>>dwc3_gadget_disable_irq()
>>>> synchronize_irq()
>>>> spin_lock_irqsave()
>>>> if(!is_on) {
>>>> ...
>>>>
>>>> But the logic to only apply this on the pullup removal case is a little
>>>> messy.  Also, from my understanding, the spin_lock_irqsave() will only
>>>> disable the local CPU IRQs, but not the interrupt line on the GIC, which
>>>> means other CPUs can handle it, unless we explicitly set the IRQ
>>>> affinity to CPUX.
>>>
>>> Yeah, the way I understand this can't really happen. But I'm open to
>>> being educated. Maybe Alan can explain if this is really possibility?
>>

Hi Felipe/Alan,

Thanks for the detailed explanations and inputs.  Useful information to
have!

>> It depends on the details of the hardware, but yes, it is possible in
>> general for an interrupt handler to run after you have turned off the
>> device's interrupt-request line.  For example:
>>
>>  CPU A   CPU B
>>  --- --
>>  Gets an IRQ from the device
>>  Calls handler routine   spin_lock_irq
>>spin_lock_irq Turns off the IRQ line
>>...spins...   spin_unlock_irq
>>Rest of handler runs
>>spin_unlock_irq
>>
>> That's why we have synchronize_irq().  The usual pattern is something
>> like this:
>>
>>  spin_lock_irq(>lock);
>>  priv->disconnected = true;
>>  my_disable_irq(priv);
>>  spin_unlock_irq(>lock);
>>  synchronize_irq(priv->irq);
>>
>> And of course this has to be done in a context that can sleep.
>>
>> Does this answer your question?
> 
> It does, thank you Alan. It seems like we don't need a call to
> disable_irq(), only synchronize_irq() is enough, however it should be
> called with spinlocks released, not held.
> 

I mean...I'm not against using the synchronize_irq() +
dwc3_gadget_disable_irq() route, since that will address the concern as
well.  It was just with the disable/enable IRQ route, I didn't need to
explicitly check the is_on flag again, since I didn't need to worry
about overwriting the DEVTEN reg (for the pullup enable case).  Will
include this on the next version.

Thanks
Wesley Cheng

> Thanks
> 

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


Re: [PATCH v3] usb: dwc3: Stop active transfers before halting the controller

2020-09-08 Thread Wesley Cheng



On 9/6/2020 11:20 PM, Felipe Balbi wrote:
> 
> Hi,
> 
> Wesley Cheng  writes:
>> diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
>> index 59f2e8c31bd1..456aa87e8778 100644
>> --- a/drivers/usb/dwc3/ep0.c
>> +++ b/drivers/usb/dwc3/ep0.c
>> @@ -197,7 +197,7 @@ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct 
>> usb_request *request,
>>  int ret;
>>  
>>  spin_lock_irqsave(>lock, flags);
>> -if (!dep->endpoint.desc) {
>> +if (!dep->endpoint.desc || !dwc->pullups_connected) {
> 
> this looks odd. If we don't have pullups connected, we shouldn't have a
> descriptor, likewise if we don't have a a description, we haven't been
> enumerated, therefore we shouldn't have pullups connected.
> 
> What am I missing here?
> 

Hi Felipe,

When we
echo "" > /sys/kernel/config/usb_gadget/g1/UDC

This triggers the usb_gadget_disconnect() routine to execute.

int usb_gadget_disconnect(struct usb_gadget *gadget)
{
...
ret = gadget->ops->pullup(gadget, 0);
if (!ret) {
gadget->connected = 0;
gadget->udc->driver->disconnect(gadget);
}

So it is possible that we've already disabled the pullup before running
the disable() callbacks in the function drivers.  The disable()
callbacks usually are the ones responsible for calling usb_ep_disable(),
where we clear the desc field.  This means there is a brief period where
the pullups_connected = 0, but we still have valid ep desc, as it has
not been disabled yet.

Also, for function drivers like mass storage, the fsg_disable() routine
defers the actual usb_ep_disable() call to the fsg_thread, so its not
always ensured that the disconnect() execution would result in the
usb_ep_disable() to occur synchronously.

>> @@ -1926,6 +1926,21 @@ static int dwc3_gadget_set_selfpowered(struct 
>> usb_gadget *g,
>>  return 0;
>>  }
>>  
>> +static void dwc3_stop_active_transfers(struct dwc3 *dwc)
>> +{
>> +u32 epnum;
>> +
>> +for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
> 
> dwc3 knows the number of endpoints available in the HW. Use dwc->num_eps
> instead.
> 

Sure, will do.

>> @@ -1971,6 +1986,8 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int 
>> is_on, int suspend)
>>  return 0;
>>  }
>>  
>> +static void __dwc3_gadget_stop(struct dwc3 *dwc);
>> +
>>  static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
>>  {
>>  struct dwc3 *dwc = gadget_to_dwc(g);
>> @@ -1994,9 +2011,37 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, 
>> int is_on)
>>  }
>>  }
>>  
>> +/*
>> + * Synchronize and disable any further event handling while controller
>> + * is being enabled/disabled.
>> + */
>> +disable_irq(dwc->irq_gadget);
> 
> why isn't dwc3_gadget_disable_irq() enough?
> 
>>  spin_lock_irqsave(>lock, flags);
> 
> spin_lock_irqsave() will disable interrupts, why disable_irq() above?
> 

In the discussion I had with Thinh, the concern was that with the newly
added code to override the lpos here, if the interrupt routine
(dwc3_check_event_buf()) runs, then it will reference the lpos for
copying the event buffer contents to the event cache, and potentially
process events.  There is no locking in place, so it could be possible
to have both run in parallel.

Hence, the reason if there was already a pending IRQ triggered, the
dwc3_gadget_disable_irq() won't ensure the IRQ is handled.  We can do
something like:
if (!is_on)
dwc3_gadget_disable_irq()
synchronize_irq()
spin_lock_irqsave()
if(!is_on) {
...

But the logic to only apply this on the pullup removal case is a little
messy.  Also, from my understanding, the spin_lock_irqsave() will only
disable the local CPU IRQs, but not the interrupt line on the GIC, which
means other CPUs can handle it, unless we explicitly set the IRQ
affinity to CPUX.

>> +/* Controller is not halted until pending events are acknowledged */
>> +if (!is_on) {
>> +u32 count;
>> +
>> +/*
>> + * The databook explicitly mentions for a device-initiated
>> + * disconnect sequence, the SW needs to ensure that it ends any
>> + * active transfers.
>> + */
> 
> make this a little better by mentioning the version and section of the
> databook you're reading. That makes it easier for future
> reference. Also, use an actual quote from the databook, along the lines
> of:
> 
>   /*
>  * Synopsys DesignWare Cores USB3 Da

[PATCH v9 2/4] dt-bindings: usb: Add Qualcomm PMIC type C controller dt-binding

2020-09-04 Thread Wesley Cheng
Introduce the dt-binding for enabling USB type C orientation and role
detection using the PM8150B.  The driver will be responsible for receiving
the interrupt at a state change on the CC lines, reading the
orientation/role, and communicating this information to the remote
clients, which can include a role switch node and a type C switch.

Signed-off-by: Wesley Cheng 
---
 .../bindings/usb/qcom,pmic-typec.yaml | 108 ++
 1 file changed, 108 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml

diff --git a/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml 
b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
new file mode 100644
index ..8582ab6a3cc4
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
@@ -0,0 +1,108 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/usb/qcom,pmic-typec.yaml#;
+$schema: "http://devicetree.org/meta-schemas/core.yaml#;
+
+title: Qualcomm PMIC based USB type C Detection Driver
+
+maintainers:
+  - Wesley Cheng 
+
+description: |
+  Qualcomm PMIC Type C Detect
+
+properties:
+  compatible:
+enum:
+  - qcom,pm8150b-usb-typec
+
+  reg:
+maxItems: 1
+description: Type C base address
+
+  interrupts:
+maxItems: 1
+description: CC change interrupt from PMIC
+
+  connector:
+$ref: /connector/usb-connector.yaml#
+description: Connector type for remote endpoints
+type: object
+
+properties:
+  compatible:
+enum:
+  - usb-c-connector
+
+  power-role: true
+  data-role: true
+
+  ports:
+description: Remote endpoint connections
+type: object
+
+properties:
+  port@1:
+description: Remote endpoints for the Super Speed path
+type: object
+
+properties:
+  endpoint@0:
+description: Connection to USB type C mux node
+type: object
+
+  endpoint@1:
+description: Connection to role switch node
+type: object
+
+required:
+  - compatible
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - connector
+
+additionalProperties: false
+
+examples:
+  - |
+#include 
+pm8150b {
+#address-cells = <1>;
+#size-cells = <0>;
+pm8150b_typec: typec@1500 {
+compatible = "qcom,pm8150b-usb-typec";
+reg = <0x1500>;
+interrupts = <0x2 0x15 0x5 IRQ_TYPE_EDGE_RISING>;
+
+connector {
+compatible = "usb-c-connector";
+power-role = "dual";
+data-role = "dual";
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+};
+port@1 {
+reg = <1>;
+#address-cells = <1>;
+#size-cells = <0>;
+usb3_data_ss: endpoint@0 {
+reg = <0>;
+remote-endpoint = <_ss_mux>;
+};
+usb3_role: endpoint@1 {
+reg = <1>;
+remote-endpoint = <_drd_switch>;
+};
+};
+};
+};
+};
+};
+...
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v9 4/4] arm64: boot: dts: qcom: pm8150b: Add DTS node for PMIC VBUS booster

2020-09-04 Thread Wesley Cheng
Add the required DTS node for the USB VBUS output regulator, which is
available on PM8150B.  This will provide the VBUS source to connected
peripherals.

Signed-off-by: Wesley Cheng 
---
 arch/arm64/boot/dts/qcom/pm8150b.dtsi   | 6 ++
 arch/arm64/boot/dts/qcom/sm8150-mtp.dts | 4 
 2 files changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi 
b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
index 053c659734a7..b49caa63cd4c 100644
--- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
@@ -53,6 +53,12 @@ power-on@800 {
status = "disabled";
};
 
+   pm8150b_vbus: regulator@1100 {
+   compatible = "qcom,pm8150b-vbus-reg";
+   status = "disabled";
+   reg = <0x1100>;
+   };
+
pm8150b_typec: typec@1500 {
compatible = "qcom,pm8150b-usb-typec";
status = "disabled";
diff --git a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts 
b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
index 6c6325c3af59..ba3b5b802954 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8150-mtp.dts
@@ -409,6 +409,10 @@ _mem_phy {
vdda-pll-max-microamp = <19000>;
 };
 
+_vbus {
+   status = "okay";
+};
+
 _1_hsphy {
status = "okay";
vdda-pll-supply = <_usb_hs_core>;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v9 0/4] Introduce PMIC based USB type C detection

2020-09-04 Thread Wesley Cheng
Changes in v9:
 - Fixed dt-binding to reference usb-connector from the 'connector' node,
   removed properties that didn't have further constraints (than specified in
   usb-connector.yaml), and make 'reg' a required property.
 - Moved vbus_reg get call into probe(), and will fail if the regulator is not
   available.
 - Removed some references from qcom_pmic_typec, as they were not needed after
   probe().
 - Moved interrupt registration until after all used variables were initialized.

Changes in v8:
 - Simplified some property definitions, and corrected the
   connector reference in the dt binding.

Changes in v7:
 - Fixups in qcom-pmic-typec.c to remove uncesscary includes, printk formatting,
   and revising some logic operations. 

Changes in v6:
 - Removed qcom_usb_vbus-regulator.c and qcom,usb-vbus-regulator.yaml from the
   series as they have been merged on regulator.git
 - Added separate references to the usb-connector.yaml in qcom,pmic-typec.yaml
   instead of referencing the entire schema.

Changes in v5:
 - Fix dt_binding_check warning/error in qcom,pmic-typec.yaml

Changes in v4:
 - Modified qcom,pmic-typec binding to include the SS mux and the DRD remote
   endpoint nodes underneath port@1, which is assigned to the SSUSB path
   according to usb-connector
 - Added usb-connector reference to the typec dt-binding
 - Added tags to the usb type c and vbus nodes
 - Removed "qcom" tags from type c and vbus nodes
 - Modified Kconfig module name, and removed module alias from the typec driver
 
Changes in v3:
 - Fix driver reference to match driver name in Kconfig for
   qcom_usb_vbus-regulator.c
 - Utilize regulator bitmap helpers for enable, disable and is enabled calls in
   qcom_usb_vbus-regulator.c
 - Use of_get_regulator_init_data() to initialize regulator init data, and to
   set constraints in qcom_usb_vbus-regulator.c
 - Remove the need for a local device structure in the vbus regulator driver
 
Changes in v2:
 - Use devm_kzalloc() in qcom_pmic_typec_probe()
 - Add checks to make sure return value of typec_find_port_power_role() is
   valid
 - Added a VBUS output regulator driver, which will be used by the PMIC USB
   type c driver to enable/disable the source
 - Added logic to control vbus source from the PMIC type c driver when
   UFP/DFP is detected
 - Added dt-binding for this new regulator driver
 - Fixed Kconfig typec notation to match others
 - Leave type C block disabled until enabled by a platform DTS

Wesley Cheng (4):
  usb: typec: Add QCOM PMIC typec detection driver
  dt-bindings: usb: Add Qualcomm PMIC type C controller dt-binding
  arm64: boot: dts: qcom: pm8150b: Add node for USB type C block
  arm64: boot: dts: qcom: pm8150b: Add DTS node for PMIC VBUS booster

 .../bindings/usb/qcom,pmic-typec.yaml | 108 
 arch/arm64/boot/dts/qcom/pm8150b.dtsi |  13 +
 arch/arm64/boot/dts/qcom/sm8150-mtp.dts   |   4 +
 drivers/usb/typec/Kconfig |  12 +
 drivers/usb/typec/Makefile|   1 +
 drivers/usb/typec/qcom-pmic-typec.c   | 262 ++
 6 files changed, 400 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/qcom,pmic-typec.yaml
 create mode 100644 drivers/usb/typec/qcom-pmic-typec.c

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v9 3/4] arm64: boot: dts: qcom: pm8150b: Add node for USB type C block

2020-09-04 Thread Wesley Cheng
The PM8150B has a dedicated USB type C block, which can be used for type C
orientation and role detection.  Create the reference node to this type C
block for further use.

Signed-off-by: Wesley Cheng 
Reviewed-by: Bjorn Andersson 
---
 arch/arm64/boot/dts/qcom/pm8150b.dtsi | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi 
b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
index e112e8876db6..053c659734a7 100644
--- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
@@ -53,6 +53,13 @@ power-on@800 {
status = "disabled";
};
 
+   pm8150b_typec: typec@1500 {
+   compatible = "qcom,pm8150b-usb-typec";
+   status = "disabled";
+   reg = <0x1500>;
+   interrupts = <0x2 0x15 0x5 IRQ_TYPE_EDGE_RISING>;
+   };
+
pm8150b_temp: temp-alarm@2400 {
compatible = "qcom,spmi-temp-alarm";
reg = <0x2400>;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH v9 1/4] usb: typec: Add QCOM PMIC typec detection driver

2020-09-04 Thread Wesley Cheng
The QCOM SPMI typec driver handles the role and orientation detection, and
notifies client drivers using the USB role switch framework.   It registers
as a typec port, so orientation can be communicated using the typec switch
APIs.  The driver also attains a handle to the VBUS output regulator, so it
can enable/disable the VBUS source when acting as a host/device.

Signed-off-by: Wesley Cheng 
Acked-by: Heikki Krogerus 
Reviewed-by: Stephen Boyd 
---
 drivers/usb/typec/Kconfig   |  12 ++
 drivers/usb/typec/Makefile  |   1 +
 drivers/usb/typec/qcom-pmic-typec.c | 262 
 3 files changed, 275 insertions(+)
 create mode 100644 drivers/usb/typec/qcom-pmic-typec.c

diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig
index 559dd06117e7..63789cf88fce 100644
--- a/drivers/usb/typec/Kconfig
+++ b/drivers/usb/typec/Kconfig
@@ -73,6 +73,18 @@ config TYPEC_TPS6598X
  If you choose to build this driver as a dynamically linked module, the
  module will be called tps6598x.ko.
 
+config TYPEC_QCOM_PMIC
+   tristate "Qualcomm PMIC USB Type-C driver"
+   depends on ARCH_QCOM || COMPILE_TEST
+   help
+ Driver for supporting role switch over the Qualcomm PMIC.  This will
+ handle the USB Type-C role and orientation detection reported by the
+ QCOM PMIC if the PMIC has the capability to handle USB Type-C
+ detection.
+
+ It will also enable the VBUS output to connected devices when a
+ DFP connection is made.
+
 source "drivers/usb/typec/mux/Kconfig"
 
 source "drivers/usb/typec/altmodes/Kconfig"
diff --git a/drivers/usb/typec/Makefile b/drivers/usb/typec/Makefile
index 7753a5c3cd46..cceffd987643 100644
--- a/drivers/usb/typec/Makefile
+++ b/drivers/usb/typec/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_TYPEC_TCPM)+= tcpm/
 obj-$(CONFIG_TYPEC_UCSI)   += ucsi/
 obj-$(CONFIG_TYPEC_HD3SS3220)  += hd3ss3220.o
 obj-$(CONFIG_TYPEC_TPS6598X)   += tps6598x.o
+obj-$(CONFIG_TYPEC_QCOM_PMIC)  += qcom-pmic-typec.o
 obj-$(CONFIG_TYPEC)+= mux/
diff --git a/drivers/usb/typec/qcom-pmic-typec.c 
b/drivers/usb/typec/qcom-pmic-typec.c
new file mode 100644
index ..9fc5e69d6e82
--- /dev/null
+++ b/drivers/usb/typec/qcom-pmic-typec.c
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define TYPEC_MISC_STATUS  0xb
+#define CC_ATTACHEDBIT(0)
+#define CC_ORIENTATION BIT(1)
+#define SNK_SRC_MODE   BIT(6)
+#define TYPEC_MODE_CFG 0x44
+#define TYPEC_DISABLE_CMD  BIT(0)
+#define EN_SNK_ONLYBIT(1)
+#define EN_SRC_ONLYBIT(2)
+#define TYPEC_VCONN_CONTROL0x46
+#define VCONN_EN_SRC   BIT(0)
+#define VCONN_EN_VAL   BIT(1)
+#define TYPEC_EXIT_STATE_CFG   0x50
+#define SEL_SRC_UPPER_REF  BIT(2)
+#define TYPEC_INTR_EN_CFG_10x5e
+#define TYPEC_INTR_EN_CFG_1_MASK   GENMASK(7, 0)
+
+struct qcom_pmic_typec {
+   struct device   *dev;
+   struct regmap   *regmap;
+   u32 base;
+
+   struct typec_port   *port;
+   struct usb_role_switch *role_sw;
+
+   struct regulator*vbus_reg;
+   boolvbus_enabled;
+};
+
+static void qcom_pmic_typec_enable_vbus_regulator(struct qcom_pmic_typec
+   *qcom_usb, bool enable)
+{
+   int ret;
+
+   if (enable == qcom_usb->vbus_enabled)
+   return;
+
+   if (enable) {
+   ret = regulator_enable(qcom_usb->vbus_reg);
+   if (ret)
+   return;
+   } else {
+   ret = regulator_disable(qcom_usb->vbus_reg);
+   if (ret)
+   return;
+   }
+   qcom_usb->vbus_enabled = enable;
+}
+
+static void qcom_pmic_typec_check_connection(struct qcom_pmic_typec *qcom_usb)
+{
+   enum typec_orientation orientation;
+   enum usb_role role;
+   unsigned int stat;
+   bool enable_vbus;
+
+   regmap_read(qcom_usb->regmap, qcom_usb->base + TYPEC_MISC_STATUS,
+   );
+
+   if (stat & CC_ATTACHED) {
+   orientation = (stat & CC_ORIENTATION) ?
+   TYPEC_ORIENTATION_REVERSE :
+   TYPEC_ORIENTATION_NORMAL;
+   typec_set_orientation(qcom_usb->port, orientation);
+
+   role = (stat & SNK_SRC_MODE) ? USB_ROLE_HOST : USB_ROLE_DEVICE;
+   if (role == USB_ROLE_HOST)
+   enable_vbus = true;
+   e

Re: [PATCH v8 4/4] arm64: boot: dts: qcom: pm8150b: Add DTS node for PMIC VBUS booster

2020-09-03 Thread Wesley Cheng



On 8/30/2020 10:52 AM, Bjorn Andersson wrote:
> On Thu 20 Aug 07:47 UTC 2020, Wesley Cheng wrote:
> 
>>
>>
>> On 8/12/2020 2:34 AM, Sergei Shtylyov wrote:
>>> Hello!
>>>
>>> On 12.08.2020 10:19, Wesley Cheng wrote:
>>>
>>>> Add the required DTS node for the USB VBUS output regulator, which is
>>>> available on PM8150B.  This will provide the VBUS source to connected
>>>> peripherals.
>>>>
>>>> Signed-off-by: Wesley Cheng 
>>>> ---
>>>>   arch/arm64/boot/dts/qcom/pm8150b.dtsi   | 6 ++
>>>>   arch/arm64/boot/dts/qcom/sm8150-mtp.dts | 4 
>>>>   2 files changed, 10 insertions(+)
>>>>
>>>> diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi
>>>> b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
>>>> index 053c659734a7..9e560c1ca30d 100644
>>>> --- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi
>>>> +++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
>>>> @@ -53,6 +53,12 @@ power-on@800 {
>>>>   status = "disabled";
>>>>   };
>>>>   +    pm8150b_vbus: dcdc@1100 {
>>>
>>>    s/dcdc/regulator/? What is "dcdc", anyway?
>>>    The device nodes must have the generic names, according to the DT spec.
>>>
>>
>> Hi Sergei,
>>
>> Thanks for the comment!
>>
>> DCDC is the label that we use for the DC to DC converter block, since
>> the VBUS booster will output 5V to the connected devices.  Would it make
>> more sense to have "dc-dc?"
>>
> 
> At this level it's just a regulator at 0x1100, so it should be
> "regulator@1100". If you would like a more useful name in the running
> system you should be able to use the "regulator-name" property.
> 
> Regards,
> Bjorn
> 

Hi Bjorn,

Thanks for the suggestion.  Sounds good, I will just use the "regulator"
name for now.

Thanks
Wesley

>> Thanks
>> Wesley
>>
>>>> +    compatible = "qcom,pm8150b-vbus-reg";
>>>> +    status = "disabled";
>>>> +    reg = <0x1100>;
>>>> +    };
>>>> +
>>>>   pm8150b_typec: typec@1500 {
>>>>   compatible = "qcom,pm8150b-usb-typec";
>>>>   status = "disabled";
>>> [...]
>>>
>>> MBR, Sergei
>>
>> -- 
>> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
>> a Linux Foundation Collaborative Project

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


  1   2   3   >