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.