summaryrefslogtreecommitdiff
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/bsr.c2
-rw-r--r--drivers/char/dsp56k.c2
-rw-r--r--drivers/char/hangcheck-timer.c33
-rw-r--r--drivers/char/hw_random/core.c47
-rw-r--r--drivers/char/hw_random/virtio-rng.c10
-rw-r--r--drivers/char/i8k.c123
-rw-r--r--drivers/char/pcmcia/synclink_cs.c4
-rw-r--r--drivers/char/random.c17
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c1
9 files changed, 154 insertions, 85 deletions
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index 8fedbc250414..a6cef548e01e 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -259,7 +259,7 @@ static int bsr_add_node(struct device_node *bn)
}
cur->bsr_device = device_create(bsr_class, NULL, cur->bsr_dev,
- cur, cur->bsr_name);
+ cur, "%s", cur->bsr_name);
if (IS_ERR(cur->bsr_device)) {
printk(KERN_ERR "device_create failed for %s\n",
cur->bsr_name);
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 01a5ca7425d7..8bf70e8c3f79 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -383,7 +383,7 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
return put_user(status, &hf->status);
}
case DSP56K_HOST_CMD:
- if (arg > 31 || arg < 0)
+ if (arg > 31)
return -EINVAL;
mutex_lock(&dsp56k_mutex);
dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) |
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index f953c96efc86..ebc4c73d8ca4 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -49,7 +49,7 @@
#include <asm/uaccess.h>
#include <linux/sysrq.h>
#include <linux/timer.h>
-#include <linux/time.h>
+#include <linux/hrtimer.h>
#define VERSION_STR "0.9.1"
@@ -117,24 +117,7 @@ __setup("hcheck_reboot", hangcheck_parse_reboot);
__setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
#endif /* not MODULE */
-#if defined(CONFIG_S390)
-# define HAVE_MONOTONIC
-# define TIMER_FREQ 1000000000ULL
-#else
-# define TIMER_FREQ 1000000000ULL
-#endif
-
-#ifdef HAVE_MONOTONIC
-extern unsigned long long monotonic_clock(void);
-#else
-static inline unsigned long long monotonic_clock(void)
-{
- struct timespec ts;
- getrawmonotonic(&ts);
- return timespec_to_ns(&ts);
-}
-#endif /* HAVE_MONOTONIC */
-
+#define TIMER_FREQ 1000000000ULL
/* Last time scheduled */
static unsigned long long hangcheck_tsc, hangcheck_tsc_margin;
@@ -143,12 +126,11 @@ static void hangcheck_fire(unsigned long);
static DEFINE_TIMER(hangcheck_ticktock, hangcheck_fire, 0, 0);
-
static void hangcheck_fire(unsigned long data)
{
unsigned long long cur_tsc, tsc_diff;
- cur_tsc = monotonic_clock();
+ cur_tsc = ktime_get_ns();
if (cur_tsc > hangcheck_tsc)
tsc_diff = cur_tsc - hangcheck_tsc;
@@ -177,7 +159,7 @@ static void hangcheck_fire(unsigned long data)
tsc_diff, tsc_diff - hangcheck_tick*TIMER_FREQ);
#endif
mod_timer(&hangcheck_ticktock, jiffies + (hangcheck_tick*HZ));
- hangcheck_tsc = monotonic_clock();
+ hangcheck_tsc = ktime_get_ns();
}
@@ -185,16 +167,11 @@ static int __init hangcheck_init(void)
{
printk("Hangcheck: starting hangcheck timer %s (tick is %d seconds, margin is %d seconds).\n",
VERSION_STR, hangcheck_tick, hangcheck_margin);
-#if defined (HAVE_MONOTONIC)
- printk("Hangcheck: Using monotonic_clock().\n");
-#else
- printk("Hangcheck: Using getrawmonotonic().\n");
-#endif /* HAVE_MONOTONIC */
hangcheck_tsc_margin =
(unsigned long long)(hangcheck_margin + hangcheck_tick);
hangcheck_tsc_margin *= (unsigned long long)TIMER_FREQ;
- hangcheck_tsc = monotonic_clock();
+ hangcheck_tsc = ktime_get_ns();
mod_timer(&hangcheck_ticktock, jiffies + (hangcheck_tick*HZ));
return 0;
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 334601cc81cf..c4419ea1ab07 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -55,16 +55,41 @@ static DEFINE_MUTEX(rng_mutex);
static int data_avail;
static u8 *rng_buffer;
+static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
+ int wait);
+
static size_t rng_buffer_size(void)
{
return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES;
}
+static void add_early_randomness(struct hwrng *rng)
+{
+ unsigned char bytes[16];
+ int bytes_read;
+
+ /*
+ * Currently only virtio-rng cannot return data during device
+ * probe, and that's handled in virtio-rng.c itself. If there
+ * are more such devices, this call to rng_get_data can be
+ * made conditional here instead of doing it per-device.
+ */
+ bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1);
+ if (bytes_read > 0)
+ add_device_randomness(bytes, bytes_read);
+}
+
static inline int hwrng_init(struct hwrng *rng)
{
- if (!rng->init)
- return 0;
- return rng->init(rng);
+ if (rng->init) {
+ int ret;
+
+ ret = rng->init(rng);
+ if (ret)
+ return ret;
+ }
+ add_early_randomness(rng);
+ return 0;
}
static inline void hwrng_cleanup(struct hwrng *rng)
@@ -304,8 +329,6 @@ int hwrng_register(struct hwrng *rng)
{
int err = -EINVAL;
struct hwrng *old_rng, *tmp;
- unsigned char bytes[16];
- int bytes_read;
if (rng->name == NULL ||
(rng->data_read == NULL && rng->read == NULL))
@@ -347,9 +370,17 @@ int hwrng_register(struct hwrng *rng)
INIT_LIST_HEAD(&rng->list);
list_add_tail(&rng->list, &rng_list);
- bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1);
- if (bytes_read > 0)
- add_device_randomness(bytes, bytes_read);
+ if (old_rng && !rng->init) {
+ /*
+ * Use a new device's input to add some randomness to
+ * the system. If this rng device isn't going to be
+ * used right away, its init function hasn't been
+ * called yet; so only use the randomness from devices
+ * that don't need an init callback.
+ */
+ add_early_randomness(rng);
+ }
+
out_unlock:
mutex_unlock(&rng_mutex);
out:
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index f3e71501de54..e9b15bc18b4d 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -38,6 +38,8 @@ struct virtrng_info {
int index;
};
+static bool probe_done;
+
static void random_recv_done(struct virtqueue *vq)
{
struct virtrng_info *vi = vq->vdev->priv;
@@ -67,6 +69,13 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
int ret;
struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
+ /*
+ * Don't ask host for data till we're setup. This call can
+ * happen during hwrng_register(), after commit d9e7972619.
+ */
+ if (unlikely(!probe_done))
+ return 0;
+
if (!vi->busy) {
vi->busy = true;
init_completion(&vi->have_data);
@@ -137,6 +146,7 @@ static int probe_common(struct virtio_device *vdev)
return err;
}
+ probe_done = true;
return 0;
}
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index 93dcad0c1cbe..65525c7e903c 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -65,6 +65,8 @@ static char bios_version[4];
static struct device *i8k_hwmon_dev;
static u32 i8k_hwmon_flags;
static int i8k_fan_mult;
+static int i8k_pwm_mult;
+static int i8k_fan_max = I8K_FAN_HIGH;
#define I8K_HWMON_HAVE_TEMP1 (1 << 0)
#define I8K_HWMON_HAVE_TEMP2 (1 << 1)
@@ -97,6 +99,10 @@ static int fan_mult = I8K_FAN_MULT;
module_param(fan_mult, int, 0);
MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with");
+static int fan_max = I8K_FAN_HIGH;
+module_param(fan_max, int, 0);
+MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed");
+
static int i8k_open_fs(struct inode *inode, struct file *file);
static long i8k_ioctl(struct file *, unsigned int, unsigned long);
@@ -276,7 +282,7 @@ static int i8k_set_fan(int fan, int speed)
{
struct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };
- speed = (speed < 0) ? 0 : ((speed > I8K_FAN_MAX) ? I8K_FAN_MAX : speed);
+ speed = (speed < 0) ? 0 : ((speed > i8k_fan_max) ? i8k_fan_max : speed);
regs.ebx = (fan & 0xff) | (speed << 8);
return i8k_smm(&regs) ? : i8k_get_fan_status(fan);
@@ -521,7 +527,7 @@ static ssize_t i8k_hwmon_show_pwm(struct device *dev,
status = i8k_get_fan_status(index);
if (status < 0)
return -EIO;
- return sprintf(buf, "%d\n", clamp_val(status * 128, 0, 255));
+ return sprintf(buf, "%d\n", clamp_val(status * i8k_pwm_mult, 0, 255));
}
static ssize_t i8k_hwmon_set_pwm(struct device *dev,
@@ -535,7 +541,7 @@ static ssize_t i8k_hwmon_set_pwm(struct device *dev,
err = kstrtoul(buf, 10, &val);
if (err)
return err;
- val = clamp_val(DIV_ROUND_CLOSEST(val, 128), 0, 2);
+ val = clamp_val(DIV_ROUND_CLOSEST(val, i8k_pwm_mult), 0, i8k_fan_max);
mutex_lock(&i8k_mutex);
err = i8k_set_fan(index, val);
@@ -544,20 +550,6 @@ static ssize_t i8k_hwmon_set_pwm(struct device *dev,
return err < 0 ? -EIO : count;
}
-static ssize_t i8k_hwmon_show_label(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- static const char *labels[3] = {
- "CPU",
- "Left Fan",
- "Right Fan",
- };
- int index = to_sensor_dev_attr(devattr)->index;
-
- return sprintf(buf, "%s\n", labels[index]);
-}
-
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 0);
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 1);
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 2);
@@ -570,41 +562,34 @@ static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL,
I8K_FAN_RIGHT);
static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,
i8k_hwmon_set_pwm, I8K_FAN_RIGHT);
-static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, i8k_hwmon_show_label, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_label, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_label, NULL, 2);
static struct attribute *i8k_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr, /* 0 */
- &sensor_dev_attr_temp1_label.dev_attr.attr, /* 1 */
- &sensor_dev_attr_temp2_input.dev_attr.attr, /* 2 */
- &sensor_dev_attr_temp3_input.dev_attr.attr, /* 3 */
- &sensor_dev_attr_temp4_input.dev_attr.attr, /* 4 */
- &sensor_dev_attr_fan1_input.dev_attr.attr, /* 5 */
- &sensor_dev_attr_pwm1.dev_attr.attr, /* 6 */
- &sensor_dev_attr_fan1_label.dev_attr.attr, /* 7 */
- &sensor_dev_attr_fan2_input.dev_attr.attr, /* 8 */
- &sensor_dev_attr_pwm2.dev_attr.attr, /* 9 */
- &sensor_dev_attr_fan2_label.dev_attr.attr, /* 10 */
+ &sensor_dev_attr_temp2_input.dev_attr.attr, /* 1 */
+ &sensor_dev_attr_temp3_input.dev_attr.attr, /* 2 */
+ &sensor_dev_attr_temp4_input.dev_attr.attr, /* 3 */
+ &sensor_dev_attr_fan1_input.dev_attr.attr, /* 4 */
+ &sensor_dev_attr_pwm1.dev_attr.attr, /* 5 */
+ &sensor_dev_attr_fan2_input.dev_attr.attr, /* 6 */
+ &sensor_dev_attr_pwm2.dev_attr.attr, /* 7 */
NULL
};
static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
int index)
{
- if ((index == 0 || index == 1) &&
- !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
+ if (index == 0 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
return 0;
- if (index == 2 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2))
+ if (index == 1 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2))
return 0;
- if (index == 3 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3))
+ if (index == 2 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3))
return 0;
- if (index == 4 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4))
+ if (index == 3 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4))
return 0;
- if (index >= 5 && index <= 7 &&
+ if (index >= 4 && index <= 5 &&
!(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1))
return 0;
- if (index >= 8 && index <= 10 &&
+ if (index >= 6 && index <= 7 &&
!(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2))
return 0;
@@ -659,6 +644,37 @@ static int __init i8k_init_hwmon(void)
return 0;
}
+struct i8k_config_data {
+ int fan_mult;
+ int fan_max;
+};
+
+enum i8k_configs {
+ DELL_LATITUDE_D520,
+ DELL_PRECISION_490,
+ DELL_STUDIO,
+ DELL_XPS_M140,
+};
+
+static const struct i8k_config_data i8k_config_data[] = {
+ [DELL_LATITUDE_D520] = {
+ .fan_mult = 1,
+ .fan_max = I8K_FAN_TURBO,
+ },
+ [DELL_PRECISION_490] = {
+ .fan_mult = 1,
+ .fan_max = I8K_FAN_TURBO,
+ },
+ [DELL_STUDIO] = {
+ .fan_mult = 1,
+ .fan_max = I8K_FAN_HIGH,
+ },
+ [DELL_XPS_M140] = {
+ .fan_mult = 1,
+ .fan_max = I8K_FAN_HIGH,
+ },
+};
+
static struct dmi_system_id i8k_dmi_table[] __initdata = {
{
.ident = "Dell Inspiron",
@@ -682,6 +698,14 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
},
},
{
+ .ident = "Dell Latitude D520",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D520"),
+ },
+ .driver_data = (void *)&i8k_config_data[DELL_LATITUDE_D520],
+ },
+ {
.ident = "Dell Latitude 2",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
@@ -703,6 +727,15 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
},
},
{
+ .ident = "Dell Precision 490",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME,
+ "Precision WorkStation 490"),
+ },
+ .driver_data = (void *)&i8k_config_data[DELL_PRECISION_490],
+ },
+ {
.ident = "Dell Precision",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
@@ -729,7 +762,7 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Studio"),
},
- .driver_data = (void *)1, /* fan multiplier override */
+ .driver_data = (void *)&i8k_config_data[DELL_STUDIO],
},
{
.ident = "Dell XPS M140",
@@ -737,7 +770,7 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "MXC051"),
},
- .driver_data = (void *)1, /* fan multiplier override */
+ .driver_data = (void *)&i8k_config_data[DELL_XPS_M140],
},
{ }
};
@@ -777,9 +810,17 @@ static int __init i8k_probe(void)
}
i8k_fan_mult = fan_mult;
+ i8k_fan_max = fan_max ? : I8K_FAN_HIGH; /* Must not be 0 */
id = dmi_first_match(i8k_dmi_table);
- if (id && fan_mult == I8K_FAN_MULT && id->driver_data)
- i8k_fan_mult = (unsigned long)id->driver_data;
+ if (id && id->driver_data) {
+ const struct i8k_config_data *conf = id->driver_data;
+
+ if (fan_mult == I8K_FAN_MULT && conf->fan_mult)
+ i8k_fan_mult = conf->fan_mult;
+ if (fan_max == I8K_FAN_HIGH && conf->fan_max)
+ i8k_fan_max = conf->fan_max;
+ }
+ i8k_pwm_mult = DIV_ROUND_UP(255, i8k_fan_max);
return 0;
}
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 8320abd1ef14..0ea9986059af 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2347,8 +2347,6 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp)
printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
__FILE__, __LINE__, info->device_name, port->count);
- WARN_ON(!port->count);
-
if (tty_port_close_start(port, tty, filp) == 0)
goto cleanup;
@@ -2510,7 +2508,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
__FILE__, __LINE__, tty->driver->name, port->count);
/* If port is closing, signal caller to try again */
- if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING){
+ if (port->flags & ASYNC_CLOSING){
wait_event_interruptible_tty(tty, port->close_wait,
!(port->flags & ASYNC_CLOSING));
retval = ((port->flags & ASYNC_HUP_NOTIFY) ?
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 0a7ac0a7b252..71529e196b84 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -641,7 +641,7 @@ retry:
} while (unlikely(entropy_count < pool_size-2 && pnfrac));
}
- if (entropy_count < 0) {
+ if (unlikely(entropy_count < 0)) {
pr_warn("random: negative entropy/overflow: pool %s count %d\n",
r->name, entropy_count);
WARN_ON(1);
@@ -981,7 +981,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
int reserved)
{
int entropy_count, orig;
- size_t ibytes;
+ size_t ibytes, nfrac;
BUG_ON(r->entropy_count > r->poolinfo->poolfracbits);
@@ -999,7 +999,17 @@ retry:
}
if (ibytes < min)
ibytes = 0;
- if ((entropy_count -= ibytes << (ENTROPY_SHIFT + 3)) < 0)
+
+ if (unlikely(entropy_count < 0)) {
+ pr_warn("random: negative entropy count: pool %s count %d\n",
+ r->name, entropy_count);
+ WARN_ON(1);
+ entropy_count = 0;
+ }
+ nfrac = ibytes << (ENTROPY_SHIFT + 3);
+ if ((size_t) entropy_count > nfrac)
+ entropy_count -= nfrac;
+ else
entropy_count = 0;
if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
@@ -1376,6 +1386,7 @@ urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
"with %d bits of entropy available\n",
current->comm, nonblocking_pool.entropy_total);
+ nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);
trace_urandom_read(8 * nbytes, ENTROPY_BITS(&nonblocking_pool),
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index f6345f932e46..9b1a5ac4881d 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -661,6 +661,7 @@ static int hwicap_setup(struct device *dev, int id,
drvdata->base_address = ioremap(drvdata->mem_start, drvdata->mem_size);
if (!drvdata->base_address) {
dev_err(dev, "ioremap() failed\n");
+ retval = -ENOMEM;
goto failed2;
}