[PATCH]autosuspend for cdc-acm
Oliver Neukum <[email protected]>
| Newsgroups | gmane.linux.usb.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi, this patch implements autosuspend for CDC ACM devices. It addresses Alan's concerns about using the existing suspend/resume methods for this. Locking indeed has been had to be changed. Regards Oliver Signed-off-by: Oliver Neukum <[email protected]> ---- --- linux-2.6.23-rc9/drivers/usb/class/cdc-acm.h 2007-10-11 10:02:26.000000000 +0200 +++ acm/drivers/usb/class/cdc-acm.h 2007-10-10 12:55:12.000000000 +0200 @@ -107,6 +107,7 @@ struct acm { int write_used; /* number of non-empty write buffers */ int write_ready; /* write urb is not running */ spinlock_t write_lock; + 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 tasklet_struct urb_task; /* rx processing */ --- linux-2.6.23-rc9/drivers/usb/class/cdc-acm.c 2007-10-11 10:02:26.000000000 +0200 +++ acm/drivers/usb/class/cdc-acm.c 2007-10-11 09:38:08.000000000 +0200 @@ -496,10 +496,19 @@ static int acm_tty_open(struct tty_struc otherwise it is scheduled, and with high data rates data can get lost. */ tty->low_latency = 1; + if (usb_autopm_get_interface(acm->control)) { + mutex_unlock(&open_mutex); + return -EIO; + } + + mutex_lock(&acm->mutex); + mutex_unlock(&open_mutex); if (acm->used++) { + usb_autopm_put_interface(acm->control); goto done; } + acm->ctrlurb->dev = acm->dev; if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { dbg("usb_submit_urb(ctrl irq) failed"); @@ -526,14 +535,15 @@ static int acm_tty_open(struct tty_struc done: err_out: - mutex_unlock(&open_mutex); + mutex_unlock(&acm->mutex); return rv; full_bailout: usb_kill_urb(acm->ctrlurb); bail_out: + usb_autopm_put_interface(acm->control); acm->used--; - mutex_unlock(&open_mutex); + mutex_unlock(&acm->mutex); return -EIO; } @@ -570,6 +580,7 @@ static void acm_tty_close(struct tty_str usb_kill_urb(acm->writeurb); for (i = 0; i < nr; i++) usb_kill_urb(acm->ru[i].urb); + usb_autopm_put_interface(acm->control); } else acm_tty_unregister(acm); } @@ -980,6 +991,7 @@ skip_normal_probe: spin_lock_init(&acm->throttle_lock); spin_lock_init(&acm->write_lock); spin_lock_init(&acm->read_lock); + mutex_init(&acm->mutex); acm->write_ready = 1; acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress); @@ -1112,7 +1124,7 @@ static void stop_data_traffic(struct acm tasklet_enable(&acm->urb_task); - flush_scheduled_work(); /* wait for acm_softint */ + cancel_work_sync(&acm->work); } static void acm_disconnect(struct usb_interface *intf) @@ -1170,15 +1182,15 @@ static int acm_suspend(struct usb_interf if (acm->susp_count++) return 0; /* - we treat opened interface differently, - we must giard against open + we treat opened interfaces differently, + we must guard against open */ - mutex_lock(&open_mutex); + mutex_lock(&acm->mutex); if (acm->used) stop_data_traffic(acm); - mutex_unlock(&open_mutex); + mutex_unlock(&acm->mutex); return 0; } @@ -1190,7 +1202,7 @@ static int acm_resume(struct usb_interfa if (--acm->susp_count) return 0; - mutex_lock(&open_mutex); + mutex_lock(&acm->mutex); if (acm->used) { rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); if (rv < 0) @@ -1200,7 +1212,7 @@ static int acm_resume(struct usb_interfa } err_out: - mutex_unlock(&open_mutex); + mutex_unlock(&acm->mutex); return rv; } /* @@ -1258,6 +1270,7 @@ static struct usb_driver acm_driver = { .suspend = acm_suspend, .resume = acm_resume, .id_table = acm_ids, + .supports_autosuspend = 1, }; /* ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ [email protected] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel