RE: Potential issue in xhci-ring handle_tx_event()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: Dmitry Torokhov [mailto:dtor@xxxxxxxxxx]
> Sent: Thursday, February 24, 2011 12:48 PM
> To: Xu, Andiry; Sarah Sharp
> Cc: linux-usb@xxxxxxxxxxxxxxx
> Subject: Potential issue in xhci-ring handle_tx_event()
> 
> Hi Andiry, Sarah,
> 
> I was compiling xhci and got a warning that event_trb might be used
> uninitialized in handle_tx_event(). Looking at the implementation the
> logic is quite convoluted but appears that if the following condition
is
> true:
> 
> 	!event_seg && ep->skip && usb_endpoint_xfer_isoc(...)
> 
> we indeed will end up calling process_*_td(..., event_trb, ...).
> 

Well, if the condition is met, it must be an isoc endpoint and
process_isoc_td() will be called with ep->skip set. You can follow the
call trace and see that event_trb will never be used in that case.
That's a normal case for isoc transfer. Sometimes the xHC is unable to
process all the isoc tds in time and it will miss some tds. The driver
will never find the corresponding event_trb for these tds in this case.

> I think something like the following is needed...
> 
> diff --git a/drivers/usb/host/xhci-ring.c
b/drivers/usb/host/xhci-ring.c
> index 3e8211c..85ae5ef 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -1918,22 +1918,26 @@ static int handle_tx_event(struct xhci_hcd
*xhci,
>  		}
> 
>  		td = list_entry(ep_ring->td_list.next, struct xhci_td,
> td_list);
> +
>  		/* Is this a TRB in the currently executing TD? */
>  		event_seg = trb_in_td(ep_ring->deq_seg,
ep_ring->dequeue,
>  				td->last_trb, event_dma);
> -		if (event_seg && ep->skip) {
> -			xhci_dbg(xhci, "Found td. Clear skip flag.\n");
> -			ep->skip = false;
> -		}
> -		if (!event_seg &&
> -		   (!ep->skip ||
!usb_endpoint_xfer_isoc(&td->urb->ep->desc)))
> {
> +		if (!event_seg) {
> +			if (ep->skip &&
> +			    usb_endpoint_xfer_isoc(&td->urb->ep->desc))
{
> +				ret = 0;
> +				goto cleanup;
> +			}

By doing this you will skip the process_isoc_td calling. Actually it's
really needed. 

>  			/* HC is busted, give up! */
> -			xhci_err(xhci, "ERROR Transfer event TRB DMA ptr
not "
> -					"part of current TD\n");
> +			xhci_err(xhci,
> +				"ERROR Transfer event TRB DMA ptr not
part of
> current TD\n");
>  			return -ESHUTDOWN;
> -		}
> +		} else {
> +			if (ep->skip) {
> +				xhci_dbg(xhci, "Found td. Clear skip
flag.\n");
> +				ep->skip = false;
> +			}
> 
> -		if (event_seg) {
>  			event_trb = &event_seg->trbs[(event_dma -
>  					 event_seg->dma) /
sizeof(*event_trb)];
>  			/*
> 

If you are just worry about a compile warning for an uninitialized
variable, I think simply initialize event_trb with NULL will do.

Thanks,

Andiry


--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux