diff options
Diffstat (limited to 'arch/um/drivers/line.c')
-rw-r--r-- | arch/um/drivers/line.c | 60 |
1 files changed, 39 insertions, 21 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 1fb3e51108b9..3e0b68e297f2 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
@@ -749,8 +749,24 @@ struct winch { | |||
749 | int tty_fd; | 749 | int tty_fd; |
750 | int pid; | 750 | int pid; |
751 | struct tty_struct *tty; | 751 | struct tty_struct *tty; |
752 | unsigned long stack; | ||
752 | }; | 753 | }; |
753 | 754 | ||
755 | static void free_winch(struct winch *winch, int free_irq_ok) | ||
756 | { | ||
757 | list_del(&winch->list); | ||
758 | |||
759 | if (winch->pid != -1) | ||
760 | os_kill_process(winch->pid, 1); | ||
761 | if (winch->fd != -1) | ||
762 | os_close_file(winch->fd); | ||
763 | if (winch->stack != 0) | ||
764 | free_stack(winch->stack, 0); | ||
765 | if (free_irq_ok) | ||
766 | free_irq(WINCH_IRQ, winch); | ||
767 | kfree(winch); | ||
768 | } | ||
769 | |||
754 | static irqreturn_t winch_interrupt(int irq, void *data) | 770 | static irqreturn_t winch_interrupt(int irq, void *data) |
755 | { | 771 | { |
756 | struct winch *winch = data; | 772 | struct winch *winch = data; |
@@ -767,12 +783,13 @@ static irqreturn_t winch_interrupt(int irq, void *data) | |||
767 | "errno = %d\n", -err); | 783 | "errno = %d\n", -err); |
768 | printk("fd %d is losing SIGWINCH support\n", | 784 | printk("fd %d is losing SIGWINCH support\n", |
769 | winch->tty_fd); | 785 | winch->tty_fd); |
786 | free_winch(winch, 0); | ||
770 | return IRQ_HANDLED; | 787 | return IRQ_HANDLED; |
771 | } | 788 | } |
772 | goto out; | 789 | goto out; |
773 | } | 790 | } |
774 | } | 791 | } |
775 | tty = winch->tty; | 792 | tty = winch->tty; |
776 | if (tty != NULL) { | 793 | if (tty != NULL) { |
777 | line = tty->driver_data; | 794 | line = tty->driver_data; |
778 | chan_window_size(&line->chan_list, &tty->winsize.ws_row, | 795 | chan_window_size(&line->chan_list, &tty->winsize.ws_row, |
@@ -785,43 +802,44 @@ static irqreturn_t winch_interrupt(int irq, void *data) | |||
785 | return IRQ_HANDLED; | 802 | return IRQ_HANDLED; |
786 | } | 803 | } |
787 | 804 | ||
788 | void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) | 805 | void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, |
806 | unsigned long stack) | ||
789 | { | 807 | { |
790 | struct winch *winch; | 808 | struct winch *winch; |
791 | 809 | ||
792 | winch = kmalloc(sizeof(*winch), GFP_KERNEL); | 810 | winch = kmalloc(sizeof(*winch), GFP_KERNEL); |
793 | if (winch == NULL) { | 811 | if (winch == NULL) { |
794 | printk("register_winch_irq - kmalloc failed\n"); | 812 | printk("register_winch_irq - kmalloc failed\n"); |
795 | return; | 813 | goto cleanup; |
796 | } | 814 | } |
797 | 815 | ||
798 | *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list), | 816 | *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list), |
799 | .fd = fd, | 817 | .fd = fd, |
800 | .tty_fd = tty_fd, | 818 | .tty_fd = tty_fd, |
801 | .pid = pid, | 819 | .pid = pid, |
802 | .tty = tty }); | 820 | .tty = tty, |
821 | .stack = stack }); | ||
822 | |||
823 | if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, | ||
824 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | ||
825 | "winch", winch) < 0) { | ||
826 | printk("register_winch_irq - failed to register IRQ\n"); | ||
827 | goto out_free; | ||
828 | } | ||
803 | 829 | ||
804 | spin_lock(&winch_handler_lock); | 830 | spin_lock(&winch_handler_lock); |
805 | list_add(&winch->list, &winch_handlers); | 831 | list_add(&winch->list, &winch_handlers); |
806 | spin_unlock(&winch_handler_lock); | 832 | spin_unlock(&winch_handler_lock); |
807 | 833 | ||
808 | if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, | 834 | return; |
809 | IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, | ||
810 | "winch", winch) < 0) | ||
811 | printk("register_winch_irq - failed to register IRQ\n"); | ||
812 | } | ||
813 | |||
814 | static void free_winch(struct winch *winch) | ||
815 | { | ||
816 | list_del(&winch->list); | ||
817 | |||
818 | if(winch->pid != -1) | ||
819 | os_kill_process(winch->pid, 1); | ||
820 | if(winch->fd != -1) | ||
821 | os_close_file(winch->fd); | ||
822 | 835 | ||
823 | free_irq(WINCH_IRQ, winch); | 836 | out_free: |
824 | kfree(winch); | 837 | kfree(winch); |
838 | cleanup: | ||
839 | os_kill_process(pid, 1); | ||
840 | os_close_file(fd); | ||
841 | if (stack != 0) | ||
842 | free_stack(stack, 0); | ||
825 | } | 843 | } |
826 | 844 | ||
827 | static void unregister_winch(struct tty_struct *tty) | 845 | static void unregister_winch(struct tty_struct *tty) |
@@ -834,7 +852,7 @@ static void unregister_winch(struct tty_struct *tty) | |||
834 | list_for_each(ele, &winch_handlers){ | 852 | list_for_each(ele, &winch_handlers){ |
835 | winch = list_entry(ele, struct winch, list); | 853 | winch = list_entry(ele, struct winch, list); |
836 | if(winch->tty == tty){ | 854 | if(winch->tty == tty){ |
837 | free_winch(winch); | 855 | free_winch(winch, 1); |
838 | break; | 856 | break; |
839 | } | 857 | } |
840 | } | 858 | } |
@@ -850,7 +868,7 @@ static void winch_cleanup(void) | |||
850 | 868 | ||
851 | list_for_each_safe(ele, next, &winch_handlers){ | 869 | list_for_each_safe(ele, next, &winch_handlers){ |
852 | winch = list_entry(ele, struct winch, list); | 870 | winch = list_entry(ele, struct winch, list); |
853 | free_winch(winch); | 871 | free_winch(winch, 1); |
854 | } | 872 | } |
855 | 873 | ||
856 | spin_unlock(&winch_handler_lock); | 874 | spin_unlock(&winch_handler_lock); |