Hi,

Here's a patch for usb-serial against 2.3.99-pre4-3 that hopefully takes
care of the module reference potential race condition bug, and also adds
better support for devfs. The tty_driver is now only registered with the
tty layer when a device is found. This makes the devfs nodes only show
up when a device is actually present (instead of 16 empty device nodes
which was the way the code was working before this patch, which is kinda
against the whole devfs thing.)

For any users that are using the pilot-link package with a HandSpring
Visor, you need to have a patch to the pilot-xfer program in order for
it to work properly with devfs (there is a filename size bug). If anyone
wants the patch, please let me know.

thanks,

greg k-h
[EMAIL PROTECTED]
diff -Naur -X dontdiff linux-2.3.99-pre4-3/drivers/usb/serial/ftdi_sio.c 
linux-2.3.99-pre4-3-greg/drivers/usb/serial/ftdi_sio.c
--- linux-2.3.99-pre4-3/drivers/usb/serial/ftdi_sio.c   Mon Apr  3 06:04:10 2000
+++ linux-2.3.99-pre4-3-greg/drivers/usb/serial/ftdi_sio.c      Mon Apr  3 06:01:24 
+2000
@@ -608,9 +608,9 @@
 static int set_termios(struct usb_serial_port *port, struct termios *old_termios, int 
opt)
 { /* set_termios */
        struct tty_struct *tty = port->tty;
+#ifdef  NOT_IMPLEMENTED_YET
        int retval;
 
-#ifdef  NOT_IMPLEMENTED_YET
        retval = tty_check_change(tty);
        if (retval)
                return retval;
diff -Naur -X dontdiff linux-2.3.99-pre4-3/drivers/usb/serial/usb-serial.h 
linux-2.3.99-pre4-3-greg/drivers/usb/serial/usb-serial.h
--- linux-2.3.99-pre4-3/drivers/usb/serial/usb-serial.h Mon Apr  3 06:04:10 2000
+++ linux-2.3.99-pre4-3-greg/drivers/usb/serial/usb-serial.h    Mon Apr  3 05:34:02 
+2000
@@ -34,7 +34,7 @@
 struct usb_serial_port {
        int                     magic;
        struct usb_serial       *serial;        /* pointer back to the owner of this 
port */
-       struct tty_struct *     tty;            /* the coresponding tty for this 
device */
+       struct tty_struct *     tty;            /* the coresponding tty for this port 
+*/
        unsigned char           minor;
        unsigned char           number;
        char                    active;         /* someone has this device open */
@@ -56,8 +56,9 @@
 struct usb_serial {
        int                             magic;
        struct usb_device *             dev;
-       struct usb_serial_device_type * type;
-       unsigned char                   minor;
+       struct usb_serial_device_type * type;                   /* the type of usb 
+serial device this is */
+       struct tty_driver *             tty_driver;             /* the tty_driver for 
+this device */
+       unsigned char                   minor;                  /* the starting minor 
+number for this device */
        unsigned char                   num_ports;              /* the number of ports 
this device has */
        char                            num_interrupt_in;       /* number of interrupt 
in endpoints we have */
        char                            num_bulk_in;            /* number of bulk in 
endpoints we have */
diff -Naur -X dontdiff linux-2.3.99-pre4-3/drivers/usb/serial/usbserial.c 
linux-2.3.99-pre4-3-greg/drivers/usb/serial/usbserial.c
--- linux-2.3.99-pre4-3/drivers/usb/serial/usbserial.c  Mon Apr  3 06:04:10 2000
+++ linux-2.3.99-pre4-3-greg/drivers/usb/serial/usbserial.c     Mon Apr  3 06:40:34 
+2000
@@ -14,6 +14,11 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (04/03/2000) gkh
+ *     Changed the probe process to remove the module unload races.
+ *     Changed where the tty layer gets initialized to have devfs work nicer.
+ *     Added initial devfs support.
+ *
  * (03/26/2000) gkh
  *     Split driver up into device specific pieces.
  * 
@@ -269,6 +274,10 @@
 };
 
 
+/* variables needed for the tty_driver structure */
+static char *driver_name       = "usb";
+static char *tty_driver_name   = "usb/tty/%d";
+
 
 /* local function prototypes */
 static int  serial_open (struct tty_struct *tty, struct file * filp);
@@ -924,6 +933,48 @@
 }
 
 
+static struct tty_driver * usb_serial_tty_driver_init (struct usb_serial *serial)
+{
+       struct tty_driver *serial_tty_driver;
+
+       if (!(serial_tty_driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL))) {
+               err("Out of memory");
+               return NULL;
+       }
+
+       memset (serial_tty_driver, 0x00, sizeof(struct tty_driver));
+
+       /* initialize the entries that we don't want to be NULL */
+       serial_tty_driver->magic                = TTY_DRIVER_MAGIC;
+       serial_tty_driver->driver_name          = driver_name;
+       serial_tty_driver->name                 = tty_driver_name;
+       serial_tty_driver->major                = SERIAL_TTY_MAJOR;
+       serial_tty_driver->minor_start          = serial->minor;
+       serial_tty_driver->num                  = serial->num_ports;
+       serial_tty_driver->type                 = TTY_DRIVER_TYPE_SERIAL;
+       serial_tty_driver->subtype              = SERIAL_TYPE_NORMAL;
+       serial_tty_driver->flags                = TTY_DRIVER_REAL_RAW;
+       serial_tty_driver->refcount             = &serial_refcount;
+       serial_tty_driver->table                = serial_tty;
+       serial_tty_driver->termios              = serial_termios;
+       serial_tty_driver->termios_locked       = serial_termios_locked;
+       serial_tty_driver->open                 = serial_open;
+       serial_tty_driver->close                = serial_close;
+       serial_tty_driver->write                = serial_write;
+       serial_tty_driver->write_room           = serial_write_room;
+       serial_tty_driver->ioctl                = serial_ioctl;
+       serial_tty_driver->set_termios          = serial_set_termios;
+       serial_tty_driver->throttle             = serial_throttle;
+       serial_tty_driver->unthrottle           = serial_unthrottle;
+       serial_tty_driver->break_ctl            = serial_break;
+       serial_tty_driver->chars_in_buffer      = serial_chars_in_buffer;
+       serial_tty_driver->init_termios         = tty_std_termios;
+       serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+
+       return serial_tty_driver;
+}
+
+
 static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
 {
        struct usb_serial *serial = NULL;
@@ -1000,6 +1051,7 @@
                            (bulk_in_pipe & type->needs_bulk_in) &&
                            (bulk_out_pipe & type->needs_bulk_out)) {
                                /* found all that we need */
+                               MOD_INC_USE_COUNT;
                                info("%s converter detected", type->name);
 
 #ifdef CONFIG_USB_SERIAL_GENERIC
@@ -1012,6 +1064,7 @@
                                serial = get_free_serial (num_ports, &minor);
                                if (serial == NULL) {
                                        err("No more free serial devices");
+                                       MOD_DEC_USE_COUNT;
                                        return NULL;
                                }
        
@@ -1023,6 +1076,18 @@
                                serial->num_bulk_out = num_bulk_out;
                                serial->num_interrupt_in = num_interrupt_in;
 
+                               /* initialize a tty_driver for this device */
+                               serial->tty_driver = usb_serial_tty_driver_init 
+(serial);
+                               if (serial->tty_driver == NULL) {
+                                       err("Can't create a tty_serial_driver");
+                                       goto probe_error;
+                               }
+
+                               if (tty_register_driver (serial->tty_driver)) {
+                                       err("failed to register tty driver");
+                                       goto probe_error;
+                               }
+
                                /* collect interrupt_in endpoints now, because
                                   the keyspan_pda startup function needs
                                   to know about them */
@@ -1040,8 +1105,7 @@
                                /* if this device type has a startup function, call it 
*/
                                if (type->startup) {
                                        if (type->startup (serial)) {
-                                               return_serial (serial);
-                                               return NULL;
+                                               goto probe_error;
                                        }
                                }
 
@@ -1114,8 +1178,6 @@
                                        info("%s converter now attached to ttyUSB%d", 
type->name, serial->minor + i);
                                }
 
