Re: [PATCH] usb: dwc2: host: fix isoc urb actual length

2017-11-06 Thread wlf

Hi Minas,

在 2017年11月06日 17:28, Minas Harutyunyan 写道:

Hi,

On 11/6/2017 12:46 PM, William Wu wrote:

The actual_length in dwc2_hcd_urb structure is used
to indicate the total data length transferred so far,
but in dwc2_update_isoc_urb_state(), it just updates
the actual_length of isoc frame, and don't update the
urb actual_length at the same time, this will cause
device drivers working error which depend on the urb
actual_length.

we can easily find this issue if use an USB camera,
the userspace use libusb to get USB data from kernel
via devio driver.In usb devio driver, processcompl()
function will process urb complete and copy data to
userspace depending on urb actual_length.

Let's update the urb actual_length if the isoc frame
is valid.

Signed-off-by: William Wu 
---
   drivers/usb/dwc2/hcd_intr.c | 2 ++
   1 file changed, 2 insertions(+)

diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index 28a8210..01b1e13 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -580,6 +580,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
frame_desc->status = 0;
frame_desc->actual_length = dwc2_get_actual_xfer_length(hsotg,
chan, chnum, qtd, halt_status, NULL);
+   urb->actual_length += frame_desc->actual_length;
break;
case DWC2_HC_XFER_FRAME_OVERRUN:
urb->error_count++;
@@ -599,6 +600,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
frame_desc->status = -EPROTO;
frame_desc->actual_length = dwc2_get_actual_xfer_length(hsotg,
chan, chnum, qtd, halt_status, NULL);
+   urb->actual_length += frame_desc->actual_length;
   
   		/* Skip whole frame */

if (chan->qh->do_split &&


According urb description in usb.h urb->actual_length used for non-iso
transfers:

"@actual_length: This is read in non-iso completion functions, and ...

   * ISO transfer status is reported in the status and actual_length fields
   * of the iso_frame_desc array, "
Yes,  urb->actual_length is used for non-iso transfers.  And for ISO 
transfer,  the most
usb class drivers can only use iso frame status and actual_length to 
handle usb data,

like: kernel v4.4 drivers/media/usb/uvc/uvc_video.c

But the usb devio driver really need the urb actual_length in the 
processcompl() if

handle ISO transfer, just as I mentioned in the commit message.

And I also found the same issue on raspberrypi board:
https://github.com/raspberrypi/linux/issues/903

So do you think we need to fix the usb devio driver, rather than fix dwc2?
I think maybe we can use urb actual length for ISO transfer, it seems that
don't cause any side-effect.



Thanks,
Minas








--
吴良峰 William.Wu
福建省福州市铜盘路软件大道89号软件园A区21号楼
No.21 Building, A District, No.89,software Boulevard Fuzhou,Fujian, PRC
手机: 13685012275
座机: 0591-83991906-8520
邮件:w...@rock-chips.com




Re: [PATCH v2 1/2] usb: dwc2: alloc dma aligned buffer for isoc split in

2018-05-02 Thread wlf

Dear Doug,


在 2018年05月02日 12:33, Doug Anderson 写道:

Hi,

On Tue, May 1, 2018 at 8:04 PM, William Wu  wrote:

The commit 3bc04e28a030 ("usb: dwc2: host: Get aligned DMA in
a more supported way") rips out a lot of code to simply the
allocation of aligned DMA. However, it also introduces a new
issue when use isoc split in transfer.

In my test case, I connect the dwc2 controller with an usb hs
Hub (GL852G-12), and plug an usb fs audio device (Plantronics
headset) into the downstream port of Hub. Then use the usb mic
to record, we can find noise when playback.

It's because that the usb Hub uses an MDATA for the first
transaction and a DATA0 for the second transaction for the isoc
split in transaction. An typical isoc split in transaction sequence
like this:

- SSPLIT IN transaction
- CSPLIT IN transaction
   - MDATA packet
- CSPLIT IN transaction
   - DATA0 packet

The DMA address of MDATA (urb->dma) is always DWORD-aligned, but
the DMA address of DATA0 (urb->dma + qtd->isoc_split_offset) may
not be DWORD-aligned, it depends on the qtd->isoc_split_offset (the
length of MDATA). In my test case, the length of MDATA is usually
unaligned, this casue DATA0 packet transmission error.

This patch base on the old way of aligned DMA allocation in the
dwc2 driver to get aligned DMA for isoc split in.

Signed-off-by: William Wu 
---
Changes in v2:
- None

  drivers/usb/dwc2/hcd.c   | 63 +---
  drivers/usb/dwc2/hcd.h   | 10 +++
  drivers/usb/dwc2/hcd_intr.c  |  8 ++
  drivers/usb/dwc2/hcd_queue.c |  8 +-
  4 files changed, 85 insertions(+), 4 deletions(-)

A word of warning that I'm pretty rusty on dwc2 and even when I was
making lots of patches I still considered myself a bit clueless.
...so if something seems wrong, please call me on it...

Most of your suggestions are great, thanks very much!



diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 190f959..8c2b35f 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1562,11 +1562,20 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg 
*hsotg,
 }

 if (hsotg->params.host_dma) {
-   dwc2_writel((u32)chan->xfer_dma,
-   hsotg->regs + HCDMA(chan->hc_num));
+   dma_addr_t dma_addr;
+
+   if (chan->align_buf) {
+   if (dbg_hc(chan))
+   dev_vdbg(hsotg->dev, "align_buf\n");
+   dma_addr = chan->align_buf;
+   } else {
+   dma_addr = chan->xfer_dma;
+   }
+   dwc2_writel((u32)dma_addr, hsotg->regs + HCDMA(chan->hc_num));
+
 if (dbg_hc(chan))
 dev_vdbg(hsotg->dev, "Wrote %08lx to HCDMA(%d)\n",
-(unsigned long)chan->xfer_dma, chan->hc_num);
+(unsigned long)dma_addr, chan->hc_num);
 }

 /* Start the split */
@@ -2620,6 +2629,33 @@ static void dwc2_hc_init_xfer(struct dwc2_hsotg *hsotg,
 }
  }

