Greg:
This patch makes some simple changes to the way the UHCI driver does short
packet detection. The current implementation is incorrect in several
ways:
The Short-Packet-Detect flag is set for OUT transfers, which
yields undefined behavior according to the UHCI spec.
It's not set for URBs with URB_SHORT_NOT_OK, which is just the
opposite of what we want! Those are the ones where short packets
do matter.
It is set for the last packet in a transfer, which causes an
unnecessary pause in the data flow (except of course that the
pause _is_ necessary when URB_SHORT_NOT_OK is set).
The patch also implements the URB_NO_INTERRUPT flag for bulk transfers,
which can help improve system performance by reducing interrupt overhead.
Please apply.
Alan Stern
===== uhci-hcd.c 1.97 vs edited =====
--- 1.97/drivers/usb/host/uhci-hcd.c Wed Mar 17 14:16:48 2004
+++ edited/drivers/usb/host/uhci-hcd.c Fri Mar 19 16:30:38 2004
@@ -840,13 +840,16 @@
urb->setup_dma);
/*
- * If direction is "send", change the frame from SETUP (0x2D)
- * to OUT (0xE1). Else change it from SETUP to IN (0x69).
+ * If direction is "send", change the packet ID from SETUP (0x2D)
+ * to OUT (0xE1). Else change it from SETUP to IN (0x69) and
+ * set Short Packet Detect (SPD) for all data packets.
*/
- destination ^= (USB_PID_SETUP ^ usb_packetid(urb->pipe));
-
- if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
+ if (usb_pipeout(urb->pipe))
+ destination ^= (USB_PID_SETUP ^ USB_PID_OUT);
+ else {
+ destination ^= (USB_PID_SETUP ^ USB_PID_IN);
status |= TD_CTRL_SPD;
+ }
/*
* Build the DATA TD's
@@ -1101,17 +1104,20 @@
status = uhci_maxerr(3) | TD_CTRL_ACTIVE;
if (urb->dev->speed == USB_SPEED_LOW)
status |= TD_CTRL_LS;
- if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
+ if (usb_pipein(urb->pipe))
status |= TD_CTRL_SPD;
/*
* Build the DATA TD's
*/
do { /* Allow zero length packets */
- int pktsze = len;
+ int pktsze = maxsze;
- if (pktsze > maxsze)
- pktsze = maxsze;
+ if (pktsze >= len) {
+ pktsze = len;
+ if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
+ status &= ~TD_CTRL_SPD;
+ }
td = uhci_alloc_td(uhci, urb->dev);
if (!td)
@@ -1154,7 +1160,8 @@
}
/* Set the flag on the last packet */
- td->status |= cpu_to_le32(TD_CTRL_IOC);
+ if (!(urb->transfer_flags & URB_NO_INTERRUPT))
+ td->status |= cpu_to_le32(TD_CTRL_IOC);
qh = uhci_alloc_qh(uhci, urb->dev);
if (!qh)
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel