char/nvram: Allow the set_checksum and initialize ioctls to be omitted
The drivers/char/nvram.c module has previously supported only RTC "CMOS" NVRAM, for which it provides appropriate checksum ioctls. Make these ioctls optional so the module can be re-used with other kinds of NVRAM. The ops struct methods that implement the ioctls now return error codes so that a multi-platform kernel binary can do the right thing when running on hardware without a suitable NVRAM. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d5bbb5021c
commit
2d58636e0a
|
@ -136,16 +136,25 @@ static void __nvram_set_checksum(void)
|
|||
__nvram_write_byte(sum & 0xff, PC_CKS_LOC + 1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void nvram_set_checksum(void)
|
||||
static long pc_nvram_set_checksum(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&rtc_lock, flags);
|
||||
spin_lock_irq(&rtc_lock);
|
||||
__nvram_set_checksum();
|
||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||
spin_unlock_irq(&rtc_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long pc_nvram_initialize(void)
|
||||
{
|
||||
ssize_t i;
|
||||
|
||||
spin_lock_irq(&rtc_lock);
|
||||
for (i = 0; i < NVRAM_BYTES; ++i)
|
||||
__nvram_write_byte(0, i);
|
||||
__nvram_set_checksum();
|
||||
spin_unlock_irq(&rtc_lock);
|
||||
return 0;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
static ssize_t pc_nvram_get_size(void)
|
||||
{
|
||||
|
@ -156,6 +165,8 @@ const struct nvram_ops arch_nvram_ops = {
|
|||
.read_byte = pc_nvram_read_byte,
|
||||
.write_byte = pc_nvram_write_byte,
|
||||
.get_size = pc_nvram_get_size,
|
||||
.set_checksum = pc_nvram_set_checksum,
|
||||
.initialize = pc_nvram_initialize,
|
||||
};
|
||||
EXPORT_SYMBOL(arch_nvram_ops);
|
||||
#endif /* CONFIG_X86 */
|
||||
|
@ -241,51 +252,50 @@ checksum_err:
|
|||
static long nvram_misc_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int i;
|
||||
long ret = -ENOTTY;
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case NVRAM_INIT:
|
||||
/* initialize NVRAM contents and checksum */
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EACCES;
|
||||
|
||||
mutex_lock(&nvram_mutex);
|
||||
spin_lock_irq(&rtc_lock);
|
||||
|
||||
for (i = 0; i < NVRAM_BYTES; ++i)
|
||||
__nvram_write_byte(0, i);
|
||||
__nvram_set_checksum();
|
||||
|
||||
spin_unlock_irq(&rtc_lock);
|
||||
mutex_unlock(&nvram_mutex);
|
||||
return 0;
|
||||
|
||||
if (arch_nvram_ops.initialize != NULL) {
|
||||
mutex_lock(&nvram_mutex);
|
||||
ret = arch_nvram_ops.initialize();
|
||||
mutex_unlock(&nvram_mutex);
|
||||
}
|
||||
break;
|
||||
case NVRAM_SETCKS:
|
||||
/* just set checksum, contents unchanged (maybe useful after
|
||||
* checksum garbaged somehow...) */
|
||||
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:
|
||||
return -ENOTTY;
|
||||
if (arch_nvram_ops.set_checksum != NULL) {
|
||||
mutex_lock(&nvram_mutex);
|
||||
ret = arch_nvram_ops.set_checksum();
|
||||
mutex_unlock(&nvram_mutex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nvram_misc_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
spin_lock(&nvram_state_lock);
|
||||
|
||||
/* Prevent multiple readers/writers if desired. */
|
||||
if ((nvram_open_cnt && (file->f_flags & O_EXCL)) ||
|
||||
(nvram_open_mode & NVRAM_EXCL) ||
|
||||
((file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE))) {
|
||||
(nvram_open_mode & NVRAM_EXCL)) {
|
||||
spin_unlock(&nvram_state_lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Prevent multiple writers if the set_checksum ioctl is implemented. */
|
||||
if ((arch_nvram_ops.set_checksum != NULL) &&
|
||||
(file->f_mode & FMODE_WRITE) && (nvram_open_mode & NVRAM_WRITE)) {
|
||||
spin_unlock(&nvram_state_lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ struct nvram_ops {
|
|||
void (*write_byte)(unsigned char, int);
|
||||
ssize_t (*read)(char *, size_t, loff_t *);
|
||||
ssize_t (*write)(char *, size_t, loff_t *);
|
||||
long (*initialize)(void);
|
||||
long (*set_checksum)(void);
|
||||
};
|
||||
|
||||
extern const struct nvram_ops arch_nvram_ops;
|
||||
|
|
Loading…
Reference in New Issue