bus: Add ACPI locator support

Add support for printing ACPI paths. This is a bit of a degenerate case
for this interface since it's always just the device handle if the
device has one. But it is illustrtive of how to do this for a few nodes
in the tree.

Sponsored by:		Netflix
Reviewed by:		jhb
Differential Revision:	https://reviews.freebsd.org/D32748
This commit is contained in:
Warner Losh 2022-02-28 14:27:42 -07:00
parent f5366026ad
commit cae7d9ec83
8 changed files with 76 additions and 1 deletions

View File

@ -187,6 +187,8 @@ static int acpi_child_location_method(device_t acdev, device_t child,
struct sbuf *sb);
static int acpi_child_pnpinfo_method(device_t acdev, device_t child,
struct sbuf *sb);
static int acpi_get_device_path(device_t bus, device_t child,
const char *locator, struct sbuf *sb);
static void acpi_enable_pcie(void);
static void acpi_hint_device_unit(device_t acdev, device_t child,
const char *name, int *unitp);
@ -226,6 +228,7 @@ static device_method_t acpi_methods[] = {
DEVMETHOD(bus_get_cpus, acpi_get_cpus),
DEVMETHOD(bus_get_domain, acpi_get_domain),
DEVMETHOD(bus_get_property, acpi_bus_get_prop),
DEVMETHOD(bus_get_device_path, acpi_get_device_path),
/* ACPI bus */
DEVMETHOD(acpi_id_probe, acpi_device_id_probe),
@ -928,6 +931,37 @@ acpi_child_pnpinfo_method(device_t cbdev, device_t child, struct sbuf *sb)
return (acpi_pnpinfo(dinfo->ad_handle, sb));
}
/*
* Note: the check for ACPI locator may be reduntant. However, this routine is
* suitable for both busses whose only locator is ACPI and as a building block
* for busses that have multiple locators to cope with.
*/
int
acpi_get_acpi_device_path(device_t bus, device_t child, const char *locator, struct sbuf *sb)
{
if (strcmp(locator, BUS_LOCATOR_ACPI) == 0) {
ACPI_HANDLE *handle = acpi_get_handle(child);
if (handle != NULL)
sbuf_printf(sb, "%s", acpi_name(handle));
return (0);
}
return (bus_generic_get_device_path(bus, child, locator, sb));
}
static int
acpi_get_device_path(device_t bus, device_t child, const char *locator, struct sbuf *sb)
{
struct acpi_device *dinfo = device_get_ivars(child);
if (strcmp(locator, BUS_LOCATOR_ACPI) == 0)
return (acpi_get_acpi_device_path(bus, child, locator, sb));
/* For the rest, punt to the default handler */
return (bus_generic_get_device_path(bus, child, locator, sb));
}
/*
* Handle device deletion.
*/

View File

