diff options
Diffstat (limited to 'arch/um/kernel/irq.c')
-rw-r--r-- | arch/um/kernel/irq.c | 62 |
1 files changed, 19 insertions, 43 deletions
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index bfd0bdc8cd40..589c69a75043 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c | |||
@@ -110,18 +110,7 @@ void sigio_handler(int sig, union uml_pt_regs *regs) | |||
110 | free_irqs(); | 110 | free_irqs(); |
111 | } | 111 | } |
112 | 112 | ||
113 | static void maybe_sigio_broken(int fd, int type) | 113 | static DEFINE_SPINLOCK(irq_lock); |
114 | { | ||
115 | if (os_isatty(fd)) { | ||
116 | if ((type == IRQ_WRITE) && !pty_output_sigio) { | ||
117 | write_sigio_workaround(); | ||
118 | add_sigio_fd(fd, 0); | ||
119 | } else if ((type == IRQ_READ) && !pty_close_sigio) { | ||
120 | write_sigio_workaround(); | ||
121 | add_sigio_fd(fd, 1); | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | 114 | ||
126 | int activate_fd(int irq, int fd, int type, void *dev_id) | 115 | int activate_fd(int irq, int fd, int type, void *dev_id) |
127 | { | 116 | { |
@@ -166,7 +155,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
166 | * this is called only from process context, and can be locked with | 155 | * this is called only from process context, and can be locked with |
167 | * a semaphore. | 156 | * a semaphore. |
168 | */ | 157 | */ |
169 | flags = irq_lock(); | 158 | spin_lock_irqsave(&irq_lock, flags); |
170 | for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { | 159 | for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { |
171 | if ((irq_fd->fd == fd) && (irq_fd->type == type)) { | 160 | if ((irq_fd->fd == fd) && (irq_fd->type == type)) { |
172 | printk("Registering fd %d twice\n", fd); | 161 | printk("Registering fd %d twice\n", fd); |
@@ -199,7 +188,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
199 | * so we will not be able to put new pollfd struct to pollfds | 188 | * so we will not be able to put new pollfd struct to pollfds |
200 | * then we free the buffer tmp_fds and try again. | 189 | * then we free the buffer tmp_fds and try again. |
201 | */ | 190 | */ |
202 | irq_unlock(flags); | 191 | spin_unlock_irqrestore(&irq_lock, flags); |
203 | kfree(tmp_pfd); | 192 | kfree(tmp_pfd); |
204 | tmp_pfd = NULL; | 193 | tmp_pfd = NULL; |
205 | 194 | ||
@@ -207,24 +196,24 @@ int activate_fd(int irq, int fd, int type, void *dev_id) | |||
207 | if (tmp_pfd == NULL) | 196 | if (tmp_pfd == NULL) |
208 | goto out_kfree; | 197 | goto out_kfree; |
209 | 198 | ||
210 | flags = irq_lock(); | 199 | spin_lock_irqsave(&irq_lock, flags); |
211 | } | 200 | } |
212 | /*-------------*/ | 201 | /*-------------*/ |
213 | 202 | ||
214 | *last_irq_ptr = new_fd; | 203 | *last_irq_ptr = new_fd; |
215 | last_irq_ptr = &new_fd->next; | 204 | last_irq_ptr = &new_fd->next; |
216 | 205 | ||
217 | irq_unlock(flags); | 206 | spin_unlock_irqrestore(&irq_lock, flags); |
218 | 207 | ||
219 | /* This calls activate_fd, so it has to be outside the critical | 208 | /* This calls activate_fd, so it has to be outside the critical |
220 | * section. | 209 | * section. |
221 | */ | 210 | */ |
222 | maybe_sigio_broken(fd, type); | 211 | maybe_sigio_broken(fd, (type == IRQ_READ)); |
223 | 212 | ||
224 | return(0); | 213 | return(0); |
225 | 214 | ||
226 | out_unlock: | 215 | out_unlock: |
227 | irq_unlock(flags); | 216 | spin_unlock_irqrestore(&irq_lock, flags); |
228 | out_kfree: | 217 | out_kfree: |
229 | kfree(new_fd); | 218 | kfree(new_fd); |
230 | out: | 219 | out: |
@@ -235,9 +224,9 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) | |||
235 | { | 224 | { |
236 | unsigned long flags; | 225 | unsigned long flags; |
237 | 226 | ||
238 | flags = irq_lock(); | 227 | spin_lock_irqsave(&irq_lock, flags); |
239 | os_free_irq_by_cb(test, arg, active_fds, &last_irq_ptr); | 228 | os_free_irq_by_cb(test, arg, active_fds, &last_irq_ptr); |
240 | irq_unlock(flags); | 229 | spin_unlock_irqrestore(&irq_lock, flags); |
241 | } | 230 | } |
242 | 231 | ||
243 | struct irq_and_dev { | 232 | struct irq_and_dev { |
@@ -304,19 +293,19 @@ void reactivate_fd(int fd, int irqnum) | |||
304 | unsigned long flags; | 293 | unsigned long flags; |
305 | int i; | 294 | int i; |
306 | 295 | ||
307 | flags = irq_lock(); | 296 | spin_lock_irqsave(&irq_lock, flags); |
308 | irq = find_irq_by_fd(fd, irqnum, &i); | 297 | irq = find_irq_by_fd(fd, irqnum, &i); |
309 | if (irq == NULL) { | 298 | if (irq == NULL) { |
310 | irq_unlock(flags); | 299 | spin_unlock_irqrestore(&irq_lock, flags); |
311 | return; | 300 | return; |
312 | } | 301 | } |
313 | os_set_pollfd(i, irq->fd); | 302 | os_set_pollfd(i, irq->fd); |
314 | irq_unlock(flags); | 303 | spin_unlock_irqrestore(&irq_lock, flags); |
315 | 304 | ||
316 | /* This calls activate_fd, so it has to be outside the critical | 305 | /* This calls activate_fd, so it has to be outside the critical |
317 | * section. | 306 | * section. |
318 | */ | 307 | */ |
319 | maybe_sigio_broken(fd, irq->type); | 308 | maybe_sigio_broken(fd, (irq->type == IRQ_READ)); |
320 | } | 309 | } |
321 | 310 | ||
322 | void deactivate_fd(int fd, int irqnum) | 311 | void deactivate_fd(int fd, int irqnum) |
@@ -325,13 +314,13 @@ void deactivate_fd(int fd, int irqnum) | |||
325 | unsigned long flags; | 314 | unsigned long flags; |
326 | int i; | 315 | int i; |
327 | 316 | ||
328 | flags = irq_lock(); | 317 | spin_lock_irqsave(&irq_lock, flags); |
329 | irq = find_irq_by_fd(fd, irqnum, &i); | 318 | irq = find_irq_by_fd(fd, irqnum, &i); |
330 | if (irq == NULL) | 319 | if (irq == NULL) |
331 | goto out; | 320 | goto out; |
332 | os_set_pollfd(i, -1); | 321 | os_set_pollfd(i, -1); |
333 | out: | 322 | out: |
334 | irq_unlock(flags); | 323 | spin_unlock_irqrestore(&irq_lock, flags); |
335 | } | 324 | } |
336 | 325 | ||
337 | int deactivate_all_fds(void) | 326 | int deactivate_all_fds(void) |
@@ -350,13 +339,14 @@ int deactivate_all_fds(void) | |||
350 | return 0; | 339 | return 0; |
351 | } | 340 | } |
352 | 341 | ||
342 | #ifdef CONFIG_MODE_TT | ||
353 | void forward_interrupts(int pid) | 343 | void forward_interrupts(int pid) |
354 | { | 344 | { |
355 | struct irq_fd *irq; | 345 | struct irq_fd *irq; |
356 | unsigned long flags; | 346 | unsigned long flags; |
357 | int err; | 347 | int err; |
358 | 348 | ||
359 | flags = irq_lock(); | 349 | spin_lock_irqsave(&irq_lock, flags); |
360 | for (irq = active_fds; irq != NULL; irq = irq->next) { | 350 | for (irq = active_fds; irq != NULL; irq = irq->next) { |
361 | err = os_set_owner(irq->fd, pid); | 351 | err = os_set_owner(irq->fd, pid); |
362 | if (err < 0) { | 352 | if (err < 0) { |
@@ -369,8 +359,9 @@ void forward_interrupts(int pid) | |||
369 | 359 | ||
370 | irq->pid = pid; | 360 | irq->pid = pid; |
371 | } | 361 | } |
372 | irq_unlock(flags); | 362 | spin_unlock_irqrestore(&irq_lock, flags); |
373 | } | 363 | } |
364 | #endif | ||
374 | 365 | ||
375 | /* | 366 | /* |
376 | * do_IRQ handles all normal device IRQ's (the special | 367 | * do_IRQ handles all normal device IRQ's (the special |
@@ -403,21 +394,6 @@ int um_request_irq(unsigned int irq, int fd, int type, | |||
403 | EXPORT_SYMBOL(um_request_irq); | 394 | EXPORT_SYMBOL(um_request_irq); |
404 | EXPORT_SYMBOL(reactivate_fd); | 395 | EXPORT_SYMBOL(reactivate_fd); |
405 | 396 | ||
406 | static DEFINE_SPINLOCK(irq_spinlock); | ||
407 | |||
408 | unsigned long irq_lock(void) | ||
409 | { | ||
410 | unsigned long flags; | ||
411 | |||
412 | spin_lock_irqsave(&irq_spinlock, flags); | ||
413 | return flags; | ||
414 | } | ||
415 | |||
416 | void irq_unlock(unsigned long flags) | ||
417 | { | ||
418 | spin_unlock_irqrestore(&irq_spinlock, flags); | ||
419 | } | ||
420 | |||
421 | /* hw_interrupt_type must define (startup || enable) && | 397 | /* hw_interrupt_type must define (startup || enable) && |
422 | * (shutdown || disable) && end */ | 398 | * (shutdown || disable) && end */ |
423 | static void dummy(unsigned int irq) | 399 | static void dummy(unsigned int irq) |