diff for duplicates of <5378F711.2020606@linux.vnet.ibm.com> diff --git a/a/1.txt b/N1/1.txt index 3903959..dbc7a9a 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -1,317 +1,569 @@ -T24gMDUvMTQvMjAxNCAxMDozOSBQTSwgR3VlbnRlciBSb2VjayB3cm90ZToKPiBPbiBXZWQsIE1h -eSAxNCwgMjAxNCBhdCAxMTozMTo1M0FNICswNTMwLCBOZWVsZXNoIEd1cHRhIHdyb3RlOgo+PiBU -aGlzIHBhdGNoIGFkZHMgYmFzaWMga2VybmVsIGVuYWJsZW1lbnQgZm9yIHJlYWRpbmcgcG93ZXIg -dmFsdWVzLCBmYW4KPj4gc3BlZWQgcnBtIGFuZCB0ZW1wZXJhdHVyZSB2YWx1ZXMgb24gcG93ZXJu -diBwbGF0Zm9ybXMgd2hpY2ggd2lsbAo+PiBiZSBleHBvcnRlZCB0byB1c2VyIHNwYWNlIHRocm91 -Z2ggc3lzZnMgaW50ZXJmYWNlLgo+Pgo+PiBUZXN0IHJlc3VsdHM6Cj4+IC0tLS0tLS0tLS0tLS0K -Pj4gW3Jvb3RAdHVsMTYzcDEgfl0jIHNlbnNvcnMKPj4gaWJtcG93ZXJudi1pc2EtMDAwMAo+PiBB -ZGFwdGVyOiBJU0EgYWRhcHRlcgo+PiBmYW4xOiAgICAgICAgNTI5NCBSUE0gIChtaW4gPSAgICAw -IFJQTSkKPj4gZmFuMjogICAgICAgIDQ5NDUgUlBNICAobWluID0gICAgMCBSUE0pCj4+IGZhbjM6 -ICAgICAgICA1ODMxIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+PiBmYW40OiAgICAgICAgNTIxMiBS -UE0gIChtaW4gPSAgICAwIFJQTSkKPj4gZmFuNTogICAgICAgICAgIDAgUlBNICAobWluID0gICAg -MCBSUE0pCj4+IGZhbjY6ICAgICAgICAgICAwIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+PiBmYW43 -OiAgICAgICAgNzQ3MiBSUE0gIChtaW4gPSAgICAwIFJQTSkKPj4gZmFuODogICAgICAgIDc5MjAg -UlBNICAobWluID0gICAgMCBSUE0pCj4+IHRlbXAxOiAgICAgICAgKzM5LjDCsEMgIChoaWdoID0g -ICswLjDCsEMpCj4+IHBvd2VyMTogICAgICAxOTIuMDAgVwo+Pgo+PiBbcm9vdEB0dWwxNjNwMSB+ -XSMKPj4gW3Jvb3RAdHVsMTYzcDEgfl0jIGxzIC9zeXMvZGV2aWNlcy9wbGF0Zm9ybS9pYm1wb3dl -cm52LjAvCj4+IGRyaXZlciAgICAgIGZhbjJfbWluICAgIGZhbjRfbWluICAgIGZhbjZfbWluICAg -IGZhbjhfbWluICAgbW9kYWxpYXMgICAgICB1ZXZlbnQKPj4gZmFuMV9mYXVsdCAgZmFuM19mYXVs -dCAgZmFuNV9mYXVsdCAgZmFuN19mYXVsdCAgaHdtb24gICAgICBuYW1lCj4+IGZhbjFfaW5wdXQg -IGZhbjNfaW5wdXQgIGZhbjVfaW5wdXQgIGZhbjdfaW5wdXQgIGluMV9mYXVsdCAgcG93ZXIxX2lu -cHV0Cj4+IGZhbjFfbWluICAgIGZhbjNfbWluICAgIGZhbjVfbWluICAgIGZhbjdfbWluICAgIGlu -Ml9mYXVsdCAgc3Vic3lzdGVtCj4+IGZhbjJfZmF1bHQgIGZhbjRfZmF1bHQgIGZhbjZfZmF1bHQg -IGZhbjhfZmF1bHQgIGluM19mYXVsdCAgdGVtcDFfaW5wdXQKPj4gZmFuMl9pbnB1dCAgZmFuNF9p -bnB1dCAgZmFuNl9pbnB1dCAgZmFuOF9pbnB1dCAgaW40X2ZhdWx0ICB0ZW1wMV9tYXgKPj4gW3Jv -b3RAdHVsMTYzcDEgfl0jCj4+IFtyb290QHR1bDE2M3AxIH5dIyBscyAvc3lzL2NsYXNzL2h3bW9u -L2h3bW9uMC9kZXZpY2UvCj4+IGRyaXZlciAgICAgIGZhbjJfbWluICAgIGZhbjRfbWluICAgIGZh -bjZfbWluICAgIGZhbjhfbWluICAgbW9kYWxpYXMgICAgICB1ZXZlbnQKPj4gZmFuMV9mYXVsdCAg -ZmFuM19mYXVsdCAgZmFuNV9mYXVsdCAgZmFuN19mYXVsdCAgaHdtb24gICAgICBuYW1lCj4+IGZh -bjFfaW5wdXQgIGZhbjNfaW5wdXQgIGZhbjVfaW5wdXQgIGZhbjdfaW5wdXQgIGluMV9mYXVsdCAg -cG93ZXIxX2lucHV0Cj4+IGZhbjFfbWluICAgIGZhbjNfbWluICAgIGZhbjVfbWluICAgIGZhbjdf -bWluICAgIGluMl9mYXVsdCAgc3Vic3lzdGVtCj4+IGZhbjJfZmF1bHQgIGZhbjRfZmF1bHQgIGZh -bjZfZmF1bHQgIGZhbjhfZmF1bHQgIGluM19mYXVsdCAgdGVtcDFfaW5wdXQKPj4gZmFuMl9pbnB1 -dCAgZmFuNF9pbnB1dCAgZmFuNl9pbnB1dCAgZmFuOF9pbnB1dCAgaW40X2ZhdWx0ICB0ZW1wMV9t -YXgKPj4gW3Jvb3RAdHVsMTYzcDEgfl0jCj4+Cj4+IFNpZ25lZC1vZmYtYnk6IFNoaXZhcHJhc2Fk -IEcgQmhhdCA8c2JoYXRAbGludXgudm5ldC5pYm0uY29tPgo+PiBTaWduZWQtb2ZmLWJ5OiBOZWVs -ZXNoIEd1cHRhIDxuZWVsZWd1cEBsaW51eC52bmV0LmlibS5jb20+Cj4+IC0tLQo+PiAgIGRyaXZl -cnMvaHdtb24vS2NvbmZpZyAgICAgIHwgICAgOCArCj4+ICAgZHJpdmVycy9od21vbi9NYWtlZmls -ZSAgICAgfCAgICAxCj4+ICAgZHJpdmVycy9od21vbi9pYm1wb3dlcm52LmMgfCAgMzg2ICsrKysr -KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCj4+ICAgMyBmaWxlcyBjaGFu -Z2VkLCAzOTUgaW5zZXJ0aW9ucygrKQo+PiAgIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2h3 -bW9uL2libXBvd2VybnYuYwo+Pgo+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmln -IGIvZHJpdmVycy9od21vbi9LY29uZmlnCj4+IGluZGV4IGJjMTk2ZjQuLjNlMzA4ZmEgMTAwNjQ0 -Cj4+IC0tLSBhL2RyaXZlcnMvaHdtb24vS2NvbmZpZwo+PiArKysgYi9kcml2ZXJzL2h3bW9uL0tj -b25maWcKPj4gQEAgLTU1NCw2ICs1NTQsMTQgQEAgY29uZmlnIFNFTlNPUlNfSUJNUEVYCj4+ICAg -CSAgVGhpcyBkcml2ZXIgY2FuIGFsc28gYmUgYnVpbHQgYXMgYSBtb2R1bGUuICBJZiBzbywgdGhl -IG1vZHVsZQo+PiAgIAkgIHdpbGwgYmUgY2FsbGVkIGlibXBleC4KPj4gICAKPj4gK2NvbmZpZyBT -RU5TT1JTX0lCTVBPV0VSTlYKPj4gKwl0cmlzdGF0ZSAiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vu -c29ycyIKPj4gKwlkZXBlbmRzIG9uIFBQQ19QT1dFUk5WCj4+ICsJZGVmYXVsdCB5Cj4+ICsJaGVs -cAo+PiArCSAgSWYgeW91IHNheSB5ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIHRoZSB0ZW1w -ZXJhdHVyZS9mYW4vcG93ZXIKPj4gKwkgIHNlbnNvcnMgb24geW91ciBwbGF0Zm9ybS4KPj4gKwo+ -PiAgIGNvbmZpZyBTRU5TT1JTX0lJT19IV01PTgo+PiAgIAl0cmlzdGF0ZSAiSHdtb24gZHJpdmVy -IHRoYXQgdXNlcyBjaGFubmVscyBzcGVjaWZpZWQgdmlhIGlpbyBtYXBzIgo+PiAgIAlkZXBlbmRz -IG9uIElJTwo+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9NYWtlZmlsZSBiL2RyaXZlcnMv -aHdtb24vTWFrZWZpbGUKPj4gaW5kZXggYzQ4Zjk4Ny4uMTk5YzQwMSAxMDA2NDQKPj4gLS0tIGEv -ZHJpdmVycy9od21vbi9NYWtlZmlsZQo+PiArKysgYi9kcml2ZXJzL2h3bW9uL01ha2VmaWxlCj4+ -IEBAIC03MSw2ICs3MSw3IEBAIG9iai0kKENPTkZJR19TRU5TT1JTX1VMVFJBNDUpCSs9IHVsdHJh -NDVfZW52Lm8KPj4gICBvYmotJChDT05GSUdfU0VOU09SU19JNUtfQU1CKQkrPSBpNWtfYW1iLm8K -Pj4gICBvYmotJChDT05GSUdfU0VOU09SU19JQk1BRU0pCSs9IGlibWFlbS5vCj4+ICAgb2JqLSQo -Q09ORklHX1NFTlNPUlNfSUJNUEVYKQkrPSBpYm1wZXgubwo+PiArb2JqLSQoQ09ORklHX1NFTlNP -UlNfSUJNUE9XRVJOVikrPSBpYm1wb3dlcm52Lm8KPj4gICBvYmotJChDT05GSUdfU0VOU09SU19J -SU9fSFdNT04pICs9IGlpb19od21vbi5vCj4+ICAgb2JqLSQoQ09ORklHX1NFTlNPUlNfSU5BMjA5 -KQkrPSBpbmEyMDkubwo+PiAgIG9iai0kKENPTkZJR19TRU5TT1JTX0lOQTJYWCkJKz0gaW5hMnh4 -Lm8KPj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jIGIvZHJpdmVycy9o -d21vbi9pYm1wb3dlcm52LmMKPj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPj4gaW5kZXggMDAwMDAw -MC4uZTVjZmZjZQo+PiAtLS0gL2Rldi9udWxsCj4+ICsrKyBiL2RyaXZlcnMvaHdtb24vaWJtcG93 -ZXJudi5jCj4+IEBAIC0wLDAgKzEsMzg2IEBACj4+ICsvKgo+PiArICogSUJNIFBvd2VyTlYgcGxh -dGZvcm0gc2Vuc29ycyBmb3IgdGVtcGVyYXR1cmUvZmFuL3Bvd2VyCj4+ICsgKiBDb3B5cmlnaHQg -KEMpIDIwMTQgSUJNCj4+ICsgKgo+PiArICogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7 -IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkKPj4gKyAqIGl0IHVuZGVyIHRo -ZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5 -Cj4+ICsgKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIgdmVyc2lvbiAyIG9m -IHRoZSBMaWNlbnNlLCBvcgo+PiArICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lv -bi4KPj4gKyAqCj4+ICsgKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUg -dGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKPj4gKyAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsg -d2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCj4+ICsgKiBNRVJDSEFOVEFCSUxJ -VFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCj4+ICsgKiBH -TlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgo+PiArICoKPj4gKyAq -IFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1Ymxp -YyBMaWNlbnNlCj4+ICsgKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0 -byB0aGUgRnJlZSBTb2Z0d2FyZQo+PiArICogRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBs -YWNlLCBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgIDAyMTExLTEzMDcgIFVTQQo+IFBsZWFzZSBkcm9w -IHRoZSBGU0YgYWRkcmVzczsgaXQgY2FuIGNoYW5nZSwgYW5kIHdlIGRvbid0IHdhbnQgdG8gdXBk -YXRlIHRoZQo+IGRyaXZlciBlYWNoIHRpbWUgaXQgZG9lcy4KPgo+PiArICovCj4+ICsKPj4gKyNp -bmNsdWRlIDxsaW51eC9pbml0Lmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+Cj4+ICsj -aW5jbHVkZSA8bGludXgva2VybmVsLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvaHdtb24uaD4KPj4g -KyNpbmNsdWRlIDxsaW51eC9od21vbi1zeXNmcy5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L29mLmg+ -Cj4+ICsjaW5jbHVkZSA8bGludXgvc2xhYi5oPgo+PiArCj4+ICsjaW5jbHVkZSA8bGludXgvcGxh -dGZvcm1fZGV2aWNlLmg+Cj4+ICsjaW5jbHVkZSA8YXNtL29wYWwuaD4KPj4gKyNpbmNsdWRlIDxs -aW51eC9lcnIuaD4KPj4gKwo+PiArI2RlZmluZSBEUlZOQU1FCQkiaWJtcG93ZXJudiIKPj4gKyNk -ZWZpbmUgTUFYX0FUVFJfTEVOCTMyCj4+ICsKPj4gKy8qIFNlbnNvciBzdWZmaXggbmFtZSBmcm9t -IERUICovCj4+ICsjZGVmaW5lIERUX0ZBVUxUX0FUVFJfU1VGRklYCQkiZmF1bHRlZCIKPj4gKyNk -ZWZpbmUgRFRfREFUQV9BVFRSX1NVRkZJWAkJImRhdGEiCj4+ICsjZGVmaW5lIERUX1RIUkVTSE9M -RF9BVFRSX1NVRkZJWAkidGhycyIKPj4gKwo+PiArLyogRW51bWVyYXRlcyBhbGwgdGhlIHNlbnNv -cnMgaW4gdGhlIFBPV0VSTlYgcGxhdGZvcm0gYW5kIGFsc28gaW5kZXggaW50bwo+PiArICogJ3N0 -cnVjdCBzZW5zb3JfbmFtZScKPiBDb21tZW50IGNvZGluZyBzdHlsZSwgcGxlYXNlICh0aGlzIGlz -IG5vdCB0aGUgbmV0d29ya2luZyBzdWJzeXN0ZW0gOy0pCj4KPj4gKyAqLwo+PiArZW51bSBzZW5z -b3JzIHsKPj4gKwlGQU4sCj4+ICsJQU1CSUVOVF9URU1QLAo+PiArCVBPV0VSU1VQUExZLAo+PiAr -CVBPV0VSLAo+PiArCU1BWF9TRU5TT1JfVFlQRSwKPj4gK307Cj4+ICsKPj4gK3N0YXRpYyBzdHJ1 -Y3Qgc2Vuc29yX25hbWUgewo+IGNvbnN0ID8KPgo+PiArCWNoYXIgKm5hbWU7Cj4+ICsJY2hhciAq -Y29tcGF0aWJsZTsKPj4gK30gc2Vuc29yX25hbWVzW10gPSB7Cj4+ICsJeyJmYW4iLCAiaWJtLG9w -YWwtc2Vuc29yLWNvb2xpbmctZmFuIn0sCj4+ICsJeyJ0ZW1wIiwgImlibSxvcGFsLXNlbnNvci1h -bWItdGVtcCJ9LAo+PiArCXsiaW4iLCAiaWJtLG9wYWwtc2Vuc29yLXBvd2VyLXN1cHBseSJ9LAo+ -PiArCXsicG93ZXIiLCAiaWJtLG9wYWwtc2Vuc29yLXBvd2VyIn0KPj4gK307Cj4+ICsKPj4gK3N0 -cnVjdCBwbGF0Zm9ybV9kYXRhIHsKPj4gKwlzdHJ1Y3QgZGV2aWNlICpod21vbl9kZXY7Cj4gTm90 -IG5lZWRlZC4KPgo+PiArCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlIG5hbWVfYXR0cjsKPj4gKwlz -dHJ1Y3QgbGlzdF9oZWFkIGF0dHJfbGlzdDsKPj4gK307Cj4+ICsKPj4gK3N0cnVjdCBzZW5zb3Jf -ZGF0YSB7Cj4+ICsJdTMyIGlkOwo+PiArCWVudW0gc2Vuc29ycyBzdHlwZTsKPj4gKwljaGFyIG5h -bWVbTUFYX0FUVFJfTEVOXTsKPj4gKwlzdHJ1Y3Qgc2Vuc29yX2RldmljZV9hdHRyaWJ1dGUgc2Rf -YXR0cjsKPj4gKwlzdHJ1Y3QgbGlzdF9oZWFkIGxpc3Q7Cj4+ICt9Owo+PiArCj4+ICsvKiBQbGF0 -Zm9ybSBkZXZpY2UgcmVwcmVzZW50aW5nIGFsbCB0aGUgaWJtcG93ZXJudiBzZW5zb3JzICovCj4+ -ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldmljZTsKPj4gKwo+PiArc3RhdGlj -IHZvaWQgZ2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0IGNoYXIgKm5hbWUsIHUzMiAqaW5kZXgs -IGNoYXIgKmF0dHIpCj4+ICt7Cj4+ICsJY2hhciAqaGFzaF9wb3MgPSBzdHJjaHIobmFtZSwgJyMn -KTsKPj4gKwljaGFyICpkYXNoX3BvczsKPj4gKwl1MzIgY29weV9sZW47Cj4+ICsJY2hhciBidWZb -OF07Cj4+ICsKPj4gKwltZW1zZXQoYnVmLCAwLCBzaXplb2YoYnVmKSk7Cj4+ICsJKmluZGV4ID0g -MDsKPj4gKwkqYXR0ciA9ICdcMCc7Cj4+ICsKPj4gKwlpZiAoaGFzaF9wb3MpIHsKPj4gKwkJZGFz -aF9wb3MgPSBzdHJjaHIoaGFzaF9wb3MsICctJyk7Cj4+ICsJCWlmIChkYXNoX3Bvcykgewo+PiAr -CQkJY29weV9sZW4gPSBkYXNoX3BvcyAtIGhhc2hfcG9zIC0gMTsKPj4gKwkJCWlmIChjb3B5X2xl -biA8IHNpemVvZihidWYpKSB7Cj4+ICsJCQkJc3RybmNweShidWYsIGhhc2hfcG9zICsgMSwgY29w -eV9sZW4pOwo+PiArCQkJCXNzY2FuZihidWYsICIlZCIsIGluZGV4KTsKPj4gKwkJCX0KPj4gKwo+ -PiArCQkJc3RybmNweShhdHRyLCBkYXNoX3BvcyArIDEsIE1BWF9BVFRSX0xFTik7Cj4+ICsJCX0K -Pj4gKwl9Cj4+ICt9Cj4+ICsKPj4gKy8qCj4+ICsgKiBUaGlzIGZ1bmN0aW9uIHRyYW5zbGF0ZXMg -dGhlIERUIG5vZGUgbmFtZSBpbnRvIHRoZSAnaHdtb24nIGF0dHJpYnV0ZSBuYW1lLgo+PiArICog -SUJNUE9XRVJOViBkZXZpY2Ugbm9kZSBhcHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIGFt -Yi10ZW1wIzEtdGhycyBldGMuCj4+ICsgKiB3aGljaCBuZWVkIHRvIGJlIG1hcHBlZCBhcyBmYW4y -X2lucHV0LCB0ZW1wMV9tYXggcmVzcGVjdGl2ZWx5IGJlZm9yZQo+PiArICogcG9wdWxhdGluZyB0 -aGVtIGluc2lkZSBod21vbiBkZXZpY2UgY2xhc3MuLgo+PiArICovCj4+ICtzdGF0aWMgaW50IGNy -ZWF0ZV9od21vbl9hdHRyX25hbWUoZW51bSBzZW5zb3JzIHN0eXBlLCBjb25zdCBjaGFyICpub2Rl -X25hbWUsCj4+ICsJCWNoYXIgKmh3bW9uX2F0dHJfbmFtZSkKPiBQbGVhc2UgZm9sbG93IENvZGlu -Z1N0eWxlIGZvciBjb250aW51YXRpb24gbGluZSBhbGlnbm1lbnQuCj4KPj4gK3sKPj4gKwljaGFy -IGF0dHJfc3VmZml4W01BWF9BVFRSX0xFTl07Cj4+ICsJY2hhciAqYXR0cl9uYW1lOwo+PiArCXUz -MiBpbmRleDsKPj4gKwo+PiArCWdldF9zZW5zb3JfaW5kZXhfYXR0cihub2RlX25hbWUsICZpbmRl -eCwgYXR0cl9zdWZmaXgpOwo+PiArCWlmICghaW5kZXggfHwgIXN0cmxlbihhdHRyX3N1ZmZpeCkp -IHsKPj4gKwkJcHJfaW5mbygiJXM6IFNlbnNvciBkZXZpY2Ugbm9kZSBuYW1lIGlzIGludmFsaWQs -IG5hbWU6ICVzXG4iLAo+PiArCQkJCV9fZnVuY19fLCBub2RlX25hbWUpOwo+PiArCQlyZXR1cm4g -LUVJTlZBTDsKPj4gKwl9Cj4+ICsKPj4gKwlpZiAoIXN0cmNtcChhdHRyX3N1ZmZpeCwgRFRfRkFV -TFRfQVRUUl9TVUZGSVgpKQo+PiArCQlhdHRyX25hbWUgPSAiZmF1bHQiOwo+PiArCWVsc2UgaWYo -IXN0cmNtcChhdHRyX3N1ZmZpeCwgRFRfREFUQV9BVFRSX1NVRkZJWCkpCj4+ICsJCWF0dHJfbmFt -ZSA9ICJpbnB1dCI7Cj4+ICsJZWxzZSBpZiAoIXN0cmNtcChhdHRyX3N1ZmZpeCwgRFRfVEhSRVNI -T0xEX0FUVFJfU1VGRklYKSkgewo+PiArCQlpZiAoc3R5cGUgPT0gQU1CSUVOVF9URU1QKQo+PiAr -CQkJYXR0cl9uYW1lID0gIm1heCI7Cj4+ICsJCWVsc2UgaWYgKHN0eXBlID09IEZBTikKPj4gKwkJ -CWF0dHJfbmFtZSA9ICJtaW4iOwo+PiArCQllbHNlCj4+ICsJCQlyZXR1cm4gLUVOT0VOVDsKPj4g -Kwl9IGVsc2UKPj4gKwkJcmV0dXJuIC1FTk9FTlQ7Cj4+ICsKPj4gKwlzbnByaW50Zihod21vbl9h -dHRyX25hbWUsIE1BWF9BVFRSX0xFTiwgIiVzJWRfJXMiLAo+PiArCQkJc2Vuc29yX25hbWVzW3N0 -eXBlXS5uYW1lLCBpbmRleCwgYXR0cl9uYW1lKTsKPj4gKwlyZXR1cm4gMDsKPj4gK30KPj4gKwo+ -PiArc3RhdGljIHNzaXplX3Qgc2hvd19zZW5zb3Ioc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3Qg -ZGV2aWNlX2F0dHJpYnV0ZSAqZGV2YXR0ciwKPj4gKwkJY2hhciAqYnVmKQo+PiArewo+PiArCXN0 -cnVjdCBzZW5zb3JfZGV2aWNlX2F0dHJpYnV0ZSAqc2RfYXR0ciA9IHRvX3NlbnNvcl9kZXZfYXR0 -cihkZXZhdHRyKTsKPj4gKwlzdHJ1Y3Qgc2Vuc29yX2RhdGEgKnNkYXRhID0gY29udGFpbmVyX29m -KHNkX2F0dHIsIHN0cnVjdCBzZW5zb3JfZGF0YSwKPj4gKwkJCXNkX2F0dHIpOwo+PiArCWludCBl -cnI7Cj4+ICsJdTMyIHg7Cj4+ICsKPj4gKwllcnIgPSBvcGFsX2dldF9zZW5zb3JfZGF0YShzZGF0 -YS0+aWQsICZ4KTsKPj4gKwlpZiAoZXJyKSB7Cj4+ICsJCXByX2VycigiJXM6IEZhaWxlZCB0byBn -ZXQgb3BhbCBzZW5zb3IgZGF0YVxuIiwgX19mdW5jX18pOwo+PiArCQl4ID0gLTE7Cj4gVW51c3Vh -bC4gV2h5IG5vdCByZXBvcnQgdGhlIGVycm9yIHRvIHVzZXIgc3BhY2UgPwo+IFJlcG9ydGluZyA8 -bWF4dWludD4gb24gZXJyb3IgZG9lc24ndCBzZWVtIHRvIGJlIHZlcnkgdXNlZnVsLgo+Cj4+ICsJ -fQo+PiArCj4+ICsJLyogQ29udmVydCB0ZW1wZXJhdHVyZSB0byBtaWxsaS1kZWdyZWVzICovCj4+ -ICsJaWYgKHNkYXRhLT5zdHlwZSA9PSBBTUJJRU5UX1RFTVAgJiYgeCA+IDApCj4+ICsJCXggKj0g -MTAwMDsKPj4gKwkvKiBDb252ZXJ0IHBvd2VyIHRvIG1pY3JvLXdhdHRzICovCj4+ICsJZWxzZSBp -ZiAoc2RhdGEtPnN0eXBlID09IFBPV0VSICYmIHggPiAwKQo+PiArCQl4ICo9IDEwMDAwMDA7Cj4+ -ICsKPiBJcyB0aGVyZSBhbiBvdmVyZmxvdyBjb25jZXJuID8gR3Vlc3Mgbm90IC4uLiBvdmVyZmxv -dyBoYXBwZW5zIGF0IH4xN0tXLgo+IEp1c3Qgd29uZGVyaW5nLgo+Cj4+ICsJcmV0dXJuIHNwcmlu -dGYoYnVmLCAiJWRcbiIsIHgpOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgdm9pZCByZW1vdmVfZGV2 -aWNlX2F0dHJzKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4+ICt7Cj4+ICsJc3RydWN0 -IHBsYXRmb3JtX2RhdGEgKnBkYXRhID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7Cj4+ICsJ -c3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRldjsKPj4gKwlzdHJ1Y3Qgc2Vuc29yX2RhdGEg -KnMsICpuZXh0Owo+PiArCj4+ICsJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKHMsIG5leHQsICZw -ZGF0YS0+YXR0cl9saXN0LCBsaXN0KSB7Cj4+ICsJCWRldmljZV9yZW1vdmVfZmlsZShkZXYsICZz -LT5zZF9hdHRyLmRldl9hdHRyKTsKPj4gKwkJbGlzdF9kZWwoJnMtPmxpc3QpOwo+IFRoaXMgaXMg -dW5uZWNlc3Nhcnkgc2luY2UgeW91IGFsd2F5cyByZW1vdmUgdGhlIGVudGlyZSBsaXN0IGFueXdh -eS4KPiBBY3R1YWxseSwgSSBkb24ndCB0aGluayB5b3UgbmVlZCB0aGUgbGlzdCBpbiB0aGUgZmly -c3QgcGxhY2UuCj4gWW91IG9ubHkgdXNlIGl0IHRvIGRlbGV0ZSBlbnRyaWVzLCBidXQgdGhhdCBj -YW4gYmUgaGFuZGxlZCBhdXRvbWF0aWNhbGx5Cj4gYnkgdGhlIGluZnJhc3RydWN0dXJlLiBBbGwg -eW91IHJlYWxseSBuZWVkIGlzIGFuIGFycmF5IHBvaW50aW5nIHRvIHRoZSBkZXZpY2UKPiBhdHRy -aWJ1dGVzIHNvIHlvdSBjYW4gY3JlYXRlIGFsbCBhdHRyaWJ1dGUgZmlsZXMgd2l0aCBhIHNpbmds -ZSBvcGVyYXRpb24uCj4KPj4gKwkJa2ZyZWUocyk7Cj4+ICsJfQo+PiArfQo+PiArCj4+ICsvKgo+ -PiArICogSXRlcmF0ZSB0aHJvdWdoIHRoZSBkZXZpY2UgdHJlZSBhbmQgZm9yIGVhY2ggY2hpbGQg -b2Ygc2Vuc29yIG5vZGUsIGNyZWF0ZQo+PiArICogYSBzeXNmcyBhdHRyaWJ1dGUgZmlsZSwgdGhl -IGZpbGUgaXMgbmFtZWQgYnkgdHJhbnNsYXRpbmcgdGhlIERUIG5vZGUgbmFtZQo+PiArICogdG8g -dGhlIG5hbWUgcmVxdWlyZWQgYnkgdGhlIGhpZ2hlciAnaHdtb24nIGRyaXZlciBsaWtlIGZhbjFf -aW5wdXQsIHRlbXAxX21heAo+PiArICogZXRjLi4KPj4gKyAqLwo+PiArc3RhdGljIGludCBjcmVh -dGVfZGV2aWNlX2F0dHJzKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4+ICt7Cj4+ICsJ -c3RydWN0IHBsYXRmb3JtX2RhdGEgKnBkYXRhID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7 -Cj4+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRldjsKPj4gKwlzdHJ1Y3QgZGV2aWNl -X25vZGUgKm9wYWwsICpucDsKPj4gKwlzdHJ1Y3Qgc2Vuc29yX2RhdGEgKnNkYXRhOwo+PiArCWNv -bnN0IHUzMiAqc2Vuc29yX2lkOwo+PiArCWVudW0gc2Vuc29ycyBzdHlwZTsKPj4gKwlpbnQgZXJy -Owo+PiArCj4+ICsJb3BhbCA9IG9mX2ZpbmRfbm9kZV9ieV9wYXRoKCIvaWJtLG9wYWwvc2Vuc29y -cyIpOwo+PiArICAgICAgICBpZiAoIW9wYWwpIHsKPj4gKwkJcHJfZXJyKCIlczogT3BhbCAnc2Vu -c29ycycgbm9kZSBub3QgZm91bmRcbiIsIF9fZnVuY19fKTsKPj4gKwkJZXJyID0gLUVOWElPOwo+ -IAlFTk9ERVYgPwo+Cj4+ICsJCWdvdG8gZXhpdDsKPiAJSSB3b3VsZCBzdWdnZXN0IHRvIHNpbXBs -eSByZXR1cm4gaGVyZS4KPgo+PiArICAgICAgICB9Cj4+ICsKPj4gKwlmb3JfZWFjaF9jaGlsZF9v -Zl9ub2RlKG9wYWwsIG5wKSB7Cj4+ICsgICAgICAgICAgICAgICAgaWYgKG5wLT5uYW1lID09IE5V -TEwpCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKPj4gKwo+PiArCQlmb3Ig -KHN0eXBlID0gMDsgc3R5cGUgPCBNQVhfU0VOU09SX1RZUEU7IHN0eXBlKyspCj4+ICsJCQlpZiAo -b2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCj4+ICsJCQkJCXNlbnNvcl9uYW1lc1tzdHlwZV0u -Y29tcGF0aWJsZSkpCj4+ICsJCQkJYnJlYWs7Cj4+ICsKPj4gKwkJaWYgKHN0eXBlID09IE1BWF9T -RU5TT1JfVFlQRSkKPj4gKwkJCWNvbnRpbnVlOwo+PiArCj4+ICsJCXNlbnNvcl9pZCA9IG9mX2dl -dF9wcm9wZXJ0eShucCwgInNlbnNvci1pZCIsIE5VTEwpOwo+PiArCQlpZiAoIXNlbnNvcl9pZCkg -ewo+PiArCQkJcHJfaW5mbygiJXM6ICVzIGRvZXNuJ3QgaGF2ZSBzZW5zb3ItaWRcbiIsIF9fZnVu -Y19fLAo+PiArCQkJCQlucC0+bmFtZSk7Cj4+ICsJCQljb250aW51ZTsKPj4gKwkJfQo+PiArCj4+ -ICsJCXNkYXRhID0ga3phbGxvYyhzaXplb2YoKnNkYXRhKSwgR0ZQX0tFUk5FTCk7Cj4gQ2FuIHlv -dSB1c2UgZGV2bV9remFsbG9jKCkgPwo+Cj4+ICsJCWlmICghc2RhdGEpIHsKPj4gKwkJCXByX2Vy -cigiJXM6IEZhaWxlZCB0byBhbGxvY2F0ZSBtZW1vcnkgZm9yIHNlbnNvcl9kYXRhIiwKPj4gKwkJ -CQkJX19mdW5jX18pOwo+PiArCQkJZXJyID0gLUVOT01FTTsKPj4gKwkJCWdvdG8gZXhpdF9wdXRf -bm9kZTsKPj4gKwkJfQo+PiArCj4+ICsJCXNkYXRhLT5pZCA9ICpzZW5zb3JfaWQ7Cj4+ICsJCXNk -YXRhLT5zdHlwZSA9IHN0eXBlOwo+PiArCQllcnIgPSBjcmVhdGVfaHdtb25fYXR0cl9uYW1lKHN0 -eXBlLCBucC0+bmFtZSwgc2RhdGEtPm5hbWUpOwo+PiArCQlpZiAoZXJyKSB7Cj4+ICsJCQlwcl9l -cnIoIiVzOiBGYWlsZWQgdG8gY3JlYXRlIHRoZSBod21vbiBhdHRyaWJ1dGUgbmFtZVxuIiwKPj4g -KwkJCQkJX19mdW5jX18pOwo+IGNyZWF0ZV9od21vbl9hdHRyX25hbWUoKSAoc29tZXRpbWVzKSBh -bHJlYWR5IGNyZWF0ZXMgYW4gZXJyb3IgbWVzc2FnZS4KPiBXb3VsZCBiZSBuaWNlIGlmIHlvdSBj -YW4gYXZvaWQgZHVwbGljYXRlIGVycm9yIG1lc3NhZ2VzLgo+Cj4+ICsJCQlnb3RvIGV4aXRfZnJl -ZV9zZGF0YTsKPj4gKwkJfQo+PiArCj4+ICsJCXN5c2ZzX2F0dHJfaW5pdCgmc2RhdGEtPnNkX2F0 -dHIuZGV2X2F0dHIuYXR0cik7Cj4+ICsJCXNkYXRhLT5zZF9hdHRyLmRldl9hdHRyLmF0dHIubmFt -ZSA9IHNkYXRhLT5uYW1lOwo+PiArCQlzZGF0YS0+c2RfYXR0ci5kZXZfYXR0ci5hdHRyLm1vZGUg -PSBTX0lSVUdPOwo+PiArCQlzZGF0YS0+c2RfYXR0ci5kZXZfYXR0ci5zaG93ID0gc2hvd19zZW5z -b3I7Cj4gU2luY2UgeW91IGFyZSBub3QgdXNpbmcgdGhlIGluZGV4IHZhbHVlIGZyb20gc2Vuc29y -X2RldmljZV9hdHRyaWJ1dGUsCj4gYnV0IHVzZSB5b3VyIG93biAnaWQnIHZhcmlhYmxlIGluc3Rl -YWQsIHlvdSBkb24ndCBuZWVkIHNlbnNvcl9kZXZpY2VfYXR0cmlidXRlCj4gYnV0IGNhbiB1c2Ug -ZGV2aWNlX2F0dHJpYnV0ZSBpbnN0ZWFkIChvciBkcm9wICdpZCcgYW5kIHVzZQo+IHNkX2F0dHIu -aW5kZXggaW5zdGVhZCkuCj4KPj4gKwo+PiArCQkvKiBDcmVhdGUgc3lzZnMgYXR0cmlidXRlIGZp -bGUgKi8KPj4gKwkJZXJyID0gZGV2aWNlX2NyZWF0ZV9maWxlKGRldiwgJnNkYXRhLT5zZF9hdHRy -LmRldl9hdHRyKTsKPj4gKwkJaWYgKGVycikKPj4gKwkJCWdvdG8gZXhpdF9mcmVlX3NkYXRhOwo+ -PiArCj4gUGxlYXNlIGRvbid0IGNyZWF0ZSB0aGUgYXR0cmlidXRlIGZpbGVzIGhlcmUgYnV0IGp1 -c3QgYSBsaXN0IG9mIGF0dHJpYnV0ZXMKPiBpbnN0ZWFkLiBTZWUgYmVsb3cgZm9yIG1vcmUgZGV0 -YWlscy4KPgo+PiArCQlsaXN0X2FkZF90YWlsKCZzZGF0YS0+bGlzdCwgJnBkYXRhLT5hdHRyX2xp -c3QpOwo+PiArCX0KPj4gKwo+PiArCW9mX25vZGVfcHV0KG9wYWwpOwo+PiArCXJldHVybiAwOwo+ -PiArCj4+ICtleGl0X2ZyZWVfc2RhdGE6Cj4+ICsJa2ZyZWUoc2RhdGEpOwo+PiArZXhpdF9wdXRf -bm9kZToKPj4gKwlvZl9ub2RlX3B1dChvcGFsKTsKPj4gKwlyZW1vdmVfZGV2aWNlX2F0dHJzKHBk -ZXYpOwo+PiArZXhpdDoKPj4gKwlyZXR1cm4gZXJyOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgc3Np -emVfdCBzaG93X25hbWUoc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgZGV2aWNlX2F0dHJpYnV0 -ZSAqZGV2YXR0ciwKPj4gKwkJY2hhciAqYnVmKQo+PiArewo+PiArCXN0cnVjdCBwbGF0Zm9ybV9k -ZXZpY2UgKnBkZXYgPSB0b19wbGF0Zm9ybV9kZXZpY2UoZGV2KTsKPj4gKwlyZXR1cm4gc3ByaW50 -ZihidWYsICIlc1xuIiwgcGRldi0+bmFtZSk7Cj4+ICt9Cj4gTm90IG5lY2Vzc2FyeTsgc2VlIGJl -bG93Lgo+Cj4+ICsKPj4gK3N0YXRpYyBpbnQgaWJtcG93ZXJudl9wcm9iZShzdHJ1Y3QgcGxhdGZv -cm1fZGV2aWNlICpwZGV2KQo+PiArewo+PiArCXN0cnVjdCBkZXZpY2UgKmRldiA9ICZwZGV2LT5k -ZXY7Cj4+ICsJc3RydWN0IHBsYXRmb3JtX2RhdGEgKnBkYXRhOwo+PiArCWludCBlcnI7Cj4+ICsK -Pj4gKwlwZGF0YSA9IGRldm1fa3phbGxvYyhkZXYsIHNpemVvZigqcGRhdGEpLCBHRlBfS0VSTkVM -KTsKPj4gKwlpZiAoIXBkYXRhKSB7Cj4+ICsJCWVyciA9IC1FTk9NRU07Cj4+ICsJCWdvdG8gZXhp -dDsKPj4gKwl9Cj4+ICsKPj4gKwlJTklUX0xJU1RfSEVBRCgmcGRhdGEtPmF0dHJfbGlzdCk7Cj4+ -ICsJcGxhdGZvcm1fc2V0X2RydmRhdGEocGRldiwgcGRhdGEpOwo+PiArCj4+ICsJLyogQ3JlYXRl -IHBsYXRmb3JtIGRldmljZSAnbmFtZScgYXR0cmlidXRlICovCj4+ICsJc3lzZnNfYXR0cl9pbml0 -KCZwZGF0YS0+bmFtZV9hdHRyLmF0dHIpOwo+PiArCXBkYXRhLT5uYW1lX2F0dHIuYXR0ci5uYW1l -ID0gIm5hbWUiOwo+PiArCXBkYXRhLT5uYW1lX2F0dHIuYXR0ci5tb2RlID0gU19JUlVHTzsKPj4g -KwlwZGF0YS0+bmFtZV9hdHRyLnNob3cgPSBzaG93X25hbWU7Cj4+ICsJZXJyID0gZGV2aWNlX2Ny -ZWF0ZV9maWxlKGRldiwgJnBkYXRhLT5uYW1lX2F0dHIpOwo+IFlvdSBkb24ndCBuZWVkIHRvIGNy -ZWF0ZSBhIG5hbWUgYXR0cmlidXRlLgo+IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhf -Z3JvdXBzIGRvZXMgaXQgZm9yIHlvdSAoZnJvbSB0aGUgc2Vjb25kCj4gYXJndW1lbnQpLgo+Cj4+ -ICsJaWYgKGVycikKPj4gKwkJZ290byBleGl0Owo+PiArCj4+ICsJLyogQ3JlYXRlIHN5c2ZzIGF0 -dHJpYnV0ZSBmaWxlIGZvciBlYWNoIHNlbnNvciBmb3VuZCBpbiB0aGUgRFQgKi8KPj4gKwllcnIg -PSBjcmVhdGVfZGV2aWNlX2F0dHJzKHBkZXYpOwo+IFRoYXQgZGVmZWF0cyB0aGUgcHVycG9zZSBv -ZiB1c2luZyBkZXZtX2h3bW9uX2RldmljZV9yZWdpc3Rlcl93aXRoX2dyb3Vwcy4KPiBUaGUgaWRl -YSBoZXJlIGlzIHRvIGJ1aWxkIGEgbGlzdCBvZiBhdHRyaWJ1dGVzLCB3aGljaCB5b3UgY2FuIGRv -IGluCj4gY3JlYXRlX2RldmljZV9hdHRycygpLCBidXQgbm90IGNyZWF0ZSB0aGUgYWN0dWFsIGRl -dmljZSBlbnRyaWVzLgo+IFRoZW4gYWxzbyBjcmVhdGUgYW4gYXR0cmlidXRlX2dyb3VwIGFzIHdl -bGwgYXMgYSBsaXN0IG9mIGdyb3VwcywKPiBhbmQgcGFzcyB0aGF0IGFzIGxhc3QgYXJndW1lbnQg -dG8gZGV2bV9od21vbl9kZXZpY2VfcmVnaXN0ZXJfd2l0aF9ncm91cHMoKS4KPgo+IGRyaXZlcnMv -aHdtb24vcG1idXMvcG1idXNfY29yZS5jIGRvZXMgc29tZXRoaW5nIHNpbWlsYXI7IG1heWJlIHlv -dSBjYW4KPiB1c2UgYSBzaW1pbGFyIGFwcHJvYWNoLgo+Cj4gV2l0aCB0aGF0LCB5b3UgYWxzbyBk -b24ndCBuZWVkIHRoZSByZW1vdmUgZnVuY3Rpb25zLCBzaW5jZSB0aGUgaHdtb24KPiBzdWJzeXN0 -ZW0gd2lsbCBhdXRvLXJlbW92ZSB0aGUgYXR0cmlidXRlcy4gSWYgeW91IGRvIGl0IGNvcnJlY3Rs -eQo+IChpZSB1c2UgZGV2bV9remFsbG9jKCkgZm9yIGFsbG9jYXRpbmcgbWVtb3J5KSB5b3Ugc2hv -dWxkIG5vdCBuZWVkIGEKPiByZW1vdmUgZnVuY3Rpb24gYXQgYWxsLgo+Cj4+ICsJaWYgKGVycikg -ewo+PiArCQlwcl9lcnIoIiVzOiBGYWlsZWQgdG8gY3JlYXRlIHRoZSBkZXZpY2UgYXR0cmlidXRl -c1xuIiwKPj4gKwkJCQlfX2Z1bmNfXyk7Cj4+ICsJCWdvdG8gZXhpdF9yZW1vdmVfbmFtZTsKPj4g -Kwl9Cj4+ICsKPj4gKwkvKiBGaW5hbGx5LCByZWdpc3RlciB3aXRoIGh3bW9uICovCj4+ICsJcGRh -dGEtPmh3bW9uX2RldiA9IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhfZ3JvdXBzKGRl -diwgRFJWTkFNRSwKPj4gKwkJCXBkYXRhLCBOVUxMKTsKPj4gKwlpZiAoSVNfRVJSKHBkYXRhLT5o -d21vbl9kZXYpKSB7Cj4+ICsJCWVyciA9IFBUUl9FUlIocGRhdGEtPmh3bW9uX2Rldik7Cj4+ICsJ -CWdvdG8gZXhpdF9yZW1vdmVfZGV2YXR0cnM7Cj4+ICsJfQo+PiArCj4+ICsJcmV0dXJuIDA7Cj4+ -ICsKPj4gK2V4aXRfcmVtb3ZlX2RldmF0dHJzOgo+PiArCXJlbW92ZV9kZXZpY2VfYXR0cnMocGRl -dik7Cj4+ICtleGl0X3JlbW92ZV9uYW1lOgo+PiArCWRldmljZV9yZW1vdmVfZmlsZShkZXYsICZw -ZGF0YS0+bmFtZV9hdHRyKTsKPj4gK2V4aXQ6Cj4+ICsJcmV0dXJuIGVycjsKPiBJZiB5b3UgZG8g -aXQgcmlnaHQgeW91IHNob3VsZCBiZSBhYmxlIHRvIHJlZHVjZSB0aGlzIHRvIHNvbWV0aGluZyBs -aWtlCj4KPiAJaHdtb25fZGV2ID0gZGV2bV9od21vbl9kZXZpY2VfcmVnaXN0ZXJfd2l0aF9ncm91 -cHMoZGV2LCBEUlZOQU1FLCBwZGF0YSwKPiAJCQkJCQkJICAgcGRhdGEtPmF0dHJfZ3JvdXBzKTsK -PiAJcmV0dXJuIFBUUl9FUlJfT1JfWkVSTyhod21vbl9kZXYpOwo+Cj4gLi4uCj4KPj4gK30KPj4g -Kwo+PiArc3RhdGljIGludCBpYm1wb3dlcm52X3JlbW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNl -ICpwZGV2KQo+PiArewo+PiArCXN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YSA9IHBsYXRmb3Jt -X2dldF9kcnZkYXRhKHBkZXYpOwo+PiArCXN0cnVjdCBkZXZpY2UgKmRldiA9ICZwZGV2LT5kZXY7 -Cj4+ICsKPj4gKwlyZW1vdmVfZGV2aWNlX2F0dHJzKHBkZXYpOwo+PiArCWRldmljZV9yZW1vdmVf -ZmlsZShkZXYsICZwZGF0YS0+bmFtZV9hdHRyKTsKPj4gKwo+PiArCXJldHVybiAwOwo+PiArfQo+ -IC4uLiBhbmQgeW91IHNob3VsZCBiZSBhYmxlIHRvIHJlbW92ZSB0aGlzIGVudGlyZSBmdW5jdGlv -bi4KPgo+PiArCj4+ICsKPiBObyBkb3VibGUgZW1wdHkgbGluZXMgcGxlYXNlLgo+Cj4+ICtzdGF0 -aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBpYm1wb3dlcm52X2RyaXZlciA9IHsKPj4gKwkuZHJp -dmVyID0gewo+PiArCQkub3duZXIgPSBUSElTX01PRFVMRSwKPj4gKwkJLm5hbWUgPSBEUlZOQU1F -LAo+PiArCX0sCj4+ICsJLnByb2JlID0gaWJtcG93ZXJudl9wcm9iZSwKPj4gKwkucmVtb3ZlID0g -aWJtcG93ZXJudl9yZW1vdmUsCj4+ICt9Owo+PiArCj4+ICsKPiBFeGNlc3NpdmUgZW1wdHkgbGlu -ZXMuCj4KPj4gK3N0YXRpYyBpbnQgX19pbml0IGlibXBvd2VybnZfaW5pdCh2b2lkKQo+PiArewo+ -PiArCWludCBlcnI7Cj4+ICsKPj4gKwo+IEV4Y2Vzc2l2ZSBlbXB0eSBsaW5lcy4KPgo+PiArCWVy -ciA9IHBsYXRmb3JtX2RyaXZlcl9yZWdpc3RlcigmaWJtcG93ZXJudl9kcml2ZXIpOwo+PiArCWlm -IChlcnIpCj4+ICsJCWdvdG8gZXhpdDsKPiBTb21ldGltZXMgeW91IGNyZWF0ZSBhbiBlcnJvciBt -ZXNzYWdlLCBzb21ldGltZXMgbm90LiBJJ2QgcHJlZmVyIG5vIGVycm9yCj4gbWVzc2FnZSB0byBz -dGFydCB3aXRoICh0aGUgbW9kdWxlIGxvYWRlciB3aWxsIGNyZWF0ZSBvbmUgYW55d2F5KSwgYnV0 -Cj4gYXQgbGVhc3QgcGxlYXNlIGJlIGNvbnNpc3RlbnQuCj4KPj4gKwo+PiArCj4gRXhjZXNzaXZl -IGVtcHR5IGxpbmVzLgo+Cj4+ICsJcGRldmljZSA9IHBsYXRmb3JtX2RldmljZV9hbGxvYyhEUlZO -QU1FLCAwKTsKPj4gKwlpZiAoIXBkZXZpY2UpIHsKPj4gKwkJcHJfZXJyKCIlczogRGV2aWNlIGFs -bG9jYXRpb24gZmFpbGVkXG4iLCBfX2Z1bmNfXyk7Cj4+ICsJCWVyciA9IC1FTk9NRU07Cj4+ICsJ -CWdvdG8gZXhpdF9kcml2ZXJfdW5yZWc7Cj4+ICsJfQo+PiArCj4+ICsJZXJyID0gcGxhdGZvcm1f -ZGV2aWNlX2FkZChwZGV2aWNlKTsKPj4gKwlpZiAoZXJyKSB7Cj4+ICsJCXByX2VycigiJXM6IERl -dmljZSBhZGRpdGlvbiBmYWlsZWQgKCVkKVxuIiwgX19mdW5jX18sIGVycik7Cj4+ICsJCWdvdG8g -ZXhpdF9kZXZpY2VfcHV0Owo+PiArCX0KPj4gKwo+IENhbiB5b3UgdXNlIHBsYXRmb3JtX2RyaXZl -cl9wcm9iZSgpIGhlcmUgPwo+Cj4+ICsJcmV0dXJuIDA7Cj4+ICsKPj4gK2V4aXRfZGV2aWNlX3B1 -dDoKPj4gKwlwbGF0Zm9ybV9kZXZpY2VfcHV0KHBkZXZpY2UpOwo+PiArZXhpdF9kcml2ZXJfdW5y -ZWc6Cj4+ICsJcGxhdGZvcm1fZHJpdmVyX3VucmVnaXN0ZXIoJmlibXBvd2VybnZfZHJpdmVyKTsK -Pj4gK2V4aXQ6Cj4+ICsJcmV0dXJuIGVycjsKPj4gK30KPj4gKwo+PiArc3RhdGljIHZvaWQgX19l -eGl0IGlibXBvd2VybnZfZXhpdCh2b2lkKQo+PiArewo+PiArCXBsYXRmb3JtX2RldmljZV91bnJl -Z2lzdGVyKHBkZXZpY2UpOwo+PiArCXBsYXRmb3JtX2RyaXZlcl91bnJlZ2lzdGVyKCZpYm1wb3dl -cm52X2RyaXZlcik7Cj4+ICt9Cj4+ICsKPj4gK01PRFVMRV9ERVNDUklQVElPTigiSUJNIFBPV0VS -TlYgcGxhdGZvcm0gc2Vuc29ycyIpOwo+PiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwo+PiArCj4+ -ICttb2R1bGVfaW5pdChpYm1wb3dlcm52X2luaXQpOwo+PiArbW9kdWxlX2V4aXQoaWJtcG93ZXJu -dl9leGl0KTsKPj4KPj4KPiBFbXB0eSBsaW5lcyBhdCBlbmQuCj4KPiBfX19fX19fX19fX19fX19f -X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwo+IExpbnV4cHBjLWRldiBtYWlsaW5nIGxp -c3QKPiBMaW51eHBwYy1kZXZAbGlzdHMub3psYWJzLm9yZwo+IGh0dHBzOi8vbGlzdHMub3psYWJz -Lm9yZy9saXN0aW5mby9saW51eHBwYy1kZXYKSGkgR3VlbnRlciwKClRoYW5rcyBmb3IgdGhlIHJl -dmlldy4gSSdsbCByZXdvcmsgb24gdGhlIHBhdGNoIGFuZCBwb3N0IHRoZSB2Mi4KCi0gTmVlbGVz -aAoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxtLXNl -bnNvcnMgbWFpbGluZyBsaXN0CmxtLXNlbnNvcnNAbG0tc2Vuc29ycy5vcmcKaHR0cDovL2xpc3Rz -LmxtLXNlbnNvcnMub3JnL21haWxtYW4vbGlzdGluZm8vbG0tc2Vuc29ycw= +On 05/14/2014 10:39 PM, Guenter Roeck wrote: +> On Wed, May 14, 2014 at 11:31:53AM +0530, 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: 5294 RPM (min = 0 RPM) +>> fan2: 4945 RPM (min = 0 RPM) +>> fan3: 5831 RPM (min = 0 RPM) +>> fan4: 5212 RPM (min = 0 RPM) +>> fan5: 0 RPM (min = 0 RPM) +>> fan6: 0 RPM (min = 0 RPM) +>> fan7: 7472 RPM (min = 0 RPM) +>> fan8: 7920 RPM (min = 0 RPM) +>> temp1: +39.0°C (high = +0.0°C) +>> power1: 192.00 W +>> +>> [root@tul163p1 ~]# +>> [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/ +>> driver fan2_min fan4_min fan6_min fan8_min modalias uevent +>> fan1_fault fan3_fault fan5_fault fan7_fault hwmon name +>> fan1_input fan3_input fan5_input fan7_input in1_fault power1_input +>> fan1_min fan3_min fan5_min fan7_min in2_fault subsystem +>> fan2_fault fan4_fault fan6_fault fan8_fault in3_fault temp1_input +>> fan2_input fan4_input fan6_input fan8_input in4_fault temp1_max +>> [root@tul163p1 ~]# +>> [root@tul163p1 ~]# ls /sys/class/hwmon/hwmon0/device/ +>> driver fan2_min fan4_min fan6_min fan8_min modalias uevent +>> fan1_fault fan3_fault fan5_fault fan7_fault hwmon name +>> fan1_input fan3_input fan5_input fan7_input in1_fault power1_input +>> fan1_min fan3_min fan5_min fan7_min in2_fault subsystem +>> fan2_fault fan4_fault fan6_fault fan8_fault in3_fault temp1_input +>> fan2_input fan4_input fan6_input fan8_input in4_fault temp1_max +>> [root@tul163p1 ~]# +>> +>> Signed-off-by: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com> +>> Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com> +>> --- +>> drivers/hwmon/Kconfig | 8 + +>> drivers/hwmon/Makefile | 1 +>> drivers/hwmon/ibmpowernv.c | 386 ++++++++++++++++++++++++++++++++++++++++++++ +>> 3 files changed, 395 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..e5cffce +>> --- /dev/null +>> +++ b/drivers/hwmon/ibmpowernv.c +>> @@ -0,0 +1,386 @@ +>> +/* +>> + * 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; if not, write to the Free Software +>> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +> Please drop the FSF address; it can change, and we don't want to update the +> driver each time it does. +> +>> + */ +>> + +>> +#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 sensors in the POWERNV platform and also index into +>> + * 'struct sensor_name' +> Comment coding style, please (this is not the networking subsystem ;-) +> +>> + */ +>> +enum sensors { +>> + FAN, +>> + AMBIENT_TEMP, +>> + POWERSUPPLY, +>> + POWER, +>> + MAX_SENSOR_TYPE, +>> +}; +>> + +>> +static struct sensor_name { +> const ? +> +>> + char *name; +>> + char *compatible; +>> +} sensor_names[] = { +>> + {"fan", "ibm,opal-sensor-cooling-fan"}, +>> + {"temp", "ibm,opal-sensor-amb-temp"}, +>> + {"in", "ibm,opal-sensor-power-supply"}, +>> + {"power", "ibm,opal-sensor-power"} +>> +}; +>> + +>> +struct platform_data { +>> + struct device *hwmon_dev; +> Not needed. +> +>> + struct device_attribute name_attr; +>> + struct list_head attr_list; +>> +}; +>> + +>> +struct sensor_data { +>> + u32 id; +>> + enum sensors stype; +>> + char name[MAX_ATTR_LEN]; +>> + struct sensor_device_attribute sd_attr; +>> + struct list_head list; +>> +}; +>> + +>> +/* Platform device representing all the ibmpowernv sensors */ +>> +static struct platform_device *pdevice; +>> + +>> +static void 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); +>> + } +>> + +>> + 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 create_hwmon_attr_name(enum sensors stype, const char *node_name, +>> + char *hwmon_attr_name) +> Please follow CodingStyle for continuation line alignment. +> +>> +{ +>> + 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 (stype == AMBIENT_TEMP) +>> + attr_name = "max"; +>> + else if (stype == FAN) +>> + attr_name = "min"; +>> + else +>> + return -ENOENT; +>> + } else +>> + return -ENOENT; +>> + +>> + snprintf(hwmon_attr_name, MAX_ATTR_LEN, "%s%d_%s", +>> + sensor_names[stype].name, index, attr_name); +>> + return 0; +>> +} +>> + +>> +static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr, +>> + char *buf) +>> +{ +>> + struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(devattr); +>> + struct sensor_data *sdata = container_of(sd_attr, struct sensor_data, +>> + sd_attr); +>> + int err; +>> + u32 x; +>> + +>> + err = opal_get_sensor_data(sdata->id, &x); +>> + if (err) { +>> + pr_err("%s: Failed to get opal sensor data\n", __func__); +>> + x = -1; +> Unusual. Why not report the error to user space ? +> Reporting <maxuint> on error doesn't seem to be very useful. +> +>> + } +>> + +>> + /* Convert temperature to milli-degrees */ +>> + if (sdata->stype == AMBIENT_TEMP && x > 0) +>> + x *= 1000; +>> + /* Convert power to micro-watts */ +>> + else if (sdata->stype == POWER && x > 0) +>> + x *= 1000000; +>> + +> Is there an overflow concern ? Guess not ... overflow happens at ~17KW. +> Just wondering. +> +>> + return sprintf(buf, "%d\n", x); +>> +} +>> + +>> +static void remove_device_attrs(struct platform_device *pdev) +>> +{ +>> + struct platform_data *pdata = platform_get_drvdata(pdev); +>> + struct device *dev = &pdev->dev; +>> + struct sensor_data *s, *next; +>> + +>> + list_for_each_entry_safe(s, next, &pdata->attr_list, list) { +>> + device_remove_file(dev, &s->sd_attr.dev_attr); +>> + list_del(&s->list); +> This is unnecessary since you always remove the entire list anyway. +> Actually, I don't think you need the list in the first place. +> You only use it to delete entries, but that can be handled automatically +> by the infrastructure. All you really need is an array pointing to the device +> attributes so you can create all attribute files with a single operation. +> +>> + kfree(s); +>> + } +>> +} +>> + +>> +/* +>> + * Iterate through the device tree and 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 create_device_attrs(struct platform_device *pdev) +>> +{ +>> + struct platform_data *pdata = platform_get_drvdata(pdev); +>> + struct device *dev = &pdev->dev; +>> + struct device_node *opal, *np; +>> + struct sensor_data *sdata; +>> + const u32 *sensor_id; +>> + enum sensors stype; +>> + int err; +>> + +>> + opal = of_find_node_by_path("/ibm,opal/sensors"); +>> + if (!opal) { +>> + pr_err("%s: Opal 'sensors' node not found\n", __func__); +>> + err = -ENXIO; +> ENODEV ? +> +>> + goto exit; +> I would suggest to simply return here. +> +>> + } +>> + +>> + for_each_child_of_node(opal, np) { +>> + if (np->name == NULL) +>> + continue; +>> + +>> + for (stype = 0; stype < MAX_SENSOR_TYPE; stype++) +>> + if (of_device_is_compatible(np, +>> + sensor_names[stype].compatible)) +>> + break; +>> + +>> + if (stype == 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; +>> + } +>> + +>> + sdata = kzalloc(sizeof(*sdata), GFP_KERNEL); +> Can you use devm_kzalloc() ? +> +>> + if (!sdata) { +>> + pr_err("%s: Failed to allocate memory for sensor_data", +>> + __func__); +>> + err = -ENOMEM; +>> + goto exit_put_node; +>> + } +>> + +>> + sdata->id = *sensor_id; +>> + sdata->stype = stype; +>> + err = create_hwmon_attr_name(stype, np->name, sdata->name); +>> + if (err) { +>> + pr_err("%s: Failed to create the hwmon attribute name\n", +>> + __func__); +> create_hwmon_attr_name() (sometimes) already creates an error message. +> Would be nice if you can avoid duplicate error messages. +> +>> + goto exit_free_sdata; +>> + } +>> + +>> + sysfs_attr_init(&sdata->sd_attr.dev_attr.attr); +>> + sdata->sd_attr.dev_attr.attr.name = sdata->name; +>> + sdata->sd_attr.dev_attr.attr.mode = S_IRUGO; +>> + sdata->sd_attr.dev_attr.show = show_sensor; +> Since you are not using the index value from sensor_device_attribute, +> but use your own 'id' variable instead, you don't need sensor_device_attribute +> but can use device_attribute instead (or drop 'id' and use +> sd_attr.index instead). +> +>> + +>> + /* Create sysfs attribute file */ +>> + err = device_create_file(dev, &sdata->sd_attr.dev_attr); +>> + if (err) +>> + goto exit_free_sdata; +>> + +> Please don't create the attribute files here but just a list of attributes +> instead. See below for more details. +> +>> + list_add_tail(&sdata->list, &pdata->attr_list); +>> + } +>> + +>> + of_node_put(opal); +>> + return 0; +>> + +>> +exit_free_sdata: +>> + kfree(sdata); +>> +exit_put_node: +>> + of_node_put(opal); +>> + remove_device_attrs(pdev); +>> +exit: +>> + return err; +>> +} +>> + +>> +static ssize_t show_name(struct device *dev, struct device_attribute *devattr, +>> + char *buf) +>> +{ +>> + struct platform_device *pdev = to_platform_device(dev); +>> + return sprintf(buf, "%s\n", pdev->name); +>> +} +> Not necessary; see below. +> +>> + +>> +static int ibmpowernv_probe(struct platform_device *pdev) +>> +{ +>> + struct device *dev = &pdev->dev; +>> + struct platform_data *pdata; +>> + int err; +>> + +>> + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); +>> + if (!pdata) { +>> + err = -ENOMEM; +>> + goto exit; +>> + } +>> + +>> + INIT_LIST_HEAD(&pdata->attr_list); +>> + platform_set_drvdata(pdev, pdata); +>> + +>> + /* Create platform device 'name' attribute */ +>> + sysfs_attr_init(&pdata->name_attr.attr); +>> + pdata->name_attr.attr.name = "name"; +>> + pdata->name_attr.attr.mode = S_IRUGO; +>> + pdata->name_attr.show = show_name; +>> + err = device_create_file(dev, &pdata->name_attr); +> You don't need to create a name attribute. +> devm_hwmon_device_register_with_groups does it for you (from the second +> argument). +> +>> + if (err) +>> + goto exit; +>> + +>> + /* Create sysfs attribute file for each sensor found in the DT */ +>> + err = create_device_attrs(pdev); +> That defeats the purpose of using devm_hwmon_device_register_with_groups. +> The idea here is to build a list of attributes, which you can do in +> create_device_attrs(), but not create the actual device entries. +> Then also create an attribute_group as well as a list of groups, +> and pass that as last argument to devm_hwmon_device_register_with_groups(). +> +> drivers/hwmon/pmbus/pmbus_core.c does something similar; maybe you can +> use a similar approach. +> +> With that, you also don't need the remove functions, since the hwmon +> subsystem will auto-remove the attributes. If you do it correctly +> (ie use devm_kzalloc() for allocating memory) you should not need a +> remove function at all. +> +>> + if (err) { +>> + pr_err("%s: Failed to create the device attributes\n", +>> + __func__); +>> + goto exit_remove_name; +>> + } +>> + +>> + /* Finally, register with hwmon */ +>> + pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME, +>> + pdata, NULL); +>> + if (IS_ERR(pdata->hwmon_dev)) { +>> + err = PTR_ERR(pdata->hwmon_dev); +>> + goto exit_remove_devattrs; +>> + } +>> + +>> + return 0; +>> + +>> +exit_remove_devattrs: +>> + remove_device_attrs(pdev); +>> +exit_remove_name: +>> + device_remove_file(dev, &pdata->name_attr); +>> +exit: +>> + return err; +> If you do it right you should be able to reduce this to something like +> +> hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME, pdata, +> pdata->attr_groups); +> return PTR_ERR_OR_ZERO(hwmon_dev); +> +> ... +> +>> +} +>> + +>> +static int ibmpowernv_remove(struct platform_device *pdev) +>> +{ +>> + struct platform_data *pdata = platform_get_drvdata(pdev); +>> + struct device *dev = &pdev->dev; +>> + +>> + remove_device_attrs(pdev); +>> + device_remove_file(dev, &pdata->name_attr); +>> + +>> + return 0; +>> +} +> ... and you should be able to remove this entire function. +> +>> + +>> + +> No double empty lines please. +> +>> +static struct platform_driver ibmpowernv_driver = { +>> + .driver = { +>> + .owner = THIS_MODULE, +>> + .name = DRVNAME, +>> + }, +>> + .probe = ibmpowernv_probe, +>> + .remove = ibmpowernv_remove, +>> +}; +>> + +>> + +> Excessive empty lines. +> +>> +static int __init ibmpowernv_init(void) +>> +{ +>> + int err; +>> + +>> + +> Excessive empty lines. +> +>> + err = platform_driver_register(&ibmpowernv_driver); +>> + if (err) +>> + goto exit; +> Sometimes you create an error message, sometimes not. I'd prefer no error +> message to start with (the module loader will create one anyway), but +> at least please be consistent. +> +>> + +>> + +> Excessive empty lines. +> +>> + pdevice = platform_device_alloc(DRVNAME, 0); +>> + if (!pdevice) { +>> + pr_err("%s: Device allocation failed\n", __func__); +>> + err = -ENOMEM; +>> + goto exit_driver_unreg; +>> + } +>> + +>> + err = platform_device_add(pdevice); +>> + if (err) { +>> + pr_err("%s: Device addition failed (%d)\n", __func__, err); +>> + goto exit_device_put; +>> + } +>> + +> Can you use platform_driver_probe() here ? +> +>> + return 0; +>> + +>> +exit_device_put: +>> + platform_device_put(pdevice); +>> +exit_driver_unreg: +>> + platform_driver_unregister(&ibmpowernv_driver); +>> +exit: +>> + return err; +>> +} +>> + +>> +static void __exit ibmpowernv_exit(void) +>> +{ +>> + platform_device_unregister(pdevice); +>> + platform_driver_unregister(&ibmpowernv_driver); +>> +} +>> + +>> +MODULE_DESCRIPTION("IBM POWERNV platform sensors"); +>> +MODULE_LICENSE("GPL"); +>> + +>> +module_init(ibmpowernv_init); +>> +module_exit(ibmpowernv_exit); +>> +>> +> Empty lines at end. +> +> _______________________________________________ +> Linuxppc-dev mailing list +> Linuxppc-dev@lists.ozlabs.org +> https://lists.ozlabs.org/listinfo/linuxppc-dev +Hi Guenter, + +Thanks for the review. I'll rework on the patch and post the v2. + +- Neelesh diff --git a/a/content_digest b/N1/content_digest index 9ca7c90..32d1687 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -1,8 +1,8 @@ "ref\020140514055859.16148.35534.stgit@neelegup-tp-t420.in.ibm.com\0" "ref\020140514170933.GB18032@roeck-us.net\0" "From\0Neelesh Gupta <neelegup@linux.vnet.ibm.com>\0" - "Subject\0Re: [lm-sensors] [PATCH] powerpc/powernv: hwmon driver for power values, fan rpm and temperature\0" - "Date\0Sun, 18 May 2014 18:20:17 +0000\0" + "Subject\0Re: [PATCH] powerpc/powernv: hwmon driver for power values, fan rpm and temperature\0" + "Date\0Sun, 18 May 2014 23:38:17 +0530\0" "To\0Guenter Roeck <linux@roeck-us.net>\0" "Cc\0linuxppc-dev@lists.ozlabs.org" sbhat@linux.vnet.ibm.com @@ -10,322 +10,574 @@ " lm-sensors@lm-sensors.org\0" "\00:1\0" "b\0" - "T24gMDUvMTQvMjAxNCAxMDozOSBQTSwgR3VlbnRlciBSb2VjayB3cm90ZToKPiBPbiBXZWQsIE1h\n" - "eSAxNCwgMjAxNCBhdCAxMTozMTo1M0FNICswNTMwLCBOZWVsZXNoIEd1cHRhIHdyb3RlOgo+PiBU\n" - "aGlzIHBhdGNoIGFkZHMgYmFzaWMga2VybmVsIGVuYWJsZW1lbnQgZm9yIHJlYWRpbmcgcG93ZXIg\n" - "dmFsdWVzLCBmYW4KPj4gc3BlZWQgcnBtIGFuZCB0ZW1wZXJhdHVyZSB2YWx1ZXMgb24gcG93ZXJu\n" - "diBwbGF0Zm9ybXMgd2hpY2ggd2lsbAo+PiBiZSBleHBvcnRlZCB0byB1c2VyIHNwYWNlIHRocm91\n" - "Z2ggc3lzZnMgaW50ZXJmYWNlLgo+Pgo+PiBUZXN0IHJlc3VsdHM6Cj4+IC0tLS0tLS0tLS0tLS0K\n" - "Pj4gW3Jvb3RAdHVsMTYzcDEgfl0jIHNlbnNvcnMKPj4gaWJtcG93ZXJudi1pc2EtMDAwMAo+PiBB\n" - "ZGFwdGVyOiBJU0EgYWRhcHRlcgo+PiBmYW4xOiAgICAgICAgNTI5NCBSUE0gIChtaW4gPSAgICAw\n" - "IFJQTSkKPj4gZmFuMjogICAgICAgIDQ5NDUgUlBNICAobWluID0gICAgMCBSUE0pCj4+IGZhbjM6\n" - "ICAgICAgICA1ODMxIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+PiBmYW40OiAgICAgICAgNTIxMiBS\n" - "UE0gIChtaW4gPSAgICAwIFJQTSkKPj4gZmFuNTogICAgICAgICAgIDAgUlBNICAobWluID0gICAg\n" - "MCBSUE0pCj4+IGZhbjY6ICAgICAgICAgICAwIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+PiBmYW43\n" - "OiAgICAgICAgNzQ3MiBSUE0gIChtaW4gPSAgICAwIFJQTSkKPj4gZmFuODogICAgICAgIDc5MjAg\n" - "UlBNICAobWluID0gICAgMCBSUE0pCj4+IHRlbXAxOiAgICAgICAgKzM5LjDCsEMgIChoaWdoID0g\n" - "ICswLjDCsEMpCj4+IHBvd2VyMTogICAgICAxOTIuMDAgVwo+Pgo+PiBbcm9vdEB0dWwxNjNwMSB+\n" - "XSMKPj4gW3Jvb3RAdHVsMTYzcDEgfl0jIGxzIC9zeXMvZGV2aWNlcy9wbGF0Zm9ybS9pYm1wb3dl\n" - "cm52LjAvCj4+IGRyaXZlciAgICAgIGZhbjJfbWluICAgIGZhbjRfbWluICAgIGZhbjZfbWluICAg\n" - "IGZhbjhfbWluICAgbW9kYWxpYXMgICAgICB1ZXZlbnQKPj4gZmFuMV9mYXVsdCAgZmFuM19mYXVs\n" - "dCAgZmFuNV9mYXVsdCAgZmFuN19mYXVsdCAgaHdtb24gICAgICBuYW1lCj4+IGZhbjFfaW5wdXQg\n" - "IGZhbjNfaW5wdXQgIGZhbjVfaW5wdXQgIGZhbjdfaW5wdXQgIGluMV9mYXVsdCAgcG93ZXIxX2lu\n" - "cHV0Cj4+IGZhbjFfbWluICAgIGZhbjNfbWluICAgIGZhbjVfbWluICAgIGZhbjdfbWluICAgIGlu\n" - "Ml9mYXVsdCAgc3Vic3lzdGVtCj4+IGZhbjJfZmF1bHQgIGZhbjRfZmF1bHQgIGZhbjZfZmF1bHQg\n" - "IGZhbjhfZmF1bHQgIGluM19mYXVsdCAgdGVtcDFfaW5wdXQKPj4gZmFuMl9pbnB1dCAgZmFuNF9p\n" - "bnB1dCAgZmFuNl9pbnB1dCAgZmFuOF9pbnB1dCAgaW40X2ZhdWx0ICB0ZW1wMV9tYXgKPj4gW3Jv\n" - "b3RAdHVsMTYzcDEgfl0jCj4+IFtyb290QHR1bDE2M3AxIH5dIyBscyAvc3lzL2NsYXNzL2h3bW9u\n" - "L2h3bW9uMC9kZXZpY2UvCj4+IGRyaXZlciAgICAgIGZhbjJfbWluICAgIGZhbjRfbWluICAgIGZh\n" - "bjZfbWluICAgIGZhbjhfbWluICAgbW9kYWxpYXMgICAgICB1ZXZlbnQKPj4gZmFuMV9mYXVsdCAg\n" - "ZmFuM19mYXVsdCAgZmFuNV9mYXVsdCAgZmFuN19mYXVsdCAgaHdtb24gICAgICBuYW1lCj4+IGZh\n" - "bjFfaW5wdXQgIGZhbjNfaW5wdXQgIGZhbjVfaW5wdXQgIGZhbjdfaW5wdXQgIGluMV9mYXVsdCAg\n" - "cG93ZXIxX2lucHV0Cj4+IGZhbjFfbWluICAgIGZhbjNfbWluICAgIGZhbjVfbWluICAgIGZhbjdf\n" - "bWluICAgIGluMl9mYXVsdCAgc3Vic3lzdGVtCj4+IGZhbjJfZmF1bHQgIGZhbjRfZmF1bHQgIGZh\n" - "bjZfZmF1bHQgIGZhbjhfZmF1bHQgIGluM19mYXVsdCAgdGVtcDFfaW5wdXQKPj4gZmFuMl9pbnB1\n" - "dCAgZmFuNF9pbnB1dCAgZmFuNl9pbnB1dCAgZmFuOF9pbnB1dCAgaW40X2ZhdWx0ICB0ZW1wMV9t\n" - "YXgKPj4gW3Jvb3RAdHVsMTYzcDEgfl0jCj4+Cj4+IFNpZ25lZC1vZmYtYnk6IFNoaXZhcHJhc2Fk\n" - "IEcgQmhhdCA8c2JoYXRAbGludXgudm5ldC5pYm0uY29tPgo+PiBTaWduZWQtb2ZmLWJ5OiBOZWVs\n" - "ZXNoIEd1cHRhIDxuZWVsZWd1cEBsaW51eC52bmV0LmlibS5jb20+Cj4+IC0tLQo+PiAgIGRyaXZl\n" - "cnMvaHdtb24vS2NvbmZpZyAgICAgIHwgICAgOCArCj4+ICAgZHJpdmVycy9od21vbi9NYWtlZmls\n" - "ZSAgICAgfCAgICAxCj4+ICAgZHJpdmVycy9od21vbi9pYm1wb3dlcm52LmMgfCAgMzg2ICsrKysr\n" - "KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCj4+ICAgMyBmaWxlcyBjaGFu\n" - "Z2VkLCAzOTUgaW5zZXJ0aW9ucygrKQo+PiAgIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2h3\n" - "bW9uL2libXBvd2VybnYuYwo+Pgo+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmln\n" - "IGIvZHJpdmVycy9od21vbi9LY29uZmlnCj4+IGluZGV4IGJjMTk2ZjQuLjNlMzA4ZmEgMTAwNjQ0\n" - "Cj4+IC0tLSBhL2RyaXZlcnMvaHdtb24vS2NvbmZpZwo+PiArKysgYi9kcml2ZXJzL2h3bW9uL0tj\n" - "b25maWcKPj4gQEAgLTU1NCw2ICs1NTQsMTQgQEAgY29uZmlnIFNFTlNPUlNfSUJNUEVYCj4+ICAg\n" - "CSAgVGhpcyBkcml2ZXIgY2FuIGFsc28gYmUgYnVpbHQgYXMgYSBtb2R1bGUuICBJZiBzbywgdGhl\n" - "IG1vZHVsZQo+PiAgIAkgIHdpbGwgYmUgY2FsbGVkIGlibXBleC4KPj4gICAKPj4gK2NvbmZpZyBT\n" - "RU5TT1JTX0lCTVBPV0VSTlYKPj4gKwl0cmlzdGF0ZSAiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vu\n" - "c29ycyIKPj4gKwlkZXBlbmRzIG9uIFBQQ19QT1dFUk5WCj4+ICsJZGVmYXVsdCB5Cj4+ICsJaGVs\n" - "cAo+PiArCSAgSWYgeW91IHNheSB5ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIHRoZSB0ZW1w\n" - "ZXJhdHVyZS9mYW4vcG93ZXIKPj4gKwkgIHNlbnNvcnMgb24geW91ciBwbGF0Zm9ybS4KPj4gKwo+\n" - "PiAgIGNvbmZpZyBTRU5TT1JTX0lJT19IV01PTgo+PiAgIAl0cmlzdGF0ZSAiSHdtb24gZHJpdmVy\n" - "IHRoYXQgdXNlcyBjaGFubmVscyBzcGVjaWZpZWQgdmlhIGlpbyBtYXBzIgo+PiAgIAlkZXBlbmRz\n" - "IG9uIElJTwo+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9NYWtlZmlsZSBiL2RyaXZlcnMv\n" - "aHdtb24vTWFrZWZpbGUKPj4gaW5kZXggYzQ4Zjk4Ny4uMTk5YzQwMSAxMDA2NDQKPj4gLS0tIGEv\n" - "ZHJpdmVycy9od21vbi9NYWtlZmlsZQo+PiArKysgYi9kcml2ZXJzL2h3bW9uL01ha2VmaWxlCj4+\n" - "IEBAIC03MSw2ICs3MSw3IEBAIG9iai0kKENPTkZJR19TRU5TT1JTX1VMVFJBNDUpCSs9IHVsdHJh\n" - "NDVfZW52Lm8KPj4gICBvYmotJChDT05GSUdfU0VOU09SU19JNUtfQU1CKQkrPSBpNWtfYW1iLm8K\n" - "Pj4gICBvYmotJChDT05GSUdfU0VOU09SU19JQk1BRU0pCSs9IGlibWFlbS5vCj4+ICAgb2JqLSQo\n" - "Q09ORklHX1NFTlNPUlNfSUJNUEVYKQkrPSBpYm1wZXgubwo+PiArb2JqLSQoQ09ORklHX1NFTlNP\n" - "UlNfSUJNUE9XRVJOVikrPSBpYm1wb3dlcm52Lm8KPj4gICBvYmotJChDT05GSUdfU0VOU09SU19J\n" - "SU9fSFdNT04pICs9IGlpb19od21vbi5vCj4+ICAgb2JqLSQoQ09ORklHX1NFTlNPUlNfSU5BMjA5\n" - "KQkrPSBpbmEyMDkubwo+PiAgIG9iai0kKENPTkZJR19TRU5TT1JTX0lOQTJYWCkJKz0gaW5hMnh4\n" - "Lm8KPj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jIGIvZHJpdmVycy9o\n" - "d21vbi9pYm1wb3dlcm52LmMKPj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPj4gaW5kZXggMDAwMDAw\n" - "MC4uZTVjZmZjZQo+PiAtLS0gL2Rldi9udWxsCj4+ICsrKyBiL2RyaXZlcnMvaHdtb24vaWJtcG93\n" - "ZXJudi5jCj4+IEBAIC0wLDAgKzEsMzg2IEBACj4+ICsvKgo+PiArICogSUJNIFBvd2VyTlYgcGxh\n" - "dGZvcm0gc2Vuc29ycyBmb3IgdGVtcGVyYXR1cmUvZmFuL3Bvd2VyCj4+ICsgKiBDb3B5cmlnaHQg\n" - "KEMpIDIwMTQgSUJNCj4+ICsgKgo+PiArICogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7\n" - "IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkKPj4gKyAqIGl0IHVuZGVyIHRo\n" - "ZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5\n" - "Cj4+ICsgKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIgdmVyc2lvbiAyIG9m\n" - "IHRoZSBMaWNlbnNlLCBvcgo+PiArICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lv\n" - "bi4KPj4gKyAqCj4+ICsgKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUg\n" - "dGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKPj4gKyAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsg\n" - "d2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCj4+ICsgKiBNRVJDSEFOVEFCSUxJ\n" - "VFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCj4+ICsgKiBH\n" - "TlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgo+PiArICoKPj4gKyAq\n" - "IFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1Ymxp\n" - "YyBMaWNlbnNlCj4+ICsgKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbTsgaWYgbm90LCB3cml0ZSB0\n" - "byB0aGUgRnJlZSBTb2Z0d2FyZQo+PiArICogRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBs\n" - "YWNlLCBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgIDAyMTExLTEzMDcgIFVTQQo+IFBsZWFzZSBkcm9w\n" - "IHRoZSBGU0YgYWRkcmVzczsgaXQgY2FuIGNoYW5nZSwgYW5kIHdlIGRvbid0IHdhbnQgdG8gdXBk\n" - "YXRlIHRoZQo+IGRyaXZlciBlYWNoIHRpbWUgaXQgZG9lcy4KPgo+PiArICovCj4+ICsKPj4gKyNp\n" - "bmNsdWRlIDxsaW51eC9pbml0Lmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+Cj4+ICsj\n" - "aW5jbHVkZSA8bGludXgva2VybmVsLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvaHdtb24uaD4KPj4g\n" - "KyNpbmNsdWRlIDxsaW51eC9od21vbi1zeXNmcy5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L29mLmg+\n" - "Cj4+ICsjaW5jbHVkZSA8bGludXgvc2xhYi5oPgo+PiArCj4+ICsjaW5jbHVkZSA8bGludXgvcGxh\n" - "dGZvcm1fZGV2aWNlLmg+Cj4+ICsjaW5jbHVkZSA8YXNtL29wYWwuaD4KPj4gKyNpbmNsdWRlIDxs\n" - "aW51eC9lcnIuaD4KPj4gKwo+PiArI2RlZmluZSBEUlZOQU1FCQkiaWJtcG93ZXJudiIKPj4gKyNk\n" - "ZWZpbmUgTUFYX0FUVFJfTEVOCTMyCj4+ICsKPj4gKy8qIFNlbnNvciBzdWZmaXggbmFtZSBmcm9t\n" - "IERUICovCj4+ICsjZGVmaW5lIERUX0ZBVUxUX0FUVFJfU1VGRklYCQkiZmF1bHRlZCIKPj4gKyNk\n" - "ZWZpbmUgRFRfREFUQV9BVFRSX1NVRkZJWAkJImRhdGEiCj4+ICsjZGVmaW5lIERUX1RIUkVTSE9M\n" - "RF9BVFRSX1NVRkZJWAkidGhycyIKPj4gKwo+PiArLyogRW51bWVyYXRlcyBhbGwgdGhlIHNlbnNv\n" - "cnMgaW4gdGhlIFBPV0VSTlYgcGxhdGZvcm0gYW5kIGFsc28gaW5kZXggaW50bwo+PiArICogJ3N0\n" - "cnVjdCBzZW5zb3JfbmFtZScKPiBDb21tZW50IGNvZGluZyBzdHlsZSwgcGxlYXNlICh0aGlzIGlz\n" - "IG5vdCB0aGUgbmV0d29ya2luZyBzdWJzeXN0ZW0gOy0pCj4KPj4gKyAqLwo+PiArZW51bSBzZW5z\n" - "b3JzIHsKPj4gKwlGQU4sCj4+ICsJQU1CSUVOVF9URU1QLAo+PiArCVBPV0VSU1VQUExZLAo+PiAr\n" - "CVBPV0VSLAo+PiArCU1BWF9TRU5TT1JfVFlQRSwKPj4gK307Cj4+ICsKPj4gK3N0YXRpYyBzdHJ1\n" - "Y3Qgc2Vuc29yX25hbWUgewo+IGNvbnN0ID8KPgo+PiArCWNoYXIgKm5hbWU7Cj4+ICsJY2hhciAq\n" - "Y29tcGF0aWJsZTsKPj4gK30gc2Vuc29yX25hbWVzW10gPSB7Cj4+ICsJeyJmYW4iLCAiaWJtLG9w\n" - "YWwtc2Vuc29yLWNvb2xpbmctZmFuIn0sCj4+ICsJeyJ0ZW1wIiwgImlibSxvcGFsLXNlbnNvci1h\n" - "bWItdGVtcCJ9LAo+PiArCXsiaW4iLCAiaWJtLG9wYWwtc2Vuc29yLXBvd2VyLXN1cHBseSJ9LAo+\n" - "PiArCXsicG93ZXIiLCAiaWJtLG9wYWwtc2Vuc29yLXBvd2VyIn0KPj4gK307Cj4+ICsKPj4gK3N0\n" - "cnVjdCBwbGF0Zm9ybV9kYXRhIHsKPj4gKwlzdHJ1Y3QgZGV2aWNlICpod21vbl9kZXY7Cj4gTm90\n" - "IG5lZWRlZC4KPgo+PiArCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlIG5hbWVfYXR0cjsKPj4gKwlz\n" - "dHJ1Y3QgbGlzdF9oZWFkIGF0dHJfbGlzdDsKPj4gK307Cj4+ICsKPj4gK3N0cnVjdCBzZW5zb3Jf\n" - "ZGF0YSB7Cj4+ICsJdTMyIGlkOwo+PiArCWVudW0gc2Vuc29ycyBzdHlwZTsKPj4gKwljaGFyIG5h\n" - "bWVbTUFYX0FUVFJfTEVOXTsKPj4gKwlzdHJ1Y3Qgc2Vuc29yX2RldmljZV9hdHRyaWJ1dGUgc2Rf\n" - "YXR0cjsKPj4gKwlzdHJ1Y3QgbGlzdF9oZWFkIGxpc3Q7Cj4+ICt9Owo+PiArCj4+ICsvKiBQbGF0\n" - "Zm9ybSBkZXZpY2UgcmVwcmVzZW50aW5nIGFsbCB0aGUgaWJtcG93ZXJudiBzZW5zb3JzICovCj4+\n" - "ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldmljZTsKPj4gKwo+PiArc3RhdGlj\n" - "IHZvaWQgZ2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0IGNoYXIgKm5hbWUsIHUzMiAqaW5kZXgs\n" - "IGNoYXIgKmF0dHIpCj4+ICt7Cj4+ICsJY2hhciAqaGFzaF9wb3MgPSBzdHJjaHIobmFtZSwgJyMn\n" - "KTsKPj4gKwljaGFyICpkYXNoX3BvczsKPj4gKwl1MzIgY29weV9sZW47Cj4+ICsJY2hhciBidWZb\n" - "OF07Cj4+ICsKPj4gKwltZW1zZXQoYnVmLCAwLCBzaXplb2YoYnVmKSk7Cj4+ICsJKmluZGV4ID0g\n" - "MDsKPj4gKwkqYXR0ciA9ICdcMCc7Cj4+ICsKPj4gKwlpZiAoaGFzaF9wb3MpIHsKPj4gKwkJZGFz\n" - "aF9wb3MgPSBzdHJjaHIoaGFzaF9wb3MsICctJyk7Cj4+ICsJCWlmIChkYXNoX3Bvcykgewo+PiAr\n" - "CQkJY29weV9sZW4gPSBkYXNoX3BvcyAtIGhhc2hfcG9zIC0gMTsKPj4gKwkJCWlmIChjb3B5X2xl\n" - "biA8IHNpemVvZihidWYpKSB7Cj4+ICsJCQkJc3RybmNweShidWYsIGhhc2hfcG9zICsgMSwgY29w\n" - "eV9sZW4pOwo+PiArCQkJCXNzY2FuZihidWYsICIlZCIsIGluZGV4KTsKPj4gKwkJCX0KPj4gKwo+\n" - "PiArCQkJc3RybmNweShhdHRyLCBkYXNoX3BvcyArIDEsIE1BWF9BVFRSX0xFTik7Cj4+ICsJCX0K\n" - "Pj4gKwl9Cj4+ICt9Cj4+ICsKPj4gKy8qCj4+ICsgKiBUaGlzIGZ1bmN0aW9uIHRyYW5zbGF0ZXMg\n" - "dGhlIERUIG5vZGUgbmFtZSBpbnRvIHRoZSAnaHdtb24nIGF0dHJpYnV0ZSBuYW1lLgo+PiArICog\n" - "SUJNUE9XRVJOViBkZXZpY2Ugbm9kZSBhcHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIGFt\n" - "Yi10ZW1wIzEtdGhycyBldGMuCj4+ICsgKiB3aGljaCBuZWVkIHRvIGJlIG1hcHBlZCBhcyBmYW4y\n" - "X2lucHV0LCB0ZW1wMV9tYXggcmVzcGVjdGl2ZWx5IGJlZm9yZQo+PiArICogcG9wdWxhdGluZyB0\n" - "aGVtIGluc2lkZSBod21vbiBkZXZpY2UgY2xhc3MuLgo+PiArICovCj4+ICtzdGF0aWMgaW50IGNy\n" - "ZWF0ZV9od21vbl9hdHRyX25hbWUoZW51bSBzZW5zb3JzIHN0eXBlLCBjb25zdCBjaGFyICpub2Rl\n" - "X25hbWUsCj4+ICsJCWNoYXIgKmh3bW9uX2F0dHJfbmFtZSkKPiBQbGVhc2UgZm9sbG93IENvZGlu\n" - "Z1N0eWxlIGZvciBjb250aW51YXRpb24gbGluZSBhbGlnbm1lbnQuCj4KPj4gK3sKPj4gKwljaGFy\n" - "IGF0dHJfc3VmZml4W01BWF9BVFRSX0xFTl07Cj4+ICsJY2hhciAqYXR0cl9uYW1lOwo+PiArCXUz\n" - "MiBpbmRleDsKPj4gKwo+PiArCWdldF9zZW5zb3JfaW5kZXhfYXR0cihub2RlX25hbWUsICZpbmRl\n" - "eCwgYXR0cl9zdWZmaXgpOwo+PiArCWlmICghaW5kZXggfHwgIXN0cmxlbihhdHRyX3N1ZmZpeCkp\n" - "IHsKPj4gKwkJcHJfaW5mbygiJXM6IFNlbnNvciBkZXZpY2Ugbm9kZSBuYW1lIGlzIGludmFsaWQs\n" - "IG5hbWU6ICVzXG4iLAo+PiArCQkJCV9fZnVuY19fLCBub2RlX25hbWUpOwo+PiArCQlyZXR1cm4g\n" - "LUVJTlZBTDsKPj4gKwl9Cj4+ICsKPj4gKwlpZiAoIXN0cmNtcChhdHRyX3N1ZmZpeCwgRFRfRkFV\n" - "TFRfQVRUUl9TVUZGSVgpKQo+PiArCQlhdHRyX25hbWUgPSAiZmF1bHQiOwo+PiArCWVsc2UgaWYo\n" - "IXN0cmNtcChhdHRyX3N1ZmZpeCwgRFRfREFUQV9BVFRSX1NVRkZJWCkpCj4+ICsJCWF0dHJfbmFt\n" - "ZSA9ICJpbnB1dCI7Cj4+ICsJZWxzZSBpZiAoIXN0cmNtcChhdHRyX3N1ZmZpeCwgRFRfVEhSRVNI\n" - "T0xEX0FUVFJfU1VGRklYKSkgewo+PiArCQlpZiAoc3R5cGUgPT0gQU1CSUVOVF9URU1QKQo+PiAr\n" - "CQkJYXR0cl9uYW1lID0gIm1heCI7Cj4+ICsJCWVsc2UgaWYgKHN0eXBlID09IEZBTikKPj4gKwkJ\n" - "CWF0dHJfbmFtZSA9ICJtaW4iOwo+PiArCQllbHNlCj4+ICsJCQlyZXR1cm4gLUVOT0VOVDsKPj4g\n" - "Kwl9IGVsc2UKPj4gKwkJcmV0dXJuIC1FTk9FTlQ7Cj4+ICsKPj4gKwlzbnByaW50Zihod21vbl9h\n" - "dHRyX25hbWUsIE1BWF9BVFRSX0xFTiwgIiVzJWRfJXMiLAo+PiArCQkJc2Vuc29yX25hbWVzW3N0\n" - "eXBlXS5uYW1lLCBpbmRleCwgYXR0cl9uYW1lKTsKPj4gKwlyZXR1cm4gMDsKPj4gK30KPj4gKwo+\n" - "PiArc3RhdGljIHNzaXplX3Qgc2hvd19zZW5zb3Ioc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3Qg\n" - "ZGV2aWNlX2F0dHJpYnV0ZSAqZGV2YXR0ciwKPj4gKwkJY2hhciAqYnVmKQo+PiArewo+PiArCXN0\n" - "cnVjdCBzZW5zb3JfZGV2aWNlX2F0dHJpYnV0ZSAqc2RfYXR0ciA9IHRvX3NlbnNvcl9kZXZfYXR0\n" - "cihkZXZhdHRyKTsKPj4gKwlzdHJ1Y3Qgc2Vuc29yX2RhdGEgKnNkYXRhID0gY29udGFpbmVyX29m\n" - "KHNkX2F0dHIsIHN0cnVjdCBzZW5zb3JfZGF0YSwKPj4gKwkJCXNkX2F0dHIpOwo+PiArCWludCBl\n" - "cnI7Cj4+ICsJdTMyIHg7Cj4+ICsKPj4gKwllcnIgPSBvcGFsX2dldF9zZW5zb3JfZGF0YShzZGF0\n" - "YS0+aWQsICZ4KTsKPj4gKwlpZiAoZXJyKSB7Cj4+ICsJCXByX2VycigiJXM6IEZhaWxlZCB0byBn\n" - "ZXQgb3BhbCBzZW5zb3IgZGF0YVxuIiwgX19mdW5jX18pOwo+PiArCQl4ID0gLTE7Cj4gVW51c3Vh\n" - "bC4gV2h5IG5vdCByZXBvcnQgdGhlIGVycm9yIHRvIHVzZXIgc3BhY2UgPwo+IFJlcG9ydGluZyA8\n" - "bWF4dWludD4gb24gZXJyb3IgZG9lc24ndCBzZWVtIHRvIGJlIHZlcnkgdXNlZnVsLgo+Cj4+ICsJ\n" - "fQo+PiArCj4+ICsJLyogQ29udmVydCB0ZW1wZXJhdHVyZSB0byBtaWxsaS1kZWdyZWVzICovCj4+\n" - "ICsJaWYgKHNkYXRhLT5zdHlwZSA9PSBBTUJJRU5UX1RFTVAgJiYgeCA+IDApCj4+ICsJCXggKj0g\n" - "MTAwMDsKPj4gKwkvKiBDb252ZXJ0IHBvd2VyIHRvIG1pY3JvLXdhdHRzICovCj4+ICsJZWxzZSBp\n" - "ZiAoc2RhdGEtPnN0eXBlID09IFBPV0VSICYmIHggPiAwKQo+PiArCQl4ICo9IDEwMDAwMDA7Cj4+\n" - "ICsKPiBJcyB0aGVyZSBhbiBvdmVyZmxvdyBjb25jZXJuID8gR3Vlc3Mgbm90IC4uLiBvdmVyZmxv\n" - "dyBoYXBwZW5zIGF0IH4xN0tXLgo+IEp1c3Qgd29uZGVyaW5nLgo+Cj4+ICsJcmV0dXJuIHNwcmlu\n" - "dGYoYnVmLCAiJWRcbiIsIHgpOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgdm9pZCByZW1vdmVfZGV2\n" - "aWNlX2F0dHJzKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4+ICt7Cj4+ICsJc3RydWN0\n" - "IHBsYXRmb3JtX2RhdGEgKnBkYXRhID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7Cj4+ICsJ\n" - "c3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRldjsKPj4gKwlzdHJ1Y3Qgc2Vuc29yX2RhdGEg\n" - "KnMsICpuZXh0Owo+PiArCj4+ICsJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKHMsIG5leHQsICZw\n" - "ZGF0YS0+YXR0cl9saXN0LCBsaXN0KSB7Cj4+ICsJCWRldmljZV9yZW1vdmVfZmlsZShkZXYsICZz\n" - "LT5zZF9hdHRyLmRldl9hdHRyKTsKPj4gKwkJbGlzdF9kZWwoJnMtPmxpc3QpOwo+IFRoaXMgaXMg\n" - "dW5uZWNlc3Nhcnkgc2luY2UgeW91IGFsd2F5cyByZW1vdmUgdGhlIGVudGlyZSBsaXN0IGFueXdh\n" - "eS4KPiBBY3R1YWxseSwgSSBkb24ndCB0aGluayB5b3UgbmVlZCB0aGUgbGlzdCBpbiB0aGUgZmly\n" - "c3QgcGxhY2UuCj4gWW91IG9ubHkgdXNlIGl0IHRvIGRlbGV0ZSBlbnRyaWVzLCBidXQgdGhhdCBj\n" - "YW4gYmUgaGFuZGxlZCBhdXRvbWF0aWNhbGx5Cj4gYnkgdGhlIGluZnJhc3RydWN0dXJlLiBBbGwg\n" - "eW91IHJlYWxseSBuZWVkIGlzIGFuIGFycmF5IHBvaW50aW5nIHRvIHRoZSBkZXZpY2UKPiBhdHRy\n" - "aWJ1dGVzIHNvIHlvdSBjYW4gY3JlYXRlIGFsbCBhdHRyaWJ1dGUgZmlsZXMgd2l0aCBhIHNpbmds\n" - "ZSBvcGVyYXRpb24uCj4KPj4gKwkJa2ZyZWUocyk7Cj4+ICsJfQo+PiArfQo+PiArCj4+ICsvKgo+\n" - "PiArICogSXRlcmF0ZSB0aHJvdWdoIHRoZSBkZXZpY2UgdHJlZSBhbmQgZm9yIGVhY2ggY2hpbGQg\n" - "b2Ygc2Vuc29yIG5vZGUsIGNyZWF0ZQo+PiArICogYSBzeXNmcyBhdHRyaWJ1dGUgZmlsZSwgdGhl\n" - "IGZpbGUgaXMgbmFtZWQgYnkgdHJhbnNsYXRpbmcgdGhlIERUIG5vZGUgbmFtZQo+PiArICogdG8g\n" - "dGhlIG5hbWUgcmVxdWlyZWQgYnkgdGhlIGhpZ2hlciAnaHdtb24nIGRyaXZlciBsaWtlIGZhbjFf\n" - "aW5wdXQsIHRlbXAxX21heAo+PiArICogZXRjLi4KPj4gKyAqLwo+PiArc3RhdGljIGludCBjcmVh\n" - "dGVfZGV2aWNlX2F0dHJzKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4+ICt7Cj4+ICsJ\n" - "c3RydWN0IHBsYXRmb3JtX2RhdGEgKnBkYXRhID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7\n" - "Cj4+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRldjsKPj4gKwlzdHJ1Y3QgZGV2aWNl\n" - "X25vZGUgKm9wYWwsICpucDsKPj4gKwlzdHJ1Y3Qgc2Vuc29yX2RhdGEgKnNkYXRhOwo+PiArCWNv\n" - "bnN0IHUzMiAqc2Vuc29yX2lkOwo+PiArCWVudW0gc2Vuc29ycyBzdHlwZTsKPj4gKwlpbnQgZXJy\n" - "Owo+PiArCj4+ICsJb3BhbCA9IG9mX2ZpbmRfbm9kZV9ieV9wYXRoKCIvaWJtLG9wYWwvc2Vuc29y\n" - "cyIpOwo+PiArICAgICAgICBpZiAoIW9wYWwpIHsKPj4gKwkJcHJfZXJyKCIlczogT3BhbCAnc2Vu\n" - "c29ycycgbm9kZSBub3QgZm91bmRcbiIsIF9fZnVuY19fKTsKPj4gKwkJZXJyID0gLUVOWElPOwo+\n" - "IAlFTk9ERVYgPwo+Cj4+ICsJCWdvdG8gZXhpdDsKPiAJSSB3b3VsZCBzdWdnZXN0IHRvIHNpbXBs\n" - "eSByZXR1cm4gaGVyZS4KPgo+PiArICAgICAgICB9Cj4+ICsKPj4gKwlmb3JfZWFjaF9jaGlsZF9v\n" - "Zl9ub2RlKG9wYWwsIG5wKSB7Cj4+ICsgICAgICAgICAgICAgICAgaWYgKG5wLT5uYW1lID09IE5V\n" - "TEwpCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKPj4gKwo+PiArCQlmb3Ig\n" - "KHN0eXBlID0gMDsgc3R5cGUgPCBNQVhfU0VOU09SX1RZUEU7IHN0eXBlKyspCj4+ICsJCQlpZiAo\n" - "b2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCj4+ICsJCQkJCXNlbnNvcl9uYW1lc1tzdHlwZV0u\n" - "Y29tcGF0aWJsZSkpCj4+ICsJCQkJYnJlYWs7Cj4+ICsKPj4gKwkJaWYgKHN0eXBlID09IE1BWF9T\n" - "RU5TT1JfVFlQRSkKPj4gKwkJCWNvbnRpbnVlOwo+PiArCj4+ICsJCXNlbnNvcl9pZCA9IG9mX2dl\n" - "dF9wcm9wZXJ0eShucCwgInNlbnNvci1pZCIsIE5VTEwpOwo+PiArCQlpZiAoIXNlbnNvcl9pZCkg\n" - "ewo+PiArCQkJcHJfaW5mbygiJXM6ICVzIGRvZXNuJ3QgaGF2ZSBzZW5zb3ItaWRcbiIsIF9fZnVu\n" - "Y19fLAo+PiArCQkJCQlucC0+bmFtZSk7Cj4+ICsJCQljb250aW51ZTsKPj4gKwkJfQo+PiArCj4+\n" - "ICsJCXNkYXRhID0ga3phbGxvYyhzaXplb2YoKnNkYXRhKSwgR0ZQX0tFUk5FTCk7Cj4gQ2FuIHlv\n" - "dSB1c2UgZGV2bV9remFsbG9jKCkgPwo+Cj4+ICsJCWlmICghc2RhdGEpIHsKPj4gKwkJCXByX2Vy\n" - "cigiJXM6IEZhaWxlZCB0byBhbGxvY2F0ZSBtZW1vcnkgZm9yIHNlbnNvcl9kYXRhIiwKPj4gKwkJ\n" - "CQkJX19mdW5jX18pOwo+PiArCQkJZXJyID0gLUVOT01FTTsKPj4gKwkJCWdvdG8gZXhpdF9wdXRf\n" - "bm9kZTsKPj4gKwkJfQo+PiArCj4+ICsJCXNkYXRhLT5pZCA9ICpzZW5zb3JfaWQ7Cj4+ICsJCXNk\n" - "YXRhLT5zdHlwZSA9IHN0eXBlOwo+PiArCQllcnIgPSBjcmVhdGVfaHdtb25fYXR0cl9uYW1lKHN0\n" - "eXBlLCBucC0+bmFtZSwgc2RhdGEtPm5hbWUpOwo+PiArCQlpZiAoZXJyKSB7Cj4+ICsJCQlwcl9l\n" - "cnIoIiVzOiBGYWlsZWQgdG8gY3JlYXRlIHRoZSBod21vbiBhdHRyaWJ1dGUgbmFtZVxuIiwKPj4g\n" - "KwkJCQkJX19mdW5jX18pOwo+IGNyZWF0ZV9od21vbl9hdHRyX25hbWUoKSAoc29tZXRpbWVzKSBh\n" - "bHJlYWR5IGNyZWF0ZXMgYW4gZXJyb3IgbWVzc2FnZS4KPiBXb3VsZCBiZSBuaWNlIGlmIHlvdSBj\n" - "YW4gYXZvaWQgZHVwbGljYXRlIGVycm9yIG1lc3NhZ2VzLgo+Cj4+ICsJCQlnb3RvIGV4aXRfZnJl\n" - "ZV9zZGF0YTsKPj4gKwkJfQo+PiArCj4+ICsJCXN5c2ZzX2F0dHJfaW5pdCgmc2RhdGEtPnNkX2F0\n" - "dHIuZGV2X2F0dHIuYXR0cik7Cj4+ICsJCXNkYXRhLT5zZF9hdHRyLmRldl9hdHRyLmF0dHIubmFt\n" - "ZSA9IHNkYXRhLT5uYW1lOwo+PiArCQlzZGF0YS0+c2RfYXR0ci5kZXZfYXR0ci5hdHRyLm1vZGUg\n" - "PSBTX0lSVUdPOwo+PiArCQlzZGF0YS0+c2RfYXR0ci5kZXZfYXR0ci5zaG93ID0gc2hvd19zZW5z\n" - "b3I7Cj4gU2luY2UgeW91IGFyZSBub3QgdXNpbmcgdGhlIGluZGV4IHZhbHVlIGZyb20gc2Vuc29y\n" - "X2RldmljZV9hdHRyaWJ1dGUsCj4gYnV0IHVzZSB5b3VyIG93biAnaWQnIHZhcmlhYmxlIGluc3Rl\n" - "YWQsIHlvdSBkb24ndCBuZWVkIHNlbnNvcl9kZXZpY2VfYXR0cmlidXRlCj4gYnV0IGNhbiB1c2Ug\n" - "ZGV2aWNlX2F0dHJpYnV0ZSBpbnN0ZWFkIChvciBkcm9wICdpZCcgYW5kIHVzZQo+IHNkX2F0dHIu\n" - "aW5kZXggaW5zdGVhZCkuCj4KPj4gKwo+PiArCQkvKiBDcmVhdGUgc3lzZnMgYXR0cmlidXRlIGZp\n" - "bGUgKi8KPj4gKwkJZXJyID0gZGV2aWNlX2NyZWF0ZV9maWxlKGRldiwgJnNkYXRhLT5zZF9hdHRy\n" - "LmRldl9hdHRyKTsKPj4gKwkJaWYgKGVycikKPj4gKwkJCWdvdG8gZXhpdF9mcmVlX3NkYXRhOwo+\n" - "PiArCj4gUGxlYXNlIGRvbid0IGNyZWF0ZSB0aGUgYXR0cmlidXRlIGZpbGVzIGhlcmUgYnV0IGp1\n" - "c3QgYSBsaXN0IG9mIGF0dHJpYnV0ZXMKPiBpbnN0ZWFkLiBTZWUgYmVsb3cgZm9yIG1vcmUgZGV0\n" - "YWlscy4KPgo+PiArCQlsaXN0X2FkZF90YWlsKCZzZGF0YS0+bGlzdCwgJnBkYXRhLT5hdHRyX2xp\n" - "c3QpOwo+PiArCX0KPj4gKwo+PiArCW9mX25vZGVfcHV0KG9wYWwpOwo+PiArCXJldHVybiAwOwo+\n" - "PiArCj4+ICtleGl0X2ZyZWVfc2RhdGE6Cj4+ICsJa2ZyZWUoc2RhdGEpOwo+PiArZXhpdF9wdXRf\n" - "bm9kZToKPj4gKwlvZl9ub2RlX3B1dChvcGFsKTsKPj4gKwlyZW1vdmVfZGV2aWNlX2F0dHJzKHBk\n" - "ZXYpOwo+PiArZXhpdDoKPj4gKwlyZXR1cm4gZXJyOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgc3Np\n" - "emVfdCBzaG93X25hbWUoc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgZGV2aWNlX2F0dHJpYnV0\n" - "ZSAqZGV2YXR0ciwKPj4gKwkJY2hhciAqYnVmKQo+PiArewo+PiArCXN0cnVjdCBwbGF0Zm9ybV9k\n" - "ZXZpY2UgKnBkZXYgPSB0b19wbGF0Zm9ybV9kZXZpY2UoZGV2KTsKPj4gKwlyZXR1cm4gc3ByaW50\n" - "ZihidWYsICIlc1xuIiwgcGRldi0+bmFtZSk7Cj4+ICt9Cj4gTm90IG5lY2Vzc2FyeTsgc2VlIGJl\n" - "bG93Lgo+Cj4+ICsKPj4gK3N0YXRpYyBpbnQgaWJtcG93ZXJudl9wcm9iZShzdHJ1Y3QgcGxhdGZv\n" - "cm1fZGV2aWNlICpwZGV2KQo+PiArewo+PiArCXN0cnVjdCBkZXZpY2UgKmRldiA9ICZwZGV2LT5k\n" - "ZXY7Cj4+ICsJc3RydWN0IHBsYXRmb3JtX2RhdGEgKnBkYXRhOwo+PiArCWludCBlcnI7Cj4+ICsK\n" - "Pj4gKwlwZGF0YSA9IGRldm1fa3phbGxvYyhkZXYsIHNpemVvZigqcGRhdGEpLCBHRlBfS0VSTkVM\n" - "KTsKPj4gKwlpZiAoIXBkYXRhKSB7Cj4+ICsJCWVyciA9IC1FTk9NRU07Cj4+ICsJCWdvdG8gZXhp\n" - "dDsKPj4gKwl9Cj4+ICsKPj4gKwlJTklUX0xJU1RfSEVBRCgmcGRhdGEtPmF0dHJfbGlzdCk7Cj4+\n" - "ICsJcGxhdGZvcm1fc2V0X2RydmRhdGEocGRldiwgcGRhdGEpOwo+PiArCj4+ICsJLyogQ3JlYXRl\n" - "IHBsYXRmb3JtIGRldmljZSAnbmFtZScgYXR0cmlidXRlICovCj4+ICsJc3lzZnNfYXR0cl9pbml0\n" - "KCZwZGF0YS0+bmFtZV9hdHRyLmF0dHIpOwo+PiArCXBkYXRhLT5uYW1lX2F0dHIuYXR0ci5uYW1l\n" - "ID0gIm5hbWUiOwo+PiArCXBkYXRhLT5uYW1lX2F0dHIuYXR0ci5tb2RlID0gU19JUlVHTzsKPj4g\n" - "KwlwZGF0YS0+bmFtZV9hdHRyLnNob3cgPSBzaG93X25hbWU7Cj4+ICsJZXJyID0gZGV2aWNlX2Ny\n" - "ZWF0ZV9maWxlKGRldiwgJnBkYXRhLT5uYW1lX2F0dHIpOwo+IFlvdSBkb24ndCBuZWVkIHRvIGNy\n" - "ZWF0ZSBhIG5hbWUgYXR0cmlidXRlLgo+IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhf\n" - "Z3JvdXBzIGRvZXMgaXQgZm9yIHlvdSAoZnJvbSB0aGUgc2Vjb25kCj4gYXJndW1lbnQpLgo+Cj4+\n" - "ICsJaWYgKGVycikKPj4gKwkJZ290byBleGl0Owo+PiArCj4+ICsJLyogQ3JlYXRlIHN5c2ZzIGF0\n" - "dHJpYnV0ZSBmaWxlIGZvciBlYWNoIHNlbnNvciBmb3VuZCBpbiB0aGUgRFQgKi8KPj4gKwllcnIg\n" - "PSBjcmVhdGVfZGV2aWNlX2F0dHJzKHBkZXYpOwo+IFRoYXQgZGVmZWF0cyB0aGUgcHVycG9zZSBv\n" - "ZiB1c2luZyBkZXZtX2h3bW9uX2RldmljZV9yZWdpc3Rlcl93aXRoX2dyb3Vwcy4KPiBUaGUgaWRl\n" - "YSBoZXJlIGlzIHRvIGJ1aWxkIGEgbGlzdCBvZiBhdHRyaWJ1dGVzLCB3aGljaCB5b3UgY2FuIGRv\n" - "IGluCj4gY3JlYXRlX2RldmljZV9hdHRycygpLCBidXQgbm90IGNyZWF0ZSB0aGUgYWN0dWFsIGRl\n" - "dmljZSBlbnRyaWVzLgo+IFRoZW4gYWxzbyBjcmVhdGUgYW4gYXR0cmlidXRlX2dyb3VwIGFzIHdl\n" - "bGwgYXMgYSBsaXN0IG9mIGdyb3VwcywKPiBhbmQgcGFzcyB0aGF0IGFzIGxhc3QgYXJndW1lbnQg\n" - "dG8gZGV2bV9od21vbl9kZXZpY2VfcmVnaXN0ZXJfd2l0aF9ncm91cHMoKS4KPgo+IGRyaXZlcnMv\n" - "aHdtb24vcG1idXMvcG1idXNfY29yZS5jIGRvZXMgc29tZXRoaW5nIHNpbWlsYXI7IG1heWJlIHlv\n" - "dSBjYW4KPiB1c2UgYSBzaW1pbGFyIGFwcHJvYWNoLgo+Cj4gV2l0aCB0aGF0LCB5b3UgYWxzbyBk\n" - "b24ndCBuZWVkIHRoZSByZW1vdmUgZnVuY3Rpb25zLCBzaW5jZSB0aGUgaHdtb24KPiBzdWJzeXN0\n" - "ZW0gd2lsbCBhdXRvLXJlbW92ZSB0aGUgYXR0cmlidXRlcy4gSWYgeW91IGRvIGl0IGNvcnJlY3Rs\n" - "eQo+IChpZSB1c2UgZGV2bV9remFsbG9jKCkgZm9yIGFsbG9jYXRpbmcgbWVtb3J5KSB5b3Ugc2hv\n" - "dWxkIG5vdCBuZWVkIGEKPiByZW1vdmUgZnVuY3Rpb24gYXQgYWxsLgo+Cj4+ICsJaWYgKGVycikg\n" - "ewo+PiArCQlwcl9lcnIoIiVzOiBGYWlsZWQgdG8gY3JlYXRlIHRoZSBkZXZpY2UgYXR0cmlidXRl\n" - "c1xuIiwKPj4gKwkJCQlfX2Z1bmNfXyk7Cj4+ICsJCWdvdG8gZXhpdF9yZW1vdmVfbmFtZTsKPj4g\n" - "Kwl9Cj4+ICsKPj4gKwkvKiBGaW5hbGx5LCByZWdpc3RlciB3aXRoIGh3bW9uICovCj4+ICsJcGRh\n" - "dGEtPmh3bW9uX2RldiA9IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhfZ3JvdXBzKGRl\n" - "diwgRFJWTkFNRSwKPj4gKwkJCXBkYXRhLCBOVUxMKTsKPj4gKwlpZiAoSVNfRVJSKHBkYXRhLT5o\n" - "d21vbl9kZXYpKSB7Cj4+ICsJCWVyciA9IFBUUl9FUlIocGRhdGEtPmh3bW9uX2Rldik7Cj4+ICsJ\n" - "CWdvdG8gZXhpdF9yZW1vdmVfZGV2YXR0cnM7Cj4+ICsJfQo+PiArCj4+ICsJcmV0dXJuIDA7Cj4+\n" - "ICsKPj4gK2V4aXRfcmVtb3ZlX2RldmF0dHJzOgo+PiArCXJlbW92ZV9kZXZpY2VfYXR0cnMocGRl\n" - "dik7Cj4+ICtleGl0X3JlbW92ZV9uYW1lOgo+PiArCWRldmljZV9yZW1vdmVfZmlsZShkZXYsICZw\n" - "ZGF0YS0+bmFtZV9hdHRyKTsKPj4gK2V4aXQ6Cj4+ICsJcmV0dXJuIGVycjsKPiBJZiB5b3UgZG8g\n" - "aXQgcmlnaHQgeW91IHNob3VsZCBiZSBhYmxlIHRvIHJlZHVjZSB0aGlzIHRvIHNvbWV0aGluZyBs\n" - "aWtlCj4KPiAJaHdtb25fZGV2ID0gZGV2bV9od21vbl9kZXZpY2VfcmVnaXN0ZXJfd2l0aF9ncm91\n" - "cHMoZGV2LCBEUlZOQU1FLCBwZGF0YSwKPiAJCQkJCQkJICAgcGRhdGEtPmF0dHJfZ3JvdXBzKTsK\n" - "PiAJcmV0dXJuIFBUUl9FUlJfT1JfWkVSTyhod21vbl9kZXYpOwo+Cj4gLi4uCj4KPj4gK30KPj4g\n" - "Kwo+PiArc3RhdGljIGludCBpYm1wb3dlcm52X3JlbW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNl\n" - "ICpwZGV2KQo+PiArewo+PiArCXN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YSA9IHBsYXRmb3Jt\n" - "X2dldF9kcnZkYXRhKHBkZXYpOwo+PiArCXN0cnVjdCBkZXZpY2UgKmRldiA9ICZwZGV2LT5kZXY7\n" - "Cj4+ICsKPj4gKwlyZW1vdmVfZGV2aWNlX2F0dHJzKHBkZXYpOwo+PiArCWRldmljZV9yZW1vdmVf\n" - "ZmlsZShkZXYsICZwZGF0YS0+bmFtZV9hdHRyKTsKPj4gKwo+PiArCXJldHVybiAwOwo+PiArfQo+\n" - "IC4uLiBhbmQgeW91IHNob3VsZCBiZSBhYmxlIHRvIHJlbW92ZSB0aGlzIGVudGlyZSBmdW5jdGlv\n" - "bi4KPgo+PiArCj4+ICsKPiBObyBkb3VibGUgZW1wdHkgbGluZXMgcGxlYXNlLgo+Cj4+ICtzdGF0\n" - "aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBpYm1wb3dlcm52X2RyaXZlciA9IHsKPj4gKwkuZHJp\n" - "dmVyID0gewo+PiArCQkub3duZXIgPSBUSElTX01PRFVMRSwKPj4gKwkJLm5hbWUgPSBEUlZOQU1F\n" - "LAo+PiArCX0sCj4+ICsJLnByb2JlID0gaWJtcG93ZXJudl9wcm9iZSwKPj4gKwkucmVtb3ZlID0g\n" - "aWJtcG93ZXJudl9yZW1vdmUsCj4+ICt9Owo+PiArCj4+ICsKPiBFeGNlc3NpdmUgZW1wdHkgbGlu\n" - "ZXMuCj4KPj4gK3N0YXRpYyBpbnQgX19pbml0IGlibXBvd2VybnZfaW5pdCh2b2lkKQo+PiArewo+\n" - "PiArCWludCBlcnI7Cj4+ICsKPj4gKwo+IEV4Y2Vzc2l2ZSBlbXB0eSBsaW5lcy4KPgo+PiArCWVy\n" - "ciA9IHBsYXRmb3JtX2RyaXZlcl9yZWdpc3RlcigmaWJtcG93ZXJudl9kcml2ZXIpOwo+PiArCWlm\n" - "IChlcnIpCj4+ICsJCWdvdG8gZXhpdDsKPiBTb21ldGltZXMgeW91IGNyZWF0ZSBhbiBlcnJvciBt\n" - "ZXNzYWdlLCBzb21ldGltZXMgbm90LiBJJ2QgcHJlZmVyIG5vIGVycm9yCj4gbWVzc2FnZSB0byBz\n" - "dGFydCB3aXRoICh0aGUgbW9kdWxlIGxvYWRlciB3aWxsIGNyZWF0ZSBvbmUgYW55d2F5KSwgYnV0\n" - "Cj4gYXQgbGVhc3QgcGxlYXNlIGJlIGNvbnNpc3RlbnQuCj4KPj4gKwo+PiArCj4gRXhjZXNzaXZl\n" - "IGVtcHR5IGxpbmVzLgo+Cj4+ICsJcGRldmljZSA9IHBsYXRmb3JtX2RldmljZV9hbGxvYyhEUlZO\n" - "QU1FLCAwKTsKPj4gKwlpZiAoIXBkZXZpY2UpIHsKPj4gKwkJcHJfZXJyKCIlczogRGV2aWNlIGFs\n" - "bG9jYXRpb24gZmFpbGVkXG4iLCBfX2Z1bmNfXyk7Cj4+ICsJCWVyciA9IC1FTk9NRU07Cj4+ICsJ\n" - "CWdvdG8gZXhpdF9kcml2ZXJfdW5yZWc7Cj4+ICsJfQo+PiArCj4+ICsJZXJyID0gcGxhdGZvcm1f\n" - "ZGV2aWNlX2FkZChwZGV2aWNlKTsKPj4gKwlpZiAoZXJyKSB7Cj4+ICsJCXByX2VycigiJXM6IERl\n" - "dmljZSBhZGRpdGlvbiBmYWlsZWQgKCVkKVxuIiwgX19mdW5jX18sIGVycik7Cj4+ICsJCWdvdG8g\n" - "ZXhpdF9kZXZpY2VfcHV0Owo+PiArCX0KPj4gKwo+IENhbiB5b3UgdXNlIHBsYXRmb3JtX2RyaXZl\n" - "cl9wcm9iZSgpIGhlcmUgPwo+Cj4+ICsJcmV0dXJuIDA7Cj4+ICsKPj4gK2V4aXRfZGV2aWNlX3B1\n" - "dDoKPj4gKwlwbGF0Zm9ybV9kZXZpY2VfcHV0KHBkZXZpY2UpOwo+PiArZXhpdF9kcml2ZXJfdW5y\n" - "ZWc6Cj4+ICsJcGxhdGZvcm1fZHJpdmVyX3VucmVnaXN0ZXIoJmlibXBvd2VybnZfZHJpdmVyKTsK\n" - "Pj4gK2V4aXQ6Cj4+ICsJcmV0dXJuIGVycjsKPj4gK30KPj4gKwo+PiArc3RhdGljIHZvaWQgX19l\n" - "eGl0IGlibXBvd2VybnZfZXhpdCh2b2lkKQo+PiArewo+PiArCXBsYXRmb3JtX2RldmljZV91bnJl\n" - "Z2lzdGVyKHBkZXZpY2UpOwo+PiArCXBsYXRmb3JtX2RyaXZlcl91bnJlZ2lzdGVyKCZpYm1wb3dl\n" - "cm52X2RyaXZlcik7Cj4+ICt9Cj4+ICsKPj4gK01PRFVMRV9ERVNDUklQVElPTigiSUJNIFBPV0VS\n" - "TlYgcGxhdGZvcm0gc2Vuc29ycyIpOwo+PiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwo+PiArCj4+\n" - "ICttb2R1bGVfaW5pdChpYm1wb3dlcm52X2luaXQpOwo+PiArbW9kdWxlX2V4aXQoaWJtcG93ZXJu\n" - "dl9leGl0KTsKPj4KPj4KPiBFbXB0eSBsaW5lcyBhdCBlbmQuCj4KPiBfX19fX19fX19fX19fX19f\n" - "X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwo+IExpbnV4cHBjLWRldiBtYWlsaW5nIGxp\n" - "c3QKPiBMaW51eHBwYy1kZXZAbGlzdHMub3psYWJzLm9yZwo+IGh0dHBzOi8vbGlzdHMub3psYWJz\n" - "Lm9yZy9saXN0aW5mby9saW51eHBwYy1kZXYKSGkgR3VlbnRlciwKClRoYW5rcyBmb3IgdGhlIHJl\n" - "dmlldy4gSSdsbCByZXdvcmsgb24gdGhlIHBhdGNoIGFuZCBwb3N0IHRoZSB2Mi4KCi0gTmVlbGVz\n" - "aAoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxtLXNl\n" - "bnNvcnMgbWFpbGluZyBsaXN0CmxtLXNlbnNvcnNAbG0tc2Vuc29ycy5vcmcKaHR0cDovL2xpc3Rz\n" - LmxtLXNlbnNvcnMub3JnL21haWxtYW4vbGlzdGluZm8vbG0tc2Vuc29ycw= + "On 05/14/2014 10:39 PM, Guenter Roeck wrote:\n" + "> On Wed, May 14, 2014 at 11:31:53AM +0530, 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: 5294 RPM (min = 0 RPM)\n" + ">> fan2: 4945 RPM (min = 0 RPM)\n" + ">> fan3: 5831 RPM (min = 0 RPM)\n" + ">> fan4: 5212 RPM (min = 0 RPM)\n" + ">> fan5: 0 RPM (min = 0 RPM)\n" + ">> fan6: 0 RPM (min = 0 RPM)\n" + ">> fan7: 7472 RPM (min = 0 RPM)\n" + ">> fan8: 7920 RPM (min = 0 RPM)\n" + ">> temp1: +39.0\302\260C (high = +0.0\302\260C)\n" + ">> power1: 192.00 W\n" + ">>\n" + ">> [root@tul163p1 ~]#\n" + ">> [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/\n" + ">> driver fan2_min fan4_min fan6_min fan8_min modalias uevent\n" + ">> fan1_fault fan3_fault fan5_fault fan7_fault hwmon name\n" + ">> fan1_input fan3_input fan5_input fan7_input in1_fault power1_input\n" + ">> fan1_min fan3_min fan5_min fan7_min in2_fault subsystem\n" + ">> fan2_fault fan4_fault fan6_fault fan8_fault in3_fault temp1_input\n" + ">> fan2_input fan4_input fan6_input fan8_input in4_fault temp1_max\n" + ">> [root@tul163p1 ~]#\n" + ">> [root@tul163p1 ~]# ls /sys/class/hwmon/hwmon0/device/\n" + ">> driver fan2_min fan4_min fan6_min fan8_min modalias uevent\n" + ">> fan1_fault fan3_fault fan5_fault fan7_fault hwmon name\n" + ">> fan1_input fan3_input fan5_input fan7_input in1_fault power1_input\n" + ">> fan1_min fan3_min fan5_min fan7_min in2_fault subsystem\n" + ">> fan2_fault fan4_fault fan6_fault fan8_fault in3_fault temp1_input\n" + ">> fan2_input fan4_input fan6_input fan8_input in4_fault temp1_max\n" + ">> [root@tul163p1 ~]#\n" + ">>\n" + ">> Signed-off-by: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com>\n" + ">> Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>\n" + ">> ---\n" + ">> drivers/hwmon/Kconfig | 8 +\n" + ">> drivers/hwmon/Makefile | 1\n" + ">> drivers/hwmon/ibmpowernv.c | 386 ++++++++++++++++++++++++++++++++++++++++++++\n" + ">> 3 files changed, 395 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" + ">> \t This driver can also be built as a module. If so, the module\n" + ">> \t will be called ibmpex.\n" + ">> \n" + ">> +config SENSORS_IBMPOWERNV\n" + ">> +\ttristate \"IBM POWERNV platform sensors\"\n" + ">> +\tdepends on PPC_POWERNV\n" + ">> +\tdefault y\n" + ">> +\thelp\n" + ">> +\t If you say yes here you get support for the temperature/fan/power\n" + ">> +\t sensors on your platform.\n" + ">> +\n" + ">> config SENSORS_IIO_HWMON\n" + ">> \ttristate \"Hwmon driver that uses channels specified via iio maps\"\n" + ">> \tdepends 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)\t+= ultra45_env.o\n" + ">> obj-$(CONFIG_SENSORS_I5K_AMB)\t+= i5k_amb.o\n" + ">> obj-$(CONFIG_SENSORS_IBMAEM)\t+= ibmaem.o\n" + ">> obj-$(CONFIG_SENSORS_IBMPEX)\t+= ibmpex.o\n" + ">> +obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o\n" + ">> obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o\n" + ">> obj-$(CONFIG_SENSORS_INA209)\t+= ina209.o\n" + ">> obj-$(CONFIG_SENSORS_INA2XX)\t+= ina2xx.o\n" + ">> diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c\n" + ">> new file mode 100644\n" + ">> index 0000000..e5cffce\n" + ">> --- /dev/null\n" + ">> +++ b/drivers/hwmon/ibmpowernv.c\n" + ">> @@ -0,0 +1,386 @@\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; if not, write to the Free Software\n" + ">> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" + "> Please drop the FSF address; it can change, and we don't want to update the\n" + "> driver each time it does.\n" + ">\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\t\t\"ibmpowernv\"\n" + ">> +#define MAX_ATTR_LEN\t32\n" + ">> +\n" + ">> +/* Sensor suffix name from DT */\n" + ">> +#define DT_FAULT_ATTR_SUFFIX\t\t\"faulted\"\n" + ">> +#define DT_DATA_ATTR_SUFFIX\t\t\"data\"\n" + ">> +#define DT_THRESHOLD_ATTR_SUFFIX\t\"thrs\"\n" + ">> +\n" + ">> +/* Enumerates all the sensors in the POWERNV platform and also index into\n" + ">> + * 'struct sensor_name'\n" + "> Comment coding style, please (this is not the networking subsystem ;-)\n" + ">\n" + ">> + */\n" + ">> +enum sensors {\n" + ">> +\tFAN,\n" + ">> +\tAMBIENT_TEMP,\n" + ">> +\tPOWERSUPPLY,\n" + ">> +\tPOWER,\n" + ">> +\tMAX_SENSOR_TYPE,\n" + ">> +};\n" + ">> +\n" + ">> +static struct sensor_name {\n" + "> const ?\n" + ">\n" + ">> +\tchar *name;\n" + ">> +\tchar *compatible;\n" + ">> +} sensor_names[] = {\n" + ">> +\t{\"fan\", \"ibm,opal-sensor-cooling-fan\"},\n" + ">> +\t{\"temp\", \"ibm,opal-sensor-amb-temp\"},\n" + ">> +\t{\"in\", \"ibm,opal-sensor-power-supply\"},\n" + ">> +\t{\"power\", \"ibm,opal-sensor-power\"}\n" + ">> +};\n" + ">> +\n" + ">> +struct platform_data {\n" + ">> +\tstruct device *hwmon_dev;\n" + "> Not needed.\n" + ">\n" + ">> +\tstruct device_attribute name_attr;\n" + ">> +\tstruct list_head attr_list;\n" + ">> +};\n" + ">> +\n" + ">> +struct sensor_data {\n" + ">> +\tu32 id;\n" + ">> +\tenum sensors stype;\n" + ">> +\tchar name[MAX_ATTR_LEN];\n" + ">> +\tstruct sensor_device_attribute sd_attr;\n" + ">> +\tstruct list_head list;\n" + ">> +};\n" + ">> +\n" + ">> +/* Platform device representing all the ibmpowernv sensors */\n" + ">> +static struct platform_device *pdevice;\n" + ">> +\n" + ">> +static void get_sensor_index_attr(const char *name, u32 *index, char *attr)\n" + ">> +{\n" + ">> +\tchar *hash_pos = strchr(name, '#');\n" + ">> +\tchar *dash_pos;\n" + ">> +\tu32 copy_len;\n" + ">> +\tchar buf[8];\n" + ">> +\n" + ">> +\tmemset(buf, 0, sizeof(buf));\n" + ">> +\t*index = 0;\n" + ">> +\t*attr = '\\0';\n" + ">> +\n" + ">> +\tif (hash_pos) {\n" + ">> +\t\tdash_pos = strchr(hash_pos, '-');\n" + ">> +\t\tif (dash_pos) {\n" + ">> +\t\t\tcopy_len = dash_pos - hash_pos - 1;\n" + ">> +\t\t\tif (copy_len < sizeof(buf)) {\n" + ">> +\t\t\t\tstrncpy(buf, hash_pos + 1, copy_len);\n" + ">> +\t\t\t\tsscanf(buf, \"%d\", index);\n" + ">> +\t\t\t}\n" + ">> +\n" + ">> +\t\t\tstrncpy(attr, dash_pos + 1, MAX_ATTR_LEN);\n" + ">> +\t\t}\n" + ">> +\t}\n" + ">> +}\n" + ">> +\n" + ">> +/*\n" + ">> + * This function translates the DT node name into the 'hwmon' attribute name.\n" + ">> + * IBMPOWERNV device node appear like cooling-fan#2-data, 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 create_hwmon_attr_name(enum sensors stype, const char *node_name,\n" + ">> +\t\tchar *hwmon_attr_name)\n" + "> Please follow CodingStyle for continuation line alignment.\n" + ">\n" + ">> +{\n" + ">> +\tchar attr_suffix[MAX_ATTR_LEN];\n" + ">> +\tchar *attr_name;\n" + ">> +\tu32 index;\n" + ">> +\n" + ">> +\tget_sensor_index_attr(node_name, &index, attr_suffix);\n" + ">> +\tif (!index || !strlen(attr_suffix)) {\n" + ">> +\t\tpr_info(\"%s: Sensor device node name is invalid, name: %s\\n\",\n" + ">> +\t\t\t\t__func__, node_name);\n" + ">> +\t\treturn -EINVAL;\n" + ">> +\t}\n" + ">> +\n" + ">> +\tif (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX))\n" + ">> +\t\tattr_name = \"fault\";\n" + ">> +\telse if(!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX))\n" + ">> +\t\tattr_name = \"input\";\n" + ">> +\telse if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) {\n" + ">> +\t\tif (stype == AMBIENT_TEMP)\n" + ">> +\t\t\tattr_name = \"max\";\n" + ">> +\t\telse if (stype == FAN)\n" + ">> +\t\t\tattr_name = \"min\";\n" + ">> +\t\telse\n" + ">> +\t\t\treturn -ENOENT;\n" + ">> +\t} else\n" + ">> +\t\treturn -ENOENT;\n" + ">> +\n" + ">> +\tsnprintf(hwmon_attr_name, MAX_ATTR_LEN, \"%s%d_%s\",\n" + ">> +\t\t\tsensor_names[stype].name, index, attr_name);\n" + ">> +\treturn 0;\n" + ">> +}\n" + ">> +\n" + ">> +static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr,\n" + ">> +\t\tchar *buf)\n" + ">> +{\n" + ">> +\tstruct sensor_device_attribute *sd_attr = to_sensor_dev_attr(devattr);\n" + ">> +\tstruct sensor_data *sdata = container_of(sd_attr, struct sensor_data,\n" + ">> +\t\t\tsd_attr);\n" + ">> +\tint err;\n" + ">> +\tu32 x;\n" + ">> +\n" + ">> +\terr = opal_get_sensor_data(sdata->id, &x);\n" + ">> +\tif (err) {\n" + ">> +\t\tpr_err(\"%s: Failed to get opal sensor data\\n\", __func__);\n" + ">> +\t\tx = -1;\n" + "> Unusual. Why not report the error to user space ?\n" + "> Reporting <maxuint> on error doesn't seem to be very useful.\n" + ">\n" + ">> +\t}\n" + ">> +\n" + ">> +\t/* Convert temperature to milli-degrees */\n" + ">> +\tif (sdata->stype == AMBIENT_TEMP && x > 0)\n" + ">> +\t\tx *= 1000;\n" + ">> +\t/* Convert power to micro-watts */\n" + ">> +\telse if (sdata->stype == POWER && x > 0)\n" + ">> +\t\tx *= 1000000;\n" + ">> +\n" + "> Is there an overflow concern ? Guess not ... overflow happens at ~17KW.\n" + "> Just wondering.\n" + ">\n" + ">> +\treturn sprintf(buf, \"%d\\n\", x);\n" + ">> +}\n" + ">> +\n" + ">> +static void remove_device_attrs(struct platform_device *pdev)\n" + ">> +{\n" + ">> +\tstruct platform_data *pdata = platform_get_drvdata(pdev);\n" + ">> +\tstruct device *dev = &pdev->dev;\n" + ">> +\tstruct sensor_data *s, *next;\n" + ">> +\n" + ">> +\tlist_for_each_entry_safe(s, next, &pdata->attr_list, list) {\n" + ">> +\t\tdevice_remove_file(dev, &s->sd_attr.dev_attr);\n" + ">> +\t\tlist_del(&s->list);\n" + "> This is unnecessary since you always remove the entire list anyway.\n" + "> Actually, I don't think you need the list in the first place.\n" + "> You only use it to delete entries, but that can be handled automatically\n" + "> by the infrastructure. All you really need is an array pointing to the device\n" + "> attributes so you can create all attribute files with a single operation.\n" + ">\n" + ">> +\t\tkfree(s);\n" + ">> +\t}\n" + ">> +}\n" + ">> +\n" + ">> +/*\n" + ">> + * Iterate through the device tree and for each child of sensor node, create\n" + ">> + * a sysfs attribute file, the file is named by translating the DT node name\n" + ">> + * to the name required by the higher 'hwmon' driver like fan1_input, temp1_max\n" + ">> + * etc..\n" + ">> + */\n" + ">> +static int create_device_attrs(struct platform_device *pdev)\n" + ">> +{\n" + ">> +\tstruct platform_data *pdata = platform_get_drvdata(pdev);\n" + ">> +\tstruct device *dev = &pdev->dev;\n" + ">> +\tstruct device_node *opal, *np;\n" + ">> +\tstruct sensor_data *sdata;\n" + ">> +\tconst u32 *sensor_id;\n" + ">> +\tenum sensors stype;\n" + ">> +\tint err;\n" + ">> +\n" + ">> +\topal = of_find_node_by_path(\"/ibm,opal/sensors\");\n" + ">> + if (!opal) {\n" + ">> +\t\tpr_err(\"%s: Opal 'sensors' node not found\\n\", __func__);\n" + ">> +\t\terr = -ENXIO;\n" + "> \tENODEV ?\n" + ">\n" + ">> +\t\tgoto exit;\n" + "> \tI would suggest to simply return here.\n" + ">\n" + ">> + }\n" + ">> +\n" + ">> +\tfor_each_child_of_node(opal, np) {\n" + ">> + if (np->name == NULL)\n" + ">> + continue;\n" + ">> +\n" + ">> +\t\tfor (stype = 0; stype < MAX_SENSOR_TYPE; stype++)\n" + ">> +\t\t\tif (of_device_is_compatible(np,\n" + ">> +\t\t\t\t\tsensor_names[stype].compatible))\n" + ">> +\t\t\t\tbreak;\n" + ">> +\n" + ">> +\t\tif (stype == MAX_SENSOR_TYPE)\n" + ">> +\t\t\tcontinue;\n" + ">> +\n" + ">> +\t\tsensor_id = of_get_property(np, \"sensor-id\", NULL);\n" + ">> +\t\tif (!sensor_id) {\n" + ">> +\t\t\tpr_info(\"%s: %s doesn't have sensor-id\\n\", __func__,\n" + ">> +\t\t\t\t\tnp->name);\n" + ">> +\t\t\tcontinue;\n" + ">> +\t\t}\n" + ">> +\n" + ">> +\t\tsdata = kzalloc(sizeof(*sdata), GFP_KERNEL);\n" + "> Can you use devm_kzalloc() ?\n" + ">\n" + ">> +\t\tif (!sdata) {\n" + ">> +\t\t\tpr_err(\"%s: Failed to allocate memory for sensor_data\",\n" + ">> +\t\t\t\t\t__func__);\n" + ">> +\t\t\terr = -ENOMEM;\n" + ">> +\t\t\tgoto exit_put_node;\n" + ">> +\t\t}\n" + ">> +\n" + ">> +\t\tsdata->id = *sensor_id;\n" + ">> +\t\tsdata->stype = stype;\n" + ">> +\t\terr = create_hwmon_attr_name(stype, np->name, sdata->name);\n" + ">> +\t\tif (err) {\n" + ">> +\t\t\tpr_err(\"%s: Failed to create the hwmon attribute name\\n\",\n" + ">> +\t\t\t\t\t__func__);\n" + "> create_hwmon_attr_name() (sometimes) already creates an error message.\n" + "> Would be nice if you can avoid duplicate error messages.\n" + ">\n" + ">> +\t\t\tgoto exit_free_sdata;\n" + ">> +\t\t}\n" + ">> +\n" + ">> +\t\tsysfs_attr_init(&sdata->sd_attr.dev_attr.attr);\n" + ">> +\t\tsdata->sd_attr.dev_attr.attr.name = sdata->name;\n" + ">> +\t\tsdata->sd_attr.dev_attr.attr.mode = S_IRUGO;\n" + ">> +\t\tsdata->sd_attr.dev_attr.show = show_sensor;\n" + "> Since you are not using the index value from sensor_device_attribute,\n" + "> but use your own 'id' variable instead, you don't need sensor_device_attribute\n" + "> but can use device_attribute instead (or drop 'id' and use\n" + "> sd_attr.index instead).\n" + ">\n" + ">> +\n" + ">> +\t\t/* Create sysfs attribute file */\n" + ">> +\t\terr = device_create_file(dev, &sdata->sd_attr.dev_attr);\n" + ">> +\t\tif (err)\n" + ">> +\t\t\tgoto exit_free_sdata;\n" + ">> +\n" + "> Please don't create the attribute files here but just a list of attributes\n" + "> instead. See below for more details.\n" + ">\n" + ">> +\t\tlist_add_tail(&sdata->list, &pdata->attr_list);\n" + ">> +\t}\n" + ">> +\n" + ">> +\tof_node_put(opal);\n" + ">> +\treturn 0;\n" + ">> +\n" + ">> +exit_free_sdata:\n" + ">> +\tkfree(sdata);\n" + ">> +exit_put_node:\n" + ">> +\tof_node_put(opal);\n" + ">> +\tremove_device_attrs(pdev);\n" + ">> +exit:\n" + ">> +\treturn err;\n" + ">> +}\n" + ">> +\n" + ">> +static ssize_t show_name(struct device *dev, struct device_attribute *devattr,\n" + ">> +\t\tchar *buf)\n" + ">> +{\n" + ">> +\tstruct platform_device *pdev = to_platform_device(dev);\n" + ">> +\treturn sprintf(buf, \"%s\\n\", pdev->name);\n" + ">> +}\n" + "> Not necessary; see below.\n" + ">\n" + ">> +\n" + ">> +static int ibmpowernv_probe(struct platform_device *pdev)\n" + ">> +{\n" + ">> +\tstruct device *dev = &pdev->dev;\n" + ">> +\tstruct platform_data *pdata;\n" + ">> +\tint err;\n" + ">> +\n" + ">> +\tpdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);\n" + ">> +\tif (!pdata) {\n" + ">> +\t\terr = -ENOMEM;\n" + ">> +\t\tgoto exit;\n" + ">> +\t}\n" + ">> +\n" + ">> +\tINIT_LIST_HEAD(&pdata->attr_list);\n" + ">> +\tplatform_set_drvdata(pdev, pdata);\n" + ">> +\n" + ">> +\t/* Create platform device 'name' attribute */\n" + ">> +\tsysfs_attr_init(&pdata->name_attr.attr);\n" + ">> +\tpdata->name_attr.attr.name = \"name\";\n" + ">> +\tpdata->name_attr.attr.mode = S_IRUGO;\n" + ">> +\tpdata->name_attr.show = show_name;\n" + ">> +\terr = device_create_file(dev, &pdata->name_attr);\n" + "> You don't need to create a name attribute.\n" + "> devm_hwmon_device_register_with_groups does it for you (from the second\n" + "> argument).\n" + ">\n" + ">> +\tif (err)\n" + ">> +\t\tgoto exit;\n" + ">> +\n" + ">> +\t/* Create sysfs attribute file for each sensor found in the DT */\n" + ">> +\terr = create_device_attrs(pdev);\n" + "> That defeats the purpose of using devm_hwmon_device_register_with_groups.\n" + "> The idea here is to build a list of attributes, which you can do in\n" + "> create_device_attrs(), but not create the actual device entries.\n" + "> Then also create an attribute_group as well as a list of groups,\n" + "> and pass that as last argument to devm_hwmon_device_register_with_groups().\n" + ">\n" + "> drivers/hwmon/pmbus/pmbus_core.c does something similar; maybe you can\n" + "> use a similar approach.\n" + ">\n" + "> With that, you also don't need the remove functions, since the hwmon\n" + "> subsystem will auto-remove the attributes. If you do it correctly\n" + "> (ie use devm_kzalloc() for allocating memory) you should not need a\n" + "> remove function at all.\n" + ">\n" + ">> +\tif (err) {\n" + ">> +\t\tpr_err(\"%s: Failed to create the device attributes\\n\",\n" + ">> +\t\t\t\t__func__);\n" + ">> +\t\tgoto exit_remove_name;\n" + ">> +\t}\n" + ">> +\n" + ">> +\t/* Finally, register with hwmon */\n" + ">> +\tpdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME,\n" + ">> +\t\t\tpdata, NULL);\n" + ">> +\tif (IS_ERR(pdata->hwmon_dev)) {\n" + ">> +\t\terr = PTR_ERR(pdata->hwmon_dev);\n" + ">> +\t\tgoto exit_remove_devattrs;\n" + ">> +\t}\n" + ">> +\n" + ">> +\treturn 0;\n" + ">> +\n" + ">> +exit_remove_devattrs:\n" + ">> +\tremove_device_attrs(pdev);\n" + ">> +exit_remove_name:\n" + ">> +\tdevice_remove_file(dev, &pdata->name_attr);\n" + ">> +exit:\n" + ">> +\treturn err;\n" + "> If you do it right you should be able to reduce this to something like\n" + ">\n" + "> \thwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME, pdata,\n" + "> \t\t\t\t\t\t\t pdata->attr_groups);\n" + "> \treturn PTR_ERR_OR_ZERO(hwmon_dev);\n" + ">\n" + "> ...\n" + ">\n" + ">> +}\n" + ">> +\n" + ">> +static int ibmpowernv_remove(struct platform_device *pdev)\n" + ">> +{\n" + ">> +\tstruct platform_data *pdata = platform_get_drvdata(pdev);\n" + ">> +\tstruct device *dev = &pdev->dev;\n" + ">> +\n" + ">> +\tremove_device_attrs(pdev);\n" + ">> +\tdevice_remove_file(dev, &pdata->name_attr);\n" + ">> +\n" + ">> +\treturn 0;\n" + ">> +}\n" + "> ... and you should be able to remove this entire function.\n" + ">\n" + ">> +\n" + ">> +\n" + "> No double empty lines please.\n" + ">\n" + ">> +static struct platform_driver ibmpowernv_driver = {\n" + ">> +\t.driver = {\n" + ">> +\t\t.owner = THIS_MODULE,\n" + ">> +\t\t.name = DRVNAME,\n" + ">> +\t},\n" + ">> +\t.probe = ibmpowernv_probe,\n" + ">> +\t.remove = ibmpowernv_remove,\n" + ">> +};\n" + ">> +\n" + ">> +\n" + "> Excessive empty lines.\n" + ">\n" + ">> +static int __init ibmpowernv_init(void)\n" + ">> +{\n" + ">> +\tint err;\n" + ">> +\n" + ">> +\n" + "> Excessive empty lines.\n" + ">\n" + ">> +\terr = platform_driver_register(&ibmpowernv_driver);\n" + ">> +\tif (err)\n" + ">> +\t\tgoto exit;\n" + "> Sometimes you create an error message, sometimes not. I'd prefer no error\n" + "> message to start with (the module loader will create one anyway), but\n" + "> at least please be consistent.\n" + ">\n" + ">> +\n" + ">> +\n" + "> Excessive empty lines.\n" + ">\n" + ">> +\tpdevice = platform_device_alloc(DRVNAME, 0);\n" + ">> +\tif (!pdevice) {\n" + ">> +\t\tpr_err(\"%s: Device allocation failed\\n\", __func__);\n" + ">> +\t\terr = -ENOMEM;\n" + ">> +\t\tgoto exit_driver_unreg;\n" + ">> +\t}\n" + ">> +\n" + ">> +\terr = platform_device_add(pdevice);\n" + ">> +\tif (err) {\n" + ">> +\t\tpr_err(\"%s: Device addition failed (%d)\\n\", __func__, err);\n" + ">> +\t\tgoto exit_device_put;\n" + ">> +\t}\n" + ">> +\n" + "> Can you use platform_driver_probe() here ?\n" + ">\n" + ">> +\treturn 0;\n" + ">> +\n" + ">> +exit_device_put:\n" + ">> +\tplatform_device_put(pdevice);\n" + ">> +exit_driver_unreg:\n" + ">> +\tplatform_driver_unregister(&ibmpowernv_driver);\n" + ">> +exit:\n" + ">> +\treturn err;\n" + ">> +}\n" + ">> +\n" + ">> +static void __exit ibmpowernv_exit(void)\n" + ">> +{\n" + ">> +\tplatform_device_unregister(pdevice);\n" + ">> +\tplatform_driver_unregister(&ibmpowernv_driver);\n" + ">> +}\n" + ">> +\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" + "> Empty lines at end.\n" + ">\n" + "> _______________________________________________\n" + "> Linuxppc-dev mailing list\n" + "> Linuxppc-dev@lists.ozlabs.org\n" + "> https://lists.ozlabs.org/listinfo/linuxppc-dev\n" + "Hi Guenter,\n" + "\n" + "Thanks for the review. I'll rework on the patch and post the v2.\n" + "\n" + - Neelesh -071bedabf8cedc43f19c83038da12e4d0bab53021d2dfaad76a4950e7739f764 +2caf65c23ca88ecd14e2bfb66b6cf8c01c31e7ab4dc75c4892e87cdfb8878496
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.