aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2006-01-06 03:18:57 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:33:46 -0500
commit165dc5911627a9c4752e909a0da661b96b6fd269 (patch)
tree7e8eb47b7e766a5296b9e15ef177f958dec16d93 /arch/um/kernel
parent1f80171e81ed0d08dcdb6efe239d7b929aef498f (diff)
[PATCH] uml: Simplify console opening/closing and irq registration
This patch simplifies the opening and closing of host console devices and the registration and deregistration of IRQs. The intent is to make it obvious that an IRQ can't exist without an open file descriptor. chan_enable will now open the channel, and when both opening and IRQ registration are desired, this should be used. Opening only is done for the initial console, so that interface still needs to exist. The free_irqs_later interface is now gone. It was intended to avoid freeing an IRQ while it was being processed. It did this, but it didn't eliminate the possiblity of free_irq being called from an interrupt, which is bad. In its place is a list of irqs to be freed, which is processed by the signal handler just before exiting. close_one_chan now disables irqs. When a host device disappears, it is just closed, and that disables IRQs. The device id registered with the IRQ is now the chan structure, not the tty. This is because the interrupt arrives on a descriptor associated with the channel. This caused equivalent changes in the arguments to line_timer_cb. line_disable is gone since it is not used any more. The count field in the line structure is gone. tty->count is used instead. The complicated logic in sigio_handler with freeing IRQs when necessary and making sure its idea of the next irq is correct is now much simpler. The irq list can't be rearranged underneath it, so it is now a simple list walk. Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/irq_user.c48
1 files changed, 7 insertions, 41 deletions
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index c3ccaf24f3e0..50a2aa35cda9 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -29,7 +29,6 @@ struct irq_fd {
29 int pid; 29 int pid;
30 int events; 30 int events;
31 int current_events; 31 int current_events;
32 int freed;
33}; 32};
34 33
35static struct irq_fd *active_fds = NULL; 34static struct irq_fd *active_fds = NULL;
@@ -41,9 +40,11 @@ static int pollfds_size = 0;
41 40
42extern int io_count, intr_count; 41extern int io_count, intr_count;
43 42
43extern void free_irqs(void);
44
44void sigio_handler(int sig, union uml_pt_regs *regs) 45void sigio_handler(int sig, union uml_pt_regs *regs)
45{ 46{
46 struct irq_fd *irq_fd, *next; 47 struct irq_fd *irq_fd;
47 int i, n; 48 int i, n;
48 49
49 if(smp_sigio_handler()) return; 50 if(smp_sigio_handler()) return;
@@ -66,29 +67,15 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
66 irq_fd = irq_fd->next; 67 irq_fd = irq_fd->next;
67 } 68 }
68 69
69 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ 70 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
70 next = irq_fd->next;
71 if(irq_fd->current_events != 0){ 71 if(irq_fd->current_events != 0){
72 irq_fd->current_events = 0; 72 irq_fd->current_events = 0;
73 do_IRQ(irq_fd->irq, regs); 73 do_IRQ(irq_fd->irq, regs);
74
75 /* This is here because the next irq may be
76 * freed in the handler. If a console goes
77 * away, both the read and write irqs will be
78 * freed. After do_IRQ, ->next will point to
79 * a good IRQ.
80 * Irqs can't be freed inside their handlers,
81 * so the next best thing is to have them
82 * marked as needing freeing, so that they
83 * can be freed here.
84 */
85 next = irq_fd->next;
86 if(irq_fd->freed){
87 free_irq(irq_fd->irq, irq_fd->id);
88 }
89 } 74 }
90 } 75 }
91 } 76 }
77
78 free_irqs();
92} 79}
93 80
94int activate_ipi(int fd, int pid) 81int activate_ipi(int fd, int pid)
@@ -136,8 +123,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
136 .irq = irq, 123 .irq = irq,
137 .pid = pid, 124 .pid = pid,
138 .events = events, 125 .events = events,
139 .current_events = 0, 126 .current_events = 0 } );
140 .freed = 0 } );
141 127
142 /* Critical section - locked by a spinlock because this stuff can 128 /* Critical section - locked by a spinlock because this stuff can
143 * be changed from interrupt handlers. The stuff above is done 129 * be changed from interrupt handlers. The stuff above is done
@@ -313,26 +299,6 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
313 return(irq); 299 return(irq);
314} 300}
315 301
316void free_irq_later(int irq, void *dev_id)
317{
318 struct irq_fd *irq_fd;
319 unsigned long flags;
320
321 flags = irq_lock();
322 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
323 if((irq_fd->irq == irq) && (irq_fd->id == dev_id))
324 break;
325 }
326 if(irq_fd == NULL){
327 printk("free_irq_later found no irq, irq = %d, "
328 "dev_id = 0x%p\n", irq, dev_id);
329 goto out;
330 }
331 irq_fd->freed = 1;
332 out:
333 irq_unlock(flags);
334}
335
336void reactivate_fd(int fd, int irqnum) 302void reactivate_fd(int fd, int irqnum)
337{ 303{
338 struct irq_fd *irq; 304 struct irq_fd *irq;