All of lore.kernel.org
 help / color / mirror / Atom feed
From: Guenter Roeck <linux@roeck-us.net>
To: Neelesh Gupta
	<neelegup-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
	jdelvare-l3A5Bk7waGM@public.gmane.org,
	lm-sensors-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org
Cc: benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org,
	svaidy-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org,
	sbhat-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org,
	"devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org"
	<devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Subject: Re: [lm-sensors] [PATCH v4] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperatur
Date: Sat, 05 Jul 2014 02:25:36 +0000	[thread overview]
Message-ID: <53B76220.9090900@roeck-us.net> (raw)
In-Reply-To: <20140704105343.22437.52125.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>

T24gMDcvMDQvMjAxNCAwNDowMiBBTSwgTmVlbGVzaCBHdXB0YSB3cm90ZToKPiBUaGlzIHBhdGNo
IGFkZHMgYmFzaWMga2VybmVsIHN1cHBvcnQgZm9yIHJlYWRpbmcgcG93ZXIgdmFsdWVzLCBmYW4K
PiBzcGVlZCBycG0sIHZvbHRhZ2UgYW5kIHRlbXBlcmF0dXJlIGRhdGEgb24gcG93ZXJudiBwbGF0
Zm9ybXMgd2hpY2ggd2lsbAo+IGJlIGV4cG9ydGVkIHRvIHVzZXIgc3BhY2UgdGhyb3VnaCBzeXNm
cyBpbnRlcmZhY2UuCj4KCkhpIE5lZWxlc2gsCgpDb3B5aW5nIGRldmljZXRyZWUgbWFpbGluZyBs
aXN0LiBQbGVhc2UgY29weSBpdCBvbiB0aGUgbmV4dCAoaG9wZWZ1bGx5IGZpbmFsKQpyZXZpc2lv
bjsgZGV2aWNldHJlZSBtYWludGFpbmVycyBhdCBsZWFzdCBuZWVkIGEgY2hhbmNlIHRvIGNvbW1l
bnQuClsgWWVzLCBJIHVuZGVyc3RhbmQgdGhpcyBpcyBhIHNoaXBwaW5nIHByb2R1Y3QsIGJ1dCBz
dGlsbCAuLi4gXQoKSSBhbSBvayB3aXRoIHRoZSBjb2RlIGV4Y2VwdCBmb3IgYSBjb3VwbGUgb2Yg
bWlub3Igbml0cGlja3MgKHNlZSBiZWxvdykuCgpUaGFua3MsCkd1ZW50ZXIKCj4gVGVzdCByZXN1
bHRzOgo+IC0tLS0tLS0tLS0tLS0KPiBbcm9vdEB0dWwxNjNwMSB+XSMgc2Vuc29ycwo+IGlibXBv
d2VybnYtaXNhLTAwMDAKPiBBZGFwdGVyOiBJU0EgYWRhcHRlcgo+IGZhbjE6ICAgICAgICA1NTY3
IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjI6ICAgICAgICA1MjMyIFJQTSAgKG1pbiA9ICAg
IDAgUlBNKQo+IGZhbjM6ICAgICAgICA1NTMyIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjQ6
ICAgICAgICA0OTQ1IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjU6ICAgICAgICAgICAwIFJQ
TSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjY6ICAgICAgICAgICAwIFJQTSAgKG1pbiA9ICAgIDAg
UlBNKQo+IGZhbjc6ICAgICAgICA3MzkyIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjg6ICAg
ICAgICA3OTM2IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IHRlbXAxOiAgICAgICAgKzM5LjDCsEMg
IChoaWdoID0gICswLjDCsEMpCj4gcG93ZXIxOiAgICAgIDE5MS4wMCBXCj4KPiBbcm9vdEB0dWwx
NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtLwo+IGFsYXJtdGltZXIgIGlibXBvd2Vy
bnYuMCAgcG93ZXIgIHJ0Yy1nZW5lcmljICBzZXJpYWw4MjUwICB1ZXZlbnQKPiBbcm9vdEB0dWwx
NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtL2libXBvd2VybnYuMC9od21vbi9od21v
bjAvCj4gZGV2aWNlCSAgICBmYW4yX21pbglmYW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAg
IHBvd2VyCj4gZmFuMV9mYXVsdCAgZmFuM19mYXVsdAlmYW41X2ZhdWx0ICBmYW43X2ZhdWx0CWlu
MV9mYXVsdCAgcG93ZXIxX2lucHV0Cj4gZmFuMV9pbnB1dCAgZmFuM19pbnB1dAlmYW41X2lucHV0
ICBmYW43X2lucHV0CWluMl9mYXVsdCAgc3Vic3lzdGVtCj4gZmFuMV9taW4gICAgZmFuM19taW4J
ZmFuNV9taW4gICAgZmFuN19taW4JaW4zX2ZhdWx0ICB0ZW1wMV9pbnB1dAo+IGZhbjJfZmF1bHQg
IGZhbjRfZmF1bHQJZmFuNl9mYXVsdCAgZmFuOF9mYXVsdAlpbjRfZmF1bHQgIHRlbXAxX21heAo+
IGZhbjJfaW5wdXQgIGZhbjRfaW5wdXQJZmFuNl9pbnB1dCAgZmFuOF9pbnB1dAluYW1lCSAgIHVl
dmVudAo+IFtyb290QHR1bDE2M3AxIH5dIwo+IFtyb290QHR1bDE2M3AxIH5dIyBscyAvc3lzL2Ns
YXNzL2h3bW9uL2h3bW9uMC8KPiBkZXZpY2UJICAgIGZhbjJfbWluCWZhbjRfbWluICAgIGZhbjZf
bWluCWZhbjhfbWluICAgcG93ZXIKPiBmYW4xX2ZhdWx0ICBmYW4zX2ZhdWx0CWZhbjVfZmF1bHQg
IGZhbjdfZmF1bHQJaW4xX2ZhdWx0ICBwb3dlcjFfaW5wdXQKPiBmYW4xX2lucHV0ICBmYW4zX2lu
cHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5wdXQJaW4yX2ZhdWx0ICBzdWJzeXN0ZW0KPiBmYW4xX21p
biAgICBmYW4zX21pbglmYW41X21pbiAgICBmYW43X21pbglpbjNfZmF1bHQgIHRlbXAxX2lucHV0
Cj4gZmFuMl9mYXVsdCAgZmFuNF9mYXVsdAlmYW42X2ZhdWx0ICBmYW44X2ZhdWx0CWluNF9mYXVs
dCAgdGVtcDFfbWF4Cj4gZmFuMl9pbnB1dCAgZmFuNF9pbnB1dAlmYW42X2lucHV0ICBmYW44X2lu
cHV0CW5hbWUJICAgdWV2ZW50Cj4gW3Jvb3RAdHVsMTYzcDEgfl0jCj4KPiBTaWduZWQtb2ZmLWJ5
OiBOZWVsZXNoIEd1cHRhIDxuZWVsZWd1cEBsaW51eC52bmV0LmlibS5jb20+Cj4gLS0tCj4KPiBD
aGFuZ2VzIGluIHY0Cj4gPT09PT09PT09PT09PQo+IC0gUmVwbGFjZWQgcHJfZXJyKCkgd2l0aCBk
ZXZfZXJyKCkgZm9yIGxvZ2dpbiBwcmludCBtZXNzYWdlcy4KPiAtIFVzaW5nIGtzdHJ0b3UzMigp
IGZ1bmN0aW9uIGZvciBjb252ZXJ0aW5nIHN0cmluZyB0byB1MzIgaW5zdGVhZCBvZiBzc2NhbmYo
KS4KPgo+IENoYW5nZXMgaW4gdjMKPiA9PT09PT09PT09PT09Cj4gLSBGaXhlZCBhbiBlbmRpYW5u
ZXNzIGJ1ZyBsZWFkaW5nIHRoZSBkcml2ZXIgdG8gYnJlYWsgb24gTEUuCj4gLSBGaXhlZCBhIGJ1
ZyB0aGF0IHdoZW4gb25lIG9mIHRoZSAnYXR0cmlidXRlX2dyb3VwJyBub3QgcG9wdWxhdGVkLCBm
b2xsb3dpbmcKPiAgICBncm91cHMgYXR0cmlidXRlcyB3ZXJlIGRyb3BwZWQuCj4gLSBSZXdyaXRl
IHRoZSBnZXRfc2Vuc29yX2luZGV4X2F0dHIoKSBmdW5jdGlvbiB0byBoYW5kbGUgYWxsIHRoZSBl
cnJvciBzY2VuYXJpb3MKPiAgICBsaWtlICdzc2NhbmYnIGV0Yy4KPiAtIEZpeGVkIGFsbCB0aGUg
ZXJyb3JzL3dhcm5pbmdzIHJlbGF0ZWQgdG8gY29kaW5nIHN0eWxlL3doaXRlc3BhY2UuCj4gLSBB
ZGRlZCAnRG9jdW1lbnRhdGlvbicgZmlsZXMuCj4gLSBBZGRyZXNzZWQgcmVtYWluaW5nIHJldmll
dyBjb21tZW50cyBvbiBWMi4KPgo+IENoYW5nZXMgaW4gdjIKPiA9PT09PT09PT09PT09Cj4gLSBH
ZW5lcmljIHVzZSBvZiBkZXZtXyogZnVuY3Rpb25zIGluIGh3bW9uIGxpa2UgdXNpbmcgZGV2bV9r
emFsbG9jKCkgZm9yIGR5bmFtaWMKPiAgICBtZW1vcnkgcmVxdWVzdCwgYXZvaWRpbmcgdGhlIG5l
ZWQgdG8gZXhwbGljaXQgZnJlZSBvZiBtZW1vcnkuCj4gICAgQWRkaW5nICdzdHJ1Y3QgYXR0cmli
dXRlX2dyb3VwJyBhcyBtZW1iZXIgb2YgcGxhdGZvcm0gZGF0YSBzdHJ1Y3R1cmUgdG8gYmUKPiAg
ICBwb3B1bGF0ZWQgYW5kIHRoZW4gcGFzc2VkIHRvIGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVy
X3dpdGhfZ3JvdXBzKCkuCj4KPiAgICBOb3RlOiBIYXZpbmcgYW4gYXJyYXkgb2YgcG9pbnRlcnMg
b2YgJ2F0dHJpYnV0ZV9ncm91cCcgYW5kIGVhY2ggZ3JvdXAKPiAgICBjb3JyZXNwb25kcyB0byAn
ZW51bSBzZW5zb3JzJyB0eXBlLiBOb3QgY29tcGxldGVseSBzdXJlLCBpZiBpdCdzIGlkZWFsIG9y
Cj4gICAgY291bGQgaGF2ZSBqdXN0IG9uZSBncm91cCBwb3B1bGF0ZWQgd2l0aCBhdHRyaWJ1dGVz
IG9mIHNlbnNvciB0eXBlcz8KPgo+IC0gJ2libXBvd2VybnYnIGlzIG5vdCBob3QtcGx1Z2dhYmxl
IGRldmljZSBzbyBtb3ZpbmcgJ3BsYXRmb3JtX2RyaXZlcicgY2FsbGJhY2sKPiAgICBmdW5jdGlv
biAocHJvYmUpIGFzIHBhcnQgb2YgX19pbml0IGNvZGUuCj4gLSBGaXhlZCBpc3N1ZXMgcmVsYXRl
ZCB0byBjb2Rpbmcgc3R5bGUuCj4gLSBPdGhlciBnZW5lcmFsIGNvbW1lbnRzIGluIHYxLgo+Cj4g
ICAuLi4vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4dCAgICAgICB8ICAg
MjcgKwo+ICAgRG9jdW1lbnRhdGlvbi9od21vbi9pYm1wb3dlcm52ICAgICAgICAgICAgICAgICAg
ICAgfCAgIDQxICsrCj4gICBkcml2ZXJzL2h3bW9uL0tjb25maWcgICAgICAgICAgICAgICAgICAg
ICAgICAgICAgICB8ICAgMTEgKwo+ICAgZHJpdmVycy9od21vbi9NYWtlZmlsZSAgICAgICAgICAg
ICAgICAgICAgICAgICAgICAgfCAgICAxCj4gICBkcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYyAg
ICAgICAgICAgICAgICAgICAgICAgICB8ICAzNjIgKysrKysrKysrKysrKysrKysrKysKPiAgIDUg
ZmlsZXMgY2hhbmdlZCwgNDQyIGluc2VydGlvbnMoKykKPiAgIGNyZWF0ZSBtb2RlIDEwMDY0NCBE
b2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQKPiAg
IGNyZWF0ZSBtb2RlIDEwMDY0NCBEb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYKPiAgIGNy
ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYwo+Cj4gZGlmZiAtLWdp
dCBhL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4
dCBiL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4
dAo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uZTNiZDFlYgo+IC0tLSAv
ZGV2L251bGwKPiArKysgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvaHdtb24v
aWJtcG93ZXJudi50eHQKPiBAQCAtMCwwICsxLDI3IEBACj4gK0lCTSBQT1dFUk5WIHBsYXRmb3Jt
IHNlbnNvcnMKPiArLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo+ICsKPiArUmVxdWlyZWQg
bm9kZSBwcm9wZXJ0aWVzOgo+ICstIGNvbXBhdGlibGU6IG11c3QgYmUgb25lIG9mCj4gKwkJImli
bSxvcGFsLXNlbnNvci1jb29saW5nLWZhbiIKPiArCQkiaWJtLG9wYWwtc2Vuc29yLWFtYi10ZW1w
Igo+ICsJCSJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3VwcGx5Igo+ICsJCSJpYm0sb3BhbC1zZW5z
b3ItcG93ZXIiCj4gKy0gc2Vuc29yLWlkOiBhbiBvcGFxdWUgaWQgcHJvdmlkZWQgYnkgdGhlIGZp
cm13YXJlIHRvIHRoZSBrZXJuZWwsIGlkZW50aWZpZXMgYQo+ICsJICAgICBnaXZlbiBzZW5zb3Ig
YW5kIGl0cyBhdHRyaWJ1dGUgZGF0YQo+ICsKPiArRXhhbXBsZSBzZW5zb3JzIG5vZGU6Cj4gKwo+
ICtjb29saW5nLWZhbiM4LWRhdGEgewo+ICsJc2Vuc29yLWlkID0gPDB4NzA1MjEwNz47Cj4gKwlw
aGFuZGxlID0gPDB4MTAwMDAwMjg+Owo+ICsJbGludXgscGhhbmRsZSA9IDwweDEwMDAwMDI4PjsK
PiArCWNvbXBhdGlibGUgPSAiaWJtLG9wYWwtc2Vuc29yLWNvb2xpbmctZmFuIjsKCnBoYW5kbGUg
YW5kIGxpbnV4LXBoYW5kbGUgYXJlIG5laXRoZXIgZG9jdW1lbnRlZCBub3IgdXNlZC4gRWl0aGVy
IGRvY3VtZW50IG9yIGRyb3AuCgo+ICt9Owo+ICsKPiArYW1iLXRlbXAjMS10aHJzIHsKPiArCXNl
bnNvci1pZCA9IDwweDUwOTYwMDA+Owo+ICsJcGhhbmRsZSA9IDwweDEwMDAwMDE3PjsKPiArCWxp
bnV4LHBoYW5kbGUgPSA8MHgxMDAwMDAxNz47Cj4gKwljb21wYXRpYmxlID0gImlibSxvcGFsLXNl
bnNvci1hbWItdGVtcCI7Cj4gK307Cj4gZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24vaHdtb24v
aWJtcG93ZXJudiBiL0RvY3VtZW50YXRpb24vaHdtb24vaWJtcG93ZXJudgo+IG5ldyBmaWxlIG1v
ZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uNjQ0MjQ1YQo+IC0tLSAvZGV2L251bGwKPiArKysg
Yi9Eb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYKPiBAQCAtMCwwICsxLDQxIEBACj4gK0tl
cm5lbCBEcml2ZXIgSUJNUE9XRU5WCj4gKz09PT09PT09PT09PT09PT09PT09PT09Cj4gKwo+ICtT
dXBwb3J0ZWQgc3lzdGVtczoKPiArICAqIEFueSByZWNlbnQgSUJNIFAgc2VydmVycyBiYXNlZCBv
biBQT1dFUk5WIHBsYXRmb3JtCj4gKwo+ICtBdXRob3I6IE5lZWxlc2ggR3VwdGEKPiArCj4gK0Rl
c2NyaXB0aW9uCj4gKy0tLS0tLS0tLS0tCj4gKwo+ICtUaGlzIGRyaXZlciBpbXBsZW1lbnRzIHJl
YWRpbmcgdGhlIHBsYXRmb3JtIHNlbnNvcnMgZGF0YSBsaWtlIHRlbXBlcmF0dXJlL2Zhbi8KPiAr
dm9sdGFnZS9wb3dlciBmb3IgJ1BPV0VSTlYnIHBsYXRmb3JtLgo+ICsKPiArVGhlIGRyaXZlciB1
c2VzIHRoZSBwbGF0Zm9ybSBkZXZpY2UgaW5mcmFzdHJ1Y3R1cmUuIEl0IHByb2JlcyB0aGUgZGV2
aWNlIHRyZWUKPiArZm9yIHNlbnNvciBkZXZpY2VzIGR1cmluZyB0aGUgX19pbml0IHBoYXNlIGFu
ZCByZWdpc3RlcnMgdGhlbSB3aXRoIHRoZSAnaHdtb24nLgo+ICsnaHdtb24nIHBvcHVsYXRlcyB0
aGUgJ3N5c2ZzJyB0cmVlIGhhdmluZyBhdHRyaWJ1dGUgZmlsZXMsIGVhY2ggZm9yIGEgZ2l2ZW4K
PiArc2Vuc29yIHR5cGUgYW5kIGl0cyBhdHRyaWJ1dGUgZGF0YS4KPiArCj4gK0FsbCB0aGUgbm9k
ZXMgaW4gdGhlIERUIGFwcGVhciB1bmRlciAiL2libSxvcGFsL3NlbnNvcnMiIGFuZCBlYWNoIHZh
bGlkIG5vZGUgaW4KPiArdGhlIERUIG1hcHMgdG8gYW4gYXR0cmlidXRlIGZpbGUgaW4gJ3N5c2Zz
Jy4gVGhlIG5vZGUgZXhwb3J0cyB1bmlxdWUgJ3NlbnNvci1pZCcKPiArd2hpY2ggdGhlIGRyaXZl
ciB1c2VzIHRvIG1ha2UgYW4gT1BBTCBjYWxsIHRvIHRoZSBmaXJtd2FyZS4KPiArCj4gK1VzYWdl
IG5vdGVzCj4gKy0tLS0tLS0tLS0tCj4gK1RoZSBkcml2ZXIgaXMgYnVpbHQgc3RhdGljYWxseSB3
aXRoIHRoZSBrZXJuZWwgYnkgZW5hYmxpbmcgdGhlIGNvbmZpZwo+ICtDT05GSUdfU0VOU09SU19J
Qk1QT1dFUk5WLiBJdCBjYW4gYWxzbyBiZSBidWlsdCBhcyBtb2R1bGUgJ2libXBvd2VybnYnLgo+
ICsKPiArU3lzZnMgYXR0cmlidXRlcwo+ICstLS0tLS0tLS0tLS0tLS0tCj4gKwo+ICtmYW5YX2lu
cHV0CQlNZWFzdXJlZCBSUE0gdmFsdWUuCj4gK2ZhblhfbWluCQlUaHJlc2hvbGQgUlBNIGZvciBh
bGVydCBnZW5lcmF0aW9uLgo+ICtmYW5YX2ZhdWx0CQkwOiBObyBmYWlsIGNvbmRpdGlvbgo+ICsJ
CQkxOiBGYWlsaW5nIGZhbgo+ICt0ZW1wWF9pbnB1dAkJTWVhc3VyZWQgYW1iaWVudCB0ZW1wZXJh
dHVyZS4KPiArdGVtcFhfbWF4CQlUaHJlc2hvbGQgYW1iaWVudCB0ZW1wZXJhdHVyZSBmb3IgYWxl
cnQgZ2VuZXJhdGlvbi4KPiAraW5YX2lucHV0CQlNZWFzdXJlZCBwb3dlciBzdXBwbHkgdm9sdGFn
ZQo+ICtpblhfZmF1bHQJCTA6IE5vIGZhaWwgY29uZGl0aW9uLgo+ICsJCQkxOiBGYWlsaW5nIHBv
d2VyIHN1cHBseS4KPiArcG93ZXIxX2lucHV0CQlTeXN0ZW0gcG93ZXIgY29uc3VtcHRpb24gKG1p
Y3JvV2F0dCkKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmlnIGIvZHJpdmVycy9o
d21vbi9LY29uZmlnCj4gaW5kZXggMDJkM2Q4NS4uMjljM2ZjYiAxMDA2NDQKPiAtLS0gYS9kcml2
ZXJzL2h3bW9uL0tjb25maWcKPiArKysgYi9kcml2ZXJzL2h3bW9uL0tjb25maWcKPiBAQCAtNTU0
LDYgKzU1NCwxNyBAQCBjb25maWcgU0VOU09SU19JQk1QRVgKPiAgIAkgIFRoaXMgZHJpdmVyIGNh
biBhbHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiAgSWYgc28sIHRoZSBtb2R1bGUKPiAgIAkgIHdp
bGwgYmUgY2FsbGVkIGlibXBleC4KPgo+ICtjb25maWcgU0VOU09SU19JQk1QT1dFUk5WCj4gKwl0
cmlzdGF0ZSAiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIKPiArCWRlcGVuZHMgb24gUFBD
X1BPV0VSTlYKPiArCWRlZmF1bHQgeQo+ICsJaGVscAo+ICsJICBJZiB5b3Ugc2F5IHllcyBoZXJl
IHlvdSBnZXQgc3VwcG9ydCBmb3IgdGhlIHRlbXBlcmF0dXJlL2Zhbi9wb3dlcgo+ICsJICBzZW5z
b3JzIG9uIHlvdXIgUG93ZXJOViBwbGF0Zm9ybS4KPiArCj4gKwkgIFRoaXMgZHJpdmVyIGNhbiBh
bHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiBJZiBzbywgdGhlIG1vZHVsZQo+ICsJICB3aWxsIGJl
IGNhbGxlZCBpYm1wb3dlcm52Lgo+ICsKPiAgIGNvbmZpZyBTRU5TT1JTX0lJT19IV01PTgo+ICAg
CXRyaXN0YXRlICJId21vbiBkcml2ZXIgdGhhdCB1c2VzIGNoYW5uZWxzIHNwZWNpZmllZCB2aWEg
aWlvIG1hcHMiCj4gICAJZGVwZW5kcyBvbiBJSU8KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21v
bi9NYWtlZmlsZSBiL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPiBpbmRleCAzZGMwZjAyLi5mYzRl
ZDI2IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPiArKysgYi9kcml2ZXJz
L2h3bW9uL01ha2VmaWxlCj4gQEAgLTcxLDYgKzcxLDcgQEAgb2JqLSQoQ09ORklHX1NFTlNPUlNf
VUxUUkE0NSkJKz0gdWx0cmE0NV9lbnYubwo+ICAgb2JqLSQoQ09ORklHX1NFTlNPUlNfSTVLX0FN
QikJKz0gaTVrX2FtYi5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JQk1BRU0pCSs9IGlibWFl
bS5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JQk1QRVgpCSs9IGlibXBleC5vCj4gK29iai0k
KENPTkZJR19TRU5TT1JTX0lCTVBPV0VSTlYpKz0gaWJtcG93ZXJudi5vCj4gICBvYmotJChDT05G
SUdfU0VOU09SU19JSU9fSFdNT04pICs9IGlpb19od21vbi5vCj4gICBvYmotJChDT05GSUdfU0VO
U09SU19JTkEyMDkpCSs9IGluYTIwOS5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JTkEyWFgp
CSs9IGluYTJ4eC5vCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jIGIv
ZHJpdmVycy9od21vbi9pYm1wb3dlcm52LmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4
IDAwMDAwMDAuLjQ0ZGNkOTkKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy9od21vbi9p
Ym1wb3dlcm52LmMKPiBAQCAtMCwwICsxLDM2MiBAQAo+ICsvKgo+ICsgKiBJQk0gUG93ZXJOViBw
bGF0Zm9ybSBzZW5zb3JzIGZvciB0ZW1wZXJhdHVyZS9mYW4vdm9sdGFnZS9wb3dlcgo+ICsgKiBD
b3B5cmlnaHQgKEMpIDIwMTQgSUJNCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNv
ZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5Cj4gKyAqIGl0IHVu
ZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlz
aGVkIGJ5Cj4gKyAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9u
IDIgb2YgdGhlIExpY2Vuc2UsIG9yCj4gKyAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZl
cnNpb24uCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9w
ZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAo+ICsgKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7
IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgo+ICsgKiBNRVJDSEFOVEFCSUxJ
VFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCj4gKyAqIEdO
VSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCj4gKyAqCj4gKyAqIFlv
dSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBM
aWNlbnNlCj4gKyAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtLgo+ICsgKi8KPiArCj4gKyNkZWZp
bmUgRFJWTkFNRQkJImlibXBvd2VybnYiCj4gKyNkZWZpbmUgcHJfZm10KGZtdCkJRFJWTkFNRSAi
OiAiIGZtdAo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KPiArI2luY2x1ZGUgPGxpbnV4
L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgva2VybmVsLmg+Cj4gKyNpbmNsdWRlIDxsaW51
eC9od21vbi5oPgo+ICsjaW5jbHVkZSA8bGludXgvaHdtb24tc3lzZnMuaD4KPiArI2luY2x1ZGUg
PGxpbnV4L29mLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cj4gKwo+ICsjaW5jbHVkZSA8
bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4gKyNpbmNsdWRlIDxhc20vb3BhbC5oPgo+ICsjaW5j
bHVkZSA8bGludXgvZXJyLmg+Cj4gKwo+ICsjZGVmaW5lIE1BWF9BVFRSX0xFTgkzMgo+ICsKPiAr
LyogU2Vuc29yIHN1ZmZpeCBuYW1lIGZyb20gRFQgKi8KPiArI2RlZmluZSBEVF9GQVVMVF9BVFRS
X1NVRkZJWAkJImZhdWx0ZWQiCj4gKyNkZWZpbmUgRFRfREFUQV9BVFRSX1NVRkZJWAkJImRhdGEi
Cj4gKyNkZWZpbmUgRFRfVEhSRVNIT0xEX0FUVFJfU1VGRklYCSJ0aHJzIgo+ICsKPiArLyoKPiAr
ICogRW51bWVyYXRlcyBhbGwgdGhlIHR5cGVzIG9mIHNlbnNvcnMgaW4gdGhlIFBPV0VSTlYgcGxh
dGZvcm0gYW5kIGRvZXMgaW5kZXgKPiArICogaW50byAnc3RydWN0IHNlbnNvcl9ncm91cCcKPiAr
ICovCj4gK2VudW0gc2Vuc29ycyB7Cj4gKwlGQU4sCj4gKwlBTUJJRU5UX1RFTVAsCj4gKwlQT1dF
Ul9TVVBQTFksCj4gKwlQT1dFUl9JTlBVVCwKPiArCU1BWF9TRU5TT1JfVFlQRSwKPiArfTsKPiAr
Cj4gK3N0YXRpYyBzdHJ1Y3Qgc2Vuc29yX2dyb3VwIHsKPiArCWNvbnN0IGNoYXIgKm5hbWU7Cj4g
Kwljb25zdCBjaGFyICpjb21wYXRpYmxlOwo+ICsJc3RydWN0IGF0dHJpYnV0ZV9ncm91cCBncm91
cDsKPiArCXUzMiBhdHRyX2NvdW50Owo+ICt9IHNlbnNvcl9ncm91cHNbXSA9IHsKPiArCXsiZmFu
IiwgImlibSxvcGFsLXNlbnNvci1jb29saW5nLWZhbiJ9LAo+ICsJeyJ0ZW1wIiwgImlibSxvcGFs
LXNlbnNvci1hbWItdGVtcCJ9LAo+ICsJeyJpbiIsICJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3Vw
cGx5In0sCj4gKwl7InBvd2VyIiwgImlibSxvcGFsLXNlbnNvci1wb3dlciJ9Cj4gK307Cj4gKwo+
ICtzdHJ1Y3Qgc2Vuc29yX2RhdGEgewo+ICsJdTMyIGlkOyAvKiBBbiBvcGFxdWUgaWQgb2YgdGhl
IGZpcm13YXJlIGZvciBlYWNoIHNlbnNvciAqLwo+ICsJZW51bSBzZW5zb3JzIHR5cGU7Cj4gKwlj
aGFyIG5hbWVbTUFYX0FUVFJfTEVOXTsKPiArCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlIGRldl9h
dHRyOwo+ICt9Owo+ICsKPiArc3RydWN0IHBsYXRmb3JtX2RhdGEgewo+ICsJY29uc3Qgc3RydWN0
IGF0dHJpYnV0ZV9ncm91cCAqYXR0cl9ncm91cHNbTUFYX1NFTlNPUl9UWVBFICsgMV07Cj4gKwl1
MzIgc2Vuc29yc19jb3VudDsgLyogVG90YWwgY291bnQgb2Ygc2Vuc29ycyBmcm9tIGVhY2ggZ3Jv
dXAgKi8KPiArfTsKPiArCj4gKy8qIFBsYXRmb3JtIGRldmljZSByZXByZXNlbnRpbmcgYWxsIHRo
ZSBpYm1wb3dlcm52IHNlbnNvcnMgKi8KPiArc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2Ug
KnBkZXZpY2U7Cj4gKwo+ICtzdGF0aWMgc3NpemVfdCBzaG93X3NlbnNvcihzdHJ1Y3QgZGV2aWNl
ICpkZXYsIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkZXZhdHRyLAo+ICsJCQkgICBjaGFyICpi
dWYpCj4gK3sKPiArCXN0cnVjdCBzZW5zb3JfZGF0YSAqc2RhdGEgPSBjb250YWluZXJfb2YoZGV2
YXR0ciwgc3RydWN0IHNlbnNvcl9kYXRhLAo+ICsJCQkJCQkgZGV2X2F0dHIpOwo+ICsJc3NpemVf
dCByZXQ7Cj4gKwl1MzIgeDsKPiArCj4gKwlyZXQgPSBvcGFsX2dldF9zZW5zb3JfZGF0YShzZGF0
YS0+aWQsICZ4KTsKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwkvKiBDb252
ZXJ0IHRlbXBlcmF0dXJlIHRvIG1pbGxpLWRlZ3JlZXMgKi8KPiArCWlmIChzZGF0YS0+dHlwZSA9
PSBBTUJJRU5UX1RFTVApCj4gKwkJeCAqPSAxMDAwOwo+ICsJLyogQ29udmVydCBwb3dlciB0byBt
aWNyby13YXR0cyAqLwo+ICsJZWxzZSBpZiAoc2RhdGEtPnR5cGUgPT0gUE9XRVJfSU5QVVQpCj4g
KwkJeCAqPSAxMDAwMDAwOwo+ICsKPiArCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiV1XG4iLCB4KTsK
PiArfQo+ICsKPiArc3RhdGljIGludCBfX2luaXQgZ2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0
IGNoYXIgKm5hbWUsIHUzMiAqaW5kZXgsCj4gKwkJCQkJY2hhciAqYXR0cikKPiArewo+ICsJY2hh
ciAqaGFzaF9wb3MgPSBzdHJjaHIobmFtZSwgJyMnKTsKPiArCWNoYXIgYnVmWzhdID0geyAwIH07
Cj4gKwljaGFyICpkYXNoX3BvczsKPiArCXUzMiBjb3B5X2xlbjsKPiArCj4gKwlpZiAoIWhhc2hf
cG9zKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCWRhc2hfcG9zID0gc3RyY2hyKGhhc2hf
cG9zLCAnLScpOwo+ICsJaWYgKCFkYXNoX3BvcykKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4g
Kwljb3B5X2xlbiA9IGRhc2hfcG9zIC0gaGFzaF9wb3MgLSAxOwo+ICsJaWYgKGNvcHlfbGVuID49
IHNpemVvZihidWYpKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXN0cm5jcHkoYnVmLCBo
YXNoX3BvcyArIDEsIGNvcHlfbGVuKTsKPiArCj4gKwlpZiAoa3N0cnRvdTMyKGJ1ZiwgMTAsIGlu
ZGV4KSkKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCnNtYXRjaCBpc24ndCBnb2luZyB0byBsaWtl
IHRoYXQuIFBsZWFzZSB1c2UKCglpbnQgZXJyOwoJLi4uCgllcnIgPSBrc3RydG91MzIoYnVmLCAx
MCwgaW5kZXgpKTsKCWlmIChlcnIpCgkJcmV0dXJuIGVycjsKCj4gKwlzdHJuY3B5KGF0dHIsIGRh
c2hfcG9zICsgMSwgTUFYX0FUVFJfTEVOKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiAr
LyoKPiArICogVGhpcyBmdW5jdGlvbiB0cmFuc2xhdGVzIHRoZSBEVCBub2RlIG5hbWUgaW50byB0
aGUgJ2h3bW9uJyBhdHRyaWJ1dGUgbmFtZS4KPiArICogSUJNUE9XRVJOViBkZXZpY2Ugbm9kZSBh
cHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIGFtYi10ZW1wIzEtdGhycyBldGMuCj4gKyAq
IHdoaWNoIG5lZWQgdG8gYmUgbWFwcGVkIGFzIGZhbjJfaW5wdXQsIHRlbXAxX21heCByZXNwZWN0
aXZlbHkgYmVmb3JlCj4gKyAqIHBvcHVsYXRpbmcgdGhlbSBpbnNpZGUgaHdtb24gZGV2aWNlIGNs
YXNzLgo+ICsgKi8KPiArc3RhdGljIGludCBfX2luaXQgY3JlYXRlX2h3bW9uX2F0dHJfbmFtZShz
dHJ1Y3QgZGV2aWNlICpkZXYsIGVudW0gc2Vuc29ycyB0eXBlLAo+ICsJCQkJCSBjb25zdCBjaGFy
ICpub2RlX25hbWUsCj4gKwkJCQkJIGNoYXIgKmh3bW9uX2F0dHJfbmFtZSkKPiArewo+ICsJY2hh
ciBhdHRyX3N1ZmZpeFtNQVhfQVRUUl9MRU5dOwo+ICsJY2hhciAqYXR0cl9uYW1lOwo+ICsJdTMy
IGluZGV4Owo+ICsJaW50IGVycjsKPiArCj4gKwllcnIgPSBnZXRfc2Vuc29yX2luZGV4X2F0dHIo
bm9kZV9uYW1lLCAmaW5kZXgsIGF0dHJfc3VmZml4KTsKPiArCWlmIChlcnIpIHsKPiArCQlkZXZf
ZXJyKGRldiwgIlNlbnNvciBkZXZpY2Ugbm9kZSBuYW1lICclcycgaXMgaW52YWxpZFxuIiwKPiAr
CQkJbm9kZV9uYW1lKTsKPiArCQlyZXR1cm4gZXJyOwo+ICsJfQo+ICsKPiArCWlmICghc3RyY21w
KGF0dHJfc3VmZml4LCBEVF9GQVVMVF9BVFRSX1NVRkZJWCkpIHsKPiArCQlhdHRyX25hbWUgPSAi
ZmF1bHQiOwo+ICsJfSBlbHNlIGlmICghc3RyY21wKGF0dHJfc3VmZml4LCBEVF9EQVRBX0FUVFJf
U1VGRklYKSkgewo+ICsJCWF0dHJfbmFtZSA9ICJpbnB1dCI7Cj4gKwl9IGVsc2UgaWYgKCFzdHJj
bXAoYXR0cl9zdWZmaXgsIERUX1RIUkVTSE9MRF9BVFRSX1NVRkZJWCkpIHsKPiArCQlpZiAodHlw
ZSA9PSBBTUJJRU5UX1RFTVApCj4gKwkJCWF0dHJfbmFtZSA9ICJtYXgiOwo+ICsJCWVsc2UgaWYg
KHR5cGUgPT0gRkFOKQo+ICsJCQlhdHRyX25hbWUgPSAibWluIjsKPiArCQllbHNlCj4gKwkJCXJl
dHVybiAtRU5PRU5UOwo+ICsJfSBlbHNlIHsKPiArCQlyZXR1cm4gLUVOT0VOVDsKPiArCX0KPiAr
Cj4gKwlzbnByaW50Zihod21vbl9hdHRyX25hbWUsIE1BWF9BVFRSX0xFTiwgIiVzJWRfJXMiLAo+
ICsJCSBzZW5zb3JfZ3JvdXBzW3R5cGVdLm5hbWUsIGluZGV4LCBhdHRyX25hbWUpOwo+ICsJcmV0
dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgX19pbml0IHBvcHVsYXRlX2F0dHJfZ3JvdXBz
KHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiArCXN0cnVjdCBwbGF0Zm9ybV9k
YXRhICpwZGF0YSA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ICsJY29uc3Qgc3RydWN0
IGF0dHJpYnV0ZV9ncm91cCAqKnBncm91cHMgPSBwZGF0YS0+YXR0cl9ncm91cHM7Cj4gKwlzdHJ1
Y3QgZGV2aWNlX25vZGUgKm9wYWwsICpucDsKPiArCWVudW0gc2Vuc29ycyB0eXBlOwo+ICsKPiAr
CW9wYWwgPSBvZl9maW5kX25vZGVfYnlfcGF0aCgiL2libSxvcGFsL3NlbnNvcnMiKTsKPiArCWlm
ICghb3BhbCkgewo+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgIk9wYWwgbm9kZSAnc2Vuc29ycycg
bm90IGZvdW5kXG4iKTsKPiArCQlyZXR1cm4gLUVOT0RFVjsKPiArCX0KPiArCj4gKwlmb3JfZWFj
aF9jaGlsZF9vZl9ub2RlKG9wYWwsIG5wKSB7Cj4gKwkJaWYgKG5wLT5uYW1lID09IE5VTEwpCj4g
KwkJCWNvbnRpbnVlOwo+ICsKPiArCQlmb3IgKHR5cGUgPSAwOyB0eXBlIDwgTUFYX1NFTlNPUl9U
WVBFOyB0eXBlKyspCj4gKwkJCWlmIChvZl9kZXZpY2VfaXNfY29tcGF0aWJsZShucCwKPiArCQkJ
CQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmNvbXBhdGlibGUpKSB7Cj4gKwkJCQlzZW5zb3JfZ3JvdXBz
W3R5cGVdLmF0dHJfY291bnQrKzsKPiArCQkJCWJyZWFrOwo+ICsJCQl9Cj4gKwl9Cj4gKwo+ICsJ
b2Zfbm9kZV9wdXQob3BhbCk7Cj4gKwo+ICsJZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5T
T1JfVFlQRTsgdHlwZSsrKSB7Cj4gKwkJc2Vuc29yX2dyb3Vwc1t0eXBlXS5ncm91cC5hdHRycyA9
IGRldm1fa3phbGxvYygmcGRldi0+ZGV2LAo+ICsJCQkJCXNpemVvZihzdHJ1Y3QgYXR0cmlidXRl
ICopICoKPiArCQkJCQkoc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRyX2NvdW50ICsgMSksCj4gKwkJ
CQkJR0ZQX0tFUk5FTCk7Cj4gKwkJaWYgKCFzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJz
KQo+ICsJCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwkJcGdyb3Vwc1t0eXBlXSA9ICZzZW5zb3Jf
Z3JvdXBzW3R5cGVdLmdyb3VwOwo+ICsJCXBkYXRhLT5zZW5zb3JzX2NvdW50ICs9IHNlbnNvcl9n
cm91cHNbdHlwZV0uYXR0cl9jb3VudDsKPiArCQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmF0dHJfY291
bnQgPSAwOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICsvKgo+ICsgKiBJdGVy
YXRlIHRocm91Z2ggdGhlIGRldmljZSB0cmVlIGZvciBlYWNoIGNoaWxkIG9mICdzZW5zb3JzJyBu
b2RlLCBjcmVhdGUKPiArICogYSBzeXNmcyBhdHRyaWJ1dGUgZmlsZSwgdGhlIGZpbGUgaXMgbmFt
ZWQgYnkgdHJhbnNsYXRpbmcgdGhlIERUIG5vZGUgbmFtZQo+ICsgKiB0byB0aGUgbmFtZSByZXF1
aXJlZCBieSB0aGUgaGlnaGVyICdod21vbicgZHJpdmVyIGxpa2UgZmFuMV9pbnB1dCwgdGVtcDFf
bWF4Cj4gKyAqIGV0Yy4uCj4gKyAqLwo+ICtzdGF0aWMgaW50IF9faW5pdCBjcmVhdGVfZGV2aWNl
X2F0dHJzKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiArCXN0cnVjdCBwbGF0
Zm9ybV9kYXRhICpwZGF0YSA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ICsJY29uc3Qg
c3RydWN0IGF0dHJpYnV0ZV9ncm91cCAqKnBncm91cHMgPSBwZGF0YS0+YXR0cl9ncm91cHM7Cj4g
KwlzdHJ1Y3QgZGV2aWNlX25vZGUgKm9wYWwsICpucDsKPiArCXN0cnVjdCBzZW5zb3JfZGF0YSAq
c2RhdGE7Cj4gKwljb25zdCBfX2JlMzIgKnNlbnNvcl9pZDsKPiArCWVudW0gc2Vuc29ycyB0eXBl
Owo+ICsJdTMyIGNvdW50ID0gMDsKPiArCWludCBlcnIgPSAwOwo+ICsKPiArCW9wYWwgPSBvZl9m
aW5kX25vZGVfYnlfcGF0aCgiL2libSxvcGFsL3NlbnNvcnMiKTsKPiArCXNkYXRhID0gZGV2bV9r
emFsbG9jKCZwZGV2LT5kZXYsIHBkYXRhLT5zZW5zb3JzX2NvdW50ICogc2l6ZW9mKCpzZGF0YSks
Cj4gKwkJCSAgICAgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIXNkYXRhKSB7Cj4gKwkJZXJyID0gLUVO
T01FTTsKPiArCQlnb3RvIGV4aXRfcHV0X25vZGU7Cj4gKwl9Cj4gKwo+ICsJZm9yX2VhY2hfY2hp
bGRfb2Zfbm9kZShvcGFsLCBucCkgewo+ICsJCWlmIChucC0+bmFtZSA9PSBOVUxMKQo+ICsJCQlj
b250aW51ZTsKPiArCj4gKwkJZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5TT1JfVFlQRTsg
dHlwZSsrKQo+ICsJCQlpZiAob2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCj4gKwkJCQkJc2Vu
c29yX2dyb3Vwc1t0eXBlXS5jb21wYXRpYmxlKSkKPiArCQkJCWJyZWFrOwo+ICsKPiArCQlpZiAo
dHlwZSA9PSBNQVhfU0VOU09SX1RZUEUpCj4gKwkJCWNvbnRpbnVlOwo+ICsKPiArCQlzZW5zb3Jf
aWQgPSBvZl9nZXRfcHJvcGVydHkobnAsICJzZW5zb3ItaWQiLCBOVUxMKTsKPiArCQlpZiAoIXNl
bnNvcl9pZCkgewo+ICsJCQlkZXZfaW5mbygmcGRldi0+ZGV2LAo+ICsJCQkJICInc2Vuc29yLWlk
JyBtaXNzaW5nIGluIHRoZSBub2RlICclcydcbiIsCj4gKwkJCQkgbnAtPm5hbWUpOwo+ICsJCQlj
b250aW51ZTsKPiArCQl9Cj4gKwo+ICsJCXNkYXRhW2NvdW50XS5pZCA9IGJlMzJfdG9fY3B1cChz
ZW5zb3JfaWQpOwo+ICsJCXNkYXRhW2NvdW50XS50eXBlID0gdHlwZTsKPiArCQllcnIgPSBjcmVh
dGVfaHdtb25fYXR0cl9uYW1lKCZwZGV2LT5kZXYsIHR5cGUsIG5wLT5uYW1lLAo+ICsJCQkJCSAg
ICAgc2RhdGFbY291bnRdLm5hbWUpOwo+ICsJCWlmIChlcnIpCj4gKwkJCWdvdG8gZXhpdF9wdXRf
bm9kZTsKPiArCj4gKwkJc3lzZnNfYXR0cl9pbml0KCZzZGF0YVtjb3VudF0uZGV2X2F0dHIuYXR0
cik7Cj4gKwkJc2RhdGFbY291bnRdLmRldl9hdHRyLmF0dHIubmFtZSA9IHNkYXRhW2NvdW50XS5u
YW1lOwo+ICsJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5hdHRyLm1vZGUgPSBTX0lSVUdPOwo+ICsJ
CXNkYXRhW2NvdW50XS5kZXZfYXR0ci5zaG93ID0gc2hvd19zZW5zb3I7Cj4gKwo+ICsJCXBncm91
cHNbdHlwZV0tPmF0dHJzW3NlbnNvcl9ncm91cHNbdHlwZV0uYXR0cl9jb3VudCsrXSA9Cj4gKwkJ
CQkmc2RhdGFbY291bnQrK10uZGV2X2F0dHIuYXR0cjsKPiArCX0KPiArCj4gK2V4aXRfcHV0X25v
ZGU6Cj4gKwlvZl9ub2RlX3B1dChvcGFsKTsKPiArCXJldHVybiBlcnI7Cj4gK30KPiArCj4gK3N0
YXRpYyBpbnQgX19pbml0IGlibXBvd2VybnZfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAq
cGRldikKPiArewo+ICsJc3RydWN0IHBsYXRmb3JtX2RhdGEgKnBkYXRhOwo+ICsJc3RydWN0IGRl
dmljZSAqaHdtb25fZGV2Owo+ICsJaW50IGVycjsKPiArCj4gKwlwZGF0YSA9IGRldm1fa3phbGxv
YygmcGRldi0+ZGV2LCBzaXplb2YoKnBkYXRhKSwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIXBkYXRh
KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYs
IHBkYXRhKTsKPiArCXBkYXRhLT5zZW5zb3JzX2NvdW50ID0gMDsKPiArCWVyciA9IHBvcHVsYXRl
X2F0dHJfZ3JvdXBzKHBkZXYpOwo+ICsJaWYgKGVycikKPiArCQlyZXR1cm4gZXJyOwo+ICsKPiAr
CS8qIENyZWF0ZSBzeXNmcyBhdHRyaWJ1dGUgZGF0YSBmb3IgZWFjaCBzZW5zb3IgZm91bmQgaW4g
dGhlIERUICovCj4gKwllcnIgPSBjcmVhdGVfZGV2aWNlX2F0dHJzKHBkZXYpOwo+ICsJaWYgKGVy
cikKPiArCQlyZXR1cm4gZXJyOwo+ICsKPiArCS8qIEZpbmFsbHksIHJlZ2lzdGVyIHdpdGggaHdt
b24gKi8KPiArCWh3bW9uX2RldiA9IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhfZ3Jv
dXBzKCZwZGV2LT5kZXYsIERSVk5BTUUsCj4gKwkJCQkJCQkgICBwZGF0YSwKPiArCQkJCQkJCSAg
IHBkYXRhLT5hdHRyX2dyb3Vwcyk7Cj4gKwo+ICsJcmV0dXJuIFBUUl9FUlJfT1JfWkVSTyhod21v
bl9kZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBpYm1wb3dl
cm52X2RyaXZlciA9IHsKPiArCS5kcml2ZXIgPSB7Cj4gKwkJLm93bmVyID0gVEhJU19NT0RVTEUs
Cj4gKwkJLm5hbWUgPSBEUlZOQU1FLAo+ICsJfSwKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgX19p
bml0IGlibXBvd2VybnZfaW5pdCh2b2lkKQo+ICt7Cj4gKwlpbnQgZXJyOwo+ICsKPiArCXBkZXZp
Y2UgPSBwbGF0Zm9ybV9kZXZpY2VfYWxsb2MoRFJWTkFNRSwgMCk7Cj4gKwlpZiAoIXBkZXZpY2Up
IHsKPiArCQlwcl9lcnIoIkRldmljZSBhbGxvY2F0aW9uIGZhaWxlZFxuIik7Cj4gKwkJZXJyID0g
LUVOT01FTTsKPiArCQlnb3RvIGV4aXQ7Cj4gKwl9Cj4gKwo+ICsJZXJyID0gcGxhdGZvcm1fZGV2
aWNlX2FkZChwZGV2aWNlKTsKPiArCWlmIChlcnIpIHsKPiArCQlwcl9lcnIoIkRldmljZSBhZGRp
dGlvbiBmYWlsZWQgKCVkKVxuIiwgZXJyKTsKPiArCQlnb3RvIGV4aXRfZGV2aWNlX3B1dDsKPiAr
CX0KPiArCj4gKwllcnIgPSBwbGF0Zm9ybV9kcml2ZXJfcHJvYmUoJmlibXBvd2VybnZfZHJpdmVy
LCBpYm1wb3dlcm52X3Byb2JlKTsKPiArCWlmIChlcnIpIHsKPiArCQlwcl9lcnIoIlBsYXRmcm9t
IGRyaXZlciBwcm9iZSBmYWlsZWRcbiIpOwo+ICsJCWdvdG8gZXhpdF9kZXZpY2VfZGVsOwo+ICsJ
fQo+ICsKPiArCXJldHVybiAwOwo+ICsKPiArZXhpdF9kZXZpY2VfZGVsOgo+ICsJcGxhdGZvcm1f
ZGV2aWNlX2RlbChwZGV2aWNlKTsKPiArZXhpdF9kZXZpY2VfcHV0Ogo+ICsJcGxhdGZvcm1fZGV2
aWNlX3B1dChwZGV2aWNlKTsKPiArZXhpdDoKPiArCXJldHVybiBlcnI7Cj4gK30KPiArCj4gK3N0
YXRpYyB2b2lkIF9fZXhpdCBpYm1wb3dlcm52X2V4aXQodm9pZCkKPiArewo+ICsJcGxhdGZvcm1f
ZHJpdmVyX3VucmVnaXN0ZXIoJmlibXBvd2VybnZfZHJpdmVyKTsKPiArCXBsYXRmb3JtX2Rldmlj
ZV91bnJlZ2lzdGVyKHBkZXZpY2UpOwo+ICt9Cj4gKwo+ICtNT0RVTEVfQVVUSE9SKCJOZWVsZXNo
IEd1cHRhIDxuZWVsZWd1cEBsaW51eC52bmV0LmlibS5jb20+Iik7Cj4gK01PRFVMRV9ERVNDUklQ
VElPTigiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIpOwo+ICtNT0RVTEVfTElDRU5TRSgi
R1BMIik7Cj4gKwo+ICttb2R1bGVfaW5pdChpYm1wb3dlcm52X2luaXQpOwo+ICttb2R1bGVfZXhp
dChpYm1wb3dlcm52X2V4aXQpOwo+Cj4KPgoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fCmxtLXNlbnNvcnMgbWFpbGluZyBsaXN0CmxtLXNlbnNvcnNAbG0t
c2Vuc29ycy5vcmcKaHR0cDovL2xpc3RzLmxtLXNlbnNvcnMub3JnL21haWxtYW4vbGlzdGluZm8v
bG0tc2Vuc29ycw=

