Well if I had tested this patch with some devices OTHER than usb-serial
ones, I would have found the bug that Randy instantly found.

Attached is the revised patch. I moved MOD_USE_COUNT to it's proper
place now.

Sorry about that,

greg k-h
[EMAIL PROTECTED]



On Mon, Apr 03, 2000 at 12:35:01PM -0700, Greg KH wrote:
> 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 14:05:13 
+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,8 +1215,16 @@
                /* 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