@ -81,6 +81,8 @@ static int acpi_pci_attach(device_t dev);
static void acpi_pci_child_deleted(device_t dev, device_t child);
static int acpi_pci_child_location_method(device_t cbdev,
device_t child, struct sbuf *sb);
static int acpi_pci_get_device_path(device_t cbdev,
device_t child, const char *locator, struct sbuf *sb);
static int acpi_pci_detach(device_t dev);
static int acpi_pci_probe(device_t dev);
static int acpi_pci_read_ivar(device_t dev, device_t child, int which,
@ -105,6 +107,7 @@ static device_method_t acpi_pci_methods[] = {
DEVMETHOD(bus_write_ivar, acpi_pci_write_ivar),
DEVMETHOD(bus_child_deleted, acpi_pci_child_deleted),
DEVMETHOD(bus_child_location, acpi_pci_child_location_method),
DEVMETHOD(bus_get_device_path, acpi_pci_get_device_path),
DEVMETHOD(bus_get_cpus, acpi_get_cpus),
DEVMETHOD(bus_get_dma_tag, acpi_pci_get_dma_tag),
DEVMETHOD(bus_get_domain, acpi_get_domain),
@ -196,6 +199,17 @@ acpi_pci_child_location_method(device_t cbdev, device_t child, struct sbuf *sb)
return (0);
}
static int
acpi_pci_get_device_path(device_t bus, device_t child, const char *locator, struct sbuf *sb)
{
if (strcmp(locator, BUS_LOCATOR_ACPI) == 0)
return (acpi_get_acpi_device_path(bus, child, locator, sb));
/* For the rest, punt to the default handler */
return (bus_generic_get_device_path(bus, child, locator, sb));
}
/*
* PCI power manangement
*/

View File

@ -495,6 +495,8 @@ acpi_get_verbose(struct acpi_softc *sc)
char *acpi_name(ACPI_HANDLE handle);
int acpi_avoid(ACPI_HANDLE handle);
int acpi_disabled(char *subsys);
int acpi_get_acpi_device_path(device_t bus, device_t child,
const char *locator, struct sbuf *sb);
int acpi_machdep_init(device_t dev);
void acpi_install_wakeup_handler(struct acpi_softc *sc);
int acpi_sleep_machdep(struct acpi_softc *sc, int state);

View File

@ -764,6 +764,7 @@ static device_method_t acpi_iicbus_methods[] = {
DEVMETHOD(bus_write_ivar, acpi_iicbus_write_ivar),
DEVMETHOD(bus_child_location, acpi_iicbus_child_location),
DEVMETHOD(bus_child_pnpinfo, acpi_iicbus_child_pnpinfo),
DEVMETHOD(bus_get_device_path, acpi_get_acpi_device_path),
DEVMETHOD_END,
};

View File

@ -265,6 +265,7 @@ static device_method_t nvdimm_acpi_methods[] = {
DEVMETHOD(bus_read_ivar, nvdimm_root_read_ivar),
DEVMETHOD(bus_write_ivar, nvdimm_root_write_ivar),
DEVMETHOD(bus_child_location, nvdimm_root_child_location),
DEVMETHOD(bus_get_device_path, acpi_get_acpi_device_path),
DEVMETHOD_END
};

View File

@ -553,11 +553,22 @@ acpi_uhub_child_location(device_t parent, device_t child, struct sbuf *sb)
return (0);
}
static int
acpi_uhub_get_device_path(device_t bus, device_t child, const char *locator, struct sbuf *sb)
{
if (strcmp(locator, BUS_LOCATOR_ACPI) == 0)
return (acpi_get_acpi_device_path(bus, child, locator, sb));
/* For the rest, punt to the default handler */
return (bus_generic_get_device_path(bus, child, locator, sb));
}
static device_method_t acpi_uhub_methods[] = {
DEVMETHOD(device_probe, acpi_uhub_probe),
DEVMETHOD(device_attach, acpi_uhub_attach),
DEVMETHOD(device_detach, acpi_uhub_detach),
DEVMETHOD(bus_child_location, acpi_uhub_child_location),
DEVMETHOD(bus_get_device_path, acpi_uhub_get_device_path),
DEVMETHOD(bus_read_ivar, acpi_uhub_read_ivar),
DEVMETHOD_END
@ -569,6 +580,7 @@ static device_method_t acpi_uhub_root_methods[] = {
DEVMETHOD(device_detach, acpi_uhub_detach),
DEVMETHOD(bus_read_ivar, acpi_uhub_read_ivar),
DEVMETHOD(bus_child_location, acpi_uhub_child_location),
DEVMETHOD(bus_get_device_path, acpi_uhub_get_device_path),
DEVMETHOD_END
};

View File

@ -4645,9 +4645,19 @@ bus_generic_get_device_path(device_t bus, device_t child, const char *locator,
int rv = 0;
device_t parent;
/*
* We don't recurse on ACPI since either we know the handle for the
* device or we don't. And if we're in the generic routine, we don't
* have a ACPI override. All other locators build up a path by having
* their parents create a path and then adding the path element for this
* node. That's why we recurse with parent, bus rather than the typical
* parent, child: each spot in the tree is independent of what our child
* will do with this path.
*/
parent = device_get_parent(bus);
if (parent != NULL)
if (parent != NULL && strcmp(locator, BUS_LOCATOR_ACPI) != 0) {
rv = BUS_GET_DEVICE_PATH(parent, bus, locator, sb);
}
if (strcmp(locator, BUS_LOCATOR_FREEBSD) == 0) {
if (rv == 0) {
sbuf_printf(sb, "/%s", device_get_nameunit(child));

View File

@ -737,6 +737,7 @@ void bus_data_generation_update(void);
#define BUS_PASS_ORDER_LATE 7
#define BUS_PASS_ORDER_LAST 9
#define BUS_LOCATOR_ACPI "ACPI"
#define BUS_LOCATOR_FREEBSD "FreeBSD"
extern int bus_current_pass;