diff options
| author | Pete Zaitcev <zaitcev@redhat.com> | 2006-06-21 18:00:45 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-07-12 19:03:21 -0400 |
| commit | 34f8e761724ecbfe46246f3faa4c7dbfc3555c26 (patch) | |
| tree | 46e6c7e63b34ed2990c7263aa3d980d814a98f47 | |
| parent | 92164c5dd1ade33f4e90b72e407910de6694de49 (diff) | |
[PATCH] USB: fix usb-serial leaks, oopses on disconnect
This fix addresses two issues:
- Unattached port structures were not freed
- My initial fix for crash when eventd runs a work in a freed port
did not go far enough
Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
| -rw-r--r-- | drivers/usb/serial/usb-serial.c | 23 |
1 files changed, 9 insertions, 14 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index b59a0536ea5c..5be79cf06fa9 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
| @@ -40,6 +40,8 @@ | |||
| 40 | #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/" | 40 | #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/" |
| 41 | #define DRIVER_DESC "USB Serial Driver core" | 41 | #define DRIVER_DESC "USB Serial Driver core" |
| 42 | 42 | ||
| 43 | static void port_free(struct usb_serial_port *port); | ||
| 44 | |||
| 43 | /* Driver structure we register with the USB core */ | 45 | /* Driver structure we register with the USB core */ |
| 44 | static struct usb_driver usb_serial_driver = { | 46 | static struct usb_driver usb_serial_driver = { |
| 45 | .name = "usbserial", | 47 | .name = "usbserial", |
| @@ -146,23 +148,10 @@ static void destroy_serial(struct kref *kref) | |||
| 146 | port = serial->port[i]; | 148 | port = serial->port[i]; |
| 147 | if (!port) | 149 | if (!port) |
| 148 | continue; | 150 | continue; |
| 149 | usb_kill_urb(port->read_urb); | 151 | port_free(port); |
| 150 | usb_free_urb(port->read_urb); | ||
| 151 | usb_kill_urb(port->write_urb); | ||
| 152 | usb_free_urb(port->write_urb); | ||
| 153 | usb_kill_urb(port->interrupt_in_urb); | ||
| 154 | usb_free_urb(port->interrupt_in_urb); | ||
| 155 | usb_kill_urb(port->interrupt_out_urb); | ||
| 156 | usb_free_urb(port->interrupt_out_urb); | ||
| 157 | kfree(port->bulk_in_buffer); | ||
| 158 | kfree(port->bulk_out_buffer); | ||
| 159 | kfree(port->interrupt_in_buffer); | ||
| 160 | kfree(port->interrupt_out_buffer); | ||
| 161 | } | 152 | } |
| 162 | } | 153 | } |
| 163 | 154 | ||
| 164 | flush_scheduled_work(); /* port->work */ | ||
| 165 | |||
| 166 | usb_put_dev(serial->dev); | 155 | usb_put_dev(serial->dev); |
| 167 | 156 | ||
| 168 | /* free up any memory that we allocated */ | 157 | /* free up any memory that we allocated */ |
| @@ -564,6 +553,11 @@ static void port_release(struct device *dev) | |||
| 564 | struct usb_serial_port *port = to_usb_serial_port(dev); | 553 | struct usb_serial_port *port = to_usb_serial_port(dev); |
| 565 | 554 | ||
| 566 | dbg ("%s - %s", __FUNCTION__, dev->bus_id); | 555 | dbg ("%s - %s", __FUNCTION__, dev->bus_id); |
| 556 | port_free(port); | ||
| 557 | } | ||
| 558 | |||
| 559 | static void port_free(struct usb_serial_port *port) | ||
| 560 | { | ||
| 567 | usb_kill_urb(port->read_urb); | 561 | usb_kill_urb(port->read_urb); |
| 568 | usb_free_urb(port->read_urb); | 562 | usb_free_urb(port->read_urb); |
| 569 | usb_kill_urb(port->write_urb); | 563 | usb_kill_urb(port->write_urb); |
| @@ -576,6 +570,7 @@ static void port_release(struct device *dev) | |||
| 576 | kfree(port->bulk_out_buffer); | 570 | kfree(port->bulk_out_buffer); |
| 577 | kfree(port->interrupt_in_buffer); | 571 | kfree(port->interrupt_in_buffer); |
| 578 | kfree(port->interrupt_out_buffer); | 572 | kfree(port->interrupt_out_buffer); |
| 573 | flush_scheduled_work(); /* port->work */ | ||
| 579 | kfree(port); | 574 | kfree(port); |
| 580 | } | 575 | } |
| 581 | 576 | ||
