The code here is moved out of the list for each into a separate
function. There should be no functional change.

Signed-off-by: Sebastian Andrzej Siewior <bige...@linutronix.de>
---
 drivers/usb/gadget/dummy_hcd.c |  314 +++++++++++++++++++++-------------------
 1 file changed, 162 insertions(+), 152 deletions(-)

diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 0f7541b..ea702c6 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -1659,6 +1659,164 @@ static int handle_control_request(struct dummy_hcd 
*dum_hcd, struct urb *urb,
        return ret_val;
 }
 
+static int handle_one_urb(struct urbp *urbp, struct dummy_hcd *dum_hcd, int 
*total)
+{
+       struct dummy            *dum = dum_hcd->dum;
+       struct urb              *urb;
+       struct dummy_request    *req;
+       u8                      address;
+       struct dummy_ep         *ep = NULL;
+       int                     type;
+       int                     status = -EINPROGRESS;
+       int                     limit;
+
+       urb = urbp->urb;
+       if (urb->unlinked)
+               goto return_urb;
+       else if (dum_hcd->rh_state != DUMMY_RH_RUNNING)
+               return 0;
+       type = usb_pipetype(urb->pipe);
+
+       /* used up this frame's non-periodic bandwidth?
+        * FIXME there's infinite bandwidth for control and
+        * periodic transfers ... unrealistic.
+        */
+       if (*total <= 0 && type == PIPE_BULK)
+               return 0;
+
+       /* find the gadget's ep for this request (if configured) */
+       address = usb_pipeendpoint (urb->pipe);
+       if (usb_pipein(urb->pipe))
+               address |= USB_DIR_IN;
+       ep = find_endpoint(dum, address);
+       if (!ep) {
+               /* set_configuration() disagreement */
+               dev_dbg(dummy_dev(dum_hcd),
+                               "no ep configured for urb %p\n",
+                               urb);
+               status = -EPROTO;
+               goto return_urb;
+       }
+
+       if (ep->already_seen)
+               return 0;
+       ep->already_seen = 1;
+       if (ep == &dum->ep[0] && urb->error_count) {
+               ep->setup_stage = 1;    /* a new urb */
+               urb->error_count = 0;
+       }
+       if (ep->halted && !ep->setup_stage) {
+               /* NOTE: must not be iso! */
+               dev_dbg(dummy_dev(dum_hcd), "ep %s halted, urb %p\n",
+                               ep->ep.name, urb);
+               status = -EPIPE;
+               goto return_urb;
+       }
+       /* FIXME make sure both ends agree on maxpacket */
+
+       /* handle control requests */
+       if (ep == &dum->ep[0] && ep->setup_stage) {
+               struct usb_ctrlrequest          setup;
+               int                             value = 1;
+
+               setup = *(struct usb_ctrlrequest *) urb->setup_packet;
+               /* paranoia, in case of stale queued data */
+               list_for_each_entry(req, &ep->queue, queue) {
+                       list_del_init(&req->queue);
+                       req->req.status = -EOVERFLOW;
+                       dev_dbg(udc_dev(dum), "stale req = %p\n",
+                                       req);
+
+                       spin_unlock(&dum->lock);
+                       req->req.complete(&ep->ep, &req->req);
+                       spin_lock(&dum->lock);
+                       ep->already_seen = 0;
+                       return 1;
+               }
+
+               /* gadget driver never sees set_address or operations
+                * on standard feature flags.  some hardware doesn't
+                * even expose them.
+                */
+               ep->last_io = jiffies;
+               ep->setup_stage = 0;
+               ep->halted = 0;
+
+               value = handle_control_request(dum_hcd, urb, &setup,
+                               &status);
+
+               /* gadget driver handles all other requests.  block
+                * until setup() returns; no reentrancy issues etc.
+                */
+               if (value > 0) {
+                       spin_unlock(&dum->lock);
+                       value = dum->driver->setup(&dum->gadget,
+                                       &setup);
+                       spin_lock(&dum->lock);
+
+                       if (value >= 0) {
+                               /* no delays (max 64KB data stage) */
+                               limit = 64*1024;
+                               goto treat_control_like_bulk;
+                       }
+                       /* error, see below */
+               }
+
+               if (value < 0) {
+                       if (value != -EOPNOTSUPP)
+                               dev_dbg(udc_dev(dum),
+                                               "setup --> %d\n",
+                                               value);
+                       status = -EPIPE;
+                       urb->actual_length = 0;
+               }
+
+               goto return_urb;
+       }
+
+       /* non-control requests */
+       limit = *total;
+       switch (usb_pipetype(urb->pipe)) {
+               case PIPE_ISOCHRONOUS:
+                       /* FIXME is it urb->interval since the last xfer?
+                        * use urb->iso_frame_desc[i].
+                        * complete whether or not ep has requests queued.
+                        * report random errors, to debug drivers.
+                        */
+                       limit = max(limit, periodic_bytes(dum, ep));
+                       status = -ENOSYS;
+                       break;
+
+               case PIPE_INTERRUPT:
+                       /* FIXME is it urb->interval since the last xfer?
+                        * this almost certainly polls too fast.
+                        */
+                       limit = max(limit, periodic_bytes(dum, ep));
+                       /* FALLTHROUGH */
+
+               default:
+treat_control_like_bulk:
+                       ep->last_io = jiffies;
+                       *total = transfer(dum_hcd, urb, ep, limit, &status);
+                       break;
+       }
+
+       /* incomplete transfer? */
+       if (status == -EINPROGRESS)
+               return 0;
+return_urb:
+       list_del(&urbp->urbp_list);
+       kfree(urbp);
+       if (ep)
+               ep->already_seen = ep->setup_stage = 0;
+
+       usb_hcd_unlink_urb_from_ep(dummy_hcd_to_hcd(dum_hcd), urb);
+       spin_unlock(&dum->lock);
+       usb_hcd_giveback_urb(dummy_hcd_to_hcd(dum_hcd), urb, status);
+       spin_lock(&dum->lock);
+       return 1;
+}
+
 /* drive both sides of the transfers; looks like irq handlers to
  * both drivers except the callbacks aren't in_irq().
  */
