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.c60
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
755static 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
754static irqreturn_t winch_interrupt(int irq, void *data) 770static 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
788void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) 805void 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
814static 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
827static void unregister_winch(struct tty_struct *tty) 845static 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);