v1 of IBM power meter driver
Subsystems (2)
PATCH 1/1 v1 of IBM power meter driver
Hi everyone,
Attached is a driver to export sensor readings from power meters that are found in several IBM x86 systems. At the moment, the hwmon sysfs documentation doesn't mention any naming conventions for sensors that measure Watts, so I am proposing that they be called "powerX_input" in a fashion similar to temperature/rpm/current sensors. If that is agreeable to everyone, I'll post a follow-up patch to amend the documentation.
The patch should apply against 2.6.23-rc3 and has been tested on the x3550, x3650, x3655, x3755 and HS20 blades that support it. As far as I know, those are the only systems in existence that have this interface.
---ibm_pex: Driver to export IBM PowerExecutive power meter sensors.
---
drivers/hwmon/Kconfig | 12 + drivers/hwmon/Makefile | 1 drivers/hwmon/ibmpex.c | 615 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 628 insertions(+), 0 deletions(-)
drivers/hwmon/Kconfig +12 -0
@@ -275,6 +275,18 @@ config SENSORS_CORETEMP sensor inside your CPU. Supported all are all known variants of Intel Core family. +config SENSORS_IBMPEX + tristate "IBM PowerExecutive temperature/power sensors" + depends on IPMI_SI + help + If you say yes here you get support for the temperature and + power sensors in various IBM System X servers that support + PowerExecutive. So far this includes the x3550, x3650, x3655, + x3755, and certain HS20 blades. + + This driver can also be built as a module. If so, the module + will be called ibmpex. + config SENSORS_IT87 tristate "ITE IT87xx and compatibles" select HWMON_VID
drivers/hwmon/Makefile +1 -0
@@ -35,6 +35,7 @@ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o +obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_LM63) += lm63.o
drivers/hwmon/ibmpex.c new file +615 -0
615 lines not on this page · raw message
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Quoted 5 lines · Darrick J. Wong
documentation doesn't mention any naming conventions for sensors that measure Watts, so I am proposing that they be called "
powerX_input" in a fashion similar to temperature/rpm/current sensors. If that is agreeable to everyone, I'll post a follow-up patch to amend the documentation.
What unit should we use? Watts are way, way too big as there is no floating/fixed point in sysfs. 10^-6 W is probably what is called for, since we already need 10^-3 V and 10^-3 A. Small portable devices can easily draw less than 10^-3 W nowadays.
Signature · 9 lines
"One disk to rule them all, One disk to find them. One disk to bring them all and in the darkness grind them. In the Land of Redmond where the shadows lie." -- The Silicon Valley Tarot Henrique Holschuh _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Hi Darrick, hi Henrique,
Good thing that manufacturers start including wattmeters in their hardware. Hopefully this will help users better control their power consumption in the long run.
Quoted 11 lines · Henrique de Moraes Holschuh
Quoted 5 lines · Darrick J. Wong
documentation doesn't mention any naming conventions for sensors that measure Watts, so I am proposing that they be called "
powerX_input" in a fashion similar to temperature/rpm/current sensors. If that is agreeable to everyone, I'll post a follow-up patch to amend the documentation.What unit should we use? Watts are way, way too big as there is no floating/fixed point in sysfs. 10^-6 W is probably what is called for, since we already need 10^-3 V and 10^-3 A. Small portable devices can easily draw less than 10^-3 W nowadays.
Good point. The driver currently exports non-integer values, which is not acceptable, so indeed it needs to be changed. We want at least a resolution of 10^-3 W. Not sure about 10^-6 W. I am surprised that portable devices can really draw less than 1 mW, and be it the case, I doubt that manufacturers will embed a wattmetter: it would probably draw more current than the rest of the device ;) so it may not be relevant for our decision.
So I think I'd go with 10^-3 W, but I welcome diverging opinions. Out of curiosity, what is the physical resolution of IBM's device?
I see that the driver relies on IPMI. Can't it be merged with the out-of-tree impisensors driver then? This would give that driver some momentum so that it can finally be merged, and I would like to avoid having two drivers if one is enough. Note though that I don't know anything about IPMI so I might as well be totally wrong ;)
Signature · 1 line
Jean Delvare
Quoted 5 lines · Jean Delvare
Hi Darrick, hi Henrique,
Good thing that manufacturers start including wattmeters in their hardware. Hopefully this will help users better control their power consumption in the long run.
Yes, we're working on that too. :)
Quoted 7 lines
Quoted 4 lines
What unit should we use? Watts are way, way too big as there is no floating/fixed point in sysfs. 10^-6 W is probably what is called for, since we already need 10^-3 V and 10^-3 A. Small portable devices can easily draw less than 10^-3 W nowadays.
Good point. The driver currently exports non-integer values, which is not acceptable, so indeed it needs to be changed. We want at least a
I had a feeling you might say that. :) I'll post a follow-up patch that presents the power meters in mW instead of W.
Quoted 2 lines
resolution of 10^-3 W. Not sure about 10^-6 W. I am surprised that portable devices can really draw less than 1 mW, and be it the case, I
Are there meters that can measure that small a quantity of power? If so, then I'll vote for uW; otherwise, mW is fine enough for me.
Quoted 6 lines
doubt that manufacturers will embed a wattmetter: it would probably draw more current than the rest of the device ;) so it may not be relevant for our decision.
So I think I'd go with 10^-3 W, but I welcome diverging opinions. Out of curiosity, what is the physical resolution of IBM's device?
I don't know for sure, but my observation is that they're no more accurate than a Watt. Some of those meters appear to be averages, which would explain why they occasionally have deciWatt components.
Quoted 5 lines
I see that the driver relies on IPMI. Can't it be merged with the out-of-tree impisensors driver then? This would give that driver some momentum so that it can finally be merged, and I would like to avoid having two drivers if one is enough. Note though that I don't know anything about IPMI so I might as well be totally wrong ;)
The IBM PEx meters are accessible via custom IPMI commands, not the standard IPMI sensor interface. I considered modifying the ipmisensors driver, but reached the opinion that it would clutter that driver unnecessarily, particularly since there are a lot of systems with IPMI BMCs, but most of them will not have this interface.
That said, what is standing in the way of ipmisensors being merged? I think I can shake out some free time to apply TLC.
--D
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Hi Darrick,
Quoted 7 lines · Darrick J. Wong
Quoted 5 lines · Jean Delvare
I see that the driver relies on IPMI. Can't it be merged with the out-of-tree impisensors driver then? This would give that driver some momentum so that it can finally be merged, and I would like to avoid having two drivers if one is enough. Note though that I don't know anything about IPMI so I might as well be totally wrong ;)
Quoted 5 lines
The IBM PEx meters are accessible via custom IPMI commands, not the standard IPMI sensor interface. I considered modifying the ipmisensors driver, but reached the opinion that it would clutter that driver unnecessarily, particularly since there are a lot of systems with IPMI BMCs, but most of them will not have this interface.
OK, fine with me then.
Quoted 2 lines
That said, what is standing in the way of ipmisensors being merged? I think I can shake out some free time to apply TLC.
I don't know exactly, check out the website for details:
http://bmcsensors-26.sourceforge.net/
It needs at least review and testing, but maybe there are a few more steps before merging can be considered. Adding Yani (the author) to Cc, please work with him if you're interested.
Signature · 1 line
Jean Delvare
Quoted 3 lines
It needs at least review and testing, but maybe there are a few more steps before merging can be considered. Adding Yani (the author) to Cc, please work with him if you're interested.
As a user, I can tell you that it completely fills my dmesg with this sort
ipmisensors: sensor 50 (type 1) reading 60
ipmisensors: Send 0x2d 0x30 0x0
ipmisensors: received message
ipmisensors: sensor 48 (type 1) reading 28
ipmisensors: Send 0x2d 0x1b 0x0
ipmisensors: received message
ipmisensors: sensor 27 (type 2) reading 34
ipmisensors: Send 0x2d 0x1a 0x0
ipmisensors: received message
ipmisensors: sensor 26 (type 2) reading 187
ipmisensors: Send 0x2d 0x18 0x0
That's the only problem I have. It would be great to see it merged.
Frank
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
PATCH 1/1 hwmon: Add power meters to Documentation/hwmon/sysfs-interface
In reply to Jean DelvareUpdate the hwmon sysfs interface documentation to include a specification for power meters.
---
Documentation/hwmon/sysfs-interface | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-)
Documentation/hwmon/sysfs-interface +15 -0
@@ -304,6 +304,21 @@ curr[1-*]_input Current input value Unit: milliampere RO +********* +* Power * +********* + +power[1-*]_input Current power use + Unit: milliWatt + RO + +power[1-*]_max_input Historical maximum power use + Unit: milliWatt + RO + +power[1-*]_min_input Historical minimum power use + Unit: milliWatt + RO ********** * Alarms *
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH] hwmon: Add power meters to Documentation/hwmon/sysfs-interface
Hi Darrick,
Quoted 23 lines · Darrick J. Wong
Update the hwmon sysfs interface documentation to include a specification for power meters.
Signed-off-by Darrick J. Wong <[email protected]>---
Documentation/hwmon/sysfs-interface | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-)Documentation/hwmon/sysfs-interface +6
-0@@ -304,6 +304,21 @@ curr[1-*]_input Current input value Unit: milliampere RO +********* +* Power * +********* + +power[1-*]_input Current power use + Unit: milliWatt
Documentation/hwmon/sysfs-interface curr[1-*]_input Current input value · line 322
Quoted 10 lines
Documentation/hwmon/sysfs-interface +9
-0+ RO + +power[1-*]_max_input Historical maximum power use + Unit: milliWatt + RO + +power[1-*]_min_input Historical minimum power use + Unit: milliWatt + RO
I'm not sure if we want these "historical" files. We don't have them for the other input types, and I believe that it's not the driver's job to compute and export these values. If anyone cares about the history of sensed values, that's something for a user-space application to implement. This will also be much more flexible in user-space, as it becomes possible to decide the exact time range to consider, to remember at which time the peak occurred, etc.
Signature · 1 line
Jean Delvare
Re: [PATCH] hwmon: Add power meters to Documentation/hwmon/sysfs-interface
Quoted 3 lines · Jean Delvare
I'm not sure if we want these "historical" files. We don't have them for the other input types, and I believe that it's not the driver's job to compute and export these values. If anyone cares about the history of
In the case of ibmpex, it is the _hardware_ that computes the historical data; the driver merely exports what it sees.
--D
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH] hwmon: Add power meters to Documentation/hwmon/sysfs-interface
Hi Darrick,
Quoted 8 lines · Darrick J. Wong
Quoted 3 lines · Jean Delvare
I'm not sure if we want these "historical" files. We don't have them for the other input types, and I believe that it's not the driver's job to compute and export these values. If anyone cares about the history of
In the case of ibmpex, it is the _hardware_ that computes the historical data; the driver merely exports what it sees.
OK, that's a bit different then, but I'm still not sure that there is much value in exporting these values in sysfs, in particular if there is no way to reset them.
I am also not happy with the names you proposed: power1_max_input and power1_min_input are somewhat confusing IMHO, I'd suggest power1_input_highest and power1_input_lowest to make them clearly different from the min and max limits we have for other sensor types. If we have them at all, of course.
Signature · 1 line
Jean Delvare
Re: [PATCH] hwmon: Add power meters to Documentation/hwmon/sysfs-interface
Quoted 3 lines · Jean Delvare
OK, that's a bit different then, but I'm still not sure that there is much value in exporting these values in sysfs, in particular if there is no way to reset them.
It turns out there _is_ a way to reset them; the next iteration of the driver will have it.
Quoted 5 lines
I am also not happy with the names you proposed:
power1_max_inputandpower1_min_inputare somewhat confusing IMHO, I'd suggestpower1_input_highestandpower1_input_lowestto make them clearly different from the min and max limits we have for other sensor types. If we have them at all, of course.
Agreed and changed.
--D
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH] hwmon: Add power meters to Documentation/hwmon/sysfs-interface
In reply to Darrick J. WongHi!
Quoted 13 lines
Documentation/hwmon/sysfs-interface +5
-0@@ -304,6 +304,21 @@ curr[1-*]_input Current input value Unit: milliampere RO +********* +* Power * +********* + +power[1-*]_input Current power use
Documentation/hwmon/sysfs-interface curr[1-*]_input Current input value · line 321
Quoted 10 lines
Documentation/hwmon/sysfs-interface +10
-0+ Unit: milliWatt + RO + +power[1-*]_max_input Historical maximum power use + Unit: milliWatt + RO + +power[1-*]_min_input Historical minimum power use + Unit: milliWatt + RO
Should we add power?_10sec_avg_input? IIRC thinkpads export that, too.
Pavel
Signature · 7 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH] hwmon: Add power meters to Documentation/hwmon/sysfs-interface
Quoted 18 lines · Pavel Machek
Quoted 18 lines
Documentation/hwmon/sysfs-interface +10
-0@@ -304,6 +304,21 @@ curr[1-*]_input Current input value Unit: milliampere RO +********* +* Power * +********* + +power[1-*]_input Current power use + Unit: milliWatt + RO + +power[1-*]_max_input Historical maximum power use + Unit: milliWatt
Quoted 8 lines
Documentation/hwmon/sysfs-interface curr[1-*]_input Current input value · line 321
Quoted 5 lines
Documentation/hwmon/sysfs-interface +5
-0+ RO + +power[1-*]_min_input Historical minimum power use + Unit: milliWatt + ROShould we add power?_10sec_avg_input? IIRC thinkpads export that, too.
Indeed, ThinkPads report both instantaneous power/current and a rolling average (exponentially decaying, I think) over the last ~10 seconds. ACPI provides only the rolling average, and the out-of-tree tp_smapi driver provides both.
More generally, linux/power_supply.h defines these attributes:
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_VOLTAGE_AVG,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CURRENT_AVG,
It would be nice if the power meter interface uses the same conventions as the power supply interface, since the former is essentially a subset of the latter. Userspace app that read power meters via sysfs should work for power supplies too.
Shem
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [lm-sensors] [PATCH] hwmon: Add power meters to Documentation/hwmon/sysfs-interface
Quoted 2 lines · Shem Multinymous
Quoted 2 lines
Should we add power?_10sec_avg_input? IIRC thinkpads export that, too.
I'd say it is enough to know it is an average, you don't need to specify HOW it is averaged.
But there is a real need to export both instantaneous and averaged values in power supplies/power sources, so we should have a standard way to do so in hwmon, and power_supply class should use it (or the opposite, it doesn't matter, as long as everyone does it the same way).
Quoted 4 lines
It would be nice if the power meter interface uses the same conventions as the power supply interface, since the former is essentially a subset of the latter. Userspace app that read power meters via sysfs should work for power supplies too.
Agreed.
Signature · 9 lines
"One disk to rule them all, One disk to find them. One disk to bring them all and in the darkness grind them. In the Land of Redmond where the shadows lie." -- The Silicon Valley Tarot Henrique Holschuh _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [lm-sensors] [PATCH] hwmon: Add power meters to Documentation/hwmon/sysfs-interface
Quoted 6 lines · Henrique de Moraes Holschuh
Quoted 2 lines · Shem Multinymous
Quoted 2 lines
Should we add power?_10sec_avg_input? IIRC thinkpads export that, too.
I'd say it is enough to know it is an average, you don't need to specify HOW it is averaged.
Agreed.
Quoted 4 lines
But there is a real need to export both instantaneous and averaged values in power supplies/power sources, so we should have a standard way to do so in hwmon, and
power_supplyclass should use it (or the opposite, it doesn't matter, as long as everyone does it the same way).
I guess power[1-*]_average would be OK?
Signature · 1 line
Jean Delvare
Re: [lm-sensors] [PATCH] hwmon: Add power meters to Documentation/hwmon/sysfs-interface
Quoted 8 lines · Jean Delvare
Quoted 6 lines · Henrique de Moraes Holschuh
Quoted 2 lines · Shem Multinymous
Quoted 2 lines
Should we add power?_10sec_avg_input? IIRC thinkpads export that, too.
I'd say it is enough to know it is an average, you don't need to specify HOW it is averaged.
Quoted 8 lines
Agreed.
Quoted 4 lines
But there is a real need to export both instantaneous and averaged values in power supplies/power sources, so we should have a standard way to do so in hwmon, and
power_supplyclass should use it (or the opposite, it doesn't matter, as long as everyone does it the same way).I guess power[1-*]_average would be OK?
AFAIK, yes. It is probably not 100% in sync with the power supply class, though.
Signature · 9 lines
"One disk to rule them all, One disk to find them. One disk to bring them all and in the darkness grind them. In the Land of Redmond where the shadows lie." -- The Silicon Valley Tarot Henrique Holschuh _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [lm-sensors] [PATCH] hwmon: Add power meters to Documentation/hwmon/sysfs-interface
Quoted 5 lines · Henrique de Moraes Holschuh
Quoted 1 line · Jean Delvare
I guess power[1-*]_average would be OK?
AFAIK, yes. It is probably not 100% in sync with the power supply class, though.
Is the power supply class creating sysfs files? I see a number of attributes listed in Documentation/power_supply_class.txt, but they are all uppercase, which doesn't seem suitable for sysfs file names. That document also doesn't list the numbering convention when multiple channels are present.
My main worry is that we will have to add support for power measurement in libsensors, and I would like it to be as easy as possible. Thus sticking to the same naming convention hwmon have been using for years appears to be the best solution.
I see that the power supply class units are 10^-6 A and 10^-6 W, so if we are supposed to be compatible, I guess we'll have to use this too.
Signature · 1 line
Jean Delvare
Re: [lm-sensors] [PATCH] hwmon: Add power meters to Documentation/hwmon/sysfs-interface
Quoted 4 lines · Jean Delvare
Quoted 3 lines · Henrique de Moraes Holschuh
Quoted 1 line · Jean Delvare
I guess power[1-*]_average would be OK?
Quoted 8 lines
Quoted 2 lines
AFAIK, yes. It is probably not 100% in sync with the power supply class, though.
Is the power supply class creating sysfs files? I see a number of attributes listed in
Documentation/power_supply_class.txt, but they are all uppercase, which doesn't seem suitable for sysfs file names. That document also doesn't list the numbering convention when multiple channels are present.
Looks like power supply needs some tweaks, then.
Quoted 4 lines
My main worry is that we will have to add support for power measurement in libsensors, and I would like it to be as easy as possible. Thus sticking to the same naming convention hwmon have been using for years appears to be the best solution.
Agreed.
Quoted 2 lines
I see that the power supply class units are 10^-6 A and 10^-6 W, so if we are supposed to be compatible, I guess we'll have to use this too.
There was a good reason for that, and people who deal with small portables said that they needed 10^-4 A or somesuch, at which point it makes more sense to just go to 10^-6 already. I don't recall why 10^-6 W, though.
Signature · 9 lines
"One disk to rule them all, One disk to find them. One disk to bring them all and in the darkness grind them. In the Land of Redmond where the shadows lie." -- The Silicon Valley Tarot Henrique Holschuh _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [lm-sensors] [PATCH] hwmon: Add power meters to Documentation/hwmon/sysfs-interface
Quoted 7 lines · Henrique de Moraes Holschuh
Quoted 2 lines · Jean Delvare
I see that the power supply class units are 10^-6 A and 10^-6 W, so if we are supposed to be compatible, I guess we'll have to use this too.
There was a good reason for that, and people who deal with small portables said that they needed 10^-4 A or somesuch, at which point it makes more sense to just go to 10^-6 already. I don't recall why 10^-6 W, though.
Well, if we need 10^-4 A, and we use voltages in the 1-2 V range (that's what CPU, AGP etc. use these days), then we obviously need 10^-4 W as well.
Signature · 1 line
Jean Delvare
Re: [lm-sensors] [PATCH] hwmon: Add power meters to Documentation/hwmon/sysfs-interface
Quoted 5 lines · Jean Delvare
Quoted 4 lines · Henrique de Moraes Holschuh
Quoted 2 lines · Jean Delvare
I see that the power supply class units are 10^-6 A and 10^-6 W, so if we are supposed to be compatible, I guess we'll have to use this too.
Quoted 7 lines
Quoted 3 lines
There was a good reason for that, and people who deal with small portables said that they needed 10^-4 A or somesuch, at which point it makes more sense to just go to 10^-6 already. I don't recall why 10^-6 W, though.
Well, if we need 10^-4 A, and we use voltages in the 1-2 V range (that's what CPU, AGP etc. use these days), then we obviously need 10^-4 W as well.
I see, and in that case it is safer to just go to 10^-6 for both. It is more future-proof.
Signature · 9 lines
"One disk to rule them all, One disk to find them. One disk to bring them all and in the darkness grind them. In the Land of Redmond where the shadows lie." -- The Silicon Valley Tarot Henrique Holschuh _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
PATCH 1/1 v2 of IBM power meter driver
In reply to Jean Delvareibm_pex: Driver to export IBM PowerExecutive power meter sensor readings in mW.
---
drivers/hwmon/Kconfig | 12 + drivers/hwmon/Makefile | 1 drivers/hwmon/ibmpex.c | 600 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 613 insertions(+), 0 deletions(-)
drivers/hwmon/Kconfig +12 -0
@@ -275,6 +275,18 @@ config SENSORS_CORETEMP sensor inside your CPU. Supported all are all known variants of Intel Core family. +config SENSORS_IBMPEX + tristate "IBM PowerExecutive temperature/power sensors" + depends on IPMI_SI + help + If you say yes here you get support for the temperature and + power sensors in various IBM System X servers that support + PowerExecutive. So far this includes the x3550, x3650, x3655, + x3755, and certain HS20 blades. + + This driver can also be built as a module. If so, the module + will be called ibmpex. + config SENSORS_IT87 tristate "ITE IT87xx and compatibles" select HWMON_VID
drivers/hwmon/Makefile +1 -0
@@ -35,6 +35,7 @@ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o +obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_LM63) += lm63.o
drivers/hwmon/ibmpex.c new file +600 -0
600 lines not on this page · raw message
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
PATCH 1/1 v3 of IBM power meter driver
Dave Hansen complained about the magic numbers, repetitive code, and various other minor problems with the driver code, so here's a v3 with the magic numbers migrated to the top of the file and #define'd, helper macros taking place of the bit shifting/masking activities, and the compression of the value/min/max sysfs code into parameterized functions.
--ibm_pex: Driver to export IBM PowerExecutive power meter sensors.
---
drivers/hwmon/Kconfig | 12 + drivers/hwmon/Makefile | 1 drivers/hwmon/ibmpex.c | 564 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 577 insertions(+), 0 deletions(-)
drivers/hwmon/Kconfig +12 -0
@@ -275,6 +275,18 @@ config SENSORS_CORETEMP sensor inside your CPU. Supported all are all known variants of Intel Core family. +config SENSORS_IBMPEX + tristate "IBM PowerExecutive temperature/power sensors" + depends on IPMI_SI + help + If you say yes here you get support for the temperature and + power sensors in various IBM System X servers that support + PowerExecutive. So far this includes the x3550, x3650, x3655, + x3755, and certain HS20 blades. + + This driver can also be built as a module. If so, the module + will be called ibmpex. + config SENSORS_IT87 tristate "ITE IT87xx and compatibles" select HWMON_VID
drivers/hwmon/Makefile +1 -0
@@ -35,6 +35,7 @@ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o +obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_LM63) += lm63.o
drivers/hwmon/ibmpex.c new file +564 -0
564 lines not on this page · raw message
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH] v3 of IBM power meter driver
Hi Darrick:
Quoted 10 lines · Darrick J. Wong
Dave Hansen complained about the magic numbers, repetitive code, and various other minor problems with the driver code, so here's a v3 with the magic numbers migrated to the top of the file and #define'd, helper macros taking place of the bit shifting/masking activities, and the compression of the value/min/max sysfs code into parameterized functions.
--ibm_pex: Driver to export IBM PowerExecutive power meter sensors.Signed-off-by Darrick J. Wong <[email protected]>
I am not an IPMI expert, so I would appreciate getting an Acked-by from someone who knows more about that subsystem.
Anyway, some comments are below. This is nowhere near a complete review yet.
Quoted 12 lines
---
drivers/hwmon/Kconfig | 12 + drivers/hwmon/Makefile | 1 drivers/hwmon/ibmpex.c | 564 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 577 insertions(+), 0 deletions(-)drivers/hwmon/Kconfig +0
-0
drivers/hwmon/Kconfig config SENSORS_CORETEMP · line 280
Quoted 6 lines
drivers/hwmon/Kconfig +3
-0@@ -275,6 +275,18 @@ config SENSORS_CORETEMP sensor inside your CPU. Supported all are all known variants of Intel Core family. +config SENSORS_IBMPEX + tristate "IBM PowerExecutive temperature/power sensors" + depends on IPMI_SI
Open question: can we use "select" here? As written, it took some hunting to even get this driver to show up as an option in menuconfig.
Quoted 45 lines
drivers/hwmon/Kconfig +9
-0+ help + If you say yes here you get support for the temperature and + power sensors in various IBM System X servers that support + PowerExecutive. So far this includes the x3550, x3650, x3655, + x3755, and certain HS20 blades. + + This driver can also be built as a module. If so, the module + will be called ibmpex. + config SENSORS_IT87 tristate "ITE IT87xx and compatibles" select HWMON_VIDdrivers/hwmon/Makefile +1
-0@@ -35,6 +35,7 @@ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o +obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o obj-$(CONFIG_SENSORS_LM63) += lm63.odrivers/hwmon/ibmpex.c new file +15
-0@@ -0,0 +1,564 @@ +/* +* A hwmon driver for the IBM PowerExecutive temperature/power sensors +* Copyright (C) 2007 IBM +* +* Author: Darrick J. Wong <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program 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.
drivers/hwmon/ibmpex.c line 25
Quoted 10 lines
drivers/hwmon/ibmpex.c new file +10
-0+* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/ipmi.h> +#include <linux/module.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h>
#include <linux/jiffies.h>
Quoted 7 lines
drivers/hwmon/ibmpex.c new file +7
-0+#include <linux/mutex.h> + +#define REFRESH_INTERVAL (5 * HZ) +#define DRVNAME "ibmpex" + +#define PEX_GET_VERSION 1 +#define PEX_GET_SENSOR_COUNT 2
drivers/hwmon/ibmpex.c line 42
Quoted 10 lines
drivers/hwmon/ibmpex.c new file +10
-0+#define PEX_GET_SENSOR_NAME 3 +#define PEX_GET_SENSOR_DATA 6 + +#define PEX_NET_FUNCTION 0x3A +#define PEX_COMMAND 0x3C + +static inline u16 extract_value (const char *data,int offset) +{ +u16 val = *(u16 *)&data[offset]; +return be16_to_cpu (val);
return be16_to_cpup((u16*)&data[offset]);
Quoted 4 lines
drivers/hwmon/ibmpex.c new file +4
-0+} + +#define PEX_INTERFACE (idx) ((idx) >> 16) +#define PEX_SENSOR (idx) (((idx) >> 8) & 0xFF)
drivers/hwmon/ibmpex.c line 56
Quoted 10 lines
drivers/hwmon/ibmpex.c new file +10
-0+#define PEX_FUNC (idx) ((idx) & 0xFF) +#define PEX_INDEX (iface, num, fn) (((iface) << 16) | ((num) << 8) | (fn)) + +#define PEX_SENSOR_TYPE_LEN 3 +static char power_sensor_sig[] = {0x70 ,0x77 ,0x72 }; +static char temp_sensor_sig[] = {0x74 ,0x65 ,0x6D }; + +#define PEX_MULT_LEN 2 +static char watt_sensor_sig[] = {0x41 ,0x43 }; +
All three above should be "static u8 const"
drivers/hwmon/ibmpex.c line 63
Quoted 7 lines
drivers/hwmon/ibmpex.c new file +7
-0+#define PEX_NUM_SENSOR_FUNCS 3 +static char *sensor_name_templates[] = { +"%s%d_input" , +"%s%d_min_input" , +"%s%d_max_input" +}; +
static char const * const sensor_name_templates[] = {
Quoted 5 lines
drivers/hwmon/ibmpex.c new file +5
-0+static void ibmpex_msg_handler (struct ipmi_recv_msg *msg,void *user_msg_data); +static void ibmpex_register_bmc (int iface,struct device *dev); +static void ibmpex_bmc_gone (int iface); + +struct ibmpex_sensor_data {
drivers/hwmon/ibmpex.c line 78
Quoted 10 lines
drivers/hwmon/ibmpex.c new file +10
-0+int in_use; +s16 values[PEX_NUM_SENSOR_FUNCS ]; +int multiplier; + +struct sensor_device_attribute attr[PEX_NUM_SENSOR_FUNCS ]; +}; + +struct ibmpex_bmc_data { +struct list_head list; +struct class_device *class_dev;
My current stack of patches includes one which requires that this be changed to 'struct device *hwmon_dev', as 'struct class_device' is going away soon. You may rebase on my testing tree[1], or else I will just follow up with a patch to fix this up after I eventually merge yours.
[1] http://lm-sensors.org/kernel?p=kernel/mhoffman/hwmon-2.6.git;a=shortlog;h=testing
Quoted 168 lines
drivers/hwmon/ibmpex.c new file +168
-0+struct device *bmc_device; +struct mutex lock; +char valid; +unsigned long last_updated;/* In jiffies */ + +struct ipmi_addr address; +struct completion read_complete; +ipmi_user_t user; +int interface; + +struct kernel_ipmi_msg tx_message; +unsigned char tx_msg_data[IPMI_MAX_MSG_LENGTH ]; +long tx_msgid; + +unsigned char rx_msg_data[IPMI_MAX_MSG_LENGTH ]; +unsigned long rx_msg_len; +unsigned char rx_result; +int rx_recv_type; + +unsigned char sensor_major; +unsigned char sensor_minor; + +unsigned char num_sensors; +struct ibmpex_sensor_data *sensors; +}; + +struct ibmpex_driver_data { +struct list_head bmc_data; +struct ipmi_smi_watcher bmc_events; +struct ipmi_user_hndl ipmi_hndlrs; +}; + +static struct ibmpex_driver_data driver_data = { + .bmc_data =LIST_HEAD_INIT (driver_data.bmc_data), + .bmc_events = { + .owner =THIS_MODULE , + .new_smi = ibmpex_register_bmc, + .smi_gone = ibmpex_bmc_gone, + }, + .ipmi_hndlrs = { + .ipmi_recv_hndl = ibmpex_msg_handler, + }, +}; + +static int ibmpex_send_message (struct ibmpex_bmc_data *data) +{ +int err; + + err =ipmi_validate_addr (&data->address,sizeof (data->address)); +if (err) + goto out; + + data->tx_msgid++; + err =ipmi_request_settime (data->user, &data->address, data->tx_msgid, + &data->tx_message, data,0 ,0 ,0 ); +if (err) + goto out1; + +return 0 ; +out1: +printk (KERN_ERR "%s: request_settime=%x\n" , __FUNCTION__, err); +return err; +out: +printk (KERN_ERR "%s: validate_addr=%x\n" , __FUNCTION__, err); +return err; +} + +static int ibmpex_ver_check (struct ibmpex_bmc_data *data) +{ + data->tx_msg_data[0 ] =PEX_GET_VERSION ; + data->tx_message.data_len =1 ; +ibmpex_send_message (data); + +wait_for_completion (&data->read_complete); + +if (data->rx_result || data->rx_msg_len !=6 ) +return -ENOENT ; + + data->sensor_major = data->rx_msg_data[0 ]; + data->sensor_minor = data->rx_msg_data[1 ]; + + printk(KERN_INFO DRVNAME ": Found BMC with sensor interface " +"v%d.%d %d-%02d-%02d on interface %d\n" , + data->sensor_major, + data->sensor_minor, +extract_value (data->rx_msg_data,2 ), + data->rx_msg_data[4 ], + data->rx_msg_data[5 ], + data->interface); + +return 0 ; +} + +static int ibmpex_query_sensor_count (struct ibmpex_bmc_data *data) +{ + data->tx_msg_data[0 ] =PEX_GET_SENSOR_COUNT ; + data->tx_message.data_len =1 ; +ibmpex_send_message (data); + +wait_for_completion (&data->read_complete); + +if (data->rx_result || data->rx_msg_len !=1 ) +return -ENOENT ; + +return data->rx_msg_data[0 ]; +} + +static int ibmpex_query_sensor_name (struct ibmpex_bmc_data *data,int sensor) +{ + data->tx_msg_data[0 ] =PEX_GET_SENSOR_NAME ; + data->tx_msg_data[1 ] = sensor; + data->tx_message.data_len =2 ; +ibmpex_send_message (data); + +wait_for_completion (&data->read_complete); + +if (data->rx_result || data->rx_msg_len <1 ) +return -ENOENT ; + +return 0 ; +} + +static int ibmpex_query_sensor_data (struct ibmpex_bmc_data *data,int sensor) +{ + data->tx_msg_data[0 ] =PEX_GET_SENSOR_DATA ; + data->tx_msg_data[1 ] = sensor; + data->tx_message.data_len =2 ; +ibmpex_send_message (data); + +wait_for_completion (&data->read_complete); + +if (data->rx_result || data->rx_msg_len <26 ) { +printk (KERN_ERR "Error reading sensor %d, please check.\n" , + sensor); +return -ENOENT ; + } + +return 0 ; +} + +static void ibmpex_update_device (struct ibmpex_bmc_data *data) +{ +int i, err; + +mutex_lock (&data->lock); +if (time_before (jiffies, data->last_updated +REFRESH_INTERVAL ) && + data->valid) + goto out; + +for (i =0 ; i < data->num_sensors; i++) { +if (!data->sensors[i].in_use) +continue ; + err =ibmpex_query_sensor_data (data, i); +if (err) +continue ; + data->sensors[i].values[0 ] > +extract_value (data->rx_msg_data,16 ); + data->sensors[i].values[1 ] > +extract_value (data->rx_msg_data,18 ); + data->sensors[i].values[2 ] > +extract_value (data->rx_msg_data,20 ); + } + + data->last_updated = jiffies; + data->valid =1 ; + +out: +mutex_unlock (&data->lock); +} + +static struct ibmpex_bmc_data *get_bmc_data (int iface)
drivers/hwmon/ibmpex.c line 259
Quoted 10 lines
drivers/hwmon/ibmpex.c new file +10
-0+{ +struct ibmpex_bmc_data *p, *next; + +list_for_each_entry_safe (p, next, &driver_data.bmc_data, list) +if (p->interface = iface) +return p; + +return NULL ; +} +
That function is yucky...
Quoted 6 lines
drivers/hwmon/ibmpex.c new file +6
-0+static ssize_t show_name (struct device *dev,struct device_attribute *devattr, +char *buf) +{ +return sprintf (buf,"%s\n" ,DRVNAME ); +} +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
drivers/hwmon/ibmpex.c line 275
Quoted 10 lines
drivers/hwmon/ibmpex.c new file +10
-0+ +static ssize_t ibmpex_show_sensor (struct device *dev, +struct device_attribute *devattr, +char *buf) +{ +struct sensor_device_attribute *attr =to_sensor_dev_attr (devattr); +int iface =PEX_INTERFACE (attr->index); +int sensor =PEX_SENSOR (attr->index); +int func =PEX_FUNC (attr->index); +struct ibmpex_bmc_data *data =get_bmc_data (iface);
... especially given how many times you're going to call it. Is there any reason you can't use the driver_data field of struct device *dev for that?
E.g. i2c based hwmon drivers do this at some point during the probe:
i2c_set_clientdata(new_client, data);
(which becomes)
dev_set_drvdata(&new_client->dev, data);
If you could do that, then you no longer need 'iface' at all in the function above... *that* may allow you to use the SENSOR_ATTR_2 mechanism from hwmon-sysfs.h - much easier to read than the manual number packing for 'sensor' and 'func'.
Quoted 68 lines
drivers/hwmon/ibmpex.c new file +68
-0+int multiplier = data->sensors[sensor].multiplier; +ibmpex_update_device (data); + +return sprintf (buf,"%d\n" , + data->sensors[sensor].values[func] * multiplier); +} + +static int is_power_sensor (const char *sensor_id,int len) +{ +if (len <PEX_SENSOR_TYPE_LEN ) +return 0 ; + +if (!memcmp (sensor_id, power_sensor_sig,PEX_SENSOR_TYPE_LEN )) +return 1 ; +return 0 ; +} + +static int is_temp_sensor (const char *sensor_id,int len) +{ +if (len <PEX_SENSOR_TYPE_LEN ) +return 0 ; + +if (!memcmp (sensor_id, temp_sensor_sig,PEX_SENSOR_TYPE_LEN )) +return 1 ; +return 0 ; +} + +static int power_sensor_multiplier (const char *sensor_id,int len) +{ +int i; + +for (i =PEX_SENSOR_TYPE_LEN ; i < len -1 ; i++) +if (!memcmp (&sensor_id[i], watt_sensor_sig,PEX_MULT_LEN )) +return 1000 ; + +return 100 ; +} + +static int create_sensor (struct ibmpex_bmc_data *data,const char *type, +int counter,int sensor,int func) +{ +int err; +char *n; + + n =kmalloc (32 ,GFP_KERNEL ); +if (!n) +return -ENOMEM ; + +sprintf (n, sensor_name_templates[func], type, counter); + data->sensors[sensor].attr[func].dev_attr.attr.name = n; + data->sensors[sensor].attr[func].dev_attr.attr.mode =S_IRUGO ; + data->sensors[sensor].attr[func].dev_attr.show = ibmpex_show_sensor; + data->sensors[sensor].attr[func].index > +PEX_INDEX (data->interface, sensor, func); + + err =device_create_file (data->bmc_device, + &data->sensors[sensor].attr[func].dev_attr); +if (err) { + data->sensors[sensor].attr[func].dev_attr.attr.name =NULL ; +kfree (n); +return err; + } + +return 0 ; +} + +static int ibmpex_find_sensors (struct ibmpex_bmc_data *data) +{ +int i, j, err;
drivers/hwmon/ibmpex.c line 354
Quoted 10 lines
drivers/hwmon/ibmpex.c new file +10
-0+char *sensor_type; +int sensor_counter; +int num_power =0 ; +int num_temp =0 ; + + err =ibmpex_query_sensor_count (data); +if (err <0 ) +return -ENOENT ; + data->num_sensors = err; +
Did you mean 'if (err <= 0)' ?
Quoted 21 lines
drivers/hwmon/ibmpex.c new file +21
-0+ data->sensors =kzalloc (data->num_sensors *sizeof (*data->sensors), +GFP_KERNEL ); +if (!data->sensors) +return -ENOMEM ; + +for (i =0 ; i < data->num_sensors; i++) { + err =ibmpex_query_sensor_name (data, i); +if (err) +continue ; + +if (is_power_sensor (data->rx_msg_data, data->rx_msg_len)) { + sensor_type ="power" ; + num_power++; + sensor_counter = num_power; + data->sensors[i].multiplier > +power_sensor_multiplier (data->rx_msg_data, + data->rx_msg_len); + }else if (is_temp_sensor (data->rx_msg_data, + data->rx_msg_len)) { + sensor_type ="temp" ; + num_temp++; + sensor_counter = num_temp;
drivers/hwmon/ibmpex.c line 386
Quoted 10 lines
drivers/hwmon/ibmpex.c new file +10
-0+ data->sensors[i].multiplier =1 ; + }else +continue ; + + data->sensors[i].in_use =1 ; + +/* Create attributes */ +for (j =0 ; j <PEX_NUM_SENSOR_FUNCS ; j++) +if (create_sensor (data, sensor_type, sensor_counter, + i, j))
Why not 'err = create_sensor(...)' and propagate the actual error here?
Quoted 12 lines
drivers/hwmon/ibmpex.c new file +12
-0+ goto exit_remove; + } + + err =device_create_file (data->bmc_device, + &sensor_dev_attr_name.dev_attr); +if (err) + goto exit_remove; + +return 0 ; + +exit_remove: +for (i =0 ; i < data->num_sensors; i++)
drivers/hwmon/ibmpex.c line 408
Quoted 10 lines
drivers/hwmon/ibmpex.c new file +10
-0+for (j =0 ; j <PEX_NUM_SENSOR_FUNCS ; j++) { +if (!data->sensors[i].attr[j].dev_attr.attr.name) +continue ; +device_remove_file (data->bmc_device, + &data->sensors[i].attr[j].dev_attr); +kfree (data->sensors[i].attr[j].dev_attr.attr.name); + } + +kfree (data->sensors); +return -ENOENT ;
... and 'return err' here instead.
Quoted 146 lines
drivers/hwmon/ibmpex.c new file +146
-0+} + +static void ibmpex_register_bmc (int iface,struct device *dev) +{ +struct ibmpex_bmc_data *data; +int err; + + data =kzalloc (sizeof (*data),GFP_KERNEL ); +if (!data) { + printk(KERN_ERR DRVNAME ": Insufficient memory for BMC " + "interface %d.\n", data->interface); +return ; + } + + data->address.addr_type =IPMI_SYSTEM_INTERFACE_ADDR_TYPE ; + data->address.channel =IPMI_BMC_CHANNEL ; + data->address.data[0 ] =0 ; + data->interface = iface; + data->bmc_device = dev; + +/* Create IPMI messaging interface user */ + err =ipmi_create_user (data->interface, &driver_data.ipmi_hndlrs, + data, &data->user); +if (err <0 ) { + printk(KERN_ERR DRVNAME ": Error, unable to register user with " +"ipmi interface %d\n" , + data->interface); + goto out; + } + +mutex_init (&data->lock); + +/* Initialize message */ + data->tx_msgid =0 ; +init_completion (&data->read_complete); + data->tx_message.netfn =PEX_NET_FUNCTION ; + data->tx_message.cmd =PEX_COMMAND ; + data->tx_message.data = data->tx_msg_data; + +/* Does this BMC support PowerExecutive? */ + err =ibmpex_ver_check (data); +if (err) + goto out_user; + +/* Register the BMC as a HWMON class device */ + data->class_dev =hwmon_device_register (data->bmc_device); + +if (IS_ERR (data->class_dev)) { + printk(KERN_ERR DRVNAME ": Error, unable to register hwmon " +"class device for interface %d\n" , + data->interface); +kfree (data); +return ; + } + +/* finally add the new bmc data to the bmc data list */ +list_add_tail (&data->list, &driver_data.bmc_data); + +/* Now go find all the sensors */ + err =ibmpex_find_sensors (data); +if (err) { +printk (KERN_ERR "Error %d allocating memory\n" , err); + goto out_register; + } + +return ; + +out_register: +hwmon_device_unregister (data->class_dev); +out_user: +ipmi_destroy_user (data->user); +out: +kfree (data); +} + +static void ibmpex_bmc_delete (struct ibmpex_bmc_data *data) +{ +int i, j; + +device_remove_file (data->bmc_device, &sensor_dev_attr_name.dev_attr); +for (i =0 ; i < data->num_sensors; i++) +for (j =0 ; j <PEX_NUM_SENSOR_FUNCS ; j++) { +if (!data->sensors[i].attr[j].dev_attr.attr.name) +continue ; +device_remove_file (data->bmc_device, + &data->sensors[i].attr[j].dev_attr); +kfree (data->sensors[i].attr[j].dev_attr.attr.name); + } + +list_del (&data->list); +hwmon_device_unregister (data->class_dev); +ipmi_destroy_user (data->user); +if (data->sensors) +kfree (data->sensors); +kfree (data); +} + +static void ibmpex_bmc_gone (int iface) +{ +struct ibmpex_bmc_data *data =get_bmc_data (iface); + +if (!data) +return ; + +ibmpex_bmc_delete (data); +} + +static void ibmpex_msg_handler (struct ipmi_recv_msg *msg,void *user_msg_data) +{ +struct ibmpex_bmc_data *data = (struct ibmpex_bmc_data *)user_msg_data; + +if (msg->msgid != data->tx_msgid) { +printk (KERN_ERR "Received msgid (%02x) and transmitted " +"msgid (%02x) mismatch!\n" , + (int )msg->msgid, + (int )data->tx_msgid); +ipmi_free_recv_msg (msg); +return ; + } + + data->rx_recv_type = msg->recv_type; +if (msg->msg.data_len >0 ) + data->rx_result = msg->msg.data[0 ]; +else + data->rx_result =IPMI_UNKNOWN_ERR_COMPLETION_CODE ; + +if (msg->msg.data_len >1 ) { + data->rx_msg_len = msg->msg.data_len -1 ; +memcpy (data->rx_msg_data, msg->msg.data +1 , data->rx_msg_len); + }else + data->rx_msg_len =0 ; + +ipmi_free_recv_msg (msg); +complete (&data->read_complete); +} + +static int __init ibmpex_init (void ) +{ +return ipmi_smi_watcher_register (&driver_data.bmc_events); +} + +static void __exit ibmpex_exit(void) +{ +struct ibmpex_bmc_data *p, *next; + +ipmi_smi_watcher_unregister (&driver_data.bmc_events);
drivers/hwmon/ibmpex.c line 564
Quoted 10 lines
drivers/hwmon/ibmpex.c new file +10
-0+list_for_each_entry_safe (p, next, &driver_data.bmc_data, list) +ibmpex_bmc_delete (p); +} + +MODULE_AUTHOR ("Darrick J. Wong <[email protected]>" ); +MODULE_DESCRIPTION ("IBM PowerExecutive power/temperature sensor driver" ); +MODULE_LICENSE ("GPL" ); + +module_init (ibmpex_init); +module_exit (ibmpex_exit);
Regards,
Signature · 8 lines
Mark M. Hoffman [email protected] _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH] v3 of IBM power meter driver
Quoted 7 lines · Mark M. Hoffman
Quoted 6 lines · Darrick J. Wong
drivers/hwmon/Kconfig +0
-0@@ -275,6 +275,18 @@ config SENSORS_CORETEMP sensor inside your CPU. Supported all are all known variants of Intel Core family.
Quoted 6 lines
drivers/hwmon/Kconfig config SENSORS_CORETEMP · line 280
Quoted 3 lines
drivers/hwmon/Kconfig +3
-0+config SENSORS_IBMPEX + tristate "IBM PowerExecutive temperature/power sensors" + depends on IPMI_SIOpen question: can we use "select" here? As written, it took some hunting to even get this driver to show up as an option in menuconfig.
My 2 cents: I assume that people who have IPMI-capable hardware are aware that they do. Thus, if you change the above to "select IPMI_SI", you probably want to add "depends on IPMI_HANDLER" (not sure why it's not just named CONFIG_IPMI).
--
Jean Delvare
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH] v3 of IBM power meter driver
In reply to Mark M. HoffmanQuoted 4 lines · Mark M. Hoffman
I am not an IPMI expert, so I would appreciate getting an Acked-by from someone who knows more about that subsystem.
Anyway, some comments are below. This is nowhere near a complete review yet.
Thank you for the review! Comments interspersed below, though for brevity the one-liners have been fixed.
Quoted 6 lines
drivers/hwmon/Kconfig config SENSORS_CORETEMP · line 280
Quoted 3 lines
drivers/hwmon/Kconfig +3
-0+config SENSORS_IBMPEX + tristate "IBM PowerExecutive temperature/power sensors" + depends on IPMI_SIOpen question: can we use "select" here? As written, it took some hunting to even get this driver to show up as an option in menuconfig.
Changed, since it seems reasonable that someone looking for PEx support might not necessarily know that it is based upon IPMI.
Quoted 10 lines
drivers/hwmon/ibmpex.c line 78
Quoted 3 lines
drivers/hwmon/ibmpex.c new file +3
-0+struct ibmpex_bmc_data { +struct list_head list; +struct class_device *class_dev;My current stack of patches includes one which requires that this be changed to 'struct device
*hwmon_dev', as 'structclass_device' is going away soon. You may rebase on my testing tree[1], or else I will just follow up with a patch to fix this up after I eventually merge yours.[1] http://lm-sensors.org/kernel?p=kernel/mhoffman/hwmon-2.6.git;a=shortlog;h=testing
Done.
Quoted 4 lines
Quoted 4 lines
drivers/hwmon/ibmpex.c new file +4
-0+static ssize_t ibmpex_show_sensor (struct device *dev, +struct device_attribute *devattr, +char *buf) +{
Quoted 8 lines
drivers/hwmon/ibmpex.c line 275
Quoted 5 lines
drivers/hwmon/ibmpex.c new file +5
-0+struct sensor_device_attribute *attr =to_sensor_dev_attr (devattr); +int iface =PEX_INTERFACE (attr->index); +int sensor =PEX_SENSOR (attr->index); +int func =PEX_FUNC (attr->index); +struct ibmpex_bmc_data *data =get_bmc_data (iface);... especially given how many times you're going to call it. Is there any reason you can't use the
driver_datafield of struct device *dev for that?
I can (and did) update the code to use dev_get/set_drvdata for the accessors. However, the "iface" field exists as a mechanism to map interface numbers to struct ibmpex_bmc_data/struct device data because the callback that IPMI uses to notify clients that BMCs are going away only passes the interface number, not the struct device itself. Unfortunately, this means that get_bmc_data() must remain, but now it is only used once at the end of life.
Quoted 4 lines
E.g. i2c based hwmon drivers do this at some point during the probe:
i2c_set_clientdata(new_client, data);
Quoted 8 lines
(which becomes)
dev_set_drvdata(&new_client->dev, data);If you could do that, then you no longer need 'iface' at all in the function above... *that* may allow you to use the
SENSOR_ATTR_2mechanism fromhwmon-sysfs.h- much easier to read than the manual number packing for 'sensor' and 'func'.
Doesn't look too hard; I'll have a go at it and see how it does.
Quoted 7 lines
drivers/hwmon/ibmpex.c line 354
Quoted 5 lines
drivers/hwmon/ibmpex.c new file +5
-0+ err =ibmpex_query_sensor_count (data); +if (err <0 ) +return -ENOENT ; + data->num_sensors = err; +Did you mean 'if (err <= 0)' ?
Yes.
Quoted 6 lines
drivers/hwmon/ibmpex.c line 386
Quoted 4 lines
drivers/hwmon/ibmpex.c new file +4
-0+/* Create attributes */ +for (j =0 ; j <PEX_NUM_SENSOR_FUNCS ; j++) +if (create_sensor (data, sensor_type, sensor_counter, + i, j))Why not 'err =
create_sensor(...)' and propagate the actual error here?
Rough draft syndrome? 'tis fixed. :)
--D
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
PATCH v2 1/1 hwmon: Update Documentation/hwmon/sysfs-interface
In reply to Mark M. HoffmanUpdate the hwmon sysfs interface documentation to include a specification for power meters.
---
Documentation/hwmon/sysfs-interface | 30 ++++++++++++++++++++++++++++++ 1 files changed, 30 insertions(+), 0 deletions(-)
Documentation/hwmon/sysfs-interface +30 -0
@@ -324,6 +324,36 @@ curr[1-*]_input Current input value Unit: milliampere RO +********* +* Power * +********* + +power[1-*]_average Average power use + Unit: microWatt + RO + +power[1-*]_average_highest Historical average maximum power use + Unit: microWatt + RO + +power[1-*]_average_lowest Historical average minimum power use + Unit: microWatt + RO + +power[1-*]_input Instantaneous power use + Unit: microWatt + RO + +power[1-*]_input_highest Historical maximum power use + Unit: microWatt + RO + +power[1-*]_input_lowest Historical minimum power use + Unit: microWatt + RO + +power[1-*]_high_low_reset Reset input_highest/input_lowest. + WO ********** * Alarms *
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v2] hwmon: Update Documentation/hwmon/sysfs-interface
Hi Darrick,
Quoted 2 lines · Darrick J. Wong
Update the hwmon sysfs interface documentation to include a specification for power meters.
Thanks for the update. I have some more comments. And sorry if it looks like nitpicking, but this is a standard interface we're defining so we better make sure that we get it right.
First of all, please think of a better subject line for this patch. "Update Documentation/hwmon/sysfs-interface" is too vague when your patch is rather specific.
Quoted 19 lines
Signed-off-by Darrick J. Wong <[email protected]>---
Documentation/hwmon/sysfs-interface | 30 ++++++++++++++++++++++++++++++ 1 files changed, 30 insertions(+), 0 deletions(-)Documentation/hwmon/sysfs-interface +5
-0@@ -324,6 +324,36 @@ curr[1-*]_input Current input value Unit: milliampere RO +********* +* Power * +********* + +power[1-*]_average Average power use
Documentation/hwmon/sysfs-interface curr[1-*]_input Current input value · line 341
Quoted 10 lines
Documentation/hwmon/sysfs-interface +10
-0+ Unit: microWatt + RO + +power[1-*]_average_highest Historical average maximum power use + Unit: microWatt + RO + +power[1-*]_average_lowest Historical average minimum power use + Unit: microWatt + RO
How useful are historical extremes of an average?
Quoted 5 lines
Documentation/hwmon/sysfs-interface +5
-0+ +power[1-*]_input Instantaneous power use + Unit: microWatt + RO +
Documentation/hwmon/sysfs-interface curr[1-*]_input Current input value · line 356
Quoted 10 lines
Documentation/hwmon/sysfs-interface +10
-0+power[1-*]_input_highest Historical maximum power use + Unit: microWatt + RO + +power[1-*]_input_lowest Historical minimum power use + Unit: microWatt + RO + +power[1-*]_high_low_reset Reset input_highest/input_lowest. + WO
I don't much like this name. It sounds like a name crafted for the specific feature of a given chip, while we try to use generic names for the standard interface. I would rather go for power[1-*]_reset_history if we have a single file for resetting all the extremes of a given channel, or power[1-*]_input_lowest_reset and power[1-*]_input_highest_reset if we go for a per-value reset.
Alternatively, we could simply make the power[1-*]_input_lowest and power[1-*]_input_highest files writable, and "cat power1_input > power1_input_lowest" (or any write?) would reset the history.
Documentation/hwmon/sysfs-interface curr[1-*]_input Current input value · line 359
Quoted 3 lines
Documentation/hwmon/sysfs-interface +0
-0********** * Alarms *
Thanks,
Signature · 1 line
Jean Delvare
Re: [PATCH v2] hwmon: Update Documentation/hwmon/sysfs-interface
Quoted 3 lines · Jean Delvare
Thanks for the update. I have some more comments. And sorry if it looks like nitpicking, but this is a standard interface we're defining so we better make sure that we get it right.
Agreed. :)
Quoted 4 lines
First of all, please think of a better subject line for this patch. "Update
Documentation/hwmon/sysfs-interface" is too vague when your patch is rather specific.
Will change to:
"Add power meter spec to Documentation/hwmon/sysfs-interface"
Quoted 5 lines
Documentation/hwmon/sysfs-interface curr[1-*]_input Current input value · line 341
Quoted 3 lines
Documentation/hwmon/sysfs-interface +3
-0+power[1-*]_average_lowest Historical average minimum power use + Unit: microWatt + ROHow useful are historical extremes of an average?
I don't know if anybody ever really requires this data, but the device I'm talking to records the extremes in hardware, so I put it in the driver.
Quoted 5 lines
Documentation/hwmon/sysfs-interface curr[1-*]_input Current input value · line 356
Quoted 2 lines
Documentation/hwmon/sysfs-interface +2
-0+power[1-*]_high_low_reset Reset input_highest/input_lowest. + WOI don't much like this name. It sounds like a name crafted for the specific feature of a given chip, while we try to use generic names for
Guilty as charged. Since ibmpex is the only on-board power meter hardware to which I have access, the interface proposal includes the various odd pieces that the hardware provides in addition to the meters. I could take the historical extreme and reset bits out of the proposal and put them in something like Documentation/hwmon/ibmpex.txt as extra chip-specific features if people prefer that.
Quoted 1 line
the standard interface. I would rather go for power[1-*]_reset_history
Me too.
Quoted 3 lines
if we have a single file for resetting all the extremes of a given channel, or power[1-*]_input_lowest_reset and power[1-*]_input_highest_reset if we go for a per-value reset.
The ibmpex hardware only knows how to reset all of them.
Quoted 3 lines
Alternatively, we could simply make the power[1-*]_input_lowest and power[1-*]_input_highest files writable, and "cat
power1_input>power1_input_lowest" (or any write?) would reset the history.
I'd prefer to leave it explicitly called out as a separate sysfs knob, unless there are established precedents for resetting a sensor by writing something to its sysfs file.
--D
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v2] hwmon: Update Documentation/hwmon/sysfs-interface
Hi Darrick,
Quoted 7 lines · Darrick J. Wong
Quoted 3 lines · Jean Delvare
First of all, please think of a better subject line for this patch. "Update
Documentation/hwmon/sysfs-interface" is too vague when your patch is rather specific.Will change to:
"Add power meter spec toDocumentation/hwmon/sysfs-interface"
Sounds good, thanks.
Quoted 8 lines
Quoted 5 lines
Documentation/hwmon/sysfs-interface curr[1-*]_input Current input value · line 341
Quoted 3 lines
Documentation/hwmon/sysfs-interface +3
-0+power[1-*]_average_lowest Historical average minimum power use + Unit: microWatt + ROHow useful are historical extremes of an average?
I don't know if anybody ever really requires this data, but the device I'm talking to records the extremes in hardware, so I put it in the driver.
OK, fine with me then.
Quoted 6 lines
Quoted 5 lines
Documentation/hwmon/sysfs-interface curr[1-*]_input Current input value · line 356
Quoted 2 lines
Documentation/hwmon/sysfs-interface +2
-0+power[1-*]_high_low_reset Reset input_highest/input_lowest. + WOI don't much like this name. It sounds like a name crafted for the specific feature of a given chip, while we try to use generic names for
Quoted 6 lines
Guilty as charged. Since ibmpex is the only on-board power meter hardware to which I have access, the interface proposal includes the various odd pieces that the hardware provides in addition to the meters. I could take the historical extreme and reset bits out of the proposal and put them in something like
Documentation/hwmon/ibmpex.txtas extra chip-specific features if people prefer that.
I'm fine having them in the spec as long as the interface is made generic enough.
Quoted 9 lines
Quoted 1 line
the standard interface. I would rather go for power[1-*]_reset_history
Me too.
Quoted 3 lines
if we have a single file for resetting all the extremes of a given channel, or power[1-*]_input_lowest_reset and power[1-*]_input_highest_reset if we go for a per-value reset.
The ibmpex hardware only knows how to reset all of them.
This doesn't mean we do not want separate files. The same problem exists for many other hardware monitoring features. For example most thermal sensor chips have one high temperature limit per temperature channel. However some of them have a single limit register for several channels! The approach we have taken so far was to have individual files, and it's up to the driver to keep them in sync.
Another example is alarm files. Some chips have a single alarm for out-of-range voltage measurements. Others have separate alarms for low voltage and high voltage limit crossing. In that case, we decided to have either a single file (in0_alarm) or separate files (in0_min_alarm and in0_max_alarm) depending on what the chip supports. Admittedly this is not very consistent with what we did for the shared temperature limits.
Quoted 7 lines
Quoted 3 lines
Alternatively, we could simply make the power[1-*]_input_lowest and power[1-*]_input_highest files writable, and "cat
power1_input>power1_input_lowest" (or any write?) would reset the history.I'd prefer to leave it explicitly called out as a separate sysfs knob, unless there are established precedents for resetting a sensor by writing something to its sysfs file.
No, there's no such established precedent. This was only a suggestion from me as it seems to make some sense. If you don't like the idea, just ignore it.
Signature · 1 line
Jean Delvare
PATCH v4 1/1 IBM power meter driver
In reply to Mark M. HoffmanHere's a fourth revision where I've tried to clean up the things that people complained about, as well as shifted the sysfs file names to match the spec that we've been drifting towards.
---ibm_pex: Driver to export IBM PowerExecutive power meter sensors.
---
drivers/hwmon/Kconfig | 13 + drivers/hwmon/Makefile | 1 drivers/hwmon/ibmpex.c | 608 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 622 insertions(+), 0 deletions(-)
drivers/hwmon/Kconfig +13 -0
@@ -315,6 +315,19 @@ config SENSORS_CORETEMP sensor inside your CPU. Supported all are all known variants of Intel Core family. +config SENSORS_IBMPEX + tristate "IBM PowerExecutive temperature/power sensors" + select IPMI_SI + depends on IPMI_HANDLER + help + If you say yes here you get support for the temperature and + power sensors in various IBM System X servers that support + PowerExecutive. So far this includes the x3550, x3650, x3655, + x3755, and certain HS20 blades. + + This driver can also be built as a module. If so, the module + will be called ibmpex. + config SENSORS_IT87 tristate "ITE IT87xx and compatibles" select HWMON_VID
drivers/hwmon/Makefile +1 -0
@@ -38,6 +38,7 @@ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o +obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IPMI) += ipmisensors.o obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
drivers/hwmon/ibmpex.c new file +608 -0
608 lines not on this page · raw message
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v4] IBM power meter driver
Hi Darrick:
Quoted 3 lines · Darrick J. Wong
Here's a fourth revision where I've tried to clean up the things that people complained about, as well as shifted the sysfs file names to match the spec that we've been drifting towards.
Sorry it took me so long to get back to this. I've applied this to my hwmon testing branch, but I would still like to get a review from an IPMI expert.
OBTW: please try to send patches which apply cleanly to some tree to which I have access. E.g. from the Makefile - preceding and trailing context are not present in any git tree that I know.
Quoted 647 lines
---
ibm_pex: Driver to export IBM PowerExecutive power meter sensors.Signed-off-by Darrick J. Wong <[email protected]>---
drivers/hwmon/Kconfig | 13 + drivers/hwmon/Makefile | 1 drivers/hwmon/ibmpex.c | 608 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 622 insertions(+), 0 deletions(-)drivers/hwmon/Kconfig +13
-0@@ -315,6 +315,19 @@ config SENSORS_CORETEMP sensor inside your CPU. Supported all are all known variants of Intel Core family. +config SENSORS_IBMPEX + tristate "IBM PowerExecutive temperature/power sensors" + select IPMI_SI + depends on IPMI_HANDLER + help + If you say yes here you get support for the temperature and + power sensors in various IBM System X servers that support + PowerExecutive. So far this includes the x3550, x3650, x3655, + x3755, and certain HS20 blades. + + This driver can also be built as a module. If so, the module + will be called ibmpex. + config SENSORS_IT87 tristate "ITE IT87xx and compatibles" select HWMON_VIDdrivers/hwmon/Makefile +1
-0@@ -38,6 +38,7 @@ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o +obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IPMI) += ipmisensors.o obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.odrivers/hwmon/ibmpex.c new file +594
-0@@ -0,0 +1,608 @@ +/* +* A hwmon driver for the IBM PowerExecutive temperature/power sensors +* Copyright (C) 2007 IBM +* +* Author: Darrick J. Wong <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program 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 program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/ipmi.h> +#include <linux/module.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/jiffies.h> +#include <linux/mutex.h> + +#define REFRESH_INTERVAL (2 * HZ) +#define DRVNAME "ibmpex" + +#define PEX_GET_VERSION 1 +#define PEX_GET_SENSOR_COUNT 2 +#define PEX_GET_SENSOR_NAME 3 +#define PEX_RESET_HIGH_LOW 4 +#define PEX_GET_SENSOR_DATA 6 + +#define PEX_NET_FUNCTION 0x3A +#define PEX_COMMAND 0x3C + +static inline u16 extract_value (const char *data,int offset) +{ +return be16_to_cpup ((u16 *)&data[offset]); +} + +#define TEMP_SENSOR 1 +#define POWER_SENSOR 2 + +#define PEX_SENSOR_TYPE_LEN 3 +static u8 const power_sensor_sig[] = {0x70 ,0x77 ,0x72 }; +static u8 const temp_sensor_sig[] = {0x74 ,0x65 ,0x6D }; + +#define PEX_MULT_LEN 2 +static u8 const watt_sensor_sig[] = {0x41 ,0x43 }; + +#define PEX_NUM_SENSOR_FUNCS 3 +static char const *const power_sensor_name_templates[] = { +"%s%d_average" , +"%s%d_average_lowest" , +"%s%d_average_highest" +}; +static char const *const temp_sensor_name_templates[] = { +"%s%d_input" , +"%s%d_input_lowest" , +"%s%d_input_highest" +}; + +static void ibmpex_msg_handler (struct ipmi_recv_msg *msg,void *user_msg_data); +static void ibmpex_register_bmc (int iface,struct device *dev); +static void ibmpex_bmc_gone (int iface); + +struct ibmpex_sensor_data { +int in_use; +s16 values[PEX_NUM_SENSOR_FUNCS ]; +int multiplier; + +struct sensor_device_attribute_2 attr[PEX_NUM_SENSOR_FUNCS ]; +}; + +struct ibmpex_bmc_data { +struct list_head list; +struct device *hwmon_dev; +struct device *bmc_device; +struct mutex lock; +char valid; +unsigned long last_updated;/* In jiffies */ + +struct ipmi_addr address; +struct completion read_complete; +ipmi_user_t user; +int interface; + +struct kernel_ipmi_msg tx_message; +unsigned char tx_msg_data[IPMI_MAX_MSG_LENGTH ]; +long tx_msgid; + +unsigned char rx_msg_data[IPMI_MAX_MSG_LENGTH ]; +unsigned long rx_msg_len; +unsigned char rx_result; +int rx_recv_type; + +unsigned char sensor_major; +unsigned char sensor_minor; + +unsigned char num_sensors; +struct ibmpex_sensor_data *sensors; +}; + +struct ibmpex_driver_data { +struct list_head bmc_data; +struct ipmi_smi_watcher bmc_events; +struct ipmi_user_hndl ipmi_hndlrs; +}; + +static struct ibmpex_driver_data driver_data = { + .bmc_data =LIST_HEAD_INIT (driver_data.bmc_data), + .bmc_events = { + .owner =THIS_MODULE , + .new_smi = ibmpex_register_bmc, + .smi_gone = ibmpex_bmc_gone, + }, + .ipmi_hndlrs = { + .ipmi_recv_hndl = ibmpex_msg_handler, + }, +}; + +static int ibmpex_send_message (struct ibmpex_bmc_data *data) +{ +int err; + + err =ipmi_validate_addr (&data->address,sizeof (data->address)); +if (err) + goto out; + + data->tx_msgid++; + err =ipmi_request_settime (data->user, &data->address, data->tx_msgid, + &data->tx_message, data,0 ,0 ,0 ); +if (err) + goto out1; + +return 0 ; +out1: +printk (KERN_ERR "%s: request_settime=%x\n" , __FUNCTION__, err); +return err; +out: +printk (KERN_ERR "%s: validate_addr=%x\n" , __FUNCTION__, err); +return err; +} + +static int ibmpex_ver_check (struct ibmpex_bmc_data *data) +{ + data->tx_msg_data[0 ] =PEX_GET_VERSION ; + data->tx_message.data_len =1 ; +ibmpex_send_message (data); + +wait_for_completion (&data->read_complete); + +if (data->rx_result || data->rx_msg_len !=6 ) +return -ENOENT ; + + data->sensor_major = data->rx_msg_data[0 ]; + data->sensor_minor = data->rx_msg_data[1 ]; + + printk(KERN_INFO DRVNAME ": Found BMC with sensor interface " +"v%d.%d %d-%02d-%02d on interface %d\n" , + data->sensor_major, + data->sensor_minor, +extract_value (data->rx_msg_data,2 ), + data->rx_msg_data[4 ], + data->rx_msg_data[5 ], + data->interface); + +return 0 ; +} + +static int ibmpex_query_sensor_count (struct ibmpex_bmc_data *data) +{ + data->tx_msg_data[0 ] =PEX_GET_SENSOR_COUNT ; + data->tx_message.data_len =1 ; +ibmpex_send_message (data); + +wait_for_completion (&data->read_complete); + +if (data->rx_result || data->rx_msg_len !=1 ) +return -ENOENT ; + +return data->rx_msg_data[0 ]; +} + +static int ibmpex_query_sensor_name (struct ibmpex_bmc_data *data,int sensor) +{ + data->tx_msg_data[0 ] =PEX_GET_SENSOR_NAME ; + data->tx_msg_data[1 ] = sensor; + data->tx_message.data_len =2 ; +ibmpex_send_message (data); + +wait_for_completion (&data->read_complete); + +if (data->rx_result || data->rx_msg_len <1 ) +return -ENOENT ; + +return 0 ; +} + +static int ibmpex_query_sensor_data (struct ibmpex_bmc_data *data,int sensor) +{ + data->tx_msg_data[0 ] =PEX_GET_SENSOR_DATA ; + data->tx_msg_data[1 ] = sensor; + data->tx_message.data_len =2 ; +ibmpex_send_message (data); + +wait_for_completion (&data->read_complete); + +if (data->rx_result || data->rx_msg_len <26 ) { +printk (KERN_ERR "Error reading sensor %d, please check.\n" , + sensor); +return -ENOENT ; + } + +return 0 ; +} + +static int ibmpex_reset_high_low_data (struct ibmpex_bmc_data *data) +{ + data->tx_msg_data[0 ] =PEX_RESET_HIGH_LOW ; + data->tx_message.data_len =1 ; +ibmpex_send_message (data); + +wait_for_completion (&data->read_complete); + +return 0 ; +} + +static void ibmpex_update_device (struct ibmpex_bmc_data *data) +{ +int i, err; + +mutex_lock (&data->lock); +if (time_before (jiffies, data->last_updated +REFRESH_INTERVAL ) && + data->valid) + goto out; + +for (i =0 ; i < data->num_sensors; i++) { +if (!data->sensors[i].in_use) +continue ; + err =ibmpex_query_sensor_data (data, i); +if (err) +continue ; + data->sensors[i].values[0 ] > +extract_value (data->rx_msg_data,16 ); + data->sensors[i].values[1 ] > +extract_value (data->rx_msg_data,18 ); + data->sensors[i].values[2 ] > +extract_value (data->rx_msg_data,20 ); + } + + data->last_updated = jiffies; + data->valid =1 ; + +out: +mutex_unlock (&data->lock); +} + +static struct ibmpex_bmc_data *get_bmc_data (int iface) +{ +struct ibmpex_bmc_data *p, *next; + +list_for_each_entry_safe (p, next, &driver_data.bmc_data, list) +if (p->interface = iface) +return p; + +return NULL ; +} + +static ssize_t show_name (struct device *dev,struct device_attribute *devattr, +char *buf) +{ +return sprintf (buf,"%s\n" ,DRVNAME ); +} +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); + +static ssize_t ibmpex_show_sensor (struct device *dev, +struct device_attribute *devattr, +char *buf) +{ +struct sensor_device_attribute_2 *attr =to_sensor_dev_attr_2 (devattr); +struct ibmpex_bmc_data *data =dev_get_drvdata (dev); +int mult = data->sensors[attr->index].multiplier; +ibmpex_update_device (data); + +return sprintf (buf,"%d\n" , + data->sensors[attr->index].values[attr->nr] * mult); +} + +static ssize_t ibmpex_reset_high_low (struct device *dev, +struct device_attribute *devattr, +const char *buf, +size_t count) +{ +struct ibmpex_bmc_data *data =dev_get_drvdata (dev); + +ibmpex_reset_high_low_data (data); + +return count; +} + +static SENSOR_DEVICE_ATTR(reset_high_low, S_IWUSR, NULL, + ibmpex_reset_high_low, 0); + +static int is_power_sensor (const char *sensor_id,int len) +{ +if (len <PEX_SENSOR_TYPE_LEN ) +return 0 ; + +if (!memcmp (sensor_id, power_sensor_sig,PEX_SENSOR_TYPE_LEN )) +return 1 ; +return 0 ; +} + +static int is_temp_sensor (const char *sensor_id,int len) +{ +if (len <PEX_SENSOR_TYPE_LEN ) +return 0 ; + +if (!memcmp (sensor_id, temp_sensor_sig,PEX_SENSOR_TYPE_LEN )) +return 1 ; +return 0 ; +} + +static int power_sensor_multiplier (const char *sensor_id,int len) +{ +int i; + +for (i =PEX_SENSOR_TYPE_LEN ; i < len -1 ; i++) +if (!memcmp (&sensor_id[i], watt_sensor_sig,PEX_MULT_LEN )) +return 1000000 ; + +return 100000 ; +} + +static int create_sensor (struct ibmpex_bmc_data *data,int type, +int counter,int sensor,int func) +{ +int err; +char *n; + + n =kmalloc (32 ,GFP_KERNEL ); +if (!n) +return -ENOMEM ; + +if (type =TEMP_SENSOR ) +sprintf (n, temp_sensor_name_templates[func],"temp" , counter); +else if (type =POWER_SENSOR ) +sprintf (n, power_sensor_name_templates[func],"power" , counter); + + data->sensors[sensor].attr[func].dev_attr.attr.name = n; + data->sensors[sensor].attr[func].dev_attr.attr.mode =S_IRUGO ; + data->sensors[sensor].attr[func].dev_attr.show = ibmpex_show_sensor; + data->sensors[sensor].attr[func].index = sensor; + data->sensors[sensor].attr[func].nr = func; + + err =device_create_file (data->bmc_device, + &data->sensors[sensor].attr[func].dev_attr); +if (err) { + data->sensors[sensor].attr[func].dev_attr.attr.name =NULL ; +kfree (n); +return err; + } + +return 0 ; +} + +static int ibmpex_find_sensors (struct ibmpex_bmc_data *data) +{ +int i, j, err; +int sensor_type; +int sensor_counter; +int num_power =0 ; +int num_temp =0 ; + + err =ibmpex_query_sensor_count (data); +if (err <=0 ) +return -ENOENT ; + data->num_sensors = err; + + data->sensors =kzalloc (data->num_sensors *sizeof (*data->sensors), +GFP_KERNEL ); +if (!data->sensors) +return -ENOMEM ; + +for (i =0 ; i < data->num_sensors; i++) { + err =ibmpex_query_sensor_name (data, i); +if (err) +continue ; + +if (is_power_sensor (data->rx_msg_data, data->rx_msg_len)) { + sensor_type =POWER_SENSOR ; + num_power++; + sensor_counter = num_power; + data->sensors[i].multiplier > +power_sensor_multiplier (data->rx_msg_data, + data->rx_msg_len); + }else if (is_temp_sensor (data->rx_msg_data, + data->rx_msg_len)) { + sensor_type =TEMP_SENSOR ; + num_temp++; + sensor_counter = num_temp; + data->sensors[i].multiplier =1 ; + }else +continue ; + + data->sensors[i].in_use =1 ; + +/* Create attributes */ +for (j =0 ; j <PEX_NUM_SENSOR_FUNCS ; j++) { + err =create_sensor (data, sensor_type, sensor_counter, + i, j); +if (err) + goto exit_remove; + } + } + + err =device_create_file (data->bmc_device, + &sensor_dev_attr_reset_high_low.dev_attr); +if (err) + goto exit_remove; + + err =device_create_file (data->bmc_device, + &sensor_dev_attr_name.dev_attr); +if (err) + goto exit_remove; + +return 0 ; + +exit_remove: +device_remove_file (data->bmc_device, + &sensor_dev_attr_reset_high_low.dev_attr); +device_remove_file (data->bmc_device, &sensor_dev_attr_name.dev_attr); +for (i =0 ; i < data->num_sensors; i++) +for (j =0 ; j <PEX_NUM_SENSOR_FUNCS ; j++) { +if (!data->sensors[i].attr[j].dev_attr.attr.name) +continue ; +device_remove_file (data->bmc_device, + &data->sensors[i].attr[j].dev_attr); +kfree (data->sensors[i].attr[j].dev_attr.attr.name); + } + +kfree (data->sensors); +return err; +} + +static void ibmpex_register_bmc (int iface,struct device *dev) +{ +struct ibmpex_bmc_data *data; +int err; + + data =kzalloc (sizeof (*data),GFP_KERNEL ); +if (!data) { + printk(KERN_ERR DRVNAME ": Insufficient memory for BMC " + "interface %d.\n", data->interface); +return ; + } + + data->address.addr_type =IPMI_SYSTEM_INTERFACE_ADDR_TYPE ; + data->address.channel =IPMI_BMC_CHANNEL ; + data->address.data[0 ] =0 ; + data->interface = iface; + data->bmc_device = dev; + +/* Create IPMI messaging interface user */ + err =ipmi_create_user (data->interface, &driver_data.ipmi_hndlrs, + data, &data->user); +if (err <0 ) { + printk(KERN_ERR DRVNAME ": Error, unable to register user with " +"ipmi interface %d\n" , + data->interface); + goto out; + } + +mutex_init (&data->lock); + +/* Initialize message */ + data->tx_msgid =0 ; +init_completion (&data->read_complete); + data->tx_message.netfn =PEX_NET_FUNCTION ; + data->tx_message.cmd =PEX_COMMAND ; + data->tx_message.data = data->tx_msg_data; + +/* Does this BMC support PowerExecutive? */ + err =ibmpex_ver_check (data); +if (err) + goto out_user; + +/* Register the BMC as a HWMON class device */ + data->hwmon_dev =hwmon_device_register (data->bmc_device); + +if (IS_ERR (data->hwmon_dev)) { + printk(KERN_ERR DRVNAME ": Error, unable to register hwmon " +"class device for interface %d\n" , + data->interface); +kfree (data); +return ; + } + +/* finally add the new bmc data to the bmc data list */ +dev_set_drvdata (dev, data); +list_add_tail (&data->list, &driver_data.bmc_data); + +/* Now go find all the sensors */ + err =ibmpex_find_sensors (data); +if (err) { +printk (KERN_ERR "Error %d allocating memory\n" , err); + goto out_register; + } + +return ; + +out_register: +hwmon_device_unregister (data->hwmon_dev); +out_user: +ipmi_destroy_user (data->user); +out: +kfree (data); +} + +static void ibmpex_bmc_delete (struct ibmpex_bmc_data *data) +{ +int i, j; + +device_remove_file (data->bmc_device, + &sensor_dev_attr_reset_high_low.dev_attr); +device_remove_file (data->bmc_device, &sensor_dev_attr_name.dev_attr); +for (i =0 ; i < data->num_sensors; i++) +for (j =0 ; j <PEX_NUM_SENSOR_FUNCS ; j++) { +if (!data->sensors[i].attr[j].dev_attr.attr.name) +continue ; +device_remove_file (data->bmc_device, + &data->sensors[i].attr[j].dev_attr); +kfree (data->sensors[i].attr[j].dev_attr.attr.name); + } + +list_del (&data->list); +dev_set_drvdata (data->bmc_device,NULL ); +hwmon_device_unregister (data->hwmon_dev); +ipmi_destroy_user (data->user); +kfree (data->sensors); +kfree (data); +} + +static void ibmpex_bmc_gone (int iface) +{ +struct ibmpex_bmc_data *data =get_bmc_data (iface); + +if (!data) +return ; + +ibmpex_bmc_delete (data); +} + +static void ibmpex_msg_handler (struct ipmi_recv_msg *msg,void *user_msg_data) +{ +struct ibmpex_bmc_data *data = (struct ibmpex_bmc_data *)user_msg_data; + +if (msg->msgid != data->tx_msgid) { +printk (KERN_ERR "Received msgid (%02x) and transmitted " +"msgid (%02x) mismatch!\n" , + (int )msg->msgid, + (int )data->tx_msgid); +ipmi_free_recv_msg (msg); +return ; + } + + data->rx_recv_type = msg->recv_type; +if (msg->msg.data_len >0 ) + data->rx_result = msg->msg.data[0 ]; +else + data->rx_result =IPMI_UNKNOWN_ERR_COMPLETION_CODE ; + +if (msg->msg.data_len >1 ) { + data->rx_msg_len = msg->msg.data_len -1 ; +memcpy (data->rx_msg_data, msg->msg.data +1 , data->rx_msg_len); + }else + data->rx_msg_len =0 ; + +ipmi_free_recv_msg (msg); +complete (&data->read_complete); +} + +static int __init ibmpex_init (void ) +{ +return ipmi_smi_watcher_register (&driver_data.bmc_events); +} + +static void __exit ibmpex_exit(void) +{ +struct ibmpex_bmc_data *p, *next; + +ipmi_smi_watcher_unregister (&driver_data.bmc_events);
drivers/hwmon/ibmpex.c line 604
Quoted 10 lines
drivers/hwmon/ibmpex.c new file +10
-0+list_for_each_entry_safe (p, next, &driver_data.bmc_data, list) +ibmpex_bmc_delete (p); +} + +MODULE_AUTHOR ("Darrick J. Wong <[email protected]>" ); +MODULE_DESCRIPTION ("IBM PowerExecutive power/temperature sensor driver" ); +MODULE_LICENSE ("GPL" ); + +module_init (ibmpex_init); +module_exit (ibmpex_exit);
Regards,
Signature · 8 lines
Mark M. Hoffman [email protected] _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v4] IBM power meter driver
Quoted 43 lines · Mark M. Hoffman
Quoted 43 lines
drivers/hwmon/ibmpex.c new file +43
-0+static void ibmpex_register_bmc (int iface,struct device *dev) +{ +struct ibmpex_bmc_data *data; +int err; + + data =kzalloc (sizeof (*data),GFP_KERNEL ); +if (!data) { + printk(KERN_ERR DRVNAME ": Insufficient memory for BMC " + "interface %d.\n", data->interface); +return ; + } + + data->address.addr_type =IPMI_SYSTEM_INTERFACE_ADDR_TYPE ; + data->address.channel =IPMI_BMC_CHANNEL ; + data->address.data[0 ] =0 ; + data->interface = iface; + data->bmc_device = dev; + +/* Create IPMI messaging interface user */ + err =ipmi_create_user (data->interface, &driver_data.ipmi_hndlrs, + data, &data->user); +if (err <0 ) { + printk(KERN_ERR DRVNAME ": Error, unable to register user with " +"ipmi interface %d\n" , + data->interface); + goto out; + } + +mutex_init (&data->lock); + +/* Initialize message */ + data->tx_msgid =0 ; +init_completion (&data->read_complete); + data->tx_message.netfn =PEX_NET_FUNCTION ; + data->tx_message.cmd =PEX_COMMAND ; + data->tx_message.data = data->tx_msg_data; + +/* Does this BMC support PowerExecutive? */ + err =ibmpex_ver_check (data); +if (err) + goto out_user; + +/* Register the BMC as a HWMON class device */
Quoted 8 lines
drivers/hwmon/ibmpex.c line 502
Quoted 8 lines
drivers/hwmon/ibmpex.c new file +8
-0+ data->hwmon_dev =hwmon_device_register (data->bmc_device); + +if (IS_ERR (data->hwmon_dev)) { + printk(KERN_ERR DRVNAME ": Error, unable to register hwmon " +"class device for interface %d\n" , + data->interface); +kfree (data); +return ;
don't you want to goto out_user here instead?
Quoted 14 lines
Quoted 14 lines
drivers/hwmon/ibmpex.c new file +14
-0+ } + +/* finally add the new bmc data to the bmc data list */ +dev_set_drvdata (dev, data); +list_add_tail (&data->list, &driver_data.bmc_data); + +/* Now go find all the sensors */ + err =ibmpex_find_sensors (data); +if (err) { +printk (KERN_ERR "Error %d allocating memory\n" , err); + goto out_register; + } + +return ;
Quoted 8 lines
drivers/hwmon/ibmpex.c line 524
Quoted 8 lines
drivers/hwmon/ibmpex.c new file +8
-0+ +out_register: +hwmon_device_unregister (data->hwmon_dev); +out_user: +ipmi_destroy_user (data->user); +out: +kfree (data); +}
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v4] IBM power meter driver
Quoted 8 lines · Roel Kluin
Quoted 6 lines
drivers/hwmon/ibmpex.c line 502
Quoted 6 lines
drivers/hwmon/ibmpex.c new file +6
-0+if (IS_ERR (data->hwmon_dev)) { + printk(KERN_ERR DRVNAME ": Error, unable to register hwmon " +"class device for interface %d\n" , + data->interface); +kfree (data); +return ;don't you want to goto
out_userhere instead?
Err, yes, thank you for catching that.
--D
PATCH 1/1 ibmpex: Release IPMI user if hwmon registration fails
In reply to Roel KluinRoel Kluin <[email protected]> found a minor defect in the init code if hwmon device registration fails.
---
drivers/hwmon/ibmpex.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)
drivers/hwmon/ibmpex.c +1 -2
@@ -498,8 +498,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev) printk(KERN_ERR DRVNAME ": Error, unable to register hwmon ""class device for interface %d\n" , data->interface); -kfree (data); -return ; + goto out_user; }/* finally add the new bmc data to the bmc data list */
Re: [PATCH] ibmpex: Release IPMI user if hwmon registration fails
Hi:
Quoted 14 lines · Darrick J. Wong
Roel Kluin <[email protected]> found a minor defect in the init code if hwmon device registration fails.
Signed-off-by Darrick J. Wong <[email protected]>---
drivers/hwmon/ibmpex.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)drivers/hwmon/ibmpex.c +0
-0
drivers/hwmon/ibmpex.c static void ibmpex_register_bmc(int iface, struct device *dev) · line 504
Quoted 9 lines
drivers/hwmon/ibmpex.c +1
-2@@ -498,8 +498,7 @@ static void ibmpex_register_bmc(int iface, struct device *dev) printk(KERN_ERR DRVNAME ": Error, unable to register hwmon ""class device for interface %d\n" , data->interface); -kfree (data); -return ; + goto out_user; }/* finally add the new bmc data to the bmc data list */
Applied to hwmon-2.6.git/testing, thanks.
Signature · 8 lines
Mark M. Hoffman [email protected] _______________________________________________ lm-sensors mailing list [email protected] http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Re: [PATCH v4] IBM power meter driver
In reply to Mark M. HoffmanQuoted 2 lines · Mark M. Hoffman
Sorry it took me so long to get back to this. I've applied this to my hwmon testing branch, but I would still like to get a review from an IPMI expert.
I'm working on finding somebody to do that.
Quoted 3 lines
OBTW: please try to send patches which apply cleanly to some tree to which I have access. E.g. from the
Makefile- preceding and trailing context are not present in any git tree that I know.
Oops, sorry about that.
The i5k_amb driver referenced in the Makefile diff is the same one that I posted to lm-sensors a few weeks ago, though there hasn't been much discussion after it was pointed out that someone had already written a driver to achieve the same purpose. Unfortunately, nothing's happened to either driver; any thoughts? I'm thinking that we ought to get one of them into shape for upstream, though I don't particularly care which one it is...
--D
_______________________________________________
lm-sensors mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors