Commit 99a6f73c authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

USB: kl5kusb105: fix port-data memory leak

Fix port-data memory leak by replacing attach and release with
port_probe and port_remove.

Since commit 0998d063 (device-core: Ensure drvdata = NULL when no
driver is bound) the port private data is no longer freed at release as
it is no longer accessible.

Note that the write waitqueue was initialised but never used.

Compile-only tested.

Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarJohan Hovold <jhovold@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 00361530
...@@ -60,8 +60,8 @@ ...@@ -60,8 +60,8 @@
/* /*
* Function prototypes * Function prototypes
*/ */
static int klsi_105_startup(struct usb_serial *serial); static int klsi_105_port_probe(struct usb_serial_port *port);
static void klsi_105_release(struct usb_serial *serial); static int klsi_105_port_remove(struct usb_serial_port *port);
static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port); static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port);
static void klsi_105_close(struct usb_serial_port *port); static void klsi_105_close(struct usb_serial_port *port);
static void klsi_105_set_termios(struct tty_struct *tty, static void klsi_105_set_termios(struct tty_struct *tty,
...@@ -99,8 +99,8 @@ static struct usb_serial_driver kl5kusb105d_device = { ...@@ -99,8 +99,8 @@ static struct usb_serial_driver kl5kusb105d_device = {
/*.break_ctl = klsi_105_break_ctl,*/ /*.break_ctl = klsi_105_break_ctl,*/
.tiocmget = klsi_105_tiocmget, .tiocmget = klsi_105_tiocmget,
.tiocmset = klsi_105_tiocmset, .tiocmset = klsi_105_tiocmset,
.attach = klsi_105_startup, .port_probe = klsi_105_port_probe,
.release = klsi_105_release, .port_remove = klsi_105_port_remove,
.throttle = usb_serial_generic_throttle, .throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle, .unthrottle = usb_serial_generic_unthrottle,
.process_read_urb = klsi_105_process_read_urb, .process_read_urb = klsi_105_process_read_urb,
...@@ -223,60 +223,40 @@ static int klsi_105_get_line_state(struct usb_serial_port *port, ...@@ -223,60 +223,40 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
* Driver's tty interface functions * Driver's tty interface functions
*/ */
static int klsi_105_startup(struct usb_serial *serial) static int klsi_105_port_probe(struct usb_serial_port *port)
{ {
struct klsi_105_private *priv; struct klsi_105_private *priv;
int i;
/* check if we support the product id (see keyspan.c) priv = kmalloc(sizeof(*priv), GFP_KERNEL);
* FIXME if (!priv)
*/ return -ENOMEM;
/* allocate the private data structure */ /* set initial values for control structures */
for (i = 0; i < serial->num_ports; i++) { priv->cfg.pktlen = 5;
priv = kmalloc(sizeof(struct klsi_105_private), priv->cfg.baudrate = kl5kusb105a_sio_b9600;
GFP_KERNEL); priv->cfg.databits = kl5kusb105a_dtb_8;
if (!priv) { priv->cfg.unknown1 = 0;
dev_dbg(&serial->interface->dev, priv->cfg.unknown2 = 1;
"%s - kmalloc for klsi_105_private failed.\n",
__func__);
i--;
goto err_cleanup;
}
/* set initial values for control structures */
priv->cfg.pktlen = 5;
priv->cfg.baudrate = kl5kusb105a_sio_b9600;
priv->cfg.databits = kl5kusb105a_dtb_8;
priv->cfg.unknown1 = 0;
priv->cfg.unknown2 = 1;
priv->line_state = 0; priv->line_state = 0;
usb_set_serial_port_data(serial->port[i], priv); spin_lock_init(&priv->lock);
spin_lock_init(&priv->lock); /* priv->termios is left uninitialized until port opening */
/* priv->termios is left uninitialized until port opening */ usb_set_serial_port_data(port, priv);
init_waitqueue_head(&serial->port[i]->write_wait);
}
return 0; return 0;
err_cleanup:
for (; i >= 0; i--) {
priv = usb_get_serial_port_data(serial->port[i]);
kfree(priv);
usb_set_serial_port_data(serial->port[i], NULL);
}
return -ENOMEM;
} }
static void klsi_105_release(struct usb_serial *serial) static int klsi_105_port_remove(struct usb_serial_port *port)
{ {
int i; struct klsi_105_private *priv;
priv = usb_get_serial_port_data(port);
kfree(priv);
for (i = 0; i < serial->num_ports; ++i) return 0;
kfree(usb_get_serial_port_data(serial->port[i]));
} }
static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment