mirror of
https://github.com/freebsd/freebsd-src
synced 2024-07-21 18:27:22 +00:00
acpi: Allow child drivers to use bus_set_resource for more resources
acpi_set_resource excludes certain types of resources for certain devices. The intention of this is to avoid adding resource entries for bogus resources enumerated via _CRS. However, this also prevents drivers from adding those resources explicitly if needed. To fix this, move the logic to exclude these resources into an ignore hook used when parsing _CRS to create the initial set of resources for each device. Reviewed by: imp Differential Revision: https://reviews.freebsd.org/D43892
This commit is contained in:
parent
e05436d577
commit
055c1fe230
|
@ -97,7 +97,6 @@ struct acpi_interface {
|
|||
};
|
||||
|
||||
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 @@ acpi_set_resource(device_t dev, device_t child, int type, int rid,
|
|||
{
|
||||
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 */
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#if defined(__i386__) || defined(__amd64__)
|
||||
#include <machine/pci_cfgreg.h>
|
||||
#endif
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
@ -62,6 +65,8 @@ struct lookup_irq_request {
|
|||
int pol;
|
||||
};
|
||||
|
||||
static char *pcilink_ids[] = { "PNP0C0F", NULL };
|
||||
|
||||
static ACPI_STATUS
|
||||
acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *context)
|
||||
{
|
||||
|
@ -582,6 +587,52 @@ struct acpi_res_context {
|
|||
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 @@ acpi_res_set_ioport(device_t dev, void *context, uint64_t base,
|
|||
|
||||
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 @@ acpi_res_set_iorange(device_t dev, void *context, uint64_t low,
|
|||
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 @@ acpi_res_set_memory(device_t dev, void *context, uint64_t base,
|
|||
|
||||
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 @@ acpi_res_set_irq(device_t dev, void *context, uint8_t *irq, int count,
|
|||
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 @@ acpi_res_set_ext_irq(device_t dev, void *context, uint32_t *irq, int count,
|
|||
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 @@ acpi_res_set_drq(device_t dev, void *context, uint8_t *drq, int count)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue