And it works better if you send the actual diff you would like tested
sorry about this, but please test this one.


Index: sys/dev/acpi/acpicpu.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpicpu.c,v
retrieving revision 1.53
diff -N -u -p -u -p sys/dev/acpi/acpicpu.c
--- sys/dev/acpi/acpicpu.c      24 Feb 2009 13:20:02 -0000      1.53
+++ sys/dev/acpi/acpicpu.c      7 Jun 2009 04:21:24 -0000
@@ -41,12 +41,29 @@ int acpicpu_match(struct device *, void *, void *);
 void   acpicpu_attach(struct device *, struct device *, void *);
 int    acpicpu_notify(struct aml_node *, int, void *);
 void   acpicpu_setperf(int);
+void   acpicpu_setperf_ppc_change(struct acpicpu_pss *, int);
 
 #define ACPI_STATE_C0          0x00
 #define ACPI_STATE_C1          0x01
 #define ACPI_STATE_C2          0x02
 #define ACPI_STATE_C3          0x03
 
+#define ACPI_PDC_REVID         0x1
+#define ACPI_PDC_SMP           0xa
+#define ACPI_PDC_MSR           0x1
+
+/* _PDC Intel capabilities flags from linux */
+#define ACPI_PDC_P_FFH         0x0001
+#define ACPI_PDC_C_C1_HALT     0x0002
+#define ACPI_PDC_T_FFH         0x0004
+#define ACPI_PDC_SMP_C1PT      0x0008
+#define ACPI_PDC_SMP_C2C3      0x0010
+#define ACPI_PDC_SMP_P_SWCOORD 0x0020
+#define ACPI_PDC_SMP_C_SWCOORD 0x0040
+#define ACPI_PDC_SMP_T_SWCOORD 0x0080
+#define ACPI_PDC_C_C1_FFH      0x0100
+#define ACPI_PDC_C_C2C3_FFH    0x0200
+
 #define FLAGS_NO_C2            0x01
 #define FLAGS_NO_C3            0x02
 #define FLAGS_BMCHECK          0x04
@@ -121,6 +138,8 @@ int acpicpu_getpct(struct acpicpu_softc *);
 int    acpicpu_getpss(struct acpicpu_softc *);
 struct acpi_cstate *acpicpu_add_cstate(struct acpicpu_softc *, int, int, int,
     int);
+void   acpicpu_set_pdc(struct acpicpu_softc *);
+
 #if 0
 void    acpicpu_set_throttle(struct acpicpu_softc *, int);
 struct acpi_cstate *acpicpu_find_cstate(struct acpicpu_softc *, int);
@@ -170,6 +189,55 @@ acpicpu_find_cstate(struct acpicpu_softc *sc, int type
 }
 #endif
 
+
+void
+acpicpu_set_pdc(struct acpicpu_softc *sc)
+{
+       struct aml_value cmd, osc_cmd[4];
+       struct aml_value res;
+       uint32_t buf[3];
+
+       /* 4077A616-290C-47BE-9EBD-D87058713953 */
+       static uint8_t cpu_oscuuid[16] = { 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29,
+                                          0xBE, 0x47, 0x9E, 0xBD, 0xD8, 0x70,
+                                          0x58, 0x71, 0x39, 0x53 };
+       /* Evaluate _PDC */
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.type = AML_OBJTYPE_BUFFER;
+       cmd.v_buffer = (uint8_t *)&buf;
+       cmd.length = sizeof(buf);
+
+       buf[0] = ACPI_PDC_REVID;
+       buf[1] = 1;
+       buf[2] = ACPI_PDC_C_C1_HALT | ACPI_PDC_P_FFH | ACPI_PDC_C_C1_FFH
+           | ACPI_PDC_C_C2C3_FFH | ACPI_PDC_SMP_P_SWCOORD | ACPI_PDC_SMP_C2C3
+           | ACPI_PDC_SMP_C1PT;
+
+       aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PDC", 1, &cmd, &res);
+
+       /* Evalualte _OSC */
+       memset(&osc_cmd, 0, sizeof(cmd) * 4);
+       osc_cmd[0].type = AML_OBJTYPE_BUFFER;
+       osc_cmd[0].v_buffer = (uint8_t *)&cpu_oscuuid;
+       osc_cmd[0].length = sizeof(cpu_oscuuid);
+
+       osc_cmd[1].type = AML_OBJTYPE_INTEGER;
+       osc_cmd[1].v_integer = 1;
+       osc_cmd[1].length = 1;
+
+       osc_cmd[2].type = AML_OBJTYPE_INTEGER;
+       osc_cmd[2].v_integer = 1;
+       osc_cmd[2].length = 1;
+
+       buf[0] = 0;
+       osc_cmd[3].type = AML_OBJTYPE_BUFFER;
+       osc_cmd[3].v_buffer = (int8_t *)&buf;
+       osc_cmd[3].length = sizeof(buf);
+
+       aml_evalname(sc->sc_acpi, sc->sc_devnode, "_OSC", 4, osc_cmd, &res);
+}
+
+
 struct acpi_cstate *
 acpicpu_add_cstate(struct acpicpu_softc *sc, int type, int latency, int power,
     int address)
