aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers/line.c
diff options
context:
space:
mode:
authorPaolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>2005-07-07 20:56:52 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-07-07 21:23:44 -0400
commit605a69ac81249cca531cdc6b3e695f15dda63102 (patch)
treef42d781478ddf14288d3952263363efde1bc45a2 /arch/um/drivers/line.c
parent3f580470baa3afc423e38fdc6e19667446b5aac0 (diff)
[PATCH] uml: remove winch sem
Replace a semaphore (winch_handler_sem) used in atomic code with a spinlock, and reduces as needed the amount of protected code to the bare minimum (for instance no kmalloc calls are needed). This fixes the last problems with spinlocking (in UP mode with DEBUG options); the semaphore, taken inside spinlocks, caused a "spin_lock was already locked" warning, without this patch. Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Cc: Jeff Dike <jdike@addtoit.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um/drivers/line.c')
-rw-r--r--arch/um/drivers/line.c37
1 files changed, 24 insertions, 13 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 2bb4c4f5dec4..e0fdffa2d542 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -663,11 +663,15 @@ struct tty_driver *line_register_devfs(struct lines *set,
663 return driver; 663 return driver;
664} 664}
665 665
666static spinlock_t winch_handler_lock;
667LIST_HEAD(winch_handlers);
668
666void lines_init(struct line *lines, int nlines) 669void lines_init(struct line *lines, int nlines)
667{ 670{
668 struct line *line; 671 struct line *line;
669 int i; 672 int i;
670 673
674 spin_lock_init(&winch_handler_lock);
671 for(i = 0; i < nlines; i++){ 675 for(i = 0; i < nlines; i++){
672 line = &lines[i]; 676 line = &lines[i];
673 INIT_LIST_HEAD(&line->chan_list); 677 INIT_LIST_HEAD(&line->chan_list);
@@ -724,31 +728,30 @@ irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
724 return IRQ_HANDLED; 728 return IRQ_HANDLED;
725} 729}
726 730
727DECLARE_MUTEX(winch_handler_sem);
728LIST_HEAD(winch_handlers);
729
730void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) 731void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty)
731{ 732{
732 struct winch *winch; 733 struct winch *winch;
733 734
734 down(&winch_handler_sem);
735 winch = kmalloc(sizeof(*winch), GFP_KERNEL); 735 winch = kmalloc(sizeof(*winch), GFP_KERNEL);
736 if (winch == NULL) { 736 if (winch == NULL) {
737 printk("register_winch_irq - kmalloc failed\n"); 737 printk("register_winch_irq - kmalloc failed\n");
738 goto out; 738 return;
739 } 739 }
740
740 *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list), 741 *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list),
741 .fd = fd, 742 .fd = fd,
742 .tty_fd = tty_fd, 743 .tty_fd = tty_fd,
743 .pid = pid, 744 .pid = pid,
744 .tty = tty }); 745 .tty = tty });
746
747 spin_lock(&winch_handler_lock);
745 list_add(&winch->list, &winch_handlers); 748 list_add(&winch->list, &winch_handlers);
749 spin_unlock(&winch_handler_lock);
750
746 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, 751 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
747 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 752 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
748 "winch", winch) < 0) 753 "winch", winch) < 0)
749 printk("register_winch_irq - failed to register IRQ\n"); 754 printk("register_winch_irq - failed to register IRQ\n");
750 out:
751 up(&winch_handler_sem);
752} 755}
753 756
754static void unregister_winch(struct tty_struct *tty) 757static void unregister_winch(struct tty_struct *tty)
@@ -756,7 +759,7 @@ static void unregister_winch(struct tty_struct *tty)
756 struct list_head *ele; 759 struct list_head *ele;
757 struct winch *winch, *found = NULL; 760 struct winch *winch, *found = NULL;
758 761
759 down(&winch_handler_sem); 762 spin_lock(&winch_handler_lock);
760 list_for_each(ele, &winch_handlers){ 763 list_for_each(ele, &winch_handlers){
761 winch = list_entry(ele, struct winch, list); 764 winch = list_entry(ele, struct winch, list);
762 if(winch->tty == tty){ 765 if(winch->tty == tty){
@@ -764,20 +767,25 @@ static void unregister_winch(struct tty_struct *tty)
764 break; 767 break;
765 } 768 }
766 } 769 }
767
768 if(found == NULL) 770 if(found == NULL)
769 goto out; 771 goto err;
772
773 list_del(&winch->list);
774 spin_unlock(&winch_handler_lock);
770 775
771 if(winch->pid != -1) 776 if(winch->pid != -1)
772 os_kill_process(winch->pid, 1); 777 os_kill_process(winch->pid, 1);
773 778
774 free_irq(WINCH_IRQ, winch); 779 free_irq(WINCH_IRQ, winch);
775 list_del(&winch->list);
776 kfree(winch); 780 kfree(winch);
777 out: 781
778 up(&winch_handler_sem); 782 return;
783err:
784 spin_unlock(&winch_handler_lock);
779} 785}
780 786
787/* XXX: No lock as it's an exitcall... is this valid? Depending on cleanup
788 * order... are we sure that nothing else is done on the list? */
781static void winch_cleanup(void) 789static void winch_cleanup(void)
782{ 790{
783 struct list_head *ele; 791 struct list_head *ele;
@@ -786,6 +794,9 @@ static void winch_cleanup(void)
786 list_for_each(ele, &winch_handlers){ 794 list_for_each(ele, &winch_handlers){
787 winch = list_entry(ele, struct winch, list); 795 winch = list_entry(ele, struct winch, list);
788 if(winch->fd != -1){ 796 if(winch->fd != -1){
797 /* Why is this different from the above free_irq(),
798 * which deactivates SIGIO? This searches the FD
799 * somewhere else and removes it from the list... */
789 deactivate_fd(winch->fd, WINCH_IRQ); 800 deactivate_fd(winch->fd, WINCH_IRQ);
790 os_close_file(winch->fd); 801 os_close_file(winch->fd);
791 } 802 }