On Mon, Jun 18, 2007 at 11:00:10AM -0400, Alan Stern wrote:
> Olav,
> 
> What would be involved in refactoring isp116x-hcd so that the driver
> called usb_hcd_giveback_urb() as soon as the URB was completed?  If I
> understand the current code correctly, postproc_atl_queue() goes
> through all the active endpoints and stores the status for the
> completed URBs, and then later finish_atl_transfers() gives them back.
> 
> It looks like this shouldn't present any difficulty except for one 
> thing: When you get a short Control-IN transfer with URB_SHORT_NOT_OK 
> set, the error status gets stored while the URB's status stage 
> executes.  That would have to be changed so that the status stage was 
> skipped entirely.  Doing this shouldn't cause any problems in practice; 
> the other HCDs skip the status stage when this sort of error occurs.
> 
> The point of making this change is that it would allow the driver to 
> avoid saving values in urb->status, leading eventually to the 
> possibility of removing the status field from struct urb.

Hi Alan,

Do you mean something like that below? I haven't tested it.

Olav


--- linux-2.6.22-rc5-or/drivers/usb/host/isp116x-hcd.c  2007-06-17 
05:09:12.000000000 +0300
+++ linux-2.6.22-rc5-isp/drivers/usb/host/isp116x-hcd.c 2007-06-20 
22:49:27.000000000 +0300
@@ -210,6 +210,9 @@
 
 /*---------------------------------------------------------------*/
 
+static void finish_request(struct isp116x *isp116x, struct isp116x_ep *ep,
+                          struct urb *urb);
+
 /*
   Set up PTD's.
 */
@@ -296,11 +299,6 @@
                short_not_ok = 1;
                spin_lock(&urb->lock);
 
-               /* Data underrun is special. For allowed underrun
-                  we clear the error and continue as normal. For
-                  forbidden underrun we finish the DATA stage
-                  immediately while for control transfer,
-                  we do a STATUS stage. */
                if (cc == TD_DATAUNDERRUN) {
                        if (!(urb->transfer_flags & URB_SHORT_NOT_OK)) {
                                DBG("Allowed data underrun\n");
@@ -308,22 +306,16 @@
                                short_not_ok = 0;
                        } else {
                                ep->error_count = 1;
-                               if (usb_pipecontrol(urb->pipe))
-                                       ep->nextpid = USB_PID_ACK;
-                               else
-                                       usb_settoggle(udev, ep->epnum,
-                                                     ep->nextpid ==
-                                                     USB_PID_OUT,
-                                                     PTD_GET_TOGGLE(ptd));
+                               usb_settoggle(udev, ep->epnum,
+                                             ep->nextpid == USB_PID_OUT,
+                                             PTD_GET_TOGGLE(ptd));
                                urb->actual_length += PTD_GET_COUNT(ptd);
                                urb->status = cc_to_error[TD_DATAUNDERRUN];
+                               finish_request(isp116x, ep, urb);
                                spin_unlock(&urb->lock);
                                continue;
                        }
                }
-               /* Keep underrun error through the STATUS stage */
-               if (urb->status == cc_to_error[TD_DATAUNDERRUN])
-                       cc = TD_DATAUNDERRUN;
 
                if (cc != TD_CC_NOERROR && cc != TD_NOTACCESSED
                    && (++ep->error_count >= 3 || cc == TD_CC_STALL
@@ -332,6 +324,7 @@
                                urb->status = cc_to_error[cc];
                        if (ep->nextpid == USB_PID_ACK)
                                ep->nextpid = 0;
+                       finish_request(isp116x, ep, urb);
                        spin_unlock(&urb->lock);
                        continue;
                }
@@ -341,6 +334,7 @@
                if (usb_pipeint(urb->pipe) && !PTD_GET_LEN(ptd)) {
                        if (urb->status == -EINPROGRESS)
                                urb->status = 0;
+                       finish_request(isp116x, ep, urb);
                        spin_unlock(&urb->lock);
                        continue;
                }
@@ -409,6 +403,8 @@
                default:
                        BUG();
                }
+               if (urb->status != -EINPROGRESS)
+                       finish_request(isp116x, ep, urb);
                spin_unlock(&urb->lock);
        }
 }
@@ -570,9 +566,6 @@
 */
 static void finish_atl_transfers(struct isp116x *isp116x)
 {
-       struct isp116x_ep *ep;
-       struct urb *urb;
-
        if (!isp116x->atl_active)
                return;
        /* Fifo not ready? */
@@ -582,16 +575,6 @@
        atomic_inc(&isp116x->atl_finishing);
        unpack_fifo(isp116x);
        postproc_atl_queue(isp116x);
-       for (ep = isp116x->atl_active; ep; ep = ep->active) {
-               urb =
-                   container_of(ep->hep->urb_list.next, struct urb, urb_list);
-               /* USB_PID_ACK check here avoids finishing of
-                  control transfers, for which TD_DATAUNDERRUN
-                  occured, while URB_SHORT_NOT_OK was set */
-               if (urb && urb->status != -EINPROGRESS
-                   && ep->nextpid != USB_PID_ACK)
-                       finish_request(isp116x, ep, urb);
-       }
        atomic_dec(&isp116x->atl_finishing);
 }
 

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to