hwmon: Add driver for AMD family 15h processor
Subsystems (4)
PATCH 1/1 hwmon: Add driver for AMD family 15h processor
From: Andreas Herrmann <[email protected]>
This CPU family provides NB register values to gather following TDP information
* ProcessorPwrWatts: Specifies in Watts the maximum amount of power the processor can support.
* CurrPwrWatts: Specifies in Watts the current amount of power being consumed by the processor.
This driver provides
* power1_cap (ProcessorPwrWatts)
* power1_input (CurrPwrWatts)
--- drivers/hwmon/Kconfig | 10 +++ drivers/hwmon/Makefile | 1 + drivers/hwmon/f15h_power.c | 190 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 201 insertions(+), 0 deletions(-) create mode 100644 drivers/hwmon/f15h_power.c
When using lm_sensors 3.x, the sensors command shows
# sensors
f15h_power-pci-00c4
Adapter: PCI adapter
power1: 94.41 W
f15h_power-pci-00cc
Adapter: PCI adapter
power1: 94.41 W
(This example was with lm_sensors 3.1.2.)
Comments welcome. If there are no objections please apply the patch.
Thanks,
Andreas
PS: Patch is against v2.6.38-4148-g054cfaa
drivers/hwmon/Kconfig +10 -0
@@ -249,6 +249,16 @@ config SENSORS_K10TEMP This driver can also be built as a module. If so, the module will be called k10temp. +config SENSORS_F15H_POWER + tristate "AMD Family 15h processor power" + depends on X86 && PCI + help + If you say yes here you get support for processor power + information of your AMD family 15h CPU. + + This driver can also be built as a module. If so, the module + will be called f15hpower. + config SENSORS_ASB100 tristate "Asus ASB100 Bach" depends on X86 && I2C && EXPERIMENTAL
drivers/hwmon/Makefile +1 -0
@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_JC42) += jc42.o obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o +obj-$(CONFIG_SENSORS_F15H_POWER) += f15h_power.o obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o obj-$(CONFIG_SENSORS_LIS3_I2C) += lis3lv02d.o lis3lv02d_i2c.o
drivers/hwmon/f15h_power.c new file +190 -0
190 lines not on this page · raw message
Signature · 7 lines
1.7.3.1 _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
PATCH v2 1/1 hwmon: Add driver for AMD family 15h processor power information
From: Andreas Herrmann <[email protected]>
This CPU family provides NB register values to gather following TDP information
* ProcessorPwrWatts: Specifies in Watts the maximum amount of power the processor can support.
* CurrPwrWatts: Specifies in Watts the current amount of power being consumed by the processor.
This driver provides
* power1_cap (ProcessorPwrWatts)
* power1_input (CurrPwrWatts)
Changes from v1::
- removed deprecated code line,
- fixed comment,
- report power only once per socket (Power information is provided for the entire package. On multi-node processors it should only be reported on internal node 0.)
--- drivers/hwmon/Kconfig | 10 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/f15h_power.c | 216 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 227 insertions(+), 0 deletions(-) create mode 100644 drivers/hwmon/f15h_power.c
drivers/hwmon/Kconfig +10 -0
@@ -249,6 +249,16 @@ config SENSORS_K10TEMP This driver can also be built as a module. If so, the module will be called k10temp. +config SENSORS_F15H_POWER + tristate "AMD Family 15h processor power" + depends on X86 && PCI + help + If you say yes here you get support for processor power + information of your AMD family 15h CPU. + + This driver can also be built as a module. If so, the module + will be called f15hpower. + config SENSORS_ASB100 tristate "Asus ASB100 Bach" depends on X86 && I2C && EXPERIMENTAL
drivers/hwmon/Makefile +1 -0
@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_JC42) += jc42.o obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o +obj-$(CONFIG_SENSORS_F15H_POWER) += f15h_power.o obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o obj-$(CONFIG_SENSORS_LIS3_I2C) += lis3lv02d.o lis3lv02d_i2c.o
drivers/hwmon/f15h_power.c new file +216 -0
216 lines not on this page · raw message
Signature · 7 lines
1.7.3.1 _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v2] hwmon: Add driver for AMD family 15h processor power information
Quoted 5 lines · Andreas Herrmann
From: Andreas Herrmann <[email protected]>
This CPU family provides NB register values to gather following TDP information
Quoted 8 lines
* ProcessorPwrWatts: Specifies in Watts the maximum amount of power the processor can support.
* CurrPwrWatts: Specifies in Watts the current amount of power being consumed by the processor.This driver provides
*
power1_cap(ProcessorPwrWatts)
Hi Andreas,
What does the CPU do if ProcessorPwrWatts is reached ? Does it start to limit power consumption, ie does it enforce the limit ?
If not you might want to use power1_max instead.
Quoted 9 lines
*
power1_input(CurrPwrWatts)Changes from v1::
- removed deprecated code line,
- fixed comment,
- report power only once per socket (Power information is provided for the entire package. On multi-node processors it should only be reported on internal node 0.)
Quoted 5 lines
Signed-off-by Andreas Herrmann <[email protected]>--- drivers/hwmon/Kconfig | 10 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/f15h_power.c | 216 ++++++++++++++++++++++++++++++++++++++++++++
Please also add Documentation/hwmon/f15h_power.
Quoted 10 lines
3 files changed, 227 insertions(+), 0 deletions(-) create mode 100644 drivers/hwmon/f15h_power.cdrivers/hwmon/Kconfig +0
-0@@ -249,6 +249,16 @@ config SENSORS_K10TEMP This driver can also be built as a module. If so, the module will be called k10temp.
drivers/hwmon/Kconfig config SENSORS_K10TEMP · line 260
Quoted 10 lines
drivers/hwmon/Kconfig +9
-0+config SENSORS_F15H_POWER + tristate "AMD Family 15h processor power" + depends on X86 && PCI + help + If you say yes here you get support for processor power + information of your AMD family 15h CPU. + + This driver can also be built as a module. If so, the module + will be called f15hpower.
f15h_power
Quoted 72 lines
drivers/hwmon/Kconfig +1
-0+ config SENSORS_ASB100 tristate "Asus ASB100 Bach" depends on X86 && I2C && EXPERIMENTALdrivers/hwmon/Makefile +1
-0@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_JC42) += jc42.o obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o +obj-$(CONFIG_SENSORS_F15H_POWER) += f15h_power.o obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o obj-$(CONFIG_SENSORS_LIS3_I2C) += lis3lv02d.o lis3lv02d_i2c.odrivers/hwmon/f15h_power.c new file +50
-0@@ -0,0 +1,216 @@ +/* +* f15h_power.c - AMD Family 15h processor power monitoring +* +* Copyright (c) 2011 Advanced Micro Devices, Inc. +* Author: Andreas Herrmann <[email protected]> +* +* +* This driver is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License; either +* version 2 of the License, or (at your option) any later version. +* +* This driver is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this driver; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include <linux/err.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/bitops.h> +#include <asm/processor.h> + +MODULE_DESCRIPTION ("AMD Family 15h CPU processor power monitor" ); +MODULE_AUTHOR ("Andreas Herrmann <[email protected]>" ); +MODULE_LICENSE ("GPL" ); + +/* D18F3 */ +#define REG_NORTHBRIDGE_CAP 0xe8 + +/* D18F4 */ +#define REG_PROCESSOR_TDP 0x1b8 + +/* D18F5 */ +#define REG_TDP_RUNNING_AVERAGE 0xe0 +#define REG_TDP_LIMIT3 0xe8 + +static ssize_t show_power (struct device *dev, +struct device_attribute *attr,char *buf) +{ +u32 val, btdp, tdpl, tdp2w, arange; +s32 acap; +u64 ctdp; +struct pci_dev *f4 =to_pci_dev (dev);
drivers/hwmon/f15h_power.c line 60
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+struct pci_dev *f5; + +pci_read_config_dword (f4,REG_PROCESSOR_TDP , &val); + btdp = (val >>16 ) &0xffff ; + + f5 =pci_get_slot (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),5 )); +if (!f5) { +dev_err (dev,"no function 5 available on this slot\n" ); +return 0 ; + }
Unless this is a temporary error condition, you should check if this function exists in the probe function, and not create a sysfs entry if it doesn't.
If it is a temporary error which needs a runtime check, you should return a negative value to indicate that there was an error.
Quoted 13 lines
drivers/hwmon/f15h_power.c new file +13
-0+ +pci_read_config_dword (f5,REG_TDP_RUNNING_AVERAGE , &val); + acap = (val >>4 ) &0x3fffff ; + acap =sign_extend32 (acap,22 ); + arange = val &0xf ; + +pci_read_config_dword (f5,REG_TDP_LIMIT3 , &val); +pci_dev_put (f5); + + tdpl = (val >>16 ) &0x1fff ; + tdp2w = ((val &0x3ff ) <<6 ) | ((val >>10 ) &0x3f ); + ctdp = tdpl - (s32)(acap >> (arange +1 )) + btdp; + ctdp *= tdp2w;
drivers/hwmon/f15h_power.c line 83
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+ +/* +* Convert to microWatt +* +* power is in Watt provided as fixed point integer with +* scaling factor 1/(2^16). For conversion we use +* (10^6)/(2^16) = 15625/(2^10) +*/ + ctdp = (ctdp *15625 ) >>10 ; +return sprintf (buf,"%d\n" , (u32 ) ctdp);
%u
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+} +static DEVICE_ATTR(power1_input, S_IRUGO, show_power, NULL); + +static ssize_t show_power_cap (struct device *dev, +struct device_attribute *attr,char *buf) +{ +u32 val, tdp2w; +u64 ptdp; +struct pci_dev *f4 =to_pci_dev (dev); +struct pci_dev *f5;
drivers/hwmon/f15h_power.c line 103
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+ +pci_read_config_dword (f4,REG_PROCESSOR_TDP , &val); + ptdp = val &0xffff ; + + f5 =pci_get_slot (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),5 )); +if (!f5) { +dev_err (dev,"no function 5 available on this slot\n" ); +return 0 ; + } +
Same as above - should be checked in probe function.
If it is a temporary error which needs a runtime check, you should return a negative value to indicate that there was an error.
drivers/hwmon/f15h_power.c line 112
Quoted 9 lines
drivers/hwmon/f15h_power.c new file +9
-0+pci_read_config_dword (f5,REG_TDP_LIMIT3 , &val); +pci_dev_put (f5); + + tdp2w = ((val &0x3ff ) <<6 ) | ((val >>10 ) &0x3f ); + ptdp *= tdp2w; + +/* result not allowed to be >= 256W */ +WARN_ON (ptdp>>16 >=256 ); +
Does this really ask for such drastic measures, or would dev_warn() be sufficient ?
drivers/hwmon/f15h_power.c line 115
Quoted 3 lines
drivers/hwmon/f15h_power.c new file +3
-0+/* convert to microWatt */ + ptdp = (ptdp *15625 ) >>10 ; +return sprintf (buf,"%d\n" , (u32 ) ptdp);
%u
Quoted 9 lines
drivers/hwmon/f15h_power.c new file +9
-0+} +static DEVICE_ATTR(power1_cap, S_IRUGO, show_power_cap, NULL); + +static ssize_t show_name (struct device *dev, +struct device_attribute *attr,char *buf) +{ +return sprintf (buf,"f15h_power\n" ); +} +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
drivers/hwmon/f15h_power.c line 134
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+ +static int __devinit f15h_power_is_internal_node0 (struct pci_dev *f4) +{ +u32 val; +struct pci_dev *f3; + + f3 =pci_get_slot (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),3 )); +if (!f3) { +dev_err (&f4->dev,"no function 3 available on this slot\n" ); +return 0 ;
It is a common practice to return a negative value on errors. Why not here ? Also, is this really an error which asks for an error message, or just a CPU or system which does not support the attribute ? In the latter case, you should not display an error message.
Quoted 48 lines
drivers/hwmon/f15h_power.c new file +48
-0+ } + +pci_read_config_dword (f3,REG_NORTHBRIDGE_CAP , &val); +pci_dev_put (f3); + +if ((val &BIT (29 )) && ((val >>30 ) &3 )) +return 0 ; + +return 1 ; +} + +static int __devinit f15h_power_probe (struct pci_dev *pdev, +const struct pci_device_id *id) +{ +struct device *hwmon_dev; +int err = -ENODEV ; + +if (!f15h_power_is_internal_node0 (pdev)) + goto exit; + + err =device_create_file (&pdev->dev, &dev_attr_power1_input); +if (err) + goto exit; + err =device_create_file (&pdev->dev, &dev_attr_power1_cap); +if (err) + goto exit_remove; + + err =device_create_file (&pdev->dev, &dev_attr_name); +if (err) + goto exit_remove; + + hwmon_dev =hwmon_device_register (&pdev->dev); +if (IS_ERR (hwmon_dev)) { + err =PTR_ERR (hwmon_dev); + goto exit_remove; + } +dev_set_drvdata (&pdev->dev, hwmon_dev); + +return 0 ; + +exit_remove: +device_remove_file (&pdev->dev, &dev_attr_name); +device_remove_file (&pdev->dev, &dev_attr_power1_input); +device_remove_file (&pdev->dev, &dev_attr_power1_cap); +exit: +return err; +} +
drivers/hwmon/f15h_power.c line 192
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+static void __devexit f15h_power_remove(struct pci_dev *pdev) +{ +hwmon_device_unregister (dev_get_drvdata (&pdev->dev)); +device_remove_file (&pdev->dev, &dev_attr_name); +device_remove_file (&pdev->dev, &dev_attr_power1_input); +device_remove_file (&pdev->dev, &dev_attr_power1_cap); +dev_set_drvdata (&pdev->dev,NULL ); +} + +static const struct pci_device_id f15h_power_id_table[] = {
checkpatch says:
WARNING: Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id #326: FILE: drivers/hwmon/f15h_power.c:192:
Please fix.
Quoted 27 lines
drivers/hwmon/f15h_power.c new file +24
-0+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_LINK) }, + {} +}; +MODULE_DEVICE_TABLE (pci, f15h_power_id_table); + +static struct pci_driver f15h_power_driver = { + .name ="f15h_power" , + .id_table = f15h_power_id_table, + .probe = f15h_power_probe, + .remove =__devexit_p (f15h_power_remove), +}; + +static int __init f15h_power_init (void ) +{ +return pci_register_driver (&f15h_power_driver); +} + +static void __exit f15h_power_exit(void) +{ +pci_unregister_driver (&f15h_power_driver); +} + +module_init (f15h_power_init) +module_exit (f15h_power_exit)Signature · 1 line
1.7.3.1
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Clemens Ladisch
maintainerRe: [PATCH v2] hwmon: Add driver for AMD family 15h processor power information
Quoted 12 lines · Guenter Roeck
drivers/hwmon/f15h_power.c line 134
Quoted 9 lines · Andreas Herrmann
drivers/hwmon/f15h_power.c new file +9
-0+static int __devinit f15h_power_is_internal_node0 (struct pci_dev *f4) +{ +u32 val; +struct pci_dev *f3; + + f3 =pci_get_slot (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),3 )); +if (!f3) { +dev_err (&f4->dev,"no function 3 available on this slot\n" ); +return 0 ;It is a common practice to return a negative value on errors. Why not here ?
Apparently, this function returns a boolean value. Using "bool"/"true"/ "false" would have made this more obvious.
Quoted 2 lines
Also, is this really an error which asks for an error message, or just a CPU or system which does not support the attribute ?
AFAICT all F15h CPUs are _known_ to have all these PCI functions; the error should never occur in practice.
What I do in the k10temp driver in this situation is to trust the CPU to be there, omitting the pci_get_slot/pci_dev_put and just replacing this:
Quoted 2 lines
drivers/hwmon/f15h_power.c line 138
Quoted 2 lines
drivers/hwmon/f15h_power.c new file +2
-0+pci_read_config_dword (f3,REG_NORTHBRIDGE_CAP , &val); +pci_dev_put (f3);
with the equivalent of:
pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 3),
REG_NORTHBRIDGE_CAP, &val);
BTW: The family 15h CPUs have the same temperature sensor registers (D18F3xA4 and D18F3x64) as the earlier families, haven't they?
Regards,
Clemens
Re: [PATCH v2] hwmon: Add driver for AMD family 15h processor power information
Quoted 14 lines · Clemens Ladisch
Quoted 12 lines · Guenter Roeck
drivers/hwmon/f15h_power.c line 134
Quoted 9 lines · Andreas Herrmann
drivers/hwmon/f15h_power.c new file +9
-0+static int __devinit f15h_power_is_internal_node0 (struct pci_dev *f4) +{ +u32 val; +struct pci_dev *f3; + + f3 =pci_get_slot (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),3 )); +if (!f3) { +dev_err (&f4->dev,"no function 3 available on this slot\n" ); +return 0 ;It is a common practice to return a negative value on errors. Why not here ?
Quoted 2 lines
Apparently, this function returns a boolean value. Using "bool"/"true"/ "false" would have made this more obvious.
Agreed, using bool as return type would have been the better choice. I'll adapt it.
Quoted 5 lines
Quoted 2 lines
Also, is this really an error which asks for an error message, or just a CPU or system which does not support the attribute ?
AFAICT all F15h CPUs are _known_ to have all these PCI functions; the error should never occur in practice.
Except under virtualization. But common practice is to not pass any such devices into a guest. So either all CPU northbridge functions are there or no function at all. I'll adapt the code to your suggestion.
Quoted 8 lines
What I do in the k10temp driver in this situation is to trust the CPU to be there, omitting the pci_get_slot/pci_dev_put and just replacing this:
Quoted 2 lines
drivers/hwmon/f15h_power.c line 138
Quoted 2 lines
drivers/hwmon/f15h_power.c new file +2
-0+pci_read_config_dword (f3,REG_NORTHBRIDGE_CAP , &val); +pci_dev_put (f3);with the equivalent of:
Quoted 6 lines
pci_bus_read_config_dword(f4->bus,
PCI_DEVFN(PCI_SLOT(f4->devfn), 3),REG_NORTHBRIDGE_CAP, &val);BTW: The family 15h CPUs have the same temperature sensor registers (D18F3xA4 and D18F3x64) as the earlier families, haven't they?
Yes and I think Andre has just sent a patch to add support for 15h to k10temp.
Thanks,
Andreas
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v2] hwmon: Add driver for AMD family 15h processor power information
In reply to Guenter RoeckQuoted 11 lines · Guenter Roeck
Quoted 10 lines · Andreas Herrmann
From: Andreas Herrmann <[email protected]>
This CPU family provides NB register values to gather following TDP information
* ProcessorPwrWatts: Specifies in Watts the maximum amount of power the processor can support.
* CurrPwrWatts: Specifies in Watts the current amount of power being consumed by the processor.
Quoted 8 lines
Quoted 3 lines
This driver provides
*
power1_cap(ProcessorPwrWatts)Hi Andreas,
What does the CPU do if ProcessorPwrWatts is reached ? Does it start to limit power consumption, ie does it enforce the limit ?
No.
Quoted 1 line
If not you might want to use
power1_maxinstead.
Ok, so I picked the wrong attribute. Will correct this.
Quoted 9 lines
Quoted 9 lines
*
power1_input(CurrPwrWatts)Changes from v1::
- removed deprecated code line,
- fixed comment,
- report power only once per socket (Power information is provided for the entire package. On multi-node processors it should only be reported on internal node 0.)
Quoted 7 lines
Quoted 5 lines
Signed-off-by Andreas Herrmann <[email protected]>--- drivers/hwmon/Kconfig | 10 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/f15h_power.c | 216 ++++++++++++++++++++++++++++++++++++++++++++Please also add
Documentation/hwmon/f15h_power.
Ok.
Quoted 11 lines
Quoted 11 lines
3 files changed, 227 insertions(+), 0 deletions(-) create mode 100644 drivers/hwmon/f15h_power.cdrivers/hwmon/Kconfig +0
-0@@ -249,6 +249,16 @@ config SENSORS_K10TEMP This driver can also be built as a module. If so, the module will be called k10temp.
Quoted 11 lines
drivers/hwmon/Kconfig config SENSORS_K10TEMP · line 260
Quoted 9 lines
drivers/hwmon/Kconfig +9
-0+config SENSORS_F15H_POWER + tristate "AMD Family 15h processor power" + depends on X86 && PCI + help + If you say yes here you get support for processor power + information of your AMD family 15h CPU. + + This driver can also be built as a module. If so, the module + will be called f15hpower.f15h_power
Good catch.
Quoted 86 lines
Quoted 72 lines
drivers/hwmon/Kconfig +1
-0+ config SENSORS_ASB100 tristate "Asus ASB100 Bach" depends on X86 && I2C && EXPERIMENTALdrivers/hwmon/Makefile +1
-0@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_JC42) += jc42.o obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o +obj-$(CONFIG_SENSORS_F15H_POWER) += f15h_power.o obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o obj-$(CONFIG_SENSORS_LIS3_I2C) += lis3lv02d.o lis3lv02d_i2c.odrivers/hwmon/f15h_power.c new file +50
-0@@ -0,0 +1,216 @@ +/* +* f15h_power.c - AMD Family 15h processor power monitoring +* +* Copyright (c) 2011 Advanced Micro Devices, Inc. +* Author: Andreas Herrmann <[email protected]> +* +* +* This driver is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License; either +* version 2 of the License, or (at your option) any later version. +* +* This driver is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this driver; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include <linux/err.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/bitops.h> +#include <asm/processor.h> + +MODULE_DESCRIPTION ("AMD Family 15h CPU processor power monitor" ); +MODULE_AUTHOR ("Andreas Herrmann <[email protected]>" ); +MODULE_LICENSE ("GPL" ); + +/* D18F3 */ +#define REG_NORTHBRIDGE_CAP 0xe8 + +/* D18F4 */ +#define REG_PROCESSOR_TDP 0x1b8 + +/* D18F5 */ +#define REG_TDP_RUNNING_AVERAGE 0xe0 +#define REG_TDP_LIMIT3 0xe8 + +static ssize_t show_power (struct device *dev, +struct device_attribute *attr,char *buf) +{ +u32 val, btdp, tdpl, tdp2w, arange; +s32 acap; +u64 ctdp; +struct pci_dev *f4 =to_pci_dev (dev);drivers/hwmon/f15h_power.c line 60
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+struct pci_dev *f5; + +pci_read_config_dword (f4,REG_PROCESSOR_TDP , &val); + btdp = (val >>16 ) &0xffff ; + + f5 =pci_get_slot (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),5 )); +if (!f5) { +dev_err (dev,"no function 5 available on this slot\n" ); +return 0 ; + }Unless this is a temporary error condition, you should check if this function exists in the probe function, and not create a sysfs entry if it doesn't.
Quoted 2 lines
If it is a temporary error which needs a runtime check, you should return a negative value to indicate that there was an error.
Probably I'll follow Clemens' advice to ignore the theoretic case that the device doesn't exist. (AFAIK such a scenario is only imaginable under virtualization if only some PCI devices are passed into a guest.)
Quoted 16 lines
Quoted 16 lines
drivers/hwmon/f15h_power.c new file +16
-0+pci_read_config_dword (f5,REG_TDP_RUNNING_AVERAGE , &val); + acap = (val >>4 ) &0x3fffff ; + acap =sign_extend32 (acap,22 ); + arange = val &0xf ; + +pci_read_config_dword (f5,REG_TDP_LIMIT3 , &val); +pci_dev_put (f5); + + tdpl = (val >>16 ) &0x1fff ; + tdp2w = ((val &0x3ff ) <<6 ) | ((val >>10 ) &0x3f ); + ctdp = tdpl - (s32)(acap >> (arange +1 )) + btdp; + ctdp *= tdp2w; + +/* +* Convert to microWatt +*
Quoted 8 lines
drivers/hwmon/f15h_power.c line 83
Quoted 6 lines
drivers/hwmon/f15h_power.c new file +6
-0+* power is in Watt provided as fixed point integer with +* scaling factor 1/(2^16). For conversion we use +* (10^6)/(2^16) = 15625/(2^10) +*/ + ctdp = (ctdp *15625 ) >>10 ; +return sprintf (buf,"%d\n" , (u32 ) ctdp);%u
Yep.
Quoted 25 lines
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+} +static DEVICE_ATTR(power1_input, S_IRUGO, show_power, NULL); + +static ssize_t show_power_cap (struct device *dev, +struct device_attribute *attr,char *buf) +{ +u32 val, tdp2w; +u64 ptdp; +struct pci_dev *f4 =to_pci_dev (dev); +struct pci_dev *f5;drivers/hwmon/f15h_power.c line 103
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+ +pci_read_config_dword (f4,REG_PROCESSOR_TDP , &val); + ptdp = val &0xffff ; + + f5 =pci_get_slot (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),5 )); +if (!f5) { +dev_err (dev,"no function 5 available on this slot\n" ); +return 0 ; + } +Same as above - should be checked in probe function.
If it is a temporary error which needs a runtime check, you should return a negative value to indicate that there was an error.
Quoted 10 lines
drivers/hwmon/f15h_power.c line 112
Quoted 9 lines
drivers/hwmon/f15h_power.c new file +9
-0+pci_read_config_dword (f5,REG_TDP_LIMIT3 , &val); +pci_dev_put (f5); + + tdp2w = ((val &0x3ff ) <<6 ) | ((val >>10 ) &0x3f ); + ptdp *= tdp2w; + +/* result not allowed to be >= 256W */ +WARN_ON (ptdp>>16 >=256 ); +Does this really ask for such drastic measures, or would
dev_warn()be sufficient ?
dev_warn() should be sufficient.
Quoted 24 lines
drivers/hwmon/f15h_power.c line 115
Quoted 3 lines
drivers/hwmon/f15h_power.c new file +3
-0+/* convert to microWatt */ + ptdp = (ptdp *15625 ) >>10 ; +return sprintf (buf,"%d\n" , (u32 ) ptdp);%uQuoted 16 lines
drivers/hwmon/f15h_power.c new file +16
-0+} +static DEVICE_ATTR(power1_cap, S_IRUGO, show_power_cap, NULL); + +static ssize_t show_name (struct device *dev, +struct device_attribute *attr,char *buf) +{ +return sprintf (buf,"f15h_power\n" ); +} +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + +static int __devinit f15h_power_is_internal_node0 (struct pci_dev *f4) +{ +u32 val; +struct pci_dev *f3; + + f3 =pci_get_slot (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),3 ));
Quoted 8 lines
drivers/hwmon/f15h_power.c line 134
Quoted 3 lines
drivers/hwmon/f15h_power.c new file +3
-0+if (!f3) { +dev_err (&f4->dev,"no function 3 available on this slot\n" ); +return 0 ;It is a common practice to return a negative value on errors. Why not here ? Also, is this really an error which asks for an error message, or just a CPU or system which does not support the attribute ? In the latter case, you should not display an error message.
This paranoid check will be removed.
Quoted 61 lines
Quoted 48 lines
drivers/hwmon/f15h_power.c new file +48
-0+ } + +pci_read_config_dword (f3,REG_NORTHBRIDGE_CAP , &val); +pci_dev_put (f3); + +if ((val &BIT (29 )) && ((val >>30 ) &3 )) +return 0 ; + +return 1 ; +} + +static int __devinit f15h_power_probe (struct pci_dev *pdev, +const struct pci_device_id *id) +{ +struct device *hwmon_dev; +int err = -ENODEV ; + +if (!f15h_power_is_internal_node0 (pdev)) + goto exit; + + err =device_create_file (&pdev->dev, &dev_attr_power1_input); +if (err) + goto exit; + err =device_create_file (&pdev->dev, &dev_attr_power1_cap); +if (err) + goto exit_remove; + + err =device_create_file (&pdev->dev, &dev_attr_name); +if (err) + goto exit_remove; + + hwmon_dev =hwmon_device_register (&pdev->dev); +if (IS_ERR (hwmon_dev)) { + err =PTR_ERR (hwmon_dev); + goto exit_remove; + } +dev_set_drvdata (&pdev->dev, hwmon_dev); + +return 0 ; + +exit_remove: +device_remove_file (&pdev->dev, &dev_attr_name); +device_remove_file (&pdev->dev, &dev_attr_power1_input); +device_remove_file (&pdev->dev, &dev_attr_power1_cap); +exit: +return err; +} +drivers/hwmon/f15h_power.c line 192
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+static void __devexit f15h_power_remove(struct pci_dev *pdev) +{ +hwmon_device_unregister (dev_get_drvdata (&pdev->dev)); +device_remove_file (&pdev->dev, &dev_attr_name); +device_remove_file (&pdev->dev, &dev_attr_power1_input); +device_remove_file (&pdev->dev, &dev_attr_power1_cap); +dev_set_drvdata (&pdev->dev,NULL ); +} + +static const struct pci_device_id f15h_power_id_table[] = {checkpatch says:
Quoted 4 lines
WARNING: Use
DEFINE_PCI_DEVICE_TABLEfor structpci_device_id#326: FILE:drivers/hwmon/f15h_power.c:192:Please fix.
Ok.
Quoted 16 lines
Quoted 16 lines
drivers/hwmon/f15h_power.c new file +16
-0+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_LINK) }, + {} +}; +MODULE_DEVICE_TABLE (pci, f15h_power_id_table); + +static struct pci_driver f15h_power_driver = { + .name ="f15h_power" , + .id_table = f15h_power_id_table, + .probe = f15h_power_probe, + .remove =__devexit_p (f15h_power_remove), +}; + +static int __init f15h_power_init (void ) +{ +return pci_register_driver (&f15h_power_driver); +}
Quoted 8 lines
drivers/hwmon/f15h_power.c line 216
Quoted 8 lines
drivers/hwmon/f15h_power.c new file +8
-0+ +static void __exit f15h_power_exit(void) +{ +pci_unregister_driver (&f15h_power_driver); +} + +module_init (f15h_power_init) +module_exit (f15h_power_exit)
Thanks for the review.
Andreas
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
PATCH v3 1/1 hwmon: Add driver for AMD family 15h processor power information
In reply to Andreas HerrmannFrom: Andreas Herrmann <[email protected]>
This CPU family provides NB register values to gather following TDP information
* ProcessorPwrWatts: Specifies in Watts the maximum amount of power the processor can support.
* CurrPwrWatts: Specifies in Watts the current amount of power being consumed by the processor.
This driver provides
* power1_max (ProcessorPwrWatts)
* power1_input (CurrPwrWatts)
Changes from v2::
- fix format strings
- removed paranoid checks for existense of functions 3 and 5
- changed return type of function f15h_power_is_internal_node0
- provide power1_max instead of power1_cap
- use dev_warn instead of WARN_ON
- rebased against 2.6.39-rc2
- added Documentation/hwmon/f15h_power
--- Documentation/hwmon/f15h_power | 37 ++++++++ drivers/hwmon/Kconfig | 10 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/f15h_power.c | 197 ++++++++++++++++++++++++++++++++++++++++ drivers/hwmon/k10temp.c | 2 +- 5 files changed, 246 insertions(+), 1 deletions(-) create mode 100644 Documentation/hwmon/f15h_power create mode 100644 drivers/hwmon/f15h_power.c
Documentation/hwmon/f15h_power new file +37 -0
@@ -0,0 +1,37 @@ +Kernel driver f15h_power +============ + +Supported chips: +* AMD Family 15h Processors + + Prefix: 'f15h_power' + Addresses scanned: PCI space + Datasheets: + BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors + (not yet published) + +Author: Andreas Herrmann <[email protected]> + +Description +----------- + +This driver permits reading of registers providing power information +of AMD Family 15h processors. + +For AMD Family 15h processors the following power values can be +calculated using different processor northbridge function registers + +* BasePwrWatts: Specifies in watts the maximum amount of power + consumed by the processor for NB and logic external to the core. +* ProcessorPwrWatts: Specifies in watts the maximum amount of power + the processor can support. +* CurrPwrWatts: Specifies in watts the current amount of power being + consumed by the processor. + +This driver provides ProcessorPwrWatts and CurrPwrWatts: +* power1_max (ProcessorPwrWatts) +* power1_input (CurrPwrWatts) + +On multi-node processors the calculated value is for the entire +package and not for a single node. Thus the driver creates sysfs +attributes only for internal node0 of a multi-node processor.
drivers/hwmon/Kconfig +10 -0
@@ -249,6 +249,16 @@ config SENSORS_K10TEMP This driver can also be built as a module. If so, the module will be called k10temp. +config SENSORS_F15H_POWER + tristate "AMD Family 15h processor power" + depends on X86 && PCI + help + If you say yes here you get support for processor power + information of your AMD family 15h CPU. + + This driver can also be built as a module. If so, the module + will be called f15h_power. + config SENSORS_ASB100 tristate "Asus ASB100 Bach" depends on X86 && I2C && EXPERIMENTAL
drivers/hwmon/Makefile +1 -0
@@ -63,6 +63,7 @@ obj-$(CONFIG_SENSORS_JC42) += jc42.o obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o +obj-$(CONFIG_SENSORS_F15H_POWER) += f15h_power.o obj-$(CONFIG_SENSORS_LINEAGE) += lineage-pem.o obj-$(CONFIG_SENSORS_LM63) += lm63.o obj-$(CONFIG_SENSORS_LM70) += lm70.o
drivers/hwmon/f15h_power.c new file +197 -0
197 lines not on this page · raw message
drivers/hwmon/k10temp.c +1 -1
@@ -205,7 +205,7 @@ static void __devexit k10temp_remove(struct pci_dev *pdev)dev_set_drvdata (&pdev->dev,NULL ); } -static const struct pci_device_id k10temp_id_table[] = { +static DEFINE_PCI_DEVICE_TABLE (k10temp_id_table) = { {PCI_VDEVICE (AMD ,PCI_DEVICE_ID_AMD_10H_NB_MISC ) }, {PCI_VDEVICE (AMD ,PCI_DEVICE_ID_AMD_11H_NB_MISC ) }, {PCI_VDEVICE (AMD ,PCI_DEVICE_ID_AMD_CNB17H_F3 ) },
Signature · 7 lines
1.7.4.1 _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v3] hwmon: Add driver for AMD family 15h processor power information
Hi Andreas,
Quoted 6 lines · Andreas Herrmann
Documentation/hwmon/f15h_power new file +3
-0@@ -0,0 +1,37 @@ +Kernel driver f15h_power +============ +
Documentation/hwmon/f15h_power line 13
Quoted 10 lines
Documentation/hwmon/f15h_power new file +10
-0+Supported chips: +* AMD Family 15h Processors + + Prefix: 'f15h_power' + Addresses scanned: PCI space + Datasheets: + BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors + (not yet published) + +Author: Andreas Herrmann <[email protected]>
BTW, please consider adding an entry in MAINTAINERS.
Documentation/hwmon/f15h_power line 22
Quoted 9 lines
Documentation/hwmon/f15h_power new file +9
-0+ +Description +----------- + +This driver permits reading of registers providing power information +of AMD Family 15h processors. + +For AMD Family 15h processors the following power values can be +calculated using different processor northbridge function registers
A trailing ":" would be nice.
Documentation/hwmon/f15h_power line 32
Quoted 10 lines
Documentation/hwmon/f15h_power new file +10
-0+ +* BasePwrWatts: Specifies in watts the maximum amount of power + consumed by the processor for NB and logic external to the core. +* ProcessorPwrWatts: Specifies in watts the maximum amount of power + the processor can support. +* CurrPwrWatts: Specifies in watts the current amount of power being + consumed by the processor. + +This driver provides ProcessorPwrWatts and CurrPwrWatts: +* power1_max (ProcessorPwrWatts)
I see you changed this name once already, but... What is expected to happen if the power consumed exceeds this limit? If you expect the CPU to get damaged, then power1_crit would be more appropriate.
Another way to decide if _max or _crit is more appropriate is by answering the question: if a second limit was added in the future, would it more likely be below or above this one?
Documentation/hwmon/f15h_power
Quoted 8 lines
Documentation/hwmon/f15h_power new file +6
-0+* power1_input (CurrPwrWatts) + +On multi-node processors the calculated value is for the entire +package and not for a single node. Thus the driver creates sysfs +attributes only for internal node0 of a multi-node processor. + return sprintf(buf, "%u\n", (u32) ptdp);
Maybe I'm just nitpicking, but I still don't think it's correct. %u wants unsigned int, not u32. It might be the same but that's by luck.
drivers/hwmon/k10temp.c static void __devexit k10temp_remove(struct pci_dev *pdev) · line 211
Quoted 11 lines
drivers/hwmon/k10temp.c +1
-1@@ -205,7 +205,7 @@ static void __devexit k10temp_remove(struct pci_dev *pdev)dev_set_drvdata (&pdev->dev,NULL ); } -static const struct pci_device_id k10temp_id_table[] = { +static DEFINE_PCI_DEVICE_TABLE (k10temp_id_table) = { {PCI_VDEVICE (AMD ,PCI_DEVICE_ID_AMD_10H_NB_MISC ) }, {PCI_VDEVICE (AMD ,PCI_DEVICE_ID_AMD_11H_NB_MISC ) }, {PCI_VDEVICE (AMD ,PCI_DEVICE_ID_AMD_CNB17H_F3 ) },
Such cleanups should go to separate patches, as they don't have anything to do with your initial effort. And that way you can fix k8temp i5k_amb too.
Signature · 6 lines
Jean Delvare _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v3] hwmon: Add driver for AMD family 15h processor power information
Quoted 13 lines · Jean Delvare
Hi Andreas,
Quoted 10 lines · Andreas Herrmann
Documentation/hwmon/f15h_power new file +7
-0@@ -0,0 +1,37 @@ +Kernel driver f15h_power +============ + +Supported chips: +* AMD Family 15h Processors + + Prefix: 'f15h_power'
Quoted 8 lines
Documentation/hwmon/f15h_power line 13
Quoted 6 lines
Documentation/hwmon/f15h_power new file +6
-0+ Addresses scanned: PCI space + Datasheets: + BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors + (not yet published) + +Author: Andreas Herrmann <[email protected]>BTW, please consider adding an entry in
MAINTAINERS.
Yep.
Quoted 27 lines
Documentation/hwmon/f15h_power line 22
Quoted 9 lines
Documentation/hwmon/f15h_power new file +9
-0+ +Description +----------- + +This driver permits reading of registers providing power information +of AMD Family 15h processors. + +For AMD Family 15h processors the following power values can be +calculated using different processor northbridge function registersA trailing ":" would be nice.
Documentation/hwmon/f15h_power line 32
Quoted 10 lines
Documentation/hwmon/f15h_power new file +10
-0+ +* BasePwrWatts: Specifies in watts the maximum amount of power + consumed by the processor for NB and logic external to the core. +* ProcessorPwrWatts: Specifies in watts the maximum amount of power + the processor can support. +* CurrPwrWatts: Specifies in watts the current amount of power being + consumed by the processor. + +This driver provides ProcessorPwrWatts and CurrPwrWatts: +* power1_max (ProcessorPwrWatts)I see you changed this name once already, but... What is expected to happen if the power consumed exceeds this limit? If you expect the CPU to get damaged, then
power1_critwould be more appropriate.
Quoted 3 lines
Another way to decide if
_maxor_critis more appropriate is by answering the question: if a second limit was added in the future, would it more likely be below or above this one?
It might make sense to use it as _crit and the interim result of
(tdp_limit + base_tdp) * tdp_to_watts
being less than ProcessorPwrWatts as _max.
Quoted 18 lines
Documentation/hwmon/f15h_power
Quoted 8 lines
Documentation/hwmon/f15h_power new file +6
-0+* power1_input (CurrPwrWatts) + +On multi-node processors the calculated value is for the entire +package and not for a single node. Thus the driver creates sysfs +attributes only for internal node0 of a multi-node processor. + return sprintf(buf, "%u\n", (u32) ptdp);Maybe I'm just nitpicking, but I still don't think it's correct. %u wants unsigned int, not u32. It might be the same but that's by luck.
Quoted 6 lines
drivers/hwmon/k10temp.c +0
-0@@ -205,7 +205,7 @@ static void __devexit k10temp_remove(struct pci_dev *pdev)dev_set_drvdata (&pdev->dev,NULL ); }
Quoted 9 lines
drivers/hwmon/k10temp.c static void __devexit k10temp_remove(struct pci_dev *pdev) · line 211
Quoted 5 lines
drivers/hwmon/k10temp.c +1
-1-static const struct pci_device_id k10temp_id_table[] = { +static DEFINE_PCI_DEVICE_TABLE (k10temp_id_table) = { {PCI_VDEVICE (AMD ,PCI_DEVICE_ID_AMD_10H_NB_MISC ) }, {PCI_VDEVICE (AMD ,PCI_DEVICE_ID_AMD_11H_NB_MISC ) }, {PCI_VDEVICE (AMD ,PCI_DEVICE_ID_AMD_CNB17H_F3 ) },Such cleanups should go to separate patches, as they don't have anything to do with your initial effort. And that way you can fix k8temp
i5k_ambtoo.
This slipped in by accident. I might send a separate patch to clean this up in several hwmon drivers.
Andreas
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
PATCH v4 1/1 hwmon: Add driver for AMD family 15h processor power information
In reply to Andreas HerrmannFrom: Andreas Herrmann <[email protected]>
This CPU family provides NB register values to gather following TDP information
* ProcessorPwrWatts: Specifies in Watts the maximum amount of power the processor can support.
* CurrPwrWatts: Specifies in Watts the current amount of power being consumed by the processor.
This driver provides
* power1_max (ProcessorPwrWatts)
* power1_input (CurrPwrWatts)
Changes from v2:
- fix format strings
- removed paranoid checks for existense of functions 3 and 5
- changed return type of function f15h_power_is_internal_node0
- use power1_max instead of power1_cap
- use dev_warn instead of WARN_ON
- rebased against 2.6.39-rc2
- added Documentation/hwmon/f15h_power
Changes from v3:
- read static power information only once (during driver initialization)
- made use of attribute groups
- renamed f15h_power to fam15h_power
--- Documentation/hwmon/fam15h_power | 37 ++++++ drivers/hwmon/Kconfig | 10 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/fam15h_power.c | 229 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 277 insertions(+), 0 deletions(-) create mode 100644 Documentation/hwmon/fam15h_power create mode 100644 drivers/hwmon/fam15h_power.c
At this stage I consider the _max attribute as the right one for reporting ProcessorPwrWatts.
Hopefully I've addressed all your coments.
Please apply.
Thanks,
Andreas
Documentation/hwmon/fam15h_power new file +37 -0
@@ -0,0 +1,37 @@ +Kernel driver fam15h_power +============= + +Supported chips: +* AMD Family 15h Processors + + Prefix: 'fam15h_power' + Addresses scanned: PCI space + Datasheets: + BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors + (not yet published) + +Author: Andreas Herrmann <[email protected]> + +Description +----------- + +This driver permits reading of registers providing power information +of AMD Family 15h processors. + +For AMD Family 15h processors the following power values can be +calculated using different processor northbridge function registers: + +* BasePwrWatts: Specifies in watts the maximum amount of power + consumed by the processor for NB and logic external to the core. +* ProcessorPwrWatts: Specifies in watts the maximum amount of power + the processor can support. +* CurrPwrWatts: Specifies in watts the current amount of power being + consumed by the processor. + +This driver provides ProcessorPwrWatts and CurrPwrWatts: +* power1_max (ProcessorPwrWatts) +* power1_input (CurrPwrWatts) + +On multi-node processors the calculated value is for the entire +package and not for a single node. Thus the driver creates sysfs +attributes only for internal node0 of a multi-node processor.
drivers/hwmon/Kconfig +10 -0
@@ -249,6 +249,16 @@ config SENSORS_K10TEMP This driver can also be built as a module. If so, the module will be called k10temp. +config SENSORS_FAM15H_POWER + tristate "AMD Family 15h processor power" + depends on X86 && PCI + help + If you say yes here you get support for processor power + information of your AMD family 15h CPU. + + This driver can also be built as a module. If so, the module + will be called fam15h_power. + config SENSORS_ASB100 tristate "Asus ASB100 Bach" depends on X86 && I2C && EXPERIMENTAL
drivers/hwmon/Makefile +1 -0
@@ -49,6 +49,7 @@ obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o obj-$(CONFIG_SENSORS_F71805F) += f71805f.o obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o obj-$(CONFIG_SENSORS_F75375S) += f75375s.o +obj-$(CONFIG_SENSORS_FAM15H_POWER) += fam15h_power.o obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o obj-$(CONFIG_SENSORS_G760A) += g760a.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
drivers/hwmon/fam15h_power.c new file +229 -0
229 lines not on this page · raw message
Signature · 7 lines
1.7.4.1 _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v4] hwmon: Add driver for AMD family 15h processor power information
Hi Andreas,
Quoted 5 lines · Andreas Herrmann
From: Andreas Herrmann <[email protected]>
This CPU family provides NB register values to gather following TDP information
Quoted 8 lines
* ProcessorPwrWatts: Specifies in Watts the maximum amount of power the processor can support.
* CurrPwrWatts: Specifies in Watts the current amount of power being consumed by the processor.This driver provides
*
power1_max(ProcessorPwrWatts)
Still questionable whether power1_crit would be more appropriate...
Quoted 26 lines
*
power1_input(CurrPwrWatts)Changes from v2:
- fix format strings
- removed paranoid checks for existense of functions 3 and 5
- changed return type of functionf15h_power_is_internal_node0
- usepower1_maxinstead ofpower1_cap
- usedev_warninstead ofWARN_ON
- rebased against 2.6.39-rc2
- addedDocumentation/hwmon/f15h_powerChanges from v3:
- read static power information only once (during driver initialization)
- made use of attribute groups
- renamedf15h_powertofam15h_powerSigned-off-by Andreas Herrmann <[email protected]>--- Documentation/hwmon/fam15h_power | 37 ++++++ drivers/hwmon/Kconfig | 10 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/fam15h_power.c | 229 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 277 insertions(+), 0 deletions(-) create mode 100644 Documentation/hwmon/fam15h_power create mode 100644 drivers/hwmon/fam15h_power.c
Quoted 5 lines
At this stage I consider the
_maxattribute as the right one for reporting ProcessorPwrWatts.Hopefully I've addressed all your coments.
Please apply.
It seems I have some more comments, but these are very small things you should have no problem addressing quickly:
Quoted 120 lines
Documentation/hwmon/fam15h_power new file +37
-0@@ -0,0 +1,37 @@ +Kernel driver fam15h_power +============= + +Supported chips: +* AMD Family 15h Processors + + Prefix: 'fam15h_power' + Addresses scanned: PCI space + Datasheets: + BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors + (not yet published) + +Author: Andreas Herrmann <[email protected]> + +Description +----------- + +This driver permits reading of registers providing power information +of AMD Family 15h processors. + +For AMD Family 15h processors the following power values can be +calculated using different processor northbridge function registers: + +* BasePwrWatts: Specifies in watts the maximum amount of power + consumed by the processor for NB and logic external to the core. +* ProcessorPwrWatts: Specifies in watts the maximum amount of power + the processor can support. +* CurrPwrWatts: Specifies in watts the current amount of power being + consumed by the processor. + +This driver provides ProcessorPwrWatts and CurrPwrWatts: +* power1_max (ProcessorPwrWatts) +* power1_input (CurrPwrWatts) + +On multi-node processors the calculated value is for the entire +package and not for a single node. Thus the driver creates sysfs +attributes only for internal node0 of a multi-node processor.drivers/hwmon/Kconfig +10
-0@@ -249,6 +249,16 @@ config SENSORS_K10TEMP This driver can also be built as a module. If so, the module will be called k10temp. +config SENSORS_FAM15H_POWER + tristate "AMD Family 15h processor power" + depends on X86 && PCI + help + If you say yes here you get support for processor power + information of your AMD family 15h CPU. + + This driver can also be built as a module. If so, the module + will be called fam15h_power. + config SENSORS_ASB100 tristate "Asus ASB100 Bach" depends on X86 && I2C && EXPERIMENTALdrivers/hwmon/Makefile +1
-0@@ -49,6 +49,7 @@ obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o obj-$(CONFIG_SENSORS_F71805F) += f71805f.o obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o obj-$(CONFIG_SENSORS_F75375S) += f75375s.o +obj-$(CONFIG_SENSORS_FAM15H_POWER) += fam15h_power.o obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o obj-$(CONFIG_SENSORS_G760A) += g760a.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.odrivers/hwmon/fam15h_power.c new file +38
-0@@ -0,0 +1,229 @@ +/* +* fam15h_power.c - AMD Family 15h processor power monitoring +* +* Copyright (c) 2011 Advanced Micro Devices, Inc. +* Author: Andreas Herrmann <[email protected]> +* +* +* This driver is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License; either +* version 2 of the License, or (at your option) any later version. +* +* This driver is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this driver; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include <linux/err.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/bitops.h> +#include <asm/processor.h> + +MODULE_DESCRIPTION ("AMD Family 15h CPU processor power monitor" ); +MODULE_AUTHOR ("Andreas Herrmann <[email protected]>" ); +MODULE_LICENSE ("GPL" ); + +/* D18F3 */ +#define REG_NORTHBRIDGE_CAP 0xe8 + +/* D18F4 */ +#define REG_PROCESSOR_TDP 0x1b8
drivers/hwmon/fam15h_power.c line 48
Quoted 10 lines
drivers/hwmon/fam15h_power.c new file +10
-0+ +/* D18F5 */ +#define REG_TDP_RUNNING_AVERAGE 0xe0 +#define REG_TDP_LIMIT3 0xe8 + +struct fam15h_power_data { +struct device *hwmon_dev; +unsigned int tdp_to_watt; +unsigned int base_tdp; +unsigned int processor_pwr_watts;
watt vs. watts is inconsistent, isn't it?
drivers/hwmon/fam15h_power.c line 58
Quoted 10 lines
drivers/hwmon/fam15h_power.c new file +10
-0+}; + +static ssize_t show_power (struct device *dev, +struct device_attribute *attr,char *buf) +{ +u32 val, tdp_limit, running_avg_range; +s32 running_avg_capture; +u64 curr_pwr_watts; +struct pci_dev *f4 =to_pci_dev (dev); +struct fam15h_power_data *data =pci_get_drvdata (f4);
dev_get_drvdata(dev) would be more efficient.
drivers/hwmon/fam15h_power.c line 70
Quoted 12 lines
drivers/hwmon/fam15h_power.c new file +12
-0+ +pci_bus_read_config_dword (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),5 ), +REG_TDP_RUNNING_AVERAGE , &val); + running_avg_capture = (val >>4 ) &0x3fffff ; + running_avg_capture =sign_extend32 (running_avg_capture,22 ); + running_avg_range = val &0xf ; + +pci_bus_read_config_dword (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),5 ), +REG_TDP_LIMIT3 , &val); + + tdp_limit = val >>16 ; + curr_pwr_watts = tdp_limit + data->base_tdp -
Doubled space.
Quoted 10 lines
drivers/hwmon/fam15h_power.c new file +10
-0+ (s32)(running_avg_capture >> (running_avg_range +1 )); + curr_pwr_watts *= data->tdp_to_watt; + +/* +* Convert to microWatt +* +* power is in Watt provided as fixed point integer with +* scaling factor 1/(2^16). For conversion we use +* (10^6)/(2^16) = 15625/(2^10) +*/
drivers/hwmon/fam15h_power.c line 90
Quoted 10 lines
drivers/hwmon/fam15h_power.c new file +10
-0+ curr_pwr_watts = (curr_pwr_watts *15625 ) >>10 ; +return sprintf (buf,"%u\n" , (unsigned int ) curr_pwr_watts); +} +static DEVICE_ATTR(power1_input, S_IRUGO, show_power, NULL); + +static ssize_t show_power_max (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct pci_dev *f4 =to_pci_dev (dev); +struct fam15h_power_data *data =pci_get_drvdata (f4);
dev_get_drvdata(dev) would be more efficient (you don't even need f4 then.)
Quoted 9 lines
drivers/hwmon/fam15h_power.c new file +9
-0+return sprintf (buf,"%u\n" , data->processor_pwr_watts); +} +static DEVICE_ATTR(power1_max, S_IRUGO, show_power_max, NULL); + +static ssize_t show_name (struct device *dev, +struct device_attribute *attr,char *buf) +{ +return sprintf (buf,"fam15h_power\n" ); +}
drivers/hwmon/fam15h_power.c line 110
Quoted 10 lines
drivers/hwmon/fam15h_power.c new file +10
-0+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + +static struct attribute *fam15h_power_attrs[] = { + &dev_attr_power1_input.attr, + &dev_attr_power1_max.attr, + &dev_attr_name.attr, +NULL +}; + +static struct attribute_group fam15h_power_attr_group = {
Can be made const.
Quoted 23 lines
drivers/hwmon/fam15h_power.c new file +23
-0+ .attrs = fam15h_power_attrs, +}; + +static bool __devinit fam15h_power_is_internal_node0 (struct pci_dev *f4) +{ +u32 val; + +pci_bus_read_config_dword (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),3 ), +REG_NORTHBRIDGE_CAP , &val); +if ((val &BIT (29 )) && ((val >>30 ) &3 )) +return false; + +return true; +} + +static void __devinit fam15h_power_init_data (struct pci_dev *f4, +struct fam15h_power_data *data) +{ +u32 val; +u64 tmp; + +pci_read_config_dword (f4,REG_PROCESSOR_TDP , &val); + data->base_tdp = val >>16 ;
drivers/hwmon/fam15h_power.c line 143
Quoted 10 lines
drivers/hwmon/fam15h_power.c new file +10
-0+ tmp = val &0xffff ; + +pci_bus_read_config_dword (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),5 ), +REG_TDP_LIMIT3 , &val); + + data->tdp_to_watt = ((val &0x3ff ) <<6 ) | ((val >>10 ) &0x3f ); + tmp *= data->tdp_to_watt; + +/* result not allowed to be >= 256W */ +if ((tmp>>16 ) >=256 )
Please add spaces around ">>" for consistency.
Quoted 28 lines
drivers/hwmon/fam15h_power.c new file +28
-0+dev_warn (&f4->dev,"Bogus value for ProcessorPwrWatts " +"(processor_pwr_watts>=%u)\n" , + (unsigned int ) (tmp >>16 )); + +/* convert to microWatt */ + data->processor_pwr_watts = (tmp *15625 ) >>10 ; +} + +static int __devinit fam15h_power_probe (struct pci_dev *pdev, +const struct pci_device_id *id) +{ +struct fam15h_power_data *data; +struct device *dev; +int err; + +if (!fam15h_power_is_internal_node0 (pdev)) { + err = -ENODEV ; + goto exit; + } + + data =kzalloc (sizeof (struct fam15h_power_data ),GFP_KERNEL ); +if (!data) { + err = -ENOMEM ; + goto exit; + } +fam15h_power_init_data (pdev, data); + + dev = &pdev->dev;
drivers/hwmon/fam15h_power.c line 181
Quoted 10 lines
drivers/hwmon/fam15h_power.c new file +10
-0+ err =sysfs_create_group (&dev->kobj, &fam15h_power_attr_group); +if (err) + goto exit_free_data; + + data->hwmon_dev =hwmon_device_register (&pdev->dev); +if (IS_ERR (data->hwmon_dev)) { + err =PTR_ERR (data->hwmon_dev); + goto exit_remove_group; + } +pci_set_drvdata (pdev, data);
This is racy. pci_set_drvdata() should be called before creating the sysfs attributes, because the sysfs callbacks need it.
Quoted 38 lines
drivers/hwmon/fam15h_power.c new file +38
-0+ +return 0 ; + +exit_remove_group: +sysfs_remove_group (&dev->kobj, &fam15h_power_attr_group); +exit_free_data: +kfree (data); +exit: +return err; +} + +static void __devexit fam15h_power_remove(struct pci_dev *pdev) +{ +struct device *dev; +struct fam15h_power_data *data =pci_get_drvdata (pdev); + + dev = &pdev->dev; +hwmon_device_unregister (data->hwmon_dev); +sysfs_remove_group (&dev->kobj, &fam15h_power_attr_group); +pci_set_drvdata (pdev,NULL ); +kfree (data); +} + +static DEFINE_PCI_DEVICE_TABLE (fam15h_power_id_table) = { + {PCI_VDEVICE (AMD ,PCI_DEVICE_ID_AMD_15H_NB_F4 ) }, + {} +}; +MODULE_DEVICE_TABLE (pci, fam15h_power_id_table); + +static struct pci_driver fam15h_power_driver = { + .name ="fam15h_power" , + .id_table = fam15h_power_id_table, + .probe = fam15h_power_probe, + .remove =__devexit_p (fam15h_power_remove), +}; + +static int __init fam15h_power_init (void ) +{
drivers/hwmon/fam15h_power.c line 229
Quoted 10 lines
drivers/hwmon/fam15h_power.c new file +10
-0+return pci_register_driver (&fam15h_power_driver); +} + +static void __exit fam15h_power_exit(void) +{ +pci_unregister_driver (&fam15h_power_driver); +} + +module_init (fam15h_power_init) +module_exit (fam15h_power_exit)
Thanks,
Signature · 6 lines
Jean Delvare _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v4] hwmon: Add driver for AMD family 15h processor power information
Quoted 13 lines · Jean Delvare
Hi Andreas,
Quoted 10 lines · Andreas Herrmann
From: Andreas Herrmann <[email protected]>
This CPU family provides NB register values to gather following TDP information
* ProcessorPwrWatts: Specifies in Watts the maximum amount of power the processor can support.
* CurrPwrWatts: Specifies in Watts the current amount of power being consumed by the processor.
Quoted 5 lines
Quoted 3 lines
This driver provides
*
power1_max(ProcessorPwrWatts)Still questionable whether
power1_critwould be more appropriate...
Finally, I've changed it.
Quoted 159 lines
Quoted 26 lines
*
power1_input(CurrPwrWatts)Changes from v2:
- fix format strings
- removed paranoid checks for existense of functions 3 and 5
- changed return type of functionf15h_power_is_internal_node0
- usepower1_maxinstead ofpower1_cap
- usedev_warninstead ofWARN_ON
- rebased against 2.6.39-rc2
- addedDocumentation/hwmon/f15h_powerChanges from v3:
- read static power information only once (during driver initialization)
- made use of attribute groups
- renamedf15h_powertofam15h_powerSigned-off-by Andreas Herrmann <[email protected]>--- Documentation/hwmon/fam15h_power | 37 ++++++ drivers/hwmon/Kconfig | 10 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/fam15h_power.c | 229 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 277 insertions(+), 0 deletions(-) create mode 100644 Documentation/hwmon/fam15h_power create mode 100644 drivers/hwmon/fam15h_power.cQuoted 5 lines
At this stage I consider the
_maxattribute as the right one for reporting ProcessorPwrWatts.Hopefully I've addressed all your coments.
Please apply.It seems I have some more comments, but these are very small things you should have no problem addressing quickly:
Quoted 124 lines
Documentation/hwmon/fam15h_power new file +37
-0@@ -0,0 +1,37 @@ +Kernel driver fam15h_power +============= + +Supported chips: +* AMD Family 15h Processors + + Prefix: 'fam15h_power' + Addresses scanned: PCI space + Datasheets: + BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors + (not yet published) + +Author: Andreas Herrmann <[email protected]> + +Description +----------- + +This driver permits reading of registers providing power information +of AMD Family 15h processors. + +For AMD Family 15h processors the following power values can be +calculated using different processor northbridge function registers: + +* BasePwrWatts: Specifies in watts the maximum amount of power + consumed by the processor for NB and logic external to the core. +* ProcessorPwrWatts: Specifies in watts the maximum amount of power + the processor can support. +* CurrPwrWatts: Specifies in watts the current amount of power being + consumed by the processor. + +This driver provides ProcessorPwrWatts and CurrPwrWatts: +* power1_max (ProcessorPwrWatts) +* power1_input (CurrPwrWatts) + +On multi-node processors the calculated value is for the entire +package and not for a single node. Thus the driver creates sysfs +attributes only for internal node0 of a multi-node processor.drivers/hwmon/Kconfig +10
-0@@ -249,6 +249,16 @@ config SENSORS_K10TEMP This driver can also be built as a module. If so, the module will be called k10temp. +config SENSORS_FAM15H_POWER + tristate "AMD Family 15h processor power" + depends on X86 && PCI + help + If you say yes here you get support for processor power + information of your AMD family 15h CPU. + + This driver can also be built as a module. If so, the module + will be called fam15h_power. + config SENSORS_ASB100 tristate "Asus ASB100 Bach" depends on X86 && I2C && EXPERIMENTALdrivers/hwmon/Makefile +1
-0@@ -49,6 +49,7 @@ obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o obj-$(CONFIG_SENSORS_F71805F) += f71805f.o obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o obj-$(CONFIG_SENSORS_F75375S) += f75375s.o +obj-$(CONFIG_SENSORS_FAM15H_POWER) += fam15h_power.o obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o obj-$(CONFIG_SENSORS_G760A) += g760a.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.odrivers/hwmon/fam15h_power.c new file +42
-0@@ -0,0 +1,229 @@ +/* +* fam15h_power.c - AMD Family 15h processor power monitoring +* +* Copyright (c) 2011 Advanced Micro Devices, Inc. +* Author: Andreas Herrmann <[email protected]> +* +* +* This driver is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License; either +* version 2 of the License, or (at your option) any later version. +* +* This driver is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this driver; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include <linux/err.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/bitops.h> +#include <asm/processor.h> + +MODULE_DESCRIPTION ("AMD Family 15h CPU processor power monitor" ); +MODULE_AUTHOR ("Andreas Herrmann <[email protected]>" ); +MODULE_LICENSE ("GPL" ); + +/* D18F3 */ +#define REG_NORTHBRIDGE_CAP 0xe8 + +/* D18F4 */ +#define REG_PROCESSOR_TDP 0x1b8 + +/* D18F5 */ +#define REG_TDP_RUNNING_AVERAGE 0xe0 +#define REG_TDP_LIMIT3 0xe8
Quoted 8 lines
drivers/hwmon/fam15h_power.c line 48
Quoted 6 lines
drivers/hwmon/fam15h_power.c new file +6
-0+ +struct fam15h_power_data { +struct device *hwmon_dev; +unsigned int tdp_to_watt; +unsigned int base_tdp; +unsigned int processor_pwr_watts;watt vs. watts is inconsistent, isn't it?
Changed.
Quoted 13 lines
drivers/hwmon/fam15h_power.c line 58
Quoted 10 lines
drivers/hwmon/fam15h_power.c new file +10
-0+}; + +static ssize_t show_power (struct device *dev, +struct device_attribute *attr,char *buf) +{ +u32 val, tdp_limit, running_avg_range; +s32 running_avg_capture; +u64 curr_pwr_watts; +struct pci_dev *f4 =to_pci_dev (dev); +struct fam15h_power_data *data =pci_get_drvdata (f4);
dev_get_drvdata(dev)would be more efficient.
Quoted 14 lines
drivers/hwmon/fam15h_power.c line 70
Quoted 12 lines
drivers/hwmon/fam15h_power.c new file +12
-0+ +pci_bus_read_config_dword (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),5 ), +REG_TDP_RUNNING_AVERAGE , &val); + running_avg_capture = (val >>4 ) &0x3fffff ; + running_avg_capture =sign_extend32 (running_avg_capture,22 ); + running_avg_range = val &0xf ; + +pci_bus_read_config_dword (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),5 ), +REG_TDP_LIMIT3 , &val); + + tdp_limit = val >>16 ; + curr_pwr_watts = tdp_limit + data->base_tdp -Doubled space.
Whoops!
Quoted 37 lines
Quoted 10 lines
drivers/hwmon/fam15h_power.c new file +10
-0+ (s32)(running_avg_capture >> (running_avg_range +1 )); + curr_pwr_watts *= data->tdp_to_watt; + +/* +* Convert to microWatt +* +* power is in Watt provided as fixed point integer with +* scaling factor 1/(2^16). For conversion we use +* (10^6)/(2^16) = 15625/(2^10) +*/ drivers/hwmon/fam15h_power.c line 90
Quoted 10 lines
drivers/hwmon/fam15h_power.c new file +10
-0+ curr_pwr_watts = (curr_pwr_watts *15625 ) >>10 ; +return sprintf (buf,"%u\n" , (unsigned int ) curr_pwr_watts); +} +static DEVICE_ATTR(power1_input, S_IRUGO, show_power, NULL); + +static ssize_t show_power_max (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct pci_dev *f4 =to_pci_dev (dev); +struct fam15h_power_data *data =pci_get_drvdata (f4);
dev_get_drvdata(dev)would be more efficient (you don't even need f4 then.)Quoted 13 lines
drivers/hwmon/fam15h_power.c new file +13
-0+return sprintf (buf,"%u\n" , data->processor_pwr_watts); +} +static DEVICE_ATTR(power1_max, S_IRUGO, show_power_max, NULL); + +static ssize_t show_name (struct device *dev, +struct device_attribute *attr,char *buf) +{ +return sprintf (buf,"fam15h_power\n" ); +} +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + +static struct attribute *fam15h_power_attrs[] = { + &dev_attr_power1_input.attr,
Quoted 8 lines
drivers/hwmon/fam15h_power.c line 110
Quoted 6 lines
drivers/hwmon/fam15h_power.c new file +6
-0+ &dev_attr_power1_max.attr, + &dev_attr_name.attr, +NULL +}; + +static struct attribute_group fam15h_power_attr_group = {Can be made const.
Done this ....
Quoted 27 lines
Quoted 27 lines
drivers/hwmon/fam15h_power.c new file +27
-0+ .attrs = fam15h_power_attrs, +}; + +static bool __devinit fam15h_power_is_internal_node0 (struct pci_dev *f4) +{ +u32 val; + +pci_bus_read_config_dword (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),3 ), +REG_NORTHBRIDGE_CAP , &val); +if ((val &BIT (29 )) && ((val >>30 ) &3 )) +return false; + +return true; +} + +static void __devinit fam15h_power_init_data (struct pci_dev *f4, +struct fam15h_power_data *data) +{ +u32 val; +u64 tmp; + +pci_read_config_dword (f4,REG_PROCESSOR_TDP , &val); + data->base_tdp = val >>16 ; + tmp = val &0xffff ; + +pci_bus_read_config_dword (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),5 ), +REG_TDP_LIMIT3 , &val);
Quoted 8 lines
drivers/hwmon/fam15h_power.c line 143
Quoted 6 lines
drivers/hwmon/fam15h_power.c new file +6
-0+ + data->tdp_to_watt = ((val &0x3ff ) <<6 ) | ((val >>10 ) &0x3f ); + tmp *= data->tdp_to_watt; + +/* result not allowed to be >= 256W */ +if ((tmp>>16 ) >=256 )Please add spaces around ">>" for consistency.
... and that.
Quoted 33 lines
Quoted 33 lines
drivers/hwmon/fam15h_power.c new file +33
-0+dev_warn (&f4->dev,"Bogus value for ProcessorPwrWatts " +"(processor_pwr_watts>=%u)\n" , + (unsigned int ) (tmp >>16 )); + +/* convert to microWatt */ + data->processor_pwr_watts = (tmp *15625 ) >>10 ; +} + +static int __devinit fam15h_power_probe (struct pci_dev *pdev, +const struct pci_device_id *id) +{ +struct fam15h_power_data *data; +struct device *dev; +int err; + +if (!fam15h_power_is_internal_node0 (pdev)) { + err = -ENODEV ; + goto exit; + } + + data =kzalloc (sizeof (struct fam15h_power_data ),GFP_KERNEL ); +if (!data) { + err = -ENOMEM ; + goto exit; + } +fam15h_power_init_data (pdev, data); + + dev = &pdev->dev; + err =sysfs_create_group (&dev->kobj, &fam15h_power_attr_group); +if (err) + goto exit_free_data; + + data->hwmon_dev =hwmon_device_register (&pdev->dev);
Quoted 8 lines
drivers/hwmon/fam15h_power.c line 181
Quoted 5 lines
drivers/hwmon/fam15h_power.c new file +5
-0+if (IS_ERR (data->hwmon_dev)) { + err =PTR_ERR (data->hwmon_dev); + goto exit_remove_group; + } +pci_set_drvdata (pdev, data);This is racy.
pci_set_drvdata()should be called before creating the sysfs attributes, because the sysfs callbacks need it.
Oops -- fixed.
Quoted 2 lines
drivers/hwmon/fam15h_power.c line 182
Quoted 2 lines
drivers/hwmon/fam15h_power.c new file +2
-0+ +return 0 ;
[snip]
Thanks again for the review
Andreas
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
PATCH v5 1/1 hwmon: Add driver for AMD family 15h processor power information
In reply to Andreas HerrmannFrom: Andreas Herrmann <[email protected]>
This CPU family provides NB register values to gather following TDP information
* ProcessorPwrWatts: Specifies in Watts the maximum amount of power the processor can support.
* CurrPwrWatts: Specifies in Watts the current amount of power being consumed by the processor.
This driver provides
* power1_crit (ProcessorPwrWatts)
* power1_input (CurrPwrWatts)
Changes from v2:
- fix format strings
- removed paranoid checks for existense of functions 3 and 5
- changed return type of function f15h_power_is_internal_node0
- use power1_max instead of power1_cap
- use dev_warn instead of WARN_ON
- rebased against 2.6.39-rc2
- added Documentation/hwmon/f15h_power
Changes from v3:
- read static power information only once (during driver initialization)
- made use of attribute groups
- renamed f15h_power to fam15h_power
Changes from v4:
- fixed race in probe function
- use power1_crit instead of powe1_max
- coding style changes
--- Documentation/hwmon/fam15h_power | 37 ++++++ drivers/hwmon/Kconfig | 10 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/fam15h_power.c | 229 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 277 insertions(+), 0 deletions(-) create mode 100644 Documentation/hwmon/fam15h_power create mode 100644 drivers/hwmon/fam15h_power.c
Patch is rebased on v2.6.39-rc3-82-g85f2e68
Andreas
Documentation/hwmon/fam15h_power new file +37 -0
@@ -0,0 +1,37 @@ +Kernel driver fam15h_power +============= + +Supported chips: +* AMD Family 15h Processors + + Prefix: 'fam15h_power' + Addresses scanned: PCI space + Datasheets: + BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors + (not yet published) + +Author: Andreas Herrmann <[email protected]> + +Description +----------- + +This driver permits reading of registers providing power information +of AMD Family 15h processors. + +For AMD Family 15h processors the following power values can be +calculated using different processor northbridge function registers: + +* BasePwrWatts: Specifies in watts the maximum amount of power + consumed by the processor for NB and logic external to the core. +* ProcessorPwrWatts: Specifies in watts the maximum amount of power + the processor can support. +* CurrPwrWatts: Specifies in watts the current amount of power being + consumed by the processor. + +This driver provides ProcessorPwrWatts and CurrPwrWatts: +* power1_crit (ProcessorPwrWatts) +* power1_input (CurrPwrWatts) + +On multi-node processors the calculated value is for the entire +package and not for a single node. Thus the driver creates sysfs +attributes only for internal node0 of a multi-node processor.
drivers/hwmon/Kconfig +10 -0
@@ -249,6 +249,16 @@ config SENSORS_K10TEMP This driver can also be built as a module. If so, the module will be called k10temp. +config SENSORS_FAM15H_POWER + tristate "AMD Family 15h processor power" + depends on X86 && PCI + help + If you say yes here you get support for processor power + information of your AMD family 15h CPU. + + This driver can also be built as a module. If so, the module + will be called fam15h_power. + config SENSORS_ASB100 tristate "Asus ASB100 Bach" depends on X86 && I2C && EXPERIMENTAL
drivers/hwmon/Makefile +1 -0
@@ -49,6 +49,7 @@ obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o obj-$(CONFIG_SENSORS_F71805F) += f71805f.o obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o obj-$(CONFIG_SENSORS_F75375S) += f75375s.o +obj-$(CONFIG_SENSORS_FAM15H_POWER) += fam15h_power.o obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o obj-$(CONFIG_SENSORS_G760A) += g760a.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
drivers/hwmon/fam15h_power.c new file +229 -0
229 lines not on this page · raw message
Signature · 7 lines
1.7.5.rc1 _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Jean Delvare
AppliedRe: [PATCH v5] hwmon: Add driver for AMD family 15h processor power information
Quoted 10 lines · Andreas Herrmann
From: Andreas Herrmann <[email protected]>
This CPU family provides NB register values to gather following TDP information
* ProcessorPwrWatts: Specifies in Watts the maximum amount of power the processor can support.
* CurrPwrWatts: Specifies in Watts the current amount of power being consumed by the processor.
Quoted 5 lines
This driver provides
*
power1_crit(ProcessorPwrWatts)
*power1_input(CurrPwrWatts)
(...)
Applied, thanks.
Signature · 6 lines
Jean Delvare _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
PATCH 1/1 hwmon, fam15h_power: Add maintainers entry
In reply to Andreas HerrmannFrom: Andreas Herrmann <[email protected]>
--- MAINTAINERS | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)
As suggested by Jean, here's a patch to add a maintainers entry for the new driver.
Regards,
Andreas
MAINTAINERS +7 -0
@@ -483,6 +483,13 @@ F: drivers/tty/serial/altera_jtaguart.c F: include/linux/altera_uart.h F: include/linux/altera_jtaguart.h +AMD FAM15H PROCESSOR POWER HARDWARE MONITORING DRIVER +M: Andreas Herrmann <[email protected]> +L: [email protected] +S: Maintained +F: Documentation/hwmon/fam15h_power +F: drivers/hwmon/fam15h_power.c + AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER M: Thomas Dahlmann <[email protected]> L: [email protected] (moderated for non-subscribers)
Signature · 7 lines
1.7.4.1 _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH] hwmon, fam15h_power: Add maintainers entry
Hi Andreas,
Quoted 20 lines · Andreas Herrmann
From: Andreas Herrmann <[email protected]>
Signed-off-by Andreas Herrmann <[email protected]>--- MAINTAINERS | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)As suggested by Jean, here's a patch to add a maintainers entry for the new driver.
Regards,
Andreas
MAINTAINERS +0
-0
MAINTAINERS F: drivers/tty/serial/altera_jtaguart.c · line 486
Quoted 4 lines
MAINTAINERS +1
-0@@ -483,6 +483,13 @@ F: drivers/tty/serial/altera_jtaguart.c F: include/linux/altera_uart.h F: include/linux/altera_jtaguart.h +AMD FAM15H PROCESSOR POWER HARDWARE MONITORING DRIVER
I'd remove "HARDWARE" as the target hardware is already described.
MAINTAINERS F: drivers/tty/serial/altera_jtaguart.c · line 495
Quoted 9 lines
MAINTAINERS +6
-0+M: Andreas Herrmann <[email protected]> +L: [email protected] +S: Maintained +F: Documentation/hwmon/fam15h_power +F: drivers/hwmon/fam15h_power.c + AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER M: Thomas Dahlmann <[email protected]> L: [email protected] (moderated for non-subscribers)
Other than this small detail, which I can fix myself if you agree with me, this looks good, thanks for stepping in!
Signature · 6 lines
Jean Delvare _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH] hwmon, fam15h_power: Add maintainers entry
Quoted 30 lines · Jean Delvare
Hi Andreas,
Quoted 20 lines · Andreas Herrmann
From: Andreas Herrmann <[email protected]>
Signed-off-by Andreas Herrmann <[email protected]>--- MAINTAINERS | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-)As suggested by Jean, here's a patch to add a maintainers entry for the new driver.
Regards,
Andreas
MAINTAINERS +0
-0MAINTAINERS F: drivers/tty/serial/altera_jtaguart.c · line 486
Quoted 4 lines
MAINTAINERS +1
-0@@ -483,6 +483,13 @@ F: drivers/tty/serial/altera_jtaguart.c F: include/linux/altera_uart.h F: include/linux/altera_jtaguart.h +AMD FAM15H PROCESSOR POWER HARDWARE MONITORING DRIVERI'd remove "HARDWARE" as the target hardware is already described.
Quoted 12 lines
MAINTAINERS F: drivers/tty/serial/altera_jtaguart.c · line 495
Quoted 9 lines
MAINTAINERS +6
-0+M: Andreas Herrmann <[email protected]> +L: [email protected] +S: Maintained +F: Documentation/hwmon/fam15h_power +F: drivers/hwmon/fam15h_power.c + AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER M: Thomas Dahlmann <[email protected]> L: [email protected] (moderated for non-subscribers)Other than this small detail, which I can fix myself if you agree with me, this looks good, thanks for stepping in!
I agree.
Thanks,
Andreas
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v2] hwmon: Add driver for AMD family 15h processor power information
In reply to Andreas HerrmannQuoted 10 lines · Andreas Herrmann
From: Andreas Herrmann <[email protected]>
This CPU family provides NB register values to gather following TDP information
* ProcessorPwrWatts: Specifies in Watts the maximum amount of power the processor can support.
* CurrPwrWatts: Specifies in Watts the current amount of power being consumed by the processor.
Quoted 4 lines
This driver provides
*
power1_cap(ProcessorPwrWatts)
*power1_input(CurrPwrWatts)
Just a few random comments as I don't have the time for a complete review:
Quoted 8 lines
Changes from v1::
- removed deprecated code line,
- fixed comment,
- report power only once per socket (Power information is provided for the entire package. On multi-node processors it should only be reported on internal node 0.)
Quoted 5 lines
Signed-off-by Andreas Herrmann <[email protected]>--- drivers/hwmon/Kconfig | 10 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/f15h_power.c | 216 ++++++++++++++++++++++++++++++++++++++++++++
I would prefer fam15h to f15h. The latter is a little too cryptic for me.
Quoted 29 lines
3 files changed, 227 insertions(+), 0 deletions(-) create mode 100644 drivers/hwmon/f15h_power.cdrivers/hwmon/Kconfig +10
-0@@ -249,6 +249,16 @@ config SENSORS_K10TEMP This driver can also be built as a module. If so, the module will be called k10temp. +config SENSORS_F15H_POWER + tristate "AMD Family 15h processor power" + depends on X86 && PCI + help + If you say yes here you get support for processor power + information of your AMD family 15h CPU. + + This driver can also be built as a module. If so, the module + will be called f15hpower. + config SENSORS_ASB100 tristate "Asus ASB100 Bach" depends on X86 && I2C && EXPERIMENTALdrivers/hwmon/Makefile +0
-0
drivers/hwmon/Makefile obj-$(CONFIG_SENSORS_JC42) += jc42.o · line 65
Quoted 4 lines
drivers/hwmon/Makefile +1
-0@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_JC42) += jc42.o obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o +obj-$(CONFIG_SENSORS_F15H_POWER) += f15h_power.o
Alphabetic order please.
Quoted 48 lines
drivers/hwmon/Makefile +0
-0obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o obj-$(CONFIG_SENSORS_LIS3_I2C) += lis3lv02d.o lis3lv02d_i2c.odrivers/hwmon/f15h_power.c new file +39
-0@@ -0,0 +1,216 @@ +/* +* f15h_power.c - AMD Family 15h processor power monitoring +* +* Copyright (c) 2011 Advanced Micro Devices, Inc. +* Author: Andreas Herrmann <[email protected]> +* +* +* This driver is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License; either +* version 2 of the License, or (at your option) any later version. +* +* This driver is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this driver; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include <linux/err.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/bitops.h> +#include <asm/processor.h> + +MODULE_DESCRIPTION ("AMD Family 15h CPU processor power monitor" ); +MODULE_AUTHOR ("Andreas Herrmann <[email protected]>" ); +MODULE_LICENSE ("GPL" ); + +/* D18F3 */ +#define REG_NORTHBRIDGE_CAP 0xe8 + +/* D18F4 */ +#define REG_PROCESSOR_TDP 0x1b8 +
drivers/hwmon/f15h_power.c line 49
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+/* D18F5 */ +#define REG_TDP_RUNNING_AVERAGE 0xe0 +#define REG_TDP_LIMIT3 0xe8 + +static ssize_t show_power (struct device *dev, +struct device_attribute *attr,char *buf) +{ +u32 val, btdp, tdpl, tdp2w, arange; +s32 acap; +u64 ctdp;
These variable names aren't easy to understand.
drivers/hwmon/f15h_power.c line 54
Quoted 5 lines
drivers/hwmon/f15h_power.c new file +5
-0+struct pci_dev *f4 =to_pci_dev (dev); +struct pci_dev *f5; + +pci_read_config_dword (f4,REG_PROCESSOR_TDP , &val); + btdp = (val >>16 ) &0xffff ;
Useless masking.
drivers/hwmon/f15h_power.c line 62
Quoted 8 lines
drivers/hwmon/f15h_power.c new file +8
-0+ + f5 =pci_get_slot (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),5 )); +if (!f5) { +dev_err (dev,"no function 5 available on this slot\n" ); +return 0 ; + } + +pci_read_config_dword (f5,REG_TDP_RUNNING_AVERAGE , &val);
Does this value change over time?
drivers/hwmon/f15h_power.c line 67
Quoted 5 lines
drivers/hwmon/f15h_power.c new file +5
-0+ acap = (val >>4 ) &0x3fffff ; + acap =sign_extend32 (acap,22 ); + arange = val &0xf ; + +pci_read_config_dword (f5,REG_TDP_LIMIT3 , &val);
Same question here. If these values don't change over time, they should be stored in a per-device structure to avoid repeated PCI configuration space access.
Quoted 6 lines
drivers/hwmon/f15h_power.c new file +6
-0+pci_dev_put (f5); + + tdpl = (val >>16 ) &0x1fff ; + tdp2w = ((val &0x3ff ) <<6 ) | ((val >>10 ) &0x3f ); + ctdp = tdpl - (s32)(acap >> (arange +1 )) + btdp; + ctdp *= tdp2w;
drivers/hwmon/f15h_power.c line 83
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+ +/* +* Convert to microWatt +* +* power is in Watt provided as fixed point integer with +* scaling factor 1/(2^16). For conversion we use +* (10^6)/(2^16) = 15625/(2^10) +*/ + ctdp = (ctdp *15625 ) >>10 ; +return sprintf (buf,"%d\n" , (u32 ) ctdp);
%d and u32 aren't compatible. %lu and long unsigned int would be OK.
Quoted 11 lines
drivers/hwmon/f15h_power.c new file +11
-0+} +static DEVICE_ATTR(power1_input, S_IRUGO, show_power, NULL); + +static ssize_t show_power_cap (struct device *dev, +struct device_attribute *attr,char *buf) +{ +u32 val, tdp2w; +u64 ptdp; +struct pci_dev *f4 =to_pci_dev (dev); +struct pci_dev *f5; +
drivers/hwmon/f15h_power.c line 104
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+pci_read_config_dword (f4,REG_PROCESSOR_TDP , &val); + ptdp = val &0xffff ; + + f5 =pci_get_slot (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),5 )); +if (!f5) { +dev_err (dev,"no function 5 available on this slot\n" ); +return 0 ; + } + +pci_read_config_dword (f5,REG_TDP_LIMIT3 , &val);
Same question as above, can this value change over time?
drivers/hwmon/f15h_power.c line 115
Quoted 11 lines
drivers/hwmon/f15h_power.c new file +11
-0+pci_dev_put (f5); + + tdp2w = ((val &0x3ff ) <<6 ) | ((val >>10 ) &0x3f ); + ptdp *= tdp2w; + +/* result not allowed to be >= 256W */ +WARN_ON (ptdp>>16 >=256 ); + +/* convert to microWatt */ + ptdp = (ptdp *15625 ) >>10 ; +return sprintf (buf,"%d\n" , (u32 ) ptdp);
%d and u32 aren't compatible. %lu and long unsigned int would be OK.
Quoted 8 lines
drivers/hwmon/f15h_power.c new file +8
-0+} +static DEVICE_ATTR(power1_cap, S_IRUGO, show_power_cap, NULL); + +static ssize_t show_name (struct device *dev, +struct device_attribute *attr,char *buf) +{ +return sprintf (buf,"f15h_power\n" ); +}
drivers/hwmon/f15h_power.c line 133
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + +static int __devinit f15h_power_is_internal_node0 (struct pci_dev *f4) +{ +u32 val; +struct pci_dev *f3; + + f3 =pci_get_slot (f4->bus,PCI_DEVFN (PCI_SLOT (f4->devfn),3 )); +if (!f3) { +dev_err (&f4->dev,"no function 3 available on this slot\n" );
Please use %d and pass the number as a parameter, and do the same for the 2 similar messages above. This will let the compiler reuse the string.
Quoted 7 lines
drivers/hwmon/f15h_power.c new file +7
-0+return 0 ; + } + +pci_read_config_dword (f3,REG_NORTHBRIDGE_CAP , &val); +pci_dev_put (f3); + +if ((val &BIT (29 )) && ((val >>30 ) &3 ))
drivers/hwmon/f15h_power.c line 150
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+return 0 ; + +return 1 ; +} + +static int __devinit f15h_power_probe (struct pci_dev *pdev, +const struct pci_device_id *id) +{ +struct device *hwmon_dev; +int err = -ENODEV ;
You should move this initialization to the only case which needs it. Otherwise you're slowing down the success path with no good reason.
Quoted 4 lines
drivers/hwmon/f15h_power.c new file +4
-0+ +if (!f15h_power_is_internal_node0 (pdev)) + goto exit; +
drivers/hwmon/f15h_power.c line 164
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+ err =device_create_file (&pdev->dev, &dev_attr_power1_input); +if (err) + goto exit; + err =device_create_file (&pdev->dev, &dev_attr_power1_cap); +if (err) + goto exit_remove; + + err =device_create_file (&pdev->dev, &dev_attr_name); +if (err) + goto exit_remove;
Please consider defining and using an attribute group, it makes the code more simple.
drivers/hwmon/f15h_power.c line 171
Quoted 7 lines
drivers/hwmon/f15h_power.c new file +7
-0+ + hwmon_dev =hwmon_device_register (&pdev->dev); +if (IS_ERR (hwmon_dev)) { + err =PTR_ERR (hwmon_dev); + goto exit_remove; + } +dev_set_drvdata (&pdev->dev, hwmon_dev);
pci_set_drvdata()
Quoted 8 lines
drivers/hwmon/f15h_power.c new file +8
-0+ +return 0 ; + +exit_remove: +device_remove_file (&pdev->dev, &dev_attr_name); +device_remove_file (&pdev->dev, &dev_attr_power1_input); +device_remove_file (&pdev->dev, &dev_attr_power1_cap); +exit:
drivers/hwmon/f15h_power.c line 189
Quoted 10 lines
drivers/hwmon/f15h_power.c new file +10
-0+return err; +} + +static void __devexit f15h_power_remove(struct pci_dev *pdev) +{ +hwmon_device_unregister (dev_get_drvdata (&pdev->dev)); +device_remove_file (&pdev->dev, &dev_attr_name); +device_remove_file (&pdev->dev, &dev_attr_power1_input); +device_remove_file (&pdev->dev, &dev_attr_power1_cap); +dev_set_drvdata (&pdev->dev,NULL );
pci_set_drvdata()
drivers/hwmon/f15h_power.c line 193
Quoted 4 lines
drivers/hwmon/f15h_power.c new file +4
-0+} + +static const struct pci_device_id f15h_power_id_table[] = { + {PCI_VDEVICE (AMD ,PCI_DEVICE_ID_AMD_15H_NB_LINK ) },
Not defined anywhere, causing the driver to fail building:
drivers/hwmon/f15h_power.c:193:1: error: 'PCI_DEVICE_ID_AMD_15H_NB_LINK' undeclared here (not in a function) make[2]: *** [drivers/hwmon/f15h_power.o] Error 1
make[1]: *** [drivers/hwmon] Error 2
make[1]: *** Waiting for unfinished jobs....
make: *** [drivers] Error 2
Quoted 23 lines
drivers/hwmon/f15h_power.c new file +23
-0+ {} +}; +MODULE_DEVICE_TABLE (pci, f15h_power_id_table); + +static struct pci_driver f15h_power_driver = { + .name ="f15h_power" , + .id_table = f15h_power_id_table, + .probe = f15h_power_probe, + .remove =__devexit_p (f15h_power_remove), +}; + +static int __init f15h_power_init (void ) +{ +return pci_register_driver (&f15h_power_driver); +} + +static void __exit f15h_power_exit(void) +{ +pci_unregister_driver (&f15h_power_driver); +} + +module_init (f15h_power_init) +module_exit (f15h_power_exit)
Signature · 6 lines
Jean Delvare _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v2] hwmon: Add driver for AMD family 15h processor power information
Quoted 27 lines · Jean Delvare
Quoted 10 lines · Andreas Herrmann
From: Andreas Herrmann <[email protected]>
This CPU family provides NB register values to gather following TDP information
* ProcessorPwrWatts: Specifies in Watts the maximum amount of power the processor can support.
* CurrPwrWatts: Specifies in Watts the current amount of power being consumed by the processor.Quoted 4 lines
This driver provides
*
power1_cap(ProcessorPwrWatts)
*power1_input(CurrPwrWatts)Just a few random comments as I don't have the time for a complete review:
Quoted 8 lines
Changes from v1::
- removed deprecated code line,
- fixed comment,
- report power only once per socket (Power information is provided for the entire package. On multi-node processors it should only be reported on internal node 0.)
Quoted 8 lines
Quoted 5 lines
Signed-off-by Andreas Herrmann <[email protected]>--- drivers/hwmon/Kconfig | 10 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/f15h_power.c | 216 ++++++++++++++++++++++++++++++++++++++++++++I would prefer fam15h to f15h. The latter is a little too cryptic for me.
Hmm, (unfortunately;-) seconded, e.g.
linux-2.6 $ grep -rs fam10h arch/x86 | wc
71 450 7930
linux-2.6 $ grep -rs f10h arch/x86 | wc
0 0 0
Will change it.
[snip]
Quoted 9 lines
drivers/hwmon/Makefile obj-$(CONFIG_SENSORS_JC42) += jc42.o · line 65
Quoted 7 lines
drivers/hwmon/Makefile +1
-0@@ -62,6 +62,7 @@ obj-$(CONFIG_SENSORS_JC42) += jc42.o obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o +obj-$(CONFIG_SENSORS_F15H_POWER) += f15h_power.oAlphabetic order please.
ok.
[snip]
Quoted 8 lines
drivers/hwmon/Makefile obj-$(CONFIG_SENSORS_JC42) += jc42.o
Quoted 6 lines
drivers/hwmon/Makefile +6
-0+static ssize_t show_power(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 val, btdp, tdpl, tdp2w, arange; + s32 acap; + u64 ctdp;These variable names aren't easy to understand.
Just random names which eventually map to the spec:
btdp - base_tdp
tdpl - tdp_limit
tdp2w - tdp_to_watt
acap - average_accumulator_capture (or even worse how about "processor_tdp_running_average_accumulator":( arange - average_range
I don't think that changing the names make it much easier to reconstruct the calculation but if you insist in changing it I'll adapt it.
Quoted 7 lines
drivers/hwmon/Makefile
Quoted 5 lines
drivers/hwmon/Makefile +5
-0+ struct pci_dev *f4 = to_pci_dev(dev); + struct pci_dev *f5; + + pci_read_config_dword(f4, REG_PROCESSOR_TDP, &val); + btdp = (val >> 16) & 0xffff;Useless masking.
To be removed.
Quoted 10 lines
drivers/hwmon/Makefile
Quoted 8 lines
drivers/hwmon/Makefile +8
-0+ + f5 = pci_get_slot(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5)); + if (!f5) { + dev_err(dev, "no function 5 available on this slot\n"); + return 0; + } + + pci_read_config_dword(f5, REG_TDP_RUNNING_AVERAGE, &val);Does this value change over time?
Yes.
Quoted 9 lines
drivers/hwmon/Makefile
Quoted 5 lines
drivers/hwmon/Makefile +5
-0+ acap = (val >> 4) & 0x3fffff; + acap = sign_extend32(acap, 22); + arange = val & 0xf; + + pci_read_config_dword(f5, REG_TDP_LIMIT3, &val);Same question here. If these values don't change over time, they should be stored in a per-device structure to avoid repeated PCI configuration space access.
The parts I use from this register shouldn't change => code to be modified.
Quoted 10 lines
Quoted 10 lines
drivers/hwmon/Makefile +10
-0+ pci_dev_put(f5); + + tdpl = (val >> 16) & 0x1fff; + tdp2w = ((val & 0x3ff) << 6) | ((val >> 10) & 0x3f); + ctdp = tdpl - (s32)(acap >> (arange + 1)) + btdp; + ctdp *= tdp2w; + + /* + * Convert to microWatt + *
Quoted 8 lines
drivers/hwmon/Makefile
Quoted 6 lines
drivers/hwmon/Makefile +6
-0+ * power is in Watt provided as fixed point integer with + * scaling factor 1/(2^16). For conversion we use + * (10^6)/(2^16) = 15625/(2^10) + */ + ctdp = (ctdp * 15625) >> 10; + return sprintf(buf, "%d\n", (u32) ctdp);%d and u32 aren't compatible. %lu and long unsigned int would be OK.
already fixed in v3
Quoted 15 lines
Quoted 15 lines
drivers/hwmon/Makefile +15
-0+} +static DEVICE_ATTR(power1_input, S_IRUGO, show_power, NULL); + +static ssize_t show_power_cap(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u32 val, tdp2w; + u64 ptdp; + struct pci_dev *f4 = to_pci_dev(dev); + struct pci_dev *f5; + + pci_read_config_dword(f4, REG_PROCESSOR_TDP, &val); + ptdp = val & 0xffff; + + f5 = pci_get_slot(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5));
Quoted 8 lines
drivers/hwmon/Makefile
Quoted 6 lines
drivers/hwmon/Makefile +6
-0+ if (!f5) { + dev_err(dev, "no function 5 available on this slot\n"); + return 0; + } + + pci_read_config_dword(f5, REG_TDP_LIMIT3, &val);Same question as above, can this value change over time?
Needs to be modified.
Quoted 5 lines
Quoted 5 lines
drivers/hwmon/Makefile +5
-0+ pci_dev_put(f5); + + tdp2w = ((val & 0x3ff) << 6) | ((val >> 10) & 0x3f); + ptdp *= tdp2w; +
Quoted 8 lines
drivers/hwmon/Makefile
Quoted 6 lines
drivers/hwmon/Makefile +6
-0+ /* result not allowed to be >= 256W */ + WARN_ON(ptdp>>16 >= 256); + + /* convert to microWatt */ + ptdp = (ptdp * 15625) >> 10; + return sprintf(buf, "%d\n", (u32) ptdp);%d and u32 aren't compatible. %lu and long unsigned int would be OK.
fixed in v3.
Quoted 14 lines
Quoted 14 lines
drivers/hwmon/Makefile +14
-0+} +static DEVICE_ATTR(power1_cap, S_IRUGO, show_power_cap, NULL); + +static ssize_t show_name(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "f15h_power\n"); +} +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); + +static int __devinit f15h_power_is_internal_node0(struct pci_dev *f4) +{ + u32 val; + struct pci_dev *f3;
Quoted 8 lines
drivers/hwmon/Makefile
Quoted 4 lines
drivers/hwmon/Makefile +4
-0+ + f3 = pci_get_slot(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 3)); + if (!f3) { + dev_err(&f4->dev, "no function 3 available on this slot\n");Please use %d and pass the number as a parameter, and do the same for the 2 similar messages above. This will let the compiler reuse the string.
message removed in v3
Quoted 12 lines
Quoted 12 lines
drivers/hwmon/Makefile +12
-0+ return 0; + } + + pci_read_config_dword(f3, REG_NORTHBRIDGE_CAP, &val); + pci_dev_put(f3); + + if ((val & BIT(29)) && ((val >> 30) & 3)) + return 0; + + return 1; +} +
Quoted 8 lines
drivers/hwmon/Makefile
Quoted 5 lines
drivers/hwmon/Makefile +5
-0+static int __devinit f15h_power_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct device *hwmon_dev; + int err = -ENODEV;You should move this initialization to the only case which needs it. Otherwise you're slowing down the success path with no good reason.
to be done
Quoted 9 lines
Quoted 9 lines
drivers/hwmon/Makefile +9
-0+ + if (!f15h_power_is_internal_node0(pdev)) + goto exit; + + err = device_create_file(&pdev->dev, &dev_attr_power1_input); + if (err) + goto exit; + err = device_create_file(&pdev->dev, &dev_attr_power1_cap); + if (err)
Quoted 8 lines
drivers/hwmon/Makefile
Quoted 5 lines
drivers/hwmon/Makefile +5
-0+ goto exit_remove; + + err = device_create_file(&pdev->dev, &dev_attr_name); + if (err) + goto exit_remove;Please consider defining and using an attribute group, it makes the code more simple.
Will think about it.
Quoted 9 lines
drivers/hwmon/Makefile
Quoted 7 lines
drivers/hwmon/Makefile +7
-0+ + hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(hwmon_dev)) { + err = PTR_ERR(hwmon_dev); + goto exit_remove; + } + dev_set_drvdata(&pdev->dev, hwmon_dev);
pci_set_drvdata()
Are you sure?
No single hwmon driver is using this wrapper around dev_set_drvdata() so far. (Or I just missed it.) At the moment only dev_set_drvdata() is used by
drivers/hwmon/adcxx.c
drivers/hwmon/lm70.c
drivers/hwmon/ultra45_env.c
drivers/hwmon/ibmpex.c
drivers/hwmon/k10temp.c
drivers/hwmon/ibmaem.c
drivers/hwmon/k8temp.c
Quoted 28 lines
Quoted 8 lines
drivers/hwmon/Makefile +8
-0+ + return 0; + +exit_remove: + device_remove_file(&pdev->dev, &dev_attr_name); + device_remove_file(&pdev->dev, &dev_attr_power1_input); + device_remove_file(&pdev->dev, &dev_attr_power1_cap); +exit:drivers/hwmon/Makefile
Quoted 10 lines
drivers/hwmon/Makefile +10
-0+ return err; +} + +static void __devexit f15h_power_remove(struct pci_dev *pdev) +{ + hwmon_device_unregister(dev_get_drvdata(&pdev->dev)); + device_remove_file(&pdev->dev, &dev_attr_name); + device_remove_file(&pdev->dev, &dev_attr_power1_input); + device_remove_file(&pdev->dev, &dev_attr_power1_cap); + dev_set_drvdata(&pdev->dev, NULL);
pci_set_drvdata()drivers/hwmon/Makefile
Quoted 4 lines
drivers/hwmon/Makefile +4
-0+} + +static const struct pci_device_id f15h_power_id_table[] = { + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_LINK) },Not defined anywhere, causing the driver to fail building:
Quoted 5 lines
drivers/hwmon/f15h_power.c:193:1: error: 'PCI_DEVICE_ID_AMD_15H_NB_LINK' undeclared here (not in a function) make[2]: *** [drivers/hwmon/f15h_power.o] Error 1
make[1]: *** [drivers/hwmon] Error 2
make[1]: *** Waiting for unfinished jobs....
make: *** [drivers] Error 2
The macro changed with .39-rc2
Already fixed in v3
Thanks for your review,
Please let me know whether changing the variable names and using pci_set_drvdata() is strictly required.
Andreas
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v2] hwmon: Add driver for AMD family 15h processor power information
Quoted 11 lines · Andreas Herrmann
Quoted 9 lines · Jean Delvare
drivers/hwmon/f15h_power.c line 49
Quoted 6 lines · Andreas Herrmann
drivers/hwmon/f15h_power.c new file +6
-0+static ssize_t show_power (struct device *dev, +struct device_attribute *attr,char *buf) +{ +u32 val, btdp, tdpl, tdp2w, arange; +s32 acap; +u64 ctdp;These variable names aren't easy to understand.
Quoted 7 lines
Just random names which eventually map to the spec:
btdp -
base_tdp
tdpl -tdp_limit
tdp2w -tdp_to_watt
acap -average_accumulator_capture(or even worse how about "processor_tdp_running_average_accumulator":( arange -average_range
avg_cap and avg_range would do, respectively, for the last two.
Quoted 3 lines
I don't think that changing the names make it much easier to reconstruct the calculation but if you insist in changing it I'll adapt it.
I do prefer the "extended" names, really. Sure, this doesn't change the calculations, but it helps the reader understand what's going on. Which will be useful if one ever has to fix a bug in the code or extend it for a different CPU family.
But maybe this is just me. Guenter, do you have an opinion?
Quoted 6 lines
Quoted 4 lines
drivers/hwmon/f15h_power.c line 171
Quoted 2 lines
(...)
drivers/hwmon/f15h_power.c new file +1
-0+dev_set_drvdata (&pdev->dev, hwmon_dev);
pci_set_drvdata()Are you sure?
Yes, I'm sure. This function exists, so there is no reason not to use it.
Quoted 1 line
No single hwmon driver is using this wrapper around
dev_set_drvdata()so far. (Or I just missed it.)
$ grep i2c_set_clientdata drivers/hwmon/*.c | wc -l 67 $ grep spi_set_drvdata drivers/hwmon/*.c | wc -l 2 $ grep platform_set_drvdata drivers/hwmon/*.c | wc -l 66 $
Quoted 9 lines
At the moment only
dev_set_drvdata()is used by
drivers/hwmon/adcxx.c
drivers/hwmon/lm70.c
drivers/hwmon/ultra45_env.c
drivers/hwmon/ibmpex.c
drivers/hwmon/k10temp.c
drivers/hwmon/ibmaem.c
drivers/hwmon/k8temp.c
Most of these (at least spi and pci drivers) should be fixed. I'll send a patch later.
Signature · 6 lines
Jean Delvare _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v2] hwmon: Add driver for AMD family 15h processor power information
Quoted 26 lines · Jean Delvare
Quoted 11 lines · Andreas Herrmann
Quoted 9 lines · Jean Delvare
drivers/hwmon/f15h_power.c line 49
Quoted 6 lines · Andreas Herrmann
drivers/hwmon/f15h_power.c new file +6
-0+static ssize_t show_power (struct device *dev, +struct device_attribute *attr,char *buf) +{ +u32 val, btdp, tdpl, tdp2w, arange; +s32 acap; +u64 ctdp;These variable names aren't easy to understand.
Quoted 7 lines
Just random names which eventually map to the spec:
btdp -
base_tdp
tdpl -tdp_limit
tdp2w -tdp_to_watt
acap -average_accumulator_capture(or even worse how about "processor_tdp_running_average_accumulator":( arange -average_range
avg_capandavg_rangewould do, respectively, for the last two.Quoted 3 lines
I don't think that changing the names make it much easier to reconstruct the calculation but if you insist in changing it I'll adapt it.
Quoted 7 lines
I do prefer the "extended" names, really. Sure, this doesn't change the calculations, but it helps the reader understand what's going on. Which will be useful if one ever has to fix a bug in the code or extend it for a different CPU family.
But maybe this is just me. Guenter, do you have an opinion?
I agree. base_tdp is definitely much better than btdp. Same for the others.
Thanks,
Guenter
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v2] hwmon: Add driver for AMD family 15h processor power information
Quoted 32 lines · Guenter Roeck
Quoted 31 lines · Jean Delvare
Quoted 11 lines · Andreas Herrmann
Quoted 9 lines · Jean Delvare
drivers/hwmon/f15h_power.c line 49
Quoted 6 lines · Andreas Herrmann
drivers/hwmon/f15h_power.c new file +6
-0+static ssize_t show_power (struct device *dev, +struct device_attribute *attr,char *buf) +{ +u32 val, btdp, tdpl, tdp2w, arange; +s32 acap; +u64 ctdp;These variable names aren't easy to understand.
Quoted 7 lines
Just random names which eventually map to the spec:
btdp -
base_tdp
tdpl -tdp_limit
tdp2w -tdp_to_watt
acap -average_accumulator_capture(or even worse how about "processor_tdp_running_average_accumulator":( arange -average_range
avg_capandavg_rangewould do, respectively, for the last two.Quoted 3 lines
I don't think that changing the names make it much easier to reconstruct the calculation but if you insist in changing it I'll adapt it.
I do prefer the "extended" names, really. Sure, this doesn't change the calculations, but it helps the reader understand what's going on. Which will be useful if one ever has to fix a bug in the code or extend it for a different CPU family.
Quoted 6 lines
Quoted 2 lines
But maybe this is just me. Guenter, do you have an opinion?
I agree.
base_tdpis definitely much better than btdp. Same for the others.Thanks,
Guenter
Ok.
Will update the patch soon.
Andreas
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors