diff options
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/drivers/harddog_kern.c | 2 | ||||
-rw-r--r-- | arch/um/drivers/hostaudio_kern.c | 2 | ||||
-rw-r--r-- | arch/um/drivers/mconsole_kern.c | 2 | ||||
-rw-r--r-- | arch/um/drivers/mmapper_kern.c | 2 | ||||
-rw-r--r-- | arch/um/drivers/random.c | 2 | ||||
-rw-r--r-- | arch/um/drivers/ubd.h | 5 | ||||
-rw-r--r-- | arch/um/drivers/ubd_kern.c | 168 | ||||
-rw-r--r-- | arch/um/drivers/ubd_user.c | 21 | ||||
-rw-r--r-- | arch/um/kernel/exec.c | 2 | ||||
-rw-r--r-- | arch/um/kernel/exitcode.c | 2 | ||||
-rw-r--r-- | arch/um/kernel/process.c | 2 | ||||
-rw-r--r-- | arch/um/kernel/ptrace.c | 2 | ||||
-rw-r--r-- | arch/um/kernel/syscall.c | 2 | ||||
-rw-r--r-- | arch/um/kernel/time.c | 2 |
14 files changed, 178 insertions, 38 deletions
diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index 3282787bbcfb..6d381279b362 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c @@ -45,7 +45,7 @@ #include <linux/mutex.h> #include <linux/init.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include "mconsole.h" MODULE_LICENSE("GPL"); diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index 3a4b58730f5f..12bdb5996bf5 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c @@ -9,7 +9,7 @@ #include <linux/sound.h> #include <linux/soundcard.h> #include <linux/mutex.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <init.h> #include <os.h> diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 8a6b57108ac2..8a4c72af3bc0 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -24,7 +24,7 @@ #include <linux/fs.h> #include <linux/mount.h> #include <linux/file.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/switch_to.h> #include <init.h> diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index 62145c276167..3645fcb2a787 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c @@ -17,7 +17,7 @@ #include <linux/module.h> #include <linux/mm.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <mem_user.h> /* These are set in mmapper_init, which is called at boot time */ diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index dd16c902ff70..05523f14d7b2 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c @@ -12,7 +12,7 @@ #include <linux/interrupt.h> #include <linux/miscdevice.h> #include <linux/delay.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <irq_kern.h> #include <os.h> diff --git a/arch/um/drivers/ubd.h b/arch/um/drivers/ubd.h index 3b48cd2081ee..cc1cc85f5afc 100644 --- a/arch/um/drivers/ubd.h +++ b/arch/um/drivers/ubd.h @@ -11,5 +11,10 @@ extern int start_io_thread(unsigned long sp, int *fds_out); extern int io_thread(void *arg); extern int kernel_fd; +extern int ubd_read_poll(int timeout); +extern int ubd_write_poll(int timeout); + +#define UBD_REQ_BUFFER_SIZE 64 + #endif diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index f3540270d096..85410279beab 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2015-2016 Anton Ivanov (aivanov@brocade.com) * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -58,6 +59,17 @@ struct io_thread_req { int error; }; + +static struct io_thread_req * (*irq_req_buffer)[]; +static struct io_thread_req *irq_remainder; +static int irq_remainder_size; + +static struct io_thread_req * (*io_req_buffer)[]; +static struct io_thread_req *io_remainder; +static int io_remainder_size; + + + static inline int ubd_test_bit(__u64 bit, unsigned char *data) { __u64 n; @@ -442,29 +454,91 @@ static void do_ubd_request(struct request_queue * q); static int thread_fd = -1; static LIST_HEAD(restart); -/* XXX - move this inside ubd_intr. */ +/* Function to read several request pointers at a time +* handling fractional reads if (and as) needed +*/ + +static int bulk_req_safe_read( + int fd, + struct io_thread_req * (*request_buffer)[], + struct io_thread_req **remainder, + int *remainder_size, + int max_recs + ) +{ + int n = 0; + int res = 0; + + if (*remainder_size > 0) { + memmove( + (char *) request_buffer, + (char *) remainder, *remainder_size + ); + n = *remainder_size; + } + + res = os_read_file( + fd, + ((char *) request_buffer) + *remainder_size, + sizeof(struct io_thread_req *)*max_recs + - *remainder_size + ); + if (res > 0) { + n += res; + if ((n % sizeof(struct io_thread_req *)) > 0) { + /* + * Read somehow returned not a multiple of dword + * theoretically possible, but never observed in the + * wild, so read routine must be able to handle it + */ + *remainder_size = n % sizeof(struct io_thread_req *); + WARN(*remainder_size > 0, "UBD IPC read returned a partial result"); + memmove( + remainder, + ((char *) request_buffer) + + (n/sizeof(struct io_thread_req *))*sizeof(struct io_thread_req *), + *remainder_size + ); + n = n - *remainder_size; + } + } else { + n = res; + } + return n; +} + /* Called without dev->lock held, and only in interrupt context. */ static void ubd_handler(void) { - struct io_thread_req *req; struct ubd *ubd; struct list_head *list, *next_ele; unsigned long flags; int n; + int count; while(1){ - n = os_read_file(thread_fd, &req, - sizeof(struct io_thread_req *)); - if(n != sizeof(req)){ + n = bulk_req_safe_read( + thread_fd, + irq_req_buffer, + &irq_remainder, + &irq_remainder_size, + UBD_REQ_BUFFER_SIZE + ); + if (n < 0) { if(n == -EAGAIN) break; printk(KERN_ERR "spurious interrupt in ubd_handler, " "err = %d\n", -n); return; } - - blk_end_request(req->req, 0, req->length); - kfree(req); + for (count = 0; count < n/sizeof(struct io_thread_req *); count++) { + blk_end_request( + (*irq_req_buffer)[count]->req, + 0, + (*irq_req_buffer)[count]->length + ); + kfree((*irq_req_buffer)[count]); + } } reactivate_fd(thread_fd, UBD_IRQ); @@ -1064,6 +1138,28 @@ static int __init ubd_init(void) if (register_blkdev(fake_major, "ubd")) return -1; } + + irq_req_buffer = kmalloc( + sizeof(struct io_thread_req *) * UBD_REQ_BUFFER_SIZE, + GFP_KERNEL + ); + irq_remainder = 0; + + if (irq_req_buffer == NULL) { + printk(KERN_ERR "Failed to initialize ubd buffering\n"); + return -1; + } + io_req_buffer = kmalloc( + sizeof(struct io_thread_req *) * UBD_REQ_BUFFER_SIZE, + GFP_KERNEL + ); + + io_remainder = 0; + + if (io_req_buffer == NULL) { + printk(KERN_ERR "Failed to initialize ubd buffering\n"); + return -1; + } platform_driver_register(&ubd_driver); mutex_lock(&ubd_lock); for (i = 0; i < MAX_DEV; i++){ @@ -1458,31 +1554,51 @@ static int io_count = 0; int io_thread(void *arg) { - struct io_thread_req *req; - int n; + int n, count, written, res; os_fix_helper_signals(); while(1){ - n = os_read_file(kernel_fd, &req, - sizeof(struct io_thread_req *)); - if(n != sizeof(struct io_thread_req *)){ - if(n < 0) + n = bulk_req_safe_read( + kernel_fd, + io_req_buffer, + &io_remainder, + &io_remainder_size, + UBD_REQ_BUFFER_SIZE + ); + if (n < 0) { + if (n == -EAGAIN) { + ubd_read_poll(-1); + continue; + } else { printk("io_thread - read failed, fd = %d, " - "err = %d\n", kernel_fd, -n); - else { - printk("io_thread - short read, fd = %d, " - "length = %d\n", kernel_fd, n); + "err = %d," + "reminder = %d\n", + kernel_fd, -n, io_remainder_size); } - continue; } - io_count++; - do_io(req); - n = os_write_file(kernel_fd, &req, - sizeof(struct io_thread_req *)); - if(n != sizeof(struct io_thread_req *)) - printk("io_thread - write failed, fd = %d, err = %d\n", - kernel_fd, -n); + + for (count = 0; count < n/sizeof(struct io_thread_req *); count++) { + io_count++; + do_io((*io_req_buffer)[count]); + } + + written = 0; + + do { + res = os_write_file(kernel_fd, ((char *) io_req_buffer) + written, n); + if (res > 0) { + written += res; + } else { + if (res != -EAGAIN) { + printk("io_thread - read failed, fd = %d, " + "err = %d\n", kernel_fd, -n); + } + } + if (written < n) { + ubd_write_poll(-1); + } + } while (written < n); } return 0; diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c index e376f9b9c68d..6f744794d141 100644 --- a/arch/um/drivers/ubd_user.c +++ b/arch/um/drivers/ubd_user.c @@ -1,4 +1,5 @@ -/* +/* + * Copyright (C) 2016 Anton Ivanov (aivanov@brocade.com) * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com) * Licensed under the GPL @@ -20,6 +21,9 @@ #include "ubd.h" #include <os.h> +#include <poll.h> + +struct pollfd kernel_pollfd; int start_io_thread(unsigned long sp, int *fd_out) { @@ -32,9 +36,12 @@ int start_io_thread(unsigned long sp, int *fd_out) } kernel_fd = fds[0]; + kernel_pollfd.fd = kernel_fd; + kernel_pollfd.events = POLLIN; *fd_out = fds[1]; err = os_set_fd_block(*fd_out, 0); + err = os_set_fd_block(kernel_fd, 0); if (err) { printk("start_io_thread - failed to set nonblocking I/O.\n"); goto out_close; @@ -57,3 +64,15 @@ int start_io_thread(unsigned long sp, int *fd_out) out: return err; } + +int ubd_read_poll(int timeout) +{ + kernel_pollfd.events = POLLIN; + return poll(&kernel_pollfd, 1, timeout); +} +int ubd_write_poll(int timeout) +{ + kernel_pollfd.events = POLLOUT; + return poll(&kernel_pollfd, 1, timeout); +} + diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 0d7103c9eff3..770ec07b6a6a 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@ -11,7 +11,7 @@ #include <linux/slab.h> #include <asm/current.h> #include <asm/processor.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <as-layout.h> #include <mem_user.h> #include <skas.h> diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c index 41ebbfebb333..546302e3b7fb 100644 --- a/arch/um/kernel/exitcode.c +++ b/arch/um/kernel/exitcode.c @@ -10,7 +10,7 @@ #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/types.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> /* * If read and write race, the read will still atomically read a valid diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 034b42c7ab40..078630d6448c 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -24,7 +24,7 @@ #include <asm/current.h> #include <asm/pgtable.h> #include <asm/mmu_context.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <as-layout.h> #include <kern_util.h> #include <os.h> diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 6a826cbb15c4..bc2a516c190f 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -7,7 +7,7 @@ #include <linux/ptrace.h> #include <linux/sched.h> #include <linux/tracehook.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/ptrace-abi.h> void user_enable_single_step(struct task_struct *child) diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index c1d0ae069b53..6258676bed85 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -11,7 +11,7 @@ #include <linux/syscalls.h> #include <asm/current.h> #include <asm/mman.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/unistd.h> long old_mmap(unsigned long addr, unsigned long len, diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 25c23666d592..ba87a27d6715 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -83,7 +83,7 @@ static irqreturn_t um_timer(int irq, void *dev) return IRQ_HANDLED; } -static cycle_t timer_read(struct clocksource *cs) +static u64 timer_read(struct clocksource *cs) { return os_nsecs() / TIMER_MULTIPLIER; } |