aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/fam15h_power.c
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@amd.com>2012-04-09 18:16:34 -0400
committerGuenter Roeck <guenter.roeck@ericsson.com>2012-04-18 14:15:40 -0400
commit00250ec90963b7ef6678438888f3244985ecde14 (patch)
tree7149e9f7a126465a32b1e8b3584aaa3f8f7fc1b8 /drivers/hwmon/fam15h_power.c
parente816b57a337ea3b755de72bec38c10c864f23015 (diff)
hwmon: fam15h_power: fix bogus values with current BIOSes
Newer BKDG[1] versions recommend a different initialization value for the running average range register in the northbridge. This improves the power reading by avoiding counter saturations resulting in bogus values for anything below about 80% of TDP power consumption. Updated BIOSes will have this new value set up from the beginning, but meanwhile we correct this value ourselves. This needs to be done on all northbridges, even on those where the driver itself does not register at. This fixes the driver on all current machines to provide proper values for idle load. [1] http://support.amd.com/us/Processor_TechDocs/42301_15h_Mod_00h-0Fh_BKDG.pdf Chapter 3.8: D18F5xE0 Processor TDP Running Average (p. 452) Signed-off-by: Andre Przywara <andre.przywara@amd.com> Acked-by: Jean Delvare <khali@linux-fr.org> [guenter.roeck@ericsson.com: Removed unnecessary return statement] Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com> Cc: stable@vger.kernel.org # 3.0+
Diffstat (limited to 'drivers/hwmon/fam15h_power.c')
-rw-r--r--drivers/hwmon/fam15h_power.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index b7494af1e4a9..37a8fc92b44a 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -122,6 +122,38 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4)
122 return true; 122 return true;
123} 123}
124 124
125/*
126 * Newer BKDG versions have an updated recommendation on how to properly
127 * initialize the running average range (was: 0xE, now: 0x9). This avoids
128 * counter saturations resulting in bogus power readings.
129 * We correct this value ourselves to cope with older BIOSes.
130 */
131static void __devinit tweak_runavg_range(struct pci_dev *pdev)
132{
133 u32 val;
134 const struct pci_device_id affected_device = {
135 PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) };
136
137 /*
138 * let this quirk apply only to the current version of the
139 * northbridge, since future versions may change the behavior
140 */
141 if (!pci_match_id(&affected_device, pdev))
142 return;
143
144 pci_bus_read_config_dword(pdev->bus,
145 PCI_DEVFN(PCI_SLOT(pdev->devfn), 5),
146 REG_TDP_RUNNING_AVERAGE, &val);
147 if ((val & 0xf) != 0xe)
148 return;
149
150 val &= ~0xf;
151 val |= 0x9;
152 pci_bus_write_config_dword(pdev->bus,
153 PCI_DEVFN(PCI_SLOT(pdev->devfn), 5),
154 REG_TDP_RUNNING_AVERAGE, val);
155}
156
125static void __devinit fam15h_power_init_data(struct pci_dev *f4, 157static void __devinit fam15h_power_init_data(struct pci_dev *f4,
126 struct fam15h_power_data *data) 158 struct fam15h_power_data *data)
127{ 159{
@@ -155,6 +187,13 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev,
155 struct device *dev; 187 struct device *dev;
156 int err; 188 int err;
157 189
190 /*
191 * though we ignore every other northbridge, we still have to
192 * do the tweaking on _each_ node in MCM processors as the counters
193 * are working hand-in-hand
194 */
195 tweak_runavg_range(pdev);
196
158 if (!fam15h_power_is_internal_node0(pdev)) { 197 if (!fam15h_power_is_internal_node0(pdev)) {
159 err = -ENODEV; 198 err = -ENODEV;
160 goto exit; 199 goto exit;