[patch]autosuspend for usb serial

Oliver Neukum <[email protected]>
Newsgroups gmane.linux.usb.devel
Organization Novell
Message-ID <[email protected]>
Hi,

this implements the standard open/close autosuspend support for
usb serial devices.

	Regards
		Oliver
Signed-off-by: Oliver Neukum <[email protected]>
-- 

--- a/drivers/usb/serial/usb-serial.c	2007-04-27 11:19:41.000000000 +0200
+++ b/drivers/usb/serial/usb-serial.c	2007-04-27 17:52:26.000000000 +0200
@@ -50,6 +50,7 @@ static struct usb_driver usb_serial_driv
 	.suspend =	usb_serial_suspend,
 	.resume =	usb_serial_resume,
 	.no_dynamic_id = 	1,
+	.supports_autosuspend =	1,
 };
 
 /* There is no MODULE_DEVICE_TABLE for usbserial.c.  Instead
@@ -226,16 +227,21 @@ static int serial_open (struct tty_struc
 			goto bailout_mutex_unlock;
 		}
 
+		retval = usb_autopm_get_interface(serial->interface);
+		if (retval)
+			goto bailout_module_put;
+
 		/* only call the device specific open if this 
 		 * is the first time the port is opened */
 		retval = serial->type->open(port, filp);
 		if (retval)
-			goto bailout_module_put;
+			goto bailout_module_put_autopm;
 	}
 
 	mutex_unlock(&port->mutex);
 	return 0;
-
+bailout_module_put_autopm:
+	usb_autopm_put_interface(serial->interface);
 bailout_module_put:
 	module_put(serial->type->driver.owner);
 bailout_mutex_unlock:
@@ -276,6 +282,8 @@ static void serial_close(struct tty_stru
 			port->tty = NULL;
 		}
 
+		if (!port->disconnected)
+			usb_autopm_put_interface(port->serial->interface);
 		module_put(port->serial->type->driver.owner);
 	}
 
@@ -1059,6 +1067,9 @@ void usb_serial_disconnect(struct usb_in
 	if (serial) {
 		for (i = 0; i < serial->num_ports; ++i) {
 			port = serial->port[i];
+			mutex_lock(&port->mutex);
+			port->disconnected = 1;
+			mutex_unlock(&port->mutex);
 			if (port) {
 				if (port->tty)
 					tty_hangup(port->tty);
@@ -1078,6 +1089,7 @@ int usb_serial_suspend(struct usb_interf
 	struct usb_serial_port *port;
 	int i, r = 0;
 
+	dev_info(&intf->dev, "suspending device\n");
 	if (serial) {
 		for (i = 0; i < serial->num_ports; ++i) {
 			port = serial->port[i];
@@ -1098,6 +1110,7 @@ int usb_serial_resume(struct usb_interfa
 {
 	struct usb_serial *serial = usb_get_intfdata(intf);
 
+	dev_info(&intf->dev,"resuming device\n");
 	return serial->type->resume(serial);
 }
 
--- a/include/linux/usb/serial.h	2007-04-27 11:21:06.000000000 +0200
+++ b/include/linux/usb/serial.h	2007-04-27 11:21:56.000000000 +0200
@@ -64,8 +64,9 @@ struct usb_serial_port {
 	struct usb_serial *	serial;
 	struct tty_struct *	tty;
 	spinlock_t		lock;
-	struct mutex            mutex;
+	struct mutex		mutex;
 	unsigned char		number;
+	unsigned char		disconnected;
 
 	unsigned char *		interrupt_in_buffer;
 	struct urb *		interrupt_in_urb;


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
[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.