diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2006-04-25 01:46:17 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-21 18:04:09 -0400 |
commit | 73e487fdb75f8abf230968dbf73a3dc3b16808d3 (patch) | |
tree | 3e40b1888ec5529b2f3e9a2dfa5d5e6b47947b48 | |
parent | ca85485c1f482e6625f36aceb85eaaeff4b22d79 (diff) |
[PATCH] USB console: fix disconnection issues
Prevent sending further output to a USB-serial console after the dongle is
disconnected, take care not to leak kref.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/usb/serial/console.c | 17 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 16 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.h | 3 |
3 files changed, 29 insertions, 7 deletions
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index fc4a0f731d91..f3404e10afb4 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c | |||
@@ -202,7 +202,7 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun | |||
202 | struct usb_serial *serial; | 202 | struct usb_serial *serial; |
203 | int retval = -ENODEV; | 203 | int retval = -ENODEV; |
204 | 204 | ||
205 | if (!port) | 205 | if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) |
206 | return; | 206 | return; |
207 | serial = port->serial; | 207 | serial = port->serial; |
208 | 208 | ||
@@ -255,6 +255,14 @@ static struct console usbcons = { | |||
255 | .index = -1, | 255 | .index = -1, |
256 | }; | 256 | }; |
257 | 257 | ||
258 | void usb_serial_console_disconnect(struct usb_serial *serial) | ||
259 | { | ||
260 | if (serial && serial->port && serial->port[0] && serial->port[0] == usbcons_info.port) { | ||
261 | usb_serial_console_exit(); | ||
262 | usb_serial_put(serial); | ||
263 | } | ||
264 | } | ||
265 | |||
258 | void usb_serial_console_init (int serial_debug, int minor) | 266 | void usb_serial_console_init (int serial_debug, int minor) |
259 | { | 267 | { |
260 | debug = serial_debug; | 268 | debug = serial_debug; |
@@ -280,6 +288,11 @@ void usb_serial_console_init (int serial_debug, int minor) | |||
280 | 288 | ||
281 | void usb_serial_console_exit (void) | 289 | void usb_serial_console_exit (void) |
282 | { | 290 | { |
283 | unregister_console(&usbcons); | 291 | if (usbcons_info.port) { |
292 | unregister_console(&usbcons); | ||
293 | if (usbcons_info.port->open_count) | ||
294 | usbcons_info.port->open_count--; | ||
295 | usbcons_info.port = NULL; | ||
296 | } | ||
284 | } | 297 | } |
285 | 298 | ||
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index de9111d97a58..92200f05b531 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -168,6 +168,11 @@ static void destroy_serial(struct kref *kref) | |||
168 | kfree (serial); | 168 | kfree (serial); |
169 | } | 169 | } |
170 | 170 | ||
171 | void usb_serial_put(struct usb_serial *serial) | ||
172 | { | ||
173 | kref_put(&serial->kref, destroy_serial); | ||
174 | } | ||
175 | |||
171 | /***************************************************************************** | 176 | /***************************************************************************** |
172 | * Driver tty interface functions | 177 | * Driver tty interface functions |
173 | *****************************************************************************/ | 178 | *****************************************************************************/ |
@@ -232,7 +237,7 @@ bailout_mutex_unlock: | |||
232 | port->open_count = 0; | 237 | port->open_count = 0; |
233 | mutex_unlock(&port->mutex); | 238 | mutex_unlock(&port->mutex); |
234 | bailout_kref_put: | 239 | bailout_kref_put: |
235 | kref_put(&serial->kref, destroy_serial); | 240 | usb_serial_put(serial); |
236 | return retval; | 241 | return retval; |
237 | } | 242 | } |
238 | 243 | ||
@@ -268,7 +273,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp) | |||
268 | } | 273 | } |
269 | 274 | ||
270 | mutex_unlock(&port->mutex); | 275 | mutex_unlock(&port->mutex); |
271 | kref_put(&port->serial->kref, destroy_serial); | 276 | usb_serial_put(port->serial); |
272 | } | 277 | } |
273 | 278 | ||
274 | static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) | 279 | static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) |
@@ -276,7 +281,7 @@ static int serial_write (struct tty_struct * tty, const unsigned char *buf, int | |||
276 | struct usb_serial_port *port = tty->driver_data; | 281 | struct usb_serial_port *port = tty->driver_data; |
277 | int retval = -EINVAL; | 282 | int retval = -EINVAL; |
278 | 283 | ||
279 | if (!port) | 284 | if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED) |
280 | goto exit; | 285 | goto exit; |
281 | 286 | ||
282 | dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); | 287 | dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count); |
@@ -473,7 +478,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int | |||
473 | begin += length; | 478 | begin += length; |
474 | length = 0; | 479 | length = 0; |
475 | } | 480 | } |
476 | kref_put(&serial->kref, destroy_serial); | 481 | usb_serial_put(serial); |
477 | } | 482 | } |
478 | *eof = 1; | 483 | *eof = 1; |
479 | done: | 484 | done: |
@@ -985,6 +990,7 @@ void usb_serial_disconnect(struct usb_interface *interface) | |||
985 | struct device *dev = &interface->dev; | 990 | struct device *dev = &interface->dev; |
986 | struct usb_serial_port *port; | 991 | struct usb_serial_port *port; |
987 | 992 | ||
993 | usb_serial_console_disconnect(serial); | ||
988 | dbg ("%s", __FUNCTION__); | 994 | dbg ("%s", __FUNCTION__); |
989 | 995 | ||
990 | usb_set_intfdata (interface, NULL); | 996 | usb_set_intfdata (interface, NULL); |
@@ -996,7 +1002,7 @@ void usb_serial_disconnect(struct usb_interface *interface) | |||
996 | } | 1002 | } |
997 | /* let the last holder of this object | 1003 | /* let the last holder of this object |
998 | * cause it to be cleaned up */ | 1004 | * cause it to be cleaned up */ |
999 | kref_put(&serial->kref, destroy_serial); | 1005 | usb_serial_put(serial); |
1000 | } | 1006 | } |
1001 | dev_info(dev, "device disconnected\n"); | 1007 | dev_info(dev, "device disconnected\n"); |
1002 | } | 1008 | } |
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h index dc89d8710460..c07ece3fef1d 100644 --- a/drivers/usb/serial/usb-serial.h +++ b/drivers/usb/serial/usb-serial.h | |||
@@ -248,13 +248,16 @@ extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit); | |||
248 | #ifdef CONFIG_USB_SERIAL_CONSOLE | 248 | #ifdef CONFIG_USB_SERIAL_CONSOLE |
249 | extern void usb_serial_console_init (int debug, int minor); | 249 | extern void usb_serial_console_init (int debug, int minor); |
250 | extern void usb_serial_console_exit (void); | 250 | extern void usb_serial_console_exit (void); |
251 | extern void usb_serial_console_disconnect(struct usb_serial *serial); | ||
251 | #else | 252 | #else |
252 | static inline void usb_serial_console_init (int debug, int minor) { } | 253 | static inline void usb_serial_console_init (int debug, int minor) { } |
253 | static inline void usb_serial_console_exit (void) { } | 254 | static inline void usb_serial_console_exit (void) { } |
255 | static inline void usb_serial_console_disconnect(struct usb_serial *serial) {} | ||
254 | #endif | 256 | #endif |
255 | 257 | ||
256 | /* Functions needed by other parts of the usbserial core */ | 258 | /* Functions needed by other parts of the usbserial core */ |
257 | extern struct usb_serial *usb_serial_get_by_index (unsigned int minor); | 259 | extern struct usb_serial *usb_serial_get_by_index (unsigned int minor); |
260 | extern void usb_serial_put(struct usb_serial *serial); | ||
258 | extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); | 261 | extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); |
259 | extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count); | 262 | extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count); |
260 | extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); | 263 | extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); |