diff options
author | Johan Hovold <jhovold@gmail.com> | 2012-10-17 07:34:55 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-17 16:47:57 -0400 |
commit | 5c1a0f418d8d985f3a62849bcac43fc5404cc592 (patch) | |
tree | 23dec95c6ba2a47abff6cdf5a91e2ee8d2a56804 /drivers/usb/serial | |
parent | 301a29da6e891e7eb95c843af0ecdbe86d01f723 (diff) |
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 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.
Cc: <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/cypress_m8.c | 75 |
1 files changed, 37 insertions, 38 deletions
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 1befce21e173..f0da1279c114 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
@@ -123,10 +123,10 @@ struct cypress_private { | |||
123 | }; | 123 | }; |
124 | 124 | ||
125 | /* function prototypes for the Cypress USB to serial device */ | 125 | /* function prototypes for the Cypress USB to serial device */ |
126 | static int cypress_earthmate_startup(struct usb_serial *serial); | 126 | static int cypress_earthmate_port_probe(struct usb_serial_port *port); |
127 | static int cypress_hidcom_startup(struct usb_serial *serial); | 127 | static int cypress_hidcom_port_probe(struct usb_serial_port *port); |
128 | static int cypress_ca42v2_startup(struct usb_serial *serial); | 128 | static int cypress_ca42v2_port_probe(struct usb_serial_port *port); |
129 | static void cypress_release(struct usb_serial *serial); | 129 | static int cypress_port_remove(struct usb_serial_port *port); |
130 | static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port); | 130 | static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port); |
131 | static void cypress_close(struct usb_serial_port *port); | 131 | static void cypress_close(struct usb_serial_port *port); |
132 | static void cypress_dtr_rts(struct usb_serial_port *port, int on); | 132 | static void cypress_dtr_rts(struct usb_serial_port *port, int on); |
@@ -156,8 +156,8 @@ static struct usb_serial_driver cypress_earthmate_device = { | |||
156 | .description = "DeLorme Earthmate USB", | 156 | .description = "DeLorme Earthmate USB", |
157 | .id_table = id_table_earthmate, | 157 | .id_table = id_table_earthmate, |
158 | .num_ports = 1, | 158 | .num_ports = 1, |
159 | .attach = cypress_earthmate_startup, | 159 | .port_probe = cypress_earthmate_port_probe, |
160 | .release = cypress_release, | 160 | .port_remove = cypress_port_remove, |
161 | .open = cypress_open, | 161 | .open = cypress_open, |
162 | .close = cypress_close, | 162 | .close = cypress_close, |
163 | .dtr_rts = cypress_dtr_rts, | 163 | .dtr_rts = cypress_dtr_rts, |
@@ -182,8 +182,8 @@ static struct usb_serial_driver cypress_hidcom_device = { | |||
182 | .description = "HID->COM RS232 Adapter", | 182 | .description = "HID->COM RS232 Adapter", |
183 | .id_table = id_table_cyphidcomrs232, | 183 | .id_table = id_table_cyphidcomrs232, |
184 | .num_ports = 1, | 184 | .num_ports = 1, |
185 | .attach = cypress_hidcom_startup, | 185 | .port_probe = cypress_hidcom_port_probe, |
186 | .release = cypress_release, | 186 | .port_remove = cypress_port_remove, |
187 | .open = cypress_open, | 187 | .open = cypress_open, |
188 | .close = cypress_close, | 188 | .close = cypress_close, |
189 | .dtr_rts = cypress_dtr_rts, | 189 | .dtr_rts = cypress_dtr_rts, |
@@ -208,8 +208,8 @@ static struct usb_serial_driver cypress_ca42v2_device = { | |||
208 | .description = "Nokia CA-42 V2 Adapter", | 208 | .description = "Nokia CA-42 V2 Adapter", |
209 | .id_table = id_table_nokiaca42v2, | 209 | .id_table = id_table_nokiaca42v2, |
210 | .num_ports = 1, | 210 | .num_ports = 1, |
211 | .attach = cypress_ca42v2_startup, | 211 | .port_probe = cypress_ca42v2_port_probe, |
212 | .release = cypress_release, | 212 | .port_remove = cypress_port_remove, |
213 | .open = cypress_open, | 213 | .open = cypress_open, |
214 | .close = cypress_close, | 214 | .close = cypress_close, |
215 | .dtr_rts = cypress_dtr_rts, | 215 | .dtr_rts = cypress_dtr_rts, |
@@ -438,10 +438,10 @@ static void cypress_set_dead(struct usb_serial_port *port) | |||
438 | *****************************************************************************/ | 438 | *****************************************************************************/ |
439 | 439 | ||
440 | 440 | ||
441 | static int generic_startup(struct usb_serial *serial) | 441 | static int cypress_generic_port_probe(struct usb_serial_port *port) |
442 | { | 442 | { |
443 | struct usb_serial *serial = port->serial; | ||
443 | struct cypress_private *priv; | 444 | struct cypress_private *priv; |
444 | struct usb_serial_port *port = serial->port[0]; | ||
445 | 445 | ||
446 | priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); | 446 | priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL); |
447 | if (!priv) | 447 | if (!priv) |
@@ -490,14 +490,16 @@ static int generic_startup(struct usb_serial *serial) | |||
490 | } | 490 | } |
491 | 491 | ||
492 | 492 | ||
493 | static int cypress_earthmate_startup(struct usb_serial *serial) | 493 | static int cypress_earthmate_port_probe(struct usb_serial_port *port) |
494 | { | 494 | { |
495 | struct usb_serial *serial = port->serial; | ||
495 | struct cypress_private *priv; | 496 | struct cypress_private *priv; |
496 | struct usb_serial_port *port = serial->port[0]; | 497 | int ret; |
497 | 498 | ||
498 | if (generic_startup(serial)) { | 499 | ret = cypress_generic_port_probe(port); |
500 | if (ret) { | ||
499 | dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); | 501 | dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); |
500 | return 1; | 502 | return ret; |
501 | } | 503 | } |
502 | 504 | ||
503 | priv = usb_get_serial_port_data(port); | 505 | priv = usb_get_serial_port_data(port); |
@@ -518,56 +520,53 @@ static int cypress_earthmate_startup(struct usb_serial *serial) | |||
518 | } | 520 | } |
519 | 521 | ||
520 | return 0; | 522 | return 0; |
521 | } /* cypress_earthmate_startup */ | 523 | } |
522 | |||
523 | 524 | ||
524 | static int cypress_hidcom_startup(struct usb_serial *serial) | 525 | static int cypress_hidcom_port_probe(struct usb_serial_port *port) |
525 | { | 526 | { |
526 | struct cypress_private *priv; | 527 | struct cypress_private *priv; |
527 | struct usb_serial_port *port = serial->port[0]; | 528 | int ret; |
528 | 529 | ||
529 | if (generic_startup(serial)) { | 530 | ret = cypress_generic_port_probe(port); |
531 | if (ret) { | ||
530 | dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); | 532 | dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); |
531 | return 1; | 533 | return ret; |
532 | } | 534 | } |
533 | 535 | ||
534 | priv = usb_get_serial_port_data(port); | 536 | priv = usb_get_serial_port_data(port); |
535 | priv->chiptype = CT_CYPHIDCOM; | 537 | priv->chiptype = CT_CYPHIDCOM; |
536 | 538 | ||
537 | return 0; | 539 | return 0; |
538 | } /* cypress_hidcom_startup */ | 540 | } |
539 | |||
540 | 541 | ||
541 | static int cypress_ca42v2_startup(struct usb_serial *serial) | 542 | static int cypress_ca42v2_port_probe(struct usb_serial_port *port) |
542 | { | 543 | { |
543 | struct cypress_private *priv; | 544 | struct cypress_private *priv; |
544 | struct usb_serial_port *port = serial->port[0]; | 545 | int ret; |
545 | 546 | ||
546 | if (generic_startup(serial)) { | 547 | ret = cypress_generic_port_probe(port); |
548 | if (ret) { | ||
547 | dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); | 549 | dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); |
548 | return 1; | 550 | return ret; |
549 | } | 551 | } |
550 | 552 | ||
551 | priv = usb_get_serial_port_data(port); | 553 | priv = usb_get_serial_port_data(port); |
552 | priv->chiptype = CT_CA42V2; | 554 | priv->chiptype = CT_CA42V2; |
553 | 555 | ||
554 | return 0; | 556 | return 0; |
555 | } /* cypress_ca42v2_startup */ | 557 | } |
556 | |||
557 | 558 | ||
558 | static void cypress_release(struct usb_serial *serial) | 559 | static int cypress_port_remove(struct usb_serial_port *port) |
559 | { | 560 | { |
560 | struct cypress_private *priv; | 561 | struct cypress_private *priv; |
561 | 562 | ||
562 | /* all open ports are closed at this point */ | 563 | priv = usb_get_serial_port_data(port); |
563 | priv = usb_get_serial_port_data(serial->port[0]); | ||
564 | 564 | ||
565 | if (priv) { | 565 | kfifo_free(&priv->write_fifo); |
566 | kfifo_free(&priv->write_fifo); | 566 | kfree(priv); |
567 | kfree(priv); | ||
568 | } | ||
569 | } | ||
570 | 567 | ||
568 | return 0; | ||
569 | } | ||
571 | 570 | ||
572 | static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) | 571 | static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port) |
573 | { | 572 | { |