WARNING: multiple messages have this Message-ID (diff)
From: Guenter Roeck <linux@roeck-us.net>
To: Neelesh Gupta <neelegup@linux.vnet.ibm.com>,
	linuxppc-dev@lists.ozlabs.org, jdelvare@suse.de,
	lm-sensors@lm-sensors.org
Cc: sbhat@linux.vnet.ibm.com,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>
Subject: Re: [PATCH v4] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature
Date: Fri, 04 Jul 2014 19:25:36 -0700	[thread overview]
Message-ID: <53B76220.9090900@roeck-us.net> (raw)
In-Reply-To: <20140704105343.22437.52125.stgit@localhost.localdomain>

On 07/04/2014 04:02 AM, Neelesh Gupta wrote:
> This patch adds basic kernel support for reading power values, fan
> speed rpm, voltage and temperature data on powernv platforms which will
> be exported to user space through sysfs interface.
>

Hi Neelesh,

Copying devicetree mailing list. Please copy it on the next (hopefully final)
revision; devicetree maintainers at least need a chance to comment.
[ Yes, I understand this is a shipping product, but still ... ]

I am ok with the code except for a couple of minor nitpicks (see below).

Thanks,
Guenter

> Test results:
> -------------
> [root@tul163p1 ~]# sensors
> ibmpowernv-isa-0000
> Adapter: ISA adapter
> fan1:        5567 RPM  (min =    0 RPM)
> fan2:        5232 RPM  (min =    0 RPM)
> fan3:        5532 RPM  (min =    0 RPM)
> fan4:        4945 RPM  (min =    0 RPM)
> fan5:           0 RPM  (min =    0 RPM)
> fan6:           0 RPM  (min =    0 RPM)
> fan7:        7392 RPM  (min =    0 RPM)
> fan8:        7936 RPM  (min =    0 RPM)
> temp1:        +39.0°C  (high =  +0.0°C)
> power1:      191.00 W
>
> [root@tul163p1 ~]# ls /sys/devices/platform/
> alarmtimer  ibmpowernv.0  power  rtc-generic  serial8250  uevent
> [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/hwmon/hwmon0/
> device	    fan2_min	fan4_min    fan6_min	fan8_min   power
> fan1_fault  fan3_fault	fan5_fault  fan7_fault	in1_fault  power1_input
> fan1_input  fan3_input	fan5_input  fan7_input	in2_fault  subsystem
> fan1_min    fan3_min	fan5_min    fan7_min	in3_fault  temp1_input
> fan2_fault  fan4_fault	fan6_fault  fan8_fault	in4_fault  temp1_max
> fan2_input  fan4_input	fan6_input  fan8_input	name	   uevent
> [root@tul163p1 ~]#
> [root@tul163p1 ~]# ls /sys/class/hwmon/hwmon0/
> device	    fan2_min	fan4_min    fan6_min	fan8_min   power
> fan1_fault  fan3_fault	fan5_fault  fan7_fault	in1_fault  power1_input
> fan1_input  fan3_input	fan5_input  fan7_input	in2_fault  subsystem
> fan1_min    fan3_min	fan5_min    fan7_min	in3_fault  temp1_input
> fan2_fault  fan4_fault	fan6_fault  fan8_fault	in4_fault  temp1_max
> fan2_input  fan4_input	fan6_input  fan8_input	name	   uevent
> [root@tul163p1 ~]#
>
> Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>
> ---
>
> Changes in v4
> =============
> - Replaced pr_err() with dev_err() for loggin print messages.
> - Using kstrtou32() function for converting string to u32 instead of sscanf().
>
> Changes in v3
> =============
> - Fixed an endianness bug leading the driver to break on LE.
> - Fixed a bug that when one of the 'attribute_group' not populated, following
>    groups attributes were dropped.
> - Rewrite the get_sensor_index_attr() function to handle all the error scenarios
>    like 'sscanf' etc.
> - Fixed all the errors/warnings related to coding style/whitespace.
> - Added 'Documentation' files.
> - Addressed remaining review comments on V2.
>
> Changes in v2
> =============
> - Generic use of devm_* functions in hwmon like using devm_kzalloc() for dynamic
>    memory request, avoiding the need to explicit free of memory.
>    Adding 'struct attribute_group' as member of platform data structure to be
>    populated and then passed to devm_hwmon_device_register_with_groups().
>
>    Note: Having an array of pointers of 'attribute_group' and each group
>    corresponds to 'enum sensors' type. Not completely sure, if it's ideal or
>    could have just one group populated with attributes of sensor types?
>
> - 'ibmpowernv' is not hot-pluggable device so moving 'platform_driver' callback
>    function (probe) as part of __init code.
> - Fixed issues related to coding style.
> - Other general comments in v1.
>
>   .../devicetree/bindings/hwmon/ibmpowernv.txt       |   27 +
>   Documentation/hwmon/ibmpowernv                     |   41 ++
>   drivers/hwmon/Kconfig                              |   11 +
>   drivers/hwmon/Makefile                             |    1
>   drivers/hwmon/ibmpowernv.c                         |  362 ++++++++++++++++++++
>   5 files changed, 442 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/hwmon/ibmpowernv.txt
>   create mode 100644 Documentation/hwmon/ibmpowernv
>   create mode 100644 drivers/hwmon/ibmpowernv.c
>
> diff --git a/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt
> new file mode 100644
> index 0000000..e3bd1eb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt
> @@ -0,0 +1,27 @@
> +IBM POWERNV platform sensors
> +----------------------------
> +
> +Required node properties:
> +- compatible: must be one of
> +		"ibm,opal-sensor-cooling-fan"
> +		"ibm,opal-sensor-amb-temp"
> +		"ibm,opal-sensor-power-supply"
> +		"ibm,opal-sensor-power"
> +- sensor-id: an opaque id provided by the firmware to the kernel, identifies a
> +	     given sensor and its attribute data
> +
> +Example sensors node:
> +
> +cooling-fan#8-data {
> +	sensor-id = <0x7052107>;
> +	phandle = <0x10000028>;
> +	linux,phandle = <0x10000028>;
> +	compatible = "ibm,opal-sensor-cooling-fan";

phandle and linux-phandle are neither documented nor used. Either document or drop.

> +};
> +
> +amb-temp#1-thrs {
> +	sensor-id = <0x5096000>;
> +	phandle = <0x10000017>;
> +	linux,phandle = <0x10000017>;
> +	compatible = "ibm,opal-sensor-amb-temp";
> +};
> diff --git a/Documentation/hwmon/ibmpowernv b/Documentation/hwmon/ibmpowernv
> new file mode 100644
> index 0000000..644245a
> --- /dev/null
> +++ b/Documentation/hwmon/ibmpowernv
> @@ -0,0 +1,41 @@
> +Kernel Driver IBMPOWENV
> +=======================
> +
> +Supported systems:
> +  * Any recent IBM P servers based on POWERNV platform
> +
> +Author: Neelesh Gupta
> +
> +Description
> +-----------
> +
> +This driver implements reading the platform sensors data like temperature/fan/
> +voltage/power for 'POWERNV' platform.
> +
> +The driver uses the platform device infrastructure. It probes the device tree
> +for sensor devices during the __init phase and registers them with the 'hwmon'.
> +'hwmon' populates the 'sysfs' tree having attribute files, each for a given
> +sensor type and its attribute data.
> +
> +All the nodes in the DT appear under "/ibm,opal/sensors" and each valid node in
> +the DT maps to an attribute file in 'sysfs'. The node exports unique 'sensor-id'
> +which the driver uses to make an OPAL call to the firmware.
> +
> +Usage notes
> +-----------
> +The driver is built statically with the kernel by enabling the config
> +CONFIG_SENSORS_IBMPOWERNV. It can also be built as module 'ibmpowernv'.
> +
> +Sysfs attributes
> +----------------
> +
> +fanX_input		Measured RPM value.
> +fanX_min		Threshold RPM for alert generation.
> +fanX_fault		0: No fail condition
> +			1: Failing fan
> +tempX_input		Measured ambient temperature.
> +tempX_max		Threshold ambient temperature for alert generation.
> +inX_input		Measured power supply voltage
> +inX_fault		0: No fail condition.
> +			1: Failing power supply.
> +power1_input		System power consumption (microWatt)
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 02d3d85..29c3fcb 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -554,6 +554,17 @@ config SENSORS_IBMPEX
>   	  This driver can also be built as a module.  If so, the module
>   	  will be called ibmpex.
>
> +config SENSORS_IBMPOWERNV
> +	tristate "IBM POWERNV platform sensors"
> +	depends on PPC_POWERNV
> +	default y
> +	help
> +	  If you say yes here you get support for the temperature/fan/power
> +	  sensors on your PowerNV platform.
> +
> +	  This driver can also be built as a module. If so, the module
> +	  will be called ibmpowernv.
> +
>   config SENSORS_IIO_HWMON
>   	tristate "Hwmon driver that uses channels specified via iio maps"
>   	depends on IIO
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 3dc0f02..fc4ed26 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -71,6 +71,7 @@ obj-$(CONFIG_SENSORS_ULTRA45)	+= ultra45_env.o
>   obj-$(CONFIG_SENSORS_I5K_AMB)	+= i5k_amb.o
>   obj-$(CONFIG_SENSORS_IBMAEM)	+= ibmaem.o
>   obj-$(CONFIG_SENSORS_IBMPEX)	+= ibmpex.o
> +obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o
>   obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o
>   obj-$(CONFIG_SENSORS_INA209)	+= ina209.o
>   obj-$(CONFIG_SENSORS_INA2XX)	+= ina2xx.o
> diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c
> new file mode 100644
> index 0000000..44dcd99
> --- /dev/null
> +++ b/drivers/hwmon/ibmpowernv.c
> @@ -0,0 +1,362 @@
> +/*
> + * IBM PowerNV platform sensors for temperature/fan/voltage/power
> + * Copyright (C) 2014 IBM
> + *
> + * 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.
> + */
> +
> +#define DRVNAME		"ibmpowernv"
> +#define pr_fmt(fmt)	DRVNAME ": " fmt
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>
> +
> +#include <linux/platform_device.h>
> +#include <asm/opal.h>
> +#include <linux/err.h>
> +
> +#define MAX_ATTR_LEN	32
> +
> +/* Sensor suffix name from DT */
> +#define DT_FAULT_ATTR_SUFFIX		"faulted"
> +#define DT_DATA_ATTR_SUFFIX		"data"
> +#define DT_THRESHOLD_ATTR_SUFFIX	"thrs"
> +
> +/*
> + * Enumerates all the types of sensors in the POWERNV platform and does index
> + * into 'struct sensor_group'
> + */
> +enum sensors {
> +	FAN,
> +	AMBIENT_TEMP,
> +	POWER_SUPPLY,
> +	POWER_INPUT,
> +	MAX_SENSOR_TYPE,
> +};
> +
> +static struct sensor_group {
> +	const char *name;
> +	const char *compatible;
> +	struct attribute_group group;
> +	u32 attr_count;
> +} sensor_groups[] = {
> +	{"fan", "ibm,opal-sensor-cooling-fan"},
> +	{"temp", "ibm,opal-sensor-amb-temp"},
> +	{"in", "ibm,opal-sensor-power-supply"},
> +	{"power", "ibm,opal-sensor-power"}
> +};
> +
> +struct sensor_data {
> +	u32 id; /* An opaque id of the firmware for each sensor */
> +	enum sensors type;
> +	char name[MAX_ATTR_LEN];
> +	struct device_attribute dev_attr;
> +};
> +
> +struct platform_data {
> +	const struct attribute_group *attr_groups[MAX_SENSOR_TYPE + 1];
> +	u32 sensors_count; /* Total count of sensors from each group */
> +};
> +
> +/* Platform device representing all the ibmpowernv sensors */
> +static struct platform_device *pdevice;
> +
> +static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr,
> +			   char *buf)
> +{
> +	struct sensor_data *sdata = container_of(devattr, struct sensor_data,
> +						 dev_attr);
> +	ssize_t ret;
> +	u32 x;
> +
> +	ret = opal_get_sensor_data(sdata->id, &x);
> +	if (ret)
> +		return ret;
> +
> +	/* Convert temperature to milli-degrees */
> +	if (sdata->type == AMBIENT_TEMP)
> +		x *= 1000;
> +	/* Convert power to micro-watts */
> +	else if (sdata->type == POWER_INPUT)
> +		x *= 1000000;
> +
> +	return sprintf(buf, "%u\n", x);
> +}
> +
> +static int __init get_sensor_index_attr(const char *name, u32 *index,
> +					char *attr)
> +{
> +	char *hash_pos = strchr(name, '#');
> +	char buf[8] = { 0 };
> +	char *dash_pos;
> +	u32 copy_len;
> +
> +	if (!hash_pos)
> +		return -EINVAL;
> +
> +	dash_pos = strchr(hash_pos, '-');
> +	if (!dash_pos)
> +		return -EINVAL;
> +
> +	copy_len = dash_pos - hash_pos - 1;
> +	if (copy_len >= sizeof(buf))
> +		return -EINVAL;
> +
> +	strncpy(buf, hash_pos + 1, copy_len);
> +
> +	if (kstrtou32(buf, 10, index))
> +		return -EINVAL;
> +
smatch isn't going to like that. Please use

	int err;
	...
	err = kstrtou32(buf, 10, index));
	if (err)
		return err;

