Messages in this thread Patch in this message | | | Date | Tue, 02 Jan 2001 08:52:39 -0500 | From | Paul Gortmaker <> | Subject | [PATCH] CMOS locking for 2.4 (was: /proc/apm slows system time) |
| |
Alan Cox wrote: > > > Is there at least away we can recover the proper system time > > after these stalls? > > > > re-read the RTC -- but that's pretty slow and ugly > > Be very careful doing that in 2.4test. The 2.2 CMOS locking patches are not yet > in so there is already a window for CMOS problems as far as I can tell. Don't > make it bigger
This should cover CMOS locking for 2400-prerel.
Paul.
diff -ur linux-orig/Documentation/rtc.txt linux/Documentation/rtc.txt --- linux-orig/Documentation/rtc.txt Fri May 26 16:03:14 2000 +++ linux/Documentation/rtc.txt Tue Jan 2 05:48:03 2001 @@ -56,7 +56,7 @@ exclusive access to the device for your applications. The alarm and/or interrupt frequency are programmed into the RTC via -various ioctl(2) calls as listed in ./include/linux/mc146818rtc.h +various ioctl(2) calls as listed in ./include/linux/rtc.h Rather than write 50 pages describing the ioctl() and so on, it is perhaps more useful to include a small test program that demonstrates how to use them, and demonstrates the features of the driver. This is @@ -81,7 +81,7 @@ */ #include <stdio.h> -#include <linux/mc146818rtc.h> +#include <linux/rtc.h> #include <sys/ioctl.h> #include <sys/time.h> #include <sys/types.h> diff -ur linux-orig/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- linux-orig/arch/i386/kernel/process.c Mon Jan 1 04:36:51 2001 +++ linux/arch/i386/kernel/process.c Tue Jan 2 08:58:50 2001 @@ -32,6 +32,7 @@ #include <linux/delay.h> #include <linux/reboot.h> #include <linux/init.h> +#include <linux/mc146818rtc.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -257,6 +258,8 @@ */ void machine_real_restart(unsigned char *code, int length) { + unsigned long flags; + cli(); /* Write zero to CMOS register number 0x0f, which the BIOS POST @@ -266,10 +269,12 @@ disable NMIs by setting the top bit in the CMOS address register, as we're about to do peculiar things to the CPU. I'm not sure if `outb_p' is needed instead of just `outb'. Use it to be on the - safe side. */ + safe side. (Yes, CMOS_WRITE does outb_p's. - Paul G.) + */ - outb_p (0x8f, 0x70); - outb_p (0x00, 0x71); + spin_lock_irqsave(&rtc_lock, flags); + CMOS_WRITE(0x00, 0x8f); + spin_unlock_irqrestore(&rtc_lock, flags); /* Remap the kernel at virtual address zero, as well as offset zero from the kernel segment. This assumes the kernel segment starts at diff -ur linux-orig/drivers/char/nvram.c linux/drivers/char/nvram.c --- linux-orig/drivers/char/nvram.c Mon Nov 20 04:12:31 2000 +++ linux/drivers/char/nvram.c Tue Jan 2 05:50:36 2001 @@ -107,8 +107,6 @@ #include <asm/uaccess.h> #include <asm/system.h> -extern spinlock_t rtc_lock; - static int nvram_open_cnt; /* #times opened */ static int nvram_open_mode; /* special open modes */ #define NVRAM_WRITE 1 /* opened for writing (exclusive) */ diff -ur linux-orig/drivers/char/rtc.c linux/drivers/char/rtc.c --- linux-orig/drivers/char/rtc.c Mon Nov 20 04:19:54 2000 +++ linux/drivers/char/rtc.c Tue Jan 2 05:50:29 2001 @@ -89,8 +89,6 @@ static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); -extern spinlock_t rtc_lock; - static struct timer_list rtc_irq_timer; static loff_t rtc_llseek(struct file *file, loff_t offset, int origin); diff -ur linux-orig/drivers/ide/hd.c linux/drivers/ide/hd.c --- linux-orig/drivers/ide/hd.c Mon Nov 20 04:19:58 2000 +++ linux/drivers/ide/hd.c Tue Jan 2 08:05:44 2001 @@ -738,6 +738,7 @@ if (!NR_HD) { extern struct drive_info drive_info; unsigned char *BIOS = (unsigned char *) &drive_info; + unsigned long flags; int cmos_disks; for (drive=0 ; drive<2 ; drive++) { @@ -773,10 +774,15 @@ Needless to say, a non-zero value means we have an AT controller hard disk for that drive. - + Currently the rtc_lock is a bit academic since this + driver is non-modular, but someday... ? Paul G. */ - if ((cmos_disks = CMOS_READ(0x12)) & 0xf0) { + spin_lock_irqsave(&rtc_lock, flags); + cmos_disks = CMOS_READ(0x12); + spin_unlock_irqrestore(&rtc_lock, flags); + + if (cmos_disks & 0xf0) { if (cmos_disks & 0x0f) NR_HD = 2; else diff -ur linux-orig/drivers/ide/ide-geometry.c linux/drivers/ide/ide-geometry.c --- linux-orig/drivers/ide/ide-geometry.c Tue Aug 8 03:56:16 2000 +++ linux/drivers/ide/ide-geometry.c Tue Jan 2 07:25:10 2001 @@ -3,6 +3,7 @@ */ #include <linux/config.h> #include <linux/ide.h> +#include <linux/mc146818rtc.h> #include <asm/io.h> /* @@ -46,13 +47,15 @@ extern struct drive_info_struct drive_info; byte cmos_disks, *BIOS = (byte *) &drive_info; int unit; + unsigned long flags; #ifdef CONFIG_BLK_DEV_PDC4030 if (hwif->chipset == ide_pdc4030 && hwif->channel != 0) return; #endif /* CONFIG_BLK_DEV_PDC4030 */ - outb_p(0x12,0x70); /* specify CMOS address 0x12 */ - cmos_disks = inb_p(0x71); /* read the data from 0x12 */ + spin_lock_irqsave(&rtc_lock, flags); + cmos_disks = CMOS_READ(0x12); + spin_unlock_irqrestore(&rtc_lock, flags); /* Extract drive geometry from CMOS+BIOS if not already setup */ for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; diff -ur linux-orig/include/asm-i386/floppy.h linux/include/asm-i386/floppy.h --- linux-orig/include/asm-i386/floppy.h Mon Nov 20 04:17:40 2000 +++ linux/include/asm-i386/floppy.h Tue Jan 2 06:19:09 2001 @@ -285,8 +285,28 @@ static int FDC1 = 0x3f0; static int FDC2 = -1; -#define FLOPPY0_TYPE ((CMOS_READ(0x10) >> 4) & 15) -#define FLOPPY1_TYPE (CMOS_READ(0x10) & 15) +/* + * Floppy types are stored in the rtc's CMOS RAM and so rtc_lock + * is needed to prevent corrupted CMOS RAM in case "insmod floppy" + * coincides with another rtc CMOS user. Paul G. + */ +#define FLOPPY0_TYPE ({ \ + unsigned long flags; \ + unsigned char val; \ + spin_lock_irqsave(&rtc_lock, flags); \ + val = (CMOS_READ(0x10) >> 4) & 15; \ + spin_unlock_irqrestore(&rtc_lock, flags); \ + val; \ +}) + +#define FLOPPY1_TYPE ({ \ + unsigned long flags; \ + unsigned char val; \ + spin_lock_irqsave(&rtc_lock, flags); \ + val = CMOS_READ(0x10) & 15; \ + spin_unlock_irqrestore(&rtc_lock, flags); \ + val; \ +}) #define N_FDC 2 #define N_DRIVE 8 diff -ur linux-orig/include/linux/mc146818rtc.h linux/include/linux/mc146818rtc.h --- linux-orig/include/linux/mc146818rtc.h Wed Jun 28 11:39:35 2000 +++ linux/include/linux/mc146818rtc.h Tue Jan 2 05:21:51 2001 @@ -15,6 +15,8 @@ #include <linux/rtc.h> /* get the user-level API */ #include <asm/mc146818rtc.h> /* register access macros */ +extern spinlock_t rtc_lock; /* serialize CMOS RAM access */ + /********************************************************************** * register summary **********************************************************************/ diff -ur linux-orig/include/linux/rtc.h linux/include/linux/rtc.h --- linux-orig/include/linux/rtc.h Wed Jul 12 04:18:51 2000 +++ linux/include/linux/rtc.h Tue Jan 2 05:37:04 2001 @@ -2,6 +2,8 @@ * Generic RTC interface. * This version contains the part of the user interface to the Real Time Clock * service. It is used with both the legacy mc146818 and also EFI + * Struct rtc_time and first 12 ioctl by Paul Gortmaker, 1996 - separated out + * from <linux/mc146818rtc.h> to this file for 2.4 kernels. * * Copyright (C) 1999 Hewlett-Packard Co. * Copyright (C) 1999 Stephane Eranian <eranian@hpl.hp.com>
__________________________________________________ Do You Yahoo!? Talk to your friends online with Yahoo! Messenger. http://im.yahoo.com - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org Please read the FAQ at http://www.tux.org/lkml/
| |