aboutsummaryrefslogtreecommitdiff
path: root/arch/um/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/drivers')
-rw-r--r--arch/um/drivers/chan_user.c1
-rw-r--r--arch/um/drivers/cow_sys.h2
-rw-r--r--arch/um/drivers/daemon_user.c4
-rw-r--r--arch/um/drivers/fd.c2
-rw-r--r--arch/um/drivers/hostaudio_kern.c2
-rw-r--r--arch/um/drivers/mcast_user.c3
-rw-r--r--arch/um/drivers/net_user.c2
-rw-r--r--arch/um/drivers/pcap_user.c2
-rw-r--r--arch/um/drivers/port_user.c2
-rw-r--r--arch/um/drivers/pty.c2
-rw-r--r--arch/um/drivers/random.c122
-rw-r--r--arch/um/drivers/slip_user.c2
-rw-r--r--arch/um/drivers/tty.c2
-rw-r--r--arch/um/drivers/ubd_kern.c5
-rw-r--r--arch/um/drivers/xterm.c2
15 files changed, 96 insertions, 59 deletions
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 025764089ac..cfeb3f4a44a 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -11,6 +11,7 @@
#include <termios.h>
#include <sys/ioctl.h>
#include "chan_user.h"
+#include "kern_constants.h"
#include "os.h"
#include "um_malloc.h"
#include "user.h"
diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h
index ca8c9e11a39..f5701fd2ef9 100644
--- a/arch/um/drivers/cow_sys.h
+++ b/arch/um/drivers/cow_sys.h
@@ -8,7 +8,7 @@
static inline void *cow_malloc(int size)
{
- return kmalloc(size, UM_GFP_KERNEL);
+ return uml_kmalloc(size, UM_GFP_KERNEL);
}
static inline void cow_free(void *ptr)
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index f23c109a055..f8e85e0bdac 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -34,7 +34,7 @@ static struct sockaddr_un *new_addr(void *name, int len)
{
struct sockaddr_un *sun;
- sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
+ sun = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
if (sun == NULL) {
printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un "
"failed\n");
@@ -83,7 +83,7 @@ static int connect_to_switch(struct daemon_data *pri)
goto out_close;
}
- sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
+ sun = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
if (sun == NULL) {
printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un "
"failed\n");
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index 0a2bb5b64b8..f5a981a1624 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -40,7 +40,7 @@ static void *fd_init(char *str, int device, const struct chan_opts *opts)
return NULL;
}
- data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
+ data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
if (data == NULL)
return NULL;
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index ff1b22b69e9..368219cc236 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -154,7 +154,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
case SNDCTL_DSP_SUBDIVIDE:
case SNDCTL_DSP_SETFRAGMENT:
if (get_user(data, (int __user *) arg))
- return EFAULT;
+ return -EFAULT;
break;
default:
break;
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index 5f647d7a729..ee19e91568a 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -15,6 +15,7 @@
#include <unistd.h>
#include <errno.h>
#include <netinet/in.h>
+#include "kern_constants.h"
#include "mcast.h"
#include "net_user.h"
#include "um_malloc.h"
@@ -24,7 +25,7 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port)
{
struct sockaddr_in *sin;
- sin = kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL);
+ sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL);
if (sin == NULL) {
printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in "
"failed\n");
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index abf2653f551..9415dd9e63e 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -222,7 +222,7 @@ static void change(char *dev, char *what, unsigned char *addr,
netmask[2], netmask[3]);
output_len = UM_KERN_PAGE_SIZE;
- output = kmalloc(output_len, UM_GFP_KERNEL);
+ output = uml_kmalloc(output_len, UM_GFP_KERNEL);
if (output == NULL)
printk(UM_KERN_ERR "change : failed to allocate output "
"buffer\n");
diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c
index e9809356c53..5f903587d69 100644
--- a/arch/um/drivers/pcap_user.c
+++ b/arch/um/drivers/pcap_user.c
@@ -50,7 +50,7 @@ static int pcap_open(void *data)
return -EIO;
}
- pri->compiled = kmalloc(sizeof(struct bpf_program),
+ pri->compiled = uml_kmalloc(sizeof(struct bpf_program),
UM_GFP_KERNEL);
if (pri->compiled == NULL) {
printk(UM_KERN_ERR "pcap_open : kmalloc failed\n");
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index d269ca387f1..b49bf56a56a 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -47,7 +47,7 @@ static void *port_init(char *str, int device, const struct chan_opts *opts)
if (kern_data == NULL)
return NULL;
- data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
+ data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
if (data == NULL)
goto err;
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index 49c79dda604..1113911dcb2 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -29,7 +29,7 @@ static void *pty_chan_init(char *str, int device, const struct chan_opts *opts)
{
struct pty_chan *data;
- data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
+ data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
if (data == NULL)
return NULL;
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index 71f0959c153..4949044773b 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2005 Jeff Dike <jdike@addtoit.com> */
+/* Copyright (C) 2005 - 2008 Jeff Dike <jdike@{linux.intel,addtoit}.com> */
+
/* Much of this ripped from drivers/char/hw_random.c, see there for other
* copyright.
*
@@ -8,16 +9,18 @@
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/fs.h>
+#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
+#include "irq_kern.h"
#include "os.h"
/*
* core module and version information
*/
#define RNG_VERSION "1.0.0"
-#define RNG_MODULE_NAME "random"
+#define RNG_MODULE_NAME "hw_random"
#define RNG_MISCDEV_MINOR 183 /* official */
@@ -26,47 +29,67 @@
* protects against a module being loaded twice at the same time.
*/
static int random_fd = -1;
+static DECLARE_WAIT_QUEUE_HEAD(host_read_wait);
static int rng_dev_open (struct inode *inode, struct file *filp)
{
/* enforce read-only access to this chrdev */
if ((filp->f_mode & FMODE_READ) == 0)
return -EINVAL;
- if (filp->f_mode & FMODE_WRITE)
+ if ((filp->f_mode & FMODE_WRITE) != 0)
return -EINVAL;
return 0;
}
+static atomic_t host_sleep_count = ATOMIC_INIT(0);
+
static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
- loff_t * offp)
+ loff_t *offp)
{
- u32 data;
- int n, ret = 0, have_data;
-
- while(size){
- n = os_read_file(random_fd, &data, sizeof(data));
- if(n > 0){
- have_data = n;
- while (have_data && size) {
- if (put_user((u8)data, buf++)) {
- ret = ret ? : -EFAULT;
- break;
- }
- size--;
- ret++;
- have_data--;
- data>>=8;
- }
- }
- else if(n == -EAGAIN){
- if (filp->f_flags & O_NONBLOCK)
- return ret ? : -EAGAIN;
-
- if(need_resched())
- schedule_timeout_interruptible(1);
- }
- else return n;
+ u32 data;
+ int n, ret = 0, have_data;
+
+ while (size) {
+ n = os_read_file(random_fd, &data, sizeof(data));
+ if (n > 0) {
+ have_data = n;
+ while (have_data && size) {
+ if (put_user((u8) data, buf++)) {
+ ret = ret ? : -EFAULT;
+ break;
+ }
+ size--;
+ ret++;
+ have_data--;
+ data >>= 8;
+ }
+ }
+ else if (n == -EAGAIN) {
+ DECLARE_WAITQUEUE(wait, current);
+
+ if (filp->f_flags & O_NONBLOCK)
+ return ret ? : -EAGAIN;
+
+ atomic_inc(&host_sleep_count);
+ reactivate_fd(random_fd, RANDOM_IRQ);
+ add_sigio_fd(random_fd);
+
+ add_wait_queue(&host_read_wait, &wait);
+ set_task_state(current, TASK_INTERRUPTIBLE);
+
+ schedule();
+ set_task_state(current, TASK_RUNNING);
+ remove_wait_queue(&host_read_wait, &wait);
+
+ if (atomic_dec_and_test(&host_sleep_count)) {
+ ignore_sigio_fd(random_fd);
+ deactivate_fd(random_fd, RANDOM_IRQ);
+ }
+ }
+ else
+ return n;
+
if (signal_pending (current))
return ret ? : -ERESTARTSYS;
}
@@ -86,6 +109,13 @@ static struct miscdevice rng_miscdev = {
&rng_chrdev_ops,
};
+static irqreturn_t random_interrupt(int irq, void *data)
+{
+ wake_up(&host_read_wait);
+
+ return IRQ_HANDLED;
+}
+
/*
* rng_init - initialize RNG module
*/
@@ -93,28 +123,33 @@ static int __init rng_init (void)
{
int err;
- err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0);
- if(err < 0)
- goto out;
+ err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0);
+ if (err < 0)
+ goto out;
- random_fd = err;
+ random_fd = err;
- err = os_set_fd_block(random_fd, 0);
- if(err)
+ err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,
+ IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random",
+ NULL);
+ if (err)
goto err_out_cleanup_hw;
+ sigio_broken(random_fd, 1);
+
err = misc_register (&rng_miscdev);
if (err) {
- printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n");
+ printk (KERN_ERR RNG_MODULE_NAME ": misc device register "
+ "failed\n");
goto err_out_cleanup_hw;
}
+out:
+ return err;
- out:
- return err;
-
- err_out_cleanup_hw:
- random_fd = -1;
- goto out;
+err_out_cleanup_hw:
+ os_close_file(random_fd);
+ random_fd = -1;
+ goto out;
}
/*
@@ -122,6 +157,7 @@ static int __init rng_init (void)
*/
static void __exit rng_cleanup (void)
{
+ os_close_file(random_fd);
misc_deregister (&rng_miscdev);
}
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index 8b80505a3fb..a1c2d2c98a9 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -96,7 +96,7 @@ static int slip_tramp(char **argv, int fd)
pid = err;
output_len = UM_KERN_PAGE_SIZE;
- output = kmalloc(output_len, UM_GFP_KERNEL);
+ output = uml_kmalloc(output_len, UM_GFP_KERNEL);
if (output == NULL) {
printk(UM_KERN_ERR "slip_tramp : failed to allocate output "
"buffer\n");
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index c930fedc517..495858a090e 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -29,7 +29,7 @@ static void *tty_chan_init(char *str, int device, const struct chan_opts *opts)
}
str++;
- data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
+ data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
if (data == NULL)
return NULL;
*data = ((struct tty_chan) { .dev = str,
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 5e45e39a8a8..b58fb8941d8 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -49,7 +49,6 @@
#include "irq_user.h"
#include "irq_kern.h"
#include "ubd_user.h"
-#include "kern_util.h"
#include "os.h"
#include "mem.h"
#include "mem_kern.h"
@@ -1178,8 +1177,8 @@ static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
* by one word. Thanks to Lynn Kerby for the fix and James McMechan
* for the original diagnosis.
*/
- if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) /
- sizeof(unsigned long) - 1))
+ if (*cow_offset == (DIV_ROUND_UP(bitmap_len,
+ sizeof(unsigned long)) - 1))
(*cow_offset)--;
bitmap_words[0] = bitmap[*cow_offset];
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 8a1c18a9b24..da2caa5a21e 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -30,7 +30,7 @@ static void *xterm_init(char *str, int device, const struct chan_opts *opts)
{
struct xterm_chan *data;
- data = kmalloc(sizeof(*data), UM_GFP_KERNEL);
+ data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
if (data == NULL)
return NULL;
*data = ((struct xterm_chan) { .pid = -1,