Re: [PATCH v3] xhci: fix reporting of 0-sized URBs in control endpoint

2015-02-26 Thread Alan Stern
On Thu, 26 Feb 2015, Mathias Nyman wrote:

> On 26.02.2015 16:57, Alan Stern wrote:
> > On Thu, 26 Feb 2015, Mathias Nyman wrote:
> > 
> >> I'm starting to like your idea of setting the urb->actual_length in 
> >> advance,
> >> It may actually simplify things.
> > 
> > But it will make unlinking more difficult.  Also, what will you do if 
> > there is more than one TRB?
> > 
> 
> current xhci driver can't handle more than one data trb in control tranfers:
> xhci-ring.c,

Yes, that's right.  I was thinking about bulk transfers.  I guess they 
don't suffer from this problem, though.

> Shouldn't control urbs only be given back when they finish (SUCCESS, STALL, 
> SHORT etc),
> are dequeued, or some major host failure causes us to empty the rings?

Yes.  In fact, that's true for every URB, not just control.

> I thought it would be enough to set urb->actual_length = 0 for the ctrl URBs 
> in all other
> cases than short or successful completion?

urb->actual_length should always be set to the number of bytes actually
transferred, as closely as you can tell.  For example, suppose you have
a 1500-byte transfer.  If the first packet successfully sends 1024
bytes but the second packet fails (so the entire URB fails),
actual_length should be set to 1024.

Alan Stern

--
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] xhci: fix reporting of 0-sized URBs in control endpoint

2015-02-26 Thread Mathias Nyman
On 26.02.2015 16:57, Alan Stern wrote:
> On Thu, 26 Feb 2015, Mathias Nyman wrote:
> 
>> I'm starting to like your idea of setting the urb->actual_length in advance,
>> It may actually simplify things.
> 
> But it will make unlinking more difficult.  Also, what will you do if 
> there is more than one TRB?
> 

current xhci driver can't handle more than one data trb in control tranfers:
xhci-ring.c,

int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
struct urb *urb, int slot_id, unsigned int ep_index)
...
  /* 1 TRB for setup, 1 for status */
num_trbs = 2;
/*  

 * Don't need to check if we need additional event data and normal 
TRBs,
 * since data in control transfers will never get bigger than 16MB  

 * XXX: can we get a buffer that crosses 64KB boundaries?   

 */
if (urb->transfer_buffer_length > 0)
num_trbs++;


Shouldn't control urbs only be given back when they finish (SUCCESS, STALL, 
SHORT etc),
are dequeued, or some major host failure causes us to empty the rings?

I thought it would be enough to set urb->actual_length = 0 for the ctrl URBs in 
all other
cases than short or successful completion?

I'll send a RFC so you can see if it makes sense to try out this path, or If Im 
only shooting
myself in the foot.

-Mathias

--
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] xhci: fix reporting of 0-sized URBs in control endpoint

2015-02-26 Thread Alan Stern
On Thu, 26 Feb 2015, Mathias Nyman wrote:

> I'm starting to like your idea of setting the urb->actual_length in advance,
> It may actually simplify things.

But it will make unlinking more difficult.  Also, what will you do if 
there is more than one TRB?

Alan Stern

--
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] xhci: fix reporting of 0-sized URBs in control endpoint

2015-02-26 Thread Mathias Nyman
...
> 
> The second event is always COMP_SUCCESS and the event->transfer_len is
> always set to 0 in that one. The 3 cases I've seen are:
> 
> case 1: 1 event on last TRB
>   COMP_SUCCESS, event->len=0
> 
> case 2:  short event but with data
>   COMP_SHORT_TX, event->len < urb->transfer_buffer_len
>   COMP_SUCCESS, event->len=0
> 
> case 3: short event with no data
>   COMP_SHORT_TX, event->len = urb->transfer_buffer_len
>   COMP_SUCCESS, event->len=0
> 

Ok, I was hoping COMP_SUCCESS event->len in case 2 and 3 would
show the same value as the previous COMP_SHORT_TX event->len

>>>
>>> The other thing I thought of was to somehow always initialize the URB
>>> actual length to the transfer buffer length from the very beginning,
>>> and only update it if a COMP_SHORT_TX event is received. Not sure if
>>> that would be much more complex to handle, though.
>>>
>>
>> This could be an option, need to look into it.
> 

I'm starting to like your idea of setting the urb->actual_length in advance,
It may actually simplify things.

I already started implementing a testpatch, will send it shortly If you'd like 
to
test it with your device and hso driver. 

-Mathias 

--
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] xhci: fix reporting of 0-sized URBs in control endpoint

