diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-07-10 23:18:26 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-07-10 23:18:26 +0000 |
commit | c7c4310f7fc1485925d800628bf50b3aeab535ef (patch) | |
tree | b12aa4be0e8fb82aaaea97fb475e793e8a347c49 /drivers/char | |
parent | 1ffd1d069ca4c5ffe16fea6175dab1b9bbb15820 (diff) |
Merge with Linux 2.4.0-test3-pre8. Linus has accepted most of what
I've sent him, so we're very close to full integration of the MIPS
port into his sources.
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/nvram.c | 130 |
1 files changed, 65 insertions, 65 deletions
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 42063cefa..a32cd18df 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -25,9 +25,12 @@ * the kernel and is not a module. Since the functions are used by some Atari * drivers, this is the case on the Atari. * + * + * 1.1 Cesar Barros: SMP locking fixes + * added changelog */ -#define NVRAM_VERSION "1.0" +#define NVRAM_VERSION "1.1" #include <linux/module.h> #include <linux/config.h> @@ -81,7 +84,7 @@ #endif /* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with - * interrupts disabled. Due to the index-port/data-port design of the RTC, we + * 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.) */ @@ -96,11 +99,13 @@ #include <linux/nvram.h> #include <linux/init.h> #include <linux/proc_fs.h> +#include <linux/spinlock.h> #include <asm/io.h> #include <asm/uaccess.h> #include <asm/system.h> +extern spinlock_t rtc_lock; static int nvram_open_cnt = 0; /* #times opened */ static int nvram_open_mode; /* special open modes */ @@ -163,21 +168,20 @@ unsigned char nvram_read_byte( int i ) unsigned long flags; unsigned char c; - save_flags(flags); - cli(); + spin_lock_irqsave (&rtc_lock, flags); c = nvram_read_int( i ); - restore_flags(flags); + spin_unlock_irqrestore (&rtc_lock, flags); return( c ); } +/* This races nicely with trying to read with checksum checking (nvram_read) */ void nvram_write_byte( unsigned char c, int i ) { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave (&rtc_lock, flags); nvram_write_int( c, i ); - restore_flags(flags); + spin_unlock_irqrestore (&rtc_lock, flags); } int nvram_check_checksum( void ) @@ -185,10 +189,9 @@ int nvram_check_checksum( void ) unsigned long flags; int rv; - save_flags(flags); - cli(); + spin_lock_irqsave (&rtc_lock, flags); rv = nvram_check_checksum_int(); - restore_flags(flags); + spin_unlock_irqrestore (&rtc_lock, flags); return( rv ); } @@ -196,10 +199,9 @@ void nvram_set_checksum( void ) { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave (&rtc_lock, flags); nvram_set_checksum_int(); - restore_flags(flags); + spin_unlock_irqrestore (&rtc_lock, flags); } #endif /* MACH == ATARI */ @@ -228,63 +230,67 @@ static long long nvram_llseek(struct file *file,loff_t offset, int origin ) static ssize_t nvram_read(struct file * file, char * buf, size_t count, loff_t *ppos ) { - unsigned long flags; + char contents [NVRAM_BYTES]; unsigned i = *ppos; - char *tmp = buf; - - if (i != *ppos) - return -EINVAL; + char *tmp; - save_flags(flags); - cli(); + spin_lock_irq (&rtc_lock); - if (!nvram_check_checksum_int()) { - restore_flags(flags); - return( -EIO ); - } + if (!nvram_check_checksum_int()) + goto checksum_err; + + for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp) + *tmp = nvram_read_int(i); + + spin_unlock_irq (&rtc_lock); + + copy_to_user_ret (buf, contents, tmp - contents, -EFAULT); - for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp ) - put_user( nvram_read_int(i), tmp ); *ppos = i; - restore_flags(flags); - return( tmp - buf ); + return (tmp - contents); + +checksum_err: + spin_unlock_irq (&rtc_lock); + return -EIO; } static ssize_t nvram_write(struct file * file, const char * buf, size_t count, loff_t *ppos ) { - unsigned long flags; + char contents [NVRAM_BYTES]; unsigned i = *ppos; - const char *tmp = buf; - char c; - - if (i != *ppos) - return -EINVAL; + char * tmp; - save_flags(flags); - cli(); - - if (!nvram_check_checksum_int()) { - restore_flags(flags); - return( -EIO ); - } + /* could comebody please help me indent this better? */ + copy_from_user_ret (contents, buf, (NVRAM_BYTES - i) < count ? + (NVRAM_BYTES - i) : count, + -EFAULT); + + spin_lock_irq (&rtc_lock); + + if (!nvram_check_checksum_int()) + goto checksum_err; + + for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp) + nvram_write_int (*tmp, i); - for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp ) { - get_user( c, tmp ); - nvram_write_int( c, i ); - } nvram_set_checksum_int(); + + spin_unlock_irq (&rtc_lock); + *ppos = i; - restore_flags(flags); - return( tmp - buf ); + return (tmp - contents); + +checksum_err: + spin_unlock_irq (&rtc_lock); + return -EIO; } static int nvram_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg ) { - unsigned long flags; int i; switch( cmd ) { @@ -293,14 +299,13 @@ static int nvram_ioctl( struct inode *inode, struct file *file, if (!capable(CAP_SYS_ADMIN)) return( -EACCES ); - save_flags(flags); - cli(); + spin_lock_irq (&rtc_lock); for( i = 0; i < NVRAM_BYTES; ++i ) nvram_write_int( 0, i ); nvram_set_checksum_int(); - restore_flags(flags); + spin_unlock_irq (&rtc_lock); return( 0 ); case NVRAM_SETCKS: /* just set checksum, contents unchanged @@ -309,10 +314,9 @@ static int nvram_ioctl( struct inode *inode, struct file *file, if (!capable(CAP_SYS_ADMIN)) return( -EACCES ); - save_flags(flags); - cli(); + spin_lock_irq (&rtc_lock); nvram_set_checksum_int(); - restore_flags(flags); + spin_unlock_irq (&rtc_lock); return( 0 ); default: @@ -355,16 +359,14 @@ static int nvram_read_proc( char *buffer, char **start, off_t offset, static int nvram_read_proc( char *buffer, char **start, off_t offset, int size, int *eof, void *data ) { - unsigned long flags; unsigned char contents[NVRAM_BYTES]; int i, len = 0; off_t begin = 0; - - save_flags(flags); - cli(); + + spin_lock_irq (&rtc_lock); for( i = 0; i < NVRAM_BYTES; ++i ) contents[i] = nvram_read_int( i ); - restore_flags(flags); + spin_unlock_irq (&rtc_lock); *eof = mach_proc_infos( contents, buffer, &len, &begin, offset, size ); @@ -475,15 +477,13 @@ static char *gfx_types[] = { static int pc_proc_infos( unsigned char *nvram, char *buffer, int *len, off_t *begin, off_t offset, int size ) { - unsigned long flags; int checksum; int type; - save_flags(flags); - cli(); + spin_lock_irq (&rtc_lock); checksum = nvram_check_checksum_int(); - restore_flags(flags); - + spin_unlock_irq (&rtc_lock); + PRINT_PROC( "Checksum status: %svalid\n", checksum ? "" : "not " ); PRINT_PROC( "# floppies : %d\n", |