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