From: Mathias Nyman <mathias.nyman@linux.intel.com>
To: Marek Szyprowski <m.szyprowski@samsung.com>,
Nicolas Saenz Julienne <nsaenzjulienne@suse.de>,
gregkh@linuxfoundation.org
Cc: linux-usb@vger.kernel.org, Krzysztof Kozlowski <krzk@kernel.org>,
'Linux Samsung SOC' <linux-samsung-soc@vger.kernel.org>
Subject: Re: [PATCH 1/4] usb: xhci: add Immediate Data Transfer support
Date: Fri, 10 May 2019 10:30:21 +0300 [thread overview]
Message-ID: <51cf2371-baf3-1788-a77c-bca84ec11c9f@linux.intel.com> (raw)
In-Reply-To: <d5076a1a-b20e-8779-c38e-6bee0007b743@samsung.com>
On 10.5.2019 9.28, Marek Szyprowski wrote:
> Hi Mathias,
>
> On 2019-05-09 17:10, Mathias Nyman wrote:
>> On 9.5.2019 14.51, Nicolas Saenz Julienne wrote:
>>> On Thu, 2019-05-09 at 14:40 +0300, Mathias Nyman wrote:
>>>> On 9.5.2019 13.32, Marek Szyprowski wrote:
>>>>> Dear All,
>>>>>
>>>>> On 2019-04-26 15:23, Mathias Nyman wrote:
>>>>>> From: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
>>>>>>
>>>>>> Immediate data transfers (IDT) allow the HCD to copy small chunks of
>>>>>> data (up to 8bytes) directly into its output transfer TRBs. This
>>>>>> avoids
>>>>>> the somewhat expensive DMA mappings that are performed by default on
>>>>>> most URBs submissions.
>>>>>>
>>>>>> In the case an URB was suitable for IDT. The data is directly copied
>>>>>> into the "Data Buffer Pointer" region of the TRB and the IDT flag is
>>>>>> set. Instead of triggering memory accesses the HC will use the data
>>>>>> directly.
>>>>>>
>>>>>> The implementation could cover all kind of output endpoints. Yet
>>>>>> Isochronous endpoints are bypassed as I was unable to find one that
>>>>>> matched IDT's constraints. As we try to bypass the default DMA
>>>>>> mappings
>>>>>> on URB buffers we'd need to find a Isochronous device with an
>>>>>> urb->transfer_buffer_length <= 8 bytes.
>>>>>>
>>>>>> The implementation takes into account that the 8 byte buffers
>>>>>> provided
>>>>>> by the URB will never cross a 64KB boundary.
>>>>>>
>>>>>> Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
>>>>>> Reviewed-by: Felipe Balbi <felipe.balbi@linux.intel.com>
>>>>>> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
>>>>>
>>>>> I've noticed that this patch causes regression on various Samsung
>>>>> Exynos
>>>>> 5420/5422/5800 boards, which have USB3.0 host ports provided by
>>>>> DWC3/XHCI hardware module. The regression can be observed with ASIX
>>>>> USB
>>>>> 2.0 ethernet dongle, which stops working after applying this patch
>>>>> (eth0
>>>>> interface is registered, but no packets are transmitted/received).
>>>>> I can
>>>>> provide more debugging information or do some tests, just let me know
>>>>> what do you need. Reverting this commit makes ASIX USB ethernet dongle
>>>>> operational again.
>>>>>
>>>>
>>>> Thanks for reporting.
>>>>
>>>> Would it be possible to check if your ASIX ethernet dongle works on
>>>> some
>>>> desktop/laptop setup with this same IDT patch?
>>>>
>>>> Also Exynos xhci traces could help, they would show the content of
>>>> the TRBs
>>>> using IDT.
>>>> Maybe byte order gets messed up?
>>>>
>>>> Take traces with:
>>>>
>>>> mount -t debugfs none /sys/kernel/debug
>>>> echo 81920 > /sys/kernel/debug/tracing/buffer_size_kb
>>>> echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/enable
>>>>
>>>> <connect ASIX eth dongle, try to use it>
>>>>
>>>> send /sys/kernel/debug/tracing/trace content to me
>>>>
>>>> If we can't get this fixed I'll revert the IDT patch
>>>
>>> Hi Matthias, thanks for your help.
>>>
>>> I'll also be looking into it, so please send me the logs too.
>>>
>>
>> Got the logs off list, thanks
>>
>> The "Buffer" data in Control transfer Data stage look suspicious.
>>
>> grep "flags I:" trace_fail | grep Data
>> kworker/0:2-124 [000] d..1 63.092399: xhci_queue_trb: CTRL:
>> Buffer 0000000018b65000 length 6 TD size 0 intr 0 type 'Data Stage'
>> flags I:i:c:s:i:e:C
>> ifconfig-1429 [005] d..1 93.181231: xhci_queue_trb: CTRL: Buffer
>> 0000000018b65000 length 6 TD size 0 intr 0 type 'Data Stage' flags
>> I:i:c:s:i:e:C
>> ifconfig-1429 [007] dn.2 93.182050: xhci_queue_trb: CTRL: Buffer
>> 0000000000000000 length 8 TD size 0 intr 0 type 'Data Stage' flags
>> I:i:c:s:i:e:C
>> ifconfig-1429 [007] d..2 93.182499: xhci_queue_trb: CTRL: Buffer
>> 0000000080000000 length 8 TD size 0 intr 0 type 'Data Stage' flags
>> I:i:c:s:i:e:C
>> ifconfig-1429 [007] d..2 93.182736: xhci_queue_trb: CTRL: Buffer
>> 0000000080000000 length 8 TD size 0 intr 0 type 'Data Stage' flags
>> I:i:c:s:i:e:C
>> kworker/0:3-1409 [000] d..3 93.382630: xhci_queue_trb: CTRL:
>> Buffer 0000000080000000 length 8 TD size 0 intr 0 type 'Data Stage'
>> flags I:i:c:s:i:e:C
>>
>> First guess would be that in case URB has URB_NO_TRANSFER_DMA_MAP set
>> then data
>> will be mapped and urb->transfer_dma is already set.
>> The IDT patch uses urb->trabfer_dma as a temporary buffer, and copies the
>> urb->transfer_buffer there.
>> if transfer buffer is already dma mapped the urb->transfer_buffer can
>> be garbage,
>> (shouldn't, but it can be)
>>
>> Below code avoids IDT if URB_NO_TRANSFER_DMA_MAP is set, and doesn't
>> touch
>> urb->transfer_dma (patch attached)
>> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
>> index fed3385..f080054 100644
>> --- a/drivers/usb/host/xhci-ring.c
>> +++ b/drivers/usb/host/xhci-ring.c
>> @@ -3423,11 +3423,14 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci,
>> gfp_t mem_flags,
>>
>> if (urb->transfer_buffer_length > 0) {
>> u32 length_field, remainder;
>> + u64 addr;
>>
>> if (xhci_urb_suitable_for_idt(urb)) {
>> - memcpy(&urb->transfer_dma, urb->transfer_buffer,
>> + memcpy(&addr, urb->transfer_buffer,
>> urb->transfer_buffer_length);
>> field |= TRB_IDT;
>> + } else {
>> + addr = (u64) urb->transfer_dma;
>> }
>>
>> remainder = xhci_td_remainder(xhci, 0,
>> @@ -3440,8 +3443,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci,
>> gfp_t mem_flags,
>> if (setup->bRequestType & USB_DIR_IN)
>> field |= TRB_DIR_IN;
>> queue_trb(xhci, ep_ring, true,
>> - lower_32_bits(urb->transfer_dma),
>> - upper_32_bits(urb->transfer_dma),
>> + lower_32_bits(addr),
>> + upper_32_bits(addr),
>> length_field,
>> field | ep_ring->cycle_state);
>> }
>> diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
>> index a450a99..7f8b950 100644
>> --- a/drivers/usb/host/xhci.h
>> +++ b/drivers/usb/host/xhci.h
>> @@ -2160,7 +2160,8 @@ static inline bool
>> xhci_urb_suitable_for_idt(struct urb *urb)
>> {
>> if (!usb_endpoint_xfer_isoc(&urb->ep->desc) &&
>> usb_urb_dir_out(urb) &&
>> usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE &&
>> - urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE)
>> + urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE &&
>> + !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
>> return true;
>>
>> return false;
>>
> > If that doesn't help, then it's possible DATA trbs in control
> transfer can't
>> use IDT at all. IDT is supported for Normal TRBs, which have a
>> different trb
>> type than DATA trbs in control transfers.
>>
>> Also xhci specs 4.11.7 limit IDT usage:
>>
>> "If the IDT flag is set in one TRB of a TD, then it shall be the only
>> Transfer
>> TRB of the TD"
>>
>> A whole control transfer is one TD, and it already contains a SETUP
>> transfer TRB
>> which is using the IDT flag.
>>
>> Following disables IDT for control transfers (testpatch attached as well)
>>
>> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
>> index fed3385..4c1c9ad 100644
>> --- a/drivers/usb/host/xhci-ring.c
>> +++ b/drivers/usb/host/xhci-ring.c
>> @@ -3424,12 +3424,6 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci,
>> gfp_t mem_flags,
>> if (urb->transfer_buffer_length > 0) {
>> u32 length_field, remainder;
>>
>> - if (xhci_urb_suitable_for_idt(urb)) {
>> - memcpy(&urb->transfer_dma, urb->transfer_buffer,
>> - urb->transfer_buffer_length);
>> - field |= TRB_IDT;
>> - }
>> -
>> remainder = xhci_td_remainder(xhci, 0,
>> urb->transfer_buffer_length,
>> urb->transfer_buffer_length,
>> diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
>> index a450a99..2e16ff7 100644
>> --- a/drivers/usb/host/xhci.h
>> +++ b/drivers/usb/host/xhci.h
>> @@ -2158,9 +2158,11 @@ static inline struct xhci_ring
>> *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,
>> */
>> static inline bool xhci_urb_suitable_for_idt(struct urb *urb)
>> {
>> - if (!usb_endpoint_xfer_isoc(&urb->ep->desc) &&
>> usb_urb_dir_out(urb) &&
>> + if (!usb_endpoint_xfer_control(&urb->ep->desc) &&
>> + !usb_endpoint_xfer_isoc(&urb->ep->desc) &&
>> usb_urb_dir_out(urb) &&
>> usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE &&
>> - urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE)
>> + urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE &&
>> + !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
>> return true;
>>
>> return false;
>>
>> -Mathias
>
>
> Thanks for the patches to test! Both patches applied separately (without
> the other one) fixes the issue with ASIX USB dongle, but from the
> discussion I assume that the first one
> (0001-xhci-don-t-use-IDT-transfer-buffer-is-already-dma-ma.patch) really
> fixes the issue, while the second one is just a workaround.
>
> You can add:
>
> Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
>
> Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
>
Great, thanks, I'll send the first patch forward after the merge window
Mathias
next prev parent reply other threads:[~2019-05-10 7:27 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-04-26 13:23 [PATCH 0/4] xhci features for usb-next Mathias Nyman
[not found] ` <CGME20190509103220eucas1p1330f2827916b55e05b1b791504963630@eucas1p1.samsung.com>
2019-04-26 13:23 ` [1/4] usb: xhci: add Immediate Data Transfer support Mathias Nyman
2019-04-26 13:23 ` [PATCH 1/4] " Mathias Nyman
2019-05-09 10:32 ` Marek Szyprowski
2019-05-09 11:40 ` Mathias Nyman
2019-05-09 11:51 ` Nicolas Saenz Julienne
2019-05-09 15:10 ` Mathias Nyman
2019-05-09 15:38 ` Nicolas Saenz Julienne
2019-05-10 6:11 ` Mathias Nyman
2019-05-10 6:28 ` Marek Szyprowski
2019-05-10 7:30 ` Mathias Nyman [this message]
-- strict thread matches above, loose matches on Subject: below --
2019-04-26 13:23 [3/4] xhci: Add tracing for input control context Mathias Nyman
2019-04-26 13:23 ` [PATCH 3/4] " Mathias Nyman
2019-04-26 13:23 [4/4] usb: xhci: add endpoint context tracing when an endpoint is added Mathias Nyman
2019-04-26 13:23 ` [PATCH 4/4] " Mathias Nyman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51cf2371-baf3-1788-a77c-bca84ec11c9f@linux.intel.com \
--to=mathias.nyman@linux.intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=krzk@kernel.org \
--cc=linux-samsung-soc@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=m.szyprowski@samsung.com \
--cc=nsaenzjulienne@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.