aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2006-04-25 01:46:17 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-06-21 18:04:09 -0400
commit73e487fdb75f8abf230968dbf73a3dc3b16808d3 (patch)
tree3e40b1888ec5529b2f3e9a2dfa5d5e6b47947b48
parentca85485c1f482e6625f36aceb85eaaeff4b22d79 (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.c17
-rw-r--r--drivers/usb/serial/usb-serial.c16
-rw-r--r--drivers/usb/serial/usb-serial.h3
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
258void 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
258void usb_serial_console_init (int serial_debug, int minor) 266void 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
281void usb_serial_console_exit (void) 289void 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
171void 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);
234bailout_kref_put: 239bailout_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
274static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count) 279static 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;
479done: 484done:
@@ -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
249extern void usb_serial_console_init (int debug, int minor); 249extern void usb_serial_console_init (int debug, int minor);
250extern void usb_serial_console_exit (void); 250extern void usb_serial_console_exit (void);
251extern void usb_serial_console_disconnect(struct usb_serial *serial);
251#else 252#else
252static inline void usb_serial_console_init (int debug, int minor) { } 253static inline void usb_serial_console_init (int debug, int minor) { }
253static inline void usb_serial_console_exit (void) { } 254static inline void usb_serial_console_exit (void) { }
255static 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 */
257extern struct usb_serial *usb_serial_get_by_index (unsigned int minor); 259extern struct usb_serial *usb_serial_get_by_index (unsigned int minor);
260extern void usb_serial_put(struct usb_serial *serial);
258extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); 261extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp);
259extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count); 262extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count);
260extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); 263extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);