+static int dwc2_alloc_split_dma_aligned_buf(struct dwc2_hsotg *hsotg,
+   struct dwc2_qh *qh,
+   struct dwc2_host_chan *chan)
+{
+   if (!qh->dw_align_buf) {
+   qh->dw_align_buf = kmalloc(chan->max_packet,

So you're potentially doing a bounce buffer atop a bounce buffer now,
right?  That seems pretty non-optimal.  You're also back to doing a
kmalloc at interrupt time which I found was pretty bad for
performance.
Yes, I just allocate an additional bounce buffer here. I haven't thought 
consummately
about this patch, it's really not a good way to use a kmalloc at 
interrut time.

Is there really no way you can do your memory allocation in
dwc2_alloc_dma_aligned_buffer() instead of here?  For input packets,
if you could just allocate an extra 3 bytes in the original bounce
buffer you could just re-use the original bounce buffer together with
a memmove?  AKA:

transfersize = 13 + 64;
buf = alloc(16 + 64);

// Do the first transfer, no problems.
dma_into(buf, 13);

// 2nd transfer isn't aligned, so align.
// we allocated a little extra to account for this
dma_into(buf + 16, 64);

// move back where it belongs.
memmove(buf + 13, buf + 16, 64);


To make the above work you'd need to still allocate a bounce buffer
even if the original "urb->transfer_buffer" was already aligned.
Ideally you'd be able to know when dwc2_alloc_dma_aligned_buffer()
that this is one of the special cases where you need a slightly
oversized bounce buffer.
It's a good way to allocate an extra 3 bytes in the original bounce 
buffer for this unaligned
issue, it's similar to the tailroom of sk_buff. However, just as you 
said, we'd better find
the special cases where we need an oversized bounce buffer, otherwise,we 
need to allocate

a bounce buffer for all of urbs.

It's hard for me to know the special cases in

Re: [PATCH v2 2/2] usb: dwc2: fix isoc split in transfer with no data

2018-05-02 Thread wlf

Dear Doug,


在 2018年05月02日 13:02, Doug Anderson 写道:

Hi,

On Tue, May 1, 2018 at 8:04 PM, William Wu  wrote:

If isoc split in transfer with no data (the length of DATA0
packet is zero), we can't simply return immediately. Because
the DATA0 can be the first transaction or the second transaction
for the isoc split in transaction. If the DATA0 packet with no
data is in the first transaction, we can return immediately.
But if the DATA0 packet with no data is in the second transaction
of isoc split in transaction sequence, we need to increase the
qtd->isoc_frame_index and giveback urb to device driver if needed,
otherwise, the MDATA packet will be lost.

A typical test case is that connect the dwc2 controller with an
usb hs Hub (GL852G-12), and plug an usb fs audio device (Plantronics
headset) into the downstream port of Hub. Then use the usb mic
to record, we can find noise when playback.

In the case, the isoc split in transaction sequence like this:

- SSPLIT IN transaction
- CSPLIT IN transaction
   - MDATA packet (176 bytes)
- CSPLIT IN transaction
   - DATA0 packet (0 byte)

This patch use both the length of DATA0 and qtd->isoc_split_offset
to check if the DATA0 is in the second transaction.

Signed-off-by: William Wu 
---
Changes in v2:
- Modify the commit message

  drivers/usb/dwc2/hcd_intr.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index 5e2378f..479f628 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -930,7 +930,7 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg 
*hsotg,
 frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
 len = dwc2_get_actual_xfer_length(hsotg, chan, chnum, qtd,
   DWC2_HC_XFER_COMPLETE, NULL);
-   if (!len) {
+   if (!len && !qtd->isoc_split_offset) {
 qtd->complete_split = 0;
 qtd->isoc_split_offset = 0;
 return 0;

I don't think my USB-fu is strong enough to do a real review of this
patch, but one small nitpick is that you can remove
"qtd->isoc_split_offset = 0" in the if test now.  AKA:

if (!len && !qtd->isoc_split_offset) {
   qtd->complete_split = 0;
   return 0;
}

Yes, good idea! I will fix it in next patch. Thank you!


...since you only enter the "if" test now when isoc_split_offset is
already 0...  Hopefully John Youn will have some time to comment on
this patch with more real USB knowledge...


-Doug


Best regards,
 wulf







Re: [PATCH 2/2] usb: dwc2: fix isoc split in transfer with no data

2018-04-24 Thread wlf

Dear Sergei,


在 2018年04月24日 16:27, Sergei Shtylyov 写道:

Hello!

On 4/24/2018 5:43 AM, William Wu wrote:


If isoc split in transfer with no data (the length of DATA0
packet is 0), we can't simply return immediately. Because the
DATA0 can be the first transaction or the second transaction for
the isoc split in transaction. If the DATA0 packet with on data

  ^^ no?

Thank you for correcting me. I will fix it in next patch version.



is in the first transaction, we can return immediately. But if
the the DATA0 packet with on data is in the second transaction


  One "the" too many. And that "on data" again... :-)
Ah, sorry to make such a simple mistake. I will fix these in next patch 
version.



of isoc split in transaction sequence, we need to increase the
qtd->isoc_frame_index and giveback urb to device driver if needed,
otherwise, the MDATA packet will be lost.

A typical test case is that connect the dwc2 controller with an
usb hs Hub (GL852G-12), and plug an usb fs audio device (Plantronics
headset) into the downstream port of Hub. Then use the usb mic
to record, we can find noise when playback.

In the case, the isoc split in transaction sequence like this:

- SSPLIT IN transaction
- CSPLIT IN transaction
   - MDATA packet (176 bytes)
- CSPLIT IN transaction
   - DATA0 packet (0 byte)

This patch use both the length of DATA0 and qtd->isoc_split_offset
to check if the DATA0 is in the second transaction.

Signed-off-by: William Wu 

[...]

MBR, Sergei

Best regards,
    wulf









Re: [PATCH v3 1/2] usb: dwc2: alloc dma aligned buffer for isoc split in

2018-05-09 Thread wlf

Dear Doug,

在 2018年05月08日 23:29, Doug Anderson 写道:

Hi,

On Tue, May 8, 2018 at 12:43 AM, wlf  wrote:

Dear Doug,

在 2018年05月08日 13:11, Doug Anderson 写道:

Hi,

On Mon, May 7, 2018 at 8:07 PM, William Wu 
wrote:

+static int dwc2_alloc_split_dma_aligned_buf(struct dwc2_hsotg *hsotg,
+   struct dwc2_qh *qh,
+   struct dwc2_host_chan *chan)
+{
+   if (!hsotg->unaligned_cache)
+   return -ENOMEM;
+
+   if (!qh->dw_align_buf) {
+   qh->dw_align_buf =
kmem_cache_alloc(hsotg->unaligned_cache,
+   GFP_ATOMIC |
GFP_DMA);
+   if (!qh->dw_align_buf)
+   return -ENOMEM;
+
+   qh->dw_align_buf_size = min_t(u32, chan->max_packet,
+
DWC2_KMEM_UNALIGNED_BUF_SIZE);

Rather than using min_t, wouldn't it be better to return -ENOMEM if
"max_packet" > DWC2_KMEM_UNALIGNED_BUF_SIZE?  As it is, you might
allocate less space than you need, right?  That seems like it would be
bad (even though this is probably impossible).

Yes, good idea! So is it good to fix it like this?

if (!qh->dw_align_buf || chan->max_packet >
 DWC2_KMEM_UNALIGNED_BUF_SIZE)
 return -ENOMEM;

qh->dw_align_buf_size = chan->max_packet;

Won't that orphan memory in the case that the allocation is OK but the
size is wrong?

I would have put it all the way at the top:

if (!hsotg->unaligned_cache ||
 chan->max_packet > DWC2_KMEM_UNALIGNED_BUF_SIZE)
   return -ENOMEM;

Ah, yes, you're right! Thank you for correcting me.


It also feels like you should get rid of "qh->dw_align_buf_size".  The
buffer is always DWC2_KMEM_UNALIGNED_BUF_SIZE.

...if you need to keep track of how many bytes you mapped with
dma_map_single() and somehow can't get back to "chan", rename this to
qh->dw_align_buf_mapped_bytes or something.  I haven't followed
through all the code, but I _think_ you'd want to make sure to set
qh->dw_align_buf_mapped_bytes every time through
dwc2_alloc_split_dma_aligned_buf(), even if dw_align_buf was already
allocated.  Specifically, my worry is in the case where you enter
dwc2_alloc_split_dma_aligned_buf() and qh->dw_align_buf is non-NULL.
Could "max_packet" be different in this case compared to what it was
when dw_align_buf was first allocated?
Sorry to make you feel confused. It's really not suitable to use 
"qh->dw_align_buf_size" for the dma mapped size. And I think the 
"max_packet" should be  always be the same. However, just in case, maybe 
I can get rid of "qh->dw_align_buf_size" and just use 
DWC2_KMEM_UNALIGNED_BUF_SIZE to do dma_map_single().




@@ -2797,6 +2837,32 @@ static int dwc2_assign_and_init_hc(struct
dwc2_hsotg *hsotg, struct dwc2_qh *qh)
  /* Set the transfer attributes */
  dwc2_hc_init_xfer(hsotg, chan, qtd);

+   /* For non-dword aligned buffers */
+   if (hsotg->params.host_dma && qh->do_split &&
+   chan->ep_is_in && (chan->xfer_dma & 0x3)) {
+   dev_vdbg(hsotg->dev, "Non-aligned buffer\n");
+   if (dwc2_alloc_split_dma_aligned_buf(hsotg, qh, chan)) {
+   dev_err(hsotg->dev,
+   "Failed to allocate memory to handle
non-aligned buffer\n");
+   /* Add channel back to free list */
+   chan->align_buf = 0;
+   chan->multi_count = 0;
+   list_add_tail(&chan->hc_list_entry,
+ &hsotg->free_hc_list);
+   qtd->in_process = 0;
+   qh->channel = NULL;
+   return -ENOMEM;
+   }
+   } else {
+   /*
+* We assume that DMA is always aligned in non-split
+* case or split out case. Warn if not.
+*/
+   WARN_ON_ONCE(hsotg->params.host_dma &&
+(chan->xfer_dma & 0x3));
+   chan->align_buf = 0;
+   }
+
  if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
  chan->ep_type == USB_ENDPOINT_XFER_ISOC)
  /*
@@ -5241,6 +5307,17 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
  hsotg->params.dma_desc_enable = false;
  hsotg->params.dma_desc_fs_enable = false;
  }
+   } else if (hsotg->params.host_dma) {

Are you sure this is "else if"?  Can't you have descriptor DMA enabled
in the controller and still need to do a normal DMA transfer if you
plug in a hub?  Seems like this should be just "if".

Sorry, I don't understand

Re: [PATCH v3 1/2] usb: dwc2: alloc dma aligned buffer for isoc split in

2018-05-11 Thread wlf

Dear Doug,


在 2018年05月11日 04:59, Doug Anderson 写道:

Hi,

On Wed, May 9, 2018 at 1:55 AM, wlf  wrote:

+   } else if (hsotg->params.host_dma) {

Are you sure this is "else if"?  Can't you have descriptor DMA enabled
in the controller and still need to do a normal DMA transfer if you
plug in a hub?  Seems like this should be just "if".

Sorry, I don't understand the case "have descriptor DMA enabled in the
controller and still need to do a normal DMA transfer". But maybe it
still
has another problem if just use "if" here, because it will create kmem
caches for Slave mode which actually doesn't need aligned DMA buf.

So right now your code looks like:

if (hsotg->params.dma_desc_enable ||
  hsotg->params.dma_desc_fs_enable) {
  ...
  ...
} else if (hsotg->params.host_dma) {
 ...
}


I've never played much with "descriptor DMA" on dwc2 because every
time I enabled it (last I tried was years ago) a whole bunch of
peripherals stopped working and I didn't dig (I just left it off).
Thus, I'm no expert on descriptor DMA.  ...that being said, my
understanding is that if you enable descriptor DMA in the controller
then it will enable a smarter DMA mode for some of the transfers.
IIRC Descriptor DMA mode specifically can't handle splits.  Is my
memory correct there?  Presumably that means that when you enable
descriptor DMA in the controller the driver will automatically fall
back to normal Address DMA mode if things get too complicated.  When
it falls back to Address DMA mode, presumably dwc2_hcd_init() won't
get called again.  That means that any data structures that are needed
for Address DMA need to be allocated in dwc2_hcd_init() even if
descriptor DMA is enabled because we might need to fall back to
Address DMA.

Thus, I'm suggesting changing the code to:

if (hsotg->params.dma_desc_enable ||
  hsotg->params.dma_desc_fs_enable) {
  ...
  ...
}

if (hsotg->params.host_dma) {
 ...
}


...as I said, I'm no expert and I could just be confused.  If
something I say seems wrong please correct me.

Ah, I got it. Thanks for your detailed explanation. Although I don't know if
it's possible that dwc2 driver automatically fall back to normal Address DMA
mode when desc DMA work abnormally with split, I agree with your suggestion.
I'll fix it in V4 patch.

Hmm, I guess you're right.  I did a quick search and I can't find any
evidence of a fallback like this.  Maybe I dreamed that.  I found some
old comment in the commit history that said:
I think you're right. I find that it's possible to fall back to Address 
DMA mode if desc DMA initialization failure. The error case is:in 
dwc2_hcd_init(),  if it fails to create dwc2 generic desc cache or dwc2 
hs isoc desc cache, then it will disable desc DMA and fall back to 
Address DMA mode.


/*
  * Disable descriptor dma mode by default as the HW can support
  * it, but does not support it for SPLIT transactions.
  * Disable it for FS devices as well.
  */

...and it looks there's currently nobody using descriptor DMA anyway
(assuming I read the code correctly).  It does seem like people were
ever going to turn it on then it would have to be dynamic as I was
dreaming it was...
Yes, the dwc2 desc DMA mode can't support split transaction. So few 
people use desc DMA mode for OTG Host mode. BTW, I find that the latest 
code enable desc DMA mode by default for the OTG peripheral mode if the 
dwc2 hardware support desc DMA.







Re: [PATCH v4 1/2] usb: dwc2: alloc dma aligned buffer for isoc split in

2018-05-11 Thread wlf

Dear Doug,

在 2018年05月11日 05:01, Doug Anderson 写道:

Hi,

On Wed, May 9, 2018 at 3:11 AM, William Wu  wrote:

The commit 3bc04e28a030 ("usb: dwc2: host: Get aligned DMA in
a more supported way") rips out a lot of code to simply the
allocation of aligned DMA. However, it also introduces a new
issue when use isoc split in transfer.

In my test case, I connect the dwc2 controller with an usb hs
Hub (GL852G-12), and plug an usb fs audio device (Plantronics
headset) into the downstream port of Hub. Then use the usb mic
to record, we can find noise when playback.

It's because that the usb Hub uses an MDATA for the first
transaction and a DATA0 for the second transaction for the isoc
split in transaction. An typical isoc split in transaction sequence
like this:

- SSPLIT IN transaction
- CSPLIT IN transaction
   - MDATA packet
- CSPLIT IN transaction
   - DATA0 packet

The DMA address of MDATA (urb->dma) is always DWORD-aligned, but
the DMA address of DATA0 (urb->dma + qtd->isoc_split_offset) may
not be DWORD-aligned, it depends on the qtd->isoc_split_offset (the
length of MDATA). In my test case, the length of MDATA is usually
unaligned, this cause DATA0 packet transmission error.

This patch use kmem_cache to allocate aligned DMA buf for isoc
split in transaction. Note that according to usb 2.0 spec, the
maximum data payload size is 1023 bytes for each fs isoc ep,
and the maximum allowable interrupt data payload size is 64 bytes
or less for fs interrupt ep. So we set the size of object to be
1024 bytes in the kmem cache.

Signed-off-by: William Wu 
---
Changes in v4:
- get rid of "qh->dw_align_buf_size"
- allocate unaligned_cache for Address DMA mode and Desc DMA mode
- freeing order opposite of allocation

You only did half of this.  You changed the order under "error4" but
forgot to make dwc2_hcd_remove() match.

Ah, sorry, I'm careless.




- do dma_map_single() with the size of DWC2_KMEM_UNALIGNED_BUF_SIZE

Changes in v3:
- Modify the commit message
- Use Kmem_cache to allocate aligned DMA buf
- Fix coding style

Changes in v2:
- None

  drivers/usb/dwc2/core.h  |  3 ++
  drivers/usb/dwc2/hcd.c   | 87 ++--
  drivers/usb/dwc2/hcd.h   |  8 
  drivers/usb/dwc2/hcd_intr.c  |  8 
  drivers/usb/dwc2/hcd_queue.c |  3 ++
  5 files changed, 105 insertions(+), 4 deletions(-)

My only remaining comment is a really nitty detail.  Unless someone
else feels strongly about it, I'm not sure it's worth spinning the
patch just for that nit unless someone else has review comments.

I believe I've looked at this enough to say:

Reviewed-by: Douglas Anderson 
Thank you very much for your review. I will submit V5 patches to fix the 
order of memory free in dwc2_hcd_remove(), and also add Review-by.









Re: [PATCH v2 1/2] usb: dwc2: alloc dma aligned buffer for isoc split in

2018-05-07 Thread wlf

Dear Doug,

在 2018年05月07日 15:19, Allen Hsu (許嘉銘) 写道:

Add more:


Best regards,
BU4 EE
Allen Hsu
QCI 886-3-327-2345 ext 15410

-Original Message-
From: Doug Anderson [mailto:diand...@google.com]
Sent: Friday, May 4, 2018 11:58 PM
To: wlf 
Cc: William Wu ; hmi...@synopsys.com; felipe.ba...@linux.intel.com; Greg Kroah-Hartman ; 
Sergei Shtylyov ; Heiko Stübner ; LKML ; 
linux-...@vger.kernel.org; open list:ARM/Rockchip SoC... ; Frank Wang ; 黄涛 
; daniel.meng ; John Youn ; 王征增 ; 
z...@rock-chips.com; Allen Hsu (許嘉銘) ; Stan Tsui 
Subject: Re: [PATCH v2 1/2] usb: dwc2: alloc dma aligned buffer for isoc split 
in

Hi,

On Wed, May 2, 2018 at 10:14 AM, wlf  wrote:

It's a good way to allocate an extra 3 bytes in the original bounce
buffer for this unaligned
issue, it's similar to the tailroom of sk_buff. However, just as you
said, we'd better find the special cases where we need an oversized
bounce buffer, otherwise,we
need to allocate
a bounce buffer for all of urbs.

It's hard for me to know the special cases in the
dwc2_alloc_dma_aligned_buffer(), because it's called from
usb_submit_urb() in the device class driver, and I hardly know the
split state in this process, much less if the split transaction need
aligned buffer. Do you have any idea?

I suppose that we can't find the special cases where we need an
oversized bounce buffer in the dwc2_alloc_dma_aligned_buffer(), and if
we still want to re-use the original bounce buffer with extra 3 bytes,
then we need to allocate a  bounce buffer for all of urbs, and do
unnecessary  data copy for these urbs  whose transfer_buffer were
already aligned.  This may reduce the transmission rate of USB.

Can we just pre-allocate an additional aligned buffer (the size is 200
bytes) for split transaction
in dwc2_map_urb_for_dma for all of urbs. And if we find the split
transaction is unaligned,
we can easily use the pre-allocated aligned buffer.

OK, so thinking about this more...

Previously things got really slow at interrupt time because we were trying to 
allocate as much as 64K at interrupt time.  That wasn't so great.  In your 
case, you're only allocating 200 bytes.  As I understand things, allocating 200 
bytes at interrupt time is probably not a huge deal.

...so I guess it come down to a tradeoff here: is it worth eating 200 bytes for 
each URB to save an 200 byte allocation at interrupt time in this one rare case.

I'd certainly welcome anyone's opinion here, but I'm going to go with saying 
it's fine to allocate the 200 bytes at interrupt time (like your patch does).  
...but, I _think_ you want to use
kmem_cache_create() to create a cache and then kmem_cache_zalloc().
Since all allocations are the same size and you want this to be fast, I think 
using kmem_cache is good.
Yes, it seems good to use kmem_cache. I'm trying to test a new patch 
with kmem_cache, and I will upstream v3 patch as soon as possible.

+   /* For non-dword aligned buffers */
+   if (hsotg->params.host_dma > 0 && qh->do_split &&
+   chan->ep_is_in && (chan->xfer_dma & 0x3)) {

So what happens if were unaligned (AKA (chan->xfer_dma & 0x3)) but
we're not doing split or it's not an IN EP?  Do we just fail then?

I guess the rest of this patch only handles the "in" case and maybe
you expect that the problems will only come about for do_split, but
it still might be wise to at least print a warning in the other cases?
>From reading dwc2_hc_init_xfer() it seems like you could run into 

this

same problem in the "out" case?

Actually, I only find non-dword aligned issue in the case of split in
transaction.
And I think that if we're not doing split or it's an OUT EP, we can
always get aligned buffer in the current code. For non-split case, the
dwc2_alloc_dma_aligned_buffer() is enough. And for split out case, if
the transaction is subdivided into multiple start-splits, each with a
data payload of 188 bytes or less, so the DMA address is always
aligned.

Can you at least print an error message if you end up with non-aligned DMA in 
one of the other cases?
That's an excellent suggestion. I will add warning message if end up 
with unexpected non-aligned DMA.

DMA_FROM_DEVICE);
+   memcpy(qtd->urb->buf + frame_desc->offset +
+  qtd->isoc_split_offset,
+ chan->qh->dw_align_buf,
len);

Assuming I'm understanding this patch correctly, I think it would be
better to write:

memcpy(qtd->xfer_dma, chan->qh->dw_align_buf, len);

Sorry, there's no "xfer_buf" in qtd, do you means the
"chan->xfer_dma"? If it's, I think we can't do memcpy from a transfer
buffer to a DMA address. Maybe chan->xfer_buf is more suitable, but it
seems that the dwc2 driver doesn't update the chan->xfer_buf for isoc
transfer with dma enabl

Re: [PATCH v3 2/2] usb: dwc2: fix isoc split in transfer with no data

2018-05-08 Thread wlf

Dear Doug,

在 2018年05月08日 13:13, Doug Anderson 写道:

Hi,

On Mon, May 7, 2018 at 8:07 PM, William Wu  wrote:

If isoc split in transfer with no data (the length of DATA0
packet is zero), we can't simply return immediately. Because
the DATA0 can be the first transaction or the second transaction
for the isoc split in transaction. If the DATA0 packet with no
data is in the first transaction, we can return immediately.
But if the DATA0 packet with no data is in the second transaction
of isoc split in transaction sequence, we need to increase the
qtd->isoc_frame_index and giveback urb to device driver if needed,
otherwise, the MDATA packet will be lost.

A typical test case is that connect the dwc2 controller with an
usb hs Hub (GL852G-12), and plug an usb fs audio device (Plantronics
headset) into the downstream port of Hub. Then use the usb mic
to record, we can find noise when playback.

In the case, the isoc split in transaction sequence like this:

- SSPLIT IN transaction
- CSPLIT IN transaction
   - MDATA packet (176 bytes)
- CSPLIT IN transaction
   - DATA0 packet (0 byte)

This patch use both the length of DATA0 and qtd->isoc_split_offset
to check if the DATA0 is in the second transaction.

Signed-off-by: William Wu 
---
Changes in v3:
- Remove "qtd->isoc_split_offset = 0" in the if test

Changes in v2:
- Modify the commit message

  drivers/usb/dwc2/hcd_intr.c | 3 +--
  1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index ba6fd852..3003594 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -930,9 +930,8 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg 
*hsotg,
 frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
 len = dwc2_get_actual_xfer_length(hsotg, chan, chnum, qtd,
   DWC2_HC_XFER_COMPLETE, NULL);
-   if (!len) {
+   if (!len && !qtd->isoc_split_offset) {
 qtd->complete_split = 0;
-   qtd->isoc_split_offset = 0;
 return 0;
 }

This looks fine to me now, but as per my comments on the previous
version I don't think I've dug through this problem enough to add my
Reviewed-by tag.  I'll assume that John or someone with more knowledge
of the USB protocol than I have will Review / Ack.

Thanks very much for your review. Let's wait for other experts' suggestion.


-Doug








Re: [PATCH v3 1/2] usb: dwc2: alloc dma aligned buffer for isoc split in

2018-05-08 Thread wlf

Dear Doug,

在 2018年05月08日 13:11, Doug Anderson 写道:

Hi,

On Mon, May 7, 2018 at 8:07 PM, William Wu  wrote:

+static int dwc2_alloc_split_dma_aligned_buf(struct dwc2_hsotg *hsotg,
+   struct dwc2_qh *qh,
+   struct dwc2_host_chan *chan)
+{
+   if (!hsotg->unaligned_cache)
+   return -ENOMEM;
+
+   if (!qh->dw_align_buf) {
+   qh->dw_align_buf = kmem_cache_alloc(hsotg->unaligned_cache,
+   GFP_ATOMIC | GFP_DMA);
+   if (!qh->dw_align_buf)
+   return -ENOMEM;
+
+   qh->dw_align_buf_size = min_t(u32, chan->max_packet,
+ DWC2_KMEM_UNALIGNED_BUF_SIZE);

Rather than using min_t, wouldn't it be better to return -ENOMEM if
"max_packet" > DWC2_KMEM_UNALIGNED_BUF_SIZE?  As it is, you might
allocate less space than you need, right?  That seems like it would be
bad (even though this is probably impossible).

Yes, good idea! So is it good to fix it like this?

if (!qh->dw_align_buf || chan->max_packet >
DWC2_KMEM_UNALIGNED_BUF_SIZE)
return -ENOMEM; 

qh->dw_align_buf_size = chan->max_packet;




@@ -2797,6 +2837,32 @@ static int dwc2_assign_and_init_hc(struct dwc2_hsotg 
*hsotg, struct dwc2_qh *qh)
 /* Set the transfer attributes */
 dwc2_hc_init_xfer(hsotg, chan, qtd);

+   /* For non-dword aligned buffers */
+   if (hsotg->params.host_dma && qh->do_split &&
+   chan->ep_is_in && (chan->xfer_dma & 0x3)) {
+   dev_vdbg(hsotg->dev, "Non-aligned buffer\n");
+   if (dwc2_alloc_split_dma_aligned_buf(hsotg, qh, chan)) {
+   dev_err(hsotg->dev,
+   "Failed to allocate memory to handle non-aligned 
buffer\n");
+   /* Add channel back to free list */
+   chan->align_buf = 0;
+   chan->multi_count = 0;
+   list_add_tail(&chan->hc_list_entry,
+ &hsotg->free_hc_list);
+   qtd->in_process = 0;
+   qh->channel = NULL;
+   return -ENOMEM;
+   }
+   } else {
+   /*
+* We assume that DMA is always aligned in non-split
+* case or split out case. Warn if not.
+*/
+   WARN_ON_ONCE(hsotg->params.host_dma &&
+(chan->xfer_dma & 0x3));
+   chan->align_buf = 0;
+   }
+
 if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
 chan->ep_type == USB_ENDPOINT_XFER_ISOC)
 /*
@@ -5241,6 +5307,17 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
 hsotg->params.dma_desc_enable = false;
 hsotg->params.dma_desc_fs_enable = false;
 }
+   } else if (hsotg->params.host_dma) {

Are you sure this is "else if"?  Can't you have descriptor DMA enabled
in the controller and still need to do a normal DMA transfer if you
plug in a hub?  Seems like this should be just "if".
Sorry, I don't understand the case "have descriptor DMA enabled in the 
controller and still need to do a normal DMA transfer". But maybe it 
still has another problem if just use "if" here, because it will create 
kmem caches for Slave mode which actually doesn't need aligned DMA buf.




+   /*
+* Create kmem caches to handle non-aligned buffer
+* in Buffer DMA mode.
+*/
+   hsotg->unaligned_cache = kmem_cache_create("dwc2-unaligned-dma",
+   DWC2_KMEM_UNALIGNED_BUF_SIZE, 4,

Worth using "DWC2_USB_DMA_ALIGN" rather than 4?



+   SLAB_CACHE_DMA, NULL);
+   if (!hsotg->unaligned_cache)
+   dev_err(hsotg->dev,
+   "unable to create dwc2 unaligned cache\n");
 }

 hsotg->otg_port = 1;
@@ -5279,6 +5356,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
  error4:
 kmem_cache_destroy(hsotg->desc_gen_cache);
 kmem_cache_destroy(hsotg->desc_hsisoc_cache);
+   kmem_cache_destroy(hsotg->unaligned_cache);

nitty nit: freeing order should be opposite of allocation, so the new
line should be above the other two.
Ah, I got it. But note that it's impossible to allocate the 
"unaligned_cache" and "desc *cache" at the same time. Should we still 
fix the free order? If yes, maybe the correct free order is:


kmem_cache_destroy(hsotg->unaligned_cache);
kmem_cache_destroy(hsotg->desc_hsisoc_cache);
kmem_cache_destroy(hsotg->desc_gen_cache);

Right?

And should we also need to fix the same free order in the "dwc2_hcd_remove"?
Best regards,
        wulf








Re: [PATCH] usb: hcd: initialize hcd->flags to 0 when rm hcd

2017-01-12 Thread wlf

Hi Roger,

在 2017年01月12日 23:38, Roger Quadros 写道:

On 12/01/17 17:33, Alan Stern wrote:

On Thu, 12 Jan 2017, Roger Quadros wrote:


William,

On 12/01/17 14:03, William Wu wrote:

From: William wu 

On some platforms(e.g. rk3399 board), we can call hcd_add/remove
consecutively without calling usb_put_hcd/usb_create_hcd in between,
so hcd->flags can be stale.

If the HC dies due to whatever reason then without this patch we get
the below error on next hcd_add.

[173.296154] xhci-hcd xhci-hcd.2.auto: HC died; cleaning up
[173.296209] xhci-hcd xhci-hcd.2.auto: xHCI Host Controller
[173.296762] xhci-hcd xhci-hcd.2.auto: new USB bus registered, assigned bus 
number 6
[173.296931] usb usb6: We don't know the algorithms for LPM for this host, 
disabling LPM.
[173.297179] usb usb6: New USB device found, idVendor=1d6b, idProduct=0003
[173.297203] usb usb6: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[173.297222] usb usb6: Product: xHCI Host Controller
[173.297240] usb usb6: Manufacturer: Linux 4.4.21 xhci-hcd
[173.297257] usb usb6: SerialNumber: xhci-hcd.2.auto
[173.298680] hub 6-0:1.0: USB hub found
[173.298749] hub 6-0:1.0: 1 port detected
[173.299382] rockchip-dwc3 usb@fe80: USB HOST connected
[173.395418] hub 5-0:1.0: activate --> -19
[173.603447] irq 228: nobody cared (try booting with the "irqpoll" option)
[173.603493] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 4.4.21 #9
[173.603513] Hardware name: Google Kevin (DT)
[173.603531] Call trace:
[173.603568] [] dump_backtrace+0x0/0x160
[173.603596] [] show_stack+0x20/0x28
[173.603623] [] dump_stack+0x90/0xb0
[173.603650] [] __report_bad_irq+0x48/0xe8
[173.603674] [] note_interrupt+0x1e8/0x28c
[173.603698] [] handle_irq_event_percpu+0x1d4/0x25c
[173.603722] [] handle_irq_event+0x4c/0x7c
[173.603748] [] handle_fasteoi_irq+0xb4/0x124
[173.603777] [] generic_handle_irq+0x30/0x44
[173.603804] [] __handle_domain_irq+0x90/0xbc
[173.603827] [] gic_handle_irq+0xcc/0x188
...
[173.604500] [] el1_irq+0x80/0xf8
[173.604530] [] cpu_startup_entry+0x38/0x3cc
[173.604558] [] rest_init+0x8c/0x94
[173.604585] [] start_kernel+0x3d0/0x3fc
[173.604607] [<00b16000>] 0xb16000
[173.604622] handlers:
[173.604648] [] usb_hcd_irq
[173.604673] Disabling IRQ #228

Signed-off-by: William wu 
Signed-off-by: William wu 
---
  drivers/usb/core/hcd.c | 1 +
  1 file changed, 1 insertion(+)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 479e223..612fab6 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -3017,6 +3017,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
}
  
  	usb_put_invalidate_rhdev(hcd);

+   hcd->flags = 0;
  }
  EXPORT_SYMBOL_GPL(usb_remove_hcd);
  


I suggest to initialize hcd->flags to 0 in usb_add_hcd() instead.

cheers,
-roger

Roger, didn't you originally propose this very same patch in

http://marc.info/?l=linux-usb&m=146556415503583&w=2

(and of course, the earlier versions before v10)?  What happened to it?

Alan, You are right. That patch got lost in the ML. Looks like I didn't push it 
hard enough
and then forgot about it. Sorry.

William,

You don't need to do any changes. My earlier version was clearing the flag
in usb_add_hcd() and I guess Alan suggested to move it to usb_remove_hcd().

So your patch is good.
You can add my.

Acked-by: Roger Quadros 

cheers,
-roger

Thanks very much for your suggestion,I  will add acked-by immediately.









Re: [PATCH] usb: host: xhci: plat: check hcc_params after add hcd

2017-01-15 Thread wlf

Hi Roger,

在 2017年01月13日 19:02, Roger Quadros 写道:

Hi,

On 13/01/17 05:18, William Wu wrote:

From: William wu 

The commit 4ac53087d6d4 ("usb: xhci: plat: Create both
HCDs before adding them") move add hcd to the end of
probe, this cause hcc_params uninitiated, because xHCI
driver sets hcc_params in xhci_gen_setup() called from
usb_add_hcd().

This patch checks the Maximum Primary Stream Array Size
in the hcc_params register after add hcd.

Signed-off-by: William wu 
---
  drivers/usb/host/xhci-plat.c | 6 +++---
  1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index ddfab30..52ce697 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -232,9 +232,6 @@ static int xhci_plat_probe(struct platform_device *pdev)
if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable"))
xhci->quirks |= XHCI_LPM_SUPPORT;
  
-	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)

-   xhci->shared_hcd->can_do_streams = 1;
-
hcd->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
if (IS_ERR(hcd->usb_phy)) {
ret = PTR_ERR(hcd->usb_phy);
@@ -255,6 +252,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
if (ret)
goto dealloc_usb2_hcd;
  
+	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)

+   xhci->shared_hcd->can_do_streams = 1;
+

xhci->hcc_params is initialized after the first usb_add_hcd().
Should this bit come before the usb_add_hcd(xhci->shared_hcd,..)?

Yes, good idea!I will move it behind the first usb_add_hcd().


You will also need to copy to v4.2+ . Thanks.

OK, thank you for reminding me!



return 0;
  
  


cheers,
-roger








Re: linux-next: build warning after merge of the phy-next tree

2016-11-16 Thread wlf

Hi Stephen,

在 2016年11月16日 11:00, Stephen Rothwell 写道:

Hi Kishon,

After merging the phy-next tree, today's linux-next build (x86_64
allmodconfig) produced this warning:

drivers/phy/phy-rockchip-inno-usb2.c: In function 'rockchip_chg_detect_work':
drivers/phy/phy-rockchip-inno-usb2.c:717:7: warning: 'tmout' may be used 
uninitialized in this function [-Wmaybe-uninitialized]
 if (tmout) {
^

Introduced by commit

   0c42fe48fd23 ("phy: rockchip-inno-usb2: support otg-port for rk3399")
The variable "tmout" is initialized in the prior  code "case 
USB_CHG_STATE_WAIT_FOR_DCD",
and this case will be executed before "if (tmout)", so I think it's a 
mis-warning for some

special compiler.

Could you provide me some suggestion about this warning? Should I upload 
a new patch to

fix this compiler mis-warning or just ignore it ? :-)

Best regards,
 wulf








Re: [PATCH 1/2] phy: rockchip-inno-usb2: fix uninitialized tmout variable

2016-11-17 Thread wlf

Hi Arnd,

在 2016年11月16日 22:22, Arnd Bergmann 写道:

The newly added OTG support has an obvious uninitialized variable
access that gcc warns about:

drivers/phy/phy-rockchip-inno-usb2.c: In function 'rockchip_chg_detect_work':
drivers/phy/phy-rockchip-inno-usb2.c:717:7: error: 'tmout' may be used 
uninitialized in this function [-Werror=maybe-uninitialized]

This replaces the use of the uninitialized variable with what
the value was in the previous USB_CHG_STATE_WAIT_FOR_DCD
state.

Fixes: 0c42fe48fd23 ("phy: rockchip-inno-usb2: support otg-port for rk3399")
Signed-off-by: Arnd Bergmann 
---
  drivers/phy/phy-rockchip-inno-usb2.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/phy/phy-rockchip-inno-usb2.c 
b/drivers/phy/phy-rockchip-inno-usb2.c
index eb89de59b68f..2f99ec95079c 100644
--- a/drivers/phy/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/phy-rockchip-inno-usb2.c
@@ -714,7 +714,7 @@ static void rockchip_chg_detect_work(struct work_struct 
*work)
delay = CHG_SECONDARY_DET_TIME;
rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE;
} else {
-   if (tmout) {
+   if (rphy->dcd_retries == CHG_DCD_MAX_RETRIES) {
/* floating charger found */
rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
rphy->chg_state = USB_CHG_STATE_DETECTED;

Thanks very much for your help.

Reviewed-by: William Wu 

Best Regards,
  wulf






Re: [PATCH v2 1/2] phy: rockchip-inno-usb2: correct clk_ops callback

2016-11-14 Thread wlf

Hi Doug,

在 2016年11月15日 02:15, Doug Anderson 写道:

William

On Sun, Nov 13, 2016 at 11:01 PM, William Wu  wrote:

Since we needs to delay ~1ms to wait for 480MHz output clock
of USB2 PHY to become stable after turn on it, the delay time
is pretty long for something that's supposed to be "atomic"
like a clk_enable(). Consider that clk_enable() will disable
interrupt and that a 1ms interrupt latency is not sensible.

The 480MHz output clock should be handled in prepare callbacks
which support gate a clk if the operation may sleep.

Signed-off-by: William Wu 
---
  drivers/phy/phy-rockchip-inno-usb2.c | 12 ++--
  1 file changed, 6 insertions(+), 6 deletions(-)

Reviewed-by: Douglas Anderson 


Thanks! I'll add  Reviewed-by.









Re: [PATCH v3 2/2] phy: rockchip-inno-usb2: correct 480MHz output clock stable time

2016-11-14 Thread wlf

Hi Doug,

在 2016年11月15日 02:17, Doug Anderson 写道:

William,

On Mon, Nov 14, 2016 at 1:27 AM, William Wu  wrote:

We found that the system crashed due to 480MHz output clock of
USB2 PHY was unstable after clock had been enabled by gpu module.

Theoretically, 1 millisecond is a critical value for 480MHz
output clock stable time, so we try to change the delay time
to 1.2 millisecond to avoid this issue.

And the commit ed907fb1d7c3 ("phy: rockchip-inno-usb2: correct
clk_ops callback") used prepare callbacks instead of enable
callbacks to support gate a clk if the operation may sleep. So
we can switch from delay to sleep functions.

Signed-off-by: William Wu 
---
Changes in v3:
- fix kbuild test error: too few arguments to function 'usleep_range'

Changes in v2:
- use usleep_range() function instead of mdelay()

  drivers/phy/phy-rockchip-inno-usb2.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/phy/phy-rockchip-inno-usb2.c 
b/drivers/phy/phy-rockchip-inno-usb2.c
index 365e077..0e52b25 100644
--- a/drivers/phy/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/phy-rockchip-inno-usb2.c
@@ -166,7 +166,7 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw 
*hw)
 return ret;

 /* waitting for the clk become stable */
-   mdelay(1);
+   usleep_range(1200, 1300);

Sight nit that you could also fix the spelling from "waitting" to "waiting".

...but that's pre-existing, so:

Reviewed-by: Douglas Anderson 

Thanks! I'll add  Reviewed-by and fix the spelling issue.









Re: [PATCH] phy: rockchip-inno-usb2: correct 480MHz output clock stable time

2016-11-09 Thread wlf

Hi Doug,

在 2016年11月10日 04:54, Doug Anderson 写道:

Hi,

On Mon, Nov 7, 2016 at 5:00 AM, William Wu  wrote:

We found that the system crashed due to 480MHz output clock of
USB2 PHY was unstable after clock had been enabled by gpu module.

Theoretically, 1 millisecond is a critical value for 480MHz
output clock stable time, so we try to change the delay time
to 1.2 millisecond to avoid this issue.

Signed-off-by: William Wu 
---
  drivers/phy/phy-rockchip-inno-usb2.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/phy/phy-rockchip-inno-usb2.c 
b/drivers/phy/phy-rockchip-inno-usb2.c
index ecfd7d1..8f2d2b6 100644
--- a/drivers/phy/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/phy-rockchip-inno-usb2.c
@@ -267,7 +267,7 @@ static int rockchip_usb2phy_clk480m_enable(struct clk_hw 
*hw)
 return ret;

 /* waitting for the clk become stable */
-   mdelay(1);
+   udelay(1200);

Several people who have seen this patch have expressed concern that a
1.2 ms delay is pretty long for something that's supposed to be
"atomic" like a clk_enable().  Consider that someone might call
clk_enable() while interrupts are disabled and that a 1.2 ms interrupt
latency is not so great.

It seems like this clock should be moved to be enabled in "prepare"
and the "enable" should be a no-op.  This is a functionality change,
but I don't think there are any real users for this clock at the
moment so it should be fine.

(of course, the 1 ms latency that existed before this patch was still
pretty bad, but ...)

Thanks a lot for your suggestion.
I agree with you.  clk_enable() will call spin_lock_irqsave() to disable 
interrupt, and we add

more than 1ms in clk_enable may cause big latency.

And according to clk_prepare() description:
 In a simple case, clk_prepare can be used instead of clk_enable to 
ungate a clk if the

 operation may sleep.  One example is a clk which is accessed over I2c.

So maybe we can remove the clock to clk_prepare.

Hi Heiko, Frank,
   What  do you think of it?

Best regards,
wulf


-Doug








Re: [PATCH] phy: rockchip-inno-usb2: correct 480MHz output clock stable time

2016-11-10 Thread wlf

Hi Heiko,

在 2016年11月10日 17:21, Heiko Stübner 写道:

Am Donnerstag, 10. November 2016, 10:54:49 schrieb wlf:

Hi Doug,

在 2016年11月10日 04:54, Doug Anderson 写道:

Hi,

On Mon, Nov 7, 2016 at 5:00 AM, William Wu  wrote:

We found that the system crashed due to 480MHz output clock of
USB2 PHY was unstable after clock had been enabled by gpu module.

Theoretically, 1 millisecond is a critical value for 480MHz
output clock stable time, so we try to change the delay time
to 1.2 millisecond to avoid this issue.

Signed-off-by: William Wu 
---

   drivers/phy/phy-rockchip-inno-usb2.c | 2 +-
   1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/phy/phy-rockchip-inno-usb2.c
b/drivers/phy/phy-rockchip-inno-usb2.c index ecfd7d1..8f2d2b6 100644
--- a/drivers/phy/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/phy-rockchip-inno-usb2.c
@@ -267,7 +267,7 @@ static int rockchip_usb2phy_clk480m_enable(struct
clk_hw *hw)>>
  return ret;
  
  /* waitting for the clk become stable */


-   mdelay(1);
+   udelay(1200);

Several people who have seen this patch have expressed concern that a
1.2 ms delay is pretty long for something that's supposed to be
"atomic" like a clk_enable().  Consider that someone might call
clk_enable() while interrupts are disabled and that a 1.2 ms interrupt
latency is not so great.

It seems like this clock should be moved to be enabled in "prepare"
and the "enable" should be a no-op.  This is a functionality change,
but I don't think there are any real users for this clock at the
moment so it should be fine.

(of course, the 1 ms latency that existed before this patch was still
pretty bad, but ...)

Thanks a lot for your suggestion.
I agree with you.  clk_enable() will call spin_lock_irqsave() to disable
interrupt, and we add
more than 1ms in clk_enable may cause big latency.

And according to clk_prepare() description:
   In a simple case, clk_prepare can be used instead of clk_enable to
ungate a clk if the
   operation may sleep.  One example is a clk which is accessed over I2c.

So maybe we can remove the clock to clk_prepare.

Hi Heiko, Frank,
 What  do you think of it?

moving to clk_prepare sounds sensible. That way you can switch from delay to
sleep functions as well.

Thanks very much.
I will try to update a new patch.

Best regards,
 Wulf




Heiko








Re: [RESEND PATCH v2] arm64: dts: rockchip: add u2phy clock for ehci and ohci of rk3399

2016-12-22 Thread wlf

Dear Doug & Xing Zheng,

在 2016年12月22日 08:47, Doug Anderson 写道:

Hi,

On Wed, Dec 21, 2016 at 2:41 AM, Xing Zheng  wrote:

From: William wu 

We found that the suspend process was blocked when it run into
ehci/ohci module due to clk-480m of usb2-phy was disabled.

The root cause is that usb2-phy suspended earlier than ehci/ohci
(usb2-phy will be auto suspended if no devices plug-in). and the
clk-480m provided by it was disabled if no module used. However,

I suggest that change the "clk-480m" to "utmi clock" here.


some suspend process related ehci/ohci are base on this clock,
so we should refer it into ehci/ohci driver to prevent this case.

The u2phy clock flow like this:
===
   u2phy 
|||-> UTMI_CLK -> | EHCI |
OSC_24M ---|---> PHY_PLL||
|^___||-> 480M_CLK ---|G|---> | USBPHY_480M_SRC| 
> USBPHY_480M for SoC
 |
 |
GRF
===

Signed-off-by: William wu 
Signed-off-by: Xing Zheng 
---

Changes in v2:
- update the commit message
- remove patches whic add and export the USBPHYx_480M_SRC clock IDs

  arch/arm64/boot/dts/rockchip/rk3399.dtsi | 28 
  1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index b65c193..2ad9255 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -315,8 +315,10 @@
 compatible = "generic-ehci";
 reg = <0x0 0xfe38 0x0 0x2>;
 interrupts = ;
-   clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>;
-   clock-names = "hclk_host0", "hclk_host0_arb";
+   clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>,
+<&u2phy0>;
+   clock-names = "usbhost", "arbiter",
+ "utmi";
 phys = <&u2phy0_host>;
 phy-names = "usb";
 status = "disabled";
@@ -326,8 +328,12 @@
 compatible = "generic-ohci";
 reg = <0x0 0xfe3a 0x0 0x2>;
 interrupts = ;
-   clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>;
-   clock-names = "hclk_host0", "hclk_host0_arb";
+   clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST0_ARB>,
+<&u2phy0>;
+   clock-names = "usbhost", "arbiter",
+ "utmi";
+   phys = <&u2phy0_host>;
+   phy-names = "usb";
 status = "disabled";
 };

@@ -335,8 +341,10 @@
 compatible = "generic-ehci";
 reg = <0x0 0xfe3c 0x0 0x2>;
 interrupts = ;
-   clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>;
-   clock-names = "hclk_host1", "hclk_host1_arb";
+   clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>,
+<&u2phy1>;
+   clock-names = "usbhost", "arbiter",
+ "utmi";
 phys = <&u2phy1_host>;
 phy-names = "usb";
 status = "disabled";
@@ -346,8 +354,12 @@
 compatible = "generic-ohci";
 reg = <0x0 0xfe3e 0x0 0x2>;
 interrupts = ;
-   clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>;
-   clock-names = "hclk_host1", "hclk_host1_arb";
+   clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST1_ARB>,
+<&u2phy1>;
+   clock-names = "usbhost", "arbiter",
+ "utmi";
+   phys = <&u2phy1_host>;
+   phy-names = "usb";

This all looks better to me.  From a device tree point of view it
makes lots of sense to expose this PHY clock to the controller.  Thus:

Reviewed-by: Douglas Anderson 


I can't say that I understand all the interactions between the PHY
code and the USB driver, but presumably others have reviewed that
more?  Offline Heiko pointed me at rockchip_usb2phy_otg_sm_work()
which apparently calls rockchip_usb2phy_power_off() and
rockchip_usb2phy_power_on() directly sometimes behind the back of the
PHY framework.  Very strange.


Yes, the rockchip_usb2phy_otg_sm_work() in the USB2 PHY driver and 
EHCI/OHCI platform
driver via the PHY framework can both do phy power on/off.  We do that 
because we want

to reduce USB2 PHY consumption in system runtime and deep sleep.

For EHCI/OHCI platform drivers, they call phy_power_on() in probe to 
power on USB2 PHY,
and don't power off USB2 PHY in system runtime, even if there's no USB2 
device connected.
They just call phy_power_off() in PM suspend, and call phy_power_on() in 
PM resume to
power on USB2 PHY again. AKA the EHCI/OHCI platform driver can only 
support USB power

management in deep s

Re: [PATCH v2 1/2] phy: rockchip-inno-usb2: support otg-port for rk3399

2016-11-04 Thread wlf

Hi Kishon,

在 2016年11月04日 01:17, Kishon Vijay Abraham I 写道:


On Thursday 03 November 2016 07:36 AM, William Wu wrote:

The rk3399 SoC USB2 PHY is comprised of one Host port and
one OTG port. And OTG port is for USB2.0 part of USB3.0 OTG
controller, as a part to construct a fully feature Type-C
subsystem.

With this patch, we can support OTG port with the following
functions:
- Support BC1.2 charger detect, and use extcon notifier to
   send USB charger types to power driver.
- Support PHY suspend for power management.
- Support OTG Host only mode.

Also, correct 480MHz output clock stable time. We found that
the system crashed due to 480MHz output clock of USB2 PHY was
unstable after clock had been enabled by gpu module.

Can you split the clock fix into a separate patch?

OK, I will separate the clock patch in next version.

Best regards,
 wulf


Thanks
Kishon

Theoretically, 1 millisecond is a critical value for 480 output
clock stable time, so we try changing the delay time to 1.2
millisecond to avoid this issue.

Signed-off-by: William Wu 
---
Changes in v2:
- remove wakelock

  drivers/phy/phy-rockchip-inno-usb2.c | 593 +--
  1 file changed, 562 insertions(+), 31 deletions(-)

diff --git a/drivers/phy/phy-rockchip-inno-usb2.c 
b/drivers/phy/phy-rockchip-inno-usb2.c
index ac20310..8f2d2b6 100644
--- a/drivers/phy/phy-rockchip-inno-usb2.c
+++ b/drivers/phy/phy-rockchip-inno-usb2.c
@@ -17,6 +17,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -30,11 +31,15 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
+#include 
+#include 
  
  #define BIT_WRITEABLE_SHIFT	16

-#define SCHEDULE_DELAY (60 * HZ)
+#define SCHEDULE_DELAY (60 * HZ)
+#define OTG_SCHEDULE_DELAY (2 * HZ)
  
  enum rockchip_usb2phy_port_id {

USB2PHY_PORT_OTG,
@@ -49,6 +54,37 @@ enum rockchip_usb2phy_host_state {
PHY_STATE_FS_LS_ONLINE  = 4,
  };
  
+/**

+ * Different states involved in USB charger detection.
+ * USB_CHG_STATE_UNDEFINED USB charger is not connected or detection
+ * process is not yet started.
+ * USB_CHG_STATE_WAIT_FOR_DCD  Waiting for Data pins contact.
+ * USB_CHG_STATE_DCD_DONE  Data pin contact is detected.
+ * USB_CHG_STATE_PRIMARY_DONE  Primary detection is completed (Detects
+ * between SDP and DCP/CDP).
+ * USB_CHG_STATE_SECONDARY_DONESecondary detection is completed 
(Detects
+ * between DCP and CDP).
+ * USB_CHG_STATE_DETECTED  USB charger type is determined.
+ */
+enum usb_chg_state {
+   USB_CHG_STATE_UNDEFINED = 0,
+   USB_CHG_STATE_WAIT_FOR_DCD,
+   USB_CHG_STATE_DCD_DONE,
+   USB_CHG_STATE_PRIMARY_DONE,
+   USB_CHG_STATE_SECONDARY_DONE,
+   USB_CHG_STATE_DETECTED,
+};
+
+static const unsigned int rockchip_usb2phy_extcon_cable[] = {
+   EXTCON_USB,
+   EXTCON_USB_HOST,
+   EXTCON_CHG_USB_SDP,
+   EXTCON_CHG_USB_CDP,
+   EXTCON_CHG_USB_DCP,
+   EXTCON_CHG_USB_SLOW,
+   EXTCON_NONE,
+};
+
  struct usb2phy_reg {
unsigned intoffset;
unsigned intbitend;
@@ -58,19 +94,55 @@ struct usb2phy_reg {
  };
  
  /**

+ * struct rockchip_chg_det_reg: usb charger detect registers
+ * @cp_det: charging port detected successfully.
+ * @dcp_det: dedicated charging port detected successfully.
+ * @dp_det: assert data pin connect successfully.
+ * @idm_sink_en: open dm sink curren.
+ * @idp_sink_en: open dp sink current.
+ * @idp_src_en: open dm source current.
+ * @rdm_pdwn_en: open dm pull down resistor.
+ * @vdm_src_en: open dm voltage source.
+ * @vdp_src_en: open dp voltage source.
+ * @opmode: utmi operational mode.
+ */
+struct rockchip_chg_det_reg {
+   struct usb2phy_reg  cp_det;
+   struct usb2phy_reg  dcp_det;
+   struct usb2phy_reg  dp_det;
+   struct usb2phy_reg  idm_sink_en;
+   struct usb2phy_reg  idp_sink_en;
+   struct usb2phy_reg  idp_src_en;
+   struct usb2phy_reg  rdm_pdwn_en;
+   struct usb2phy_reg  vdm_src_en;
+   struct usb2phy_reg  vdp_src_en;
+   struct usb2phy_reg  opmode;
+};
+
+/**
   * struct rockchip_usb2phy_port_cfg: usb-phy port configuration.
   * @phy_sus: phy suspend register.
+ * @bvalid_det_en: vbus valid rise detection enable register.
+ * @bvalid_det_st: vbus valid rise detection status register.
+ * @bvalid_det_clr: vbus valid rise detection clear register.
   * @ls_det_en: linestate detection enable register.
   * @ls_det_st: linestate detection state register.
   * @ls_det_clr: linestate detection clear register.
+ * @utmi_avalid: utmi vbus avalid status register.
+ * @utmi_bvalid: utmi vbus bvalid status register.
   * @utmi_ls: utmi linestate state register.
   * @utmi_hstdet: utmi host disconnect register.
   */
  struct rockchip_usb2phy_port_cfg {
struct usb2phy_reg  phy_sus;
+   str

Re: [PATCH v2] usb: dwc3: add disable u2mac linestate check quirk

2017-04-18 Thread wlf

Dear Guenter,


在 2017年04月18日 21:18, Guenter Roeck 写道:

On Mon, Apr 17, 2017 at 10:17 PM, William Wu  wrote:

This patch adds a quirk to disable USB 2.0 MAC linestate check
during HS transmit. Refer the dwc3 databook, we can use it for
some special platforms if the linestate not reflect the expected
line state(J) during transmission.

When use this quirk, the controller implements a fixed 40-bit
TxEndDelay after the packet is given on UTMI and ignores the
linestate during the transmit of a token (during token-to-token
and token-to-data IPGAP).

On some rockchip platforms (e.g. rk3399), it requires to disable
the u2mac linestate check to decrease the SSPLIT token to SETUP
token inter-packet delay from 566ns to 466ns, and fix the issue
that FS/LS devices not recognized if inserted through USB 3.0 HUB.

Signed-off-by: William Wu 
---
Changes in v2:
- fix coding style

  Documentation/devicetree/bindings/usb/dwc3.txt |  2 ++
  drivers/usb/dwc3/core.c| 14 ++
  drivers/usb/dwc3/core.h|  4 
  3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt 
b/Documentation/devicetree/bindings/usb/dwc3.txt
index f658f39..6a89f0c 100644
--- a/Documentation/devicetree/bindings/usb/dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/dwc3.txt
@@ -45,6 +45,8 @@ Optional properties:
 a free-running PHY clock.
   - snps,dis-del-phy-power-chg-quirk: when set core will change PHY power
 from P0 to P1/P2/P3 without delay.
+ - snps,tx-ipgap-linecheck-dis-quirk: when set, disable u2mac linestate check
+   during HS transmit.

All other disable-something quirks are named
"snps,dis-something-quirk". Maybe use the same naming convention ?
Yes, good idea! I will fix it with "snps,dis-tx-ipgap-linecheck-quirk"  
in next patch verison.

Thanks:-)



   - snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
 utmi_l1_suspend_n, false when asserts utmi_sleep_n
   - snps,hird-threshold: HIRD threshold
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 455d89a..03429c5 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -796,15 +796,19 @@ static int dwc3_core_init(struct dwc3 *dwc)
 dwc3_writel(dwc->regs, DWC3_GUCTL2, reg);
 }

+   reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
+

My understanding is that the register was only introduced with dwc3
revision 2.50a. Is it ok to read and write it unconditionally ?
Yes, refer to dwc3 databook, the DWC3_GUCTL1 was introduced since 2.50a. 
Maybe it's better

to read and write it only when we know our controller version.

Is it good to fix it like the following patch?
But this patch has a problem that we need to read and write the register
twice if our controller verison > = 2.90a, and need this quirk.

--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -806,6 +806,12 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
}

+   if (dwc->dis_tx_ipgap_linecheck_quirk) {
+   reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
+   reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
+   dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
+   }
+

Hi John & Felipe,
   Could you provide me some suggestion?
   Thank you!

 /*
  * Enable hardware control of sending remote wakeup in HS when
  * the device is in the L1 state.
  */
-   if (dwc->revision >= DWC3_REVISION_290A) {
-   reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
+   if (dwc->revision >= DWC3_REVISION_290A)
 reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
-   dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
-   }
+
+   if (dwc->tx_ipgap_linecheck_dis_quirk)
+   reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
+
+   dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);

 return 0;

@@ -1023,6 +1027,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
 "snps,dis-u2-freeclk-exists-quirk");
 dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev,
 "snps,dis-del-phy-power-chg-quirk");
+   dwc->tx_ipgap_linecheck_dis_quirk = device_property_read_bool(dev,
+   "snps,tx-ipgap-linecheck-dis-quirk");

 dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
 "snps,tx_de_emphasis_quirk");
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 981c77f..3c2537b 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -204,6 +204,7 @@
  #define DWC3_GCTL_DSBLCLKGTNG  BIT(0)

  /* Global User Control 1 Register */
+#define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS BIT(28)
  #define DWC3_GUCTL1_DEV_L1_EXIT_BY_HW  BIT(24)

  /* Global USB2 P

Re: [PATCH v2] usb: dwc3: add disable u2mac linestate check quirk

2017-04-19 Thread wlf

Dear Guenter,

在 2017年04月19日 13:15, Guenter Roeck 写道:

On Tue, Apr 18, 2017 at 8:59 PM, wlf  wrote:

Dear Guenter,



在 2017年04月18日 21:18, Guenter Roeck 写道:

On Mon, Apr 17, 2017 at 10:17 PM, William Wu 
wrote:

This patch adds a quirk to disable USB 2.0 MAC linestate check
during HS transmit. Refer the dwc3 databook, we can use it for
some special platforms if the linestate not reflect the expected
line state(J) during transmission.

When use this quirk, the controller implements a fixed 40-bit
TxEndDelay after the packet is given on UTMI and ignores the
linestate during the transmit of a token (during token-to-token
and token-to-data IPGAP).

On some rockchip platforms (e.g. rk3399), it requires to disable
the u2mac linestate check to decrease the SSPLIT token to SETUP
token inter-packet delay from 566ns to 466ns, and fix the issue
that FS/LS devices not recognized if inserted through USB 3.0 HUB.

Signed-off-by: William Wu 
---
Changes in v2:
- fix coding style

   Documentation/devicetree/bindings/usb/dwc3.txt |  2 ++
   drivers/usb/dwc3/core.c| 14 ++
   drivers/usb/dwc3/core.h|  4 
   3 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt
b/Documentation/devicetree/bindings/usb/dwc3.txt
index f658f39..6a89f0c 100644
--- a/Documentation/devicetree/bindings/usb/dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/dwc3.txt
@@ -45,6 +45,8 @@ Optional properties:
  a free-running PHY clock.
- snps,dis-del-phy-power-chg-quirk: when set core will change PHY
power
  from P0 to P1/P2/P3 without delay.
+ - snps,tx-ipgap-linecheck-dis-quirk: when set, disable u2mac linestate
check
+   during HS transmit.

All other disable-something quirks are named
"snps,dis-something-quirk". Maybe use the same naming convention ?

Yes, good idea! I will fix it with "snps,dis-tx-ipgap-linecheck-quirk"  in
next patch verison.
Thanks:-)



- snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
  utmi_l1_suspend_n, false when asserts
utmi_sleep_n
- snps,hird-threshold: HIRD threshold
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 455d89a..03429c5 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -796,15 +796,19 @@ static int dwc3_core_init(struct dwc3 *dwc)
  dwc3_writel(dwc->regs, DWC3_GUCTL2, reg);
  }

+   reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
+

My understanding is that the register was only introduced with dwc3
revision 2.50a. Is it ok to read and write it unconditionally ?

Yes, refer to dwc3 databook, the DWC3_GUCTL1 was introduced since 2.50a.
Maybe it's better
to read and write it only when we know our controller version.

Is it good to fix it like the following patch?
But this patch has a problem that we need to read and write the register
twice if our controller verison > = 2.90a, and need this quirk.

--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -806,6 +806,12 @@ static int dwc3_core_init(struct dwc3 *dwc)
 dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
 }

+   if (dwc->dis_tx_ipgap_linecheck_quirk) {
+   reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
+   reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
+   dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
+   }
+


How about this ?

 if (dwc->revision >= DWC3_REVISION_250A) {
 reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
 if (dwc->revision >= DWC3_REVISION_290A)
 reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
 if (dwc->dis_tx_ipgap_linecheck_quirk)
reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
 dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
 }

Thanks,
Guenter

Thanks, looks good to me. I will fix it in patch v2.



Hi John & Felipe,
Could you provide me some suggestion?
Thank you!


  /*
   * Enable hardware control of sending remote wakeup in HS when
   * the device is in the L1 state.
   */
-   if (dwc->revision >= DWC3_REVISION_290A) {
-   reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
+   if (dwc->revision >= DWC3_REVISION_290A)
  reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW;
-   dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
-   }
+
+   if (dwc->tx_ipgap_linecheck_dis_quirk)
+   reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS;
+
+   dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);

  return 0;

@@ -1023,6 +1027,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
  "snps,dis-u2-freeclk-exists-quirk");
  dwc->dis_del_phy_power_chg_quirk =
device_property_read_bool(dev,
  &q

Re: [PATCH 1/3] dt-bindings: phy: phy-rockchip-typec: add usb3 otg reset

2018-02-12 Thread wlf

Dear Heiko,

在 2018年02月11日 03:55, Heiko Stuebner 写道:

Hi Wulf,

Am Montag, 22. Januar 2018, 12:33:05 CET schrieb wlf:

在 2018年01月20日 05:49, Rob Herring 写道:

On Thu, Jan 18, 2018 at 09:47:50AM -0800, Brian Norris wrote:

On Thu, Jan 18, 2018 at 06:20:09PM +0100, Enric Balletbo Serra wrote:

As Brian said commit 06c47e6286d5 'usb: dwc3: of-simple: Add support
to get resets for the device' introduced the support to get the resets
from dwc3-of-simple and the queued commit 'b7e63d95c14d arm64: dts:
rockchip: add reset property for dwc3 controllers on rk3399' started
using it. Without the latest I get errors like this doing bind/unbind
tests.

 dwc3: probe of fe90.dwc3 failed with error -110

I just tested these series on top of mainline, I reverted my patch
because otherwise two drivers are requesting the same reset and fails,
and I did some of the bind/unbind test. They just worked fine, and
seems that this is right way, so this makes me think some questions.

Actually, this was intended to coexist with DWC3 optionally controlling
the same reset. It was written before the reset framework was rewritten
to have shared and exclusive resets. Should this be rewritten to use
shared resets? We'd have to modify both dwc3 core and the PHY driver.

Seems like abuse of DT to me. If you need to control the controller's
reset from the phy driver, then get the reset out of the controller
node. The phy node should describe the connections to the phy.

I try to get the reset out of the controller, but I don't find a good
way to get the reset ofthe controller associated with the given phy
device node.  Is there an API like theof_usb_get_dr_mode_by_phy() to
get 'dr_mode' of the controller?

I guess the easiest way would be taking the of_usb_get_dr_mode_by_phy()
function move the part above the "finish" label into a separate function
like of_usb_get_node_by_phy (or possibly move that to an even more general
place as it is not usb-related at all) and use that function in
of_usb_get_dr_mode_by_phy() and also use it to get the reset you want via
something like:

node = of_usb_get_node_by_phy(...);
rst = of_reset_control_get(node, ...);
Thanks for your good suggestion. I think it's a good way to get the 
reset of the

controller by phy.

And we're trying to find another method to fix the RK3399 tcphy power
on fail issue.If we get another proper method, we may not need these
phy patch series.

Did you find any different solution for that yet?

Heiko

Yes, finally, we have found another way to fix the  RK3399 tcphy usb power
on fail issue. And Enric Balletbo i Serra  has 
submitted

new patch series, refer to the following patches:
https://patchwork.kernel.org/patch/10207261/
https://patchwork.kernel.org/patch/10207267/
https://patchwork.kernel.org/patch/10207263/

So my patches can be abandoned.







Re: [PATCH] usb: gadget: f_fs: get the correct address of comp_desc

2018-02-06 Thread wlf

Hi Jack,

在 2018年02月06日 02:17, Jack Pham 写道:

Hi William,

On Mon, Feb 05, 2018 at 07:33:38PM +0800, William Wu wrote:

Refer to the USB 3.0 spec '9.6.7 SuperSpeed Endpoint Companion',
the companion descriptor follows the standard endpoint descriptor.
This descriptor is only defined for SuperSpeed endpoints. The
f_fs driver gets the address of the companion descriptor via
'ds + USB_DT_ENDPOINT_SIZE', and actually, the ds variable is
a pointer to the struct usb_endpoint_descriptor, so the offset
of the companion descriptor which we get is USB_DT_ENDPOINT_SIZE *
sizeof(struct usb_endpoint_descriptor), the wrong offset is 63
bytes. This cause out-of-bound with the following error log if
CONFIG_KASAN and CONFIG_SLUB_DEBUG is enabled on Rockchip RK3399
Evaluation Board.

android_work: sent uevent USB_STATE=CONNECTED
configfs-gadget gadget: super-speed config #1: b
==
BUG: KASAN: slab-out-of-bounds in ffs_func_set_alt+0x230/0x398
Read of size 1 at addr ffc0ce2d0b10 by task irq/224-dwc3/364
Memory state around the buggy address:
  ffc0ce2d0a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  ffc0ce2d0a80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  >ffc0ce2d0b00: 00 04 fc fc fc fc fc fc fc fc fc fc fc fc fc fc
  ^
  ffc0ce2d0b80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
  ffc0ce2d0c00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==
Disabling lock debugging due to kernel taint
android_work: sent uevent USB_STATE=CONFIGURED

This patch adds struct usb_endpoint_descriptor * -> u8 * type conversion
for ds variable, then we can get the correct address of comp_desc
with offset USB_DT_ENDPOINT_SIZE bytes.

Signed-off-by: William Wu 
---
  drivers/usb/gadget/function/f_fs.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/function/f_fs.c 
b/drivers/usb/gadget/function/f_fs.c
index 6756472..f13ead0 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1882,8 +1882,8 @@ static int ffs_func_eps_enable(struct ffs_function *func)
ep->ep->desc = ds;
  
  		if (needs_comp_desc) {

-   comp_desc = (struct usb_ss_ep_comp_descriptor *)(ds +
-   USB_DT_ENDPOINT_SIZE);
+   comp_desc = (struct usb_ss_ep_comp_descriptor *)
+((u8 *)ds + USB_DT_ENDPOINT_SIZE);
ep->ep->maxburst = comp_desc->bMaxBurst + 1;
ep->ep->comp_desc = comp_desc;
}

Please see my alternative fix for this. I proposed changing this
function to use config_ep_by_speed() instead.

https://www.spinics.net/lists/linux-usb/msg165149.html

Thanks for your great job!
 Your patch seems good, I will test your patch on my RK3399-EVB board.

William



Jack





Re: [PATCH v3 1/3] dt-bindings: usb: add DT binding for RK3328 dwc3 controller

2017-08-23 Thread wlf

Dear Balbi & Gregkh,

在 2017年08月21日 21:36, William Wu 写道:

Adds the device tree bindings description for RK3328 and
compatible USB DWC3 controller.

Signed-off-by: William Wu 
---
Changes in v3:
- Add this for separate usb dt-bindings patch.

Changes in v2:
- None

  Documentation/devicetree/bindings/usb/rockchip,dwc3.txt | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt 
b/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt
index 0536a93..d6b2e47 100644
--- a/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt
@@ -1,7 +1,9 @@
  Rockchip SuperSpeed DWC3 USB SoC controller
  
  Required properties:

-- compatible:  should contain "rockchip,rk3399-dwc3" for rk3399 SoC
+- compatible:  should be one of the following:
+  - "rockchip,rk3399-dwc3": for rk3399 SoC
+  - "rockchip,rk3328-dwc3", "rockchip,rk3399-dwc3": for rk3328 SoC
  - clocks: A list of phandle + clock-specifier pairs for the
clocks listed in clock-names
  - clock-names:Should contain the following:
Could you help to reviewed this patch? According to Heiko's 
suggestion, this patch

need to be submitted to usb tree or at least get an Ack from you.

Thank you!

--
吴良峰 William.Wu
福建省福州市铜盘路软件大道89号软件园A区21号楼
No.21 Building, A District, No.89,software Boulevard Fuzhou,Fujian, PRC
手机: 13685012275
座机: 0591-83991906-8520
邮件:w...@rock-chips.com




Re: [PATCH v2 1/2] arm64: dts: rockchip: add usb3 controller node for RK3328 SoCs

2017-08-21 Thread wlf

Dear Heiko,

在 2017年08月18日 17:24, Heiko Stuebner 写道:

Hi William,

Am Donnerstag, 17. August 2017, 15:54:49 CEST schrieb William Wu:

RK3328 has one USB 3.0 OTG controller which uses DWC_USB3
core's general architecture. It can act as static xHCI host
controller, static device controller, USB 3.0/2.0 OTG basing
on ID of USB3.0 PHY.

Signed-off-by: William Wu 
---
Changes in v2:
- Modify the dwc3 quirk "snps,tx-ipgap-linecheck-dis-quirk" to
   "snps,dis-tx-ipgap-linecheck-quirk"

  .../devicetree/bindings/usb/rockchip,dwc3.txt  |  4 +++-
  arch/arm64/boot/dts/rockchip/rk3328.dtsi   | 27 ++
  2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt 
b/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt
index 0536a93..d6b2e47 100644
--- a/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt
@@ -1,7 +1,9 @@
  Rockchip SuperSpeed DWC3 USB SoC controller
  
  Required properties:

-- compatible:  should contain "rockchip,rk3399-dwc3" for rk3399 SoC
+- compatible:  should be one of the following:
+  - "rockchip,rk3399-dwc3": for rk3399 SoC
+  - "rockchip,rk3328-dwc3", "rockchip,rk3399-dwc3": for rk3328 SoC
  - clocks: A list of phandle + clock-specifier pairs for the
clocks listed in clock-names
  - clock-names:Should contain the following:

This probably shouldn't be part of the patch adding the dts node, but
instead should be a separate patch and should either go through some
usb tree or at least get an Ack from usb maintainers (Felipe Balbi and/or
Greg Kroah Hartman), so you should definitly include them into your
recipient list.
Thanks for your  suggestion. I will submit two patches separately, and 
add usb maintainers in

the recipient list.



Heiko






--
吴良峰 William.Wu
福建省福州市铜盘路软件大道89号软件园A区21号楼
No.21 Building, A District, No.89,software Boulevard Fuzhou,Fujian, PRC
手机: 13685012275
座机: 0591-83991906-8520
邮件:w...@rock-chips.com




Re: [PATCH 1/2] ARM: dts: rockchip: add usb nodes on rk322x

2017-06-01 Thread wlf

Dear Heiko,

在 2017年06月02日 04:22, Heiko Stuebner 写道:

Hi William,

Am Mittwoch, 31. Mai 2017, 09:21:23 CEST schrieb William Wu:

This patch adds usb otg/host controllers and phys nodes on rk322x.

Signed-off-by: William Wu 
---
  arch/arm/boot/dts/rk322x.dtsi | 138 +-
  1 file changed, 137 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi
index df57413..d4bfd3c 100644
--- a/arch/arm/boot/dts/rk322x.dtsi
+++ b/arch/arm/boot/dts/rk322x.dtsi
@@ -210,8 +210,61 @@
};
  
  	grf: syscon@1100 {

-   compatible = "syscon";
+   compatible = "syscon", "simple-mfd";
reg = <0x1100 0x1000>;
+   #address-cells = <1>;
+   #size-cells = <1>;
+
+   u2phy0: usb2-phy@760 {
+   compatible = "rockchip,rk322x-usb2phy";

as commented on the driver-side some moments ago, compatibles should not
contain wildcards, so please make this
"rockchip,rk3228-usb2phy"
instead.

Same below and also for the dwc2 node.

Thanks, I'll fix it immediately.



Thanks
Heiko


+   reg = <0x0760 0x0c>;
+   clocks = <&cru SCLK_OTGPHY0>;
+   clock-names = "phyclk";
+   #clock-cells = <0>;
+   clock-output-names = "usb480m_phy0";
+   status = "disabled";
+
+   u2phy0_otg: otg-port {
+   #phy-cells = <0>;
+   interrupts = ,
+,
+;
+   interrupt-names = "otg-bvalid", "otg-id",
+ "linestate";
+   status = "disabled";
+   };
+
+   u2phy0_host: host-port {
+   #phy-cells = <0>;
+   interrupts = ;
+   interrupt-names = "linestate";
+   status = "disabled";
+   };
+   };
+
+   u2phy1: usb2-phy@800 {
+   compatible = "rockchip,rk322x-usb2phy";

rockchip,rk3228-usb2phy

OK, I'll fix it immediately.



+   reg = <0x0800 0x0c>;
+   clocks = <&cru SCLK_OTGPHY1>;
+   clock-names = "phyclk";
+   #clock-cells = <0>;
+   clock-output-names = "usb480m_phy1";
+   status = "disabled";
+
+   u2phy1_otg: otg-port {
+   #phy-cells = <0>;
+   interrupts = ;
+   interrupt-names = "linestate";
+   status = "disabled";
+   };
+
+   u2phy1_host: host-port {
+   #phy-cells = <0>;
+   interrupts = ;
+   interrupt-names = "linestate";
+   status = "disabled";
+   };
+   };
};
  
  	uart0: serial@1101 {

@@ -467,6 +520,89 @@
status = "disabled";
};
  
+	usb_otg: usb@3004 {

+   compatible = "rockchip,rk322x-usb", "rockchip,rk3066-usb",

rockchip,rk3228-usb

OK, I'll fix it immediately.:-)



+"snps,dwc2";
+   reg = <0x3004 0x4>;
+   interrupts = ;
+   clocks = <&cru HCLK_OTG>;
+   clock-names = "otg";
+   dr_mode = "otg";
+   g-np-tx-fifo-size = <16>;
+   g-rx-fifo-size = <280>;
+   g-tx-fifo-size = <256 128 128 64 32 16>;
+   g-use-dma;
+   phys = <&u2phy0_otg>;
+   phy-names = "usb2-phy";
+   status = "disabled";
+   };
+
+   usb_host0_ehci: usb@3008 {
+   compatible = "generic-ehci";
+   reg = <0x3008 0x2>;
+   interrupts = ;
+   clocks = <&cru HCLK_HOST0>, <&u2phy0>;
+   clock-names = "usbhost", "utmi";
+   phys = <&u2phy0_host>;
+   phy-names = "usb";
+   status = "disabled";
+   };
+
+   usb_host0_ohci: usb@300a {
+   compatible = "generic-ohci";
+   reg = <0x300a 0x2>;
+   interrupts = ;
+   clocks = <&cru HCLK_HOST0>, <&u2phy0>;
+   clock-names = "usbhost", "utmi";
+   phys = <&u2phy0_host>;
+   phy-names = "usb";
+   status = "disabled";
+   };
+
+   usb_host1_ehci: usb@300c {
+   compatible = "generic-ehci";
+   reg = <0x300c 0x2>;
+  

Re: [PATCH] usb: dwc2: host: fix isoc urb actual length

2017-11-07 Thread wlf

Hi Alan,

在 2017年11月07日 03:17, Alan Stern 写道:

On Mon, 6 Nov 2017, wlf wrote:


Hi Minas,

在 2017年11月06日 17:28, Minas Harutyunyan 写道:

Hi,

On 11/6/2017 12:46 PM, William Wu wrote:

The actual_length in dwc2_hcd_urb structure is used
to indicate the total data length transferred so far,
but in dwc2_update_isoc_urb_state(), it just updates
the actual_length of isoc frame, and don't update the
urb actual_length at the same time, this will cause
device drivers working error which depend on the urb
actual_length.

we can easily find this issue if use an USB camera,
the userspace use libusb to get USB data from kernel
via devio driver.In usb devio driver, processcompl()
function will process urb complete and copy data to
userspace depending on urb actual_length.

Let's update the urb actual_length if the isoc frame
is valid.

Signed-off-by: William Wu 
---
drivers/usb/dwc2/hcd_intr.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c
index 28a8210..01b1e13 100644
--- a/drivers/usb/dwc2/hcd_intr.c
+++ b/drivers/usb/dwc2/hcd_intr.c
@@ -580,6 +580,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
frame_desc->status = 0;
frame_desc->actual_length = dwc2_get_actual_xfer_length(hsotg,
chan, chnum, qtd, halt_status, NULL);
+   urb->actual_length += frame_desc->actual_length;
break;
case DWC2_HC_XFER_FRAME_OVERRUN:
urb->error_count++;
@@ -599,6 +600,7 @@ static enum dwc2_halt_status dwc2_update_isoc_urb_state(
frame_desc->status = -EPROTO;
frame_desc->actual_length = dwc2_get_actual_xfer_length(hsotg,
chan, chnum, qtd, halt_status, NULL);
+   urb->actual_length += frame_desc->actual_length;

		/* Skip whole frame */

if (chan->qh->do_split &&


According urb description in usb.h urb->actual_length used for non-iso
transfers:

"@actual_length: This is read in non-iso completion functions, and ...

* ISO transfer status is reported in the status and actual_length fields
* of the iso_frame_desc array, "

Yes,  urb->actual_length is used for non-iso transfers.  And for ISO
transfer,  the most
usb class drivers can only use iso frame status and actual_length to
handle usb data,
like: kernel v4.4 drivers/media/usb/uvc/uvc_video.c

But the usb devio driver really need the urb actual_length in the
processcompl() if
handle ISO transfer, just as I mentioned in the commit message.

And I also found the same issue on raspberrypi board:
https://github.com/raspberrypi/linux/issues/903

So do you think we need to fix the usb devio driver, rather than fix dwc2?
I think maybe we can use urb actual length for ISO transfer, it seems that
don't cause any side-effect.

That sounds like a good idea.  Minas, does the following patch fix your
problem?

In theory we could do this calculation for every isochronous URB, not
just those coming from usbfs.  But I don't think there's any point,
since the USB class drivers don't use it.

Alan Stern



Index: usb-4.x/drivers/usb/core/devio.c
===
--- usb-4.x.orig/drivers/usb/core/devio.c
+++ usb-4.x/drivers/usb/core/devio.c
@@ -1828,6 +1828,18 @@ static int proc_unlinkurb(struct usb_dev
return 0;
  }
  
+static void compute_isochronous_actual_length(struct urb *urb)

+{
+   unsigned i;
+
+   if (urb->number_of_packets > 0) {
+   urb->actual_length = 0;
+   for (i = 0; i < urb->number_of_packets; i++)
+   urb->actual_length +=
+   urb->iso_frame_desc[i].actual_length;
+   }
+}
+
  static int processcompl(struct async *as, void __user * __user *arg)
  {
struct urb *urb = as->urb;
@@ -1835,6 +1847,8 @@ static int processcompl(struct async *as
void __user *addr = as->userurb;
unsigned int i;
  
+	compute_isochronous_actual_length(urb);

+
if (as->userbuffer && urb->actual_length) {
if (copy_urb_data_to_user(as->userbuffer, urb))
goto err_out;
@@ -2003,6 +2017,8 @@ static int processcompl_compat(struct as
void __user *addr = as->userurb;
unsigned int i;
  
+	compute_isochronous_actual_length(urb);

+
if (as->userbuffer && urb->actual_length) {
if (copy_urb_data_to_user(as->userbuffer, urb))
return -EFAULT;


Yeah,  it's a good idea to calculate the urb actual length in the devio 
driver.
Your patch seems good,  and I think we can do a small optimization base 
your patch,

like the following patch:

diff --git a/drivers/usb/core/dev

Re: [PATCH] usb: dwc2: host: fix isoc urb actual length

2017-11-07 Thread wlf

Hi Alan,

在 2017年11月07日 23:18, Alan Stern 写道:

On Tue, 7 Nov 2017, wlf wrote:


That sounds like a good idea.  Minas, does the following patch fix your
problem?

In theory we could do this calculation for every isochronous URB, not
just those coming from usbfs.  But I don't think there's any point,
since the USB class drivers don't use it.

Alan Stern



Index: usb-4.x/drivers/usb/core/devio.c
===
--- usb-4.x.orig/drivers/usb/core/devio.c
+++ usb-4.x/drivers/usb/core/devio.c
@@ -1828,6 +1828,18 @@ static int proc_unlinkurb(struct usb_dev
return 0;
   }
   
+static void compute_isochronous_actual_length(struct urb *urb)

+{
+   unsigned i;
+
+   if (urb->number_of_packets > 0) {
+   urb->actual_length = 0;
+   for (i = 0; i < urb->number_of_packets; i++)
+   urb->actual_length +=
+   urb->iso_frame_desc[i].actual_length;
+   }
+}
+
   static int processcompl(struct async *as, void __user * __user *arg)
   {
struct urb *urb = as->urb;
@@ -1835,6 +1847,8 @@ static int processcompl(struct async *as
void __user *addr = as->userurb;
unsigned int i;
   
+	compute_isochronous_actual_length(urb);

+
if (as->userbuffer && urb->actual_length) {
if (copy_urb_data_to_user(as->userbuffer, urb))
goto err_out;
@@ -2003,6 +2017,8 @@ static int processcompl_compat(struct as
void __user *addr = as->userurb;
unsigned int i;
   
+	compute_isochronous_actual_length(urb);

+
if (as->userbuffer && urb->actual_length) {
if (copy_urb_data_to_user(as->userbuffer, urb))
return -EFAULT;



Yeah,  it's a good idea to calculate the urb actual length in the devio
driver.
Your patch seems good,  and I think we can do a small optimization base
your patch,
like the following patch:

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index bd94192..a2e7b97 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1664,6 +1664,9 @@ static int processcompl(struct async *as, void
__user * __user *arg)
  void __user *addr = as->userurb;
  unsigned int i;

+   if (usb_endpoint_xfer_isoc(&urb->ep->desc))
+   compute_isochronous_actual_length(urb);
+
  if (as->userbuffer && urb->actual_length) {
  if (copy_urb_data_to_user(as->userbuffer, urb))
  goto err_out;
@@ -1833,6 +1836,9 @@ static int processcompl_compat(struct async *as,
void __user * __user *arg)
  void __user *addr = as->userurb;
  unsigned int i;

+   if (usb_endpoint_xfer_isoc(&urb->ep->desc))
+   compute_isochronous_actual_length(urb);
+

Well, this depends on whether you want to optimize for space or for
speed.  I've been going for space.  And since usbfs is inherently
rather slow, I don't think this will make any significant speed
difference.  So I don't think adding the extra tests is worthwhile.

(Besides, if you really wanted to do it this way, you should have moved
the test for "urb->number_of_packets > 0" into the callers instead of
adding an additional test of the endpoint type.)

Yes,  agree with you.



However, nobody has answered my original question: Does the patch
actually fix the problem?
I test your patch on Rockchip RK3188 platform,  use UsbWebCamera APP by 
Serenegiant

(libusb + devio)  with  usb camera, it work well.



Alan Stern






--
吴良峰 William.Wu
福建省福州市铜盘路软件大道89号软件园A区21号楼
No.21 Building, A District, No.89,software Boulevard Fuzhou,Fujian, PRC
手机: 13685012275
座机: 0591-83991906-8520
邮件:w...@rock-chips.com