diff options
author | Conrad Meyer <cem@FreeBSD.org> | 2018-12-01 21:37:47 +0000 |
---|---|---|
committer | Conrad Meyer <cem@FreeBSD.org> | 2018-12-01 21:37:47 +0000 |
commit | d86e0b338fb7fbe7ff7e02021d6d8bfc17fe67d6 (patch) | |
tree | 0688c2230a49d70616a74d868d8e1e19d1759b2f | |
parent | 23459e135d01faad4650344d8087dff8c9e71d90 (diff) | |
download | src-d86e0b338fb7fbe7ff7e02021d6d8bfc17fe67d6.tar.gz src-d86e0b338fb7fbe7ff7e02021d6d8bfc17fe67d6.zip |
pmcr: Fix pstate setting on Power8
Fix p-state setting on Power8 by removing the accidental double-indirection of
the pstate_ids table.
The pstate_ids table comes from the OF property "ibm,pstate-ids." On Power9,
the values happen to be identical to the indices, so the extra indirection was
harmless. On Power8, the values were out of the range [0, npstates], so
pmcr_set() would fail the spec[0] range check with EINVAL.
While here, include both the value and index in the driver-specific register
array as spec[0] and spec[1] respectively. They're redundant, but relatively
harmless, and it may aid debugging.
While here, fix the range check to exclude the index npstates, which is one
past the last valid index.
PR: 233693
Reported and tested by: sbruno
Reviewed by: jhibbits
Notes
Notes:
svn path=/head/; revision=341389
-rw-r--r-- | sys/powerpc/cpufreq/pmcr.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/sys/powerpc/cpufreq/pmcr.c b/sys/powerpc/cpufreq/pmcr.c index 03cb4cde371f..681e053444d5 100644 --- a/sys/powerpc/cpufreq/pmcr.c +++ b/sys/powerpc/cpufreq/pmcr.c @@ -174,6 +174,7 @@ pmcr_settings(device_t dev, struct cf_setting *sets, int *count) for (i = 0; i < npstates; i++) { sets[i].freq = pstate_freqs[i]; sets[i].spec[0] = pstate_ids[i]; + sets[i].spec[1] = i; sets[i].dev = dev; } *count = npstates; @@ -189,13 +190,11 @@ pmcr_set(device_t dev, const struct cf_setting *set) if (set == NULL) return (EINVAL); - if (set->spec[0] < 0 || set->spec[0] > npstates) + if (set->spec[1] < 0 || set->spec[1] >= npstates) return (EINVAL); - pmcr = ((long)pstate_ids[set->spec[0]] << PMCR_LOWERPS_SHIFT) & - PMCR_LOWERPS_MASK; - pmcr |= ((long)pstate_ids[set->spec[0]] << PMCR_UPPERPS_SHIFT) & - PMCR_UPPERPS_MASK; + pmcr = ((long)set->spec[0] << PMCR_LOWERPS_SHIFT) & PMCR_LOWERPS_MASK; + pmcr |= ((long)set->spec[0] << PMCR_UPPERPS_SHIFT) & PMCR_UPPERPS_MASK; pmcr |= PMCR_VERSION_1; mtspr(SPR_PMCR, pmcr); @@ -228,6 +227,7 @@ pmcr_get(device_t dev, struct cf_setting *set) return (EINVAL); set->spec[0] = pstate; + set->spec[1] = i; set->freq = pstate_freqs[i]; set->dev = dev; |