aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel/irq_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/kernel/irq_user.c')
-rw-r--r--arch/um/kernel/irq_user.c49
1 files changed, 7 insertions, 42 deletions
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index c3ccaf24f3e0..0e32f5f4a887 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -15,7 +15,6 @@
15#include "kern_util.h" 15#include "kern_util.h"
16#include "user.h" 16#include "user.h"
17#include "process.h" 17#include "process.h"
18#include "signal_user.h"
19#include "sigio.h" 18#include "sigio.h"
20#include "irq_user.h" 19#include "irq_user.h"
21#include "os.h" 20#include "os.h"
@@ -29,7 +28,6 @@ struct irq_fd {
29 int pid; 28 int pid;
30 int events; 29 int events;
31 int current_events; 30 int current_events;
32 int freed;
33}; 31};
34 32
35static struct irq_fd *active_fds = NULL; 33static struct irq_fd *active_fds = NULL;
@@ -41,9 +39,11 @@ static int pollfds_size = 0;
41 39
42extern int io_count, intr_count; 40extern int io_count, intr_count;
43 41
42extern void free_irqs(void);
43
44void sigio_handler(int sig, union uml_pt_regs *regs) 44void sigio_handler(int sig, union uml_pt_regs *regs)
45{ 45{
46 struct irq_fd *irq_fd, *next; 46 struct irq_fd *irq_fd;
47 int i, n; 47 int i, n;
48 48
49 if(smp_sigio_handler()) return; 49 if(smp_sigio_handler()) return;
@@ -66,29 +66,15 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
66 irq_fd = irq_fd->next; 66 irq_fd = irq_fd->next;
67 } 67 }
68 68
69 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ 69 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){ 70 if(irq_fd->current_events != 0){
72 irq_fd->current_events = 0; 71 irq_fd->current_events = 0;
73 do_IRQ(irq_fd->irq, regs); 72 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 } 73 }
90 } 74 }
91 } 75 }
76
77 free_irqs();
92} 78}
93 79
94int activate_ipi(int fd, int pid) 80int activate_ipi(int fd, int pid)
@@ -136,8 +122,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
136 .irq = irq, 122 .irq = irq,
137 .pid = pid, 123 .pid = pid,
138 .events = events, 124 .events = events,
139 .current_events = 0, 125 .current_events = 0 } );
140 .freed = 0 } );
141 126
142 /* Critical section - locked by a spinlock because this stuff can 127 /* Critical section - locked by a spinlock because this stuff can
143 * be changed from interrupt handlers. The stuff above is done 128 * be changed from interrupt handlers. The stuff above is done
@@ -313,26 +298,6 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
313 return(irq); 298 return(irq);
314} 299}
315 300
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) 301void reactivate_fd(int fd, int irqnum)
337{ 302{
338 struct irq_fd *irq; 303 struct irq_fd *irq;