All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <53956D06.40800@linux.vnet.ibm.com>

diff --git a/a/1.txt b/N1/1.txt
index e7fffed..05732f9 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -1,336 +1,598 @@
-Ck9uIDA1LzI4LzIwMTQgMTI6NTMgUE0sIEd1ZW50ZXIgUm9lY2sgd3JvdGU6Cj4gT24gMDUvMTkv
-MjAxNCAwNzoyNiBBTSwgTmVlbGVzaCBHdXB0YSB3cm90ZToKPj4gVGhpcyBwYXRjaCBhZGRzIGJh
-c2ljIGtlcm5lbCBlbmFibGVtZW50IGZvciByZWFkaW5nIHBvd2VyIHZhbHVlcywgZmFuCj4+IHNw
-ZWVkIHJwbSBhbmQgdGVtcGVyYXR1cmUgdmFsdWVzIG9uIHBvd2VybnYgcGxhdGZvcm1zIHdoaWNo
-IHdpbGwKPj4gYmUgZXhwb3J0ZWQgdG8gdXNlciBzcGFjZSB0aHJvdWdoIHN5c2ZzIGludGVyZmFj
-ZS4KPj4KPj4gVGVzdCByZXN1bHRzOgo+PiAtLS0tLS0tLS0tLS0tCj4+IFtyb290QHR1bDE2M3Ax
-IH5dIyBzZW5zb3JzCj4+IGlibXBvd2VybnYtaXNhLTAwMDAKPj4gQWRhcHRlcjogSVNBIGFkYXB0
-ZXIKPj4gZmFuMTogICAgICAgIDU0ODcgUlBNICAobWluID0gICAgMCBSUE0pCj4+IGZhbjI6ICAg
-ICAgICA1MTUyIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+PiBmYW4zOiAgICAgICAgNTU5MCBSUE0g
-IChtaW4gPSAgICAwIFJQTSkKPj4gZmFuNDogICAgICAgIDQ5NjMgUlBNICAobWluID0gICAgMCBS
-UE0pCj4+IGZhbjU6ICAgICAgICAgICAwIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+PiBmYW42OiAg
-ICAgICAgICAgMCBSUE0gIChtaW4gPSAgICAwIFJQTSkKPj4gZmFuNzogICAgICAgIDc0ODggUlBN
-ICAobWluID0gICAgMCBSUE0pCj4+IGZhbjg6ICAgICAgICA3OTQ0IFJQTSAgKG1pbiA9ICAgIDAg
-UlBNKQo+PiB0ZW1wMTogICAgICAgICszOS4wwrBDICAoaGlnaCA9ICArMC4wwrBDKQo+PiBwb3dl
-cjE6ICAgICAgMTkyLjAwIFcKPj4KPj4gW3Jvb3RAdHVsMTYzcDEgfl0jIGxzIC9zeXMvZGV2aWNl
-cy9wbGF0Zm9ybS8KPj4gYWxhcm10aW1lciAgaWJtcG93ZXJudi4wICBydGMtZ2VuZXJpYyAgc2Vy
-aWFsODI1MCAgdWV2ZW50Cj4+IFtyb290QHR1bDE2M3AxIH5dIyBscyAvc3lzL2RldmljZXMvcGxh
-dGZvcm0vaWJtcG93ZXJudi4wLwo+PiBkcml2ZXIvICAgIGh3bW9uLyAgICAgbW9kYWxpYXMgICBz
-dWJzeXN0ZW0vIHVldmVudAo+PiBbcm9vdEB0dWwxNjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3Bs
-YXRmb3JtL2libXBvd2VybnYuMC9od21vbi9od21vbjAvCj4+IGRldmljZSAgICAgICAgZmFuMl9t
-aW4gICAgZmFuNF9taW4gICAgZmFuNl9taW4gICAgZmFuOF9taW4gcG93ZXIxX2lucHV0Cj4+IGZh
-bjFfZmF1bHQgIGZhbjNfZmF1bHQgICAgZmFuNV9mYXVsdCAgZmFuN19mYXVsdCAgICBpbjFfZmF1
-bHQgc3Vic3lzdGVtCj4+IGZhbjFfaW5wdXQgIGZhbjNfaW5wdXQgICAgZmFuNV9pbnB1dCAgZmFu
-N19pbnB1dCAgICBpbjJfZmF1bHQgCj4+IHRlbXAxX2lucHV0Cj4+IGZhbjFfbWluICAgIGZhbjNf
-bWluICAgIGZhbjVfbWluICAgIGZhbjdfbWluICAgIGluM19mYXVsdCB0ZW1wMV9tYXgKPj4gZmFu
-Ml9mYXVsdCAgZmFuNF9mYXVsdCAgICBmYW42X2ZhdWx0ICBmYW44X2ZhdWx0ICAgIGluNF9mYXVs
-dCB1ZXZlbnQKPj4gZmFuMl9pbnB1dCAgZmFuNF9pbnB1dCAgICBmYW42X2lucHV0ICBmYW44X2lu
-cHV0ICAgIG5hbWUKPj4gW3Jvb3RAdHVsMTYzcDEgfl0jCj4+IFtyb290QHR1bDE2M3AxIH5dIyBs
-cyAvc3lzL2NsYXNzL2h3bW9uL2h3bW9uMC8KPj4gZGV2aWNlICAgICAgICBmYW4yX21pbiAgICBm
-YW40X21pbiAgICBmYW42X21pbiAgICBmYW44X21pbiBwb3dlcjFfaW5wdXQKPj4gZmFuMV9mYXVs
-dCAgZmFuM19mYXVsdCAgICBmYW41X2ZhdWx0ICBmYW43X2ZhdWx0ICAgIGluMV9mYXVsdCBzdWJz
-eXN0ZW0KPj4gZmFuMV9pbnB1dCAgZmFuM19pbnB1dCAgICBmYW41X2lucHV0ICBmYW43X2lucHV0
-ICAgIGluMl9mYXVsdCAKPj4gdGVtcDFfaW5wdXQKPj4gZmFuMV9taW4gICAgZmFuM19taW4gICAg
-ZmFuNV9taW4gICAgZmFuN19taW4gICAgaW4zX2ZhdWx0IHRlbXAxX21heAo+PiBmYW4yX2ZhdWx0
-ICBmYW40X2ZhdWx0ICAgIGZhbjZfZmF1bHQgIGZhbjhfZmF1bHQgICAgaW40X2ZhdWx0IHVldmVu
-dAo+PiBmYW4yX2lucHV0ICBmYW40X2lucHV0ICAgIGZhbjZfaW5wdXQgIGZhbjhfaW5wdXQgICAg
-bmFtZQo+PiBbcm9vdEB0dWwxNjNwMSB+XSMKPj4KPgo+Cj4gVGhlIGluWF9mYXVsdCBhdHRyaWJ1
-dGVzIGRvbid0IHJlYWxseSBtYWtlIG11Y2ggc2Vuc2UuIF9mYXVsdCAKPiBhdHRyaWJ1dGVzIHdp
-dGhvdXQKPiBfaW5wdXQgYXR0cmlidXRlcyBkb24ndCBoYXZlIGFueSB2YWx1ZSBhbmQgYXJlLCBh
-cyB5b3Ugbm90aWNlZCwgbm90IAo+IGRpc3BsYXllZAo+IHdpdGggdGhlIHNlbnNvcnMgY29tbWFu
-ZC4gSXMgdGhpcyBhIHByb2JsZW0gaW4gdGVoIGRldmljZXRyZWUgZGF0YSBvciAKPiBkbyB5b3UK
-PiByZWFsbHkgaGF2ZSB2b2x0YWdlIGZhdWx0cyB3aXRob3V0IHZvbHRhZ2VzID8KClRoZXJlIGlz
-IG5vIGlzc3VlIHdpdGggdGhlIGRldmljZSBkYXRhLCBzb21laG93IEknbSBnZXR0aW5nIG9ubHkg
-dGhlIApfZmF1bHQgYXR0cmlidXRlCmZvciB0aGUgaW5YXyAocG93ZXItc3VwcGx5KSBhdHRyaWJ1
-dGVzLgoKPgo+PiBTaWduZWQtb2ZmLWJ5OiBOZWVsZXNoIEd1cHRhIDxuZWVsZWd1cEBsaW51eC52
-bmV0LmlibS5jb20+Cj4+IC0tLQo+Pgo+IENoZWNrcGF0Y2ggc2F5czoKPgo+IHRvdGFsOiA4IGVy
-cm9ycywgMTEgd2FybmluZ3MsIDM4OSBsaW5lcyBjaGVja2VkCj4KPiBOT1RFOiB3aGl0ZXNwYWNl
-IGVycm9ycyBkZXRlY3RlZCwgeW91IG1heSB3aXNoIHRvIHVzZSAKPiBzY3JpcHRzL2NsZWFucGF0
-Y2ggb3IKPiAgICAgICBzY3JpcHRzL2NsZWFuZmlsZQo+Cj4gd2hpY2ggc2hvdWxkIHJlYWxseSBu
-b3QgaGFwcGVuIGF0IHRoaXMgcG9pbnQuCj4KPiBQbGVhc2UgbWFrZSBzdXJlIHlvdSBmb2xsb3cg
-Q29kaW5nU3R5bGUuIGNoZWNrcGF0Y2ggLS1zdHJpY3QgcG9pbnRzIHRvIAo+IGEgbnVtYmVyCj4g
-b2YgYWRkaXRpb25hbCB2aW9sYXRpb25zLgo+Cj4gTW9yZSBjb21tZW50cyBpbmxpbmUuCgpGaXhl
-ZCBhbGwgb2YgdGhlc2UgaXNzdWVzIHJlbGF0ZWQgdG8gY29kaW5nIHN0eWxlLgoKPgo+PiBDaGFu
-Z2VzIGluIHYyCj4+ID09PT09PT09PT09PT0KPj4gLSBHZW5lcmljIHVzZSBvZiBkZXZtXyogZnVu
-Y3Rpb25zIGluIGh3bW9uIGxpa2UgdXNpbmcgZGV2bV9remFsbG9jKCkgCj4+IGZvciBkeW5hbWlj
-Cj4+ICAgIG1lbW9yeSByZXF1ZXN0LCBhdm9pZGluZyB0aGUgbmVlZCB0byBleHBsaWNpdCBmcmVl
-IG9mIG1lbW9yeS4KPj4gICAgQWRkaW5nICdzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwJyBhcyBtZW1i
-ZXIgb2YgcGxhdGZvcm0gZGF0YSAKPj4gc3RydWN0dXJlIHRvIGJlCj4+ICAgIHBvcHVsYXRlZCBh
-bmQgdGhlbiBwYXNzZWQgdG8gCj4+IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhfZ3Jv
-dXBzKCkuCj4+Cj4+ICAgIE5vdGU6IEhhdmluZyBhbiBhcnJheSBvZiBwb2ludGVycyBvZiAnYXR0
-cmlidXRlX2dyb3VwJyBhbmQgZWFjaCBncm91cAo+PiAgICBjb3JyZXNwb25kcyB0byAnZW51bSBz
-ZW5zb3JzJyB0eXBlLiBOb3QgY29tcGxldGVseSBzdXJlLCBpZiBpdCdzIAo+PiBpZGVhbCBvcgo+
-PiAgICBjb3VsZCBoYXZlIGp1c3Qgb25lIGdyb3VwIHBvcHVsYXRlZCB3aXRoIGF0dHJpYnV0ZXMg
-b2Ygc2Vuc29yIHR5cGVzPwo+Pgo+IFlvdXIgY2FsbCwgcmVhbGx5OyB3aGF0ZXZlciBpcyBlYXNp
-ZXIgZm9yIHlvdS4gSSB3b24ndCBkaWN0YXRlIG9uZSBvciAKPiB0aGUgb3RoZXIuCj4KPiBRdWVz
-dGlvbiB0aG91Z2ggaXMgd2hhdCBoYXBwZW5zIGlmIG9uZSBncm91cCBpcyBub3QgcG9wdWxhdGVk
-LiBJZiBJIAo+IHVuZGVyc3RhbmQKPiB0aGUgY29kZSBjb3JyZWN0bHkgdGhpcyB3aWxsIHJlc3Vs
-dCBpbiB0aGUgcmVtYWluaW5nIGdyb3VwcyB0byBiZSAKPiAnZHJvcHBlZCcsCj4gaWUgbm90IGRp
-c3BsYXllZCBhdCBhbGwuCgpZZXMsIHNob3VsZCBiZSBmaXhlZC4KCj4KPj4gLSAnaWJtcG93ZXJu
-dicgaXMgbm90IGhvdC1wbHVnZ2FibGUgZGV2aWNlIHNvIG1vdmluZyAKPj4gJ3BsYXRmb3JtX2Ry
-aXZlcicgY2FsbGJhY2sKPj4gICAgZnVuY3Rpb24gKHByb2JlKSBhcyBwYXJ0IG9mIF9faW5pdCBj
-b2RlLgo+PiAtIEZpeGVkIGlzc3VlcyByZWxhdGVkIHRvIGNvZGluZyBzdHlsZS4KPj4gLSBPdGhl
-ciBnZW5lcmFsIGNvbW1lbnRzIGluIHYxLgo+Pgo+PiAgIGRyaXZlcnMvaHdtb24vS2NvbmZpZyAg
-ICAgIHwgICAgOCArCj4+ICAgZHJpdmVycy9od21vbi9NYWtlZmlsZSAgICAgfCAgICAxCj4+ICAg
-ZHJpdmVycy9od21vbi9pYm1wb3dlcm52LmMgfCAgMzY4IAo+PiArKysrKysrKysrKysrKysrKysr
-KysrKysrKysrKysrKysrKysrKysrKysrKwo+Cj4gWW91J2xsIGFsc28gbmVlZCBEb2N1bWVudGF0
-aW9uL2h3bW9uL2libXBvd2VybnYgYW5kCj4gRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRp
-bmdzL2h3bW9uL2libXBvd2VybnYuCj4KPiBUaGUgbGF0dGVyIHdpbGwgbmVlZCB0byBnZXQgYW4g
-QWNrIGZyb20gdGhlIGRldmljZXRyZWUgbWFpbnRhaW5lcnMuCgpJJ2xsIGRvIGFzIHJlcXVpcmVk
-LgoKPj4gICAzIGZpbGVzIGNoYW5nZWQsIDM3NyBpbnNlcnRpb25zKCspCj4+ICAgY3JlYXRlIG1v
-ZGUgMTAwNjQ0IGRyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jCj4+Cj4+IGRpZmYgLS1naXQgYS9k
-cml2ZXJzL2h3bW9uL0tjb25maWcgYi9kcml2ZXJzL2h3bW9uL0tjb25maWcKPj4gaW5kZXggYmMx
-OTZmNC4uM2UzMDhmYSAxMDA2NDQKPj4gLS0tIGEvZHJpdmVycy9od21vbi9LY29uZmlnCj4+ICsr
-KyBiL2RyaXZlcnMvaHdtb24vS2NvbmZpZwo+PiBAQCAtNTU0LDYgKzU1NCwxNCBAQCBjb25maWcg
-U0VOU09SU19JQk1QRVgKPj4gICAgICAgICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBh
-cyBhIG1vZHVsZS4gIElmIHNvLCB0aGUgbW9kdWxlCj4+ICAgICAgICAgd2lsbCBiZSBjYWxsZWQg
-aWJtcGV4Lgo+Pgo+PiArY29uZmlnIFNFTlNPUlNfSUJNUE9XRVJOVgo+PiArICAgIHRyaXN0YXRl
-ICJJQk0gUE9XRVJOViBwbGF0Zm9ybSBzZW5zb3JzIgo+PiArICAgIGRlcGVuZHMgb24gUFBDX1BP
-V0VSTlYKPj4gKyAgICBkZWZhdWx0IHkKPj4gKyAgICBoZWxwCj4+ICsgICAgICBJZiB5b3Ugc2F5
-IHllcyBoZXJlIHlvdSBnZXQgc3VwcG9ydCBmb3IgdGhlIHRlbXBlcmF0dXJlL2Zhbi9wb3dlcgo+
-PiArICAgICAgc2Vuc29ycyBvbiB5b3VyIHBsYXRmb3JtLgo+PiArCj4+ICAgY29uZmlnIFNFTlNP
-UlNfSUlPX0hXTU9OCj4+ICAgICAgIHRyaXN0YXRlICJId21vbiBkcml2ZXIgdGhhdCB1c2VzIGNo
-YW5uZWxzIHNwZWNpZmllZCB2aWEgaWlvIG1hcHMiCj4+ICAgICAgIGRlcGVuZHMgb24gSUlPCj4+
-IGRpZmYgLS1naXQgYS9kcml2ZXJzL2h3bW9uL01ha2VmaWxlIGIvZHJpdmVycy9od21vbi9NYWtl
-ZmlsZQo+PiBpbmRleCBjNDhmOTg3Li4xOTljNDAxIDEwMDY0NAo+PiAtLS0gYS9kcml2ZXJzL2h3
-bW9uL01ha2VmaWxlCj4+ICsrKyBiL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPj4gQEAgLTcxLDYg
-KzcxLDcgQEAgb2JqLSQoQ09ORklHX1NFTlNPUlNfVUxUUkE0NSkgICAgKz0gdWx0cmE0NV9lbnYu
-bwo+PiAgIG9iai0kKENPTkZJR19TRU5TT1JTX0k1S19BTUIpICAgICs9IGk1a19hbWIubwo+PiAg
-IG9iai0kKENPTkZJR19TRU5TT1JTX0lCTUFFTSkgICAgKz0gaWJtYWVtLm8KPj4gICBvYmotJChD
-T05GSUdfU0VOU09SU19JQk1QRVgpICAgICs9IGlibXBleC5vCj4+ICtvYmotJChDT05GSUdfU0VO
-U09SU19JQk1QT1dFUk5WKSs9IGlibXBvd2VybnYubwo+PiAgIG9iai0kKENPTkZJR19TRU5TT1JT
-X0lJT19IV01PTikgKz0gaWlvX2h3bW9uLm8KPj4gICBvYmotJChDT05GSUdfU0VOU09SU19JTkEy
-MDkpICAgICs9IGluYTIwOS5vCj4+ICAgb2JqLSQoQ09ORklHX1NFTlNPUlNfSU5BMlhYKSAgICAr
-PSBpbmEyeHgubwo+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9pYm1wb3dlcm52LmMgYi9k
-cml2ZXJzL2h3bW9uL2libXBvd2VybnYuYwo+PiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+PiBpbmRl
-eCAwMDAwMDAwLi5hZmNlNjIwCj4+IC0tLSAvZGV2L251bGwKPj4gKysrIGIvZHJpdmVycy9od21v
-bi9pYm1wb3dlcm52LmMKPj4gQEAgLTAsMCArMSwzNjggQEAKPj4gKy8qCj4+ICsgKiBJQk0gUG93
-ZXJOViBwbGF0Zm9ybSBzZW5zb3JzIGZvciB0ZW1wZXJhdHVyZS9mYW4vcG93ZXIKPj4gKyAqIENv
-cHlyaWdodCAoQykgMjAxNCBJQk0KPj4gKyAqCj4+ICsgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBz
-b2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQo+PiArICogaXQg
-dW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJs
-aXNoZWQgYnkKPj4gKyAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJz
-aW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yCj4+ICsgKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRl
-ciB2ZXJzaW9uLgo+PiArICoKPj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0
-aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAo+PiArICogYnV0IFdJVEhPVVQgQU5ZIFdB
-UlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKPj4gKyAqIE1FUkNI
-QU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUK
-Pj4gKyAqIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCj4+ICsg
-Kgo+PiArICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVy
-YWwgUHVibGljIExpY2Vuc2UKPj4gKyAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtLgo+PiArICov
-Cj4+ICsKPj4gKyNpbmNsdWRlIDxsaW51eC9pbml0Lmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvbW9k
-dWxlLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgva2VybmVsLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgv
-aHdtb24uaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9od21vbi1zeXNmcy5oPgo+PiArI2luY2x1ZGUg
-PGxpbnV4L29mLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvc2xhYi5oPgo+PiArCj4+ICsjaW5jbHVk
-ZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4+ICsjaW5jbHVkZSA8YXNtL29wYWwuaD4KPj4g
-KyNpbmNsdWRlIDxsaW51eC9lcnIuaD4KPj4gKwo+PiArI2RlZmluZSBEUlZOQU1FICAgICAgICAi
-aWJtcG93ZXJudiIKPj4gKyNkZWZpbmUgTUFYX0FUVFJfTEVOICAgIDMyCj4+ICsKPj4gKy8qIFNl
-bnNvciBzdWZmaXggbmFtZSBmcm9tIERUICovCj4+ICsjZGVmaW5lIERUX0ZBVUxUX0FUVFJfU1VG
-RklYICAgICAgICAiZmF1bHRlZCIKPj4gKyNkZWZpbmUgRFRfREFUQV9BVFRSX1NVRkZJWCAgICAg
-ICAgImRhdGEiCj4+ICsjZGVmaW5lIERUX1RIUkVTSE9MRF9BVFRSX1NVRkZJWCAgICAidGhycyIK
-Pj4gKwo+PiArLyoKPj4gKyAqIEVudW1lcmF0ZXMgYWxsIHRoZSB0eXBlcyBvZiBzZW5zb3JzIGlu
-IHRoZSBQT1dFUk5WIHBsYXRmb3JtIGFuZCAKPj4gZG9lcyBpbmRleAo+PiArICogaW50byAnc3Ry
-dWN0IHNlbnNvcl9ncm91cCcKPj4gKyAqLwo+PiArZW51bSBzZW5zb3JzIHsKPj4gKyAgICBGQU4s
-Cj4+ICsgICAgQU1CSUVOVF9URU1QLAo+PiArICAgIFBPV0VSX1NVUFBMWSwKPj4gKyAgICBQT1dF
-Ul9JTlBVVCwKPj4gKyAgICBNQVhfU0VOU09SX1RZUEUsCj4+ICt9Owo+PiArCj4+ICtzdGF0aWMg
-c3RydWN0IHNlbnNvcl9ncm91cCB7Cj4+ICsgICAgY29uc3QgY2hhciAqbmFtZTsKPj4gKyAgICBj
-b25zdCBjaGFyICpjb21wYXRpYmxlOwo+PiArICAgIHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgZ3Jv
-dXA7Cj4+ICsgICAgdTMyIGF0dHJfY291bnQ7Cj4+ICt9IHNlbnNvcl9ncm91cHNbXSA9IHsKPj4g
-KyAgICB7ImZhbiIsICJpYm0sb3BhbC1zZW5zb3ItY29vbGluZy1mYW4iLCB7MH0sIDB9LAo+PiAr
-ICAgIHsidGVtcCIsICJpYm0sb3BhbC1zZW5zb3ItYW1iLXRlbXAiLCB7MH0sIDB9LAo+PiArICAg
-IHsiaW4iLCAiaWJtLG9wYWwtc2Vuc29yLXBvd2VyLXN1cHBseSIsIHswfSwgMH0sCj4+ICsgICAg
-eyJwb3dlciIsICJpYm0sb3BhbC1zZW5zb3ItcG93ZXIiLCB7MH0sIDB9Cj4+ICt9Owo+PiArCj4g
-VGhlICcwJyBpbml0aWFsaXphdGlvbnMgc2hvdWxkIG5vdCBiZSBuZWNlc3NhcnkuCj4KPgo+PiAr
-c3RydWN0IHNlbnNvcl9kYXRhIHsKPj4gKyAgICB1MzIgaWQ7IC8qIEFuIG9wYXF1ZSBpZCBvZiB0
-aGUgZmlybXdhcmUgZm9yIGVhY2ggc2Vuc29yICovCj4+ICsgICAgZW51bSBzZW5zb3JzIHR5cGU7
-Cj4+ICsgICAgY2hhciBuYW1lW01BWF9BVFRSX0xFTl07Cj4+ICsgICAgc3RydWN0IGRldmljZV9h
-dHRyaWJ1dGUgZGV2X2F0dHI7Cj4+ICt9Owo+PiArCj4+ICtzdHJ1Y3QgcGxhdGZvcm1fZGF0YSB7
-Cj4+ICsgICAgY29uc3Qgc3RydWN0IGF0dHJpYnV0ZV9ncm91cCAqYXR0cl9ncm91cHNbTUFYX1NF
-TlNPUl9UWVBFICsgMV07Cj4+ICsgICAgdTMyIHNlbnNvcnNfY291bnQ7IC8qIFRvdGFsIGNvdW50
-IG9mIHNlbnNvcnMgZnJvbSBlYWNoIGdyb3VwICovCj4+ICt9Owo+PiArCj4+ICsvKiBQbGF0Zm9y
-bSBkZXZpY2UgcmVwcmVzZW50aW5nIGFsbCB0aGUgaWJtcG93ZXJudiBzZW5zb3JzICovCj4+ICtz
-dGF0aWMgc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldmljZTsKPj4gKwo+PiArc3RhdGljIHNz
-aXplX3Qgc2hvd19zZW5zb3Ioc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgCj4+IGRldmljZV9h
-dHRyaWJ1dGUgKmRldmF0dHIsCj4+ICsgICAgICAgICAgICAgICBjaGFyICpidWYpCj4+ICt7Cj4+
-ICsgICAgc3RydWN0IHNlbnNvcl9kYXRhICpzZGF0YSA9IGNvbnRhaW5lcl9vZihkZXZhdHRyLCBz
-dHJ1Y3QgCj4+IHNlbnNvcl9kYXRhLAo+PiArICAgICAgICAgICAgICAgICAgICAgICAgIGRldl9h
-dHRyKTsKPj4gKyAgICBzc2l6ZV90IHJldDsKPj4gKyAgICB1MzIgeDsKPj4gKwo+PiArICAgIHJl
-dCA9IG9wYWxfZ2V0X3NlbnNvcl9kYXRhKHNkYXRhLT5pZCwgJngpOwo+PiArICAgIGlmIChyZXQp
-IHsKPj4gKyAgICAgICAgcHJfZXJyKCIlczogRmFpbGVkIHRvIGdldCBvcGFsIHNlbnNvciBkYXRh
-XG4iLCBfX2Z1bmNfXyk7Cj4+ICsgICAgICAgIHJldHVybiByZXQ7Cj4+ICsgICAgfQo+PiArCj4+
-ICsgICAgLyogQ29udmVydCB0ZW1wZXJhdHVyZSB0byBtaWxsaS1kZWdyZWVzICovCj4+ICsgICAg
-aWYgKHNkYXRhLT50eXBlID09IEFNQklFTlRfVEVNUCkKPj4gKyAgICAgICAgeCAqPSAxMDAwOwo+
-PiArICAgIC8qIENvbnZlcnQgcG93ZXIgdG8gbWljcm8td2F0dHMgKi8KPj4gKyAgICBlbHNlIGlm
-IChzZGF0YS0+dHlwZSA9PSBQT1dFUl9JTlBVVCkKPj4gKyAgICAgICAgeCAqPSAxMDAwMDAwOwo+
-PiArCj4+ICsgICAgcmV0dXJuIHNwcmludGYoYnVmLCAiJWRcbiIsIHgpOwo+Cj4geCBpcyB1bnNp
-Z25lZCwgc28gJXUuCgpEb25lLgoKPgo+PiArfQo+PiArCj4+ICtzdGF0aWMgdm9pZCBfX2luaXQg
-Z2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0IGNoYXIgKm5hbWUsIHUzMiAKPj4gKmluZGV4LCBj
-aGFyICphdHRyKQo+PiArewo+PiArICAgIGNoYXIgKmhhc2hfcG9zID0gc3RyY2hyKG5hbWUsICcj
-Jyk7Cj4+ICsgICAgY2hhciAqZGFzaF9wb3M7Cj4+ICsgICAgdTMyIGNvcHlfbGVuOwo+PiArICAg
-IGNoYXIgYnVmWzhdOwo+PiArCj4+ICsgICAgbWVtc2V0KGJ1ZiwgMCwgc2l6ZW9mKGJ1ZikpOwo+
-PiArICAgICppbmRleCA9IDA7Cj4+ICsgICAgKmF0dHIgPSAnXDAnOwo+PiArCj4+ICsgICAgaWYg
-KGhhc2hfcG9zKSB7Cj4+ICsgICAgICAgIGRhc2hfcG9zID0gc3RyY2hyKGhhc2hfcG9zLCAnLScp
-Owo+PiArICAgICAgICBpZiAoZGFzaF9wb3MpIHsKPj4gKyAgICAgICAgICAgIGNvcHlfbGVuID0g
-ZGFzaF9wb3MgLSBoYXNoX3BvcyAtIDE7Cj4+ICsgICAgICAgICAgICBpZiAoY29weV9sZW4gPCBz
-aXplb2YoYnVmKSkgewo+PiArICAgICAgICAgICAgICAgIHN0cm5jcHkoYnVmLCBoYXNoX3BvcyAr
-IDEsIGNvcHlfbGVuKTsKPj4gKyAgICAgICAgICAgICAgICBzc2NhbmYoYnVmLCAiJWQiLCBpbmRl
-eCk7Cj4KPiBXaGF0IGlmIHNzY2FuZiBmYWlscyA/IE1pZ2h0IGJlIGFuIGludGVyZXN0aW5nIGV4
-ZXJjaXNlIHRvIHRyeSBhbmQgY3JlYXRlCj4gbXVsdGlwbGUgc2Vuc29ycyB3aXRoIGluZGV4IDAg
-KG9yLCBmb3IgdGhhdCBtYXR0ZXIsIHdpdGggdGhlIHNhbWUgCj4gaW5kZXggdmFsdWUpLgo+IERv
-IHlvdSBoYXZlIGFueSBwcm90ZWN0aW9uIGFnYWluc3QgYmFkIGlucHV0IGRhdGEgPyBHdWVzcyBu
-b3Q7IGRpZCB5b3UgCj4gdGVzdAo+IHdoYXQgaGFwcGVucyBpZiB5b3UgcGFzcyBiYWQgZGF0YSB0
-byB0aGUgZHJpdmVyIChzdWNoIGFzIGR1cGxpY2F0ZSBzZW5zb3IKPiBlbnRyaWVzKSA/CgpXZWxs
-LCByZXdyaXRpbmcgdGhpcyBmdW5jdGlvbiB0byByZXR1cm4gdGhlIGVycm9yIGNvZGUgaWYgZmFp
-bHMuCk5leHQgdmVyc2lvbiB3aWxsIGNvdmVyIHRoZXNlIHRlc3QgY2FzZXMgY292ZXJlZC4gVGhh
-bmtzLgoKPgo+PiArICAgICAgICAgICAgfQo+PiArCj4+ICsgICAgICAgICAgICBzdHJuY3B5KGF0
-dHIsIGRhc2hfcG9zICsgMSwgTUFYX0FUVFJfTEVOKTsKPj4gKyAgICAgICAgfQo+PiArICAgIH0K
-Pj4gK30KPj4gKwo+PiArLyoKPj4gKyAqIFRoaXMgZnVuY3Rpb24gdHJhbnNsYXRlcyB0aGUgRFQg
-bm9kZSBuYW1lIGludG8gdGhlICdod21vbicgCj4+IGF0dHJpYnV0ZSBuYW1lLgo+PiArICogSUJN
-UE9XRVJOViBkZXZpY2Ugbm9kZSBhcHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIAo+PiBh
-bWItdGVtcCMxLXRocnMgZXRjLgo+PiArICogd2hpY2ggbmVlZCB0byBiZSBtYXBwZWQgYXMgZmFu
-Ml9pbnB1dCwgdGVtcDFfbWF4IHJlc3BlY3RpdmVseSBiZWZvcmUKPj4gKyAqIHBvcHVsYXRpbmcg
-dGhlbSBpbnNpZGUgaHdtb24gZGV2aWNlIGNsYXNzLi4KPj4gKyAqLwo+PiArc3RhdGljIGludCBf
-X2luaXQgY3JlYXRlX2h3bW9uX2F0dHJfbmFtZShlbnVtIHNlbnNvcnMgdHlwZSwgY29uc3QgCj4+
-IGNoYXIgKm5vZGVfbmFtZSwKPj4gKyAgICAgICAgICAgICAgICAgIGNoYXIgKmh3bW9uX2F0dHJf
-bmFtZSkKPj4gK3sKPj4gKyAgICBjaGFyIGF0dHJfc3VmZml4W01BWF9BVFRSX0xFTl07Cj4+ICsg
-ICAgY2hhciAqYXR0cl9uYW1lOwo+PiArICAgIHUzMiBpbmRleDsKPj4gKwo+PiArICAgIGdldF9z
-ZW5zb3JfaW5kZXhfYXR0cihub2RlX25hbWUsICZpbmRleCwgYXR0cl9zdWZmaXgpOwo+PiArICAg
-IGlmICghaW5kZXggfHwgIXN0cmxlbihhdHRyX3N1ZmZpeCkpIHsKPj4gKyAgICAgICAgcHJfaW5m
-bygiJXM6IFNlbnNvciBkZXZpY2Ugbm9kZSBuYW1lIGlzIGludmFsaWQsIG5hbWU6ICVzXG4iLAo+
-PiArICAgICAgICAgICAgICAgIF9fZnVuY19fLCBub2RlX25hbWUpOwo+PiArICAgICAgICByZXR1
-cm4gLUVJTlZBTDsKPj4gKyAgICB9Cj4+ICsKPj4gKyAgICBpZiAoIXN0cmNtcChhdHRyX3N1ZmZp
-eCwgRFRfRkFVTFRfQVRUUl9TVUZGSVgpKQo+PiArICAgICAgICBhdHRyX25hbWUgPSAiZmF1bHQi
-Owo+PiArICAgIGVsc2UgaWYoIXN0cmNtcChhdHRyX3N1ZmZpeCwgRFRfREFUQV9BVFRSX1NVRkZJ
-WCkpCj4+ICsgICAgICAgIGF0dHJfbmFtZSA9ICJpbnB1dCI7Cj4+ICsgICAgZWxzZSBpZiAoIXN0
-cmNtcChhdHRyX3N1ZmZpeCwgRFRfVEhSRVNIT0xEX0FUVFJfU1VGRklYKSkgewo+PiArICAgICAg
-ICBpZiAodHlwZSA9PSBBTUJJRU5UX1RFTVApCj4+ICsgICAgICAgICAgICBhdHRyX25hbWUgPSAi
-bWF4IjsKPj4gKyAgICAgICAgZWxzZSBpZiAodHlwZSA9PSBGQU4pCj4+ICsgICAgICAgICAgICBh
-dHRyX25hbWUgPSAibWluIjsKPj4gKyAgICAgICAgZWxzZQo+PiArICAgICAgICAgICAgcmV0dXJu
-IC1FTk9FTlQ7Cj4+ICsgICAgfSBlbHNlCj4+ICsgICAgICAgIHJldHVybiAtRU5PRU5UOwo+PiAr
-Cj4+ICsgICAgc25wcmludGYoaHdtb25fYXR0cl9uYW1lLCBNQVhfQVRUUl9MRU4sICIlcyVkXyVz
-IiwKPj4gKyAgICAgICAgICAgIHNlbnNvcl9ncm91cHNbdHlwZV0ubmFtZSwgaW5kZXgsIGF0dHJf
-bmFtZSk7Cj4+ICsgICAgcmV0dXJuIDA7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBpbnQgX19pbml0
-IHBvcHVsYXRlX2F0dHJfZ3JvdXBzKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4+ICt7
-Cj4+ICsgICAgc3RydWN0IHBsYXRmb3JtX2RhdGEgKnBkYXRhID0gcGxhdGZvcm1fZ2V0X2RydmRh
-dGEocGRldik7Cj4+ICsgICAgY29uc3Qgc3RydWN0IGF0dHJpYnV0ZV9ncm91cCAqKnBncm91cHMg
-PSBwZGF0YS0+YXR0cl9ncm91cHM7Cj4+ICsgICAgc3RydWN0IGRldmljZV9ub2RlICpvcGFsLCAq
-bnA7Cj4+ICsgICAgZW51bSBzZW5zb3JzIHR5cGU7Cj4+ICsgICAgaW50IGVyciA9IDA7Cj4+ICsK
-Pj4gKyAgICBvcGFsID0gb2ZfZmluZF9ub2RlX2J5X3BhdGgoIi9pYm0sb3BhbC9zZW5zb3JzIik7
-Cj4+ICsgICAgICAgIGlmICghb3BhbCkgewo+Cj4gQW4gb2J2aW91cyB3aGl0ZXNwYWNlIGVycm9y
-IGhlcmUuCj4KPj4gKyAgICAgICAgcHJfZXJyKCIlczogT3BhbCAnc2Vuc29ycycgbm9kZSBub3Qg
-Zm91bmRcbiIsIF9fZnVuY19fKTsKPj4gKyAgICAgICAgcmV0dXJuIC1FTk9ERVY7Cj4+ICsgICAg
-ICAgIH0KPj4gKwo+PiArICAgIGZvcl9lYWNoX2NoaWxkX29mX25vZGUob3BhbCwgbnApIHsKPj4g
-KyAgICAgICAgaWYgKG5wLT5uYW1lID09IE5VTEwpCj4+ICsgICAgICAgICAgICBjb250aW51ZTsK
-Pj4gKwo+PiArICAgICAgICBmb3IgKHR5cGUgPSAwOyB0eXBlIDwgTUFYX1NFTlNPUl9UWVBFOyB0
-eXBlKyspCj4+ICsgICAgICAgICAgICBpZiAob2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCj4+
-ICsgICAgICAgICAgICAgICAgc2Vuc29yX2dyb3Vwc1t0eXBlXS5jb21wYXRpYmxlKSkgewo+PiAr
-ICAgICAgICAgICAgICAgIHNlbnNvcl9ncm91cHNbdHlwZV0uYXR0cl9jb3VudCsrOwo+PiArICAg
-ICAgICAgICAgICAgIGJyZWFrOwo+PiArICAgICAgICAgICAgfQo+PiArICAgIH0KPgo+IFlvdSBz
-aG91bGQgYmUgYWJsZSB0byBkbwo+ICAgICBvZl9ub2RlX3B1dChvcGFsKTsKPgo+IGhlcmUuIFRo
-ZW4geW91IGNhbiByZXR1cm4gaW1tZWRpYXRlbHkgb24gZXJyb3IgYmVsb3cuCgpEb25lLgoKPgo+
-PiArCj4+ICsgICAgZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5TT1JfVFlQRTsgdHlwZSsr
-KSB7Cj4+ICsgICAgICAgIGlmICghc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRyX2NvdW50KQo+PiAr
-ICAgICAgICAgICAgY29udGludWU7Cj4+ICsKPj4gKyAgICAgICAgc2Vuc29yX2dyb3Vwc1t0eXBl
-XS5ncm91cC5hdHRycyA9IGRldm1fa3phbGxvYygmcGRldi0+ZGV2LAo+PiArICAgICAgICAgICAg
-ICAgICAgICBzaXplb2Yoc3RydWN0IGF0dHJpYnV0ZSopICoKPj4gKyAgICAgICAgICAgICAgICAg
-ICAgKHNlbnNvcl9ncm91cHNbdHlwZV0uYXR0cl9jb3VudCArIDEpLAo+PiArICAgICAgICAgICAg
-ICAgICAgICBHRlBfS0VSTkVMKTsKPj4gKyAgICAgICAgaWYgKCFzZW5zb3JfZ3JvdXBzW3R5cGVd
-Lmdyb3VwLmF0dHJzKSB7Cj4+ICsgICAgICAgICAgICBwcl9lcnIoIiVzOiBGYWlsZWQgdG8gYWxs
-b2NhdGUgbWVtb3J5IGZvciBhdHRyaWJ1dGUiCj4+ICsgICAgICAgICAgICAgICAgICAgICJhcnJh
-eVxuIiwgX19mdW5jX18pOwo+Cj4gZGV2bV9remFsbG9jKCkgYWxyZWFkeSBkdW1wcyBhbiBlcnJv
-ciBtZXNzYWdlLiBTYW1lIGZvciBhbGwgb3RoZXIgCj4gbWVtb3J5IGVycm9yIG1lc3NhZ2VzLgo+
-Cj4+ICsgICAgICAgICAgICBlcnIgPSAtRU5PTUVNOwo+PiArICAgICAgICAgICAgZ290byBleGl0
-X3B1dF9ub2RlOwo+PiArICAgICAgICB9Cj4+ICsKPj4gKyAgICAgICAgcGdyb3Vwc1t0eXBlXSA9
-ICZzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwOwo+PiArICAgICAgICBwZGF0YS0+c2Vuc29yc19j
-b3VudCArPSBzZW5zb3JfZ3JvdXBzW3R5cGVdLmF0dHJfY291bnQ7Cj4+ICsgICAgICAgIHNlbnNv
-cl9ncm91cHNbdHlwZV0uYXR0cl9jb3VudCA9IDA7Cj4+ICsgICAgfQo+PiArCj4+ICtleGl0X3B1
-dF9ub2RlOgo+PiArICAgIG9mX25vZGVfcHV0KG9wYWwpOwo+PiArICAgIHJldHVybiBlcnI7Cj4+
-ICt9Cj4+ICsKPj4gKy8qCj4+ICsgKiBJdGVyYXRlIHRocm91Z2ggdGhlIGRldmljZSB0cmVlIGZv
-ciBlYWNoIGNoaWxkIG9mIHNlbnNvciBub2RlLCAKPj4gY3JlYXRlCj4+ICsgKiBhIHN5c2ZzIGF0
-dHJpYnV0ZSBmaWxlLCB0aGUgZmlsZSBpcyBuYW1lZCBieSB0cmFuc2xhdGluZyB0aGUgRFQgCj4+
-IG5vZGUgbmFtZQo+PiArICogdG8gdGhlIG5hbWUgcmVxdWlyZWQgYnkgdGhlIGhpZ2hlciAnaHdt
-b24nIGRyaXZlciBsaWtlIAo+PiBmYW4xX2lucHV0LCB0ZW1wMV9tYXgKPj4gKyAqIGV0Yy4uCj4+
-ICsgKi8KPj4gK3N0YXRpYyBpbnQgX19pbml0IGNyZWF0ZV9kZXZpY2VfYXR0cnMoc3RydWN0IHBs
-YXRmb3JtX2RldmljZSAqcGRldikKPj4gK3sKPj4gKyAgICBzdHJ1Y3QgcGxhdGZvcm1fZGF0YSAq
-cGRhdGEgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKPj4gKyAgICBjb25zdCBzdHJ1Y3Qg
-YXR0cmlidXRlX2dyb3VwICoqcGdyb3VwcyA9IHBkYXRhLT5hdHRyX2dyb3VwczsKPj4gKyAgICBz
-dHJ1Y3QgZGV2aWNlX25vZGUgKm9wYWwsICpucDsKPj4gKyAgICBzdHJ1Y3Qgc2Vuc29yX2RhdGEg
-KnNkYXRhOwo+PiArICAgIGNvbnN0IHUzMiAqc2Vuc29yX2lkOwo+PiArICAgIGVudW0gc2Vuc29y
-cyB0eXBlOwo+PiArICAgIHUzMiBjb3VudCA9IDA7Cj4+ICsgICAgaW50IGVyciA9IDA7Cj4+ICsK
-Pj4gKyAgICBvcGFsID0gb2ZfZmluZF9ub2RlX2J5X3BhdGgoIi9pYm0sb3BhbC9zZW5zb3JzIik7
-Cj4+ICsgICAgICAgIGlmICghb3BhbCkgewo+PiArICAgICAgICBwcl9lcnIoIiVzOiBPcGFsICdz
-ZW5zb3JzJyBub2RlIG5vdCBmb3VuZFxuIiwgX19mdW5jX18pOwo+PiArICAgICAgICByZXR1cm4g
-LUVOT0RFVjsKPj4gKyAgICAgICAgfQo+PiArCj4+ICsgICAgc2RhdGEgPSBkZXZtX2t6YWxsb2Mo
-JnBkZXYtPmRldiwgKHBkYXRhLT5zZW5zb3JzX2NvdW50KSAqCj4+ICsgICAgICAgICAgICAgICAg
-IHNpemVvZigqc2RhdGEpLCBHRlBfS0VSTkVMKTsKPj4gKyAgICBpZiAoIXNkYXRhKSB7Cj4+ICsg
-ICAgICAgIHByX2VycigiJXM6IEZhaWxlZCB0byBhbGxvY2F0ZSBtZW1vcnkgZm9yIHRoZSBzZW5z
-b3JfZGF0YSIsCj4+ICsgICAgICAgICAgICAgICAgX19mdW5jX18pOwo+PiArICAgICAgICBlcnIg
-PSAtRU5PTUVNOwo+PiArICAgICAgICBnb3RvIGV4aXRfcHV0X25vZGU7Cj4+ICsgICAgfQo+PiAr
-Cj4+ICsgICAgZm9yX2VhY2hfY2hpbGRfb2Zfbm9kZShvcGFsLCBucCkgewo+PiArICAgICAgICAg
-ICAgICAgIGlmIChucC0+bmFtZSA9PSBOVUxMKQo+PiArICAgICAgICAgICAgICAgICAgICAgICAg
-Y29udGludWU7Cj4+ICsKPj4gKyAgICAgICAgZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5T
-T1JfVFlQRTsgdHlwZSsrKQo+PiArICAgICAgICAgICAgaWYgKG9mX2RldmljZV9pc19jb21wYXRp
-YmxlKG5wLAo+PiArICAgICAgICAgICAgICAgICAgICBzZW5zb3JfZ3JvdXBzW3R5cGVdLmNvbXBh
-dGlibGUpKQo+PiArICAgICAgICAgICAgICAgIGJyZWFrOwo+PiArCj4+ICsgICAgICAgIGlmICh0
-eXBlID09IE1BWF9TRU5TT1JfVFlQRSkKPj4gKyAgICAgICAgICAgIGNvbnRpbnVlOwo+PiArCj4+
-ICsgICAgICAgIHNlbnNvcl9pZCA9IG9mX2dldF9wcm9wZXJ0eShucCwgInNlbnNvci1pZCIsIE5V
-TEwpOwo+PiArICAgICAgICBpZiAoIXNlbnNvcl9pZCkgewo+PiArICAgICAgICAgICAgcHJfaW5m
-bygiJXM6ICVzIGRvZXNuJ3QgaGF2ZSBzZW5zb3ItaWRcbiIsIF9fZnVuY19fLAo+PiArICAgICAg
-ICAgICAgICAgIG5wLT5uYW1lKTsKPj4gKyAgICAgICAgICAgIGNvbnRpbnVlOwo+PiArICAgICAg
-ICB9Cj4+ICsKPiBDb25zaWRlciB1c2luZyBvZl9wcm9wZXJ0eV9yZWFkX3UzMigpLgoKT2theS4K
-Cj4KPj4gKyAgICAgICAgc2RhdGFbY291bnRdLmlkID0gKnNlbnNvcl9pZDsKPj4gKyAgICAgICAg
-c2RhdGFbY291bnRdLnR5cGUgPSB0eXBlOwo+PiArICAgICAgICBlcnIgPSBjcmVhdGVfaHdtb25f
-YXR0cl9uYW1lKHR5cGUsIG5wLT5uYW1lLCAKPj4gc2RhdGFbY291bnRdLm5hbWUpOwo+PiArICAg
-ICAgICBpZiAoZXJyKQo+PiArICAgICAgICAgICAgZ290byBleGl0X3B1dF9ub2RlOwo+PiArCj4+
-ICsgICAgICAgIHN5c2ZzX2F0dHJfaW5pdCgmc2RhdGFbY291bnRdLmRldl9hdHRyLmF0dHIpOwo+
-PiArICAgICAgICBzZGF0YVtjb3VudF0uZGV2X2F0dHIuYXR0ci5uYW1lID0gc2RhdGFbY291bnRd
-Lm5hbWU7Cj4+ICsgICAgICAgIHNkYXRhW2NvdW50XS5kZXZfYXR0ci5hdHRyLm1vZGUgPSBTX0lS
-VUdPOwo+PiArICAgICAgICBzZGF0YVtjb3VudF0uZGV2X2F0dHIuc2hvdyA9IHNob3dfc2Vuc29y
-Owo+PiArCj4+ICsgcGdyb3Vwc1t0eXBlXS0+YXR0cnNbc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRy
-X2NvdW50KytdID0KPj4gKyAgICAgICAgICAgICAgICAmc2RhdGFbY291bnQrK10uZGV2X2F0dHIu
-YXR0cjsKPj4gKyAgICB9Cj4+ICsKPj4gK2V4aXRfcHV0X25vZGU6Cj4+ICsgICAgb2Zfbm9kZV9w
-dXQob3BhbCk7Cj4+ICsgICAgcmV0dXJuIGVycjsKPj4gK30KPj4gKwo+PiArc3RhdGljIGludCBf
-X2luaXQgaWJtcG93ZXJudl9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+PiAr
-ewo+PiArICAgIHN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YTsKPj4gKyAgICBzdHJ1Y3QgZGV2
-aWNlICpod21vbl9kZXY7Cj4+ICsgICAgaW50IGVycjsKPj4gKwo+PiArICAgIHBkYXRhID0gZGV2
-bV9remFsbG9jKCZwZGV2LT5kZXYsIHNpemVvZigqcGRhdGEpLCBHRlBfS0VSTkVMKTsKPj4gKyAg
-ICBpZiAoIXBkYXRhKQo+PiArICAgICAgICByZXR1cm4gLUVOT01FTTsKPj4gKwo+PiArICAgIHBs
-YXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIHBkYXRhKTsKPj4gKyAgICBwZGF0YS0+c2Vuc29yc19j
-b3VudCA9IDA7Cj4+ICsgICAgZXJyID0gcG9wdWxhdGVfYXR0cl9ncm91cHMocGRldik7Cj4+ICsg
-ICAgaWYgKGVycikKPj4gKyAgICAgICAgcmV0dXJuIGVycjsKPj4gKwo+PiArICAgIC8qIENyZWF0
-ZSBzeXNmcyBhdHRyaWJ1dGUgZmlsZSBmb3IgZWFjaCBzZW5zb3IgZm91bmQgaW4gdGhlIERUICov
-Cj4KPiBBdHRyaWJ1dGUgZGF0YSwgbm90IGZpbGUKPgo+PiArICAgIGVyciA9IGNyZWF0ZV9kZXZp
-Y2VfYXR0cnMocGRldik7Cj4+ICsgICAgaWYgKGVycikKPj4gKyAgICAgICAgcmV0dXJuIGVycjsK
-Pj4gKwo+PiArICAgIC8qIEZpbmFsbHksIHJlZ2lzdGVyIHdpdGggaHdtb24gKi8KPj4gKyAgICBo
-d21vbl9kZXYgPSBkZXZtX2h3bW9uX2RldmljZV9yZWdpc3Rlcl93aXRoX2dyb3VwcygmcGRldi0+
-ZGV2LCAKPj4gRFJWTkFNRSwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZGF0
-YSwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZGF0YS0+YXR0cl9ncm91cHMp
-Owo+PiArCj4+ICsgICAgcmV0dXJuIFBUUl9FUlJfT1JfWkVSTyhod21vbl9kZXYpOwo+PiArfQo+
-PiArCj4+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBpYm1wb3dlcm52X2RyaXZlciA9
-IHsKPj4gKyAgICAuZHJpdmVyID0gewo+PiArICAgICAgICAub3duZXIgPSBUSElTX01PRFVMRSwK
-Pj4gKyAgICAgICAgLm5hbWUgPSBEUlZOQU1FLAo+PiArICAgIH0sCj4+ICt9Owo+PiArCj4+ICtz
-dGF0aWMgaW50IF9faW5pdCBpYm1wb3dlcm52X2luaXQodm9pZCkKPj4gK3sKPj4gKyAgICBpbnQg
-ZXJyOwo+PiArCj4+ICsgICAgcGRldmljZSA9IHBsYXRmb3JtX2RldmljZV9hbGxvYyhEUlZOQU1F
-LCAwKTsKPj4gKyAgICBpZiAoIXBkZXZpY2UpIHsKPj4gKyAgICAgICAgcHJfZXJyKCIlczogRGV2
-aWNlIGFsbG9jYXRpb24gZmFpbGVkXG4iLCBfX2Z1bmNfXyk7Cj4+ICsgICAgICAgIGVyciA9IC1F
-Tk9NRU07Cj4+ICsgICAgICAgIGdvdG8gZXhpdDsKPj4gKyAgICB9Cj4+ICsKPj4gKyAgICBlcnIg
-PSBwbGF0Zm9ybV9kZXZpY2VfYWRkKHBkZXZpY2UpOwo+PiArICAgIGlmIChlcnIpIHsKPj4gKyAg
-ICAgICAgcHJfZXJyKCIlczogRGV2aWNlIGFkZGl0aW9uIGZhaWxlZCAoJWQpXG4iLCBfX2Z1bmNf
-XywgZXJyKTsKPj4gKyAgICAgICAgZ290byBleGl0X2RldmljZV9wdXQ7Cj4+ICsgICAgfQo+PiAr
-Cj4+ICsgICAgZXJyID0gcGxhdGZvcm1fZHJpdmVyX3Byb2JlKCZpYm1wb3dlcm52X2RyaXZlciwg
-aWJtcG93ZXJudl9wcm9iZSk7Cj4+ICsgICAgaWYgKGVycikgewo+PiArICAgICAgICBwcl9lcnIo
-IiVzOiBQbGF0ZnJvbSBkcml2ZXIgcHJvYmUgZmFpbGVkXG4iLCBfX2Z1bmNfXyk7Cj4+ICsgICAg
-ICAgIGdvdG8gZXhpdF9kZXZpY2VfZGVsOwo+PiArICAgIH0KPj4gKwo+PiArICAgIHJldHVybiAw
-Owo+PiArCj4+ICtleGl0X2RldmljZV9kZWw6Cj4+ICsgICAgcGxhdGZvcm1fZGV2aWNlX2RlbChw
-ZGV2aWNlKTsKPj4gK2V4aXRfZGV2aWNlX3B1dDoKPj4gKyAgICBwbGF0Zm9ybV9kZXZpY2VfcHV0
-KHBkZXZpY2UpOwo+PiArZXhpdDoKPj4gKyAgICByZXR1cm4gZXJyOwo+PiArfQo+PiArCj4+ICtz
-dGF0aWMgdm9pZCBfX2V4aXQgaWJtcG93ZXJudl9leGl0KHZvaWQpCj4+ICt7Cj4+ICsgICAgcGxh
-dGZvcm1fZHJpdmVyX3VucmVnaXN0ZXIoJmlibXBvd2VybnZfZHJpdmVyKTsKPj4gKyAgICBwbGF0
-Zm9ybV9kZXZpY2VfdW5yZWdpc3RlcihwZGV2aWNlKTsKPj4gK30KPj4gKwo+PiArTU9EVUxFX0FV
-VEhPUigiTmVlbGVzaCBHdXB0YSA8bmVlbGVndXBAbGludXgudm5ldC5pYm0uY29tPiIpOwo+PiAr
-TU9EVUxFX0RFU0NSSVBUSU9OKCJJQk0gUE9XRVJOViBwbGF0Zm9ybSBzZW5zb3JzIik7Cj4+ICtN
-T0RVTEVfTElDRU5TRSgiR1BMIik7Cj4+ICsKPj4gK21vZHVsZV9pbml0KGlibXBvd2VybnZfaW5p
-dCk7Cj4+ICttb2R1bGVfZXhpdChpYm1wb3dlcm52X2V4aXQpOwo+Pgo+Pgo+Pgo+CgoKX19fX19f
-X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbG0tc2Vuc29ycyBtYWls
-aW5nIGxpc3QKbG0tc2Vuc29yc0BsbS1zZW5zb3JzLm9yZwpodHRwOi8vbGlzdHMubG0tc2Vuc29y
-cy5vcmcvbWFpbG1hbi9saXN0aW5mby9sbS1zZW5zb3Jz
+
+On 05/28/2014 12:53 PM, Guenter Roeck wrote:
+> On 05/19/2014 07:26 AM, Neelesh Gupta wrote:
+>> This patch adds basic kernel enablement for reading power values, fan
+>> speed rpm and temperature values on powernv platforms which will
+>> be exported to user space through sysfs interface.
+>>
+>> Test results:
+>> -------------
+>> [root@tul163p1 ~]# sensors
+>> ibmpowernv-isa-0000
+>> Adapter: ISA adapter
+>> fan1:        5487 RPM  (min =    0 RPM)
+>> fan2:        5152 RPM  (min =    0 RPM)
+>> fan3:        5590 RPM  (min =    0 RPM)
+>> fan4:        4963 RPM  (min =    0 RPM)
+>> fan5:           0 RPM  (min =    0 RPM)
+>> fan6:           0 RPM  (min =    0 RPM)
+>> fan7:        7488 RPM  (min =    0 RPM)
+>> fan8:        7944 RPM  (min =    0 RPM)
+>> temp1:        +39.0°C  (high =  +0.0°C)
+>> power1:      192.00 W
+>>
+>> [root@tul163p1 ~]# ls /sys/devices/platform/
+>> alarmtimer  ibmpowernv.0  rtc-generic  serial8250  uevent
+>> [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/
+>> driver/    hwmon/     modalias   subsystem/ uevent
+>> [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/hwmon/hwmon0/
+>> device        fan2_min    fan4_min    fan6_min    fan8_min power1_input
+>> fan1_fault  fan3_fault    fan5_fault  fan7_fault    in1_fault subsystem
+>> fan1_input  fan3_input    fan5_input  fan7_input    in2_fault 
+>> temp1_input
+>> fan1_min    fan3_min    fan5_min    fan7_min    in3_fault temp1_max
+>> fan2_fault  fan4_fault    fan6_fault  fan8_fault    in4_fault uevent
+>> fan2_input  fan4_input    fan6_input  fan8_input    name
+>> [root@tul163p1 ~]#
+>> [root@tul163p1 ~]# ls /sys/class/hwmon/hwmon0/
+>> device        fan2_min    fan4_min    fan6_min    fan8_min power1_input
+>> fan1_fault  fan3_fault    fan5_fault  fan7_fault    in1_fault subsystem
+>> fan1_input  fan3_input    fan5_input  fan7_input    in2_fault 
+>> temp1_input
+>> fan1_min    fan3_min    fan5_min    fan7_min    in3_fault temp1_max
+>> fan2_fault  fan4_fault    fan6_fault  fan8_fault    in4_fault uevent
+>> fan2_input  fan4_input    fan6_input  fan8_input    name
+>> [root@tul163p1 ~]#
+>>
+>
+>
+> The inX_fault attributes don't really make much sense. _fault 
+> attributes without
+> _input attributes don't have any value and are, as you noticed, not 
+> displayed
+> with the sensors command. Is this a problem in teh devicetree data or 
+> do you
+> really have voltage faults without voltages ?
+
+There is no issue with the device data, somehow I'm getting only the 
+_fault attribute
+for the inX_ (power-supply) attributes.
+
+>
+>> Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>
+>> ---
+>>
+> Checkpatch says:
+>
+> total: 8 errors, 11 warnings, 389 lines checked
+>
+> NOTE: whitespace errors detected, you may wish to use 
+> scripts/cleanpatch or
+>       scripts/cleanfile
+>
+> which should really not happen at this point.
+>
+> Please make sure you follow CodingStyle. checkpatch --strict points to 
+> a number
+> of additional violations.
+>
+> More comments inline.
+
+Fixed all of these issues related to coding style.
+
+>
+>> 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?
+>>
+> Your call, really; whatever is easier for you. I won't dictate one or 
+> the other.
+>
+> Question though is what happens if one group is not populated. If I 
+> understand
+> the code correctly this will result in the remaining groups to be 
+> 'dropped',
+> ie not displayed at all.
+
+Yes, should be fixed.
+
+>
+>> - '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.
+>>
+>>   drivers/hwmon/Kconfig      |    8 +
+>>   drivers/hwmon/Makefile     |    1
+>>   drivers/hwmon/ibmpowernv.c |  368 
+>> ++++++++++++++++++++++++++++++++++++++++++++
+>
+> You'll also need Documentation/hwmon/ibmpowernv and
+> Documentation/devicetree/bindings/hwmon/ibmpowernv.
+>
+> The latter will need to get an Ack from the devicetree maintainers.
+
+I'll do as required.
+
+>>   3 files changed, 377 insertions(+)
+>>   create mode 100644 drivers/hwmon/ibmpowernv.c
+>>
+>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
+>> index bc196f4..3e308fa 100644
+>> --- a/drivers/hwmon/Kconfig
+>> +++ b/drivers/hwmon/Kconfig
+>> @@ -554,6 +554,14 @@ 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 platform.
+>> +
+>>   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 c48f987..199c401 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..afce620
+>> --- /dev/null
+>> +++ b/drivers/hwmon/ibmpowernv.c
+>> @@ -0,0 +1,368 @@
+>> +/*
+>> + * IBM PowerNV platform sensors for temperature/fan/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.
+>> + */
+>> +
+>> +#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 DRVNAME        "ibmpowernv"
+>> +#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", {0}, 0},
+>> +    {"temp", "ibm,opal-sensor-amb-temp", {0}, 0},
+>> +    {"in", "ibm,opal-sensor-power-supply", {0}, 0},
+>> +    {"power", "ibm,opal-sensor-power", {0}, 0}
+>> +};
+>> +
+> The '0' initializations should not be necessary.
+>
+>
+>> +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) {
+>> +        pr_err("%s: Failed to get opal sensor data\n", __func__);
+>> +        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, "%d\n", x);
+>
+> x is unsigned, so %u.
+
+Done.
+
+>
+>> +}
+>> +
+>> +static void __init get_sensor_index_attr(const char *name, u32 
+>> *index, char *attr)
+>> +{
+>> +    char *hash_pos = strchr(name, '#');
+>> +    char *dash_pos;
+>> +    u32 copy_len;
+>> +    char buf[8];
+>> +
+>> +    memset(buf, 0, sizeof(buf));
+>> +    *index = 0;
+>> +    *attr = '\0';
+>> +
+>> +    if (hash_pos) {
+>> +        dash_pos = strchr(hash_pos, '-');
+>> +        if (dash_pos) {
+>> +            copy_len = dash_pos - hash_pos - 1;
+>> +            if (copy_len < sizeof(buf)) {
+>> +                strncpy(buf, hash_pos + 1, copy_len);
+>> +                sscanf(buf, "%d", index);
+>
+> What if sscanf fails ? Might be an interesting exercise to try and create
+> multiple sensors with index 0 (or, for that matter, with the same 
+> index value).
+> Do you have any protection against bad input data ? Guess not; did you 
+> test
+> what happens if you pass bad data to the driver (such as duplicate sensor
+> entries) ?
+
+Well, rewriting this function to return the error code if fails.
+Next version will cover these test cases covered. Thanks.
+
+>
+>> +            }
+>> +
+>> +            strncpy(attr, dash_pos + 1, MAX_ATTR_LEN);
+>> +        }
+>> +    }
+>> +}
+>> +
+>> +/*
+>> + * 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(enum sensors type, const 
+>> char *node_name,
+>> +                  char *hwmon_attr_name)
+>> +{
+>> +    char attr_suffix[MAX_ATTR_LEN];
+>> +    char *attr_name;
+>> +    u32 index;
+>> +
+>> +    get_sensor_index_attr(node_name, &index, attr_suffix);
+>> +    if (!index || !strlen(attr_suffix)) {
+>> +        pr_info("%s: Sensor device node name is invalid, name: %s\n",
+>> +                __func__, node_name);
+>> +        return -EINVAL;
+>> +    }
+>> +
+>> +    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;
+>> +    int err = 0;
+>> +
+>> +    opal = of_find_node_by_path("/ibm,opal/sensors");
+>> +        if (!opal) {
+>
+> An obvious whitespace error here.
+>
+>> +        pr_err("%s: Opal 'sensors' node not found\n", __func__);
+>> +        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;
+>> +            }
+>> +    }
+>
+> You should be able to do
+>     of_node_put(opal);
+>
+> here. Then you can return immediately on error below.
+
+Done.
+
+>
+>> +
+>> +    for (type = 0; type < MAX_SENSOR_TYPE; type++) {
+>> +        if (!sensor_groups[type].attr_count)
+>> +            continue;
+>> +
+>> +        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) {
+>> +            pr_err("%s: Failed to allocate memory for attribute"
+>> +                    "array\n", __func__);
+>
+> devm_kzalloc() already dumps an error message. Same for all other 
+> memory error messages.
+>
+>> +            err = -ENOMEM;
+>> +            goto exit_put_node;
+>> +        }
+>> +
+>> +        pgroups[type] = &sensor_groups[type].group;
+>> +        pdata->sensors_count += sensor_groups[type].attr_count;
+>> +        sensor_groups[type].attr_count = 0;
+>> +    }
+>> +
+>> +exit_put_node:
+>> +    of_node_put(opal);
+>> +    return err;
+>> +}
+>> +
+>> +/*
+>> + * Iterate through the device tree for each child of sensor 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 u32 *sensor_id;
+>> +    enum sensors type;
+>> +    u32 count = 0;
+>> +    int err = 0;
+>> +
+>> +    opal = of_find_node_by_path("/ibm,opal/sensors");
+>> +        if (!opal) {
+>> +        pr_err("%s: Opal 'sensors' node not found\n", __func__);
+>> +        return -ENODEV;
+>> +        }
+>> +
+>> +    sdata = devm_kzalloc(&pdev->dev, (pdata->sensors_count) *
+>> +                 sizeof(*sdata), GFP_KERNEL);
+>> +    if (!sdata) {
+>> +        pr_err("%s: Failed to allocate memory for the sensor_data",
+>> +                __func__);
+>> +        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) {
+>> +            pr_info("%s: %s doesn't have sensor-id\n", __func__,
+>> +                np->name);
+>> +            continue;
+>> +        }
+>> +
+> Consider using of_property_read_u32().
+
+Okay.
+
+>
+>> +        sdata[count].id = *sensor_id;
+>> +        sdata[count].type = type;
+>> +        err = create_hwmon_attr_name(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 file for each sensor found in the DT */
+>
+> Attribute data, not file
+>
+>> +    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("%s: Device allocation failed\n", __func__);
+>> +        err = -ENOMEM;
+>> +        goto exit;
+>> +    }
+>> +
+>> +    err = platform_device_add(pdevice);
+>> +    if (err) {
+>> +        pr_err("%s: Device addition failed (%d)\n", __func__, err);
+>> +        goto exit_device_put;
+>> +    }
+>> +
+>> +    err = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe);
+>> +    if (err) {
+>> +        pr_err("%s: Platfrom driver probe failed\n", __func__);
+>> +        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);
+>>
+>>
+>>
+>
diff --git a/a/content_digest b/N1/content_digest
index ff36db8..e15dd15 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -1,8 +1,8 @@
  "ref\020140519141931.9248.11356.stgit@neelegup-tp-t420.in.ibm.com\0"
  "ref\053858F02.2020808@roeck-us.net\0"
  "From\0Neelesh Gupta <neelegup@linux.vnet.ibm.com>\0"