2015-02-25 Thread Aleksander Morgado
 When a control transfer has a short data stage, the xHCI controller 
 generates
 two transfer events: a COMP_SHORT_TX event that specifies the untransferred
 amount, and a COMP_SUCCESS event. But when the data stage is not short, 
 only the
 COMP_SUCCESS event occurs. Therefore, xhci-hcd must set urb->actual_length 
 to
 urb->transfer_buffer_length while processing the COMP_SUCCESS event, unless
 urb->actual_length was set already by a previous COMP_SHORT_TX event.

>>>
>>> I think that the only case you should see a COMP_SUCCESS after a 
>>> COMP_SHORT_TX
>>> is if xhci hits a link TRB while automatically moving to the next TRB after 
>>> the
>>> short packet.
>>>
>>> If Event Data TRBs are used, or a later TRB in that TD has the IOC flag set 
>>> then xhci should just
>>> generate a second transfer event with the same COMP_SHORT_TX completion 
>>> code.
>>> (xhci specs section 4.10.1.1)
>>>
>>
>> Well, I can only speak for this usecase I have here with the Option
>> HSO modem; in this case the COMP_SHORT_TX+COMP_SUCCESS pair happens
>> always, as the hso driver submits a URB with a 1024 byte buffer, and
>> the modem usually replies with AT responses character by character;
>> for each character I end up getting both events: first with
>> COMP_SHORT_TX and the event length set to 1023, second with
>> COMP_SUCESS and event length set to 0.
>>
>
> Looking at the code it seems that xhci controllers after 0.96 generate a
> spurious COMP_SUCCESS after short packet, code says:
>
> /* In xhci controllers which follow xhci 1.0 spec gives a spurious
>  * success event after a short transfer. This quirk will ignore such
>  * spurious event.
>  */
> if (xhci->hci_version > 0x96)
> xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
>
>> I read the xhci specs as well and I also got the impression that there
>> wasn't anything explicitly stating that a COMP_SUCCESS event always
>> follows a COMP_SHORT_TX. But, the code already assumes that if you get
>> a COMP_SHORT_TX event for a TRB which isn't the last one, you should
>> still get an event for the last TRB (i.e. finish_td() isn't called for
>> a COMP_SHORT_TX event if the TRB isn't the first one (event_trb !=
>> ep_ring->dequeue) and if it isn't the last one (event_trb !=
>> td->last_trb).
>
> Thats right, we always set the IOC (interrupt on completion) in the last TRB 
> of
> a control transfer, so it will always interrupt, generating a transfer event.
>
> I read through your previous mails where you were investigating this and also 
> looked a bit
> in more detail at the xhci code. I now understand better the issue. Its 
> clearly a bug in xhci driver.
>
> Can you still add some debugging and check the if the second event after the 
> COMP_SHORT_TX really
> is a COMP_SUCCESS ? and also what it says about the transfer length.
>
> printing out these values for the second event should do it:
>   GET_COMP_CODE(le32_to_cpu(event->transfer_len))
>   EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))
>

The second event is always COMP_SUCCESS and the event->transfer_len is
always set to 0 in that one. The 3 cases I've seen are:

case 1: 1 event on last TRB
  COMP_SUCCESS, event->len=0

case 2:  short event but with data
  COMP_SHORT_TX, event->len < urb->transfer_buffer_len
  COMP_SUCCESS, event->len=0

case 3: short event with no data
  COMP_SHORT_TX, event->len = urb->transfer_buffer_len
  COMP_SUCCESS, event->len=0

> Right now process_ctrl_td() sets the urb->actual_length based on TRB position 
> in TD (first, last, neither) and
> what value urb->actual_length contains. I think that by checking the actual 
> event completion code, and the event
> reported  remaining length we could get this correct without adding any 
> additional fields to struct xhci_td.
>

The problem with that logic is that just by checking the last event
completion code and event->length we cannot know whether there was a
previous COMP_SHORT_TX event. i.e. when processing that last event you
wouldn't know whether it was case 1, case 2 or case 3 from above.

> If I find the time I'll rewrite this part, if not then I'll add your patch, 
> (v4)
>

If you want to suggest any other approach, let me know and I'll spend
time with it.

>
>>
>>>
 The driver checks this by seeing whether urb->actual_length == 0, but this 
 alone
 is the wrong test, as it is entirely possible for a short transfer to have 
 an
 urb->actual_length = 0.
>>>
>>> This should be fixed, handling short packets look a bit messy in general 
>>> right now
>>>

 This patch changes the xhci driver to rely not only on the 
 urb->actual_length,
 but also on the ep_ring->last_td_was_short flag, which is set to true when 
 a
 COMP_SHORT_TX event is received.

 This fixes a bug which affected the HSO plugin, which relies on URBs with
 urb->actual_length == 0 to halt re-submitting the RX URB in the control

