diff options
-rw-r--r-- | sys/arch/amd64/amd64/powernow-k8.c | 80 | ||||
-rw-r--r-- | sys/arch/i386/i386/powernow-k8.c | 47 |
2 files changed, 86 insertions, 41 deletions
diff --git a/sys/arch/amd64/amd64/powernow-k8.c b/sys/arch/amd64/amd64/powernow-k8.c index ef02ff3e55b..90ab3aa719e 100644 --- a/sys/arch/amd64/amd64/powernow-k8.c +++ b/sys/arch/amd64/amd64/powernow-k8.c @@ -1,4 +1,4 @@ -/* $OpenBSD: powernow-k8.c,v 1.20 2008/06/15 00:10:47 gwk Exp $ */ +/* $OpenBSD: powernow-k8.c,v 1.21 2008/06/29 03:50:49 gwk Exp $ */ /* * Copyright (c) 2004 Martin Végiard. * Copyright (c) 2004-2005 Bruno Ducrot @@ -50,6 +50,7 @@ #define BIOS_LEN 0x20000 extern int setperf_prio; +extern int perflevel; /* * MSRs and bits used by PowerNow technology @@ -86,6 +87,9 @@ extern int setperf_prio; #define PN8_ACPI_CTRL_TO_RVO(x) (((x) >> 28) & 0x03) #define PN8_ACPI_CTRL_TO_IRT(x) (((x) >> 30) & 0x03) +#define PN8_PSS_CFID(x) ((x) & 0x3f) +#define PN8_PSS_CVID(x) (((x) >> 6) & 0x1f) + #define WRITE_FIDVID(fid, vid, ctrl) \ wrmsr(MSR_AMDK7_FIDVID_CTL, \ (((ctrl) << 32) | (1ULL << 16) | ((vid) << 8) | (fid))) @@ -138,8 +142,8 @@ struct k8pnow_cpu_state *k8pnow_current_state; int k8pnow_read_pending_wait(uint64_t *); int k8pnow_decode_pst(struct k8pnow_cpu_state *, uint8_t *); -int k8pnow_states(struct k8pnow_cpu_state *, uint32_t, unsigned int, - unsigned int); +int k8pnow_states(struct k8pnow_cpu_state *, uint32_t, unsigned int, unsigned int); +void k8pnow_transition(struct k8pnow_cpu_state *e, int); #if NACPICPU > 0 int k8pnow_acpi_init(struct k8pnow_cpu_state *, uint64_t); @@ -167,11 +171,24 @@ void k8_powernow_setperf(int level) { unsigned int i; + struct k8pnow_cpu_state *cstate; + + cstate = k8pnow_current_state; + + i = ((level * cstate->n_states) + 1) / 101; + if (i >= cstate->n_states) + i = cstate->n_states - 1; + + k8pnow_transition(cstate, i); +} + +void +k8pnow_transition(struct k8pnow_cpu_state *cstate, int level) +{ uint64_t status; int cfid, cvid, fid = 0, vid = 0; int rvo; u_int val; - struct k8pnow_cpu_state *cstate; /* * We dont do a k8pnow_read_pending_wait here, need to ensure that the @@ -183,14 +200,8 @@ k8_powernow_setperf(int level) cfid = PN8_STA_CFID(status); cvid = PN8_STA_CVID(status); - cstate = k8pnow_current_state; - - i = ((level * cstate->n_states) + 1) / 101; - if (i >= cstate->n_states) - i = cstate->n_states - 1; - - fid = cstate->state_table[i].fid; - vid = cstate->state_table[i].vid; + fid = cstate->state_table[level].fid; + vid = cstate->state_table[level].vid; if (fid == cfid && vid == cvid) return; @@ -262,7 +273,7 @@ k8_powernow_setperf(int level) } if (cfid == fid || cvid == vid) - cpuspeed = cstate->state_table[i].freq; + cpuspeed = cstate->state_table[level].freq; } /* @@ -310,7 +321,8 @@ k8pnow_acpi_states(struct k8pnow_cpu_state * cstate, struct acpicpu_pss * pss, k = -1; for (n = 0; n < cstate->n_states; n++) { - if (status == pss[n].pss_status) + if ((PN8_STA_CFID(status) == PN8_PSS_CFID(pss[n].pss_status)) && + (PN8_STA_CVID(status) == PN8_PSS_CVID(pss[n].pss_status))) k = n; ctrl = pss[n].pss_ctrl; state.fid = PN8_ACPI_CTRL_TO_FID(ctrl); @@ -334,24 +346,44 @@ k8pnow_acpi_states(struct k8pnow_cpu_state * cstate, struct acpicpu_pss * pss, void k8pnow_acpi_pss_changed(struct acpicpu_pss * pss, int npss) { - int curs; - struct k8pnow_cpu_state * cstate; + int curs, needtran; + struct k8pnow_cpu_state *cstate, *nstate; uint32_t ctrl; uint64_t status; status = rdmsr(MSR_AMDK7_FIDVID_STATUS); cstate = k8pnow_current_state; - curs = k8pnow_acpi_states(cstate, pss, npss, status); + nstate = malloc(sizeof(struct k8pnow_cpu_state), M_DEVBUF, M_NOWAIT); + if (!nstate) + return; + + curs = k8pnow_acpi_states(nstate, pss, npss, status); + needtran = 0; + + if (curs < 0) { + /* Our current opearting state is not among the ones found the new PSS */ + curs = ((perflevel * npss) + 1) / 101; + if (curs >= npss) + curs = npss - 1; + needtran = 1; + } + ctrl = pss[curs].pss_ctrl; - cstate->rvo = PN8_ACPI_CTRL_TO_RVO(ctrl); - cstate->vst = PN8_ACPI_CTRL_TO_VST(ctrl); - cstate->mvs = PN8_ACPI_CTRL_TO_MVS(ctrl); - cstate->pll = PN8_ACPI_CTRL_TO_PLL(ctrl); - cstate->irt = PN8_ACPI_CTRL_TO_IRT(ctrl); - cstate->low = 0; - cstate->n_states = npss; + nstate->rvo = PN8_ACPI_CTRL_TO_RVO(ctrl); + nstate->vst = PN8_ACPI_CTRL_TO_VST(ctrl); + nstate->mvs = PN8_ACPI_CTRL_TO_MVS(ctrl); + nstate->pll = PN8_ACPI_CTRL_TO_PLL(ctrl); + nstate->irt = PN8_ACPI_CTRL_TO_IRT(ctrl); + nstate->low = 0; + nstate->n_states = npss; + + if (needtran) + k8pnow_transition(nstate, curs); + + free(cstate, M_DEVBUF); + k8pnow_current_state = nstate; } int diff --git a/sys/arch/i386/i386/powernow-k8.c b/sys/arch/i386/i386/powernow-k8.c index af296e02fc3..d2889b9d5e8 100644 --- a/sys/arch/i386/i386/powernow-k8.c +++ b/sys/arch/i386/i386/powernow-k8.c @@ -1,4 +1,4 @@ -/* $OpenBSD: powernow-k8.c,v 1.24 2008/06/15 00:10:47 gwk Exp $ */ +/* $OpenBSD: powernow-k8.c,v 1.25 2008/06/29 03:50:49 gwk Exp $ */ /* * Copyright (c) 2004 Martin Végiard. @@ -88,6 +88,9 @@ #define PN8_ACPI_CTRL_TO_RVO(x) (((x) >> 28) & 0x03) #define PN8_ACPI_CTRL_TO_IRT(x) (((x) >> 30) & 0x03) +#define PN8_PSS_CFID(x) ((x) & 0x3f) +#define PN8_PSS_CVID(x) (((x) >> 6) & 0x1f) + #define PN8_PLL_LOCK(x) ((x) * 1000/5) #define WRITE_FIDVID(fid, vid, ctrl) \ wrmsr(MSR_AMDK7_FIDVID_CTL, \ @@ -138,11 +141,12 @@ struct pst_s { struct k8pnow_cpu_state *k8pnow_current_state = NULL; extern int setperf_prio; +extern int perflevel; int k8pnow_read_pending_wait(uint64_t *); int k8pnow_decode_pst(struct k8pnow_cpu_state *, uint8_t *); -int k8pnow_states(struct k8pnow_cpu_state *, uint32_t, unsigned int, - unsigned int); +int k8pnow_states(struct k8pnow_cpu_state *, uint32_t, unsigned int, unsigned int); +void k8pnow_transition(struct k8pnow_cpu_state *e, int); #if NACPICPU > 0 int k8pnow_acpi_init(struct k8pnow_cpu_state *, uint64_t); @@ -170,10 +174,24 @@ void k8_powernow_setperf(int level) { unsigned int i; + struct k8pnow_cpu_state *cstate; + + cstate = k8pnow_current_state; + + i = ((level * cstate->n_states) + 1) / 101; + if (i >= cstate->n_states) + i = cstate->n_states - 1; + + k8pnow_transition(cstate, i); +} + +void +k8pnow_transition(struct k8pnow_cpu_state *cstate, int level) +{ uint64_t status; - int cfid, cvid, fid = 0, vid = 0, rvo; + int cfid, cvid, fid = 0, vid = 0; + int rvo; u_int val; - struct k8pnow_cpu_state *cstate; /* * We dont do a k8pnow_read_pending_wait here, need to ensure that the @@ -185,13 +203,8 @@ k8_powernow_setperf(int level) cfid = PN8_STA_CFID(status); cvid = PN8_STA_CVID(status); - cstate = k8pnow_current_state; - - i = ((level * cstate->n_states) + 1) / 101; - if (i >= cstate->n_states) - i = cstate->n_states - 1; - fid = cstate->state_table[i].fid; - vid = cstate->state_table[i].vid; + fid = cstate->state_table[level].fid; + vid = cstate->state_table[level].vid; if (fid == cfid && vid == cvid) return; @@ -236,8 +249,7 @@ k8_powernow_setperf(int level) val = FID_TO_VCO_FID(cfid) + 2; } else val = cfid - 2; - WRITE_FIDVID(val, cvid, (uint64_t) - PN8_PLL_LOCK(cstate->pll)); + WRITE_FIDVID(val, cvid, (uint64_t)cstate->pll * 1000 / 5); if (k8pnow_read_pending_wait(&status)) return; @@ -247,7 +259,7 @@ k8_powernow_setperf(int level) vco_cfid = FID_TO_VCO_FID(cfid); } - WRITE_FIDVID(fid, cvid, (uint64_t) PN8_PLL_LOCK(cstate->pll)); + WRITE_FIDVID(fid, cvid, (uint64_t) cstate->pll * 1000 / 5); if (k8pnow_read_pending_wait(&status)) return; cfid = PN8_STA_CFID(status); @@ -264,7 +276,7 @@ k8_powernow_setperf(int level) } if (cfid == fid || cvid == vid) - cpuspeed = cstate->state_table[i].freq; + cpuspeed = cstate->state_table[level].freq; } /* @@ -357,7 +369,8 @@ k8pnow_acpi_states(struct k8pnow_cpu_state * cstate, struct acpicpu_pss * pss, k = -1; for (n = 0; n < cstate->n_states; n++) { - if (status == pss[n].pss_status) + if ((PN8_STA_CFID(status) == PN8_PSS_CFID(pss[n].pss_status)) && + (PN8_STA_CVID(status) == PN8_PSS_CVID(pss[n].pss_status))) k = n; ctrl = pss[n].pss_ctrl; state.fid = PN8_ACPI_CTRL_TO_FID(ctrl); |