- "Subject\0Re: [lm-sensors] [PATCH v2] powerpc/powernv: hwmon driver for power values, fan rpm and temperature\0"
- "Date\0Mon, 09 Jun 2014 08:27:02 +0000\0"
+ "Subject\0Re: [PATCH v2] powerpc/powernv: hwmon driver for power values, fan rpm and temperature\0"
+ "Date\0Mon, 09 Jun 2014 13:45:02 +0530\0"
  "To\0Guenter Roeck <linux@roeck-us.net>"
   linuxppc-dev@lists.ozlabs.org
   jdelvare@suse.de
@@ -10,341 +10,603 @@
  "Cc\0sbhat@linux.vnet.ibm.com\0"
  "\00:1\0"
  "b\0"
- "Ck9uIDA1LzI4LzIwMTQgMTI6NTMgUE0sIEd1ZW50ZXIgUm9lY2sgd3JvdGU6Cj4gT24gMDUvMTkv\n"
- "MjAxNCAwNzoyNiBBTSwgTmVlbGVzaCBHdXB0YSB3cm90ZToKPj4gVGhpcyBwYXRjaCBhZGRzIGJh\n"
- "c2ljIGtlcm5lbCBlbmFibGVtZW50IGZvciByZWFkaW5nIHBvd2VyIHZhbHVlcywgZmFuCj4+IHNw\n"
- "ZWVkIHJwbSBhbmQgdGVtcGVyYXR1cmUgdmFsdWVzIG9uIHBvd2VybnYgcGxhdGZvcm1zIHdoaWNo\n"
- "IHdpbGwKPj4gYmUgZXhwb3J0ZWQgdG8gdXNlciBzcGFjZSB0aHJvdWdoIHN5c2ZzIGludGVyZmFj\n"
- "ZS4KPj4KPj4gVGVzdCByZXN1bHRzOgo+PiAtLS0tLS0tLS0tLS0tCj4+IFtyb290QHR1bDE2M3Ax\n"
- "IH5dIyBzZW5zb3JzCj4+IGlibXBvd2VybnYtaXNhLTAwMDAKPj4gQWRhcHRlcjogSVNBIGFkYXB0\n"
- "ZXIKPj4gZmFuMTogICAgICAgIDU0ODcgUlBNICAobWluID0gICAgMCBSUE0pCj4+IGZhbjI6ICAg\n"
- "ICAgICA1MTUyIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+PiBmYW4zOiAgICAgICAgNTU5MCBSUE0g\n"
- "IChtaW4gPSAgICAwIFJQTSkKPj4gZmFuNDogICAgICAgIDQ5NjMgUlBNICAobWluID0gICAgMCBS\n"
- "UE0pCj4+IGZhbjU6ICAgICAgICAgICAwIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+PiBmYW42OiAg\n"
- "ICAgICAgICAgMCBSUE0gIChtaW4gPSAgICAwIFJQTSkKPj4gZmFuNzogICAgICAgIDc0ODggUlBN\n"
- "ICAobWluID0gICAgMCBSUE0pCj4+IGZhbjg6ICAgICAgICA3OTQ0IFJQTSAgKG1pbiA9ICAgIDAg\n"
- "UlBNKQo+PiB0ZW1wMTogICAgICAgICszOS4wwrBDICAoaGlnaCA9ICArMC4wwrBDKQo+PiBwb3dl\n"
- "cjE6ICAgICAgMTkyLjAwIFcKPj4KPj4gW3Jvb3RAdHVsMTYzcDEgfl0jIGxzIC9zeXMvZGV2aWNl\n"
- "cy9wbGF0Zm9ybS8KPj4gYWxhcm10aW1lciAgaWJtcG93ZXJudi4wICBydGMtZ2VuZXJpYyAgc2Vy\n"
- "aWFsODI1MCAgdWV2ZW50Cj4+IFtyb290QHR1bDE2M3AxIH5dIyBscyAvc3lzL2RldmljZXMvcGxh\n"
- "dGZvcm0vaWJtcG93ZXJudi4wLwo+PiBkcml2ZXIvICAgIGh3bW9uLyAgICAgbW9kYWxpYXMgICBz\n"
- "dWJzeXN0ZW0vIHVldmVudAo+PiBbcm9vdEB0dWwxNjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3Bs\n"
- "YXRmb3JtL2libXBvd2VybnYuMC9od21vbi9od21vbjAvCj4+IGRldmljZSAgICAgICAgZmFuMl9t\n"
- "aW4gICAgZmFuNF9taW4gICAgZmFuNl9taW4gICAgZmFuOF9taW4gcG93ZXIxX2lucHV0Cj4+IGZh\n"
- "bjFfZmF1bHQgIGZhbjNfZmF1bHQgICAgZmFuNV9mYXVsdCAgZmFuN19mYXVsdCAgICBpbjFfZmF1\n"
- "bHQgc3Vic3lzdGVtCj4+IGZhbjFfaW5wdXQgIGZhbjNfaW5wdXQgICAgZmFuNV9pbnB1dCAgZmFu\n"
- "N19pbnB1dCAgICBpbjJfZmF1bHQgCj4+IHRlbXAxX2lucHV0Cj4+IGZhbjFfbWluICAgIGZhbjNf\n"
- "bWluICAgIGZhbjVfbWluICAgIGZhbjdfbWluICAgIGluM19mYXVsdCB0ZW1wMV9tYXgKPj4gZmFu\n"
- "Ml9mYXVsdCAgZmFuNF9mYXVsdCAgICBmYW42X2ZhdWx0ICBmYW44X2ZhdWx0ICAgIGluNF9mYXVs\n"
- "dCB1ZXZlbnQKPj4gZmFuMl9pbnB1dCAgZmFuNF9pbnB1dCAgICBmYW42X2lucHV0ICBmYW44X2lu\n"
- "cHV0ICAgIG5hbWUKPj4gW3Jvb3RAdHVsMTYzcDEgfl0jCj4+IFtyb290QHR1bDE2M3AxIH5dIyBs\n"
- "cyAvc3lzL2NsYXNzL2h3bW9uL2h3bW9uMC8KPj4gZGV2aWNlICAgICAgICBmYW4yX21pbiAgICBm\n"
- "YW40X21pbiAgICBmYW42X21pbiAgICBmYW44X21pbiBwb3dlcjFfaW5wdXQKPj4gZmFuMV9mYXVs\n"
- "dCAgZmFuM19mYXVsdCAgICBmYW41X2ZhdWx0ICBmYW43X2ZhdWx0ICAgIGluMV9mYXVsdCBzdWJz\n"
- "eXN0ZW0KPj4gZmFuMV9pbnB1dCAgZmFuM19pbnB1dCAgICBmYW41X2lucHV0ICBmYW43X2lucHV0\n"
- "ICAgIGluMl9mYXVsdCAKPj4gdGVtcDFfaW5wdXQKPj4gZmFuMV9taW4gICAgZmFuM19taW4gICAg\n"
- "ZmFuNV9taW4gICAgZmFuN19taW4gICAgaW4zX2ZhdWx0IHRlbXAxX21heAo+PiBmYW4yX2ZhdWx0\n"
- "ICBmYW40X2ZhdWx0ICAgIGZhbjZfZmF1bHQgIGZhbjhfZmF1bHQgICAgaW40X2ZhdWx0IHVldmVu\n"
- "dAo+PiBmYW4yX2lucHV0ICBmYW40X2lucHV0ICAgIGZhbjZfaW5wdXQgIGZhbjhfaW5wdXQgICAg\n"
- "bmFtZQo+PiBbcm9vdEB0dWwxNjNwMSB+XSMKPj4KPgo+Cj4gVGhlIGluWF9mYXVsdCBhdHRyaWJ1\n"
- "dGVzIGRvbid0IHJlYWxseSBtYWtlIG11Y2ggc2Vuc2UuIF9mYXVsdCAKPiBhdHRyaWJ1dGVzIHdp\n"
- "dGhvdXQKPiBfaW5wdXQgYXR0cmlidXRlcyBkb24ndCBoYXZlIGFueSB2YWx1ZSBhbmQgYXJlLCBh\n"
- "cyB5b3Ugbm90aWNlZCwgbm90IAo+IGRpc3BsYXllZAo+IHdpdGggdGhlIHNlbnNvcnMgY29tbWFu\n"
- "ZC4gSXMgdGhpcyBhIHByb2JsZW0gaW4gdGVoIGRldmljZXRyZWUgZGF0YSBvciAKPiBkbyB5b3UK\n"
- "PiByZWFsbHkgaGF2ZSB2b2x0YWdlIGZhdWx0cyB3aXRob3V0IHZvbHRhZ2VzID8KClRoZXJlIGlz\n"
- "IG5vIGlzc3VlIHdpdGggdGhlIGRldmljZSBkYXRhLCBzb21laG93IEknbSBnZXR0aW5nIG9ubHkg\n"
- "dGhlIApfZmF1bHQgYXR0cmlidXRlCmZvciB0aGUgaW5YXyAocG93ZXItc3VwcGx5KSBhdHRyaWJ1\n"
- "dGVzLgoKPgo+PiBTaWduZWQtb2ZmLWJ5OiBOZWVsZXNoIEd1cHRhIDxuZWVsZWd1cEBsaW51eC52\n"
- "bmV0LmlibS5jb20+Cj4+IC0tLQo+Pgo+IENoZWNrcGF0Y2ggc2F5czoKPgo+IHRvdGFsOiA4IGVy\n"
- "cm9ycywgMTEgd2FybmluZ3MsIDM4OSBsaW5lcyBjaGVja2VkCj4KPiBOT1RFOiB3aGl0ZXNwYWNl\n"
- "IGVycm9ycyBkZXRlY3RlZCwgeW91IG1heSB3aXNoIHRvIHVzZSAKPiBzY3JpcHRzL2NsZWFucGF0\n"
- "Y2ggb3IKPiAgICAgICBzY3JpcHRzL2NsZWFuZmlsZQo+Cj4gd2hpY2ggc2hvdWxkIHJlYWxseSBu\n"
- "b3QgaGFwcGVuIGF0IHRoaXMgcG9pbnQuCj4KPiBQbGVhc2UgbWFrZSBzdXJlIHlvdSBmb2xsb3cg\n"
- "Q29kaW5nU3R5bGUuIGNoZWNrcGF0Y2ggLS1zdHJpY3QgcG9pbnRzIHRvIAo+IGEgbnVtYmVyCj4g\n"
- "b2YgYWRkaXRpb25hbCB2aW9sYXRpb25zLgo+Cj4gTW9yZSBjb21tZW50cyBpbmxpbmUuCgpGaXhl\n"
- "ZCBhbGwgb2YgdGhlc2UgaXNzdWVzIHJlbGF0ZWQgdG8gY29kaW5nIHN0eWxlLgoKPgo+PiBDaGFu\n"
- "Z2VzIGluIHYyCj4+ID09PT09PT09PT09PT0KPj4gLSBHZW5lcmljIHVzZSBvZiBkZXZtXyogZnVu\n"
- "Y3Rpb25zIGluIGh3bW9uIGxpa2UgdXNpbmcgZGV2bV9remFsbG9jKCkgCj4+IGZvciBkeW5hbWlj\n"
- "Cj4+ICAgIG1lbW9yeSByZXF1ZXN0LCBhdm9pZGluZyB0aGUgbmVlZCB0byBleHBsaWNpdCBmcmVl\n"
- "IG9mIG1lbW9yeS4KPj4gICAgQWRkaW5nICdzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwJyBhcyBtZW1i\n"
- "ZXIgb2YgcGxhdGZvcm0gZGF0YSAKPj4gc3RydWN0dXJlIHRvIGJlCj4+ICAgIHBvcHVsYXRlZCBh\n"
- "bmQgdGhlbiBwYXNzZWQgdG8gCj4+IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhfZ3Jv\n"
- "dXBzKCkuCj4+Cj4+ICAgIE5vdGU6IEhhdmluZyBhbiBhcnJheSBvZiBwb2ludGVycyBvZiAnYXR0\n"
- "cmlidXRlX2dyb3VwJyBhbmQgZWFjaCBncm91cAo+PiAgICBjb3JyZXNwb25kcyB0byAnZW51bSBz\n"
- "ZW5zb3JzJyB0eXBlLiBOb3QgY29tcGxldGVseSBzdXJlLCBpZiBpdCdzIAo+PiBpZGVhbCBvcgo+\n"
- "PiAgICBjb3VsZCBoYXZlIGp1c3Qgb25lIGdyb3VwIHBvcHVsYXRlZCB3aXRoIGF0dHJpYnV0ZXMg\n"
- "b2Ygc2Vuc29yIHR5cGVzPwo+Pgo+IFlvdXIgY2FsbCwgcmVhbGx5OyB3aGF0ZXZlciBpcyBlYXNp\n"
- "ZXIgZm9yIHlvdS4gSSB3b24ndCBkaWN0YXRlIG9uZSBvciAKPiB0aGUgb3RoZXIuCj4KPiBRdWVz\n"
- "dGlvbiB0aG91Z2ggaXMgd2hhdCBoYXBwZW5zIGlmIG9uZSBncm91cCBpcyBub3QgcG9wdWxhdGVk\n"
- "LiBJZiBJIAo+IHVuZGVyc3RhbmQKPiB0aGUgY29kZSBjb3JyZWN0bHkgdGhpcyB3aWxsIHJlc3Vs\n"
- "dCBpbiB0aGUgcmVtYWluaW5nIGdyb3VwcyB0byBiZSAKPiAnZHJvcHBlZCcsCj4gaWUgbm90IGRp\n"
- "c3BsYXllZCBhdCBhbGwuCgpZZXMsIHNob3VsZCBiZSBmaXhlZC4KCj4KPj4gLSAnaWJtcG93ZXJu\n"
- "dicgaXMgbm90IGhvdC1wbHVnZ2FibGUgZGV2aWNlIHNvIG1vdmluZyAKPj4gJ3BsYXRmb3JtX2Ry\n"
- "aXZlcicgY2FsbGJhY2sKPj4gICAgZnVuY3Rpb24gKHByb2JlKSBhcyBwYXJ0IG9mIF9faW5pdCBj\n"
- "b2RlLgo+PiAtIEZpeGVkIGlzc3VlcyByZWxhdGVkIHRvIGNvZGluZyBzdHlsZS4KPj4gLSBPdGhl\n"
- "ciBnZW5lcmFsIGNvbW1lbnRzIGluIHYxLgo+Pgo+PiAgIGRyaXZlcnMvaHdtb24vS2NvbmZpZyAg\n"
- "ICAgIHwgICAgOCArCj4+ICAgZHJpdmVycy9od21vbi9NYWtlZmlsZSAgICAgfCAgICAxCj4+ICAg\n"
- "ZHJpdmVycy9od21vbi9pYm1wb3dlcm52LmMgfCAgMzY4IAo+PiArKysrKysrKysrKysrKysrKysr\n"
- "KysrKysrKysrKysrKysrKysrKysrKysrKwo+Cj4gWW91J2xsIGFsc28gbmVlZCBEb2N1bWVudGF0\n"
- "aW9uL2h3bW9uL2libXBvd2VybnYgYW5kCj4gRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRp\n"
- "bmdzL2h3bW9uL2libXBvd2VybnYuCj4KPiBUaGUgbGF0dGVyIHdpbGwgbmVlZCB0byBnZXQgYW4g\n"
- "QWNrIGZyb20gdGhlIGRldmljZXRyZWUgbWFpbnRhaW5lcnMuCgpJJ2xsIGRvIGFzIHJlcXVpcmVk\n"
- "LgoKPj4gICAzIGZpbGVzIGNoYW5nZWQsIDM3NyBpbnNlcnRpb25zKCspCj4+ICAgY3JlYXRlIG1v\n"
- "ZGUgMTAwNjQ0IGRyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jCj4+Cj4+IGRpZmYgLS1naXQgYS9k\n"
- "cml2ZXJzL2h3bW9uL0tjb25maWcgYi9kcml2ZXJzL2h3bW9uL0tjb25maWcKPj4gaW5kZXggYmMx\n"
- "OTZmNC4uM2UzMDhmYSAxMDA2NDQKPj4gLS0tIGEvZHJpdmVycy9od21vbi9LY29uZmlnCj4+ICsr\n"
- "KyBiL2RyaXZlcnMvaHdtb24vS2NvbmZpZwo+PiBAQCAtNTU0LDYgKzU1NCwxNCBAQCBjb25maWcg\n"
- "U0VOU09SU19JQk1QRVgKPj4gICAgICAgICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBh\n"
- "cyBhIG1vZHVsZS4gIElmIHNvLCB0aGUgbW9kdWxlCj4+ICAgICAgICAgd2lsbCBiZSBjYWxsZWQg\n"
- "aWJtcGV4Lgo+Pgo+PiArY29uZmlnIFNFTlNPUlNfSUJNUE9XRVJOVgo+PiArICAgIHRyaXN0YXRl\n"
- "ICJJQk0gUE9XRVJOViBwbGF0Zm9ybSBzZW5zb3JzIgo+PiArICAgIGRlcGVuZHMgb24gUFBDX1BP\n"
- "V0VSTlYKPj4gKyAgICBkZWZhdWx0IHkKPj4gKyAgICBoZWxwCj4+ICsgICAgICBJZiB5b3Ugc2F5\n"
- "IHllcyBoZXJlIHlvdSBnZXQgc3VwcG9ydCBmb3IgdGhlIHRlbXBlcmF0dXJlL2Zhbi9wb3dlcgo+\n"
- "PiArICAgICAgc2Vuc29ycyBvbiB5b3VyIHBsYXRmb3JtLgo+PiArCj4+ICAgY29uZmlnIFNFTlNP\n"
- "UlNfSUlPX0hXTU9OCj4+ICAgICAgIHRyaXN0YXRlICJId21vbiBkcml2ZXIgdGhhdCB1c2VzIGNo\n"
- "YW5uZWxzIHNwZWNpZmllZCB2aWEgaWlvIG1hcHMiCj4+ICAgICAgIGRlcGVuZHMgb24gSUlPCj4+\n"
- "IGRpZmYgLS1naXQgYS9kcml2ZXJzL2h3bW9uL01ha2VmaWxlIGIvZHJpdmVycy9od21vbi9NYWtl\n"
- "ZmlsZQo+PiBpbmRleCBjNDhmOTg3Li4xOTljNDAxIDEwMDY0NAo+PiAtLS0gYS9kcml2ZXJzL2h3\n"
- "bW9uL01ha2VmaWxlCj4+ICsrKyBiL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPj4gQEAgLTcxLDYg\n"
- "KzcxLDcgQEAgb2JqLSQoQ09ORklHX1NFTlNPUlNfVUxUUkE0NSkgICAgKz0gdWx0cmE0NV9lbnYu\n"
- "bwo+PiAgIG9iai0kKENPTkZJR19TRU5TT1JTX0k1S19BTUIpICAgICs9IGk1a19hbWIubwo+PiAg\n"
- "IG9iai0kKENPTkZJR19TRU5TT1JTX0lCTUFFTSkgICAgKz0gaWJtYWVtLm8KPj4gICBvYmotJChD\n"
- "T05GSUdfU0VOU09SU19JQk1QRVgpICAgICs9IGlibXBleC5vCj4+ICtvYmotJChDT05GSUdfU0VO\n"
- "U09SU19JQk1QT1dFUk5WKSs9IGlibXBvd2VybnYubwo+PiAgIG9iai0kKENPTkZJR19TRU5TT1JT\n"
- "X0lJT19IV01PTikgKz0gaWlvX2h3bW9uLm8KPj4gICBvYmotJChDT05GSUdfU0VOU09SU19JTkEy\n"
- "MDkpICAgICs9IGluYTIwOS5vCj4+ICAgb2JqLSQoQ09ORklHX1NFTlNPUlNfSU5BMlhYKSAgICAr\n"
- "PSBpbmEyeHgubwo+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9pYm1wb3dlcm52LmMgYi9k\n"
- "cml2ZXJzL2h3bW9uL2libXBvd2VybnYuYwo+PiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+PiBpbmRl\n"
- "eCAwMDAwMDAwLi5hZmNlNjIwCj4+IC0tLSAvZGV2L251bGwKPj4gKysrIGIvZHJpdmVycy9od21v\n"
- "bi9pYm1wb3dlcm52LmMKPj4gQEAgLTAsMCArMSwzNjggQEAKPj4gKy8qCj4+ICsgKiBJQk0gUG93\n"
- "ZXJOViBwbGF0Zm9ybSBzZW5zb3JzIGZvciB0ZW1wZXJhdHVyZS9mYW4vcG93ZXIKPj4gKyAqIENv\n"
- "cHlyaWdodCAoQykgMjAxNCBJQk0KPj4gKyAqCj4+ICsgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBz\n"
- "b2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQo+PiArICogaXQg\n"
- "dW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJs\n"
- "aXNoZWQgYnkKPj4gKyAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJz\n"
- "aW9uIDIgb2YgdGhlIExpY2Vuc2UsIG9yCj4+ICsgKiAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRl\n"
- "ciB2ZXJzaW9uLgo+PiArICoKPj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0\n"
- "aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAo+PiArICogYnV0IFdJVEhPVVQgQU5ZIFdB\n"
- "UlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKPj4gKyAqIE1FUkNI\n"
- "QU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUK\n"
- "Pj4gKyAqIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCj4+ICsg\n"
- "Kgo+PiArICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVy\n"
- "YWwgUHVibGljIExpY2Vuc2UKPj4gKyAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtLgo+PiArICov\n"
- "Cj4+ICsKPj4gKyNpbmNsdWRlIDxsaW51eC9pbml0Lmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvbW9k\n"
- "dWxlLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgva2VybmVsLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgv\n"
- "aHdtb24uaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9od21vbi1zeXNmcy5oPgo+PiArI2luY2x1ZGUg\n"
- "PGxpbnV4L29mLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvc2xhYi5oPgo+PiArCj4+ICsjaW5jbHVk\n"
- "ZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4+ICsjaW5jbHVkZSA8YXNtL29wYWwuaD4KPj4g\n"
- "KyNpbmNsdWRlIDxsaW51eC9lcnIuaD4KPj4gKwo+PiArI2RlZmluZSBEUlZOQU1FICAgICAgICAi\n"
- "aWJtcG93ZXJudiIKPj4gKyNkZWZpbmUgTUFYX0FUVFJfTEVOICAgIDMyCj4+ICsKPj4gKy8qIFNl\n"
- "bnNvciBzdWZmaXggbmFtZSBmcm9tIERUICovCj4+ICsjZGVmaW5lIERUX0ZBVUxUX0FUVFJfU1VG\n"
- "RklYICAgICAgICAiZmF1bHRlZCIKPj4gKyNkZWZpbmUgRFRfREFUQV9BVFRSX1NVRkZJWCAgICAg\n"
- "ICAgImRhdGEiCj4+ICsjZGVmaW5lIERUX1RIUkVTSE9MRF9BVFRSX1NVRkZJWCAgICAidGhycyIK\n"
- "Pj4gKwo+PiArLyoKPj4gKyAqIEVudW1lcmF0ZXMgYWxsIHRoZSB0eXBlcyBvZiBzZW5zb3JzIGlu\n"
- "IHRoZSBQT1dFUk5WIHBsYXRmb3JtIGFuZCAKPj4gZG9lcyBpbmRleAo+PiArICogaW50byAnc3Ry\n"
- "dWN0IHNlbnNvcl9ncm91cCcKPj4gKyAqLwo+PiArZW51bSBzZW5zb3JzIHsKPj4gKyAgICBGQU4s\n"
- "Cj4+ICsgICAgQU1CSUVOVF9URU1QLAo+PiArICAgIFBPV0VSX1NVUFBMWSwKPj4gKyAgICBQT1dF\n"
- "Ul9JTlBVVCwKPj4gKyAgICBNQVhfU0VOU09SX1RZUEUsCj4+ICt9Owo+PiArCj4+ICtzdGF0aWMg\n"
- "c3RydWN0IHNlbnNvcl9ncm91cCB7Cj4+ICsgICAgY29uc3QgY2hhciAqbmFtZTsKPj4gKyAgICBj\n"
- "b25zdCBjaGFyICpjb21wYXRpYmxlOwo+PiArICAgIHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgZ3Jv\n"
- "dXA7Cj4+ICsgICAgdTMyIGF0dHJfY291bnQ7Cj4+ICt9IHNlbnNvcl9ncm91cHNbXSA9IHsKPj4g\n"
- "KyAgICB7ImZhbiIsICJpYm0sb3BhbC1zZW5zb3ItY29vbGluZy1mYW4iLCB7MH0sIDB9LAo+PiAr\n"
- "ICAgIHsidGVtcCIsICJpYm0sb3BhbC1zZW5zb3ItYW1iLXRlbXAiLCB7MH0sIDB9LAo+PiArICAg\n"
- "IHsiaW4iLCAiaWJtLG9wYWwtc2Vuc29yLXBvd2VyLXN1cHBseSIsIHswfSwgMH0sCj4+ICsgICAg\n"
- "eyJwb3dlciIsICJpYm0sb3BhbC1zZW5zb3ItcG93ZXIiLCB7MH0sIDB9Cj4+ICt9Owo+PiArCj4g\n"
- "VGhlICcwJyBpbml0aWFsaXphdGlvbnMgc2hvdWxkIG5vdCBiZSBuZWNlc3NhcnkuCj4KPgo+PiAr\n"
- "c3RydWN0IHNlbnNvcl9kYXRhIHsKPj4gKyAgICB1MzIgaWQ7IC8qIEFuIG9wYXF1ZSBpZCBvZiB0\n"
- "aGUgZmlybXdhcmUgZm9yIGVhY2ggc2Vuc29yICovCj4+ICsgICAgZW51bSBzZW5zb3JzIHR5cGU7\n"
- "Cj4+ICsgICAgY2hhciBuYW1lW01BWF9BVFRSX0xFTl07Cj4+ICsgICAgc3RydWN0IGRldmljZV9h\n"
- "dHRyaWJ1dGUgZGV2X2F0dHI7Cj4+ICt9Owo+PiArCj4+ICtzdHJ1Y3QgcGxhdGZvcm1fZGF0YSB7\n"
- "Cj4+ICsgICAgY29uc3Qgc3RydWN0IGF0dHJpYnV0ZV9ncm91cCAqYXR0cl9ncm91cHNbTUFYX1NF\n"
- "TlNPUl9UWVBFICsgMV07Cj4+ICsgICAgdTMyIHNlbnNvcnNfY291bnQ7IC8qIFRvdGFsIGNvdW50\n"
- "IG9mIHNlbnNvcnMgZnJvbSBlYWNoIGdyb3VwICovCj4+ICt9Owo+PiArCj4+ICsvKiBQbGF0Zm9y\n"
- "bSBkZXZpY2UgcmVwcmVzZW50aW5nIGFsbCB0aGUgaWJtcG93ZXJudiBzZW5zb3JzICovCj4+ICtz\n"
- "dGF0aWMgc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldmljZTsKPj4gKwo+PiArc3RhdGljIHNz\n"
- "aXplX3Qgc2hvd19zZW5zb3Ioc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgCj4+IGRldmljZV9h\n"
- "dHRyaWJ1dGUgKmRldmF0dHIsCj4+ICsgICAgICAgICAgICAgICBjaGFyICpidWYpCj4+ICt7Cj4+\n"
- "ICsgICAgc3RydWN0IHNlbnNvcl9kYXRhICpzZGF0YSA9IGNvbnRhaW5lcl9vZihkZXZhdHRyLCBz\n"
- "dHJ1Y3QgCj4+IHNlbnNvcl9kYXRhLAo+PiArICAgICAgICAgICAgICAgICAgICAgICAgIGRldl9h\n"
- "dHRyKTsKPj4gKyAgICBzc2l6ZV90IHJldDsKPj4gKyAgICB1MzIgeDsKPj4gKwo+PiArICAgIHJl\n"
- "dCA9IG9wYWxfZ2V0X3NlbnNvcl9kYXRhKHNkYXRhLT5pZCwgJngpOwo+PiArICAgIGlmIChyZXQp\n"
- "IHsKPj4gKyAgICAgICAgcHJfZXJyKCIlczogRmFpbGVkIHRvIGdldCBvcGFsIHNlbnNvciBkYXRh\n"
- "XG4iLCBfX2Z1bmNfXyk7Cj4+ICsgICAgICAgIHJldHVybiByZXQ7Cj4+ICsgICAgfQo+PiArCj4+\n"
- "ICsgICAgLyogQ29udmVydCB0ZW1wZXJhdHVyZSB0byBtaWxsaS1kZWdyZWVzICovCj4+ICsgICAg\n"
- "aWYgKHNkYXRhLT50eXBlID09IEFNQklFTlRfVEVNUCkKPj4gKyAgICAgICAgeCAqPSAxMDAwOwo+\n"
- "PiArICAgIC8qIENvbnZlcnQgcG93ZXIgdG8gbWljcm8td2F0dHMgKi8KPj4gKyAgICBlbHNlIGlm\n"
- "IChzZGF0YS0+dHlwZSA9PSBQT1dFUl9JTlBVVCkKPj4gKyAgICAgICAgeCAqPSAxMDAwMDAwOwo+\n"
- "PiArCj4+ICsgICAgcmV0dXJuIHNwcmludGYoYnVmLCAiJWRcbiIsIHgpOwo+Cj4geCBpcyB1bnNp\n"
- "Z25lZCwgc28gJXUuCgpEb25lLgoKPgo+PiArfQo+PiArCj4+ICtzdGF0aWMgdm9pZCBfX2luaXQg\n"
- "Z2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0IGNoYXIgKm5hbWUsIHUzMiAKPj4gKmluZGV4LCBj\n"
- "aGFyICphdHRyKQo+PiArewo+PiArICAgIGNoYXIgKmhhc2hfcG9zID0gc3RyY2hyKG5hbWUsICcj\n"
- "Jyk7Cj4+ICsgICAgY2hhciAqZGFzaF9wb3M7Cj4+ICsgICAgdTMyIGNvcHlfbGVuOwo+PiArICAg\n"
- "IGNoYXIgYnVmWzhdOwo+PiArCj4+ICsgICAgbWVtc2V0KGJ1ZiwgMCwgc2l6ZW9mKGJ1ZikpOwo+\n"
- "PiArICAgICppbmRleCA9IDA7Cj4+ICsgICAgKmF0dHIgPSAnXDAnOwo+PiArCj4+ICsgICAgaWYg\n"
- "KGhhc2hfcG9zKSB7Cj4+ICsgICAgICAgIGRhc2hfcG9zID0gc3RyY2hyKGhhc2hfcG9zLCAnLScp\n"
- "Owo+PiArICAgICAgICBpZiAoZGFzaF9wb3MpIHsKPj4gKyAgICAgICAgICAgIGNvcHlfbGVuID0g\n"
- "ZGFzaF9wb3MgLSBoYXNoX3BvcyAtIDE7Cj4+ICsgICAgICAgICAgICBpZiAoY29weV9sZW4gPCBz\n"
- "aXplb2YoYnVmKSkgewo+PiArICAgICAgICAgICAgICAgIHN0cm5jcHkoYnVmLCBoYXNoX3BvcyAr\n"
- "IDEsIGNvcHlfbGVuKTsKPj4gKyAgICAgICAgICAgICAgICBzc2NhbmYoYnVmLCAiJWQiLCBpbmRl\n"
- "eCk7Cj4KPiBXaGF0IGlmIHNzY2FuZiBmYWlscyA/IE1pZ2h0IGJlIGFuIGludGVyZXN0aW5nIGV4\n"
- "ZXJjaXNlIHRvIHRyeSBhbmQgY3JlYXRlCj4gbXVsdGlwbGUgc2Vuc29ycyB3aXRoIGluZGV4IDAg\n"
- "KG9yLCBmb3IgdGhhdCBtYXR0ZXIsIHdpdGggdGhlIHNhbWUgCj4gaW5kZXggdmFsdWUpLgo+IERv\n"
- "IHlvdSBoYXZlIGFueSBwcm90ZWN0aW9uIGFnYWluc3QgYmFkIGlucHV0IGRhdGEgPyBHdWVzcyBu\n"
- "b3Q7IGRpZCB5b3UgCj4gdGVzdAo+IHdoYXQgaGFwcGVucyBpZiB5b3UgcGFzcyBiYWQgZGF0YSB0\n"
- "byB0aGUgZHJpdmVyIChzdWNoIGFzIGR1cGxpY2F0ZSBzZW5zb3IKPiBlbnRyaWVzKSA/CgpXZWxs\n"
- "LCByZXdyaXRpbmcgdGhpcyBmdW5jdGlvbiB0byByZXR1cm4gdGhlIGVycm9yIGNvZGUgaWYgZmFp\n"
- "bHMuCk5leHQgdmVyc2lvbiB3aWxsIGNvdmVyIHRoZXNlIHRlc3QgY2FzZXMgY292ZXJlZC4gVGhh\n"
- "bmtzLgoKPgo+PiArICAgICAgICAgICAgfQo+PiArCj4+ICsgICAgICAgICAgICBzdHJuY3B5KGF0\n"
- "dHIsIGRhc2hfcG9zICsgMSwgTUFYX0FUVFJfTEVOKTsKPj4gKyAgICAgICAgfQo+PiArICAgIH0K\n"
- "Pj4gK30KPj4gKwo+PiArLyoKPj4gKyAqIFRoaXMgZnVuY3Rpb24gdHJhbnNsYXRlcyB0aGUgRFQg\n"
- "bm9kZSBuYW1lIGludG8gdGhlICdod21vbicgCj4+IGF0dHJpYnV0ZSBuYW1lLgo+PiArICogSUJN\n"
- "UE9XRVJOViBkZXZpY2Ugbm9kZSBhcHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIAo+PiBh\n"
- "bWItdGVtcCMxLXRocnMgZXRjLgo+PiArICogd2hpY2ggbmVlZCB0byBiZSBtYXBwZWQgYXMgZmFu\n"
- "Ml9pbnB1dCwgdGVtcDFfbWF4IHJlc3BlY3RpdmVseSBiZWZvcmUKPj4gKyAqIHBvcHVsYXRpbmcg\n"
- "dGhlbSBpbnNpZGUgaHdtb24gZGV2aWNlIGNsYXNzLi4KPj4gKyAqLwo+PiArc3RhdGljIGludCBf\n"
- "X2luaXQgY3JlYXRlX2h3bW9uX2F0dHJfbmFtZShlbnVtIHNlbnNvcnMgdHlwZSwgY29uc3QgCj4+\n"
- "IGNoYXIgKm5vZGVfbmFtZSwKPj4gKyAgICAgICAgICAgICAgICAgIGNoYXIgKmh3bW9uX2F0dHJf\n"
- "bmFtZSkKPj4gK3sKPj4gKyAgICBjaGFyIGF0dHJfc3VmZml4W01BWF9BVFRSX0xFTl07Cj4+ICsg\n"
- "ICAgY2hhciAqYXR0cl9uYW1lOwo+PiArICAgIHUzMiBpbmRleDsKPj4gKwo+PiArICAgIGdldF9z\n"
- "ZW5zb3JfaW5kZXhfYXR0cihub2RlX25hbWUsICZpbmRleCwgYXR0cl9zdWZmaXgpOwo+PiArICAg\n"
- "IGlmICghaW5kZXggfHwgIXN0cmxlbihhdHRyX3N1ZmZpeCkpIHsKPj4gKyAgICAgICAgcHJfaW5m\n"
- "bygiJXM6IFNlbnNvciBkZXZpY2Ugbm9kZSBuYW1lIGlzIGludmFsaWQsIG5hbWU6ICVzXG4iLAo+\n"
- "PiArICAgICAgICAgICAgICAgIF9fZnVuY19fLCBub2RlX25hbWUpOwo+PiArICAgICAgICByZXR1\n"
- "cm4gLUVJTlZBTDsKPj4gKyAgICB9Cj4+ICsKPj4gKyAgICBpZiAoIXN0cmNtcChhdHRyX3N1ZmZp\n"
- "eCwgRFRfRkFVTFRfQVRUUl9TVUZGSVgpKQo+PiArICAgICAgICBhdHRyX25hbWUgPSAiZmF1bHQi\n"
- "Owo+PiArICAgIGVsc2UgaWYoIXN0cmNtcChhdHRyX3N1ZmZpeCwgRFRfREFUQV9BVFRSX1NVRkZJ\n"
- "WCkpCj4+ICsgICAgICAgIGF0dHJfbmFtZSA9ICJpbnB1dCI7Cj4+ICsgICAgZWxzZSBpZiAoIXN0\n"
- "cmNtcChhdHRyX3N1ZmZpeCwgRFRfVEhSRVNIT0xEX0FUVFJfU1VGRklYKSkgewo+PiArICAgICAg\n"
- "ICBpZiAodHlwZSA9PSBBTUJJRU5UX1RFTVApCj4+ICsgICAgICAgICAgICBhdHRyX25hbWUgPSAi\n"
- "bWF4IjsKPj4gKyAgICAgICAgZWxzZSBpZiAodHlwZSA9PSBGQU4pCj4+ICsgICAgICAgICAgICBh\n"
- "dHRyX25hbWUgPSAibWluIjsKPj4gKyAgICAgICAgZWxzZQo+PiArICAgICAgICAgICAgcmV0dXJu\n"
- "IC1FTk9FTlQ7Cj4+ICsgICAgfSBlbHNlCj4+ICsgICAgICAgIHJldHVybiAtRU5PRU5UOwo+PiAr\n"
- "Cj4+ICsgICAgc25wcmludGYoaHdtb25fYXR0cl9uYW1lLCBNQVhfQVRUUl9MRU4sICIlcyVkXyVz\n"
- "IiwKPj4gKyAgICAgICAgICAgIHNlbnNvcl9ncm91cHNbdHlwZV0ubmFtZSwgaW5kZXgsIGF0dHJf\n"
- "bmFtZSk7Cj4+ICsgICAgcmV0dXJuIDA7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBpbnQgX19pbml0\n"
- "IHBvcHVsYXRlX2F0dHJfZ3JvdXBzKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4+ICt7\n"
- "Cj4+ICsgICAgc3RydWN0IHBsYXRmb3JtX2RhdGEgKnBkYXRhID0gcGxhdGZvcm1fZ2V0X2RydmRh\n"
- "dGEocGRldik7Cj4+ICsgICAgY29uc3Qgc3RydWN0IGF0dHJpYnV0ZV9ncm91cCAqKnBncm91cHMg\n"
- "PSBwZGF0YS0+YXR0cl9ncm91cHM7Cj4+ICsgICAgc3RydWN0IGRldmljZV9ub2RlICpvcGFsLCAq\n"
- "bnA7Cj4+ICsgICAgZW51bSBzZW5zb3JzIHR5cGU7Cj4+ICsgICAgaW50IGVyciA9IDA7Cj4+ICsK\n"
- "Pj4gKyAgICBvcGFsID0gb2ZfZmluZF9ub2RlX2J5X3BhdGgoIi9pYm0sb3BhbC9zZW5zb3JzIik7\n"
- "Cj4+ICsgICAgICAgIGlmICghb3BhbCkgewo+Cj4gQW4gb2J2aW91cyB3aGl0ZXNwYWNlIGVycm9y\n"
- "IGhlcmUuCj4KPj4gKyAgICAgICAgcHJfZXJyKCIlczogT3BhbCAnc2Vuc29ycycgbm9kZSBub3Qg\n"
- "Zm91bmRcbiIsIF9fZnVuY19fKTsKPj4gKyAgICAgICAgcmV0dXJuIC1FTk9ERVY7Cj4+ICsgICAg\n"
- "ICAgIH0KPj4gKwo+PiArICAgIGZvcl9lYWNoX2NoaWxkX29mX25vZGUob3BhbCwgbnApIHsKPj4g\n"
- "KyAgICAgICAgaWYgKG5wLT5uYW1lID09IE5VTEwpCj4+ICsgICAgICAgICAgICBjb250aW51ZTsK\n"
- "Pj4gKwo+PiArICAgICAgICBmb3IgKHR5cGUgPSAwOyB0eXBlIDwgTUFYX1NFTlNPUl9UWVBFOyB0\n"
- "eXBlKyspCj4+ICsgICAgICAgICAgICBpZiAob2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCj4+\n"
- "ICsgICAgICAgICAgICAgICAgc2Vuc29yX2dyb3Vwc1t0eXBlXS5jb21wYXRpYmxlKSkgewo+PiAr\n"
- "ICAgICAgICAgICAgICAgIHNlbnNvcl9ncm91cHNbdHlwZV0uYXR0cl9jb3VudCsrOwo+PiArICAg\n"
- "ICAgICAgICAgICAgIGJyZWFrOwo+PiArICAgICAgICAgICAgfQo+PiArICAgIH0KPgo+IFlvdSBz\n"
- "aG91bGQgYmUgYWJsZSB0byBkbwo+ICAgICBvZl9ub2RlX3B1dChvcGFsKTsKPgo+IGhlcmUuIFRo\n"
- "ZW4geW91IGNhbiByZXR1cm4gaW1tZWRpYXRlbHkgb24gZXJyb3IgYmVsb3cuCgpEb25lLgoKPgo+\n"
- "PiArCj4+ICsgICAgZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5TT1JfVFlQRTsgdHlwZSsr\n"
- "KSB7Cj4+ICsgICAgICAgIGlmICghc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRyX2NvdW50KQo+PiAr\n"
- "ICAgICAgICAgICAgY29udGludWU7Cj4+ICsKPj4gKyAgICAgICAgc2Vuc29yX2dyb3Vwc1t0eXBl\n"
- "XS5ncm91cC5hdHRycyA9IGRldm1fa3phbGxvYygmcGRldi0+ZGV2LAo+PiArICAgICAgICAgICAg\n"
- "ICAgICAgICBzaXplb2Yoc3RydWN0IGF0dHJpYnV0ZSopICoKPj4gKyAgICAgICAgICAgICAgICAg\n"
- "ICAgKHNlbnNvcl9ncm91cHNbdHlwZV0uYXR0cl9jb3VudCArIDEpLAo+PiArICAgICAgICAgICAg\n"
- "ICAgICAgICBHRlBfS0VSTkVMKTsKPj4gKyAgICAgICAgaWYgKCFzZW5zb3JfZ3JvdXBzW3R5cGVd\n"
- "Lmdyb3VwLmF0dHJzKSB7Cj4+ICsgICAgICAgICAgICBwcl9lcnIoIiVzOiBGYWlsZWQgdG8gYWxs\n"
- "b2NhdGUgbWVtb3J5IGZvciBhdHRyaWJ1dGUiCj4+ICsgICAgICAgICAgICAgICAgICAgICJhcnJh\n"
- "eVxuIiwgX19mdW5jX18pOwo+Cj4gZGV2bV9remFsbG9jKCkgYWxyZWFkeSBkdW1wcyBhbiBlcnJv\n"
- "ciBtZXNzYWdlLiBTYW1lIGZvciBhbGwgb3RoZXIgCj4gbWVtb3J5IGVycm9yIG1lc3NhZ2VzLgo+\n"
- "Cj4+ICsgICAgICAgICAgICBlcnIgPSAtRU5PTUVNOwo+PiArICAgICAgICAgICAgZ290byBleGl0\n"
- "X3B1dF9ub2RlOwo+PiArICAgICAgICB9Cj4+ICsKPj4gKyAgICAgICAgcGdyb3Vwc1t0eXBlXSA9\n"
- "ICZzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwOwo+PiArICAgICAgICBwZGF0YS0+c2Vuc29yc19j\n"
- "b3VudCArPSBzZW5zb3JfZ3JvdXBzW3R5cGVdLmF0dHJfY291bnQ7Cj4+ICsgICAgICAgIHNlbnNv\n"
- "cl9ncm91cHNbdHlwZV0uYXR0cl9jb3VudCA9IDA7Cj4+ICsgICAgfQo+PiArCj4+ICtleGl0X3B1\n"
- "dF9ub2RlOgo+PiArICAgIG9mX25vZGVfcHV0KG9wYWwpOwo+PiArICAgIHJldHVybiBlcnI7Cj4+\n"
- "ICt9Cj4+ICsKPj4gKy8qCj4+ICsgKiBJdGVyYXRlIHRocm91Z2ggdGhlIGRldmljZSB0cmVlIGZv\n"
- "ciBlYWNoIGNoaWxkIG9mIHNlbnNvciBub2RlLCAKPj4gY3JlYXRlCj4+ICsgKiBhIHN5c2ZzIGF0\n"
- "dHJpYnV0ZSBmaWxlLCB0aGUgZmlsZSBpcyBuYW1lZCBieSB0cmFuc2xhdGluZyB0aGUgRFQgCj4+\n"
- "IG5vZGUgbmFtZQo+PiArICogdG8gdGhlIG5hbWUgcmVxdWlyZWQgYnkgdGhlIGhpZ2hlciAnaHdt\n"
- "b24nIGRyaXZlciBsaWtlIAo+PiBmYW4xX2lucHV0LCB0ZW1wMV9tYXgKPj4gKyAqIGV0Yy4uCj4+\n"
- "ICsgKi8KPj4gK3N0YXRpYyBpbnQgX19pbml0IGNyZWF0ZV9kZXZpY2VfYXR0cnMoc3RydWN0IHBs\n"
- "YXRmb3JtX2RldmljZSAqcGRldikKPj4gK3sKPj4gKyAgICBzdHJ1Y3QgcGxhdGZvcm1fZGF0YSAq\n"
- "cGRhdGEgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKPj4gKyAgICBjb25zdCBzdHJ1Y3Qg\n"
- "YXR0cmlidXRlX2dyb3VwICoqcGdyb3VwcyA9IHBkYXRhLT5hdHRyX2dyb3VwczsKPj4gKyAgICBz\n"
- "dHJ1Y3QgZGV2aWNlX25vZGUgKm9wYWwsICpucDsKPj4gKyAgICBzdHJ1Y3Qgc2Vuc29yX2RhdGEg\n"
- "KnNkYXRhOwo+PiArICAgIGNvbnN0IHUzMiAqc2Vuc29yX2lkOwo+PiArICAgIGVudW0gc2Vuc29y\n"
- "cyB0eXBlOwo+PiArICAgIHUzMiBjb3VudCA9IDA7Cj4+ICsgICAgaW50IGVyciA9IDA7Cj4+ICsK\n"
- "Pj4gKyAgICBvcGFsID0gb2ZfZmluZF9ub2RlX2J5X3BhdGgoIi9pYm0sb3BhbC9zZW5zb3JzIik7\n"
- "Cj4+ICsgICAgICAgIGlmICghb3BhbCkgewo+PiArICAgICAgICBwcl9lcnIoIiVzOiBPcGFsICdz\n"
- "ZW5zb3JzJyBub2RlIG5vdCBmb3VuZFxuIiwgX19mdW5jX18pOwo+PiArICAgICAgICByZXR1cm4g\n"
- "LUVOT0RFVjsKPj4gKyAgICAgICAgfQo+PiArCj4+ICsgICAgc2RhdGEgPSBkZXZtX2t6YWxsb2Mo\n"
- "JnBkZXYtPmRldiwgKHBkYXRhLT5zZW5zb3JzX2NvdW50KSAqCj4+ICsgICAgICAgICAgICAgICAg\n"
- "IHNpemVvZigqc2RhdGEpLCBHRlBfS0VSTkVMKTsKPj4gKyAgICBpZiAoIXNkYXRhKSB7Cj4+ICsg\n"
- "ICAgICAgIHByX2VycigiJXM6IEZhaWxlZCB0byBhbGxvY2F0ZSBtZW1vcnkgZm9yIHRoZSBzZW5z\n"
- "b3JfZGF0YSIsCj4+ICsgICAgICAgICAgICAgICAgX19mdW5jX18pOwo+PiArICAgICAgICBlcnIg\n"
- "PSAtRU5PTUVNOwo+PiArICAgICAgICBnb3RvIGV4aXRfcHV0X25vZGU7Cj4+ICsgICAgfQo+PiAr\n"
- "Cj4+ICsgICAgZm9yX2VhY2hfY2hpbGRfb2Zfbm9kZShvcGFsLCBucCkgewo+PiArICAgICAgICAg\n"
- "ICAgICAgIGlmIChucC0+bmFtZSA9PSBOVUxMKQo+PiArICAgICAgICAgICAgICAgICAgICAgICAg\n"
- "Y29udGludWU7Cj4+ICsKPj4gKyAgICAgICAgZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5T\n"
- "T1JfVFlQRTsgdHlwZSsrKQo+PiArICAgICAgICAgICAgaWYgKG9mX2RldmljZV9pc19jb21wYXRp\n"
- "YmxlKG5wLAo+PiArICAgICAgICAgICAgICAgICAgICBzZW5zb3JfZ3JvdXBzW3R5cGVdLmNvbXBh\n"
- "dGlibGUpKQo+PiArICAgICAgICAgICAgICAgIGJyZWFrOwo+PiArCj4+ICsgICAgICAgIGlmICh0\n"
- "eXBlID09IE1BWF9TRU5TT1JfVFlQRSkKPj4gKyAgICAgICAgICAgIGNvbnRpbnVlOwo+PiArCj4+\n"
- "ICsgICAgICAgIHNlbnNvcl9pZCA9IG9mX2dldF9wcm9wZXJ0eShucCwgInNlbnNvci1pZCIsIE5V\n"
- "TEwpOwo+PiArICAgICAgICBpZiAoIXNlbnNvcl9pZCkgewo+PiArICAgICAgICAgICAgcHJfaW5m\n"
- "bygiJXM6ICVzIGRvZXNuJ3QgaGF2ZSBzZW5zb3ItaWRcbiIsIF9fZnVuY19fLAo+PiArICAgICAg\n"
- "ICAgICAgICAgIG5wLT5uYW1lKTsKPj4gKyAgICAgICAgICAgIGNvbnRpbnVlOwo+PiArICAgICAg\n"
- "ICB9Cj4+ICsKPiBDb25zaWRlciB1c2luZyBvZl9wcm9wZXJ0eV9yZWFkX3UzMigpLgoKT2theS4K\n"
- "Cj4KPj4gKyAgICAgICAgc2RhdGFbY291bnRdLmlkID0gKnNlbnNvcl9pZDsKPj4gKyAgICAgICAg\n"
- "c2RhdGFbY291bnRdLnR5cGUgPSB0eXBlOwo+PiArICAgICAgICBlcnIgPSBjcmVhdGVfaHdtb25f\n"
- "YXR0cl9uYW1lKHR5cGUsIG5wLT5uYW1lLCAKPj4gc2RhdGFbY291bnRdLm5hbWUpOwo+PiArICAg\n"
- "ICAgICBpZiAoZXJyKQo+PiArICAgICAgICAgICAgZ290byBleGl0X3B1dF9ub2RlOwo+PiArCj4+\n"
- "ICsgICAgICAgIHN5c2ZzX2F0dHJfaW5pdCgmc2RhdGFbY291bnRdLmRldl9hdHRyLmF0dHIpOwo+\n"
- "PiArICAgICAgICBzZGF0YVtjb3VudF0uZGV2X2F0dHIuYXR0ci5uYW1lID0gc2RhdGFbY291bnRd\n"
- "Lm5hbWU7Cj4+ICsgICAgICAgIHNkYXRhW2NvdW50XS5kZXZfYXR0ci5hdHRyLm1vZGUgPSBTX0lS\n"
- "VUdPOwo+PiArICAgICAgICBzZGF0YVtjb3VudF0uZGV2X2F0dHIuc2hvdyA9IHNob3dfc2Vuc29y\n"
- "Owo+PiArCj4+ICsgcGdyb3Vwc1t0eXBlXS0+YXR0cnNbc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRy\n"
- "X2NvdW50KytdID0KPj4gKyAgICAgICAgICAgICAgICAmc2RhdGFbY291bnQrK10uZGV2X2F0dHIu\n"
- "YXR0cjsKPj4gKyAgICB9Cj4+ICsKPj4gK2V4aXRfcHV0X25vZGU6Cj4+ICsgICAgb2Zfbm9kZV9w\n"
- "dXQob3BhbCk7Cj4+ICsgICAgcmV0dXJuIGVycjsKPj4gK30KPj4gKwo+PiArc3RhdGljIGludCBf\n"
- "X2luaXQgaWJtcG93ZXJudl9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+PiAr\n"
- "ewo+PiArICAgIHN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YTsKPj4gKyAgICBzdHJ1Y3QgZGV2\n"
- "aWNlICpod21vbl9kZXY7Cj4+ICsgICAgaW50IGVycjsKPj4gKwo+PiArICAgIHBkYXRhID0gZGV2\n"
- "bV9remFsbG9jKCZwZGV2LT5kZXYsIHNpemVvZigqcGRhdGEpLCBHRlBfS0VSTkVMKTsKPj4gKyAg\n"
- "ICBpZiAoIXBkYXRhKQo+PiArICAgICAgICByZXR1cm4gLUVOT01FTTsKPj4gKwo+PiArICAgIHBs\n"
- "YXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIHBkYXRhKTsKPj4gKyAgICBwZGF0YS0+c2Vuc29yc19j\n"
- "b3VudCA9IDA7Cj4+ICsgICAgZXJyID0gcG9wdWxhdGVfYXR0cl9ncm91cHMocGRldik7Cj4+ICsg\n"
- "ICAgaWYgKGVycikKPj4gKyAgICAgICAgcmV0dXJuIGVycjsKPj4gKwo+PiArICAgIC8qIENyZWF0\n"
- "ZSBzeXNmcyBhdHRyaWJ1dGUgZmlsZSBmb3IgZWFjaCBzZW5zb3IgZm91bmQgaW4gdGhlIERUICov\n"
- "Cj4KPiBBdHRyaWJ1dGUgZGF0YSwgbm90IGZpbGUKPgo+PiArICAgIGVyciA9IGNyZWF0ZV9kZXZp\n"
- "Y2VfYXR0cnMocGRldik7Cj4+ICsgICAgaWYgKGVycikKPj4gKyAgICAgICAgcmV0dXJuIGVycjsK\n"
- "Pj4gKwo+PiArICAgIC8qIEZpbmFsbHksIHJlZ2lzdGVyIHdpdGggaHdtb24gKi8KPj4gKyAgICBo\n"
- "d21vbl9kZXYgPSBkZXZtX2h3bW9uX2RldmljZV9yZWdpc3Rlcl93aXRoX2dyb3VwcygmcGRldi0+\n"
- "ZGV2LCAKPj4gRFJWTkFNRSwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZGF0\n"
- "YSwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZGF0YS0+YXR0cl9ncm91cHMp\n"
- "Owo+PiArCj4+ICsgICAgcmV0dXJuIFBUUl9FUlJfT1JfWkVSTyhod21vbl9kZXYpOwo+PiArfQo+\n"
- "PiArCj4+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBpYm1wb3dlcm52X2RyaXZlciA9\n"
- "IHsKPj4gKyAgICAuZHJpdmVyID0gewo+PiArICAgICAgICAub3duZXIgPSBUSElTX01PRFVMRSwK\n"
- "Pj4gKyAgICAgICAgLm5hbWUgPSBEUlZOQU1FLAo+PiArICAgIH0sCj4+ICt9Owo+PiArCj4+ICtz\n"
- "dGF0aWMgaW50IF9faW5pdCBpYm1wb3dlcm52X2luaXQodm9pZCkKPj4gK3sKPj4gKyAgICBpbnQg\n"
- "ZXJyOwo+PiArCj4+ICsgICAgcGRldmljZSA9IHBsYXRmb3JtX2RldmljZV9hbGxvYyhEUlZOQU1F\n"
- "LCAwKTsKPj4gKyAgICBpZiAoIXBkZXZpY2UpIHsKPj4gKyAgICAgICAgcHJfZXJyKCIlczogRGV2\n"
- "aWNlIGFsbG9jYXRpb24gZmFpbGVkXG4iLCBfX2Z1bmNfXyk7Cj4+ICsgICAgICAgIGVyciA9IC1F\n"
- "Tk9NRU07Cj4+ICsgICAgICAgIGdvdG8gZXhpdDsKPj4gKyAgICB9Cj4+ICsKPj4gKyAgICBlcnIg\n"
- "PSBwbGF0Zm9ybV9kZXZpY2VfYWRkKHBkZXZpY2UpOwo+PiArICAgIGlmIChlcnIpIHsKPj4gKyAg\n"
- "ICAgICAgcHJfZXJyKCIlczogRGV2aWNlIGFkZGl0aW9uIGZhaWxlZCAoJWQpXG4iLCBfX2Z1bmNf\n"
- "XywgZXJyKTsKPj4gKyAgICAgICAgZ290byBleGl0X2RldmljZV9wdXQ7Cj4+ICsgICAgfQo+PiAr\n"
- "Cj4+ICsgICAgZXJyID0gcGxhdGZvcm1fZHJpdmVyX3Byb2JlKCZpYm1wb3dlcm52X2RyaXZlciwg\n"
- "aWJtcG93ZXJudl9wcm9iZSk7Cj4+ICsgICAgaWYgKGVycikgewo+PiArICAgICAgICBwcl9lcnIo\n"
- "IiVzOiBQbGF0ZnJvbSBkcml2ZXIgcHJvYmUgZmFpbGVkXG4iLCBfX2Z1bmNfXyk7Cj4+ICsgICAg\n"
- "ICAgIGdvdG8gZXhpdF9kZXZpY2VfZGVsOwo+PiArICAgIH0KPj4gKwo+PiArICAgIHJldHVybiAw\n"
- "Owo+PiArCj4+ICtleGl0X2RldmljZV9kZWw6Cj4+ICsgICAgcGxhdGZvcm1fZGV2aWNlX2RlbChw\n"
- "ZGV2aWNlKTsKPj4gK2V4aXRfZGV2aWNlX3B1dDoKPj4gKyAgICBwbGF0Zm9ybV9kZXZpY2VfcHV0\n"
- "KHBkZXZpY2UpOwo+PiArZXhpdDoKPj4gKyAgICByZXR1cm4gZXJyOwo+PiArfQo+PiArCj4+ICtz\n"
- "dGF0aWMgdm9pZCBfX2V4aXQgaWJtcG93ZXJudl9leGl0KHZvaWQpCj4+ICt7Cj4+ICsgICAgcGxh\n"
- "dGZvcm1fZHJpdmVyX3VucmVnaXN0ZXIoJmlibXBvd2VybnZfZHJpdmVyKTsKPj4gKyAgICBwbGF0\n"
- "Zm9ybV9kZXZpY2VfdW5yZWdpc3RlcihwZGV2aWNlKTsKPj4gK30KPj4gKwo+PiArTU9EVUxFX0FV\n"
- "VEhPUigiTmVlbGVzaCBHdXB0YSA8bmVlbGVndXBAbGludXgudm5ldC5pYm0uY29tPiIpOwo+PiAr\n"
- "TU9EVUxFX0RFU0NSSVBUSU9OKCJJQk0gUE9XRVJOViBwbGF0Zm9ybSBzZW5zb3JzIik7Cj4+ICtN\n"
- "T0RVTEVfTElDRU5TRSgiR1BMIik7Cj4+ICsKPj4gK21vZHVsZV9pbml0KGlibXBvd2VybnZfaW5p\n"
- "dCk7Cj4+ICttb2R1bGVfZXhpdChpYm1wb3dlcm52X2V4aXQpOwo+Pgo+Pgo+Pgo+CgoKX19fX19f\n"
- "X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbG0tc2Vuc29ycyBtYWls\n"
- "aW5nIGxpc3QKbG0tc2Vuc29yc0BsbS1zZW5zb3JzLm9yZwpodHRwOi8vbGlzdHMubG0tc2Vuc29y\n"
- cy5vcmcvbWFpbG1hbi9saXN0aW5mby9sbS1zZW5zb3Jz
+ "\n"
+ "On 05/28/2014 12:53 PM, Guenter Roeck wrote:\n"
+ "> On 05/19/2014 07:26 AM, Neelesh Gupta wrote:\n"
+ ">> This patch adds basic kernel enablement for reading power values, fan\n"
+ ">> speed rpm and temperature values on powernv platforms which will\n"
+ ">> be exported to user space through sysfs interface.\n"
+ ">>\n"
+ ">> Test results:\n"
+ ">> -------------\n"
+ ">> [root@tul163p1 ~]# sensors\n"
+ ">> ibmpowernv-isa-0000\n"
+ ">> Adapter: ISA adapter\n"
+ ">> fan1:        5487 RPM  (min =    0 RPM)\n"
+ ">> fan2:        5152 RPM  (min =    0 RPM)\n"
+ ">> fan3:        5590 RPM  (min =    0 RPM)\n"
+ ">> fan4:        4963 RPM  (min =    0 RPM)\n"
+ ">> fan5:           0 RPM  (min =    0 RPM)\n"
+ ">> fan6:           0 RPM  (min =    0 RPM)\n"
+ ">> fan7:        7488 RPM  (min =    0 RPM)\n"
+ ">> fan8:        7944 RPM  (min =    0 RPM)\n"
+ ">> temp1:        +39.0\302\260C  (high =  +0.0\302\260C)\n"
+ ">> power1:      192.00 W\n"
+ ">>\n"
+ ">> [root@tul163p1 ~]# ls /sys/devices/platform/\n"
+ ">> alarmtimer  ibmpowernv.0  rtc-generic  serial8250  uevent\n"
+ ">> [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/\n"
+ ">> driver/    hwmon/     modalias   subsystem/ uevent\n"
+ ">> [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/hwmon/hwmon0/\n"
+ ">> device        fan2_min    fan4_min    fan6_min    fan8_min power1_input\n"
+ ">> fan1_fault  fan3_fault    fan5_fault  fan7_fault    in1_fault subsystem\n"
+ ">> fan1_input  fan3_input    fan5_input  fan7_input    in2_fault \n"
+ ">> temp1_input\n"
+ ">> fan1_min    fan3_min    fan5_min    fan7_min    in3_fault temp1_max\n"
+ ">> fan2_fault  fan4_fault    fan6_fault  fan8_fault    in4_fault uevent\n"
+ ">> fan2_input  fan4_input    fan6_input  fan8_input    name\n"
+ ">> [root@tul163p1 ~]#\n"
+ ">> [root@tul163p1 ~]# ls /sys/class/hwmon/hwmon0/\n"
+ ">> device        fan2_min    fan4_min    fan6_min    fan8_min power1_input\n"
+ ">> fan1_fault  fan3_fault    fan5_fault  fan7_fault    in1_fault subsystem\n"
+ ">> fan1_input  fan3_input    fan5_input  fan7_input    in2_fault \n"
+ ">> temp1_input\n"
+ ">> fan1_min    fan3_min    fan5_min    fan7_min    in3_fault temp1_max\n"
+ ">> fan2_fault  fan4_fault    fan6_fault  fan8_fault    in4_fault uevent\n"
+ ">> fan2_input  fan4_input    fan6_input  fan8_input    name\n"
+ ">> [root@tul163p1 ~]#\n"
+ ">>\n"
+ ">\n"
+ ">\n"
+ "> The inX_fault attributes don't really make much sense. _fault \n"
+ "> attributes without\n"
+ "> _input attributes don't have any value and are, as you noticed, not \n"
+ "> displayed\n"
+ "> with the sensors command. Is this a problem in teh devicetree data or \n"
+ "> do you\n"
+ "> really have voltage faults without voltages ?\n"
+ "\n"
+ "There is no issue with the device data, somehow I'm getting only the \n"
+ "_fault attribute\n"
+ "for the inX_ (power-supply) attributes.\n"
+ "\n"
+ ">\n"
+ ">> Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>\n"
+ ">> ---\n"
+ ">>\n"
+ "> Checkpatch says:\n"
+ ">\n"
+ "> total: 8 errors, 11 warnings, 389 lines checked\n"
+ ">\n"
+ "> NOTE: whitespace errors detected, you may wish to use \n"
+ "> scripts/cleanpatch or\n"
+ ">       scripts/cleanfile\n"
+ ">\n"
+ "> which should really not happen at this point.\n"
+ ">\n"
+ "> Please make sure you follow CodingStyle. checkpatch --strict points to \n"
+ "> a number\n"
+ "> of additional violations.\n"
+ ">\n"
+ "> More comments inline.\n"
+ "\n"
+ "Fixed all of these issues related to coding style.\n"
+ "\n"
+ ">\n"
+ ">> Changes in v2\n"
+ ">> =============\n"
+ ">> - Generic use of devm_* functions in hwmon like using devm_kzalloc() \n"
+ ">> for dynamic\n"
+ ">>    memory request, avoiding the need to explicit free of memory.\n"
+ ">>    Adding 'struct attribute_group' as member of platform data \n"
+ ">> structure to be\n"
+ ">>    populated and then passed to \n"
+ ">> devm_hwmon_device_register_with_groups().\n"
+ ">>\n"
+ ">>    Note: Having an array of pointers of 'attribute_group' and each group\n"
+ ">>    corresponds to 'enum sensors' type. Not completely sure, if it's \n"
+ ">> ideal or\n"
+ ">>    could have just one group populated with attributes of sensor types?\n"
+ ">>\n"
+ "> Your call, really; whatever is easier for you. I won't dictate one or \n"
+ "> the other.\n"
+ ">\n"
+ "> Question though is what happens if one group is not populated. If I \n"
+ "> understand\n"
+ "> the code correctly this will result in the remaining groups to be \n"
+ "> 'dropped',\n"
+ "> ie not displayed at all.\n"
+ "\n"
+ "Yes, should be fixed.\n"
+ "\n"
+ ">\n"
+ ">> - 'ibmpowernv' is not hot-pluggable device so moving \n"
+ ">> 'platform_driver' callback\n"
+ ">>    function (probe) as part of __init code.\n"
+ ">> - Fixed issues related to coding style.\n"
+ ">> - Other general comments in v1.\n"
+ ">>\n"
+ ">>   drivers/hwmon/Kconfig      |    8 +\n"
+ ">>   drivers/hwmon/Makefile     |    1\n"
+ ">>   drivers/hwmon/ibmpowernv.c |  368 \n"
+ ">> ++++++++++++++++++++++++++++++++++++++++++++\n"
+ ">\n"
+ "> You'll also need Documentation/hwmon/ibmpowernv and\n"
+ "> Documentation/devicetree/bindings/hwmon/ibmpowernv.\n"
+ ">\n"
+ "> The latter will need to get an Ack from the devicetree maintainers.\n"
+ "\n"
+ "I'll do as required.\n"
+ "\n"
+ ">>   3 files changed, 377 insertions(+)\n"
+ ">>   create mode 100644 drivers/hwmon/ibmpowernv.c\n"
+ ">>\n"
+ ">> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig\n"
+ ">> index bc196f4..3e308fa 100644\n"
+ ">> --- a/drivers/hwmon/Kconfig\n"
+ ">> +++ b/drivers/hwmon/Kconfig\n"
+ ">> @@ -554,6 +554,14 @@ config SENSORS_IBMPEX\n"
+ ">>         This driver can also be built as a module.  If so, the module\n"
+ ">>         will be called ibmpex.\n"
+ ">>\n"
+ ">> +config SENSORS_IBMPOWERNV\n"
+ ">> +    tristate \"IBM POWERNV platform sensors\"\n"
+ ">> +    depends on PPC_POWERNV\n"
+ ">> +    default y\n"
+ ">> +    help\n"
+ ">> +      If you say yes here you get support for the temperature/fan/power\n"
+ ">> +      sensors on your platform.\n"
+ ">> +\n"
+ ">>   config SENSORS_IIO_HWMON\n"
+ ">>       tristate \"Hwmon driver that uses channels specified via iio maps\"\n"
+ ">>       depends on IIO\n"
+ ">> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile\n"
+ ">> index c48f987..199c401 100644\n"
+ ">> --- a/drivers/hwmon/Makefile\n"
+ ">> +++ b/drivers/hwmon/Makefile\n"
+ ">> @@ -71,6 +71,7 @@ obj-$(CONFIG_SENSORS_ULTRA45)    += ultra45_env.o\n"
+ ">>   obj-$(CONFIG_SENSORS_I5K_AMB)    += i5k_amb.o\n"
+ ">>   obj-$(CONFIG_SENSORS_IBMAEM)    += ibmaem.o\n"
+ ">>   obj-$(CONFIG_SENSORS_IBMPEX)    += ibmpex.o\n"
+ ">> +obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o\n"
+ ">>   obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o\n"
+ ">>   obj-$(CONFIG_SENSORS_INA209)    += ina209.o\n"
+ ">>   obj-$(CONFIG_SENSORS_INA2XX)    += ina2xx.o\n"
+ ">> diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c\n"
+ ">> new file mode 100644\n"
+ ">> index 0000000..afce620\n"
+ ">> --- /dev/null\n"
+ ">> +++ b/drivers/hwmon/ibmpowernv.c\n"
+ ">> @@ -0,0 +1,368 @@\n"
+ ">> +/*\n"
+ ">> + * IBM PowerNV platform sensors for temperature/fan/power\n"
+ ">> + * Copyright (C) 2014 IBM\n"
+ ">> + *\n"
+ ">> + * This program is free software; you can redistribute it and/or modify\n"
+ ">> + * it under the terms of the GNU General Public License as published by\n"
+ ">> + * the Free Software Foundation; either version 2 of the License, or\n"
+ ">> + * (at your option) any later version.\n"
+ ">> + *\n"
+ ">> + * This program is distributed in the hope that it will be useful,\n"
+ ">> + * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ ">> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
+ ">> + * GNU General Public License for more details.\n"
+ ">> + *\n"
+ ">> + * You should have received a copy of the GNU General Public License\n"
+ ">> + * along with this program.\n"
+ ">> + */\n"
+ ">> +\n"
+ ">> +#include <linux/init.h>\n"
+ ">> +#include <linux/module.h>\n"
+ ">> +#include <linux/kernel.h>\n"
+ ">> +#include <linux/hwmon.h>\n"
+ ">> +#include <linux/hwmon-sysfs.h>\n"
+ ">> +#include <linux/of.h>\n"
+ ">> +#include <linux/slab.h>\n"
+ ">> +\n"
+ ">> +#include <linux/platform_device.h>\n"
+ ">> +#include <asm/opal.h>\n"
+ ">> +#include <linux/err.h>\n"
+ ">> +\n"
+ ">> +#define DRVNAME        \"ibmpowernv\"\n"
+ ">> +#define MAX_ATTR_LEN    32\n"
+ ">> +\n"
+ ">> +/* Sensor suffix name from DT */\n"
+ ">> +#define DT_FAULT_ATTR_SUFFIX        \"faulted\"\n"
+ ">> +#define DT_DATA_ATTR_SUFFIX        \"data\"\n"
+ ">> +#define DT_THRESHOLD_ATTR_SUFFIX    \"thrs\"\n"
+ ">> +\n"
+ ">> +/*\n"
+ ">> + * Enumerates all the types of sensors in the POWERNV platform and \n"
+ ">> does index\n"
+ ">> + * into 'struct sensor_group'\n"
+ ">> + */\n"
+ ">> +enum sensors {\n"
+ ">> +    FAN,\n"
+ ">> +    AMBIENT_TEMP,\n"
+ ">> +    POWER_SUPPLY,\n"
+ ">> +    POWER_INPUT,\n"
+ ">> +    MAX_SENSOR_TYPE,\n"
+ ">> +};\n"
+ ">> +\n"
+ ">> +static struct sensor_group {\n"
+ ">> +    const char *name;\n"
+ ">> +    const char *compatible;\n"
+ ">> +    struct attribute_group group;\n"
+ ">> +    u32 attr_count;\n"
+ ">> +} sensor_groups[] = {\n"
+ ">> +    {\"fan\", \"ibm,opal-sensor-cooling-fan\", {0}, 0},\n"
+ ">> +    {\"temp\", \"ibm,opal-sensor-amb-temp\", {0}, 0},\n"
+ ">> +    {\"in\", \"ibm,opal-sensor-power-supply\", {0}, 0},\n"
+ ">> +    {\"power\", \"ibm,opal-sensor-power\", {0}, 0}\n"
+ ">> +};\n"
+ ">> +\n"
+ "> The '0' initializations should not be necessary.\n"
+ ">\n"
+ ">\n"
+ ">> +struct sensor_data {\n"
+ ">> +    u32 id; /* An opaque id of the firmware for each sensor */\n"
+ ">> +    enum sensors type;\n"
+ ">> +    char name[MAX_ATTR_LEN];\n"
+ ">> +    struct device_attribute dev_attr;\n"
+ ">> +};\n"
+ ">> +\n"
+ ">> +struct platform_data {\n"
+ ">> +    const struct attribute_group *attr_groups[MAX_SENSOR_TYPE + 1];\n"
+ ">> +    u32 sensors_count; /* Total count of sensors from each group */\n"
+ ">> +};\n"
+ ">> +\n"
+ ">> +/* Platform device representing all the ibmpowernv sensors */\n"
+ ">> +static struct platform_device *pdevice;\n"
+ ">> +\n"
+ ">> +static ssize_t show_sensor(struct device *dev, struct \n"
+ ">> device_attribute *devattr,\n"
+ ">> +               char *buf)\n"
+ ">> +{\n"
+ ">> +    struct sensor_data *sdata = container_of(devattr, struct \n"
+ ">> sensor_data,\n"
+ ">> +                         dev_attr);\n"
+ ">> +    ssize_t ret;\n"
+ ">> +    u32 x;\n"
+ ">> +\n"
+ ">> +    ret = opal_get_sensor_data(sdata->id, &x);\n"
+ ">> +    if (ret) {\n"
+ ">> +        pr_err(\"%s: Failed to get opal sensor data\\n\", __func__);\n"
+ ">> +        return ret;\n"
+ ">> +    }\n"
+ ">> +\n"
+ ">> +    /* Convert temperature to milli-degrees */\n"
+ ">> +    if (sdata->type == AMBIENT_TEMP)\n"
+ ">> +        x *= 1000;\n"
+ ">> +    /* Convert power to micro-watts */\n"
+ ">> +    else if (sdata->type == POWER_INPUT)\n"
+ ">> +        x *= 1000000;\n"
+ ">> +\n"
+ ">> +    return sprintf(buf, \"%d\\n\", x);\n"
+ ">\n"
+ "> x is unsigned, so %u.\n"
+ "\n"
+ "Done.\n"
+ "\n"
+ ">\n"
+ ">> +}\n"
+ ">> +\n"
+ ">> +static void __init get_sensor_index_attr(const char *name, u32 \n"
+ ">> *index, char *attr)\n"
+ ">> +{\n"
+ ">> +    char *hash_pos = strchr(name, '#');\n"
+ ">> +    char *dash_pos;\n"
+ ">> +    u32 copy_len;\n"
+ ">> +    char buf[8];\n"
+ ">> +\n"
+ ">> +    memset(buf, 0, sizeof(buf));\n"
+ ">> +    *index = 0;\n"
+ ">> +    *attr = '\\0';\n"
+ ">> +\n"
+ ">> +    if (hash_pos) {\n"
+ ">> +        dash_pos = strchr(hash_pos, '-');\n"
+ ">> +        if (dash_pos) {\n"
+ ">> +            copy_len = dash_pos - hash_pos - 1;\n"
+ ">> +            if (copy_len < sizeof(buf)) {\n"
+ ">> +                strncpy(buf, hash_pos + 1, copy_len);\n"
+ ">> +                sscanf(buf, \"%d\", index);\n"
+ ">\n"
+ "> What if sscanf fails ? Might be an interesting exercise to try and create\n"
+ "> multiple sensors with index 0 (or, for that matter, with the same \n"
+ "> index value).\n"
+ "> Do you have any protection against bad input data ? Guess not; did you \n"
+ "> test\n"
+ "> what happens if you pass bad data to the driver (such as duplicate sensor\n"
+ "> entries) ?\n"
+ "\n"
+ "Well, rewriting this function to return the error code if fails.\n"
+ "Next version will cover these test cases covered. Thanks.\n"
+ "\n"
+ ">\n"
+ ">> +            }\n"
+ ">> +\n"
+ ">> +            strncpy(attr, dash_pos + 1, MAX_ATTR_LEN);\n"
+ ">> +        }\n"
+ ">> +    }\n"
+ ">> +}\n"
+ ">> +\n"
+ ">> +/*\n"
+ ">> + * This function translates the DT node name into the 'hwmon' \n"
+ ">> attribute name.\n"
+ ">> + * IBMPOWERNV device node appear like cooling-fan#2-data, \n"
+ ">> amb-temp#1-thrs etc.\n"
+ ">> + * which need to be mapped as fan2_input, temp1_max respectively before\n"
+ ">> + * populating them inside hwmon device class..\n"
+ ">> + */\n"
+ ">> +static int __init create_hwmon_attr_name(enum sensors type, const \n"
+ ">> char *node_name,\n"
+ ">> +                  char *hwmon_attr_name)\n"
+ ">> +{\n"
+ ">> +    char attr_suffix[MAX_ATTR_LEN];\n"
+ ">> +    char *attr_name;\n"
+ ">> +    u32 index;\n"
+ ">> +\n"
+ ">> +    get_sensor_index_attr(node_name, &index, attr_suffix);\n"
+ ">> +    if (!index || !strlen(attr_suffix)) {\n"
+ ">> +        pr_info(\"%s: Sensor device node name is invalid, name: %s\\n\",\n"
+ ">> +                __func__, node_name);\n"
+ ">> +        return -EINVAL;\n"
+ ">> +    }\n"
+ ">> +\n"
+ ">> +    if (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX))\n"
+ ">> +        attr_name = \"fault\";\n"
+ ">> +    else if(!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX))\n"
+ ">> +        attr_name = \"input\";\n"
+ ">> +    else if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) {\n"
+ ">> +        if (type == AMBIENT_TEMP)\n"
+ ">> +            attr_name = \"max\";\n"
+ ">> +        else if (type == FAN)\n"
+ ">> +            attr_name = \"min\";\n"
+ ">> +        else\n"
+ ">> +            return -ENOENT;\n"
+ ">> +    } else\n"
+ ">> +        return -ENOENT;\n"
+ ">> +\n"
+ ">> +    snprintf(hwmon_attr_name, MAX_ATTR_LEN, \"%s%d_%s\",\n"
+ ">> +            sensor_groups[type].name, index, attr_name);\n"
+ ">> +    return 0;\n"
+ ">> +}\n"
+ ">> +\n"
+ ">> +static int __init populate_attr_groups(struct platform_device *pdev)\n"
+ ">> +{\n"
+ ">> +    struct platform_data *pdata = platform_get_drvdata(pdev);\n"
+ ">> +    const struct attribute_group **pgroups = pdata->attr_groups;\n"
+ ">> +    struct device_node *opal, *np;\n"
+ ">> +    enum sensors type;\n"
+ ">> +    int err = 0;\n"
+ ">> +\n"
+ ">> +    opal = of_find_node_by_path(\"/ibm,opal/sensors\");\n"
+ ">> +        if (!opal) {\n"
+ ">\n"
+ "> An obvious whitespace error here.\n"
+ ">\n"
+ ">> +        pr_err(\"%s: Opal 'sensors' node not found\\n\", __func__);\n"
+ ">> +        return -ENODEV;\n"
+ ">> +        }\n"
+ ">> +\n"
+ ">> +    for_each_child_of_node(opal, np) {\n"
+ ">> +        if (np->name == NULL)\n"
+ ">> +            continue;\n"
+ ">> +\n"
+ ">> +        for (type = 0; type < MAX_SENSOR_TYPE; type++)\n"
+ ">> +            if (of_device_is_compatible(np,\n"
+ ">> +                sensor_groups[type].compatible)) {\n"
+ ">> +                sensor_groups[type].attr_count++;\n"
+ ">> +                break;\n"
+ ">> +            }\n"
+ ">> +    }\n"
+ ">\n"
+ "> You should be able to do\n"
+ ">     of_node_put(opal);\n"
+ ">\n"
+ "> here. Then you can return immediately on error below.\n"
+ "\n"
+ "Done.\n"
+ "\n"
+ ">\n"
+ ">> +\n"
+ ">> +    for (type = 0; type < MAX_SENSOR_TYPE; type++) {\n"
+ ">> +        if (!sensor_groups[type].attr_count)\n"
+ ">> +            continue;\n"
+ ">> +\n"
+ ">> +        sensor_groups[type].group.attrs = devm_kzalloc(&pdev->dev,\n"
+ ">> +                    sizeof(struct attribute*) *\n"
+ ">> +                    (sensor_groups[type].attr_count + 1),\n"
+ ">> +                    GFP_KERNEL);\n"
+ ">> +        if (!sensor_groups[type].group.attrs) {\n"
+ ">> +            pr_err(\"%s: Failed to allocate memory for attribute\"\n"
+ ">> +                    \"array\\n\", __func__);\n"
+ ">\n"
+ "> devm_kzalloc() already dumps an error message. Same for all other \n"
+ "> memory error messages.\n"
+ ">\n"
+ ">> +            err = -ENOMEM;\n"
+ ">> +            goto exit_put_node;\n"
+ ">> +        }\n"
+ ">> +\n"
+ ">> +        pgroups[type] = &sensor_groups[type].group;\n"
+ ">> +        pdata->sensors_count += sensor_groups[type].attr_count;\n"
+ ">> +        sensor_groups[type].attr_count = 0;\n"
+ ">> +    }\n"
+ ">> +\n"
+ ">> +exit_put_node:\n"
+ ">> +    of_node_put(opal);\n"
+ ">> +    return err;\n"
+ ">> +}\n"
+ ">> +\n"
+ ">> +/*\n"
+ ">> + * Iterate through the device tree for each child of sensor node, \n"
+ ">> create\n"
+ ">> + * a sysfs attribute file, the file is named by translating the DT \n"
+ ">> node name\n"
+ ">> + * to the name required by the higher 'hwmon' driver like \n"
+ ">> fan1_input, temp1_max\n"
+ ">> + * etc..\n"
+ ">> + */\n"
+ ">> +static int __init create_device_attrs(struct platform_device *pdev)\n"
+ ">> +{\n"
+ ">> +    struct platform_data *pdata = platform_get_drvdata(pdev);\n"
+ ">> +    const struct attribute_group **pgroups = pdata->attr_groups;\n"
+ ">> +    struct device_node *opal, *np;\n"
+ ">> +    struct sensor_data *sdata;\n"
+ ">> +    const u32 *sensor_id;\n"
+ ">> +    enum sensors type;\n"
+ ">> +    u32 count = 0;\n"
+ ">> +    int err = 0;\n"
+ ">> +\n"
+ ">> +    opal = of_find_node_by_path(\"/ibm,opal/sensors\");\n"
+ ">> +        if (!opal) {\n"
+ ">> +        pr_err(\"%s: Opal 'sensors' node not found\\n\", __func__);\n"
+ ">> +        return -ENODEV;\n"
+ ">> +        }\n"
+ ">> +\n"
+ ">> +    sdata = devm_kzalloc(&pdev->dev, (pdata->sensors_count) *\n"
+ ">> +                 sizeof(*sdata), GFP_KERNEL);\n"
+ ">> +    if (!sdata) {\n"
+ ">> +        pr_err(\"%s: Failed to allocate memory for the sensor_data\",\n"
+ ">> +                __func__);\n"
+ ">> +        err = -ENOMEM;\n"
+ ">> +        goto exit_put_node;\n"
+ ">> +    }\n"
+ ">> +\n"
+ ">> +    for_each_child_of_node(opal, np) {\n"
+ ">> +                if (np->name == NULL)\n"
+ ">> +                        continue;\n"
+ ">> +\n"
+ ">> +        for (type = 0; type < MAX_SENSOR_TYPE; type++)\n"
+ ">> +            if (of_device_is_compatible(np,\n"
+ ">> +                    sensor_groups[type].compatible))\n"
+ ">> +                break;\n"
+ ">> +\n"
+ ">> +        if (type == MAX_SENSOR_TYPE)\n"
+ ">> +            continue;\n"
+ ">> +\n"
+ ">> +        sensor_id = of_get_property(np, \"sensor-id\", NULL);\n"
+ ">> +        if (!sensor_id) {\n"
+ ">> +            pr_info(\"%s: %s doesn't have sensor-id\\n\", __func__,\n"
+ ">> +                np->name);\n"
+ ">> +            continue;\n"
+ ">> +        }\n"
+ ">> +\n"
+ "> Consider using of_property_read_u32().\n"
+ "\n"
+ "Okay.\n"
+ "\n"
+ ">\n"
+ ">> +        sdata[count].id = *sensor_id;\n"
+ ">> +        sdata[count].type = type;\n"
+ ">> +        err = create_hwmon_attr_name(type, np->name, \n"
+ ">> sdata[count].name);\n"
+ ">> +        if (err)\n"
+ ">> +            goto exit_put_node;\n"
+ ">> +\n"
+ ">> +        sysfs_attr_init(&sdata[count].dev_attr.attr);\n"
+ ">> +        sdata[count].dev_attr.attr.name = sdata[count].name;\n"
+ ">> +        sdata[count].dev_attr.attr.mode = S_IRUGO;\n"
+ ">> +        sdata[count].dev_attr.show = show_sensor;\n"
+ ">> +\n"
+ ">> + pgroups[type]->attrs[sensor_groups[type].attr_count++] =\n"
+ ">> +                &sdata[count++].dev_attr.attr;\n"
+ ">> +    }\n"
+ ">> +\n"
+ ">> +exit_put_node:\n"
+ ">> +    of_node_put(opal);\n"
+ ">> +    return err;\n"
+ ">> +}\n"
+ ">> +\n"
+ ">> +static int __init ibmpowernv_probe(struct platform_device *pdev)\n"
+ ">> +{\n"
+ ">> +    struct platform_data *pdata;\n"
+ ">> +    struct device *hwmon_dev;\n"
+ ">> +    int err;\n"
+ ">> +\n"
+ ">> +    pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);\n"
+ ">> +    if (!pdata)\n"
+ ">> +        return -ENOMEM;\n"
+ ">> +\n"
+ ">> +    platform_set_drvdata(pdev, pdata);\n"
+ ">> +    pdata->sensors_count = 0;\n"
+ ">> +    err = populate_attr_groups(pdev);\n"
+ ">> +    if (err)\n"
+ ">> +        return err;\n"
+ ">> +\n"
+ ">> +    /* Create sysfs attribute file for each sensor found in the DT */\n"
+ ">\n"
+ "> Attribute data, not file\n"
+ ">\n"
+ ">> +    err = create_device_attrs(pdev);\n"
+ ">> +    if (err)\n"
+ ">> +        return err;\n"
+ ">> +\n"
+ ">> +    /* Finally, register with hwmon */\n"
+ ">> +    hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, \n"
+ ">> DRVNAME,\n"
+ ">> +                               pdata,\n"
+ ">> +                               pdata->attr_groups);\n"
+ ">> +\n"
+ ">> +    return PTR_ERR_OR_ZERO(hwmon_dev);\n"
+ ">> +}\n"
+ ">> +\n"
+ ">> +static struct platform_driver ibmpowernv_driver = {\n"
+ ">> +    .driver = {\n"
+ ">> +        .owner = THIS_MODULE,\n"
+ ">> +        .name = DRVNAME,\n"
+ ">> +    },\n"
+ ">> +};\n"
+ ">> +\n"
+ ">> +static int __init ibmpowernv_init(void)\n"
+ ">> +{\n"
+ ">> +    int err;\n"
+ ">> +\n"
+ ">> +    pdevice = platform_device_alloc(DRVNAME, 0);\n"
+ ">> +    if (!pdevice) {\n"
+ ">> +        pr_err(\"%s: Device allocation failed\\n\", __func__);\n"
+ ">> +        err = -ENOMEM;\n"
+ ">> +        goto exit;\n"
+ ">> +    }\n"
+ ">> +\n"
+ ">> +    err = platform_device_add(pdevice);\n"
+ ">> +    if (err) {\n"
+ ">> +        pr_err(\"%s: Device addition failed (%d)\\n\", __func__, err);\n"
+ ">> +        goto exit_device_put;\n"
+ ">> +    }\n"
+ ">> +\n"
+ ">> +    err = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe);\n"
+ ">> +    if (err) {\n"
+ ">> +        pr_err(\"%s: Platfrom driver probe failed\\n\", __func__);\n"
+ ">> +        goto exit_device_del;\n"
+ ">> +    }\n"
+ ">> +\n"
+ ">> +    return 0;\n"
+ ">> +\n"
+ ">> +exit_device_del:\n"
+ ">> +    platform_device_del(pdevice);\n"
+ ">> +exit_device_put:\n"
+ ">> +    platform_device_put(pdevice);\n"
+ ">> +exit:\n"
+ ">> +    return err;\n"
+ ">> +}\n"
+ ">> +\n"
+ ">> +static void __exit ibmpowernv_exit(void)\n"
+ ">> +{\n"
+ ">> +    platform_driver_unregister(&ibmpowernv_driver);\n"
+ ">> +    platform_device_unregister(pdevice);\n"
+ ">> +}\n"
+ ">> +\n"
+ ">> +MODULE_AUTHOR(\"Neelesh Gupta <neelegup@linux.vnet.ibm.com>\");\n"
+ ">> +MODULE_DESCRIPTION(\"IBM POWERNV platform sensors\");\n"
+ ">> +MODULE_LICENSE(\"GPL\");\n"
+ ">> +\n"
+ ">> +module_init(ibmpowernv_init);\n"
+ ">> +module_exit(ibmpowernv_exit);\n"
+ ">>\n"
+ ">>\n"
+ ">>\n"
+ >
 
-069233182dae714caedfe3240cf4a56b842bf6436e388de38031560ba7c3c521
+d252ff49b5b3316440c0dd8e443b0b3b99e88d604a90c705fedd849ed3c2d112

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.