Commit a32564f2 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] USB: Return better result codes in UHCI

This patch changes the result code returned by the UHCI driver for a
certain class of errors.  Under a number of circumstances a USB device is
obliged to send a response packet within a fairly short turn-around time,
typically 1 - 10 microseconds depending on the bus speed.  Failure to do
so is a protocol error and should be reported as such, not as a timeout,
which is really a higher-level concept.  I believe the EHCI driver already
does this.

I trust nobody will object to the update this patch adds to
Documentation/usb/error-codes.txt, making this more explicit.

In a vaguely related change, the patch corrects the terminology in a few
comments.  The parts of a control transfer are called "stages", not
"phases".
parent ff4e68e9
...@@ -70,7 +70,9 @@ one or more packets could finish before an error stops further endpoint I/O. ...@@ -70,7 +70,9 @@ one or more packets could finish before an error stops further endpoint I/O.
(That is, if drivers see this it's a bug.) (That is, if drivers see this it's a bug.)
-EPROTO (*) a) bitstuff error -EPROTO (*) a) bitstuff error
b) unknown USB error b) no response packet received within the
prescribed bus turn-around time
c) unknown USB error
-EILSEQ (*) CRC mismatch -EILSEQ (*) CRC mismatch
......
...@@ -781,7 +781,8 @@ static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb) ...@@ -781,7 +781,8 @@ static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb)
/* /*
* Map status to standard result codes * Map status to standard result codes
* *
* <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)] * <status> is (td->status & 0xF60000) [a.k.a. uhci_status_bits(td->status)]
* Note: status does not include the TD_CTRL_NAK bit.
* <dir_out> is True for output TDs and False for input TDs. * <dir_out> is True for output TDs and False for input TDs.
*/ */
static int uhci_map_status(int status, int dir_out) static int uhci_map_status(int status, int dir_out)
...@@ -792,22 +793,18 @@ static int uhci_map_status(int status, int dir_out) ...@@ -792,22 +793,18 @@ static int uhci_map_status(int status, int dir_out)
return -EPROTO; return -EPROTO;
if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */ if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */
if (dir_out) if (dir_out)
return -ETIMEDOUT; return -EPROTO;
else else
return -EILSEQ; return -EILSEQ;
} }
if (status & TD_CTRL_NAK) /* NAK */
return -ETIMEDOUT;
if (status & TD_CTRL_BABBLE) /* Babble */ if (status & TD_CTRL_BABBLE) /* Babble */
return -EOVERFLOW; return -EOVERFLOW;
if (status & TD_CTRL_DBUFERR) /* Buffer error */ if (status & TD_CTRL_DBUFERR) /* Buffer error */
return -ENOSR; return -ENOSR;
if (status & TD_CTRL_STALLED) /* Stalled */ if (status & TD_CTRL_STALLED) /* Stalled */
return -EPIPE; return -EPIPE;
if (status & TD_CTRL_ACTIVE) /* Active */ WARN_ON(status & TD_CTRL_ACTIVE); /* Active */
return 0; return 0;
return -EINVAL;
} }
/* /*
...@@ -832,7 +829,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur ...@@ -832,7 +829,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
status |= TD_CTRL_LS; status |= TD_CTRL_LS;
/* /*
* Build the TD for the control request * Build the TD for the control request setup packet
*/ */
td = uhci_alloc_td(uhci, urb->dev); td = uhci_alloc_td(uhci, urb->dev);
if (!td) if (!td)
...@@ -990,13 +987,13 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) ...@@ -990,13 +987,13 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
if (urbp->short_control_packet) { if (urbp->short_control_packet) {
tmp = head->prev; tmp = head->prev;
goto status_phase; goto status_stage;
} }
tmp = head->next; tmp = head->next;
td = list_entry(tmp, struct uhci_td, list); td = list_entry(tmp, struct uhci_td, list);
/* The first TD is the SETUP phase, check the status, but skip */ /* The first TD is the SETUP stage, check the status, but skip */
/* the count */ /* the count */
status = uhci_status_bits(td_status(td)); status = uhci_status_bits(td_status(td));
if (status & TD_CTRL_ACTIVE) if (status & TD_CTRL_ACTIVE)
...@@ -1037,10 +1034,10 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) ...@@ -1037,10 +1034,10 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
} }
} }
status_phase: status_stage:
td = list_entry(tmp, struct uhci_td, list); td = list_entry(tmp, struct uhci_td, list);
/* Control status phase */ /* Control status stage */
status = td_status(td); status = td_status(td);
#ifdef I_HAVE_BUGGY_APC_BACKUPS #ifdef I_HAVE_BUGGY_APC_BACKUPS
...@@ -1053,10 +1050,11 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) ...@@ -1053,10 +1050,11 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
return 0; return 0;
#endif #endif
status = uhci_status_bits(status);
if (status & TD_CTRL_ACTIVE) if (status & TD_CTRL_ACTIVE)
return -EINPROGRESS; return -EINPROGRESS;
if (uhci_status_bits(status)) if (status)
goto td_error; goto td_error;
return 0; return 0;
...@@ -1403,7 +1401,8 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) ...@@ -1403,7 +1401,8 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
urb->iso_frame_desc[i].actual_length = actlength; urb->iso_frame_desc[i].actual_length = actlength;
urb->actual_length += actlength; urb->actual_length += actlength;
status = uhci_map_status(uhci_status_bits(td_status(td)), usb_pipeout(urb->pipe)); status = uhci_map_status(uhci_status_bits(td_status(td)),
usb_pipeout(urb->pipe));
urb->iso_frame_desc[i].status = status; urb->iso_frame_desc[i].status = status;
if (status) { if (status) {
urb->error_count++; urb->error_count++;
......
...@@ -141,7 +141,7 @@ struct uhci_qh { ...@@ -141,7 +141,7 @@ struct uhci_qh {
TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
#define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT) #define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT)
#define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xFE0000) #define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xF60000)
#define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */ #define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment