Some BIOSes ACPI bytecode needs to take (sleepable) acpi mutex for

acpi_GetInteger() execution.  Intel DMAR interrupt remapping code
needs to know UID of the HPET to properly route the FSB interrupts
from the HPET, even when interrupt remapping is disabled, and the code
is executed under some non-sleepable mutexes.

Cache HPET UIDs in the device softc at the attach time and provide
lock-less method to get UID, use the method from the dmar hpet
handling code instead of calling GetInteger().

Reported and tested by:	Larry Rosenman <ler@lerctr.org>
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2016-02-20 13:37:04 +00:00
parent 94a4ee3be7
commit 2fe1339ea2
3 changed files with 15 additions and 6 deletions

View File

@ -85,6 +85,7 @@ struct hpet_softc {
struct resource *intr_res;
void *intr_handle;
ACPI_HANDLE handle;
uint32_t acpi_uid;
uint64_t freq;
uint32_t caps;
struct timecounter tc;
@ -295,6 +296,15 @@ hpet_intr(void *arg)
return (FILTER_STRAY);
}
uint32_t
hpet_get_uid(device_t dev)
{
struct hpet_softc *sc;
sc = device_get_softc(dev);
return (sc->acpi_uid);
}
static ACPI_STATUS
hpet_find(ACPI_HANDLE handle, UINT32 level, void *context,
void **status)
@ -746,6 +756,7 @@ hpet_attach(device_t dev)
maxhpetet++;
}
}
acpi_GetInteger(sc->handle, "_UID", &sc->acpi_uid);
make_dev_args_init(&mda);
mda.mda_devsw = &hpet_cdevsw;

View File

@ -441,6 +441,8 @@ int acpi_wakeup_machdep(struct acpi_softc *sc, int state,
int acpi_table_quirks(int *quirks);
int acpi_machdep_quirks(int *quirks);
uint32_t hpet_get_uid(device_t dev);
/* Battery Abstraction. */
struct acpi_battinfo;

View File

@ -826,13 +826,9 @@ dmar_find_nonpci(u_int id, u_int entry_type, uint16_t *rid)
struct dmar_unit *
dmar_find_hpet(device_t dev, uint16_t *rid)
{
ACPI_HANDLE handle;
uint32_t hpet_id;
handle = acpi_get_handle(dev);
if (ACPI_FAILURE(acpi_GetInteger(handle, "_UID", &hpet_id)))
return (NULL);
return (dmar_find_nonpci(hpet_id, ACPI_DMAR_SCOPE_TYPE_HPET, rid));
return (dmar_find_nonpci(hpet_get_uid(dev), ACPI_DMAR_SCOPE_TYPE_HPET,
rid));
}
struct dmar_unit *