USB: cdc-acm: Update to new autopm API
authorOliver Neukum <oliver@neukum.org>
Wed, 16 Dec 2009 16:05:57 +0000 (17:05 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 2 Mar 2010 22:53:19 +0000 (14:53 -0800)
Update cdc-acm to the async methods eliminating the workqueue

Signed-off-by: Oliver Neukum <oliver@neukum.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.h

index ef2e6f9c890693ae40c6b9d66b3168356d1f5b6c..6ae7ccaff07f357a3ef0084fa4878da80681ddca 100644 (file)
@@ -170,6 +170,7 @@ static void acm_write_done(struct acm *acm, struct acm_wb *wb)
 {
        wb->use = 0;
        acm->transmitting--;
+       usb_autopm_put_interface_async(acm->control);
 }
 
 /*
@@ -211,9 +212,12 @@ static int acm_write_start(struct acm *acm, int wbn)
        }
 
        dbg("%s susp_count: %d", __func__, acm->susp_count);
+       usb_autopm_get_interface_async(acm->control);
        if (acm->susp_count) {
-               acm->delayed_wb = wb;
-               schedule_work(&acm->waker);
+               if (!acm->delayed_wb)
+                       acm->delayed_wb = wb;
+               else
+                       usb_autopm_put_interface_async(acm->control);
                spin_unlock_irqrestore(&acm->write_lock, flags);
                return 0;       /* A white lie */
        }
@@ -534,23 +538,6 @@ static void acm_softint(struct work_struct *work)
        tty_kref_put(tty);
 }
 
-static void acm_waker(struct work_struct *waker)
-{
-       struct acm *acm = container_of(waker, struct acm, waker);
-       int rv;
-
-       rv = usb_autopm_get_interface(acm->control);
-       if (rv < 0) {
-               dev_err(&acm->dev->dev, "Autopm failure in %s\n", __func__);
-               return;
-       }
-       if (acm->delayed_wb) {
-               acm_start_wb(acm, acm->delayed_wb);
-               acm->delayed_wb = NULL;
-       }
-       usb_autopm_put_interface(acm->control);
-}
-
 /*
  * TTY handlers
  */
@@ -1178,7 +1165,6 @@ made_compressed_probe:
        acm->urb_task.func = acm_rx_tasklet;
        acm->urb_task.data = (unsigned long) acm;
        INIT_WORK(&acm->work, acm_softint);
-       INIT_WORK(&acm->waker, acm_waker);
        init_waitqueue_head(&acm->drain_wait);
        spin_lock_init(&acm->throttle_lock);
        spin_lock_init(&acm->write_lock);
@@ -1343,7 +1329,6 @@ static void stop_data_traffic(struct acm *acm)
        tasklet_enable(&acm->urb_task);
 
        cancel_work_sync(&acm->work);
-       cancel_work_sync(&acm->waker);
 }
 
 static void acm_disconnect(struct usb_interface *intf)
@@ -1435,6 +1420,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
 static int acm_resume(struct usb_interface *intf)
 {
        struct acm *acm = usb_get_intfdata(intf);
+       struct acm_wb *wb;
        int rv = 0;
        int cnt;
 
@@ -1449,6 +1435,21 @@ static int acm_resume(struct usb_interface *intf)
        mutex_lock(&acm->mutex);
        if (acm->port.count) {
                rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
+
+               spin_lock_irq(&acm->write_lock);
+               if (acm->delayed_wb) {
+                       wb = acm->delayed_wb;
+                       acm->delayed_wb = NULL;
+                       spin_unlock_irq(&acm->write_lock);
+                       acm_start_wb(acm, acm->delayed_wb);
+               } else {
+                       spin_unlock_irq(&acm->write_lock);
+               }
+
+               /*
+                * delayed error checking because we must
+                * do the write path at all cost
+                */
                if (rv < 0)
                        goto err_out;
 
index c4a0ee8ffccfb3ae4203c8cac4d091d88177b478..519eb638b6e960a8325d65deff2f7829932050f6 100644 (file)
@@ -112,7 +112,6 @@ struct acm {
        struct mutex mutex;
        struct usb_cdc_line_coding line;                /* bits, stop, parity */
        struct work_struct work;                        /* work queue entry for line discipline waking up */
-       struct work_struct waker;
        wait_queue_head_t drain_wait;                   /* close processing */
        struct tasklet_struct urb_task;                 /* rx processing */
        spinlock_t throttle_lock;                       /* synchronize throtteling and read callback */