diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/hpet.c | 11 | ||||
-rw-r--r-- | drivers/char/hw_random/core.c | 108 | ||||
-rw-r--r-- | drivers/char/hw_random/virtio-rng.c | 78 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_poweroff.c | 11 | ||||
-rw-r--r-- | drivers/char/pty.c | 14 | ||||
-rw-r--r-- | drivers/char/random.c | 54 | ||||
-rw-r--r-- | drivers/char/rtc.c | 11 | ||||
-rw-r--r-- | drivers/char/vt.c | 11 |
8 files changed, 125 insertions, 173 deletions
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 70a770ac0138..e481c5938bad 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -675,36 +675,33 @@ static int hpet_is_known(struct hpet_data *hdp) static ctl_table hpet_table[] = { { - .ctl_name = CTL_UNNUMBERED, .procname = "max-user-freq", .data = &hpet_max_freq, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec, + .proc_handler = proc_dointvec, }, - {.ctl_name = 0} + {} }; static ctl_table hpet_root[] = { { - .ctl_name = CTL_UNNUMBERED, .procname = "hpet", .maxlen = 0, .mode = 0555, .child = hpet_table, }, - {.ctl_name = 0} + {} }; static ctl_table dev_root[] = { { - .ctl_name = CTL_DEV, .procname = "dev", .maxlen = 0, .mode = 0555, .child = hpet_root, }, - {.ctl_name = 0} + {} }; static struct ctl_table_header *sysctl_header; diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 1573aebd54b5..8b7d56a0fe3a 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -52,7 +52,9 @@ static struct hwrng *current_rng; static LIST_HEAD(rng_list); static DEFINE_MUTEX(rng_mutex); - +static int data_avail; +static u8 rng_buffer[SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES] + __cacheline_aligned; static inline int hwrng_init(struct hwrng *rng) { @@ -67,19 +69,6 @@ static inline void hwrng_cleanup(struct hwrng *rng) rng->cleanup(rng); } -static inline int hwrng_data_present(struct hwrng *rng, int wait) -{ - if (!rng->data_present) - return 1; - return rng->data_present(rng, wait); -} - -static inline int hwrng_data_read(struct hwrng *rng, u32 *data) -{ - return rng->data_read(rng, data); -} - - static int rng_dev_open(struct inode *inode, struct file *filp) { /* enforce read-only access to this chrdev */ @@ -91,54 +80,87 @@ static int rng_dev_open(struct inode *inode, struct file *filp) return 0; } +static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size, + int wait) { + int present; + + if (rng->read) + return rng->read(rng, (void *)buffer, size, wait); + + if (rng->data_present) + present = rng->data_present(rng, wait); + else + present = 1; + + if (present) + return rng->data_read(rng, (u32 *)buffer); + + return 0; +} + static ssize_t rng_dev_read(struct file *filp, char __user *buf, size_t size, loff_t *offp) { - u32 data; ssize_t ret = 0; int err = 0; - int bytes_read; + int bytes_read, len; while (size) { - err = -ERESTARTSYS; - if (mutex_lock_interruptible(&rng_mutex)) + if (mutex_lock_interruptible(&rng_mutex)) { + err = -ERESTARTSYS; goto out; + } + if (!current_rng) { - mutex_unlock(&rng_mutex); err = -ENODEV; - goto out; + goto out_unlock; } - bytes_read = 0; - if (hwrng_data_present(current_rng, - !(filp->f_flags & O_NONBLOCK))) - bytes_read = hwrng_data_read(current_rng, &data); - mutex_unlock(&rng_mutex); - - err = -EAGAIN; - if (!bytes_read && (filp->f_flags & O_NONBLOCK)) - goto out; - if (bytes_read < 0) { - err = bytes_read; - goto out; + if (!data_avail) { + bytes_read = rng_get_data(current_rng, rng_buffer, + sizeof(rng_buffer), + !(filp->f_flags & O_NONBLOCK)); + if (bytes_read < 0) { + err = bytes_read; + goto out_unlock; + } + data_avail = bytes_read; } - err = -EFAULT; - while (bytes_read && size) { - if (put_user((u8)data, buf++)) - goto out; - size--; - ret++; - bytes_read--; - data >>= 8; + if (!data_avail) { + if (filp->f_flags & O_NONBLOCK) { + err = -EAGAIN; + goto out_unlock; + } + } else { + len = data_avail; + if (len > size) + len = size; + + data_avail -= len; + + if (copy_to_user(buf + ret, rng_buffer + data_avail, + len)) { + err = -EFAULT; + goto out_unlock; + } + + size -= len; + ret += len; } + mutex_unlock(&rng_mutex); + if (need_resched()) schedule_timeout_interruptible(1); - err = -ERESTARTSYS; - if (signal_pending(current)) + + if (signal_pending(current)) { + err = -ERESTARTSYS; goto out; + } } +out_unlock: + mutex_unlock(&rng_mutex); out: return ret ? : err; } @@ -280,7 +302,7 @@ int hwrng_register(struct hwrng *rng) struct hwrng *old_rng, *tmp; if (rng->name == NULL || - rng->data_read == NULL) + (rng->data_read == NULL && rng->read == NULL)) goto out; mutex_lock(&rng_mutex); diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 915157fcff98..bdaef8e94021 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -16,6 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + #include <linux/err.h> #include <linux/hw_random.h> #include <linux/scatterlist.h> @@ -23,78 +24,64 @@ #include <linux/virtio.h> #include <linux/virtio_rng.h> -/* The host will fill any buffer we give it with sweet, sweet randomness. We - * give it 64 bytes at a time, and the hwrng framework takes it 4 bytes at a - * time. */ -#define RANDOM_DATA_SIZE 64 - static struct virtqueue *vq; -static u32 *random_data; -static unsigned int data_left; +static unsigned int data_avail; static DECLARE_COMPLETION(have_data); +static bool busy; static void random_recv_done(struct virtqueue *vq) { - unsigned int len; - /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ - if (!vq->vq_ops->get_buf(vq, &len)) + if (!vq->vq_ops->get_buf(vq, &data_avail)) return; - data_left += len; complete(&have_data); } -static void register_buffer(void) +/* The host will fill any buffer we give it with sweet, sweet randomness. */ +static void register_buffer(u8 *buf, size_t size) { struct scatterlist sg; - sg_init_one(&sg, random_data+data_left, RANDOM_DATA_SIZE-data_left); + sg_init_one(&sg, buf, size); + /* There should always be room for one buffer. */ - if (vq->vq_ops->add_buf(vq, &sg, 0, 1, random_data) < 0) + if (vq->vq_ops->add_buf(vq, &sg, 0, 1, buf) < 0) BUG(); + vq->vq_ops->kick(vq); } -/* At least we don't udelay() in a loop like some other drivers. */ -static int virtio_data_present(struct hwrng *rng, int wait) +static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) { - if (data_left >= sizeof(u32)) - return 1; -again: + if (!busy) { + busy = true; + init_completion(&have_data); + register_buffer(buf, size); + } + if (!wait) return 0; wait_for_completion(&have_data); - /* Not enough? Re-register. */ - if (unlikely(data_left < sizeof(u32))) { - register_buffer(); - goto again; - } + busy = false; - return 1; + return data_avail; } -/* virtio_data_present() must have succeeded before this is called. */ -static int virtio_data_read(struct hwrng *rng, u32 *data) +static void virtio_cleanup(struct hwrng *rng) { - BUG_ON(data_left < sizeof(u32)); - data_left -= sizeof(u32); - *data = random_data[data_left / 4]; - - if (data_left < sizeof(u32)) { - init_completion(&have_data); - register_buffer(); - } - return sizeof(*data); + if (busy) + wait_for_completion(&have_data); } + static struct hwrng virtio_hwrng = { - .name = "virtio", - .data_present = virtio_data_present, - .data_read = virtio_data_read, + .name = "virtio", + .cleanup = virtio_cleanup, + .read = virtio_read, }; static int virtrng_probe(struct virtio_device *vdev) @@ -112,7 +99,6 @@ static int virtrng_probe(struct virtio_device *vdev) return err; } - register_buffer(); return 0; } @@ -138,21 +124,11 @@ static struct virtio_driver virtio_rng = { static int __init init(void) { - int err; - - random_data = kmalloc(RANDOM_DATA_SIZE, GFP_KERNEL); - if (!random_data) - return -ENOMEM; - - err = register_virtio_driver(&virtio_rng); - if (err) - kfree(random_data); - return err; + return register_virtio_driver(&virtio_rng); } static void __exit fini(void) { - kfree(random_data); unregister_virtio_driver(&virtio_rng); } module_init(init); diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index 2e66b5f773dd..0dec5da000ef 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -660,26 +660,23 @@ static struct ipmi_smi_watcher smi_watcher = { #include <linux/sysctl.h> static ctl_table ipmi_table[] = { - { .ctl_name = DEV_IPMI_POWEROFF_POWERCYCLE, - .procname = "poweroff_powercycle", + { .procname = "poweroff_powercycle", .data = &poweroff_powercycle, .maxlen = sizeof(poweroff_powercycle), .mode = 0644, - .proc_handler = &proc_dointvec }, + .proc_handler = proc_dointvec }, { } }; static ctl_table ipmi_dir_table[] = { - { .ctl_name = DEV_IPMI, - .procname = "ipmi", + { .procname = "ipmi", .mode = 0555, .child = ipmi_table }, { } }; static ctl_table ipmi_root_table[] = { - { .ctl_name = CTL_DEV, - .procname = "dev", + { .procname = "dev", .mode = 0555, .child = ipmi_dir_table }, { } diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 62f282e67638..d86c0bc05c1c 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -431,30 +431,25 @@ static struct cdev ptmx_cdev; static struct ctl_table pty_table[] = { { - .ctl_name = PTY_MAX, .procname = "max", .maxlen = sizeof(int), .mode = 0644, .data = &pty_limit, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, + .proc_handler = proc_dointvec_minmax, .extra1 = &pty_limit_min, .extra2 = &pty_limit_max, }, { - .ctl_name = PTY_NR, .procname = "nr", .maxlen = sizeof(int), .mode = 0444, .data = &pty_count, - .proc_handler = &proc_dointvec, - }, { - .ctl_name = 0 - } + .proc_handler = proc_dointvec, + }, + {} }; static struct ctl_table pty_kern_table[] = { { - .ctl_name = KERN_PTY, .procname = "pty", .mode = 0555, .child = pty_table, @@ -464,7 +459,6 @@ static struct ctl_table pty_kern_table[] = { static struct ctl_table pty_root_table[] = { { - .ctl_name = CTL_KERN, .procname = "kernel", .mode = 0555, .child = pty_kern_table, diff --git a/drivers/char/random.c b/drivers/char/random.c index 04b505e5a5e2..dcd08635cf1b 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1257,94 +1257,54 @@ static int proc_do_uuid(ctl_table *table, int write, return proc_dostring(&fake_table, write, buffer, lenp, ppos); } -static int uuid_strategy(ctl_table *table, - void __user *oldval, size_t __user *oldlenp, - void __user *newval, size_t newlen) -{ - unsigned char tmp_uuid[16], *uuid; - unsigned int len; - - if (!oldval || !oldlenp) - return 1; - - uuid = table->data; - if (!uuid) { - uuid = tmp_uuid; - uuid[8] = 0; - } - if (uuid[8] == 0) - generate_random_uuid(uuid); - - if (get_user(len, oldlenp)) - return -EFAULT; - if (len) { - if (len > 16) - len = 16; - if (copy_to_user(oldval, uuid, len) || - put_user(len, oldlenp)) - return -EFAULT; - } - return 1; -} - static int sysctl_poolsize = INPUT_POOL_WORDS * 32; ctl_table random_table[] = { { - .ctl_name = RANDOM_POOLSIZE, .procname = "poolsize", .data = &sysctl_poolsize, .maxlen = sizeof(int), .mode = 0444, - .proc_handler = &proc_dointvec, + .proc_handler = proc_dointvec, }, { - .ctl_name = RANDOM_ENTROPY_COUNT, .procname = "entropy_avail", .maxlen = sizeof(int), .mode = 0444, - .proc_handler = &proc_dointvec, + .proc_handler = proc_dointvec, .data = &input_pool.entropy_count, }, { - .ctl_name = RANDOM_READ_THRESH, .procname = "read_wakeup_threshold", .data = &random_read_wakeup_thresh, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, + .proc_handler = proc_dointvec_minmax, .extra1 = &min_read_thresh, .extra2 = &max_read_thresh, }, { - .ctl_name = RANDOM_WRITE_THRESH, .procname = "write_wakeup_threshold", .data = &random_write_wakeup_thresh, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, + .proc_handler = proc_dointvec_minmax, .extra1 = &min_write_thresh, .extra2 = &max_write_thresh, }, { - .ctl_name = RANDOM_BOOT_ID, .procname = "boot_id", .data = &sysctl_bootid, .maxlen = 16, .mode = 0444, - .proc_handler = &proc_do_uuid, - .strategy = &uuid_strategy, + .proc_handler = proc_do_uuid, }, { - .ctl_name = RANDOM_UUID, .procname = "uuid", .maxlen = 16, .mode = 0444, - .proc_handler = &proc_do_uuid, - .strategy = &uuid_strategy, + .proc_handler = proc_do_uuid, }, - { .ctl_name = 0 } + { } }; #endif /* CONFIG_SYSCTL */ diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index bc4ab3e54550..95acb8c880f4 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -282,34 +282,31 @@ static irqreturn_t rtc_interrupt(int irq, void *dev_id) */ static ctl_table rtc_table[] = { { - .ctl_name = CTL_UNNUMBERED, .procname = "max-user-freq", .data = &rtc_max_user_freq, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec, + .proc_handler = proc_dointvec, }, - { .ctl_name = 0 } + { } }; static ctl_table rtc_root[] = { { - .ctl_name = CTL_UNNUMBERED, .procname = "rtc", .mode = 0555, .child = rtc_table, }, - { .ctl_name = 0 } + { } }; static ctl_table dev_root[] = { { - .ctl_name = CTL_DEV, .procname = "dev", .mode = 0555, .child = rtc_root, }, - { .ctl_name = 0 } + { } }; static struct ctl_table_header *sysctl_header; diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 0c80c68cd047..1e3d728dbf7e 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -161,6 +161,8 @@ static void set_palette(struct vc_data *vc); static int printable; /* Is console ready for printing? */ int default_utf8 = true; module_param(default_utf8, int, S_IRUGO | S_IWUSR); +int global_cursor_default = -1; +module_param(global_cursor_default, int, S_IRUGO | S_IWUSR); /* * ignore_poke: don't unblank the screen when things are typed. This is @@ -775,6 +777,12 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ vc_cons[currcons].d = NULL; return -ENOMEM; } + + /* If no drivers have overridden us and the user didn't pass a + boot option, default to displaying the cursor */ + if (global_cursor_default == -1) + global_cursor_default = 1; + vc_init(vc, vc->vc_rows, vc->vc_cols, 1); vcs_make_sysfs(currcons); atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, ¶m); @@ -1616,7 +1624,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear) vc->vc_decscnm = 0; vc->vc_decom = 0; vc->vc_decawm = 1; - vc->vc_deccm = 1; + vc->vc_deccm = global_cursor_default; vc->vc_decim = 0; set_kbd(vc, decarm); @@ -4078,6 +4086,7 @@ EXPORT_SYMBOL(fg_console); EXPORT_SYMBOL(console_blank_hook); EXPORT_SYMBOL(console_blanked); EXPORT_SYMBOL(vc_cons); +EXPORT_SYMBOL(global_cursor_default); #ifndef VT_SINGLE_DRIVER EXPORT_SYMBOL(take_over_console); EXPORT_SYMBOL(give_up_console); |