diff options
Diffstat (limited to 'drivers/char/nvram.c')
| -rw-r--r-- | drivers/char/nvram.c | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 88cee4099be..9df78e2cc45 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -38,7 +38,6 @@ #define NVRAM_VERSION "1.3" #include <linux/module.h> -#include <linux/smp_lock.h> #include <linux/nvram.h> #define PC 1 @@ -95,13 +94,12 @@ /* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with * rtc_lock held. Due to the index-port/data-port design of the RTC, we * don't want two different things trying to get to it at once. (e.g. the - * periodic 11 min sync from time.c vs. this driver.) + * periodic 11 min sync from kernel/time/ntp.c vs. this driver.) */ #include <linux/types.h> #include <linux/errno.h> #include <linux/miscdevice.h> -#include <linux/slab.h> #include <linux/ioport.h> #include <linux/fcntl.h> #include <linux/mc146818rtc.h> @@ -111,9 +109,10 @@ #include <linux/spinlock.h> #include <linux/io.h> #include <linux/uaccess.h> +#include <linux/mutex.h> -#include <asm/system.h> +static DEFINE_MUTEX(nvram_mutex); static DEFINE_SPINLOCK(nvram_state_lock); static int nvram_open_cnt; /* #times opened */ static int nvram_open_mode; /* special open modes */ @@ -214,7 +213,6 @@ void nvram_set_checksum(void) static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) { - lock_kernel(); switch (origin) { case 0: /* nothing to do */ @@ -225,8 +223,10 @@ static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) case 2: offset += NVRAM_BYTES; break; + default: + return -EINVAL; } - unlock_kernel(); + return (offset >= 0) ? (file->f_pos = offset) : -EINVAL; } @@ -265,10 +265,16 @@ static ssize_t nvram_write(struct file *file, const char __user *buf, unsigned char contents[NVRAM_BYTES]; unsigned i = *ppos; unsigned char *tmp; - int len; - len = (NVRAM_BYTES - i) < count ? (NVRAM_BYTES - i) : count; - if (copy_from_user(contents, buf, len)) + if (i >= NVRAM_BYTES) + return 0; /* Past EOF */ + + if (count > NVRAM_BYTES - i) + count = NVRAM_BYTES - i; + if (count > NVRAM_BYTES) + return -EFAULT; /* Can't happen, but prove it to gcc */ + + if (copy_from_user(contents, buf, count)) return -EFAULT; spin_lock_irq(&rtc_lock); @@ -276,7 +282,7 @@ static ssize_t nvram_write(struct file *file, const char __user *buf, if (!__nvram_check_checksum()) goto checksum_err; - for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp) + for (tmp = contents; count--; ++i, ++tmp) __nvram_write_byte(*tmp, i); __nvram_set_checksum(); @@ -292,8 +298,8 @@ checksum_err: return -EIO; } -static int nvram_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long nvram_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { int i; @@ -304,6 +310,7 @@ static int nvram_ioctl(struct inode *inode, struct file *file, if (!capable(CAP_SYS_ADMIN)) return -EACCES; + mutex_lock(&nvram_mutex); spin_lock_irq(&rtc_lock); for (i = 0; i < NVRAM_BYTES; ++i) @@ -311,6 +318,7 @@ static int nvram_ioctl(struct inode *inode, struct file *file, __nvram_set_checksum(); spin_unlock_irq(&rtc_lock); + mutex_unlock(&nvram_mutex); return 0; case NVRAM_SETCKS: @@ -319,9 +327,11 @@ static int nvram_ioctl(struct inode *inode, struct file *file, if (!capable(CAP_SYS_ADMIN)) return -EACCES; + mutex_lock(&nvram_mutex); spin_lock_irq(&rtc_lock); __nvram_set_checksum(); spin_unlock_irq(&rtc_lock); + mutex_unlock(&nvram_mutex); return 0; default: @@ -331,14 +341,12 @@ static int nvram_ioctl(struct inode *inode, struct file *file, static int nvram_open(struct inode *inode, struct file *file) { - lock_kernel(); spin_lock(&nvram_state_lock); if ((nvram_open_cnt && (file->f_flags & O_EXCL)) || (nvram_open_mode & NVRAM_EXCL) || ((file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE))) { spin_unlock(&nvram_state_lock); - unlock_kernel(); return -EBUSY; } @@ -349,7 +357,6 @@ static int nvram_open(struct inode *inode, struct file *file) nvram_open_cnt++; spin_unlock(&nvram_state_lock); - unlock_kernel(); return 0; } @@ -421,7 +428,7 @@ static const struct file_operations nvram_fops = { .llseek = nvram_llseek, .read = nvram_read, .write = nvram_write, - .ioctl = nvram_ioctl, + .unlocked_ioctl = nvram_ioctl, .open = nvram_open, .release = nvram_release, }; |