Re: [PATCH v3] xhci: fix reporting of 0-sized URBs in control endpoint

2015-02-25 Thread Mathias Nyman
On 23.02.2015 19:02, Aleksander Morgado wrote:
> On Mon, Feb 23, 2015 at 4:23 PM, Mathias Nyman
>  wrote:
>> Hi
>>
>> On 23.02.2015 13:52, Aleksander Morgado wrote:
>>> When a control transfer has a short data stage, the xHCI controller 
>>> generates
>>> two transfer events: a COMP_SHORT_TX event that specifies the untransferred
>>> amount, and a COMP_SUCCESS event. But when the data stage is not short, 
>>> only the
>>> COMP_SUCCESS event occurs. Therefore, xhci-hcd must set urb->actual_length 
>>> to
>>> urb->transfer_buffer_length while processing the COMP_SUCCESS event, unless
>>> urb->actual_length was set already by a previous COMP_SHORT_TX event.
>>>
>>
>> I think that the only case you should see a COMP_SUCCESS after a 
>> COMP_SHORT_TX
>> is if xhci hits a link TRB while automatically moving to the next TRB after 
>> the
>> short packet.
>>
>> If Event Data TRBs are used, or a later TRB in that TD has the IOC flag set 
>> then xhci should just
>> generate a second transfer event with the same COMP_SHORT_TX completion code.
>> (xhci specs section 4.10.1.1)
>>
> 
> Well, I can only speak for this usecase I have here with the Option
> HSO modem; in this case the COMP_SHORT_TX+COMP_SUCCESS pair happens
> always, as the hso driver submits a URB with a 1024 byte buffer, and
> the modem usually replies with AT responses character by character;
> for each character I end up getting both events: first with
> COMP_SHORT_TX and the event length set to 1023, second with
> COMP_SUCESS and event length set to 0.
> 

Looking at the code it seems that xhci controllers after 0.96 generate a 
spurious COMP_SUCCESS after short packet, code says:

/* In xhci controllers which follow xhci 1.0 spec gives a spurious  

 * success event after a short transfer. This quirk will ignore such

 * spurious event.  

 */
if (xhci->hci_version > 0x96)
xhci->quirks |= XHCI_SPURIOUS_SUCCESS;

> I read the xhci specs as well and I also got the impression that there
> wasn't anything explicitly stating that a COMP_SUCCESS event always
> follows a COMP_SHORT_TX. But, the code already assumes that if you get
> a COMP_SHORT_TX event for a TRB which isn't the last one, you should
> still get an event for the last TRB (i.e. finish_td() isn't called for
> a COMP_SHORT_TX event if the TRB isn't the first one (event_trb !=
> ep_ring->dequeue) and if it isn't the last one (event_trb !=
> td->last_trb).

Thats right, we always set the IOC (interrupt on completion) in the last TRB of
a control transfer, so it will always interrupt, generating a transfer event.

I read through your previous mails where you were investigating this and also 
looked a bit
in more detail at the xhci code. I now understand better the issue. Its clearly 
a bug in xhci driver.

Can you still add some debugging and check the if the second event after the 
COMP_SHORT_TX really
is a COMP_SUCCESS ? and also what it says about the transfer length.

printing out these values for the second event should do it:
  GET_COMP_CODE(le32_to_cpu(event->transfer_len))
  EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))

Right now process_ctrl_td() sets the urb->actual_length based on TRB position 
in TD (first, last, neither) and
what value urb->actual_length contains. I think that by checking the actual 
event completion code, and the event
reported  remaining length we could get this correct without adding any 
additional fields to struct xhci_td.

If I find the time I'll rewrite this part, if not then I'll add your patch, 
(v4) 

 
> 
>>
>>> The driver checks this by seeing whether urb->actual_length == 0, but this 
>>> alone
>>> is the wrong test, as it is entirely possible for a short transfer to have 
>>> an
>>> urb->actual_length = 0.
>>
>> This should be fixed, handling short packets look a bit messy in general 
>> right now
>>
>>>
>>> This patch changes the xhci driver to rely not only on the 
>>> urb->actual_length,
>>> but also on the ep_ring->last_td_was_short flag, which is set to true when a
>>> COMP_SHORT_TX event is received.
>>>
>>> This fixes a bug which affected the HSO plugin, which relies on URBs with
>>> urb->actual_length == 0 to halt re-submitting the RX URB in the control
>>> endpoint.
>>>
>>> Signed-off-by: Aleksander Morgado 
>>> ---
>>>
>>> Hey,
>>>
>>> This is the third update of the patch:
>>>
>>>  * v2 modified the commit message to make it shorter and clearer.
>>>
>>>  * v3 updated the format of the commented lines in the patch.
>>>
>>> Cheers!
>>>
>>> ---
>>>  drivers/usb/host/xhci-ring.c | 16 +++-
>>>  1 file changed, 11 insertions(+), 5 deletions(-)
>>>
>>> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
>>> index 88da8d6..eda3276 100644
>>> --- a/drivers/usb/host/xhci-ring.c
>>> +++ b/drivers/usb/host/xhci-ring.c
>>> @@ -1955,7 

