diff options
author | Steven Rostedt <srostedt@redhat.com> | 2012-05-14 09:41:25 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2012-05-14 09:41:25 -0400 |
commit | ba8759f5e5187b66daf96be2fd6f652834bccf42 (patch) | |
tree | 0eef407bf8806321e46d4029411dfa9c5b6df977 /drivers/hwmon/fam15h_power.c | |
parent | 7985105c05c5e517d254d9f3666a37cc5fc33f82 (diff) | |
parent | bea37381fd9a34c6660e5195d31beea86aa3dda3 (diff) |
Merge tag 'v3.0.31' into v3.0-rt
This is the 3.0.31 stable release
Diffstat (limited to 'drivers/hwmon/fam15h_power.c')
-rw-r--r-- | drivers/hwmon/fam15h_power.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 930370de5201..9a4c3abc9d92 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -122,6 +122,41 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4) return true; } +/* + * Newer BKDG versions have an updated recommendation on how to properly + * initialize the running average range (was: 0xE, now: 0x9). This avoids + * counter saturations resulting in bogus power readings. + * We correct this value ourselves to cope with older BIOSes. + */ +static DEFINE_PCI_DEVICE_TABLE(affected_device) = { + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, + { 0 } +}; + +static void __devinit tweak_runavg_range(struct pci_dev *pdev) +{ + u32 val; + + /* + * let this quirk apply only to the current version of the + * northbridge, since future versions may change the behavior + */ + if (!pci_match_id(affected_device, pdev)) + return; + + pci_bus_read_config_dword(pdev->bus, + PCI_DEVFN(PCI_SLOT(pdev->devfn), 5), + REG_TDP_RUNNING_AVERAGE, &val); + if ((val & 0xf) != 0xe) + return; + + val &= ~0xf; + val |= 0x9; + pci_bus_write_config_dword(pdev->bus, + PCI_DEVFN(PCI_SLOT(pdev->devfn), 5), + REG_TDP_RUNNING_AVERAGE, val); +} + static void __devinit fam15h_power_init_data(struct pci_dev *f4, struct fam15h_power_data *data) { @@ -155,6 +190,13 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev, struct device *dev; int err; + /* + * though we ignore every other northbridge, we still have to + * do the tweaking on _each_ node in MCM processors as the counters + * are working hand-in-hand + */ + tweak_runavg_range(pdev); + if (!fam15h_power_is_internal_node0(pdev)) { err = -ENODEV; goto exit; |