Module Name:    src
Committed By:   jruoho
Date:           Fri Feb 25 19:55:07 UTC 2011

Modified Files:
        src/sys/dev/acpi: acpi_cpu.c acpi_cpu.h acpi_cpu_cstate.c
            acpi_cpu_pstate.c acpi_cpu_tstate.c

Log Message:
Start to derive the percpu(9) (or per-domain) state coordination
mechanisms by parsing the _CSD, _PSD, and _TSD objects by default.


To generate a diff of this commit:
cvs rdiff -u -r1.28 -r1.29 src/sys/dev/acpi/acpi_cpu.c
cvs rdiff -u -r1.31 -r1.32 src/sys/dev/acpi/acpi_cpu.h
cvs rdiff -u -r1.45 -r1.46 src/sys/dev/acpi/acpi_cpu_cstate.c
cvs rdiff -u -r1.39 -r1.40 src/sys/dev/acpi/acpi_cpu_pstate.c
cvs rdiff -u -r1.22 -r1.23 src/sys/dev/acpi/acpi_cpu_tstate.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/acpi/acpi_cpu.c
diff -u src/sys/dev/acpi/acpi_cpu.c:1.28 src/sys/dev/acpi/acpi_cpu.c:1.29
--- src/sys/dev/acpi/acpi_cpu.c:1.28	Fri Feb 25 12:08:35 2011
+++ src/sys/dev/acpi/acpi_cpu.c	Fri Feb 25 19:55:06 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu.c,v 1.28 2011/02/25 12:08:35 jruoho Exp $ */
+/* $NetBSD: acpi_cpu.c,v 1.29 2011/02/25 19:55:06 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2010, 2011 Jukka Ruohonen <[email protected]>
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.28 2011/02/25 12:08:35 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.29 2011/02/25 19:55:06 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/cpu.h>
@@ -54,6 +54,8 @@
 static int		  acpicpu_once_detach(void);
 static void		  acpicpu_prestart(device_t);
 static void		  acpicpu_start(device_t);
+static void		  acpicpu_debug_print(struct acpicpu_softc *);
+static const char	 *acpicpu_debug_print_dep(uint32_t);
 static void		  acpicpu_sysctl(device_t);
 
 static int		  acpicpu_object(ACPI_HANDLE, struct acpicpu_object *);
@@ -145,6 +147,7 @@
 	acpicpu_sc[id] = sc;
 
 	sc->sc_cap = acpicpu_cap(sc);
+	sc->sc_ncpus = acpi_md_ncpus();
 	sc->sc_flags |= acpicpu_md_flags();
 
 	mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE);
@@ -156,6 +159,8 @@
 	(void)config_defer(self, acpicpu_prestart);
 	(void)acpi_register_notify(sc->sc_node, acpicpu_notify);
 	(void)pmf_device_register(self, acpicpu_suspend, acpicpu_resume);
+
+	acpicpu_debug_print(sc);
 }
 
 static int
@@ -632,6 +637,59 @@
 	return true;
 }
 
+static void
+acpicpu_debug_print(struct acpicpu_softc *sc)
+{
+	struct acpicpu_dep *dep;
+
+	if ((sc->sc_flags & ACPICPU_FLAG_C_DEP) != 0) {
+
+		dep = &sc->sc_cstate_dep;
+
+		aprint_debug_dev(sc->sc_dev, "C-state coordination: "
+		    "%u CPUs, domain %u, type %s\n", dep->dep_ncpus,
+		    dep->dep_domain, acpicpu_debug_print_dep(dep->dep_type));
+	}
+
+	if ((sc->sc_flags & ACPICPU_FLAG_P_DEP) != 0) {
+
+		dep = &sc->sc_pstate_dep;
+
+		aprint_debug_dev(sc->sc_dev, "P-state coordination: "
+		    "%u CPUs, domain %u, type %s\n", dep->dep_ncpus,
+		    dep->dep_domain, acpicpu_debug_print_dep(dep->dep_type));
+	}
+
+	if ((sc->sc_flags & ACPICPU_FLAG_T_DEP) != 0) {
+
+		dep = &sc->sc_tstate_dep;
+
+		aprint_debug_dev(sc->sc_dev, "T-state coordination: "
+		    "%u CPUs, domain %u, type %s\n", dep->dep_ncpus,
+		    dep->dep_domain, acpicpu_debug_print_dep(dep->dep_type));
+	}
+}
+
+static const char *
+acpicpu_debug_print_dep(uint32_t val)
+{
+
+	switch (val) {
+
+	case ACPICPU_DEP_SW_ALL:
+		return "SW_ALL";
+
+	case ACPICPU_DEP_SW_ANY:
+		return "SW_ANY";
+
+	case ACPICPU_DEP_HW_ALL:
+		return "HW_ALL";
+
+	default:
+		return "unknown";
+	}
+}
+
 MODULE(MODULE_CLASS_DRIVER, acpicpu, NULL);
 
 #ifdef _MODULE

Index: src/sys/dev/acpi/acpi_cpu.h
diff -u src/sys/dev/acpi/acpi_cpu.h:1.31 src/sys/dev/acpi/acpi_cpu.h:1.32
--- src/sys/dev/acpi/acpi_cpu.h:1.31	Fri Feb 25 12:08:35 2011
+++ src/sys/dev/acpi/acpi_cpu.h	Fri Feb 25 19:55:06 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu.h,v 1.31 2011/02/25 12:08:35 jruoho Exp $ */
+/* $NetBSD: acpi_cpu.h,v 1.32 2011/02/25 19:55:06 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2010, 2011 Jukka Ruohonen <[email protected]>
@@ -63,6 +63,13 @@
 #define ACPICPU_T_NOTIFY	 0x82		/* _TPC */
 
 /*
+ * Dependency coordination.
+ */
+#define ACPICPU_DEP_SW_ALL	 0xFC
+#define ACPICPU_DEP_SW_ANY	 0xFD
+#define ACPICPU_DEP_HW_ALL	 0xFE
+
+/*
  * C-states.
  */
 #define ACPICPU_C_C2_LATENCY_MAX 100		/* us */
