summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeshendra Gadagottu <sgadagottu@nvidia.com>2012-01-03 12:46:16 +0530
committerRohan Somvanshi <rsomvanshi@nvidia.com>2012-01-24 10:59:14 -0800
commit65ab9647d93da8dce3ea14922a6095bbcf64efcd (patch)
treeaa50b79a613cb263244d28ed4ffb6a0fd175c825
parentbd4116d82f800957161272a89eaa4015f6b9c0f4 (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.c47
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