[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.