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.c324
1 files changed, 0 insertions, 324 deletions
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
deleted file mode 100644
index 483e79c5ab98..000000000000
--- a/arch/um/kernel/irq_user.c
+++ /dev/null
@@ -1,324 +0,0 @@
1/*
2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
4 */
5
6#include <stdlib.h>
7#include <unistd.h>
8#include <errno.h>
9#include <signal.h>
10#include <string.h>
11#include <sys/poll.h>
12#include <sys/types.h>
13#include <sys/time.h>
14#include "user_util.h"
15#include "kern_util.h"
16#include "user.h"
17#include "process.h"
18#include "sigio.h"
19#include "irq_user.h"
20#include "os.h"
21#include "misc_constants.h"
22
23struct irq_fd *active_fds = NULL;
24static struct irq_fd **last_irq_ptr = &active_fds;
25
26extern void free_irqs(void);
27
28void sigio_handler(int sig, union uml_pt_regs *regs)
29{
30 struct irq_fd *irq_fd;
31 int n;
32
33 if(smp_sigio_handler()) return;
34 while(1){
35 n = os_waiting_for_events(active_fds);
36 if (n <= 0) {
37 if(n == -EINTR) continue;
38 else break;
39 }
40
41 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
42 if(irq_fd->current_events != 0){
43 irq_fd->current_events = 0;
44 do_IRQ(irq_fd->irq, regs);
45 }
46 }
47 }
48
49 free_irqs();
50}
51
52static void maybe_sigio_broken(int fd, int type)
53{
54 if(os_isatty(fd)){
55 if((type == IRQ_WRITE) && !pty_output_sigio){
56 write_sigio_workaround();
57 add_sigio_fd(fd, 0);
58 }
59 else if((type == IRQ_READ) && !pty_close_sigio){
60 write_sigio_workaround();
61 add_sigio_fd(fd, 1);
62 }
63 }
64}
65
66
67int activate_fd(int irq, int fd, int type, void *dev_id)
68{
69 struct pollfd *tmp_pfd;
70 struct irq_fd *new_fd, *irq_fd;
71 unsigned long flags;
72 int pid, events, err, n;
73
74 pid = os_getpid();
75 err = os_set_fd_async(fd, pid);
76 if(err < 0)
77 goto out;
78
79 new_fd = um_kmalloc(sizeof(*new_fd));
80 err = -ENOMEM;
81 if(new_fd == NULL)
82 goto out;
83
84 if(type == IRQ_READ) events = UM_POLLIN | UM_POLLPRI;
85 else events = UM_POLLOUT;
86 *new_fd = ((struct irq_fd) { .next = NULL,
87 .id = dev_id,
88 .fd = fd,
89 .type = type,
90 .irq = irq,
91 .pid = pid,
92 .events = events,
93 .current_events = 0 } );
94
95 /* Critical section - locked by a spinlock because this stuff can
96 * be changed from interrupt handlers. The stuff above is done
97 * outside the lock because it allocates memory.
98 */
99
100 /* Actually, it only looks like it can be called from interrupt
101 * context. The culprit is reactivate_fd, which calls
102 * maybe_sigio_broken, which calls write_sigio_workaround,
103 * which calls activate_fd. However, write_sigio_workaround should
104 * only be called once, at boot time. That would make it clear that
105 * this is called only from process context, and can be locked with
106 * a semaphore.
107 */
108 flags = irq_lock();
109 for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
110 if((irq_fd->fd == fd) && (irq_fd->type == type)){
111 printk("Registering fd %d twice\n", fd);
112 printk("Irqs : %d, %d\n", irq_fd->irq, irq);
113 printk("Ids : 0x%x, 0x%x\n", irq_fd->id, dev_id);
114 goto out_unlock;
115 }
116 }
117
118 /*-------------*/
119 if(type == IRQ_WRITE)
120 fd = -1;
121
122 tmp_pfd = NULL;
123 n = 0;
124
125 while(1){
126 n = os_create_pollfd(fd, events, tmp_pfd, n);
127 if (n == 0)
128 break;
129
130 /* n > 0
131 * It means we couldn't put new pollfd to current pollfds
132 * and tmp_fds is NULL or too small for new pollfds array.
133 * Needed size is equal to n as minimum.
134 *
135 * Here we have to drop the lock in order to call
136 * kmalloc, which might sleep.
137 * If something else came in and changed the pollfds array
138 * so we will not be able to put new pollfd struct to pollfds
139 * then we free the buffer tmp_fds and try again.
140 */
141 irq_unlock(flags);
142 if (tmp_pfd != NULL) {
143 kfree(tmp_pfd);
144 tmp_pfd = NULL;
145 }
146
147 tmp_pfd = um_kmalloc(n);
148 if (tmp_pfd == NULL)
149 goto out_kfree;
150
151 flags = irq_lock();
152 }
153 /*-------------*/
154
155 *last_irq_ptr = new_fd;
156 last_irq_ptr = &new_fd->next;
157
158 irq_unlock(flags);
159
160 /* This calls activate_fd, so it has to be outside the critical
161 * section.
162 */
163 maybe_sigio_broken(fd, type);
164
165 return(0);
166
167 out_unlock:
168 irq_unlock(flags);
169 out_kfree:
170 kfree(new_fd);
171 out:
172 return(err);
173}
174
175static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
176{
177 unsigned long flags;
178
179 flags = irq_lock();
180 os_free_irq_by_cb(test, arg, active_fds, &last_irq_ptr);
181 irq_unlock(flags);
182}
183
184struct irq_and_dev {
185 int irq;
186 void *dev;
187};
188
189static int same_irq_and_dev(struct irq_fd *irq, void *d)
190{
191 struct irq_and_dev *data = d;
192
193 return((irq->irq == data->irq) && (irq->id == data->dev));
194}
195
196void free_irq_by_irq_and_dev(unsigned int irq, void *dev)
197{
198 struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq,
199 .dev = dev });
200
201 free_irq_by_cb(same_irq_and_dev, &data);
202}
203
204static int same_fd(struct irq_fd *irq, void *fd)
205{
206 return(irq->fd == *((int *) fd));
207}
208
209void free_irq_by_fd(int fd)
210{
211 free_irq_by_cb(same_fd, &fd);
212}
213
214static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
215{
216 struct irq_fd *irq;
217 int i = 0;
218 int fdi;
219
220 for(irq=active_fds; irq != NULL; irq = irq->next){
221 if((irq->fd == fd) && (irq->irq == irqnum)) break;
222 i++;
223 }
224 if(irq == NULL){
225 printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
226 goto out;
227 }
228 fdi = os_get_pollfd(i);
229 if((fdi != -1) && (fdi != fd)){
230 printk("find_irq_by_fd - mismatch between active_fds and "
231 "pollfds, fd %d vs %d, need %d\n", irq->fd,
232 fdi, fd);
233 irq = NULL;
234 goto out;
235 }
236 *index_out = i;
237 out:
238 return(irq);
239}
240
241void reactivate_fd(int fd, int irqnum)
242{
243 struct irq_fd *irq;
244 unsigned long flags;
245 int i;
246
247 flags = irq_lock();
248 irq = find_irq_by_fd(fd, irqnum, &i);
249 if(irq == NULL){
250 irq_unlock(flags);
251 return;
252 }
253 os_set_pollfd(i, irq->fd);
254 irq_unlock(flags);
255
256 /* This calls activate_fd, so it has to be outside the critical
257 * section.
258 */
259 maybe_sigio_broken(fd, irq->type);
260}
261
262void deactivate_fd(int fd, int irqnum)
263{
264 struct irq_fd *irq;
265 unsigned long flags;
266 int i;
267
268 flags = irq_lock();
269 irq = find_irq_by_fd(fd, irqnum, &i);
270 if(irq == NULL)
271 goto out;
272 os_set_pollfd(i, -1);
273 out:
274 irq_unlock(flags);
275}
276
277int deactivate_all_fds(void)
278{
279 struct irq_fd *irq;
280 int err;
281
282 for(irq=active_fds;irq != NULL;irq = irq->next){
283 err = os_clear_fd_async(irq->fd);
284 if(err)
285 return(err);
286 }
287 /* If there is a signal already queued, after unblocking ignore it */
288 os_set_ioignore();
289
290 return(0);
291}
292
293void forward_interrupts(int pid)
294{
295 struct irq_fd *irq;
296 unsigned long flags;
297 int err;
298
299 flags = irq_lock();
300 for(irq=active_fds;irq != NULL;irq = irq->next){
301 err = os_set_owner(irq->fd, pid);
302 if(err < 0){
303 /* XXX Just remove the irq rather than
304 * print out an infinite stream of these
305 */
306 printk("Failed to forward %d to pid %d, err = %d\n",
307 irq->fd, pid, -err);
308 }
309
310 irq->pid = pid;
311 }
312 irq_unlock(flags);
313}
314
315/*
316 * Overrides for Emacs so that we follow Linus's tabbing style.
317 * Emacs will notice this stuff at the end of the file and automatically
318 * adjust the settings for this buffer only. This must remain at the end
319 * of the file.
320 * ---------------------------------------------------------------------------
321 * Local variables:
322 * c-file-style: "linux"
323 * End:
324 */