@@ -97,21 +104,24 @@
 
 #define ACPICPU_FLAG_C_FFH	 __BIT(4)	/* Native C-states           */
 #define ACPICPU_FLAG_C_FADT	 __BIT(5)	/* C-states with FADT        */
-#define ACPICPU_FLAG_C_BM	 __BIT(6)	/* Bus master control        */
-#define ACPICPU_FLAG_C_BM_STS	 __BIT(7)	/* Bus master check required */
-#define ACPICPU_FLAG_C_ARB	 __BIT(8)	/* Bus master arbitration    */
-#define ACPICPU_FLAG_C_TSC	 __BIT(9)	/* TSC broken, > C1, Px, Tx  */
-#define ACPICPU_FLAG_C_APIC	 __BIT(10)	/* APIC timer broken, > C1   */
-#define ACPICPU_FLAG_C_C1E	 __BIT(11)	/* AMD C1E detected	     */
-
-#define ACPICPU_FLAG_P_FFH	 __BIT(12)	/* Native P-states           */
-#define ACPICPU_FLAG_P_HW	 __BIT(13)	/* HW coordination supported */
-#define ACPICPU_FLAG_P_XPSS	 __BIT(14)	/* Microsoft XPSS in use     */
-#define ACPICPU_FLAG_P_TURBO	 __BIT(15)	/* Turbo Boost / Turbo Core  */
-#define ACPICPU_FLAG_P_FIDVID	 __BIT(16)	/* AMD "FID/VID algorithm"   */
-
-#define ACPICPU_FLAG_T_FFH	 __BIT(17)	/* Native throttling         */
-#define ACPICPU_FLAG_T_FADT	 __BIT(18)	/* Throttling with FADT      */
+#define ACPICPU_FLAG_C_DEP	 __BIT(6)	/* C-state CPU coordination  */
+#define ACPICPU_FLAG_C_BM	 __BIT(7)	/* Bus master control        */
+#define ACPICPU_FLAG_C_BM_STS	 __BIT(8)	/* Bus master check required */
+#define ACPICPU_FLAG_C_ARB	 __BIT(9)	/* Bus master arbitration    */
+#define ACPICPU_FLAG_C_TSC	 __BIT(10)	/* TSC broken, > C1, Px, Tx  */
+#define ACPICPU_FLAG_C_APIC	 __BIT(11)	/* APIC timer broken, > C1   */
+#define ACPICPU_FLAG_C_C1E	 __BIT(12)	/* AMD C1E detected	     */
+
+#define ACPICPU_FLAG_P_FFH	 __BIT(13)	/* Native P-states           */
+#define ACPICPU_FLAG_P_DEP	 __BIT(14)	/* P-state CPU coordination  */
+#define ACPICPU_FLAG_P_HW	 __BIT(15)	/* HW coordination supported */
+#define ACPICPU_FLAG_P_XPSS	 __BIT(16)	/* Microsoft XPSS in use     */
+#define ACPICPU_FLAG_P_TURBO	 __BIT(17)	/* Turbo Boost / Turbo Core  */
+#define ACPICPU_FLAG_P_FIDVID	 __BIT(18)	/* AMD "FID/VID algorithm"   */
+
+#define ACPICPU_FLAG_T_FFH	 __BIT(19)	/* Native throttling         */
+#define ACPICPU_FLAG_T_FADT	 __BIT(20)	/* Throttling with FADT      */
+#define ACPICPU_FLAG_T_DEP	 __BIT(21)	/* T-state CPU coordination  */
 
 /*
  * This is AML_RESOURCE_GENERIC_REGISTER,
@@ -127,6 +137,13 @@
 	uint64_t		 reg_addr;
 } __packed;
 
+struct acpicpu_dep {
+	uint32_t		 dep_domain;
+	uint32_t		 dep_type;
+	uint32_t		 dep_ncpus;
+	uint32_t		 dep_index;
+};
+
 struct acpicpu_cstate {
 	struct evcnt		 cs_evcnt;
 	char			 cs_name[EVCNT_STRING_MAX];
@@ -183,9 +200,11 @@
 	struct acpicpu_object	 sc_object;
 
 	struct acpicpu_cstate	 sc_cstate[ACPI_C_STATE_COUNT];
+	struct acpicpu_dep	 sc_cstate_dep;
 	uint32_t		 sc_cstate_sleep;
 
 	struct acpicpu_pstate	*sc_pstate;
+	struct acpicpu_dep	 sc_pstate_dep;
 	struct acpicpu_reg	 sc_pstate_control;
 	struct acpicpu_reg	 sc_pstate_status;
 	uint64_t		 sc_pstate_aperf;	/* ACPICPU_FLAG_P_HW */
