aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers/line.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/drivers/line.c')
-rw-r--r--arch/um/drivers/line.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index d0f97127adf6..025d3be8aca4 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -462,12 +462,15 @@ out:
return err;
}
+static void unregister_winch(struct tty_struct *tty);
+
void line_close(struct tty_struct *tty, struct file * filp)
{
struct line *line = tty->driver_data;
- /* XXX: I assume this should be called in process context, not with interrupt
- * disabled!*/
+ /* XXX: I assume this should be called in process context, not with
+ * interrupts disabled!
+ */
spin_lock_irq(&line->lock);
/* We ignore the error anyway! */
@@ -478,6 +481,12 @@ void line_close(struct tty_struct *tty, struct file * filp)
line_disable(tty, -1);
tty->driver_data = NULL;
}
+
+ if((line->count == 0) && line->sigio){
+ unregister_winch(tty);
+ line->sigio = 0;
+ }
+
spin_unlock_irq(&line->lock);
}
@@ -729,6 +738,34 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
up(&winch_handler_sem);
}
+static void unregister_winch(struct tty_struct *tty)
+{
+ struct list_head *ele;
+ struct winch *winch, *found = NULL;
+
+ down(&winch_handler_sem);
+ list_for_each(ele, &winch_handlers){
+ winch = list_entry(ele, struct winch, list);
+ if(winch->tty == tty){
+ found = winch;
+ break;
+ }
+ }
+
+ if(found == NULL)
+ goto out;
+
+ if(winch->pid != -1)
+ os_kill_process(winch->pid, 1);
+
+ free_irq_by_irq_and_dev(WINCH_IRQ, winch);
+ free_irq(WINCH_IRQ, winch);
+ list_del(&winch->list);
+ kfree(winch);
+ out:
+ up(&winch_handler_sem);
+}
+
static void winch_cleanup(void)
{
struct list_head *ele;