diff options
author | Johan Hovold <jhovold@gmail.com> | 2012-10-25 04:28:59 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-25 12:36:57 -0400 |
commit | 50dde8686eec41bf3d7cbec7a6f76c073ab01903 (patch) | |
tree | 6353829484f34cc1269d55e57ab32eb002ead831 /drivers/usb | |
parent | d7870af7e2e3a91b462075ec1ca669b482215187 (diff) |
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 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.
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>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/metro-usb.c | 50 |
1 files changed, 13 insertions, 37 deletions
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 0b257ddffbdb..25cb97c25ad4 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c | |||
@@ -271,51 +271,27 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr | |||
271 | return retval; | 271 | return retval; |
272 | } | 272 | } |
273 | 273 | ||
274 | static void metrousb_shutdown(struct usb_serial *serial) | 274 | static int metrousb_port_probe(struct usb_serial_port *port) |
275 | { | 275 | { |
276 | int i = 0; | 276 | struct metrousb_private *metro_priv; |
277 | 277 | ||
278 | dev_dbg(&serial->dev->dev, "%s\n", __func__); | 278 | metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL); |
279 | if (!metro_priv) | ||
280 | return -ENOMEM; | ||
279 | 281 | ||
280 | /* Stop reading and writing on all ports. */ | 282 | spin_lock_init(&metro_priv->lock); |
281 | for (i = 0; i < serial->num_ports; ++i) { | ||
282 | /* Close any open urbs. */ | ||
283 | metrousb_cleanup(serial->port[i]); | ||
284 | 283 | ||
285 | /* Free memory. */ | 284 | usb_set_serial_port_data(port, metro_priv); |
286 | kfree(usb_get_serial_port_data(serial->port[i])); | ||
287 | usb_set_serial_port_data(serial->port[i], NULL); | ||
288 | 285 | ||
289 | dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n", | 286 | return 0; |
290 | __func__, serial->port[i]->number); | ||
291 | } | ||
292 | } | 287 | } |
293 | 288 | ||
294 | static int metrousb_startup(struct usb_serial *serial) | 289 | static int metrousb_port_remove(struct usb_serial_port *port) |
295 | { | 290 | { |
296 | struct metrousb_private *metro_priv; | 291 | struct metrousb_private *metro_priv; |
297 | struct usb_serial_port *port; | ||
298 | int i = 0; | ||
299 | |||
300 | dev_dbg(&serial->dev->dev, "%s\n", __func__); | ||
301 | 292 | ||
302 | /* Loop through the serial ports setting up the private structures. | 293 | metro_priv = usb_get_serial_port_data(port); |
303 | * Currently we only use one port. */ | 294 | kfree(metro_priv); |
304 | for (i = 0; i < serial->num_ports; ++i) { | ||
305 | port = serial->port[i]; | ||
306 | |||
307 | /* Declare memory. */ | ||
308 | metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL); | ||
309 | if (!metro_priv) | ||
310 | return -ENOMEM; | ||
311 | |||
312 | /* Initialize memory. */ | ||
313 | spin_lock_init(&metro_priv->lock); | ||
314 | usb_set_serial_port_data(port, metro_priv); | ||
315 | |||
316 | dev_dbg(&serial->dev->dev, "%s - port number=%d\n ", | ||
317 | __func__, port->number); | ||
318 | } | ||
319 | 295 | ||
320 | return 0; | 296 | return 0; |
321 | } | 297 | } |
@@ -414,8 +390,8 @@ static struct usb_serial_driver metrousb_device = { | |||
414 | .close = metrousb_cleanup, | 390 | .close = metrousb_cleanup, |
415 | .read_int_callback = metrousb_read_int_callback, | 391 | .read_int_callback = metrousb_read_int_callback, |
416 | .write_int_callback = metrousb_write_int_callback, | 392 | .write_int_callback = metrousb_write_int_callback, |
417 | .attach = metrousb_startup, | 393 | .port_probe = metrousb_port_probe, |
418 | .release = metrousb_shutdown, | 394 | .port_remove = metrousb_port_remove, |
419 | .throttle = metrousb_throttle, | 395 | .throttle = metrousb_throttle, |
420 | .unthrottle = metrousb_unthrottle, | 396 | .unthrottle = metrousb_unthrottle, |
421 | .tiocmget = metrousb_tiocmget, | 397 | .tiocmget = metrousb_tiocmget, |