> +	strncpy(attr, dash_pos + 1, MAX_ATTR_LEN);
> +
> +	return 0;
> +}
> +
> +/*
> + * This function translates the DT node name into the 'hwmon' attribute name.
> + * IBMPOWERNV device node appear like cooling-fan#2-data, amb-temp#1-thrs etc.
> + * which need to be mapped as fan2_input, temp1_max respectively before
> + * populating them inside hwmon device class.
> + */
> +static int __init create_hwmon_attr_name(struct device *dev, enum sensors type,
> +					 const char *node_name,
> +					 char *hwmon_attr_name)
> +{
> +	char attr_suffix[MAX_ATTR_LEN];
> +	char *attr_name;
> +	u32 index;
> +	int err;
> +
> +	err = get_sensor_index_attr(node_name, &index, attr_suffix);
> +	if (err) {
> +		dev_err(dev, "Sensor device node name '%s' is invalid\n",
> +			node_name);
> +		return err;
> +	}
> +
> +	if (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX)) {
> +		attr_name = "fault";
> +	} else if (!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX)) {
> +		attr_name = "input";
> +	} else if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) {
> +		if (type == AMBIENT_TEMP)
> +			attr_name = "max";
> +		else if (type == FAN)
> +			attr_name = "min";
> +		else
> +			return -ENOENT;
> +	} else {
> +		return -ENOENT;
> +	}
> +
> +	snprintf(hwmon_attr_name, MAX_ATTR_LEN, "%s%d_%s",
> +		 sensor_groups[type].name, index, attr_name);
> +	return 0;
> +}
> +
> +static int __init populate_attr_groups(struct platform_device *pdev)
> +{
> +	struct platform_data *pdata = platform_get_drvdata(pdev);
> +	const struct attribute_group **pgroups = pdata->attr_groups;
> +	struct device_node *opal, *np;
> +	enum sensors type;
> +
> +	opal = of_find_node_by_path("/ibm,opal/sensors");
> +	if (!opal) {
> +		dev_err(&pdev->dev, "Opal node 'sensors' not found\n");
> +		return -ENODEV;
> +	}
> +
> +	for_each_child_of_node(opal, np) {
> +		if (np->name == NULL)
> +			continue;
> +
> +		for (type = 0; type < MAX_SENSOR_TYPE; type++)
> +			if (of_device_is_compatible(np,
> +					sensor_groups[type].compatible)) {
> +				sensor_groups[type].attr_count++;
> +				break;
> +			}
> +	}
> +
> +	of_node_put(opal);
> +
> +	for (type = 0; type < MAX_SENSOR_TYPE; type++) {
> +		sensor_groups[type].group.attrs = devm_kzalloc(&pdev->dev,
> +					sizeof(struct attribute *) *
> +					(sensor_groups[type].attr_count + 1),
> +					GFP_KERNEL);
> +		if (!sensor_groups[type].group.attrs)
> +			return -ENOMEM;
> +
> +		pgroups[type] = &sensor_groups[type].group;
> +		pdata->sensors_count += sensor_groups[type].attr_count;
> +		sensor_groups[type].attr_count = 0;
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * Iterate through the device tree for each child of 'sensors' node, create
> + * a sysfs attribute file, the file is named by translating the DT node name
> + * to the name required by the higher 'hwmon' driver like fan1_input, temp1_max
> + * etc..
> + */
> +static int __init create_device_attrs(struct platform_device *pdev)
> +{
> +	struct platform_data *pdata = platform_get_drvdata(pdev);
> +	const struct attribute_group **pgroups = pdata->attr_groups;
> +	struct device_node *opal, *np;
> +	struct sensor_data *sdata;
> +	const __be32 *sensor_id;
> +	enum sensors type;
> +	u32 count = 0;
> +	int err = 0;
> +
> +	opal = of_find_node_by_path("/ibm,opal/sensors");
> +	sdata = devm_kzalloc(&pdev->dev, pdata->sensors_count * sizeof(*sdata),
> +			     GFP_KERNEL);
> +	if (!sdata) {
> +		err = -ENOMEM;
> +		goto exit_put_node;
> +	}
> +
> +	for_each_child_of_node(opal, np) {
> +		if (np->name == NULL)
> +			continue;
> +
> +		for (type = 0; type < MAX_SENSOR_TYPE; type++)
> +			if (of_device_is_compatible(np,
> +					sensor_groups[type].compatible))
> +				break;
> +
> +		if (type == MAX_SENSOR_TYPE)
> +			continue;
> +
> +		sensor_id = of_get_property(np, "sensor-id", NULL);
> +		if (!sensor_id) {
> +			dev_info(&pdev->dev,
> +				 "'sensor-id' missing in the node '%s'\n",
> +				 np->name);
> +			continue;
> +		}
> +
> +		sdata[count].id = be32_to_cpup(sensor_id);
> +		sdata[count].type = type;
> +		err = create_hwmon_attr_name(&pdev->dev, type, np->name,
> +					     sdata[count].name);
> +		if (err)
> +			goto exit_put_node;
> +
> +		sysfs_attr_init(&sdata[count].dev_attr.attr);
> +		sdata[count].dev_attr.attr.name = sdata[count].name;
> +		sdata[count].dev_attr.attr.mode = S_IRUGO;
> +		sdata[count].dev_attr.show = show_sensor;
> +
> +		pgroups[type]->attrs[sensor_groups[type].attr_count++] =
> +				&sdata[count++].dev_attr.attr;
> +	}
> +
> +exit_put_node:
> +	of_node_put(opal);
> +	return err;
> +}
> +
> +static int __init ibmpowernv_probe(struct platform_device *pdev)
> +{
> +	struct platform_data *pdata;
> +	struct device *hwmon_dev;
> +	int err;
> +
> +	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> +	if (!pdata)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, pdata);
> +	pdata->sensors_count = 0;
> +	err = populate_attr_groups(pdev);
> +	if (err)
> +		return err;
> +
> +	/* Create sysfs attribute data for each sensor found in the DT */
> +	err = create_device_attrs(pdev);
> +	if (err)
> +		return err;
> +
> +	/* Finally, register with hwmon */
> +	hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, DRVNAME,
> +							   pdata,
> +							   pdata->attr_groups);
> +
> +	return PTR_ERR_OR_ZERO(hwmon_dev);
> +}
> +
> +static struct platform_driver ibmpowernv_driver = {
> +	.driver = {
> +		.owner = THIS_MODULE,
> +		.name = DRVNAME,
> +	},
> +};
> +
> +static int __init ibmpowernv_init(void)
> +{
> +	int err;
> +
> +	pdevice = platform_device_alloc(DRVNAME, 0);
> +	if (!pdevice) {
> +		pr_err("Device allocation failed\n");
> +		err = -ENOMEM;
> +		goto exit;
> +	}
> +
> +	err = platform_device_add(pdevice);
> +	if (err) {
> +		pr_err("Device addition failed (%d)\n", err);
> +		goto exit_device_put;
> +	}
> +
> +	err = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe);
> +	if (err) {
> +		pr_err("Platfrom driver probe failed\n");
> +		goto exit_device_del;
> +	}
> +
> +	return 0;
> +
> +exit_device_del:
> +	platform_device_del(pdevice);
> +exit_device_put:
> +	platform_device_put(pdevice);
> +exit:
> +	return err;
> +}
> +
> +static void __exit ibmpowernv_exit(void)
> +{
> +	platform_driver_unregister(&ibmpowernv_driver);
> +	platform_device_unregister(pdevice);
> +}
> +
> +MODULE_AUTHOR("Neelesh Gupta <neelegup@linux.vnet.ibm.com>");
> +MODULE_DESCRIPTION("IBM POWERNV platform sensors");
> +MODULE_LICENSE("GPL");
> +
> +module_init(ibmpowernv_init);
> +module_exit(ibmpowernv_exit);
>
>
>

