All of lore.kernel.org
 help / color / mirror / Atom feed
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.