ChangeSet 1.1123.18.9, 2003/08/13 10:08:22-07:00, [EMAIL PROTECTED]
[PATCH] USB: fix usb serial port release problem by untieing it from the usb_serial
structure.
This fixes the kobject messages when disconnecting a usb serial device that
people have been complaining about.
drivers/usb/serial/usb-serial.c | 153 ++++++++++++++++++++++++----------------
drivers/usb/serial/usb-serial.h | 3
2 files changed, 95 insertions(+), 61 deletions(-)
diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
--- a/drivers/usb/serial/usb-serial.c Fri Aug 15 10:46:59 2003
+++ b/drivers/usb/serial/usb-serial.c Fri Aug 15 10:46:59 2003
@@ -466,7 +466,7 @@
/* set up our port structure making the tty driver remember our port object,
and us it */
portNumber = tty->index - serial->minor;
- port = &serial->port[portNumber];
+ port = serial->port[portNumber];
tty->driver_data = port;
port->tty = tty;
@@ -863,13 +863,13 @@
struct usb_serial_port *port;
int i;
- dbg ("%s", __FUNCTION__);
+ dbg ("%s - %s", __FUNCTION__, kobj->name);
serial = to_usb_serial(kobj);
/* fail all future close/read/write/ioctl/etc calls */
for (i = 0; i < serial->num_ports; ++i) {
- port = &serial->port[i];
+ port = serial->port[i];
if (port->tty != NULL) {
port->tty->driver_data = NULL;
while (port->open_count > 0) {
@@ -881,41 +881,41 @@
serial_shutdown (serial);
+ /* return the minor range that this device had */
+ return_serial(serial);
+
for (i = 0; i < serial->num_ports; ++i)
- device_unregister(&serial->port[i].dev);
+ serial->port[i]->open_count = 0;
+ /* the ports are cleaned up and released in port_release() */
for (i = 0; i < serial->num_ports; ++i)
- serial->port[i].open_count = 0;
+ device_unregister(&serial->port[i]->dev);
- for (i = 0; i < serial->num_bulk_in; ++i) {
- port = &serial->port[i];
- if (port->read_urb) {
- usb_unlink_urb (port->read_urb);
- usb_free_urb (port->read_urb);
- }
- if (port->bulk_in_buffer)
- kfree (port->bulk_in_buffer);
- }
- for (i = 0; i < serial->num_bulk_out; ++i) {
- port = &serial->port[i];
- if (port->write_urb) {
- usb_unlink_urb (port->write_urb);
- usb_free_urb (port->write_urb);
- }
- if (port->bulk_out_buffer)
- kfree (port->bulk_out_buffer);
- }
- for (i = 0; i < serial->num_interrupt_in; ++i) {
- port = &serial->port[i];
- if (port->interrupt_in_urb) {
- usb_unlink_urb (port->interrupt_in_urb);
- usb_free_urb (port->interrupt_in_urb);
+ /* If this is a "fake" port, we have to clean it up here, as it will
+ * not get cleaned up in port_release() as it was never registered with
+ * the driver core */
+ if (serial->num_ports < serial->num_port_pointers) {
+ for (i = serial->num_ports; i < serial->num_port_pointers; ++i) {
+ port = serial->port[i];
+ if (!port)
+ continue;
+ if (port->read_urb) {
+ usb_unlink_urb(port->read_urb);
+ usb_free_urb(port->read_urb);
+ }
+ if (port->write_urb) {
+ usb_unlink_urb(port->write_urb);
+ usb_free_urb(port->write_urb);
+ }
+ if (port->interrupt_in_urb) {
+ usb_unlink_urb(port->interrupt_in_urb);
+ usb_free_urb(port->interrupt_in_urb);
+ }
+ kfree(port->bulk_in_buffer);
+ kfree(port->bulk_out_buffer);
+ kfree(port->interrupt_in_buffer);
}
- if (port->interrupt_in_buffer)
- kfree (port->interrupt_in_buffer);
}
- /* return the minor range that this device had */
- return_serial (serial);
usb_put_dev(serial->dev);
@@ -927,6 +927,29 @@
.release = destroy_serial,
};
+static void port_release(struct device *dev)
+{
+ struct usb_serial_port *port = to_usb_serial_port(dev);
+
+ dbg ("%s - %s", __FUNCTION__, dev->bus_id);
+ if (port->read_urb) {
+ usb_unlink_urb(port->read_urb);
+ usb_free_urb(port->read_urb);
+ }
+ if (port->write_urb) {
+ usb_unlink_urb(port->write_urb);
+ usb_free_urb(port->write_urb);
+ }
+ if (port->interrupt_in_urb) {
+ usb_unlink_urb(port->interrupt_in_urb);
+ usb_free_urb(port->interrupt_in_urb);
+ }
+ kfree(port->bulk_in_buffer);
+ kfree(port->bulk_out_buffer);
+ kfree(port->interrupt_in_buffer);
+ kfree(port);
+}
+
static struct usb_serial * create_serial (struct usb_device *dev,
struct usb_interface *interface,
struct usb_serial_device_type *type)
@@ -1124,10 +1147,29 @@
serial->num_bulk_out = num_bulk_out;
serial->num_interrupt_in = num_interrupt_in;
+ /* create our ports, we need as many as the max endpoints */
+ /* we don't use num_ports here cauz some devices have more endpoint pairs than
ports */
+ max_endpoints = max(num_bulk_in, num_bulk_out);
+ max_endpoints = max(max_endpoints, num_interrupt_in);
+ max_endpoints = max(max_endpoints, (int)serial->num_ports);
+ serial->num_port_pointers = max_endpoints;
+ dbg("%s - setting up %d port structures for this device", __FUNCTION__,
max_endpoints);
+ for (i = 0; i < max_endpoints; ++i) {
+ port = kmalloc(sizeof(struct usb_serial_port), GFP_KERNEL);
+ if (!port)
+ goto probe_error;
+ memset(port, 0x00, sizeof(struct usb_serial_port));
+ port->number = i + serial->minor;
+ port->serial = serial;
+ port->magic = USB_SERIAL_PORT_MAGIC;
+ INIT_WORK(&port->work, usb_serial_port_softint, port);
+ serial->port[i] = port;
+ }
+
/* set up the endpoint information */
for (i = 0; i < num_bulk_in; ++i) {
endpoint = bulk_in_endpoint[i];
- port = &serial->port[i];
+ port = serial->port[i];
port->read_urb = usb_alloc_urb (0, GFP_KERNEL);
if (!port->read_urb) {
dev_err(&interface->dev, "No free urbs available\n");
@@ -1152,7 +1194,7 @@
for (i = 0; i < num_bulk_out; ++i) {
endpoint = bulk_out_endpoint[i];
- port = &serial->port[i];
+ port = serial->port[i];
port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->write_urb) {
dev_err(&interface->dev, "No free urbs available\n");
@@ -1178,7 +1220,7 @@
for (i = 0; i < num_interrupt_in; ++i) {
endpoint = interrupt_in_endpoint[i];
- port = &serial->port[i];
+ port = serial->port[i];
port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->interrupt_in_urb) {
dev_err(&interface->dev, "No free urbs available\n");
@@ -1199,20 +1241,6 @@
endpoint->bInterval);
}
- /* initialize some parts of the port structures */
- /* we don't use num_ports here cauz some devices have more endpoint pairs than
ports */
- max_endpoints = max(num_bulk_in, num_bulk_out);
- max_endpoints = max(max_endpoints, num_interrupt_in);
- max_endpoints = max(max_endpoints, (int)serial->num_ports);
- dbg("%s - setting up %d port structures for this device", __FUNCTION__,
max_endpoints);
- for (i = 0; i < max_endpoints; ++i) {
- port = &serial->port[i];
- port->number = i + serial->minor;
- port->serial = serial;
- port->magic = USB_SERIAL_PORT_MAGIC;
- INIT_WORK(&port->work, usb_serial_port_softint, port);
- }
-
/* if this device type has an attach function, call it */
if (type->attach) {
if (!try_module_get(type->owner)) {
@@ -1232,10 +1260,11 @@
/* register all of the individual ports with the driver core */
for (i = 0; i < num_ports; ++i) {
- port = &serial->port[i];
+ port = serial->port[i];
port->dev.parent = &serial->dev->dev;
port->dev.driver = NULL;
port->dev.bus = &usb_serial_bus_type;
+ port->dev.release = &port_release;
snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d",
port->number);
dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id);
@@ -1249,34 +1278,38 @@
usb_set_intfdata (interface, serial);
return 0;
-
probe_error:
for (i = 0; i < num_bulk_in; ++i) {
- port = &serial->port[i];
+ port = serial->port[i];
+ if (!port)
+ continue;
if (port->read_urb)
usb_free_urb (port->read_urb);
- if (port->bulk_in_buffer)
- kfree (port->bulk_in_buffer);
+ kfree(port->bulk_in_buffer);
}
for (i = 0; i < num_bulk_out; ++i) {
- port = &serial->port[i];
+ port = serial->port[i];
+ if (!port)
+ continue;
if (port->write_urb)
usb_free_urb (port->write_urb);
- if (port->bulk_out_buffer)
- kfree (port->bulk_out_buffer);
+ kfree(port->bulk_out_buffer);
}
for (i = 0; i < num_interrupt_in; ++i) {
- port = &serial->port[i];
+ port = serial->port[i];
+ if (!port)
+ continue;
if (port->interrupt_in_urb)
usb_free_urb (port->interrupt_in_urb);
- if (port->interrupt_in_buffer)
- kfree (port->interrupt_in_buffer);
+ kfree(port->interrupt_in_buffer);
}
/* return the minor range that this device had */
return_serial (serial);
/* free up any memory that we allocated */
+ for (i = 0; i < serial->num_port_pointers; ++i)
+ kfree(serial->port[i]);
kfree (serial);
return -EIO;
}
diff -Nru a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
--- a/drivers/usb/serial/usb-serial.h Fri Aug 15 10:46:59 2003
+++ b/drivers/usb/serial/usb-serial.h Fri Aug 15 10:46:59 2003
@@ -156,12 +156,13 @@
struct usb_interface * interface;
unsigned char minor;
unsigned char num_ports;
+ unsigned char num_port_pointers;
char num_interrupt_in;
char num_bulk_in;
char num_bulk_out;
__u16 vendor;
__u16 product;
- struct usb_serial_port port[MAX_NUM_PORTS];
+ struct usb_serial_port * port[MAX_NUM_PORTS];
struct kobject kobj;
void * private;
};
-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel