diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/Kconfig | 9 | ||||
-rw-r--r-- | drivers/char/i8k.c | 316 | ||||
-rw-r--r-- | drivers/char/mem.c | 22 | ||||
-rw-r--r-- | drivers/char/virtio_console.c | 6 |
4 files changed, 240 insertions, 113 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index efefd12a0f7b..a4af8221751e 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -6,6 +6,15 @@ menu "Character devices" source "drivers/tty/Kconfig" +config DEVMEM + bool "/dev/mem virtual device support" + default y + help + Say Y here if you want to support the /dev/mem device. + The /dev/mem device is used to access areas of physical + memory. + When in doubt, say "Y". + config DEVKMEM bool "/dev/kmem virtual device support" default y diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index e34a019eb930..24cc4ed9a780 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -5,7 +5,8 @@ * * Hwmon integration: * Copyright (C) 2011 Jean Delvare <jdelvare@suse.de> - * Copyright (C) 2013 Guenter Roeck <linux@roeck-us.net> + * Copyright (C) 2013, 2014 Guenter Roeck <linux@roeck-us.net> + * Copyright (C) 2014 Pali Rohár <pali.rohar@gmail.com> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -20,6 +21,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <linux/delay.h> #include <linux/module.h> #include <linux/types.h> #include <linux/init.h> @@ -41,11 +43,15 @@ #define I8K_SMM_SET_FAN 0x01a3 #define I8K_SMM_GET_FAN 0x00a3 #define I8K_SMM_GET_SPEED 0x02a3 +#define I8K_SMM_GET_FAN_TYPE 0x03a3 +#define I8K_SMM_GET_NOM_SPEED 0x04a3 #define I8K_SMM_GET_TEMP 0x10a3 +#define I8K_SMM_GET_TEMP_TYPE 0x11a3 #define I8K_SMM_GET_DELL_SIG1 0xfea3 #define I8K_SMM_GET_DELL_SIG2 0xffa3 #define I8K_FAN_MULT 30 +#define I8K_FAN_MAX_RPM 30000 #define I8K_MAX_TEMP 127 #define I8K_FN_NONE 0x00 @@ -58,15 +64,13 @@ #define I8K_POWER_AC 0x05 #define I8K_POWER_BATTERY 0x01 -#define I8K_TEMPERATURE_BUG 1 - static DEFINE_MUTEX(i8k_mutex); 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; +static uint i8k_fan_mult = I8K_FAN_MULT; +static uint i8k_pwm_mult; +static uint i8k_fan_max = I8K_FAN_HIGH; #define I8K_HWMON_HAVE_TEMP1 (1 << 0) #define I8K_HWMON_HAVE_TEMP2 (1 << 1) @@ -95,13 +99,13 @@ static bool power_status; module_param(power_status, bool, 0600); MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); -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 uint fan_mult; +module_param(fan_mult, uint, 0); +MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with (default: autodetect)"); -static int fan_max = I8K_FAN_HIGH; -module_param(fan_max, int, 0); -MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed"); +static uint fan_max; +module_param(fan_max, uint, 0); +MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed (default: autodetect)"); static int i8k_open_fs(struct inode *inode, struct file *file); static long i8k_ioctl(struct file *, unsigned int, unsigned long); @@ -276,6 +280,28 @@ static int i8k_get_fan_speed(int fan) } /* + * Read the fan type. + */ +static int i8k_get_fan_type(int fan) +{ + struct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, }; + + regs.ebx = fan & 0xff; + return i8k_smm(®s) ? : regs.eax & 0xff; +} + +/* + * Read the fan nominal rpm for specific fan speed. + */ +static int i8k_get_fan_nominal_speed(int fan, int speed) +{ + struct smm_regs regs = { .eax = I8K_SMM_GET_NOM_SPEED, }; + + regs.ebx = (fan & 0xff) | (speed << 8); + return i8k_smm(®s) ? : (regs.eax & 0xffff) * i8k_fan_mult; +} + +/* * Set the fan speed (off, low, high). Returns the new fan status. */ static int i8k_set_fan(int fan, int speed) @@ -288,42 +314,52 @@ static int i8k_set_fan(int fan, int speed) return i8k_smm(®s) ? : i8k_get_fan_status(fan); } +static int i8k_get_temp_type(int sensor) +{ + struct smm_regs regs = { .eax = I8K_SMM_GET_TEMP_TYPE, }; + + regs.ebx = sensor & 0xff; + return i8k_smm(®s) ? : regs.eax & 0xff; +} + /* * Read the cpu temperature. */ -static int i8k_get_temp(int sensor) +static int _i8k_get_temp(int sensor) { - struct smm_regs regs = { .eax = I8K_SMM_GET_TEMP, }; - int rc; - int temp; + struct smm_regs regs = { + .eax = I8K_SMM_GET_TEMP, + .ebx = sensor & 0xff, + }; -#ifdef I8K_TEMPERATURE_BUG - static int prev[4] = { I8K_MAX_TEMP+1, I8K_MAX_TEMP+1, I8K_MAX_TEMP+1, I8K_MAX_TEMP+1 }; -#endif - regs.ebx = sensor & 0xff; - rc = i8k_smm(®s); - if (rc < 0) - return rc; + return i8k_smm(®s) ? : regs.eax & 0xff; +} - temp = regs.eax & 0xff; +static int i8k_get_temp(int sensor) +{ + int temp = _i8k_get_temp(sensor); -#ifdef I8K_TEMPERATURE_BUG /* * Sometimes the temperature sensor returns 0x99, which is out of range. - * In this case we return (once) the previous cached value. For example: + * In this case we retry (once) before returning an error. # 1003655137 00000058 00005a4b # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees # 1003655139 00000054 00005c52 */ - if (temp > I8K_MAX_TEMP) { - temp = prev[sensor]; - prev[sensor] = I8K_MAX_TEMP+1; - } else { - prev[sensor] = temp; + if (temp == 0x99) { + msleep(100); + temp = _i8k_get_temp(sensor); } + /* + * Return -ENODATA for all invalid temperatures. + * + * Known instances are the 0x99 value as seen above as well as + * 0xc1 (193), which may be returned when trying to read the GPU + * temperature if the system supports a GPU and it is currently + * turned off. + */ if (temp > I8K_MAX_TEMP) - return -ERANGE; -#endif + return -ENODATA; return temp; } @@ -493,6 +529,29 @@ static int i8k_open_fs(struct inode *inode, struct file *file) * Hwmon interface */ +static ssize_t i8k_hwmon_show_temp_label(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + static const char * const labels[] = { + "CPU", + "GPU", + "SODIMM", + "Other", + "Ambient", + "Other", + }; + int index = to_sensor_dev_attr(devattr)->index; + int type; + + type = i8k_get_temp_type(index); + if (type < 0) + return type; + if (type >= ARRAY_SIZE(labels)) + type = ARRAY_SIZE(labels) - 1; + return sprintf(buf, "%s\n", labels[type]); +} + static ssize_t i8k_hwmon_show_temp(struct device *dev, struct device_attribute *devattr, char *buf) @@ -501,13 +560,42 @@ static ssize_t i8k_hwmon_show_temp(struct device *dev, int temp; temp = i8k_get_temp(index); - if (temp == -ERANGE) - return -EINVAL; if (temp < 0) return temp; return sprintf(buf, "%d\n", temp * 1000); } +static ssize_t i8k_hwmon_show_fan_label(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + static const char * const labels[] = { + "Processor Fan", + "Motherboard Fan", + "Video Fan", + "Power Supply Fan", + "Chipset Fan", + "Other Fan", + }; + int index = to_sensor_dev_attr(devattr)->index; + bool dock = false; + int type; + + type = i8k_get_fan_type(index); + if (type < 0) + return type; + + if (type & 0x10) { + dock = true; + type &= 0x0F; + } + + if (type >= ARRAY_SIZE(labels)) + type = (ARRAY_SIZE(labels) - 1); + + return sprintf(buf, "%s%s\n", (dock ? "Docking " : ""), labels[type]); +} + static ssize_t i8k_hwmon_show_fan(struct device *dev, struct device_attribute *devattr, char *buf) @@ -555,45 +643,66 @@ static ssize_t i8k_hwmon_set_pwm(struct device *dev, } static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL, + 0); static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 1); +static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL, + 1); static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 2); +static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL, + 2); static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 3); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, - I8K_FAN_LEFT); +static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL, + 3); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, 0); +static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL, + 0); static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, - i8k_hwmon_set_pwm, I8K_FAN_LEFT); + i8k_hwmon_set_pwm, 0); static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL, - I8K_FAN_RIGHT); + 1); +static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL, + 1); static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, - i8k_hwmon_set_pwm, I8K_FAN_RIGHT); + i8k_hwmon_set_pwm, 1); static struct attribute *i8k_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, /* 0 */ - &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 */ + &sensor_dev_attr_temp1_label.dev_attr.attr, /* 1 */ + &sensor_dev_attr_temp2_input.dev_attr.attr, /* 2 */ + &sensor_dev_attr_temp2_label.dev_attr.attr, /* 3 */ + &sensor_dev_attr_temp3_input.dev_attr.attr, /* 4 */ + &sensor_dev_attr_temp3_label.dev_attr.attr, /* 5 */ + &sensor_dev_attr_temp4_input.dev_attr.attr, /* 6 */ + &sensor_dev_attr_temp4_label.dev_attr.attr, /* 7 */ + &sensor_dev_attr_fan1_input.dev_attr.attr, /* 8 */ + &sensor_dev_attr_fan1_label.dev_attr.attr, /* 9 */ + &sensor_dev_attr_pwm1.dev_attr.attr, /* 10 */ + &sensor_dev_attr_fan2_input.dev_attr.attr, /* 11 */ + &sensor_dev_attr_fan2_label.dev_attr.attr, /* 12 */ + &sensor_dev_attr_pwm2.dev_attr.attr, /* 13 */ NULL }; static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr, int index) { - if (index == 0 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1)) + if (index >= 0 && index <= 1 && + !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1)) return 0; - if (index == 1 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2)) + if (index >= 2 && index <= 3 && + !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2)) return 0; - if (index == 2 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3)) + if (index >= 4 && index <= 5 && + !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3)) return 0; - if (index == 3 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4)) + if (index >= 6 && index <= 7 && + !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4)) return 0; - if (index >= 4 && index <= 5 && + if (index >= 8 && index <= 10 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1)) return 0; - if (index >= 6 && index <= 7 && + if (index >= 11 && index <= 13 && !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2)) return 0; @@ -612,28 +721,28 @@ static int __init i8k_init_hwmon(void) i8k_hwmon_flags = 0; - /* CPU temperature attributes, if temperature reading is OK */ - err = i8k_get_temp(0); - if (err >= 0 || err == -ERANGE) + /* CPU temperature attributes, if temperature type is OK */ + err = i8k_get_temp_type(0); + if (err >= 0) i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP1; /* check for additional temperature sensors */ - err = i8k_get_temp(1); - if (err >= 0 || err == -ERANGE) + err = i8k_get_temp_type(1); + if (err >= 0) i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP2; - err = i8k_get_temp(2); - if (err >= 0 || err == -ERANGE) + err = i8k_get_temp_type(2); + if (err >= 0) i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP3; - err = i8k_get_temp(3); - if (err >= 0 || err == -ERANGE) + err = i8k_get_temp_type(3); + if (err >= 0) i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4; - /* Left fan attributes, if left fan is present */ - err = i8k_get_fan_status(I8K_FAN_LEFT); + /* First fan attributes, if fan type is OK */ + err = i8k_get_fan_type(0); if (err >= 0) i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1; - /* Right fan attributes, if right fan is present */ - err = i8k_get_fan_status(I8K_FAN_RIGHT); + /* Second fan attributes, if fan type is OK */ + err = i8k_get_fan_type(1); if (err >= 0) i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2; @@ -649,16 +758,15 @@ static int __init i8k_init_hwmon(void) } struct i8k_config_data { - int fan_mult; - int fan_max; + uint fan_mult; + uint fan_max; }; enum i8k_configs { DELL_LATITUDE_D520, - DELL_LATITUDE_E6540, DELL_PRECISION_490, DELL_STUDIO, - DELL_XPS_M140, + DELL_XPS, }; static const struct i8k_config_data i8k_config_data[] = { @@ -666,10 +774,6 @@ static const struct i8k_config_data i8k_config_data[] = { .fan_mult = 1, .fan_max = I8K_FAN_TURBO, }, - [DELL_LATITUDE_E6540] = { - .fan_mult = 1, - .fan_max = I8K_FAN_HIGH, - }, [DELL_PRECISION_490] = { .fan_mult = 1, .fan_max = I8K_FAN_TURBO, @@ -678,7 +782,7 @@ static const struct i8k_config_data i8k_config_data[] = { .fan_mult = 1, .fan_max = I8K_FAN_HIGH, }, - [DELL_XPS_M140] = { + [DELL_XPS] = { .fan_mult = 1, .fan_max = I8K_FAN_HIGH, }, @@ -715,22 +819,6 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = { .driver_data = (void *)&i8k_config_data[DELL_LATITUDE_D520], }, { - .ident = "Dell Latitude E6440", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6440"), - }, - .driver_data = (void *)&i8k_config_data[DELL_LATITUDE_E6540], - }, - { - .ident = "Dell Latitude E6540", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6540"), - }, - .driver_data = (void *)&i8k_config_data[DELL_LATITUDE_E6540], - }, - { .ident = "Dell Latitude 2", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), @@ -790,12 +878,20 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = { .driver_data = (void *)&i8k_config_data[DELL_STUDIO], }, { + .ident = "Dell XPS 13", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "XPS13"), + }, + .driver_data = (void *)&i8k_config_data[DELL_XPS], + }, + { .ident = "Dell XPS M140", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "MXC051"), }, - .driver_data = (void *)&i8k_config_data[DELL_XPS_M140], + .driver_data = (void *)&i8k_config_data[DELL_XPS], }, { } }; @@ -808,6 +904,7 @@ MODULE_DEVICE_TABLE(dmi, i8k_dmi_table); static int __init i8k_probe(void) { const struct dmi_system_id *id; + int fan, ret; /* * Get DMI information @@ -836,19 +933,40 @@ static int __init i8k_probe(void) return -ENODEV; } - i8k_fan_mult = fan_mult; - i8k_fan_max = fan_max ? : I8K_FAN_HIGH; /* Must not be 0 */ + /* + * Set fan multiplier and maximal fan speed from dmi config + * Values specified in module parameters override values from dmi + */ id = dmi_first_match(i8k_dmi_table); 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; + if (!fan_mult && conf->fan_mult) + fan_mult = conf->fan_mult; + if (!fan_max && conf->fan_max) + fan_max = conf->fan_max; } + + i8k_fan_max = fan_max ? : I8K_FAN_HIGH; /* Must not be 0 */ i8k_pwm_mult = DIV_ROUND_UP(255, i8k_fan_max); + if (!fan_mult) { + /* + * Autodetect fan multiplier based on nominal rpm + * If fan reports rpm value too high then set multiplier to 1 + */ + for (fan = 0; fan < 2; ++fan) { + ret = i8k_get_fan_nominal_speed(fan, i8k_fan_max); + if (ret < 0) + continue; + if (ret > I8K_FAN_MAX_RPM) + i8k_fan_mult = 1; + break; + } + } else { + /* Fan multiplier was specified in module param or in dmi */ + i8k_fan_mult = fan_mult; + } + return 0; } diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 9a6b63783a94..297110c12635 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -28,7 +28,7 @@ #include <linux/io.h> #include <linux/aio.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #ifdef CONFIG_IA64 # include <linux/efi.h> @@ -352,7 +352,6 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma) return 0; } -#ifdef CONFIG_DEVKMEM static int mmap_kmem(struct file *file, struct vm_area_struct *vma) { unsigned long pfn; @@ -373,9 +372,7 @@ static int mmap_kmem(struct file *file, struct vm_area_struct *vma) vma->vm_pgoff = pfn; return mmap_mem(file, vma); } -#endif -#ifdef CONFIG_DEVKMEM /* * This function reads the *virtual* memory as seen by the kernel. */ @@ -555,9 +552,7 @@ static ssize_t write_kmem(struct file *file, const char __user *buf, *ppos = p; return virtr + wrote ? : err; } -#endif -#ifdef CONFIG_DEVPORT static ssize_t read_port(struct file *file, char __user *buf, size_t count, loff_t *ppos) { @@ -586,6 +581,7 @@ static ssize_t write_port(struct file *file, const char __user *buf, return -EFAULT; while (count-- > 0 && i < 65536) { char c; + if (__get_user(c, tmp)) { if (tmp > buf) break; @@ -598,7 +594,6 @@ static ssize_t write_port(struct file *file, const char __user *buf, *ppos = i; return tmp-buf; } -#endif static ssize_t read_null(struct file *file, char __user *buf, size_t count, loff_t *ppos) @@ -642,6 +637,7 @@ static ssize_t read_iter_zero(struct kiocb *iocb, struct iov_iter *iter) while (iov_iter_count(iter)) { size_t chunk = iov_iter_count(iter), n; + if (chunk > PAGE_SIZE) chunk = PAGE_SIZE; /* Just for latency reasons */ n = iov_iter_zero(chunk, iter); @@ -726,7 +722,7 @@ static int open_port(struct inode *inode, struct file *filp) #define open_mem open_port #define open_kmem open_mem -static const struct file_operations mem_fops = { +static const struct file_operations __maybe_unused mem_fops = { .llseek = memory_lseek, .read = read_mem, .write = write_mem, @@ -738,8 +734,7 @@ static const struct file_operations mem_fops = { #endif }; -#ifdef CONFIG_DEVKMEM -static const struct file_operations kmem_fops = { +static const struct file_operations __maybe_unused kmem_fops = { .llseek = memory_lseek, .read = read_kmem, .write = write_kmem, @@ -750,7 +745,6 @@ static const struct file_operations kmem_fops = { .mmap_capabilities = memory_mmap_capabilities, #endif }; -#endif static const struct file_operations null_fops = { .llseek = null_lseek, @@ -761,14 +755,12 @@ static const struct file_operations null_fops = { .splice_write = splice_write_null, }; -#ifdef CONFIG_DEVPORT -static const struct file_operations port_fops = { +static const struct file_operations __maybe_unused port_fops = { .llseek = memory_lseek, .read = read_port, .write = write_port, .open = open_port, }; -#endif static const struct file_operations zero_fops = { .llseek = zero_lseek, @@ -795,7 +787,9 @@ static const struct memdev { const struct file_operations *fops; fmode_t fmode; } devlist[] = { +#ifdef CONFIG_DEVMEM [1] = { "mem", 0, &mem_fops, FMODE_UNSIGNED_OFFSET }, +#endif #ifdef CONFIG_DEVKMEM [2] = { "kmem", 0, &kmem_fops, FMODE_UNSIGNED_OFFSET }, #endif diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index de03df9dd7c9..26afb56a8073 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1986,6 +1986,12 @@ static int virtcons_probe(struct virtio_device *vdev) bool multiport; bool early = early_put_chars != NULL; + if (!vdev->config->get) { + dev_err(&vdev->dev, "%s failure: config access disabled\n", + __func__); + return -EINVAL; + } + /* Ensure to read early_put_chars now */ barrier(); |