tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: 4.0/i386 auich_calibrate() and GENERIC.NOACPI failure
> On Sat, Jan 12, 2008 at 11:07:51AM -0500, Chuck Cranor wrote:
> > The i8254 may be slow, but it seemed to work just fine before this...?
> >
> > At any rate, Joerg suggested I put the auich_calibrate() loop in an
> > splvm(), so I did that plus your curcpu()->ci_ilevel suggestion.
> > The results:
> >
> > 1. splvm() didn't help
> > 2. splclock() _did_ fix the problem!
> > 3. the value of curcpu()->ci_ilevel is 0 (zero) before the loop.
> > Are you sure we are supposed to be at IPL_HIGH? I thought zero
> > was IPL_NONE?
hi-
I did even more debugging and I think I discovered the root cause
to this timer problem!! The spl() thing turned out to be a symptom
of the problem rather than the cause.
The problem was inadverently introduced in 1.98 of
src/sys/arch/i386/isa/clock.c when the variable "clkintr_pending"
was removed because it was "unused" ... that's not really true.
It was always zero (because it was never set) thus permanently
short-circuited out part of an if statement in the function
i8254_get_timecount():
@@ -195,8 +195,6 @@
static inline int gettick_broken_latch(void);
-int clkintr_pending;
-
static volatile uint32_t i8254_lastcount;
static volatile uint32_t i8254_offset;
static volatile int i8254_ticked;
@@ -434,7 +432,7 @@
high = inb(IO_TIMER1 + TIMER_CNTR0);
count = rtclock_tval - ((high << 8) | low);
- if (rtclock_tval && (count < i8254_lastcount || (!i8254_ticked &&
clkintr_pending))) {
+ if (rtclock_tval && (count < i8254_lastcount || !i8254_ticked)) {
i8254_ticked = 1;
i8254_offset += rtclock_tval;
}
Since clkintr_pending is always zero, what really happened here was that
the "if" statement changed from:
OLD: if (rtclock_tval && count < i8254_lastcount) {
NEW: if (rtclock_tval && (count < i8254_lastcount || !i8254_ticked)) {
To test this, I checked out a source tree from 2006.09.03.20.00.00
(auich works properly), and then rolled clock.c forward from 1.97 to
1.98 (auich fails).
Furthermore, if you take a netbsd-4-0-RELEASE source tree, patch
src/sys/arch/x86/isa/clock.c like this:
--- clock.c_ORIG 2008-01-14 16:30:01.000000000 -0500
+++ clock.c 2008-01-14 16:30:31.000000000 -0500
@@ -439,7 +439,7 @@
high = inb(IO_TIMER1 + TIMER_CNTR0);
count = rtclock_tval - ((high << 8) | low);
- if (rtclock_tval && (count < i8254_lastcount || !i8254_ticked)) {
+ if (rtclock_tval && (count < i8254_lastcount /*|| !i8254_ticked*/)) {
i8254_ticked = 1;
i8254_offset += rtclock_tval;
}
and compile a GENERIC.NOACPI with that change, then the auich_calibrate()
probe works just fine:
auich0 at pci0 dev 31 function 5: i82801BA (ICH2) AC-97 Audio
auich0: interrupting at irq 10
auich0: ac97: Analog Devices AD1885 codec; headphone, Analog Devices Phat Stereo
auich0: ac97: ext id 1<VRA>
auich0: measured ac97 link rate at 55071 Hz, will use 55000 Hz
audio0 at auich0: full duplex, mmap, independent
My theory on the spls is that they were blocking rtclock_tval and
friends from being used during the test, so it masked out both
the interrupts and the bug (?).
So, do we need !i8254_ticked?
chuck
Home |
Main Index |
Thread Index |
Old Index