@@ -1668,7 +1826,7 @@ static void dummy_timer(unsigned long _dum_hcd)
        struct dummy            *dum = dum_hcd->dum;
        struct urbp             *urbp, *tmp;
        unsigned long           flags;
-       int                     limit, total;
+       int                     total;
        int                     i;
 
        /* simplistic model for one frame's bandwidth */
@@ -1711,159 +1869,11 @@ static void dummy_timer(unsigned long _dum_hcd)
 
 restart:
        list_for_each_entry_safe(urbp, tmp, &dum_hcd->urbp_list, urbp_list) {
-               struct urb              *urb;
-               struct dummy_request    *req;
-               u8                      address;
-               struct dummy_ep         *ep = NULL;
-               int                     type;
-               int                     status = -EINPROGRESS;
-
-               urb = urbp->urb;
-               if (urb->unlinked)
-                       goto return_urb;
-               else if (dum_hcd->rh_state != DUMMY_RH_RUNNING)
-                       continue;
-               type = usb_pipetype(urb->pipe);
-
-               /* used up this frame's non-periodic bandwidth?
-                * FIXME there's infinite bandwidth for control and
-                * periodic transfers ... unrealistic.
-                */
-               if (total <= 0 && type == PIPE_BULK)
-                       continue;
-
-               /* find the gadget's ep for this request (if configured) */
-               address = usb_pipeendpoint (urb->pipe);
-               if (usb_pipein(urb->pipe))
-                       address |= USB_DIR_IN;
-               ep = find_endpoint(dum, address);
-               if (!ep) {
-                       /* set_configuration() disagreement */
-                       dev_dbg(dummy_dev(dum_hcd),
-                               "no ep configured for urb %p\n",
-                               urb);
-                       status = -EPROTO;
-                       goto return_urb;
-               }
+               int ret;
 
-               if (ep->already_seen)
+               ret = handle_one_urb(urbp, dum_hcd, &total);
+               if (!ret)
                        continue;
-               ep->already_seen = 1;
-               if (ep == &dum->ep[0] && urb->error_count) {
-                       ep->setup_stage = 1;    /* a new urb */
-                       urb->error_count = 0;
-               }
-               if (ep->halted && !ep->setup_stage) {
-                       /* NOTE: must not be iso! */
-                       dev_dbg(dummy_dev(dum_hcd), "ep %s halted, urb %p\n",
-                                       ep->ep.name, urb);
-                       status = -EPIPE;
-                       goto return_urb;
-               }
-               /* FIXME make sure both ends agree on maxpacket */
-
-               /* handle control requests */
-               if (ep == &dum->ep[0] && ep->setup_stage) {
-                       struct usb_ctrlrequest          setup;
-                       int                             value = 1;
-
-                       setup = *(struct usb_ctrlrequest *) urb->setup_packet;
-                       /* paranoia, in case of stale queued data */
-                       list_for_each_entry(req, &ep->queue, queue) {
-                               list_del_init(&req->queue);
-                               req->req.status = -EOVERFLOW;
-                               dev_dbg(udc_dev(dum), "stale req = %p\n",
-                                               req);
-
-                               spin_unlock(&dum->lock);
-                               req->req.complete(&ep->ep, &req->req);
-                               spin_lock(&dum->lock);
-                               ep->already_seen = 0;
-                               goto restart;
-                       }
-
-                       /* gadget driver never sees set_address or operations
-                        * on standard feature flags.  some hardware doesn't
-                        * even expose them.
-                        */
-                       ep->last_io = jiffies;
-                       ep->setup_stage = 0;
-                       ep->halted = 0;
-
-                       value = handle_control_request(dum_hcd, urb, &setup,
-                                                      &status);
-
-                       /* gadget driver handles all other requests.  block
-                        * until setup() returns; no reentrancy issues etc.
-                        */
-                       if (value > 0) {
-                               spin_unlock(&dum->lock);
-                               value = dum->driver->setup(&dum->gadget,
-                                               &setup);
-                               spin_lock(&dum->lock);
-
-                               if (value >= 0) {
-                                       /* no delays (max 64KB data stage) */
-                                       limit = 64*1024;
-                                       goto treat_control_like_bulk;
-                               }
-                               /* error, see below */
-                       }
-
-                       if (value < 0) {
-                               if (value != -EOPNOTSUPP)
-                                       dev_dbg(udc_dev(dum),
-                                               "setup --> %d\n",
-                                               value);
-                               status = -EPIPE;
-                               urb->actual_length = 0;
-                       }
-
-                       goto return_urb;
-               }
-
-               /* non-control requests */
-               limit = total;
-               switch (usb_pipetype(urb->pipe)) {
-               case PIPE_ISOCHRONOUS:
-                       /* FIXME is it urb->interval since the last xfer?
-                        * use urb->iso_frame_desc[i].
-                        * complete whether or not ep has requests queued.
-                        * report random errors, to debug drivers.
-                        */
-                       limit = max(limit, periodic_bytes(dum, ep));
-                       status = -ENOSYS;
-                       break;
-
-               case PIPE_INTERRUPT:
-                       /* FIXME is it urb->interval since the last xfer?
-                        * this almost certainly polls too fast.
-                        */
-                       limit = max(limit, periodic_bytes(dum, ep));
-                       /* FALLTHROUGH */
-
-               default:
-treat_control_like_bulk:
-                       ep->last_io = jiffies;
-                       total = transfer(dum_hcd, urb, ep, limit, &status);
-                       break;
-               }
-
-               /* incomplete transfer? */
-               if (status == -EINPROGRESS)
-                       continue;
-
-return_urb:
-               list_del(&urbp->urbp_list);
-               kfree(urbp);
-               if (ep)
-                       ep->already_seen = ep->setup_stage = 0;
-
-               usb_hcd_unlink_urb_from_ep(dummy_hcd_to_hcd(dum_hcd), urb);
-               spin_unlock(&dum->lock);
-               usb_hcd_giveback_urb(dummy_hcd_to_hcd(dum_hcd), urb, status);
-               spin_lock(&dum->lock);
-
                goto restart;
        }
 
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to