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 <bigeasy@xxxxxxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html