diff for duplicates of <568EB58C.3090701@topic.nl> diff --git a/a/1.txt b/N1/1.txt index 300346d..1333d0e 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -1,283 +1,508 @@ -VGhhbmsgeW91IHZlcnkgbXVjaCBmb3IgeW91ciByZXZpZXcgY29tbWVudHMsIEknbGwgdXBkYXRl -IHRoZSBkcml2ZXIgYW5kIApwb3N0IGEgdjIgcGF0Y2guCgpJbmxpbmVkIHNvbWUgcmVwbGllcyBi -ZWxvdy4gQXNzdW1lIHRoYXQgSSAid2lsbCBkbyIgZm9yIGFsbCBjb21tZW50cyBJIApkaWRuJ3Qg -Y29tbWVudCBvbiBpbmxpbmUuLi4KCk9uIDA2LTAxLTE2IDE2OjIyLCBHdWVudGVyIFJvZWNrIHdy -b3RlOgo+IEhlbGxvIE1pa2UsCj4KPiBPbiAwMS8wNi8yMDE2IDEyOjA3IEFNLCBNaWtlIExvb2lq -bWFucyB3cm90ZToKPj4gVGhpcyBhZGRzIHN1cHBvcnQgZm9yIHRoZSBMaW5lYXIgVGVjaG5vbG9n -eSBMVEMyOTkwICBJMkMgU3lzdGVtIE1vbml0b3IuCj4KPiBzLyAgLyAvCj4KPj4gVGhlIExUQzI5 -OTAgc3VwcG9ydHMgYSBjb21iaW5hdGlvbiBvZiB2b2x0YWdlLCBjdXJyZW50IGFuZCB0ZW1wZXJh -dHVyZQo+PiBtb25pdG9yaW5nLCBidXQgdGhpcyBkcml2ZXIgY3VycmVudGx5IG9ubHkgc3VwcG9y -dHMgcmVhZGluZyB0d28gY3VycmVudHMKPj4gYnkgbWVhc3VyaW5nIHR3byBkaWZmZXJlbnRpYWwg -dm9sdGFnZXMgYWNyb3NzIHNlcmllcyByZXNpc3RvcnMuCj4+Cj4gUGx1cyBWQ0MsIHBsdXMgdGhl -IGludGVybmFsIHRlbXBlcmF0dXJlLgoKWWVhaCwgSSBzaG91bGQgZ2l2ZSBteXNlbGYgbW9yZSBj -cmVkaXQgOikgSSdsbCBhZGQgdGhhdCBpbiBLY29uZmlnIHRvby4KCj4+IFRoaXMgaXMgc3VmZmlj -aWVudCB0byBzdXBwb3J0IHRoZSBUb3BpYyBNaWFtaSBTT00gd2hpY2ggdXNlcyB0aGlzIGNoaXAK -Pj4gdG8gbW9uaXRvciB0aGUgY3VycmVudHMgZmxvd2luZyBpbnRvIHRoZSBGUEdBIGFuZCB0aGUg -Q1BVIHBhcnRzLgo+Pgo+PiBTaWduZWQtb2ZmLWJ5OiBNaWtlIExvb2lqbWFucyA8bWlrZS5sb29p -am1hbnNAdG9waWMubmw+Cj4+IC0tLQo+PiAgIGRyaXZlcnMvaHdtb24vS2NvbmZpZyAgIHwgIDE1 -ICsrKwo+PiAgIGRyaXZlcnMvaHdtb24vTWFrZWZpbGUgIHwgICAxICsKPj4gICBkcml2ZXJzL2h3 -bW9uL2x0YzI5OTAuYyB8IDI3Mwo+PiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr -KysrKysrKysrKysrKysKPgo+IFBsZWFzZSBhbHNvIHByb3ZpZGUgRG9jdW1lbnRhdGlvbi9od21v -bi9sdGMyOTkwLgo+Cj4gQWxzbywgcGxlYXNlIHJlYWQgYW5kIGZvbGxvdyBEb2N1bWVudGF0aW9u -L2h3bW9uL3N1Ym1pdHRpbmctcGF0Y2hlcy4KPgo+PiAgIDMgZmlsZXMgY2hhbmdlZCwgMjg5IGlu -c2VydGlvbnMoKykKPj4gICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9od21vbi9sdGMyOTkw -LmMKPj4KPj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvaHdtb24vS2NvbmZpZyBiL2RyaXZlcnMvaHdt -b24vS2NvbmZpZwo+PiBpbmRleCA4MGE3M2JmLi5iM2VlZjMxIDEwMDY0NAo+PiAtLS0gYS9kcml2 -ZXJzL2h3bW9uL0tjb25maWcKPj4gKysrIGIvZHJpdmVycy9od21vbi9LY29uZmlnCj4+IEBAIC02 -ODUsNiArNjg1LDIxIEBAIGNvbmZpZyBTRU5TT1JTX0xUQzI5NDUKPj4gICAgICAgICBUaGlzIGRy -aXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1vZHVsZS4gSWYgc28sIHRoZSBtb2R1bGUgd2ls -bAo+PiAgICAgICAgIGJlIGNhbGxlZCBsdGMyOTQ1Lgo+Pgo+PiArY29uZmlnIFNFTlNPUlNfTFRD -Mjk5MAo+PiArICAgIHRyaXN0YXRlICJMaW5lYXIgVGVjaG5vbG9neSBMVEMyOTkwIChjdXJyZW50 -IG1vbml0b3JpbmcgbW9kZSBvbmx5KSIKPj4gKyAgICBkZXBlbmRzIG9uIEkyQwo+PiArICAgIHNl -bGVjdCBSRUdNQVBfSTJDCj4KPiBVc2luZyByZWdtYXAgZm9yIHRoZSBkcml2ZXIgbWlnaHQgYmUg -YSBnb29kIGlkZWEsIGJ1dCB5b3UgZG9uJ3QuCgpMb29raW5nIGF0IHRoZSByZWdtYXAsIHRoZSBk -cml2ZXIgb25seSB3cml0ZXMgdGhlIG9uZSBjYWNoYWJsZSByZWdpc3RlciAKb25jZSwgdGhlICJj -b250cm9sIi4gQWxsIHRoZSBvdGhlciByZWdpc3RlcnMgY2Fubm90IGJlIGNhY2hlZCwgYXJlIApl -aXRoZXIgcmVhZC1vbmx5IG9yIHdyaXRlLW9ubHkuIERvbid0IHRoaW5rIHJlZ21hcCB3aWxsIGhl -bHAsIHNvIEknbGwgCnJlbW92ZSB0aGUgInNlbGVjdCIgaGVyZS4KCj4+ICsgICAgZGVmYXVsdCBu -Cj4KPiBOb3QgbmVjZXNzYXJ5Lgo+Cj4+ICsgICAgaGVscAo+PiArICAgICAgSWYgeW91IHNheSB5 -ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIExpbmVhciBUZWNobm9sb2d5IExUQzI5OTAKPj4g -KyAgICAgIEkyQyBTeXN0ZW0gTW9uaXRvci4gVGhlIExUQzI5OTAgc3VwcG9ydHMgYSBjb21iaW5h -dGlvbiBvZiB2b2x0YWdlLAo+PiArICAgICAgY3VycmVudCBhbmQgdGVtcGVyYXR1cmUgbW9uaXRv -cmluZywgYnV0IHRoaXMgZHJpdmVyIGN1cnJlbnRseSBvbmx5Cj4+ICsgICAgICBzdXBwb3J0cyBy -ZWFkaW5nIHR3byBjdXJyZW50cyBieSBtZWFzdXJpbmcgdHdvIGRpZmZlcmVudGlhbAo+PiB2b2x0 -YWdlcwo+PiArICAgICAgYWNyb3NzIHNlcmllcyByZXNpc3RvcnMuCj4+ICsKPj4gKyAgICAgIFRo -aXMgZHJpdmVyIGNhbiBhbHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiBJZiBzbywgdGhlIG1vZHVs -ZSB3aWxsCj4+ICsgICAgICBiZSBjYWxsZWQgbHRjMjk5MC4KPj4gKwo+PiAgIGNvbmZpZyBTRU5T -T1JTX0xUQzQxNTEKPj4gICAgICAgdHJpc3RhdGUgIkxpbmVhciBUZWNobm9sb2d5IExUQzQxNTEi -Cj4+ICAgICAgIGRlcGVuZHMgb24gSTJDCj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2h3bW9uL01h -a2VmaWxlIGIvZHJpdmVycy9od21vbi9NYWtlZmlsZQo+PiBpbmRleCAxMmEzMjM5Li5lNGJkMTVi -IDEwMDY0NAo+PiAtLS0gYS9kcml2ZXJzL2h3bW9uL01ha2VmaWxlCj4+ICsrKyBiL2RyaXZlcnMv -aHdtb24vTWFrZWZpbGUKPj4gQEAgLTEwMSw2ICsxMDEsNyBAQCBvYmotJChDT05GSUdfU0VOU09S -U19MTTk1MjM0KSAgICArPSBsbTk1MjM0Lm8KPj4gICBvYmotJChDT05GSUdfU0VOU09SU19MTTk1 -MjQxKSAgICArPSBsbTk1MjQxLm8KPj4gICBvYmotJChDT05GSUdfU0VOU09SU19MTTk1MjQ1KSAg -ICArPSBsbTk1MjQ1Lm8KPj4gICBvYmotJChDT05GSUdfU0VOU09SU19MVEMyOTQ1KSAgICArPSBs -dGMyOTQ1Lm8KPj4gK29iai0kKENPTkZJR19TRU5TT1JTX0xUQzI5OTApICAgICs9IGx0YzI5OTAu -bwo+PiAgIG9iai0kKENPTkZJR19TRU5TT1JTX0xUQzQxNTEpICAgICs9IGx0YzQxNTEubwo+PiAg -IG9iai0kKENPTkZJR19TRU5TT1JTX0xUQzQyMTUpICAgICs9IGx0YzQyMTUubwo+PiAgIG9iai0k -KENPTkZJR19TRU5TT1JTX0xUQzQyMjIpICAgICs9IGx0YzQyMjIubwo+PiBkaWZmIC0tZ2l0IGEv -ZHJpdmVycy9od21vbi9sdGMyOTkwLmMgYi9kcml2ZXJzL2h3bW9uL2x0YzI5OTAuYwo+PiBuZXcg -ZmlsZSBtb2RlIDEwMDY0NAo+PiBpbmRleCAwMDAwMDAwLi4xNjFkOTk1Cj4+IC0tLSAvZGV2L251 -bGwKPj4gKysrIGIvZHJpdmVycy9od21vbi9sdGMyOTkwLmMKPj4gQEAgLTAsMCArMSwyNzMgQEAK -Pj4gKy8qCj4+ICsgKiBkcml2ZXIgZm9yIExpbmVhciBUZWNobm9sb2d5IExUQzI5OTAgcG93ZXIg -bW9uaXRvcgo+Cj4gRHJpdmVyCj4KPj4gKyAqCj4+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMTQgVG9w -aWMgRW1iZWRkZWQgUHJvZHVjdHMKPgo+IDIwMTUgPwoKSSB3cm90ZSB0aGUgZHJpdmVyIGVhcmx5 -IGxhc3QgeWVhci4gSSBvbmx5IGRpZCBzb21lIGNvc21ldGljIGNsZWFudXAgYW5kIApyZWJhc2Ug -b24gbWFzdGVyIGJlZm9yZSBzdWJtaXR0aW5nLgoKPgo+PiArICogQXV0aG9yOiBNaWtlIExvb2lq -bWFucyA8bWlrZS5sb29pam1hbnNAdG9waWMubmw+Cj4+ICsgKgo+PiArICogTGljZW5zZTogR1BM -djIKPj4gKyAqCj4+ICsgKiBUaGlzIGRyaXZlciBhc3N1bWVzIHRoZSBjaGlwIGlzIHdpcmVkIGFz -IGEgZHVhbCBjdXJyZW50IG1vbml0b3IsIGFuZAo+PiArICogcmVwb3J0cyB0aGUgdm9sdGFnZSBk -cm9wIGFjcm9zcyB0d28gc2VyaWVzIHJlc2lzdG9ycy4KPgo+IEl0IGFsc28gbW9uaXRvcnMgdGhl -IHRlbXBlcmF0dXJlIGFuZCBWQ0MuCj4KPj4gKyAqLwo+PiArCj4+ICsjaW5jbHVkZSA8bGludXgv -YnVnLmg+Cj4KPiBJcyB0aGlzIHVzZWQgYW55d2hlcmUgaW4gdGhlIGRyaXZlciA/CgpOb3QgYW55 -IG1vcmUuLi4KCj4KPj4gKyNpbmNsdWRlIDxsaW51eC9kZWxheS5oPgo+PiArI2luY2x1ZGUgPGxp -bnV4L2Vyci5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2h3bW9uLmg+Cj4+ICsjaW5jbHVkZSA8bGlu -dXgvaHdtb24tc3lzZnMuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9pMmMuaD4KPj4gKyNpbmNsdWRl -IDxsaW51eC9rZXJuZWwuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KPj4gKyNpbmNs -dWRlIDxsaW51eC9zbGFiLmg+Cj4+ICsKPj4gKyNkZWZpbmUgTFRDMjk5MF9TVEFUVVMgICAgMHgw -MAo+PiArI2RlZmluZSBMVEMyOTkwX0NPTlRST0wgICAgMHgwMQo+PiArI2RlZmluZSBMVEMyOTkw -X1RSSUdHRVIgICAgMHgwMgo+PiArI2RlZmluZSBMVEMyOTkwX1RJTlRfTVNCICAgIDB4MDQKPj4g -KyNkZWZpbmUgTFRDMjk5MF9USU5UX0xTQiAgICAweDA1Cj4+ICsjZGVmaW5lIExUQzI5OTBfVjFf -TVNCICAgIDB4MDYKPj4gKyNkZWZpbmUgTFRDMjk5MF9WMV9MU0IgICAgMHgwNwo+PiArI2RlZmlu -ZSBMVEMyOTkwX1YyX01TQiAgICAweDA4Cj4+ICsjZGVmaW5lIExUQzI5OTBfVjJfTFNCICAgIDB4 -MDkKPj4gKyNkZWZpbmUgTFRDMjk5MF9WM19NU0IgICAgMHgwQQo+PiArI2RlZmluZSBMVEMyOTkw -X1YzX0xTQiAgICAweDBCCj4+ICsjZGVmaW5lIExUQzI5OTBfVjRfTVNCICAgIDB4MEMKPj4gKyNk -ZWZpbmUgTFRDMjk5MF9WNF9MU0IgICAgMHgwRAo+PiArI2RlZmluZSBMVEMyOTkwX1ZDQ19NU0Ig -ICAgMHgwRQo+PiArI2RlZmluZSBMVEMyOTkwX1ZDQ19MU0IgICAgMHgwRgo+PiArCj4+ICsjZGVm -aW5lIExUQzI5OTBfU1RBVFVTX0JVU1kgICAgQklUKDApCj4+ICsjZGVmaW5lIExUQzI5OTBfU1RB -VFVTX1RJTlQgICAgQklUKDEpCj4+ICsjZGVmaW5lIExUQzI5OTBfU1RBVFVTX1YxICAgIEJJVCgy -KQo+PiArI2RlZmluZSBMVEMyOTkwX1NUQVRVU19WMiAgICBCSVQoMykKPj4gKyNkZWZpbmUgTFRD -Mjk5MF9TVEFUVVNfVjMgICAgQklUKDQpCj4+ICsjZGVmaW5lIExUQzI5OTBfU1RBVFVTX1Y0ICAg -IEJJVCg1KQo+PiArI2RlZmluZSBMVEMyOTkwX1NUQVRVU19WQ0MgICAgQklUKDYpCj4+ICsKPj4g -Ky8qIE9ubHkgZGVmaW5lIGNvbnRyb2wgc2V0dGluZ3Mgd2UgYWN0dWFsbHkgdXNlICovCj4+ICsj -ZGVmaW5lIExUQzI5OTBfQ09OVFJPTF9LRUxWSU4gICAgICAgIEJJVCg3KQo+PiArI2RlZmluZSBM -VEMyOTkwX0NPTlRST0xfU0lOR0xFICAgICAgICBCSVQoNikKPj4gKyNkZWZpbmUgTFRDMjk5MF9D -T05UUk9MX01FQVNVUkVfQUxMICAgICgweDMgPDwgMykKPj4gKyNkZWZpbmUgTFRDMjk5MF9DT05U -Uk9MX01PREVfQ1VSUkVOVCAgICAweDA2Cj4+ICsjZGVmaW5lIExUQzI5OTBfQ09OVFJPTF9NT0RF -X1ZPTFRBR0UgICAgMHgwNwo+PiArCj4+ICtzdHJ1Y3QgbHRjMjk5MF9kYXRhIHsKPj4gKyAgICBz -dHJ1Y3QgZGV2aWNlICpod21vbl9kZXY7Cj4+ICsgICAgc3RydWN0IG11dGV4IHVwZGF0ZV9sb2Nr -Owo+PiArICAgIHVuc2lnbmVkIGxvbmcgbGFzdF91cGRhdGVkOwo+PiArICAgIHNob3J0IHZhbHVl -c1s2XTsKPgo+IHUxNiA/Cj4KPj4gKyAgICBib29sIHZhbGlkOwo+PiArICAgIHU4IHVwZGF0ZV9j -b3VudGVyOwo+Cj4gTm90IHVzZWQgYW55d2hlcmUuCj4KPj4gK307Cj4+ICsKPj4gK3N0YXRpYyBp -bnQgbHRjMjk5MF93cml0ZShzdHJ1Y3QgaTJjX2NsaWVudCAqaTJjLCB1OCByZWcsIHU4IHZhbHVl -KQo+PiArewo+PiArICAgIHJldHVybiBpMmNfc21idXNfd3JpdGVfYnl0ZV9kYXRhKGkyYywgcmVn -LCB2YWx1ZSk7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBpbnQgbHRjMjk5MF9yZWFkX2J5dGUoc3Ry -dWN0IGkyY19jbGllbnQgKmkyYywgdTggcmVnKQo+PiArewo+PiArICAgIHJldHVybiBpMmNfc21i -dXNfcmVhZF9ieXRlX2RhdGEoaTJjLCByZWcpOwo+PiArfQo+PiArCj4KPiBVc2VsZXNzIHNoaW0g -ZnVuY3Rpb25zLgoKVHJ1ZSwgc2hvdWxkIGhhdmUgcmVtb3ZlZCB0aGVtIGFmdGVyIHJlZmFjdG9y -aW5nIHRoZW0gaW50byBvbmUtbGluZXJzLgpUaGV5IHdlcmUgY29udmVuaWVudCBlYXJseSBvbi4K -Cj4KPj4gK3N0YXRpYyBpbnQgbHRjMjk5MF9yZWFkX3dvcmQoc3RydWN0IGkyY19jbGllbnQgKmky -YywgdTggcmVnKQo+PiArewo+PiArICAgIGludCByZXN1bHQgPSBpMmNfc21idXNfcmVhZF93b3Jk -X2RhdGEoaTJjLCByZWcpOwo+PiArICAgIC8qIFJlc3VsdCBpcyBNU0IgZmlyc3QsIGJ1dCBzbWJ1 -cyBzcGVjcyBzYXkgTFNCIGZpcnN0LCBzbyBzd2FwIHRoZQo+PiArICAgICAqIHJlc3VsdCAqLwo+ -Cj4gQmFkIG11bHRpLWxpbmUgY29tbWVudC4KPgo+PiArICAgIHJldHVybiByZXN1bHQgPCAwID8g -cmVzdWx0IDogc3dhYjE2KHJlc3VsdCk7Cj4KPiBQbGVhc2UgdXNlIGkyY19zbWJ1c19yZWFkX3dv -cmRfc3dhcHBlZCgpIGFuZCBkcm9wIHRoZSBzaGltIGZ1bmN0aW9uLgo+Cj4+ICt9Cj4+ICsKPj4g -K3N0YXRpYyBzdHJ1Y3QgbHRjMjk5MF9kYXRhICpsdGMyOTkwX3VwZGF0ZV9kZXZpY2Uoc3RydWN0 -IGRldmljZSAqZGV2KQo+PiArewo+PiArICAgIHN0cnVjdCBpMmNfY2xpZW50ICppMmMgPSB0b19p -MmNfY2xpZW50KGRldik7Cj4+ICsgICAgc3RydWN0IGx0YzI5OTBfZGF0YSAqZGF0YSA9IGkyY19n -ZXRfY2xpZW50ZGF0YShpMmMpOwo+PiArICAgIHN0cnVjdCBsdGMyOTkwX2RhdGEgKnJldCA9IGRh -dGE7Cj4+ICsgICAgdW5zaWduZWQgaW50IHRpbWVvdXQ7Cj4+ICsKPj4gKyAgICBtdXRleF9sb2Nr -KCZkYXRhLT51cGRhdGVfbG9jayk7Cj4+ICsKPj4gKyAgICAvKiBVcGRhdGUgYWJvdXQgNCB0aW1l -cyBwZXIgc2Vjb25kIG1heCAqLwo+PiArICAgIGlmICh0aW1lX2FmdGVyKGppZmZpZXMsIGRhdGEt -Pmxhc3RfdXBkYXRlZCArIEhaIC8gNCkgfHwKPj4gIWRhdGEtPnZhbGlkKSB7Cj4+ICsgICAgICAg -IGludCB2YWw7Cj4+ICsgICAgICAgIGludCBpOwo+PiArCj4KPiBQbGVhc2UgY29uc2lkZXIgdXNp -bmcgY29udGludW91cyBjb252ZXJzaW9uLiBUaGlzIHdvdWxkIHNpbXBsaWZ5IHRoZQo+IGNvZGUg -c2lnbmlmaWNhbnRseQo+IGFuZCByZWR1Y2UgcmVhZCBkZWxheXMuCgpJdCBtaWdodCBpbmNyZWFz -ZSBwb3dlciBjb25zdW1wdGlvbiB0aG91Z2gsIGFzIHR5cGljYWxseSBzb21lIHVzZXIgCnByb2dy -YW0gd291bGQgcG9sbCB0aGlzIGV2ZXJ5IDEwIHNlY29uZHMgb3Igc28uIEknbGwgY2hlY2sgdGhl -IGRhdGEgc2hlZXQuCgo+PiArICAgICAgICAvKiBUcmlnZ2VyIEFEQywgYW55IHZhbHVlIHdpbGwg -ZG8gKi8KPj4gKyAgICAgICAgdmFsID0gbHRjMjk5MF93cml0ZShpMmMsIExUQzI5OTBfVFJJR0dF -UiwgMSk7Cj4+ICsgICAgICAgIGlmICh1bmxpa2VseSh2YWwgPCAwKSkgewo+PiArICAgICAgICAg -ICAgcmV0ID0gRVJSX1BUUih2YWwpOwo+PiArICAgICAgICAgICAgZ290byBhYm9ydDsKPj4gKyAg -ICAgICAgfQo+PiArCj4+ICsgICAgICAgIC8qIFdhaXQgZm9yIGNvbnZlcnNpb24gY29tcGxldGUg -Ki8KPj4gKyAgICAgICAgdGltZW91dCA9IDIwMDsKPj4gKyAgICAgICAgZm9yICg7Oykgewo+PiAr -ICAgICAgICAgICAgdXNsZWVwX3JhbmdlKDIwMDAsIDQwMDApOwo+PiArICAgICAgICAgICAgdmFs -ID0gbHRjMjk5MF9yZWFkX2J5dGUoaTJjLCBMVEMyOTkwX1NUQVRVUyk7Cj4+ICsgICAgICAgICAg -ICBpZiAodW5saWtlbHkodmFsIDwgMCkpIHsKPj4gKyAgICAgICAgICAgICAgICByZXQgPSBFUlJf -UFRSKHZhbCk7Cj4+ICsgICAgICAgICAgICAgICAgZ290byBhYm9ydDsKPj4gKyAgICAgICAgICAg -IH0KPj4gKyAgICAgICAgICAgIC8qIFNpbmdsZS1zaG90IG1vZGUsIHdhaXQgZm9yIGNvbnZlcnNp -b24gdG8gY29tcGxldGUgKi8KPj4gKyAgICAgICAgICAgIGlmICgodmFsICYgTFRDMjk5MF9TVEFU -VVNfQlVTWSkgPT0gMCkKPgo+ICAgICAgICAgICAgICBpZiAoISguLi4pKQo+Cj4+ICsgICAgICAg -ICAgICAgICAgYnJlYWs7Cj4+ICsgICAgICAgICAgICBpZiAoLS10aW1lb3V0ID09IDApIHsKPj4g -KyAgICAgICAgICAgICAgICByZXQgPSBFUlJfUFRSKC1FVElNRURPVVQpOwo+PiArICAgICAgICAg -ICAgICAgIGdvdG8gYWJvcnQ7Cj4+ICsgICAgICAgICAgICB9Cj4+ICsgICAgICAgIH0KPgo+IEFn -YWluLCBwbGVhc2UgY29uc2lkZXIgdXNpbmcgY29udGludW91cyBjb252ZXJzaW9uIG1vZGUuCj4K -PiBJZiB0aGlzIGlzIG5vdCBmZWFzaWJsZSBmb3Igc29tZSByZWFzb24sIHlvdSBtaWdodCBhcyB3 -ZWxsIGp1c3Qgd2FpdCBmb3IKPiB0aGUKPiBtaW5pbXVtIGNvbnZlcnNpb24gdGltZSBiZWZvcmUg -dHJ5aW5nIHRvIHJlYWQgZm9yIHRoZSBmaXJzdCB0aW1lLiBJZiBzbywKPiBwbGVhc2UgdXNlIGEg -Zml4ZWQgdGltZW91dCBieSBjb21wYXJpbmcgdGhlIGVsYXBzZWQgdGltZSBpbnN0ZWFkIG9mIGxv -b3BpbmcKPiBmb3IgYSBtYXhpbXVtIG51bWJlciBvZiB0aW1lcy4gTm90IGV2ZW4gY291bnRpbmcg -dGhlIHRpbWUgZm9yIGV4ZWN1dGluZyB0aGUKPiBjb2RlLCB0aGUgbWF4aW11bSBkZWxheSBpcyBi -ZXR3ZWVuIDQwMCBtcyBhbmQgODAwIG1zLCB3aGljaCBpcyB3YXkgdG9vIGhpZ2gKPiAoY2hpcCBz -cGVjIHNheXMgMTY3IG1zIHdvcnN0IGNhc2UsIGlmIHRocmVlIHRlbXBlcmF0dXJlIHNlbnNvcnMg -YXJlCj4gY29uZmlndXJlZCkuCgpPciBtYXliZSBJIHNob3VsZCBqdXN0IHNsZWVwIGZvciAxNjdt -cyBhbmQgYmUgZG9uZSB3aXRoIGl0LiBUaG91Z2ggSSAKdGhpbmsgSSdsIGdvdCB3aXRoIHlvdXIg -bWluaW1hbCB0aW1lIGZpcnN0IHN1Z2dlc3Rpb24uCgo+PiArCj4+ICsgICAgICAgIC8qIFJlYWQg -YWxsIHJlZ2lzdGVycyAqLwo+PiArICAgICAgICBmb3IgKGkgPSAwOyBpIDwgQVJSQVlfU0laRShk -YXRhLT52YWx1ZXMpOyArK2kpIHsKPj4gKyAgICAgICAgICAgIHZhbCA9IGx0YzI5OTBfcmVhZF93 -b3JkKGkyYywgKGk8PDEpICsgTFRDMjk5MF9USU5UX01TQik7Cj4KPiBNaXNzaW5nIHNwYWNlcyBh -cm91bmQgPDwKPgo+PiArICAgICAgICAgICAgaWYgKHVubGlrZWx5KHZhbCA8IDApKSB7Cj4+ICsg -ICAgICAgICAgICAgICAgZGV2X2RiZyhkZXYsCj4+ICsgICAgICAgICAgICAgICAgICAgICJGYWls -ZWQgdG8gcmVhZCBBREMgdmFsdWU6IGVycm9yICVkXG4iLAo+PiArICAgICAgICAgICAgICAgICAg -ICB2YWwpOwo+PiArICAgICAgICAgICAgICAgIHJldCA9IEVSUl9QVFIodmFsKTsKPj4gKyAgICAg -ICAgICAgICAgICBnb3RvIGFib3J0Owo+PiArICAgICAgICAgICAgfQo+PiArICAgICAgICAgICAg -ZGF0YS0+dmFsdWVzW2ldID0gdmFsICYgMHg3RkZGOyAvKiBTdHJpcCAnbmV3JyBiaXQgKi8KPgo+ -IFRoZSBiaXQgaXMgbmV2ZXIgZXZhbHVhdGVkLCBzbyB5b3UgbWlnaHQgYXMgd2VsbCBzdG9yZSB0 -aGUgcmF3IHZhbHVlLgo+Cj4+ICsgICAgICAgIH0KPj4gKyAgICAgICAgZGF0YS0+bGFzdF91cGRh -dGVkID0gamlmZmllczsKPj4gKyAgICAgICAgZGF0YS0+dmFsaWQgPSAxOwo+Cj4gICAgICA9IHRy -dWU7Cj4KPj4gKwo+PiArICAgICAgICAvKgo+PiArICAgICAgICAgKiAgUXVpcms6IFNlY29uZCB0 -cmlnZ2VyIGlzIGlnbm9yZWQ/IEFmdGVyIHRoaXMsIHRoZSBCVVNZIHdpbGwKPj4gKyAgICAgICAg -ICogc3RpbGwgYmUgc2V0IHRvICIwIiBhbmQgbm8gY29udmVyc2lvbiBwZXJmb3JtZWQuCj4+ICsg -ICAgICAgICAqLwo+PiArICAgICAgICB2YWwgPSBsdGMyOTkwX3dyaXRlKGkyYywgTFRDMjk5MF9U -UklHR0VSLCAwKTsKPj4gKyAgICB9Cj4+ICthYm9ydDoKPj4gKyAgICBtdXRleF91bmxvY2soJmRh -dGEtPnVwZGF0ZV9sb2NrKTsKPj4gKyAgICByZXR1cm4gcmV0Owo+PiArfQo+PiArCj4+ICsvKiBS -ZXR1cm4gdGhlIGNvbnZlcnRlZCB2YWx1ZSBmcm9tIHRoZSBnaXZlbiByZWdpc3RlciBpbiB1ViBv -ciBtQyAqLwo+PiArc3RhdGljIGludCBsdGMyOTkwX2dldF92YWx1ZShzdHJ1Y3QgbHRjMjk5MF9k -YXRhICpkYXRhLCB1OCBpbmRleCkKPj4gK3sKPj4gKyAgICBzMzIgcmVzdWx0Owo+PiArICAgIHMx -NiB2Owo+PiArCj4+ICsgICAgaWYgKGluZGV4ID09IDApIHsgLyogaW50ZXJuYWwgdGVtcCwgMC4w -NjI1IGRlZ3JlZXMvTFNCLCAxMi1iaXQgICovCj4+ICsgICAgICAgIHYgPSBkYXRhLT52YWx1ZXNb -aW5kZXhdIDw8IDM7Cj4+ICsgICAgICAgIHJlc3VsdCA9IChzMzIpdiAqIDEwMDAgPj4gNzsKPj4g -KyAgICB9IGVsc2UgaWYgKGluZGV4IDwgNSkgeyAvKiBWeC1WeSwgMTkuNDJ1Vi9MU0IsIDE0LWJp -dCAqLwo+PiArICAgICAgICB2ID0gZGF0YS0+dmFsdWVzW2luZGV4XSA8PCAyOwo+Cj4gRGF0YXNo -ZWV0IHNheXMgdGhhdCB0aGUgc2lnbiBiaXQgaXMgaW4gYml0IDE0LCBzbyB0aGlzIGRyb3BzIHRo -ZSBzaWduIGJpdC4KCkknbGwgY2hlY2sgdGhlIGRhdGEgc2hlZXQsIHdvdWxkIG5vdCBoYXZlIG5v -dGljZWQgdGhpcyBzaW5jZSBjdXJyZW50IApkb2Vzbid0IHRlbmQgdG8gcnVuIGZyb20gdGhlIENQ -VSBiYWNrIGludG8gdGhlIGJhdHRlcnkgOikKCj4+ICsgICAgICAgIHJlc3VsdCA9IChzMzIpdiAq -IDE5NDIgLyAoNCAqIDEwMCk7Cj4+ICsgICAgfSBlbHNlIHsgLyogVmNjLCAzMDUuMTjOvFYvTFNC -LCAyLjVWIG9mZnNldCwgMTQtYml0ICovCj4+ICsgICAgICAgIHYgPSBkYXRhLT52YWx1ZXNbaW5k -ZXhdIDw8IDI7Cj4+ICsgICAgICAgIHJlc3VsdCA9IChzMzIpdiAqIDMwNTE4IC8gKDQgKiAxMDAp -Owo+PiArICAgICAgICByZXN1bHQgKz0gMjUwMDAwMDsKPj4gKyAgICB9Cj4+ICsgICAgcmV0dXJu -IHJlc3VsdDsKPj4gK30KPj4gKwo+PiArc3RhdGljIHNzaXplX3QgbHRjMjk5MF9zaG93X3ZhbHVl -KHN0cnVjdCBkZXZpY2UgKmRldiwKPj4gKyAgICAgICAgICAgICAgICAgIHN0cnVjdCBkZXZpY2Vf -YXR0cmlidXRlICpkYSwgY2hhciAqYnVmKQo+PiArewo+PiArICAgIHN0cnVjdCBzZW5zb3JfZGV2 -aWNlX2F0dHJpYnV0ZSAqYXR0ciA9IHRvX3NlbnNvcl9kZXZfYXR0cihkYSk7Cj4+ICsgICAgc3Ry -dWN0IGx0YzI5OTBfZGF0YSAqZGF0YSA9IGx0YzI5OTBfdXBkYXRlX2RldmljZShkZXYpOwo+PiAr -ICAgIGludCB2YWx1ZTsKPj4gKwo+PiArICAgIGlmIChJU19FUlIoZGF0YSkpCj4+ICsgICAgICAg -IHJldHVybiBQVFJfRVJSKGRhdGEpOwo+PiArCj4+ICsgICAgdmFsdWUgPSBsdGMyOTkwX2dldF92 -YWx1ZShkYXRhLCBhdHRyLT5pbmRleCk7Cj4+ICsgICAgcmV0dXJuIHNucHJpbnRmKGJ1ZiwgUEFH -RV9TSVpFLCAiJWRcbiIsIHZhbHVlKTsKPj4gK30KPj4gKwo+PiArc3RhdGljIFNFTlNPUl9ERVZJ -Q0VfQVRUUih0ZW1wX2ludCwgU19JUlVHTywgbHRjMjk5MF9zaG93X3ZhbHVlLAo+PiBOVUxMLCAw -KTsKPj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodjF2Ml9kaWZmLCBTX0lSVUdPLCBsdGMy -OTkwX3Nob3dfdmFsdWUsCj4+IE5VTEwsIDEpOwo+PiArc3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRU -Uih2M3Y0X2RpZmYsIFNfSVJVR08sIGx0YzI5OTBfc2hvd192YWx1ZSwKPj4gTlVMTCwgMyk7Cj4+ -ICtzdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHZjYywgU19JUlVHTywgbHRjMjk5MF9zaG93X3Zh -bHVlLCBOVUxMLCA1KTsKPj4gKwo+Cj4gUGxlYXNlIHVzZSBzdGFuZGFyZCBhdHRyaWJ1dGUgbmFt -ZXMgKGFuZCB1bml0cykgYXMgcGVyCj4gRG9jdW1lbnRhdGlvbi9od21vbi9zeXNmcy1pbnRlcmZh -Y2UuCj4KPj4gK3N0YXRpYyBzdHJ1Y3QgYXR0cmlidXRlICpsdGMyOTkwX2F0dHJpYnV0ZXNbXSA9 -IHsKPj4gKyAgICAmc2Vuc29yX2Rldl9hdHRyX3RlbXBfaW50LmRldl9hdHRyLmF0dHIsCj4+ICsg -ICAgJnNlbnNvcl9kZXZfYXR0cl92MXYyX2RpZmYuZGV2X2F0dHIuYXR0ciwKPj4gKyAgICAmc2Vu -c29yX2Rldl9hdHRyX3YzdjRfZGlmZi5kZXZfYXR0ci5hdHRyLAo+PiArICAgICZzZW5zb3JfZGV2 -X2F0dHJfdmNjLmRldl9hdHRyLmF0dHIsCj4+ICsgICAgTlVMTCwKPj4gK307Cj4+ICsKPj4gK3N0 -YXRpYyBjb25zdCBzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIGx0YzI5OTBfZ3JvdXAgPSB7Cj4+ICsg -ICAgLmF0dHJzID0gbHRjMjk5MF9hdHRyaWJ1dGVzLAo+PiArfTsKPj4gKwo+Cj4gUGxlYXNlIHVz -ZSB0aGUgQVRUUklCVVRFX0dST1VQUygpIG1hY3JvLiBBbHNvIHNlZSBiZWxvdy4KCk9rYXksIHdp -bGwgUlRGTS4KCj4KPj4gK3N0YXRpYyBpbnQgbHRjMjk5MF9pMmNfcHJvYmUoCj4+ICsgICAgc3Ry -dWN0IGkyY19jbGllbnQgKmkyYywgY29uc3Qgc3RydWN0IGkyY19kZXZpY2VfaWQgKmlkKQo+Cj4g -UGxlYXNlIHNwbGl0IGFzCj4KPiBzdGF0aWMgaW50IGx0YzI5OTBfaTJjX3Byb2JlKHN0cnVjdCBp -MmNfY2xpZW50ICppMmMsCj4gICAgICAgICAgICAgICAgICAgY29uc3Qgc3RydWN0IGkyY19kZXZp -Y2VfaWQgKmlkKQo+Cj4+ICt7Cj4+ICsgICAgaW50IHJldDsKPj4gKyAgICBzdHJ1Y3QgbHRjMjk5 -MF9kYXRhICpsdGMyOTkwOwo+PiArCj4+ICsgICAgaWYgKCFpMmNfY2hlY2tfZnVuY3Rpb25hbGl0 -eShpMmMtPmFkYXB0ZXIsCj4+IEkyQ19GVU5DX1NNQlVTX0JZVEVfREFUQSkpCj4+ICsgICAgICAg -IHJldHVybiAtRU5PREVWOwo+PiArCj4+ICsgICAgbHRjMjk5MCA9IGRldm1fa3phbGxvYygmaTJj -LT5kZXYsCj4+ICsgICAgICAgIHNpemVvZihzdHJ1Y3QgbHRjMjk5MF9kYXRhKSwgR0ZQX0tFUk5F -TCk7Cj4KPiBQbGVhc2UgYWxpZ24gY29udGludWF0aW9uIGxpbmVzIHdpdGggJygnLgo+Cj4+ICsg -ICAgaWYgKGx0YzI5OTAgPT0gTlVMTCkKPj4gKyAgICAgICAgcmV0dXJuIC1FTk9NRU07Cj4+ICsK -Pj4gKyAgICByZXQgPSBsdGMyOTkwX3JlYWRfYnl0ZShpMmMsIDApOwo+PiArICAgIGlmIChyZXQg -PCAwKSB7Cj4+ICsgICAgICAgIGRldl9lcnIoJmkyYy0+ZGV2LCAiQ291bGQgbm90IHJlYWQgTFRD -Mjk5MCBvbiBpMmMgYnVzLlxuIik7Cj4+ICsgICAgICAgIHJldHVybiByZXQ7Cj4+ICsgICAgfQo+ -Cj4gVGhlIHdyaXRlIGJlbG93IHdvdWxkIGFsc28gcmV0dXJuIGFuIGVycm9yIGlmIHRoZSBjaGlw -IGlzbid0IHRoZXJlLAo+IHNvIHRoaXMgYWRkaXRpb25hbCByZWFkIGRvZXMgbm90IHByb3ZpZGUg -YW55IHJlYWwgdmFsdWUuCj4KPj4gKyAgICByZXQgPSBsdGMyOTkwX3dyaXRlKGkyYywgTFRDMjk5 -MF9DT05UUk9MLAo+PiArICAgICAgICBMVEMyOTkwX0NPTlRST0xfU0lOR0xFIHwgTFRDMjk5MF9D -T05UUk9MX01FQVNVUkVfQUxMIHwKPj4gKyAgICAgICAgTFRDMjk5MF9DT05UUk9MX01PREVfQ1VS -UkVOVCk7Cj4KPiBJJ2xsIGhhdmUgdG8gdGhpbmsgYWJvdXQgdGhpcy4gV2hpbGUgaXQgYWRkcmVz -c2VzIHlvdXIgdXNlIGNhc2UsCj4gaXQgbGltaXRzIHRoZSBzY29wZSBvZiB0aGlzIGRyaXZlciBz -aWduaWZpY2FudGx5LiBMb29raW5nIGludG8gdGhlIGJvYXJkCj4gc3BlY2lmaWNhdGlvbnMsIHlv -dSBtaWdodCBhcyB3ZWxsIGRvIGl0IHJpZ2h0IGFuZCBkZXRlcm1pbmUgKGFuZCBzZXQpCj4gdGhl -IGNvcnJlY3QgY29uZmlndXJhdGlvbiB1c2luZyBkZXZpY2V0cmVlIGRhdGEgaW5zdGVhZCBvZiBm -b3JjaW5nIHlvdXIKPiB1c2UgY2FzZSBvbiBldmVyeW9uZS4KPgo+IFN1cmUsIHlvdSBtYXkgYXJn -dWUgdGhhdCB5b3UgZG9uJ3QgY2FyZSwgYnV0IHdlIHdpbGwgYmUgdGhlIG9uZXMgd2hvCj4gd2ls -bCBoYXZlCj4gdG8gaGFuZGxlIGVycm9yIHJlcG9ydHMgdGhhdCB0aGUgZHJpdmVyIHVuZXhwZWN0 -ZWRseSBjaGFuZ2VzIHRoZQo+IGNvbmZpZ3VyYXRpb24KPiBpbiBvdGhlciB1c2UgY2FzZXMgKHdo -ZXJlLCBmb3IgZXhhbXBsZSwgdGhlIG1vZGUgbWF5IGhhdmUgYmVlbiBwcmUtc2V0IGJ5Cj4gdGhl -IEJJT1Mgb3IgUk9NTU9OKS4KClRoZSByZWFzb24gSSBkaWRuJ3Qgc3VibWl0IHRoZSBkcml2ZXIg -bGFzdCB5ZWFyIHdhcyB0aGF0IEkgd2FzIHN0aWxsIAp0aGlua2luZyBhYm91dCBpdC4gT24gdGhl -IG90aGVyIGhhbmQsIGEgbGltaXRlZCBkcml2ZXIgaXMgc3RpbGwgbXVjaCAKYmV0dGVyIHRoYW4g -bm8gZHJpdmVyIGF0IGFsbCwgc28gdGhhdCBtYWRlIG1lIHBvc3QgaXQsIHdpdGggdGhlIGFkZGVk -IApyZW1hcmtzIGFib3V0IHRoZSBkcml2ZXIgYmVpbmcgbGltaXRlZC4KCkFkZGluZyB0aGUgb3Ro -ZXIgZnVuY3Rpb25zIGl0IHF1aXRlIGEgYml0IG1vcmUgd29yayB0aGFuIGp1c3Qgd3JpdGluZyAK -dGhpcyByZWdpc3Rlci4gSXQgYWxzbyBjaGFuZ2VzIHRoZSBwcm9wZXJ0aWVzIHRvIGJlIGV4cG9y -dGVkIHRvIHN5c2ZzLCAKYW5kIHRoZSBjYWxjdWxhdGlvbiBvZiB0aGUgZW5kIHZhbHVlcy4KCj4K -Pj4gKyAgICBpZiAocmV0IDwgMCkgewo+PiArICAgICAgICBkZXZfZXJyKCZpMmMtPmRldiwgIkVy -cm9yOiBGYWlsZWQgdG8gc2V0IGNvbnRyb2wgbW9kZS5cbiIpOwo+PiArICAgICAgICByZXR1cm4g -cmV0Owo+PiArICAgIH0KPj4gKwo+PiArICAgIG11dGV4X2luaXQoJmx0YzI5OTAtPnVwZGF0ZV9s -b2NrKTsKPj4gKyAgICBpMmNfc2V0X2NsaWVudGRhdGEoaTJjLCBsdGMyOTkwKTsKPj4gKwo+PiAr -ICAgIC8qIFJlZ2lzdGVyIHN5c2ZzIGhvb2tzICovCj4+ICsgICAgcmV0ID0gc3lzZnNfY3JlYXRl -X2dyb3VwKCZpMmMtPmRldi5rb2JqLCAmbHRjMjk5MF9ncm91cCk7Cj4+ICsgICAgaWYgKHJldCkK -Pj4gKyAgICAgICAgcmV0dXJuIHJldDsKPj4gKwo+PiArICAgIGx0YzI5OTAtPmh3bW9uX2RldiA9 -IGh3bW9uX2RldmljZV9yZWdpc3RlcigmaTJjLT5kZXYpOwo+Cj4gUGxlYXNlIHVzZSBkZXZtX2h3 -bW9uX2RldmljZV9yZWdpc3Rlcl93aXRoX2dyb3VwcygpLgo+Cj4+ICsgICAgaWYgKElTX0VSUihs -dGMyOTkwLT5od21vbl9kZXYpKSB7Cj4+ICsgICAgICAgIHJldCA9IFBUUl9FUlIobHRjMjk5MC0+ -aHdtb25fZGV2KTsKPj4gKyAgICAgICAgZ290byBvdXRfaHdtb25fZGV2aWNlX3JlZ2lzdGVyOwo+ -PiArICAgIH0KPj4gKwo+PiArICAgIHJldHVybiAwOwo+PiArCj4+ICtvdXRfaHdtb25fZGV2aWNl -X3JlZ2lzdGVyOgo+PiArICAgIHN5c2ZzX3JlbW92ZV9ncm91cCgmaTJjLT5kZXYua29iaiwgJmx0 -YzI5OTBfZ3JvdXApOwo+PiArICAgIHJldHVybiByZXQ7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBp -bnQgbHRjMjk5MF9pMmNfcmVtb3ZlKHN0cnVjdCBpMmNfY2xpZW50ICppMmMpCj4+ICt7Cj4+ICsg -ICAgc3RydWN0IGx0YzI5OTBfZGF0YSAqbHRjMjk5MCA9IGkyY19nZXRfY2xpZW50ZGF0YShpMmMp -Owo+PiArCj4+ICsgICAgaHdtb25fZGV2aWNlX3VucmVnaXN0ZXIobHRjMjk5MC0+aHdtb25fZGV2 -KTsKPj4gKyAgICBzeXNmc19yZW1vdmVfZ3JvdXAoJmkyYy0+ZGV2LmtvYmosICZsdGMyOTkwX2dy -b3VwKTsKPj4gKyAgICByZXR1cm4gMDsKPj4gK30KPj4gKwo+PiArc3RhdGljIGNvbnN0IHN0cnVj -dCBpMmNfZGV2aWNlX2lkIGx0YzI5OTBfaTJjX2lkW10gPSB7Cj4+ICsgICAgeyAibHRjMjk5MCIs -IDAgfSwKPj4gKyAgICB7fQo+PiArfTsKPj4gK01PRFVMRV9ERVZJQ0VfVEFCTEUoaTJjLCBsdGMy -OTkwX2kyY19pZCk7Cj4+ICsKPj4gK3N0YXRpYyBzdHJ1Y3QgaTJjX2RyaXZlciBsdGMyOTkwX2ky -Y19kcml2ZXIgPSB7Cj4+ICsgICAgLmRyaXZlciA9IHsKPj4gKyAgICAgICAgLm5hbWUgPSAibHRj -Mjk5MCIsCj4+ICsgICAgfSwKPj4gKyAgICAucHJvYmUgICAgPSBsdGMyOTkwX2kyY19wcm9iZSwK -Pj4gKyAgICAucmVtb3ZlICAgPSBsdGMyOTkwX2kyY19yZW1vdmUsCj4+ICsgICAgLmlkX3RhYmxl -ID0gbHRjMjk5MF9pMmNfaWQsCj4+ICt9Owo+PiArCj4+ICttb2R1bGVfaTJjX2RyaXZlcihsdGMy -OTkwX2kyY19kcml2ZXIpOwo+PiArCj4+ICtNT0RVTEVfREVTQ1JJUFRJT04oIkxUQzI5OTAgU2Vu -c29yIERyaXZlciIpOwo+PiArTU9EVUxFX0FVVEhPUigiVG9waWMgRW1iZWRkZWQgUHJvZHVjdHMi -KTsKPj4gK01PRFVMRV9MSUNFTlNFKCJHUEwgdjIiKTsKPj4KPgoKCi0tIApNaWtlIExvb2lqbWFu -cwoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbG0tc2Vu -c29ycyBtYWlsaW5nIGxpc3QKbG0tc2Vuc29yc0BsbS1zZW5zb3JzLm9yZwpodHRwOi8vbGlzdHMu -bG0tc2Vuc29ycy5vcmcvbWFpbG1hbi9saXN0aW5mby9sbS1zZW5zb3Jz +Thank you very much for your review comments, I'll update the driver and +post a v2 patch. + +Inlined some replies below. Assume that I "will do" for all comments I +didn't comment on inline... + +On 06-01-16 16:22, Guenter Roeck wrote: +> Hello Mike, +> +> On 01/06/2016 12:07 AM, Mike Looijmans wrote: +>> This adds support for the Linear Technology LTC2990 I2C System Monitor. +> +> s/ / / +> +>> The LTC2990 supports a combination of voltage, current and temperature +>> monitoring, but this driver currently only supports reading two currents +>> by measuring two differential voltages across series resistors. +>> +> Plus VCC, plus the internal temperature. + +Yeah, I should give myself more credit :) I'll add that in Kconfig too. + +>> This is sufficient to support the Topic Miami SOM which uses this chip +>> to monitor the currents flowing into the FPGA and the CPU parts. +>> +>> Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl> +>> --- +>> drivers/hwmon/Kconfig | 15 +++ +>> drivers/hwmon/Makefile | 1 + +>> drivers/hwmon/ltc2990.c | 273 +>> ++++++++++++++++++++++++++++++++++++++++++++++++ +> +> Please also provide Documentation/hwmon/ltc2990. +> +> Also, please read and follow Documentation/hwmon/submitting-patches. +> +>> 3 files changed, 289 insertions(+) +>> create mode 100644 drivers/hwmon/ltc2990.c +>> +>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +>> index 80a73bf..b3eef31 100644 +>> --- a/drivers/hwmon/Kconfig +>> +++ b/drivers/hwmon/Kconfig +>> @@ -685,6 +685,21 @@ config SENSORS_LTC2945 +>> This driver can also be built as a module. If so, the module will +>> be called ltc2945. +>> +>> +config SENSORS_LTC2990 +>> + tristate "Linear Technology LTC2990 (current monitoring mode only)" +>> + depends on I2C +>> + select REGMAP_I2C +> +> Using regmap for the driver might be a good idea, but you don't. + +Looking at the regmap, the driver only writes the one cachable register +once, the "control". All the other registers cannot be cached, are +either read-only or write-only. Don't think regmap will help, so I'll +remove the "select" here. + +>> + default n +> +> Not necessary. +> +>> + help +>> + If you say yes here you get support for Linear Technology LTC2990 +>> + I2C System Monitor. The LTC2990 supports a combination of voltage, +>> + current and temperature monitoring, but this driver currently only +>> + supports reading two currents by measuring two differential +>> voltages +>> + across series resistors. +>> + +>> + This driver can also be built as a module. If so, the module will +>> + be called ltc2990. +>> + +>> config SENSORS_LTC4151 +>> tristate "Linear Technology LTC4151" +>> depends on I2C +>> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +>> index 12a3239..e4bd15b 100644 +>> --- a/drivers/hwmon/Makefile +>> +++ b/drivers/hwmon/Makefile +>> @@ -101,6 +101,7 @@ obj-$(CONFIG_SENSORS_LM95234) += lm95234.o +>> obj-$(CONFIG_SENSORS_LM95241) += lm95241.o +>> obj-$(CONFIG_SENSORS_LM95245) += lm95245.o +>> obj-$(CONFIG_SENSORS_LTC2945) += ltc2945.o +>> +obj-$(CONFIG_SENSORS_LTC2990) += ltc2990.o +>> obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o +>> obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o +>> obj-$(CONFIG_SENSORS_LTC4222) += ltc4222.o +>> diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c +>> new file mode 100644 +>> index 0000000..161d995 +>> --- /dev/null +>> +++ b/drivers/hwmon/ltc2990.c +>> @@ -0,0 +1,273 @@ +>> +/* +>> + * driver for Linear Technology LTC2990 power monitor +> +> Driver +> +>> + * +>> + * Copyright (C) 2014 Topic Embedded Products +> +> 2015 ? + +I wrote the driver early last year. I only did some cosmetic cleanup and +rebase on master before submitting. + +> +>> + * Author: Mike Looijmans <mike.looijmans@topic.nl> +>> + * +>> + * License: GPLv2 +>> + * +>> + * This driver assumes the chip is wired as a dual current monitor, and +>> + * reports the voltage drop across two series resistors. +> +> It also monitors the temperature and VCC. +> +>> + */ +>> + +>> +#include <linux/bug.h> +> +> Is this used anywhere in the driver ? + +Not any more... + +> +>> +#include <linux/delay.h> +>> +#include <linux/err.h> +>> +#include <linux/hwmon.h> +>> +#include <linux/hwmon-sysfs.h> +>> +#include <linux/i2c.h> +>> +#include <linux/kernel.h> +>> +#include <linux/module.h> +>> +#include <linux/slab.h> +>> + +>> +#define LTC2990_STATUS 0x00 +>> +#define LTC2990_CONTROL 0x01 +>> +#define LTC2990_TRIGGER 0x02 +>> +#define LTC2990_TINT_MSB 0x04 +>> +#define LTC2990_TINT_LSB 0x05 +>> +#define LTC2990_V1_MSB 0x06 +>> +#define LTC2990_V1_LSB 0x07 +>> +#define LTC2990_V2_MSB 0x08 +>> +#define LTC2990_V2_LSB 0x09 +>> +#define LTC2990_V3_MSB 0x0A +>> +#define LTC2990_V3_LSB 0x0B +>> +#define LTC2990_V4_MSB 0x0C +>> +#define LTC2990_V4_LSB 0x0D +>> +#define LTC2990_VCC_MSB 0x0E +>> +#define LTC2990_VCC_LSB 0x0F +>> + +>> +#define LTC2990_STATUS_BUSY BIT(0) +>> +#define LTC2990_STATUS_TINT BIT(1) +>> +#define LTC2990_STATUS_V1 BIT(2) +>> +#define LTC2990_STATUS_V2 BIT(3) +>> +#define LTC2990_STATUS_V3 BIT(4) +>> +#define LTC2990_STATUS_V4 BIT(5) +>> +#define LTC2990_STATUS_VCC BIT(6) +>> + +>> +/* Only define control settings we actually use */ +>> +#define LTC2990_CONTROL_KELVIN BIT(7) +>> +#define LTC2990_CONTROL_SINGLE BIT(6) +>> +#define LTC2990_CONTROL_MEASURE_ALL (0x3 << 3) +>> +#define LTC2990_CONTROL_MODE_CURRENT 0x06 +>> +#define LTC2990_CONTROL_MODE_VOLTAGE 0x07 +>> + +>> +struct ltc2990_data { +>> + struct device *hwmon_dev; +>> + struct mutex update_lock; +>> + unsigned long last_updated; +>> + short values[6]; +> +> u16 ? +> +>> + bool valid; +>> + u8 update_counter; +> +> Not used anywhere. +> +>> +}; +>> + +>> +static int ltc2990_write(struct i2c_client *i2c, u8 reg, u8 value) +>> +{ +>> + return i2c_smbus_write_byte_data(i2c, reg, value); +>> +} +>> + +>> +static int ltc2990_read_byte(struct i2c_client *i2c, u8 reg) +>> +{ +>> + return i2c_smbus_read_byte_data(i2c, reg); +>> +} +>> + +> +> Useless shim functions. + +True, should have removed them after refactoring them into one-liners. +They were convenient early on. + +> +>> +static int ltc2990_read_word(struct i2c_client *i2c, u8 reg) +>> +{ +>> + int result = i2c_smbus_read_word_data(i2c, reg); +>> + /* Result is MSB first, but smbus specs say LSB first, so swap the +>> + * result */ +> +> Bad multi-line comment. +> +>> + return result < 0 ? result : swab16(result); +> +> Please use i2c_smbus_read_word_swapped() and drop the shim function. +> +>> +} +>> + +>> +static struct ltc2990_data *ltc2990_update_device(struct device *dev) +>> +{ +>> + struct i2c_client *i2c = to_i2c_client(dev); +>> + struct ltc2990_data *data = i2c_get_clientdata(i2c); +>> + struct ltc2990_data *ret = data; +>> + unsigned int timeout; +>> + +>> + mutex_lock(&data->update_lock); +>> + +>> + /* Update about 4 times per second max */ +>> + if (time_after(jiffies, data->last_updated + HZ / 4) || +>> !data->valid) { +>> + int val; +>> + int i; +>> + +> +> Please consider using continuous conversion. This would simplify the +> code significantly +> and reduce read delays. + +It might increase power consumption though, as typically some user +program would poll this every 10 seconds or so. I'll check the data sheet. + +>> + /* Trigger ADC, any value will do */ +>> + val = ltc2990_write(i2c, LTC2990_TRIGGER, 1); +>> + if (unlikely(val < 0)) { +>> + ret = ERR_PTR(val); +>> + goto abort; +>> + } +>> + +>> + /* Wait for conversion complete */ +>> + timeout = 200; +>> + for (;;) { +>> + usleep_range(2000, 4000); +>> + val = ltc2990_read_byte(i2c, LTC2990_STATUS); +>> + if (unlikely(val < 0)) { +>> + ret = ERR_PTR(val); +>> + goto abort; +>> + } +>> + /* Single-shot mode, wait for conversion to complete */ +>> + if ((val & LTC2990_STATUS_BUSY) == 0) +> +> if (!(...)) +> +>> + break; +>> + if (--timeout == 0) { +>> + ret = ERR_PTR(-ETIMEDOUT); +>> + goto abort; +>> + } +>> + } +> +> Again, please consider using continuous conversion mode. +> +> If this is not feasible for some reason, you might as well just wait for +> the +> minimum conversion time before trying to read for the first time. If so, +> please use a fixed timeout by comparing the elapsed time instead of looping +> for a maximum number of times. Not even counting the time for executing the +> code, the maximum delay is between 400 ms and 800 ms, which is way too high +> (chip spec says 167 ms worst case, if three temperature sensors are +> configured). + +Or maybe I should just sleep for 167ms and be done with it. Though I +think I'l got with your minimal time first suggestion. + +>> + +>> + /* Read all registers */ +>> + for (i = 0; i < ARRAY_SIZE(data->values); ++i) { +>> + val = ltc2990_read_word(i2c, (i<<1) + LTC2990_TINT_MSB); +> +> Missing spaces around << +> +>> + if (unlikely(val < 0)) { +>> + dev_dbg(dev, +>> + "Failed to read ADC value: error %d\n", +>> + val); +>> + ret = ERR_PTR(val); +>> + goto abort; +>> + } +>> + data->values[i] = val & 0x7FFF; /* Strip 'new' bit */ +> +> The bit is never evaluated, so you might as well store the raw value. +> +>> + } +>> + data->last_updated = jiffies; +>> + data->valid = 1; +> +> = true; +> +>> + +>> + /* +>> + * Quirk: Second trigger is ignored? After this, the BUSY will +>> + * still be set to "0" and no conversion performed. +>> + */ +>> + val = ltc2990_write(i2c, LTC2990_TRIGGER, 0); +>> + } +>> +abort: +>> + mutex_unlock(&data->update_lock); +>> + return ret; +>> +} +>> + +>> +/* Return the converted value from the given register in uV or mC */ +>> +static int ltc2990_get_value(struct ltc2990_data *data, u8 index) +>> +{ +>> + s32 result; +>> + s16 v; +>> + +>> + if (index == 0) { /* internal temp, 0.0625 degrees/LSB, 12-bit */ +>> + v = data->values[index] << 3; +>> + result = (s32)v * 1000 >> 7; +>> + } else if (index < 5) { /* Vx-Vy, 19.42uV/LSB, 14-bit */ +>> + v = data->values[index] << 2; +> +> Datasheet says that the sign bit is in bit 14, so this drops the sign bit. + +I'll check the data sheet, would not have noticed this since current +doesn't tend to run from the CPU back into the battery :) + +>> + result = (s32)v * 1942 / (4 * 100); +>> + } else { /* Vcc, 305.18μV/LSB, 2.5V offset, 14-bit */ +>> + v = data->values[index] << 2; +>> + result = (s32)v * 30518 / (4 * 100); +>> + result += 2500000; +>> + } +>> + return result; +>> +} +>> + +>> +static ssize_t ltc2990_show_value(struct device *dev, +>> + struct device_attribute *da, char *buf) +>> +{ +>> + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); +>> + struct ltc2990_data *data = ltc2990_update_device(dev); +>> + int value; +>> + +>> + if (IS_ERR(data)) +>> + return PTR_ERR(data); +>> + +>> + value = ltc2990_get_value(data, attr->index); +>> + return snprintf(buf, PAGE_SIZE, "%d\n", value); +>> +} +>> + +>> +static SENSOR_DEVICE_ATTR(temp_int, S_IRUGO, ltc2990_show_value, +>> NULL, 0); +>> +static SENSOR_DEVICE_ATTR(v1v2_diff, S_IRUGO, ltc2990_show_value, +>> NULL, 1); +>> +static SENSOR_DEVICE_ATTR(v3v4_diff, S_IRUGO, ltc2990_show_value, +>> NULL, 3); +>> +static SENSOR_DEVICE_ATTR(vcc, S_IRUGO, ltc2990_show_value, NULL, 5); +>> + +> +> Please use standard attribute names (and units) as per +> Documentation/hwmon/sysfs-interface. +> +>> +static struct attribute *ltc2990_attributes[] = { +>> + &sensor_dev_attr_temp_int.dev_attr.attr, +>> + &sensor_dev_attr_v1v2_diff.dev_attr.attr, +>> + &sensor_dev_attr_v3v4_diff.dev_attr.attr, +>> + &sensor_dev_attr_vcc.dev_attr.attr, +>> + NULL, +>> +}; +>> + +>> +static const struct attribute_group ltc2990_group = { +>> + .attrs = ltc2990_attributes, +>> +}; +>> + +> +> Please use the ATTRIBUTE_GROUPS() macro. Also see below. + +Okay, will RTFM. + +> +>> +static int ltc2990_i2c_probe( +>> + struct i2c_client *i2c, const struct i2c_device_id *id) +> +> Please split as +> +> static int ltc2990_i2c_probe(struct i2c_client *i2c, +> const struct i2c_device_id *id) +> +>> +{ +>> + int ret; +>> + struct ltc2990_data *ltc2990; +>> + +>> + if (!i2c_check_functionality(i2c->adapter, +>> I2C_FUNC_SMBUS_BYTE_DATA)) +>> + return -ENODEV; +>> + +>> + ltc2990 = devm_kzalloc(&i2c->dev, +>> + sizeof(struct ltc2990_data), GFP_KERNEL); +> +> Please align continuation lines with '('. +> +>> + if (ltc2990 == NULL) +>> + return -ENOMEM; +>> + +>> + ret = ltc2990_read_byte(i2c, 0); +>> + if (ret < 0) { +>> + dev_err(&i2c->dev, "Could not read LTC2990 on i2c bus.\n"); +>> + return ret; +>> + } +> +> The write below would also return an error if the chip isn't there, +> so this additional read does not provide any real value. +> +>> + ret = ltc2990_write(i2c, LTC2990_CONTROL, +>> + LTC2990_CONTROL_SINGLE | LTC2990_CONTROL_MEASURE_ALL | +>> + LTC2990_CONTROL_MODE_CURRENT); +> +> I'll have to think about this. While it addresses your use case, +> it limits the scope of this driver significantly. Looking into the board +> specifications, you might as well do it right and determine (and set) +> the correct configuration using devicetree data instead of forcing your +> use case on everyone. +> +> Sure, you may argue that you don't care, but we will be the ones who +> will have +> to handle error reports that the driver unexpectedly changes the +> configuration +> in other use cases (where, for example, the mode may have been pre-set by +> the BIOS or ROMMON). + +The reason I didn't submit the driver last year was that I was still +thinking about it. On the other hand, a limited driver is still much +better than no driver at all, so that made me post it, with the added +remarks about the driver being limited. + +Adding the other functions it quite a bit more work than just writing +this register. It also changes the properties to be exported to sysfs, +and the calculation of the end values. + +> +>> + if (ret < 0) { +>> + dev_err(&i2c->dev, "Error: Failed to set control mode.\n"); +>> + return ret; +>> + } +>> + +>> + mutex_init(<c2990->update_lock); +>> + i2c_set_clientdata(i2c, ltc2990); +>> + +>> + /* Register sysfs hooks */ +>> + ret = sysfs_create_group(&i2c->dev.kobj, <c2990_group); +>> + if (ret) +>> + return ret; +>> + +>> + ltc2990->hwmon_dev = hwmon_device_register(&i2c->dev); +> +> Please use devm_hwmon_device_register_with_groups(). +> +>> + if (IS_ERR(ltc2990->hwmon_dev)) { +>> + ret = PTR_ERR(ltc2990->hwmon_dev); +>> + goto out_hwmon_device_register; +>> + } +>> + +>> + return 0; +>> + +>> +out_hwmon_device_register: +>> + sysfs_remove_group(&i2c->dev.kobj, <c2990_group); +>> + return ret; +>> +} +>> + +>> +static int ltc2990_i2c_remove(struct i2c_client *i2c) +>> +{ +>> + struct ltc2990_data *ltc2990 = i2c_get_clientdata(i2c); +>> + +>> + hwmon_device_unregister(ltc2990->hwmon_dev); +>> + sysfs_remove_group(&i2c->dev.kobj, <c2990_group); +>> + return 0; +>> +} +>> + +>> +static const struct i2c_device_id ltc2990_i2c_id[] = { +>> + { "ltc2990", 0 }, +>> + {} +>> +}; +>> +MODULE_DEVICE_TABLE(i2c, ltc2990_i2c_id); +>> + +>> +static struct i2c_driver ltc2990_i2c_driver = { +>> + .driver = { +>> + .name = "ltc2990", +>> + }, +>> + .probe = ltc2990_i2c_probe, +>> + .remove = ltc2990_i2c_remove, +>> + .id_table = ltc2990_i2c_id, +>> +}; +>> + +>> +module_i2c_driver(ltc2990_i2c_driver); +>> + +>> +MODULE_DESCRIPTION("LTC2990 Sensor Driver"); +>> +MODULE_AUTHOR("Topic Embedded Products"); +>> +MODULE_LICENSE("GPL v2"); +>> +> + + +-- +Mike Looijmans diff --git a/a/content_digest b/N1/content_digest index fdf3626..a73dd89 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -1,296 +1,521 @@ "ref\01452067627-24939-1-git-send-email-mike.looijmans@topic.nl\0" "ref\0568D3127.5090901@roeck-us.net\0" "From\0Mike Looijmans <mike.looijmans@topic.nl>\0" - "Subject\0Re: [lm-sensors] [PATCH] hwmon: Add LTC2990 sensor driver\0" - "Date\0Thu, 07 Jan 2016 18:59:24 +0000\0" + "Subject\0Re: [PATCH] hwmon: Add LTC2990 sensor driver\0" + "Date\0Thu, 7 Jan 2016 19:59:24 +0100\0" "To\0Guenter Roeck <linux@roeck-us.net>" " lm-sensors@lm-sensors.org\0" "Cc\0jdelvare@suse.com" " linux-kernel@vger.kernel.org\0" "\00:1\0" "b\0" - "VGhhbmsgeW91IHZlcnkgbXVjaCBmb3IgeW91ciByZXZpZXcgY29tbWVudHMsIEknbGwgdXBkYXRl\n" - "IHRoZSBkcml2ZXIgYW5kIApwb3N0IGEgdjIgcGF0Y2guCgpJbmxpbmVkIHNvbWUgcmVwbGllcyBi\n" - "ZWxvdy4gQXNzdW1lIHRoYXQgSSAid2lsbCBkbyIgZm9yIGFsbCBjb21tZW50cyBJIApkaWRuJ3Qg\n" - "Y29tbWVudCBvbiBpbmxpbmUuLi4KCk9uIDA2LTAxLTE2IDE2OjIyLCBHdWVudGVyIFJvZWNrIHdy\n" - "b3RlOgo+IEhlbGxvIE1pa2UsCj4KPiBPbiAwMS8wNi8yMDE2IDEyOjA3IEFNLCBNaWtlIExvb2lq\n" - "bWFucyB3cm90ZToKPj4gVGhpcyBhZGRzIHN1cHBvcnQgZm9yIHRoZSBMaW5lYXIgVGVjaG5vbG9n\n" - "eSBMVEMyOTkwICBJMkMgU3lzdGVtIE1vbml0b3IuCj4KPiBzLyAgLyAvCj4KPj4gVGhlIExUQzI5\n" - "OTAgc3VwcG9ydHMgYSBjb21iaW5hdGlvbiBvZiB2b2x0YWdlLCBjdXJyZW50IGFuZCB0ZW1wZXJh\n" - "dHVyZQo+PiBtb25pdG9yaW5nLCBidXQgdGhpcyBkcml2ZXIgY3VycmVudGx5IG9ubHkgc3VwcG9y\n" - "dHMgcmVhZGluZyB0d28gY3VycmVudHMKPj4gYnkgbWVhc3VyaW5nIHR3byBkaWZmZXJlbnRpYWwg\n" - "dm9sdGFnZXMgYWNyb3NzIHNlcmllcyByZXNpc3RvcnMuCj4+Cj4gUGx1cyBWQ0MsIHBsdXMgdGhl\n" - "IGludGVybmFsIHRlbXBlcmF0dXJlLgoKWWVhaCwgSSBzaG91bGQgZ2l2ZSBteXNlbGYgbW9yZSBj\n" - "cmVkaXQgOikgSSdsbCBhZGQgdGhhdCBpbiBLY29uZmlnIHRvby4KCj4+IFRoaXMgaXMgc3VmZmlj\n" - "aWVudCB0byBzdXBwb3J0IHRoZSBUb3BpYyBNaWFtaSBTT00gd2hpY2ggdXNlcyB0aGlzIGNoaXAK\n" - "Pj4gdG8gbW9uaXRvciB0aGUgY3VycmVudHMgZmxvd2luZyBpbnRvIHRoZSBGUEdBIGFuZCB0aGUg\n" - "Q1BVIHBhcnRzLgo+Pgo+PiBTaWduZWQtb2ZmLWJ5OiBNaWtlIExvb2lqbWFucyA8bWlrZS5sb29p\n" - "am1hbnNAdG9waWMubmw+Cj4+IC0tLQo+PiAgIGRyaXZlcnMvaHdtb24vS2NvbmZpZyAgIHwgIDE1\n" - "ICsrKwo+PiAgIGRyaXZlcnMvaHdtb24vTWFrZWZpbGUgIHwgICAxICsKPj4gICBkcml2ZXJzL2h3\n" - "bW9uL2x0YzI5OTAuYyB8IDI3Mwo+PiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr\n" - "KysrKysrKysrKysrKysKPgo+IFBsZWFzZSBhbHNvIHByb3ZpZGUgRG9jdW1lbnRhdGlvbi9od21v\n" - "bi9sdGMyOTkwLgo+Cj4gQWxzbywgcGxlYXNlIHJlYWQgYW5kIGZvbGxvdyBEb2N1bWVudGF0aW9u\n" - "L2h3bW9uL3N1Ym1pdHRpbmctcGF0Y2hlcy4KPgo+PiAgIDMgZmlsZXMgY2hhbmdlZCwgMjg5IGlu\n" - "c2VydGlvbnMoKykKPj4gICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9od21vbi9sdGMyOTkw\n" - "LmMKPj4KPj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvaHdtb24vS2NvbmZpZyBiL2RyaXZlcnMvaHdt\n" - "b24vS2NvbmZpZwo+PiBpbmRleCA4MGE3M2JmLi5iM2VlZjMxIDEwMDY0NAo+PiAtLS0gYS9kcml2\n" - "ZXJzL2h3bW9uL0tjb25maWcKPj4gKysrIGIvZHJpdmVycy9od21vbi9LY29uZmlnCj4+IEBAIC02\n" - "ODUsNiArNjg1LDIxIEBAIGNvbmZpZyBTRU5TT1JTX0xUQzI5NDUKPj4gICAgICAgICBUaGlzIGRy\n" - "aXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1vZHVsZS4gSWYgc28sIHRoZSBtb2R1bGUgd2ls\n" - "bAo+PiAgICAgICAgIGJlIGNhbGxlZCBsdGMyOTQ1Lgo+Pgo+PiArY29uZmlnIFNFTlNPUlNfTFRD\n" - "Mjk5MAo+PiArICAgIHRyaXN0YXRlICJMaW5lYXIgVGVjaG5vbG9neSBMVEMyOTkwIChjdXJyZW50\n" - "IG1vbml0b3JpbmcgbW9kZSBvbmx5KSIKPj4gKyAgICBkZXBlbmRzIG9uIEkyQwo+PiArICAgIHNl\n" - "bGVjdCBSRUdNQVBfSTJDCj4KPiBVc2luZyByZWdtYXAgZm9yIHRoZSBkcml2ZXIgbWlnaHQgYmUg\n" - "YSBnb29kIGlkZWEsIGJ1dCB5b3UgZG9uJ3QuCgpMb29raW5nIGF0IHRoZSByZWdtYXAsIHRoZSBk\n" - "cml2ZXIgb25seSB3cml0ZXMgdGhlIG9uZSBjYWNoYWJsZSByZWdpc3RlciAKb25jZSwgdGhlICJj\n" - "b250cm9sIi4gQWxsIHRoZSBvdGhlciByZWdpc3RlcnMgY2Fubm90IGJlIGNhY2hlZCwgYXJlIApl\n" - "aXRoZXIgcmVhZC1vbmx5IG9yIHdyaXRlLW9ubHkuIERvbid0IHRoaW5rIHJlZ21hcCB3aWxsIGhl\n" - "bHAsIHNvIEknbGwgCnJlbW92ZSB0aGUgInNlbGVjdCIgaGVyZS4KCj4+ICsgICAgZGVmYXVsdCBu\n" - "Cj4KPiBOb3QgbmVjZXNzYXJ5Lgo+Cj4+ICsgICAgaGVscAo+PiArICAgICAgSWYgeW91IHNheSB5\n" - "ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIExpbmVhciBUZWNobm9sb2d5IExUQzI5OTAKPj4g\n" - "KyAgICAgIEkyQyBTeXN0ZW0gTW9uaXRvci4gVGhlIExUQzI5OTAgc3VwcG9ydHMgYSBjb21iaW5h\n" - "dGlvbiBvZiB2b2x0YWdlLAo+PiArICAgICAgY3VycmVudCBhbmQgdGVtcGVyYXR1cmUgbW9uaXRv\n" - "cmluZywgYnV0IHRoaXMgZHJpdmVyIGN1cnJlbnRseSBvbmx5Cj4+ICsgICAgICBzdXBwb3J0cyBy\n" - "ZWFkaW5nIHR3byBjdXJyZW50cyBieSBtZWFzdXJpbmcgdHdvIGRpZmZlcmVudGlhbAo+PiB2b2x0\n" - "YWdlcwo+PiArICAgICAgYWNyb3NzIHNlcmllcyByZXNpc3RvcnMuCj4+ICsKPj4gKyAgICAgIFRo\n" - "aXMgZHJpdmVyIGNhbiBhbHNvIGJlIGJ1aWx0IGFzIGEgbW9kdWxlLiBJZiBzbywgdGhlIG1vZHVs\n" - "ZSB3aWxsCj4+ICsgICAgICBiZSBjYWxsZWQgbHRjMjk5MC4KPj4gKwo+PiAgIGNvbmZpZyBTRU5T\n" - "T1JTX0xUQzQxNTEKPj4gICAgICAgdHJpc3RhdGUgIkxpbmVhciBUZWNobm9sb2d5IExUQzQxNTEi\n" - "Cj4+ICAgICAgIGRlcGVuZHMgb24gSTJDCj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2h3bW9uL01h\n" - "a2VmaWxlIGIvZHJpdmVycy9od21vbi9NYWtlZmlsZQo+PiBpbmRleCAxMmEzMjM5Li5lNGJkMTVi\n" - "IDEwMDY0NAo+PiAtLS0gYS9kcml2ZXJzL2h3bW9uL01ha2VmaWxlCj4+ICsrKyBiL2RyaXZlcnMv\n" - "aHdtb24vTWFrZWZpbGUKPj4gQEAgLTEwMSw2ICsxMDEsNyBAQCBvYmotJChDT05GSUdfU0VOU09S\n" - "U19MTTk1MjM0KSAgICArPSBsbTk1MjM0Lm8KPj4gICBvYmotJChDT05GSUdfU0VOU09SU19MTTk1\n" - "MjQxKSAgICArPSBsbTk1MjQxLm8KPj4gICBvYmotJChDT05GSUdfU0VOU09SU19MTTk1MjQ1KSAg\n" - "ICArPSBsbTk1MjQ1Lm8KPj4gICBvYmotJChDT05GSUdfU0VOU09SU19MVEMyOTQ1KSAgICArPSBs\n" - "dGMyOTQ1Lm8KPj4gK29iai0kKENPTkZJR19TRU5TT1JTX0xUQzI5OTApICAgICs9IGx0YzI5OTAu\n" - "bwo+PiAgIG9iai0kKENPTkZJR19TRU5TT1JTX0xUQzQxNTEpICAgICs9IGx0YzQxNTEubwo+PiAg\n" - "IG9iai0kKENPTkZJR19TRU5TT1JTX0xUQzQyMTUpICAgICs9IGx0YzQyMTUubwo+PiAgIG9iai0k\n" - "KENPTkZJR19TRU5TT1JTX0xUQzQyMjIpICAgICs9IGx0YzQyMjIubwo+PiBkaWZmIC0tZ2l0IGEv\n" - "ZHJpdmVycy9od21vbi9sdGMyOTkwLmMgYi9kcml2ZXJzL2h3bW9uL2x0YzI5OTAuYwo+PiBuZXcg\n" - "ZmlsZSBtb2RlIDEwMDY0NAo+PiBpbmRleCAwMDAwMDAwLi4xNjFkOTk1Cj4+IC0tLSAvZGV2L251\n" - "bGwKPj4gKysrIGIvZHJpdmVycy9od21vbi9sdGMyOTkwLmMKPj4gQEAgLTAsMCArMSwyNzMgQEAK\n" - "Pj4gKy8qCj4+ICsgKiBkcml2ZXIgZm9yIExpbmVhciBUZWNobm9sb2d5IExUQzI5OTAgcG93ZXIg\n" - "bW9uaXRvcgo+Cj4gRHJpdmVyCj4KPj4gKyAqCj4+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMTQgVG9w\n" - "aWMgRW1iZWRkZWQgUHJvZHVjdHMKPgo+IDIwMTUgPwoKSSB3cm90ZSB0aGUgZHJpdmVyIGVhcmx5\n" - "IGxhc3QgeWVhci4gSSBvbmx5IGRpZCBzb21lIGNvc21ldGljIGNsZWFudXAgYW5kIApyZWJhc2Ug\n" - "b24gbWFzdGVyIGJlZm9yZSBzdWJtaXR0aW5nLgoKPgo+PiArICogQXV0aG9yOiBNaWtlIExvb2lq\n" - "bWFucyA8bWlrZS5sb29pam1hbnNAdG9waWMubmw+Cj4+ICsgKgo+PiArICogTGljZW5zZTogR1BM\n" - "djIKPj4gKyAqCj4+ICsgKiBUaGlzIGRyaXZlciBhc3N1bWVzIHRoZSBjaGlwIGlzIHdpcmVkIGFz\n" - "IGEgZHVhbCBjdXJyZW50IG1vbml0b3IsIGFuZAo+PiArICogcmVwb3J0cyB0aGUgdm9sdGFnZSBk\n" - "cm9wIGFjcm9zcyB0d28gc2VyaWVzIHJlc2lzdG9ycy4KPgo+IEl0IGFsc28gbW9uaXRvcnMgdGhl\n" - "IHRlbXBlcmF0dXJlIGFuZCBWQ0MuCj4KPj4gKyAqLwo+PiArCj4+ICsjaW5jbHVkZSA8bGludXgv\n" - "YnVnLmg+Cj4KPiBJcyB0aGlzIHVzZWQgYW55d2hlcmUgaW4gdGhlIGRyaXZlciA/CgpOb3QgYW55\n" - "IG1vcmUuLi4KCj4KPj4gKyNpbmNsdWRlIDxsaW51eC9kZWxheS5oPgo+PiArI2luY2x1ZGUgPGxp\n" - "bnV4L2Vyci5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2h3bW9uLmg+Cj4+ICsjaW5jbHVkZSA8bGlu\n" - "dXgvaHdtb24tc3lzZnMuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9pMmMuaD4KPj4gKyNpbmNsdWRl\n" - "IDxsaW51eC9rZXJuZWwuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KPj4gKyNpbmNs\n" - "dWRlIDxsaW51eC9zbGFiLmg+Cj4+ICsKPj4gKyNkZWZpbmUgTFRDMjk5MF9TVEFUVVMgICAgMHgw\n" - "MAo+PiArI2RlZmluZSBMVEMyOTkwX0NPTlRST0wgICAgMHgwMQo+PiArI2RlZmluZSBMVEMyOTkw\n" - "X1RSSUdHRVIgICAgMHgwMgo+PiArI2RlZmluZSBMVEMyOTkwX1RJTlRfTVNCICAgIDB4MDQKPj4g\n" - "KyNkZWZpbmUgTFRDMjk5MF9USU5UX0xTQiAgICAweDA1Cj4+ICsjZGVmaW5lIExUQzI5OTBfVjFf\n" - "TVNCICAgIDB4MDYKPj4gKyNkZWZpbmUgTFRDMjk5MF9WMV9MU0IgICAgMHgwNwo+PiArI2RlZmlu\n" - "ZSBMVEMyOTkwX1YyX01TQiAgICAweDA4Cj4+ICsjZGVmaW5lIExUQzI5OTBfVjJfTFNCICAgIDB4\n" - "MDkKPj4gKyNkZWZpbmUgTFRDMjk5MF9WM19NU0IgICAgMHgwQQo+PiArI2RlZmluZSBMVEMyOTkw\n" - "X1YzX0xTQiAgICAweDBCCj4+ICsjZGVmaW5lIExUQzI5OTBfVjRfTVNCICAgIDB4MEMKPj4gKyNk\n" - "ZWZpbmUgTFRDMjk5MF9WNF9MU0IgICAgMHgwRAo+PiArI2RlZmluZSBMVEMyOTkwX1ZDQ19NU0Ig\n" - "ICAgMHgwRQo+PiArI2RlZmluZSBMVEMyOTkwX1ZDQ19MU0IgICAgMHgwRgo+PiArCj4+ICsjZGVm\n" - "aW5lIExUQzI5OTBfU1RBVFVTX0JVU1kgICAgQklUKDApCj4+ICsjZGVmaW5lIExUQzI5OTBfU1RB\n" - "VFVTX1RJTlQgICAgQklUKDEpCj4+ICsjZGVmaW5lIExUQzI5OTBfU1RBVFVTX1YxICAgIEJJVCgy\n" - "KQo+PiArI2RlZmluZSBMVEMyOTkwX1NUQVRVU19WMiAgICBCSVQoMykKPj4gKyNkZWZpbmUgTFRD\n" - "Mjk5MF9TVEFUVVNfVjMgICAgQklUKDQpCj4+ICsjZGVmaW5lIExUQzI5OTBfU1RBVFVTX1Y0ICAg\n" - "IEJJVCg1KQo+PiArI2RlZmluZSBMVEMyOTkwX1NUQVRVU19WQ0MgICAgQklUKDYpCj4+ICsKPj4g\n" - "Ky8qIE9ubHkgZGVmaW5lIGNvbnRyb2wgc2V0dGluZ3Mgd2UgYWN0dWFsbHkgdXNlICovCj4+ICsj\n" - "ZGVmaW5lIExUQzI5OTBfQ09OVFJPTF9LRUxWSU4gICAgICAgIEJJVCg3KQo+PiArI2RlZmluZSBM\n" - "VEMyOTkwX0NPTlRST0xfU0lOR0xFICAgICAgICBCSVQoNikKPj4gKyNkZWZpbmUgTFRDMjk5MF9D\n" - "T05UUk9MX01FQVNVUkVfQUxMICAgICgweDMgPDwgMykKPj4gKyNkZWZpbmUgTFRDMjk5MF9DT05U\n" - "Uk9MX01PREVfQ1VSUkVOVCAgICAweDA2Cj4+ICsjZGVmaW5lIExUQzI5OTBfQ09OVFJPTF9NT0RF\n" - "X1ZPTFRBR0UgICAgMHgwNwo+PiArCj4+ICtzdHJ1Y3QgbHRjMjk5MF9kYXRhIHsKPj4gKyAgICBz\n" - "dHJ1Y3QgZGV2aWNlICpod21vbl9kZXY7Cj4+ICsgICAgc3RydWN0IG11dGV4IHVwZGF0ZV9sb2Nr\n" - "Owo+PiArICAgIHVuc2lnbmVkIGxvbmcgbGFzdF91cGRhdGVkOwo+PiArICAgIHNob3J0IHZhbHVl\n" - "c1s2XTsKPgo+IHUxNiA/Cj4KPj4gKyAgICBib29sIHZhbGlkOwo+PiArICAgIHU4IHVwZGF0ZV9j\n" - "b3VudGVyOwo+Cj4gTm90IHVzZWQgYW55d2hlcmUuCj4KPj4gK307Cj4+ICsKPj4gK3N0YXRpYyBp\n" - "bnQgbHRjMjk5MF93cml0ZShzdHJ1Y3QgaTJjX2NsaWVudCAqaTJjLCB1OCByZWcsIHU4IHZhbHVl\n" - "KQo+PiArewo+PiArICAgIHJldHVybiBpMmNfc21idXNfd3JpdGVfYnl0ZV9kYXRhKGkyYywgcmVn\n" - "LCB2YWx1ZSk7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBpbnQgbHRjMjk5MF9yZWFkX2J5dGUoc3Ry\n" - "dWN0IGkyY19jbGllbnQgKmkyYywgdTggcmVnKQo+PiArewo+PiArICAgIHJldHVybiBpMmNfc21i\n" - "dXNfcmVhZF9ieXRlX2RhdGEoaTJjLCByZWcpOwo+PiArfQo+PiArCj4KPiBVc2VsZXNzIHNoaW0g\n" - "ZnVuY3Rpb25zLgoKVHJ1ZSwgc2hvdWxkIGhhdmUgcmVtb3ZlZCB0aGVtIGFmdGVyIHJlZmFjdG9y\n" - "aW5nIHRoZW0gaW50byBvbmUtbGluZXJzLgpUaGV5IHdlcmUgY29udmVuaWVudCBlYXJseSBvbi4K\n" - "Cj4KPj4gK3N0YXRpYyBpbnQgbHRjMjk5MF9yZWFkX3dvcmQoc3RydWN0IGkyY19jbGllbnQgKmky\n" - "YywgdTggcmVnKQo+PiArewo+PiArICAgIGludCByZXN1bHQgPSBpMmNfc21idXNfcmVhZF93b3Jk\n" - "X2RhdGEoaTJjLCByZWcpOwo+PiArICAgIC8qIFJlc3VsdCBpcyBNU0IgZmlyc3QsIGJ1dCBzbWJ1\n" - "cyBzcGVjcyBzYXkgTFNCIGZpcnN0LCBzbyBzd2FwIHRoZQo+PiArICAgICAqIHJlc3VsdCAqLwo+\n" - "Cj4gQmFkIG11bHRpLWxpbmUgY29tbWVudC4KPgo+PiArICAgIHJldHVybiByZXN1bHQgPCAwID8g\n" - "cmVzdWx0IDogc3dhYjE2KHJlc3VsdCk7Cj4KPiBQbGVhc2UgdXNlIGkyY19zbWJ1c19yZWFkX3dv\n" - "cmRfc3dhcHBlZCgpIGFuZCBkcm9wIHRoZSBzaGltIGZ1bmN0aW9uLgo+Cj4+ICt9Cj4+ICsKPj4g\n" - "K3N0YXRpYyBzdHJ1Y3QgbHRjMjk5MF9kYXRhICpsdGMyOTkwX3VwZGF0ZV9kZXZpY2Uoc3RydWN0\n" - "IGRldmljZSAqZGV2KQo+PiArewo+PiArICAgIHN0cnVjdCBpMmNfY2xpZW50ICppMmMgPSB0b19p\n" - "MmNfY2xpZW50KGRldik7Cj4+ICsgICAgc3RydWN0IGx0YzI5OTBfZGF0YSAqZGF0YSA9IGkyY19n\n" - "ZXRfY2xpZW50ZGF0YShpMmMpOwo+PiArICAgIHN0cnVjdCBsdGMyOTkwX2RhdGEgKnJldCA9IGRh\n" - "dGE7Cj4+ICsgICAgdW5zaWduZWQgaW50IHRpbWVvdXQ7Cj4+ICsKPj4gKyAgICBtdXRleF9sb2Nr\n" - "KCZkYXRhLT51cGRhdGVfbG9jayk7Cj4+ICsKPj4gKyAgICAvKiBVcGRhdGUgYWJvdXQgNCB0aW1l\n" - "cyBwZXIgc2Vjb25kIG1heCAqLwo+PiArICAgIGlmICh0aW1lX2FmdGVyKGppZmZpZXMsIGRhdGEt\n" - "Pmxhc3RfdXBkYXRlZCArIEhaIC8gNCkgfHwKPj4gIWRhdGEtPnZhbGlkKSB7Cj4+ICsgICAgICAg\n" - "IGludCB2YWw7Cj4+ICsgICAgICAgIGludCBpOwo+PiArCj4KPiBQbGVhc2UgY29uc2lkZXIgdXNp\n" - "bmcgY29udGludW91cyBjb252ZXJzaW9uLiBUaGlzIHdvdWxkIHNpbXBsaWZ5IHRoZQo+IGNvZGUg\n" - "c2lnbmlmaWNhbnRseQo+IGFuZCByZWR1Y2UgcmVhZCBkZWxheXMuCgpJdCBtaWdodCBpbmNyZWFz\n" - "ZSBwb3dlciBjb25zdW1wdGlvbiB0aG91Z2gsIGFzIHR5cGljYWxseSBzb21lIHVzZXIgCnByb2dy\n" - "YW0gd291bGQgcG9sbCB0aGlzIGV2ZXJ5IDEwIHNlY29uZHMgb3Igc28uIEknbGwgY2hlY2sgdGhl\n" - "IGRhdGEgc2hlZXQuCgo+PiArICAgICAgICAvKiBUcmlnZ2VyIEFEQywgYW55IHZhbHVlIHdpbGwg\n" - "ZG8gKi8KPj4gKyAgICAgICAgdmFsID0gbHRjMjk5MF93cml0ZShpMmMsIExUQzI5OTBfVFJJR0dF\n" - "UiwgMSk7Cj4+ICsgICAgICAgIGlmICh1bmxpa2VseSh2YWwgPCAwKSkgewo+PiArICAgICAgICAg\n" - "ICAgcmV0ID0gRVJSX1BUUih2YWwpOwo+PiArICAgICAgICAgICAgZ290byBhYm9ydDsKPj4gKyAg\n" - "ICAgICAgfQo+PiArCj4+ICsgICAgICAgIC8qIFdhaXQgZm9yIGNvbnZlcnNpb24gY29tcGxldGUg\n" - "Ki8KPj4gKyAgICAgICAgdGltZW91dCA9IDIwMDsKPj4gKyAgICAgICAgZm9yICg7Oykgewo+PiAr\n" - "ICAgICAgICAgICAgdXNsZWVwX3JhbmdlKDIwMDAsIDQwMDApOwo+PiArICAgICAgICAgICAgdmFs\n" - "ID0gbHRjMjk5MF9yZWFkX2J5dGUoaTJjLCBMVEMyOTkwX1NUQVRVUyk7Cj4+ICsgICAgICAgICAg\n" - "ICBpZiAodW5saWtlbHkodmFsIDwgMCkpIHsKPj4gKyAgICAgICAgICAgICAgICByZXQgPSBFUlJf\n" - "UFRSKHZhbCk7Cj4+ICsgICAgICAgICAgICAgICAgZ290byBhYm9ydDsKPj4gKyAgICAgICAgICAg\n" - "IH0KPj4gKyAgICAgICAgICAgIC8qIFNpbmdsZS1zaG90IG1vZGUsIHdhaXQgZm9yIGNvbnZlcnNp\n" - "b24gdG8gY29tcGxldGUgKi8KPj4gKyAgICAgICAgICAgIGlmICgodmFsICYgTFRDMjk5MF9TVEFU\n" - "VVNfQlVTWSkgPT0gMCkKPgo+ICAgICAgICAgICAgICBpZiAoISguLi4pKQo+Cj4+ICsgICAgICAg\n" - "ICAgICAgICAgYnJlYWs7Cj4+ICsgICAgICAgICAgICBpZiAoLS10aW1lb3V0ID09IDApIHsKPj4g\n" - "KyAgICAgICAgICAgICAgICByZXQgPSBFUlJfUFRSKC1FVElNRURPVVQpOwo+PiArICAgICAgICAg\n" - "ICAgICAgIGdvdG8gYWJvcnQ7Cj4+ICsgICAgICAgICAgICB9Cj4+ICsgICAgICAgIH0KPgo+IEFn\n" - "YWluLCBwbGVhc2UgY29uc2lkZXIgdXNpbmcgY29udGludW91cyBjb252ZXJzaW9uIG1vZGUuCj4K\n" - "PiBJZiB0aGlzIGlzIG5vdCBmZWFzaWJsZSBmb3Igc29tZSByZWFzb24sIHlvdSBtaWdodCBhcyB3\n" - "ZWxsIGp1c3Qgd2FpdCBmb3IKPiB0aGUKPiBtaW5pbXVtIGNvbnZlcnNpb24gdGltZSBiZWZvcmUg\n" - "dHJ5aW5nIHRvIHJlYWQgZm9yIHRoZSBmaXJzdCB0aW1lLiBJZiBzbywKPiBwbGVhc2UgdXNlIGEg\n" - "Zml4ZWQgdGltZW91dCBieSBjb21wYXJpbmcgdGhlIGVsYXBzZWQgdGltZSBpbnN0ZWFkIG9mIGxv\n" - "b3BpbmcKPiBmb3IgYSBtYXhpbXVtIG51bWJlciBvZiB0aW1lcy4gTm90IGV2ZW4gY291bnRpbmcg\n" - "dGhlIHRpbWUgZm9yIGV4ZWN1dGluZyB0aGUKPiBjb2RlLCB0aGUgbWF4aW11bSBkZWxheSBpcyBi\n" - "ZXR3ZWVuIDQwMCBtcyBhbmQgODAwIG1zLCB3aGljaCBpcyB3YXkgdG9vIGhpZ2gKPiAoY2hpcCBz\n" - "cGVjIHNheXMgMTY3IG1zIHdvcnN0IGNhc2UsIGlmIHRocmVlIHRlbXBlcmF0dXJlIHNlbnNvcnMg\n" - "YXJlCj4gY29uZmlndXJlZCkuCgpPciBtYXliZSBJIHNob3VsZCBqdXN0IHNsZWVwIGZvciAxNjdt\n" - "cyBhbmQgYmUgZG9uZSB3aXRoIGl0LiBUaG91Z2ggSSAKdGhpbmsgSSdsIGdvdCB3aXRoIHlvdXIg\n" - "bWluaW1hbCB0aW1lIGZpcnN0IHN1Z2dlc3Rpb24uCgo+PiArCj4+ICsgICAgICAgIC8qIFJlYWQg\n" - "YWxsIHJlZ2lzdGVycyAqLwo+PiArICAgICAgICBmb3IgKGkgPSAwOyBpIDwgQVJSQVlfU0laRShk\n" - "YXRhLT52YWx1ZXMpOyArK2kpIHsKPj4gKyAgICAgICAgICAgIHZhbCA9IGx0YzI5OTBfcmVhZF93\n" - "b3JkKGkyYywgKGk8PDEpICsgTFRDMjk5MF9USU5UX01TQik7Cj4KPiBNaXNzaW5nIHNwYWNlcyBh\n" - "cm91bmQgPDwKPgo+PiArICAgICAgICAgICAgaWYgKHVubGlrZWx5KHZhbCA8IDApKSB7Cj4+ICsg\n" - "ICAgICAgICAgICAgICAgZGV2X2RiZyhkZXYsCj4+ICsgICAgICAgICAgICAgICAgICAgICJGYWls\n" - "ZWQgdG8gcmVhZCBBREMgdmFsdWU6IGVycm9yICVkXG4iLAo+PiArICAgICAgICAgICAgICAgICAg\n" - "ICB2YWwpOwo+PiArICAgICAgICAgICAgICAgIHJldCA9IEVSUl9QVFIodmFsKTsKPj4gKyAgICAg\n" - "ICAgICAgICAgICBnb3RvIGFib3J0Owo+PiArICAgICAgICAgICAgfQo+PiArICAgICAgICAgICAg\n" - "ZGF0YS0+dmFsdWVzW2ldID0gdmFsICYgMHg3RkZGOyAvKiBTdHJpcCAnbmV3JyBiaXQgKi8KPgo+\n" - "IFRoZSBiaXQgaXMgbmV2ZXIgZXZhbHVhdGVkLCBzbyB5b3UgbWlnaHQgYXMgd2VsbCBzdG9yZSB0\n" - "aGUgcmF3IHZhbHVlLgo+Cj4+ICsgICAgICAgIH0KPj4gKyAgICAgICAgZGF0YS0+bGFzdF91cGRh\n" - "dGVkID0gamlmZmllczsKPj4gKyAgICAgICAgZGF0YS0+dmFsaWQgPSAxOwo+Cj4gICAgICA9IHRy\n" - "dWU7Cj4KPj4gKwo+PiArICAgICAgICAvKgo+PiArICAgICAgICAgKiAgUXVpcms6IFNlY29uZCB0\n" - "cmlnZ2VyIGlzIGlnbm9yZWQ/IEFmdGVyIHRoaXMsIHRoZSBCVVNZIHdpbGwKPj4gKyAgICAgICAg\n" - "ICogc3RpbGwgYmUgc2V0IHRvICIwIiBhbmQgbm8gY29udmVyc2lvbiBwZXJmb3JtZWQuCj4+ICsg\n" - "ICAgICAgICAqLwo+PiArICAgICAgICB2YWwgPSBsdGMyOTkwX3dyaXRlKGkyYywgTFRDMjk5MF9U\n" - "UklHR0VSLCAwKTsKPj4gKyAgICB9Cj4+ICthYm9ydDoKPj4gKyAgICBtdXRleF91bmxvY2soJmRh\n" - "dGEtPnVwZGF0ZV9sb2NrKTsKPj4gKyAgICByZXR1cm4gcmV0Owo+PiArfQo+PiArCj4+ICsvKiBS\n" - "ZXR1cm4gdGhlIGNvbnZlcnRlZCB2YWx1ZSBmcm9tIHRoZSBnaXZlbiByZWdpc3RlciBpbiB1ViBv\n" - "ciBtQyAqLwo+PiArc3RhdGljIGludCBsdGMyOTkwX2dldF92YWx1ZShzdHJ1Y3QgbHRjMjk5MF9k\n" - "YXRhICpkYXRhLCB1OCBpbmRleCkKPj4gK3sKPj4gKyAgICBzMzIgcmVzdWx0Owo+PiArICAgIHMx\n" - "NiB2Owo+PiArCj4+ICsgICAgaWYgKGluZGV4ID09IDApIHsgLyogaW50ZXJuYWwgdGVtcCwgMC4w\n" - "NjI1IGRlZ3JlZXMvTFNCLCAxMi1iaXQgICovCj4+ICsgICAgICAgIHYgPSBkYXRhLT52YWx1ZXNb\n" - "aW5kZXhdIDw8IDM7Cj4+ICsgICAgICAgIHJlc3VsdCA9IChzMzIpdiAqIDEwMDAgPj4gNzsKPj4g\n" - "KyAgICB9IGVsc2UgaWYgKGluZGV4IDwgNSkgeyAvKiBWeC1WeSwgMTkuNDJ1Vi9MU0IsIDE0LWJp\n" - "dCAqLwo+PiArICAgICAgICB2ID0gZGF0YS0+dmFsdWVzW2luZGV4XSA8PCAyOwo+Cj4gRGF0YXNo\n" - "ZWV0IHNheXMgdGhhdCB0aGUgc2lnbiBiaXQgaXMgaW4gYml0IDE0LCBzbyB0aGlzIGRyb3BzIHRo\n" - "ZSBzaWduIGJpdC4KCkknbGwgY2hlY2sgdGhlIGRhdGEgc2hlZXQsIHdvdWxkIG5vdCBoYXZlIG5v\n" - "dGljZWQgdGhpcyBzaW5jZSBjdXJyZW50IApkb2Vzbid0IHRlbmQgdG8gcnVuIGZyb20gdGhlIENQ\n" - "VSBiYWNrIGludG8gdGhlIGJhdHRlcnkgOikKCj4+ICsgICAgICAgIHJlc3VsdCA9IChzMzIpdiAq\n" - "IDE5NDIgLyAoNCAqIDEwMCk7Cj4+ICsgICAgfSBlbHNlIHsgLyogVmNjLCAzMDUuMTjOvFYvTFNC\n" - "LCAyLjVWIG9mZnNldCwgMTQtYml0ICovCj4+ICsgICAgICAgIHYgPSBkYXRhLT52YWx1ZXNbaW5k\n" - "ZXhdIDw8IDI7Cj4+ICsgICAgICAgIHJlc3VsdCA9IChzMzIpdiAqIDMwNTE4IC8gKDQgKiAxMDAp\n" - "Owo+PiArICAgICAgICByZXN1bHQgKz0gMjUwMDAwMDsKPj4gKyAgICB9Cj4+ICsgICAgcmV0dXJu\n" - "IHJlc3VsdDsKPj4gK30KPj4gKwo+PiArc3RhdGljIHNzaXplX3QgbHRjMjk5MF9zaG93X3ZhbHVl\n" - "KHN0cnVjdCBkZXZpY2UgKmRldiwKPj4gKyAgICAgICAgICAgICAgICAgIHN0cnVjdCBkZXZpY2Vf\n" - "YXR0cmlidXRlICpkYSwgY2hhciAqYnVmKQo+PiArewo+PiArICAgIHN0cnVjdCBzZW5zb3JfZGV2\n" - "aWNlX2F0dHJpYnV0ZSAqYXR0ciA9IHRvX3NlbnNvcl9kZXZfYXR0cihkYSk7Cj4+ICsgICAgc3Ry\n" - "dWN0IGx0YzI5OTBfZGF0YSAqZGF0YSA9IGx0YzI5OTBfdXBkYXRlX2RldmljZShkZXYpOwo+PiAr\n" - "ICAgIGludCB2YWx1ZTsKPj4gKwo+PiArICAgIGlmIChJU19FUlIoZGF0YSkpCj4+ICsgICAgICAg\n" - "IHJldHVybiBQVFJfRVJSKGRhdGEpOwo+PiArCj4+ICsgICAgdmFsdWUgPSBsdGMyOTkwX2dldF92\n" - "YWx1ZShkYXRhLCBhdHRyLT5pbmRleCk7Cj4+ICsgICAgcmV0dXJuIHNucHJpbnRmKGJ1ZiwgUEFH\n" - "RV9TSVpFLCAiJWRcbiIsIHZhbHVlKTsKPj4gK30KPj4gKwo+PiArc3RhdGljIFNFTlNPUl9ERVZJ\n" - "Q0VfQVRUUih0ZW1wX2ludCwgU19JUlVHTywgbHRjMjk5MF9zaG93X3ZhbHVlLAo+PiBOVUxMLCAw\n" - "KTsKPj4gK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodjF2Ml9kaWZmLCBTX0lSVUdPLCBsdGMy\n" - "OTkwX3Nob3dfdmFsdWUsCj4+IE5VTEwsIDEpOwo+PiArc3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRU\n" - "Uih2M3Y0X2RpZmYsIFNfSVJVR08sIGx0YzI5OTBfc2hvd192YWx1ZSwKPj4gTlVMTCwgMyk7Cj4+\n" - "ICtzdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHZjYywgU19JUlVHTywgbHRjMjk5MF9zaG93X3Zh\n" - "bHVlLCBOVUxMLCA1KTsKPj4gKwo+Cj4gUGxlYXNlIHVzZSBzdGFuZGFyZCBhdHRyaWJ1dGUgbmFt\n" - "ZXMgKGFuZCB1bml0cykgYXMgcGVyCj4gRG9jdW1lbnRhdGlvbi9od21vbi9zeXNmcy1pbnRlcmZh\n" - "Y2UuCj4KPj4gK3N0YXRpYyBzdHJ1Y3QgYXR0cmlidXRlICpsdGMyOTkwX2F0dHJpYnV0ZXNbXSA9\n" - "IHsKPj4gKyAgICAmc2Vuc29yX2Rldl9hdHRyX3RlbXBfaW50LmRldl9hdHRyLmF0dHIsCj4+ICsg\n" - "ICAgJnNlbnNvcl9kZXZfYXR0cl92MXYyX2RpZmYuZGV2X2F0dHIuYXR0ciwKPj4gKyAgICAmc2Vu\n" - "c29yX2Rldl9hdHRyX3YzdjRfZGlmZi5kZXZfYXR0ci5hdHRyLAo+PiArICAgICZzZW5zb3JfZGV2\n" - "X2F0dHJfdmNjLmRldl9hdHRyLmF0dHIsCj4+ICsgICAgTlVMTCwKPj4gK307Cj4+ICsKPj4gK3N0\n" - "YXRpYyBjb25zdCBzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIGx0YzI5OTBfZ3JvdXAgPSB7Cj4+ICsg\n" - "ICAgLmF0dHJzID0gbHRjMjk5MF9hdHRyaWJ1dGVzLAo+PiArfTsKPj4gKwo+Cj4gUGxlYXNlIHVz\n" - "ZSB0aGUgQVRUUklCVVRFX0dST1VQUygpIG1hY3JvLiBBbHNvIHNlZSBiZWxvdy4KCk9rYXksIHdp\n" - "bGwgUlRGTS4KCj4KPj4gK3N0YXRpYyBpbnQgbHRjMjk5MF9pMmNfcHJvYmUoCj4+ICsgICAgc3Ry\n" - "dWN0IGkyY19jbGllbnQgKmkyYywgY29uc3Qgc3RydWN0IGkyY19kZXZpY2VfaWQgKmlkKQo+Cj4g\n" - "UGxlYXNlIHNwbGl0IGFzCj4KPiBzdGF0aWMgaW50IGx0YzI5OTBfaTJjX3Byb2JlKHN0cnVjdCBp\n" - "MmNfY2xpZW50ICppMmMsCj4gICAgICAgICAgICAgICAgICAgY29uc3Qgc3RydWN0IGkyY19kZXZp\n" - "Y2VfaWQgKmlkKQo+Cj4+ICt7Cj4+ICsgICAgaW50IHJldDsKPj4gKyAgICBzdHJ1Y3QgbHRjMjk5\n" - "MF9kYXRhICpsdGMyOTkwOwo+PiArCj4+ICsgICAgaWYgKCFpMmNfY2hlY2tfZnVuY3Rpb25hbGl0\n" - "eShpMmMtPmFkYXB0ZXIsCj4+IEkyQ19GVU5DX1NNQlVTX0JZVEVfREFUQSkpCj4+ICsgICAgICAg\n" - "IHJldHVybiAtRU5PREVWOwo+PiArCj4+ICsgICAgbHRjMjk5MCA9IGRldm1fa3phbGxvYygmaTJj\n" - "LT5kZXYsCj4+ICsgICAgICAgIHNpemVvZihzdHJ1Y3QgbHRjMjk5MF9kYXRhKSwgR0ZQX0tFUk5F\n" - "TCk7Cj4KPiBQbGVhc2UgYWxpZ24gY29udGludWF0aW9uIGxpbmVzIHdpdGggJygnLgo+Cj4+ICsg\n" - "ICAgaWYgKGx0YzI5OTAgPT0gTlVMTCkKPj4gKyAgICAgICAgcmV0dXJuIC1FTk9NRU07Cj4+ICsK\n" - "Pj4gKyAgICByZXQgPSBsdGMyOTkwX3JlYWRfYnl0ZShpMmMsIDApOwo+PiArICAgIGlmIChyZXQg\n" - "PCAwKSB7Cj4+ICsgICAgICAgIGRldl9lcnIoJmkyYy0+ZGV2LCAiQ291bGQgbm90IHJlYWQgTFRD\n" - "Mjk5MCBvbiBpMmMgYnVzLlxuIik7Cj4+ICsgICAgICAgIHJldHVybiByZXQ7Cj4+ICsgICAgfQo+\n" - "Cj4gVGhlIHdyaXRlIGJlbG93IHdvdWxkIGFsc28gcmV0dXJuIGFuIGVycm9yIGlmIHRoZSBjaGlw\n" - "IGlzbid0IHRoZXJlLAo+IHNvIHRoaXMgYWRkaXRpb25hbCByZWFkIGRvZXMgbm90IHByb3ZpZGUg\n" - "YW55IHJlYWwgdmFsdWUuCj4KPj4gKyAgICByZXQgPSBsdGMyOTkwX3dyaXRlKGkyYywgTFRDMjk5\n" - "MF9DT05UUk9MLAo+PiArICAgICAgICBMVEMyOTkwX0NPTlRST0xfU0lOR0xFIHwgTFRDMjk5MF9D\n" - "T05UUk9MX01FQVNVUkVfQUxMIHwKPj4gKyAgICAgICAgTFRDMjk5MF9DT05UUk9MX01PREVfQ1VS\n" - "UkVOVCk7Cj4KPiBJJ2xsIGhhdmUgdG8gdGhpbmsgYWJvdXQgdGhpcy4gV2hpbGUgaXQgYWRkcmVz\n" - "c2VzIHlvdXIgdXNlIGNhc2UsCj4gaXQgbGltaXRzIHRoZSBzY29wZSBvZiB0aGlzIGRyaXZlciBz\n" - "aWduaWZpY2FudGx5LiBMb29raW5nIGludG8gdGhlIGJvYXJkCj4gc3BlY2lmaWNhdGlvbnMsIHlv\n" - "dSBtaWdodCBhcyB3ZWxsIGRvIGl0IHJpZ2h0IGFuZCBkZXRlcm1pbmUgKGFuZCBzZXQpCj4gdGhl\n" - "IGNvcnJlY3QgY29uZmlndXJhdGlvbiB1c2luZyBkZXZpY2V0cmVlIGRhdGEgaW5zdGVhZCBvZiBm\n" - "b3JjaW5nIHlvdXIKPiB1c2UgY2FzZSBvbiBldmVyeW9uZS4KPgo+IFN1cmUsIHlvdSBtYXkgYXJn\n" - "dWUgdGhhdCB5b3UgZG9uJ3QgY2FyZSwgYnV0IHdlIHdpbGwgYmUgdGhlIG9uZXMgd2hvCj4gd2ls\n" - "bCBoYXZlCj4gdG8gaGFuZGxlIGVycm9yIHJlcG9ydHMgdGhhdCB0aGUgZHJpdmVyIHVuZXhwZWN0\n" - "ZWRseSBjaGFuZ2VzIHRoZQo+IGNvbmZpZ3VyYXRpb24KPiBpbiBvdGhlciB1c2UgY2FzZXMgKHdo\n" - "ZXJlLCBmb3IgZXhhbXBsZSwgdGhlIG1vZGUgbWF5IGhhdmUgYmVlbiBwcmUtc2V0IGJ5Cj4gdGhl\n" - "IEJJT1Mgb3IgUk9NTU9OKS4KClRoZSByZWFzb24gSSBkaWRuJ3Qgc3VibWl0IHRoZSBkcml2ZXIg\n" - "bGFzdCB5ZWFyIHdhcyB0aGF0IEkgd2FzIHN0aWxsIAp0aGlua2luZyBhYm91dCBpdC4gT24gdGhl\n" - "IG90aGVyIGhhbmQsIGEgbGltaXRlZCBkcml2ZXIgaXMgc3RpbGwgbXVjaCAKYmV0dGVyIHRoYW4g\n" - "bm8gZHJpdmVyIGF0IGFsbCwgc28gdGhhdCBtYWRlIG1lIHBvc3QgaXQsIHdpdGggdGhlIGFkZGVk\n" - "IApyZW1hcmtzIGFib3V0IHRoZSBkcml2ZXIgYmVpbmcgbGltaXRlZC4KCkFkZGluZyB0aGUgb3Ro\n" - "ZXIgZnVuY3Rpb25zIGl0IHF1aXRlIGEgYml0IG1vcmUgd29yayB0aGFuIGp1c3Qgd3JpdGluZyAK\n" - "dGhpcyByZWdpc3Rlci4gSXQgYWxzbyBjaGFuZ2VzIHRoZSBwcm9wZXJ0aWVzIHRvIGJlIGV4cG9y\n" - "dGVkIHRvIHN5c2ZzLCAKYW5kIHRoZSBjYWxjdWxhdGlvbiBvZiB0aGUgZW5kIHZhbHVlcy4KCj4K\n" - "Pj4gKyAgICBpZiAocmV0IDwgMCkgewo+PiArICAgICAgICBkZXZfZXJyKCZpMmMtPmRldiwgIkVy\n" - "cm9yOiBGYWlsZWQgdG8gc2V0IGNvbnRyb2wgbW9kZS5cbiIpOwo+PiArICAgICAgICByZXR1cm4g\n" - "cmV0Owo+PiArICAgIH0KPj4gKwo+PiArICAgIG11dGV4X2luaXQoJmx0YzI5OTAtPnVwZGF0ZV9s\n" - "b2NrKTsKPj4gKyAgICBpMmNfc2V0X2NsaWVudGRhdGEoaTJjLCBsdGMyOTkwKTsKPj4gKwo+PiAr\n" - "ICAgIC8qIFJlZ2lzdGVyIHN5c2ZzIGhvb2tzICovCj4+ICsgICAgcmV0ID0gc3lzZnNfY3JlYXRl\n" - "X2dyb3VwKCZpMmMtPmRldi5rb2JqLCAmbHRjMjk5MF9ncm91cCk7Cj4+ICsgICAgaWYgKHJldCkK\n" - "Pj4gKyAgICAgICAgcmV0dXJuIHJldDsKPj4gKwo+PiArICAgIGx0YzI5OTAtPmh3bW9uX2RldiA9\n" - "IGh3bW9uX2RldmljZV9yZWdpc3RlcigmaTJjLT5kZXYpOwo+Cj4gUGxlYXNlIHVzZSBkZXZtX2h3\n" - "bW9uX2RldmljZV9yZWdpc3Rlcl93aXRoX2dyb3VwcygpLgo+Cj4+ICsgICAgaWYgKElTX0VSUihs\n" - "dGMyOTkwLT5od21vbl9kZXYpKSB7Cj4+ICsgICAgICAgIHJldCA9IFBUUl9FUlIobHRjMjk5MC0+\n" - "aHdtb25fZGV2KTsKPj4gKyAgICAgICAgZ290byBvdXRfaHdtb25fZGV2aWNlX3JlZ2lzdGVyOwo+\n" - "PiArICAgIH0KPj4gKwo+PiArICAgIHJldHVybiAwOwo+PiArCj4+ICtvdXRfaHdtb25fZGV2aWNl\n" - "X3JlZ2lzdGVyOgo+PiArICAgIHN5c2ZzX3JlbW92ZV9ncm91cCgmaTJjLT5kZXYua29iaiwgJmx0\n" - "YzI5OTBfZ3JvdXApOwo+PiArICAgIHJldHVybiByZXQ7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBp\n" - "bnQgbHRjMjk5MF9pMmNfcmVtb3ZlKHN0cnVjdCBpMmNfY2xpZW50ICppMmMpCj4+ICt7Cj4+ICsg\n" - "ICAgc3RydWN0IGx0YzI5OTBfZGF0YSAqbHRjMjk5MCA9IGkyY19nZXRfY2xpZW50ZGF0YShpMmMp\n" - "Owo+PiArCj4+ICsgICAgaHdtb25fZGV2aWNlX3VucmVnaXN0ZXIobHRjMjk5MC0+aHdtb25fZGV2\n" - "KTsKPj4gKyAgICBzeXNmc19yZW1vdmVfZ3JvdXAoJmkyYy0+ZGV2LmtvYmosICZsdGMyOTkwX2dy\n" - "b3VwKTsKPj4gKyAgICByZXR1cm4gMDsKPj4gK30KPj4gKwo+PiArc3RhdGljIGNvbnN0IHN0cnVj\n" - "dCBpMmNfZGV2aWNlX2lkIGx0YzI5OTBfaTJjX2lkW10gPSB7Cj4+ICsgICAgeyAibHRjMjk5MCIs\n" - "IDAgfSwKPj4gKyAgICB7fQo+PiArfTsKPj4gK01PRFVMRV9ERVZJQ0VfVEFCTEUoaTJjLCBsdGMy\n" - "OTkwX2kyY19pZCk7Cj4+ICsKPj4gK3N0YXRpYyBzdHJ1Y3QgaTJjX2RyaXZlciBsdGMyOTkwX2ky\n" - "Y19kcml2ZXIgPSB7Cj4+ICsgICAgLmRyaXZlciA9IHsKPj4gKyAgICAgICAgLm5hbWUgPSAibHRj\n" - "Mjk5MCIsCj4+ICsgICAgfSwKPj4gKyAgICAucHJvYmUgICAgPSBsdGMyOTkwX2kyY19wcm9iZSwK\n" - "Pj4gKyAgICAucmVtb3ZlICAgPSBsdGMyOTkwX2kyY19yZW1vdmUsCj4+ICsgICAgLmlkX3RhYmxl\n" - "ID0gbHRjMjk5MF9pMmNfaWQsCj4+ICt9Owo+PiArCj4+ICttb2R1bGVfaTJjX2RyaXZlcihsdGMy\n" - "OTkwX2kyY19kcml2ZXIpOwo+PiArCj4+ICtNT0RVTEVfREVTQ1JJUFRJT04oIkxUQzI5OTAgU2Vu\n" - "c29yIERyaXZlciIpOwo+PiArTU9EVUxFX0FVVEhPUigiVG9waWMgRW1iZWRkZWQgUHJvZHVjdHMi\n" - "KTsKPj4gK01PRFVMRV9MSUNFTlNFKCJHUEwgdjIiKTsKPj4KPgoKCi0tIApNaWtlIExvb2lqbWFu\n" - "cwoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbG0tc2Vu\n" - "c29ycyBtYWlsaW5nIGxpc3QKbG0tc2Vuc29yc0BsbS1zZW5zb3JzLm9yZwpodHRwOi8vbGlzdHMu\n" - bG0tc2Vuc29ycy5vcmcvbWFpbG1hbi9saXN0aW5mby9sbS1zZW5zb3Jz + "Thank you very much for your review comments, I'll update the driver and \n" + "post a v2 patch.\n" + "\n" + "Inlined some replies below. Assume that I \"will do\" for all comments I \n" + "didn't comment on inline...\n" + "\n" + "On 06-01-16 16:22, Guenter Roeck wrote:\n" + "> Hello Mike,\n" + ">\n" + "> On 01/06/2016 12:07 AM, Mike Looijmans wrote:\n" + ">> This adds support for the Linear Technology LTC2990 I2C System Monitor.\n" + ">\n" + "> s/ / /\n" + ">\n" + ">> The LTC2990 supports a combination of voltage, current and temperature\n" + ">> monitoring, but this driver currently only supports reading two currents\n" + ">> by measuring two differential voltages across series resistors.\n" + ">>\n" + "> Plus VCC, plus the internal temperature.\n" + "\n" + "Yeah, I should give myself more credit :) I'll add that in Kconfig too.\n" + "\n" + ">> This is sufficient to support the Topic Miami SOM which uses this chip\n" + ">> to monitor the currents flowing into the FPGA and the CPU parts.\n" + ">>\n" + ">> Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl>\n" + ">> ---\n" + ">> drivers/hwmon/Kconfig | 15 +++\n" + ">> drivers/hwmon/Makefile | 1 +\n" + ">> drivers/hwmon/ltc2990.c | 273\n" + ">> ++++++++++++++++++++++++++++++++++++++++++++++++\n" + ">\n" + "> Please also provide Documentation/hwmon/ltc2990.\n" + ">\n" + "> Also, please read and follow Documentation/hwmon/submitting-patches.\n" + ">\n" + ">> 3 files changed, 289 insertions(+)\n" + ">> create mode 100644 drivers/hwmon/ltc2990.c\n" + ">>\n" + ">> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig\n" + ">> index 80a73bf..b3eef31 100644\n" + ">> --- a/drivers/hwmon/Kconfig\n" + ">> +++ b/drivers/hwmon/Kconfig\n" + ">> @@ -685,6 +685,21 @@ config SENSORS_LTC2945\n" + ">> This driver can also be built as a module. If so, the module will\n" + ">> be called ltc2945.\n" + ">>\n" + ">> +config SENSORS_LTC2990\n" + ">> + tristate \"Linear Technology LTC2990 (current monitoring mode only)\"\n" + ">> + depends on I2C\n" + ">> + select REGMAP_I2C\n" + ">\n" + "> Using regmap for the driver might be a good idea, but you don't.\n" + "\n" + "Looking at the regmap, the driver only writes the one cachable register \n" + "once, the \"control\". All the other registers cannot be cached, are \n" + "either read-only or write-only. Don't think regmap will help, so I'll \n" + "remove the \"select\" here.\n" + "\n" + ">> + default n\n" + ">\n" + "> Not necessary.\n" + ">\n" + ">> + help\n" + ">> + If you say yes here you get support for Linear Technology LTC2990\n" + ">> + I2C System Monitor. The LTC2990 supports a combination of voltage,\n" + ">> + current and temperature monitoring, but this driver currently only\n" + ">> + supports reading two currents by measuring two differential\n" + ">> voltages\n" + ">> + across series resistors.\n" + ">> +\n" + ">> + This driver can also be built as a module. If so, the module will\n" + ">> + be called ltc2990.\n" + ">> +\n" + ">> config SENSORS_LTC4151\n" + ">> tristate \"Linear Technology LTC4151\"\n" + ">> depends on I2C\n" + ">> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile\n" + ">> index 12a3239..e4bd15b 100644\n" + ">> --- a/drivers/hwmon/Makefile\n" + ">> +++ b/drivers/hwmon/Makefile\n" + ">> @@ -101,6 +101,7 @@ obj-$(CONFIG_SENSORS_LM95234) += lm95234.o\n" + ">> obj-$(CONFIG_SENSORS_LM95241) += lm95241.o\n" + ">> obj-$(CONFIG_SENSORS_LM95245) += lm95245.o\n" + ">> obj-$(CONFIG_SENSORS_LTC2945) += ltc2945.o\n" + ">> +obj-$(CONFIG_SENSORS_LTC2990) += ltc2990.o\n" + ">> obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o\n" + ">> obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o\n" + ">> obj-$(CONFIG_SENSORS_LTC4222) += ltc4222.o\n" + ">> diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c\n" + ">> new file mode 100644\n" + ">> index 0000000..161d995\n" + ">> --- /dev/null\n" + ">> +++ b/drivers/hwmon/ltc2990.c\n" + ">> @@ -0,0 +1,273 @@\n" + ">> +/*\n" + ">> + * driver for Linear Technology LTC2990 power monitor\n" + ">\n" + "> Driver\n" + ">\n" + ">> + *\n" + ">> + * Copyright (C) 2014 Topic Embedded Products\n" + ">\n" + "> 2015 ?\n" + "\n" + "I wrote the driver early last year. I only did some cosmetic cleanup and \n" + "rebase on master before submitting.\n" + "\n" + ">\n" + ">> + * Author: Mike Looijmans <mike.looijmans@topic.nl>\n" + ">> + *\n" + ">> + * License: GPLv2\n" + ">> + *\n" + ">> + * This driver assumes the chip is wired as a dual current monitor, and\n" + ">> + * reports the voltage drop across two series resistors.\n" + ">\n" + "> It also monitors the temperature and VCC.\n" + ">\n" + ">> + */\n" + ">> +\n" + ">> +#include <linux/bug.h>\n" + ">\n" + "> Is this used anywhere in the driver ?\n" + "\n" + "Not any more...\n" + "\n" + ">\n" + ">> +#include <linux/delay.h>\n" + ">> +#include <linux/err.h>\n" + ">> +#include <linux/hwmon.h>\n" + ">> +#include <linux/hwmon-sysfs.h>\n" + ">> +#include <linux/i2c.h>\n" + ">> +#include <linux/kernel.h>\n" + ">> +#include <linux/module.h>\n" + ">> +#include <linux/slab.h>\n" + ">> +\n" + ">> +#define LTC2990_STATUS 0x00\n" + ">> +#define LTC2990_CONTROL 0x01\n" + ">> +#define LTC2990_TRIGGER 0x02\n" + ">> +#define LTC2990_TINT_MSB 0x04\n" + ">> +#define LTC2990_TINT_LSB 0x05\n" + ">> +#define LTC2990_V1_MSB 0x06\n" + ">> +#define LTC2990_V1_LSB 0x07\n" + ">> +#define LTC2990_V2_MSB 0x08\n" + ">> +#define LTC2990_V2_LSB 0x09\n" + ">> +#define LTC2990_V3_MSB 0x0A\n" + ">> +#define LTC2990_V3_LSB 0x0B\n" + ">> +#define LTC2990_V4_MSB 0x0C\n" + ">> +#define LTC2990_V4_LSB 0x0D\n" + ">> +#define LTC2990_VCC_MSB 0x0E\n" + ">> +#define LTC2990_VCC_LSB 0x0F\n" + ">> +\n" + ">> +#define LTC2990_STATUS_BUSY BIT(0)\n" + ">> +#define LTC2990_STATUS_TINT BIT(1)\n" + ">> +#define LTC2990_STATUS_V1 BIT(2)\n" + ">> +#define LTC2990_STATUS_V2 BIT(3)\n" + ">> +#define LTC2990_STATUS_V3 BIT(4)\n" + ">> +#define LTC2990_STATUS_V4 BIT(5)\n" + ">> +#define LTC2990_STATUS_VCC BIT(6)\n" + ">> +\n" + ">> +/* Only define control settings we actually use */\n" + ">> +#define LTC2990_CONTROL_KELVIN BIT(7)\n" + ">> +#define LTC2990_CONTROL_SINGLE BIT(6)\n" + ">> +#define LTC2990_CONTROL_MEASURE_ALL (0x3 << 3)\n" + ">> +#define LTC2990_CONTROL_MODE_CURRENT 0x06\n" + ">> +#define LTC2990_CONTROL_MODE_VOLTAGE 0x07\n" + ">> +\n" + ">> +struct ltc2990_data {\n" + ">> + struct device *hwmon_dev;\n" + ">> + struct mutex update_lock;\n" + ">> + unsigned long last_updated;\n" + ">> + short values[6];\n" + ">\n" + "> u16 ?\n" + ">\n" + ">> + bool valid;\n" + ">> + u8 update_counter;\n" + ">\n" + "> Not used anywhere.\n" + ">\n" + ">> +};\n" + ">> +\n" + ">> +static int ltc2990_write(struct i2c_client *i2c, u8 reg, u8 value)\n" + ">> +{\n" + ">> + return i2c_smbus_write_byte_data(i2c, reg, value);\n" + ">> +}\n" + ">> +\n" + ">> +static int ltc2990_read_byte(struct i2c_client *i2c, u8 reg)\n" + ">> +{\n" + ">> + return i2c_smbus_read_byte_data(i2c, reg);\n" + ">> +}\n" + ">> +\n" + ">\n" + "> Useless shim functions.\n" + "\n" + "True, should have removed them after refactoring them into one-liners.\n" + "They were convenient early on.\n" + "\n" + ">\n" + ">> +static int ltc2990_read_word(struct i2c_client *i2c, u8 reg)\n" + ">> +{\n" + ">> + int result = i2c_smbus_read_word_data(i2c, reg);\n" + ">> + /* Result is MSB first, but smbus specs say LSB first, so swap the\n" + ">> + * result */\n" + ">\n" + "> Bad multi-line comment.\n" + ">\n" + ">> + return result < 0 ? result : swab16(result);\n" + ">\n" + "> Please use i2c_smbus_read_word_swapped() and drop the shim function.\n" + ">\n" + ">> +}\n" + ">> +\n" + ">> +static struct ltc2990_data *ltc2990_update_device(struct device *dev)\n" + ">> +{\n" + ">> + struct i2c_client *i2c = to_i2c_client(dev);\n" + ">> + struct ltc2990_data *data = i2c_get_clientdata(i2c);\n" + ">> + struct ltc2990_data *ret = data;\n" + ">> + unsigned int timeout;\n" + ">> +\n" + ">> + mutex_lock(&data->update_lock);\n" + ">> +\n" + ">> + /* Update about 4 times per second max */\n" + ">> + if (time_after(jiffies, data->last_updated + HZ / 4) ||\n" + ">> !data->valid) {\n" + ">> + int val;\n" + ">> + int i;\n" + ">> +\n" + ">\n" + "> Please consider using continuous conversion. This would simplify the\n" + "> code significantly\n" + "> and reduce read delays.\n" + "\n" + "It might increase power consumption though, as typically some user \n" + "program would poll this every 10 seconds or so. I'll check the data sheet.\n" + "\n" + ">> + /* Trigger ADC, any value will do */\n" + ">> + val = ltc2990_write(i2c, LTC2990_TRIGGER, 1);\n" + ">> + if (unlikely(val < 0)) {\n" + ">> + ret = ERR_PTR(val);\n" + ">> + goto abort;\n" + ">> + }\n" + ">> +\n" + ">> + /* Wait for conversion complete */\n" + ">> + timeout = 200;\n" + ">> + for (;;) {\n" + ">> + usleep_range(2000, 4000);\n" + ">> + val = ltc2990_read_byte(i2c, LTC2990_STATUS);\n" + ">> + if (unlikely(val < 0)) {\n" + ">> + ret = ERR_PTR(val);\n" + ">> + goto abort;\n" + ">> + }\n" + ">> + /* Single-shot mode, wait for conversion to complete */\n" + ">> + if ((val & LTC2990_STATUS_BUSY) == 0)\n" + ">\n" + "> if (!(...))\n" + ">\n" + ">> + break;\n" + ">> + if (--timeout == 0) {\n" + ">> + ret = ERR_PTR(-ETIMEDOUT);\n" + ">> + goto abort;\n" + ">> + }\n" + ">> + }\n" + ">\n" + "> Again, please consider using continuous conversion mode.\n" + ">\n" + "> If this is not feasible for some reason, you might as well just wait for\n" + "> the\n" + "> minimum conversion time before trying to read for the first time. If so,\n" + "> please use a fixed timeout by comparing the elapsed time instead of looping\n" + "> for a maximum number of times. Not even counting the time for executing the\n" + "> code, the maximum delay is between 400 ms and 800 ms, which is way too high\n" + "> (chip spec says 167 ms worst case, if three temperature sensors are\n" + "> configured).\n" + "\n" + "Or maybe I should just sleep for 167ms and be done with it. Though I \n" + "think I'l got with your minimal time first suggestion.\n" + "\n" + ">> +\n" + ">> + /* Read all registers */\n" + ">> + for (i = 0; i < ARRAY_SIZE(data->values); ++i) {\n" + ">> + val = ltc2990_read_word(i2c, (i<<1) + LTC2990_TINT_MSB);\n" + ">\n" + "> Missing spaces around <<\n" + ">\n" + ">> + if (unlikely(val < 0)) {\n" + ">> + dev_dbg(dev,\n" + ">> + \"Failed to read ADC value: error %d\\n\",\n" + ">> + val);\n" + ">> + ret = ERR_PTR(val);\n" + ">> + goto abort;\n" + ">> + }\n" + ">> + data->values[i] = val & 0x7FFF; /* Strip 'new' bit */\n" + ">\n" + "> The bit is never evaluated, so you might as well store the raw value.\n" + ">\n" + ">> + }\n" + ">> + data->last_updated = jiffies;\n" + ">> + data->valid = 1;\n" + ">\n" + "> = true;\n" + ">\n" + ">> +\n" + ">> + /*\n" + ">> + * Quirk: Second trigger is ignored? After this, the BUSY will\n" + ">> + * still be set to \"0\" and no conversion performed.\n" + ">> + */\n" + ">> + val = ltc2990_write(i2c, LTC2990_TRIGGER, 0);\n" + ">> + }\n" + ">> +abort:\n" + ">> + mutex_unlock(&data->update_lock);\n" + ">> + return ret;\n" + ">> +}\n" + ">> +\n" + ">> +/* Return the converted value from the given register in uV or mC */\n" + ">> +static int ltc2990_get_value(struct ltc2990_data *data, u8 index)\n" + ">> +{\n" + ">> + s32 result;\n" + ">> + s16 v;\n" + ">> +\n" + ">> + if (index == 0) { /* internal temp, 0.0625 degrees/LSB, 12-bit */\n" + ">> + v = data->values[index] << 3;\n" + ">> + result = (s32)v * 1000 >> 7;\n" + ">> + } else if (index < 5) { /* Vx-Vy, 19.42uV/LSB, 14-bit */\n" + ">> + v = data->values[index] << 2;\n" + ">\n" + "> Datasheet says that the sign bit is in bit 14, so this drops the sign bit.\n" + "\n" + "I'll check the data sheet, would not have noticed this since current \n" + "doesn't tend to run from the CPU back into the battery :)\n" + "\n" + ">> + result = (s32)v * 1942 / (4 * 100);\n" + ">> + } else { /* Vcc, 305.18\316\274V/LSB, 2.5V offset, 14-bit */\n" + ">> + v = data->values[index] << 2;\n" + ">> + result = (s32)v * 30518 / (4 * 100);\n" + ">> + result += 2500000;\n" + ">> + }\n" + ">> + return result;\n" + ">> +}\n" + ">> +\n" + ">> +static ssize_t ltc2990_show_value(struct device *dev,\n" + ">> + struct device_attribute *da, char *buf)\n" + ">> +{\n" + ">> + struct sensor_device_attribute *attr = to_sensor_dev_attr(da);\n" + ">> + struct ltc2990_data *data = ltc2990_update_device(dev);\n" + ">> + int value;\n" + ">> +\n" + ">> + if (IS_ERR(data))\n" + ">> + return PTR_ERR(data);\n" + ">> +\n" + ">> + value = ltc2990_get_value(data, attr->index);\n" + ">> + return snprintf(buf, PAGE_SIZE, \"%d\\n\", value);\n" + ">> +}\n" + ">> +\n" + ">> +static SENSOR_DEVICE_ATTR(temp_int, S_IRUGO, ltc2990_show_value,\n" + ">> NULL, 0);\n" + ">> +static SENSOR_DEVICE_ATTR(v1v2_diff, S_IRUGO, ltc2990_show_value,\n" + ">> NULL, 1);\n" + ">> +static SENSOR_DEVICE_ATTR(v3v4_diff, S_IRUGO, ltc2990_show_value,\n" + ">> NULL, 3);\n" + ">> +static SENSOR_DEVICE_ATTR(vcc, S_IRUGO, ltc2990_show_value, NULL, 5);\n" + ">> +\n" + ">\n" + "> Please use standard attribute names (and units) as per\n" + "> Documentation/hwmon/sysfs-interface.\n" + ">\n" + ">> +static struct attribute *ltc2990_attributes[] = {\n" + ">> + &sensor_dev_attr_temp_int.dev_attr.attr,\n" + ">> + &sensor_dev_attr_v1v2_diff.dev_attr.attr,\n" + ">> + &sensor_dev_attr_v3v4_diff.dev_attr.attr,\n" + ">> + &sensor_dev_attr_vcc.dev_attr.attr,\n" + ">> + NULL,\n" + ">> +};\n" + ">> +\n" + ">> +static const struct attribute_group ltc2990_group = {\n" + ">> + .attrs = ltc2990_attributes,\n" + ">> +};\n" + ">> +\n" + ">\n" + "> Please use the ATTRIBUTE_GROUPS() macro. Also see below.\n" + "\n" + "Okay, will RTFM.\n" + "\n" + ">\n" + ">> +static int ltc2990_i2c_probe(\n" + ">> + struct i2c_client *i2c, const struct i2c_device_id *id)\n" + ">\n" + "> Please split as\n" + ">\n" + "> static int ltc2990_i2c_probe(struct i2c_client *i2c,\n" + "> const struct i2c_device_id *id)\n" + ">\n" + ">> +{\n" + ">> + int ret;\n" + ">> + struct ltc2990_data *ltc2990;\n" + ">> +\n" + ">> + if (!i2c_check_functionality(i2c->adapter,\n" + ">> I2C_FUNC_SMBUS_BYTE_DATA))\n" + ">> + return -ENODEV;\n" + ">> +\n" + ">> + ltc2990 = devm_kzalloc(&i2c->dev,\n" + ">> + sizeof(struct ltc2990_data), GFP_KERNEL);\n" + ">\n" + "> Please align continuation lines with '('.\n" + ">\n" + ">> + if (ltc2990 == NULL)\n" + ">> + return -ENOMEM;\n" + ">> +\n" + ">> + ret = ltc2990_read_byte(i2c, 0);\n" + ">> + if (ret < 0) {\n" + ">> + dev_err(&i2c->dev, \"Could not read LTC2990 on i2c bus.\\n\");\n" + ">> + return ret;\n" + ">> + }\n" + ">\n" + "> The write below would also return an error if the chip isn't there,\n" + "> so this additional read does not provide any real value.\n" + ">\n" + ">> + ret = ltc2990_write(i2c, LTC2990_CONTROL,\n" + ">> + LTC2990_CONTROL_SINGLE | LTC2990_CONTROL_MEASURE_ALL |\n" + ">> + LTC2990_CONTROL_MODE_CURRENT);\n" + ">\n" + "> I'll have to think about this. While it addresses your use case,\n" + "> it limits the scope of this driver significantly. Looking into the board\n" + "> specifications, you might as well do it right and determine (and set)\n" + "> the correct configuration using devicetree data instead of forcing your\n" + "> use case on everyone.\n" + ">\n" + "> Sure, you may argue that you don't care, but we will be the ones who\n" + "> will have\n" + "> to handle error reports that the driver unexpectedly changes the\n" + "> configuration\n" + "> in other use cases (where, for example, the mode may have been pre-set by\n" + "> the BIOS or ROMMON).\n" + "\n" + "The reason I didn't submit the driver last year was that I was still \n" + "thinking about it. On the other hand, a limited driver is still much \n" + "better than no driver at all, so that made me post it, with the added \n" + "remarks about the driver being limited.\n" + "\n" + "Adding the other functions it quite a bit more work than just writing \n" + "this register. It also changes the properties to be exported to sysfs, \n" + "and the calculation of the end values.\n" + "\n" + ">\n" + ">> + if (ret < 0) {\n" + ">> + dev_err(&i2c->dev, \"Error: Failed to set control mode.\\n\");\n" + ">> + return ret;\n" + ">> + }\n" + ">> +\n" + ">> + mutex_init(<c2990->update_lock);\n" + ">> + i2c_set_clientdata(i2c, ltc2990);\n" + ">> +\n" + ">> + /* Register sysfs hooks */\n" + ">> + ret = sysfs_create_group(&i2c->dev.kobj, <c2990_group);\n" + ">> + if (ret)\n" + ">> + return ret;\n" + ">> +\n" + ">> + ltc2990->hwmon_dev = hwmon_device_register(&i2c->dev);\n" + ">\n" + "> Please use devm_hwmon_device_register_with_groups().\n" + ">\n" + ">> + if (IS_ERR(ltc2990->hwmon_dev)) {\n" + ">> + ret = PTR_ERR(ltc2990->hwmon_dev);\n" + ">> + goto out_hwmon_device_register;\n" + ">> + }\n" + ">> +\n" + ">> + return 0;\n" + ">> +\n" + ">> +out_hwmon_device_register:\n" + ">> + sysfs_remove_group(&i2c->dev.kobj, <c2990_group);\n" + ">> + return ret;\n" + ">> +}\n" + ">> +\n" + ">> +static int ltc2990_i2c_remove(struct i2c_client *i2c)\n" + ">> +{\n" + ">> + struct ltc2990_data *ltc2990 = i2c_get_clientdata(i2c);\n" + ">> +\n" + ">> + hwmon_device_unregister(ltc2990->hwmon_dev);\n" + ">> + sysfs_remove_group(&i2c->dev.kobj, <c2990_group);\n" + ">> + return 0;\n" + ">> +}\n" + ">> +\n" + ">> +static const struct i2c_device_id ltc2990_i2c_id[] = {\n" + ">> + { \"ltc2990\", 0 },\n" + ">> + {}\n" + ">> +};\n" + ">> +MODULE_DEVICE_TABLE(i2c, ltc2990_i2c_id);\n" + ">> +\n" + ">> +static struct i2c_driver ltc2990_i2c_driver = {\n" + ">> + .driver = {\n" + ">> + .name = \"ltc2990\",\n" + ">> + },\n" + ">> + .probe = ltc2990_i2c_probe,\n" + ">> + .remove = ltc2990_i2c_remove,\n" + ">> + .id_table = ltc2990_i2c_id,\n" + ">> +};\n" + ">> +\n" + ">> +module_i2c_driver(ltc2990_i2c_driver);\n" + ">> +\n" + ">> +MODULE_DESCRIPTION(\"LTC2990 Sensor Driver\");\n" + ">> +MODULE_AUTHOR(\"Topic Embedded Products\");\n" + ">> +MODULE_LICENSE(\"GPL v2\");\n" + ">>\n" + ">\n" + "\n" + "\n" + "-- \n" + Mike Looijmans -9eea4df70acbde1829fbe7cd6e211a8761c9c57dc8e04b7fe788fc8167bf7835 +bc267d1278385396a5ad4fc179a6aca9a62b435f3bcc94ef5358e374d45f9540
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.