WARNING: multiple messages have this Message-ID (diff)
From: Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
To: Neelesh Gupta
	<neelegup-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
	jdelvare-l3A5Bk7waGM@public.gmane.org,
	lm-sensors-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org
Cc: benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org,
	svaidy-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org,
	sbhat-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org,
	"devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org"
	<devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
Subject: Re: [PATCH v4] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature
Date: Fri, 04 Jul 2014 19:25:36 -0700	[thread overview]
Message-ID: <53B76220.9090900@roeck-us.net> (raw)
In-Reply-To: <20140704105343.22437.52125.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>

On 07/04/2014 04:02 AM, Neelesh Gupta wrote:
> This patch adds basic kernel support for reading power values, fan
> speed rpm, voltage and temperature data on powernv platforms which will
> be exported to user space through sysfs interface.
>

Hi Neelesh,

Copying devicetree mailing list. Please copy it on the next (hopefully final)
revision; devicetree maintainers at least need a chance to comment.
[ Yes, I understand this is a shipping product, but still ... ]

I am ok with the code except for a couple of minor nitpicks (see below).

Thanks,
Guenter

> Test results:
> -------------
> [root@tul163p1 ~]# sensors
> ibmpowernv-isa-0000
> Adapter: ISA adapter
> fan1:        5567 RPM  (min =    0 RPM)
> fan2:        5232 RPM  (min =    0 RPM)
> fan3:        5532 RPM  (min =    0 RPM)
> fan4:        4945 RPM  (min =    0 RPM)
> fan5:           0 RPM  (min =    0 RPM)
> fan6:           0 RPM  (min =    0 RPM)
> fan7:        7392 RPM  (min =    0 RPM)
> fan8:        7936 RPM  (min =    0 RPM)
> temp1:        +39.0°C  (high =  +0.0°C)
> power1:      191.00 W
>
> [root@tul163p1 ~]# ls /sys/devices/platform/
> alarmtimer  ibmpowernv.0  power  rtc-generic  serial8250  uevent
> [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/hwmon/hwmon0/
> device	    fan2_min	fan4_min    fan6_min	fan8_min   power
> fan1_fault  fan3_fault	fan5_fault  fan7_fault	in1_fault  power1_input
> fan1_input  fan3_input	fan5_input  fan7_input	in2_fault  subsystem
> fan1_min    fan3_min	fan5_min    fan7_min	in3_fault  temp1_input
> fan2_fault  fan4_fault	fan6_fault  fan8_fault	in4_fault  temp1_max
> fan2_input  fan4_input	fan6_input  fan8_input	name	   uevent
> [root@tul163p1 ~]#
> [root@tul163p1 ~]# ls /sys/class/hwmon/hwmon0/
> device	    fan2_min	fan4_min    fan6_min	fan8_min   power
> fan1_fault  fan3_fault	fan5_fault  fan7_fault	in1_fault  power1_input
> fan1_input  fan3_input	fan5_input  fan7_input	in2_fault  subsystem
> fan1_min    fan3_min	fan5_min    fan7_min	in3_fault  temp1_input
> fan2_fault  fan4_fault	fan6_fault  fan8_fault	in4_fault  temp1_max
> fan2_input  fan4_input	fan6_input  fan8_input	name	   uevent
> [root@tul163p1 ~]#
>
> Signed-off-by: Neelesh Gupta <neelegup-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
> ---
>
> Changes in v4
> =============
> - Replaced pr_err() with dev_err() for loggin print messages.
> - Using kstrtou32() function for converting string to u32 instead of sscanf().
>
> Changes in v3
> =============
> - Fixed an endianness bug leading the driver to break on LE.
> - Fixed a bug that when one of the 'attribute_group' not populated, following
>    groups attributes were dropped.
> - Rewrite the get_sensor_index_attr() function to handle all the error scenarios
>    like 'sscanf' etc.
> - Fixed all the errors/warnings related to coding style/whitespace.
> - Added 'Documentation' files.
> - Addressed remaining review comments on V2.
>
> Changes in v2
> =============
> - Generic use of devm_* functions in hwmon like using devm_kzalloc() for dynamic
>    memory request, avoiding the need to explicit free of memory.
>    Adding 'struct attribute_group' as member of platform data structure to be
>    populated and then passed to devm_hwmon_device_register_with_groups().
>
>    Note: Having an array of pointers of 'attribute_group' and each group
>    corresponds to 'enum sensors' type. Not completely sure, if it's ideal or
>    could have just one group populated with attributes of sensor types?
>
> - 'ibmpowernv' is not hot-pluggable device so moving 'platform_driver' callback
>    function (probe) as part of __init code.
> - Fixed issues related to coding style.
> - Other general comments in v1.
>
>   .../devicetree/bindings/hwmon/ibmpowernv.txt       |   27 +
>   Documentation/hwmon/ibmpowernv                     |   41 ++
>   drivers/hwmon/Kconfig                              |   11 +
>   drivers/hwmon/Makefile                             |    1
>   drivers/hwmon/ibmpowernv.c                         |  362 ++++++++++++++++++++
>   5 files changed, 442 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/hwmon/ibmpowernv.txt
>   create mode 100644 Documentation/hwmon/ibmpowernv
>   create mode 100644 drivers/hwmon/ibmpowernv.c
>
> diff --git a/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt
> new file mode 100644
> index 0000000..e3bd1eb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt
> @@ -0,0 +1,27 @@
> +IBM POWERNV platform sensors
> +----------------------------
> +
> +Required node properties:
> +- compatible: must be one of
> +		"ibm,opal-sensor-cooling-fan"
> +		"ibm,opal-sensor-amb-temp"
> +		"ibm,opal-sensor-power-supply"
> +		"ibm,opal-sensor-power"
> +- sensor-id: an opaque id provided by the firmware to the kernel, identifies a
> +	     given sensor and its attribute data
> +
> +Example sensors node:
> +
> +cooling-fan#8-data {
> +	sensor-id = <0x7052107>;
> +	phandle = <0x10000028>;
> +	linux,phandle = <0x10000028>;
> +	compatible = "ibm,opal-sensor-cooling-fan";

phandle and linux-phandle are neither documented nor used. Either document or drop.

> +};
> +
> +amb-temp#1-thrs {
> +	sensor-id = <0x5096000>;
> +	phandle = <0x10000017>;
> +	linux,phandle = <0x10000017>;
> +	compatible = "ibm,opal-sensor-amb-temp";
> +};
> diff --git a/Documentation/hwmon/ibmpowernv b/Documentation/hwmon/ibmpowernv
> new file mode 100644
> index 0000000..644245a
> --- /dev/null
> +++ b/Documentation/hwmon/ibmpowernv
> @@ -0,0 +1,41 @@
> +Kernel Driver IBMPOWENV
> +=======================
> +
> +Supported systems:
> +  * Any recent IBM P servers based on POWERNV platform
> +
> +Author: Neelesh Gupta
> +
> +Description
> +-----------
> +
> +This driver implements reading the platform sensors data like temperature/fan/
> +voltage/power for 'POWERNV' platform.
> +
> +The driver uses the platform device infrastructure. It probes the device tree
> +for sensor devices during the __init phase and registers them with the 'hwmon'.
> +'hwmon' populates the 'sysfs' tree having attribute files, each for a given
> +sensor type and its attribute data.
> +
> +All the nodes in the DT appear under "/ibm,opal/sensors" and each valid node in
> +the DT maps to an attribute file in 'sysfs'. The node exports unique 'sensor-id'
> +which the driver uses to make an OPAL call to the firmware.
> +
> +Usage notes
> +-----------
> +The driver is built statically with the kernel by enabling the config
> +CONFIG_SENSORS_IBMPOWERNV. It can also be built as module 'ibmpowernv'.
> +
> +Sysfs attributes
> +----------------
> +
> +fanX_input		Measured RPM value.
> +fanX_min		Threshold RPM for alert generation.
> +fanX_fault		0: No fail condition
> +			1: Failing fan
> +tempX_input		Measured ambient temperature.
> +tempX_max		Threshold ambient temperature for alert generation.
> +inX_input		Measured power supply voltage
> +inX_fault		0: No fail condition.
> +			1: Failing power supply.
> +power1_input		System power consumption (microWatt)
> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> index 02d3d85..29c3fcb 100644
> --- a/drivers/hwmon/Kconfig
> +++ b/drivers/hwmon/Kconfig
> @@ -554,6 +554,17 @@ config SENSORS_IBMPEX
>   	  This driver can also be built as a module.  If so, the module
>   	  will be called ibmpex.
>
> +config SENSORS_IBMPOWERNV
> +	tristate "IBM POWERNV platform sensors"
> +	depends on PPC_POWERNV
> +	default y
> +	help
> +	  If you say yes here you get support for the temperature/fan/power
> +	  sensors on your PowerNV platform.
> +
> +	  This driver can also be built as a module. If so, the module
> +	  will be called ibmpowernv.
> +
>   config SENSORS_IIO_HWMON
>   	tristate "Hwmon driver that uses channels specified via iio maps"
>   	depends on IIO
> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> index 3dc0f02..fc4ed26 100644
> --- a/drivers/hwmon/Makefile
> +++ b/drivers/hwmon/Makefile
> @@ -71,6 +71,7 @@ obj-$(CONFIG_SENSORS_ULTRA45)	+= ultra45_env.o
>   obj-$(CONFIG_SENSORS_I5K_AMB)	+= i5k_amb.o
>   obj-$(CONFIG_SENSORS_IBMAEM)	+= ibmaem.o
>   obj-$(CONFIG_SENSORS_IBMPEX)	+= ibmpex.o
> +obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o
>   obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o
>   obj-$(CONFIG_SENSORS_INA209)	+= ina209.o
>   obj-$(CONFIG_SENSORS_INA2XX)	+= ina2xx.o
> diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c
> new file mode 100644
> index 0000000..44dcd99
> --- /dev/null
> +++ b/drivers/hwmon/ibmpowernv.c
> @@ -0,0 +1,362 @@
> +/*
> + * IBM PowerNV platform sensors for temperature/fan/voltage/power
> + * Copyright (C) 2014 IBM
> + *
> + * 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.
> + */
> +
> +#define DRVNAME		"ibmpowernv"
> +#define pr_fmt(fmt)	DRVNAME ": " fmt
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/hwmon.h>
> +#include <linux/hwmon-sysfs.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>
> +
> +#include <linux/platform_device.h>
> +#include <asm/opal.h>
> +#include <linux/err.h>
> +
> +#define MAX_ATTR_LEN	32
> +
> +/* Sensor suffix name from DT */
> +#define DT_FAULT_ATTR_SUFFIX		"faulted"
> +#define DT_DATA_ATTR_SUFFIX		"data"
> +#define DT_THRESHOLD_ATTR_SUFFIX	"thrs"
> +
> +/*
> + * Enumerates all the types of sensors in the POWERNV platform and does index
> + * into 'struct sensor_group'
> + */
> +enum sensors {
> +	FAN,
> +	AMBIENT_TEMP,
> +	POWER_SUPPLY,
> +	POWER_INPUT,
> +	MAX_SENSOR_TYPE,
> +};
> +
> +static struct sensor_group {
> +	const char *name;
> +	const char *compatible;
> +	struct attribute_group group;
> +	u32 attr_count;
> +} sensor_groups[] = {
> +	{"fan", "ibm,opal-sensor-cooling-fan"},
> +	{"temp", "ibm,opal-sensor-amb-temp"},
> +	{"in", "ibm,opal-sensor-power-supply"},
> +	{"power", "ibm,opal-sensor-power"}
> +};
> +
> +struct sensor_data {
> +	u32 id; /* An opaque id of the firmware for each sensor */
> +	enum sensors type;
> +	char name[MAX_ATTR_LEN];
> +	struct device_attribute dev_attr;
> +};
> +
> +struct platform_data {
> +	const struct attribute_group *attr_groups[MAX_SENSOR_TYPE + 1];
> +	u32 sensors_count; /* Total count of sensors from each group */
> +};
> +
> +/* Platform device representing all the ibmpowernv sensors */
> +static struct platform_device *pdevice;
> +
> +static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr,
> +			   char *buf)
> +{
> +	struct sensor_data *sdata = container_of(devattr, struct sensor_data,
> +						 dev_attr);
> +	ssize_t ret;
> +	u32 x;
> +
> +	ret = opal_get_sensor_data(sdata->id, &x);
> +	if (ret)
> +		return ret;
> +
> +	/* Convert temperature to milli-degrees */
> +	if (sdata->type == AMBIENT_TEMP)
> +		x *= 1000;
> +	/* Convert power to micro-watts */
> +	else if (sdata->type == POWER_INPUT)
> +		x *= 1000000;
> +
> +	return sprintf(buf, "%u\n", x);
> +}
> +
> +static int __init get_sensor_index_attr(const char *name, u32 *index,
> +					char *attr)
> +{
> +	char *hash_pos = strchr(name, '#');
> +	char buf[8] = { 0 };
> +	char *dash_pos;
> +	u32 copy_len;
> +
> +	if (!hash_pos)
> +		return -EINVAL;
> +
> +	dash_pos = strchr(hash_pos, '-');
> +	if (!dash_pos)
> +		return -EINVAL;
> +
> +	copy_len = dash_pos - hash_pos - 1;
> +	if (copy_len >= sizeof(buf))
> +		return -EINVAL;
> +
> +	strncpy(buf, hash_pos + 1, copy_len);
> +
> +	if (kstrtou32(buf, 10, index))
> +		return -EINVAL;
> +
smatch isn't going to like that. Please use

	int err;
	...
	err = kstrtou32(buf, 10, index));
	if (err)
		return err;

