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

Reply via email to