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]