@@ -268,15 +336,17 @@ acpicpu_attach(struct device *parent, struct device *s
        }
        sc->sc_duty_off = sc->sc_acpi->sc_fadt->duty_offset;
        sc->sc_duty_wid = sc->sc_acpi->sc_fadt->duty_width;
+
+       acpicpu_set_pdc(sc);
+
        if (!valid_throttle(sc->sc_duty_off, sc->sc_duty_wid, sc->sc_pblk_addr))
                sc->sc_flags |= FLAGS_NOTHROTTLE;
 #ifdef ACPI_DEBUG
        printf(": %s: ", sc->sc_devnode->name);
-       printf("\n: hdr:%x pblk:%x,%x duty:%x,%x pstate:%x (%d throttling 
states)\n",
-               sc->sc_acpi->sc_fadt->hdr_revision,
-               sc->sc_pblk_addr, sc->sc_pblk_len,
-               sc->sc_duty_off, sc->sc_duty_wid,
-               sc->sc_acpi->sc_fadt->pstate_cnt,
+       printf("\n: hdr:%x pblk:%x,%x duty:%x,%x pstate:%x "
+              "(%d throttling states)\n", sc->sc_acpi->sc_fadt->hdr_revision,
+               sc->sc_pblk_addr, sc->sc_pblk_len, sc->sc_duty_off,
+               sc->sc_duty_wid, sc->sc_acpi->sc_fadt->pstate_cnt,
                CPU_MAXSTATE(sc));
 #endif
 
@@ -342,6 +412,7 @@ acpicpu_attach(struct device *parent, struct device *s
                            DEVNAME(sc), status, sc->sc_level);
                        if (setperf_prio < 30) {
                                cpu_setperf = acpicpu_setperf;
+                               acpicpu_set_notify(acpicpu_setperf_ppc_change);
                                setperf_prio = 30;
                                acpi_hasprocfvs = 1;
                        }
