|
@@ -721,43 +721,53 @@ struct winch {
|
|
|
int pid;
|
|
|
struct tty_struct *tty;
|
|
|
unsigned long stack;
|
|
|
+ struct work_struct work;
|
|
|
};
|
|
|
|
|
|
-static void free_winch(struct winch *winch, int free_irq_ok)
|
|
|
+static void __free_winch(struct work_struct *work)
|
|
|
{
|
|
|
- int fd = winch->fd;
|
|
|
- winch->fd = -1;
|
|
|
- if (free_irq_ok)
|
|
|
- free_irq(WINCH_IRQ, winch);
|
|
|
-
|
|
|
- list_del(&winch->list);
|
|
|
+ struct winch *winch = container_of(work, struct winch, work);
|
|
|
+ free_irq(WINCH_IRQ, winch);
|
|
|
|
|
|
if (winch->pid != -1)
|
|
|
os_kill_process(winch->pid, 1);
|
|
|
- if (fd != -1)
|
|
|
- os_close_file(fd);
|
|
|
if (winch->stack != 0)
|
|
|
free_stack(winch->stack, 0);
|
|
|
kfree(winch);
|
|
|
}
|
|
|
|
|
|
+static void free_winch(struct winch *winch)
|
|
|
+{
|
|
|
+ int fd = winch->fd;
|
|
|
+ winch->fd = -1;
|
|
|
+ if (fd != -1)
|
|
|
+ os_close_file(fd);
|
|
|
+ list_del(&winch->list);
|
|
|
+ __free_winch(&winch->work);
|
|
|
+}
|
|
|
+
|
|
|
static irqreturn_t winch_interrupt(int irq, void *data)
|
|
|
{
|
|
|
struct winch *winch = data;
|
|
|
struct tty_struct *tty;
|
|
|
struct line *line;
|
|
|
+ int fd = winch->fd;
|
|
|
int err;
|
|
|
char c;
|
|
|
|
|
|
- if (winch->fd != -1) {
|
|
|
- err = generic_read(winch->fd, &c, NULL);
|
|
|
+ if (fd != -1) {
|
|
|
+ err = generic_read(fd, &c, NULL);
|
|
|
if (err < 0) {
|
|
|
if (err != -EAGAIN) {
|
|
|
+ winch->fd = -1;
|
|
|
+ list_del(&winch->list);
|
|
|
+ os_close_file(fd);
|
|
|
printk(KERN_ERR "winch_interrupt : "
|
|
|
"read failed, errno = %d\n", -err);
|
|
|
printk(KERN_ERR "fd %d is losing SIGWINCH "
|
|
|
"support\n", winch->tty_fd);
|
|
|
- free_winch(winch, 0);
|
|
|
+ INIT_WORK(&winch->work, __free_winch);
|
|
|
+ schedule_work(&winch->work);
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
goto out;
|
|
@@ -829,7 +839,7 @@ static void unregister_winch(struct tty_struct *tty)
|
|
|
list_for_each_safe(ele, next, &winch_handlers) {
|
|
|
winch = list_entry(ele, struct winch, list);
|
|
|
if (winch->tty == tty) {
|
|
|
- free_winch(winch, 1);
|
|
|
+ free_winch(winch);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
@@ -845,7 +855,7 @@ static void winch_cleanup(void)
|
|
|
|
|
|
list_for_each_safe(ele, next, &winch_handlers) {
|
|
|
winch = list_entry(ele, struct winch, list);
|
|
|
- free_winch(winch, 1);
|
|
|
+ free_winch(winch);
|
|
|
}
|
|
|
|
|
|
spin_unlock(&winch_handler_lock);
|