diff options
author | Seshendra Gadagottu <sgadagottu@nvidia.com> | 2012-01-03 12:46:16 +0530 |
---|---|---|
committer | Rohan Somvanshi <rsomvanshi@nvidia.com> | 2012-01-24 10:59:14 -0800 |
commit | 65ab9647d93da8dce3ea14922a6095bbcf64efcd (patch) | |
tree | aa50b79a613cb263244d28ed4ffb6a0fd175c825 | |
parent | bd4116d82f800957161272a89eaa4015f6b9c0f4 (diff) |
arm: usb: cdc: Modifed USB buffer logic for autopm issue
Modifed usb buffer anchor mechanism to process pending
urb requests. cdc-acm has buffer mechanism to buffer
first pending request. This mechanism is replaced with
new anchor mechanism which can buffer any number of requests.
BUG 919145
Reviewed-on: http://git-master/r/72944
Change-Id: Ibcedc92457013bd616b194e9ea3ce73e69fcdde6
Reviewed-by: Michael Hsu <mhsu@nvidia.com>
Reviewed-by: Steve Lin <stlin@nvidia.com>
Signed-off-by: Seshendra Gadagottu<sgadagottu@nvidia.com>
Signed-off-by: Varun Wadekar <vwadekar@nvidia.com>
Reviewed-on: http://git-master/r/76821
Reviewed-by: Automatic_Commit_Validation_User
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 47 |
1 files changed, 32 insertions, 15 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 98c0e79110f4..d3bb2fc7fe2b 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -170,6 +170,9 @@ static int acm_write_start(struct acm *acm, int wbn) unsigned long flags; struct acm_wb *wb = &acm->wb[wbn]; int rc; +#ifdef CONFIG_PM + struct urb *res; +#endif spin_lock_irqsave(&acm->write_lock, flags); if (!acm->dev) { @@ -183,23 +186,32 @@ static int acm_write_start(struct acm *acm, int wbn) usb_autopm_get_interface_async(acm->control); if (acm->susp_count) { #ifdef CONFIG_PM - printk("%s buffer urb\n", __func__); acm->transmitting++; wb->urb->transfer_buffer = wb->buf; wb->urb->transfer_dma = wb->dmah; wb->urb->transfer_buffer_length = wb->len; wb->urb->dev = acm->dev; usb_anchor_urb(wb->urb, &acm->deferred); -#endif +#else if (!acm->delayed_wb) acm->delayed_wb = wb; else usb_autopm_put_interface_async(acm->control); +#endif spin_unlock_irqrestore(&acm->write_lock, flags); return 0; /* A white lie */ } usb_mark_last_busy(acm->dev); - +#ifdef CONFIG_PM + while ((res = usb_get_from_anchor(&acm->deferred))) { + rc = usb_submit_urb(res, GFP_ATOMIC); + if (rc < 0) { + dbg("usb_submit_urb(pending request) failed: %d", rc); + usb_unanchor_urb(res); + acm_write_done(acm, res->context); + } + } +#endif rc = acm_start_wb(acm, wb); spin_unlock_irqrestore(&acm->write_lock, flags); @@ -1305,6 +1317,7 @@ static void acm_disconnect(struct usb_interface *intf) stop_data_traffic(acm); + usb_kill_anchored_urbs(&acm->deferred); acm_write_buffers_free(acm); usb_free_coherent(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); @@ -1370,8 +1383,10 @@ static int acm_resume(struct usb_interface *intf) struct acm *acm = usb_get_intfdata(intf); struct acm_wb *wb; int rv = 0; - struct urb *res; int cnt; +#ifdef CONFIG_PM + struct urb *res; +#endif spin_lock_irq(&acm->read_lock); acm->susp_count -= 1; @@ -1384,19 +1399,21 @@ static int acm_resume(struct usb_interface *intf) mutex_lock(&acm->mutex); -#ifdef CONFIG_PM - while ((res = usb_get_from_anchor(&acm->deferred))) { - printk("%s process buffered request \n", __func__); - rv = usb_submit_urb(res, GFP_ATOMIC); - if (rv < 0) { - dbg("usb_submit_urb(pending request) failed: %d", rv); - } - } -#endif - if (acm->port.count) { rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); spin_lock_irq(&acm->write_lock); +#ifdef CONFIG_PM + while ((res = usb_get_from_anchor(&acm->deferred))) { + rv = usb_submit_urb(res, GFP_ATOMIC); + if (rv < 0) { + dbg("usb_submit_urb(pending request)" + " failed: %d", rv); + usb_unanchor_urb(res); + acm_write_done(acm, res->context); + } + } + spin_unlock_irq(&acm->write_lock); +#else if (acm->delayed_wb) { wb = acm->delayed_wb; acm->delayed_wb = NULL; @@ -1405,7 +1422,7 @@ static int acm_resume(struct usb_interface *intf) } else { spin_unlock_irq(&acm->write_lock); } - +#endif /* * delayed error checking because we must |