[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>
This commit is contained in:
parent
ca85485c1f
commit
73e487fdb7
|
@ -202,7 +202,7 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
|
||||||
struct usb_serial *serial;
|
struct usb_serial *serial;
|
||||||
int retval = -ENODEV;
|
int retval = -ENODEV;
|
||||||
|
|
||||||
if (!port)
|
if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
|
||||||
return;
|
return;
|
||||||
serial = port->serial;
|
serial = port->serial;
|
||||||
|
|
||||||
|
@ -255,6 +255,14 @@ static struct console usbcons = {
|
||||||
.index = -1,
|
.index = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void usb_serial_console_disconnect(struct usb_serial *serial)
|
||||||
|
{
|
||||||
|
if (serial && serial->port && serial->port[0] && serial->port[0] == usbcons_info.port) {
|
||||||
|
usb_serial_console_exit();
|
||||||
|
usb_serial_put(serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void usb_serial_console_init (int serial_debug, int minor)
|
void usb_serial_console_init (int serial_debug, int minor)
|
||||||
{
|
{
|
||||||
debug = serial_debug;
|
debug = serial_debug;
|
||||||
|
@ -280,6 +288,11 @@ void usb_serial_console_init (int serial_debug, int minor)
|
||||||
|
|
||||||
void usb_serial_console_exit (void)
|
void usb_serial_console_exit (void)
|
||||||
{
|
{
|
||||||
unregister_console(&usbcons);
|
if (usbcons_info.port) {
|
||||||
|
unregister_console(&usbcons);
|
||||||
|
if (usbcons_info.port->open_count)
|
||||||
|
usbcons_info.port->open_count--;
|
||||||
|
usbcons_info.port = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,6 +168,11 @@ static void destroy_serial(struct kref *kref)
|
||||||
kfree (serial);
|
kfree (serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void usb_serial_put(struct usb_serial *serial)
|
||||||
|
{
|
||||||
|
kref_put(&serial->kref, destroy_serial);
|
||||||
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Driver tty interface functions
|
* Driver tty interface functions
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
@ -232,7 +237,7 @@ bailout_mutex_unlock:
|
||||||
port->open_count = 0;
|
port->open_count = 0;
|
||||||
mutex_unlock(&port->mutex);
|
mutex_unlock(&port->mutex);
|
||||||
bailout_kref_put:
|
bailout_kref_put:
|
||||||
kref_put(&serial->kref, destroy_serial);
|
usb_serial_put(serial);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +273,7 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&port->mutex);
|
mutex_unlock(&port->mutex);
|
||||||
kref_put(&port->serial->kref, destroy_serial);
|
usb_serial_put(port->serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
|
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
|
||||||
struct usb_serial_port *port = tty->driver_data;
|
struct usb_serial_port *port = tty->driver_data;
|
||||||
int retval = -EINVAL;
|
int retval = -EINVAL;
|
||||||
|
|
||||||
if (!port)
|
if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
|
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
|
||||||
begin += length;
|
begin += length;
|
||||||
length = 0;
|
length = 0;
|
||||||
}
|
}
|
||||||
kref_put(&serial->kref, destroy_serial);
|
usb_serial_put(serial);
|
||||||
}
|
}
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
done:
|
done:
|
||||||
|
@ -985,6 +990,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
|
||||||
struct device *dev = &interface->dev;
|
struct device *dev = &interface->dev;
|
||||||
struct usb_serial_port *port;
|
struct usb_serial_port *port;
|
||||||
|
|
||||||
|
usb_serial_console_disconnect(serial);
|
||||||
dbg ("%s", __FUNCTION__);
|
dbg ("%s", __FUNCTION__);
|
||||||
|
|
||||||
usb_set_intfdata (interface, NULL);
|
usb_set_intfdata (interface, NULL);
|
||||||
|
@ -996,7 +1002,7 @@ void usb_serial_disconnect(struct usb_interface *interface)
|
||||||
}
|
}
|
||||||
/* let the last holder of this object
|
/* let the last holder of this object
|
||||||
* cause it to be cleaned up */
|
* cause it to be cleaned up */
|
||||||
kref_put(&serial->kref, destroy_serial);
|
usb_serial_put(serial);
|
||||||
}
|
}
|
||||||
dev_info(dev, "device disconnected\n");
|
dev_info(dev, "device disconnected\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -248,13 +248,16 @@ extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit);
|
||||||
#ifdef CONFIG_USB_SERIAL_CONSOLE
|
#ifdef CONFIG_USB_SERIAL_CONSOLE
|
||||||
extern void usb_serial_console_init (int debug, int minor);
|
extern void usb_serial_console_init (int debug, int minor);
|
||||||
extern void usb_serial_console_exit (void);
|
extern void usb_serial_console_exit (void);
|
||||||
|
extern void usb_serial_console_disconnect(struct usb_serial *serial);
|
||||||
#else
|
#else
|
||||||
static inline void usb_serial_console_init (int debug, int minor) { }
|
static inline void usb_serial_console_init (int debug, int minor) { }
|
||||||
static inline void usb_serial_console_exit (void) { }
|
static inline void usb_serial_console_exit (void) { }
|
||||||
|
static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Functions needed by other parts of the usbserial core */
|
/* Functions needed by other parts of the usbserial core */
|
||||||
extern struct usb_serial *usb_serial_get_by_index (unsigned int minor);
|
extern struct usb_serial *usb_serial_get_by_index (unsigned int minor);
|
||||||
|
extern void usb_serial_put(struct usb_serial *serial);
|
||||||
extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp);
|
extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp);
|
||||||
extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count);
|
extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count);
|
||||||
extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);
|
extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);
|
||||||
|
|
Loading…
Reference in New Issue