-                               MOD_INC_USE_COUNT;
-
                                return serial;
                        } else {
                                info("descriptors matched, but endpoints did not");
@@ -1153,9 +1215,17 @@
                /* return the minor range that this device had */
                return_serial (serial);
 
+               /* if this device has a tty_driver, then unregister it and free it */
+               if (serial->tty_driver) {
+                       tty_unregister_driver (serial->tty_driver);
+                       kfree (serial->tty_driver);
+                       serial->tty_driver = NULL;
+               }
+
                /* free up any memory that we allocated */
                kfree (serial);
        }
+       MOD_DEC_USE_COUNT;
        return NULL;
 }
 
@@ -1205,6 +1275,12 @@
                /* return the minor range that this device had */
                return_serial (serial);
 
+               /* if this device has a tty_driver, then unregister it and free it */
+               if (serial->tty_driver) {
+                       tty_unregister_driver (serial->tty_driver);
+                       kfree (serial->tty_driver);
+                       serial->tty_driver = NULL;
+               }
                /* free up any memory that we allocated */
                kfree (serial);
 
@@ -1216,46 +1292,6 @@
 }
 
 
-static struct tty_driver serial_tty_driver = {
-       magic:                  TTY_DRIVER_MAGIC,
-       driver_name:            "usb",
-       name:                   "ttyUSB%d",
-       major:                  SERIAL_TTY_MAJOR,
-       minor_start:            0,
-       num:                    SERIAL_TTY_MINORS,
-       type:                   TTY_DRIVER_TYPE_SERIAL,
-       subtype:                SERIAL_TYPE_NORMAL,
-       flags:                  TTY_DRIVER_REAL_RAW,
-       refcount:               &serial_refcount,
-       table:                  serial_tty,
-       proc_entry:             NULL,
-       other:                  NULL,
-       termios:                serial_termios,
-       termios_locked:         serial_termios_locked,
-       
-       open:                   serial_open,
-       close:                  serial_close,
-       write:                  serial_write,
-       put_char:               NULL,
-       flush_chars:            NULL,
-       write_room:             serial_write_room,
-       ioctl:                  serial_ioctl,
-       set_termios:            serial_set_termios,
-       set_ldisc:              NULL, 
-       throttle:               serial_throttle,
-       unthrottle:             serial_unthrottle,
-       stop:                   NULL,
-       start:                  NULL,
-       hangup:                 NULL,
-       break_ctl:              serial_break,
-       wait_until_sent:        NULL,
-       send_xchar:             NULL,
-       read_proc:              NULL,
-       chars_in_buffer:        serial_chars_in_buffer,
-       flush_buffer:           NULL
-};
-
-
 int usb_serial_init(void)
 {
        int i;
@@ -1265,17 +1301,8 @@
                serial_table[i] = NULL;
        }
 
-       /* register the tty driver */
-       serial_tty_driver.init_termios          = tty_std_termios;
-       serial_tty_driver.init_termios.c_cflag  = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-       if (tty_register_driver (&serial_tty_driver)) {
-               err("failed to register tty driver");
-               return -EPERM;
-       }
-       
        /* register the USB driver */
        if (usb_register(&usb_serial_driver) < 0) {
-               tty_unregister_driver(&serial_tty_driver);
                return -1;
        }
 
@@ -1286,7 +1313,6 @@
 
 void usb_serial_exit(void)
 {
-       tty_unregister_driver(&serial_tty_driver);
        usb_deregister(&usb_serial_driver);
 }
 

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to