@@ -196,6 +215,7 @@
 	uint32_t		 sc_pstate_min;
 
 	struct acpicpu_tstate	*sc_tstate;
+	struct acpicpu_dep	 sc_tstate_dep;
 	struct acpicpu_reg	 sc_tstate_control;
 	struct acpicpu_reg	 sc_tstate_status;
 	uint32_t		 sc_tstate_current;
@@ -205,6 +225,7 @@
 
 	kmutex_t		 sc_mtx;
 	uint32_t		 sc_cap;
+	uint32_t		 sc_ncpus;
 	uint32_t		 sc_flags;
 	bool			 sc_cold;
 };

Index: src/sys/dev/acpi/acpi_cpu_cstate.c
diff -u src/sys/dev/acpi/acpi_cpu_cstate.c:1.45 src/sys/dev/acpi/acpi_cpu_cstate.c:1.46
--- src/sys/dev/acpi/acpi_cpu_cstate.c:1.45	Fri Feb 25 12:08:35 2011
+++ src/sys/dev/acpi/acpi_cpu_cstate.c	Fri Feb 25 19:55:06 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu_cstate.c,v 1.45 2011/02/25 12:08:35 jruoho Exp $ */
+/* $NetBSD: acpi_cpu_cstate.c,v 1.46 2011/02/25 19:55:06 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2010, 2011 Jukka Ruohonen <[email protected]>
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_cstate.c,v 1.45 2011/02/25 12:08:35 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_cstate.c,v 1.46 2011/02/25 19:55:06 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/cpu.h>
@@ -56,6 +56,7 @@
 						ACPI_OBJECT *, int );
 static void		 acpicpu_cstate_cst_bios(void);
 static void		 acpicpu_cstate_memset(struct acpicpu_softc *);
+static ACPI_STATUS	 acpicpu_cstate_dep(struct acpicpu_softc *);
 static void		 acpicpu_cstate_fadt(struct acpicpu_softc *);
 static void		 acpicpu_cstate_quirks(struct acpicpu_softc *);
 static int		 acpicpu_cstate_latency(struct acpicpu_softc *);
@@ -99,6 +100,14 @@
 		break;
 	}
 
+	/*
+	 * Query the optional _CSD.
+	 */
+	rv = acpicpu_cstate_dep(sc);
+
+	if (ACPI_SUCCESS(rv))
+		sc->sc_flags |= ACPICPU_FLAG_C_DEP;
+
 	sc->sc_flags |= ACPICPU_FLAG_C;
 
 	acpicpu_cstate_quirks(sc);
