USB: metro-usb: fix port-data memory leak
Fix port-data memory leak by moving port data allocation and
deallocation to port_probe and port_remove.
Since commit 0998d06310
(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 call to metrousb_clean (close) in shutdown was redundant.
Compile-only tested.
Cc: <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d7870af7e2
commit
50dde8686e
@ -271,52 +271,28 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void metrousb_shutdown(struct usb_serial *serial)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
dev_dbg(&serial->dev->dev, "%s\n", __func__);
|
||||
|
||||
/* Stop reading and writing on all ports. */
|
||||
for (i = 0; i < serial->num_ports; ++i) {
|
||||
/* Close any open urbs. */
|
||||
metrousb_cleanup(serial->port[i]);
|
||||
|
||||
/* Free memory. */
|
||||
kfree(usb_get_serial_port_data(serial->port[i]));
|
||||
usb_set_serial_port_data(serial->port[i], NULL);
|
||||
|
||||
dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n",
|
||||
__func__, serial->port[i]->number);
|
||||
}
|
||||
}
|
||||
|
||||
static int metrousb_startup(struct usb_serial *serial)
|
||||
static int metrousb_port_probe(struct usb_serial_port *port)
|
||||
{
|
||||
struct metrousb_private *metro_priv;
|
||||
struct usb_serial_port *port;
|
||||
int i = 0;
|
||||
|
||||
dev_dbg(&serial->dev->dev, "%s\n", __func__);
|
||||
|
||||
/* Loop through the serial ports setting up the private structures.
|
||||
* Currently we only use one port. */
|
||||
for (i = 0; i < serial->num_ports; ++i) {
|
||||
port = serial->port[i];
|
||||
|
||||
/* Declare memory. */
|
||||
metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL);
|
||||
metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL);
|
||||
if (!metro_priv)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Initialize memory. */
|
||||
spin_lock_init(&metro_priv->lock);
|
||||
|
||||
usb_set_serial_port_data(port, metro_priv);
|
||||
|
||||
dev_dbg(&serial->dev->dev, "%s - port number=%d\n ",
|
||||
__func__, port->number);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int metrousb_port_remove(struct usb_serial_port *port)
|
||||
{
|
||||
struct metrousb_private *metro_priv;
|
||||
|
||||
metro_priv = usb_get_serial_port_data(port);
|
||||
kfree(metro_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -414,8 +390,8 @@ static struct usb_serial_driver metrousb_device = {
|
||||
.close = metrousb_cleanup,
|
||||
.read_int_callback = metrousb_read_int_callback,
|
||||
.write_int_callback = metrousb_write_int_callback,
|
||||
.attach = metrousb_startup,
|
||||
.release = metrousb_shutdown,
|
||||
.port_probe = metrousb_port_probe,
|
||||
.port_remove = metrousb_port_remove,
|
||||
.throttle = metrousb_throttle,
|
||||
.unthrottle = metrousb_unthrottle,
|
||||
.tiocmget = metrousb_tiocmget,
|
||||
|
Loading…
Reference in New Issue
Block a user