diff options
author | Johan Hovold <jhovold@gmail.com> | 2012-10-17 13:34:59 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-28 10:56:12 -0700 |
commit | 8b399c3d6ae4591e28cc1bdab911ce7ccc7c2d5d (patch) | |
tree | ce38e9328c5be2c8dc972d039c144d69d5924da6 /drivers | |
parent | e8449931df18b2078327a7286c237d1d95db7715 (diff) |
USB: iuu_phoenix: fix port-data memory leak
commit 53636555b9190f88320d9d46cf142f8797895456 upstream.
Fix port-data memory leak by replacing attach and release with
port_probe and port_remove.
Since commit 0998d0631001288 (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.
Compile-only tested.
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/serial/iuu_phoenix.c | 70 |
1 files changed, 30 insertions, 40 deletions
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 22b1eb5040b7..c32f2a9afe01 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -80,64 +80,54 @@ struct iuu_private { u32 clk; }; - -static void iuu_free_buf(struct iuu_private *priv) +static int iuu_port_probe(struct usb_serial_port *port) { - kfree(priv->buf); - kfree(priv->dbgbuf); - kfree(priv->writebuf); -} + struct iuu_private *priv; + + priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); + if (!priv) + return -ENOMEM; -static int iuu_alloc_buf(struct iuu_private *priv) -{ priv->buf = kzalloc(256, GFP_KERNEL); - priv->dbgbuf = kzalloc(256, GFP_KERNEL); - priv->writebuf = kzalloc(256, GFP_KERNEL); - if (!priv->buf || !priv->dbgbuf || !priv->writebuf) { - iuu_free_buf(priv); - dbg("%s problem allocation buffer", __func__); + if (!priv->buf) { + kfree(priv); return -ENOMEM; } - dbg("%s - Privates buffers allocation success", __func__); - return 0; -} -static int iuu_startup(struct usb_serial *serial) -{ - struct iuu_private *priv; - priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); - dbg("%s- priv allocation success", __func__); - if (!priv) + priv->writebuf = kzalloc(256, GFP_KERNEL); + if (!priv->writebuf) { + kfree(priv->buf); + kfree(priv); return -ENOMEM; - if (iuu_alloc_buf(priv)) { + } + + priv->dbgbuf = kzalloc(256, GFP_KERNEL); + if (!priv->writebuf) { + kfree(priv->writebuf); + kfree(priv->buf); kfree(priv); return -ENOMEM; } + priv->vcc = vcc_default; spin_lock_init(&priv->lock); init_waitqueue_head(&priv->delta_msr_wait); - usb_set_serial_port_data(serial->port[0], priv); + + usb_set_serial_port_data(port, priv); + return 0; } -/* Release function */ -static void iuu_release(struct usb_serial *serial) +static int iuu_port_remove(struct usb_serial_port *port) { - struct usb_serial_port *port = serial->port[0]; struct iuu_private *priv = usb_get_serial_port_data(port); - if (!port) - return; - - if (priv) { - iuu_free_buf(priv); - dbg("%s - I will free all", __func__); - usb_set_serial_port_data(port, NULL); - dbg("%s - priv is not anymore in port structure", __func__); - kfree(priv); + kfree(priv->dbgbuf); + kfree(priv->writebuf); + kfree(priv->buf); + kfree(priv); - dbg("%s priv is now kfree", __func__); - } + return 0; } static int iuu_tiocmset(struct tty_struct *tty, @@ -1241,8 +1231,8 @@ static struct usb_serial_driver iuu_device = { .tiocmset = iuu_tiocmset, .set_termios = iuu_set_termios, .init_termios = iuu_init_termios, - .attach = iuu_startup, - .release = iuu_release, + .port_probe = iuu_port_probe, + .port_remove = iuu_port_remove, }; static struct usb_serial_driver * const serial_drivers[] = { |