From owner-acpi-jp@jp.FreeBSD.org Mon Jul 28 15:12:13 2003
Received: (from daemon@localhost)
	by castle.jp.FreeBSD.org (8.11.6p2+3.4W/8.11.3) id h6S6CDj89246;
	Mon, 28 Jul 2003 15:12:13 +0900 (JST)
	(envelope-from owner-acpi-jp@jp.FreeBSD.org)
Received: from rootlabs.com (root.org [67.118.192.226])
	by castle.jp.FreeBSD.org (8.11.6p2+3.4W/8.11.3) with SMTP/inet id h6S6CBT89238
	for <acpi-jp@jp.FreeBSD.org>; Mon, 28 Jul 2003 15:12:12 +0900 (JST)
	(envelope-from nate@rootlabs.com)
Received: (qmail 51682 invoked by uid 1000); 28 Jul 2003 06:12:08 -0000
From: Nate Lawson <nate@root.org>
To: "Grover, Andrew" <andrew.grover@intel.com>
cc: acpi-jp@jp.FreeBSD.org
In-Reply-To: <F760B14C9561B941B89469F59BA3A8470255EEA5@orsmsx401.jf.intel.com>
Message-ID: <20030727225701.T51580@root.org>
References: <F760B14C9561B941B89469F59BA3A8470255EEA5@orsmsx401.jf.intel.com>
MIME-Version: 1.0
Content-Type: TEXT/PLAIN; charset=US-ASCII
Reply-To: acpi-jp@jp.FreeBSD.org
Precedence: list
Date: Sun, 27 Jul 2003 23:12:08 -0700
X-Sequence: acpi-jp 2511
Subject: [acpi-jp 2511] Re: EC was: RE: acpi and cpu performance states
Sender: owner-acpi-jp@jp.FreeBSD.org
X-Originator: nate@root.org
X-Distribute: distribute version 2.1 (Alpha) patchlevel 24e+030702

On Fri, 25 Jul 2003, Grover, Andrew wrote:
> Arrgh. You want me to install FreeBSD on the T40? I was willing to do
> this but the installer wasn't able to use the onboard Intel e1000, and
> using a cardbus/pcmcia NIC causes the kernel to trap:
>
> Fatal trap 12: page fault while in kernel mode
> fault virtual address = 0x91e210a5
> fault code = supervisor write, page not present
> instruction pointer = 0x8:0xc2a59700
> frame pointer = 0x10:0xcd2f2d0c
> code segment = base 0x0, limit 0xfffff, type 0x1b
> 	= DPL 0, pres 1, def32 1, gran 1
> processor eflags = interrupt enabled, resume, IOPL = 0
> current process = 24 (irq11: cbb0 cbb1++*)
> trap number = 12
> panic: page fault
>
> This happens with ACPI enabled or disabled.

What type of card is this?

> In more general terms, can you maybe just describe your solution for
> no-response errors? Did you just increase the timeout or what, exactly?

Oh, I see.  I thought you were already using FreeBSD and were having
problems.  I took a very straightforward approach:

1. All reading of the CSR is done through polling.  This is done with the
device mutex held to block against the SCI handler grabbing the status
before a polling thread gets to it and thus the status never appearing.

2. Polling is done through a backoff function which ratchets up the DELAY
busy wait loop when the EC takes a while to respond but also drops it down
when it responds within the current DELAY quantum.  It starts at busy
waiting for 1 us and reaches a maximum of 100 us.  Many ECs respond on the
order of 1-5 us in normal operation.  I believe other issues (i.e. Giant
which is our kernel lock) may contribute to the latency some people see in
EC event handling.

3. If the EC hasn't responded within 1 ms, then sleep for up to 50 ms but
drop the mutex.  This is done through msleep().  This allows interrupts to
occur (for instance, the SCI can run) and other acpi events aren't
potentially blocked.  Since only the SCI handler accesses the EC
registers, it is the only current contender but in the future other events
may content for the same mutex.

4. The SCI handler acquires the device mutex also to prevent a race with
say a call to EcRead().  However, a caller to EcRead() may go to sleep and
drop the lock via msleep if the wait exceeds 1 ms.  In this case, if the
SCI handler is called and finds the status register is not for it (i.e.
OBF/IBE events), it stores the CSR value it read in the softc for the
sleeping thread and calls wakeup().  If EcEventWait finds it was woken up,
it uses the CSR value it was passed instead of reading the CSR again.

Note that the original code did something similar, however, it did not
force purely polled access and instead let everything be driven by
interrupts.  This does not work for many ECs.

Note also that there is a bug in the Linux code:
#define ACPI_EC_UDELAY          100     /* Poll @ 100us increments */
#define ACPI_EC_UDELAY_COUNT    1000    /* Wait 10ms max. during EC ops */

The COUNT value should be 100 if you want 10 ms.  These values result in a
wait of 100 ms.

-Nate
