diff options
Diffstat (limited to 'arch/um/kernel/irq_user.c')
-rw-r--r-- | arch/um/kernel/irq_user.c | 48 |
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 | ||
35 | static struct irq_fd *active_fds = NULL; | 34 | static struct irq_fd *active_fds = NULL; |
@@ -41,9 +40,11 @@ static int pollfds_size = 0; | |||
41 | 40 | ||
42 | extern int io_count, intr_count; | 41 | extern int io_count, intr_count; |
43 | 42 | ||
43 | extern void free_irqs(void); | ||
44 | |||
44 | void sigio_handler(int sig, union uml_pt_regs *regs) | 45 | void 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 | ||
94 | int activate_ipi(int fd, int pid) | 81 | int 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 | ||
316 | void 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 | |||
336 | void reactivate_fd(int fd, int irqnum) | 302 | void reactivate_fd(int fd, int irqnum) |
337 | { | 303 | { |
338 | struct irq_fd *irq; | 304 | struct irq_fd *irq; |