@@ -492,7 +563,7 @@ int
 acpicpu_getpss(struct acpicpu_softc *sc)
 {
        struct aml_value        res;
-       int                     i;
+       int                     i, c, cf;
 
        if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PSS", 0, NULL, &res)) {
                dprintf("%s: no _PSS\n", DEVNAME(sc));
@@ -505,21 +576,39 @@ acpicpu_getpss(struct acpicpu_softc *sc)
        sc->sc_pss = malloc(res.length * sizeof *sc->sc_pss, M_DEVBUF,
            M_WAITOK | M_ZERO);
 
+       c = 0;
        for (i = 0; i < res.length; i++) {
-               sc->sc_pss[i].pss_core_freq = aml_val2int(
-                   res.v_package[i]->v_package[0]);
-               sc->sc_pss[i].pss_power = aml_val2int(
+               cf = aml_val2int(res.v_package[i]->v_package[0]);
+
+               /* This heuristic comes from FreeBSDs 
+                * dev/acpica/acpi_perf.c to weed out invalid PSS entries.
+                */
+               if (cf == sc->sc_pss[c].pss_core_freq) {
+                       printf("%s: struck PSS entry, core frequency equals "
+                           " last\n", sc->sc_dev.dv_xname);
+                       continue;
+               }
+
+               if (cf == 0xFFFF || cf == 0x9999 || cf == 99999 || cf == 0) {
+                       printf("%s: struck PSS entry, inappropriate core "
+                           "frequency value\n", sc->sc_dev.dv_xname);
+                       continue;
+               }
+
+               sc->sc_pss[c].pss_core_freq = cf;
+               sc->sc_pss[c].pss_power = aml_val2int(
                    res.v_package[i]->v_package[1]);
-               sc->sc_pss[i].pss_trans_latency = aml_val2int(
+               sc->sc_pss[c].pss_trans_latency = aml_val2int(
                    res.v_package[i]->v_package[2]);
-               sc->sc_pss[i].pss_bus_latency = aml_val2int(
+               sc->sc_pss[c].pss_bus_latency = aml_val2int(
                    res.v_package[i]->v_package[3]);
-               sc->sc_pss[i].pss_ctrl = aml_val2int(
+               sc->sc_pss[c].pss_ctrl = aml_val2int(
                    res.v_package[i]->v_package[4]);
-               sc->sc_pss[i].pss_status = aml_val2int(
+               sc->sc_pss[c].pss_status = aml_val2int(
                    res.v_package[i]->v_package[5]);
+               c++;
        }
-       sc->sc_pss_len = res.length;
+       sc->sc_pss_len = c;
 
        aml_freevalue(&res);
 
@@ -535,8 +624,6 @@ acpicpu_fetch_pss(struct acpicpu_pss **pss)
         * XXX: According to the ACPI spec in an SMP system all processors
         * are supposed to support the same states. For now we pray
         * the bios ensures this...
-        * XXX part deux: this needs to account for _PPC as well
-        * when AC is removed the nr of _PSS entries can go down
         */
 
        sc = acpicpu_sc[0];
@@ -562,9 +649,6 @@ acpicpu_notify(struct aml_node *node, int notify_type,
                if (sc->sc_notify)
                        sc->sc_notify(sc->sc_pss, sc->sc_pss_len);
 
-               /* reset performance to current percentage */
-               /* XXX will fail for amd64 for now */
-               cpu_setperf(sc->sc_level);
                break;
        default:
                printf("%s: unhandled cpu event %x\n", DEVNAME(sc),
@@ -576,7 +660,8 @@ acpicpu_notify(struct aml_node *node, int notify_type,
 }
 
 void
-acpicpu_set_notify(void (*func)(struct acpicpu_pss *, int)) {
+acpicpu_set_notify(void (*func)(struct acpicpu_pss *, int))
+{
        struct acpicpu_softc    *sc;
 
        sc = acpicpu_sc[0];
@@ -585,6 +670,17 @@ acpicpu_set_notify(void (*func)(struct acpicpu_pss *, 
 }
 
 void
+acpicpu_setperf_ppc_change(struct acpicpu_pss *pss, int npss)
+{
+       struct acpicpu_softc    *sc;
+
+       sc = acpicpu_sc[0];
+
+       if (sc != NULL)
+               cpu_setperf(sc->sc_level);
+}
+
+void
 acpicpu_setperf(int level)
 {
        struct acpicpu_softc    *sc;
@@ -608,7 +704,8 @@ acpicpu_setperf(int level)
         * the duty cycle method instead of pss exclusively
         */
        if (sc->sc_flags & FLAGS_NOPSS || sc->sc_flags & FLAGS_NOPCT) {
-               dnprintf(10, "%s: acpicpu no _PSS or _PCT\n", 
sc->sc_devnode->name);
+               dnprintf(10, "%s: acpicpu no _PSS or _PCT\n",
+                   sc->sc_devnode->name);
                return;
        }

Reply via email to