aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/drivers/random.c41
-rw-r--r--arch/um/include/os.h1
-rw-r--r--arch/um/include/process.h16
-rw-r--r--arch/um/os-Linux/sigio.c35
-rw-r--r--include/asm-um/irq.h3
5 files changed, 65 insertions, 31 deletions
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index 71f0959c1535..f92b7c81eb00 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -8,16 +8,18 @@
8#include <linux/sched.h> 8#include <linux/sched.h>
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/fs.h> 10#include <linux/fs.h>
11#include <linux/interrupt.h>
11#include <linux/miscdevice.h> 12#include <linux/miscdevice.h>
12#include <linux/delay.h> 13#include <linux/delay.h>
13#include <asm/uaccess.h> 14#include <asm/uaccess.h>
15#include "irq_kern.h"
14#include "os.h" 16#include "os.h"
15 17
16/* 18/*
17 * core module and version information 19 * core module and version information
18 */ 20 */
19#define RNG_VERSION "1.0.0" 21#define RNG_VERSION "1.0.0"
20#define RNG_MODULE_NAME "random" 22#define RNG_MODULE_NAME "hw_random"
21 23
22#define RNG_MISCDEV_MINOR 183 /* official */ 24#define RNG_MISCDEV_MINOR 183 /* official */
23 25
@@ -26,6 +28,7 @@
26 * protects against a module being loaded twice at the same time. 28 * protects against a module being loaded twice at the same time.
27 */ 29 */
28static int random_fd = -1; 30static int random_fd = -1;
31static DECLARE_WAIT_QUEUE_HEAD(host_read_wait);
29 32
30static int rng_dev_open (struct inode *inode, struct file *filp) 33static int rng_dev_open (struct inode *inode, struct file *filp)
31{ 34{
@@ -38,6 +41,8 @@ static int rng_dev_open (struct inode *inode, struct file *filp)
38 return 0; 41 return 0;
39} 42}
40 43
44static atomic_t host_sleep_count = ATOMIC_INIT(0);
45
41static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, 46static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
42 loff_t * offp) 47 loff_t * offp)
43{ 48{
@@ -60,11 +65,26 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
60 } 65 }
61 } 66 }
62 else if(n == -EAGAIN){ 67 else if(n == -EAGAIN){
68 DECLARE_WAITQUEUE(wait, current);
69
63 if (filp->f_flags & O_NONBLOCK) 70 if (filp->f_flags & O_NONBLOCK)
64 return ret ? : -EAGAIN; 71 return ret ? : -EAGAIN;
65 72
66 if(need_resched()) 73 atomic_inc(&host_sleep_count);
67 schedule_timeout_interruptible(1); 74 reactivate_fd(random_fd, RANDOM_IRQ);
75 add_sigio_fd(random_fd);
76
77 add_wait_queue(&host_read_wait, &wait);
78 set_task_state(current, TASK_INTERRUPTIBLE);
79
80 schedule();
81 set_task_state(current, TASK_RUNNING);
82 remove_wait_queue(&host_read_wait, &wait);
83
84 if (atomic_dec_and_test(&host_sleep_count)) {
85 ignore_sigio_fd(random_fd);
86 deactivate_fd(random_fd, RANDOM_IRQ);
87 }
68 } 88 }
69 else return n; 89 else return n;
70 if (signal_pending (current)) 90 if (signal_pending (current))
@@ -86,6 +106,13 @@ static struct miscdevice rng_miscdev = {
86 &rng_chrdev_ops, 106 &rng_chrdev_ops,
87}; 107};
88 108
109static irqreturn_t random_interrupt(int irq, void *data)
110{
111 wake_up(&host_read_wait);
112
113 return IRQ_HANDLED;
114}
115
89/* 116/*
90 * rng_init - initialize RNG module 117 * rng_init - initialize RNG module
91 */ 118 */
@@ -99,10 +126,14 @@ static int __init rng_init (void)
99 126
100 random_fd = err; 127 random_fd = err;
101 128
102 err = os_set_fd_block(random_fd, 0); 129 err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,
130 IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random",
131 NULL);
103 if(err) 132 if(err)
104 goto err_out_cleanup_hw; 133 goto err_out_cleanup_hw;
105 134
135 sigio_broken(random_fd, 1);
136
106 err = misc_register (&rng_miscdev); 137 err = misc_register (&rng_miscdev);
107 if (err) { 138 if (err) {
108 printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n"); 139 printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n");
@@ -113,6 +144,7 @@ static int __init rng_init (void)
113 return err; 144 return err;
114 145
115 err_out_cleanup_hw: 146 err_out_cleanup_hw:
147 os_close_file(random_fd);
116 random_fd = -1; 148 random_fd = -1;
117 goto out; 149 goto out;
118} 150}
@@ -122,6 +154,7 @@ static int __init rng_init (void)
122 */ 154 */
123static void __exit rng_cleanup (void) 155static void __exit rng_cleanup (void)
124{ 156{
157 os_close_file(random_fd);
125 misc_deregister (&rng_miscdev); 158 misc_deregister (&rng_miscdev);
126} 159}
127 160
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 32c799e3a495..e2716ac8889a 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -290,6 +290,7 @@ extern void os_set_ioignore(void);
290extern int add_sigio_fd(int fd); 290extern int add_sigio_fd(int fd);
291extern int ignore_sigio_fd(int fd); 291extern int ignore_sigio_fd(int fd);
292extern void maybe_sigio_broken(int fd, int read); 292extern void maybe_sigio_broken(int fd, int read);
293extern void sigio_broken(int fd, int read);
293 294
294/* sys-x86_64/prctl.c */ 295/* sys-x86_64/prctl.c */
295extern int os_arch_prctl(int pid, int code, unsigned long *addr); 296extern int os_arch_prctl(int pid, int code, unsigned long *addr);
diff --git a/arch/um/include/process.h b/arch/um/include/process.h
index 5af9157ff54f..838b4802ce53 100644
--- a/arch/um/include/process.h
+++ b/arch/um/include/process.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
@@ -8,18 +8,10 @@
8 8
9#include <signal.h> 9#include <signal.h>
10 10
11/* Copied from linux/compiler-gcc.h since we can't include it directly */
12#define barrier() __asm__ __volatile__("": : :"memory")
13
11extern void sig_handler(int sig, struct sigcontext sc); 14extern void sig_handler(int sig, struct sigcontext sc);
12extern void alarm_handler(int sig, struct sigcontext sc); 15extern void alarm_handler(int sig, struct sigcontext sc);
13 16
14#endif 17#endif
15
16/*
17 * Overrides for Emacs so that we follow Linus's tabbing style.
18 * Emacs will notice this stuff at the end of the file and automatically
19 * adjust the settings for this buffer only. This must remain at the end
20 * of the file.
21 * ---------------------------------------------------------------------------
22 * Local variables:
23 * c-file-style: "linux"
24 * End:
25 */
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 0578481983c4..eb8f2e4be192 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 2 * Copyright (C) 2002 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
@@ -15,6 +15,7 @@
15#include "kern_util.h" 15#include "kern_util.h"
16#include "init.h" 16#include "init.h"
17#include "os.h" 17#include "os.h"
18#include "process.h"
18#include "sigio.h" 19#include "sigio.h"
19#include "um_malloc.h" 20#include "um_malloc.h"
20#include "user.h" 21#include "user.h"
@@ -338,20 +339,10 @@ out_close1:
338 close(l_write_sigio_fds[1]); 339 close(l_write_sigio_fds[1]);
339} 340}
340 341
341/* Changed during early boot */ 342void sigio_broken(int fd, int read)
342static int pty_output_sigio = 0;
343static int pty_close_sigio = 0;
344
345void maybe_sigio_broken(int fd, int read)
346{ 343{
347 int err; 344 int err;
348 345
349 if (!isatty(fd))
350 return;
351
352 if ((read || pty_output_sigio) && (!read || pty_close_sigio))
353 return;
354
355 write_sigio_workaround(); 346 write_sigio_workaround();
356 347
357 sigio_lock(); 348 sigio_lock();
@@ -370,6 +361,21 @@ out:
370 sigio_unlock(); 361 sigio_unlock();
371} 362}
372 363
364/* Changed during early boot */
365static int pty_output_sigio;
366static int pty_close_sigio;
367
368void maybe_sigio_broken(int fd, int read)
369{
370 if (!isatty(fd))
371 return;
372
373 if ((read || pty_output_sigio) && (!read || pty_close_sigio))
374 return;
375
376 sigio_broken(fd, read);
377}
378
373static void sigio_cleanup(void) 379static void sigio_cleanup(void)
374{ 380{
375 if (write_sigio_pid == -1) 381 if (write_sigio_pid == -1)
@@ -383,7 +389,7 @@ static void sigio_cleanup(void)
383__uml_exitcall(sigio_cleanup); 389__uml_exitcall(sigio_cleanup);
384 390
385/* Used as a flag during SIGIO testing early in boot */ 391/* Used as a flag during SIGIO testing early in boot */
386static volatile int got_sigio = 0; 392static int got_sigio;
387 393
388static void __init handler(int sig) 394static void __init handler(int sig)
389{ 395{
@@ -498,7 +504,8 @@ static void tty_output(int master, int slave)
498 if (errno != EAGAIN) 504 if (errno != EAGAIN)
499 printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n", 505 printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n",
500 errno); 506 errno);
501 while (((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) 507 while (((n = read(slave, buf, sizeof(buf))) > 0) &&
508 !({ barrier(); got_sigio; }))
502 ; 509 ;
503 510
504 if (got_sigio) { 511 if (got_sigio) {
diff --git a/include/asm-um/irq.h b/include/asm-um/irq.h
index de389a477cdd..4a2037f8204b 100644
--- a/include/asm-um/irq.h
+++ b/include/asm-um/irq.h
@@ -15,8 +15,9 @@
15#define SIGIO_WRITE_IRQ 11 15#define SIGIO_WRITE_IRQ 11
16#define TELNETD_IRQ 12 16#define TELNETD_IRQ 12
17#define XTERM_IRQ 13 17#define XTERM_IRQ 13
18#define RANDOM_IRQ 14
18 19
19#define LAST_IRQ XTERM_IRQ 20#define LAST_IRQ RANDOM_IRQ
20#define NR_IRQS (LAST_IRQ + 1) 21#define NR_IRQS (LAST_IRQ + 1)
21 22
22#endif 23#endif