diff for duplicates of <53B76220.9090900@roeck-us.net> diff --git a/a/1.txt b/N1/1.txt index d8f236d..cf6041f 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -1,330 +1,593 @@ -T24gMDcvMDQvMjAxNCAwNDowMiBBTSwgTmVlbGVzaCBHdXB0YSB3cm90ZToKPiBUaGlzIHBhdGNo -IGFkZHMgYmFzaWMga2VybmVsIHN1cHBvcnQgZm9yIHJlYWRpbmcgcG93ZXIgdmFsdWVzLCBmYW4K -PiBzcGVlZCBycG0sIHZvbHRhZ2UgYW5kIHRlbXBlcmF0dXJlIGRhdGEgb24gcG93ZXJudiBwbGF0 -Zm9ybXMgd2hpY2ggd2lsbAo+IGJlIGV4cG9ydGVkIHRvIHVzZXIgc3BhY2UgdGhyb3VnaCBzeXNm -cyBpbnRlcmZhY2UuCj4KCkhpIE5lZWxlc2gsCgpDb3B5aW5nIGRldmljZXRyZWUgbWFpbGluZyBs -aXN0LiBQbGVhc2UgY29weSBpdCBvbiB0aGUgbmV4dCAoaG9wZWZ1bGx5IGZpbmFsKQpyZXZpc2lv -bjsgZGV2aWNldHJlZSBtYWludGFpbmVycyBhdCBsZWFzdCBuZWVkIGEgY2hhbmNlIHRvIGNvbW1l -bnQuClsgWWVzLCBJIHVuZGVyc3RhbmQgdGhpcyBpcyBhIHNoaXBwaW5nIHByb2R1Y3QsIGJ1dCBz -dGlsbCAuLi4gXQoKSSBhbSBvayB3aXRoIHRoZSBjb2RlIGV4Y2VwdCBmb3IgYSBjb3VwbGUgb2Yg -bWlub3Igbml0cGlja3MgKHNlZSBiZWxvdykuCgpUaGFua3MsCkd1ZW50ZXIKCj4gVGVzdCByZXN1 -bHRzOgo+IC0tLS0tLS0tLS0tLS0KPiBbcm9vdEB0dWwxNjNwMSB+XSMgc2Vuc29ycwo+IGlibXBv -d2VybnYtaXNhLTAwMDAKPiBBZGFwdGVyOiBJU0EgYWRhcHRlcgo+IGZhbjE6ICAgICAgICA1NTY3 -IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjI6ICAgICAgICA1MjMyIFJQTSAgKG1pbiA9ICAg -IDAgUlBNKQo+IGZhbjM6ICAgICAgICA1NTMyIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjQ6 -ICAgICAgICA0OTQ1IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjU6ICAgICAgICAgICAwIFJQ -TSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjY6ICAgICAgICAgICAwIFJQTSAgKG1pbiA9ICAgIDAg -UlBNKQo+IGZhbjc6ICAgICAgICA3MzkyIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjg6ICAg -ICAgICA3OTM2IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IHRlbXAxOiAgICAgICAgKzM5LjDCsEMg -IChoaWdoID0gICswLjDCsEMpCj4gcG93ZXIxOiAgICAgIDE5MS4wMCBXCj4KPiBbcm9vdEB0dWwx -NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtLwo+IGFsYXJtdGltZXIgIGlibXBvd2Vy -bnYuMCAgcG93ZXIgIHJ0Yy1nZW5lcmljICBzZXJpYWw4MjUwICB1ZXZlbnQKPiBbcm9vdEB0dWwx -NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtL2libXBvd2VybnYuMC9od21vbi9od21v -bjAvCj4gZGV2aWNlCSAgICBmYW4yX21pbglmYW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAg -IHBvd2VyCj4gZmFuMV9mYXVsdCAgZmFuM19mYXVsdAlmYW41X2ZhdWx0ICBmYW43X2ZhdWx0CWlu -MV9mYXVsdCAgcG93ZXIxX2lucHV0Cj4gZmFuMV9pbnB1dCAgZmFuM19pbnB1dAlmYW41X2lucHV0 -ICBmYW43X2lucHV0CWluMl9mYXVsdCAgc3Vic3lzdGVtCj4gZmFuMV9taW4gICAgZmFuM19taW4J -ZmFuNV9taW4gICAgZmFuN19taW4JaW4zX2ZhdWx0ICB0ZW1wMV9pbnB1dAo+IGZhbjJfZmF1bHQg -IGZhbjRfZmF1bHQJZmFuNl9mYXVsdCAgZmFuOF9mYXVsdAlpbjRfZmF1bHQgIHRlbXAxX21heAo+ -IGZhbjJfaW5wdXQgIGZhbjRfaW5wdXQJZmFuNl9pbnB1dCAgZmFuOF9pbnB1dAluYW1lCSAgIHVl -dmVudAo+IFtyb290QHR1bDE2M3AxIH5dIwo+IFtyb290QHR1bDE2M3AxIH5dIyBscyAvc3lzL2Ns -YXNzL2h3bW9uL2h3bW9uMC8KPiBkZXZpY2UJICAgIGZhbjJfbWluCWZhbjRfbWluICAgIGZhbjZf -bWluCWZhbjhfbWluICAgcG93ZXIKPiBmYW4xX2ZhdWx0ICBmYW4zX2ZhdWx0CWZhbjVfZmF1bHQg -IGZhbjdfZmF1bHQJaW4xX2ZhdWx0ICBwb3dlcjFfaW5wdXQKPiBmYW4xX2lucHV0ICBmYW4zX2lu -cHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5wdXQJaW4yX2ZhdWx0ICBzdWJzeXN0ZW0KPiBmYW4xX21p -biAgICBmYW4zX21pbglmYW41X21pbiAgICBmYW43X21pbglpbjNfZmF1bHQgIHRlbXAxX2lucHV0 -Cj4gZmFuMl9mYXVsdCAgZmFuNF9mYXVsdAlmYW42X2ZhdWx0ICBmYW44X2ZhdWx0CWluNF9mYXVs -dCAgdGVtcDFfbWF4Cj4gZmFuMl9pbnB1dCAgZmFuNF9pbnB1dAlmYW42X2lucHV0ICBmYW44X2lu -cHV0CW5hbWUJICAgdWV2ZW50Cj4gW3Jvb3RAdHVsMTYzcDEgfl0jCj4KPiBTaWduZWQtb2ZmLWJ5 -OiBOZWVsZXNoIEd1cHRhIDxuZWVsZWd1cEBsaW51eC52bmV0LmlibS5jb20+Cj4gLS0tCj4KPiBD -aGFuZ2VzIGluIHY0Cj4gPT09PT09PT09PT09PQo+IC0gUmVwbGFjZWQgcHJfZXJyKCkgd2l0aCBk -ZXZfZXJyKCkgZm9yIGxvZ2dpbiBwcmludCBtZXNzYWdlcy4KPiAtIFVzaW5nIGtzdHJ0b3UzMigp -IGZ1bmN0aW9uIGZvciBjb252ZXJ0aW5nIHN0cmluZyB0byB1MzIgaW5zdGVhZCBvZiBzc2NhbmYo -KS4KPgo+IENoYW5nZXMgaW4gdjMKPiA9PT09PT09PT09PT09Cj4gLSBGaXhlZCBhbiBlbmRpYW5u -ZXNzIGJ1ZyBsZWFkaW5nIHRoZSBkcml2ZXIgdG8gYnJlYWsgb24gTEUuCj4gLSBGaXhlZCBhIGJ1 -ZyB0aGF0IHdoZW4gb25lIG9mIHRoZSAnYXR0cmlidXRlX2dyb3VwJyBub3QgcG9wdWxhdGVkLCBm -b2xsb3dpbmcKPiAgICBncm91cHMgYXR0cmlidXRlcyB3ZXJlIGRyb3BwZWQuCj4gLSBSZXdyaXRl -IHRoZSBnZXRfc2Vuc29yX2luZGV4X2F0dHIoKSBmdW5jdGlvbiB0byBoYW5kbGUgYWxsIHRoZSBl -cnJvciBzY2VuYXJpb3MKPiAgICBsaWtlICdzc2NhbmYnIGV0Yy4KPiAtIEZpeGVkIGFsbCB0aGUg -ZXJyb3JzL3dhcm5pbmdzIHJlbGF0ZWQgdG8gY29kaW5nIHN0eWxlL3doaXRlc3BhY2UuCj4gLSBB -ZGRlZCAnRG9jdW1lbnRhdGlvbicgZmlsZXMuCj4gLSBBZGRyZXNzZWQgcmVtYWluaW5nIHJldmll -dyBjb21tZW50cyBvbiBWMi4KPgo+IENoYW5nZXMgaW4gdjIKPiA9PT09PT09PT09PT09Cj4gLSBH -ZW5lcmljIHVzZSBvZiBkZXZtXyogZnVuY3Rpb25zIGluIGh3bW9uIGxpa2UgdXNpbmcgZGV2bV9r -emFsbG9jKCkgZm9yIGR5bmFtaWMKPiAgICBtZW1vcnkgcmVxdWVzdCwgYXZvaWRpbmcgdGhlIG5l -ZWQgdG8gZXhwbGljaXQgZnJlZSBvZiBtZW1vcnkuCj4gICAgQWRkaW5nICdzdHJ1Y3QgYXR0cmli -dXRlX2dyb3VwJyBhcyBtZW1iZXIgb2YgcGxhdGZvcm0gZGF0YSBzdHJ1Y3R1cmUgdG8gYmUKPiAg -ICBwb3B1bGF0ZWQgYW5kIHRoZW4gcGFzc2VkIHRvIGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVy -X3dpdGhfZ3JvdXBzKCkuCj4KPiAgICBOb3RlOiBIYXZpbmcgYW4gYXJyYXkgb2YgcG9pbnRlcnMg -b2YgJ2F0dHJpYnV0ZV9ncm91cCcgYW5kIGVhY2ggZ3JvdXAKPiAgICBjb3JyZXNwb25kcyB0byAn -ZW51bSBzZW5zb3JzJyB0eXBlLiBOb3QgY29tcGxldGVseSBzdXJlLCBpZiBpdCdzIGlkZWFsIG9y -Cj4gICAgY291bGQgaGF2ZSBqdXN0IG9uZSBncm91cCBwb3B1bGF0ZWQgd2l0aCBhdHRyaWJ1dGVz -IG9mIHNlbnNvciB0eXBlcz8KPgo+IC0gJ2libXBvd2VybnYnIGlzIG5vdCBob3QtcGx1Z2dhYmxl -IGRldmljZSBzbyBtb3ZpbmcgJ3BsYXRmb3JtX2RyaXZlcicgY2FsbGJhY2sKPiAgICBmdW5jdGlv -biAocHJvYmUpIGFzIHBhcnQgb2YgX19pbml0IGNvZGUuCj4gLSBGaXhlZCBpc3N1ZXMgcmVsYXRl -ZCB0byBjb2Rpbmcgc3R5bGUuCj4gLSBPdGhlciBnZW5lcmFsIGNvbW1lbnRzIGluIHYxLgo+Cj4g -ICAuLi4vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4dCAgICAgICB8ICAg -MjcgKwo+ICAgRG9jdW1lbnRhdGlvbi9od21vbi9pYm1wb3dlcm52ICAgICAgICAgICAgICAgICAg -ICAgfCAgIDQxICsrCj4gICBkcml2ZXJzL2h3bW9uL0tjb25maWcgICAgICAgICAgICAgICAgICAg -ICAgICAgICAgICB8ICAgMTEgKwo+ICAgZHJpdmVycy9od21vbi9NYWtlZmlsZSAgICAgICAgICAg -ICAgICAgICAgICAgICAgICAgfCAgICAxCj4gICBkcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYyAg -ICAgICAgICAgICAgICAgICAgICAgICB8ICAzNjIgKysrKysrKysrKysrKysrKysrKysKPiAgIDUg -ZmlsZXMgY2hhbmdlZCwgNDQyIGluc2VydGlvbnMoKykKPiAgIGNyZWF0ZSBtb2RlIDEwMDY0NCBE -b2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQKPiAg -IGNyZWF0ZSBtb2RlIDEwMDY0NCBEb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYKPiAgIGNy -ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYwo+Cj4gZGlmZiAtLWdp -dCBhL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4 -dCBiL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4 -dAo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uZTNiZDFlYgo+IC0tLSAv -ZGV2L251bGwKPiArKysgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvaHdtb24v -aWJtcG93ZXJudi50eHQKPiBAQCAtMCwwICsxLDI3IEBACj4gK0lCTSBQT1dFUk5WIHBsYXRmb3Jt -IHNlbnNvcnMKPiArLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo+ICsKPiArUmVxdWlyZWQg -bm9kZSBwcm9wZXJ0aWVzOgo+ICstIGNvbXBhdGlibGU6IG11c3QgYmUgb25lIG9mCj4gKwkJImli -bSxvcGFsLXNlbnNvci1jb29saW5nLWZhbiIKPiArCQkiaWJtLG9wYWwtc2Vuc29yLWFtYi10ZW1w -Igo+ICsJCSJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3VwcGx5Igo+ICsJCSJpYm0sb3BhbC1zZW5z -b3ItcG93ZXIiCj4gKy0gc2Vuc29yLWlkOiBhbiBvcGFxdWUgaWQgcHJvdmlkZWQgYnkgdGhlIGZp -cm13YXJlIHRvIHRoZSBrZXJuZWwsIGlkZW50aWZpZXMgYQo+ICsJICAgICBnaXZlbiBzZW5zb3Ig -YW5kIGl0cyBhdHRyaWJ1dGUgZGF0YQo+ICsKPiArRXhhbXBsZSBzZW5zb3JzIG5vZGU6Cj4gKwo+ -ICtjb29saW5nLWZhbiM4LWRhdGEgewo+ICsJc2Vuc29yLWlkID0gPDB4NzA1MjEwNz47Cj4gKwlw -aGFuZGxlID0gPDB4MTAwMDAwMjg+Owo+ICsJbGludXgscGhhbmRsZSA9IDwweDEwMDAwMDI4PjsK -PiArCWNvbXBhdGlibGUgPSAiaWJtLG9wYWwtc2Vuc29yLWNvb2xpbmctZmFuIjsKCnBoYW5kbGUg -YW5kIGxpbnV4LXBoYW5kbGUgYXJlIG5laXRoZXIgZG9jdW1lbnRlZCBub3IgdXNlZC4gRWl0aGVy -IGRvY3VtZW50IG9yIGRyb3AuCgo+ICt9Owo+ICsKPiArYW1iLXRlbXAjMS10aHJzIHsKPiArCXNl -bnNvci1pZCA9IDwweDUwOTYwMDA+Owo+ICsJcGhhbmRsZSA9IDwweDEwMDAwMDE3PjsKPiArCWxp -bnV4LHBoYW5kbGUgPSA8MHgxMDAwMDAxNz47Cj4gKwljb21wYXRpYmxlID0gImlibSxvcGFsLXNl -bnNvci1hbWItdGVtcCI7Cj4gK307Cj4gZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24vaHdtb24v -aWJtcG93ZXJudiBiL0RvY3VtZW50YXRpb24vaHdtb24vaWJtcG93ZXJudgo+IG5ldyBmaWxlIG1v -ZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uNjQ0MjQ1YQo+IC0tLSAvZGV2L251bGwKPiArKysg -Yi9Eb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYKPiBAQCAtMCwwICsxLDQxIEBACj4gK0tl -cm5lbCBEcml2ZXIgSUJNUE9XRU5WCj4gKz09PT09PT09PT09PT09PT09PT09PT09Cj4gKwo+ICtT -dXBwb3J0ZWQgc3lzdGVtczoKPiArICAqIEFueSByZWNlbnQgSUJNIFAgc2VydmVycyBiYXNlZCBv -biBQT1dFUk5WIHBsYXRmb3JtCj4gKwo+ICtBdXRob3I6IE5lZWxlc2ggR3VwdGEKPiArCj4gK0Rl -c2NyaXB0aW9uCj4gKy0tLS0tLS0tLS0tCj4gKwo+ICtUaGlzIGRyaXZlciBpbXBsZW1lbnRzIHJl -YWRpbmcgdGhlIHBsYXRmb3JtIHNlbnNvcnMgZGF0YSBsaWtlIHRlbXBlcmF0dXJlL2Zhbi8KPiAr -dm9sdGFnZS9wb3dlciBmb3IgJ1BPV0VSTlYnIHBsYXRmb3JtLgo+ICsKPiArVGhlIGRyaXZlciB1 -c2VzIHRoZSBwbGF0Zm9ybSBkZXZpY2UgaW5mcmFzdHJ1Y3R1cmUuIEl0IHByb2JlcyB0aGUgZGV2 -aWNlIHRyZWUKPiArZm9yIHNlbnNvciBkZXZpY2VzIGR1cmluZyB0aGUgX19pbml0IHBoYXNlIGFu -ZCByZWdpc3RlcnMgdGhlbSB3aXRoIHRoZSAnaHdtb24nLgo+ICsnaHdtb24nIHBvcHVsYXRlcyB0 -aGUgJ3N5c2ZzJyB0cmVlIGhhdmluZyBhdHRyaWJ1dGUgZmlsZXMsIGVhY2ggZm9yIGEgZ2l2ZW4K -PiArc2Vuc29yIHR5cGUgYW5kIGl0cyBhdHRyaWJ1dGUgZGF0YS4KPiArCj4gK0FsbCB0aGUgbm9k -ZXMgaW4gdGhlIERUIGFwcGVhciB1bmRlciAiL2libSxvcGFsL3NlbnNvcnMiIGFuZCBlYWNoIHZh -bGlkIG5vZGUgaW4KPiArdGhlIERUIG1hcHMgdG8gYW4gYXR0cmlidXRlIGZpbGUgaW4gJ3N5c2Zz -Jy4gVGhlIG5vZGUgZXhwb3J0cyB1bmlxdWUgJ3NlbnNvci1pZCcKPiArd2hpY2ggdGhlIGRyaXZl -ciB1c2VzIHRvIG1ha2UgYW4gT1BBTCBjYWxsIHRvIHRoZSBmaXJtd2FyZS4KPiArCj4gK1VzYWdl -IG5vdGVzCj4gKy0tLS0tLS0tLS0tCj4gK1RoZSBkcml2ZXIgaXMgYnVpbHQgc3RhdGljYWxseSB3 -aXRoIHRoZSBrZXJuZWwgYnkgZW5hYmxpbmcgdGhlIGNvbmZpZwo+ICtDT05GSUdfU0VOU09SU19J -Qk1QT1dFUk5WLiBJdCBjYW4gYWxzbyBiZSBidWlsdCBhcyBtb2R1bGUgJ2libXBvd2VybnYnLgo+ -ICsKPiArU3lzZnMgYXR0cmlidXRlcwo+ICstLS0tLS0tLS0tLS0tLS0tCj4gKwo+ICtmYW5YX2lu -cHV0CQlNZWFzdXJlZCBSUE0gdmFsdWUuCj4gK2ZhblhfbWluCQlUaHJlc2hvbGQgUlBNIGZvciBh -bGVydCBnZW5lcmF0aW9uLgo+ICtmYW5YX2ZhdWx0CQkwOiBObyBmYWlsIGNvbmRpdGlvbgo+ICsJ -CQkxOiBGYWlsaW5nIGZhbgo+ICt0ZW1wWF9pbnB1dAkJTWVhc3VyZWQgYW1iaWVudCB0ZW1wZXJh -dHVyZS4KPiArdGVtcFhfbWF4CQlUaHJlc2hvbGQgYW1iaWVudCB0ZW1wZXJhdHVyZSBmb3IgYWxl -cnQgZ2VuZXJhdGlvbi4KPiAraW5YX2lucHV0CQlNZWFzdXJlZCBwb3dlciBzdXBwbHkgdm9sdGFn -ZQo+ICtpblhfZmF1bHQJCTA6IE5vIGZhaWwgY29uZGl0aW9uLgo+ICsJCQkxOiBGYWlsaW5nIHBv -d2VyIHN1cHBseS4KPiArcG93ZXIxX2lucHV0CQlTeXN0ZW0gcG93ZXIgY29uc3VtcHRpb24gKG1p -Y3JvV2F0dCkKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmlnIGIvZHJpdmVycy9o -d21vbi9LY29uZmlnCj4gaW5kZXggMDJkM2Q4NS4uMjljM2ZjYiAxMDA2NDQKPiAtLS0gYS9kcml2 -ZXJzL2h3bW9uL0tjb25maWcKPiArKysgYi9kcml2ZXJzL2h3bW9uL0tjb25maWcKPiBAQCAtNTU0 -LDYgKzU1NCwxNyBAQCBjb25maWcgU0VOU09SU19JQk1QRVgKPiAgIAkgIFRoaXMgZHJpdmVyIGNh -biBhbHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiAgSWYgc28sIHRoZSBtb2R1bGUKPiAgIAkgIHdp -bGwgYmUgY2FsbGVkIGlibXBleC4KPgo+ICtjb25maWcgU0VOU09SU19JQk1QT1dFUk5WCj4gKwl0 -cmlzdGF0ZSAiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIKPiArCWRlcGVuZHMgb24gUFBD -X1BPV0VSTlYKPiArCWRlZmF1bHQgeQo+ICsJaGVscAo+ICsJICBJZiB5b3Ugc2F5IHllcyBoZXJl -IHlvdSBnZXQgc3VwcG9ydCBmb3IgdGhlIHRlbXBlcmF0dXJlL2Zhbi9wb3dlcgo+ICsJICBzZW5z -b3JzIG9uIHlvdXIgUG93ZXJOViBwbGF0Zm9ybS4KPiArCj4gKwkgIFRoaXMgZHJpdmVyIGNhbiBh -bHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiBJZiBzbywgdGhlIG1vZHVsZQo+ICsJICB3aWxsIGJl -IGNhbGxlZCBpYm1wb3dlcm52Lgo+ICsKPiAgIGNvbmZpZyBTRU5TT1JTX0lJT19IV01PTgo+ICAg -CXRyaXN0YXRlICJId21vbiBkcml2ZXIgdGhhdCB1c2VzIGNoYW5uZWxzIHNwZWNpZmllZCB2aWEg -aWlvIG1hcHMiCj4gICAJZGVwZW5kcyBvbiBJSU8KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21v -bi9NYWtlZmlsZSBiL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPiBpbmRleCAzZGMwZjAyLi5mYzRl -ZDI2IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPiArKysgYi9kcml2ZXJz -L2h3bW9uL01ha2VmaWxlCj4gQEAgLTcxLDYgKzcxLDcgQEAgb2JqLSQoQ09ORklHX1NFTlNPUlNf -VUxUUkE0NSkJKz0gdWx0cmE0NV9lbnYubwo+ICAgb2JqLSQoQ09ORklHX1NFTlNPUlNfSTVLX0FN -QikJKz0gaTVrX2FtYi5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JQk1BRU0pCSs9IGlibWFl -bS5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JQk1QRVgpCSs9IGlibXBleC5vCj4gK29iai0k -KENPTkZJR19TRU5TT1JTX0lCTVBPV0VSTlYpKz0gaWJtcG93ZXJudi5vCj4gICBvYmotJChDT05G -SUdfU0VOU09SU19JSU9fSFdNT04pICs9IGlpb19od21vbi5vCj4gICBvYmotJChDT05GSUdfU0VO -U09SU19JTkEyMDkpCSs9IGluYTIwOS5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JTkEyWFgp -CSs9IGluYTJ4eC5vCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jIGIv -ZHJpdmVycy9od21vbi9pYm1wb3dlcm52LmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4 -IDAwMDAwMDAuLjQ0ZGNkOTkKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy9od21vbi9p -Ym1wb3dlcm52LmMKPiBAQCAtMCwwICsxLDM2MiBAQAo+ICsvKgo+ICsgKiBJQk0gUG93ZXJOViBw -bGF0Zm9ybSBzZW5zb3JzIGZvciB0ZW1wZXJhdHVyZS9mYW4vdm9sdGFnZS9wb3dlcgo+ICsgKiBD -b3B5cmlnaHQgKEMpIDIwMTQgSUJNCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNv -ZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5Cj4gKyAqIGl0IHVu -ZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlz -aGVkIGJ5Cj4gKyAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9u -IDIgb2YgdGhlIExpY2Vuc2UsIG9yCj4gKyAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZl -cnNpb24uCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9w -ZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAo+ICsgKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7 -IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgo+ICsgKiBNRVJDSEFOVEFCSUxJ -VFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCj4gKyAqIEdO -VSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCj4gKyAqCj4gKyAqIFlv -dSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBM -aWNlbnNlCj4gKyAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtLgo+ICsgKi8KPiArCj4gKyNkZWZp -bmUgRFJWTkFNRQkJImlibXBvd2VybnYiCj4gKyNkZWZpbmUgcHJfZm10KGZtdCkJRFJWTkFNRSAi -OiAiIGZtdAo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KPiArI2luY2x1ZGUgPGxpbnV4 -L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgva2VybmVsLmg+Cj4gKyNpbmNsdWRlIDxsaW51 -eC9od21vbi5oPgo+ICsjaW5jbHVkZSA8bGludXgvaHdtb24tc3lzZnMuaD4KPiArI2luY2x1ZGUg -PGxpbnV4L29mLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cj4gKwo+ICsjaW5jbHVkZSA8 -bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4gKyNpbmNsdWRlIDxhc20vb3BhbC5oPgo+ICsjaW5j -bHVkZSA8bGludXgvZXJyLmg+Cj4gKwo+ICsjZGVmaW5lIE1BWF9BVFRSX0xFTgkzMgo+ICsKPiAr -LyogU2Vuc29yIHN1ZmZpeCBuYW1lIGZyb20gRFQgKi8KPiArI2RlZmluZSBEVF9GQVVMVF9BVFRS -X1NVRkZJWAkJImZhdWx0ZWQiCj4gKyNkZWZpbmUgRFRfREFUQV9BVFRSX1NVRkZJWAkJImRhdGEi -Cj4gKyNkZWZpbmUgRFRfVEhSRVNIT0xEX0FUVFJfU1VGRklYCSJ0aHJzIgo+ICsKPiArLyoKPiAr -ICogRW51bWVyYXRlcyBhbGwgdGhlIHR5cGVzIG9mIHNlbnNvcnMgaW4gdGhlIFBPV0VSTlYgcGxh -dGZvcm0gYW5kIGRvZXMgaW5kZXgKPiArICogaW50byAnc3RydWN0IHNlbnNvcl9ncm91cCcKPiAr -ICovCj4gK2VudW0gc2Vuc29ycyB7Cj4gKwlGQU4sCj4gKwlBTUJJRU5UX1RFTVAsCj4gKwlQT1dF -Ul9TVVBQTFksCj4gKwlQT1dFUl9JTlBVVCwKPiArCU1BWF9TRU5TT1JfVFlQRSwKPiArfTsKPiAr -Cj4gK3N0YXRpYyBzdHJ1Y3Qgc2Vuc29yX2dyb3VwIHsKPiArCWNvbnN0IGNoYXIgKm5hbWU7Cj4g -Kwljb25zdCBjaGFyICpjb21wYXRpYmxlOwo+ICsJc3RydWN0IGF0dHJpYnV0ZV9ncm91cCBncm91 -cDsKPiArCXUzMiBhdHRyX2NvdW50Owo+ICt9IHNlbnNvcl9ncm91cHNbXSA9IHsKPiArCXsiZmFu -IiwgImlibSxvcGFsLXNlbnNvci1jb29saW5nLWZhbiJ9LAo+ICsJeyJ0ZW1wIiwgImlibSxvcGFs -LXNlbnNvci1hbWItdGVtcCJ9LAo+ICsJeyJpbiIsICJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3Vw -cGx5In0sCj4gKwl7InBvd2VyIiwgImlibSxvcGFsLXNlbnNvci1wb3dlciJ9Cj4gK307Cj4gKwo+ -ICtzdHJ1Y3Qgc2Vuc29yX2RhdGEgewo+ICsJdTMyIGlkOyAvKiBBbiBvcGFxdWUgaWQgb2YgdGhl -IGZpcm13YXJlIGZvciBlYWNoIHNlbnNvciAqLwo+ICsJZW51bSBzZW5zb3JzIHR5cGU7Cj4gKwlj -aGFyIG5hbWVbTUFYX0FUVFJfTEVOXTsKPiArCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlIGRldl9h -dHRyOwo+ICt9Owo+ICsKPiArc3RydWN0IHBsYXRmb3JtX2RhdGEgewo+ICsJY29uc3Qgc3RydWN0 -IGF0dHJpYnV0ZV9ncm91cCAqYXR0cl9ncm91cHNbTUFYX1NFTlNPUl9UWVBFICsgMV07Cj4gKwl1 -MzIgc2Vuc29yc19jb3VudDsgLyogVG90YWwgY291bnQgb2Ygc2Vuc29ycyBmcm9tIGVhY2ggZ3Jv -dXAgKi8KPiArfTsKPiArCj4gKy8qIFBsYXRmb3JtIGRldmljZSByZXByZXNlbnRpbmcgYWxsIHRo -ZSBpYm1wb3dlcm52IHNlbnNvcnMgKi8KPiArc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2Ug -KnBkZXZpY2U7Cj4gKwo+ICtzdGF0aWMgc3NpemVfdCBzaG93X3NlbnNvcihzdHJ1Y3QgZGV2aWNl -ICpkZXYsIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkZXZhdHRyLAo+ICsJCQkgICBjaGFyICpi -dWYpCj4gK3sKPiArCXN0cnVjdCBzZW5zb3JfZGF0YSAqc2RhdGEgPSBjb250YWluZXJfb2YoZGV2 -YXR0ciwgc3RydWN0IHNlbnNvcl9kYXRhLAo+ICsJCQkJCQkgZGV2X2F0dHIpOwo+ICsJc3NpemVf -dCByZXQ7Cj4gKwl1MzIgeDsKPiArCj4gKwlyZXQgPSBvcGFsX2dldF9zZW5zb3JfZGF0YShzZGF0 -YS0+aWQsICZ4KTsKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwkvKiBDb252 -ZXJ0IHRlbXBlcmF0dXJlIHRvIG1pbGxpLWRlZ3JlZXMgKi8KPiArCWlmIChzZGF0YS0+dHlwZSA9 -PSBBTUJJRU5UX1RFTVApCj4gKwkJeCAqPSAxMDAwOwo+ICsJLyogQ29udmVydCBwb3dlciB0byBt -aWNyby13YXR0cyAqLwo+ICsJZWxzZSBpZiAoc2RhdGEtPnR5cGUgPT0gUE9XRVJfSU5QVVQpCj4g -KwkJeCAqPSAxMDAwMDAwOwo+ICsKPiArCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiV1XG4iLCB4KTsK -PiArfQo+ICsKPiArc3RhdGljIGludCBfX2luaXQgZ2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0 -IGNoYXIgKm5hbWUsIHUzMiAqaW5kZXgsCj4gKwkJCQkJY2hhciAqYXR0cikKPiArewo+ICsJY2hh -ciAqaGFzaF9wb3MgPSBzdHJjaHIobmFtZSwgJyMnKTsKPiArCWNoYXIgYnVmWzhdID0geyAwIH07 -Cj4gKwljaGFyICpkYXNoX3BvczsKPiArCXUzMiBjb3B5X2xlbjsKPiArCj4gKwlpZiAoIWhhc2hf -cG9zKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCWRhc2hfcG9zID0gc3RyY2hyKGhhc2hf -cG9zLCAnLScpOwo+ICsJaWYgKCFkYXNoX3BvcykKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4g -Kwljb3B5X2xlbiA9IGRhc2hfcG9zIC0gaGFzaF9wb3MgLSAxOwo+ICsJaWYgKGNvcHlfbGVuID49 -IHNpemVvZihidWYpKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXN0cm5jcHkoYnVmLCBo -YXNoX3BvcyArIDEsIGNvcHlfbGVuKTsKPiArCj4gKwlpZiAoa3N0cnRvdTMyKGJ1ZiwgMTAsIGlu -ZGV4KSkKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCnNtYXRjaCBpc24ndCBnb2luZyB0byBsaWtl -IHRoYXQuIFBsZWFzZSB1c2UKCglpbnQgZXJyOwoJLi4uCgllcnIgPSBrc3RydG91MzIoYnVmLCAx -MCwgaW5kZXgpKTsKCWlmIChlcnIpCgkJcmV0dXJuIGVycjsKCj4gKwlzdHJuY3B5KGF0dHIsIGRh -c2hfcG9zICsgMSwgTUFYX0FUVFJfTEVOKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiAr -LyoKPiArICogVGhpcyBmdW5jdGlvbiB0cmFuc2xhdGVzIHRoZSBEVCBub2RlIG5hbWUgaW50byB0 -aGUgJ2h3bW9uJyBhdHRyaWJ1dGUgbmFtZS4KPiArICogSUJNUE9XRVJOViBkZXZpY2Ugbm9kZSBh -cHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIGFtYi10ZW1wIzEtdGhycyBldGMuCj4gKyAq -IHdoaWNoIG5lZWQgdG8gYmUgbWFwcGVkIGFzIGZhbjJfaW5wdXQsIHRlbXAxX21heCByZXNwZWN0 -aXZlbHkgYmVmb3JlCj4gKyAqIHBvcHVsYXRpbmcgdGhlbSBpbnNpZGUgaHdtb24gZGV2aWNlIGNs -YXNzLgo+ICsgKi8KPiArc3RhdGljIGludCBfX2luaXQgY3JlYXRlX2h3bW9uX2F0dHJfbmFtZShz -dHJ1Y3QgZGV2aWNlICpkZXYsIGVudW0gc2Vuc29ycyB0eXBlLAo+ICsJCQkJCSBjb25zdCBjaGFy -ICpub2RlX25hbWUsCj4gKwkJCQkJIGNoYXIgKmh3bW9uX2F0dHJfbmFtZSkKPiArewo+ICsJY2hh -ciBhdHRyX3N1ZmZpeFtNQVhfQVRUUl9MRU5dOwo+ICsJY2hhciAqYXR0cl9uYW1lOwo+ICsJdTMy -IGluZGV4Owo+ICsJaW50IGVycjsKPiArCj4gKwllcnIgPSBnZXRfc2Vuc29yX2luZGV4X2F0dHIo -bm9kZV9uYW1lLCAmaW5kZXgsIGF0dHJfc3VmZml4KTsKPiArCWlmIChlcnIpIHsKPiArCQlkZXZf -ZXJyKGRldiwgIlNlbnNvciBkZXZpY2Ugbm9kZSBuYW1lICclcycgaXMgaW52YWxpZFxuIiwKPiAr -CQkJbm9kZV9uYW1lKTsKPiArCQlyZXR1cm4gZXJyOwo+ICsJfQo+ICsKPiArCWlmICghc3RyY21w -KGF0dHJfc3VmZml4LCBEVF9GQVVMVF9BVFRSX1NVRkZJWCkpIHsKPiArCQlhdHRyX25hbWUgPSAi -ZmF1bHQiOwo+ICsJfSBlbHNlIGlmICghc3RyY21wKGF0dHJfc3VmZml4LCBEVF9EQVRBX0FUVFJf -U1VGRklYKSkgewo+ICsJCWF0dHJfbmFtZSA9ICJpbnB1dCI7Cj4gKwl9IGVsc2UgaWYgKCFzdHJj -bXAoYXR0cl9zdWZmaXgsIERUX1RIUkVTSE9MRF9BVFRSX1NVRkZJWCkpIHsKPiArCQlpZiAodHlw -ZSA9PSBBTUJJRU5UX1RFTVApCj4gKwkJCWF0dHJfbmFtZSA9ICJtYXgiOwo+ICsJCWVsc2UgaWYg -KHR5cGUgPT0gRkFOKQo+ICsJCQlhdHRyX25hbWUgPSAibWluIjsKPiArCQllbHNlCj4gKwkJCXJl -dHVybiAtRU5PRU5UOwo+ICsJfSBlbHNlIHsKPiArCQlyZXR1cm4gLUVOT0VOVDsKPiArCX0KPiAr -Cj4gKwlzbnByaW50Zihod21vbl9hdHRyX25hbWUsIE1BWF9BVFRSX0xFTiwgIiVzJWRfJXMiLAo+ -ICsJCSBzZW5zb3JfZ3JvdXBzW3R5cGVdLm5hbWUsIGluZGV4LCBhdHRyX25hbWUpOwo+ICsJcmV0 -dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgX19pbml0IHBvcHVsYXRlX2F0dHJfZ3JvdXBz -KHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiArCXN0cnVjdCBwbGF0Zm9ybV9k -YXRhICpwZGF0YSA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ICsJY29uc3Qgc3RydWN0 -IGF0dHJpYnV0ZV9ncm91cCAqKnBncm91cHMgPSBwZGF0YS0+YXR0cl9ncm91cHM7Cj4gKwlzdHJ1 -Y3QgZGV2aWNlX25vZGUgKm9wYWwsICpucDsKPiArCWVudW0gc2Vuc29ycyB0eXBlOwo+ICsKPiAr -CW9wYWwgPSBvZl9maW5kX25vZGVfYnlfcGF0aCgiL2libSxvcGFsL3NlbnNvcnMiKTsKPiArCWlm -ICghb3BhbCkgewo+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgIk9wYWwgbm9kZSAnc2Vuc29ycycg -bm90IGZvdW5kXG4iKTsKPiArCQlyZXR1cm4gLUVOT0RFVjsKPiArCX0KPiArCj4gKwlmb3JfZWFj -aF9jaGlsZF9vZl9ub2RlKG9wYWwsIG5wKSB7Cj4gKwkJaWYgKG5wLT5uYW1lID09IE5VTEwpCj4g -KwkJCWNvbnRpbnVlOwo+ICsKPiArCQlmb3IgKHR5cGUgPSAwOyB0eXBlIDwgTUFYX1NFTlNPUl9U -WVBFOyB0eXBlKyspCj4gKwkJCWlmIChvZl9kZXZpY2VfaXNfY29tcGF0aWJsZShucCwKPiArCQkJ -CQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmNvbXBhdGlibGUpKSB7Cj4gKwkJCQlzZW5zb3JfZ3JvdXBz -W3R5cGVdLmF0dHJfY291bnQrKzsKPiArCQkJCWJyZWFrOwo+ICsJCQl9Cj4gKwl9Cj4gKwo+ICsJ -b2Zfbm9kZV9wdXQob3BhbCk7Cj4gKwo+ICsJZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5T -T1JfVFlQRTsgdHlwZSsrKSB7Cj4gKwkJc2Vuc29yX2dyb3Vwc1t0eXBlXS5ncm91cC5hdHRycyA9 -IGRldm1fa3phbGxvYygmcGRldi0+ZGV2LAo+ICsJCQkJCXNpemVvZihzdHJ1Y3QgYXR0cmlidXRl -ICopICoKPiArCQkJCQkoc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRyX2NvdW50ICsgMSksCj4gKwkJ -CQkJR0ZQX0tFUk5FTCk7Cj4gKwkJaWYgKCFzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJz -KQo+ICsJCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwkJcGdyb3Vwc1t0eXBlXSA9ICZzZW5zb3Jf -Z3JvdXBzW3R5cGVdLmdyb3VwOwo+ICsJCXBkYXRhLT5zZW5zb3JzX2NvdW50ICs9IHNlbnNvcl9n -cm91cHNbdHlwZV0uYXR0cl9jb3VudDsKPiArCQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmF0dHJfY291 -bnQgPSAwOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICsvKgo+ICsgKiBJdGVy -YXRlIHRocm91Z2ggdGhlIGRldmljZSB0cmVlIGZvciBlYWNoIGNoaWxkIG9mICdzZW5zb3JzJyBu -b2RlLCBjcmVhdGUKPiArICogYSBzeXNmcyBhdHRyaWJ1dGUgZmlsZSwgdGhlIGZpbGUgaXMgbmFt -ZWQgYnkgdHJhbnNsYXRpbmcgdGhlIERUIG5vZGUgbmFtZQo+ICsgKiB0byB0aGUgbmFtZSByZXF1 -aXJlZCBieSB0aGUgaGlnaGVyICdod21vbicgZHJpdmVyIGxpa2UgZmFuMV9pbnB1dCwgdGVtcDFf -bWF4Cj4gKyAqIGV0Yy4uCj4gKyAqLwo+ICtzdGF0aWMgaW50IF9faW5pdCBjcmVhdGVfZGV2aWNl -X2F0dHJzKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiArCXN0cnVjdCBwbGF0 -Zm9ybV9kYXRhICpwZGF0YSA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ICsJY29uc3Qg -c3RydWN0IGF0dHJpYnV0ZV9ncm91cCAqKnBncm91cHMgPSBwZGF0YS0+YXR0cl9ncm91cHM7Cj4g -KwlzdHJ1Y3QgZGV2aWNlX25vZGUgKm9wYWwsICpucDsKPiArCXN0cnVjdCBzZW5zb3JfZGF0YSAq -c2RhdGE7Cj4gKwljb25zdCBfX2JlMzIgKnNlbnNvcl9pZDsKPiArCWVudW0gc2Vuc29ycyB0eXBl -Owo+ICsJdTMyIGNvdW50ID0gMDsKPiArCWludCBlcnIgPSAwOwo+ICsKPiArCW9wYWwgPSBvZl9m -aW5kX25vZGVfYnlfcGF0aCgiL2libSxvcGFsL3NlbnNvcnMiKTsKPiArCXNkYXRhID0gZGV2bV9r -emFsbG9jKCZwZGV2LT5kZXYsIHBkYXRhLT5zZW5zb3JzX2NvdW50ICogc2l6ZW9mKCpzZGF0YSks -Cj4gKwkJCSAgICAgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIXNkYXRhKSB7Cj4gKwkJZXJyID0gLUVO -T01FTTsKPiArCQlnb3RvIGV4aXRfcHV0X25vZGU7Cj4gKwl9Cj4gKwo+ICsJZm9yX2VhY2hfY2hp -bGRfb2Zfbm9kZShvcGFsLCBucCkgewo+ICsJCWlmIChucC0+bmFtZSA9PSBOVUxMKQo+ICsJCQlj -b250aW51ZTsKPiArCj4gKwkJZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5TT1JfVFlQRTsg -dHlwZSsrKQo+ICsJCQlpZiAob2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCj4gKwkJCQkJc2Vu -c29yX2dyb3Vwc1t0eXBlXS5jb21wYXRpYmxlKSkKPiArCQkJCWJyZWFrOwo+ICsKPiArCQlpZiAo -dHlwZSA9PSBNQVhfU0VOU09SX1RZUEUpCj4gKwkJCWNvbnRpbnVlOwo+ICsKPiArCQlzZW5zb3Jf -aWQgPSBvZl9nZXRfcHJvcGVydHkobnAsICJzZW5zb3ItaWQiLCBOVUxMKTsKPiArCQlpZiAoIXNl -bnNvcl9pZCkgewo+ICsJCQlkZXZfaW5mbygmcGRldi0+ZGV2LAo+ICsJCQkJICInc2Vuc29yLWlk -JyBtaXNzaW5nIGluIHRoZSBub2RlICclcydcbiIsCj4gKwkJCQkgbnAtPm5hbWUpOwo+ICsJCQlj -b250aW51ZTsKPiArCQl9Cj4gKwo+ICsJCXNkYXRhW2NvdW50XS5pZCA9IGJlMzJfdG9fY3B1cChz -ZW5zb3JfaWQpOwo+ICsJCXNkYXRhW2NvdW50XS50eXBlID0gdHlwZTsKPiArCQllcnIgPSBjcmVh -dGVfaHdtb25fYXR0cl9uYW1lKCZwZGV2LT5kZXYsIHR5cGUsIG5wLT5uYW1lLAo+ICsJCQkJCSAg -ICAgc2RhdGFbY291bnRdLm5hbWUpOwo+ICsJCWlmIChlcnIpCj4gKwkJCWdvdG8gZXhpdF9wdXRf -bm9kZTsKPiArCj4gKwkJc3lzZnNfYXR0cl9pbml0KCZzZGF0YVtjb3VudF0uZGV2X2F0dHIuYXR0 -cik7Cj4gKwkJc2RhdGFbY291bnRdLmRldl9hdHRyLmF0dHIubmFtZSA9IHNkYXRhW2NvdW50XS5u -YW1lOwo+ICsJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5hdHRyLm1vZGUgPSBTX0lSVUdPOwo+ICsJ -CXNkYXRhW2NvdW50XS5kZXZfYXR0ci5zaG93ID0gc2hvd19zZW5zb3I7Cj4gKwo+ICsJCXBncm91 -cHNbdHlwZV0tPmF0dHJzW3NlbnNvcl9ncm91cHNbdHlwZV0uYXR0cl9jb3VudCsrXSA9Cj4gKwkJ -CQkmc2RhdGFbY291bnQrK10uZGV2X2F0dHIuYXR0cjsKPiArCX0KPiArCj4gK2V4aXRfcHV0X25v -ZGU6Cj4gKwlvZl9ub2RlX3B1dChvcGFsKTsKPiArCXJldHVybiBlcnI7Cj4gK30KPiArCj4gK3N0 -YXRpYyBpbnQgX19pbml0IGlibXBvd2VybnZfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAq -cGRldikKPiArewo+ICsJc3RydWN0IHBsYXRmb3JtX2RhdGEgKnBkYXRhOwo+ICsJc3RydWN0IGRl -dmljZSAqaHdtb25fZGV2Owo+ICsJaW50IGVycjsKPiArCj4gKwlwZGF0YSA9IGRldm1fa3phbGxv -YygmcGRldi0+ZGV2LCBzaXplb2YoKnBkYXRhKSwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIXBkYXRh -KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYs -IHBkYXRhKTsKPiArCXBkYXRhLT5zZW5zb3JzX2NvdW50ID0gMDsKPiArCWVyciA9IHBvcHVsYXRl -X2F0dHJfZ3JvdXBzKHBkZXYpOwo+ICsJaWYgKGVycikKPiArCQlyZXR1cm4gZXJyOwo+ICsKPiAr -CS8qIENyZWF0ZSBzeXNmcyBhdHRyaWJ1dGUgZGF0YSBmb3IgZWFjaCBzZW5zb3IgZm91bmQgaW4g -dGhlIERUICovCj4gKwllcnIgPSBjcmVhdGVfZGV2aWNlX2F0dHJzKHBkZXYpOwo+ICsJaWYgKGVy -cikKPiArCQlyZXR1cm4gZXJyOwo+ICsKPiArCS8qIEZpbmFsbHksIHJlZ2lzdGVyIHdpdGggaHdt -b24gKi8KPiArCWh3bW9uX2RldiA9IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhfZ3Jv -dXBzKCZwZGV2LT5kZXYsIERSVk5BTUUsCj4gKwkJCQkJCQkgICBwZGF0YSwKPiArCQkJCQkJCSAg -IHBkYXRhLT5hdHRyX2dyb3Vwcyk7Cj4gKwo+ICsJcmV0dXJuIFBUUl9FUlJfT1JfWkVSTyhod21v -bl9kZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBpYm1wb3dl -cm52X2RyaXZlciA9IHsKPiArCS5kcml2ZXIgPSB7Cj4gKwkJLm93bmVyID0gVEhJU19NT0RVTEUs -Cj4gKwkJLm5hbWUgPSBEUlZOQU1FLAo+ICsJfSwKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgX19p -bml0IGlibXBvd2VybnZfaW5pdCh2b2lkKQo+ICt7Cj4gKwlpbnQgZXJyOwo+ICsKPiArCXBkZXZp -Y2UgPSBwbGF0Zm9ybV9kZXZpY2VfYWxsb2MoRFJWTkFNRSwgMCk7Cj4gKwlpZiAoIXBkZXZpY2Up -IHsKPiArCQlwcl9lcnIoIkRldmljZSBhbGxvY2F0aW9uIGZhaWxlZFxuIik7Cj4gKwkJZXJyID0g -LUVOT01FTTsKPiArCQlnb3RvIGV4aXQ7Cj4gKwl9Cj4gKwo+ICsJZXJyID0gcGxhdGZvcm1fZGV2 -aWNlX2FkZChwZGV2aWNlKTsKPiArCWlmIChlcnIpIHsKPiArCQlwcl9lcnIoIkRldmljZSBhZGRp -dGlvbiBmYWlsZWQgKCVkKVxuIiwgZXJyKTsKPiArCQlnb3RvIGV4aXRfZGV2aWNlX3B1dDsKPiAr -CX0KPiArCj4gKwllcnIgPSBwbGF0Zm9ybV9kcml2ZXJfcHJvYmUoJmlibXBvd2VybnZfZHJpdmVy -LCBpYm1wb3dlcm52X3Byb2JlKTsKPiArCWlmIChlcnIpIHsKPiArCQlwcl9lcnIoIlBsYXRmcm9t -IGRyaXZlciBwcm9iZSBmYWlsZWRcbiIpOwo+ICsJCWdvdG8gZXhpdF9kZXZpY2VfZGVsOwo+ICsJ -fQo+ICsKPiArCXJldHVybiAwOwo+ICsKPiArZXhpdF9kZXZpY2VfZGVsOgo+ICsJcGxhdGZvcm1f -ZGV2aWNlX2RlbChwZGV2aWNlKTsKPiArZXhpdF9kZXZpY2VfcHV0Ogo+ICsJcGxhdGZvcm1fZGV2 -aWNlX3B1dChwZGV2aWNlKTsKPiArZXhpdDoKPiArCXJldHVybiBlcnI7Cj4gK30KPiArCj4gK3N0 -YXRpYyB2b2lkIF9fZXhpdCBpYm1wb3dlcm52X2V4aXQodm9pZCkKPiArewo+ICsJcGxhdGZvcm1f -ZHJpdmVyX3VucmVnaXN0ZXIoJmlibXBvd2VybnZfZHJpdmVyKTsKPiArCXBsYXRmb3JtX2Rldmlj -ZV91bnJlZ2lzdGVyKHBkZXZpY2UpOwo+ICt9Cj4gKwo+ICtNT0RVTEVfQVVUSE9SKCJOZWVsZXNo -IEd1cHRhIDxuZWVsZWd1cEBsaW51eC52bmV0LmlibS5jb20+Iik7Cj4gK01PRFVMRV9ERVNDUklQ -VElPTigiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIpOwo+ICtNT0RVTEVfTElDRU5TRSgi -R1BMIik7Cj4gKwo+ICttb2R1bGVfaW5pdChpYm1wb3dlcm52X2luaXQpOwo+ICttb2R1bGVfZXhp -dChpYm1wb3dlcm52X2V4aXQpOwo+Cj4KPgoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19f -X19fX19fX19fX19fX19fX19fCmxtLXNlbnNvcnMgbWFpbGluZyBsaXN0CmxtLXNlbnNvcnNAbG0t -c2Vuc29ycy5vcmcKaHR0cDovL2xpc3RzLmxtLXNlbnNvcnMub3JnL21haWxtYW4vbGlzdGluZm8v -bG0tc2Vuc29ycw= +On 07/04/2014 04:02 AM, Neelesh Gupta wrote: +> This patch adds basic kernel support for reading power values, fan +> speed rpm, voltage and temperature data on powernv platforms which will +> be exported to user space through sysfs interface. +> + +Hi Neelesh, + +Copying devicetree mailing list. Please copy it on the next (hopefully final) +revision; devicetree maintainers at least need a chance to comment. +[ Yes, I understand this is a shipping product, but still ... ] + +I am ok with the code except for a couple of minor nitpicks (see below). + +Thanks, +Guenter + +> Test results: +> ------------- +> [root@tul163p1 ~]# sensors +> ibmpowernv-isa-0000 +> Adapter: ISA adapter +> fan1: 5567 RPM (min = 0 RPM) +> fan2: 5232 RPM (min = 0 RPM) +> fan3: 5532 RPM (min = 0 RPM) +> fan4: 4945 RPM (min = 0 RPM) +> fan5: 0 RPM (min = 0 RPM) +> fan6: 0 RPM (min = 0 RPM) +> fan7: 7392 RPM (min = 0 RPM) +> fan8: 7936 RPM (min = 0 RPM) +> temp1: +39.0°C (high = +0.0°C) +> power1: 191.00 W +> +> [root@tul163p1 ~]# ls /sys/devices/platform/ +> alarmtimer ibmpowernv.0 power rtc-generic serial8250 uevent +> [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/hwmon/hwmon0/ +> device fan2_min fan4_min fan6_min fan8_min power +> fan1_fault fan3_fault fan5_fault fan7_fault in1_fault power1_input +> fan1_input fan3_input fan5_input fan7_input in2_fault subsystem +> fan1_min fan3_min fan5_min fan7_min in3_fault temp1_input +> fan2_fault fan4_fault fan6_fault fan8_fault in4_fault temp1_max +> fan2_input fan4_input fan6_input fan8_input name uevent +> [root@tul163p1 ~]# +> [root@tul163p1 ~]# ls /sys/class/hwmon/hwmon0/ +> device fan2_min fan4_min fan6_min fan8_min power +> fan1_fault fan3_fault fan5_fault fan7_fault in1_fault power1_input +> fan1_input fan3_input fan5_input fan7_input in2_fault subsystem +> fan1_min fan3_min fan5_min fan7_min in3_fault temp1_input +> fan2_fault fan4_fault fan6_fault fan8_fault in4_fault temp1_max +> fan2_input fan4_input fan6_input fan8_input name uevent +> [root@tul163p1 ~]# +> +> Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com> +> --- +> +> Changes in v4 +> ============= +> - Replaced pr_err() with dev_err() for loggin print messages. +> - Using kstrtou32() function for converting string to u32 instead of sscanf(). +> +> Changes in v3 +> ============= +> - Fixed an endianness bug leading the driver to break on LE. +> - Fixed a bug that when one of the 'attribute_group' not populated, following +> groups attributes were dropped. +> - Rewrite the get_sensor_index_attr() function to handle all the error scenarios +> like 'sscanf' etc. +> - Fixed all the errors/warnings related to coding style/whitespace. +> - Added 'Documentation' files. +> - Addressed remaining review comments on V2. +> +> Changes in v2 +> ============= +> - Generic use of devm_* functions in hwmon like using devm_kzalloc() for dynamic +> memory request, avoiding the need to explicit free of memory. +> Adding 'struct attribute_group' as member of platform data structure to be +> populated and then passed to devm_hwmon_device_register_with_groups(). +> +> Note: Having an array of pointers of 'attribute_group' and each group +> corresponds to 'enum sensors' type. Not completely sure, if it's ideal or +> could have just one group populated with attributes of sensor types? +> +> - 'ibmpowernv' is not hot-pluggable device so moving 'platform_driver' callback +> function (probe) as part of __init code. +> - Fixed issues related to coding style. +> - Other general comments in v1. +> +> .../devicetree/bindings/hwmon/ibmpowernv.txt | 27 + +> Documentation/hwmon/ibmpowernv | 41 ++ +> drivers/hwmon/Kconfig | 11 + +> drivers/hwmon/Makefile | 1 +> drivers/hwmon/ibmpowernv.c | 362 ++++++++++++++++++++ +> 5 files changed, 442 insertions(+) +> create mode 100644 Documentation/devicetree/bindings/hwmon/ibmpowernv.txt +> create mode 100644 Documentation/hwmon/ibmpowernv +> create mode 100644 drivers/hwmon/ibmpowernv.c +> +> diff --git a/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt +> new file mode 100644 +> index 0000000..e3bd1eb +> --- /dev/null +> +++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt +> @@ -0,0 +1,27 @@ +> +IBM POWERNV platform sensors +> +---------------------------- +> + +> +Required node properties: +> +- compatible: must be one of +> + "ibm,opal-sensor-cooling-fan" +> + "ibm,opal-sensor-amb-temp" +> + "ibm,opal-sensor-power-supply" +> + "ibm,opal-sensor-power" +> +- sensor-id: an opaque id provided by the firmware to the kernel, identifies a +> + given sensor and its attribute data +> + +> +Example sensors node: +> + +> +cooling-fan#8-data { +> + sensor-id = <0x7052107>; +> + phandle = <0x10000028>; +> + linux,phandle = <0x10000028>; +> + compatible = "ibm,opal-sensor-cooling-fan"; + +phandle and linux-phandle are neither documented nor used. Either document or drop. + +> +}; +> + +> +amb-temp#1-thrs { +> + sensor-id = <0x5096000>; +> + phandle = <0x10000017>; +> + linux,phandle = <0x10000017>; +> + compatible = "ibm,opal-sensor-amb-temp"; +> +}; +> diff --git a/Documentation/hwmon/ibmpowernv b/Documentation/hwmon/ibmpowernv +> new file mode 100644 +> index 0000000..644245a +> --- /dev/null +> +++ b/Documentation/hwmon/ibmpowernv +> @@ -0,0 +1,41 @@ +> +Kernel Driver IBMPOWENV +> +======================= +> + +> +Supported systems: +> + * Any recent IBM P servers based on POWERNV platform +> + +> +Author: Neelesh Gupta +> + +> +Description +> +----------- +> + +> +This driver implements reading the platform sensors data like temperature/fan/ +> +voltage/power for 'POWERNV' platform. +> + +> +The driver uses the platform device infrastructure. It probes the device tree +> +for sensor devices during the __init phase and registers them with the 'hwmon'. +> +'hwmon' populates the 'sysfs' tree having attribute files, each for a given +> +sensor type and its attribute data. +> + +> +All the nodes in the DT appear under "/ibm,opal/sensors" and each valid node in +> +the DT maps to an attribute file in 'sysfs'. The node exports unique 'sensor-id' +> +which the driver uses to make an OPAL call to the firmware. +> + +> +Usage notes +> +----------- +> +The driver is built statically with the kernel by enabling the config +> +CONFIG_SENSORS_IBMPOWERNV. It can also be built as module 'ibmpowernv'. +> + +> +Sysfs attributes +> +---------------- +> + +> +fanX_input Measured RPM value. +> +fanX_min Threshold RPM for alert generation. +> +fanX_fault 0: No fail condition +> + 1: Failing fan +> +tempX_input Measured ambient temperature. +> +tempX_max Threshold ambient temperature for alert generation. +> +inX_input Measured power supply voltage +> +inX_fault 0: No fail condition. +> + 1: Failing power supply. +> +power1_input System power consumption (microWatt) +> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +> index 02d3d85..29c3fcb 100644 +> --- a/drivers/hwmon/Kconfig +> +++ b/drivers/hwmon/Kconfig +> @@ -554,6 +554,17 @@ config SENSORS_IBMPEX +> This driver can also be built as a module. If so, the module +> will be called ibmpex. +> +> +config SENSORS_IBMPOWERNV +> + tristate "IBM POWERNV platform sensors" +> + depends on PPC_POWERNV +> + default y +> + help +> + If you say yes here you get support for the temperature/fan/power +> + sensors on your PowerNV platform. +> + +> + This driver can also be built as a module. If so, the module +> + will be called ibmpowernv. +> + +> config SENSORS_IIO_HWMON +> tristate "Hwmon driver that uses channels specified via iio maps" +> depends on IIO +> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +> index 3dc0f02..fc4ed26 100644 +> --- a/drivers/hwmon/Makefile +> +++ b/drivers/hwmon/Makefile +> @@ -71,6 +71,7 @@ obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o +> obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o +> obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o +> obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o +> +obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o +> obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o +> obj-$(CONFIG_SENSORS_INA209) += ina209.o +> obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o +> diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c +> new file mode 100644 +> index 0000000..44dcd99 +> --- /dev/null +> +++ b/drivers/hwmon/ibmpowernv.c +> @@ -0,0 +1,362 @@ +> +/* +> + * IBM PowerNV platform sensors for temperature/fan/voltage/power +> + * Copyright (C) 2014 IBM +> + * +> + * This program is free software; you can redistribute it and/or modify +> + * it under the terms of the GNU General Public License as published by +> + * the Free Software Foundation; either version 2 of the License, or +> + * (at your option) any later version. +> + * +> + * This program is distributed in the hope that it will be useful, +> + * but WITHOUT ANY WARRANTY; without even the implied warranty of +> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +> + * GNU General Public License for more details. +> + * +> + * You should have received a copy of the GNU General Public License +> + * along with this program. +> + */ +> + +> +#define DRVNAME "ibmpowernv" +> +#define pr_fmt(fmt) DRVNAME ": " fmt +> + +> +#include <linux/init.h> +> +#include <linux/module.h> +> +#include <linux/kernel.h> +> +#include <linux/hwmon.h> +> +#include <linux/hwmon-sysfs.h> +> +#include <linux/of.h> +> +#include <linux/slab.h> +> + +> +#include <linux/platform_device.h> +> +#include <asm/opal.h> +> +#include <linux/err.h> +> + +> +#define MAX_ATTR_LEN 32 +> + +> +/* Sensor suffix name from DT */ +> +#define DT_FAULT_ATTR_SUFFIX "faulted" +> +#define DT_DATA_ATTR_SUFFIX "data" +> +#define DT_THRESHOLD_ATTR_SUFFIX "thrs" +> + +> +/* +> + * Enumerates all the types of sensors in the POWERNV platform and does index +> + * into 'struct sensor_group' +> + */ +> +enum sensors { +> + FAN, +> + AMBIENT_TEMP, +> + POWER_SUPPLY, +> + POWER_INPUT, +> + MAX_SENSOR_TYPE, +> +}; +> + +> +static struct sensor_group { +> + const char *name; +> + const char *compatible; +> + struct attribute_group group; +> + u32 attr_count; +> +} sensor_groups[] = { +> + {"fan", "ibm,opal-sensor-cooling-fan"}, +> + {"temp", "ibm,opal-sensor-amb-temp"}, +> + {"in", "ibm,opal-sensor-power-supply"}, +> + {"power", "ibm,opal-sensor-power"} +> +}; +> + +> +struct sensor_data { +> + u32 id; /* An opaque id of the firmware for each sensor */ +> + enum sensors type; +> + char name[MAX_ATTR_LEN]; +> + struct device_attribute dev_attr; +> +}; +> + +> +struct platform_data { +> + const struct attribute_group *attr_groups[MAX_SENSOR_TYPE + 1]; +> + u32 sensors_count; /* Total count of sensors from each group */ +> +}; +> + +> +/* Platform device representing all the ibmpowernv sensors */ +> +static struct platform_device *pdevice; +> + +> +static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr, +> + char *buf) +> +{ +> + struct sensor_data *sdata = container_of(devattr, struct sensor_data, +> + dev_attr); +> + ssize_t ret; +> + u32 x; +> + +> + ret = opal_get_sensor_data(sdata->id, &x); +> + if (ret) +> + return ret; +> + +> + /* Convert temperature to milli-degrees */ +> + if (sdata->type == AMBIENT_TEMP) +> + x *= 1000; +> + /* Convert power to micro-watts */ +> + else if (sdata->type == POWER_INPUT) +> + x *= 1000000; +> + +> + return sprintf(buf, "%u\n", x); +> +} +> + +> +static int __init get_sensor_index_attr(const char *name, u32 *index, +> + char *attr) +> +{ +> + char *hash_pos = strchr(name, '#'); +> + char buf[8] = { 0 }; +> + char *dash_pos; +> + u32 copy_len; +> + +> + if (!hash_pos) +> + return -EINVAL; +> + +> + dash_pos = strchr(hash_pos, '-'); +> + if (!dash_pos) +> + return -EINVAL; +> + +> + copy_len = dash_pos - hash_pos - 1; +> + if (copy_len >= sizeof(buf)) +> + return -EINVAL; +> + +> + strncpy(buf, hash_pos + 1, copy_len); +> + +> + if (kstrtou32(buf, 10, index)) +> + return -EINVAL; +> + +smatch isn't going to like that. Please use + + int err; + ... + err = kstrtou32(buf, 10, index)); + if (err) + return err; + +> + strncpy(attr, dash_pos + 1, MAX_ATTR_LEN); +> + +> + return 0; +> +} +> + +> +/* +> + * This function translates the DT node name into the 'hwmon' attribute name. +> + * IBMPOWERNV device node appear like cooling-fan#2-data, amb-temp#1-thrs etc. +> + * which need to be mapped as fan2_input, temp1_max respectively before +> + * populating them inside hwmon device class. +> + */ +> +static int __init create_hwmon_attr_name(struct device *dev, enum sensors type, +> + const char *node_name, +> + char *hwmon_attr_name) +> +{ +> + char attr_suffix[MAX_ATTR_LEN]; +> + char *attr_name; +> + u32 index; +> + int err; +> + +> + err = get_sensor_index_attr(node_name, &index, attr_suffix); +> + if (err) { +> + dev_err(dev, "Sensor device node name '%s' is invalid\n", +> + node_name); +> + return err; +> + } +> + +> + if (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX)) { +> + attr_name = "fault"; +> + } else if (!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX)) { +> + attr_name = "input"; +> + } else if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) { +> + if (type == AMBIENT_TEMP) +> + attr_name = "max"; +> + else if (type == FAN) +> + attr_name = "min"; +> + else +> + return -ENOENT; +> + } else { +> + return -ENOENT; +> + } +> + +> + snprintf(hwmon_attr_name, MAX_ATTR_LEN, "%s%d_%s", +> + sensor_groups[type].name, index, attr_name); +> + return 0; +> +} +> + +> +static int __init populate_attr_groups(struct platform_device *pdev) +> +{ +> + struct platform_data *pdata = platform_get_drvdata(pdev); +> + const struct attribute_group **pgroups = pdata->attr_groups; +> + struct device_node *opal, *np; +> + enum sensors type; +> + +> + opal = of_find_node_by_path("/ibm,opal/sensors"); +> + if (!opal) { +> + dev_err(&pdev->dev, "Opal node 'sensors' not found\n"); +> + return -ENODEV; +> + } +> + +> + for_each_child_of_node(opal, np) { +> + if (np->name == NULL) +> + continue; +> + +> + for (type = 0; type < MAX_SENSOR_TYPE; type++) +> + if (of_device_is_compatible(np, +> + sensor_groups[type].compatible)) { +> + sensor_groups[type].attr_count++; +> + break; +> + } +> + } +> + +> + of_node_put(opal); +> + +> + for (type = 0; type < MAX_SENSOR_TYPE; type++) { +> + sensor_groups[type].group.attrs = devm_kzalloc(&pdev->dev, +> + sizeof(struct attribute *) * +> + (sensor_groups[type].attr_count + 1), +> + GFP_KERNEL); +> + if (!sensor_groups[type].group.attrs) +> + return -ENOMEM; +> + +> + pgroups[type] = &sensor_groups[type].group; +> + pdata->sensors_count += sensor_groups[type].attr_count; +> + sensor_groups[type].attr_count = 0; +> + } +> + +> + return 0; +> +} +> + +> +/* +> + * Iterate through the device tree for each child of 'sensors' node, create +> + * a sysfs attribute file, the file is named by translating the DT node name +> + * to the name required by the higher 'hwmon' driver like fan1_input, temp1_max +> + * etc.. +> + */ +> +static int __init create_device_attrs(struct platform_device *pdev) +> +{ +> + struct platform_data *pdata = platform_get_drvdata(pdev); +> + const struct attribute_group **pgroups = pdata->attr_groups; +> + struct device_node *opal, *np; +> + struct sensor_data *sdata; +> + const __be32 *sensor_id; +> + enum sensors type; +> + u32 count = 0; +> + int err = 0; +> + +> + opal = of_find_node_by_path("/ibm,opal/sensors"); +> + sdata = devm_kzalloc(&pdev->dev, pdata->sensors_count * sizeof(*sdata), +> + GFP_KERNEL); +> + if (!sdata) { +> + err = -ENOMEM; +> + goto exit_put_node; +> + } +> + +> + for_each_child_of_node(opal, np) { +> + if (np->name == NULL) +> + continue; +> + +> + for (type = 0; type < MAX_SENSOR_TYPE; type++) +> + if (of_device_is_compatible(np, +> + sensor_groups[type].compatible)) +> + break; +> + +> + if (type == MAX_SENSOR_TYPE) +> + continue; +> + +> + sensor_id = of_get_property(np, "sensor-id", NULL); +> + if (!sensor_id) { +> + dev_info(&pdev->dev, +> + "'sensor-id' missing in the node '%s'\n", +> + np->name); +> + continue; +> + } +> + +> + sdata[count].id = be32_to_cpup(sensor_id); +> + sdata[count].type = type; +> + err = create_hwmon_attr_name(&pdev->dev, type, np->name, +> + sdata[count].name); +> + if (err) +> + goto exit_put_node; +> + +> + sysfs_attr_init(&sdata[count].dev_attr.attr); +> + sdata[count].dev_attr.attr.name = sdata[count].name; +> + sdata[count].dev_attr.attr.mode = S_IRUGO; +> + sdata[count].dev_attr.show = show_sensor; +> + +> + pgroups[type]->attrs[sensor_groups[type].attr_count++] = +> + &sdata[count++].dev_attr.attr; +> + } +> + +> +exit_put_node: +> + of_node_put(opal); +> + return err; +> +} +> + +> +static int __init ibmpowernv_probe(struct platform_device *pdev) +> +{ +> + struct platform_data *pdata; +> + struct device *hwmon_dev; +> + int err; +> + +> + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); +> + if (!pdata) +> + return -ENOMEM; +> + +> + platform_set_drvdata(pdev, pdata); +> + pdata->sensors_count = 0; +> + err = populate_attr_groups(pdev); +> + if (err) +> + return err; +> + +> + /* Create sysfs attribute data for each sensor found in the DT */ +> + err = create_device_attrs(pdev); +> + if (err) +> + return err; +> + +> + /* Finally, register with hwmon */ +> + hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, DRVNAME, +> + pdata, +> + pdata->attr_groups); +> + +> + return PTR_ERR_OR_ZERO(hwmon_dev); +> +} +> + +> +static struct platform_driver ibmpowernv_driver = { +> + .driver = { +> + .owner = THIS_MODULE, +> + .name = DRVNAME, +> + }, +> +}; +> + +> +static int __init ibmpowernv_init(void) +> +{ +> + int err; +> + +> + pdevice = platform_device_alloc(DRVNAME, 0); +> + if (!pdevice) { +> + pr_err("Device allocation failed\n"); +> + err = -ENOMEM; +> + goto exit; +> + } +> + +> + err = platform_device_add(pdevice); +> + if (err) { +> + pr_err("Device addition failed (%d)\n", err); +> + goto exit_device_put; +> + } +> + +> + err = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe); +> + if (err) { +> + pr_err("Platfrom driver probe failed\n"); +> + goto exit_device_del; +> + } +> + +> + return 0; +> + +> +exit_device_del: +> + platform_device_del(pdevice); +> +exit_device_put: +> + platform_device_put(pdevice); +> +exit: +> + return err; +> +} +> + +> +static void __exit ibmpowernv_exit(void) +> +{ +> + platform_driver_unregister(&ibmpowernv_driver); +> + platform_device_unregister(pdevice); +> +} +> + +> +MODULE_AUTHOR("Neelesh Gupta <neelegup@linux.vnet.ibm.com>"); +> +MODULE_DESCRIPTION("IBM POWERNV platform sensors"); +> +MODULE_LICENSE("GPL"); +> + +> +module_init(ibmpowernv_init); +> +module_exit(ibmpowernv_exit); +> +> +> diff --git a/a/content_digest b/N1/content_digest index 0e5210b..7e20c0f 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -1,347 +1,607 @@ "ref\020140704105343.22437.52125.stgit@localhost.localdomain\0" - "ref\020140704105343.22437.52125.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org\0" "From\0Guenter Roeck <linux@roeck-us.net>\0" - "Subject\0Re: [lm-sensors] [PATCH v4] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperatur\0" - "Date\0Sat, 05 Jul 2014 02:25:36 +0000\0" - "To\0Neelesh Gupta <neelegup-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>" - linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org - jdelvare-l3A5Bk7waGM@public.gmane.org - " lm-sensors-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org\0" - "Cc\0benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org" - svaidy-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org - sbhat-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org - " devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org <devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>\0" + "Subject\0Re: [PATCH v4] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature\0" + "Date\0Fri, 04 Jul 2014 19:25:36 -0700\0" + "To\0Neelesh Gupta <neelegup@linux.vnet.ibm.com>" + linuxppc-dev@lists.ozlabs.org + jdelvare@suse.de + " lm-sensors@lm-sensors.org\0" + "Cc\0sbhat@linux.vnet.ibm.com" + " devicetree@vger.kernel.org <devicetree@vger.kernel.org>\0" "\00:1\0" "b\0" - "T24gMDcvMDQvMjAxNCAwNDowMiBBTSwgTmVlbGVzaCBHdXB0YSB3cm90ZToKPiBUaGlzIHBhdGNo\n" - "IGFkZHMgYmFzaWMga2VybmVsIHN1cHBvcnQgZm9yIHJlYWRpbmcgcG93ZXIgdmFsdWVzLCBmYW4K\n" - "PiBzcGVlZCBycG0sIHZvbHRhZ2UgYW5kIHRlbXBlcmF0dXJlIGRhdGEgb24gcG93ZXJudiBwbGF0\n" - "Zm9ybXMgd2hpY2ggd2lsbAo+IGJlIGV4cG9ydGVkIHRvIHVzZXIgc3BhY2UgdGhyb3VnaCBzeXNm\n" - "cyBpbnRlcmZhY2UuCj4KCkhpIE5lZWxlc2gsCgpDb3B5aW5nIGRldmljZXRyZWUgbWFpbGluZyBs\n" - "aXN0LiBQbGVhc2UgY29weSBpdCBvbiB0aGUgbmV4dCAoaG9wZWZ1bGx5IGZpbmFsKQpyZXZpc2lv\n" - "bjsgZGV2aWNldHJlZSBtYWludGFpbmVycyBhdCBsZWFzdCBuZWVkIGEgY2hhbmNlIHRvIGNvbW1l\n" - "bnQuClsgWWVzLCBJIHVuZGVyc3RhbmQgdGhpcyBpcyBhIHNoaXBwaW5nIHByb2R1Y3QsIGJ1dCBz\n" - "dGlsbCAuLi4gXQoKSSBhbSBvayB3aXRoIHRoZSBjb2RlIGV4Y2VwdCBmb3IgYSBjb3VwbGUgb2Yg\n" - "bWlub3Igbml0cGlja3MgKHNlZSBiZWxvdykuCgpUaGFua3MsCkd1ZW50ZXIKCj4gVGVzdCByZXN1\n" - "bHRzOgo+IC0tLS0tLS0tLS0tLS0KPiBbcm9vdEB0dWwxNjNwMSB+XSMgc2Vuc29ycwo+IGlibXBv\n" - "d2VybnYtaXNhLTAwMDAKPiBBZGFwdGVyOiBJU0EgYWRhcHRlcgo+IGZhbjE6ICAgICAgICA1NTY3\n" - "IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjI6ICAgICAgICA1MjMyIFJQTSAgKG1pbiA9ICAg\n" - "IDAgUlBNKQo+IGZhbjM6ICAgICAgICA1NTMyIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjQ6\n" - "ICAgICAgICA0OTQ1IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjU6ICAgICAgICAgICAwIFJQ\n" - "TSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjY6ICAgICAgICAgICAwIFJQTSAgKG1pbiA9ICAgIDAg\n" - "UlBNKQo+IGZhbjc6ICAgICAgICA3MzkyIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjg6ICAg\n" - "ICAgICA3OTM2IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IHRlbXAxOiAgICAgICAgKzM5LjDCsEMg\n" - "IChoaWdoID0gICswLjDCsEMpCj4gcG93ZXIxOiAgICAgIDE5MS4wMCBXCj4KPiBbcm9vdEB0dWwx\n" - "NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtLwo+IGFsYXJtdGltZXIgIGlibXBvd2Vy\n" - "bnYuMCAgcG93ZXIgIHJ0Yy1nZW5lcmljICBzZXJpYWw4MjUwICB1ZXZlbnQKPiBbcm9vdEB0dWwx\n" - "NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtL2libXBvd2VybnYuMC9od21vbi9od21v\n" - "bjAvCj4gZGV2aWNlCSAgICBmYW4yX21pbglmYW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAg\n" - "IHBvd2VyCj4gZmFuMV9mYXVsdCAgZmFuM19mYXVsdAlmYW41X2ZhdWx0ICBmYW43X2ZhdWx0CWlu\n" - "MV9mYXVsdCAgcG93ZXIxX2lucHV0Cj4gZmFuMV9pbnB1dCAgZmFuM19pbnB1dAlmYW41X2lucHV0\n" - "ICBmYW43X2lucHV0CWluMl9mYXVsdCAgc3Vic3lzdGVtCj4gZmFuMV9taW4gICAgZmFuM19taW4J\n" - "ZmFuNV9taW4gICAgZmFuN19taW4JaW4zX2ZhdWx0ICB0ZW1wMV9pbnB1dAo+IGZhbjJfZmF1bHQg\n" - "IGZhbjRfZmF1bHQJZmFuNl9mYXVsdCAgZmFuOF9mYXVsdAlpbjRfZmF1bHQgIHRlbXAxX21heAo+\n" - "IGZhbjJfaW5wdXQgIGZhbjRfaW5wdXQJZmFuNl9pbnB1dCAgZmFuOF9pbnB1dAluYW1lCSAgIHVl\n" - "dmVudAo+IFtyb290QHR1bDE2M3AxIH5dIwo+IFtyb290QHR1bDE2M3AxIH5dIyBscyAvc3lzL2Ns\n" - "YXNzL2h3bW9uL2h3bW9uMC8KPiBkZXZpY2UJICAgIGZhbjJfbWluCWZhbjRfbWluICAgIGZhbjZf\n" - "bWluCWZhbjhfbWluICAgcG93ZXIKPiBmYW4xX2ZhdWx0ICBmYW4zX2ZhdWx0CWZhbjVfZmF1bHQg\n" - "IGZhbjdfZmF1bHQJaW4xX2ZhdWx0ICBwb3dlcjFfaW5wdXQKPiBmYW4xX2lucHV0ICBmYW4zX2lu\n" - "cHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5wdXQJaW4yX2ZhdWx0ICBzdWJzeXN0ZW0KPiBmYW4xX21p\n" - "biAgICBmYW4zX21pbglmYW41X21pbiAgICBmYW43X21pbglpbjNfZmF1bHQgIHRlbXAxX2lucHV0\n" - "Cj4gZmFuMl9mYXVsdCAgZmFuNF9mYXVsdAlmYW42X2ZhdWx0ICBmYW44X2ZhdWx0CWluNF9mYXVs\n" - "dCAgdGVtcDFfbWF4Cj4gZmFuMl9pbnB1dCAgZmFuNF9pbnB1dAlmYW42X2lucHV0ICBmYW44X2lu\n" - "cHV0CW5hbWUJICAgdWV2ZW50Cj4gW3Jvb3RAdHVsMTYzcDEgfl0jCj4KPiBTaWduZWQtb2ZmLWJ5\n" - "OiBOZWVsZXNoIEd1cHRhIDxuZWVsZWd1cEBsaW51eC52bmV0LmlibS5jb20+Cj4gLS0tCj4KPiBD\n" - "aGFuZ2VzIGluIHY0Cj4gPT09PT09PT09PT09PQo+IC0gUmVwbGFjZWQgcHJfZXJyKCkgd2l0aCBk\n" - "ZXZfZXJyKCkgZm9yIGxvZ2dpbiBwcmludCBtZXNzYWdlcy4KPiAtIFVzaW5nIGtzdHJ0b3UzMigp\n" - "IGZ1bmN0aW9uIGZvciBjb252ZXJ0aW5nIHN0cmluZyB0byB1MzIgaW5zdGVhZCBvZiBzc2NhbmYo\n" - "KS4KPgo+IENoYW5nZXMgaW4gdjMKPiA9PT09PT09PT09PT09Cj4gLSBGaXhlZCBhbiBlbmRpYW5u\n" - "ZXNzIGJ1ZyBsZWFkaW5nIHRoZSBkcml2ZXIgdG8gYnJlYWsgb24gTEUuCj4gLSBGaXhlZCBhIGJ1\n" - "ZyB0aGF0IHdoZW4gb25lIG9mIHRoZSAnYXR0cmlidXRlX2dyb3VwJyBub3QgcG9wdWxhdGVkLCBm\n" - "b2xsb3dpbmcKPiAgICBncm91cHMgYXR0cmlidXRlcyB3ZXJlIGRyb3BwZWQuCj4gLSBSZXdyaXRl\n" - "IHRoZSBnZXRfc2Vuc29yX2luZGV4X2F0dHIoKSBmdW5jdGlvbiB0byBoYW5kbGUgYWxsIHRoZSBl\n" - "cnJvciBzY2VuYXJpb3MKPiAgICBsaWtlICdzc2NhbmYnIGV0Yy4KPiAtIEZpeGVkIGFsbCB0aGUg\n" - "ZXJyb3JzL3dhcm5pbmdzIHJlbGF0ZWQgdG8gY29kaW5nIHN0eWxlL3doaXRlc3BhY2UuCj4gLSBB\n" - "ZGRlZCAnRG9jdW1lbnRhdGlvbicgZmlsZXMuCj4gLSBBZGRyZXNzZWQgcmVtYWluaW5nIHJldmll\n" - "dyBjb21tZW50cyBvbiBWMi4KPgo+IENoYW5nZXMgaW4gdjIKPiA9PT09PT09PT09PT09Cj4gLSBH\n" - "ZW5lcmljIHVzZSBvZiBkZXZtXyogZnVuY3Rpb25zIGluIGh3bW9uIGxpa2UgdXNpbmcgZGV2bV9r\n" - "emFsbG9jKCkgZm9yIGR5bmFtaWMKPiAgICBtZW1vcnkgcmVxdWVzdCwgYXZvaWRpbmcgdGhlIG5l\n" - "ZWQgdG8gZXhwbGljaXQgZnJlZSBvZiBtZW1vcnkuCj4gICAgQWRkaW5nICdzdHJ1Y3QgYXR0cmli\n" - "dXRlX2dyb3VwJyBhcyBtZW1iZXIgb2YgcGxhdGZvcm0gZGF0YSBzdHJ1Y3R1cmUgdG8gYmUKPiAg\n" - "ICBwb3B1bGF0ZWQgYW5kIHRoZW4gcGFzc2VkIHRvIGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVy\n" - "X3dpdGhfZ3JvdXBzKCkuCj4KPiAgICBOb3RlOiBIYXZpbmcgYW4gYXJyYXkgb2YgcG9pbnRlcnMg\n" - "b2YgJ2F0dHJpYnV0ZV9ncm91cCcgYW5kIGVhY2ggZ3JvdXAKPiAgICBjb3JyZXNwb25kcyB0byAn\n" - "ZW51bSBzZW5zb3JzJyB0eXBlLiBOb3QgY29tcGxldGVseSBzdXJlLCBpZiBpdCdzIGlkZWFsIG9y\n" - "Cj4gICAgY291bGQgaGF2ZSBqdXN0IG9uZSBncm91cCBwb3B1bGF0ZWQgd2l0aCBhdHRyaWJ1dGVz\n" - "IG9mIHNlbnNvciB0eXBlcz8KPgo+IC0gJ2libXBvd2VybnYnIGlzIG5vdCBob3QtcGx1Z2dhYmxl\n" - "IGRldmljZSBzbyBtb3ZpbmcgJ3BsYXRmb3JtX2RyaXZlcicgY2FsbGJhY2sKPiAgICBmdW5jdGlv\n" - "biAocHJvYmUpIGFzIHBhcnQgb2YgX19pbml0IGNvZGUuCj4gLSBGaXhlZCBpc3N1ZXMgcmVsYXRl\n" - "ZCB0byBjb2Rpbmcgc3R5bGUuCj4gLSBPdGhlciBnZW5lcmFsIGNvbW1lbnRzIGluIHYxLgo+Cj4g\n" - "ICAuLi4vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4dCAgICAgICB8ICAg\n" - "MjcgKwo+ICAgRG9jdW1lbnRhdGlvbi9od21vbi9pYm1wb3dlcm52ICAgICAgICAgICAgICAgICAg\n" - "ICAgfCAgIDQxICsrCj4gICBkcml2ZXJzL2h3bW9uL0tjb25maWcgICAgICAgICAgICAgICAgICAg\n" - "ICAgICAgICAgICB8ICAgMTEgKwo+ICAgZHJpdmVycy9od21vbi9NYWtlZmlsZSAgICAgICAgICAg\n" - "ICAgICAgICAgICAgICAgICAgfCAgICAxCj4gICBkcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYyAg\n" - "ICAgICAgICAgICAgICAgICAgICAgICB8ICAzNjIgKysrKysrKysrKysrKysrKysrKysKPiAgIDUg\n" - "ZmlsZXMgY2hhbmdlZCwgNDQyIGluc2VydGlvbnMoKykKPiAgIGNyZWF0ZSBtb2RlIDEwMDY0NCBE\n" - "b2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQKPiAg\n" - "IGNyZWF0ZSBtb2RlIDEwMDY0NCBEb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYKPiAgIGNy\n" - "ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYwo+Cj4gZGlmZiAtLWdp\n" - "dCBhL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4\n" - "dCBiL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4\n" - "dAo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uZTNiZDFlYgo+IC0tLSAv\n" - "ZGV2L251bGwKPiArKysgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvaHdtb24v\n" - "aWJtcG93ZXJudi50eHQKPiBAQCAtMCwwICsxLDI3IEBACj4gK0lCTSBQT1dFUk5WIHBsYXRmb3Jt\n" - "IHNlbnNvcnMKPiArLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo+ICsKPiArUmVxdWlyZWQg\n" - "bm9kZSBwcm9wZXJ0aWVzOgo+ICstIGNvbXBhdGlibGU6IG11c3QgYmUgb25lIG9mCj4gKwkJImli\n" - "bSxvcGFsLXNlbnNvci1jb29saW5nLWZhbiIKPiArCQkiaWJtLG9wYWwtc2Vuc29yLWFtYi10ZW1w\n" - "Igo+ICsJCSJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3VwcGx5Igo+ICsJCSJpYm0sb3BhbC1zZW5z\n" - "b3ItcG93ZXIiCj4gKy0gc2Vuc29yLWlkOiBhbiBvcGFxdWUgaWQgcHJvdmlkZWQgYnkgdGhlIGZp\n" - "cm13YXJlIHRvIHRoZSBrZXJuZWwsIGlkZW50aWZpZXMgYQo+ICsJICAgICBnaXZlbiBzZW5zb3Ig\n" - "YW5kIGl0cyBhdHRyaWJ1dGUgZGF0YQo+ICsKPiArRXhhbXBsZSBzZW5zb3JzIG5vZGU6Cj4gKwo+\n" - "ICtjb29saW5nLWZhbiM4LWRhdGEgewo+ICsJc2Vuc29yLWlkID0gPDB4NzA1MjEwNz47Cj4gKwlw\n" - "aGFuZGxlID0gPDB4MTAwMDAwMjg+Owo+ICsJbGludXgscGhhbmRsZSA9IDwweDEwMDAwMDI4PjsK\n" - "PiArCWNvbXBhdGlibGUgPSAiaWJtLG9wYWwtc2Vuc29yLWNvb2xpbmctZmFuIjsKCnBoYW5kbGUg\n" - "YW5kIGxpbnV4LXBoYW5kbGUgYXJlIG5laXRoZXIgZG9jdW1lbnRlZCBub3IgdXNlZC4gRWl0aGVy\n" - "IGRvY3VtZW50IG9yIGRyb3AuCgo+ICt9Owo+ICsKPiArYW1iLXRlbXAjMS10aHJzIHsKPiArCXNl\n" - "bnNvci1pZCA9IDwweDUwOTYwMDA+Owo+ICsJcGhhbmRsZSA9IDwweDEwMDAwMDE3PjsKPiArCWxp\n" - "bnV4LHBoYW5kbGUgPSA8MHgxMDAwMDAxNz47Cj4gKwljb21wYXRpYmxlID0gImlibSxvcGFsLXNl\n" - "bnNvci1hbWItdGVtcCI7Cj4gK307Cj4gZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24vaHdtb24v\n" - "aWJtcG93ZXJudiBiL0RvY3VtZW50YXRpb24vaHdtb24vaWJtcG93ZXJudgo+IG5ldyBmaWxlIG1v\n" - "ZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uNjQ0MjQ1YQo+IC0tLSAvZGV2L251bGwKPiArKysg\n" - "Yi9Eb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYKPiBAQCAtMCwwICsxLDQxIEBACj4gK0tl\n" - "cm5lbCBEcml2ZXIgSUJNUE9XRU5WCj4gKz09PT09PT09PT09PT09PT09PT09PT09Cj4gKwo+ICtT\n" - "dXBwb3J0ZWQgc3lzdGVtczoKPiArICAqIEFueSByZWNlbnQgSUJNIFAgc2VydmVycyBiYXNlZCBv\n" - "biBQT1dFUk5WIHBsYXRmb3JtCj4gKwo+ICtBdXRob3I6IE5lZWxlc2ggR3VwdGEKPiArCj4gK0Rl\n" - "c2NyaXB0aW9uCj4gKy0tLS0tLS0tLS0tCj4gKwo+ICtUaGlzIGRyaXZlciBpbXBsZW1lbnRzIHJl\n" - "YWRpbmcgdGhlIHBsYXRmb3JtIHNlbnNvcnMgZGF0YSBsaWtlIHRlbXBlcmF0dXJlL2Zhbi8KPiAr\n" - "dm9sdGFnZS9wb3dlciBmb3IgJ1BPV0VSTlYnIHBsYXRmb3JtLgo+ICsKPiArVGhlIGRyaXZlciB1\n" - "c2VzIHRoZSBwbGF0Zm9ybSBkZXZpY2UgaW5mcmFzdHJ1Y3R1cmUuIEl0IHByb2JlcyB0aGUgZGV2\n" - "aWNlIHRyZWUKPiArZm9yIHNlbnNvciBkZXZpY2VzIGR1cmluZyB0aGUgX19pbml0IHBoYXNlIGFu\n" - "ZCByZWdpc3RlcnMgdGhlbSB3aXRoIHRoZSAnaHdtb24nLgo+ICsnaHdtb24nIHBvcHVsYXRlcyB0\n" - "aGUgJ3N5c2ZzJyB0cmVlIGhhdmluZyBhdHRyaWJ1dGUgZmlsZXMsIGVhY2ggZm9yIGEgZ2l2ZW4K\n" - "PiArc2Vuc29yIHR5cGUgYW5kIGl0cyBhdHRyaWJ1dGUgZGF0YS4KPiArCj4gK0FsbCB0aGUgbm9k\n" - "ZXMgaW4gdGhlIERUIGFwcGVhciB1bmRlciAiL2libSxvcGFsL3NlbnNvcnMiIGFuZCBlYWNoIHZh\n" - "bGlkIG5vZGUgaW4KPiArdGhlIERUIG1hcHMgdG8gYW4gYXR0cmlidXRlIGZpbGUgaW4gJ3N5c2Zz\n" - "Jy4gVGhlIG5vZGUgZXhwb3J0cyB1bmlxdWUgJ3NlbnNvci1pZCcKPiArd2hpY2ggdGhlIGRyaXZl\n" - "ciB1c2VzIHRvIG1ha2UgYW4gT1BBTCBjYWxsIHRvIHRoZSBmaXJtd2FyZS4KPiArCj4gK1VzYWdl\n" - "IG5vdGVzCj4gKy0tLS0tLS0tLS0tCj4gK1RoZSBkcml2ZXIgaXMgYnVpbHQgc3RhdGljYWxseSB3\n" - "aXRoIHRoZSBrZXJuZWwgYnkgZW5hYmxpbmcgdGhlIGNvbmZpZwo+ICtDT05GSUdfU0VOU09SU19J\n" - "Qk1QT1dFUk5WLiBJdCBjYW4gYWxzbyBiZSBidWlsdCBhcyBtb2R1bGUgJ2libXBvd2VybnYnLgo+\n" - "ICsKPiArU3lzZnMgYXR0cmlidXRlcwo+ICstLS0tLS0tLS0tLS0tLS0tCj4gKwo+ICtmYW5YX2lu\n" - "cHV0CQlNZWFzdXJlZCBSUE0gdmFsdWUuCj4gK2ZhblhfbWluCQlUaHJlc2hvbGQgUlBNIGZvciBh\n" - "bGVydCBnZW5lcmF0aW9uLgo+ICtmYW5YX2ZhdWx0CQkwOiBObyBmYWlsIGNvbmRpdGlvbgo+ICsJ\n" - "CQkxOiBGYWlsaW5nIGZhbgo+ICt0ZW1wWF9pbnB1dAkJTWVhc3VyZWQgYW1iaWVudCB0ZW1wZXJh\n" - "dHVyZS4KPiArdGVtcFhfbWF4CQlUaHJlc2hvbGQgYW1iaWVudCB0ZW1wZXJhdHVyZSBmb3IgYWxl\n" - "cnQgZ2VuZXJhdGlvbi4KPiAraW5YX2lucHV0CQlNZWFzdXJlZCBwb3dlciBzdXBwbHkgdm9sdGFn\n" - "ZQo+ICtpblhfZmF1bHQJCTA6IE5vIGZhaWwgY29uZGl0aW9uLgo+ICsJCQkxOiBGYWlsaW5nIHBv\n" - "d2VyIHN1cHBseS4KPiArcG93ZXIxX2lucHV0CQlTeXN0ZW0gcG93ZXIgY29uc3VtcHRpb24gKG1p\n" - "Y3JvV2F0dCkKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmlnIGIvZHJpdmVycy9o\n" - "d21vbi9LY29uZmlnCj4gaW5kZXggMDJkM2Q4NS4uMjljM2ZjYiAxMDA2NDQKPiAtLS0gYS9kcml2\n" - "ZXJzL2h3bW9uL0tjb25maWcKPiArKysgYi9kcml2ZXJzL2h3bW9uL0tjb25maWcKPiBAQCAtNTU0\n" - "LDYgKzU1NCwxNyBAQCBjb25maWcgU0VOU09SU19JQk1QRVgKPiAgIAkgIFRoaXMgZHJpdmVyIGNh\n" - "biBhbHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiAgSWYgc28sIHRoZSBtb2R1bGUKPiAgIAkgIHdp\n" - "bGwgYmUgY2FsbGVkIGlibXBleC4KPgo+ICtjb25maWcgU0VOU09SU19JQk1QT1dFUk5WCj4gKwl0\n" - "cmlzdGF0ZSAiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIKPiArCWRlcGVuZHMgb24gUFBD\n" - "X1BPV0VSTlYKPiArCWRlZmF1bHQgeQo+ICsJaGVscAo+ICsJICBJZiB5b3Ugc2F5IHllcyBoZXJl\n" - "IHlvdSBnZXQgc3VwcG9ydCBmb3IgdGhlIHRlbXBlcmF0dXJlL2Zhbi9wb3dlcgo+ICsJICBzZW5z\n" - "b3JzIG9uIHlvdXIgUG93ZXJOViBwbGF0Zm9ybS4KPiArCj4gKwkgIFRoaXMgZHJpdmVyIGNhbiBh\n" - "bHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiBJZiBzbywgdGhlIG1vZHVsZQo+ICsJICB3aWxsIGJl\n" - "IGNhbGxlZCBpYm1wb3dlcm52Lgo+ICsKPiAgIGNvbmZpZyBTRU5TT1JTX0lJT19IV01PTgo+ICAg\n" - "CXRyaXN0YXRlICJId21vbiBkcml2ZXIgdGhhdCB1c2VzIGNoYW5uZWxzIHNwZWNpZmllZCB2aWEg\n" - "aWlvIG1hcHMiCj4gICAJZGVwZW5kcyBvbiBJSU8KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21v\n" - "bi9NYWtlZmlsZSBiL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPiBpbmRleCAzZGMwZjAyLi5mYzRl\n" - "ZDI2IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPiArKysgYi9kcml2ZXJz\n" - "L2h3bW9uL01ha2VmaWxlCj4gQEAgLTcxLDYgKzcxLDcgQEAgb2JqLSQoQ09ORklHX1NFTlNPUlNf\n" - "VUxUUkE0NSkJKz0gdWx0cmE0NV9lbnYubwo+ICAgb2JqLSQoQ09ORklHX1NFTlNPUlNfSTVLX0FN\n" - "QikJKz0gaTVrX2FtYi5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JQk1BRU0pCSs9IGlibWFl\n" - "bS5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JQk1QRVgpCSs9IGlibXBleC5vCj4gK29iai0k\n" - "KENPTkZJR19TRU5TT1JTX0lCTVBPV0VSTlYpKz0gaWJtcG93ZXJudi5vCj4gICBvYmotJChDT05G\n" - "SUdfU0VOU09SU19JSU9fSFdNT04pICs9IGlpb19od21vbi5vCj4gICBvYmotJChDT05GSUdfU0VO\n" - "U09SU19JTkEyMDkpCSs9IGluYTIwOS5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JTkEyWFgp\n" - "CSs9IGluYTJ4eC5vCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jIGIv\n" - "ZHJpdmVycy9od21vbi9pYm1wb3dlcm52LmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4\n" - "IDAwMDAwMDAuLjQ0ZGNkOTkKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy9od21vbi9p\n" - "Ym1wb3dlcm52LmMKPiBAQCAtMCwwICsxLDM2MiBAQAo+ICsvKgo+ICsgKiBJQk0gUG93ZXJOViBw\n" - "bGF0Zm9ybSBzZW5zb3JzIGZvciB0ZW1wZXJhdHVyZS9mYW4vdm9sdGFnZS9wb3dlcgo+ICsgKiBD\n" - "b3B5cmlnaHQgKEMpIDIwMTQgSUJNCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNv\n" - "ZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5Cj4gKyAqIGl0IHVu\n" - "ZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlz\n" - "aGVkIGJ5Cj4gKyAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9u\n" - "IDIgb2YgdGhlIExpY2Vuc2UsIG9yCj4gKyAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZl\n" - "cnNpb24uCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9w\n" - "ZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAo+ICsgKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7\n" - "IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgo+ICsgKiBNRVJDSEFOVEFCSUxJ\n" - "VFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCj4gKyAqIEdO\n" - "VSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCj4gKyAqCj4gKyAqIFlv\n" - "dSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBM\n" - "aWNlbnNlCj4gKyAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtLgo+ICsgKi8KPiArCj4gKyNkZWZp\n" - "bmUgRFJWTkFNRQkJImlibXBvd2VybnYiCj4gKyNkZWZpbmUgcHJfZm10KGZtdCkJRFJWTkFNRSAi\n" - "OiAiIGZtdAo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KPiArI2luY2x1ZGUgPGxpbnV4\n" - "L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgva2VybmVsLmg+Cj4gKyNpbmNsdWRlIDxsaW51\n" - "eC9od21vbi5oPgo+ICsjaW5jbHVkZSA8bGludXgvaHdtb24tc3lzZnMuaD4KPiArI2luY2x1ZGUg\n" - "PGxpbnV4L29mLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cj4gKwo+ICsjaW5jbHVkZSA8\n" - "bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4gKyNpbmNsdWRlIDxhc20vb3BhbC5oPgo+ICsjaW5j\n" - "bHVkZSA8bGludXgvZXJyLmg+Cj4gKwo+ICsjZGVmaW5lIE1BWF9BVFRSX0xFTgkzMgo+ICsKPiAr\n" - "LyogU2Vuc29yIHN1ZmZpeCBuYW1lIGZyb20gRFQgKi8KPiArI2RlZmluZSBEVF9GQVVMVF9BVFRS\n" - "X1NVRkZJWAkJImZhdWx0ZWQiCj4gKyNkZWZpbmUgRFRfREFUQV9BVFRSX1NVRkZJWAkJImRhdGEi\n" - "Cj4gKyNkZWZpbmUgRFRfVEhSRVNIT0xEX0FUVFJfU1VGRklYCSJ0aHJzIgo+ICsKPiArLyoKPiAr\n" - "ICogRW51bWVyYXRlcyBhbGwgdGhlIHR5cGVzIG9mIHNlbnNvcnMgaW4gdGhlIFBPV0VSTlYgcGxh\n" - "dGZvcm0gYW5kIGRvZXMgaW5kZXgKPiArICogaW50byAnc3RydWN0IHNlbnNvcl9ncm91cCcKPiAr\n" - "ICovCj4gK2VudW0gc2Vuc29ycyB7Cj4gKwlGQU4sCj4gKwlBTUJJRU5UX1RFTVAsCj4gKwlQT1dF\n" - "Ul9TVVBQTFksCj4gKwlQT1dFUl9JTlBVVCwKPiArCU1BWF9TRU5TT1JfVFlQRSwKPiArfTsKPiAr\n" - "Cj4gK3N0YXRpYyBzdHJ1Y3Qgc2Vuc29yX2dyb3VwIHsKPiArCWNvbnN0IGNoYXIgKm5hbWU7Cj4g\n" - "Kwljb25zdCBjaGFyICpjb21wYXRpYmxlOwo+ICsJc3RydWN0IGF0dHJpYnV0ZV9ncm91cCBncm91\n" - "cDsKPiArCXUzMiBhdHRyX2NvdW50Owo+ICt9IHNlbnNvcl9ncm91cHNbXSA9IHsKPiArCXsiZmFu\n" - "IiwgImlibSxvcGFsLXNlbnNvci1jb29saW5nLWZhbiJ9LAo+ICsJeyJ0ZW1wIiwgImlibSxvcGFs\n" - "LXNlbnNvci1hbWItdGVtcCJ9LAo+ICsJeyJpbiIsICJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3Vw\n" - "cGx5In0sCj4gKwl7InBvd2VyIiwgImlibSxvcGFsLXNlbnNvci1wb3dlciJ9Cj4gK307Cj4gKwo+\n" - "ICtzdHJ1Y3Qgc2Vuc29yX2RhdGEgewo+ICsJdTMyIGlkOyAvKiBBbiBvcGFxdWUgaWQgb2YgdGhl\n" - "IGZpcm13YXJlIGZvciBlYWNoIHNlbnNvciAqLwo+ICsJZW51bSBzZW5zb3JzIHR5cGU7Cj4gKwlj\n" - "aGFyIG5hbWVbTUFYX0FUVFJfTEVOXTsKPiArCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlIGRldl9h\n" - "dHRyOwo+ICt9Owo+ICsKPiArc3RydWN0IHBsYXRmb3JtX2RhdGEgewo+ICsJY29uc3Qgc3RydWN0\n" - "IGF0dHJpYnV0ZV9ncm91cCAqYXR0cl9ncm91cHNbTUFYX1NFTlNPUl9UWVBFICsgMV07Cj4gKwl1\n" - "MzIgc2Vuc29yc19jb3VudDsgLyogVG90YWwgY291bnQgb2Ygc2Vuc29ycyBmcm9tIGVhY2ggZ3Jv\n" - "dXAgKi8KPiArfTsKPiArCj4gKy8qIFBsYXRmb3JtIGRldmljZSByZXByZXNlbnRpbmcgYWxsIHRo\n" - "ZSBpYm1wb3dlcm52IHNlbnNvcnMgKi8KPiArc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2Ug\n" - "KnBkZXZpY2U7Cj4gKwo+ICtzdGF0aWMgc3NpemVfdCBzaG93X3NlbnNvcihzdHJ1Y3QgZGV2aWNl\n" - "ICpkZXYsIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkZXZhdHRyLAo+ICsJCQkgICBjaGFyICpi\n" - "dWYpCj4gK3sKPiArCXN0cnVjdCBzZW5zb3JfZGF0YSAqc2RhdGEgPSBjb250YWluZXJfb2YoZGV2\n" - "YXR0ciwgc3RydWN0IHNlbnNvcl9kYXRhLAo+ICsJCQkJCQkgZGV2X2F0dHIpOwo+ICsJc3NpemVf\n" - "dCByZXQ7Cj4gKwl1MzIgeDsKPiArCj4gKwlyZXQgPSBvcGFsX2dldF9zZW5zb3JfZGF0YShzZGF0\n" - "YS0+aWQsICZ4KTsKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwkvKiBDb252\n" - "ZXJ0IHRlbXBlcmF0dXJlIHRvIG1pbGxpLWRlZ3JlZXMgKi8KPiArCWlmIChzZGF0YS0+dHlwZSA9\n" - "PSBBTUJJRU5UX1RFTVApCj4gKwkJeCAqPSAxMDAwOwo+ICsJLyogQ29udmVydCBwb3dlciB0byBt\n" - "aWNyby13YXR0cyAqLwo+ICsJZWxzZSBpZiAoc2RhdGEtPnR5cGUgPT0gUE9XRVJfSU5QVVQpCj4g\n" - "KwkJeCAqPSAxMDAwMDAwOwo+ICsKPiArCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiV1XG4iLCB4KTsK\n" - "PiArfQo+ICsKPiArc3RhdGljIGludCBfX2luaXQgZ2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0\n" - "IGNoYXIgKm5hbWUsIHUzMiAqaW5kZXgsCj4gKwkJCQkJY2hhciAqYXR0cikKPiArewo+ICsJY2hh\n" - "ciAqaGFzaF9wb3MgPSBzdHJjaHIobmFtZSwgJyMnKTsKPiArCWNoYXIgYnVmWzhdID0geyAwIH07\n" - "Cj4gKwljaGFyICpkYXNoX3BvczsKPiArCXUzMiBjb3B5X2xlbjsKPiArCj4gKwlpZiAoIWhhc2hf\n" - "cG9zKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCWRhc2hfcG9zID0gc3RyY2hyKGhhc2hf\n" - "cG9zLCAnLScpOwo+ICsJaWYgKCFkYXNoX3BvcykKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4g\n" - "Kwljb3B5X2xlbiA9IGRhc2hfcG9zIC0gaGFzaF9wb3MgLSAxOwo+ICsJaWYgKGNvcHlfbGVuID49\n" - "IHNpemVvZihidWYpKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXN0cm5jcHkoYnVmLCBo\n" - "YXNoX3BvcyArIDEsIGNvcHlfbGVuKTsKPiArCj4gKwlpZiAoa3N0cnRvdTMyKGJ1ZiwgMTAsIGlu\n" - "ZGV4KSkKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCnNtYXRjaCBpc24ndCBnb2luZyB0byBsaWtl\n" - "IHRoYXQuIFBsZWFzZSB1c2UKCglpbnQgZXJyOwoJLi4uCgllcnIgPSBrc3RydG91MzIoYnVmLCAx\n" - "MCwgaW5kZXgpKTsKCWlmIChlcnIpCgkJcmV0dXJuIGVycjsKCj4gKwlzdHJuY3B5KGF0dHIsIGRh\n" - "c2hfcG9zICsgMSwgTUFYX0FUVFJfTEVOKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiAr\n" - "LyoKPiArICogVGhpcyBmdW5jdGlvbiB0cmFuc2xhdGVzIHRoZSBEVCBub2RlIG5hbWUgaW50byB0\n" - "aGUgJ2h3bW9uJyBhdHRyaWJ1dGUgbmFtZS4KPiArICogSUJNUE9XRVJOViBkZXZpY2Ugbm9kZSBh\n" - "cHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIGFtYi10ZW1wIzEtdGhycyBldGMuCj4gKyAq\n" - "IHdoaWNoIG5lZWQgdG8gYmUgbWFwcGVkIGFzIGZhbjJfaW5wdXQsIHRlbXAxX21heCByZXNwZWN0\n" - "aXZlbHkgYmVmb3JlCj4gKyAqIHBvcHVsYXRpbmcgdGhlbSBpbnNpZGUgaHdtb24gZGV2aWNlIGNs\n" - "YXNzLgo+ICsgKi8KPiArc3RhdGljIGludCBfX2luaXQgY3JlYXRlX2h3bW9uX2F0dHJfbmFtZShz\n" - "dHJ1Y3QgZGV2aWNlICpkZXYsIGVudW0gc2Vuc29ycyB0eXBlLAo+ICsJCQkJCSBjb25zdCBjaGFy\n" - "ICpub2RlX25hbWUsCj4gKwkJCQkJIGNoYXIgKmh3bW9uX2F0dHJfbmFtZSkKPiArewo+ICsJY2hh\n" - "ciBhdHRyX3N1ZmZpeFtNQVhfQVRUUl9MRU5dOwo+ICsJY2hhciAqYXR0cl9uYW1lOwo+ICsJdTMy\n" - "IGluZGV4Owo+ICsJaW50IGVycjsKPiArCj4gKwllcnIgPSBnZXRfc2Vuc29yX2luZGV4X2F0dHIo\n" - "bm9kZV9uYW1lLCAmaW5kZXgsIGF0dHJfc3VmZml4KTsKPiArCWlmIChlcnIpIHsKPiArCQlkZXZf\n" - "ZXJyKGRldiwgIlNlbnNvciBkZXZpY2Ugbm9kZSBuYW1lICclcycgaXMgaW52YWxpZFxuIiwKPiAr\n" - "CQkJbm9kZV9uYW1lKTsKPiArCQlyZXR1cm4gZXJyOwo+ICsJfQo+ICsKPiArCWlmICghc3RyY21w\n" - "KGF0dHJfc3VmZml4LCBEVF9GQVVMVF9BVFRSX1NVRkZJWCkpIHsKPiArCQlhdHRyX25hbWUgPSAi\n" - "ZmF1bHQiOwo+ICsJfSBlbHNlIGlmICghc3RyY21wKGF0dHJfc3VmZml4LCBEVF9EQVRBX0FUVFJf\n" - "U1VGRklYKSkgewo+ICsJCWF0dHJfbmFtZSA9ICJpbnB1dCI7Cj4gKwl9IGVsc2UgaWYgKCFzdHJj\n" - "bXAoYXR0cl9zdWZmaXgsIERUX1RIUkVTSE9MRF9BVFRSX1NVRkZJWCkpIHsKPiArCQlpZiAodHlw\n" - "ZSA9PSBBTUJJRU5UX1RFTVApCj4gKwkJCWF0dHJfbmFtZSA9ICJtYXgiOwo+ICsJCWVsc2UgaWYg\n" - "KHR5cGUgPT0gRkFOKQo+ICsJCQlhdHRyX25hbWUgPSAibWluIjsKPiArCQllbHNlCj4gKwkJCXJl\n" - "dHVybiAtRU5PRU5UOwo+ICsJfSBlbHNlIHsKPiArCQlyZXR1cm4gLUVOT0VOVDsKPiArCX0KPiAr\n" - "Cj4gKwlzbnByaW50Zihod21vbl9hdHRyX25hbWUsIE1BWF9BVFRSX0xFTiwgIiVzJWRfJXMiLAo+\n" - "ICsJCSBzZW5zb3JfZ3JvdXBzW3R5cGVdLm5hbWUsIGluZGV4LCBhdHRyX25hbWUpOwo+ICsJcmV0\n" - "dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgX19pbml0IHBvcHVsYXRlX2F0dHJfZ3JvdXBz\n" - "KHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiArCXN0cnVjdCBwbGF0Zm9ybV9k\n" - "YXRhICpwZGF0YSA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ICsJY29uc3Qgc3RydWN0\n" - "IGF0dHJpYnV0ZV9ncm91cCAqKnBncm91cHMgPSBwZGF0YS0+YXR0cl9ncm91cHM7Cj4gKwlzdHJ1\n" - "Y3QgZGV2aWNlX25vZGUgKm9wYWwsICpucDsKPiArCWVudW0gc2Vuc29ycyB0eXBlOwo+ICsKPiAr\n" - "CW9wYWwgPSBvZl9maW5kX25vZGVfYnlfcGF0aCgiL2libSxvcGFsL3NlbnNvcnMiKTsKPiArCWlm\n" - "ICghb3BhbCkgewo+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgIk9wYWwgbm9kZSAnc2Vuc29ycycg\n" - "bm90IGZvdW5kXG4iKTsKPiArCQlyZXR1cm4gLUVOT0RFVjsKPiArCX0KPiArCj4gKwlmb3JfZWFj\n" - "aF9jaGlsZF9vZl9ub2RlKG9wYWwsIG5wKSB7Cj4gKwkJaWYgKG5wLT5uYW1lID09IE5VTEwpCj4g\n" - "KwkJCWNvbnRpbnVlOwo+ICsKPiArCQlmb3IgKHR5cGUgPSAwOyB0eXBlIDwgTUFYX1NFTlNPUl9U\n" - "WVBFOyB0eXBlKyspCj4gKwkJCWlmIChvZl9kZXZpY2VfaXNfY29tcGF0aWJsZShucCwKPiArCQkJ\n" - "CQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmNvbXBhdGlibGUpKSB7Cj4gKwkJCQlzZW5zb3JfZ3JvdXBz\n" - "W3R5cGVdLmF0dHJfY291bnQrKzsKPiArCQkJCWJyZWFrOwo+ICsJCQl9Cj4gKwl9Cj4gKwo+ICsJ\n" - "b2Zfbm9kZV9wdXQob3BhbCk7Cj4gKwo+ICsJZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5T\n" - "T1JfVFlQRTsgdHlwZSsrKSB7Cj4gKwkJc2Vuc29yX2dyb3Vwc1t0eXBlXS5ncm91cC5hdHRycyA9\n" - "IGRldm1fa3phbGxvYygmcGRldi0+ZGV2LAo+ICsJCQkJCXNpemVvZihzdHJ1Y3QgYXR0cmlidXRl\n" - "ICopICoKPiArCQkJCQkoc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRyX2NvdW50ICsgMSksCj4gKwkJ\n" - "CQkJR0ZQX0tFUk5FTCk7Cj4gKwkJaWYgKCFzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJz\n" - "KQo+ICsJCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwkJcGdyb3Vwc1t0eXBlXSA9ICZzZW5zb3Jf\n" - "Z3JvdXBzW3R5cGVdLmdyb3VwOwo+ICsJCXBkYXRhLT5zZW5zb3JzX2NvdW50ICs9IHNlbnNvcl9n\n" - "cm91cHNbdHlwZV0uYXR0cl9jb3VudDsKPiArCQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmF0dHJfY291\n" - "bnQgPSAwOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICsvKgo+ICsgKiBJdGVy\n" - "YXRlIHRocm91Z2ggdGhlIGRldmljZSB0cmVlIGZvciBlYWNoIGNoaWxkIG9mICdzZW5zb3JzJyBu\n" - "b2RlLCBjcmVhdGUKPiArICogYSBzeXNmcyBhdHRyaWJ1dGUgZmlsZSwgdGhlIGZpbGUgaXMgbmFt\n" - "ZWQgYnkgdHJhbnNsYXRpbmcgdGhlIERUIG5vZGUgbmFtZQo+ICsgKiB0byB0aGUgbmFtZSByZXF1\n" - "aXJlZCBieSB0aGUgaGlnaGVyICdod21vbicgZHJpdmVyIGxpa2UgZmFuMV9pbnB1dCwgdGVtcDFf\n" - "bWF4Cj4gKyAqIGV0Yy4uCj4gKyAqLwo+ICtzdGF0aWMgaW50IF9faW5pdCBjcmVhdGVfZGV2aWNl\n" - "X2F0dHJzKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiArCXN0cnVjdCBwbGF0\n" - "Zm9ybV9kYXRhICpwZGF0YSA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ICsJY29uc3Qg\n" - "c3RydWN0IGF0dHJpYnV0ZV9ncm91cCAqKnBncm91cHMgPSBwZGF0YS0+YXR0cl9ncm91cHM7Cj4g\n" - "KwlzdHJ1Y3QgZGV2aWNlX25vZGUgKm9wYWwsICpucDsKPiArCXN0cnVjdCBzZW5zb3JfZGF0YSAq\n" - "c2RhdGE7Cj4gKwljb25zdCBfX2JlMzIgKnNlbnNvcl9pZDsKPiArCWVudW0gc2Vuc29ycyB0eXBl\n" - "Owo+ICsJdTMyIGNvdW50ID0gMDsKPiArCWludCBlcnIgPSAwOwo+ICsKPiArCW9wYWwgPSBvZl9m\n" - "aW5kX25vZGVfYnlfcGF0aCgiL2libSxvcGFsL3NlbnNvcnMiKTsKPiArCXNkYXRhID0gZGV2bV9r\n" - "emFsbG9jKCZwZGV2LT5kZXYsIHBkYXRhLT5zZW5zb3JzX2NvdW50ICogc2l6ZW9mKCpzZGF0YSks\n" - "Cj4gKwkJCSAgICAgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIXNkYXRhKSB7Cj4gKwkJZXJyID0gLUVO\n" - "T01FTTsKPiArCQlnb3RvIGV4aXRfcHV0X25vZGU7Cj4gKwl9Cj4gKwo+ICsJZm9yX2VhY2hfY2hp\n" - "bGRfb2Zfbm9kZShvcGFsLCBucCkgewo+ICsJCWlmIChucC0+bmFtZSA9PSBOVUxMKQo+ICsJCQlj\n" - "b250aW51ZTsKPiArCj4gKwkJZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5TT1JfVFlQRTsg\n" - "dHlwZSsrKQo+ICsJCQlpZiAob2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCj4gKwkJCQkJc2Vu\n" - "c29yX2dyb3Vwc1t0eXBlXS5jb21wYXRpYmxlKSkKPiArCQkJCWJyZWFrOwo+ICsKPiArCQlpZiAo\n" - "dHlwZSA9PSBNQVhfU0VOU09SX1RZUEUpCj4gKwkJCWNvbnRpbnVlOwo+ICsKPiArCQlzZW5zb3Jf\n" - "aWQgPSBvZl9nZXRfcHJvcGVydHkobnAsICJzZW5zb3ItaWQiLCBOVUxMKTsKPiArCQlpZiAoIXNl\n" - "bnNvcl9pZCkgewo+ICsJCQlkZXZfaW5mbygmcGRldi0+ZGV2LAo+ICsJCQkJICInc2Vuc29yLWlk\n" - "JyBtaXNzaW5nIGluIHRoZSBub2RlICclcydcbiIsCj4gKwkJCQkgbnAtPm5hbWUpOwo+ICsJCQlj\n" - "b250aW51ZTsKPiArCQl9Cj4gKwo+ICsJCXNkYXRhW2NvdW50XS5pZCA9IGJlMzJfdG9fY3B1cChz\n" - "ZW5zb3JfaWQpOwo+ICsJCXNkYXRhW2NvdW50XS50eXBlID0gdHlwZTsKPiArCQllcnIgPSBjcmVh\n" - "dGVfaHdtb25fYXR0cl9uYW1lKCZwZGV2LT5kZXYsIHR5cGUsIG5wLT5uYW1lLAo+ICsJCQkJCSAg\n" - "ICAgc2RhdGFbY291bnRdLm5hbWUpOwo+ICsJCWlmIChlcnIpCj4gKwkJCWdvdG8gZXhpdF9wdXRf\n" - "bm9kZTsKPiArCj4gKwkJc3lzZnNfYXR0cl9pbml0KCZzZGF0YVtjb3VudF0uZGV2X2F0dHIuYXR0\n" - "cik7Cj4gKwkJc2RhdGFbY291bnRdLmRldl9hdHRyLmF0dHIubmFtZSA9IHNkYXRhW2NvdW50XS5u\n" - "YW1lOwo+ICsJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5hdHRyLm1vZGUgPSBTX0lSVUdPOwo+ICsJ\n" - "CXNkYXRhW2NvdW50XS5kZXZfYXR0ci5zaG93ID0gc2hvd19zZW5zb3I7Cj4gKwo+ICsJCXBncm91\n" - "cHNbdHlwZV0tPmF0dHJzW3NlbnNvcl9ncm91cHNbdHlwZV0uYXR0cl9jb3VudCsrXSA9Cj4gKwkJ\n" - "CQkmc2RhdGFbY291bnQrK10uZGV2X2F0dHIuYXR0cjsKPiArCX0KPiArCj4gK2V4aXRfcHV0X25v\n" - "ZGU6Cj4gKwlvZl9ub2RlX3B1dChvcGFsKTsKPiArCXJldHVybiBlcnI7Cj4gK30KPiArCj4gK3N0\n" - "YXRpYyBpbnQgX19pbml0IGlibXBvd2VybnZfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAq\n" - "cGRldikKPiArewo+ICsJc3RydWN0IHBsYXRmb3JtX2RhdGEgKnBkYXRhOwo+ICsJc3RydWN0IGRl\n" - "dmljZSAqaHdtb25fZGV2Owo+ICsJaW50IGVycjsKPiArCj4gKwlwZGF0YSA9IGRldm1fa3phbGxv\n" - "YygmcGRldi0+ZGV2LCBzaXplb2YoKnBkYXRhKSwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIXBkYXRh\n" - "KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYs\n" - "IHBkYXRhKTsKPiArCXBkYXRhLT5zZW5zb3JzX2NvdW50ID0gMDsKPiArCWVyciA9IHBvcHVsYXRl\n" - "X2F0dHJfZ3JvdXBzKHBkZXYpOwo+ICsJaWYgKGVycikKPiArCQlyZXR1cm4gZXJyOwo+ICsKPiAr\n" - "CS8qIENyZWF0ZSBzeXNmcyBhdHRyaWJ1dGUgZGF0YSBmb3IgZWFjaCBzZW5zb3IgZm91bmQgaW4g\n" - "dGhlIERUICovCj4gKwllcnIgPSBjcmVhdGVfZGV2aWNlX2F0dHJzKHBkZXYpOwo+ICsJaWYgKGVy\n" - "cikKPiArCQlyZXR1cm4gZXJyOwo+ICsKPiArCS8qIEZpbmFsbHksIHJlZ2lzdGVyIHdpdGggaHdt\n" - "b24gKi8KPiArCWh3bW9uX2RldiA9IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhfZ3Jv\n" - "dXBzKCZwZGV2LT5kZXYsIERSVk5BTUUsCj4gKwkJCQkJCQkgICBwZGF0YSwKPiArCQkJCQkJCSAg\n" - "IHBkYXRhLT5hdHRyX2dyb3Vwcyk7Cj4gKwo+ICsJcmV0dXJuIFBUUl9FUlJfT1JfWkVSTyhod21v\n" - "bl9kZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBpYm1wb3dl\n" - "cm52X2RyaXZlciA9IHsKPiArCS5kcml2ZXIgPSB7Cj4gKwkJLm93bmVyID0gVEhJU19NT0RVTEUs\n" - "Cj4gKwkJLm5hbWUgPSBEUlZOQU1FLAo+ICsJfSwKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgX19p\n" - "bml0IGlibXBvd2VybnZfaW5pdCh2b2lkKQo+ICt7Cj4gKwlpbnQgZXJyOwo+ICsKPiArCXBkZXZp\n" - "Y2UgPSBwbGF0Zm9ybV9kZXZpY2VfYWxsb2MoRFJWTkFNRSwgMCk7Cj4gKwlpZiAoIXBkZXZpY2Up\n" - "IHsKPiArCQlwcl9lcnIoIkRldmljZSBhbGxvY2F0aW9uIGZhaWxlZFxuIik7Cj4gKwkJZXJyID0g\n" - "LUVOT01FTTsKPiArCQlnb3RvIGV4aXQ7Cj4gKwl9Cj4gKwo+ICsJZXJyID0gcGxhdGZvcm1fZGV2\n" - "aWNlX2FkZChwZGV2aWNlKTsKPiArCWlmIChlcnIpIHsKPiArCQlwcl9lcnIoIkRldmljZSBhZGRp\n" - "dGlvbiBmYWlsZWQgKCVkKVxuIiwgZXJyKTsKPiArCQlnb3RvIGV4aXRfZGV2aWNlX3B1dDsKPiAr\n" - "CX0KPiArCj4gKwllcnIgPSBwbGF0Zm9ybV9kcml2ZXJfcHJvYmUoJmlibXBvd2VybnZfZHJpdmVy\n" - "LCBpYm1wb3dlcm52X3Byb2JlKTsKPiArCWlmIChlcnIpIHsKPiArCQlwcl9lcnIoIlBsYXRmcm9t\n" - "IGRyaXZlciBwcm9iZSBmYWlsZWRcbiIpOwo+ICsJCWdvdG8gZXhpdF9kZXZpY2VfZGVsOwo+ICsJ\n" - "fQo+ICsKPiArCXJldHVybiAwOwo+ICsKPiArZXhpdF9kZXZpY2VfZGVsOgo+ICsJcGxhdGZvcm1f\n" - "ZGV2aWNlX2RlbChwZGV2aWNlKTsKPiArZXhpdF9kZXZpY2VfcHV0Ogo+ICsJcGxhdGZvcm1fZGV2\n" - "aWNlX3B1dChwZGV2aWNlKTsKPiArZXhpdDoKPiArCXJldHVybiBlcnI7Cj4gK30KPiArCj4gK3N0\n" - "YXRpYyB2b2lkIF9fZXhpdCBpYm1wb3dlcm52X2V4aXQodm9pZCkKPiArewo+ICsJcGxhdGZvcm1f\n" - "ZHJpdmVyX3VucmVnaXN0ZXIoJmlibXBvd2VybnZfZHJpdmVyKTsKPiArCXBsYXRmb3JtX2Rldmlj\n" - "ZV91bnJlZ2lzdGVyKHBkZXZpY2UpOwo+ICt9Cj4gKwo+ICtNT0RVTEVfQVVUSE9SKCJOZWVsZXNo\n" - "IEd1cHRhIDxuZWVsZWd1cEBsaW51eC52bmV0LmlibS5jb20+Iik7Cj4gK01PRFVMRV9ERVNDUklQ\n" - "VElPTigiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIpOwo+ICtNT0RVTEVfTElDRU5TRSgi\n" - "R1BMIik7Cj4gKwo+ICttb2R1bGVfaW5pdChpYm1wb3dlcm52X2luaXQpOwo+ICttb2R1bGVfZXhp\n" - "dChpYm1wb3dlcm52X2V4aXQpOwo+Cj4KPgoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19f\n" - "X19fX19fX19fX19fX19fX19fCmxtLXNlbnNvcnMgbWFpbGluZyBsaXN0CmxtLXNlbnNvcnNAbG0t\n" - "c2Vuc29ycy5vcmcKaHR0cDovL2xpc3RzLmxtLXNlbnNvcnMub3JnL21haWxtYW4vbGlzdGluZm8v\n" - bG0tc2Vuc29ycw= + "On 07/04/2014 04:02 AM, Neelesh Gupta wrote:\n" + "> This patch adds basic kernel support for reading power values, fan\n" + "> speed rpm, voltage and temperature data on powernv platforms which will\n" + "> be exported to user space through sysfs interface.\n" + ">\n" + "\n" + "Hi Neelesh,\n" + "\n" + "Copying devicetree mailing list. Please copy it on the next (hopefully final)\n" + "revision; devicetree maintainers at least need a chance to comment.\n" + "[ Yes, I understand this is a shipping product, but still ... ]\n" + "\n" + "I am ok with the code except for a couple of minor nitpicks (see below).\n" + "\n" + "Thanks,\n" + "Guenter\n" + "\n" + "> Test results:\n" + "> -------------\n" + "> [root@tul163p1 ~]# sensors\n" + "> ibmpowernv-isa-0000\n" + "> Adapter: ISA adapter\n" + "> fan1: 5567 RPM (min = 0 RPM)\n" + "> fan2: 5232 RPM (min = 0 RPM)\n" + "> fan3: 5532 RPM (min = 0 RPM)\n" + "> fan4: 4945 RPM (min = 0 RPM)\n" + "> fan5: 0 RPM (min = 0 RPM)\n" + "> fan6: 0 RPM (min = 0 RPM)\n" + "> fan7: 7392 RPM (min = 0 RPM)\n" + "> fan8: 7936 RPM (min = 0 RPM)\n" + "> temp1: +39.0\302\260C (high = +0.0\302\260C)\n" + "> power1: 191.00 W\n" + ">\n" + "> [root@tul163p1 ~]# ls /sys/devices/platform/\n" + "> alarmtimer ibmpowernv.0 power rtc-generic serial8250 uevent\n" + "> [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/hwmon/hwmon0/\n" + "> device\t fan2_min\tfan4_min fan6_min\tfan8_min power\n" + "> fan1_fault fan3_fault\tfan5_fault fan7_fault\tin1_fault power1_input\n" + "> fan1_input fan3_input\tfan5_input fan7_input\tin2_fault subsystem\n" + "> fan1_min fan3_min\tfan5_min fan7_min\tin3_fault temp1_input\n" + "> fan2_fault fan4_fault\tfan6_fault fan8_fault\tin4_fault temp1_max\n" + "> fan2_input fan4_input\tfan6_input fan8_input\tname\t uevent\n" + "> [root@tul163p1 ~]#\n" + "> [root@tul163p1 ~]# ls /sys/class/hwmon/hwmon0/\n" + "> device\t fan2_min\tfan4_min fan6_min\tfan8_min power\n" + "> fan1_fault fan3_fault\tfan5_fault fan7_fault\tin1_fault power1_input\n" + "> fan1_input fan3_input\tfan5_input fan7_input\tin2_fault subsystem\n" + "> fan1_min fan3_min\tfan5_min fan7_min\tin3_fault temp1_input\n" + "> fan2_fault fan4_fault\tfan6_fault fan8_fault\tin4_fault temp1_max\n" + "> fan2_input fan4_input\tfan6_input fan8_input\tname\t uevent\n" + "> [root@tul163p1 ~]#\n" + ">\n" + "> Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>\n" + "> ---\n" + ">\n" + "> Changes in v4\n" + "> =============\n" + "> - Replaced pr_err() with dev_err() for loggin print messages.\n" + "> - Using kstrtou32() function for converting string to u32 instead of sscanf().\n" + ">\n" + "> Changes in v3\n" + "> =============\n" + "> - Fixed an endianness bug leading the driver to break on LE.\n" + "> - Fixed a bug that when one of the 'attribute_group' not populated, following\n" + "> groups attributes were dropped.\n" + "> - Rewrite the get_sensor_index_attr() function to handle all the error scenarios\n" + "> like 'sscanf' etc.\n" + "> - Fixed all the errors/warnings related to coding style/whitespace.\n" + "> - Added 'Documentation' files.\n" + "> - Addressed remaining review comments on V2.\n" + ">\n" + "> Changes in v2\n" + "> =============\n" + "> - Generic use of devm_* functions in hwmon like using devm_kzalloc() for dynamic\n" + "> memory request, avoiding the need to explicit free of memory.\n" + "> Adding 'struct attribute_group' as member of platform data structure to be\n" + "> populated and then passed to 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 ideal or\n" + "> could have just one group populated with attributes of sensor types?\n" + ">\n" + "> - 'ibmpowernv' is not hot-pluggable device so moving '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" + "> .../devicetree/bindings/hwmon/ibmpowernv.txt | 27 +\n" + "> Documentation/hwmon/ibmpowernv | 41 ++\n" + "> drivers/hwmon/Kconfig | 11 +\n" + "> drivers/hwmon/Makefile | 1\n" + "> drivers/hwmon/ibmpowernv.c | 362 ++++++++++++++++++++\n" + "> 5 files changed, 442 insertions(+)\n" + "> create mode 100644 Documentation/devicetree/bindings/hwmon/ibmpowernv.txt\n" + "> create mode 100644 Documentation/hwmon/ibmpowernv\n" + "> create mode 100644 drivers/hwmon/ibmpowernv.c\n" + ">\n" + "> diff --git a/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt\n" + "> new file mode 100644\n" + "> index 0000000..e3bd1eb\n" + "> --- /dev/null\n" + "> +++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt\n" + "> @@ -0,0 +1,27 @@\n" + "> +IBM POWERNV platform sensors\n" + "> +----------------------------\n" + "> +\n" + "> +Required node properties:\n" + "> +- compatible: must be one of\n" + "> +\t\t\"ibm,opal-sensor-cooling-fan\"\n" + "> +\t\t\"ibm,opal-sensor-amb-temp\"\n" + "> +\t\t\"ibm,opal-sensor-power-supply\"\n" + "> +\t\t\"ibm,opal-sensor-power\"\n" + "> +- sensor-id: an opaque id provided by the firmware to the kernel, identifies a\n" + "> +\t given sensor and its attribute data\n" + "> +\n" + "> +Example sensors node:\n" + "> +\n" + "> +cooling-fan#8-data {\n" + "> +\tsensor-id = <0x7052107>;\n" + "> +\tphandle = <0x10000028>;\n" + "> +\tlinux,phandle = <0x10000028>;\n" + "> +\tcompatible = \"ibm,opal-sensor-cooling-fan\";\n" + "\n" + "phandle and linux-phandle are neither documented nor used. Either document or drop.\n" + "\n" + "> +};\n" + "> +\n" + "> +amb-temp#1-thrs {\n" + "> +\tsensor-id = <0x5096000>;\n" + "> +\tphandle = <0x10000017>;\n" + "> +\tlinux,phandle = <0x10000017>;\n" + "> +\tcompatible = \"ibm,opal-sensor-amb-temp\";\n" + "> +};\n" + "> diff --git a/Documentation/hwmon/ibmpowernv b/Documentation/hwmon/ibmpowernv\n" + "> new file mode 100644\n" + "> index 0000000..644245a\n" + "> --- /dev/null\n" + "> +++ b/Documentation/hwmon/ibmpowernv\n" + "> @@ -0,0 +1,41 @@\n" + "> +Kernel Driver IBMPOWENV\n" + "> +=======================\n" + "> +\n" + "> +Supported systems:\n" + "> + * Any recent IBM P servers based on POWERNV platform\n" + "> +\n" + "> +Author: Neelesh Gupta\n" + "> +\n" + "> +Description\n" + "> +-----------\n" + "> +\n" + "> +This driver implements reading the platform sensors data like temperature/fan/\n" + "> +voltage/power for 'POWERNV' platform.\n" + "> +\n" + "> +The driver uses the platform device infrastructure. It probes the device tree\n" + "> +for sensor devices during the __init phase and registers them with the 'hwmon'.\n" + "> +'hwmon' populates the 'sysfs' tree having attribute files, each for a given\n" + "> +sensor type and its attribute data.\n" + "> +\n" + "> +All the nodes in the DT appear under \"/ibm,opal/sensors\" and each valid node in\n" + "> +the DT maps to an attribute file in 'sysfs'. The node exports unique 'sensor-id'\n" + "> +which the driver uses to make an OPAL call to the firmware.\n" + "> +\n" + "> +Usage notes\n" + "> +-----------\n" + "> +The driver is built statically with the kernel by enabling the config\n" + "> +CONFIG_SENSORS_IBMPOWERNV. It can also be built as module 'ibmpowernv'.\n" + "> +\n" + "> +Sysfs attributes\n" + "> +----------------\n" + "> +\n" + "> +fanX_input\t\tMeasured RPM value.\n" + "> +fanX_min\t\tThreshold RPM for alert generation.\n" + "> +fanX_fault\t\t0: No fail condition\n" + "> +\t\t\t1: Failing fan\n" + "> +tempX_input\t\tMeasured ambient temperature.\n" + "> +tempX_max\t\tThreshold ambient temperature for alert generation.\n" + "> +inX_input\t\tMeasured power supply voltage\n" + "> +inX_fault\t\t0: No fail condition.\n" + "> +\t\t\t1: Failing power supply.\n" + "> +power1_input\t\tSystem power consumption (microWatt)\n" + "> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig\n" + "> index 02d3d85..29c3fcb 100644\n" + "> --- a/drivers/hwmon/Kconfig\n" + "> +++ b/drivers/hwmon/Kconfig\n" + "> @@ -554,6 +554,17 @@ 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 PowerNV platform.\n" + "> +\n" + "> +\t This driver can also be built as a module. If so, the module\n" + "> +\t will be called ibmpowernv.\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 3dc0f02..fc4ed26 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..44dcd99\n" + "> --- /dev/null\n" + "> +++ b/drivers/hwmon/ibmpowernv.c\n" + "> @@ -0,0 +1,362 @@\n" + "> +/*\n" + "> + * IBM PowerNV platform sensors for temperature/fan/voltage/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" + "> +#define DRVNAME\t\t\"ibmpowernv\"\n" + "> +#define pr_fmt(fmt)\tDRVNAME \": \" fmt\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 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" + "> +/*\n" + "> + * Enumerates all the types of sensors in the POWERNV platform and does index\n" + "> + * into 'struct sensor_group'\n" + "> + */\n" + "> +enum sensors {\n" + "> +\tFAN,\n" + "> +\tAMBIENT_TEMP,\n" + "> +\tPOWER_SUPPLY,\n" + "> +\tPOWER_INPUT,\n" + "> +\tMAX_SENSOR_TYPE,\n" + "> +};\n" + "> +\n" + "> +static struct sensor_group {\n" + "> +\tconst char *name;\n" + "> +\tconst char *compatible;\n" + "> +\tstruct attribute_group group;\n" + "> +\tu32 attr_count;\n" + "> +} sensor_groups[] = {\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 sensor_data {\n" + "> +\tu32 id; /* An opaque id of the firmware for each sensor */\n" + "> +\tenum sensors type;\n" + "> +\tchar name[MAX_ATTR_LEN];\n" + "> +\tstruct device_attribute dev_attr;\n" + "> +};\n" + "> +\n" + "> +struct platform_data {\n" + "> +\tconst struct attribute_group *attr_groups[MAX_SENSOR_TYPE + 1];\n" + "> +\tu32 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 device_attribute *devattr,\n" + "> +\t\t\t char *buf)\n" + "> +{\n" + "> +\tstruct sensor_data *sdata = container_of(devattr, struct sensor_data,\n" + "> +\t\t\t\t\t\t dev_attr);\n" + "> +\tssize_t ret;\n" + "> +\tu32 x;\n" + "> +\n" + "> +\tret = opal_get_sensor_data(sdata->id, &x);\n" + "> +\tif (ret)\n" + "> +\t\treturn ret;\n" + "> +\n" + "> +\t/* Convert temperature to milli-degrees */\n" + "> +\tif (sdata->type == AMBIENT_TEMP)\n" + "> +\t\tx *= 1000;\n" + "> +\t/* Convert power to micro-watts */\n" + "> +\telse if (sdata->type == POWER_INPUT)\n" + "> +\t\tx *= 1000000;\n" + "> +\n" + "> +\treturn sprintf(buf, \"%u\\n\", x);\n" + "> +}\n" + "> +\n" + "> +static int __init get_sensor_index_attr(const char *name, u32 *index,\n" + "> +\t\t\t\t\tchar *attr)\n" + "> +{\n" + "> +\tchar *hash_pos = strchr(name, '#');\n" + "> +\tchar buf[8] = { 0 };\n" + "> +\tchar *dash_pos;\n" + "> +\tu32 copy_len;\n" + "> +\n" + "> +\tif (!hash_pos)\n" + "> +\t\treturn -EINVAL;\n" + "> +\n" + "> +\tdash_pos = strchr(hash_pos, '-');\n" + "> +\tif (!dash_pos)\n" + "> +\t\treturn -EINVAL;\n" + "> +\n" + "> +\tcopy_len = dash_pos - hash_pos - 1;\n" + "> +\tif (copy_len >= sizeof(buf))\n" + "> +\t\treturn -EINVAL;\n" + "> +\n" + "> +\tstrncpy(buf, hash_pos + 1, copy_len);\n" + "> +\n" + "> +\tif (kstrtou32(buf, 10, index))\n" + "> +\t\treturn -EINVAL;\n" + "> +\n" + "smatch isn't going to like that. Please use\n" + "\n" + "\tint err;\n" + "\t...\n" + "\terr = kstrtou32(buf, 10, index));\n" + "\tif (err)\n" + "\t\treturn err;\n" + "\n" + "> +\tstrncpy(attr, dash_pos + 1, MAX_ATTR_LEN);\n" + "> +\n" + "> +\treturn 0;\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 __init create_hwmon_attr_name(struct device *dev, enum sensors type,\n" + "> +\t\t\t\t\t const char *node_name,\n" + "> +\t\t\t\t\t char *hwmon_attr_name)\n" + "> +{\n" + "> +\tchar attr_suffix[MAX_ATTR_LEN];\n" + "> +\tchar *attr_name;\n" + "> +\tu32 index;\n" + "> +\tint err;\n" + "> +\n" + "> +\terr = get_sensor_index_attr(node_name, &index, attr_suffix);\n" + "> +\tif (err) {\n" + "> +\t\tdev_err(dev, \"Sensor device node name '%s' is invalid\\n\",\n" + "> +\t\t\tnode_name);\n" + "> +\t\treturn err;\n" + "> +\t}\n" + "> +\n" + "> +\tif (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX)) {\n" + "> +\t\tattr_name = \"fault\";\n" + "> +\t} else if (!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX)) {\n" + "> +\t\tattr_name = \"input\";\n" + "> +\t} else if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) {\n" + "> +\t\tif (type == AMBIENT_TEMP)\n" + "> +\t\t\tattr_name = \"max\";\n" + "> +\t\telse if (type == FAN)\n" + "> +\t\t\tattr_name = \"min\";\n" + "> +\t\telse\n" + "> +\t\t\treturn -ENOENT;\n" + "> +\t} else {\n" + "> +\t\treturn -ENOENT;\n" + "> +\t}\n" + "> +\n" + "> +\tsnprintf(hwmon_attr_name, MAX_ATTR_LEN, \"%s%d_%s\",\n" + "> +\t\t sensor_groups[type].name, index, attr_name);\n" + "> +\treturn 0;\n" + "> +}\n" + "> +\n" + "> +static int __init populate_attr_groups(struct platform_device *pdev)\n" + "> +{\n" + "> +\tstruct platform_data *pdata = platform_get_drvdata(pdev);\n" + "> +\tconst struct attribute_group **pgroups = pdata->attr_groups;\n" + "> +\tstruct device_node *opal, *np;\n" + "> +\tenum sensors type;\n" + "> +\n" + "> +\topal = of_find_node_by_path(\"/ibm,opal/sensors\");\n" + "> +\tif (!opal) {\n" + "> +\t\tdev_err(&pdev->dev, \"Opal node 'sensors' not found\\n\");\n" + "> +\t\treturn -ENODEV;\n" + "> +\t}\n" + "> +\n" + "> +\tfor_each_child_of_node(opal, np) {\n" + "> +\t\tif (np->name == NULL)\n" + "> +\t\t\tcontinue;\n" + "> +\n" + "> +\t\tfor (type = 0; type < MAX_SENSOR_TYPE; type++)\n" + "> +\t\t\tif (of_device_is_compatible(np,\n" + "> +\t\t\t\t\tsensor_groups[type].compatible)) {\n" + "> +\t\t\t\tsensor_groups[type].attr_count++;\n" + "> +\t\t\t\tbreak;\n" + "> +\t\t\t}\n" + "> +\t}\n" + "> +\n" + "> +\tof_node_put(opal);\n" + "> +\n" + "> +\tfor (type = 0; type < MAX_SENSOR_TYPE; type++) {\n" + "> +\t\tsensor_groups[type].group.attrs = devm_kzalloc(&pdev->dev,\n" + "> +\t\t\t\t\tsizeof(struct attribute *) *\n" + "> +\t\t\t\t\t(sensor_groups[type].attr_count + 1),\n" + "> +\t\t\t\t\tGFP_KERNEL);\n" + "> +\t\tif (!sensor_groups[type].group.attrs)\n" + "> +\t\t\treturn -ENOMEM;\n" + "> +\n" + "> +\t\tpgroups[type] = &sensor_groups[type].group;\n" + "> +\t\tpdata->sensors_count += sensor_groups[type].attr_count;\n" + "> +\t\tsensor_groups[type].attr_count = 0;\n" + "> +\t}\n" + "> +\n" + "> +\treturn 0;\n" + "> +}\n" + "> +\n" + "> +/*\n" + "> + * Iterate through the device tree for each child of 'sensors' 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 __init create_device_attrs(struct platform_device *pdev)\n" + "> +{\n" + "> +\tstruct platform_data *pdata = platform_get_drvdata(pdev);\n" + "> +\tconst struct attribute_group **pgroups = pdata->attr_groups;\n" + "> +\tstruct device_node *opal, *np;\n" + "> +\tstruct sensor_data *sdata;\n" + "> +\tconst __be32 *sensor_id;\n" + "> +\tenum sensors type;\n" + "> +\tu32 count = 0;\n" + "> +\tint err = 0;\n" + "> +\n" + "> +\topal = of_find_node_by_path(\"/ibm,opal/sensors\");\n" + "> +\tsdata = devm_kzalloc(&pdev->dev, pdata->sensors_count * sizeof(*sdata),\n" + "> +\t\t\t GFP_KERNEL);\n" + "> +\tif (!sdata) {\n" + "> +\t\terr = -ENOMEM;\n" + "> +\t\tgoto exit_put_node;\n" + "> +\t}\n" + "> +\n" + "> +\tfor_each_child_of_node(opal, np) {\n" + "> +\t\tif (np->name == NULL)\n" + "> +\t\t\tcontinue;\n" + "> +\n" + "> +\t\tfor (type = 0; type < MAX_SENSOR_TYPE; type++)\n" + "> +\t\t\tif (of_device_is_compatible(np,\n" + "> +\t\t\t\t\tsensor_groups[type].compatible))\n" + "> +\t\t\t\tbreak;\n" + "> +\n" + "> +\t\tif (type == 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\tdev_info(&pdev->dev,\n" + "> +\t\t\t\t \"'sensor-id' missing in the node '%s'\\n\",\n" + "> +\t\t\t\t np->name);\n" + "> +\t\t\tcontinue;\n" + "> +\t\t}\n" + "> +\n" + "> +\t\tsdata[count].id = be32_to_cpup(sensor_id);\n" + "> +\t\tsdata[count].type = type;\n" + "> +\t\terr = create_hwmon_attr_name(&pdev->dev, type, np->name,\n" + "> +\t\t\t\t\t sdata[count].name);\n" + "> +\t\tif (err)\n" + "> +\t\t\tgoto exit_put_node;\n" + "> +\n" + "> +\t\tsysfs_attr_init(&sdata[count].dev_attr.attr);\n" + "> +\t\tsdata[count].dev_attr.attr.name = sdata[count].name;\n" + "> +\t\tsdata[count].dev_attr.attr.mode = S_IRUGO;\n" + "> +\t\tsdata[count].dev_attr.show = show_sensor;\n" + "> +\n" + "> +\t\tpgroups[type]->attrs[sensor_groups[type].attr_count++] =\n" + "> +\t\t\t\t&sdata[count++].dev_attr.attr;\n" + "> +\t}\n" + "> +\n" + "> +exit_put_node:\n" + "> +\tof_node_put(opal);\n" + "> +\treturn err;\n" + "> +}\n" + "> +\n" + "> +static int __init ibmpowernv_probe(struct platform_device *pdev)\n" + "> +{\n" + "> +\tstruct platform_data *pdata;\n" + "> +\tstruct device *hwmon_dev;\n" + "> +\tint err;\n" + "> +\n" + "> +\tpdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);\n" + "> +\tif (!pdata)\n" + "> +\t\treturn -ENOMEM;\n" + "> +\n" + "> +\tplatform_set_drvdata(pdev, pdata);\n" + "> +\tpdata->sensors_count = 0;\n" + "> +\terr = populate_attr_groups(pdev);\n" + "> +\tif (err)\n" + "> +\t\treturn err;\n" + "> +\n" + "> +\t/* Create sysfs attribute data for each sensor found in the DT */\n" + "> +\terr = create_device_attrs(pdev);\n" + "> +\tif (err)\n" + "> +\t\treturn err;\n" + "> +\n" + "> +\t/* Finally, register with hwmon */\n" + "> +\thwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, DRVNAME,\n" + "> +\t\t\t\t\t\t\t pdata,\n" + "> +\t\t\t\t\t\t\t pdata->attr_groups);\n" + "> +\n" + "> +\treturn PTR_ERR_OR_ZERO(hwmon_dev);\n" + "> +}\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" + "> +};\n" + "> +\n" + "> +static int __init ibmpowernv_init(void)\n" + "> +{\n" + "> +\tint err;\n" + "> +\n" + "> +\tpdevice = platform_device_alloc(DRVNAME, 0);\n" + "> +\tif (!pdevice) {\n" + "> +\t\tpr_err(\"Device allocation failed\\n\");\n" + "> +\t\terr = -ENOMEM;\n" + "> +\t\tgoto exit;\n" + "> +\t}\n" + "> +\n" + "> +\terr = platform_device_add(pdevice);\n" + "> +\tif (err) {\n" + "> +\t\tpr_err(\"Device addition failed (%d)\\n\", err);\n" + "> +\t\tgoto exit_device_put;\n" + "> +\t}\n" + "> +\n" + "> +\terr = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe);\n" + "> +\tif (err) {\n" + "> +\t\tpr_err(\"Platfrom driver probe failed\\n\");\n" + "> +\t\tgoto exit_device_del;\n" + "> +\t}\n" + "> +\n" + "> +\treturn 0;\n" + "> +\n" + "> +exit_device_del:\n" + "> +\tplatform_device_del(pdevice);\n" + "> +exit_device_put:\n" + "> +\tplatform_device_put(pdevice);\n" + "> +exit:\n" + "> +\treturn err;\n" + "> +}\n" + "> +\n" + "> +static void __exit ibmpowernv_exit(void)\n" + "> +{\n" + "> +\tplatform_driver_unregister(&ibmpowernv_driver);\n" + "> +\tplatform_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" + > -6fdfb7c435f43cd5fcc811d9232709df978b636ff428b7ed0c4ff08d71baa90b +3665bca30f20813bee7a191905ce275cac8cf24bd3078a481d727ff5645571db
diff --git a/a/1.txt b/N2/1.txt index d8f236d..728b01e 100644 --- a/a/1.txt +++ b/N2/1.txt @@ -1,330 +1,598 @@ -T24gMDcvMDQvMjAxNCAwNDowMiBBTSwgTmVlbGVzaCBHdXB0YSB3cm90ZToKPiBUaGlzIHBhdGNo -IGFkZHMgYmFzaWMga2VybmVsIHN1cHBvcnQgZm9yIHJlYWRpbmcgcG93ZXIgdmFsdWVzLCBmYW4K -PiBzcGVlZCBycG0sIHZvbHRhZ2UgYW5kIHRlbXBlcmF0dXJlIGRhdGEgb24gcG93ZXJudiBwbGF0 -Zm9ybXMgd2hpY2ggd2lsbAo+IGJlIGV4cG9ydGVkIHRvIHVzZXIgc3BhY2UgdGhyb3VnaCBzeXNm -cyBpbnRlcmZhY2UuCj4KCkhpIE5lZWxlc2gsCgpDb3B5aW5nIGRldmljZXRyZWUgbWFpbGluZyBs -aXN0LiBQbGVhc2UgY29weSBpdCBvbiB0aGUgbmV4dCAoaG9wZWZ1bGx5IGZpbmFsKQpyZXZpc2lv -bjsgZGV2aWNldHJlZSBtYWludGFpbmVycyBhdCBsZWFzdCBuZWVkIGEgY2hhbmNlIHRvIGNvbW1l -bnQuClsgWWVzLCBJIHVuZGVyc3RhbmQgdGhpcyBpcyBhIHNoaXBwaW5nIHByb2R1Y3QsIGJ1dCBz -dGlsbCAuLi4gXQoKSSBhbSBvayB3aXRoIHRoZSBjb2RlIGV4Y2VwdCBmb3IgYSBjb3VwbGUgb2Yg -bWlub3Igbml0cGlja3MgKHNlZSBiZWxvdykuCgpUaGFua3MsCkd1ZW50ZXIKCj4gVGVzdCByZXN1 -bHRzOgo+IC0tLS0tLS0tLS0tLS0KPiBbcm9vdEB0dWwxNjNwMSB+XSMgc2Vuc29ycwo+IGlibXBv -d2VybnYtaXNhLTAwMDAKPiBBZGFwdGVyOiBJU0EgYWRhcHRlcgo+IGZhbjE6ICAgICAgICA1NTY3 -IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjI6ICAgICAgICA1MjMyIFJQTSAgKG1pbiA9ICAg -IDAgUlBNKQo+IGZhbjM6ICAgICAgICA1NTMyIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjQ6 -ICAgICAgICA0OTQ1IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjU6ICAgICAgICAgICAwIFJQ -TSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjY6ICAgICAgICAgICAwIFJQTSAgKG1pbiA9ICAgIDAg -UlBNKQo+IGZhbjc6ICAgICAgICA3MzkyIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjg6ICAg -ICAgICA3OTM2IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IHRlbXAxOiAgICAgICAgKzM5LjDCsEMg -IChoaWdoID0gICswLjDCsEMpCj4gcG93ZXIxOiAgICAgIDE5MS4wMCBXCj4KPiBbcm9vdEB0dWwx -NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtLwo+IGFsYXJtdGltZXIgIGlibXBvd2Vy -bnYuMCAgcG93ZXIgIHJ0Yy1nZW5lcmljICBzZXJpYWw4MjUwICB1ZXZlbnQKPiBbcm9vdEB0dWwx -NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtL2libXBvd2VybnYuMC9od21vbi9od21v -bjAvCj4gZGV2aWNlCSAgICBmYW4yX21pbglmYW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAg -IHBvd2VyCj4gZmFuMV9mYXVsdCAgZmFuM19mYXVsdAlmYW41X2ZhdWx0ICBmYW43X2ZhdWx0CWlu -MV9mYXVsdCAgcG93ZXIxX2lucHV0Cj4gZmFuMV9pbnB1dCAgZmFuM19pbnB1dAlmYW41X2lucHV0 -ICBmYW43X2lucHV0CWluMl9mYXVsdCAgc3Vic3lzdGVtCj4gZmFuMV9taW4gICAgZmFuM19taW4J -ZmFuNV9taW4gICAgZmFuN19taW4JaW4zX2ZhdWx0ICB0ZW1wMV9pbnB1dAo+IGZhbjJfZmF1bHQg -IGZhbjRfZmF1bHQJZmFuNl9mYXVsdCAgZmFuOF9mYXVsdAlpbjRfZmF1bHQgIHRlbXAxX21heAo+ -IGZhbjJfaW5wdXQgIGZhbjRfaW5wdXQJZmFuNl9pbnB1dCAgZmFuOF9pbnB1dAluYW1lCSAgIHVl -dmVudAo+IFtyb290QHR1bDE2M3AxIH5dIwo+IFtyb290QHR1bDE2M3AxIH5dIyBscyAvc3lzL2Ns -YXNzL2h3bW9uL2h3bW9uMC8KPiBkZXZpY2UJICAgIGZhbjJfbWluCWZhbjRfbWluICAgIGZhbjZf -bWluCWZhbjhfbWluICAgcG93ZXIKPiBmYW4xX2ZhdWx0ICBmYW4zX2ZhdWx0CWZhbjVfZmF1bHQg -IGZhbjdfZmF1bHQJaW4xX2ZhdWx0ICBwb3dlcjFfaW5wdXQKPiBmYW4xX2lucHV0ICBmYW4zX2lu -cHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5wdXQJaW4yX2ZhdWx0ICBzdWJzeXN0ZW0KPiBmYW4xX21p -biAgICBmYW4zX21pbglmYW41X21pbiAgICBmYW43X21pbglpbjNfZmF1bHQgIHRlbXAxX2lucHV0 -Cj4gZmFuMl9mYXVsdCAgZmFuNF9mYXVsdAlmYW42X2ZhdWx0ICBmYW44X2ZhdWx0CWluNF9mYXVs -dCAgdGVtcDFfbWF4Cj4gZmFuMl9pbnB1dCAgZmFuNF9pbnB1dAlmYW42X2lucHV0ICBmYW44X2lu -cHV0CW5hbWUJICAgdWV2ZW50Cj4gW3Jvb3RAdHVsMTYzcDEgfl0jCj4KPiBTaWduZWQtb2ZmLWJ5 -OiBOZWVsZXNoIEd1cHRhIDxuZWVsZWd1cEBsaW51eC52bmV0LmlibS5jb20+Cj4gLS0tCj4KPiBD -aGFuZ2VzIGluIHY0Cj4gPT09PT09PT09PT09PQo+IC0gUmVwbGFjZWQgcHJfZXJyKCkgd2l0aCBk -ZXZfZXJyKCkgZm9yIGxvZ2dpbiBwcmludCBtZXNzYWdlcy4KPiAtIFVzaW5nIGtzdHJ0b3UzMigp -IGZ1bmN0aW9uIGZvciBjb252ZXJ0aW5nIHN0cmluZyB0byB1MzIgaW5zdGVhZCBvZiBzc2NhbmYo -KS4KPgo+IENoYW5nZXMgaW4gdjMKPiA9PT09PT09PT09PT09Cj4gLSBGaXhlZCBhbiBlbmRpYW5u -ZXNzIGJ1ZyBsZWFkaW5nIHRoZSBkcml2ZXIgdG8gYnJlYWsgb24gTEUuCj4gLSBGaXhlZCBhIGJ1 -ZyB0aGF0IHdoZW4gb25lIG9mIHRoZSAnYXR0cmlidXRlX2dyb3VwJyBub3QgcG9wdWxhdGVkLCBm -b2xsb3dpbmcKPiAgICBncm91cHMgYXR0cmlidXRlcyB3ZXJlIGRyb3BwZWQuCj4gLSBSZXdyaXRl -IHRoZSBnZXRfc2Vuc29yX2luZGV4X2F0dHIoKSBmdW5jdGlvbiB0byBoYW5kbGUgYWxsIHRoZSBl -cnJvciBzY2VuYXJpb3MKPiAgICBsaWtlICdzc2NhbmYnIGV0Yy4KPiAtIEZpeGVkIGFsbCB0aGUg -ZXJyb3JzL3dhcm5pbmdzIHJlbGF0ZWQgdG8gY29kaW5nIHN0eWxlL3doaXRlc3BhY2UuCj4gLSBB -ZGRlZCAnRG9jdW1lbnRhdGlvbicgZmlsZXMuCj4gLSBBZGRyZXNzZWQgcmVtYWluaW5nIHJldmll -dyBjb21tZW50cyBvbiBWMi4KPgo+IENoYW5nZXMgaW4gdjIKPiA9PT09PT09PT09PT09Cj4gLSBH -ZW5lcmljIHVzZSBvZiBkZXZtXyogZnVuY3Rpb25zIGluIGh3bW9uIGxpa2UgdXNpbmcgZGV2bV9r -emFsbG9jKCkgZm9yIGR5bmFtaWMKPiAgICBtZW1vcnkgcmVxdWVzdCwgYXZvaWRpbmcgdGhlIG5l -ZWQgdG8gZXhwbGljaXQgZnJlZSBvZiBtZW1vcnkuCj4gICAgQWRkaW5nICdzdHJ1Y3QgYXR0cmli -dXRlX2dyb3VwJyBhcyBtZW1iZXIgb2YgcGxhdGZvcm0gZGF0YSBzdHJ1Y3R1cmUgdG8gYmUKPiAg -ICBwb3B1bGF0ZWQgYW5kIHRoZW4gcGFzc2VkIHRvIGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVy -X3dpdGhfZ3JvdXBzKCkuCj4KPiAgICBOb3RlOiBIYXZpbmcgYW4gYXJyYXkgb2YgcG9pbnRlcnMg -b2YgJ2F0dHJpYnV0ZV9ncm91cCcgYW5kIGVhY2ggZ3JvdXAKPiAgICBjb3JyZXNwb25kcyB0byAn -ZW51bSBzZW5zb3JzJyB0eXBlLiBOb3QgY29tcGxldGVseSBzdXJlLCBpZiBpdCdzIGlkZWFsIG9y -Cj4gICAgY291bGQgaGF2ZSBqdXN0IG9uZSBncm91cCBwb3B1bGF0ZWQgd2l0aCBhdHRyaWJ1dGVz -IG9mIHNlbnNvciB0eXBlcz8KPgo+IC0gJ2libXBvd2VybnYnIGlzIG5vdCBob3QtcGx1Z2dhYmxl -IGRldmljZSBzbyBtb3ZpbmcgJ3BsYXRmb3JtX2RyaXZlcicgY2FsbGJhY2sKPiAgICBmdW5jdGlv -biAocHJvYmUpIGFzIHBhcnQgb2YgX19pbml0IGNvZGUuCj4gLSBGaXhlZCBpc3N1ZXMgcmVsYXRl -ZCB0byBjb2Rpbmcgc3R5bGUuCj4gLSBPdGhlciBnZW5lcmFsIGNvbW1lbnRzIGluIHYxLgo+Cj4g -ICAuLi4vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4dCAgICAgICB8ICAg -MjcgKwo+ICAgRG9jdW1lbnRhdGlvbi9od21vbi9pYm1wb3dlcm52ICAgICAgICAgICAgICAgICAg -ICAgfCAgIDQxICsrCj4gICBkcml2ZXJzL2h3bW9uL0tjb25maWcgICAgICAgICAgICAgICAgICAg -ICAgICAgICAgICB8ICAgMTEgKwo+ICAgZHJpdmVycy9od21vbi9NYWtlZmlsZSAgICAgICAgICAg -ICAgICAgICAgICAgICAgICAgfCAgICAxCj4gICBkcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYyAg -ICAgICAgICAgICAgICAgICAgICAgICB8ICAzNjIgKysrKysrKysrKysrKysrKysrKysKPiAgIDUg -ZmlsZXMgY2hhbmdlZCwgNDQyIGluc2VydGlvbnMoKykKPiAgIGNyZWF0ZSBtb2RlIDEwMDY0NCBE -b2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQKPiAg -IGNyZWF0ZSBtb2RlIDEwMDY0NCBEb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYKPiAgIGNy -ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYwo+Cj4gZGlmZiAtLWdp -dCBhL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4 -dCBiL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4 -dAo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uZTNiZDFlYgo+IC0tLSAv -ZGV2L251bGwKPiArKysgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvaHdtb24v -aWJtcG93ZXJudi50eHQKPiBAQCAtMCwwICsxLDI3IEBACj4gK0lCTSBQT1dFUk5WIHBsYXRmb3Jt -IHNlbnNvcnMKPiArLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo+ICsKPiArUmVxdWlyZWQg -bm9kZSBwcm9wZXJ0aWVzOgo+ICstIGNvbXBhdGlibGU6IG11c3QgYmUgb25lIG9mCj4gKwkJImli -bSxvcGFsLXNlbnNvci1jb29saW5nLWZhbiIKPiArCQkiaWJtLG9wYWwtc2Vuc29yLWFtYi10ZW1w -Igo+ICsJCSJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3VwcGx5Igo+ICsJCSJpYm0sb3BhbC1zZW5z -b3ItcG93ZXIiCj4gKy0gc2Vuc29yLWlkOiBhbiBvcGFxdWUgaWQgcHJvdmlkZWQgYnkgdGhlIGZp -cm13YXJlIHRvIHRoZSBrZXJuZWwsIGlkZW50aWZpZXMgYQo+ICsJICAgICBnaXZlbiBzZW5zb3Ig -YW5kIGl0cyBhdHRyaWJ1dGUgZGF0YQo+ICsKPiArRXhhbXBsZSBzZW5zb3JzIG5vZGU6Cj4gKwo+ -ICtjb29saW5nLWZhbiM4LWRhdGEgewo+ICsJc2Vuc29yLWlkID0gPDB4NzA1MjEwNz47Cj4gKwlw -aGFuZGxlID0gPDB4MTAwMDAwMjg+Owo+ICsJbGludXgscGhhbmRsZSA9IDwweDEwMDAwMDI4PjsK -PiArCWNvbXBhdGlibGUgPSAiaWJtLG9wYWwtc2Vuc29yLWNvb2xpbmctZmFuIjsKCnBoYW5kbGUg -YW5kIGxpbnV4LXBoYW5kbGUgYXJlIG5laXRoZXIgZG9jdW1lbnRlZCBub3IgdXNlZC4gRWl0aGVy -IGRvY3VtZW50IG9yIGRyb3AuCgo+ICt9Owo+ICsKPiArYW1iLXRlbXAjMS10aHJzIHsKPiArCXNl -bnNvci1pZCA9IDwweDUwOTYwMDA+Owo+ICsJcGhhbmRsZSA9IDwweDEwMDAwMDE3PjsKPiArCWxp -bnV4LHBoYW5kbGUgPSA8MHgxMDAwMDAxNz47Cj4gKwljb21wYXRpYmxlID0gImlibSxvcGFsLXNl -bnNvci1hbWItdGVtcCI7Cj4gK307Cj4gZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24vaHdtb24v -aWJtcG93ZXJudiBiL0RvY3VtZW50YXRpb24vaHdtb24vaWJtcG93ZXJudgo+IG5ldyBmaWxlIG1v -ZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uNjQ0MjQ1YQo+IC0tLSAvZGV2L251bGwKPiArKysg -Yi9Eb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYKPiBAQCAtMCwwICsxLDQxIEBACj4gK0tl -cm5lbCBEcml2ZXIgSUJNUE9XRU5WCj4gKz09PT09PT09PT09PT09PT09PT09PT09Cj4gKwo+ICtT -dXBwb3J0ZWQgc3lzdGVtczoKPiArICAqIEFueSByZWNlbnQgSUJNIFAgc2VydmVycyBiYXNlZCBv -biBQT1dFUk5WIHBsYXRmb3JtCj4gKwo+ICtBdXRob3I6IE5lZWxlc2ggR3VwdGEKPiArCj4gK0Rl -c2NyaXB0aW9uCj4gKy0tLS0tLS0tLS0tCj4gKwo+ICtUaGlzIGRyaXZlciBpbXBsZW1lbnRzIHJl -YWRpbmcgdGhlIHBsYXRmb3JtIHNlbnNvcnMgZGF0YSBsaWtlIHRlbXBlcmF0dXJlL2Zhbi8KPiAr -dm9sdGFnZS9wb3dlciBmb3IgJ1BPV0VSTlYnIHBsYXRmb3JtLgo+ICsKPiArVGhlIGRyaXZlciB1 -c2VzIHRoZSBwbGF0Zm9ybSBkZXZpY2UgaW5mcmFzdHJ1Y3R1cmUuIEl0IHByb2JlcyB0aGUgZGV2 -aWNlIHRyZWUKPiArZm9yIHNlbnNvciBkZXZpY2VzIGR1cmluZyB0aGUgX19pbml0IHBoYXNlIGFu -ZCByZWdpc3RlcnMgdGhlbSB3aXRoIHRoZSAnaHdtb24nLgo+ICsnaHdtb24nIHBvcHVsYXRlcyB0 -aGUgJ3N5c2ZzJyB0cmVlIGhhdmluZyBhdHRyaWJ1dGUgZmlsZXMsIGVhY2ggZm9yIGEgZ2l2ZW4K -PiArc2Vuc29yIHR5cGUgYW5kIGl0cyBhdHRyaWJ1dGUgZGF0YS4KPiArCj4gK0FsbCB0aGUgbm9k -ZXMgaW4gdGhlIERUIGFwcGVhciB1bmRlciAiL2libSxvcGFsL3NlbnNvcnMiIGFuZCBlYWNoIHZh -bGlkIG5vZGUgaW4KPiArdGhlIERUIG1hcHMgdG8gYW4gYXR0cmlidXRlIGZpbGUgaW4gJ3N5c2Zz -Jy4gVGhlIG5vZGUgZXhwb3J0cyB1bmlxdWUgJ3NlbnNvci1pZCcKPiArd2hpY2ggdGhlIGRyaXZl -ciB1c2VzIHRvIG1ha2UgYW4gT1BBTCBjYWxsIHRvIHRoZSBmaXJtd2FyZS4KPiArCj4gK1VzYWdl -IG5vdGVzCj4gKy0tLS0tLS0tLS0tCj4gK1RoZSBkcml2ZXIgaXMgYnVpbHQgc3RhdGljYWxseSB3 -aXRoIHRoZSBrZXJuZWwgYnkgZW5hYmxpbmcgdGhlIGNvbmZpZwo+ICtDT05GSUdfU0VOU09SU19J -Qk1QT1dFUk5WLiBJdCBjYW4gYWxzbyBiZSBidWlsdCBhcyBtb2R1bGUgJ2libXBvd2VybnYnLgo+ -ICsKPiArU3lzZnMgYXR0cmlidXRlcwo+ICstLS0tLS0tLS0tLS0tLS0tCj4gKwo+ICtmYW5YX2lu -cHV0CQlNZWFzdXJlZCBSUE0gdmFsdWUuCj4gK2ZhblhfbWluCQlUaHJlc2hvbGQgUlBNIGZvciBh -bGVydCBnZW5lcmF0aW9uLgo+ICtmYW5YX2ZhdWx0CQkwOiBObyBmYWlsIGNvbmRpdGlvbgo+ICsJ -CQkxOiBGYWlsaW5nIGZhbgo+ICt0ZW1wWF9pbnB1dAkJTWVhc3VyZWQgYW1iaWVudCB0ZW1wZXJh -dHVyZS4KPiArdGVtcFhfbWF4CQlUaHJlc2hvbGQgYW1iaWVudCB0ZW1wZXJhdHVyZSBmb3IgYWxl -cnQgZ2VuZXJhdGlvbi4KPiAraW5YX2lucHV0CQlNZWFzdXJlZCBwb3dlciBzdXBwbHkgdm9sdGFn -ZQo+ICtpblhfZmF1bHQJCTA6IE5vIGZhaWwgY29uZGl0aW9uLgo+ICsJCQkxOiBGYWlsaW5nIHBv -d2VyIHN1cHBseS4KPiArcG93ZXIxX2lucHV0CQlTeXN0ZW0gcG93ZXIgY29uc3VtcHRpb24gKG1p -Y3JvV2F0dCkKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmlnIGIvZHJpdmVycy9o -d21vbi9LY29uZmlnCj4gaW5kZXggMDJkM2Q4NS4uMjljM2ZjYiAxMDA2NDQKPiAtLS0gYS9kcml2 -ZXJzL2h3bW9uL0tjb25maWcKPiArKysgYi9kcml2ZXJzL2h3bW9uL0tjb25maWcKPiBAQCAtNTU0 -LDYgKzU1NCwxNyBAQCBjb25maWcgU0VOU09SU19JQk1QRVgKPiAgIAkgIFRoaXMgZHJpdmVyIGNh -biBhbHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiAgSWYgc28sIHRoZSBtb2R1bGUKPiAgIAkgIHdp -bGwgYmUgY2FsbGVkIGlibXBleC4KPgo+ICtjb25maWcgU0VOU09SU19JQk1QT1dFUk5WCj4gKwl0 -cmlzdGF0ZSAiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIKPiArCWRlcGVuZHMgb24gUFBD -X1BPV0VSTlYKPiArCWRlZmF1bHQgeQo+ICsJaGVscAo+ICsJICBJZiB5b3Ugc2F5IHllcyBoZXJl -IHlvdSBnZXQgc3VwcG9ydCBmb3IgdGhlIHRlbXBlcmF0dXJlL2Zhbi9wb3dlcgo+ICsJICBzZW5z -b3JzIG9uIHlvdXIgUG93ZXJOViBwbGF0Zm9ybS4KPiArCj4gKwkgIFRoaXMgZHJpdmVyIGNhbiBh -bHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiBJZiBzbywgdGhlIG1vZHVsZQo+ICsJICB3aWxsIGJl -IGNhbGxlZCBpYm1wb3dlcm52Lgo+ICsKPiAgIGNvbmZpZyBTRU5TT1JTX0lJT19IV01PTgo+ICAg -CXRyaXN0YXRlICJId21vbiBkcml2ZXIgdGhhdCB1c2VzIGNoYW5uZWxzIHNwZWNpZmllZCB2aWEg -aWlvIG1hcHMiCj4gICAJZGVwZW5kcyBvbiBJSU8KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21v -bi9NYWtlZmlsZSBiL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPiBpbmRleCAzZGMwZjAyLi5mYzRl -ZDI2IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPiArKysgYi9kcml2ZXJz -L2h3bW9uL01ha2VmaWxlCj4gQEAgLTcxLDYgKzcxLDcgQEAgb2JqLSQoQ09ORklHX1NFTlNPUlNf -VUxUUkE0NSkJKz0gdWx0cmE0NV9lbnYubwo+ICAgb2JqLSQoQ09ORklHX1NFTlNPUlNfSTVLX0FN -QikJKz0gaTVrX2FtYi5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JQk1BRU0pCSs9IGlibWFl -bS5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JQk1QRVgpCSs9IGlibXBleC5vCj4gK29iai0k -KENPTkZJR19TRU5TT1JTX0lCTVBPV0VSTlYpKz0gaWJtcG93ZXJudi5vCj4gICBvYmotJChDT05G -SUdfU0VOU09SU19JSU9fSFdNT04pICs9IGlpb19od21vbi5vCj4gICBvYmotJChDT05GSUdfU0VO -U09SU19JTkEyMDkpCSs9IGluYTIwOS5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JTkEyWFgp -CSs9IGluYTJ4eC5vCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jIGIv -ZHJpdmVycy9od21vbi9pYm1wb3dlcm52LmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4 -IDAwMDAwMDAuLjQ0ZGNkOTkKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy9od21vbi9p -Ym1wb3dlcm52LmMKPiBAQCAtMCwwICsxLDM2MiBAQAo+ICsvKgo+ICsgKiBJQk0gUG93ZXJOViBw -bGF0Zm9ybSBzZW5zb3JzIGZvciB0ZW1wZXJhdHVyZS9mYW4vdm9sdGFnZS9wb3dlcgo+ICsgKiBD -b3B5cmlnaHQgKEMpIDIwMTQgSUJNCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNv -ZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5Cj4gKyAqIGl0IHVu -ZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlz -aGVkIGJ5Cj4gKyAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9u -IDIgb2YgdGhlIExpY2Vuc2UsIG9yCj4gKyAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZl -cnNpb24uCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9w -ZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAo+ICsgKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7 -IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgo+ICsgKiBNRVJDSEFOVEFCSUxJ -VFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCj4gKyAqIEdO -VSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCj4gKyAqCj4gKyAqIFlv -dSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBM -aWNlbnNlCj4gKyAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtLgo+ICsgKi8KPiArCj4gKyNkZWZp -bmUgRFJWTkFNRQkJImlibXBvd2VybnYiCj4gKyNkZWZpbmUgcHJfZm10KGZtdCkJRFJWTkFNRSAi -OiAiIGZtdAo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KPiArI2luY2x1ZGUgPGxpbnV4 -L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgva2VybmVsLmg+Cj4gKyNpbmNsdWRlIDxsaW51 -eC9od21vbi5oPgo+ICsjaW5jbHVkZSA8bGludXgvaHdtb24tc3lzZnMuaD4KPiArI2luY2x1ZGUg -PGxpbnV4L29mLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cj4gKwo+ICsjaW5jbHVkZSA8 -bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4gKyNpbmNsdWRlIDxhc20vb3BhbC5oPgo+ICsjaW5j -bHVkZSA8bGludXgvZXJyLmg+Cj4gKwo+ICsjZGVmaW5lIE1BWF9BVFRSX0xFTgkzMgo+ICsKPiAr -LyogU2Vuc29yIHN1ZmZpeCBuYW1lIGZyb20gRFQgKi8KPiArI2RlZmluZSBEVF9GQVVMVF9BVFRS -X1NVRkZJWAkJImZhdWx0ZWQiCj4gKyNkZWZpbmUgRFRfREFUQV9BVFRSX1NVRkZJWAkJImRhdGEi -Cj4gKyNkZWZpbmUgRFRfVEhSRVNIT0xEX0FUVFJfU1VGRklYCSJ0aHJzIgo+ICsKPiArLyoKPiAr -ICogRW51bWVyYXRlcyBhbGwgdGhlIHR5cGVzIG9mIHNlbnNvcnMgaW4gdGhlIFBPV0VSTlYgcGxh -dGZvcm0gYW5kIGRvZXMgaW5kZXgKPiArICogaW50byAnc3RydWN0IHNlbnNvcl9ncm91cCcKPiAr -ICovCj4gK2VudW0gc2Vuc29ycyB7Cj4gKwlGQU4sCj4gKwlBTUJJRU5UX1RFTVAsCj4gKwlQT1dF -Ul9TVVBQTFksCj4gKwlQT1dFUl9JTlBVVCwKPiArCU1BWF9TRU5TT1JfVFlQRSwKPiArfTsKPiAr -Cj4gK3N0YXRpYyBzdHJ1Y3Qgc2Vuc29yX2dyb3VwIHsKPiArCWNvbnN0IGNoYXIgKm5hbWU7Cj4g -Kwljb25zdCBjaGFyICpjb21wYXRpYmxlOwo+ICsJc3RydWN0IGF0dHJpYnV0ZV9ncm91cCBncm91 -cDsKPiArCXUzMiBhdHRyX2NvdW50Owo+ICt9IHNlbnNvcl9ncm91cHNbXSA9IHsKPiArCXsiZmFu -IiwgImlibSxvcGFsLXNlbnNvci1jb29saW5nLWZhbiJ9LAo+ICsJeyJ0ZW1wIiwgImlibSxvcGFs -LXNlbnNvci1hbWItdGVtcCJ9LAo+ICsJeyJpbiIsICJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3Vw -cGx5In0sCj4gKwl7InBvd2VyIiwgImlibSxvcGFsLXNlbnNvci1wb3dlciJ9Cj4gK307Cj4gKwo+ -ICtzdHJ1Y3Qgc2Vuc29yX2RhdGEgewo+ICsJdTMyIGlkOyAvKiBBbiBvcGFxdWUgaWQgb2YgdGhl -IGZpcm13YXJlIGZvciBlYWNoIHNlbnNvciAqLwo+ICsJZW51bSBzZW5zb3JzIHR5cGU7Cj4gKwlj -aGFyIG5hbWVbTUFYX0FUVFJfTEVOXTsKPiArCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlIGRldl9h -dHRyOwo+ICt9Owo+ICsKPiArc3RydWN0IHBsYXRmb3JtX2RhdGEgewo+ICsJY29uc3Qgc3RydWN0 -IGF0dHJpYnV0ZV9ncm91cCAqYXR0cl9ncm91cHNbTUFYX1NFTlNPUl9UWVBFICsgMV07Cj4gKwl1 -MzIgc2Vuc29yc19jb3VudDsgLyogVG90YWwgY291bnQgb2Ygc2Vuc29ycyBmcm9tIGVhY2ggZ3Jv -dXAgKi8KPiArfTsKPiArCj4gKy8qIFBsYXRmb3JtIGRldmljZSByZXByZXNlbnRpbmcgYWxsIHRo -ZSBpYm1wb3dlcm52IHNlbnNvcnMgKi8KPiArc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2Ug -KnBkZXZpY2U7Cj4gKwo+ICtzdGF0aWMgc3NpemVfdCBzaG93X3NlbnNvcihzdHJ1Y3QgZGV2aWNl -ICpkZXYsIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkZXZhdHRyLAo+ICsJCQkgICBjaGFyICpi -dWYpCj4gK3sKPiArCXN0cnVjdCBzZW5zb3JfZGF0YSAqc2RhdGEgPSBjb250YWluZXJfb2YoZGV2 -YXR0ciwgc3RydWN0IHNlbnNvcl9kYXRhLAo+ICsJCQkJCQkgZGV2X2F0dHIpOwo+ICsJc3NpemVf -dCByZXQ7Cj4gKwl1MzIgeDsKPiArCj4gKwlyZXQgPSBvcGFsX2dldF9zZW5zb3JfZGF0YShzZGF0 -YS0+aWQsICZ4KTsKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwkvKiBDb252 -ZXJ0IHRlbXBlcmF0dXJlIHRvIG1pbGxpLWRlZ3JlZXMgKi8KPiArCWlmIChzZGF0YS0+dHlwZSA9 -PSBBTUJJRU5UX1RFTVApCj4gKwkJeCAqPSAxMDAwOwo+ICsJLyogQ29udmVydCBwb3dlciB0byBt -aWNyby13YXR0cyAqLwo+ICsJZWxzZSBpZiAoc2RhdGEtPnR5cGUgPT0gUE9XRVJfSU5QVVQpCj4g -KwkJeCAqPSAxMDAwMDAwOwo+ICsKPiArCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiV1XG4iLCB4KTsK -PiArfQo+ICsKPiArc3RhdGljIGludCBfX2luaXQgZ2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0 -IGNoYXIgKm5hbWUsIHUzMiAqaW5kZXgsCj4gKwkJCQkJY2hhciAqYXR0cikKPiArewo+ICsJY2hh -ciAqaGFzaF9wb3MgPSBzdHJjaHIobmFtZSwgJyMnKTsKPiArCWNoYXIgYnVmWzhdID0geyAwIH07 -Cj4gKwljaGFyICpkYXNoX3BvczsKPiArCXUzMiBjb3B5X2xlbjsKPiArCj4gKwlpZiAoIWhhc2hf -cG9zKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCWRhc2hfcG9zID0gc3RyY2hyKGhhc2hf -cG9zLCAnLScpOwo+ICsJaWYgKCFkYXNoX3BvcykKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4g -Kwljb3B5X2xlbiA9IGRhc2hfcG9zIC0gaGFzaF9wb3MgLSAxOwo+ICsJaWYgKGNvcHlfbGVuID49 -IHNpemVvZihidWYpKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXN0cm5jcHkoYnVmLCBo -YXNoX3BvcyArIDEsIGNvcHlfbGVuKTsKPiArCj4gKwlpZiAoa3N0cnRvdTMyKGJ1ZiwgMTAsIGlu -ZGV4KSkKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCnNtYXRjaCBpc24ndCBnb2luZyB0byBsaWtl -IHRoYXQuIFBsZWFzZSB1c2UKCglpbnQgZXJyOwoJLi4uCgllcnIgPSBrc3RydG91MzIoYnVmLCAx -MCwgaW5kZXgpKTsKCWlmIChlcnIpCgkJcmV0dXJuIGVycjsKCj4gKwlzdHJuY3B5KGF0dHIsIGRh -c2hfcG9zICsgMSwgTUFYX0FUVFJfTEVOKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiAr -LyoKPiArICogVGhpcyBmdW5jdGlvbiB0cmFuc2xhdGVzIHRoZSBEVCBub2RlIG5hbWUgaW50byB0 -aGUgJ2h3bW9uJyBhdHRyaWJ1dGUgbmFtZS4KPiArICogSUJNUE9XRVJOViBkZXZpY2Ugbm9kZSBh -cHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIGFtYi10ZW1wIzEtdGhycyBldGMuCj4gKyAq -IHdoaWNoIG5lZWQgdG8gYmUgbWFwcGVkIGFzIGZhbjJfaW5wdXQsIHRlbXAxX21heCByZXNwZWN0 -aXZlbHkgYmVmb3JlCj4gKyAqIHBvcHVsYXRpbmcgdGhlbSBpbnNpZGUgaHdtb24gZGV2aWNlIGNs -YXNzLgo+ICsgKi8KPiArc3RhdGljIGludCBfX2luaXQgY3JlYXRlX2h3bW9uX2F0dHJfbmFtZShz -dHJ1Y3QgZGV2aWNlICpkZXYsIGVudW0gc2Vuc29ycyB0eXBlLAo+ICsJCQkJCSBjb25zdCBjaGFy -ICpub2RlX25hbWUsCj4gKwkJCQkJIGNoYXIgKmh3bW9uX2F0dHJfbmFtZSkKPiArewo+ICsJY2hh -ciBhdHRyX3N1ZmZpeFtNQVhfQVRUUl9MRU5dOwo+ICsJY2hhciAqYXR0cl9uYW1lOwo+ICsJdTMy -IGluZGV4Owo+ICsJaW50IGVycjsKPiArCj4gKwllcnIgPSBnZXRfc2Vuc29yX2luZGV4X2F0dHIo -bm9kZV9uYW1lLCAmaW5kZXgsIGF0dHJfc3VmZml4KTsKPiArCWlmIChlcnIpIHsKPiArCQlkZXZf -ZXJyKGRldiwgIlNlbnNvciBkZXZpY2Ugbm9kZSBuYW1lICclcycgaXMgaW52YWxpZFxuIiwKPiAr -CQkJbm9kZV9uYW1lKTsKPiArCQlyZXR1cm4gZXJyOwo+ICsJfQo+ICsKPiArCWlmICghc3RyY21w -KGF0dHJfc3VmZml4LCBEVF9GQVVMVF9BVFRSX1NVRkZJWCkpIHsKPiArCQlhdHRyX25hbWUgPSAi -ZmF1bHQiOwo+ICsJfSBlbHNlIGlmICghc3RyY21wKGF0dHJfc3VmZml4LCBEVF9EQVRBX0FUVFJf -U1VGRklYKSkgewo+ICsJCWF0dHJfbmFtZSA9ICJpbnB1dCI7Cj4gKwl9IGVsc2UgaWYgKCFzdHJj -bXAoYXR0cl9zdWZmaXgsIERUX1RIUkVTSE9MRF9BVFRSX1NVRkZJWCkpIHsKPiArCQlpZiAodHlw -ZSA9PSBBTUJJRU5UX1RFTVApCj4gKwkJCWF0dHJfbmFtZSA9ICJtYXgiOwo+ICsJCWVsc2UgaWYg -KHR5cGUgPT0gRkFOKQo+ICsJCQlhdHRyX25hbWUgPSAibWluIjsKPiArCQllbHNlCj4gKwkJCXJl -dHVybiAtRU5PRU5UOwo+ICsJfSBlbHNlIHsKPiArCQlyZXR1cm4gLUVOT0VOVDsKPiArCX0KPiAr -Cj4gKwlzbnByaW50Zihod21vbl9hdHRyX25hbWUsIE1BWF9BVFRSX0xFTiwgIiVzJWRfJXMiLAo+ -ICsJCSBzZW5zb3JfZ3JvdXBzW3R5cGVdLm5hbWUsIGluZGV4LCBhdHRyX25hbWUpOwo+ICsJcmV0 -dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgX19pbml0IHBvcHVsYXRlX2F0dHJfZ3JvdXBz -KHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiArCXN0cnVjdCBwbGF0Zm9ybV9k -YXRhICpwZGF0YSA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ICsJY29uc3Qgc3RydWN0 -IGF0dHJpYnV0ZV9ncm91cCAqKnBncm91cHMgPSBwZGF0YS0+YXR0cl9ncm91cHM7Cj4gKwlzdHJ1 -Y3QgZGV2aWNlX25vZGUgKm9wYWwsICpucDsKPiArCWVudW0gc2Vuc29ycyB0eXBlOwo+ICsKPiAr -CW9wYWwgPSBvZl9maW5kX25vZGVfYnlfcGF0aCgiL2libSxvcGFsL3NlbnNvcnMiKTsKPiArCWlm -ICghb3BhbCkgewo+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgIk9wYWwgbm9kZSAnc2Vuc29ycycg -bm90IGZvdW5kXG4iKTsKPiArCQlyZXR1cm4gLUVOT0RFVjsKPiArCX0KPiArCj4gKwlmb3JfZWFj -aF9jaGlsZF9vZl9ub2RlKG9wYWwsIG5wKSB7Cj4gKwkJaWYgKG5wLT5uYW1lID09IE5VTEwpCj4g -KwkJCWNvbnRpbnVlOwo+ICsKPiArCQlmb3IgKHR5cGUgPSAwOyB0eXBlIDwgTUFYX1NFTlNPUl9U -WVBFOyB0eXBlKyspCj4gKwkJCWlmIChvZl9kZXZpY2VfaXNfY29tcGF0aWJsZShucCwKPiArCQkJ -CQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmNvbXBhdGlibGUpKSB7Cj4gKwkJCQlzZW5zb3JfZ3JvdXBz -W3R5cGVdLmF0dHJfY291bnQrKzsKPiArCQkJCWJyZWFrOwo+ICsJCQl9Cj4gKwl9Cj4gKwo+ICsJ -b2Zfbm9kZV9wdXQob3BhbCk7Cj4gKwo+ICsJZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5T -T1JfVFlQRTsgdHlwZSsrKSB7Cj4gKwkJc2Vuc29yX2dyb3Vwc1t0eXBlXS5ncm91cC5hdHRycyA9 -IGRldm1fa3phbGxvYygmcGRldi0+ZGV2LAo+ICsJCQkJCXNpemVvZihzdHJ1Y3QgYXR0cmlidXRl -ICopICoKPiArCQkJCQkoc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRyX2NvdW50ICsgMSksCj4gKwkJ -CQkJR0ZQX0tFUk5FTCk7Cj4gKwkJaWYgKCFzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJz -KQo+ICsJCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwkJcGdyb3Vwc1t0eXBlXSA9ICZzZW5zb3Jf -Z3JvdXBzW3R5cGVdLmdyb3VwOwo+ICsJCXBkYXRhLT5zZW5zb3JzX2NvdW50ICs9IHNlbnNvcl9n -cm91cHNbdHlwZV0uYXR0cl9jb3VudDsKPiArCQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmF0dHJfY291 -bnQgPSAwOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICsvKgo+ICsgKiBJdGVy -YXRlIHRocm91Z2ggdGhlIGRldmljZSB0cmVlIGZvciBlYWNoIGNoaWxkIG9mICdzZW5zb3JzJyBu -b2RlLCBjcmVhdGUKPiArICogYSBzeXNmcyBhdHRyaWJ1dGUgZmlsZSwgdGhlIGZpbGUgaXMgbmFt -ZWQgYnkgdHJhbnNsYXRpbmcgdGhlIERUIG5vZGUgbmFtZQo+ICsgKiB0byB0aGUgbmFtZSByZXF1 -aXJlZCBieSB0aGUgaGlnaGVyICdod21vbicgZHJpdmVyIGxpa2UgZmFuMV9pbnB1dCwgdGVtcDFf -bWF4Cj4gKyAqIGV0Yy4uCj4gKyAqLwo+ICtzdGF0aWMgaW50IF9faW5pdCBjcmVhdGVfZGV2aWNl -X2F0dHJzKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiArCXN0cnVjdCBwbGF0 -Zm9ybV9kYXRhICpwZGF0YSA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ICsJY29uc3Qg -c3RydWN0IGF0dHJpYnV0ZV9ncm91cCAqKnBncm91cHMgPSBwZGF0YS0+YXR0cl9ncm91cHM7Cj4g -KwlzdHJ1Y3QgZGV2aWNlX25vZGUgKm9wYWwsICpucDsKPiArCXN0cnVjdCBzZW5zb3JfZGF0YSAq -c2RhdGE7Cj4gKwljb25zdCBfX2JlMzIgKnNlbnNvcl9pZDsKPiArCWVudW0gc2Vuc29ycyB0eXBl -Owo+ICsJdTMyIGNvdW50ID0gMDsKPiArCWludCBlcnIgPSAwOwo+ICsKPiArCW9wYWwgPSBvZl9m -aW5kX25vZGVfYnlfcGF0aCgiL2libSxvcGFsL3NlbnNvcnMiKTsKPiArCXNkYXRhID0gZGV2bV9r -emFsbG9jKCZwZGV2LT5kZXYsIHBkYXRhLT5zZW5zb3JzX2NvdW50ICogc2l6ZW9mKCpzZGF0YSks -Cj4gKwkJCSAgICAgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIXNkYXRhKSB7Cj4gKwkJZXJyID0gLUVO -T01FTTsKPiArCQlnb3RvIGV4aXRfcHV0X25vZGU7Cj4gKwl9Cj4gKwo+ICsJZm9yX2VhY2hfY2hp -bGRfb2Zfbm9kZShvcGFsLCBucCkgewo+ICsJCWlmIChucC0+bmFtZSA9PSBOVUxMKQo+ICsJCQlj -b250aW51ZTsKPiArCj4gKwkJZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5TT1JfVFlQRTsg -dHlwZSsrKQo+ICsJCQlpZiAob2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCj4gKwkJCQkJc2Vu -c29yX2dyb3Vwc1t0eXBlXS5jb21wYXRpYmxlKSkKPiArCQkJCWJyZWFrOwo+ICsKPiArCQlpZiAo -dHlwZSA9PSBNQVhfU0VOU09SX1RZUEUpCj4gKwkJCWNvbnRpbnVlOwo+ICsKPiArCQlzZW5zb3Jf -aWQgPSBvZl9nZXRfcHJvcGVydHkobnAsICJzZW5zb3ItaWQiLCBOVUxMKTsKPiArCQlpZiAoIXNl -bnNvcl9pZCkgewo+ICsJCQlkZXZfaW5mbygmcGRldi0+ZGV2LAo+ICsJCQkJICInc2Vuc29yLWlk -JyBtaXNzaW5nIGluIHRoZSBub2RlICclcydcbiIsCj4gKwkJCQkgbnAtPm5hbWUpOwo+ICsJCQlj -b250aW51ZTsKPiArCQl9Cj4gKwo+ICsJCXNkYXRhW2NvdW50XS5pZCA9IGJlMzJfdG9fY3B1cChz -ZW5zb3JfaWQpOwo+ICsJCXNkYXRhW2NvdW50XS50eXBlID0gdHlwZTsKPiArCQllcnIgPSBjcmVh -dGVfaHdtb25fYXR0cl9uYW1lKCZwZGV2LT5kZXYsIHR5cGUsIG5wLT5uYW1lLAo+ICsJCQkJCSAg -ICAgc2RhdGFbY291bnRdLm5hbWUpOwo+ICsJCWlmIChlcnIpCj4gKwkJCWdvdG8gZXhpdF9wdXRf -bm9kZTsKPiArCj4gKwkJc3lzZnNfYXR0cl9pbml0KCZzZGF0YVtjb3VudF0uZGV2X2F0dHIuYXR0 -cik7Cj4gKwkJc2RhdGFbY291bnRdLmRldl9hdHRyLmF0dHIubmFtZSA9IHNkYXRhW2NvdW50XS5u -YW1lOwo+ICsJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5hdHRyLm1vZGUgPSBTX0lSVUdPOwo+ICsJ -CXNkYXRhW2NvdW50XS5kZXZfYXR0ci5zaG93ID0gc2hvd19zZW5zb3I7Cj4gKwo+ICsJCXBncm91 -cHNbdHlwZV0tPmF0dHJzW3NlbnNvcl9ncm91cHNbdHlwZV0uYXR0cl9jb3VudCsrXSA9Cj4gKwkJ -CQkmc2RhdGFbY291bnQrK10uZGV2X2F0dHIuYXR0cjsKPiArCX0KPiArCj4gK2V4aXRfcHV0X25v -ZGU6Cj4gKwlvZl9ub2RlX3B1dChvcGFsKTsKPiArCXJldHVybiBlcnI7Cj4gK30KPiArCj4gK3N0 -YXRpYyBpbnQgX19pbml0IGlibXBvd2VybnZfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAq -cGRldikKPiArewo+ICsJc3RydWN0IHBsYXRmb3JtX2RhdGEgKnBkYXRhOwo+ICsJc3RydWN0IGRl -dmljZSAqaHdtb25fZGV2Owo+ICsJaW50IGVycjsKPiArCj4gKwlwZGF0YSA9IGRldm1fa3phbGxv -YygmcGRldi0+ZGV2LCBzaXplb2YoKnBkYXRhKSwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIXBkYXRh -KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYs -IHBkYXRhKTsKPiArCXBkYXRhLT5zZW5zb3JzX2NvdW50ID0gMDsKPiArCWVyciA9IHBvcHVsYXRl -X2F0dHJfZ3JvdXBzKHBkZXYpOwo+ICsJaWYgKGVycikKPiArCQlyZXR1cm4gZXJyOwo+ICsKPiAr -CS8qIENyZWF0ZSBzeXNmcyBhdHRyaWJ1dGUgZGF0YSBmb3IgZWFjaCBzZW5zb3IgZm91bmQgaW4g -dGhlIERUICovCj4gKwllcnIgPSBjcmVhdGVfZGV2aWNlX2F0dHJzKHBkZXYpOwo+ICsJaWYgKGVy -cikKPiArCQlyZXR1cm4gZXJyOwo+ICsKPiArCS8qIEZpbmFsbHksIHJlZ2lzdGVyIHdpdGggaHdt -b24gKi8KPiArCWh3bW9uX2RldiA9IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhfZ3Jv -dXBzKCZwZGV2LT5kZXYsIERSVk5BTUUsCj4gKwkJCQkJCQkgICBwZGF0YSwKPiArCQkJCQkJCSAg -IHBkYXRhLT5hdHRyX2dyb3Vwcyk7Cj4gKwo+ICsJcmV0dXJuIFBUUl9FUlJfT1JfWkVSTyhod21v -bl9kZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBpYm1wb3dl -cm52X2RyaXZlciA9IHsKPiArCS5kcml2ZXIgPSB7Cj4gKwkJLm93bmVyID0gVEhJU19NT0RVTEUs -Cj4gKwkJLm5hbWUgPSBEUlZOQU1FLAo+ICsJfSwKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgX19p -bml0IGlibXBvd2VybnZfaW5pdCh2b2lkKQo+ICt7Cj4gKwlpbnQgZXJyOwo+ICsKPiArCXBkZXZp -Y2UgPSBwbGF0Zm9ybV9kZXZpY2VfYWxsb2MoRFJWTkFNRSwgMCk7Cj4gKwlpZiAoIXBkZXZpY2Up -IHsKPiArCQlwcl9lcnIoIkRldmljZSBhbGxvY2F0aW9uIGZhaWxlZFxuIik7Cj4gKwkJZXJyID0g -LUVOT01FTTsKPiArCQlnb3RvIGV4aXQ7Cj4gKwl9Cj4gKwo+ICsJZXJyID0gcGxhdGZvcm1fZGV2 -aWNlX2FkZChwZGV2aWNlKTsKPiArCWlmIChlcnIpIHsKPiArCQlwcl9lcnIoIkRldmljZSBhZGRp -dGlvbiBmYWlsZWQgKCVkKVxuIiwgZXJyKTsKPiArCQlnb3RvIGV4aXRfZGV2aWNlX3B1dDsKPiAr -CX0KPiArCj4gKwllcnIgPSBwbGF0Zm9ybV9kcml2ZXJfcHJvYmUoJmlibXBvd2VybnZfZHJpdmVy -LCBpYm1wb3dlcm52X3Byb2JlKTsKPiArCWlmIChlcnIpIHsKPiArCQlwcl9lcnIoIlBsYXRmcm9t -IGRyaXZlciBwcm9iZSBmYWlsZWRcbiIpOwo+ICsJCWdvdG8gZXhpdF9kZXZpY2VfZGVsOwo+ICsJ -fQo+ICsKPiArCXJldHVybiAwOwo+ICsKPiArZXhpdF9kZXZpY2VfZGVsOgo+ICsJcGxhdGZvcm1f -ZGV2aWNlX2RlbChwZGV2aWNlKTsKPiArZXhpdF9kZXZpY2VfcHV0Ogo+ICsJcGxhdGZvcm1fZGV2 -aWNlX3B1dChwZGV2aWNlKTsKPiArZXhpdDoKPiArCXJldHVybiBlcnI7Cj4gK30KPiArCj4gK3N0 -YXRpYyB2b2lkIF9fZXhpdCBpYm1wb3dlcm52X2V4aXQodm9pZCkKPiArewo+ICsJcGxhdGZvcm1f -ZHJpdmVyX3VucmVnaXN0ZXIoJmlibXBvd2VybnZfZHJpdmVyKTsKPiArCXBsYXRmb3JtX2Rldmlj -ZV91bnJlZ2lzdGVyKHBkZXZpY2UpOwo+ICt9Cj4gKwo+ICtNT0RVTEVfQVVUSE9SKCJOZWVsZXNo -IEd1cHRhIDxuZWVsZWd1cEBsaW51eC52bmV0LmlibS5jb20+Iik7Cj4gK01PRFVMRV9ERVNDUklQ -VElPTigiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIpOwo+ICtNT0RVTEVfTElDRU5TRSgi -R1BMIik7Cj4gKwo+ICttb2R1bGVfaW5pdChpYm1wb3dlcm52X2luaXQpOwo+ICttb2R1bGVfZXhp -dChpYm1wb3dlcm52X2V4aXQpOwo+Cj4KPgoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19f -X19fX19fX19fX19fX19fX19fCmxtLXNlbnNvcnMgbWFpbGluZyBsaXN0CmxtLXNlbnNvcnNAbG0t -c2Vuc29ycy5vcmcKaHR0cDovL2xpc3RzLmxtLXNlbnNvcnMub3JnL21haWxtYW4vbGlzdGluZm8v -bG0tc2Vuc29ycw= +On 07/04/2014 04:02 AM, Neelesh Gupta wrote: +> This patch adds basic kernel support for reading power values, fan +> speed rpm, voltage and temperature data on powernv platforms which will +> be exported to user space through sysfs interface. +> + +Hi Neelesh, + +Copying devicetree mailing list. Please copy it on the next (hopefully final) +revision; devicetree maintainers at least need a chance to comment. +[ Yes, I understand this is a shipping product, but still ... ] + +I am ok with the code except for a couple of minor nitpicks (see below). + +Thanks, +Guenter + +> Test results: +> ------------- +> [root@tul163p1 ~]# sensors +> ibmpowernv-isa-0000 +> Adapter: ISA adapter +> fan1: 5567 RPM (min = 0 RPM) +> fan2: 5232 RPM (min = 0 RPM) +> fan3: 5532 RPM (min = 0 RPM) +> fan4: 4945 RPM (min = 0 RPM) +> fan5: 0 RPM (min = 0 RPM) +> fan6: 0 RPM (min = 0 RPM) +> fan7: 7392 RPM (min = 0 RPM) +> fan8: 7936 RPM (min = 0 RPM) +> temp1: +39.0°C (high = +0.0°C) +> power1: 191.00 W +> +> [root@tul163p1 ~]# ls /sys/devices/platform/ +> alarmtimer ibmpowernv.0 power rtc-generic serial8250 uevent +> [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/hwmon/hwmon0/ +> device fan2_min fan4_min fan6_min fan8_min power +> fan1_fault fan3_fault fan5_fault fan7_fault in1_fault power1_input +> fan1_input fan3_input fan5_input fan7_input in2_fault subsystem +> fan1_min fan3_min fan5_min fan7_min in3_fault temp1_input +> fan2_fault fan4_fault fan6_fault fan8_fault in4_fault temp1_max +> fan2_input fan4_input fan6_input fan8_input name uevent +> [root@tul163p1 ~]# +> [root@tul163p1 ~]# ls /sys/class/hwmon/hwmon0/ +> device fan2_min fan4_min fan6_min fan8_min power +> fan1_fault fan3_fault fan5_fault fan7_fault in1_fault power1_input +> fan1_input fan3_input fan5_input fan7_input in2_fault subsystem +> fan1_min fan3_min fan5_min fan7_min in3_fault temp1_input +> fan2_fault fan4_fault fan6_fault fan8_fault in4_fault temp1_max +> fan2_input fan4_input fan6_input fan8_input name uevent +> [root@tul163p1 ~]# +> +> Signed-off-by: Neelesh Gupta <neelegup-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org> +> --- +> +> Changes in v4 +> ============= +> - Replaced pr_err() with dev_err() for loggin print messages. +> - Using kstrtou32() function for converting string to u32 instead of sscanf(). +> +> Changes in v3 +> ============= +> - Fixed an endianness bug leading the driver to break on LE. +> - Fixed a bug that when one of the 'attribute_group' not populated, following +> groups attributes were dropped. +> - Rewrite the get_sensor_index_attr() function to handle all the error scenarios +> like 'sscanf' etc. +> - Fixed all the errors/warnings related to coding style/whitespace. +> - Added 'Documentation' files. +> - Addressed remaining review comments on V2. +> +> Changes in v2 +> ============= +> - Generic use of devm_* functions in hwmon like using devm_kzalloc() for dynamic +> memory request, avoiding the need to explicit free of memory. +> Adding 'struct attribute_group' as member of platform data structure to be +> populated and then passed to devm_hwmon_device_register_with_groups(). +> +> Note: Having an array of pointers of 'attribute_group' and each group +> corresponds to 'enum sensors' type. Not completely sure, if it's ideal or +> could have just one group populated with attributes of sensor types? +> +> - 'ibmpowernv' is not hot-pluggable device so moving 'platform_driver' callback +> function (probe) as part of __init code. +> - Fixed issues related to coding style. +> - Other general comments in v1. +> +> .../devicetree/bindings/hwmon/ibmpowernv.txt | 27 + +> Documentation/hwmon/ibmpowernv | 41 ++ +> drivers/hwmon/Kconfig | 11 + +> drivers/hwmon/Makefile | 1 +> drivers/hwmon/ibmpowernv.c | 362 ++++++++++++++++++++ +> 5 files changed, 442 insertions(+) +> create mode 100644 Documentation/devicetree/bindings/hwmon/ibmpowernv.txt +> create mode 100644 Documentation/hwmon/ibmpowernv +> create mode 100644 drivers/hwmon/ibmpowernv.c +> +> diff --git a/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt +> new file mode 100644 +> index 0000000..e3bd1eb +> --- /dev/null +> +++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt +> @@ -0,0 +1,27 @@ +> +IBM POWERNV platform sensors +> +---------------------------- +> + +> +Required node properties: +> +- compatible: must be one of +> + "ibm,opal-sensor-cooling-fan" +> + "ibm,opal-sensor-amb-temp" +> + "ibm,opal-sensor-power-supply" +> + "ibm,opal-sensor-power" +> +- sensor-id: an opaque id provided by the firmware to the kernel, identifies a +> + given sensor and its attribute data +> + +> +Example sensors node: +> + +> +cooling-fan#8-data { +> + sensor-id = <0x7052107>; +> + phandle = <0x10000028>; +> + linux,phandle = <0x10000028>; +> + compatible = "ibm,opal-sensor-cooling-fan"; + +phandle and linux-phandle are neither documented nor used. Either document or drop. + +> +}; +> + +> +amb-temp#1-thrs { +> + sensor-id = <0x5096000>; +> + phandle = <0x10000017>; +> + linux,phandle = <0x10000017>; +> + compatible = "ibm,opal-sensor-amb-temp"; +> +}; +> diff --git a/Documentation/hwmon/ibmpowernv b/Documentation/hwmon/ibmpowernv +> new file mode 100644 +> index 0000000..644245a +> --- /dev/null +> +++ b/Documentation/hwmon/ibmpowernv +> @@ -0,0 +1,41 @@ +> +Kernel Driver IBMPOWENV +> +======================= +> + +> +Supported systems: +> + * Any recent IBM P servers based on POWERNV platform +> + +> +Author: Neelesh Gupta +> + +> +Description +> +----------- +> + +> +This driver implements reading the platform sensors data like temperature/fan/ +> +voltage/power for 'POWERNV' platform. +> + +> +The driver uses the platform device infrastructure. It probes the device tree +> +for sensor devices during the __init phase and registers them with the 'hwmon'. +> +'hwmon' populates the 'sysfs' tree having attribute files, each for a given +> +sensor type and its attribute data. +> + +> +All the nodes in the DT appear under "/ibm,opal/sensors" and each valid node in +> +the DT maps to an attribute file in 'sysfs'. The node exports unique 'sensor-id' +> +which the driver uses to make an OPAL call to the firmware. +> + +> +Usage notes +> +----------- +> +The driver is built statically with the kernel by enabling the config +> +CONFIG_SENSORS_IBMPOWERNV. It can also be built as module 'ibmpowernv'. +> + +> +Sysfs attributes +> +---------------- +> + +> +fanX_input Measured RPM value. +> +fanX_min Threshold RPM for alert generation. +> +fanX_fault 0: No fail condition +> + 1: Failing fan +> +tempX_input Measured ambient temperature. +> +tempX_max Threshold ambient temperature for alert generation. +> +inX_input Measured power supply voltage +> +inX_fault 0: No fail condition. +> + 1: Failing power supply. +> +power1_input System power consumption (microWatt) +> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +> index 02d3d85..29c3fcb 100644 +> --- a/drivers/hwmon/Kconfig +> +++ b/drivers/hwmon/Kconfig +> @@ -554,6 +554,17 @@ config SENSORS_IBMPEX +> This driver can also be built as a module. If so, the module +> will be called ibmpex. +> +> +config SENSORS_IBMPOWERNV +> + tristate "IBM POWERNV platform sensors" +> + depends on PPC_POWERNV +> + default y +> + help +> + If you say yes here you get support for the temperature/fan/power +> + sensors on your PowerNV platform. +> + +> + This driver can also be built as a module. If so, the module +> + will be called ibmpowernv. +> + +> config SENSORS_IIO_HWMON +> tristate "Hwmon driver that uses channels specified via iio maps" +> depends on IIO +> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +> index 3dc0f02..fc4ed26 100644 +> --- a/drivers/hwmon/Makefile +> +++ b/drivers/hwmon/Makefile +> @@ -71,6 +71,7 @@ obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o +> obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o +> obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o +> obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o +> +obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o +> obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o +> obj-$(CONFIG_SENSORS_INA209) += ina209.o +> obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o +> diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c +> new file mode 100644 +> index 0000000..44dcd99 +> --- /dev/null +> +++ b/drivers/hwmon/ibmpowernv.c +> @@ -0,0 +1,362 @@ +> +/* +> + * IBM PowerNV platform sensors for temperature/fan/voltage/power +> + * Copyright (C) 2014 IBM +> + * +> + * This program is free software; you can redistribute it and/or modify +> + * it under the terms of the GNU General Public License as published by +> + * the Free Software Foundation; either version 2 of the License, or +> + * (at your option) any later version. +> + * +> + * This program is distributed in the hope that it will be useful, +> + * but WITHOUT ANY WARRANTY; without even the implied warranty of +> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +> + * GNU General Public License for more details. +> + * +> + * You should have received a copy of the GNU General Public License +> + * along with this program. +> + */ +> + +> +#define DRVNAME "ibmpowernv" +> +#define pr_fmt(fmt) DRVNAME ": " fmt +> + +> +#include <linux/init.h> +> +#include <linux/module.h> +> +#include <linux/kernel.h> +> +#include <linux/hwmon.h> +> +#include <linux/hwmon-sysfs.h> +> +#include <linux/of.h> +> +#include <linux/slab.h> +> + +> +#include <linux/platform_device.h> +> +#include <asm/opal.h> +> +#include <linux/err.h> +> + +> +#define MAX_ATTR_LEN 32 +> + +> +/* Sensor suffix name from DT */ +> +#define DT_FAULT_ATTR_SUFFIX "faulted" +> +#define DT_DATA_ATTR_SUFFIX "data" +> +#define DT_THRESHOLD_ATTR_SUFFIX "thrs" +> + +> +/* +> + * Enumerates all the types of sensors in the POWERNV platform and does index +> + * into 'struct sensor_group' +> + */ +> +enum sensors { +> + FAN, +> + AMBIENT_TEMP, +> + POWER_SUPPLY, +> + POWER_INPUT, +> + MAX_SENSOR_TYPE, +> +}; +> + +> +static struct sensor_group { +> + const char *name; +> + const char *compatible; +> + struct attribute_group group; +> + u32 attr_count; +> +} sensor_groups[] = { +> + {"fan", "ibm,opal-sensor-cooling-fan"}, +> + {"temp", "ibm,opal-sensor-amb-temp"}, +> + {"in", "ibm,opal-sensor-power-supply"}, +> + {"power", "ibm,opal-sensor-power"} +> +}; +> + +> +struct sensor_data { +> + u32 id; /* An opaque id of the firmware for each sensor */ +> + enum sensors type; +> + char name[MAX_ATTR_LEN]; +> + struct device_attribute dev_attr; +> +}; +> + +> +struct platform_data { +> + const struct attribute_group *attr_groups[MAX_SENSOR_TYPE + 1]; +> + u32 sensors_count; /* Total count of sensors from each group */ +> +}; +> + +> +/* Platform device representing all the ibmpowernv sensors */ +> +static struct platform_device *pdevice; +> + +> +static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr, +> + char *buf) +> +{ +> + struct sensor_data *sdata = container_of(devattr, struct sensor_data, +> + dev_attr); +> + ssize_t ret; +> + u32 x; +> + +> + ret = opal_get_sensor_data(sdata->id, &x); +> + if (ret) +> + return ret; +> + +> + /* Convert temperature to milli-degrees */ +> + if (sdata->type == AMBIENT_TEMP) +> + x *= 1000; +> + /* Convert power to micro-watts */ +> + else if (sdata->type == POWER_INPUT) +> + x *= 1000000; +> + +> + return sprintf(buf, "%u\n", x); +> +} +> + +> +static int __init get_sensor_index_attr(const char *name, u32 *index, +> + char *attr) +> +{ +> + char *hash_pos = strchr(name, '#'); +> + char buf[8] = { 0 }; +> + char *dash_pos; +> + u32 copy_len; +> + +> + if (!hash_pos) +> + return -EINVAL; +> + +> + dash_pos = strchr(hash_pos, '-'); +> + if (!dash_pos) +> + return -EINVAL; +> + +> + copy_len = dash_pos - hash_pos - 1; +> + if (copy_len >= sizeof(buf)) +> + return -EINVAL; +> + +> + strncpy(buf, hash_pos + 1, copy_len); +> + +> + if (kstrtou32(buf, 10, index)) +> + return -EINVAL; +> + +smatch isn't going to like that. Please use + + int err; + ... + err = kstrtou32(buf, 10, index)); + if (err) + return err; + +> + strncpy(attr, dash_pos + 1, MAX_ATTR_LEN); +> + +> + return 0; +> +} +> + +> +/* +> + * This function translates the DT node name into the 'hwmon' attribute name. +> + * IBMPOWERNV device node appear like cooling-fan#2-data, amb-temp#1-thrs etc. +> + * which need to be mapped as fan2_input, temp1_max respectively before +> + * populating them inside hwmon device class. +> + */ +> +static int __init create_hwmon_attr_name(struct device *dev, enum sensors type, +> + const char *node_name, +> + char *hwmon_attr_name) +> +{ +> + char attr_suffix[MAX_ATTR_LEN]; +> + char *attr_name; +> + u32 index; +> + int err; +> + +> + err = get_sensor_index_attr(node_name, &index, attr_suffix); +> + if (err) { +> + dev_err(dev, "Sensor device node name '%s' is invalid\n", +> + node_name); +> + return err; +> + } +> + +> + if (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX)) { +> + attr_name = "fault"; +> + } else if (!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX)) { +> + attr_name = "input"; +> + } else if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) { +> + if (type == AMBIENT_TEMP) +> + attr_name = "max"; +> + else if (type == FAN) +> + attr_name = "min"; +> + else +> + return -ENOENT; +> + } else { +> + return -ENOENT; +> + } +> + +> + snprintf(hwmon_attr_name, MAX_ATTR_LEN, "%s%d_%s", +> + sensor_groups[type].name, index, attr_name); +> + return 0; +> +} +> + +> +static int __init populate_attr_groups(struct platform_device *pdev) +> +{ +> + struct platform_data *pdata = platform_get_drvdata(pdev); +> + const struct attribute_group **pgroups = pdata->attr_groups; +> + struct device_node *opal, *np; +> + enum sensors type; +> + +> + opal = of_find_node_by_path("/ibm,opal/sensors"); +> + if (!opal) { +> + dev_err(&pdev->dev, "Opal node 'sensors' not found\n"); +> + return -ENODEV; +> + } +> + +> + for_each_child_of_node(opal, np) { +> + if (np->name == NULL) +> + continue; +> + +> + for (type = 0; type < MAX_SENSOR_TYPE; type++) +> + if (of_device_is_compatible(np, +> + sensor_groups[type].compatible)) { +> + sensor_groups[type].attr_count++; +> + break; +> + } +> + } +> + +> + of_node_put(opal); +> + +> + for (type = 0; type < MAX_SENSOR_TYPE; type++) { +> + sensor_groups[type].group.attrs = devm_kzalloc(&pdev->dev, +> + sizeof(struct attribute *) * +> + (sensor_groups[type].attr_count + 1), +> + GFP_KERNEL); +> + if (!sensor_groups[type].group.attrs) +> + return -ENOMEM; +> + +> + pgroups[type] = &sensor_groups[type].group; +> + pdata->sensors_count += sensor_groups[type].attr_count; +> + sensor_groups[type].attr_count = 0; +> + } +> + +> + return 0; +> +} +> + +> +/* +> + * Iterate through the device tree for each child of 'sensors' node, create +> + * a sysfs attribute file, the file is named by translating the DT node name +> + * to the name required by the higher 'hwmon' driver like fan1_input, temp1_max +> + * etc.. +> + */ +> +static int __init create_device_attrs(struct platform_device *pdev) +> +{ +> + struct platform_data *pdata = platform_get_drvdata(pdev); +> + const struct attribute_group **pgroups = pdata->attr_groups; +> + struct device_node *opal, *np; +> + struct sensor_data *sdata; +> + const __be32 *sensor_id; +> + enum sensors type; +> + u32 count = 0; +> + int err = 0; +> + +> + opal = of_find_node_by_path("/ibm,opal/sensors"); +> + sdata = devm_kzalloc(&pdev->dev, pdata->sensors_count * sizeof(*sdata), +> + GFP_KERNEL); +> + if (!sdata) { +> + err = -ENOMEM; +> + goto exit_put_node; +> + } +> + +> + for_each_child_of_node(opal, np) { +> + if (np->name == NULL) +> + continue; +> + +> + for (type = 0; type < MAX_SENSOR_TYPE; type++) +> + if (of_device_is_compatible(np, +> + sensor_groups[type].compatible)) +> + break; +> + +> + if (type == MAX_SENSOR_TYPE) +> + continue; +> + +> + sensor_id = of_get_property(np, "sensor-id", NULL); +> + if (!sensor_id) { +> + dev_info(&pdev->dev, +> + "'sensor-id' missing in the node '%s'\n", +> + np->name); +> + continue; +> + } +> + +> + sdata[count].id = be32_to_cpup(sensor_id); +> + sdata[count].type = type; +> + err = create_hwmon_attr_name(&pdev->dev, type, np->name, +> + sdata[count].name); +> + if (err) +> + goto exit_put_node; +> + +> + sysfs_attr_init(&sdata[count].dev_attr.attr); +> + sdata[count].dev_attr.attr.name = sdata[count].name; +> + sdata[count].dev_attr.attr.mode = S_IRUGO; +> + sdata[count].dev_attr.show = show_sensor; +> + +> + pgroups[type]->attrs[sensor_groups[type].attr_count++] = +> + &sdata[count++].dev_attr.attr; +> + } +> + +> +exit_put_node: +> + of_node_put(opal); +> + return err; +> +} +> + +> +static int __init ibmpowernv_probe(struct platform_device *pdev) +> +{ +> + struct platform_data *pdata; +> + struct device *hwmon_dev; +> + int err; +> + +> + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); +> + if (!pdata) +> + return -ENOMEM; +> + +> + platform_set_drvdata(pdev, pdata); +> + pdata->sensors_count = 0; +> + err = populate_attr_groups(pdev); +> + if (err) +> + return err; +> + +> + /* Create sysfs attribute data for each sensor found in the DT */ +> + err = create_device_attrs(pdev); +> + if (err) +> + return err; +> + +> + /* Finally, register with hwmon */ +> + hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, DRVNAME, +> + pdata, +> + pdata->attr_groups); +> + +> + return PTR_ERR_OR_ZERO(hwmon_dev); +> +} +> + +> +static struct platform_driver ibmpowernv_driver = { +> + .driver = { +> + .owner = THIS_MODULE, +> + .name = DRVNAME, +> + }, +> +}; +> + +> +static int __init ibmpowernv_init(void) +> +{ +> + int err; +> + +> + pdevice = platform_device_alloc(DRVNAME, 0); +> + if (!pdevice) { +> + pr_err("Device allocation failed\n"); +> + err = -ENOMEM; +> + goto exit; +> + } +> + +> + err = platform_device_add(pdevice); +> + if (err) { +> + pr_err("Device addition failed (%d)\n", err); +> + goto exit_device_put; +> + } +> + +> + err = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe); +> + if (err) { +> + pr_err("Platfrom driver probe failed\n"); +> + goto exit_device_del; +> + } +> + +> + return 0; +> + +> +exit_device_del: +> + platform_device_del(pdevice); +> +exit_device_put: +> + platform_device_put(pdevice); +> +exit: +> + return err; +> +} +> + +> +static void __exit ibmpowernv_exit(void) +> +{ +> + platform_driver_unregister(&ibmpowernv_driver); +> + platform_device_unregister(pdevice); +> +} +> + +> +MODULE_AUTHOR("Neelesh Gupta <neelegup-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>"); +> +MODULE_DESCRIPTION("IBM POWERNV platform sensors"); +> +MODULE_LICENSE("GPL"); +> + +> +module_init(ibmpowernv_init); +> +module_exit(ibmpowernv_exit); +> +> +> + +-- +To unsubscribe from this list: send the line "unsubscribe devicetree" in +the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/a/content_digest b/N2/content_digest index 0e5210b..8b638ac 100644 --- a/a/content_digest +++ b/N2/content_digest @@ -1,8 +1,8 @@ "ref\020140704105343.22437.52125.stgit@localhost.localdomain\0" "ref\020140704105343.22437.52125.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org\0" - "From\0Guenter Roeck <linux@roeck-us.net>\0" - "Subject\0Re: [lm-sensors] [PATCH v4] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperatur\0" - "Date\0Sat, 05 Jul 2014 02:25:36 +0000\0" + "From\0Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>\0" + "Subject\0Re: [PATCH v4] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature\0" + "Date\0Fri, 04 Jul 2014 19:25:36 -0700\0" "To\0Neelesh Gupta <neelegup-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>" linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org jdelvare-l3A5Bk7waGM@public.gmane.org @@ -13,335 +13,603 @@ " devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org <devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>\0" "\00:1\0" "b\0" - "T24gMDcvMDQvMjAxNCAwNDowMiBBTSwgTmVlbGVzaCBHdXB0YSB3cm90ZToKPiBUaGlzIHBhdGNo\n" - "IGFkZHMgYmFzaWMga2VybmVsIHN1cHBvcnQgZm9yIHJlYWRpbmcgcG93ZXIgdmFsdWVzLCBmYW4K\n" - "PiBzcGVlZCBycG0sIHZvbHRhZ2UgYW5kIHRlbXBlcmF0dXJlIGRhdGEgb24gcG93ZXJudiBwbGF0\n" - "Zm9ybXMgd2hpY2ggd2lsbAo+IGJlIGV4cG9ydGVkIHRvIHVzZXIgc3BhY2UgdGhyb3VnaCBzeXNm\n" - "cyBpbnRlcmZhY2UuCj4KCkhpIE5lZWxlc2gsCgpDb3B5aW5nIGRldmljZXRyZWUgbWFpbGluZyBs\n" - "aXN0LiBQbGVhc2UgY29weSBpdCBvbiB0aGUgbmV4dCAoaG9wZWZ1bGx5IGZpbmFsKQpyZXZpc2lv\n" - "bjsgZGV2aWNldHJlZSBtYWludGFpbmVycyBhdCBsZWFzdCBuZWVkIGEgY2hhbmNlIHRvIGNvbW1l\n" - "bnQuClsgWWVzLCBJIHVuZGVyc3RhbmQgdGhpcyBpcyBhIHNoaXBwaW5nIHByb2R1Y3QsIGJ1dCBz\n" - "dGlsbCAuLi4gXQoKSSBhbSBvayB3aXRoIHRoZSBjb2RlIGV4Y2VwdCBmb3IgYSBjb3VwbGUgb2Yg\n" - "bWlub3Igbml0cGlja3MgKHNlZSBiZWxvdykuCgpUaGFua3MsCkd1ZW50ZXIKCj4gVGVzdCByZXN1\n" - "bHRzOgo+IC0tLS0tLS0tLS0tLS0KPiBbcm9vdEB0dWwxNjNwMSB+XSMgc2Vuc29ycwo+IGlibXBv\n" - "d2VybnYtaXNhLTAwMDAKPiBBZGFwdGVyOiBJU0EgYWRhcHRlcgo+IGZhbjE6ICAgICAgICA1NTY3\n" - "IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjI6ICAgICAgICA1MjMyIFJQTSAgKG1pbiA9ICAg\n" - "IDAgUlBNKQo+IGZhbjM6ICAgICAgICA1NTMyIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjQ6\n" - "ICAgICAgICA0OTQ1IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjU6ICAgICAgICAgICAwIFJQ\n" - "TSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjY6ICAgICAgICAgICAwIFJQTSAgKG1pbiA9ICAgIDAg\n" - "UlBNKQo+IGZhbjc6ICAgICAgICA3MzkyIFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IGZhbjg6ICAg\n" - "ICAgICA3OTM2IFJQTSAgKG1pbiA9ICAgIDAgUlBNKQo+IHRlbXAxOiAgICAgICAgKzM5LjDCsEMg\n" - "IChoaWdoID0gICswLjDCsEMpCj4gcG93ZXIxOiAgICAgIDE5MS4wMCBXCj4KPiBbcm9vdEB0dWwx\n" - "NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtLwo+IGFsYXJtdGltZXIgIGlibXBvd2Vy\n" - "bnYuMCAgcG93ZXIgIHJ0Yy1nZW5lcmljICBzZXJpYWw4MjUwICB1ZXZlbnQKPiBbcm9vdEB0dWwx\n" - "NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtL2libXBvd2VybnYuMC9od21vbi9od21v\n" - "bjAvCj4gZGV2aWNlCSAgICBmYW4yX21pbglmYW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAg\n" - "IHBvd2VyCj4gZmFuMV9mYXVsdCAgZmFuM19mYXVsdAlmYW41X2ZhdWx0ICBmYW43X2ZhdWx0CWlu\n" - "MV9mYXVsdCAgcG93ZXIxX2lucHV0Cj4gZmFuMV9pbnB1dCAgZmFuM19pbnB1dAlmYW41X2lucHV0\n" - "ICBmYW43X2lucHV0CWluMl9mYXVsdCAgc3Vic3lzdGVtCj4gZmFuMV9taW4gICAgZmFuM19taW4J\n" - "ZmFuNV9taW4gICAgZmFuN19taW4JaW4zX2ZhdWx0ICB0ZW1wMV9pbnB1dAo+IGZhbjJfZmF1bHQg\n" - "IGZhbjRfZmF1bHQJZmFuNl9mYXVsdCAgZmFuOF9mYXVsdAlpbjRfZmF1bHQgIHRlbXAxX21heAo+\n" - "IGZhbjJfaW5wdXQgIGZhbjRfaW5wdXQJZmFuNl9pbnB1dCAgZmFuOF9pbnB1dAluYW1lCSAgIHVl\n" - "dmVudAo+IFtyb290QHR1bDE2M3AxIH5dIwo+IFtyb290QHR1bDE2M3AxIH5dIyBscyAvc3lzL2Ns\n" - "YXNzL2h3bW9uL2h3bW9uMC8KPiBkZXZpY2UJICAgIGZhbjJfbWluCWZhbjRfbWluICAgIGZhbjZf\n" - "bWluCWZhbjhfbWluICAgcG93ZXIKPiBmYW4xX2ZhdWx0ICBmYW4zX2ZhdWx0CWZhbjVfZmF1bHQg\n" - "IGZhbjdfZmF1bHQJaW4xX2ZhdWx0ICBwb3dlcjFfaW5wdXQKPiBmYW4xX2lucHV0ICBmYW4zX2lu\n" - "cHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5wdXQJaW4yX2ZhdWx0ICBzdWJzeXN0ZW0KPiBmYW4xX21p\n" - "biAgICBmYW4zX21pbglmYW41X21pbiAgICBmYW43X21pbglpbjNfZmF1bHQgIHRlbXAxX2lucHV0\n" - "Cj4gZmFuMl9mYXVsdCAgZmFuNF9mYXVsdAlmYW42X2ZhdWx0ICBmYW44X2ZhdWx0CWluNF9mYXVs\n" - "dCAgdGVtcDFfbWF4Cj4gZmFuMl9pbnB1dCAgZmFuNF9pbnB1dAlmYW42X2lucHV0ICBmYW44X2lu\n" - "cHV0CW5hbWUJICAgdWV2ZW50Cj4gW3Jvb3RAdHVsMTYzcDEgfl0jCj4KPiBTaWduZWQtb2ZmLWJ5\n" - "OiBOZWVsZXNoIEd1cHRhIDxuZWVsZWd1cEBsaW51eC52bmV0LmlibS5jb20+Cj4gLS0tCj4KPiBD\n" - "aGFuZ2VzIGluIHY0Cj4gPT09PT09PT09PT09PQo+IC0gUmVwbGFjZWQgcHJfZXJyKCkgd2l0aCBk\n" - "ZXZfZXJyKCkgZm9yIGxvZ2dpbiBwcmludCBtZXNzYWdlcy4KPiAtIFVzaW5nIGtzdHJ0b3UzMigp\n" - "IGZ1bmN0aW9uIGZvciBjb252ZXJ0aW5nIHN0cmluZyB0byB1MzIgaW5zdGVhZCBvZiBzc2NhbmYo\n" - "KS4KPgo+IENoYW5nZXMgaW4gdjMKPiA9PT09PT09PT09PT09Cj4gLSBGaXhlZCBhbiBlbmRpYW5u\n" - "ZXNzIGJ1ZyBsZWFkaW5nIHRoZSBkcml2ZXIgdG8gYnJlYWsgb24gTEUuCj4gLSBGaXhlZCBhIGJ1\n" - "ZyB0aGF0IHdoZW4gb25lIG9mIHRoZSAnYXR0cmlidXRlX2dyb3VwJyBub3QgcG9wdWxhdGVkLCBm\n" - "b2xsb3dpbmcKPiAgICBncm91cHMgYXR0cmlidXRlcyB3ZXJlIGRyb3BwZWQuCj4gLSBSZXdyaXRl\n" - "IHRoZSBnZXRfc2Vuc29yX2luZGV4X2F0dHIoKSBmdW5jdGlvbiB0byBoYW5kbGUgYWxsIHRoZSBl\n" - "cnJvciBzY2VuYXJpb3MKPiAgICBsaWtlICdzc2NhbmYnIGV0Yy4KPiAtIEZpeGVkIGFsbCB0aGUg\n" - "ZXJyb3JzL3dhcm5pbmdzIHJlbGF0ZWQgdG8gY29kaW5nIHN0eWxlL3doaXRlc3BhY2UuCj4gLSBB\n" - "ZGRlZCAnRG9jdW1lbnRhdGlvbicgZmlsZXMuCj4gLSBBZGRyZXNzZWQgcmVtYWluaW5nIHJldmll\n" - "dyBjb21tZW50cyBvbiBWMi4KPgo+IENoYW5nZXMgaW4gdjIKPiA9PT09PT09PT09PT09Cj4gLSBH\n" - "ZW5lcmljIHVzZSBvZiBkZXZtXyogZnVuY3Rpb25zIGluIGh3bW9uIGxpa2UgdXNpbmcgZGV2bV9r\n" - "emFsbG9jKCkgZm9yIGR5bmFtaWMKPiAgICBtZW1vcnkgcmVxdWVzdCwgYXZvaWRpbmcgdGhlIG5l\n" - "ZWQgdG8gZXhwbGljaXQgZnJlZSBvZiBtZW1vcnkuCj4gICAgQWRkaW5nICdzdHJ1Y3QgYXR0cmli\n" - "dXRlX2dyb3VwJyBhcyBtZW1iZXIgb2YgcGxhdGZvcm0gZGF0YSBzdHJ1Y3R1cmUgdG8gYmUKPiAg\n" - "ICBwb3B1bGF0ZWQgYW5kIHRoZW4gcGFzc2VkIHRvIGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVy\n" - "X3dpdGhfZ3JvdXBzKCkuCj4KPiAgICBOb3RlOiBIYXZpbmcgYW4gYXJyYXkgb2YgcG9pbnRlcnMg\n" - "b2YgJ2F0dHJpYnV0ZV9ncm91cCcgYW5kIGVhY2ggZ3JvdXAKPiAgICBjb3JyZXNwb25kcyB0byAn\n" - "ZW51bSBzZW5zb3JzJyB0eXBlLiBOb3QgY29tcGxldGVseSBzdXJlLCBpZiBpdCdzIGlkZWFsIG9y\n" - "Cj4gICAgY291bGQgaGF2ZSBqdXN0IG9uZSBncm91cCBwb3B1bGF0ZWQgd2l0aCBhdHRyaWJ1dGVz\n" - "IG9mIHNlbnNvciB0eXBlcz8KPgo+IC0gJ2libXBvd2VybnYnIGlzIG5vdCBob3QtcGx1Z2dhYmxl\n" - "IGRldmljZSBzbyBtb3ZpbmcgJ3BsYXRmb3JtX2RyaXZlcicgY2FsbGJhY2sKPiAgICBmdW5jdGlv\n" - "biAocHJvYmUpIGFzIHBhcnQgb2YgX19pbml0IGNvZGUuCj4gLSBGaXhlZCBpc3N1ZXMgcmVsYXRl\n" - "ZCB0byBjb2Rpbmcgc3R5bGUuCj4gLSBPdGhlciBnZW5lcmFsIGNvbW1lbnRzIGluIHYxLgo+Cj4g\n" - "ICAuLi4vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4dCAgICAgICB8ICAg\n" - "MjcgKwo+ICAgRG9jdW1lbnRhdGlvbi9od21vbi9pYm1wb3dlcm52ICAgICAgICAgICAgICAgICAg\n" - "ICAgfCAgIDQxICsrCj4gICBkcml2ZXJzL2h3bW9uL0tjb25maWcgICAgICAgICAgICAgICAgICAg\n" - "ICAgICAgICAgICB8ICAgMTEgKwo+ICAgZHJpdmVycy9od21vbi9NYWtlZmlsZSAgICAgICAgICAg\n" - "ICAgICAgICAgICAgICAgICAgfCAgICAxCj4gICBkcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYyAg\n" - "ICAgICAgICAgICAgICAgICAgICAgICB8ICAzNjIgKysrKysrKysrKysrKysrKysrKysKPiAgIDUg\n" - "ZmlsZXMgY2hhbmdlZCwgNDQyIGluc2VydGlvbnMoKykKPiAgIGNyZWF0ZSBtb2RlIDEwMDY0NCBE\n" - "b2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQKPiAg\n" - "IGNyZWF0ZSBtb2RlIDEwMDY0NCBEb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYKPiAgIGNy\n" - "ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYwo+Cj4gZGlmZiAtLWdp\n" - "dCBhL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4\n" - "dCBiL0RvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5kaW5ncy9od21vbi9pYm1wb3dlcm52LnR4\n" - "dAo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uZTNiZDFlYgo+IC0tLSAv\n" - "ZGV2L251bGwKPiArKysgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmluZGluZ3MvaHdtb24v\n" - "aWJtcG93ZXJudi50eHQKPiBAQCAtMCwwICsxLDI3IEBACj4gK0lCTSBQT1dFUk5WIHBsYXRmb3Jt\n" - "IHNlbnNvcnMKPiArLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo+ICsKPiArUmVxdWlyZWQg\n" - "bm9kZSBwcm9wZXJ0aWVzOgo+ICstIGNvbXBhdGlibGU6IG11c3QgYmUgb25lIG9mCj4gKwkJImli\n" - "bSxvcGFsLXNlbnNvci1jb29saW5nLWZhbiIKPiArCQkiaWJtLG9wYWwtc2Vuc29yLWFtYi10ZW1w\n" - "Igo+ICsJCSJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3VwcGx5Igo+ICsJCSJpYm0sb3BhbC1zZW5z\n" - "b3ItcG93ZXIiCj4gKy0gc2Vuc29yLWlkOiBhbiBvcGFxdWUgaWQgcHJvdmlkZWQgYnkgdGhlIGZp\n" - "cm13YXJlIHRvIHRoZSBrZXJuZWwsIGlkZW50aWZpZXMgYQo+ICsJICAgICBnaXZlbiBzZW5zb3Ig\n" - "YW5kIGl0cyBhdHRyaWJ1dGUgZGF0YQo+ICsKPiArRXhhbXBsZSBzZW5zb3JzIG5vZGU6Cj4gKwo+\n" - "ICtjb29saW5nLWZhbiM4LWRhdGEgewo+ICsJc2Vuc29yLWlkID0gPDB4NzA1MjEwNz47Cj4gKwlw\n" - "aGFuZGxlID0gPDB4MTAwMDAwMjg+Owo+ICsJbGludXgscGhhbmRsZSA9IDwweDEwMDAwMDI4PjsK\n" - "PiArCWNvbXBhdGlibGUgPSAiaWJtLG9wYWwtc2Vuc29yLWNvb2xpbmctZmFuIjsKCnBoYW5kbGUg\n" - "YW5kIGxpbnV4LXBoYW5kbGUgYXJlIG5laXRoZXIgZG9jdW1lbnRlZCBub3IgdXNlZC4gRWl0aGVy\n" - "IGRvY3VtZW50IG9yIGRyb3AuCgo+ICt9Owo+ICsKPiArYW1iLXRlbXAjMS10aHJzIHsKPiArCXNl\n" - "bnNvci1pZCA9IDwweDUwOTYwMDA+Owo+ICsJcGhhbmRsZSA9IDwweDEwMDAwMDE3PjsKPiArCWxp\n" - "bnV4LHBoYW5kbGUgPSA8MHgxMDAwMDAxNz47Cj4gKwljb21wYXRpYmxlID0gImlibSxvcGFsLXNl\n" - "bnNvci1hbWItdGVtcCI7Cj4gK307Cj4gZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24vaHdtb24v\n" - "aWJtcG93ZXJudiBiL0RvY3VtZW50YXRpb24vaHdtb24vaWJtcG93ZXJudgo+IG5ldyBmaWxlIG1v\n" - "ZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uNjQ0MjQ1YQo+IC0tLSAvZGV2L251bGwKPiArKysg\n" - "Yi9Eb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYKPiBAQCAtMCwwICsxLDQxIEBACj4gK0tl\n" - "cm5lbCBEcml2ZXIgSUJNUE9XRU5WCj4gKz09PT09PT09PT09PT09PT09PT09PT09Cj4gKwo+ICtT\n" - "dXBwb3J0ZWQgc3lzdGVtczoKPiArICAqIEFueSByZWNlbnQgSUJNIFAgc2VydmVycyBiYXNlZCBv\n" - "biBQT1dFUk5WIHBsYXRmb3JtCj4gKwo+ICtBdXRob3I6IE5lZWxlc2ggR3VwdGEKPiArCj4gK0Rl\n" - "c2NyaXB0aW9uCj4gKy0tLS0tLS0tLS0tCj4gKwo+ICtUaGlzIGRyaXZlciBpbXBsZW1lbnRzIHJl\n" - "YWRpbmcgdGhlIHBsYXRmb3JtIHNlbnNvcnMgZGF0YSBsaWtlIHRlbXBlcmF0dXJlL2Zhbi8KPiAr\n" - "dm9sdGFnZS9wb3dlciBmb3IgJ1BPV0VSTlYnIHBsYXRmb3JtLgo+ICsKPiArVGhlIGRyaXZlciB1\n" - "c2VzIHRoZSBwbGF0Zm9ybSBkZXZpY2UgaW5mcmFzdHJ1Y3R1cmUuIEl0IHByb2JlcyB0aGUgZGV2\n" - "aWNlIHRyZWUKPiArZm9yIHNlbnNvciBkZXZpY2VzIGR1cmluZyB0aGUgX19pbml0IHBoYXNlIGFu\n" - "ZCByZWdpc3RlcnMgdGhlbSB3aXRoIHRoZSAnaHdtb24nLgo+ICsnaHdtb24nIHBvcHVsYXRlcyB0\n" - "aGUgJ3N5c2ZzJyB0cmVlIGhhdmluZyBhdHRyaWJ1dGUgZmlsZXMsIGVhY2ggZm9yIGEgZ2l2ZW4K\n" - "PiArc2Vuc29yIHR5cGUgYW5kIGl0cyBhdHRyaWJ1dGUgZGF0YS4KPiArCj4gK0FsbCB0aGUgbm9k\n" - "ZXMgaW4gdGhlIERUIGFwcGVhciB1bmRlciAiL2libSxvcGFsL3NlbnNvcnMiIGFuZCBlYWNoIHZh\n" - "bGlkIG5vZGUgaW4KPiArdGhlIERUIG1hcHMgdG8gYW4gYXR0cmlidXRlIGZpbGUgaW4gJ3N5c2Zz\n" - "Jy4gVGhlIG5vZGUgZXhwb3J0cyB1bmlxdWUgJ3NlbnNvci1pZCcKPiArd2hpY2ggdGhlIGRyaXZl\n" - "ciB1c2VzIHRvIG1ha2UgYW4gT1BBTCBjYWxsIHRvIHRoZSBmaXJtd2FyZS4KPiArCj4gK1VzYWdl\n" - "IG5vdGVzCj4gKy0tLS0tLS0tLS0tCj4gK1RoZSBkcml2ZXIgaXMgYnVpbHQgc3RhdGljYWxseSB3\n" - "aXRoIHRoZSBrZXJuZWwgYnkgZW5hYmxpbmcgdGhlIGNvbmZpZwo+ICtDT05GSUdfU0VOU09SU19J\n" - "Qk1QT1dFUk5WLiBJdCBjYW4gYWxzbyBiZSBidWlsdCBhcyBtb2R1bGUgJ2libXBvd2VybnYnLgo+\n" - "ICsKPiArU3lzZnMgYXR0cmlidXRlcwo+ICstLS0tLS0tLS0tLS0tLS0tCj4gKwo+ICtmYW5YX2lu\n" - "cHV0CQlNZWFzdXJlZCBSUE0gdmFsdWUuCj4gK2ZhblhfbWluCQlUaHJlc2hvbGQgUlBNIGZvciBh\n" - "bGVydCBnZW5lcmF0aW9uLgo+ICtmYW5YX2ZhdWx0CQkwOiBObyBmYWlsIGNvbmRpdGlvbgo+ICsJ\n" - "CQkxOiBGYWlsaW5nIGZhbgo+ICt0ZW1wWF9pbnB1dAkJTWVhc3VyZWQgYW1iaWVudCB0ZW1wZXJh\n" - "dHVyZS4KPiArdGVtcFhfbWF4CQlUaHJlc2hvbGQgYW1iaWVudCB0ZW1wZXJhdHVyZSBmb3IgYWxl\n" - "cnQgZ2VuZXJhdGlvbi4KPiAraW5YX2lucHV0CQlNZWFzdXJlZCBwb3dlciBzdXBwbHkgdm9sdGFn\n" - "ZQo+ICtpblhfZmF1bHQJCTA6IE5vIGZhaWwgY29uZGl0aW9uLgo+ICsJCQkxOiBGYWlsaW5nIHBv\n" - "d2VyIHN1cHBseS4KPiArcG93ZXIxX2lucHV0CQlTeXN0ZW0gcG93ZXIgY29uc3VtcHRpb24gKG1p\n" - "Y3JvV2F0dCkKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmlnIGIvZHJpdmVycy9o\n" - "d21vbi9LY29uZmlnCj4gaW5kZXggMDJkM2Q4NS4uMjljM2ZjYiAxMDA2NDQKPiAtLS0gYS9kcml2\n" - "ZXJzL2h3bW9uL0tjb25maWcKPiArKysgYi9kcml2ZXJzL2h3bW9uL0tjb25maWcKPiBAQCAtNTU0\n" - "LDYgKzU1NCwxNyBAQCBjb25maWcgU0VOU09SU19JQk1QRVgKPiAgIAkgIFRoaXMgZHJpdmVyIGNh\n" - "biBhbHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiAgSWYgc28sIHRoZSBtb2R1bGUKPiAgIAkgIHdp\n" - "bGwgYmUgY2FsbGVkIGlibXBleC4KPgo+ICtjb25maWcgU0VOU09SU19JQk1QT1dFUk5WCj4gKwl0\n" - "cmlzdGF0ZSAiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIKPiArCWRlcGVuZHMgb24gUFBD\n" - "X1BPV0VSTlYKPiArCWRlZmF1bHQgeQo+ICsJaGVscAo+ICsJICBJZiB5b3Ugc2F5IHllcyBoZXJl\n" - "IHlvdSBnZXQgc3VwcG9ydCBmb3IgdGhlIHRlbXBlcmF0dXJlL2Zhbi9wb3dlcgo+ICsJICBzZW5z\n" - "b3JzIG9uIHlvdXIgUG93ZXJOViBwbGF0Zm9ybS4KPiArCj4gKwkgIFRoaXMgZHJpdmVyIGNhbiBh\n" - "bHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiBJZiBzbywgdGhlIG1vZHVsZQo+ICsJICB3aWxsIGJl\n" - "IGNhbGxlZCBpYm1wb3dlcm52Lgo+ICsKPiAgIGNvbmZpZyBTRU5TT1JTX0lJT19IV01PTgo+ICAg\n" - "CXRyaXN0YXRlICJId21vbiBkcml2ZXIgdGhhdCB1c2VzIGNoYW5uZWxzIHNwZWNpZmllZCB2aWEg\n" - "aWlvIG1hcHMiCj4gICAJZGVwZW5kcyBvbiBJSU8KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21v\n" - "bi9NYWtlZmlsZSBiL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPiBpbmRleCAzZGMwZjAyLi5mYzRl\n" - "ZDI2IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKPiArKysgYi9kcml2ZXJz\n" - "L2h3bW9uL01ha2VmaWxlCj4gQEAgLTcxLDYgKzcxLDcgQEAgb2JqLSQoQ09ORklHX1NFTlNPUlNf\n" - "VUxUUkE0NSkJKz0gdWx0cmE0NV9lbnYubwo+ICAgb2JqLSQoQ09ORklHX1NFTlNPUlNfSTVLX0FN\n" - "QikJKz0gaTVrX2FtYi5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JQk1BRU0pCSs9IGlibWFl\n" - "bS5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JQk1QRVgpCSs9IGlibXBleC5vCj4gK29iai0k\n" - "KENPTkZJR19TRU5TT1JTX0lCTVBPV0VSTlYpKz0gaWJtcG93ZXJudi5vCj4gICBvYmotJChDT05G\n" - "SUdfU0VOU09SU19JSU9fSFdNT04pICs9IGlpb19od21vbi5vCj4gICBvYmotJChDT05GSUdfU0VO\n" - "U09SU19JTkEyMDkpCSs9IGluYTIwOS5vCj4gICBvYmotJChDT05GSUdfU0VOU09SU19JTkEyWFgp\n" - "CSs9IGluYTJ4eC5vCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jIGIv\n" - "ZHJpdmVycy9od21vbi9pYm1wb3dlcm52LmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4\n" - "IDAwMDAwMDAuLjQ0ZGNkOTkKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy9od21vbi9p\n" - "Ym1wb3dlcm52LmMKPiBAQCAtMCwwICsxLDM2MiBAQAo+ICsvKgo+ICsgKiBJQk0gUG93ZXJOViBw\n" - "bGF0Zm9ybSBzZW5zb3JzIGZvciB0ZW1wZXJhdHVyZS9mYW4vdm9sdGFnZS9wb3dlcgo+ICsgKiBD\n" - "b3B5cmlnaHQgKEMpIDIwMTQgSUJNCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNv\n" - "ZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5Cj4gKyAqIGl0IHVu\n" - "ZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlz\n" - "aGVkIGJ5Cj4gKyAqIHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9u\n" - "IDIgb2YgdGhlIExpY2Vuc2UsIG9yCj4gKyAqIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZl\n" - "cnNpb24uCj4gKyAqCj4gKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9w\n" - "ZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLAo+ICsgKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7\n" - "IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgo+ICsgKiBNRVJDSEFOVEFCSUxJ\n" - "VFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCj4gKyAqIEdO\n" - "VSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCj4gKyAqCj4gKyAqIFlv\n" - "dSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBM\n" - "aWNlbnNlCj4gKyAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtLgo+ICsgKi8KPiArCj4gKyNkZWZp\n" - "bmUgRFJWTkFNRQkJImlibXBvd2VybnYiCj4gKyNkZWZpbmUgcHJfZm10KGZtdCkJRFJWTkFNRSAi\n" - "OiAiIGZtdAo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KPiArI2luY2x1ZGUgPGxpbnV4\n" - "L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgva2VybmVsLmg+Cj4gKyNpbmNsdWRlIDxsaW51\n" - "eC9od21vbi5oPgo+ICsjaW5jbHVkZSA8bGludXgvaHdtb24tc3lzZnMuaD4KPiArI2luY2x1ZGUg\n" - "PGxpbnV4L29mLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cj4gKwo+ICsjaW5jbHVkZSA8\n" - "bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4gKyNpbmNsdWRlIDxhc20vb3BhbC5oPgo+ICsjaW5j\n" - "bHVkZSA8bGludXgvZXJyLmg+Cj4gKwo+ICsjZGVmaW5lIE1BWF9BVFRSX0xFTgkzMgo+ICsKPiAr\n" - "LyogU2Vuc29yIHN1ZmZpeCBuYW1lIGZyb20gRFQgKi8KPiArI2RlZmluZSBEVF9GQVVMVF9BVFRS\n" - "X1NVRkZJWAkJImZhdWx0ZWQiCj4gKyNkZWZpbmUgRFRfREFUQV9BVFRSX1NVRkZJWAkJImRhdGEi\n" - "Cj4gKyNkZWZpbmUgRFRfVEhSRVNIT0xEX0FUVFJfU1VGRklYCSJ0aHJzIgo+ICsKPiArLyoKPiAr\n" - "ICogRW51bWVyYXRlcyBhbGwgdGhlIHR5cGVzIG9mIHNlbnNvcnMgaW4gdGhlIFBPV0VSTlYgcGxh\n" - "dGZvcm0gYW5kIGRvZXMgaW5kZXgKPiArICogaW50byAnc3RydWN0IHNlbnNvcl9ncm91cCcKPiAr\n" - "ICovCj4gK2VudW0gc2Vuc29ycyB7Cj4gKwlGQU4sCj4gKwlBTUJJRU5UX1RFTVAsCj4gKwlQT1dF\n" - "Ul9TVVBQTFksCj4gKwlQT1dFUl9JTlBVVCwKPiArCU1BWF9TRU5TT1JfVFlQRSwKPiArfTsKPiAr\n" - "Cj4gK3N0YXRpYyBzdHJ1Y3Qgc2Vuc29yX2dyb3VwIHsKPiArCWNvbnN0IGNoYXIgKm5hbWU7Cj4g\n" - "Kwljb25zdCBjaGFyICpjb21wYXRpYmxlOwo+ICsJc3RydWN0IGF0dHJpYnV0ZV9ncm91cCBncm91\n" - "cDsKPiArCXUzMiBhdHRyX2NvdW50Owo+ICt9IHNlbnNvcl9ncm91cHNbXSA9IHsKPiArCXsiZmFu\n" - "IiwgImlibSxvcGFsLXNlbnNvci1jb29saW5nLWZhbiJ9LAo+ICsJeyJ0ZW1wIiwgImlibSxvcGFs\n" - "LXNlbnNvci1hbWItdGVtcCJ9LAo+ICsJeyJpbiIsICJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3Vw\n" - "cGx5In0sCj4gKwl7InBvd2VyIiwgImlibSxvcGFsLXNlbnNvci1wb3dlciJ9Cj4gK307Cj4gKwo+\n" - "ICtzdHJ1Y3Qgc2Vuc29yX2RhdGEgewo+ICsJdTMyIGlkOyAvKiBBbiBvcGFxdWUgaWQgb2YgdGhl\n" - "IGZpcm13YXJlIGZvciBlYWNoIHNlbnNvciAqLwo+ICsJZW51bSBzZW5zb3JzIHR5cGU7Cj4gKwlj\n" - "aGFyIG5hbWVbTUFYX0FUVFJfTEVOXTsKPiArCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlIGRldl9h\n" - "dHRyOwo+ICt9Owo+ICsKPiArc3RydWN0IHBsYXRmb3JtX2RhdGEgewo+ICsJY29uc3Qgc3RydWN0\n" - "IGF0dHJpYnV0ZV9ncm91cCAqYXR0cl9ncm91cHNbTUFYX1NFTlNPUl9UWVBFICsgMV07Cj4gKwl1\n" - "MzIgc2Vuc29yc19jb3VudDsgLyogVG90YWwgY291bnQgb2Ygc2Vuc29ycyBmcm9tIGVhY2ggZ3Jv\n" - "dXAgKi8KPiArfTsKPiArCj4gKy8qIFBsYXRmb3JtIGRldmljZSByZXByZXNlbnRpbmcgYWxsIHRo\n" - "ZSBpYm1wb3dlcm52IHNlbnNvcnMgKi8KPiArc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2Ug\n" - "KnBkZXZpY2U7Cj4gKwo+ICtzdGF0aWMgc3NpemVfdCBzaG93X3NlbnNvcihzdHJ1Y3QgZGV2aWNl\n" - "ICpkZXYsIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkZXZhdHRyLAo+ICsJCQkgICBjaGFyICpi\n" - "dWYpCj4gK3sKPiArCXN0cnVjdCBzZW5zb3JfZGF0YSAqc2RhdGEgPSBjb250YWluZXJfb2YoZGV2\n" - "YXR0ciwgc3RydWN0IHNlbnNvcl9kYXRhLAo+ICsJCQkJCQkgZGV2X2F0dHIpOwo+ICsJc3NpemVf\n" - "dCByZXQ7Cj4gKwl1MzIgeDsKPiArCj4gKwlyZXQgPSBvcGFsX2dldF9zZW5zb3JfZGF0YShzZGF0\n" - "YS0+aWQsICZ4KTsKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwkvKiBDb252\n" - "ZXJ0IHRlbXBlcmF0dXJlIHRvIG1pbGxpLWRlZ3JlZXMgKi8KPiArCWlmIChzZGF0YS0+dHlwZSA9\n" - "PSBBTUJJRU5UX1RFTVApCj4gKwkJeCAqPSAxMDAwOwo+ICsJLyogQ29udmVydCBwb3dlciB0byBt\n" - "aWNyby13YXR0cyAqLwo+ICsJZWxzZSBpZiAoc2RhdGEtPnR5cGUgPT0gUE9XRVJfSU5QVVQpCj4g\n" - "KwkJeCAqPSAxMDAwMDAwOwo+ICsKPiArCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiV1XG4iLCB4KTsK\n" - "PiArfQo+ICsKPiArc3RhdGljIGludCBfX2luaXQgZ2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0\n" - "IGNoYXIgKm5hbWUsIHUzMiAqaW5kZXgsCj4gKwkJCQkJY2hhciAqYXR0cikKPiArewo+ICsJY2hh\n" - "ciAqaGFzaF9wb3MgPSBzdHJjaHIobmFtZSwgJyMnKTsKPiArCWNoYXIgYnVmWzhdID0geyAwIH07\n" - "Cj4gKwljaGFyICpkYXNoX3BvczsKPiArCXUzMiBjb3B5X2xlbjsKPiArCj4gKwlpZiAoIWhhc2hf\n" - "cG9zKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCWRhc2hfcG9zID0gc3RyY2hyKGhhc2hf\n" - "cG9zLCAnLScpOwo+ICsJaWYgKCFkYXNoX3BvcykKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4g\n" - "Kwljb3B5X2xlbiA9IGRhc2hfcG9zIC0gaGFzaF9wb3MgLSAxOwo+ICsJaWYgKGNvcHlfbGVuID49\n" - "IHNpemVvZihidWYpKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXN0cm5jcHkoYnVmLCBo\n" - "YXNoX3BvcyArIDEsIGNvcHlfbGVuKTsKPiArCj4gKwlpZiAoa3N0cnRvdTMyKGJ1ZiwgMTAsIGlu\n" - "ZGV4KSkKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCnNtYXRjaCBpc24ndCBnb2luZyB0byBsaWtl\n" - "IHRoYXQuIFBsZWFzZSB1c2UKCglpbnQgZXJyOwoJLi4uCgllcnIgPSBrc3RydG91MzIoYnVmLCAx\n" - "MCwgaW5kZXgpKTsKCWlmIChlcnIpCgkJcmV0dXJuIGVycjsKCj4gKwlzdHJuY3B5KGF0dHIsIGRh\n" - "c2hfcG9zICsgMSwgTUFYX0FUVFJfTEVOKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiAr\n" - "LyoKPiArICogVGhpcyBmdW5jdGlvbiB0cmFuc2xhdGVzIHRoZSBEVCBub2RlIG5hbWUgaW50byB0\n" - "aGUgJ2h3bW9uJyBhdHRyaWJ1dGUgbmFtZS4KPiArICogSUJNUE9XRVJOViBkZXZpY2Ugbm9kZSBh\n" - "cHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIGFtYi10ZW1wIzEtdGhycyBldGMuCj4gKyAq\n" - "IHdoaWNoIG5lZWQgdG8gYmUgbWFwcGVkIGFzIGZhbjJfaW5wdXQsIHRlbXAxX21heCByZXNwZWN0\n" - "aXZlbHkgYmVmb3JlCj4gKyAqIHBvcHVsYXRpbmcgdGhlbSBpbnNpZGUgaHdtb24gZGV2aWNlIGNs\n" - "YXNzLgo+ICsgKi8KPiArc3RhdGljIGludCBfX2luaXQgY3JlYXRlX2h3bW9uX2F0dHJfbmFtZShz\n" - "dHJ1Y3QgZGV2aWNlICpkZXYsIGVudW0gc2Vuc29ycyB0eXBlLAo+ICsJCQkJCSBjb25zdCBjaGFy\n" - "ICpub2RlX25hbWUsCj4gKwkJCQkJIGNoYXIgKmh3bW9uX2F0dHJfbmFtZSkKPiArewo+ICsJY2hh\n" - "ciBhdHRyX3N1ZmZpeFtNQVhfQVRUUl9MRU5dOwo+ICsJY2hhciAqYXR0cl9uYW1lOwo+ICsJdTMy\n" - "IGluZGV4Owo+ICsJaW50IGVycjsKPiArCj4gKwllcnIgPSBnZXRfc2Vuc29yX2luZGV4X2F0dHIo\n" - "bm9kZV9uYW1lLCAmaW5kZXgsIGF0dHJfc3VmZml4KTsKPiArCWlmIChlcnIpIHsKPiArCQlkZXZf\n" - "ZXJyKGRldiwgIlNlbnNvciBkZXZpY2Ugbm9kZSBuYW1lICclcycgaXMgaW52YWxpZFxuIiwKPiAr\n" - "CQkJbm9kZV9uYW1lKTsKPiArCQlyZXR1cm4gZXJyOwo+ICsJfQo+ICsKPiArCWlmICghc3RyY21w\n" - "KGF0dHJfc3VmZml4LCBEVF9GQVVMVF9BVFRSX1NVRkZJWCkpIHsKPiArCQlhdHRyX25hbWUgPSAi\n" - "ZmF1bHQiOwo+ICsJfSBlbHNlIGlmICghc3RyY21wKGF0dHJfc3VmZml4LCBEVF9EQVRBX0FUVFJf\n" - "U1VGRklYKSkgewo+ICsJCWF0dHJfbmFtZSA9ICJpbnB1dCI7Cj4gKwl9IGVsc2UgaWYgKCFzdHJj\n" - "bXAoYXR0cl9zdWZmaXgsIERUX1RIUkVTSE9MRF9BVFRSX1NVRkZJWCkpIHsKPiArCQlpZiAodHlw\n" - "ZSA9PSBBTUJJRU5UX1RFTVApCj4gKwkJCWF0dHJfbmFtZSA9ICJtYXgiOwo+ICsJCWVsc2UgaWYg\n" - "KHR5cGUgPT0gRkFOKQo+ICsJCQlhdHRyX25hbWUgPSAibWluIjsKPiArCQllbHNlCj4gKwkJCXJl\n" - "dHVybiAtRU5PRU5UOwo+ICsJfSBlbHNlIHsKPiArCQlyZXR1cm4gLUVOT0VOVDsKPiArCX0KPiAr\n" - "Cj4gKwlzbnByaW50Zihod21vbl9hdHRyX25hbWUsIE1BWF9BVFRSX0xFTiwgIiVzJWRfJXMiLAo+\n" - "ICsJCSBzZW5zb3JfZ3JvdXBzW3R5cGVdLm5hbWUsIGluZGV4LCBhdHRyX25hbWUpOwo+ICsJcmV0\n" - "dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgX19pbml0IHBvcHVsYXRlX2F0dHJfZ3JvdXBz\n" - "KHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiArCXN0cnVjdCBwbGF0Zm9ybV9k\n" - "YXRhICpwZGF0YSA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ICsJY29uc3Qgc3RydWN0\n" - "IGF0dHJpYnV0ZV9ncm91cCAqKnBncm91cHMgPSBwZGF0YS0+YXR0cl9ncm91cHM7Cj4gKwlzdHJ1\n" - "Y3QgZGV2aWNlX25vZGUgKm9wYWwsICpucDsKPiArCWVudW0gc2Vuc29ycyB0eXBlOwo+ICsKPiAr\n" - "CW9wYWwgPSBvZl9maW5kX25vZGVfYnlfcGF0aCgiL2libSxvcGFsL3NlbnNvcnMiKTsKPiArCWlm\n" - "ICghb3BhbCkgewo+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgIk9wYWwgbm9kZSAnc2Vuc29ycycg\n" - "bm90IGZvdW5kXG4iKTsKPiArCQlyZXR1cm4gLUVOT0RFVjsKPiArCX0KPiArCj4gKwlmb3JfZWFj\n" - "aF9jaGlsZF9vZl9ub2RlKG9wYWwsIG5wKSB7Cj4gKwkJaWYgKG5wLT5uYW1lID09IE5VTEwpCj4g\n" - "KwkJCWNvbnRpbnVlOwo+ICsKPiArCQlmb3IgKHR5cGUgPSAwOyB0eXBlIDwgTUFYX1NFTlNPUl9U\n" - "WVBFOyB0eXBlKyspCj4gKwkJCWlmIChvZl9kZXZpY2VfaXNfY29tcGF0aWJsZShucCwKPiArCQkJ\n" - "CQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmNvbXBhdGlibGUpKSB7Cj4gKwkJCQlzZW5zb3JfZ3JvdXBz\n" - "W3R5cGVdLmF0dHJfY291bnQrKzsKPiArCQkJCWJyZWFrOwo+ICsJCQl9Cj4gKwl9Cj4gKwo+ICsJ\n" - "b2Zfbm9kZV9wdXQob3BhbCk7Cj4gKwo+ICsJZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5T\n" - "T1JfVFlQRTsgdHlwZSsrKSB7Cj4gKwkJc2Vuc29yX2dyb3Vwc1t0eXBlXS5ncm91cC5hdHRycyA9\n" - "IGRldm1fa3phbGxvYygmcGRldi0+ZGV2LAo+ICsJCQkJCXNpemVvZihzdHJ1Y3QgYXR0cmlidXRl\n" - "ICopICoKPiArCQkJCQkoc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRyX2NvdW50ICsgMSksCj4gKwkJ\n" - "CQkJR0ZQX0tFUk5FTCk7Cj4gKwkJaWYgKCFzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJz\n" - "KQo+ICsJCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwkJcGdyb3Vwc1t0eXBlXSA9ICZzZW5zb3Jf\n" - "Z3JvdXBzW3R5cGVdLmdyb3VwOwo+ICsJCXBkYXRhLT5zZW5zb3JzX2NvdW50ICs9IHNlbnNvcl9n\n" - "cm91cHNbdHlwZV0uYXR0cl9jb3VudDsKPiArCQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmF0dHJfY291\n" - "bnQgPSAwOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICsvKgo+ICsgKiBJdGVy\n" - "YXRlIHRocm91Z2ggdGhlIGRldmljZSB0cmVlIGZvciBlYWNoIGNoaWxkIG9mICdzZW5zb3JzJyBu\n" - "b2RlLCBjcmVhdGUKPiArICogYSBzeXNmcyBhdHRyaWJ1dGUgZmlsZSwgdGhlIGZpbGUgaXMgbmFt\n" - "ZWQgYnkgdHJhbnNsYXRpbmcgdGhlIERUIG5vZGUgbmFtZQo+ICsgKiB0byB0aGUgbmFtZSByZXF1\n" - "aXJlZCBieSB0aGUgaGlnaGVyICdod21vbicgZHJpdmVyIGxpa2UgZmFuMV9pbnB1dCwgdGVtcDFf\n" - "bWF4Cj4gKyAqIGV0Yy4uCj4gKyAqLwo+ICtzdGF0aWMgaW50IF9faW5pdCBjcmVhdGVfZGV2aWNl\n" - "X2F0dHJzKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiArCXN0cnVjdCBwbGF0\n" - "Zm9ybV9kYXRhICpwZGF0YSA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ICsJY29uc3Qg\n" - "c3RydWN0IGF0dHJpYnV0ZV9ncm91cCAqKnBncm91cHMgPSBwZGF0YS0+YXR0cl9ncm91cHM7Cj4g\n" - "KwlzdHJ1Y3QgZGV2aWNlX25vZGUgKm9wYWwsICpucDsKPiArCXN0cnVjdCBzZW5zb3JfZGF0YSAq\n" - "c2RhdGE7Cj4gKwljb25zdCBfX2JlMzIgKnNlbnNvcl9pZDsKPiArCWVudW0gc2Vuc29ycyB0eXBl\n" - "Owo+ICsJdTMyIGNvdW50ID0gMDsKPiArCWludCBlcnIgPSAwOwo+ICsKPiArCW9wYWwgPSBvZl9m\n" - "aW5kX25vZGVfYnlfcGF0aCgiL2libSxvcGFsL3NlbnNvcnMiKTsKPiArCXNkYXRhID0gZGV2bV9r\n" - "emFsbG9jKCZwZGV2LT5kZXYsIHBkYXRhLT5zZW5zb3JzX2NvdW50ICogc2l6ZW9mKCpzZGF0YSks\n" - "Cj4gKwkJCSAgICAgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIXNkYXRhKSB7Cj4gKwkJZXJyID0gLUVO\n" - "T01FTTsKPiArCQlnb3RvIGV4aXRfcHV0X25vZGU7Cj4gKwl9Cj4gKwo+ICsJZm9yX2VhY2hfY2hp\n" - "bGRfb2Zfbm9kZShvcGFsLCBucCkgewo+ICsJCWlmIChucC0+bmFtZSA9PSBOVUxMKQo+ICsJCQlj\n" - "b250aW51ZTsKPiArCj4gKwkJZm9yICh0eXBlID0gMDsgdHlwZSA8IE1BWF9TRU5TT1JfVFlQRTsg\n" - "dHlwZSsrKQo+ICsJCQlpZiAob2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCj4gKwkJCQkJc2Vu\n" - "c29yX2dyb3Vwc1t0eXBlXS5jb21wYXRpYmxlKSkKPiArCQkJCWJyZWFrOwo+ICsKPiArCQlpZiAo\n" - "dHlwZSA9PSBNQVhfU0VOU09SX1RZUEUpCj4gKwkJCWNvbnRpbnVlOwo+ICsKPiArCQlzZW5zb3Jf\n" - "aWQgPSBvZl9nZXRfcHJvcGVydHkobnAsICJzZW5zb3ItaWQiLCBOVUxMKTsKPiArCQlpZiAoIXNl\n" - "bnNvcl9pZCkgewo+ICsJCQlkZXZfaW5mbygmcGRldi0+ZGV2LAo+ICsJCQkJICInc2Vuc29yLWlk\n" - "JyBtaXNzaW5nIGluIHRoZSBub2RlICclcydcbiIsCj4gKwkJCQkgbnAtPm5hbWUpOwo+ICsJCQlj\n" - "b250aW51ZTsKPiArCQl9Cj4gKwo+ICsJCXNkYXRhW2NvdW50XS5pZCA9IGJlMzJfdG9fY3B1cChz\n" - "ZW5zb3JfaWQpOwo+ICsJCXNkYXRhW2NvdW50XS50eXBlID0gdHlwZTsKPiArCQllcnIgPSBjcmVh\n" - "dGVfaHdtb25fYXR0cl9uYW1lKCZwZGV2LT5kZXYsIHR5cGUsIG5wLT5uYW1lLAo+ICsJCQkJCSAg\n" - "ICAgc2RhdGFbY291bnRdLm5hbWUpOwo+ICsJCWlmIChlcnIpCj4gKwkJCWdvdG8gZXhpdF9wdXRf\n" - "bm9kZTsKPiArCj4gKwkJc3lzZnNfYXR0cl9pbml0KCZzZGF0YVtjb3VudF0uZGV2X2F0dHIuYXR0\n" - "cik7Cj4gKwkJc2RhdGFbY291bnRdLmRldl9hdHRyLmF0dHIubmFtZSA9IHNkYXRhW2NvdW50XS5u\n" - "YW1lOwo+ICsJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5hdHRyLm1vZGUgPSBTX0lSVUdPOwo+ICsJ\n" - "CXNkYXRhW2NvdW50XS5kZXZfYXR0ci5zaG93ID0gc2hvd19zZW5zb3I7Cj4gKwo+ICsJCXBncm91\n" - "cHNbdHlwZV0tPmF0dHJzW3NlbnNvcl9ncm91cHNbdHlwZV0uYXR0cl9jb3VudCsrXSA9Cj4gKwkJ\n" - "CQkmc2RhdGFbY291bnQrK10uZGV2X2F0dHIuYXR0cjsKPiArCX0KPiArCj4gK2V4aXRfcHV0X25v\n" - "ZGU6Cj4gKwlvZl9ub2RlX3B1dChvcGFsKTsKPiArCXJldHVybiBlcnI7Cj4gK30KPiArCj4gK3N0\n" - "YXRpYyBpbnQgX19pbml0IGlibXBvd2VybnZfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAq\n" - "cGRldikKPiArewo+ICsJc3RydWN0IHBsYXRmb3JtX2RhdGEgKnBkYXRhOwo+ICsJc3RydWN0IGRl\n" - "dmljZSAqaHdtb25fZGV2Owo+ICsJaW50IGVycjsKPiArCj4gKwlwZGF0YSA9IGRldm1fa3phbGxv\n" - "YygmcGRldi0+ZGV2LCBzaXplb2YoKnBkYXRhKSwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIXBkYXRh\n" - "KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYs\n" - "IHBkYXRhKTsKPiArCXBkYXRhLT5zZW5zb3JzX2NvdW50ID0gMDsKPiArCWVyciA9IHBvcHVsYXRl\n" - "X2F0dHJfZ3JvdXBzKHBkZXYpOwo+ICsJaWYgKGVycikKPiArCQlyZXR1cm4gZXJyOwo+ICsKPiAr\n" - "CS8qIENyZWF0ZSBzeXNmcyBhdHRyaWJ1dGUgZGF0YSBmb3IgZWFjaCBzZW5zb3IgZm91bmQgaW4g\n" - "dGhlIERUICovCj4gKwllcnIgPSBjcmVhdGVfZGV2aWNlX2F0dHJzKHBkZXYpOwo+ICsJaWYgKGVy\n" - "cikKPiArCQlyZXR1cm4gZXJyOwo+ICsKPiArCS8qIEZpbmFsbHksIHJlZ2lzdGVyIHdpdGggaHdt\n" - "b24gKi8KPiArCWh3bW9uX2RldiA9IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhfZ3Jv\n" - "dXBzKCZwZGV2LT5kZXYsIERSVk5BTUUsCj4gKwkJCQkJCQkgICBwZGF0YSwKPiArCQkJCQkJCSAg\n" - "IHBkYXRhLT5hdHRyX2dyb3Vwcyk7Cj4gKwo+ICsJcmV0dXJuIFBUUl9FUlJfT1JfWkVSTyhod21v\n" - "bl9kZXYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBpYm1wb3dl\n" - "cm52X2RyaXZlciA9IHsKPiArCS5kcml2ZXIgPSB7Cj4gKwkJLm93bmVyID0gVEhJU19NT0RVTEUs\n" - "Cj4gKwkJLm5hbWUgPSBEUlZOQU1FLAo+ICsJfSwKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgX19p\n" - "bml0IGlibXBvd2VybnZfaW5pdCh2b2lkKQo+ICt7Cj4gKwlpbnQgZXJyOwo+ICsKPiArCXBkZXZp\n" - "Y2UgPSBwbGF0Zm9ybV9kZXZpY2VfYWxsb2MoRFJWTkFNRSwgMCk7Cj4gKwlpZiAoIXBkZXZpY2Up\n" - "IHsKPiArCQlwcl9lcnIoIkRldmljZSBhbGxvY2F0aW9uIGZhaWxlZFxuIik7Cj4gKwkJZXJyID0g\n" - "LUVOT01FTTsKPiArCQlnb3RvIGV4aXQ7Cj4gKwl9Cj4gKwo+ICsJZXJyID0gcGxhdGZvcm1fZGV2\n" - "aWNlX2FkZChwZGV2aWNlKTsKPiArCWlmIChlcnIpIHsKPiArCQlwcl9lcnIoIkRldmljZSBhZGRp\n" - "dGlvbiBmYWlsZWQgKCVkKVxuIiwgZXJyKTsKPiArCQlnb3RvIGV4aXRfZGV2aWNlX3B1dDsKPiAr\n" - "CX0KPiArCj4gKwllcnIgPSBwbGF0Zm9ybV9kcml2ZXJfcHJvYmUoJmlibXBvd2VybnZfZHJpdmVy\n" - "LCBpYm1wb3dlcm52X3Byb2JlKTsKPiArCWlmIChlcnIpIHsKPiArCQlwcl9lcnIoIlBsYXRmcm9t\n" - "IGRyaXZlciBwcm9iZSBmYWlsZWRcbiIpOwo+ICsJCWdvdG8gZXhpdF9kZXZpY2VfZGVsOwo+ICsJ\n" - "fQo+ICsKPiArCXJldHVybiAwOwo+ICsKPiArZXhpdF9kZXZpY2VfZGVsOgo+ICsJcGxhdGZvcm1f\n" - "ZGV2aWNlX2RlbChwZGV2aWNlKTsKPiArZXhpdF9kZXZpY2VfcHV0Ogo+ICsJcGxhdGZvcm1fZGV2\n" - "aWNlX3B1dChwZGV2aWNlKTsKPiArZXhpdDoKPiArCXJldHVybiBlcnI7Cj4gK30KPiArCj4gK3N0\n" - "YXRpYyB2b2lkIF9fZXhpdCBpYm1wb3dlcm52X2V4aXQodm9pZCkKPiArewo+ICsJcGxhdGZvcm1f\n" - "ZHJpdmVyX3VucmVnaXN0ZXIoJmlibXBvd2VybnZfZHJpdmVyKTsKPiArCXBsYXRmb3JtX2Rldmlj\n" - "ZV91bnJlZ2lzdGVyKHBkZXZpY2UpOwo+ICt9Cj4gKwo+ICtNT0RVTEVfQVVUSE9SKCJOZWVsZXNo\n" - "IEd1cHRhIDxuZWVsZWd1cEBsaW51eC52bmV0LmlibS5jb20+Iik7Cj4gK01PRFVMRV9ERVNDUklQ\n" - "VElPTigiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIpOwo+ICtNT0RVTEVfTElDRU5TRSgi\n" - "R1BMIik7Cj4gKwo+ICttb2R1bGVfaW5pdChpYm1wb3dlcm52X2luaXQpOwo+ICttb2R1bGVfZXhp\n" - "dChpYm1wb3dlcm52X2V4aXQpOwo+Cj4KPgoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19f\n" - "X19fX19fX19fX19fX19fX19fCmxtLXNlbnNvcnMgbWFpbGluZyBsaXN0CmxtLXNlbnNvcnNAbG0t\n" - "c2Vuc29ycy5vcmcKaHR0cDovL2xpc3RzLmxtLXNlbnNvcnMub3JnL21haWxtYW4vbGlzdGluZm8v\n" - bG0tc2Vuc29ycw= + "On 07/04/2014 04:02 AM, Neelesh Gupta wrote:\n" + "> This patch adds basic kernel support for reading power values, fan\n" + "> speed rpm, voltage and temperature data on powernv platforms which will\n" + "> be exported to user space through sysfs interface.\n" + ">\n" + "\n" + "Hi Neelesh,\n" + "\n" + "Copying devicetree mailing list. Please copy it on the next (hopefully final)\n" + "revision; devicetree maintainers at least need a chance to comment.\n" + "[ Yes, I understand this is a shipping product, but still ... ]\n" + "\n" + "I am ok with the code except for a couple of minor nitpicks (see below).\n" + "\n" + "Thanks,\n" + "Guenter\n" + "\n" + "> Test results:\n" + "> -------------\n" + "> [root@tul163p1 ~]# sensors\n" + "> ibmpowernv-isa-0000\n" + "> Adapter: ISA adapter\n" + "> fan1: 5567 RPM (min = 0 RPM)\n" + "> fan2: 5232 RPM (min = 0 RPM)\n" + "> fan3: 5532 RPM (min = 0 RPM)\n" + "> fan4: 4945 RPM (min = 0 RPM)\n" + "> fan5: 0 RPM (min = 0 RPM)\n" + "> fan6: 0 RPM (min = 0 RPM)\n" + "> fan7: 7392 RPM (min = 0 RPM)\n" + "> fan8: 7936 RPM (min = 0 RPM)\n" + "> temp1: +39.0\302\260C (high = +0.0\302\260C)\n" + "> power1: 191.00 W\n" + ">\n" + "> [root@tul163p1 ~]# ls /sys/devices/platform/\n" + "> alarmtimer ibmpowernv.0 power rtc-generic serial8250 uevent\n" + "> [root@tul163p1 ~]# ls /sys/devices/platform/ibmpowernv.0/hwmon/hwmon0/\n" + "> device\t fan2_min\tfan4_min fan6_min\tfan8_min power\n" + "> fan1_fault fan3_fault\tfan5_fault fan7_fault\tin1_fault power1_input\n" + "> fan1_input fan3_input\tfan5_input fan7_input\tin2_fault subsystem\n" + "> fan1_min fan3_min\tfan5_min fan7_min\tin3_fault temp1_input\n" + "> fan2_fault fan4_fault\tfan6_fault fan8_fault\tin4_fault temp1_max\n" + "> fan2_input fan4_input\tfan6_input fan8_input\tname\t uevent\n" + "> [root@tul163p1 ~]#\n" + "> [root@tul163p1 ~]# ls /sys/class/hwmon/hwmon0/\n" + "> device\t fan2_min\tfan4_min fan6_min\tfan8_min power\n" + "> fan1_fault fan3_fault\tfan5_fault fan7_fault\tin1_fault power1_input\n" + "> fan1_input fan3_input\tfan5_input fan7_input\tin2_fault subsystem\n" + "> fan1_min fan3_min\tfan5_min fan7_min\tin3_fault temp1_input\n" + "> fan2_fault fan4_fault\tfan6_fault fan8_fault\tin4_fault temp1_max\n" + "> fan2_input fan4_input\tfan6_input fan8_input\tname\t uevent\n" + "> [root@tul163p1 ~]#\n" + ">\n" + "> Signed-off-by: Neelesh Gupta <neelegup-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>\n" + "> ---\n" + ">\n" + "> Changes in v4\n" + "> =============\n" + "> - Replaced pr_err() with dev_err() for loggin print messages.\n" + "> - Using kstrtou32() function for converting string to u32 instead of sscanf().\n" + ">\n" + "> Changes in v3\n" + "> =============\n" + "> - Fixed an endianness bug leading the driver to break on LE.\n" + "> - Fixed a bug that when one of the 'attribute_group' not populated, following\n" + "> groups attributes were dropped.\n" + "> - Rewrite the get_sensor_index_attr() function to handle all the error scenarios\n" + "> like 'sscanf' etc.\n" + "> - Fixed all the errors/warnings related to coding style/whitespace.\n" + "> - Added 'Documentation' files.\n" + "> - Addressed remaining review comments on V2.\n" + ">\n" + "> Changes in v2\n" + "> =============\n" + "> - Generic use of devm_* functions in hwmon like using devm_kzalloc() for dynamic\n" + "> memory request, avoiding the need to explicit free of memory.\n" + "> Adding 'struct attribute_group' as member of platform data structure to be\n" + "> populated and then passed to 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 ideal or\n" + "> could have just one group populated with attributes of sensor types?\n" + ">\n" + "> - 'ibmpowernv' is not hot-pluggable device so moving '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" + "> .../devicetree/bindings/hwmon/ibmpowernv.txt | 27 +\n" + "> Documentation/hwmon/ibmpowernv | 41 ++\n" + "> drivers/hwmon/Kconfig | 11 +\n" + "> drivers/hwmon/Makefile | 1\n" + "> drivers/hwmon/ibmpowernv.c | 362 ++++++++++++++++++++\n" + "> 5 files changed, 442 insertions(+)\n" + "> create mode 100644 Documentation/devicetree/bindings/hwmon/ibmpowernv.txt\n" + "> create mode 100644 Documentation/hwmon/ibmpowernv\n" + "> create mode 100644 drivers/hwmon/ibmpowernv.c\n" + ">\n" + "> diff --git a/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt\n" + "> new file mode 100644\n" + "> index 0000000..e3bd1eb\n" + "> --- /dev/null\n" + "> +++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt\n" + "> @@ -0,0 +1,27 @@\n" + "> +IBM POWERNV platform sensors\n" + "> +----------------------------\n" + "> +\n" + "> +Required node properties:\n" + "> +- compatible: must be one of\n" + "> +\t\t\"ibm,opal-sensor-cooling-fan\"\n" + "> +\t\t\"ibm,opal-sensor-amb-temp\"\n" + "> +\t\t\"ibm,opal-sensor-power-supply\"\n" + "> +\t\t\"ibm,opal-sensor-power\"\n" + "> +- sensor-id: an opaque id provided by the firmware to the kernel, identifies a\n" + "> +\t given sensor and its attribute data\n" + "> +\n" + "> +Example sensors node:\n" + "> +\n" + "> +cooling-fan#8-data {\n" + "> +\tsensor-id = <0x7052107>;\n" + "> +\tphandle = <0x10000028>;\n" + "> +\tlinux,phandle = <0x10000028>;\n" + "> +\tcompatible = \"ibm,opal-sensor-cooling-fan\";\n" + "\n" + "phandle and linux-phandle are neither documented nor used. Either document or drop.\n" + "\n" + "> +};\n" + "> +\n" + "> +amb-temp#1-thrs {\n" + "> +\tsensor-id = <0x5096000>;\n" + "> +\tphandle = <0x10000017>;\n" + "> +\tlinux,phandle = <0x10000017>;\n" + "> +\tcompatible = \"ibm,opal-sensor-amb-temp\";\n" + "> +};\n" + "> diff --git a/Documentation/hwmon/ibmpowernv b/Documentation/hwmon/ibmpowernv\n" + "> new file mode 100644\n" + "> index 0000000..644245a\n" + "> --- /dev/null\n" + "> +++ b/Documentation/hwmon/ibmpowernv\n" + "> @@ -0,0 +1,41 @@\n" + "> +Kernel Driver IBMPOWENV\n" + "> +=======================\n" + "> +\n" + "> +Supported systems:\n" + "> + * Any recent IBM P servers based on POWERNV platform\n" + "> +\n" + "> +Author: Neelesh Gupta\n" + "> +\n" + "> +Description\n" + "> +-----------\n" + "> +\n" + "> +This driver implements reading the platform sensors data like temperature/fan/\n" + "> +voltage/power for 'POWERNV' platform.\n" + "> +\n" + "> +The driver uses the platform device infrastructure. It probes the device tree\n" + "> +for sensor devices during the __init phase and registers them with the 'hwmon'.\n" + "> +'hwmon' populates the 'sysfs' tree having attribute files, each for a given\n" + "> +sensor type and its attribute data.\n" + "> +\n" + "> +All the nodes in the DT appear under \"/ibm,opal/sensors\" and each valid node in\n" + "> +the DT maps to an attribute file in 'sysfs'. The node exports unique 'sensor-id'\n" + "> +which the driver uses to make an OPAL call to the firmware.\n" + "> +\n" + "> +Usage notes\n" + "> +-----------\n" + "> +The driver is built statically with the kernel by enabling the config\n" + "> +CONFIG_SENSORS_IBMPOWERNV. It can also be built as module 'ibmpowernv'.\n" + "> +\n" + "> +Sysfs attributes\n" + "> +----------------\n" + "> +\n" + "> +fanX_input\t\tMeasured RPM value.\n" + "> +fanX_min\t\tThreshold RPM for alert generation.\n" + "> +fanX_fault\t\t0: No fail condition\n" + "> +\t\t\t1: Failing fan\n" + "> +tempX_input\t\tMeasured ambient temperature.\n" + "> +tempX_max\t\tThreshold ambient temperature for alert generation.\n" + "> +inX_input\t\tMeasured power supply voltage\n" + "> +inX_fault\t\t0: No fail condition.\n" + "> +\t\t\t1: Failing power supply.\n" + "> +power1_input\t\tSystem power consumption (microWatt)\n" + "> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig\n" + "> index 02d3d85..29c3fcb 100644\n" + "> --- a/drivers/hwmon/Kconfig\n" + "> +++ b/drivers/hwmon/Kconfig\n" + "> @@ -554,6 +554,17 @@ 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 PowerNV platform.\n" + "> +\n" + "> +\t This driver can also be built as a module. If so, the module\n" + "> +\t will be called ibmpowernv.\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 3dc0f02..fc4ed26 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..44dcd99\n" + "> --- /dev/null\n" + "> +++ b/drivers/hwmon/ibmpowernv.c\n" + "> @@ -0,0 +1,362 @@\n" + "> +/*\n" + "> + * IBM PowerNV platform sensors for temperature/fan/voltage/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" + "> +#define DRVNAME\t\t\"ibmpowernv\"\n" + "> +#define pr_fmt(fmt)\tDRVNAME \": \" fmt\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 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" + "> +/*\n" + "> + * Enumerates all the types of sensors in the POWERNV platform and does index\n" + "> + * into 'struct sensor_group'\n" + "> + */\n" + "> +enum sensors {\n" + "> +\tFAN,\n" + "> +\tAMBIENT_TEMP,\n" + "> +\tPOWER_SUPPLY,\n" + "> +\tPOWER_INPUT,\n" + "> +\tMAX_SENSOR_TYPE,\n" + "> +};\n" + "> +\n" + "> +static struct sensor_group {\n" + "> +\tconst char *name;\n" + "> +\tconst char *compatible;\n" + "> +\tstruct attribute_group group;\n" + "> +\tu32 attr_count;\n" + "> +} sensor_groups[] = {\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 sensor_data {\n" + "> +\tu32 id; /* An opaque id of the firmware for each sensor */\n" + "> +\tenum sensors type;\n" + "> +\tchar name[MAX_ATTR_LEN];\n" + "> +\tstruct device_attribute dev_attr;\n" + "> +};\n" + "> +\n" + "> +struct platform_data {\n" + "> +\tconst struct attribute_group *attr_groups[MAX_SENSOR_TYPE + 1];\n" + "> +\tu32 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 device_attribute *devattr,\n" + "> +\t\t\t char *buf)\n" + "> +{\n" + "> +\tstruct sensor_data *sdata = container_of(devattr, struct sensor_data,\n" + "> +\t\t\t\t\t\t dev_attr);\n" + "> +\tssize_t ret;\n" + "> +\tu32 x;\n" + "> +\n" + "> +\tret = opal_get_sensor_data(sdata->id, &x);\n" + "> +\tif (ret)\n" + "> +\t\treturn ret;\n" + "> +\n" + "> +\t/* Convert temperature to milli-degrees */\n" + "> +\tif (sdata->type == AMBIENT_TEMP)\n" + "> +\t\tx *= 1000;\n" + "> +\t/* Convert power to micro-watts */\n" + "> +\telse if (sdata->type == POWER_INPUT)\n" + "> +\t\tx *= 1000000;\n" + "> +\n" + "> +\treturn sprintf(buf, \"%u\\n\", x);\n" + "> +}\n" + "> +\n" + "> +static int __init get_sensor_index_attr(const char *name, u32 *index,\n" + "> +\t\t\t\t\tchar *attr)\n" + "> +{\n" + "> +\tchar *hash_pos = strchr(name, '#');\n" + "> +\tchar buf[8] = { 0 };\n" + "> +\tchar *dash_pos;\n" + "> +\tu32 copy_len;\n" + "> +\n" + "> +\tif (!hash_pos)\n" + "> +\t\treturn -EINVAL;\n" + "> +\n" + "> +\tdash_pos = strchr(hash_pos, '-');\n" + "> +\tif (!dash_pos)\n" + "> +\t\treturn -EINVAL;\n" + "> +\n" + "> +\tcopy_len = dash_pos - hash_pos - 1;\n" + "> +\tif (copy_len >= sizeof(buf))\n" + "> +\t\treturn -EINVAL;\n" + "> +\n" + "> +\tstrncpy(buf, hash_pos + 1, copy_len);\n" + "> +\n" + "> +\tif (kstrtou32(buf, 10, index))\n" + "> +\t\treturn -EINVAL;\n" + "> +\n" + "smatch isn't going to like that. Please use\n" + "\n" + "\tint err;\n" + "\t...\n" + "\terr = kstrtou32(buf, 10, index));\n" + "\tif (err)\n" + "\t\treturn err;\n" + "\n" + "> +\tstrncpy(attr, dash_pos + 1, MAX_ATTR_LEN);\n" + "> +\n" + "> +\treturn 0;\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 __init create_hwmon_attr_name(struct device *dev, enum sensors type,\n" + "> +\t\t\t\t\t const char *node_name,\n" + "> +\t\t\t\t\t char *hwmon_attr_name)\n" + "> +{\n" + "> +\tchar attr_suffix[MAX_ATTR_LEN];\n" + "> +\tchar *attr_name;\n" + "> +\tu32 index;\n" + "> +\tint err;\n" + "> +\n" + "> +\terr = get_sensor_index_attr(node_name, &index, attr_suffix);\n" + "> +\tif (err) {\n" + "> +\t\tdev_err(dev, \"Sensor device node name '%s' is invalid\\n\",\n" + "> +\t\t\tnode_name);\n" + "> +\t\treturn err;\n" + "> +\t}\n" + "> +\n" + "> +\tif (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX)) {\n" + "> +\t\tattr_name = \"fault\";\n" + "> +\t} else if (!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX)) {\n" + "> +\t\tattr_name = \"input\";\n" + "> +\t} else if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) {\n" + "> +\t\tif (type == AMBIENT_TEMP)\n" + "> +\t\t\tattr_name = \"max\";\n" + "> +\t\telse if (type == FAN)\n" + "> +\t\t\tattr_name = \"min\";\n" + "> +\t\telse\n" + "> +\t\t\treturn -ENOENT;\n" + "> +\t} else {\n" + "> +\t\treturn -ENOENT;\n" + "> +\t}\n" + "> +\n" + "> +\tsnprintf(hwmon_attr_name, MAX_ATTR_LEN, \"%s%d_%s\",\n" + "> +\t\t sensor_groups[type].name, index, attr_name);\n" + "> +\treturn 0;\n" + "> +}\n" + "> +\n" + "> +static int __init populate_attr_groups(struct platform_device *pdev)\n" + "> +{\n" + "> +\tstruct platform_data *pdata = platform_get_drvdata(pdev);\n" + "> +\tconst struct attribute_group **pgroups = pdata->attr_groups;\n" + "> +\tstruct device_node *opal, *np;\n" + "> +\tenum sensors type;\n" + "> +\n" + "> +\topal = of_find_node_by_path(\"/ibm,opal/sensors\");\n" + "> +\tif (!opal) {\n" + "> +\t\tdev_err(&pdev->dev, \"Opal node 'sensors' not found\\n\");\n" + "> +\t\treturn -ENODEV;\n" + "> +\t}\n" + "> +\n" + "> +\tfor_each_child_of_node(opal, np) {\n" + "> +\t\tif (np->name == NULL)\n" + "> +\t\t\tcontinue;\n" + "> +\n" + "> +\t\tfor (type = 0; type < MAX_SENSOR_TYPE; type++)\n" + "> +\t\t\tif (of_device_is_compatible(np,\n" + "> +\t\t\t\t\tsensor_groups[type].compatible)) {\n" + "> +\t\t\t\tsensor_groups[type].attr_count++;\n" + "> +\t\t\t\tbreak;\n" + "> +\t\t\t}\n" + "> +\t}\n" + "> +\n" + "> +\tof_node_put(opal);\n" + "> +\n" + "> +\tfor (type = 0; type < MAX_SENSOR_TYPE; type++) {\n" + "> +\t\tsensor_groups[type].group.attrs = devm_kzalloc(&pdev->dev,\n" + "> +\t\t\t\t\tsizeof(struct attribute *) *\n" + "> +\t\t\t\t\t(sensor_groups[type].attr_count + 1),\n" + "> +\t\t\t\t\tGFP_KERNEL);\n" + "> +\t\tif (!sensor_groups[type].group.attrs)\n" + "> +\t\t\treturn -ENOMEM;\n" + "> +\n" + "> +\t\tpgroups[type] = &sensor_groups[type].group;\n" + "> +\t\tpdata->sensors_count += sensor_groups[type].attr_count;\n" + "> +\t\tsensor_groups[type].attr_count = 0;\n" + "> +\t}\n" + "> +\n" + "> +\treturn 0;\n" + "> +}\n" + "> +\n" + "> +/*\n" + "> + * Iterate through the device tree for each child of 'sensors' 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 __init create_device_attrs(struct platform_device *pdev)\n" + "> +{\n" + "> +\tstruct platform_data *pdata = platform_get_drvdata(pdev);\n" + "> +\tconst struct attribute_group **pgroups = pdata->attr_groups;\n" + "> +\tstruct device_node *opal, *np;\n" + "> +\tstruct sensor_data *sdata;\n" + "> +\tconst __be32 *sensor_id;\n" + "> +\tenum sensors type;\n" + "> +\tu32 count = 0;\n" + "> +\tint err = 0;\n" + "> +\n" + "> +\topal = of_find_node_by_path(\"/ibm,opal/sensors\");\n" + "> +\tsdata = devm_kzalloc(&pdev->dev, pdata->sensors_count * sizeof(*sdata),\n" + "> +\t\t\t GFP_KERNEL);\n" + "> +\tif (!sdata) {\n" + "> +\t\terr = -ENOMEM;\n" + "> +\t\tgoto exit_put_node;\n" + "> +\t}\n" + "> +\n" + "> +\tfor_each_child_of_node(opal, np) {\n" + "> +\t\tif (np->name == NULL)\n" + "> +\t\t\tcontinue;\n" + "> +\n" + "> +\t\tfor (type = 0; type < MAX_SENSOR_TYPE; type++)\n" + "> +\t\t\tif (of_device_is_compatible(np,\n" + "> +\t\t\t\t\tsensor_groups[type].compatible))\n" + "> +\t\t\t\tbreak;\n" + "> +\n" + "> +\t\tif (type == 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\tdev_info(&pdev->dev,\n" + "> +\t\t\t\t \"'sensor-id' missing in the node '%s'\\n\",\n" + "> +\t\t\t\t np->name);\n" + "> +\t\t\tcontinue;\n" + "> +\t\t}\n" + "> +\n" + "> +\t\tsdata[count].id = be32_to_cpup(sensor_id);\n" + "> +\t\tsdata[count].type = type;\n" + "> +\t\terr = create_hwmon_attr_name(&pdev->dev, type, np->name,\n" + "> +\t\t\t\t\t sdata[count].name);\n" + "> +\t\tif (err)\n" + "> +\t\t\tgoto exit_put_node;\n" + "> +\n" + "> +\t\tsysfs_attr_init(&sdata[count].dev_attr.attr);\n" + "> +\t\tsdata[count].dev_attr.attr.name = sdata[count].name;\n" + "> +\t\tsdata[count].dev_attr.attr.mode = S_IRUGO;\n" + "> +\t\tsdata[count].dev_attr.show = show_sensor;\n" + "> +\n" + "> +\t\tpgroups[type]->attrs[sensor_groups[type].attr_count++] =\n" + "> +\t\t\t\t&sdata[count++].dev_attr.attr;\n" + "> +\t}\n" + "> +\n" + "> +exit_put_node:\n" + "> +\tof_node_put(opal);\n" + "> +\treturn err;\n" + "> +}\n" + "> +\n" + "> +static int __init ibmpowernv_probe(struct platform_device *pdev)\n" + "> +{\n" + "> +\tstruct platform_data *pdata;\n" + "> +\tstruct device *hwmon_dev;\n" + "> +\tint err;\n" + "> +\n" + "> +\tpdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);\n" + "> +\tif (!pdata)\n" + "> +\t\treturn -ENOMEM;\n" + "> +\n" + "> +\tplatform_set_drvdata(pdev, pdata);\n" + "> +\tpdata->sensors_count = 0;\n" + "> +\terr = populate_attr_groups(pdev);\n" + "> +\tif (err)\n" + "> +\t\treturn err;\n" + "> +\n" + "> +\t/* Create sysfs attribute data for each sensor found in the DT */\n" + "> +\terr = create_device_attrs(pdev);\n" + "> +\tif (err)\n" + "> +\t\treturn err;\n" + "> +\n" + "> +\t/* Finally, register with hwmon */\n" + "> +\thwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, DRVNAME,\n" + "> +\t\t\t\t\t\t\t pdata,\n" + "> +\t\t\t\t\t\t\t pdata->attr_groups);\n" + "> +\n" + "> +\treturn PTR_ERR_OR_ZERO(hwmon_dev);\n" + "> +}\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" + "> +};\n" + "> +\n" + "> +static int __init ibmpowernv_init(void)\n" + "> +{\n" + "> +\tint err;\n" + "> +\n" + "> +\tpdevice = platform_device_alloc(DRVNAME, 0);\n" + "> +\tif (!pdevice) {\n" + "> +\t\tpr_err(\"Device allocation failed\\n\");\n" + "> +\t\terr = -ENOMEM;\n" + "> +\t\tgoto exit;\n" + "> +\t}\n" + "> +\n" + "> +\terr = platform_device_add(pdevice);\n" + "> +\tif (err) {\n" + "> +\t\tpr_err(\"Device addition failed (%d)\\n\", err);\n" + "> +\t\tgoto exit_device_put;\n" + "> +\t}\n" + "> +\n" + "> +\terr = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe);\n" + "> +\tif (err) {\n" + "> +\t\tpr_err(\"Platfrom driver probe failed\\n\");\n" + "> +\t\tgoto exit_device_del;\n" + "> +\t}\n" + "> +\n" + "> +\treturn 0;\n" + "> +\n" + "> +exit_device_del:\n" + "> +\tplatform_device_del(pdevice);\n" + "> +exit_device_put:\n" + "> +\tplatform_device_put(pdevice);\n" + "> +exit:\n" + "> +\treturn err;\n" + "> +}\n" + "> +\n" + "> +static void __exit ibmpowernv_exit(void)\n" + "> +{\n" + "> +\tplatform_driver_unregister(&ibmpowernv_driver);\n" + "> +\tplatform_device_unregister(pdevice);\n" + "> +}\n" + "> +\n" + "> +MODULE_AUTHOR(\"Neelesh Gupta <neelegup-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>\");\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" + "\n" + "--\n" + "To unsubscribe from this list: send the line \"unsubscribe devicetree\" in\n" + "the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org\n" + More majordomo info at http://vger.kernel.org/majordomo-info.html -6fdfb7c435f43cd5fcc811d9232709df978b636ff428b7ed0c4ff08d71baa90b +04202aa89e3af4fbfe97bea85945cfb7d41e9576e90c6684ef23175f6fffa1b3
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.