Re: [PATCH v3] xhci: fix reporting of 0-sized URBs in control endpoint

2015-02-23 Thread Aleksander Morgado
On Mon, Feb 23, 2015 at 4:23 PM, Mathias Nyman
 wrote:
> Hi
>
> On 23.02.2015 13:52, Aleksander Morgado wrote:
>> When a control transfer has a short data stage, the xHCI controller generates
>> two transfer events: a COMP_SHORT_TX event that specifies the untransferred
>> amount, and a COMP_SUCCESS event. But when the data stage is not short, only 
>> the
>> COMP_SUCCESS event occurs. Therefore, xhci-hcd must set urb->actual_length to
>> urb->transfer_buffer_length while processing the COMP_SUCCESS event, unless
>> urb->actual_length was set already by a previous COMP_SHORT_TX event.
>>
>
> I think that the only case you should see a COMP_SUCCESS after a COMP_SHORT_TX
> is if xhci hits a link TRB while automatically moving to the next TRB after 
> the
> short packet.
>
> If Event Data TRBs are used, or a later TRB in that TD has the IOC flag set 
> then xhci should just
> generate a second transfer event with the same COMP_SHORT_TX completion code.
> (xhci specs section 4.10.1.1)
>

Well, I can only speak for this usecase I have here with the Option
HSO modem; in this case the COMP_SHORT_TX+COMP_SUCCESS pair happens
always, as the hso driver submits a URB with a 1024 byte buffer, and
the modem usually replies with AT responses character by character;
for each character I end up getting both events: first with
COMP_SHORT_TX and the event length set to 1023, second with
COMP_SUCESS and event length set to 0.

I read the xhci specs as well and I also got the impression that there
wasn't anything explicitly stating that a COMP_SUCCESS event always
follows a COMP_SHORT_TX. But, the code already assumes that if you get
a COMP_SHORT_TX event for a TRB which isn't the last one, you should
still get an event for the last TRB (i.e. finish_td() isn't called for
a COMP_SHORT_TX event if the TRB isn't the first one (event_trb !=
ep_ring->dequeue) and if it isn't the last one (event_trb !=
td->last_trb).

