USB: cypress_m8: fix port-data memory leak

Fix port-data memory leak by replacing attach and release with
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.

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:
Johan Hovold 2012-10-17 13:34:55 +02:00 committed by Greg Kroah-Hartman
parent 301a29da6e
commit 5c1a0f418d

View File

@ -123,10 +123,10 @@ struct cypress_private {
}; };
/* function prototypes for the Cypress USB to serial device */ /* function prototypes for the Cypress USB to serial device */
static int cypress_earthmate_startup(struct usb_serial *serial); static int cypress_earthmate_port_probe(struct usb_serial_port *port);
static int cypress_hidcom_startup(struct usb_serial *serial); static int cypress_hidcom_port_probe(struct usb_serial_port *port);
static int cypress_ca42v2_startup(struct usb_serial *serial); static int cypress_ca42v2_port_probe(struct usb_serial_port *port);
static void cypress_release(struct usb_serial *serial); static int cypress_port_remove(struct usb_serial_port *port);
static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port); static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port);
static void cypress_close(struct usb_serial_port *port); static void cypress_close(struct usb_serial_port *port);
static void cypress_dtr_rts(struct usb_serial_port *port, int on); static void cypress_dtr_rts(struct usb_serial_port *port, int on);
@ -156,8 +156,8 @@ static struct usb_serial_driver cypress_earthmate_device = {
.description = "DeLorme Earthmate USB", .description = "DeLorme Earthmate USB",
.id_table = id_table_earthmate, .id_table = id_table_earthmate,
.num_ports = 1, .num_ports = 1,
.attach = cypress_earthmate_startup, .port_probe = cypress_earthmate_port_probe,
.release = cypress_release, .port_remove = cypress_port_remove,
.open = cypress_open, .open = cypress_open,
.close = cypress_close, .close = cypress_close,
.dtr_rts = cypress_dtr_rts, .dtr_rts = cypress_dtr_rts,
@ -182,8 +182,8 @@ static struct usb_serial_driver cypress_hidcom_device = {
.description = "HID->COM RS232 Adapter", .description = "HID->COM RS232 Adapter",
.id_table = id_table_cyphidcomrs232, .id_table = id_table_cyphidcomrs232,
.num_ports = 1, .num_ports = 1,
.attach = cypress_hidcom_startup, .port_probe = cypress_hidcom_port_probe,
.release = cypress_release, .port_remove = cypress_port_remove,
.open = cypress_open, .open = cypress_open,
.close = cypress_close, .close = cypress_close,
.dtr_rts = cypress_dtr_rts, .dtr_rts = cypress_dtr_rts,
@ -208,8 +208,8 @@ static struct usb_serial_driver cypress_ca42v2_device = {
.description = "Nokia CA-42 V2 Adapter", .description = "Nokia CA-42 V2 Adapter",
.id_table = id_table_nokiaca42v2, .id_table = id_table_nokiaca42v2,
.num_ports = 1, .num_ports = 1,
.attach = cypress_ca42v2_startup, .port_probe = cypress_ca42v2_port_probe,
.release = cypress_release, .port_remove = cypress_port_remove,
.open = cypress_open, .open = cypress_open,
.close = cypress_close, .close = cypress_close,
.dtr_rts = cypress_dtr_rts, .dtr_rts = cypress_dtr_rts,
@ -438,10 +438,10 @@ static void cypress_set_dead(struct usb_serial_port *port)
*****************************************************************************/ *****************************************************************************/
static int generic_startup(struct usb_serial *serial) static int cypress_generic_port_probe(struct usb_serial_port *port)
{ {
struct usb_serial *serial = port->serial;
struct cypress_private *priv; struct cypress_private *priv;
struct usb_serial_port *port = serial->port[0];
priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
if (!priv) if (!priv)
@ -490,14 +490,16 @@ static int generic_startup(struct usb_serial *serial)
} }
static int cypress_earthmate_startup(struct usb_serial *serial) static int cypress_earthmate_port_probe(struct usb_serial_port *port)
{ {
struct usb_serial *serial = port->serial;
struct cypress_private *priv; struct cypress_private *priv;
struct usb_serial_port *port = serial->port[0]; int ret;
if (generic_startup(serial)) { ret = cypress_generic_port_probe(port);
if (ret) {
dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
return 1; return ret;
} }
priv = usb_get_serial_port_data(port); priv = usb_get_serial_port_data(port);
@ -518,57 +520,54 @@ static int cypress_earthmate_startup(struct usb_serial *serial)
} }
return 0; return 0;
} /* cypress_earthmate_startup */ }
static int cypress_hidcom_port_probe(struct usb_serial_port *port)
static int cypress_hidcom_startup(struct usb_serial *serial)
{ {
struct cypress_private *priv; struct cypress_private *priv;
struct usb_serial_port *port = serial->port[0]; int ret;
if (generic_startup(serial)) { ret = cypress_generic_port_probe(port);
if (ret) {
dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
return 1; return ret;
} }
priv = usb_get_serial_port_data(port); priv = usb_get_serial_port_data(port);
priv->chiptype = CT_CYPHIDCOM; priv->chiptype = CT_CYPHIDCOM;
return 0; return 0;
} /* cypress_hidcom_startup */ }
static int cypress_ca42v2_port_probe(struct usb_serial_port *port)
static int cypress_ca42v2_startup(struct usb_serial *serial)
{ {
struct cypress_private *priv; struct cypress_private *priv;
struct usb_serial_port *port = serial->port[0]; int ret;
if (generic_startup(serial)) { ret = cypress_generic_port_probe(port);
if (ret) {
dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
return 1; return ret;
} }
priv = usb_get_serial_port_data(port); priv = usb_get_serial_port_data(port);
priv->chiptype = CT_CA42V2; priv->chiptype = CT_CA42V2;
return 0; return 0;
} /* cypress_ca42v2_startup */ }
static int cypress_port_remove(struct usb_serial_port *port)
static void cypress_release(struct usb_serial *serial)
{ {
struct cypress_private *priv; struct cypress_private *priv;
/* all open ports are closed at this point */ priv = usb_get_serial_port_data(port);
priv = usb_get_serial_port_data(serial->port[0]);
if (priv) { kfifo_free(&priv->write_fifo);
kfifo_free(&priv->write_fifo); kfree(priv);
kfree(priv);
} return 0;
} }
static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port)
{ {
struct cypress_private *priv = usb_get_serial_port_data(port); struct cypress_private *priv = usb_get_serial_port_data(port);