aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/acpica/acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/acpica/acpi.c')
-rw-r--r--sys/dev/acpica/acpi.c102
1 files changed, 66 insertions, 36 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index ad1af9373fb7..f2ff1d59ccc7 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -55,6 +55,8 @@
#if defined(__i386__) || defined(__amd64__)
#include <machine/clock.h>
#include <machine/pci_cfgreg.h>
+#include <x86/cputypes.h>
+#include <x86/x86_var.h>
#endif
#include <machine/resource.h>
#include <machine/bus.h>
@@ -140,6 +142,7 @@ static bus_child_location_t acpi_child_location_method;
static bus_hint_device_unit_t acpi_hint_device_unit;
static bus_get_property_t acpi_bus_get_prop;
static bus_get_device_path_t acpi_get_device_path;
+static bus_get_domain_t acpi_get_domain_method;
static acpi_id_probe_t acpi_device_id_probe;
static acpi_evaluate_object_t acpi_device_eval_obj;
@@ -217,7 +220,7 @@ static device_method_t acpi_methods[] = {
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_hint_device_unit, acpi_hint_device_unit),
DEVMETHOD(bus_get_cpus, acpi_get_cpus),
- DEVMETHOD(bus_get_domain, acpi_get_domain),
+ DEVMETHOD(bus_get_domain, acpi_get_domain_method),
DEVMETHOD(bus_get_property, acpi_bus_get_prop),
DEVMETHOD(bus_get_device_path, acpi_get_device_path),
@@ -297,6 +300,10 @@ int acpi_susp_bounce;
SYSCTL_INT(_debug_acpi, OID_AUTO, suspend_bounce, CTLFLAG_RW,
&acpi_susp_bounce, 0, "Don't actually suspend, just test devices.");
+#if defined(__amd64__) || defined(__i386__)
+int acpi_override_isa_irq_polarity;
+#endif
+
/*
* ACPI standard UUID for Device Specific Data Package
* "Device Properties UUID for _DSD" Rev. 2.0
@@ -611,6 +618,19 @@ acpi_attach(device_t dev)
OID_AUTO, "handle_reboot", CTLFLAG_RW,
&sc->acpi_handle_reboot, 0, "Use ACPI Reset Register to reboot");
+#if defined(__amd64__) || defined(__i386__)
+ /*
+ * Enable workaround for incorrect ISA IRQ polarity by default on
+ * systems with Intel CPUs.
+ */
+ if (cpu_vendor_id == CPU_VENDOR_INTEL)
+ acpi_override_isa_irq_polarity = 1;
+ SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
+ OID_AUTO, "override_isa_irq_polarity", CTLFLAG_RDTUN,
+ &acpi_override_isa_irq_polarity, 0,
+ "Force active-hi polarity for edge-triggered ISA IRQs");
+#endif
+
/*
* Default to 1 second before sleeping to give some machines time to
* stabilize.
@@ -800,6 +820,7 @@ acpi_add_child(device_t bus, u_int order, const char *name, int unit)
if ((ad = malloc(sizeof(*ad), M_ACPIDEV, M_NOWAIT | M_ZERO)) == NULL)
return (NULL);
+ ad->ad_domain = ACPI_DEV_DOMAIN_UNKNOWN;
resource_list_init(&ad->ad_rl);
child = device_add_child_ordered(bus, order, name, unit);
@@ -1036,6 +1057,9 @@ acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
case ACPI_IVAR_FLAGS:
*(int *)result = ad->ad_flags;
break;
+ case ACPI_IVAR_DOMAIN:
+ *(int *)result = ad->ad_domain;
+ break;
case ISA_IVAR_VENDORID:
case ISA_IVAR_SERIAL:
case ISA_IVAR_COMPATID:
@@ -1080,6 +1104,9 @@ acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
case ACPI_IVAR_FLAGS:
ad->ad_flags = (int)value;
break;
+ case ACPI_IVAR_DOMAIN:
+ ad->ad_domain = (int)value;
+ break;
default:
panic("bad ivar write request (%d)", index);
return (ENOENT);
@@ -1227,8 +1254,8 @@ acpi_hint_device_unit(device_t acdev, device_t child, const char *name,
* _PXM to a NUMA domain. If the device does not have a _PXM method,
* -2 is returned. If any other error occurs, -1 is returned.
*/
-static int
-acpi_parse_pxm(device_t dev)
+int
+acpi_pxm_parse(device_t dev)
{
#ifdef NUMA
#if defined(__i386__) || defined(__amd64__) || defined(__aarch64__)
@@ -1255,7 +1282,7 @@ acpi_get_cpus(device_t dev, device_t child, enum cpu_sets op, size_t setsize,
{
int d, error;
- d = acpi_parse_pxm(child);
+ d = acpi_pxm_parse(child);
if (d < 0)
return (bus_generic_get_cpus(dev, child, op, setsize, cpuset));
@@ -1278,29 +1305,16 @@ acpi_get_cpus(device_t dev, device_t child, enum cpu_sets op, size_t setsize,
}
}
-/*
- * Fetch the NUMA domain for the given device 'dev'.
- *
- * If a device has a _PXM method, map that to a NUMA domain.
- * Otherwise, pass the request up to the parent.
- * If there's no matching domain or the domain cannot be
- * determined, return ENOENT.
- */
-int
-acpi_get_domain(device_t dev, device_t child, int *domain)
+static int
+acpi_get_domain_method(device_t dev, device_t child, int *domain)
{
- int d;
+ int error;
- d = acpi_parse_pxm(child);
- if (d >= 0) {
- *domain = d;
+ error = acpi_read_ivar(dev, child, ACPI_IVAR_DOMAIN,
+ (uintptr_t *)domain);
+ if (error == 0 && *domain != ACPI_DEV_DOMAIN_UNKNOWN)
return (0);
- }
- if (d == -1)
- return (ENOENT);
-
- /* No _PXM node; go up a level */
- return (bus_generic_get_domain(dev, child, domain));
+ return (ENOENT);
}
static struct rman *
@@ -1651,19 +1665,22 @@ acpi_map_resource(device_t bus, device_t child, struct resource *r,
args.offset = start - rman_get_start(sysres);
args.length = length;
- return (bus_generic_map_resource(bus, child, sysres, &args, map));
+ return (bus_map_resource(bus, sysres, &args, map));
}
static int
acpi_unmap_resource(device_t bus, device_t child, struct resource *r,
struct resource_map *map)
{
- if (acpi_is_resource_managed(bus, r)) {
- r = acpi_managed_resource(bus, r);
- if (r == NULL)
- return (ENOENT);
- }
- return (bus_generic_unmap_resource(bus, child, r, map));
+ struct resource *sysres;
+
+ if (!acpi_is_resource_managed(bus, r))
+ return (bus_generic_unmap_resource(bus, child, r, map));
+
+ sysres = acpi_managed_resource(bus, r);
+ if (sysres == NULL)
+ return (ENOENT);
+ return (bus_unmap_resource(bus, sysres, map));
}
/* Allocate an IO port or memory resource, given its GAS. */
@@ -2262,11 +2279,11 @@ acpi_probe_children(device_t bus)
/* Create any static children by calling device identify methods. */
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "device identify routines\n"));
- bus_generic_probe(bus);
+ bus_identify_children(bus);
/* Probe/attach all children, created statically and from the namespace. */
- ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "acpi bus_generic_attach\n"));
- bus_generic_attach(bus);
+ ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "acpi bus_attach_children\n"));
+ bus_attach_children(bus);
/*
* Reserve resources allocated to children but not yet allocated
@@ -2326,7 +2343,7 @@ acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
ACPI_HANDLE h;
device_t bus, child;
char *handle_str;
- int order;
+ int d, order;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@@ -2374,7 +2391,7 @@ acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "scanning '%s'\n", handle_str));
order = level * 10 + ACPI_DEV_BASE_ORDER;
acpi_probe_order(handle, &order);
- child = BUS_ADD_CHILD(bus, order, NULL, -1);
+ child = BUS_ADD_CHILD(bus, order, NULL, DEVICE_UNIT_ANY);
if (child == NULL)
break;
@@ -2434,6 +2451,10 @@ acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
}
AcpiOsFree(devinfo);
}
+
+ d = acpi_pxm_parse(child);
+ if (d >= 0)
+ ad->ad_domain = d;
break;
}
}
@@ -3881,13 +3902,22 @@ acpi_invoke_wake_eventhandler(void *context)
UINT32
acpi_event_power_button_sleep(void *context)
{
+#if defined(__amd64__) || defined(__i386__)
struct acpi_softc *sc = (struct acpi_softc *)context;
+#else
+ (void)context;
+#endif
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
+#if defined(__amd64__) || defined(__i386__)
if (ACPI_FAILURE(AcpiOsExecute(OSL_NOTIFY_HANDLER,
acpi_invoke_sleep_eventhandler, &sc->acpi_power_button_sx)))
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
+#else
+ shutdown_nice(RB_POWEROFF);
+#endif
+
return_VALUE (ACPI_INTERRUPT_HANDLED);
}