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

Reply via email to