summaryrefslogtreecommitdiffstats
path: root/sys/isa
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>2006-12-03 03:49:28 +0000
committerbde <bde@FreeBSD.org>2006-12-03 03:49:28 +0000
commit852d9800f0a5838bfce44a897f8d68b336d54342 (patch)
tree2d683b9a91e7645424089178fa622a5415a9c7a3 /sys/isa
parentf6f7f2a20e8ea7e402f72ce6666741f4770e26df (diff)
downloadFreeBSD-src-852d9800f0a5838bfce44a897f8d68b336d54342.zip
FreeBSD-src-852d9800f0a5838bfce44a897f8d68b336d54342.tar.gz
Optimized RTC accesses by avoiding null writes to the index register
and by only delaying when an RTC register is written to. The delay after writing to the data register is now not just a workaround. This reduces the number of ISA accesses in the usual case from 4 to 1. The usual case is 2 rtcin()'s for each RTC interrupt. The index register is almost always RTC_INTR for this. The 3 extra ISA accesses were 1 for writing the index and 2 for delays. Some delays are needed in theory, but in practice they now just slow down slow accesses some more since almost eveyone including us does them wrong so modern systems enforce sufficient delays in hardware. I used to have the delays ifdefed out, but with the index register optimization the delays are rarely executed so the old magic ones can be kept or even implemented non- magically without significant cost. Optimizing RTC interrupt handling is more interesting than it used to be because RTC interrupts are currently needed to fix the more efficient apic timer interrupts on some systems. apic_timer_hz is normally 2000 so the RTC interrupt rate needs to be 2048 to keep the apic timer firing on such systems. Without these changes, each RTC interrupt normally took 10 ISA accesses (2 PIC accesses and 2 sets of 4 RTC accesses). Each ISA access takes 1-1.5uS so 10 of then at 2048 Hz takes 2-3% of a CPU. Now 4 of them take 0.8-1.2% of a CPU.
Diffstat (limited to 'sys/isa')
-rw-r--r--sys/isa/atrtc.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/sys/isa/atrtc.c b/sys/isa/atrtc.c
index 7d51363..bc0bf61 100644
--- a/sys/isa/atrtc.c
+++ b/sys/isa/atrtc.c
@@ -117,6 +117,7 @@ static u_int32_t i8254_offset;
static int (*i8254_pending)(struct intsrc *);
static int i8254_ticked;
static int using_lapic_timer;
+static int rtc_reg = -1;
static u_char rtc_statusa = RTCSA_DIVIDER | RTCSA_NOPROF;
static u_char rtc_statusb = RTCSB_24HR;
@@ -428,24 +429,30 @@ rtcin(reg)
u_char val;
RTC_LOCK;
- outb(IO_RTC, reg);
- inb(0x84);
+ if (rtc_reg != reg) {
+ inb(0x84);
+ outb(IO_RTC, reg);
+ rtc_reg = reg;
+ inb(0x84);
+ }
val = inb(IO_RTC + 1);
- inb(0x84);
RTC_UNLOCK;
return (val);
}
-static __inline void
-writertc(u_char reg, u_char val)
+static void
+writertc(int reg, u_char val)
{
RTC_LOCK;
- inb(0x84);
- outb(IO_RTC, reg);
- inb(0x84);
+ if (rtc_reg != reg) {
+ inb(0x84);
+ outb(IO_RTC, reg);
+ rtc_reg = reg;
+ inb(0x84);
+ }
outb(IO_RTC + 1, val);
- inb(0x84); /* XXX work around wrong order in rtcin() */
+ inb(0x84);
RTC_UNLOCK;
}
OpenPOWER on IntegriCloud