@@ -528,6 +537,96 @@
 	}
 }
 
+static ACPI_STATUS
+acpicpu_cstate_dep(struct acpicpu_softc *sc)
+{
+	ACPI_OBJECT *elm, *obj;
+	ACPI_BUFFER buf;
+	ACPI_STATUS rv;
+	uint32_t val;
+	uint8_t i, n;
+
+	rv = acpi_eval_struct(sc->sc_node->ad_handle, "_CSD", &buf);
+
+	if (ACPI_FAILURE(rv))
+		goto out;
+
+	obj = buf.Pointer;
+
+	if (obj->Type != ACPI_TYPE_PACKAGE) {
+		rv = AE_TYPE;
+		goto out;
+	}
+
+	if (obj->Package.Count != 1) {
+		rv = AE_LIMIT;
+		goto out;
+	}
+
+	elm = &obj->Package.Elements[0];
+
+	if (obj->Type != ACPI_TYPE_PACKAGE) {
+		rv = AE_TYPE;
+		goto out;
+	}
+
+	n = elm->Package.Count;
+
+	if (n != 6) {
+		rv = AE_LIMIT;
+		goto out;
+	}
+
+	elm = elm->Package.Elements;
+
+	for (i = 0; i < n; i++) {
+
+		if (elm[i].Type != ACPI_TYPE_INTEGER) {
+			rv = AE_TYPE;
+			goto out;
+		}
+
+		if (elm[i].Integer.Value > UINT32_MAX) {
+			rv = AE_AML_NUMERIC_OVERFLOW;
+			goto out;
+		}
+	}
+
+	val = elm[1].Integer.Value;
+
+	if (val != 0)
+		aprint_debug_dev(sc->sc_dev, "invalid revision in _CSD\n");
+
+	val = elm[3].Integer.Value;
+
+	if (val < ACPICPU_DEP_SW_ALL || val > ACPICPU_DEP_HW_ALL) {
+		rv = AE_AML_BAD_RESOURCE_VALUE;
+		goto out;
+	}
+
+	val = elm[4].Integer.Value;
+
+	if (val > sc->sc_ncpus) {
+		rv = AE_BAD_VALUE;
+		goto out;
+	}
+
+	sc->sc_cstate_dep.dep_domain = elm[2].Integer.Value;
+	sc->sc_cstate_dep.dep_type   = elm[3].Integer.Value;
+	sc->sc_cstate_dep.dep_ncpus  = elm[4].Integer.Value;
+	sc->sc_cstate_dep.dep_index  = elm[5].Integer.Value;
+
+out:
+	if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND)
+		aprint_debug_dev(sc->sc_dev, "failed to evaluate "
+		    "_CSD: %s\n", AcpiFormatException(rv));
+
+	if (buf.Pointer != NULL)
+		ACPI_FREE(buf.Pointer);
+
+	return rv;
+}
+
 static void
 acpicpu_cstate_fadt(struct acpicpu_softc *sc)
 {
@@ -546,7 +645,7 @@
 	if (sc->sc_object.ao_pblkaddr == 0)
 		return;
 
-	if (acpi_md_ncpus() > 1) {
+	if (sc->sc_ncpus > 1) {
 
 		if ((AcpiGbl_FADT.Flags & ACPI_FADT_C2_MP_SUPPORTED) == 0)
 			return;

Index: src/sys/dev/acpi/acpi_cpu_pstate.c
diff -u src/sys/dev/acpi/acpi_cpu_pstate.c:1.39 src/sys/dev/acpi/acpi_cpu_pstate.c:1.40
--- src/sys/dev/acpi/acpi_cpu_pstate.c:1.39	Fri Feb 25 09:16:00 2011
+++ src/sys/dev/acpi/acpi_cpu_pstate.c	Fri Feb 25 19:55:06 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu_pstate.c,v 1.39 2011/02/25 09:16:00 jruoho Exp $ */
+/* $NetBSD: acpi_cpu_pstate.c,v 1.40 2011/02/25 19:55:06 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2010, 2011 Jukka Ruohonen <[email protected]>
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_pstate.c,v 1.39 2011/02/25 09:16:00 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_pstate.c,v 1.40 2011/02/25 19:55:06 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/evcnt.h>
@@ -51,6 +51,7 @@
 static ACPI_STATUS	 acpicpu_pstate_xpss_add(struct acpicpu_pstate *,
 						 ACPI_OBJECT *);
 static ACPI_STATUS	 acpicpu_pstate_pct(struct acpicpu_softc *);
+static ACPI_STATUS	 acpicpu_pstate_dep(struct acpicpu_softc *);
 static int		 acpicpu_pstate_max(struct acpicpu_softc *);
 static int		 acpicpu_pstate_min(struct acpicpu_softc *);
 static void		 acpicpu_pstate_change(struct acpicpu_softc *);
@@ -124,6 +125,14 @@
 		goto fail;
 	}
 
+	/*
+	 * Query the optional _PSD.
+	 */
+	rv = acpicpu_pstate_dep(sc);
+
+	if (ACPI_SUCCESS(rv))
+		sc->sc_flags |= ACPICPU_FLAG_P_DEP;
+
 	sc->sc_flags |= ACPICPU_FLAG_P;
 
 	acpicpu_pstate_bios();
@@ -744,6 +753,95 @@
 	return rv;
 }
 
+static ACPI_STATUS
+acpicpu_pstate_dep(struct acpicpu_softc *sc)
+{
+	ACPI_OBJECT *elm, *obj;
+	ACPI_BUFFER buf;
+	ACPI_STATUS rv;
+	uint32_t val;
+	uint8_t i, n;
+
+	rv = acpi_eval_struct(sc->sc_node->ad_handle, "_PSD", &buf);
+
+	if (ACPI_FAILURE(rv))
+		goto out;
+
+	obj = buf.Pointer;
+
+	if (obj->Type != ACPI_TYPE_PACKAGE) {
+		rv = AE_TYPE;
+		goto out;
+	}
+
+	if (obj->Package.Count != 1) {
+		rv = AE_LIMIT;
+		goto out;
+	}
+
+	elm = &obj->Package.Elements[0];
+
+	if (obj->Type != ACPI_TYPE_PACKAGE) {
+		rv = AE_TYPE;
+		goto out;
+	}
+
+	n = elm->Package.Count;
+
+	if (n != 5) {
+		rv = AE_LIMIT;
+		goto out;
+	}
+
+	elm = elm->Package.Elements;
+
+	for (i = 0; i < n; i++) {
+
+		if (elm[i].Type != ACPI_TYPE_INTEGER) {
+			rv = AE_TYPE;
+			goto out;
+		}
+
+		if (elm[i].Integer.Value > UINT32_MAX) {
+			rv = AE_AML_NUMERIC_OVERFLOW;
+			goto out;
+		}
+	}
+
+	val = elm[1].Integer.Value;
+
+	if (val != 0)
+		aprint_debug_dev(sc->sc_dev, "invalid revision in _PSD\n");
+
+	val = elm[3].Integer.Value;
+
+	if (val < ACPICPU_DEP_SW_ALL || val > ACPICPU_DEP_HW_ALL) {
+		rv = AE_AML_BAD_RESOURCE_VALUE;
+		goto out;
+	}
+
+	val = elm[4].Integer.Value;
+
+	if (val > sc->sc_ncpus) {
+		rv = AE_BAD_VALUE;
+		goto out;
+	}
+
+	sc->sc_pstate_dep.dep_domain = elm[2].Integer.Value;
+	sc->sc_pstate_dep.dep_type   = elm[3].Integer.Value;
+	sc->sc_pstate_dep.dep_ncpus  = elm[4].Integer.Value;
+
+out:
+	if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND)
+		aprint_debug_dev(sc->sc_dev, "failed to evaluate "
+		    "_PSD: %s\n", AcpiFormatException(rv));
+
+	if (buf.Pointer != NULL)
+		ACPI_FREE(buf.Pointer);
+
+	return rv;
+}
+
 static int
 acpicpu_pstate_max(struct acpicpu_softc *sc)
 {

Index: src/sys/dev/acpi/acpi_cpu_tstate.c
diff -u src/sys/dev/acpi/acpi_cpu_tstate.c:1.22 src/sys/dev/acpi/acpi_cpu_tstate.c:1.23
--- src/sys/dev/acpi/acpi_cpu_tstate.c:1.22	Fri Feb 25 05:07:43 2011
+++ src/sys/dev/acpi/acpi_cpu_tstate.c	Fri Feb 25 19:55:07 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_cpu_tstate.c,v 1.22 2011/02/25 05:07:43 jruoho Exp $ */
+/* $NetBSD: acpi_cpu_tstate.c,v 1.23 2011/02/25 19:55:07 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2010 Jukka Ruohonen <[email protected]>
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_tstate.c,v 1.22 2011/02/25 05:07:43 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_cpu_tstate.c,v 1.23 2011/02/25 19:55:07 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/evcnt.h>
@@ -47,6 +47,7 @@
 static ACPI_STATUS	 acpicpu_tstate_tss_add(struct acpicpu_tstate *,
 						ACPI_OBJECT *);
 static ACPI_STATUS	 acpicpu_tstate_ptc(struct acpicpu_softc *);
+static ACPI_STATUS	 acpicpu_tstate_dep(struct acpicpu_softc *);
 static ACPI_STATUS	 acpicpu_tstate_fadt(struct acpicpu_softc *);
 static ACPI_STATUS	 acpicpu_tstate_change(struct acpicpu_softc *);
 static void		 acpicpu_tstate_reset(struct acpicpu_softc *);
@@ -80,6 +81,14 @@
 	}
 
 	/*
+	 * Query the optional _TSD.
+	 */
+	rv = acpicpu_tstate_dep(sc);
+
+	if (ACPI_SUCCESS(rv))
+		sc->sc_flags |= ACPICPU_FLAG_T_DEP;
+
+	/*
 	 * Comparable to P-states, the _TPC object may
 	 * be absent in some systems, even though it is
 	 * required by ACPI 3.0 along with _TSS and _PTC.
@@ -507,6 +516,95 @@
 }
 
 static ACPI_STATUS
+acpicpu_tstate_dep(struct acpicpu_softc *sc)
+{
+	ACPI_OBJECT *elm, *obj;
+	ACPI_BUFFER buf;
+	ACPI_STATUS rv;
+	uint32_t val;
+	uint8_t i, n;
+
+	rv = acpi_eval_struct(sc->sc_node->ad_handle, "_TSD", &buf);
+
+	if (ACPI_FAILURE(rv))
+		goto out;
+
+	obj = buf.Pointer;
+
+	if (obj->Type != ACPI_TYPE_PACKAGE) {
+		rv = AE_TYPE;
+		goto out;
+	}
+
+	if (obj->Package.Count != 1) {
+		rv = AE_LIMIT;
+		goto out;
+	}
+
+	elm = &obj->Package.Elements[0];
+
+	if (obj->Type != ACPI_TYPE_PACKAGE) {
+		rv = AE_TYPE;
+		goto out;
+	}
+
+	n = elm->Package.Count;
+
+	if (n != 5) {
+		rv = AE_LIMIT;
+		goto out;
+	}
+
+	elm = elm->Package.Elements;
+
+	for (i = 0; i < n; i++) {
+
+		if (elm[i].Type != ACPI_TYPE_INTEGER) {
+			rv = AE_TYPE;
+			goto out;
+		}
+
+		if (elm[i].Integer.Value > UINT32_MAX) {
+			rv = AE_AML_NUMERIC_OVERFLOW;
+			goto out;
+		}
+	}
+
+	val = elm[1].Integer.Value;
+
+	if (val != 0)
+		aprint_debug_dev(sc->sc_dev, "invalid revision in _TSD\n");
+
+	val = elm[3].Integer.Value;
+
+	if (val < ACPICPU_DEP_SW_ALL || val > ACPICPU_DEP_HW_ALL) {
+		rv = AE_AML_BAD_RESOURCE_VALUE;
+		goto out;
+	}
+
+	val = elm[4].Integer.Value;
+
+	if (val > sc->sc_ncpus) {
+		rv = AE_BAD_VALUE;
+		goto out;
+	}
+
+	sc->sc_tstate_dep.dep_domain = elm[2].Integer.Value;
+	sc->sc_tstate_dep.dep_type   = elm[3].Integer.Value;
+	sc->sc_tstate_dep.dep_ncpus  = elm[4].Integer.Value;
+
+out:
+	if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND)
+		aprint_debug_dev(sc->sc_dev, "failed to evaluate "
+		    "_TSD: %s\n", AcpiFormatException(rv));
+
+	if (buf.Pointer != NULL)
+		ACPI_FREE(buf.Pointer);
+
+	return rv;
+}
+
+static ACPI_STATUS
 acpicpu_tstate_fadt(struct acpicpu_softc *sc)
 {
 	static const size_t size = sizeof(struct acpicpu_tstate);

Reply via email to