aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-07-13 15:46:29 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-07-19 20:46:04 -0400
commite7e7c360fb07020b24652843aec442325baad0ce (patch)
tree55a7a18cfcc87e86e4f91f309082aed0d7b8a956 /drivers
parente94fa28f137813c2f6e05470b41bd8f3c5422a04 (diff)
UHCI: short control URBs get a status stage
It has recently been pointed out that short control transfers should have a status stage, even if they generate an error because URB_SHORT_NOT_OK was set. This patch (as935) changes uhci-hcd to enable the status stage when this happens. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/uhci-q.c59
1 files changed, 38 insertions, 21 deletions
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 4aed305982ec..3bb908ca38e9 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -827,8 +827,10 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
827 * If direction is "send", change the packet ID from SETUP (0x2D) 827 * If direction is "send", change the packet ID from SETUP (0x2D)
828 * to OUT (0xE1). Else change it from SETUP to IN (0x69) and 828 * to OUT (0xE1). Else change it from SETUP to IN (0x69) and
829 * set Short Packet Detect (SPD) for all data packets. 829 * set Short Packet Detect (SPD) for all data packets.
830 *
831 * 0-length transfers always get treated as "send".
830 */ 832 */
831 if (usb_pipeout(urb->pipe)) 833 if (usb_pipeout(urb->pipe) || len == 0)
832 destination ^= (USB_PID_SETUP ^ USB_PID_OUT); 834 destination ^= (USB_PID_SETUP ^ USB_PID_OUT);
833 else { 835 else {
834 destination ^= (USB_PID_SETUP ^ USB_PID_IN); 836 destination ^= (USB_PID_SETUP ^ USB_PID_IN);
@@ -839,7 +841,12 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
839 * Build the DATA TDs 841 * Build the DATA TDs
840 */ 842 */
841 while (len > 0) { 843 while (len > 0) {
842 int pktsze = min(len, maxsze); 844 int pktsze = maxsze;
845
846 if (len <= pktsze) { /* The last data packet */
847 pktsze = len;
848 status &= ~TD_CTRL_SPD;
849 }
843 850
844 td = uhci_alloc_td(uhci); 851 td = uhci_alloc_td(uhci);
845 if (!td) 852 if (!td)
@@ -866,20 +873,10 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb,
866 goto nomem; 873 goto nomem;
867 *plink = LINK_TO_TD(td); 874 *plink = LINK_TO_TD(td);
868 875
869 /* 876 /* Change direction for the status transaction */
870 * It's IN if the pipe is an output pipe or we're not expecting 877 destination ^= (USB_PID_IN ^ USB_PID_OUT);
871 * data back.
872 */
873 destination &= ~TD_TOKEN_PID_MASK;
874 if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length)
875 destination |= USB_PID_IN;
876 else
877 destination |= USB_PID_OUT;
878
879 destination |= TD_TOKEN_TOGGLE; /* End in Data1 */ 878 destination |= TD_TOKEN_TOGGLE; /* End in Data1 */
880 879
881 status &= ~TD_CTRL_SPD;
882
883 uhci_add_td_to_urbp(td, urbp); 880 uhci_add_td_to_urbp(td, urbp);
884 uhci_fill_td(td, status | TD_CTRL_IOC, 881 uhci_fill_td(td, status | TD_CTRL_IOC,
885 destination | uhci_explen(0), 0); 882 destination | uhci_explen(0), 0);
@@ -1185,10 +1182,18 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
1185 } 1182 }
1186 } 1183 }
1187 1184
1185 /* Did we receive a short packet? */
1188 } else if (len < uhci_expected_length(td_token(td))) { 1186 } else if (len < uhci_expected_length(td_token(td))) {
1189 1187
1190 /* We received a short packet */ 1188 /* For control transfers, go to the status TD if
1191 if (urb->transfer_flags & URB_SHORT_NOT_OK) 1189 * this isn't already the last data TD */
1190 if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
1191 if (td->list.next != urbp->td_list.prev)
1192 ret = 1;
1193 }
1194
1195 /* For bulk and interrupt, this may be an error */
1196 else if (urb->transfer_flags & URB_SHORT_NOT_OK)
1192 ret = -EREMOTEIO; 1197 ret = -EREMOTEIO;
1193 1198
1194 /* Fixup needed only if this isn't the URB's last TD */ 1199 /* Fixup needed only if this isn't the URB's last TD */
@@ -1208,10 +1213,6 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
1208 1213
1209err: 1214err:
1210 if (ret < 0) { 1215 if (ret < 0) {
1211 /* In case a control transfer gets an error
1212 * during the setup stage */
1213 urb->actual_length = max(urb->actual_length, 0);
1214
1215 /* Note that the queue has stopped and save 1216 /* Note that the queue has stopped and save
1216 * the next toggle value */ 1217 * the next toggle value */
1217 qh->element = UHCI_PTR_TERM; 1218 qh->element = UHCI_PTR_TERM;
@@ -1489,9 +1490,25 @@ __acquires(uhci->lock)
1489{ 1490{
1490 struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; 1491 struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
1491 1492
1493 if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
1494
1495 /* urb->actual_length < 0 means the setup transaction didn't
1496 * complete successfully. Either it failed or the URB was
1497 * unlinked first. Regardless, don't confuse people with a
1498 * negative length. */
1499 urb->actual_length = max(urb->actual_length, 0);
1500
1501 /* Report erroneous short transfers */
1502 if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
1503 urb->actual_length <
1504 urb->transfer_buffer_length &&
1505 urb->status == 0))
1506 urb->status = -EREMOTEIO;
1507 }
1508
1492 /* When giving back the first URB in an Isochronous queue, 1509 /* When giving back the first URB in an Isochronous queue,
1493 * reinitialize the QH's iso-related members for the next URB. */ 1510 * reinitialize the QH's iso-related members for the next URB. */
1494 if (qh->type == USB_ENDPOINT_XFER_ISOC && 1511 else if (qh->type == USB_ENDPOINT_XFER_ISOC &&
1495 urbp->node.prev == &qh->queue && 1512 urbp->node.prev == &qh->queue &&
1496 urbp->node.next != &qh->queue) { 1513 urbp->node.next != &qh->queue) {
1497 struct urb *nurb = list_entry(urbp->node.next, 1514 struct urb *nurb = list_entry(urbp->node.next,