From: Greg KH <greg@kroah.com>
To: torvalds@transmeta.com
Cc: linux-usb-devel@lists.sourceforge.net
Subject: [PATCH 3 of 8] USB serial module ownership change

Hi,

Here's a patch against 2.5.2-pre7 that allows the USB serial core to
control the module usage count of the USB serial driver modules.

thanks,

greg k-h


diff -Nru a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
--- a/drivers/usb/serial/usb-serial.h	Thu Jan  3 16:45:34 2002
+++ b/drivers/usb/serial/usb-serial.h	Thu Jan  3 16:45:34 2002
@@ -116,6 +116,7 @@
 
 /**
  * usb_serial_device_type - a structure that defines a usb serial device
+ * @owner: pointer to the module that owns this device.
  * @name: pointer to a string that describes this device.  This string used
  *	in the syslog messages when a device is inserted or removed.
  * @id_table: pointer to a list of usb_device_id structures that define all
@@ -138,6 +139,7 @@
  * called, the generic serial function will be used instead.
  */
 struct usb_serial_device_type {
+	struct module *owner;
 	char	*name;
 	const struct usb_device_id *id_table;
 	char	num_interrupt_in;
diff -Nru a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c
--- a/drivers/usb/serial/usbserial.c	Thu Jan  3 16:45:35 2002
+++ b/drivers/usb/serial/usbserial.c	Thu Jan  3 16:45:35 2002
@@ -506,6 +506,7 @@
 	struct usb_serial *serial;
 	struct usb_serial_port *port;
 	unsigned int portNumber;
+	int retval;
 	
 	dbg(__FUNCTION__);
 
@@ -527,10 +528,16 @@
 	 
 	/* pass on to the driver specific version of this function if it is available */
 	if (serial->type->open) {
-		return (serial->type->open(port, filp));
+		if (serial->type->owner)
+			__MOD_INC_USE_COUNT(serial->type->owner);
+		retval = serial->type->open(port, filp);
+		if (retval)
+			__MOD_DEC_USE_COUNT(serial->type->owner);
 	} else {
-		return (generic_open(port, filp));
+		retval = generic_open(port, filp);
 	}
+
+	return retval;
 }
 
 
@@ -553,6 +560,8 @@
 	/* pass on to the driver specific version of this function if it is available */
 	if (serial->type->close) {
 		serial->type->close(port, filp);
+		if (serial->type->owner)
+			__MOD_DEC_USE_COUNT(serial->type->owner);
 	} else {
 		generic_close(port, filp);
 	}
@@ -1059,6 +1068,7 @@
 	struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
 	struct usb_serial_device_type *type = NULL;
 	struct list_head *tmp;
+	int retval;
 	int found;
 	int minor;
 	int buffer_size;
@@ -1180,9 +1190,13 @@
 
 	/* if this device type has a startup function, call it */
 	if (type->startup) {
-		if (type->startup (serial)) {
+		if (type->owner)
+			__MOD_INC_USE_COUNT(type->owner);
+		retval = type->startup (serial);
+		if (type->owner)
+			__MOD_DEC_USE_COUNT(type->owner);
+		if (retval)
 			goto probe_error;
-		}
 	}
 
 	/* set up the endpoint information */
