diff -urN a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c --- a/drivers/input/serio/serport.c 2004-09-21 22:43:22.000000000 +0300 +++ b/drivers/input/serio/serport.c 2004-09-21 22:47:57.568284000 +0300 @@ -33,6 +33,7 @@ wait_queue_head_t wait; struct serio *serio; unsigned long flags; + int quit; }; /* @@ -45,11 +46,19 @@ return -(serport->tty->driver->write(serport->tty, 0, &data, 1) != 1); } +static int serport_serio_open(struct serio *serio) +{ + struct serport *serport = serio->port_data; + + serport->quit = 0; + return 0; +} + static void serport_serio_close(struct serio *serio) { struct serport *serport = serio->port_data; - serport->serio->type = 0; + serport->quit = 1; wake_up_interruptible(&serport->wait); } @@ -84,6 +93,7 @@ serio->type = SERIO_RS232; serio->write = serport_serio_write; serio->close = serport_serio_close; + serio->open = serport_serio_open; serio->port_data = serport; init_waitqueue_head(&serport->wait); @@ -98,6 +108,13 @@ static void serport_ldisc_close(struct tty_struct *tty) { struct serport *serport = (struct serport*) tty->disc_data; + + serport->quit = 1; + wake_up_interruptible(&serport->wait); + + while (test_bit(SERPORT_BUSY, &serport->flags)) + schedule(); + kfree(serport); } @@ -140,12 +157,12 @@ struct serport *serport = (struct serport*) tty->disc_data; char name[64]; - if (test_and_set_bit(SERPORT_BUSY, &serport->flags)) + if (serport->quit || test_and_set_bit(SERPORT_BUSY, &serport->flags)) return -EBUSY; serio_register_port(serport->serio); printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name)); - wait_event_interruptible(serport->wait, !serport->serio->type); + wait_event_interruptible(serport->wait, serport->quit); serio_unregister_port(serport->serio); clear_bit(SERPORT_BUSY, &serport->flags); @@ -161,6 +178,9 @@ { struct serport *serport = (struct serport*) tty->disc_data; + if (test_bit(SERPORT_BUSY, &serport->flags) || serport->quit) + return -EBUSY; + if (cmd == SPIOCSTYPE) return get_user(serport->serio->type, (unsigned long __user *) arg);