[RFC PATCH] USB: serial: rework usb_serial_register/deregister_drivers()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This reworks the usb_serial_register_drivers() and
usb_serial_deregister_drivers() to not need a pointer to a struct
usb_driver anymore.  The usb_driver structure is created dynamically and
registered and unregistered as needed.


Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

---
 drivers/usb/serial/generic.c    |    9 ++-------
 drivers/usb/serial/usb-serial.c |   30 ++++++++++++++++++------------
 include/linux/usb/serial.h      |   27 +++++++++++++++++++--------
 3 files changed, 39 insertions(+), 27 deletions(-)

Untested, but I think this will work.  It makes the usb-serial drivers
smaller, which is always nice, I'll follow-on with a patch for what is
needed to convert the individual drivers.

Any objections?

I'll test this after lunch...

diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 4e5e993..3644f51 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -46,11 +46,6 @@ static const struct usb_device_id generic_serial_ids[] = {
 	{}
 };
 
-static struct usb_driver generic_driver = {
-	.name =		"usbserial_generic",
-	.id_table =	generic_serial_ids,
-};
-
 /* All of the device info needed for the Generic Serial Converter */
 struct usb_serial_driver usb_serial_generic_device = {
 	.driver = {
@@ -84,7 +79,7 @@ int usb_serial_generic_register(int _debug)
 		USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
 
 	/* register our generic driver with ourselves */
-	retval = usb_serial_register_drivers(&generic_driver, serial_drivers);
+	retval = usb_serial_register_drivers(serial_drivers, "usbserial_generic", generic_serial_ids);
 #endif
 	return retval;
 }
@@ -93,7 +88,7 @@ void usb_serial_generic_deregister(void)
 {
 #ifdef CONFIG_USB_SERIAL_GENERIC
 	/* remove our generic driver */
-	usb_serial_deregister_drivers(&generic_driver, serial_drivers);
+	usb_serial_deregister_drivers(serial_drivers);
 #endif
 }
 
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index d1840ae..dd5e7ca 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1364,18 +1364,21 @@ static void usb_serial_deregister(struct usb_serial_driver *device)
 
 /**
  * usb_serial_register_drivers - register drivers for a usb-serial module
- * @udriver: usb_driver used for matching devices/interfaces
  * @serial_drivers: NULL-terminated array of pointers to drivers to be registered
+ * @name: name of the usb_driver for this set of @serial_drivers
+ * @id_table: list of all devices this @serial_drivers set binds to
  *
- * Registers @udriver and all the drivers in the @serial_drivers array.
+ * Registers all the drivers in the @serial_drivers array, and a struct usb_driver
+ * with the name @name.
  * Automatically fills in the .no_dynamic_id and PM fields in @udriver and
  * the .usb_driver field in each serial driver.
  */
-int usb_serial_register_drivers(struct usb_driver *udriver,
-		struct usb_serial_driver * const serial_drivers[])
+int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[],
+				const char *name,
+				const struct usb_device_id *id_table)
 {
 	int rc;
-	const struct usb_device_id *saved_id_table;
+	struct usb_driver *udriver;
 	struct usb_serial_driver * const *sd;
 
 	/*
@@ -1391,9 +1394,11 @@ int usb_serial_register_drivers(struct usb_driver *udriver,
 	 * Suspend/resume support is implemented in the usb-serial core,
 	 * so fill in the PM-related fields in udriver.
 	 */
-	saved_id_table = udriver->id_table;
-	udriver->id_table = NULL;
+	udriver = kzalloc(sizeof(*udriver), GFP_KERNEL);
+	if (!udriver)
+		return -ENOMEM;
 
+	udriver->name = name;
 	udriver->no_dynamic_id = 1;
 	udriver->supports_autosuspend = 1;
 	udriver->suspend = usb_serial_suspend;
@@ -1412,7 +1417,7 @@ int usb_serial_register_drivers(struct usb_driver *udriver,
 	}
 
 	/* Now restore udriver's id_table and look for matches */
-	udriver->id_table = saved_id_table;
+	udriver->id_table = id_table;
 	rc = driver_attach(&udriver->drvwrap.driver);
 	return 0;
 
@@ -1426,17 +1431,18 @@ EXPORT_SYMBOL_GPL(usb_serial_register_drivers);
 
 /**
  * usb_serial_deregister_drivers - deregister drivers for a usb-serial module
- * @udriver: usb_driver to unregister
  * @serial_drivers: NULL-terminated array of pointers to drivers to be deregistered
  *
- * Deregisters @udriver and all the drivers in the @serial_drivers array.
+ * Deregisters all the drivers in the @serial_drivers array.
  */
-void usb_serial_deregister_drivers(struct usb_driver *udriver,
-		struct usb_serial_driver * const serial_drivers[])
+void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_drivers[])
 {
+	struct usb_driver *udriver = (*serial_drivers)->usb_driver;
+
 	for (; *serial_drivers; ++serial_drivers)
 		usb_serial_deregister(*serial_drivers);
 	usb_deregister(udriver);
+	kfree(udriver);
 }
 EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers);
 
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index 749836f..c9f6514 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -292,10 +292,9 @@ struct usb_serial_driver {
 #define to_usb_serial_driver(d) \
 	container_of(d, struct usb_serial_driver, driver)
 
-extern int usb_serial_register_drivers(struct usb_driver *udriver,
-		struct usb_serial_driver * const serial_drivers[]);
-extern void usb_serial_deregister_drivers(struct usb_driver *udriver,
-		struct usb_serial_driver * const serial_drivers[]);
+extern int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[],
+		const char *name, const struct usb_device_id *id_table);
+extern void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_drivers[]);
 extern void usb_serial_port_softint(struct usb_serial_port *port);
 
 extern int usb_serial_suspend(struct usb_interface *intf, pm_message_t message);
@@ -396,8 +395,8 @@ do {									\
 
 /*
  * module_usb_serial_driver() - Helper macro for registering a USB Serial driver
- * @__usb_driver: usb_driver struct to register
  * @__serial_drivers: list of usb_serial drivers to register
+ * @__ids: all device ids that @__serial_drivers bind to
  *
  * Helper macro for USB serial drivers which do not do anything special
  * in module init/exit. This eliminates a lot of boilerplate. Each
@@ -405,9 +404,21 @@ do {									\
  * module_init() and module_exit()
  *
  */
-#define module_usb_serial_driver(__usb_driver, __serial_drivers)	\
-	module_driver(__usb_driver, usb_serial_register_drivers,	\
-		       usb_serial_deregister_drivers, __serial_drivers)
+#define usb_serial_module_driver(__name, __serial_drivers, __ids)	\
+static int __init usb_serial_module_init(void)				\
+{									\
+	return usb_serial_register_drivers(__serial_drivers,		\
+					   __name, __ids);		\
+}									\
+module_init(usb_serial_module_init);					\
+static void __exit usb_serial_module_exit(void)				\
+{									\
+	usb_serial_deregister_drivers(__serial_drivers);		\
+}									\
+module_exit(usb_serial_module_exit);
+
+#define module_usb_serial_driver(__serial_drivers, __ids)		\
+	usb_serial_module_driver(KBUILD_MODNAME, __serial_drivers, __ids)
 
 #endif /* __LINUX_USB_SERIAL_H */
 
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux