diff options
author | Gordon Willem Klok <gwk@cvs.openbsd.org> | 2008-06-29 03:50:50 +0000 |
---|---|---|
committer | Gordon Willem Klok <gwk@cvs.openbsd.org> | 2008-06-29 03:50:50 +0000 |
commit | ff2f273a35fb5c5564aa6c856afc44512c01709e (patch) | |
tree | 94af74981d108939ecaa3eae8db0d467eda2d65d /sys | |
parent | 660665028c302fc8c8bfe8c06bb5913b6da5ed95 (diff) |
Split k8_powernow_setperf into two functions, the new function called
k8pnow_transition handles the actual transition, this change is
necessitated by some of the ACPI work which can involve dynamic changes
in the available states in response to endogenous events such as removing
the AC power. This new code is designed to cope with the current operating
point not being among the newly available states in which case we
recalculate what the current desired performance level coresponds to among
the new states.
Also fix a screw up with the acpi_states function (fix originally by
Markus Hennecke in a diff to tech@ thanks) which resolves PR 5854. Diff
tested by numerous people thanks!
ok marco@
Diffstat (limited to 'sys')
-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); |