RE: [RFC 6/9] xHCI 1.0: Soft Retry mechanism

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

 



> -----Original Message-----
> From: Sarah Sharp [mailto:sarah.a.sharp@xxxxxxxxxxxxxxx]
> Sent: Wednesday, June 01, 2011 5:17 AM
> To: Xu, Andiry
> Cc: linux-usb@xxxxxxxxxxxxxxx; He, Alex
> Subject: Re: [RFC 6/9] xHCI 1.0: Soft Retry mechanism
> 
> Hi Andiry and Alex,
> 
> I've noticed (although I don't have time to confirm again) that the
> NEC/Rensas host controller seems to return these transaction errors
> whenever there is a link TRB in the middle of the control transfer TD.
> Have you also noticed this?  If so, we should probably let Rensas
know,
> as it might indicate a hardware bug.  Or it could mean we're doing
> something odd in the xHCI driver.
> 

Hmm... I haven't noticed that yet. Will have a try.
In order to reproduce it, can we put a link TRB in the middle of a
transfer
ring?

Thanks,
Andiry


> 
> On Thu, May 05, 2011 at 06:14:07PM +0800, Andiry Xu wrote:
> > From: Alex He <alex.he@xxxxxxx>
> >
> > xHCI 1.0 spec 4.6.8.1 describes Soft Retry mechanism.
> > A Soft Retry may effectively be used to recover from a USB
> Transaction Error
> > that was due to a temporary error condition. Oftern the delay
> introduced
> > between software detecting the error and attempting a Soft Retry is
> enough
> > to let the temporary condition clear and allow a successful
transfer.
> >
> > Signed-off-by: Alex He <alex.he@xxxxxxx>
> > Signed-off-by: Andiry Xu <andiry.xu@xxxxxxx>
> > ---
> >  drivers/usb/host/xhci-ring.c |   70
> ++++++++++++++++++++++++++++++++++++++++++
> >  drivers/usb/host/xhci.h      |    6 +++
> >  2 files changed, 76 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-
> ring.c
> > index e07162d..d0b8c85 100644
> > --- a/drivers/usb/host/xhci-ring.c
> > +++ b/drivers/usb/host/xhci-ring.c
> > @@ -1645,6 +1645,18 @@ static int process_ctrl_td(struct xhci_hcd
> *xhci, struct xhci_td *td,
> >  		if (!xhci_requires_manual_halt_cleanup(xhci,
> >  					ep_ctx, trb_comp_code))
> >  			break;
> > +		if (trb_comp_code == COMP_TX_ERR &&
> > +				xhci->hci_version == 0x100) {
> > +			if (ep->soft_retries++ < SOFT_RETRY) {
> > +				xhci_soft_retry_ep(xhci, slot_id,
ep_index,
> > +						ep_ring->stream_id, td,
> > +						event_trb);
> > +				return 0;
> > +			} else {
> > +				ep->soft_retries = 0;
> > +			}
> > +		}
> > +
> >  		xhci_dbg(xhci, "TRB error code %u, "
> >  				"halted endpoint index = %u\n",
> >  				trb_comp_code, ep_index);
> > @@ -1818,10 +1830,21 @@ static int process_bulk_intr_td(struct
> xhci_hcd *xhci, struct xhci_td *td,
> >  	union xhci_trb *event_trb, struct xhci_transfer_event *event,
> >  	struct xhci_virt_ep *ep, int *status)
> >  {
> > +	struct xhci_virt_device *xdev;
> > +	unsigned int slot_id;
> > +	struct xhci_slot_ctx *slot_ctx;
> > +	int ep_index;
> >  	struct xhci_ring *ep_ring;
> >  	union xhci_trb *cur_trb;
> >  	struct xhci_segment *cur_seg;
> >  	u32 trb_comp_code;
> > +	u32 tt_hub_slot_id;
> > +
> > +	ep_index = TRB_TO_EP_ID(event->flags) - 1;
> > +	slot_id = TRB_TO_SLOT_ID(event->flags);
> > +	xdev = xhci->devs[slot_id];
> > +	slot_ctx = xhci_get_slot_ctx(xhci, xdev->out_ctx);
> > +	tt_hub_slot_id = slot_ctx->tt_info && 0xff;
> >
> >  	ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event-
> >buffer));
> >  	trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
> > @@ -1852,6 +1875,25 @@ static int process_bulk_intr_td(struct
> xhci_hcd *xhci, struct xhci_td *td,
> >  		else
> >  			*status = 0;
> >  		break;
> > +	case COMP_TX_ERR:
> > +		if (xhci->hci_version == 0x100) {
> > +			if (usb_endpoint_xfer_bulk(&td->urb->ep->desc)
&&
> > +					(ep->soft_retries++ <
SOFT_RETRY)) {
> > +				xhci_soft_retry_ep(xhci, slot_id,
ep_index,
> > +					ep_ring->stream_id, td,
event_trb);
> > +				return 0;
> > +
> > +			}
> > +			if (usb_endpoint_xfer_int(&td->urb->ep->desc) &&
> > +					tt_hub_slot_id == 0 &&
> > +					(ep->soft_retries++ <
SOFT_RETRY)) {
> > +				xhci_soft_retry_ep(xhci, slot_id,
ep_index,
> > +					ep_ring->stream_id, td,
event_trb);
> > +				return 0;
> > +			}
> > +			ep->soft_retries = 0;
> > +		}
> > +		break;
> >  	default:
> >  		/* Others already handled above */
> >  		break;
> > @@ -3565,3 +3607,31 @@ int xhci_queue_reset_ep(struct xhci_hcd
*xhci,
> int slot_id,
> >  	return queue_command(xhci, 0, 0, 0, trb_slot_id | trb_ep_index |
> type,
> >  			false);
> >  }
> > +
> > +/*
> > + * A Soft Retry may effectively be used to recver from a USB
> Transaction Error
> > + * that was due to a temporary error codition. Details in the
> Chapter 4.6.8.1
> > + * NOTE:
> > + * 1. can't be called for isoc ep
> > + * 2. can't be called for interrupt ep behind a TT
> > + */
> > +void xhci_soft_retry_ep(struct xhci_hcd *xhci, int slot_id,
> > +		unsigned int ep_index, unsigned int stream_id,
> > +		struct xhci_td *td, union xhci_trb *event_trb)
> > +{
> > +	u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
> > +	u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
> > +	u32 type = TRB_TYPE(TRB_RESET_EP);
> > +	u32 tsp_flag = 1 << 9;
> > +	struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
> > +
> > +	ep->ep_state |= EP_HALTED;
> > +	ep->stopped_td = td;
> > +	ep->stopped_trb	= event_trb;
> > +	ep->stopped_stream = stream_id;
> > +
> > +	queue_command(xhci, 0, 0, 0,
> > +			trb_slot_id | trb_ep_index | type | tsp_flag,
false);
> > +
> > +	xhci_ring_cmd_db(xhci);
> > +}
> > diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
> > index 33a49d5..dd45929 100644
> > --- a/drivers/usb/host/xhci.h
> > +++ b/drivers/usb/host/xhci.h
> > @@ -767,6 +767,9 @@ struct xhci_virt_ep {
> >  	 * process the missed tds on the endpoint ring.
> >  	 */
> >  	bool			skip;
> > +	/* Soft Retries to prevent an infinite loop */
> > +	unsigned int		soft_retries;
> > +#define SOFT_RETRY	2
> >  };
> >
> >  struct xhci_virt_device {
> > @@ -1540,6 +1543,9 @@ void xhci_queue_config_ep_quirk(struct
xhci_hcd
> *xhci,
> >  		unsigned int slot_id, unsigned int ep_index,
> >  		struct xhci_dequeue_state *deq_state);
> >  void xhci_stop_endpoint_command_watchdog(unsigned long arg);
> > +void xhci_soft_retry_ep(struct xhci_hcd *xhci, int slot_id,
> > +		unsigned int ep_index, unsigned int stream_id,
> > +		struct xhci_td *td, union xhci_trb *event_trb);
> >  void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int
> slot_id,
> >  		unsigned int ep_index, unsigned int stream_id);
> >
> > --
> > 1.7.1
> >
> >
> >


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