From e688355bfeadf17ef522b1e62cc12f8e88e69667 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 6 Feb 2012 19:22:19 +0100 Subject: USB: serial: add macro for console error reporting Add macro which prints an error message only once if port is used a console. Reporting errors in a write path when port is used as a console could otherwise result in an infinite loop. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/serial.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'include/linux/usb/serial.h') diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 4267a9c717ba..10cb74d2ad1d 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -389,5 +389,20 @@ do { \ printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \ } while (0) +/* + * Macro for reporting errors in write path to avoid inifinite loop + * when port is used as a console. + */ +#define dev_err_console(usport, fmt, ...) \ +do { \ + static bool __print_once; \ + struct usb_serial_port *__port = (usport); \ + \ + if (!__port->port.console || !__print_once) { \ + __print_once = true; \ + dev_err(&__port->dev, fmt, ##__VA_ARGS__); \ + } \ +} while (0) + #endif /* __LINUX_USB_SERIAL_H */ -- cgit v1.2.3 From 765e0ba62613fb90f09c1b5926750df0aa56f349 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Feb 2012 14:55:59 -0500 Subject: usb-serial: new API for driver registration This patch (as1522) adds two new routines to the usb-serial core, for registering and unregistering serial drivers. Instead of registering the usb_driver and usb_serial_drivers separately, with error checking for each one, the drivers can all be registered and unregistered by a single function call. This reduces duplicated code. More importantly, the new core routines change the order in which the drivers are registered. Currently the usb-serial drivers are all registered first and the usb_driver is done last, which leaves a window for problems. A udev script may quickly add a new dynamic-ID for a usb-serial driver, causing the corresponding usb_driver to be probed. If the usb_driver hasn't been registered yet then an oops will occur. The new routine prevents such problems by registering the usb_driver first. To insure that it gets probed properly for already-attached serial devices, we call driver_attach() after all the usb-serial drivers have been registered. Along with adding the new routines, the patch modifies the "generic" serial driver to use them. Further patches will similarly modify all the other in-tree USB serial drivers. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 17 ++++------ drivers/usb/serial/usb-serial.c | 75 +++++++++++++++++++++++++++++++++++++++++ include/linux/usb/serial.h | 9 +++++ 3 files changed, 90 insertions(+), 11 deletions(-) (limited to 'include/linux/usb/serial.h') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 2a2fa2d0489d..664deb63807c 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -54,7 +54,6 @@ static struct usb_driver generic_driver = { .probe = generic_probe, .disconnect = usb_serial_disconnect, .id_table = generic_serial_ids, - .no_dynamic_id = 1, }; /* All of the device info needed for the Generic Serial Converter */ @@ -64,7 +63,6 @@ struct usb_serial_driver usb_serial_generic_device = { .name = "generic", }, .id_table = generic_device_ids, - .usb_driver = &generic_driver, .num_ports = 1, .disconnect = usb_serial_generic_disconnect, .release = usb_serial_generic_release, @@ -73,6 +71,10 @@ struct usb_serial_driver usb_serial_generic_device = { .resume = usb_serial_generic_resume, }; +static struct usb_serial_driver * const serial_drivers[] = { + &usb_serial_generic_device, NULL +}; + static int generic_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -97,13 +99,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(&usb_serial_generic_device); - if (retval) - goto exit; - retval = usb_register(&generic_driver); - if (retval) - usb_serial_deregister(&usb_serial_generic_device); -exit: + retval = usb_serial_register_drivers(&generic_driver, serial_drivers); #endif return retval; } @@ -112,8 +108,7 @@ void usb_serial_generic_deregister(void) { #ifdef CONFIG_USB_SERIAL_GENERIC /* remove our generic driver */ - usb_deregister(&generic_driver); - usb_serial_deregister(&usb_serial_generic_device); + usb_serial_deregister_drivers(&generic_driver, serial_drivers); #endif } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 611b206591cb..45b3658c601f 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1338,6 +1338,11 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, prepare_write_buffer); } +/* + * The next two routines are mainly for internal use. + * They are exported only for out-of-tree modules. + * New drivers should call usb_serial_{de}register_drivers() instead. + */ int usb_serial_register(struct usb_serial_driver *driver) { int retval; @@ -1386,6 +1391,76 @@ void usb_serial_deregister(struct usb_serial_driver *device) } EXPORT_SYMBOL_GPL(usb_serial_deregister); +/** + * 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 + * + * Registers @udriver and all the drivers in the @serial_drivers array. + * Automatically fills in the .no_dynamic_id field 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 rc; + const struct usb_device_id *saved_id_table; + struct usb_serial_driver * const *sd; + + /* + * udriver must be registered before any of the serial drivers, + * because the store_new_id() routine for the serial drivers (in + * bus.c) probes udriver. + * + * Performance hack: We don't want udriver to be probed until + * the serial drivers are registered, because the probe would + * simply fail for lack of a matching serial driver. + * Therefore save off udriver's id_table until we are all set. + */ + saved_id_table = udriver->id_table; + udriver->id_table = NULL; + + udriver->no_dynamic_id = 1; + rc = usb_register(udriver); + if (rc) + return rc; + + for (sd = serial_drivers; *sd; ++sd) { + (*sd)->usb_driver = udriver; + rc = usb_serial_register(*sd); + if (rc) + goto failed; + } + + /* Now restore udriver's id_table and look for matches */ + udriver->id_table = saved_id_table; + rc = driver_attach(&udriver->drvwrap.driver); + return 0; + + failed: + while (sd-- > serial_drivers) + usb_serial_deregister(*sd); + usb_deregister(udriver); + return rc; +} +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. + */ +void usb_serial_deregister_drivers(struct usb_driver *udriver, + struct usb_serial_driver * const serial_drivers[]) +{ + for (; *serial_drivers; ++serial_drivers) + usb_serial_deregister(*serial_drivers); + usb_deregister(udriver); +} +EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers); + /* Module information */ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 10cb74d2ad1d..8c8dbf9c5b89 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -300,8 +300,17 @@ struct usb_serial_driver { #define to_usb_serial_driver(d) \ container_of(d, struct usb_serial_driver, driver) +/* + * These two routines are kept only for backward compatibility. + * Don't use them; call usb_serial_{de}register_drivers() instead. + */ extern int usb_serial_register(struct usb_serial_driver *driver); extern void usb_serial_deregister(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 void usb_serial_port_softint(struct usb_serial_port *port); extern int usb_serial_probe(struct usb_interface *iface, -- cgit v1.2.3 From f799e7678390029e322ae2dc3cda389b11f38124 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 24 Feb 2012 12:50:30 -0800 Subject: USB: serial: remove usb_serial_register and usb_serial_deregister No one uses them anymore, they should be using the safer usb_serial_register_drivers() and usb_serial_deregister_drivers() functions instead. Thanks to Alan Stern for writing these functions and porting all in-kernel users to them. Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 12 ++---------- include/linux/usb/serial.h | 7 ------- 2 files changed, 2 insertions(+), 17 deletions(-) (limited to 'include/linux/usb/serial.h') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 45b3658c601f..63ba47dbcc71 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1338,12 +1338,7 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, prepare_write_buffer); } -/* - * The next two routines are mainly for internal use. - * They are exported only for out-of-tree modules. - * New drivers should call usb_serial_{de}register_drivers() instead. - */ -int usb_serial_register(struct usb_serial_driver *driver) +static int usb_serial_register(struct usb_serial_driver *driver) { int retval; @@ -1377,10 +1372,8 @@ int usb_serial_register(struct usb_serial_driver *driver) mutex_unlock(&table_lock); return retval; } -EXPORT_SYMBOL_GPL(usb_serial_register); - -void usb_serial_deregister(struct usb_serial_driver *device) +static void usb_serial_deregister(struct usb_serial_driver *device) { printk(KERN_INFO "USB Serial deregistering driver %s\n", device->description); @@ -1389,7 +1382,6 @@ void usb_serial_deregister(struct usb_serial_driver *device) usb_serial_bus_deregister(device); mutex_unlock(&table_lock); } -EXPORT_SYMBOL_GPL(usb_serial_deregister); /** * usb_serial_register_drivers - register drivers for a usb-serial module diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 8c8dbf9c5b89..34c06a723dcc 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -300,13 +300,6 @@ struct usb_serial_driver { #define to_usb_serial_driver(d) \ container_of(d, struct usb_serial_driver, driver) -/* - * These two routines are kept only for backward compatibility. - * Don't use them; call usb_serial_{de}register_drivers() instead. - */ -extern int usb_serial_register(struct usb_serial_driver *driver); -extern void usb_serial_deregister(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, -- cgit v1.2.3 From d1cddb4a8e9b09c33158acae05c48069d74fa4d0 Mon Sep 17 00:00:00 2001 From: Greg KH Date: Fri, 24 Feb 2012 15:38:14 -0800 Subject: USB: create module_usb_serial_driver macro Now that Alan Stern has cleaned up the usb serial driver registration, we have the ability to create a module_usb_serial_driver macro to make things a bit simpler, like the other *_driver macros created. But, as we need two functions here, we can't reuse the existing module_driver() macro, so we need to roll our own. Here's a patch implementing module_usb_serial_driver() and it converts the pl2303 driver to use it, showing a nice cleanup. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 18 +----------------- include/linux/usb/serial.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 17 deletions(-) (limited to 'include/linux/usb/serial.h') diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index cc65d810c8f5..ff4a174fa5de 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -855,23 +855,7 @@ static struct usb_serial_driver * const serial_drivers[] = { &pl2303_device, NULL }; -static int __init pl2303_init(void) -{ - int retval; - - retval = usb_serial_register_drivers(&pl2303_driver, serial_drivers); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); - return retval; -} - -static void __exit pl2303_exit(void) -{ - usb_serial_deregister_drivers(&pl2303_driver, serial_drivers); -} - -module_init(pl2303_init); -module_exit(pl2303_exit); +module_usb_serial_driver(pl2303_driver, serial_drivers); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 34c06a723dcc..7b1db841e2a8 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -406,5 +406,33 @@ do { \ } \ } while (0) +/* + * 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 + * + * Helper macro for USB serial drivers which do not do anything special + * in module init/exit. This eliminates a lot of boilerplate. Each + * module may only use this macro once, and calling it replaces + * module_init() and module_exit() + * + * Note, we can't use the generic module_driver() call here, due to the + * two parameters in the usb_serial_* functions, so we roll our own here + * :( + */ +#define module_usb_serial_driver(__usb_driver, __serial_drivers) \ +static int __init usb_serial_driver_init(void) \ +{ \ + return usb_serial_register_drivers(&(__usb_driver), \ + (__serial_drivers)); \ +} \ +module_init(usb_serial_driver_init); \ +static void __exit usb_serial_driver_exit(void) \ +{ \ + return usb_serial_deregister_drivers(&(__usb_driver), \ + (__serial_drivers)); \ +} \ +module_exit(usb_serial_driver_exit); + #endif /* __LINUX_USB_SERIAL_H */ -- cgit v1.2.3 From b790f5d1260b4c962bd066cd34ae982943c27fe1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 9 Mar 2012 16:38:14 -0800 Subject: USB: serial: use module_driver() macro Now that module_driver() can handle varargs, use it instead of rolling our own version. Cc: Lars-Peter Clausen Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/serial.h | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'include/linux/usb/serial.h') diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 7b1db841e2a8..fbb666b1b670 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -416,23 +416,10 @@ do { \ * module may only use this macro once, and calling it replaces * module_init() and module_exit() * - * Note, we can't use the generic module_driver() call here, due to the - * two parameters in the usb_serial_* functions, so we roll our own here - * :( */ #define module_usb_serial_driver(__usb_driver, __serial_drivers) \ -static int __init usb_serial_driver_init(void) \ -{ \ - return usb_serial_register_drivers(&(__usb_driver), \ - (__serial_drivers)); \ -} \ -module_init(usb_serial_driver_init); \ -static void __exit usb_serial_driver_exit(void) \ -{ \ - return usb_serial_deregister_drivers(&(__usb_driver), \ - (__serial_drivers)); \ -} \ -module_exit(usb_serial_driver_exit); + module_driver(__usb_driver, usb_serial_register_drivers, \ + usb_serial_deregister_drivers, __serial_drivers) #endif /* __LINUX_USB_SERIAL_H */ -- cgit v1.2.3