diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -97,7 +97,6 @@ }; static char *sysres_ids[] = { "PNP0C01", "PNP0C02", NULL }; -static char *pcilink_ids[] = { "PNP0C0F", NULL }; /* Global mutex for locking access to the ACPI subsystem. */ struct mtx acpi_mutex; @@ -1431,40 +1430,7 @@ { struct acpi_device *ad = device_get_ivars(child); struct resource_list *rl = &ad->ad_rl; - ACPI_DEVICE_INFO *devinfo; rman_res_t end; - int allow; - - /* Ignore IRQ resources for PCI link devices. */ - if (type == SYS_RES_IRQ && - ACPI_ID_PROBE(dev, child, pcilink_ids, NULL) <= 0) - return (0); - - /* - * Ignore most resources for PCI root bridges. Some BIOSes - * incorrectly enumerate the memory ranges they decode as plain - * memory resources instead of as ResourceProducer ranges. Other - * BIOSes incorrectly list system resource entries for I/O ranges - * under the PCI bridge. Do allow the one known-correct case on - * x86 of a PCI bridge claiming the I/O ports used for PCI config - * access. - */ - if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { - if (ACPI_SUCCESS(AcpiGetObjectInfo(ad->ad_handle, &devinfo))) { - if ((devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0) { -#if defined(__i386__) || defined(__amd64__) - allow = (type == SYS_RES_IOPORT && start == CONF1_ADDR_PORT); -#else - allow = 0; -#endif - if (!allow) { - AcpiOsFree(devinfo); - return (0); - } - } - AcpiOsFree(devinfo); - } - } #ifdef INTRNG /* map with default for now */ diff --git a/sys/dev/acpica/acpi_resource.c b/sys/dev/acpica/acpi_resource.c --- a/sys/dev/acpica/acpi_resource.c +++ b/sys/dev/acpica/acpi_resource.c @@ -34,6 +34,9 @@ #include #include +#if defined(__i386__) || defined(__amd64__) +#include +#endif #include #include #include @@ -62,6 +65,8 @@ int pol; }; +static char *pcilink_ids[] = { "PNP0C0F", NULL }; + static ACPI_STATUS acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *context) { @@ -582,6 +587,52 @@ void *ar_parent; }; +/* + * Some resources reported via _CRS should not be added as bus + * resources. This function returns true if a resource reported via + * _CRS should be ignored. + */ +static bool +acpi_res_ignore(device_t dev, int type, rman_res_t start, rman_res_t count) +{ + struct acpi_device *ad = device_get_ivars(dev); + ACPI_DEVICE_INFO *devinfo; + bool allow; + + /* Ignore IRQ resources for PCI link devices. */ + if (type == SYS_RES_IRQ && + ACPI_ID_PROBE(device_get_parent(dev), dev, pcilink_ids, NULL) <= 0) + return (true); + + /* + * Ignore most resources for PCI root bridges. Some BIOSes + * incorrectly enumerate the memory ranges they decode as plain + * memory resources instead of as ResourceProducer ranges. Other + * BIOSes incorrectly list system resource entries for I/O ranges + * under the PCI bridge. Do allow the one known-correct case on + * x86 of a PCI bridge claiming the I/O ports used for PCI config + * access. + */ + if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { + if (ACPI_SUCCESS(AcpiGetObjectInfo(ad->ad_handle, &devinfo))) { + if ((devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0) { +#if defined(__i386__) || defined(__amd64__) + allow = (type == SYS_RES_IOPORT && start == CONF1_ADDR_PORT); +#else + allow = false; +#endif + if (!allow) { + AcpiOsFree(devinfo); + return (true); + } + } + AcpiOsFree(devinfo); + } + } + + return (false); +} + static void acpi_res_set_init(device_t dev, void *arg, void **context) { @@ -612,6 +663,8 @@ if (cp == NULL) return; + if (acpi_res_ignore(dev, SYS_RES_IOPORT, base, length)) + return; bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length); } @@ -637,6 +690,8 @@ device_printf(dev, "_CRS has fixed I/O port range defined as relocatable\n"); + if (acpi_res_ignore(dev, SYS_RES_IOPORT, low, length)) + return; bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, low, length); return; } @@ -652,6 +707,8 @@ if (cp == NULL) return; + if (acpi_res_ignore(dev, SYS_RES_MEMORY, base, length)) + return; bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length); } @@ -676,8 +733,11 @@ if (cp == NULL || irq == NULL) return; - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { + if (acpi_res_ignore(dev, SYS_RES_IRQ, irq[i], 1)) + continue; bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, irq[i], 1); + } } static void @@ -690,8 +750,11 @@ if (cp == NULL || irq == NULL) return; - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { + if (acpi_res_ignore(dev, SYS_RES_IRQ, irq[i], 1)) + continue; bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, irq[i], 1); + } } static void @@ -706,6 +769,8 @@ if (count != 1) return; + if (acpi_res_ignore(dev, SYS_RES_DRQ, *drq, 1)) + return; bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1); }