> +	strncpy(attr, dash_pos + 1, MAX_ATTR_LEN);
> +
> +	return 0;
> +}
> +
> +/*
> + * This function translates the DT node name into the 'hwmon' attribute name.
> + * IBMPOWERNV device node appear like cooling-fan#2-data, amb-temp#1-thrs etc.
> + * which need to be mapped as fan2_input, temp1_max respectively before
> + * populating them inside hwmon device class.
> + */
> +static int __init create_hwmon_attr_name(struct device *dev, enum sensors type,
> +					 const char *node_name,
> +					 char *hwmon_attr_name)
> +{
> +	char attr_suffix[MAX_ATTR_LEN];
> +	char *attr_name;
> +	u32 index;
> +	int err;
> +
> +	err = get_sensor_index_attr(node_name, &index, attr_suffix);
> +	if (err) {
> +		dev_err(dev, "Sensor device node name '%s' is invalid\n",
> +			node_name);
> +		return err;
> +	}
> +
> +	if (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX)) {
> +		attr_name = "fault";
> +	} else if (!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX)) {
> +		attr_name = "input";
> +	} else if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) {
> +		if (type == AMBIENT_TEMP)
> +			attr_name = "max";
> +		else if (type == FAN)
> +			attr_name = "min";
> +		else
> +			return -ENOENT;
> +	} else {
> +		return -ENOENT;
> +	}
> +
> +	snprintf(hwmon_attr_name, MAX_ATTR_LEN, "%s%d_%s",
> +		 sensor_groups[type].name, index, attr_name);
> +	return 0;
> +}
> +
> +static int __init populate_attr_groups(struct platform_device *pdev)
> +{
> +	struct platform_data *pdata = platform_get_drvdata(pdev);
> +	const struct attribute_group **pgroups = pdata->attr_groups;
> +	struct device_node *opal, *np;
> +	enum sensors type;
> +
> +	opal = of_find_node_by_path("/ibm,opal/sensors");
> +	if (!opal) {
> +		dev_err(&pdev->dev, "Opal node 'sensors' not found\n");
> +		return -ENODEV;
> +	}
> +
> +	for_each_child_of_node(opal, np) {
> +		if (np->name == NULL)
> +			continue;
> +
> +		for (type = 0; type < MAX_SENSOR_TYPE; type++)
> +			if (of_device_is_compatible(np,
> +					sensor_groups[type].compatible)) {
> +				sensor_groups[type].attr_count++;
> +				break;
> +			}
> +	}
> +
> +	of_node_put(opal);
> +
> +	for (type = 0; type < MAX_SENSOR_TYPE; type++) {
> +		sensor_groups[type].group.attrs = devm_kzalloc(&pdev->dev,
> +					sizeof(struct attribute *) *
> +					(sensor_groups[type].attr_count + 1),
> +					GFP_KERNEL);
> +		if (!sensor_groups[type].group.attrs)
> +			return -ENOMEM;
> +
> +		pgroups[type] = &sensor_groups[type].group;
> +		pdata->sensors_count += sensor_groups[type].attr_count;
> +		sensor_groups[type].attr_count = 0;
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * Iterate through the device tree for each child of 'sensors' node, create
> + * a sysfs attribute file, the file is named by translating the DT node name
> + * to the name required by the higher 'hwmon' driver like fan1_input, temp1_max
> + * etc..
> + */
> +static int __init create_device_attrs(struct platform_device *pdev)
> +{
> +	struct platform_data *pdata = platform_get_drvdata(pdev);
> +	const struct attribute_group **pgroups = pdata->attr_groups;
> +	struct device_node *opal, *np;
> +	struct sensor_data *sdata;
> +	const __be32 *sensor_id;
> +	enum sensors type;
> +	u32 count = 0;
> +	int err = 0;
> +
> +	opal = of_find_node_by_path("/ibm,opal/sensors");
> +	sdata = devm_kzalloc(&pdev->dev, pdata->sensors_count * sizeof(*sdata),
> +			     GFP_KERNEL);
> +	if (!sdata) {
> +		err = -ENOMEM;
> +		goto exit_put_node;
> +	}
> +
> +	for_each_child_of_node(opal, np) {
> +		if (np->name == NULL)
> +			continue;
> +
> +		for (type = 0; type < MAX_SENSOR_TYPE; type++)
> +			if (of_device_is_compatible(np,
> +					sensor_groups[type].compatible))
> +				break;
> +
> +		if (type == MAX_SENSOR_TYPE)
> +			continue;
> +
> +		sensor_id = of_get_property(np, "sensor-id", NULL);
> +		if (!sensor_id) {
> +			dev_info(&pdev->dev,
> +				 "'sensor-id' missing in the node '%s'\n",
> +				 np->name);
> +			continue;
> +		}
> +
> +		sdata[count].id = be32_to_cpup(sensor_id);
> +		sdata[count].type = type;
> +		err = create_hwmon_attr_name(&pdev->dev, type, np->name,
> +					     sdata[count].name);
> +		if (err)
> +			goto exit_put_node;
> +
> +		sysfs_attr_init(&sdata[count].dev_attr.attr);
> +		sdata[count].dev_attr.attr.name = sdata[count].name;
> +		sdata[count].dev_attr.attr.mode = S_IRUGO;
> +		sdata[count].dev_attr.show = show_sensor;
> +
> +		pgroups[type]->attrs[sensor_groups[type].attr_count++] =
> +				&sdata[count++].dev_attr.attr;
> +	}
> +
> +exit_put_node:
> +	of_node_put(opal);
> +	return err;
> +}
> +
> +static int __init ibmpowernv_probe(struct platform_device *pdev)
> +{
> +	struct platform_data *pdata;
> +	struct device *hwmon_dev;
> +	int err;
> +
> +	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> +	if (!pdata)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, pdata);
> +	pdata->sensors_count = 0;
> +	err = populate_attr_groups(pdev);
> +	if (err)
> +		return err;
> +
> +	/* Create sysfs attribute data for each sensor found in the DT */
> +	err = create_device_attrs(pdev);
> +	if (err)
> +		return err;
> +
> +	/* Finally, register with hwmon */
> +	hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, DRVNAME,
> +							   pdata,
> +							   pdata->attr_groups);
> +
> +	return PTR_ERR_OR_ZERO(hwmon_dev);
> +}
> +
> +static struct platform_driver ibmpowernv_driver = {
> +	.driver = {
> +		.owner = THIS_MODULE,
> +		.name = DRVNAME,
> +	},
> +};
> +
> +static int __init ibmpowernv_init(void)
> +{
> +	int err;
> +
> +	pdevice = platform_device_alloc(DRVNAME, 0);
> +	if (!pdevice) {
> +		pr_err("Device allocation failed\n");
> +		err = -ENOMEM;
> +		goto exit;
> +	}
> +
> +	err = platform_device_add(pdevice);
> +	if (err) {
> +		pr_err("Device addition failed (%d)\n", err);
> +		goto exit_device_put;
> +	}
> +
> +	err = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe);
> +	if (err) {
> +		pr_err("Platfrom driver probe failed\n");
> +		goto exit_device_del;
> +	}
> +
> +	return 0;
> +
> +exit_device_del:
> +	platform_device_del(pdevice);
> +exit_device_put:
> +	platform_device_put(pdevice);
> +exit:
> +	return err;
> +}
> +
> +static void __exit ibmpowernv_exit(void)
> +{
> +	platform_driver_unregister(&ibmpowernv_driver);
> +	platform_device_unregister(pdevice);
> +}
> +
> +MODULE_AUTHOR("Neelesh Gupta <neelegup-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>");
> +MODULE_DESCRIPTION("IBM POWERNV platform sensors");
> +MODULE_LICENSE("GPL");
> +
> +module_init(ibmpowernv_init);
> +module_exit(ibmpowernv_exit);
>
>
>

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

  parent reply	other threads:[~2014-07-05  2:25 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-04 11:02 [PATCH v4] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature Neelesh Gupta
2014-07-04 11:14 ` [lm-sensors] " Neelesh Gupta
     [not found] ` <20140704105343.22437.52125.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2014-07-05  2:25   ` Guenter Roeck [this message]
2014-07-05  2:25     ` Guenter Roeck
2014-07-05  2:25     ` Guenter Roeck
2014-07-07  6:56     ` [lm-sensors] [PATCH v4] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperatur Benjamin Herrenschmidt
2014-07-07  6:56       ` [PATCH v4] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature Benjamin Herrenschmidt
2014-07-07  6:56       ` Benjamin Herrenschmidt
2014-07-07 12:59       ` [lm-sensors] [PATCH v4] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperatur Guenter Roeck
2014-07-07 12:59         ` [PATCH v4] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature Guenter Roeck
2014-07-07 12:59         ` Guenter Roeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=53B76220.9090900@roeck-us.net \
    --to=linux@roeck-us.net \
    --cc=benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org \
    --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=jdelvare-l3A5Bk7waGM@public.gmane.org \
    --cc=linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org \
    --cc=lm-sensors-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org \
    --cc=neelegup-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org \
    --cc=sbhat-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org \
    --cc=svaidy-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.