Re: [PATCH 1/2] usb: dwc2: Fix DMA alignment to start at allocated boundary
On 6 July 2018 at 18:57, Doug Anderson wrote: > Hi, > > Thanks for tracking this down and sorry for the original regression. > Seems like a good fix. With this fix, I'd be curious of your > observations on how dwc2 performs (both performance and compatibility > under stress) with the newest driver compared to whatever you were > using before. > My totally not scientifically accurate performance test included running iperf through my LTE dongle that was connected to dwc2. I saw throughput increase in download speeds. Before (kernel 4.9.109 with the offending commit reverted) iperf reported download bandwidth at 33.2 Mbits/sec Using newest dwc2 driver after applying "Fix DMA alignment to start at allocated boundary" patch I got 38.2 Mbits/sec If I also apply the "Fix inefficient copy of unaligned buffers" patch I could achieve a total throughput for download around 44.6 Mbits/sec which I believe is capped by my 50Mbit/s subscription. > Also: you're using the dwc2_set_ltq_params() parameters? Have you > checked if removing the "max_transfer_size" limit boosts your > performance? > Yes, I'm using the parameters set there. I tried removing max_transfer_size but it did not have noticeable impact on the performance in my tests. > Cc: sta...@vger.kernel.org > Reviewed-by: Douglas Anderson Thanks for reviewing :) -Antti -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/2] usb: dwc2: DMA alignment fixes
Here are two patches that improve DMA alignment handling of the dwc2 driver significantly. The first one ("usb: dwc2: Fix DMA alignment to start at allocated boundary") fixes an actual crash regression on some platforms introduced by commit 3bc04e28a030 ("usb: dwc2: host: Get aligned DMA in a more supported way") and should be considered for inclusion in stable kernel release. The second patch ("usb: dwc2: Fix inefficient copy of unaligned buffers") is a port of an optimization found from similar drivers to dwc2. In my tests it offered a significant performance improvement in certain use cases. Since it touches the same area that I was already modifying I decided to split it into separate patch and include in the series. Antti Seppälä (2): usb: dwc2: Fix DMA alignment to start at allocated boundary usb: dwc2: Fix inefficient copy of unaligned buffers drivers/usb/dwc2/hcd.c | 54 +- 1 file changed, 31 insertions(+), 23 deletions(-) -- 2.13.6 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] usb: dwc2: Fix DMA alignment to start at allocated boundary
The commit 3bc04e28a030 ("usb: dwc2: host: Get aligned DMA in a more supported way") introduced a common way to align DMA allocations. The code in the commit aligns the struct dma_aligned_buffer but the actual DMA address pointed by data[0] gets aligned to an offset from the allocated boundary by the kmalloc_ptr and the old_xfer_buffer pointers. This is against the recommendation in Documentation/DMA-API.txt which states: Therefore, it is recommended that driver writers who don't take special care to determine the cache line size at run time only map virtual regions that begin and end on page boundaries (which are guaranteed also to be cache line boundaries). The effect of this is that architectures with non-coherent DMA caches may run into memory corruption or kernel crashes with Unhandled kernel unaligned accesses exceptions. Fix the alignment by positioning the DMA area in front of the allocation and use memory at the end of the area for storing the orginal transfer_buffer pointer. This may have the added benefit of increased performance as the DMA area is now fully aligned on all architectures. Tested with Lantiq xRX200 (MIPS) and RPi Model B Rev 2 (ARM). Fixes: 3bc04e28a030 ("usb: dwc2: host: Get aligned DMA in a more supported way") Signed-off-by: Antti Seppälä --- drivers/usb/dwc2/hcd.c | 44 +++- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index b1104be3429c..2ed0ac18e053 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -2665,34 +2665,29 @@ static int dwc2_alloc_split_dma_aligned_buf(struct dwc2_hsotg *hsotg, #define DWC2_USB_DMA_ALIGN 4 -struct dma_aligned_buffer { - void *kmalloc_ptr; - void *old_xfer_buffer; - u8 data[0]; -}; - static void dwc2_free_dma_aligned_buffer(struct urb *urb) { - struct dma_aligned_buffer *temp; + void *stored_xfer_buffer; if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) return; - temp = container_of(urb->transfer_buffer, - struct dma_aligned_buffer, data); + /* Restore urb->transfer_buffer from the end of the allocated area */ + memcpy(_xfer_buffer, urb->transfer_buffer + + urb->transfer_buffer_length, sizeof(urb->transfer_buffer)); if (usb_urb_dir_in(urb)) - memcpy(temp->old_xfer_buffer, temp->data, + memcpy(stored_xfer_buffer, urb->transfer_buffer, urb->transfer_buffer_length); - urb->transfer_buffer = temp->old_xfer_buffer; - kfree(temp->kmalloc_ptr); + kfree(urb->transfer_buffer); + urb->transfer_buffer = stored_xfer_buffer; urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; } static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) { - struct dma_aligned_buffer *temp, *kmalloc_ptr; + void *kmalloc_ptr; size_t kmalloc_size; if (urb->num_sgs || urb->sg || @@ -2700,22 +2695,29 @@ static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) !((uintptr_t)urb->transfer_buffer & (DWC2_USB_DMA_ALIGN - 1))) return 0; - /* Allocate a buffer with enough padding for alignment */ + /* +* Allocate a buffer with enough padding for original transfer_buffer +* pointer. This allocation is guaranteed to be aligned properly for +* DMA +*/ kmalloc_size = urb->transfer_buffer_length + - sizeof(struct dma_aligned_buffer) + DWC2_USB_DMA_ALIGN - 1; + sizeof(urb->transfer_buffer); kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); if (!kmalloc_ptr) return -ENOMEM; - /* Position our struct dma_aligned_buffer such that data is aligned */ - temp = PTR_ALIGN(kmalloc_ptr + 1, DWC2_USB_DMA_ALIGN) - 1; - temp->kmalloc_ptr = kmalloc_ptr; - temp->old_xfer_buffer = urb->transfer_buffer; + /* +* Position value of original urb->transfer_buffer pointer to the end +* of allocation for later referencing +*/ + memcpy(kmalloc_ptr + urb->transfer_buffer_length, + >transfer_buffer, sizeof(urb->transfer_buffer)); + if (usb_urb_dir_out(urb)) - memcpy(temp->data, urb->transfer_buffer, + memcpy(kmalloc_ptr, urb->transfer_buffer, urb->transfer_buffer_length); - urb->transfer_buffer = temp->data; + urb->transfer_buffer = kmalloc_ptr; urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER; -- 2.13.6 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] usb: dwc2: Fix inefficient copy of unaligned buffers
Make sure only to copy any actual data rather than the whole buffer, when releasing the temporary buffer used for unaligned non-isochronous transfers. Taken directly from commit 0efd937e27d5e ("USB: ehci-tegra: fix inefficient copy of unaligned buffers") Tested with Lantiq xRX200 (MIPS) and RPi Model B Rev 2 (ARM) Signed-off-by: Antti Seppälä --- drivers/usb/dwc2/hcd.c | 12 +--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 2ed0ac18e053..6e2cdd7b93d4 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -2668,6 +2668,7 @@ static int dwc2_alloc_split_dma_aligned_buf(struct dwc2_hsotg *hsotg, static void dwc2_free_dma_aligned_buffer(struct urb *urb) { void *stored_xfer_buffer; + size_t length; if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) return; @@ -2676,9 +2677,14 @@ static void dwc2_free_dma_aligned_buffer(struct urb *urb) memcpy(_xfer_buffer, urb->transfer_buffer + urb->transfer_buffer_length, sizeof(urb->transfer_buffer)); - if (usb_urb_dir_in(urb)) - memcpy(stored_xfer_buffer, urb->transfer_buffer, - urb->transfer_buffer_length); + if (usb_urb_dir_in(urb)) { + if (usb_pipeisoc(urb->pipe)) + length = urb->transfer_buffer_length; + else + length = urb->actual_length; + + memcpy(stored_xfer_buffer, urb->transfer_buffer, length); + } kfree(urb->transfer_buffer); urb->transfer_buffer = stored_xfer_buffer; -- 2.13.6 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: usb: dwc2: crash regression in commit 3bc04e28a030 (bisected)
On 3 July 2018 at 09:56, Doug Anderson wrote: > Hi, > > On Sun, Jul 1, 2018 at 11:30 PM, Antti Seppälä wrote: >> On 30 June 2018 at 02:57, Doug Anderson wrote: >>> Hi, >>> >>> On Fri, Jun 29, 2018 at 11:29 AM, Antti Seppälä wrote: >>>> Hi Doug, John and linux-usb. >>>> >>>> I'd like to report a regression in commit 3bc04e28a030 (usb: dwc2: >>>> host: Get aligned DMA in a more supported way) >>> >>> Seems unlikely, but any chance that >>> <https://patchwork.kernel.org/patch/10393775/> helps you? >>> >> >> Thank you for your suggestion but unfortunately the patch does not >> help and the crash remains. > > A few more shots in the dark in case they help: > > 1. For the kmalloc() in dwc2_alloc_dma_aligned_buffer(), change from: > > kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); > > to: > > kmalloc_ptr = kmalloc(kmalloc_size, mem_flags | GFP_DMA); > > > The old code used to hardcode this, so maybe it somehow makes a difference? > I tried this but it did not have any effect on the crash. > --- > > 2. Change DWC2_USB_DMA_ALIGN to a larger size. Maybe 32 or 64? > I tried these values too but they did not help. It seems to me that these change the alignment of the start of the struct dma_aligned_buffer but since the issue is with the alignment of ->data inside that struct it is always moved to an unaligned location (offset by the two pointers at the start of the struct). There is even a mention of this requirement in Documentation/DMA-API.txt: Memory coherency operates at a granularity called the cache line width. In order for memory mapped by this API to operate correctly, the mapped region must begin exactly on a cache line boundary and end exactly on one (to prevent two separately mapped regions from sharing a single cache line). Since the cache line size may not be known at compile time, the API will not enforce this requirement. Therefore, it is recommended that driver writers who don't take special care to determine the cache line size at run time only map virtual regions that begin and end on page boundaries (which are guaranteed also to be cache line boundaries). > --- > > 3. Undo just the part of the patch that removed: > > /* > * Clip max_transfer_size to 65535. dwc2_hc_setup_align_buf() allocates > * coherent buffers with this size, and if it's too large we can > * exhaust the coherent DMA pool. > */ > if (hw->max_transfer_size > 65535) > hw->max_transfer_size = 65535; > > Maybe there's something on your platform where you have a problem with > big transfers? > I tried adding back this one as well but unfortunately no help from that either. Then I wrote a proof-of-concept patch that really solves the issue for me. The patch allocates additional space at the end of that temp bounce buffer and stores the original value of urb->transfer_buffer there for keeping until it is needed again. This way the bounce buffer for DMA is aligned on a page boundary that is compliant from DMA-API.txt perspective. Any thoughts or comments? If the patch doesn't look too crazy I can send it properly with git. -- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -2606,34 +2606,28 @@ #define DWC2_USB_DMA_ALIGN 4 -struct dma_aligned_buffer { -void *kmalloc_ptr; -void *old_xfer_buffer; -u8 data[0]; -}; - static void dwc2_free_dma_aligned_buffer(struct urb *urb) { -struct dma_aligned_buffer *temp; +void *stored_xfer_buffer; if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) return; -temp = container_of(urb->transfer_buffer, -struct dma_aligned_buffer, data); +memcpy(_xfer_buffer, urb->transfer_buffer + +urb->transfer_buffer_length, sizeof(void *)); if (usb_urb_dir_in(urb)) -memcpy(temp->old_xfer_buffer, temp->data, +memcpy(stored_xfer_buffer, urb->transfer_buffer, urb->transfer_buffer_length); -urb->transfer_buffer = temp->old_xfer_buffer; -kfree(temp->kmalloc_ptr); +kfree(urb->transfer_buffer); +urb->transfer_buffer = stored_xfer_buffer; urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; } static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) { -struct dma_aligned_buffer *temp, *kmalloc_ptr; +void *kmalloc_ptr; size_t kmalloc_size; if (urb->num_sgs || urb->sg || @@ -2641,22 +2635,21 @@ !((uintptr_t)urb->transfer_buffer & (DWC2_USB_DMA_ALIGN - 1))) return 0; -/* Allocate a buffer with enough padding for alignment */ -
Re: usb: dwc2: crash regression in commit 3bc04e28a030 (bisected)
On 30 June 2018 at 02:57, Doug Anderson wrote: > Hi, > > On Fri, Jun 29, 2018 at 11:29 AM, Antti Seppälä wrote: >> Hi Doug, John and linux-usb. >> >> I'd like to report a regression in commit 3bc04e28a030 (usb: dwc2: >> host: Get aligned DMA in a more supported way) > > Seems unlikely, but any chance that > <https://patchwork.kernel.org/patch/10393775/> helps you? > Thank you for your suggestion but unfortunately the patch does not help and the crash remains. > >> Apparently the patch does something nasty that the Lantiq platform >> really does not like as whenever I plug my usb 3g modem into the usb >> port of my BT HomeHub v5 (Lantiq XRX200) I get a kernel >> oops/crash/panic with usually quite a weird content that looks like >> some sort of memory corruption. >> >> I've bisected the crash and reverting 3bc04e28a030 allows the 3g-modem >> to be plugged and the kernel does not crash. >> >> Below is the console log when I plug the modem in. I used stable >> vanilla kernel 4.9.109 from OpenWrt during my tests with dwc2 debug >> prints enabled: >> >> root@lantiq:/# echo -n "module dwc2 +p" > >> /sys/kernel/debug/dynamic_debug/control >> [ 92.563454] dwc2 1e101000.ifxhcd: gintsts=0521 gintmsk=f3000806 >> [ 92.568762] dwc2 1e101000.ifxhcd: DWC OTG HCD HUB STATUS DATA: Root >> port status changed >> [ 92.576447] dwc2 1e101000.ifxhcd: port_connect_status_change: 1 >> [ 92.582523] dwc2 1e101000.ifxhcd: port_reset_change: 0 >> [ 92.587830] dwc2 1e101000.ifxhcd: port_enable_change: 0 >> [ 92.593228] dwc2 1e101000.ifxhcd: port_suspend_change: 0 >> [ 92.598710] dwc2 1e101000.ifxhcd: port_over_current_change: 0 >> [ 92.607242] dwc2 1e101000.ifxhcd: ClearPortFeature >> USB_PORT_FEAT_C_CONNECTION >> [ 92.758240] dwc2 1e101000.ifxhcd: SetPortFeature >> [ 92.761535] dwc2 1e101000.ifxhcd: SetPortFeature - USB_PORT_FEAT_RESET >> [ 92.768063] dwc2 1e101000.ifxhcd: In host mode, hprt0=00021501 >> [ 92.841013] dwc2 1e101000.ifxhcd: gintsts=0529 gintmsk=f3000806 >> [ 92.905329] dwc2 1e101000.ifxhcd: ClearPortFeature USB_PORT_FEAT_C_RESET >> [ 92.968536] usb 1-1: new high-speed USB device number 2 using dwc2 >> [ 92.975029] dwc2 1e101000.ifxhcd: SetPortFeature >> [ 92.978358] dwc2 1e101000.ifxhcd: SetPortFeature - USB_PORT_FEAT_RESET >> [ 92.984837] dwc2 1e101000.ifxhcd: In host mode, hprt0=1101 >> [ 92.990674] dwc2 1e101000.ifxhcd: gintsts=0529 gintmsk=f3000806 >> [ 93.060349] dwc2 1e101000.ifxhcd: DWC OTG HCD HUB STATUS DATA: Root >> port status changed >> [ 93.067020] dwc2 1e101000.ifxhcd: port_connect_status_change: 0 >> [ 93.073099] dwc2 1e101000.ifxhcd: port_reset_change: 0 >> [ 93.078375] dwc2 1e101000.ifxhcd: port_enable_change: 1 >> [ 93.083766] dwc2 1e101000.ifxhcd: port_suspend_change: 0 >> [ 93.089252] dwc2 1e101000.ifxhcd: port_over_current_change: 0 >> [ 93.096284] dwc2 1e101000.ifxhcd: gintsts=0529 gintmsk=f3000806 >> [ 93.152672] dwc2 1e101000.ifxhcd: ClearPortFeature USB_PORT_FEAT_C_RESET >> [ 93.216952] dwc2 1e101000.ifxhcd: DWC OTG HCD EP DISABLE: >> bEndpointAddress=0x00, ep->hcpriv=86e4fa00 >> [ 93.224792] dwc2 1e101000.ifxhcd: DWC OTG HCD EP DISABLE: >> bEndpointAddress=0x00, ep->hcpriv= (null) >> [ 93.233926] dwc2 1e101000.ifxhcd: DWC OTG HCD EP RESET: >> bEndpointAddress=0x00 >> [ 93.268547] dwc2 1e101000.ifxhcd: DWC OTG HCD EP RESET: >> bEndpointAddress=0x81 >> [ 93.274399] dwc2 1e101000.ifxhcd: DWC OTG HCD EP RESET: >> bEndpointAddress=0x01 >> [ 93.307463] usb-storage 1-1:1.0: USB Mass Storage device detected >> [ 93.312238] dwc2 1e101000.ifxhcd: DWC OTG HCD HUB STATUS DATA: Root >> port status changed >> [ 93.312256] dwc2 1e101000.ifxhcd: port_connect_status_change: 0 >> [ 93.312270] dwc2 1e101000.ifxhcd: port_reset_change: 0 >> [ 93.312329] dwc2 1e101000.ifxhcd: port_enable_change: 1 >> [ 93.312342] dwc2 1e101000.ifxhcd: port_suspend_change: 0 >> [ 93.312356] dwc2 1e101000.ifxhcd: port_over_current_change: 0 >> [ 93.408514] scsi host0: usb-storage 1-1:1.0 >> [ 93.437010] dwc2 1e101000.ifxhcd: ClearPortFeature USB_PORT_FEAT_C_ENABLE >> [ 94.152597] dwc2 1e101000.ifxhcd: DWC OTG HCD EP RESET: >> bEndpointAddress=0x01 >> [ 94.166421] dwc2 1e101000.ifxhcd: gintsts=2529 gintmsk=f3000806 >> [ 94.171336] dwc2 1e101000.ifxhcd: ++Disconnect Detected Interrupt++ >> (Host) a_host >> [ 94.180561] dwc2 1e101000.ifxhcd: DWC OTG HCD EP RESET: >> bEndpointAddress=0x01 &g
usb: dwc2: crash regression in commit 3bc04e28a030 (bisected)
Hi Doug, John and linux-usb. I'd like to report a regression in commit 3bc04e28a030 (usb: dwc2: host: Get aligned DMA in a more supported way) Apparently the patch does something nasty that the Lantiq platform really does not like as whenever I plug my usb 3g modem into the usb port of my BT HomeHub v5 (Lantiq XRX200) I get a kernel oops/crash/panic with usually quite a weird content that looks like some sort of memory corruption. I've bisected the crash and reverting 3bc04e28a030 allows the 3g-modem to be plugged and the kernel does not crash. Below is the console log when I plug the modem in. I used stable vanilla kernel 4.9.109 from OpenWrt during my tests with dwc2 debug prints enabled: root@lantiq:/# echo -n "module dwc2 +p" > /sys/kernel/debug/dynamic_debug/control [ 92.563454] dwc2 1e101000.ifxhcd: gintsts=0521 gintmsk=f3000806 [ 92.568762] dwc2 1e101000.ifxhcd: DWC OTG HCD HUB STATUS DATA: Root port status changed [ 92.576447] dwc2 1e101000.ifxhcd: port_connect_status_change: 1 [ 92.582523] dwc2 1e101000.ifxhcd: port_reset_change: 0 [ 92.587830] dwc2 1e101000.ifxhcd: port_enable_change: 0 [ 92.593228] dwc2 1e101000.ifxhcd: port_suspend_change: 0 [ 92.598710] dwc2 1e101000.ifxhcd: port_over_current_change: 0 [ 92.607242] dwc2 1e101000.ifxhcd: ClearPortFeature USB_PORT_FEAT_C_CONNECTION [ 92.758240] dwc2 1e101000.ifxhcd: SetPortFeature [ 92.761535] dwc2 1e101000.ifxhcd: SetPortFeature - USB_PORT_FEAT_RESET [ 92.768063] dwc2 1e101000.ifxhcd: In host mode, hprt0=00021501 [ 92.841013] dwc2 1e101000.ifxhcd: gintsts=0529 gintmsk=f3000806 [ 92.905329] dwc2 1e101000.ifxhcd: ClearPortFeature USB_PORT_FEAT_C_RESET [ 92.968536] usb 1-1: new high-speed USB device number 2 using dwc2 [ 92.975029] dwc2 1e101000.ifxhcd: SetPortFeature [ 92.978358] dwc2 1e101000.ifxhcd: SetPortFeature - USB_PORT_FEAT_RESET [ 92.984837] dwc2 1e101000.ifxhcd: In host mode, hprt0=1101 [ 92.990674] dwc2 1e101000.ifxhcd: gintsts=0529 gintmsk=f3000806 [ 93.060349] dwc2 1e101000.ifxhcd: DWC OTG HCD HUB STATUS DATA: Root port status changed [ 93.067020] dwc2 1e101000.ifxhcd: port_connect_status_change: 0 [ 93.073099] dwc2 1e101000.ifxhcd: port_reset_change: 0 [ 93.078375] dwc2 1e101000.ifxhcd: port_enable_change: 1 [ 93.083766] dwc2 1e101000.ifxhcd: port_suspend_change: 0 [ 93.089252] dwc2 1e101000.ifxhcd: port_over_current_change: 0 [ 93.096284] dwc2 1e101000.ifxhcd: gintsts=0529 gintmsk=f3000806 [ 93.152672] dwc2 1e101000.ifxhcd: ClearPortFeature USB_PORT_FEAT_C_RESET [ 93.216952] dwc2 1e101000.ifxhcd: DWC OTG HCD EP DISABLE: bEndpointAddress=0x00, ep->hcpriv=86e4fa00 [ 93.224792] dwc2 1e101000.ifxhcd: DWC OTG HCD EP DISABLE: bEndpointAddress=0x00, ep->hcpriv= (null) [ 93.233926] dwc2 1e101000.ifxhcd: DWC OTG HCD EP RESET: bEndpointAddress=0x00 [ 93.268547] dwc2 1e101000.ifxhcd: DWC OTG HCD EP RESET: bEndpointAddress=0x81 [ 93.274399] dwc2 1e101000.ifxhcd: DWC OTG HCD EP RESET: bEndpointAddress=0x01 [ 93.307463] usb-storage 1-1:1.0: USB Mass Storage device detected [ 93.312238] dwc2 1e101000.ifxhcd: DWC OTG HCD HUB STATUS DATA: Root port status changed [ 93.312256] dwc2 1e101000.ifxhcd: port_connect_status_change: 0 [ 93.312270] dwc2 1e101000.ifxhcd: port_reset_change: 0 [ 93.312329] dwc2 1e101000.ifxhcd: port_enable_change: 1 [ 93.312342] dwc2 1e101000.ifxhcd: port_suspend_change: 0 [ 93.312356] dwc2 1e101000.ifxhcd: port_over_current_change: 0 [ 93.408514] scsi host0: usb-storage 1-1:1.0 [ 93.437010] dwc2 1e101000.ifxhcd: ClearPortFeature USB_PORT_FEAT_C_ENABLE [ 94.152597] dwc2 1e101000.ifxhcd: DWC OTG HCD EP RESET: bEndpointAddress=0x01 [ 94.166421] dwc2 1e101000.ifxhcd: gintsts=2529 gintmsk=f3000806 [ 94.171336] dwc2 1e101000.ifxhcd: ++Disconnect Detected Interrupt++ (Host) a_host [ 94.180561] dwc2 1e101000.ifxhcd: DWC OTG HCD EP RESET: bEndpointAddress=0x01 [ 94.186473] dwc2 1e101000.ifxhcd: Not connected [ 94.300415] dwc2 1e101000.ifxhcd: DWC OTG HCD HUB STATUS DATA: Root port status changed [ 94.307074] dwc2 1e101000.ifxhcd: port_connect_status_change: 1 [ 94.313203] dwc2 1e101000.ifxhcd: port_reset_change: 0 [ 94.318467] dwc2 1e101000.ifxhcd: port_enable_change: 1 [ 94.323858] dwc2 1e101000.ifxhcd: port_suspend_change: 0 [ 94.329344] dwc2 1e101000.ifxhcd: port_over_current_change: 0 [ 94.336998] dwc2 1e101000.ifxhcd: ClearPortFeature USB_PORT_FEAT_C_CONNECTION [ 94.343368] dwc2 1e101000.ifxhcd: ClearPortFeature USB_PORT_FEAT_C_ENABLE [ 94.350145] usb 1-1: USB disconnect, device number 2 [ 94.365605] dwc2 1e101000.ifxhcd: DWC OTG HCD EP DISABLE: bEndpointAddress=0x00, ep->hcpriv=86e4f980 [ 94.373454] dwc2 1e101000.ifxhcd: DWC OTG HCD EP DISABLE: bEndpointAddress=0x00, ep->hcpriv= (null) [ 94.382555] dwc2 1e101000.ifxhcd: DWC OTG HCD EP DISABLE: bEndpointAddress=0x01, ep->hcpriv=86e61400 [ 94.391728] dwc2 1e101000.ifxhcd: DWC OTG HCD EP
[PATCH] usb: dwc2: Add support for Lantiq ARX and XRX SoCs
Add support for Lantiq ARX and XRX SoC families to the dwc2 driver. Signed-off-by: Antti Seppälä <a.sepp...@gmail.com> --- Documentation/devicetree/bindings/usb/dwc2.txt | 2 ++ drivers/usb/dwc2/platform.c| 34 ++ 2 files changed, 36 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/dwc2.txt b/Documentation/devicetree/bindings/usb/dwc2.txt index 2213682..20a68bf 100644 --- a/Documentation/devicetree/bindings/usb/dwc2.txt +++ b/Documentation/devicetree/bindings/usb/dwc2.txt @@ -8,6 +8,8 @@ Required properties: - rockchip,rk3066-usb: The DWC2 USB controller instance in the rk3066 Soc; - "rockchip,rk3188-usb", "rockchip,rk3066-usb", "snps,dwc2": for rk3188 Soc; - "rockchip,rk3288-usb", "rockchip,rk3066-usb", "snps,dwc2": for rk3288 Soc; + - "lantiq,arx100-usb": The DWC2 USB controller instance in Lantiq ARX SoCs; + - "lantiq,xrx200-usb": The DWC2 USB controller instance in Lantiq XRX SoCs; - snps,dwc2: A generic DWC2 USB controller with default parameters. - reg : Should contain 1 register range (address and length) - interrupts : Should contain 1 interrupt diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 690b9fd..0e9e4d3 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -149,6 +149,38 @@ static const struct dwc2_core_params params_rk3066 = { .hibernation= -1, }; +static const struct dwc2_core_params params_ltq = { + .otg_cap= 2,/* non-HNP/non-SRP */ + .otg_ver= -1, + .dma_enable = -1, + .dma_desc_enable= -1, + .dma_desc_fs_enable = -1, + .speed = -1, + .enable_dynamic_fifo= -1, + .en_multiple_tx_fifo= -1, + .host_rx_fifo_size = 288, /* 288 DWORDs */ + .host_nperio_tx_fifo_size = 128, /* 128 DWORDs */ + .host_perio_tx_fifo_size= 96, /* 96 DWORDs */ + .max_transfer_size = 65535, + .max_packet_count = 511, + .host_channels = -1, + .phy_type = -1, + .phy_utmi_width = -1, + .phy_ulpi_ddr = -1, + .phy_ulpi_ext_vbus = -1, + .i2c_enable = -1, + .ulpi_fs_ls = -1, + .host_support_fs_ls_low_power = -1, + .host_ls_low_power_phy_clk = -1, + .ts_dline = -1, + .reload_ctl = -1, + .ahbcfg = GAHBCFG_HBSTLEN_INCR16 << + GAHBCFG_HBSTLEN_SHIFT, + .uframe_sched = -1, + .external_id_pin_ctl= -1, + .hibernation= -1, +}; + /* * Check the dr_mode against the module configuration and hardware * capabilities. @@ -428,6 +460,8 @@ static const struct of_device_id dwc2_of_match_table[] = { { .compatible = "brcm,bcm2835-usb", .data = _bcm2835 }, { .compatible = "hisilicon,hi6220-usb", .data = _hi6220 }, { .compatible = "rockchip,rk3066-usb", .data = _rk3066 }, + { .compatible = "lantiq,arx100-usb", .data = _ltq }, + { .compatible = "lantiq,xrx200-usb", .data = _ltq }, { .compatible = "snps,dwc2", .data = NULL }, { .compatible = "samsung,s3c6400-hsotg", .data = NULL}, {}, -- 2.4.10 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 2/2] usb: dwc2: host: Clear interrupts before handling them
On 19 November 2015 at 21:45, Douglas Andersonwrote: > In general it is wise to clear interrupts before processing them. If > you don't do that, you can get: > 1. Interrupt happens > 2. You look at system state and process interrupt > 3. A new interrupt happens > 4. You clear interrupt without processing it. > > This patch was actually a first attempt to fix missing device insertions > as described in (usb: dwc2: host: Fix missing device insertions) and it > did solve some of the signal bouncing problems but not all of > them (which is why I submitted the other patch). Specifically, this > patch itself would sometimes change: > 1. hardware sees connect > 2. hardware sees disconnect > 3. hardware sees connect > 4. dwc2_port_intr() - clears connect interrupt > 5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect() > > ...to: > 1. hardware sees connect > 2. hardware sees disconnect > 3. dwc2_port_intr() - clears connect interrupt > 4. hardware sees connect > 5. dwc2_handle_common_intr() - calls dwc2_hcd_disconnect() > > ...but with different timing then sometimes we'd still miss cable > insertions. > > In any case, though this patch doesn't fix any (known) problems, it > still seems wise as a general policy to clear interrupt before handling > them. > > Signed-off-by: Douglas Anderson > Acked-by: John Youn > Tested-by: John Youn > --- > Changes in v3: > - Don't (uselessly) clear the PRTINT anymore (Felipe Balbi). > > Changes in v2: None > Hi. It seems that towards the end of hcd_intr.c you seem to be switching a few calls of dwc2_writel() to plain writel(). It looks like something that is easily overlooked but please always use dwc2_writel to preserve correct register endianness on big-endian platforms. Br, -- Antti -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3] usb: dwc2: add support for big-endian Lantiq SoCs
Here is a patch which makes it possible to support mips based big-endian SoCs made by Lantiq in the dwc2 driver. The patch converts the readl/writel io-accessors of dwc2 to big-endian friendly versions and was discussed on the linux-usb ml already earlier [1]. The patch has been included in OpenWrt for some time now and it would be nice to get some more exposure to it. It was also agreed that this patch would be redone once certain other patches have been applied to dwc2 [2]. As dust has probably settled enough here is the patch again, rebased to the latest usb-next tree. I've also dropped the dwc2 core parameters patch for Lantiq from this series for now as finding the right parameters is still a bit of a work in progress. [1] http://www.spinics.net/lists/linux-usb/msg122814.html [2] http://www.spinics.net/lists/linux-usb/msg122897.html Antti Seppälä (1): usb: dwc2: Use platform endianness when accessing registers drivers/usb/dwc2/core.c | 469 ++- drivers/usb/dwc2/core.h | 28 ++- drivers/usb/dwc2/core_intr.c | 73 +++ drivers/usb/dwc2/debugfs.c | 52 ++--- drivers/usb/dwc2/gadget.c| 314 ++--- drivers/usb/dwc2/hcd.c | 140 ++--- drivers/usb/dwc2/hcd.h | 15 +- drivers/usb/dwc2/hcd_ddma.c | 10 +- drivers/usb/dwc2/hcd_intr.c | 82 drivers/usb/dwc2/hcd_queue.c | 10 +- 10 files changed, 606 insertions(+), 587 deletions(-) -- 2.4.6 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3] usb: dwc2: Use platform endianness when accessing registers
This patch switches calls to readl/writel to their dwc2_readl/dwc2_writel equivalents which preserve platform endianness. This patch is necessary to access dwc2 registers correctly on big-endian systems such as the mips based SoCs made by Lantiq. Then dwc2 can be used to replace ifx-hcd driver for Lantiq platforms found e.g. in OpenWrt. The patch was autogenerated with the following commands: $EDITOR core.h sed -i s/\readl\/dwc2_readl/g *.c hcd.h hw.h sed -i s/\writel\/dwc2_writel/g *.c hcd.h hw.h Some files were then hand-edited to fix checkpatch.pl warnings about too long lines. Signed-off-by: Antti Seppälä a.sepp...@gmail.com Signed-off-by: Vincent Pelletier plr.vinc...@gmail.com --- Notes: Changes in v2: - Fixed wrong comment style Changes in v3 - Rebased against latest linux-next - Tweaked indentation in some files drivers/usb/dwc2/core.c | 469 ++- drivers/usb/dwc2/core.h | 28 ++- drivers/usb/dwc2/core_intr.c | 73 +++ drivers/usb/dwc2/debugfs.c | 52 ++--- drivers/usb/dwc2/gadget.c| 314 ++--- drivers/usb/dwc2/hcd.c | 140 ++--- drivers/usb/dwc2/hcd.h | 15 +- drivers/usb/dwc2/hcd_ddma.c | 10 +- drivers/usb/dwc2/hcd_intr.c | 82 drivers/usb/dwc2/hcd_queue.c | 10 +- 10 files changed, 606 insertions(+), 587 deletions(-) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index c3cc1a7..a9de441 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -73,13 +73,13 @@ static int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg) /* Backup Host regs */ hr = hsotg-hr_backup; - hr-hcfg = readl(hsotg-regs + HCFG); - hr-haintmsk = readl(hsotg-regs + HAINTMSK); + hr-hcfg = dwc2_readl(hsotg-regs + HCFG); + hr-haintmsk = dwc2_readl(hsotg-regs + HAINTMSK); for (i = 0; i hsotg-core_params-host_channels; ++i) - hr-hcintmsk[i] = readl(hsotg-regs + HCINTMSK(i)); + hr-hcintmsk[i] = dwc2_readl(hsotg-regs + HCINTMSK(i)); - hr-hprt0 = readl(hsotg-regs + HPRT0); - hr-hfir = readl(hsotg-regs + HFIR); + hr-hprt0 = dwc2_readl(hsotg-regs + HPRT0); + hr-hfir = dwc2_readl(hsotg-regs + HFIR); hr-valid = true; return 0; @@ -108,14 +108,14 @@ static int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg) } hr-valid = false; - writel(hr-hcfg, hsotg-regs + HCFG); - writel(hr-haintmsk, hsotg-regs + HAINTMSK); + dwc2_writel(hr-hcfg, hsotg-regs + HCFG); + dwc2_writel(hr-haintmsk, hsotg-regs + HAINTMSK); for (i = 0; i hsotg-core_params-host_channels; ++i) - writel(hr-hcintmsk[i], hsotg-regs + HCINTMSK(i)); + dwc2_writel(hr-hcintmsk[i], hsotg-regs + HCINTMSK(i)); - writel(hr-hprt0, hsotg-regs + HPRT0); - writel(hr-hfir, hsotg-regs + HFIR); + dwc2_writel(hr-hprt0, hsotg-regs + HPRT0); + dwc2_writel(hr-hfir, hsotg-regs + HFIR); return 0; } @@ -146,15 +146,15 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) /* Backup dev regs */ dr = hsotg-dr_backup; - dr-dcfg = readl(hsotg-regs + DCFG); - dr-dctl = readl(hsotg-regs + DCTL); - dr-daintmsk = readl(hsotg-regs + DAINTMSK); - dr-diepmsk = readl(hsotg-regs + DIEPMSK); - dr-doepmsk = readl(hsotg-regs + DOEPMSK); + dr-dcfg = dwc2_readl(hsotg-regs + DCFG); + dr-dctl = dwc2_readl(hsotg-regs + DCTL); + dr-daintmsk = dwc2_readl(hsotg-regs + DAINTMSK); + dr-diepmsk = dwc2_readl(hsotg-regs + DIEPMSK); + dr-doepmsk = dwc2_readl(hsotg-regs + DOEPMSK); for (i = 0; i hsotg-num_of_eps; i++) { /* Backup IN EPs */ - dr-diepctl[i] = readl(hsotg-regs + DIEPCTL(i)); + dr-diepctl[i] = dwc2_readl(hsotg-regs + DIEPCTL(i)); /* Ensure DATA PID is correctly configured */ if (dr-diepctl[i] DXEPCTL_DPID) @@ -162,11 +162,11 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) else dr-diepctl[i] |= DXEPCTL_SETD0PID; - dr-dieptsiz[i] = readl(hsotg-regs + DIEPTSIZ(i)); - dr-diepdma[i] = readl(hsotg-regs + DIEPDMA(i)); + dr-dieptsiz[i] = dwc2_readl(hsotg-regs + DIEPTSIZ(i)); + dr-diepdma[i] = dwc2_readl(hsotg-regs + DIEPDMA(i)); /* Backup OUT EPs */ - dr-doepctl[i] = readl(hsotg-regs + DOEPCTL(i)); + dr-doepctl[i] = dwc2_readl(hsotg-regs + DOEPCTL(i)); /* Ensure DATA PID is correctly configured */ if (dr-doepctl[i] DXEPCTL_DPID) @@ -174,8 +174,8 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg) else dr-doepctl[i] |= DXEPCTL_SETD0PID; - dr-doeptsiz
[PATCH v2 1/2] usb: dwc2: Use platform endianness when accessing registers
This patch switches calls to readl/writel to their dwc2_readl/dwc2_writel equivalents which preserve platform endianness. This patch is necessary to access dwc2 registers correctly on big endian systems such as the mips based SoCs made by Lantiq. Then dwc2 can be used to replace ifx-hcd driver for Lantiq platforms found e.g. in OpenWrt. The patch was autogenerated with the following commands: $EDITOR core.h sed -i s/\readl\/dwc2_readl/g *.c hcd.h hw.h sed -i s/\writel\/dwc2_writel/g *.c hcd.h hw.h Some files were then hand-edited to fix checkpatch.pl warnings about too long lines. Signed-off-by: Antti Seppälä a.sepp...@gmail.com Signed-off-by: Vincent Pelletier plr.vinc...@gmail.com --- drivers/usb/dwc2/core.c | 341 ++- drivers/usb/dwc2/core.h | 29 +++- drivers/usb/dwc2/core_intr.c | 73 - drivers/usb/dwc2/gadget.c| 312 +++ drivers/usb/dwc2/hcd.c | 138 - drivers/usb/dwc2/hcd.h | 15 +- drivers/usb/dwc2/hcd_ddma.c | 10 +- drivers/usb/dwc2/hcd_intr.c | 82 +-- drivers/usb/dwc2/hcd_queue.c | 10 +- 9 files changed, 515 insertions(+), 495 deletions(-) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index d5197d4..a7bad24 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -67,10 +67,10 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) u32 intmsk; /* Clear any pending OTG Interrupts */ - writel(0x, hsotg-regs + GOTGINT); + dwc2_writel(0x, hsotg-regs + GOTGINT); /* Clear any pending interrupts */ - writel(0x, hsotg-regs + GINTSTS); + dwc2_writel(0x, hsotg-regs + GINTSTS); /* Enable the interrupts in the GINTMSK */ intmsk = GINTSTS_MODEMIS | GINTSTS_OTGINT; @@ -81,7 +81,7 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) intmsk |= GINTSTS_CONIDSTSCHNG | GINTSTS_WKUPINT | GINTSTS_USBSUSP | GINTSTS_SESSREQINT; - writel(intmsk, hsotg-regs + GINTMSK); + dwc2_writel(intmsk, hsotg-regs + GINTMSK); } /* @@ -104,10 +104,10 @@ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) } dev_dbg(hsotg-dev, Initializing HCFG.FSLSPClkSel to %08x\n, val); - hcfg = readl(hsotg-regs + HCFG); + hcfg = dwc2_readl(hsotg-regs + HCFG); hcfg = ~HCFG_FSLSPCLKSEL_MASK; hcfg |= val HCFG_FSLSPCLKSEL_SHIFT; - writel(hcfg, hsotg-regs + HCFG); + dwc2_writel(hcfg, hsotg-regs + HCFG); } /* @@ -125,7 +125,7 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg) /* Wait for AHB master IDLE state */ do { usleep_range(2, 4); - greset = readl(hsotg-regs + GRSTCTL); + greset = dwc2_readl(hsotg-regs + GRSTCTL); if (++count 50) { dev_warn(hsotg-dev, %s() HANG! AHB Idle GRSTCTL=%0x\n, @@ -137,10 +137,10 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg) /* Core Soft Reset */ count = 0; greset |= GRSTCTL_CSFTRST; - writel(greset, hsotg-regs + GRSTCTL); + dwc2_writel(greset, hsotg-regs + GRSTCTL); do { usleep_range(2, 4); - greset = readl(hsotg-regs + GRSTCTL); + greset = dwc2_readl(hsotg-regs + GRSTCTL); if (++count 50) { dev_warn(hsotg-dev, %s() HANG! Soft Reset GRSTCTL=%0x\n, @@ -150,20 +150,20 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg) } while (greset GRSTCTL_CSFTRST); if (hsotg-dr_mode == USB_DR_MODE_HOST) { - gusbcfg = readl(hsotg-regs + GUSBCFG); + gusbcfg = dwc2_readl(hsotg-regs + GUSBCFG); gusbcfg = ~GUSBCFG_FORCEDEVMODE; gusbcfg |= GUSBCFG_FORCEHOSTMODE; - writel(gusbcfg, hsotg-regs + GUSBCFG); + dwc2_writel(gusbcfg, hsotg-regs + GUSBCFG); } else if (hsotg-dr_mode == USB_DR_MODE_PERIPHERAL) { - gusbcfg = readl(hsotg-regs + GUSBCFG); + gusbcfg = dwc2_readl(hsotg-regs + GUSBCFG); gusbcfg = ~GUSBCFG_FORCEHOSTMODE; gusbcfg |= GUSBCFG_FORCEDEVMODE; - writel(gusbcfg, hsotg-regs + GUSBCFG); + dwc2_writel(gusbcfg, hsotg-regs + GUSBCFG); } else if (hsotg-dr_mode == USB_DR_MODE_OTG) { - gusbcfg = readl(hsotg-regs + GUSBCFG); + gusbcfg = dwc2_readl(hsotg-regs + GUSBCFG); gusbcfg = ~GUSBCFG_FORCEHOSTMODE; gusbcfg = ~GUSBCFG_FORCEDEVMODE; - writel(gusbcfg, hsotg-regs + GUSBCFG); + dwc2_writel(gusbcfg, hsotg-regs + GUSBCFG); } /* @@ -186,9 +186,9 @@ static int dwc2_fs_phy_init(struct
[PATCH v2 0/2] usb: dwc2: add support for big-endian Lantiq SoCs
Here are two patches needed to add support for mips based big-endian SoCs made by Lantiq to dwc2 driver. The first patch converts the readl/writel io-accessors of dwc2 to big-endian friendly versions and was discussed on the linux-usb ml already earlier. The second patch adds default fifo parameters for Lantiq SoCs to dwc2 which is needed to support devices equipped with smaller fifo sizes. Note: The only reason for the second patch to exist is that dynamic calculation algorithm in dwc2_calculate_dynamic_fifo does not cope well with fifo sizes below certain limit. Changes since previous version: * Patches updated to apply to latest dwc2 code * Fixing wrong comment style (as pointed out by Felipe Balbi) Antti Seppälä (2): usb: dwc2: Use platform endianness when accessing registers usb: dwc2: Add default fifo sizes for Lantiq SoCs Documentation/devicetree/bindings/usb/dwc2.txt | 1 + drivers/usb/dwc2/core.c| 341 + drivers/usb/dwc2/core.h| 29 ++- drivers/usb/dwc2/core_intr.c | 73 +++--- drivers/usb/dwc2/gadget.c | 312 +++--- drivers/usb/dwc2/hcd.c | 138 +- drivers/usb/dwc2/hcd.h | 15 +- drivers/usb/dwc2/hcd_ddma.c| 10 +- drivers/usb/dwc2/hcd_intr.c| 82 +++--- drivers/usb/dwc2/hcd_queue.c | 10 +- drivers/usb/dwc2/platform.c| 29 +++ 11 files changed, 545 insertions(+), 495 deletions(-) -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] usb: dwc2: Add default fifo sizes for Lantiq SoCs
Lantiq SoCs define the total_fifo_size to be 552 dwords which is too small for algorithm in dwc2_calculate_dynamic_fifo to work properly. This patch provides sensible defaults for fifo sizes for Lantiq SoCs to be used in dwc2 driver. The default values are taken from original ifx-hcd driver. Signed-off-by: Antti Seppälä a.sepp...@gmail.com Signed-off-by: Vincent Pelletier plr.vinc...@gmail.com --- Documentation/devicetree/bindings/usb/dwc2.txt | 1 + drivers/usb/dwc2/platform.c| 29 ++ 2 files changed, 30 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/dwc2.txt b/Documentation/devicetree/bindings/usb/dwc2.txt index fd132cb..9182a9f 100644 --- a/Documentation/devicetree/bindings/usb/dwc2.txt +++ b/Documentation/devicetree/bindings/usb/dwc2.txt @@ -7,6 +7,7 @@ Required properties: - rockchip,rk3066-usb: The DWC2 USB controller instance in the rk3066 Soc; - rockchip,rk3188-usb, rockchip,rk3066-usb, snps,dwc2: for rk3188 Soc; - rockchip,rk3288-usb, rockchip,rk3066-usb, snps,dwc2: for rk3288 Soc; + - lantiq,dwc2: DWC2 USB controllers found in Lantiq SoCs; - snps,dwc2: A generic DWC2 USB controller with default parameters. - reg : Should contain 1 register range (address and length) - interrupts : Should contain 1 interrupt diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index ae095f0..99d6b60 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -106,6 +106,34 @@ static const struct dwc2_core_params params_rk3066 = { .uframe_sched = -1, }; +static const struct dwc2_core_params params_ltq = { + .otg_cap= -1, + .otg_ver= -1, + .dma_enable = -1, + .dma_desc_enable= -1, + .speed = -1, + .enable_dynamic_fifo= -1, + .en_multiple_tx_fifo= -1, + .host_rx_fifo_size = 240, /* 240 DWORDs */ + .host_nperio_tx_fifo_size = 240, /* 240 DWORDs */ + .host_perio_tx_fifo_size= 32, /* 32 DWORDs */ + .max_transfer_size = -1, + .max_packet_count = -1, + .host_channels = -1, + .phy_type = -1, + .phy_utmi_width = -1, + .phy_ulpi_ddr = -1, + .phy_ulpi_ext_vbus = -1, + .i2c_enable = -1, + .ulpi_fs_ls = -1, + .host_support_fs_ls_low_power = -1, + .host_ls_low_power_phy_clk = -1, + .ts_dline = -1, + .reload_ctl = -1, + .ahbcfg = -1, + .uframe_sched = -1, +}; + /** * dwc2_driver_remove() - Called when the DWC_otg core is unregistered with the * DWC_otg driver @@ -130,6 +158,7 @@ static int dwc2_driver_remove(struct platform_device *dev) static const struct of_device_id dwc2_of_match_table[] = { { .compatible = brcm,bcm2835-usb, .data = params_bcm2835 }, { .compatible = rockchip,rk3066-usb, .data = params_rk3066 }, + { .compatible = lantiq,dwc2, .data = params_ltq }, { .compatible = snps,dwc2, .data = NULL }, { .compatible = samsung,s3c6400-hsotg, .data = NULL}, {}, -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] usb: dwc2: Use platform endianness when accessing registers
This patch switches calls to readl/writel to their dwc2_readl/dwc2_writel equivalents which preserve platform endianness. This patch is necessary to access dwc2 registers correctly on big endian systems such as the mips based SoCs made by Lantiq. Then dwc2 can be used to replace ifx-hcd driver for Lantiq platforms found e.g. in OpenWrt. The patch was autogenerated with the following commands: $EDITOR core.h sed -i s/\readl\/dwc2_readl/g *.c hcd.h hw.h sed -i s/\writel\/dwc2_writel/g *.c hcd.h hw.h Some files were then hand-edited to fix checkpatch.pl warnings about too long lines. Signed-off-by: Antti Seppälä a.sepp...@gmail.com Signed-off-by: Vincent Pelletier plr.vinc...@gmail.com --- drivers/usb/dwc2/core.c | 341 ++- drivers/usb/dwc2/core.h | 24 ++- drivers/usb/dwc2/core_intr.c | 73 - drivers/usb/dwc2/gadget.c| 312 +++ drivers/usb/dwc2/hcd.c | 144 +- drivers/usb/dwc2/hcd.h | 15 +- drivers/usb/dwc2/hcd_ddma.c | 10 +- drivers/usb/dwc2/hcd_intr.c | 82 +-- drivers/usb/dwc2/hcd_queue.c | 10 +- 9 files changed, 513 insertions(+), 498 deletions(-) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 7605850b..10f50e5 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -67,10 +67,10 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) u32 intmsk; /* Clear any pending OTG Interrupts */ - writel(0x, hsotg-regs + GOTGINT); + dwc2_writel(0x, hsotg-regs + GOTGINT); /* Clear any pending interrupts */ - writel(0x, hsotg-regs + GINTSTS); + dwc2_writel(0x, hsotg-regs + GINTSTS); /* Enable the interrupts in the GINTMSK */ intmsk = GINTSTS_MODEMIS | GINTSTS_OTGINT; @@ -81,7 +81,7 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) intmsk |= GINTSTS_CONIDSTSCHNG | GINTSTS_WKUPINT | GINTSTS_USBSUSP | GINTSTS_SESSREQINT; - writel(intmsk, hsotg-regs + GINTMSK); + dwc2_writel(intmsk, hsotg-regs + GINTMSK); } /* @@ -104,10 +104,10 @@ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) } dev_dbg(hsotg-dev, Initializing HCFG.FSLSPClkSel to %08x\n, val); - hcfg = readl(hsotg-regs + HCFG); + hcfg = dwc2_readl(hsotg-regs + HCFG); hcfg = ~HCFG_FSLSPCLKSEL_MASK; hcfg |= val HCFG_FSLSPCLKSEL_SHIFT; - writel(hcfg, hsotg-regs + HCFG); + dwc2_writel(hcfg, hsotg-regs + HCFG); } /* @@ -125,7 +125,7 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg) /* Wait for AHB master IDLE state */ do { usleep_range(2, 4); - greset = readl(hsotg-regs + GRSTCTL); + greset = dwc2_readl(hsotg-regs + GRSTCTL); if (++count 50) { dev_warn(hsotg-dev, %s() HANG! AHB Idle GRSTCTL=%0x\n, @@ -137,10 +137,10 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg) /* Core Soft Reset */ count = 0; greset |= GRSTCTL_CSFTRST; - writel(greset, hsotg-regs + GRSTCTL); + dwc2_writel(greset, hsotg-regs + GRSTCTL); do { usleep_range(2, 4); - greset = readl(hsotg-regs + GRSTCTL); + greset = dwc2_readl(hsotg-regs + GRSTCTL); if (++count 50) { dev_warn(hsotg-dev, %s() HANG! Soft Reset GRSTCTL=%0x\n, @@ -150,20 +150,20 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg) } while (greset GRSTCTL_CSFTRST); if (hsotg-dr_mode == USB_DR_MODE_HOST) { - gusbcfg = readl(hsotg-regs + GUSBCFG); + gusbcfg = dwc2_readl(hsotg-regs + GUSBCFG); gusbcfg = ~GUSBCFG_FORCEDEVMODE; gusbcfg |= GUSBCFG_FORCEHOSTMODE; - writel(gusbcfg, hsotg-regs + GUSBCFG); + dwc2_writel(gusbcfg, hsotg-regs + GUSBCFG); } else if (hsotg-dr_mode == USB_DR_MODE_PERIPHERAL) { - gusbcfg = readl(hsotg-regs + GUSBCFG); + gusbcfg = dwc2_readl(hsotg-regs + GUSBCFG); gusbcfg = ~GUSBCFG_FORCEHOSTMODE; gusbcfg |= GUSBCFG_FORCEDEVMODE; - writel(gusbcfg, hsotg-regs + GUSBCFG); + dwc2_writel(gusbcfg, hsotg-regs + GUSBCFG); } else if (hsotg-dr_mode == USB_DR_MODE_OTG) { - gusbcfg = readl(hsotg-regs + GUSBCFG); + gusbcfg = dwc2_readl(hsotg-regs + GUSBCFG); gusbcfg = ~GUSBCFG_FORCEHOSTMODE; gusbcfg = ~GUSBCFG_FORCEDEVMODE; - writel(gusbcfg, hsotg-regs + GUSBCFG); + dwc2_writel(gusbcfg, hsotg-regs + GUSBCFG); } /* @@ -186,9 +186,9 @@ static int dwc2_fs_phy_init(struct
[PATCH 2/2] usb: dwc2: Add default fifo sizes for Lantiq SoCs
Lantiq SoCs define the total_fifo_size to be 552 dwords which is too small for algorithm in dwc2_calculate_dynamic_fifo to work properly. This patch provides sensible defaults for fifo sizes for Lantiq SoCs to be used in dwc2 driver. The default values are taken from original ifx-hcd driver. Signed-off-by: Antti Seppälä a.sepp...@gmail.com Signed-off-by: Vincent Pelletier plr.vinc...@gmail.com --- Documentation/devicetree/bindings/usb/dwc2.txt | 1 + drivers/usb/dwc2/platform.c| 29 ++ 2 files changed, 30 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/dwc2.txt b/Documentation/devicetree/bindings/usb/dwc2.txt index 482f815..2b3a2b2 100644 --- a/Documentation/devicetree/bindings/usb/dwc2.txt +++ b/Documentation/devicetree/bindings/usb/dwc2.txt @@ -7,6 +7,7 @@ Required properties: - rockchip,rk3066-usb: The DWC2 USB controller instance in the rk3066 Soc; - rockchip,rk3188-usb, rockchip,rk3066-usb, snps,dwc2: for rk3188 Soc; - rockchip,rk3288-usb, rockchip,rk3066-usb, snps,dwc2: for rk3288 Soc; + - lantiq,dwc2: DWC2 USB controllers found in Lantiq SoCs; - snps,dwc2: A generic DWC2 USB controller with default parameters. - reg : Should contain 1 register range (address and length) - interrupts : Should contain 1 interrupt diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 6a795aa..2b0714a 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -106,6 +106,34 @@ static const struct dwc2_core_params params_rk3066 = { .uframe_sched = -1, }; +static const struct dwc2_core_params params_ltq = { + .otg_cap= -1, + .otg_ver= -1, + .dma_enable = -1, + .dma_desc_enable= -1, + .speed = -1, + .enable_dynamic_fifo= -1, + .en_multiple_tx_fifo= -1, + .host_rx_fifo_size = 240, /* 240 DWORDs */ + .host_nperio_tx_fifo_size = 240, /* 240 DWORDs */ + .host_perio_tx_fifo_size= 32, /* 32 DWORDs */ + .max_transfer_size = -1, + .max_packet_count = -1, + .host_channels = -1, + .phy_type = -1, + .phy_utmi_width = -1, + .phy_ulpi_ddr = -1, + .phy_ulpi_ext_vbus = -1, + .i2c_enable = -1, + .ulpi_fs_ls = -1, + .host_support_fs_ls_low_power = -1, + .host_ls_low_power_phy_clk = -1, + .ts_dline = -1, + .reload_ctl = -1, + .ahbcfg = -1, + .uframe_sched = -1, +}; + /** * dwc2_driver_remove() - Called when the DWC_otg core is unregistered with the * DWC_otg driver @@ -130,6 +158,7 @@ static int dwc2_driver_remove(struct platform_device *dev) static const struct of_device_id dwc2_of_match_table[] = { { .compatible = brcm,bcm2835-usb, .data = params_bcm2835 }, { .compatible = rockchip,rk3066-usb, .data = params_rk3066 }, + { .compatible = lantiq,dwc2, .data = params_ltq }, { .compatible = snps,dwc2, .data = NULL }, { .compatible = samsung,s3c6400-hsotg, .data = NULL}, {}, -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/2] usb: dwc2: add support for big-endian Lantiq SoCs
Here are two patches needed to add support for mips based big-endian SoCs made by Lantiq to dwc2 driver. The first patch converts the readl/writel io-accessors of dwc2 to big-endian friendly versions and was discussed on the linux-usb ml already earlier. The second patch adds default fifo parameters for Lantiq SoCs to dwc2 which is needed to support devices equipped with smaller fifo sizes. Antti Seppälä (2): usb: dwc2: Use platform endianness when accessing registers usb: dwc2: Add default fifo sizes for Lantiq SoCs Documentation/devicetree/bindings/usb/dwc2.txt | 1 + drivers/usb/dwc2/core.c| 341 + drivers/usb/dwc2/core.h| 24 +- drivers/usb/dwc2/core_intr.c | 73 +++--- drivers/usb/dwc2/gadget.c | 312 +++--- drivers/usb/dwc2/hcd.c | 144 +-- drivers/usb/dwc2/hcd.h | 15 +- drivers/usb/dwc2/hcd_ddma.c| 10 +- drivers/usb/dwc2/hcd_intr.c| 82 +++--- drivers/usb/dwc2/hcd_queue.c | 10 +- drivers/usb/dwc2/platform.c| 29 +++ 11 files changed, 543 insertions(+), 498 deletions(-) -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH] usb: dwc2: Use platform endianness when accessing registers
On 27 January 2015 at 04:18, John Youn john.y...@synopsys.com wrote: From: Vincent Pelletier [mailto:plr.vinc...@gmail.com] Sent: Friday, January 23, 2015 12:19 AM On Fri, 23 Jan 2015 02:38:37 +, John Youn john.y...@synopsys.com wrote: Having the __raw functions everywhere is not pretty and probably not a good idea either. I would rather have a dwc2_writel/dwc2_readl (like in dwc3), and we can figure out what needs to happen in there to support your platform. As for readl/writel or the __raw equivalents, I am not sure. I haven't run the in-kernel driver on a big endian system so I don't know what the issue is. But I suspect there may be consequences to other platforms if we simply change this to __raw_readl/__raw_writel. (focussing on readl, but the following also applies to writel) readl is defined as __le32_to_cpu(__raw_readl(...)), so using readl on little endian is equivalent to __raw_readl, as __le32_to_cpu is a no-op. On big endian, it causes problems because __le32_to_cpu swaps bytes around, causing GSNPSID to be read as 0xnn2n544f instead of expected 0x4f542nnn - and likewise for all other registers. An earlier version (sent to linux-usb a week ago with not enough CC, but I cannot find it in archives now) defined dwc2_readl as le32_to_cpu(readl(...)) which is equivalent to le32_to_cpu(le32_to_cpu(__raw_readl(...))) and which, on big-endian, makes le32_to_cpu(le32_to_cpu()) a no-op and (ignoring possible compiler optimisation) swaps bytes twice per call. On little endian, it is still equivalent to __raw_readl(...). As for the prettiness of calling double-underscore functions, speaking for myself I'm not used to Linux development enough to tell. My python developer reflex tell me it's not how it should be. OTOH there is no raw_readl or so alias, and other USB drivers reference __raw_readl (example as of v3.14.28): linux/drivers/usb$ git grep -l __raw_readl gadget/at91_udc.c gadget/atmel_usba_udc.c gadget/atmel_usba_udc.h gadget/fsl_udc_core.c gadget/pxa27x_udc.h host/ehci-omap.c host/ehci-orion.c host/ehci-w90x900.c host/ehci.h host/isp1760-hcd.c host/ohci-da8xx.c host/ohci-nxp.c host/ohci-pxa27x.c musb/da8xx.c musb/davinci.c musb/musb_dsps.c musb/musb_io.h phy/phy-fsl-usb.c Would it be better to wrap __raw_readl in a macro and call that everywhere rather than calling __raw_readl itself ? I was thinking more along the lines of what dwc3 does. See drivers/usb/dwc3/io.h. One solution would be to do as above, and put in a compile-time check for your platform and call the appropriate access function. I believe writel/readl also preserves memory ordering so it might affect other platforms to just use the __raw equivalent in its place. Broadly speaking readl(x) can be split to three separate functions. I think it evaluates to something like below for dwc2: static inline u32 dwc2_readl(const volatile void __iomem *addr) { u32 value = __raw_readl(addr); /* Raw access to io */ value = le32_to_cpu(value); /* Ensure little-endian byte order */ mb(); /* Prevent re-ordering of io-accesses */ return value; } Now le32_to_cpu is a no-op for little-endian platforms and breaks dwc2 for big endian ones (as Vincent explained, it swaps bytes unnecessarily for big endian platforms). So I'm thinking of dropping it and re-spinning the patch with something like below: static inline u32 dwc2_readl(const volatile void __iomem *addr) { u32 value = __raw_readl(addr); /* Raw access to io */ mb(); /* Prevent re-ordering of io-accesses */ return value; } and then replacing all readl's in dwc2 with dwc2_readl (and same for writel). That way nothing should get broken on little-endian as we're only dropping a no-op and we get to use the same code for big-endian platforms too. Would that be ok? I really would not want to add platform specific io-access functionalities if we can manage with a generic approach. -- Antti -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFC PATCH] usb: dwc2: Use platform endianness when accessing registers
This patch switches calls to readl/writel to their __raw_readl/__raw_writel equivalents which preserve platform endianness. This patch is necessary to access dwc2 registers correctly on big endian systems such as mips. Then dwc2 can be used to replace ifx-hcd driver for lantiq platform found e.g. in OpenWrt. The patch was autogenerated with the following commands: sed -i s/\readl\/__raw_readl/g *.c hcd.h hw.h sed -i s/\writel\/__raw_writel/g *.c hcd.h hw.h Some files were then hand-edited to fix checkpatch.pl warning about too long lines. Signed-off-by: Antti Seppälä a.sepp...@gmail.com Signed-off-by: Vincent Pelletier plr.vinc...@gmail.com --- drivers/usb/dwc2/core.c | 341 ++- drivers/usb/dwc2/core_intr.c | 73 - drivers/usb/dwc2/gadget.c| 312 +++ drivers/usb/dwc2/hcd.c | 144 +- drivers/usb/dwc2/hcd.h | 15 +- drivers/usb/dwc2/hcd_ddma.c | 10 +- drivers/usb/dwc2/hcd_intr.c | 82 +-- drivers/usb/dwc2/hcd_queue.c | 10 +- 8 files changed, 495 insertions(+), 492 deletions(-) diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index 7605850b..30ef56b 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -67,10 +67,10 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) u32 intmsk; /* Clear any pending OTG Interrupts */ - writel(0x, hsotg-regs + GOTGINT); + __raw_writel(0x, hsotg-regs + GOTGINT); /* Clear any pending interrupts */ - writel(0x, hsotg-regs + GINTSTS); + __raw_writel(0x, hsotg-regs + GINTSTS); /* Enable the interrupts in the GINTMSK */ intmsk = GINTSTS_MODEMIS | GINTSTS_OTGINT; @@ -81,7 +81,7 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg) intmsk |= GINTSTS_CONIDSTSCHNG | GINTSTS_WKUPINT | GINTSTS_USBSUSP | GINTSTS_SESSREQINT; - writel(intmsk, hsotg-regs + GINTMSK); + __raw_writel(intmsk, hsotg-regs + GINTMSK); } /* @@ -104,10 +104,10 @@ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg) } dev_dbg(hsotg-dev, Initializing HCFG.FSLSPClkSel to %08x\n, val); - hcfg = readl(hsotg-regs + HCFG); + hcfg = __raw_readl(hsotg-regs + HCFG); hcfg = ~HCFG_FSLSPCLKSEL_MASK; hcfg |= val HCFG_FSLSPCLKSEL_SHIFT; - writel(hcfg, hsotg-regs + HCFG); + __raw_writel(hcfg, hsotg-regs + HCFG); } /* @@ -125,7 +125,7 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg) /* Wait for AHB master IDLE state */ do { usleep_range(2, 4); - greset = readl(hsotg-regs + GRSTCTL); + greset = __raw_readl(hsotg-regs + GRSTCTL); if (++count 50) { dev_warn(hsotg-dev, %s() HANG! AHB Idle GRSTCTL=%0x\n, @@ -137,10 +137,10 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg) /* Core Soft Reset */ count = 0; greset |= GRSTCTL_CSFTRST; - writel(greset, hsotg-regs + GRSTCTL); + __raw_writel(greset, hsotg-regs + GRSTCTL); do { usleep_range(2, 4); - greset = readl(hsotg-regs + GRSTCTL); + greset = __raw_readl(hsotg-regs + GRSTCTL); if (++count 50) { dev_warn(hsotg-dev, %s() HANG! Soft Reset GRSTCTL=%0x\n, @@ -150,20 +150,20 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg) } while (greset GRSTCTL_CSFTRST); if (hsotg-dr_mode == USB_DR_MODE_HOST) { - gusbcfg = readl(hsotg-regs + GUSBCFG); + gusbcfg = __raw_readl(hsotg-regs + GUSBCFG); gusbcfg = ~GUSBCFG_FORCEDEVMODE; gusbcfg |= GUSBCFG_FORCEHOSTMODE; - writel(gusbcfg, hsotg-regs + GUSBCFG); + __raw_writel(gusbcfg, hsotg-regs + GUSBCFG); } else if (hsotg-dr_mode == USB_DR_MODE_PERIPHERAL) { - gusbcfg = readl(hsotg-regs + GUSBCFG); + gusbcfg = __raw_readl(hsotg-regs + GUSBCFG); gusbcfg = ~GUSBCFG_FORCEHOSTMODE; gusbcfg |= GUSBCFG_FORCEDEVMODE; - writel(gusbcfg, hsotg-regs + GUSBCFG); + __raw_writel(gusbcfg, hsotg-regs + GUSBCFG); } else if (hsotg-dr_mode == USB_DR_MODE_OTG) { - gusbcfg = readl(hsotg-regs + GUSBCFG); + gusbcfg = __raw_readl(hsotg-regs + GUSBCFG); gusbcfg = ~GUSBCFG_FORCEHOSTMODE; gusbcfg = ~GUSBCFG_FORCEDEVMODE; - writel(gusbcfg, hsotg-regs + GUSBCFG); + __raw_writel(gusbcfg, hsotg-regs + GUSBCFG); } /* @@ -186,9 +186,9 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy
Regression: Two em28xx devices in the same xhci-hcd (bisected)
Data wMaxPacketSize 0x03ac 1x 940 bytes bInterval 1 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x85 EP 5 IN bmAttributes1 Transfer TypeIsochronous Synch Type None Usage Type Data wMaxPacketSize 0x03ac 1x 940 bytes bInterval 1 Device Qualifier (for other device speed): bLength10 bDescriptorType 6 bcdUSB 2.00 bDeviceClass0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize064 bNumConfigurations 1 Device Status: 0x (Bus Powered) Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Device Descriptor: bLength18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass9 Hub bDeviceSubClass 0 Unused bDeviceProtocol 1 Single TT bMaxPacketSize064 idVendor 0x1d6b Linux Foundation idProduct 0x0002 2.0 root hub bcdDevice3.15 iManufacturer 3 Linux 3.15.0-rc7-1-ge545e63 xhci_hcd iProduct2 xHCI Host Controller iSerial 1 :00:14.0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 25 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xe0 Self Powered Remote Wakeup MaxPower0mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 9 Hub bInterfaceSubClass 0 Unused bInterfaceProtocol 0 Full speed (or root) hub iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes3 Transfer TypeInterrupt Synch Type None Usage Type Data wMaxPacketSize 0x0004 1x 4 bytes bInterval 12 Hub Descriptor: bLength 11 bDescriptorType 41 nNbrPorts 9 wHubCharacteristic 0x000a No power switching (usb 1.0) Per-port overcurrent protection TT think time 8 FS bits bPwrOn2PwrGood 10 * 2 milli seconds bHubContrCurrent 0 milli Ampere DeviceRemovable0x00 0x02 PortPwrCtrlMask0xff 0xff Hub Port Status: Port 1: .0503 highspeed power enable connect Port 2: .0503 highspeed power enable connect Port 3: .0100 power Port 4: .0100 power Port 5: .0100 power Port 6: .0100 power Port 7: .0100 power Port 8: .0100 power Port 9: .0100 power Device Status: 0x0001 Self Powered Best regards, -- Antti Seppälä -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html