>
>> The driver checks this by seeing whether urb->actual_length == 0, but this 
>> alone
>> is the wrong test, as it is entirely possible for a short transfer to have an
>> urb->actual_length = 0.
>
> This should be fixed, handling short packets look a bit messy in general 
> right now
>
>>
>> This patch changes the xhci driver to rely not only on the 
>> urb->actual_length,
>> but also on the ep_ring->last_td_was_short flag, which is set to true when a
>> COMP_SHORT_TX event is received.
>>
>> This fixes a bug which affected the HSO plugin, which relies on URBs with
>> urb->actual_length == 0 to halt re-submitting the RX URB in the control
>> endpoint.
>>
>> Signed-off-by: Aleksander Morgado 
>> ---
>>
>> Hey,
>>
>> This is the third update of the patch:
>>
>>  * v2 modified the commit message to make it shorter and clearer.
>>
>>  * v3 updated the format of the commented lines in the patch.
>>
>> Cheers!
>>
>> ---
>>  drivers/usb/host/xhci-ring.c | 16 +++-
>>  1 file changed, 11 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
>> index 88da8d6..eda3276 100644
>> --- a/drivers/usb/host/xhci-ring.c
>> +++ b/drivers/usb/host/xhci-ring.c
>> @@ -1955,7 +1955,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, 
>> struct xhci_td *td,
>>   /* Did we already see a short data
>>* stage? */
>>   *status = -EREMOTEIO;
>> - } else {
>> + } else if (!ep_ring->last_td_was_short) {
>>   td->urb->actual_length =
>>   td->urb->transfer_buffer_length;
>>   }
>> @@ -2447,10 +2447,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
>>   ret = skip_isoc_td(xhci, td, event, ep, &status);
>>   goto cleanup;
>>   }
>> - if (trb_comp_code == COMP_SHORT_TX)
>> - ep_ring->last_td_was_short = true;
>> - else
>> - ep_ring->last_td_was_short = false;
>>
>>   if (ep->skip) {
>>   xhci_dbg(xhci, "Found td. Clear skip flag.\n");
>> @@ -2484,6 +2480,16 @@ static int handle_tx_event(struct xhci_hcd *xhci,
>>   ret = process_bulk_intr_td(xhci, td, event_trb, event,
>>ep, &status);
>>
>> + /*
>> +  * Flag whether the just processed TRB was short. Do it after
>> +  * processing, so that the processor methods can also use this
>> +  * flag.
>> +  */
>> + if (trb_comp_code == COMP_SHORT_TX)
>> + ep_ring->last_td_was_short = true;
>> + else
>> + ep_ring->last_td_was_short = false;
>> +
>
> How about the case where we only get one COMP_SHORT_TX event for that control 
> transfer,
> xhci then advances to the next TD

Re: [PATCH v3] xhci: fix reporting of 0-sized URBs in control endpoint

2015-02-23 Thread Mathias Nyman
Hi

On 23.02.2015 13:52, Aleksander Morgado wrote:
> When a control transfer has a short data stage, the xHCI controller generates
> two transfer events: a COMP_SHORT_TX event that specifies the untransferred
> amount, and a COMP_SUCCESS event. But when the data stage is not short, only 
> the
> COMP_SUCCESS event occurs. Therefore, xhci-hcd must set urb->actual_length to
> urb->transfer_buffer_length while processing the COMP_SUCCESS event, unless
> urb->actual_length was set already by a previous COMP_SHORT_TX event.
> 

I think that the only case you should see a COMP_SUCCESS after a COMP_SHORT_TX
is if xhci hits a link TRB while automatically moving to the next TRB after the 
short packet.

If Event Data TRBs are used, or a later TRB in that TD has the IOC flag set 
then xhci should just
generate a second transfer event with the same COMP_SHORT_TX completion code.
(xhci specs section 4.10.1.1)


> The driver checks this by seeing whether urb->actual_length == 0, but this 
> alone
> is the wrong test, as it is entirely possible for a short transfer to have an
> urb->actual_length = 0.

This should be fixed, handling short packets look a bit messy in general right 
now

> 
> This patch changes the xhci driver to rely not only on the urb->actual_length,
> but also on the ep_ring->last_td_was_short flag, which is set to true when a
> COMP_SHORT_TX event is received.
> 
> This fixes a bug which affected the HSO plugin, which relies on URBs with
> urb->actual_length == 0 to halt re-submitting the RX URB in the control
> endpoint.
> 
> Signed-off-by: Aleksander Morgado 
> ---
> 
> Hey,
> 
> This is the third update of the patch:
> 
>  * v2 modified the commit message to make it shorter and clearer.
> 
>  * v3 updated the format of the commented lines in the patch.
> 
> Cheers!
> 
> ---
>  drivers/usb/host/xhci-ring.c | 16 +++-
>  1 file changed, 11 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> index 88da8d6..eda3276 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -1955,7 +1955,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, 
> struct xhci_td *td,
>   /* Did we already see a short data
>* stage? */
>   *status = -EREMOTEIO;
> - } else {
> + } else if (!ep_ring->last_td_was_short) {
>   td->urb->actual_length =
>   td->urb->transfer_buffer_length;
>   }
> @@ -2447,10 +2447,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
>   ret = skip_isoc_td(xhci, td, event, ep, &status);
>   goto cleanup;
>   }
> - if (trb_comp_code == COMP_SHORT_TX)
> - ep_ring->last_td_was_short = true;
> - else
> - ep_ring->last_td_was_short = false;
> 
>   if (ep->skip) {
>   xhci_dbg(xhci, "Found td. Clear skip flag.\n");
> @@ -2484,6 +2480,16 @@ static int handle_tx_event(struct xhci_hcd *xhci,
>   ret = process_bulk_intr_td(xhci, td, event_trb, event,
>ep, &status);
> 
> + /*
> +  * Flag whether the just processed TRB was short. Do it after
> +  * processing, so that the processor methods can also use this
> +  * flag.
> +  */
> + if (trb_comp_code == COMP_SHORT_TX)
> + ep_ring->last_td_was_short = true;
> + else
> + ep_ring->last_td_was_short = false;
> +

How about the case where we only get one COMP_SHORT_TX event for that control 
transfer,
xhci then advances to the next TD, which completes successfully? That 
successful TD won't get
its td->urb->actual length set because the last_td_was_short flag it still set?

-Mathias


--
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