From: Ryan Arnold This patch prevents execution of hvc_write() and hvc_hangup() after the tty layer has executed a final hvc_close() against a device. This patch provides a better method than was previously used. tty->driver_data is no longer invalidated so we'll no longer get oopses when the tty layer allows late hangup() and write() operations. - Removed silly tty->driver_data = NULL; from hvc_close which prevents possible oops in hvc_write() and hvc_hangup() due to improperly acting ldisc close ordering. - Added hp->count <= 0 check to hvc_write() and hvc_hangup() to prevent execution of these function after hvc_close() has been invoked by the tty layer. Same tty ldisc issues as above are the reason. - Added some comments to clarify the situation. - Awaiting a forth coming patch from Alan Cox which should clean up the close ordering and prevent the late hangup and write ops from happening. Signed-off-by: Ryan S. Arnold Signed-off-by: Andrew Morton --- 25-akpm/drivers/char/hvc_console.c | 27 +++++++++++++++++++-------- 1 files changed, 19 insertions(+), 8 deletions(-) diff -puN drivers/char/hvc_console.c~hvc_console-fix-to-prevent-oops-and-late-hangup-and-write drivers/char/hvc_console.c --- 25/drivers/char/hvc_console.c~hvc_console-fix-to-prevent-oops-and-late-hangup-and-write 2004-10-04 20:21:53.175988840 -0700 +++ 25-akpm/drivers/char/hvc_console.c 2004-10-04 20:21:53.180988080 -0700 @@ -221,6 +221,7 @@ static int hvc_open(struct tty_struct *t spin_unlock_irqrestore(&hp->lock, flags); tty->driver_data = NULL; kobject_put(kobjp); + printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc); } /* Force wakeup of the polling thread */ hvc_kick(); @@ -240,7 +241,7 @@ static void hvc_close(struct tty_struct /* * No driver_data means that this close was issued after a failed - * hvcs_open by the tty layer's release_dev() function and we can just + * hvc_open by the tty layer's release_dev() function and we can just * exit cleanly because the kobject reference wasn't made. */ if (!tty->driver_data) @@ -266,13 +267,6 @@ static void hvc_close(struct tty_struct */ tty_wait_until_sent(tty, HVC_CLOSE_WAIT); - /* - * Since the line disc doesn't block writes during tty close - * operations we'll set driver_data to NULL and then make sure - * to check tty->driver_data for NULL in hvc_write(). - */ - tty->driver_data = NULL; - if (irq != NO_IRQ) free_irq(irq, hp); @@ -294,7 +288,21 @@ static void hvc_hangup(struct tty_struct int temp_open_count; struct kobject *kobjp; + if (!hp) + return; + spin_lock_irqsave(&hp->lock, flags); + + /* + * The N_TTY line discipline has problems such that in a close vs + * open->hangup case this can be called after the final close so prevent + * that from happening for now. + */ + if (hp->count <= 0) { + spin_unlock_irqrestore(&hp->lock, flags); + return; + } + kobjp = &hp->kobj; temp_open_count = hp->count; hp->count = 0; @@ -428,6 +436,9 @@ static int hvc_write(struct tty_struct * if (!hp) return -EPIPE; + if (hp->count <= 0) + return -EIO; + if (from_user) written = __hvc_write_user(hp, buf, count); else _