diff for duplicates of <20140708090315.3866.15604.stgit@localhost.localdomain> diff --git a/a/1.txt b/N1/1.txt index ab77646..b0e2de3 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -1,300 +1,568 @@ -VGhpcyBwYXRjaCBhZGRzIGJhc2ljIGtlcm5lbCBzdXBwb3J0IGZvciByZWFkaW5nIHBvd2VyIHZh -bHVlcywgZmFuCnNwZWVkIHJwbSwgdm9sdGFnZSBhbmQgdGVtcGVyYXR1cmUgZGF0YSBvbiBwb3dl -cm52IHBsYXRmb3JtcyB3aGljaAp3aWxsIGJlIGV4cG9ydGVkIHRvIHVzZXIgc3BhY2UgdGhyb3Vn -aCBzeXNmcyBpbnRlcmZhY2UuCgpUZXN0IHJlc3VsdHM6Ci0tLS0tLS0tLS0tLS0KW3Jvb3RAdHVs -MTYzcDEgfl0jIHNlbnNvcnMKaWJtcG93ZXJudi1pc2EtMDAwMApBZGFwdGVyOiBJU0EgYWRhcHRl -cgpmYW4xOiAgICAgICAgNTQ2NSBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFuMjogICAgICAgIDUx -NTIgUlBNICAobWluID0gICAgMCBSUE0pCmZhbjM6ICAgICAgICA1NTIxIFJQTSAgKG1pbiA9ICAg -IDAgUlBNKQpmYW40OiAgICAgICAgNDg5MSBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFuNTogICAg -ICAgICAgIDAgUlBNICAobWluID0gICAgMCBSUE0pCmZhbjY6ICAgICAgICAgICAwIFJQTSAgKG1p -biA9ICAgIDAgUlBNKQpmYW43OiAgICAgICAgNzQ4MCBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFu -ODogICAgICAgIDc5NDQgUlBNICAobWluID0gICAgMCBSUE0pCnRlbXAxOiAgICAgICAgKzM5LjDC -sEMgIChoaWdoID0gICswLjDCsEMpCnBvd2VyMTogICAgICAxOTAuMDAgVyAgCgpbcm9vdEB0dWwx -NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtLwphbGFybXRpbWVyICBpYm1wb3dlcm52 -LjAgIHBvd2VyICBydGMtZ2VuZXJpYyAgc2VyaWFsODI1MCAgdWV2ZW50Cltyb290QHR1bDE2M3Ax -IH5dIyBscyAvc3lzL2RldmljZXMvcGxhdGZvcm0vaWJtcG93ZXJudi4wL2h3bW9uL2h3bW9uMC8K -ZGV2aWNlCSAgICBmYW4yX21pbglmYW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAgIHBvd2Vy -CmZhbjFfZmF1bHQgIGZhbjNfZmF1bHQJZmFuNV9mYXVsdCAgZmFuN19mYXVsdAlpbjFfZmF1bHQg -IHBvd2VyMV9pbnB1dApmYW4xX2lucHV0ICBmYW4zX2lucHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5w -dXQJaW4yX2ZhdWx0ICBzdWJzeXN0ZW0KZmFuMV9taW4gICAgZmFuM19taW4JZmFuNV9taW4gICAg -ZmFuN19taW4JaW4zX2ZhdWx0ICB0ZW1wMV9pbnB1dApmYW4yX2ZhdWx0ICBmYW40X2ZhdWx0CWZh -bjZfZmF1bHQgIGZhbjhfZmF1bHQJaW40X2ZhdWx0ICB0ZW1wMV9tYXgKZmFuMl9pbnB1dCAgZmFu -NF9pbnB1dAlmYW42X2lucHV0ICBmYW44X2lucHV0CW5hbWUJICAgdWV2ZW50Cltyb290QHR1bDE2 -M3AxIH5dIyBscyAvc3lzL2NsYXNzL2h3bW9uL2h3bW9uMC8KZGV2aWNlCSAgICBmYW4yX21pbglm -YW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAgIHBvd2VyCmZhbjFfZmF1bHQgIGZhbjNfZmF1 -bHQJZmFuNV9mYXVsdCAgZmFuN19mYXVsdAlpbjFfZmF1bHQgIHBvd2VyMV9pbnB1dApmYW4xX2lu -cHV0ICBmYW4zX2lucHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5wdXQJaW4yX2ZhdWx0ICBzdWJzeXN0 -ZW0KZmFuMV9taW4gICAgZmFuM19taW4JZmFuNV9taW4gICAgZmFuN19taW4JaW4zX2ZhdWx0ICB0 -ZW1wMV9pbnB1dApmYW4yX2ZhdWx0ICBmYW40X2ZhdWx0CWZhbjZfZmF1bHQgIGZhbjhfZmF1bHQJ -aW40X2ZhdWx0ICB0ZW1wMV9tYXgKZmFuMl9pbnB1dCAgZmFuNF9pbnB1dAlmYW42X2lucHV0ICBm -YW44X2lucHV0CW5hbWUJICAgdWV2ZW50Cltyb290QHR1bDE2M3AxIH5dIwoKU2lnbmVkLW9mZi1i -eTogTmVlbGVzaCBHdXB0YSA8bmVlbGVndXBAbGludXgudm5ldC5pYm0uY29tPgpSZXZpZXdlZC1i -eTogR3VlbnRlciBSb2VjayA8bGludXhAcm9lY2stdXMubmV0PgotLS0KCkNoYW5nZXMgaW4gdjUK -PT09PT09PT09PT09PQotIEFkZHJlc3NlZCBjb3VwbGUgbWlub3IgY29tbWVudHMgaW4gdjQuCgpD -aGFuZ2VzIGluIHY0Cj09PT09PT09PT09PT0KLSBSZXBsYWNlZCBwcl9lcnIoKSB3aXRoIGRldl9l -cnIoKSBmb3IgbG9nZ2luZyBwcmludCBtZXNzYWdlcy4KLSBVc2luZyBrc3RydG91MzIoKSBmdW5j -dGlvbiBmb3IgY29udmVydGluZyBzdHJpbmcgdG8gdTMyIGluc3RlYWQgb2Ygc3NjYW5mKCkuCgpD -aGFuZ2VzIGluIHYzCj09PT09PT09PT09PT0KLSBGaXhlZCBhbiBlbmRpYW5uZXNzIGJ1ZyBsZWFk -aW5nIHRoZSBkcml2ZXIgdG8gYnJlYWsgb24gTEUuCi0gRml4ZWQgYSBidWcgdGhhdCB3aGVuIG9u -ZSBvZiB0aGUgJ2F0dHJpYnV0ZV9ncm91cCcgbm90IHBvcHVsYXRlZCwgZm9sbG93aW5nCiAgZ3Jv -dXBzIGF0dHJpYnV0ZXMgd2VyZSBkcm9wcGVkLgotIFJld3JpdGUgdGhlIGdldF9zZW5zb3JfaW5k -ZXhfYXR0cigpIGZ1bmN0aW9uIHRvIGhhbmRsZSBhbGwgdGhlIGVycm9yIHNjZW5hcmlvcwogIGxp -a2UgJ3NzY2FuZicgZXRjLgotIEZpeGVkIGFsbCB0aGUgZXJyb3JzL3dhcm5pbmdzIHJlbGF0ZWQg -dG8gY29kaW5nIHN0eWxlL3doaXRlc3BhY2UuCi0gQWRkZWQgJ0RvY3VtZW50YXRpb24nIGZpbGVz -LgotIEFkZHJlc3NlZCByZW1haW5pbmcgcmV2aWV3IGNvbW1lbnRzIG9uIFYyLgoKQ2hhbmdlcyBp -biB2Mgo9PT09PT09PT09PT09Ci0gR2VuZXJpYyB1c2Ugb2YgZGV2bV8qIGZ1bmN0aW9ucyBpbiBo -d21vbiBsaWtlIHVzaW5nIGRldm1fa3phbGxvYygpIGZvciBkeW5hbWljCiAgbWVtb3J5IHJlcXVl -c3QsIGF2b2lkaW5nIHRoZSBuZWVkIHRvIGV4cGxpY2l0IGZyZWUgb2YgbWVtb3J5LgogIEFkZGlu -ZyAnc3RydWN0IGF0dHJpYnV0ZV9ncm91cCcgYXMgbWVtYmVyIG9mIHBsYXRmb3JtIGRhdGEgc3Ry -dWN0dXJlIHRvIGJlCiAgcG9wdWxhdGVkIGFuZCB0aGVuIHBhc3NlZCB0byBkZXZtX2h3bW9uX2Rl -dmljZV9yZWdpc3Rlcl93aXRoX2dyb3VwcygpLgoKICBOb3RlOiBIYXZpbmcgYW4gYXJyYXkgb2Yg -cG9pbnRlcnMgb2YgJ2F0dHJpYnV0ZV9ncm91cCcgYW5kIGVhY2ggZ3JvdXAKICBjb3JyZXNwb25k -cyB0byAnZW51bSBzZW5zb3JzJyB0eXBlLiBOb3QgY29tcGxldGVseSBzdXJlLCBpZiBpdCdzIGlk -ZWFsIG9yCiAgY291bGQgaGF2ZSBqdXN0IG9uZSBncm91cCBwb3B1bGF0ZWQgd2l0aCBhdHRyaWJ1 -dGVzIG9mIHNlbnNvciB0eXBlcz8KCi0gJ2libXBvd2VybnYnIGlzIG5vdCBob3QtcGx1Z2dhYmxl -IGRldmljZSBzbyBtb3ZpbmcgJ3BsYXRmb3JtX2RyaXZlcicgY2FsbGJhY2sKICBmdW5jdGlvbiAo -cHJvYmUpIGFzIHBhcnQgb2YgX19pbml0IGNvZGUuCi0gRml4ZWQgaXNzdWVzIHJlbGF0ZWQgdG8g -Y29kaW5nIHN0eWxlLgotIE90aGVyIGdlbmVyYWwgY29tbWVudHMgaW4gdjEuCgogLi4uL2Rldmlj -ZXRyZWUvYmluZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQgICAgICAgfCAgIDIzICsKIERvY3Vt -ZW50YXRpb24vaHdtb24vaWJtcG93ZXJudiAgICAgICAgICAgICAgICAgICAgIHwgICA0MSArKwog -ZHJpdmVycy9od21vbi9LY29uZmlnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgIDEx -ICsKIGRyaXZlcnMvaHdtb24vTWFrZWZpbGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwg -ICAgMSAKIGRyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jICAgICAgICAgICAgICAgICAgICAgICAg -IHwgIDM2NCArKysrKysrKysrKysrKysrKysrKwogNSBmaWxlcyBjaGFuZ2VkLCA0NDAgaW5zZXJ0 -aW9ucygrKQogY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5k -aW5ncy9od21vbi9pYm1wb3dlcm52LnR4dAogY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRp -b24vaHdtb24vaWJtcG93ZXJudgogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvaHdtb24vaWJt -cG93ZXJudi5jCgpkaWZmIC0tZ2l0IGEvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdz -L2h3bW9uL2libXBvd2VybnYudHh0IGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdz -L2h3bW9uL2libXBvd2VybnYudHh0Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAu -LmY5MzI0MmIKLS0tIC9kZXYvbnVsbAorKysgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmlu -ZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQKQEAgLTAsMCArMSwyMyBAQAorSUJNIFBPV0VSTlYg -cGxhdGZvcm0gc2Vuc29ycworLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorCitSZXF1aXJl -ZCBub2RlIHByb3BlcnRpZXM6CistIGNvbXBhdGlibGU6IG11c3QgYmUgb25lIG9mCisJCSJpYm0s -b3BhbC1zZW5zb3ItY29vbGluZy1mYW4iCisJCSJpYm0sb3BhbC1zZW5zb3ItYW1iLXRlbXAiCisJ -CSJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3VwcGx5IgorCQkiaWJtLG9wYWwtc2Vuc29yLXBvd2Vy -IgorLSBzZW5zb3ItaWQ6IGFuIG9wYXF1ZSBpZCBwcm92aWRlZCBieSB0aGUgZmlybXdhcmUgdG8g -dGhlIGtlcm5lbCwgaWRlbnRpZmllcyBhCisJICAgICBnaXZlbiBzZW5zb3IgYW5kIGl0cyBhdHRy -aWJ1dGUgZGF0YQorCitFeGFtcGxlIHNlbnNvcnMgbm9kZToKKworY29vbGluZy1mYW4jOC1kYXRh -IHsKKwlzZW5zb3ItaWQgPSA8MHg3MDUyMTA3PjsKKwljb21wYXRpYmxlID0gImlibSxvcGFsLXNl -bnNvci1jb29saW5nLWZhbiI7Cit9OworCithbWItdGVtcCMxLXRocnMgeworCXNlbnNvci1pZCA9 -IDwweDUwOTYwMDA+OworCWNvbXBhdGlibGUgPSAiaWJtLG9wYWwtc2Vuc29yLWFtYi10ZW1wIjsK -K307CmRpZmYgLS1naXQgYS9Eb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYgYi9Eb2N1bWVu -dGF0aW9uL2h3bW9uL2libXBvd2VybnYKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAw -MC4uNjQ0MjQ1YQotLS0gL2Rldi9udWxsCisrKyBiL0RvY3VtZW50YXRpb24vaHdtb24vaWJtcG93 -ZXJudgpAQCAtMCwwICsxLDQxIEBACitLZXJuZWwgRHJpdmVyIElCTVBPV0VOVgorPT09PT09PT09 -PT09PT09PT09PT09PT0KKworU3VwcG9ydGVkIHN5c3RlbXM6CisgICogQW55IHJlY2VudCBJQk0g -UCBzZXJ2ZXJzIGJhc2VkIG9uIFBPV0VSTlYgcGxhdGZvcm0KKworQXV0aG9yOiBOZWVsZXNoIEd1 -cHRhCisKK0Rlc2NyaXB0aW9uCistLS0tLS0tLS0tLQorCitUaGlzIGRyaXZlciBpbXBsZW1lbnRz -IHJlYWRpbmcgdGhlIHBsYXRmb3JtIHNlbnNvcnMgZGF0YSBsaWtlIHRlbXBlcmF0dXJlL2Zhbi8K -K3ZvbHRhZ2UvcG93ZXIgZm9yICdQT1dFUk5WJyBwbGF0Zm9ybS4KKworVGhlIGRyaXZlciB1c2Vz -IHRoZSBwbGF0Zm9ybSBkZXZpY2UgaW5mcmFzdHJ1Y3R1cmUuIEl0IHByb2JlcyB0aGUgZGV2aWNl -IHRyZWUKK2ZvciBzZW5zb3IgZGV2aWNlcyBkdXJpbmcgdGhlIF9faW5pdCBwaGFzZSBhbmQgcmVn -aXN0ZXJzIHRoZW0gd2l0aCB0aGUgJ2h3bW9uJy4KKydod21vbicgcG9wdWxhdGVzIHRoZSAnc3lz -ZnMnIHRyZWUgaGF2aW5nIGF0dHJpYnV0ZSBmaWxlcywgZWFjaCBmb3IgYSBnaXZlbgorc2Vuc29y -IHR5cGUgYW5kIGl0cyBhdHRyaWJ1dGUgZGF0YS4KKworQWxsIHRoZSBub2RlcyBpbiB0aGUgRFQg -YXBwZWFyIHVuZGVyICIvaWJtLG9wYWwvc2Vuc29ycyIgYW5kIGVhY2ggdmFsaWQgbm9kZSBpbgor -dGhlIERUIG1hcHMgdG8gYW4gYXR0cmlidXRlIGZpbGUgaW4gJ3N5c2ZzJy4gVGhlIG5vZGUgZXhw -b3J0cyB1bmlxdWUgJ3NlbnNvci1pZCcKK3doaWNoIHRoZSBkcml2ZXIgdXNlcyB0byBtYWtlIGFu -IE9QQUwgY2FsbCB0byB0aGUgZmlybXdhcmUuCisKK1VzYWdlIG5vdGVzCistLS0tLS0tLS0tLQor -VGhlIGRyaXZlciBpcyBidWlsdCBzdGF0aWNhbGx5IHdpdGggdGhlIGtlcm5lbCBieSBlbmFibGlu -ZyB0aGUgY29uZmlnCitDT05GSUdfU0VOU09SU19JQk1QT1dFUk5WLiBJdCBjYW4gYWxzbyBiZSBi -dWlsdCBhcyBtb2R1bGUgJ2libXBvd2VybnYnLgorCitTeXNmcyBhdHRyaWJ1dGVzCistLS0tLS0t -LS0tLS0tLS0tCisKK2ZhblhfaW5wdXQJCU1lYXN1cmVkIFJQTSB2YWx1ZS4KK2ZhblhfbWluCQlU -aHJlc2hvbGQgUlBNIGZvciBhbGVydCBnZW5lcmF0aW9uLgorZmFuWF9mYXVsdAkJMDogTm8gZmFp -bCBjb25kaXRpb24KKwkJCTE6IEZhaWxpbmcgZmFuCit0ZW1wWF9pbnB1dAkJTWVhc3VyZWQgYW1i -aWVudCB0ZW1wZXJhdHVyZS4KK3RlbXBYX21heAkJVGhyZXNob2xkIGFtYmllbnQgdGVtcGVyYXR1 -cmUgZm9yIGFsZXJ0IGdlbmVyYXRpb24uCitpblhfaW5wdXQJCU1lYXN1cmVkIHBvd2VyIHN1cHBs -eSB2b2x0YWdlCitpblhfZmF1bHQJCTA6IE5vIGZhaWwgY29uZGl0aW9uLgorCQkJMTogRmFpbGlu -ZyBwb3dlciBzdXBwbHkuCitwb3dlcjFfaW5wdXQJCVN5c3RlbSBwb3dlciBjb25zdW1wdGlvbiAo -bWljcm9XYXR0KQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmlnIGIvZHJpdmVycy9o -d21vbi9LY29uZmlnCmluZGV4IDAyZDNkODUuLjI5YzNmY2IgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMv -aHdtb24vS2NvbmZpZworKysgYi9kcml2ZXJzL2h3bW9uL0tjb25maWcKQEAgLTU1NCw2ICs1NTQs -MTcgQEAgY29uZmlnIFNFTlNPUlNfSUJNUEVYCiAJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBi -dWlsdCBhcyBhIG1vZHVsZS4gIElmIHNvLCB0aGUgbW9kdWxlCiAJICB3aWxsIGJlIGNhbGxlZCBp -Ym1wZXguCiAKK2NvbmZpZyBTRU5TT1JTX0lCTVBPV0VSTlYKKwl0cmlzdGF0ZSAiSUJNIFBPV0VS -TlYgcGxhdGZvcm0gc2Vuc29ycyIKKwlkZXBlbmRzIG9uIFBQQ19QT1dFUk5WCisJZGVmYXVsdCB5 -CisJaGVscAorCSAgSWYgeW91IHNheSB5ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIHRoZSB0 -ZW1wZXJhdHVyZS9mYW4vcG93ZXIKKwkgIHNlbnNvcnMgb24geW91ciBQb3dlck5WIHBsYXRmb3Jt -LgorCisJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1vZHVsZS4gSWYgc28s -IHRoZSBtb2R1bGUKKwkgIHdpbGwgYmUgY2FsbGVkIGlibXBvd2VybnYuCisKIGNvbmZpZyBTRU5T -T1JTX0lJT19IV01PTgogCXRyaXN0YXRlICJId21vbiBkcml2ZXIgdGhhdCB1c2VzIGNoYW5uZWxz -IHNwZWNpZmllZCB2aWEgaWlvIG1hcHMiCiAJZGVwZW5kcyBvbiBJSU8KZGlmZiAtLWdpdCBhL2Ry -aXZlcnMvaHdtb24vTWFrZWZpbGUgYi9kcml2ZXJzL2h3bW9uL01ha2VmaWxlCmluZGV4IDNkYzBm -MDIuLmZjNGVkMjYgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKKysrIGIvZHJp -dmVycy9od21vbi9NYWtlZmlsZQpAQCAtNzEsNiArNzEsNyBAQCBvYmotJChDT05GSUdfU0VOU09S -U19VTFRSQTQ1KQkrPSB1bHRyYTQ1X2Vudi5vCiBvYmotJChDT05GSUdfU0VOU09SU19JNUtfQU1C -KQkrPSBpNWtfYW1iLm8KIG9iai0kKENPTkZJR19TRU5TT1JTX0lCTUFFTSkJKz0gaWJtYWVtLm8K -IG9iai0kKENPTkZJR19TRU5TT1JTX0lCTVBFWCkJKz0gaWJtcGV4Lm8KK29iai0kKENPTkZJR19T -RU5TT1JTX0lCTVBPV0VSTlYpKz0gaWJtcG93ZXJudi5vCiBvYmotJChDT05GSUdfU0VOU09SU19J -SU9fSFdNT04pICs9IGlpb19od21vbi5vCiBvYmotJChDT05GSUdfU0VOU09SU19JTkEyMDkpCSs9 -IGluYTIwOS5vCiBvYmotJChDT05GSUdfU0VOU09SU19JTkEyWFgpCSs9IGluYTJ4eC5vCmRpZmYg -LS1naXQgYS9kcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYyBiL2RyaXZlcnMvaHdtb24vaWJtcG93 -ZXJudi5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmU2YjY1MmEKLS0tIC9k -ZXYvbnVsbAorKysgYi9kcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYwpAQCAtMCwwICsxLDM2NCBA -QAorLyoKKyAqIElCTSBQb3dlck5WIHBsYXRmb3JtIHNlbnNvcnMgZm9yIHRlbXBlcmF0dXJlL2Zh -bi92b2x0YWdlL3Bvd2VyCisgKiBDb3B5cmlnaHQgKEMpIDIwMTQgSUJNCisgKgorICogVGhpcyBw -cm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBt -b2RpZnkKKyAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExp -Y2Vuc2UgYXMgcHVibGlzaGVkIGJ5CisgKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBl -aXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgorICogKGF0IHlvdXIgb3B0aW9uKSBh -bnkgbGF0ZXIgdmVyc2lvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4g -dGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKKyAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJS -QU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCisgKiBNRVJDSEFOVEFC -SUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCisgKiBH -TlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgorICoKKyAqIFlvdSBz -aG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNl -bnNlCisgKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS4KKyAqLworCisjZGVmaW5lIERSVk5BTUUJ -CSJpYm1wb3dlcm52IgorI2RlZmluZSBwcl9mbXQoZm10KQlEUlZOQU1FICI6ICIgZm10CisKKyNp -bmNsdWRlIDxsaW51eC9pbml0Lmg+CisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVk -ZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvaHdtb24uaD4KKyNpbmNsdWRlIDxs -aW51eC9od21vbi1zeXNmcy5oPgorI2luY2x1ZGUgPGxpbnV4L29mLmg+CisjaW5jbHVkZSA8bGlu -dXgvc2xhYi5oPgorCisjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+CisjaW5jbHVk -ZSA8YXNtL29wYWwuaD4KKyNpbmNsdWRlIDxsaW51eC9lcnIuaD4KKworI2RlZmluZSBNQVhfQVRU -Ul9MRU4JMzIKKworLyogU2Vuc29yIHN1ZmZpeCBuYW1lIGZyb20gRFQgKi8KKyNkZWZpbmUgRFRf -RkFVTFRfQVRUUl9TVUZGSVgJCSJmYXVsdGVkIgorI2RlZmluZSBEVF9EQVRBX0FUVFJfU1VGRklY -CQkiZGF0YSIKKyNkZWZpbmUgRFRfVEhSRVNIT0xEX0FUVFJfU1VGRklYCSJ0aHJzIgorCisvKgor -ICogRW51bWVyYXRlcyBhbGwgdGhlIHR5cGVzIG9mIHNlbnNvcnMgaW4gdGhlIFBPV0VSTlYgcGxh -dGZvcm0gYW5kIGRvZXMgaW5kZXgKKyAqIGludG8gJ3N0cnVjdCBzZW5zb3JfZ3JvdXAnCisgKi8K -K2VudW0gc2Vuc29ycyB7CisJRkFOLAorCUFNQklFTlRfVEVNUCwKKwlQT1dFUl9TVVBQTFksCisJ -UE9XRVJfSU5QVVQsCisJTUFYX1NFTlNPUl9UWVBFLAorfTsKKworc3RhdGljIHN0cnVjdCBzZW5z -b3JfZ3JvdXAgeworCWNvbnN0IGNoYXIgKm5hbWU7CisJY29uc3QgY2hhciAqY29tcGF0aWJsZTsK -KwlzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIGdyb3VwOworCXUzMiBhdHRyX2NvdW50OworfSBzZW5z -b3JfZ3JvdXBzW10gPSB7CisJeyJmYW4iLCAiaWJtLG9wYWwtc2Vuc29yLWNvb2xpbmctZmFuIn0s -CisJeyJ0ZW1wIiwgImlibSxvcGFsLXNlbnNvci1hbWItdGVtcCJ9LAorCXsiaW4iLCAiaWJtLG9w -YWwtc2Vuc29yLXBvd2VyLXN1cHBseSJ9LAorCXsicG93ZXIiLCAiaWJtLG9wYWwtc2Vuc29yLXBv -d2VyIn0KK307CisKK3N0cnVjdCBzZW5zb3JfZGF0YSB7CisJdTMyIGlkOyAvKiBBbiBvcGFxdWUg -aWQgb2YgdGhlIGZpcm13YXJlIGZvciBlYWNoIHNlbnNvciAqLworCWVudW0gc2Vuc29ycyB0eXBl -OworCWNoYXIgbmFtZVtNQVhfQVRUUl9MRU5dOworCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlIGRl -dl9hdHRyOworfTsKKworc3RydWN0IHBsYXRmb3JtX2RhdGEgeworCWNvbnN0IHN0cnVjdCBhdHRy -aWJ1dGVfZ3JvdXAgKmF0dHJfZ3JvdXBzW01BWF9TRU5TT1JfVFlQRSArIDFdOworCXUzMiBzZW5z -b3JzX2NvdW50OyAvKiBUb3RhbCBjb3VudCBvZiBzZW5zb3JzIGZyb20gZWFjaCBncm91cCAqLwor -fTsKKworLyogUGxhdGZvcm0gZGV2aWNlIHJlcHJlc2VudGluZyBhbGwgdGhlIGlibXBvd2VybnYg -c2Vuc29ycyAqLworc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXZpY2U7CisKK3N0 -YXRpYyBzc2l6ZV90IHNob3dfc2Vuc29yKHN0cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IGRldmlj -ZV9hdHRyaWJ1dGUgKmRldmF0dHIsCisJCQkgICBjaGFyICpidWYpCit7CisJc3RydWN0IHNlbnNv -cl9kYXRhICpzZGF0YSA9IGNvbnRhaW5lcl9vZihkZXZhdHRyLCBzdHJ1Y3Qgc2Vuc29yX2RhdGEs -CisJCQkJCQkgZGV2X2F0dHIpOworCXNzaXplX3QgcmV0OworCXUzMiB4OworCisJcmV0ID0gb3Bh -bF9nZXRfc2Vuc29yX2RhdGEoc2RhdGEtPmlkLCAmeCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJl -dDsKKworCS8qIENvbnZlcnQgdGVtcGVyYXR1cmUgdG8gbWlsbGktZGVncmVlcyAqLworCWlmIChz -ZGF0YS0+dHlwZSA9PSBBTUJJRU5UX1RFTVApCisJCXggKj0gMTAwMDsKKwkvKiBDb252ZXJ0IHBv -d2VyIHRvIG1pY3JvLXdhdHRzICovCisJZWxzZSBpZiAoc2RhdGEtPnR5cGUgPT0gUE9XRVJfSU5Q -VVQpCisJCXggKj0gMTAwMDAwMDsKKworCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiV1XG4iLCB4KTsK -K30KKworc3RhdGljIGludCBfX2luaXQgZ2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0IGNoYXIg -Km5hbWUsIHUzMiAqaW5kZXgsCisJCQkJCWNoYXIgKmF0dHIpCit7CisJY2hhciAqaGFzaF9wb3Mg -PSBzdHJjaHIobmFtZSwgJyMnKTsKKwljaGFyIGJ1Zls4XSA9IHsgMCB9OworCWNoYXIgKmRhc2hf -cG9zOworCXUzMiBjb3B5X2xlbjsKKwlpbnQgZXJyOworCisJaWYgKCFoYXNoX3BvcykKKwkJcmV0 -dXJuIC1FSU5WQUw7CisKKwlkYXNoX3BvcyA9IHN0cmNocihoYXNoX3BvcywgJy0nKTsKKwlpZiAo -IWRhc2hfcG9zKQorCQlyZXR1cm4gLUVJTlZBTDsKKworCWNvcHlfbGVuID0gZGFzaF9wb3MgLSBo -YXNoX3BvcyAtIDE7CisJaWYgKGNvcHlfbGVuID49IHNpemVvZihidWYpKQorCQlyZXR1cm4gLUVJ -TlZBTDsKKworCXN0cm5jcHkoYnVmLCBoYXNoX3BvcyArIDEsIGNvcHlfbGVuKTsKKworCWVyciA9 -IGtzdHJ0b3UzMihidWYsIDEwLCBpbmRleCk7CisJaWYgKGVycikKKwkJcmV0dXJuIGVycjsKKwor -CXN0cm5jcHkoYXR0ciwgZGFzaF9wb3MgKyAxLCBNQVhfQVRUUl9MRU4pOworCisJcmV0dXJuIDA7 -Cit9CisKKy8qCisgKiBUaGlzIGZ1bmN0aW9uIHRyYW5zbGF0ZXMgdGhlIERUIG5vZGUgbmFtZSBp -bnRvIHRoZSAnaHdtb24nIGF0dHJpYnV0ZSBuYW1lLgorICogSUJNUE9XRVJOViBkZXZpY2Ugbm9k -ZSBhcHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIGFtYi10ZW1wIzEtdGhycyBldGMuCisg -KiB3aGljaCBuZWVkIHRvIGJlIG1hcHBlZCBhcyBmYW4yX2lucHV0LCB0ZW1wMV9tYXggcmVzcGVj -dGl2ZWx5IGJlZm9yZQorICogcG9wdWxhdGluZyB0aGVtIGluc2lkZSBod21vbiBkZXZpY2UgY2xh -c3MuCisgKi8KK3N0YXRpYyBpbnQgX19pbml0IGNyZWF0ZV9od21vbl9hdHRyX25hbWUoc3RydWN0 -IGRldmljZSAqZGV2LCBlbnVtIHNlbnNvcnMgdHlwZSwKKwkJCQkJIGNvbnN0IGNoYXIgKm5vZGVf -bmFtZSwKKwkJCQkJIGNoYXIgKmh3bW9uX2F0dHJfbmFtZSkKK3sKKwljaGFyIGF0dHJfc3VmZml4 -W01BWF9BVFRSX0xFTl07CisJY2hhciAqYXR0cl9uYW1lOworCXUzMiBpbmRleDsKKwlpbnQgZXJy -OworCisJZXJyID0gZ2V0X3NlbnNvcl9pbmRleF9hdHRyKG5vZGVfbmFtZSwgJmluZGV4LCBhdHRy -X3N1ZmZpeCk7CisJaWYgKGVycikgeworCQlkZXZfZXJyKGRldiwgIlNlbnNvciBkZXZpY2Ugbm9k -ZSBuYW1lICclcycgaXMgaW52YWxpZFxuIiwKKwkJCW5vZGVfbmFtZSk7CisJCXJldHVybiBlcnI7 -CisJfQorCisJaWYgKCFzdHJjbXAoYXR0cl9zdWZmaXgsIERUX0ZBVUxUX0FUVFJfU1VGRklYKSkg -eworCQlhdHRyX25hbWUgPSAiZmF1bHQiOworCX0gZWxzZSBpZiAoIXN0cmNtcChhdHRyX3N1ZmZp -eCwgRFRfREFUQV9BVFRSX1NVRkZJWCkpIHsKKwkJYXR0cl9uYW1lID0gImlucHV0IjsKKwl9IGVs -c2UgaWYgKCFzdHJjbXAoYXR0cl9zdWZmaXgsIERUX1RIUkVTSE9MRF9BVFRSX1NVRkZJWCkpIHsK -KwkJaWYgKHR5cGUgPT0gQU1CSUVOVF9URU1QKQorCQkJYXR0cl9uYW1lID0gIm1heCI7CisJCWVs -c2UgaWYgKHR5cGUgPT0gRkFOKQorCQkJYXR0cl9uYW1lID0gIm1pbiI7CisJCWVsc2UKKwkJCXJl -dHVybiAtRU5PRU5UOworCX0gZWxzZSB7CisJCXJldHVybiAtRU5PRU5UOworCX0KKworCXNucHJp -bnRmKGh3bW9uX2F0dHJfbmFtZSwgTUFYX0FUVFJfTEVOLCAiJXMlZF8lcyIsCisJCSBzZW5zb3Jf -Z3JvdXBzW3R5cGVdLm5hbWUsIGluZGV4LCBhdHRyX25hbWUpOworCXJldHVybiAwOworfQorCitz -dGF0aWMgaW50IF9faW5pdCBwb3B1bGF0ZV9hdHRyX2dyb3VwcyhzdHJ1Y3QgcGxhdGZvcm1fZGV2 -aWNlICpwZGV2KQoreworCXN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YSA9IHBsYXRmb3JtX2dl -dF9kcnZkYXRhKHBkZXYpOworCWNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgKipwZ3JvdXBz -ID0gcGRhdGEtPmF0dHJfZ3JvdXBzOworCXN0cnVjdCBkZXZpY2Vfbm9kZSAqb3BhbCwgKm5wOwor -CWVudW0gc2Vuc29ycyB0eXBlOworCisJb3BhbCA9IG9mX2ZpbmRfbm9kZV9ieV9wYXRoKCIvaWJt -LG9wYWwvc2Vuc29ycyIpOworCWlmICghb3BhbCkgeworCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJP -cGFsIG5vZGUgJ3NlbnNvcnMnIG5vdCBmb3VuZFxuIik7CisJCXJldHVybiAtRU5PREVWOworCX0K -KworCWZvcl9lYWNoX2NoaWxkX29mX25vZGUob3BhbCwgbnApIHsKKwkJaWYgKG5wLT5uYW1lID09 -IE5VTEwpCisJCQljb250aW51ZTsKKworCQlmb3IgKHR5cGUgPSAwOyB0eXBlIDwgTUFYX1NFTlNP -Ul9UWVBFOyB0eXBlKyspCisJCQlpZiAob2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCisJCQkJ -CXNlbnNvcl9ncm91cHNbdHlwZV0uY29tcGF0aWJsZSkpIHsKKwkJCQlzZW5zb3JfZ3JvdXBzW3R5 -cGVdLmF0dHJfY291bnQrKzsKKwkJCQlicmVhazsKKwkJCX0KKwl9CisKKwlvZl9ub2RlX3B1dChv -cGFsKTsKKworCWZvciAodHlwZSA9IDA7IHR5cGUgPCBNQVhfU0VOU09SX1RZUEU7IHR5cGUrKykg -eworCQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJzID0gZGV2bV9remFsbG9jKCZwZGV2 -LT5kZXYsCisJCQkJCXNpemVvZihzdHJ1Y3QgYXR0cmlidXRlICopICoKKwkJCQkJKHNlbnNvcl9n -cm91cHNbdHlwZV0uYXR0cl9jb3VudCArIDEpLAorCQkJCQlHRlBfS0VSTkVMKTsKKwkJaWYgKCFz -ZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJzKQorCQkJcmV0dXJuIC1FTk9NRU07CisKKwkJ -cGdyb3Vwc1t0eXBlXSA9ICZzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwOworCQlwZGF0YS0+c2Vu -c29yc19jb3VudCArPSBzZW5zb3JfZ3JvdXBzW3R5cGVdLmF0dHJfY291bnQ7CisJCXNlbnNvcl9n -cm91cHNbdHlwZV0uYXR0cl9jb3VudCA9IDA7CisJfQorCisJcmV0dXJuIDA7Cit9CisKKy8qCisg -KiBJdGVyYXRlIHRocm91Z2ggdGhlIGRldmljZSB0cmVlIGZvciBlYWNoIGNoaWxkIG9mICdzZW5z -b3JzJyBub2RlLCBjcmVhdGUKKyAqIGEgc3lzZnMgYXR0cmlidXRlIGZpbGUsIHRoZSBmaWxlIGlz -IG5hbWVkIGJ5IHRyYW5zbGF0aW5nIHRoZSBEVCBub2RlIG5hbWUKKyAqIHRvIHRoZSBuYW1lIHJl -cXVpcmVkIGJ5IHRoZSBoaWdoZXIgJ2h3bW9uJyBkcml2ZXIgbGlrZSBmYW4xX2lucHV0LCB0ZW1w -MV9tYXgKKyAqIGV0Yy4uCisgKi8KK3N0YXRpYyBpbnQgX19pbml0IGNyZWF0ZV9kZXZpY2VfYXR0 -cnMoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKK3sKKwlzdHJ1Y3QgcGxhdGZvcm1fZGF0 -YSAqcGRhdGEgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKKwljb25zdCBzdHJ1Y3QgYXR0 -cmlidXRlX2dyb3VwICoqcGdyb3VwcyA9IHBkYXRhLT5hdHRyX2dyb3VwczsKKwlzdHJ1Y3QgZGV2 -aWNlX25vZGUgKm9wYWwsICpucDsKKwlzdHJ1Y3Qgc2Vuc29yX2RhdGEgKnNkYXRhOworCWNvbnN0 -IF9fYmUzMiAqc2Vuc29yX2lkOworCWVudW0gc2Vuc29ycyB0eXBlOworCXUzMiBjb3VudCA9IDA7 -CisJaW50IGVyciA9IDA7CisKKwlvcGFsID0gb2ZfZmluZF9ub2RlX2J5X3BhdGgoIi9pYm0sb3Bh -bC9zZW5zb3JzIik7CisJc2RhdGEgPSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRldiwgcGRhdGEtPnNl -bnNvcnNfY291bnQgKiBzaXplb2YoKnNkYXRhKSwKKwkJCSAgICAgR0ZQX0tFUk5FTCk7CisJaWYg -KCFzZGF0YSkgeworCQllcnIgPSAtRU5PTUVNOworCQlnb3RvIGV4aXRfcHV0X25vZGU7CisJfQor -CisJZm9yX2VhY2hfY2hpbGRfb2Zfbm9kZShvcGFsLCBucCkgeworCQlpZiAobnAtPm5hbWUgPT0g -TlVMTCkKKwkJCWNvbnRpbnVlOworCisJCWZvciAodHlwZSA9IDA7IHR5cGUgPCBNQVhfU0VOU09S -X1RZUEU7IHR5cGUrKykKKwkJCWlmIChvZl9kZXZpY2VfaXNfY29tcGF0aWJsZShucCwKKwkJCQkJ -c2Vuc29yX2dyb3Vwc1t0eXBlXS5jb21wYXRpYmxlKSkKKwkJCQlicmVhazsKKworCQlpZiAodHlw -ZSA9PSBNQVhfU0VOU09SX1RZUEUpCisJCQljb250aW51ZTsKKworCQlzZW5zb3JfaWQgPSBvZl9n -ZXRfcHJvcGVydHkobnAsICJzZW5zb3ItaWQiLCBOVUxMKTsKKwkJaWYgKCFzZW5zb3JfaWQpIHsK -KwkJCWRldl9pbmZvKCZwZGV2LT5kZXYsCisJCQkJICInc2Vuc29yLWlkJyBtaXNzaW5nIGluIHRo -ZSBub2RlICclcydcbiIsCisJCQkJIG5wLT5uYW1lKTsKKwkJCWNvbnRpbnVlOworCQl9CisKKwkJ -c2RhdGFbY291bnRdLmlkID0gYmUzMl90b19jcHVwKHNlbnNvcl9pZCk7CisJCXNkYXRhW2NvdW50 -XS50eXBlID0gdHlwZTsKKwkJZXJyID0gY3JlYXRlX2h3bW9uX2F0dHJfbmFtZSgmcGRldi0+ZGV2 -LCB0eXBlLCBucC0+bmFtZSwKKwkJCQkJICAgICBzZGF0YVtjb3VudF0ubmFtZSk7CisJCWlmIChl -cnIpCisJCQlnb3RvIGV4aXRfcHV0X25vZGU7CisKKwkJc3lzZnNfYXR0cl9pbml0KCZzZGF0YVtj -b3VudF0uZGV2X2F0dHIuYXR0cik7CisJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5hdHRyLm5hbWUg -PSBzZGF0YVtjb3VudF0ubmFtZTsKKwkJc2RhdGFbY291bnRdLmRldl9hdHRyLmF0dHIubW9kZSA9 -IFNfSVJVR087CisJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5zaG93ID0gc2hvd19zZW5zb3I7CisK -KwkJcGdyb3Vwc1t0eXBlXS0+YXR0cnNbc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRyX2NvdW50Kytd -ID0KKwkJCQkmc2RhdGFbY291bnQrK10uZGV2X2F0dHIuYXR0cjsKKwl9CisKK2V4aXRfcHV0X25v -ZGU6CisJb2Zfbm9kZV9wdXQob3BhbCk7CisJcmV0dXJuIGVycjsKK30KKworc3RhdGljIGludCBf -X2luaXQgaWJtcG93ZXJudl9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQorewor -CXN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YTsKKwlzdHJ1Y3QgZGV2aWNlICpod21vbl9kZXY7 -CisJaW50IGVycjsKKworCXBkYXRhID0gZGV2bV9remFsbG9jKCZwZGV2LT5kZXYsIHNpemVvZigq -cGRhdGEpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIXBkYXRhKQorCQlyZXR1cm4gLUVOT01FTTsKKwor -CXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIHBkYXRhKTsKKwlwZGF0YS0+c2Vuc29yc19jb3Vu -dCA9IDA7CisJZXJyID0gcG9wdWxhdGVfYXR0cl9ncm91cHMocGRldik7CisJaWYgKGVycikKKwkJ -cmV0dXJuIGVycjsKKworCS8qIENyZWF0ZSBzeXNmcyBhdHRyaWJ1dGUgZGF0YSBmb3IgZWFjaCBz -ZW5zb3IgZm91bmQgaW4gdGhlIERUICovCisJZXJyID0gY3JlYXRlX2RldmljZV9hdHRycyhwZGV2 -KTsKKwlpZiAoZXJyKQorCQlyZXR1cm4gZXJyOworCisJLyogRmluYWxseSwgcmVnaXN0ZXIgd2l0 -aCBod21vbiAqLworCWh3bW9uX2RldiA9IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhf -Z3JvdXBzKCZwZGV2LT5kZXYsIERSVk5BTUUsCisJCQkJCQkJICAgcGRhdGEsCisJCQkJCQkJICAg -cGRhdGEtPmF0dHJfZ3JvdXBzKTsKKworCXJldHVybiBQVFJfRVJSX09SX1pFUk8oaHdtb25fZGV2 -KTsKK30KKworc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgaWJtcG93ZXJudl9kcml2ZXIg -PSB7CisJLmRyaXZlciA9IHsKKwkJLm93bmVyID0gVEhJU19NT0RVTEUsCisJCS5uYW1lID0gRFJW -TkFNRSwKKwl9LAorfTsKKworc3RhdGljIGludCBfX2luaXQgaWJtcG93ZXJudl9pbml0KHZvaWQp -Cit7CisJaW50IGVycjsKKworCXBkZXZpY2UgPSBwbGF0Zm9ybV9kZXZpY2VfYWxsb2MoRFJWTkFN -RSwgMCk7CisJaWYgKCFwZGV2aWNlKSB7CisJCXByX2VycigiRGV2aWNlIGFsbG9jYXRpb24gZmFp -bGVkXG4iKTsKKwkJZXJyID0gLUVOT01FTTsKKwkJZ290byBleGl0OworCX0KKworCWVyciA9IHBs -YXRmb3JtX2RldmljZV9hZGQocGRldmljZSk7CisJaWYgKGVycikgeworCQlwcl9lcnIoIkRldmlj -ZSBhZGRpdGlvbiBmYWlsZWQgKCVkKVxuIiwgZXJyKTsKKwkJZ290byBleGl0X2RldmljZV9wdXQ7 -CisJfQorCisJZXJyID0gcGxhdGZvcm1fZHJpdmVyX3Byb2JlKCZpYm1wb3dlcm52X2RyaXZlciwg -aWJtcG93ZXJudl9wcm9iZSk7CisJaWYgKGVycikgeworCQlwcl9lcnIoIlBsYXRmcm9tIGRyaXZl -ciBwcm9iZSBmYWlsZWRcbiIpOworCQlnb3RvIGV4aXRfZGV2aWNlX2RlbDsKKwl9CisKKwlyZXR1 -cm4gMDsKKworZXhpdF9kZXZpY2VfZGVsOgorCXBsYXRmb3JtX2RldmljZV9kZWwocGRldmljZSk7 -CitleGl0X2RldmljZV9wdXQ6CisJcGxhdGZvcm1fZGV2aWNlX3B1dChwZGV2aWNlKTsKK2V4aXQ6 -CisJcmV0dXJuIGVycjsKK30KKworc3RhdGljIHZvaWQgX19leGl0IGlibXBvd2VybnZfZXhpdCh2 -b2lkKQoreworCXBsYXRmb3JtX2RyaXZlcl91bnJlZ2lzdGVyKCZpYm1wb3dlcm52X2RyaXZlcik7 -CisJcGxhdGZvcm1fZGV2aWNlX3VucmVnaXN0ZXIocGRldmljZSk7Cit9CisKK01PRFVMRV9BVVRI -T1IoIk5lZWxlc2ggR3VwdGEgPG5lZWxlZ3VwQGxpbnV4LnZuZXQuaWJtLmNvbT4iKTsKK01PRFVM -RV9ERVNDUklQVElPTigiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIpOworTU9EVUxFX0xJ -Q0VOU0UoIkdQTCIpOworCittb2R1bGVfaW5pdChpYm1wb3dlcm52X2luaXQpOworbW9kdWxlX2V4 -aXQoaWJtcG93ZXJudl9leGl0KTsKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f -X19fX19fX19fX19fXwpsbS1zZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3JzQGxtLXNlbnNv -cnMub3JnCmh0dHA6Ly9saXN0cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xtLXNl -bnNvcnM +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. + +Test results: +------------- +[root@tul163p1 ~]# sensors +ibmpowernv-isa-0000 +Adapter: ISA adapter +fan1: 5465 RPM (min = 0 RPM) +fan2: 5152 RPM (min = 0 RPM) +fan3: 5521 RPM (min = 0 RPM) +fan4: 4891 RPM (min = 0 RPM) +fan5: 0 RPM (min = 0 RPM) +fan6: 0 RPM (min = 0 RPM) +fan7: 7480 RPM (min = 0 RPM) +fan8: 7944 RPM (min = 0 RPM) +temp1: +39.0°C (high = +0.0°C) +power1: 190.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 ~]# 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> +Reviewed-by: Guenter Roeck <linux@roeck-us.net> +--- + +Changes in v5 +============= +- Addressed couple minor comments in v4. + +Changes in v4 +============= +- Replaced pr_err() with dev_err() for logging 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 | 23 + + Documentation/hwmon/ibmpowernv | 41 ++ + drivers/hwmon/Kconfig | 11 + + drivers/hwmon/Makefile | 1 + drivers/hwmon/ibmpowernv.c | 364 ++++++++++++++++++++ + 5 files changed, 440 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..f93242b +--- /dev/null ++++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt +@@ -0,0 +1,23 @@ ++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>; ++ compatible = "ibm,opal-sensor-cooling-fan"; ++}; ++ ++amb-temp#1-thrs { ++ sensor-id = <0x5096000>; ++ 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..e6b652a +--- /dev/null ++++ b/drivers/hwmon/ibmpowernv.c +@@ -0,0 +1,364 @@ ++/* ++ * 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; ++ int err; ++ ++ 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); ++ ++ 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 9d1a780..2fecda4 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -1,315 +1,581 @@ "From\0Neelesh Gupta <neelegup@linux.vnet.ibm.com>\0" - "Subject\0[lm-sensors] [PATCH v5] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature\0" - "Date\0Tue, 08 Jul 2014 09:20:38 +0000\0" - "To\0devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org" - linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@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 - jdelvare-l3A5Bk7waGM@public.gmane.org - " linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org\0" + "Subject\0[PATCH v5] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature\0" + "Date\0Tue, 08 Jul 2014 14:38:38 +0530\0" + "To\0devicetree@vger.kernel.org" + linuxppc-dev@lists.ozlabs.org + " lm-sensors@lm-sensors.org\0" + "Cc\0sbhat@linux.vnet.ibm.com" + linux@roeck-us.net + " jdelvare@suse.de\0" "\00:1\0" "b\0" - "VGhpcyBwYXRjaCBhZGRzIGJhc2ljIGtlcm5lbCBzdXBwb3J0IGZvciByZWFkaW5nIHBvd2VyIHZh\n" - "bHVlcywgZmFuCnNwZWVkIHJwbSwgdm9sdGFnZSBhbmQgdGVtcGVyYXR1cmUgZGF0YSBvbiBwb3dl\n" - "cm52IHBsYXRmb3JtcyB3aGljaAp3aWxsIGJlIGV4cG9ydGVkIHRvIHVzZXIgc3BhY2UgdGhyb3Vn\n" - "aCBzeXNmcyBpbnRlcmZhY2UuCgpUZXN0IHJlc3VsdHM6Ci0tLS0tLS0tLS0tLS0KW3Jvb3RAdHVs\n" - "MTYzcDEgfl0jIHNlbnNvcnMKaWJtcG93ZXJudi1pc2EtMDAwMApBZGFwdGVyOiBJU0EgYWRhcHRl\n" - "cgpmYW4xOiAgICAgICAgNTQ2NSBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFuMjogICAgICAgIDUx\n" - "NTIgUlBNICAobWluID0gICAgMCBSUE0pCmZhbjM6ICAgICAgICA1NTIxIFJQTSAgKG1pbiA9ICAg\n" - "IDAgUlBNKQpmYW40OiAgICAgICAgNDg5MSBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFuNTogICAg\n" - "ICAgICAgIDAgUlBNICAobWluID0gICAgMCBSUE0pCmZhbjY6ICAgICAgICAgICAwIFJQTSAgKG1p\n" - "biA9ICAgIDAgUlBNKQpmYW43OiAgICAgICAgNzQ4MCBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFu\n" - "ODogICAgICAgIDc5NDQgUlBNICAobWluID0gICAgMCBSUE0pCnRlbXAxOiAgICAgICAgKzM5LjDC\n" - "sEMgIChoaWdoID0gICswLjDCsEMpCnBvd2VyMTogICAgICAxOTAuMDAgVyAgCgpbcm9vdEB0dWwx\n" - "NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtLwphbGFybXRpbWVyICBpYm1wb3dlcm52\n" - "LjAgIHBvd2VyICBydGMtZ2VuZXJpYyAgc2VyaWFsODI1MCAgdWV2ZW50Cltyb290QHR1bDE2M3Ax\n" - "IH5dIyBscyAvc3lzL2RldmljZXMvcGxhdGZvcm0vaWJtcG93ZXJudi4wL2h3bW9uL2h3bW9uMC8K\n" - "ZGV2aWNlCSAgICBmYW4yX21pbglmYW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAgIHBvd2Vy\n" - "CmZhbjFfZmF1bHQgIGZhbjNfZmF1bHQJZmFuNV9mYXVsdCAgZmFuN19mYXVsdAlpbjFfZmF1bHQg\n" - "IHBvd2VyMV9pbnB1dApmYW4xX2lucHV0ICBmYW4zX2lucHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5w\n" - "dXQJaW4yX2ZhdWx0ICBzdWJzeXN0ZW0KZmFuMV9taW4gICAgZmFuM19taW4JZmFuNV9taW4gICAg\n" - "ZmFuN19taW4JaW4zX2ZhdWx0ICB0ZW1wMV9pbnB1dApmYW4yX2ZhdWx0ICBmYW40X2ZhdWx0CWZh\n" - "bjZfZmF1bHQgIGZhbjhfZmF1bHQJaW40X2ZhdWx0ICB0ZW1wMV9tYXgKZmFuMl9pbnB1dCAgZmFu\n" - "NF9pbnB1dAlmYW42X2lucHV0ICBmYW44X2lucHV0CW5hbWUJICAgdWV2ZW50Cltyb290QHR1bDE2\n" - "M3AxIH5dIyBscyAvc3lzL2NsYXNzL2h3bW9uL2h3bW9uMC8KZGV2aWNlCSAgICBmYW4yX21pbglm\n" - "YW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAgIHBvd2VyCmZhbjFfZmF1bHQgIGZhbjNfZmF1\n" - "bHQJZmFuNV9mYXVsdCAgZmFuN19mYXVsdAlpbjFfZmF1bHQgIHBvd2VyMV9pbnB1dApmYW4xX2lu\n" - "cHV0ICBmYW4zX2lucHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5wdXQJaW4yX2ZhdWx0ICBzdWJzeXN0\n" - "ZW0KZmFuMV9taW4gICAgZmFuM19taW4JZmFuNV9taW4gICAgZmFuN19taW4JaW4zX2ZhdWx0ICB0\n" - "ZW1wMV9pbnB1dApmYW4yX2ZhdWx0ICBmYW40X2ZhdWx0CWZhbjZfZmF1bHQgIGZhbjhfZmF1bHQJ\n" - "aW40X2ZhdWx0ICB0ZW1wMV9tYXgKZmFuMl9pbnB1dCAgZmFuNF9pbnB1dAlmYW42X2lucHV0ICBm\n" - "YW44X2lucHV0CW5hbWUJICAgdWV2ZW50Cltyb290QHR1bDE2M3AxIH5dIwoKU2lnbmVkLW9mZi1i\n" - "eTogTmVlbGVzaCBHdXB0YSA8bmVlbGVndXBAbGludXgudm5ldC5pYm0uY29tPgpSZXZpZXdlZC1i\n" - "eTogR3VlbnRlciBSb2VjayA8bGludXhAcm9lY2stdXMubmV0PgotLS0KCkNoYW5nZXMgaW4gdjUK\n" - "PT09PT09PT09PT09PQotIEFkZHJlc3NlZCBjb3VwbGUgbWlub3IgY29tbWVudHMgaW4gdjQuCgpD\n" - "aGFuZ2VzIGluIHY0Cj09PT09PT09PT09PT0KLSBSZXBsYWNlZCBwcl9lcnIoKSB3aXRoIGRldl9l\n" - "cnIoKSBmb3IgbG9nZ2luZyBwcmludCBtZXNzYWdlcy4KLSBVc2luZyBrc3RydG91MzIoKSBmdW5j\n" - "dGlvbiBmb3IgY29udmVydGluZyBzdHJpbmcgdG8gdTMyIGluc3RlYWQgb2Ygc3NjYW5mKCkuCgpD\n" - "aGFuZ2VzIGluIHYzCj09PT09PT09PT09PT0KLSBGaXhlZCBhbiBlbmRpYW5uZXNzIGJ1ZyBsZWFk\n" - "aW5nIHRoZSBkcml2ZXIgdG8gYnJlYWsgb24gTEUuCi0gRml4ZWQgYSBidWcgdGhhdCB3aGVuIG9u\n" - "ZSBvZiB0aGUgJ2F0dHJpYnV0ZV9ncm91cCcgbm90IHBvcHVsYXRlZCwgZm9sbG93aW5nCiAgZ3Jv\n" - "dXBzIGF0dHJpYnV0ZXMgd2VyZSBkcm9wcGVkLgotIFJld3JpdGUgdGhlIGdldF9zZW5zb3JfaW5k\n" - "ZXhfYXR0cigpIGZ1bmN0aW9uIHRvIGhhbmRsZSBhbGwgdGhlIGVycm9yIHNjZW5hcmlvcwogIGxp\n" - "a2UgJ3NzY2FuZicgZXRjLgotIEZpeGVkIGFsbCB0aGUgZXJyb3JzL3dhcm5pbmdzIHJlbGF0ZWQg\n" - "dG8gY29kaW5nIHN0eWxlL3doaXRlc3BhY2UuCi0gQWRkZWQgJ0RvY3VtZW50YXRpb24nIGZpbGVz\n" - "LgotIEFkZHJlc3NlZCByZW1haW5pbmcgcmV2aWV3IGNvbW1lbnRzIG9uIFYyLgoKQ2hhbmdlcyBp\n" - "biB2Mgo9PT09PT09PT09PT09Ci0gR2VuZXJpYyB1c2Ugb2YgZGV2bV8qIGZ1bmN0aW9ucyBpbiBo\n" - "d21vbiBsaWtlIHVzaW5nIGRldm1fa3phbGxvYygpIGZvciBkeW5hbWljCiAgbWVtb3J5IHJlcXVl\n" - "c3QsIGF2b2lkaW5nIHRoZSBuZWVkIHRvIGV4cGxpY2l0IGZyZWUgb2YgbWVtb3J5LgogIEFkZGlu\n" - "ZyAnc3RydWN0IGF0dHJpYnV0ZV9ncm91cCcgYXMgbWVtYmVyIG9mIHBsYXRmb3JtIGRhdGEgc3Ry\n" - "dWN0dXJlIHRvIGJlCiAgcG9wdWxhdGVkIGFuZCB0aGVuIHBhc3NlZCB0byBkZXZtX2h3bW9uX2Rl\n" - "dmljZV9yZWdpc3Rlcl93aXRoX2dyb3VwcygpLgoKICBOb3RlOiBIYXZpbmcgYW4gYXJyYXkgb2Yg\n" - "cG9pbnRlcnMgb2YgJ2F0dHJpYnV0ZV9ncm91cCcgYW5kIGVhY2ggZ3JvdXAKICBjb3JyZXNwb25k\n" - "cyB0byAnZW51bSBzZW5zb3JzJyB0eXBlLiBOb3QgY29tcGxldGVseSBzdXJlLCBpZiBpdCdzIGlk\n" - "ZWFsIG9yCiAgY291bGQgaGF2ZSBqdXN0IG9uZSBncm91cCBwb3B1bGF0ZWQgd2l0aCBhdHRyaWJ1\n" - "dGVzIG9mIHNlbnNvciB0eXBlcz8KCi0gJ2libXBvd2VybnYnIGlzIG5vdCBob3QtcGx1Z2dhYmxl\n" - "IGRldmljZSBzbyBtb3ZpbmcgJ3BsYXRmb3JtX2RyaXZlcicgY2FsbGJhY2sKICBmdW5jdGlvbiAo\n" - "cHJvYmUpIGFzIHBhcnQgb2YgX19pbml0IGNvZGUuCi0gRml4ZWQgaXNzdWVzIHJlbGF0ZWQgdG8g\n" - "Y29kaW5nIHN0eWxlLgotIE90aGVyIGdlbmVyYWwgY29tbWVudHMgaW4gdjEuCgogLi4uL2Rldmlj\n" - "ZXRyZWUvYmluZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQgICAgICAgfCAgIDIzICsKIERvY3Vt\n" - "ZW50YXRpb24vaHdtb24vaWJtcG93ZXJudiAgICAgICAgICAgICAgICAgICAgIHwgICA0MSArKwog\n" - "ZHJpdmVycy9od21vbi9LY29uZmlnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgIDEx\n" - "ICsKIGRyaXZlcnMvaHdtb24vTWFrZWZpbGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwg\n" - "ICAgMSAKIGRyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jICAgICAgICAgICAgICAgICAgICAgICAg\n" - "IHwgIDM2NCArKysrKysrKysrKysrKysrKysrKwogNSBmaWxlcyBjaGFuZ2VkLCA0NDAgaW5zZXJ0\n" - "aW9ucygrKQogY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5k\n" - "aW5ncy9od21vbi9pYm1wb3dlcm52LnR4dAogY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRp\n" - "b24vaHdtb24vaWJtcG93ZXJudgogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvaHdtb24vaWJt\n" - "cG93ZXJudi5jCgpkaWZmIC0tZ2l0IGEvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdz\n" - "L2h3bW9uL2libXBvd2VybnYudHh0IGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdz\n" - "L2h3bW9uL2libXBvd2VybnYudHh0Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAu\n" - "LmY5MzI0MmIKLS0tIC9kZXYvbnVsbAorKysgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmlu\n" - "ZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQKQEAgLTAsMCArMSwyMyBAQAorSUJNIFBPV0VSTlYg\n" - "cGxhdGZvcm0gc2Vuc29ycworLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorCitSZXF1aXJl\n" - "ZCBub2RlIHByb3BlcnRpZXM6CistIGNvbXBhdGlibGU6IG11c3QgYmUgb25lIG9mCisJCSJpYm0s\n" - "b3BhbC1zZW5zb3ItY29vbGluZy1mYW4iCisJCSJpYm0sb3BhbC1zZW5zb3ItYW1iLXRlbXAiCisJ\n" - "CSJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3VwcGx5IgorCQkiaWJtLG9wYWwtc2Vuc29yLXBvd2Vy\n" - "IgorLSBzZW5zb3ItaWQ6IGFuIG9wYXF1ZSBpZCBwcm92aWRlZCBieSB0aGUgZmlybXdhcmUgdG8g\n" - "dGhlIGtlcm5lbCwgaWRlbnRpZmllcyBhCisJICAgICBnaXZlbiBzZW5zb3IgYW5kIGl0cyBhdHRy\n" - "aWJ1dGUgZGF0YQorCitFeGFtcGxlIHNlbnNvcnMgbm9kZToKKworY29vbGluZy1mYW4jOC1kYXRh\n" - "IHsKKwlzZW5zb3ItaWQgPSA8MHg3MDUyMTA3PjsKKwljb21wYXRpYmxlID0gImlibSxvcGFsLXNl\n" - "bnNvci1jb29saW5nLWZhbiI7Cit9OworCithbWItdGVtcCMxLXRocnMgeworCXNlbnNvci1pZCA9\n" - "IDwweDUwOTYwMDA+OworCWNvbXBhdGlibGUgPSAiaWJtLG9wYWwtc2Vuc29yLWFtYi10ZW1wIjsK\n" - "K307CmRpZmYgLS1naXQgYS9Eb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYgYi9Eb2N1bWVu\n" - "dGF0aW9uL2h3bW9uL2libXBvd2VybnYKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAw\n" - "MC4uNjQ0MjQ1YQotLS0gL2Rldi9udWxsCisrKyBiL0RvY3VtZW50YXRpb24vaHdtb24vaWJtcG93\n" - "ZXJudgpAQCAtMCwwICsxLDQxIEBACitLZXJuZWwgRHJpdmVyIElCTVBPV0VOVgorPT09PT09PT09\n" - "PT09PT09PT09PT09PT0KKworU3VwcG9ydGVkIHN5c3RlbXM6CisgICogQW55IHJlY2VudCBJQk0g\n" - "UCBzZXJ2ZXJzIGJhc2VkIG9uIFBPV0VSTlYgcGxhdGZvcm0KKworQXV0aG9yOiBOZWVsZXNoIEd1\n" - "cHRhCisKK0Rlc2NyaXB0aW9uCistLS0tLS0tLS0tLQorCitUaGlzIGRyaXZlciBpbXBsZW1lbnRz\n" - "IHJlYWRpbmcgdGhlIHBsYXRmb3JtIHNlbnNvcnMgZGF0YSBsaWtlIHRlbXBlcmF0dXJlL2Zhbi8K\n" - "K3ZvbHRhZ2UvcG93ZXIgZm9yICdQT1dFUk5WJyBwbGF0Zm9ybS4KKworVGhlIGRyaXZlciB1c2Vz\n" - "IHRoZSBwbGF0Zm9ybSBkZXZpY2UgaW5mcmFzdHJ1Y3R1cmUuIEl0IHByb2JlcyB0aGUgZGV2aWNl\n" - "IHRyZWUKK2ZvciBzZW5zb3IgZGV2aWNlcyBkdXJpbmcgdGhlIF9faW5pdCBwaGFzZSBhbmQgcmVn\n" - "aXN0ZXJzIHRoZW0gd2l0aCB0aGUgJ2h3bW9uJy4KKydod21vbicgcG9wdWxhdGVzIHRoZSAnc3lz\n" - "ZnMnIHRyZWUgaGF2aW5nIGF0dHJpYnV0ZSBmaWxlcywgZWFjaCBmb3IgYSBnaXZlbgorc2Vuc29y\n" - "IHR5cGUgYW5kIGl0cyBhdHRyaWJ1dGUgZGF0YS4KKworQWxsIHRoZSBub2RlcyBpbiB0aGUgRFQg\n" - "YXBwZWFyIHVuZGVyICIvaWJtLG9wYWwvc2Vuc29ycyIgYW5kIGVhY2ggdmFsaWQgbm9kZSBpbgor\n" - "dGhlIERUIG1hcHMgdG8gYW4gYXR0cmlidXRlIGZpbGUgaW4gJ3N5c2ZzJy4gVGhlIG5vZGUgZXhw\n" - "b3J0cyB1bmlxdWUgJ3NlbnNvci1pZCcKK3doaWNoIHRoZSBkcml2ZXIgdXNlcyB0byBtYWtlIGFu\n" - "IE9QQUwgY2FsbCB0byB0aGUgZmlybXdhcmUuCisKK1VzYWdlIG5vdGVzCistLS0tLS0tLS0tLQor\n" - "VGhlIGRyaXZlciBpcyBidWlsdCBzdGF0aWNhbGx5IHdpdGggdGhlIGtlcm5lbCBieSBlbmFibGlu\n" - "ZyB0aGUgY29uZmlnCitDT05GSUdfU0VOU09SU19JQk1QT1dFUk5WLiBJdCBjYW4gYWxzbyBiZSBi\n" - "dWlsdCBhcyBtb2R1bGUgJ2libXBvd2VybnYnLgorCitTeXNmcyBhdHRyaWJ1dGVzCistLS0tLS0t\n" - "LS0tLS0tLS0tCisKK2ZhblhfaW5wdXQJCU1lYXN1cmVkIFJQTSB2YWx1ZS4KK2ZhblhfbWluCQlU\n" - "aHJlc2hvbGQgUlBNIGZvciBhbGVydCBnZW5lcmF0aW9uLgorZmFuWF9mYXVsdAkJMDogTm8gZmFp\n" - "bCBjb25kaXRpb24KKwkJCTE6IEZhaWxpbmcgZmFuCit0ZW1wWF9pbnB1dAkJTWVhc3VyZWQgYW1i\n" - "aWVudCB0ZW1wZXJhdHVyZS4KK3RlbXBYX21heAkJVGhyZXNob2xkIGFtYmllbnQgdGVtcGVyYXR1\n" - "cmUgZm9yIGFsZXJ0IGdlbmVyYXRpb24uCitpblhfaW5wdXQJCU1lYXN1cmVkIHBvd2VyIHN1cHBs\n" - "eSB2b2x0YWdlCitpblhfZmF1bHQJCTA6IE5vIGZhaWwgY29uZGl0aW9uLgorCQkJMTogRmFpbGlu\n" - "ZyBwb3dlciBzdXBwbHkuCitwb3dlcjFfaW5wdXQJCVN5c3RlbSBwb3dlciBjb25zdW1wdGlvbiAo\n" - "bWljcm9XYXR0KQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmlnIGIvZHJpdmVycy9o\n" - "d21vbi9LY29uZmlnCmluZGV4IDAyZDNkODUuLjI5YzNmY2IgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMv\n" - "aHdtb24vS2NvbmZpZworKysgYi9kcml2ZXJzL2h3bW9uL0tjb25maWcKQEAgLTU1NCw2ICs1NTQs\n" - "MTcgQEAgY29uZmlnIFNFTlNPUlNfSUJNUEVYCiAJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBi\n" - "dWlsdCBhcyBhIG1vZHVsZS4gIElmIHNvLCB0aGUgbW9kdWxlCiAJICB3aWxsIGJlIGNhbGxlZCBp\n" - "Ym1wZXguCiAKK2NvbmZpZyBTRU5TT1JTX0lCTVBPV0VSTlYKKwl0cmlzdGF0ZSAiSUJNIFBPV0VS\n" - "TlYgcGxhdGZvcm0gc2Vuc29ycyIKKwlkZXBlbmRzIG9uIFBQQ19QT1dFUk5WCisJZGVmYXVsdCB5\n" - "CisJaGVscAorCSAgSWYgeW91IHNheSB5ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIHRoZSB0\n" - "ZW1wZXJhdHVyZS9mYW4vcG93ZXIKKwkgIHNlbnNvcnMgb24geW91ciBQb3dlck5WIHBsYXRmb3Jt\n" - "LgorCisJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1vZHVsZS4gSWYgc28s\n" - "IHRoZSBtb2R1bGUKKwkgIHdpbGwgYmUgY2FsbGVkIGlibXBvd2VybnYuCisKIGNvbmZpZyBTRU5T\n" - "T1JTX0lJT19IV01PTgogCXRyaXN0YXRlICJId21vbiBkcml2ZXIgdGhhdCB1c2VzIGNoYW5uZWxz\n" - "IHNwZWNpZmllZCB2aWEgaWlvIG1hcHMiCiAJZGVwZW5kcyBvbiBJSU8KZGlmZiAtLWdpdCBhL2Ry\n" - "aXZlcnMvaHdtb24vTWFrZWZpbGUgYi9kcml2ZXJzL2h3bW9uL01ha2VmaWxlCmluZGV4IDNkYzBm\n" - "MDIuLmZjNGVkMjYgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKKysrIGIvZHJp\n" - "dmVycy9od21vbi9NYWtlZmlsZQpAQCAtNzEsNiArNzEsNyBAQCBvYmotJChDT05GSUdfU0VOU09S\n" - "U19VTFRSQTQ1KQkrPSB1bHRyYTQ1X2Vudi5vCiBvYmotJChDT05GSUdfU0VOU09SU19JNUtfQU1C\n" - "KQkrPSBpNWtfYW1iLm8KIG9iai0kKENPTkZJR19TRU5TT1JTX0lCTUFFTSkJKz0gaWJtYWVtLm8K\n" - "IG9iai0kKENPTkZJR19TRU5TT1JTX0lCTVBFWCkJKz0gaWJtcGV4Lm8KK29iai0kKENPTkZJR19T\n" - "RU5TT1JTX0lCTVBPV0VSTlYpKz0gaWJtcG93ZXJudi5vCiBvYmotJChDT05GSUdfU0VOU09SU19J\n" - "SU9fSFdNT04pICs9IGlpb19od21vbi5vCiBvYmotJChDT05GSUdfU0VOU09SU19JTkEyMDkpCSs9\n" - "IGluYTIwOS5vCiBvYmotJChDT05GSUdfU0VOU09SU19JTkEyWFgpCSs9IGluYTJ4eC5vCmRpZmYg\n" - "LS1naXQgYS9kcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYyBiL2RyaXZlcnMvaHdtb24vaWJtcG93\n" - "ZXJudi5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmU2YjY1MmEKLS0tIC9k\n" - "ZXYvbnVsbAorKysgYi9kcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYwpAQCAtMCwwICsxLDM2NCBA\n" - "QAorLyoKKyAqIElCTSBQb3dlck5WIHBsYXRmb3JtIHNlbnNvcnMgZm9yIHRlbXBlcmF0dXJlL2Zh\n" - "bi92b2x0YWdlL3Bvd2VyCisgKiBDb3B5cmlnaHQgKEMpIDIwMTQgSUJNCisgKgorICogVGhpcyBw\n" - "cm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBt\n" - "b2RpZnkKKyAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExp\n" - "Y2Vuc2UgYXMgcHVibGlzaGVkIGJ5CisgKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBl\n" - "aXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgorICogKGF0IHlvdXIgb3B0aW9uKSBh\n" - "bnkgbGF0ZXIgdmVyc2lvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4g\n" - "dGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKKyAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJS\n" - "QU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCisgKiBNRVJDSEFOVEFC\n" - "SUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCisgKiBH\n" - "TlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgorICoKKyAqIFlvdSBz\n" - "aG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNl\n" - "bnNlCisgKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS4KKyAqLworCisjZGVmaW5lIERSVk5BTUUJ\n" - "CSJpYm1wb3dlcm52IgorI2RlZmluZSBwcl9mbXQoZm10KQlEUlZOQU1FICI6ICIgZm10CisKKyNp\n" - "bmNsdWRlIDxsaW51eC9pbml0Lmg+CisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVk\n" - "ZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvaHdtb24uaD4KKyNpbmNsdWRlIDxs\n" - "aW51eC9od21vbi1zeXNmcy5oPgorI2luY2x1ZGUgPGxpbnV4L29mLmg+CisjaW5jbHVkZSA8bGlu\n" - "dXgvc2xhYi5oPgorCisjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+CisjaW5jbHVk\n" - "ZSA8YXNtL29wYWwuaD4KKyNpbmNsdWRlIDxsaW51eC9lcnIuaD4KKworI2RlZmluZSBNQVhfQVRU\n" - "Ul9MRU4JMzIKKworLyogU2Vuc29yIHN1ZmZpeCBuYW1lIGZyb20gRFQgKi8KKyNkZWZpbmUgRFRf\n" - "RkFVTFRfQVRUUl9TVUZGSVgJCSJmYXVsdGVkIgorI2RlZmluZSBEVF9EQVRBX0FUVFJfU1VGRklY\n" - "CQkiZGF0YSIKKyNkZWZpbmUgRFRfVEhSRVNIT0xEX0FUVFJfU1VGRklYCSJ0aHJzIgorCisvKgor\n" - "ICogRW51bWVyYXRlcyBhbGwgdGhlIHR5cGVzIG9mIHNlbnNvcnMgaW4gdGhlIFBPV0VSTlYgcGxh\n" - "dGZvcm0gYW5kIGRvZXMgaW5kZXgKKyAqIGludG8gJ3N0cnVjdCBzZW5zb3JfZ3JvdXAnCisgKi8K\n" - "K2VudW0gc2Vuc29ycyB7CisJRkFOLAorCUFNQklFTlRfVEVNUCwKKwlQT1dFUl9TVVBQTFksCisJ\n" - "UE9XRVJfSU5QVVQsCisJTUFYX1NFTlNPUl9UWVBFLAorfTsKKworc3RhdGljIHN0cnVjdCBzZW5z\n" - "b3JfZ3JvdXAgeworCWNvbnN0IGNoYXIgKm5hbWU7CisJY29uc3QgY2hhciAqY29tcGF0aWJsZTsK\n" - "KwlzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIGdyb3VwOworCXUzMiBhdHRyX2NvdW50OworfSBzZW5z\n" - "b3JfZ3JvdXBzW10gPSB7CisJeyJmYW4iLCAiaWJtLG9wYWwtc2Vuc29yLWNvb2xpbmctZmFuIn0s\n" - "CisJeyJ0ZW1wIiwgImlibSxvcGFsLXNlbnNvci1hbWItdGVtcCJ9LAorCXsiaW4iLCAiaWJtLG9w\n" - "YWwtc2Vuc29yLXBvd2VyLXN1cHBseSJ9LAorCXsicG93ZXIiLCAiaWJtLG9wYWwtc2Vuc29yLXBv\n" - "d2VyIn0KK307CisKK3N0cnVjdCBzZW5zb3JfZGF0YSB7CisJdTMyIGlkOyAvKiBBbiBvcGFxdWUg\n" - "aWQgb2YgdGhlIGZpcm13YXJlIGZvciBlYWNoIHNlbnNvciAqLworCWVudW0gc2Vuc29ycyB0eXBl\n" - "OworCWNoYXIgbmFtZVtNQVhfQVRUUl9MRU5dOworCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlIGRl\n" - "dl9hdHRyOworfTsKKworc3RydWN0IHBsYXRmb3JtX2RhdGEgeworCWNvbnN0IHN0cnVjdCBhdHRy\n" - "aWJ1dGVfZ3JvdXAgKmF0dHJfZ3JvdXBzW01BWF9TRU5TT1JfVFlQRSArIDFdOworCXUzMiBzZW5z\n" - "b3JzX2NvdW50OyAvKiBUb3RhbCBjb3VudCBvZiBzZW5zb3JzIGZyb20gZWFjaCBncm91cCAqLwor\n" - "fTsKKworLyogUGxhdGZvcm0gZGV2aWNlIHJlcHJlc2VudGluZyBhbGwgdGhlIGlibXBvd2VybnYg\n" - "c2Vuc29ycyAqLworc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXZpY2U7CisKK3N0\n" - "YXRpYyBzc2l6ZV90IHNob3dfc2Vuc29yKHN0cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IGRldmlj\n" - "ZV9hdHRyaWJ1dGUgKmRldmF0dHIsCisJCQkgICBjaGFyICpidWYpCit7CisJc3RydWN0IHNlbnNv\n" - "cl9kYXRhICpzZGF0YSA9IGNvbnRhaW5lcl9vZihkZXZhdHRyLCBzdHJ1Y3Qgc2Vuc29yX2RhdGEs\n" - "CisJCQkJCQkgZGV2X2F0dHIpOworCXNzaXplX3QgcmV0OworCXUzMiB4OworCisJcmV0ID0gb3Bh\n" - "bF9nZXRfc2Vuc29yX2RhdGEoc2RhdGEtPmlkLCAmeCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJl\n" - "dDsKKworCS8qIENvbnZlcnQgdGVtcGVyYXR1cmUgdG8gbWlsbGktZGVncmVlcyAqLworCWlmIChz\n" - "ZGF0YS0+dHlwZSA9PSBBTUJJRU5UX1RFTVApCisJCXggKj0gMTAwMDsKKwkvKiBDb252ZXJ0IHBv\n" - "d2VyIHRvIG1pY3JvLXdhdHRzICovCisJZWxzZSBpZiAoc2RhdGEtPnR5cGUgPT0gUE9XRVJfSU5Q\n" - "VVQpCisJCXggKj0gMTAwMDAwMDsKKworCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiV1XG4iLCB4KTsK\n" - "K30KKworc3RhdGljIGludCBfX2luaXQgZ2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0IGNoYXIg\n" - "Km5hbWUsIHUzMiAqaW5kZXgsCisJCQkJCWNoYXIgKmF0dHIpCit7CisJY2hhciAqaGFzaF9wb3Mg\n" - "PSBzdHJjaHIobmFtZSwgJyMnKTsKKwljaGFyIGJ1Zls4XSA9IHsgMCB9OworCWNoYXIgKmRhc2hf\n" - "cG9zOworCXUzMiBjb3B5X2xlbjsKKwlpbnQgZXJyOworCisJaWYgKCFoYXNoX3BvcykKKwkJcmV0\n" - "dXJuIC1FSU5WQUw7CisKKwlkYXNoX3BvcyA9IHN0cmNocihoYXNoX3BvcywgJy0nKTsKKwlpZiAo\n" - "IWRhc2hfcG9zKQorCQlyZXR1cm4gLUVJTlZBTDsKKworCWNvcHlfbGVuID0gZGFzaF9wb3MgLSBo\n" - "YXNoX3BvcyAtIDE7CisJaWYgKGNvcHlfbGVuID49IHNpemVvZihidWYpKQorCQlyZXR1cm4gLUVJ\n" - "TlZBTDsKKworCXN0cm5jcHkoYnVmLCBoYXNoX3BvcyArIDEsIGNvcHlfbGVuKTsKKworCWVyciA9\n" - "IGtzdHJ0b3UzMihidWYsIDEwLCBpbmRleCk7CisJaWYgKGVycikKKwkJcmV0dXJuIGVycjsKKwor\n" - "CXN0cm5jcHkoYXR0ciwgZGFzaF9wb3MgKyAxLCBNQVhfQVRUUl9MRU4pOworCisJcmV0dXJuIDA7\n" - "Cit9CisKKy8qCisgKiBUaGlzIGZ1bmN0aW9uIHRyYW5zbGF0ZXMgdGhlIERUIG5vZGUgbmFtZSBp\n" - "bnRvIHRoZSAnaHdtb24nIGF0dHJpYnV0ZSBuYW1lLgorICogSUJNUE9XRVJOViBkZXZpY2Ugbm9k\n" - "ZSBhcHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIGFtYi10ZW1wIzEtdGhycyBldGMuCisg\n" - "KiB3aGljaCBuZWVkIHRvIGJlIG1hcHBlZCBhcyBmYW4yX2lucHV0LCB0ZW1wMV9tYXggcmVzcGVj\n" - "dGl2ZWx5IGJlZm9yZQorICogcG9wdWxhdGluZyB0aGVtIGluc2lkZSBod21vbiBkZXZpY2UgY2xh\n" - "c3MuCisgKi8KK3N0YXRpYyBpbnQgX19pbml0IGNyZWF0ZV9od21vbl9hdHRyX25hbWUoc3RydWN0\n" - "IGRldmljZSAqZGV2LCBlbnVtIHNlbnNvcnMgdHlwZSwKKwkJCQkJIGNvbnN0IGNoYXIgKm5vZGVf\n" - "bmFtZSwKKwkJCQkJIGNoYXIgKmh3bW9uX2F0dHJfbmFtZSkKK3sKKwljaGFyIGF0dHJfc3VmZml4\n" - "W01BWF9BVFRSX0xFTl07CisJY2hhciAqYXR0cl9uYW1lOworCXUzMiBpbmRleDsKKwlpbnQgZXJy\n" - "OworCisJZXJyID0gZ2V0X3NlbnNvcl9pbmRleF9hdHRyKG5vZGVfbmFtZSwgJmluZGV4LCBhdHRy\n" - "X3N1ZmZpeCk7CisJaWYgKGVycikgeworCQlkZXZfZXJyKGRldiwgIlNlbnNvciBkZXZpY2Ugbm9k\n" - "ZSBuYW1lICclcycgaXMgaW52YWxpZFxuIiwKKwkJCW5vZGVfbmFtZSk7CisJCXJldHVybiBlcnI7\n" - "CisJfQorCisJaWYgKCFzdHJjbXAoYXR0cl9zdWZmaXgsIERUX0ZBVUxUX0FUVFJfU1VGRklYKSkg\n" - "eworCQlhdHRyX25hbWUgPSAiZmF1bHQiOworCX0gZWxzZSBpZiAoIXN0cmNtcChhdHRyX3N1ZmZp\n" - "eCwgRFRfREFUQV9BVFRSX1NVRkZJWCkpIHsKKwkJYXR0cl9uYW1lID0gImlucHV0IjsKKwl9IGVs\n" - "c2UgaWYgKCFzdHJjbXAoYXR0cl9zdWZmaXgsIERUX1RIUkVTSE9MRF9BVFRSX1NVRkZJWCkpIHsK\n" - "KwkJaWYgKHR5cGUgPT0gQU1CSUVOVF9URU1QKQorCQkJYXR0cl9uYW1lID0gIm1heCI7CisJCWVs\n" - "c2UgaWYgKHR5cGUgPT0gRkFOKQorCQkJYXR0cl9uYW1lID0gIm1pbiI7CisJCWVsc2UKKwkJCXJl\n" - "dHVybiAtRU5PRU5UOworCX0gZWxzZSB7CisJCXJldHVybiAtRU5PRU5UOworCX0KKworCXNucHJp\n" - "bnRmKGh3bW9uX2F0dHJfbmFtZSwgTUFYX0FUVFJfTEVOLCAiJXMlZF8lcyIsCisJCSBzZW5zb3Jf\n" - "Z3JvdXBzW3R5cGVdLm5hbWUsIGluZGV4LCBhdHRyX25hbWUpOworCXJldHVybiAwOworfQorCitz\n" - "dGF0aWMgaW50IF9faW5pdCBwb3B1bGF0ZV9hdHRyX2dyb3VwcyhzdHJ1Y3QgcGxhdGZvcm1fZGV2\n" - "aWNlICpwZGV2KQoreworCXN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YSA9IHBsYXRmb3JtX2dl\n" - "dF9kcnZkYXRhKHBkZXYpOworCWNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgKipwZ3JvdXBz\n" - "ID0gcGRhdGEtPmF0dHJfZ3JvdXBzOworCXN0cnVjdCBkZXZpY2Vfbm9kZSAqb3BhbCwgKm5wOwor\n" - "CWVudW0gc2Vuc29ycyB0eXBlOworCisJb3BhbCA9IG9mX2ZpbmRfbm9kZV9ieV9wYXRoKCIvaWJt\n" - "LG9wYWwvc2Vuc29ycyIpOworCWlmICghb3BhbCkgeworCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJP\n" - "cGFsIG5vZGUgJ3NlbnNvcnMnIG5vdCBmb3VuZFxuIik7CisJCXJldHVybiAtRU5PREVWOworCX0K\n" - "KworCWZvcl9lYWNoX2NoaWxkX29mX25vZGUob3BhbCwgbnApIHsKKwkJaWYgKG5wLT5uYW1lID09\n" - "IE5VTEwpCisJCQljb250aW51ZTsKKworCQlmb3IgKHR5cGUgPSAwOyB0eXBlIDwgTUFYX1NFTlNP\n" - "Ul9UWVBFOyB0eXBlKyspCisJCQlpZiAob2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCisJCQkJ\n" - "CXNlbnNvcl9ncm91cHNbdHlwZV0uY29tcGF0aWJsZSkpIHsKKwkJCQlzZW5zb3JfZ3JvdXBzW3R5\n" - "cGVdLmF0dHJfY291bnQrKzsKKwkJCQlicmVhazsKKwkJCX0KKwl9CisKKwlvZl9ub2RlX3B1dChv\n" - "cGFsKTsKKworCWZvciAodHlwZSA9IDA7IHR5cGUgPCBNQVhfU0VOU09SX1RZUEU7IHR5cGUrKykg\n" - "eworCQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJzID0gZGV2bV9remFsbG9jKCZwZGV2\n" - "LT5kZXYsCisJCQkJCXNpemVvZihzdHJ1Y3QgYXR0cmlidXRlICopICoKKwkJCQkJKHNlbnNvcl9n\n" - "cm91cHNbdHlwZV0uYXR0cl9jb3VudCArIDEpLAorCQkJCQlHRlBfS0VSTkVMKTsKKwkJaWYgKCFz\n" - "ZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJzKQorCQkJcmV0dXJuIC1FTk9NRU07CisKKwkJ\n" - "cGdyb3Vwc1t0eXBlXSA9ICZzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwOworCQlwZGF0YS0+c2Vu\n" - "c29yc19jb3VudCArPSBzZW5zb3JfZ3JvdXBzW3R5cGVdLmF0dHJfY291bnQ7CisJCXNlbnNvcl9n\n" - "cm91cHNbdHlwZV0uYXR0cl9jb3VudCA9IDA7CisJfQorCisJcmV0dXJuIDA7Cit9CisKKy8qCisg\n" - "KiBJdGVyYXRlIHRocm91Z2ggdGhlIGRldmljZSB0cmVlIGZvciBlYWNoIGNoaWxkIG9mICdzZW5z\n" - "b3JzJyBub2RlLCBjcmVhdGUKKyAqIGEgc3lzZnMgYXR0cmlidXRlIGZpbGUsIHRoZSBmaWxlIGlz\n" - "IG5hbWVkIGJ5IHRyYW5zbGF0aW5nIHRoZSBEVCBub2RlIG5hbWUKKyAqIHRvIHRoZSBuYW1lIHJl\n" - "cXVpcmVkIGJ5IHRoZSBoaWdoZXIgJ2h3bW9uJyBkcml2ZXIgbGlrZSBmYW4xX2lucHV0LCB0ZW1w\n" - "MV9tYXgKKyAqIGV0Yy4uCisgKi8KK3N0YXRpYyBpbnQgX19pbml0IGNyZWF0ZV9kZXZpY2VfYXR0\n" - "cnMoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKK3sKKwlzdHJ1Y3QgcGxhdGZvcm1fZGF0\n" - "YSAqcGRhdGEgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKKwljb25zdCBzdHJ1Y3QgYXR0\n" - "cmlidXRlX2dyb3VwICoqcGdyb3VwcyA9IHBkYXRhLT5hdHRyX2dyb3VwczsKKwlzdHJ1Y3QgZGV2\n" - "aWNlX25vZGUgKm9wYWwsICpucDsKKwlzdHJ1Y3Qgc2Vuc29yX2RhdGEgKnNkYXRhOworCWNvbnN0\n" - "IF9fYmUzMiAqc2Vuc29yX2lkOworCWVudW0gc2Vuc29ycyB0eXBlOworCXUzMiBjb3VudCA9IDA7\n" - "CisJaW50IGVyciA9IDA7CisKKwlvcGFsID0gb2ZfZmluZF9ub2RlX2J5X3BhdGgoIi9pYm0sb3Bh\n" - "bC9zZW5zb3JzIik7CisJc2RhdGEgPSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRldiwgcGRhdGEtPnNl\n" - "bnNvcnNfY291bnQgKiBzaXplb2YoKnNkYXRhKSwKKwkJCSAgICAgR0ZQX0tFUk5FTCk7CisJaWYg\n" - "KCFzZGF0YSkgeworCQllcnIgPSAtRU5PTUVNOworCQlnb3RvIGV4aXRfcHV0X25vZGU7CisJfQor\n" - "CisJZm9yX2VhY2hfY2hpbGRfb2Zfbm9kZShvcGFsLCBucCkgeworCQlpZiAobnAtPm5hbWUgPT0g\n" - "TlVMTCkKKwkJCWNvbnRpbnVlOworCisJCWZvciAodHlwZSA9IDA7IHR5cGUgPCBNQVhfU0VOU09S\n" - "X1RZUEU7IHR5cGUrKykKKwkJCWlmIChvZl9kZXZpY2VfaXNfY29tcGF0aWJsZShucCwKKwkJCQkJ\n" - "c2Vuc29yX2dyb3Vwc1t0eXBlXS5jb21wYXRpYmxlKSkKKwkJCQlicmVhazsKKworCQlpZiAodHlw\n" - "ZSA9PSBNQVhfU0VOU09SX1RZUEUpCisJCQljb250aW51ZTsKKworCQlzZW5zb3JfaWQgPSBvZl9n\n" - "ZXRfcHJvcGVydHkobnAsICJzZW5zb3ItaWQiLCBOVUxMKTsKKwkJaWYgKCFzZW5zb3JfaWQpIHsK\n" - "KwkJCWRldl9pbmZvKCZwZGV2LT5kZXYsCisJCQkJICInc2Vuc29yLWlkJyBtaXNzaW5nIGluIHRo\n" - "ZSBub2RlICclcydcbiIsCisJCQkJIG5wLT5uYW1lKTsKKwkJCWNvbnRpbnVlOworCQl9CisKKwkJ\n" - "c2RhdGFbY291bnRdLmlkID0gYmUzMl90b19jcHVwKHNlbnNvcl9pZCk7CisJCXNkYXRhW2NvdW50\n" - "XS50eXBlID0gdHlwZTsKKwkJZXJyID0gY3JlYXRlX2h3bW9uX2F0dHJfbmFtZSgmcGRldi0+ZGV2\n" - "LCB0eXBlLCBucC0+bmFtZSwKKwkJCQkJICAgICBzZGF0YVtjb3VudF0ubmFtZSk7CisJCWlmIChl\n" - "cnIpCisJCQlnb3RvIGV4aXRfcHV0X25vZGU7CisKKwkJc3lzZnNfYXR0cl9pbml0KCZzZGF0YVtj\n" - "b3VudF0uZGV2X2F0dHIuYXR0cik7CisJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5hdHRyLm5hbWUg\n" - "PSBzZGF0YVtjb3VudF0ubmFtZTsKKwkJc2RhdGFbY291bnRdLmRldl9hdHRyLmF0dHIubW9kZSA9\n" - "IFNfSVJVR087CisJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5zaG93ID0gc2hvd19zZW5zb3I7CisK\n" - "KwkJcGdyb3Vwc1t0eXBlXS0+YXR0cnNbc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRyX2NvdW50Kytd\n" - "ID0KKwkJCQkmc2RhdGFbY291bnQrK10uZGV2X2F0dHIuYXR0cjsKKwl9CisKK2V4aXRfcHV0X25v\n" - "ZGU6CisJb2Zfbm9kZV9wdXQob3BhbCk7CisJcmV0dXJuIGVycjsKK30KKworc3RhdGljIGludCBf\n" - "X2luaXQgaWJtcG93ZXJudl9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQorewor\n" - "CXN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YTsKKwlzdHJ1Y3QgZGV2aWNlICpod21vbl9kZXY7\n" - "CisJaW50IGVycjsKKworCXBkYXRhID0gZGV2bV9remFsbG9jKCZwZGV2LT5kZXYsIHNpemVvZigq\n" - "cGRhdGEpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIXBkYXRhKQorCQlyZXR1cm4gLUVOT01FTTsKKwor\n" - "CXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIHBkYXRhKTsKKwlwZGF0YS0+c2Vuc29yc19jb3Vu\n" - "dCA9IDA7CisJZXJyID0gcG9wdWxhdGVfYXR0cl9ncm91cHMocGRldik7CisJaWYgKGVycikKKwkJ\n" - "cmV0dXJuIGVycjsKKworCS8qIENyZWF0ZSBzeXNmcyBhdHRyaWJ1dGUgZGF0YSBmb3IgZWFjaCBz\n" - "ZW5zb3IgZm91bmQgaW4gdGhlIERUICovCisJZXJyID0gY3JlYXRlX2RldmljZV9hdHRycyhwZGV2\n" - "KTsKKwlpZiAoZXJyKQorCQlyZXR1cm4gZXJyOworCisJLyogRmluYWxseSwgcmVnaXN0ZXIgd2l0\n" - "aCBod21vbiAqLworCWh3bW9uX2RldiA9IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhf\n" - "Z3JvdXBzKCZwZGV2LT5kZXYsIERSVk5BTUUsCisJCQkJCQkJICAgcGRhdGEsCisJCQkJCQkJICAg\n" - "cGRhdGEtPmF0dHJfZ3JvdXBzKTsKKworCXJldHVybiBQVFJfRVJSX09SX1pFUk8oaHdtb25fZGV2\n" - "KTsKK30KKworc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgaWJtcG93ZXJudl9kcml2ZXIg\n" - "PSB7CisJLmRyaXZlciA9IHsKKwkJLm93bmVyID0gVEhJU19NT0RVTEUsCisJCS5uYW1lID0gRFJW\n" - "TkFNRSwKKwl9LAorfTsKKworc3RhdGljIGludCBfX2luaXQgaWJtcG93ZXJudl9pbml0KHZvaWQp\n" - "Cit7CisJaW50IGVycjsKKworCXBkZXZpY2UgPSBwbGF0Zm9ybV9kZXZpY2VfYWxsb2MoRFJWTkFN\n" - "RSwgMCk7CisJaWYgKCFwZGV2aWNlKSB7CisJCXByX2VycigiRGV2aWNlIGFsbG9jYXRpb24gZmFp\n" - "bGVkXG4iKTsKKwkJZXJyID0gLUVOT01FTTsKKwkJZ290byBleGl0OworCX0KKworCWVyciA9IHBs\n" - "YXRmb3JtX2RldmljZV9hZGQocGRldmljZSk7CisJaWYgKGVycikgeworCQlwcl9lcnIoIkRldmlj\n" - "ZSBhZGRpdGlvbiBmYWlsZWQgKCVkKVxuIiwgZXJyKTsKKwkJZ290byBleGl0X2RldmljZV9wdXQ7\n" - "CisJfQorCisJZXJyID0gcGxhdGZvcm1fZHJpdmVyX3Byb2JlKCZpYm1wb3dlcm52X2RyaXZlciwg\n" - "aWJtcG93ZXJudl9wcm9iZSk7CisJaWYgKGVycikgeworCQlwcl9lcnIoIlBsYXRmcm9tIGRyaXZl\n" - "ciBwcm9iZSBmYWlsZWRcbiIpOworCQlnb3RvIGV4aXRfZGV2aWNlX2RlbDsKKwl9CisKKwlyZXR1\n" - "cm4gMDsKKworZXhpdF9kZXZpY2VfZGVsOgorCXBsYXRmb3JtX2RldmljZV9kZWwocGRldmljZSk7\n" - "CitleGl0X2RldmljZV9wdXQ6CisJcGxhdGZvcm1fZGV2aWNlX3B1dChwZGV2aWNlKTsKK2V4aXQ6\n" - "CisJcmV0dXJuIGVycjsKK30KKworc3RhdGljIHZvaWQgX19leGl0IGlibXBvd2VybnZfZXhpdCh2\n" - "b2lkKQoreworCXBsYXRmb3JtX2RyaXZlcl91bnJlZ2lzdGVyKCZpYm1wb3dlcm52X2RyaXZlcik7\n" - "CisJcGxhdGZvcm1fZGV2aWNlX3VucmVnaXN0ZXIocGRldmljZSk7Cit9CisKK01PRFVMRV9BVVRI\n" - "T1IoIk5lZWxlc2ggR3VwdGEgPG5lZWxlZ3VwQGxpbnV4LnZuZXQuaWJtLmNvbT4iKTsKK01PRFVM\n" - "RV9ERVNDUklQVElPTigiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIpOworTU9EVUxFX0xJ\n" - "Q0VOU0UoIkdQTCIpOworCittb2R1bGVfaW5pdChpYm1wb3dlcm52X2luaXQpOworbW9kdWxlX2V4\n" - "aXQoaWJtcG93ZXJudl9leGl0KTsKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f\n" - "X19fX19fX19fX19fXwpsbS1zZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3JzQGxtLXNlbnNv\n" - "cnMub3JnCmh0dHA6Ly9saXN0cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xtLXNl\n" - bnNvcnM + "This patch adds basic kernel support for reading power values, fan\n" + "speed rpm, voltage and temperature data on powernv platforms which\n" + "will be exported to user space through sysfs interface.\n" + "\n" + "Test results:\n" + "-------------\n" + "[root@tul163p1 ~]# sensors\n" + "ibmpowernv-isa-0000\n" + "Adapter: ISA adapter\n" + "fan1: 5465 RPM (min = 0 RPM)\n" + "fan2: 5152 RPM (min = 0 RPM)\n" + "fan3: 5521 RPM (min = 0 RPM)\n" + "fan4: 4891 RPM (min = 0 RPM)\n" + "fan5: 0 RPM (min = 0 RPM)\n" + "fan6: 0 RPM (min = 0 RPM)\n" + "fan7: 7480 RPM (min = 0 RPM)\n" + "fan8: 7944 RPM (min = 0 RPM)\n" + "temp1: +39.0\302\260C (high = +0.0\302\260C)\n" + "power1: 190.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 ~]# 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" + "Reviewed-by: Guenter Roeck <linux@roeck-us.net>\n" + "---\n" + "\n" + "Changes in v5\n" + "=============\n" + "- Addressed couple minor comments in v4.\n" + "\n" + "Changes in v4\n" + "=============\n" + "- Replaced pr_err() with dev_err() for logging 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 | 23 +\n" + " Documentation/hwmon/ibmpowernv | 41 ++\n" + " drivers/hwmon/Kconfig | 11 +\n" + " drivers/hwmon/Makefile | 1 \n" + " drivers/hwmon/ibmpowernv.c | 364 ++++++++++++++++++++\n" + " 5 files changed, 440 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..f93242b\n" + "--- /dev/null\n" + "+++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt\n" + "@@ -0,0 +1,23 @@\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" + "+\tcompatible = \"ibm,opal-sensor-cooling-fan\";\n" + "+};\n" + "+\n" + "+amb-temp#1-thrs {\n" + "+\tsensor-id = <0x5096000>;\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..e6b652a\n" + "--- /dev/null\n" + "+++ b/drivers/hwmon/ibmpowernv.c\n" + "@@ -0,0 +1,364 @@\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" + "+\tint err;\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" + "+\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); -f99de827708da98eed28b6adde09d30b1a31d6a06d37cee5bb5aaa5c9ecec889 +064f29445fc63037fbef7f9046ad7f973a46ccbc7a10ad0867cdc34d96d64830
diff --git a/a/1.txt b/N2/1.txt index ab77646..3259e2d 100644 --- a/a/1.txt +++ b/N2/1.txt @@ -1,300 +1,573 @@ -VGhpcyBwYXRjaCBhZGRzIGJhc2ljIGtlcm5lbCBzdXBwb3J0IGZvciByZWFkaW5nIHBvd2VyIHZh -bHVlcywgZmFuCnNwZWVkIHJwbSwgdm9sdGFnZSBhbmQgdGVtcGVyYXR1cmUgZGF0YSBvbiBwb3dl -cm52IHBsYXRmb3JtcyB3aGljaAp3aWxsIGJlIGV4cG9ydGVkIHRvIHVzZXIgc3BhY2UgdGhyb3Vn -aCBzeXNmcyBpbnRlcmZhY2UuCgpUZXN0IHJlc3VsdHM6Ci0tLS0tLS0tLS0tLS0KW3Jvb3RAdHVs -MTYzcDEgfl0jIHNlbnNvcnMKaWJtcG93ZXJudi1pc2EtMDAwMApBZGFwdGVyOiBJU0EgYWRhcHRl -cgpmYW4xOiAgICAgICAgNTQ2NSBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFuMjogICAgICAgIDUx -NTIgUlBNICAobWluID0gICAgMCBSUE0pCmZhbjM6ICAgICAgICA1NTIxIFJQTSAgKG1pbiA9ICAg -IDAgUlBNKQpmYW40OiAgICAgICAgNDg5MSBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFuNTogICAg -ICAgICAgIDAgUlBNICAobWluID0gICAgMCBSUE0pCmZhbjY6ICAgICAgICAgICAwIFJQTSAgKG1p -biA9ICAgIDAgUlBNKQpmYW43OiAgICAgICAgNzQ4MCBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFu -ODogICAgICAgIDc5NDQgUlBNICAobWluID0gICAgMCBSUE0pCnRlbXAxOiAgICAgICAgKzM5LjDC -sEMgIChoaWdoID0gICswLjDCsEMpCnBvd2VyMTogICAgICAxOTAuMDAgVyAgCgpbcm9vdEB0dWwx -NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtLwphbGFybXRpbWVyICBpYm1wb3dlcm52 -LjAgIHBvd2VyICBydGMtZ2VuZXJpYyAgc2VyaWFsODI1MCAgdWV2ZW50Cltyb290QHR1bDE2M3Ax -IH5dIyBscyAvc3lzL2RldmljZXMvcGxhdGZvcm0vaWJtcG93ZXJudi4wL2h3bW9uL2h3bW9uMC8K -ZGV2aWNlCSAgICBmYW4yX21pbglmYW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAgIHBvd2Vy -CmZhbjFfZmF1bHQgIGZhbjNfZmF1bHQJZmFuNV9mYXVsdCAgZmFuN19mYXVsdAlpbjFfZmF1bHQg -IHBvd2VyMV9pbnB1dApmYW4xX2lucHV0ICBmYW4zX2lucHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5w -dXQJaW4yX2ZhdWx0ICBzdWJzeXN0ZW0KZmFuMV9taW4gICAgZmFuM19taW4JZmFuNV9taW4gICAg -ZmFuN19taW4JaW4zX2ZhdWx0ICB0ZW1wMV9pbnB1dApmYW4yX2ZhdWx0ICBmYW40X2ZhdWx0CWZh -bjZfZmF1bHQgIGZhbjhfZmF1bHQJaW40X2ZhdWx0ICB0ZW1wMV9tYXgKZmFuMl9pbnB1dCAgZmFu -NF9pbnB1dAlmYW42X2lucHV0ICBmYW44X2lucHV0CW5hbWUJICAgdWV2ZW50Cltyb290QHR1bDE2 -M3AxIH5dIyBscyAvc3lzL2NsYXNzL2h3bW9uL2h3bW9uMC8KZGV2aWNlCSAgICBmYW4yX21pbglm -YW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAgIHBvd2VyCmZhbjFfZmF1bHQgIGZhbjNfZmF1 -bHQJZmFuNV9mYXVsdCAgZmFuN19mYXVsdAlpbjFfZmF1bHQgIHBvd2VyMV9pbnB1dApmYW4xX2lu -cHV0ICBmYW4zX2lucHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5wdXQJaW4yX2ZhdWx0ICBzdWJzeXN0 -ZW0KZmFuMV9taW4gICAgZmFuM19taW4JZmFuNV9taW4gICAgZmFuN19taW4JaW4zX2ZhdWx0ICB0 -ZW1wMV9pbnB1dApmYW4yX2ZhdWx0ICBmYW40X2ZhdWx0CWZhbjZfZmF1bHQgIGZhbjhfZmF1bHQJ -aW40X2ZhdWx0ICB0ZW1wMV9tYXgKZmFuMl9pbnB1dCAgZmFuNF9pbnB1dAlmYW42X2lucHV0ICBm -YW44X2lucHV0CW5hbWUJICAgdWV2ZW50Cltyb290QHR1bDE2M3AxIH5dIwoKU2lnbmVkLW9mZi1i -eTogTmVlbGVzaCBHdXB0YSA8bmVlbGVndXBAbGludXgudm5ldC5pYm0uY29tPgpSZXZpZXdlZC1i -eTogR3VlbnRlciBSb2VjayA8bGludXhAcm9lY2stdXMubmV0PgotLS0KCkNoYW5nZXMgaW4gdjUK -PT09PT09PT09PT09PQotIEFkZHJlc3NlZCBjb3VwbGUgbWlub3IgY29tbWVudHMgaW4gdjQuCgpD -aGFuZ2VzIGluIHY0Cj09PT09PT09PT09PT0KLSBSZXBsYWNlZCBwcl9lcnIoKSB3aXRoIGRldl9l -cnIoKSBmb3IgbG9nZ2luZyBwcmludCBtZXNzYWdlcy4KLSBVc2luZyBrc3RydG91MzIoKSBmdW5j -dGlvbiBmb3IgY29udmVydGluZyBzdHJpbmcgdG8gdTMyIGluc3RlYWQgb2Ygc3NjYW5mKCkuCgpD -aGFuZ2VzIGluIHYzCj09PT09PT09PT09PT0KLSBGaXhlZCBhbiBlbmRpYW5uZXNzIGJ1ZyBsZWFk -aW5nIHRoZSBkcml2ZXIgdG8gYnJlYWsgb24gTEUuCi0gRml4ZWQgYSBidWcgdGhhdCB3aGVuIG9u -ZSBvZiB0aGUgJ2F0dHJpYnV0ZV9ncm91cCcgbm90IHBvcHVsYXRlZCwgZm9sbG93aW5nCiAgZ3Jv -dXBzIGF0dHJpYnV0ZXMgd2VyZSBkcm9wcGVkLgotIFJld3JpdGUgdGhlIGdldF9zZW5zb3JfaW5k -ZXhfYXR0cigpIGZ1bmN0aW9uIHRvIGhhbmRsZSBhbGwgdGhlIGVycm9yIHNjZW5hcmlvcwogIGxp -a2UgJ3NzY2FuZicgZXRjLgotIEZpeGVkIGFsbCB0aGUgZXJyb3JzL3dhcm5pbmdzIHJlbGF0ZWQg -dG8gY29kaW5nIHN0eWxlL3doaXRlc3BhY2UuCi0gQWRkZWQgJ0RvY3VtZW50YXRpb24nIGZpbGVz -LgotIEFkZHJlc3NlZCByZW1haW5pbmcgcmV2aWV3IGNvbW1lbnRzIG9uIFYyLgoKQ2hhbmdlcyBp -biB2Mgo9PT09PT09PT09PT09Ci0gR2VuZXJpYyB1c2Ugb2YgZGV2bV8qIGZ1bmN0aW9ucyBpbiBo -d21vbiBsaWtlIHVzaW5nIGRldm1fa3phbGxvYygpIGZvciBkeW5hbWljCiAgbWVtb3J5IHJlcXVl -c3QsIGF2b2lkaW5nIHRoZSBuZWVkIHRvIGV4cGxpY2l0IGZyZWUgb2YgbWVtb3J5LgogIEFkZGlu -ZyAnc3RydWN0IGF0dHJpYnV0ZV9ncm91cCcgYXMgbWVtYmVyIG9mIHBsYXRmb3JtIGRhdGEgc3Ry -dWN0dXJlIHRvIGJlCiAgcG9wdWxhdGVkIGFuZCB0aGVuIHBhc3NlZCB0byBkZXZtX2h3bW9uX2Rl -dmljZV9yZWdpc3Rlcl93aXRoX2dyb3VwcygpLgoKICBOb3RlOiBIYXZpbmcgYW4gYXJyYXkgb2Yg -cG9pbnRlcnMgb2YgJ2F0dHJpYnV0ZV9ncm91cCcgYW5kIGVhY2ggZ3JvdXAKICBjb3JyZXNwb25k -cyB0byAnZW51bSBzZW5zb3JzJyB0eXBlLiBOb3QgY29tcGxldGVseSBzdXJlLCBpZiBpdCdzIGlk -ZWFsIG9yCiAgY291bGQgaGF2ZSBqdXN0IG9uZSBncm91cCBwb3B1bGF0ZWQgd2l0aCBhdHRyaWJ1 -dGVzIG9mIHNlbnNvciB0eXBlcz8KCi0gJ2libXBvd2VybnYnIGlzIG5vdCBob3QtcGx1Z2dhYmxl -IGRldmljZSBzbyBtb3ZpbmcgJ3BsYXRmb3JtX2RyaXZlcicgY2FsbGJhY2sKICBmdW5jdGlvbiAo -cHJvYmUpIGFzIHBhcnQgb2YgX19pbml0IGNvZGUuCi0gRml4ZWQgaXNzdWVzIHJlbGF0ZWQgdG8g -Y29kaW5nIHN0eWxlLgotIE90aGVyIGdlbmVyYWwgY29tbWVudHMgaW4gdjEuCgogLi4uL2Rldmlj -ZXRyZWUvYmluZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQgICAgICAgfCAgIDIzICsKIERvY3Vt -ZW50YXRpb24vaHdtb24vaWJtcG93ZXJudiAgICAgICAgICAgICAgICAgICAgIHwgICA0MSArKwog -ZHJpdmVycy9od21vbi9LY29uZmlnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgIDEx -ICsKIGRyaXZlcnMvaHdtb24vTWFrZWZpbGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwg -ICAgMSAKIGRyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jICAgICAgICAgICAgICAgICAgICAgICAg -IHwgIDM2NCArKysrKysrKysrKysrKysrKysrKwogNSBmaWxlcyBjaGFuZ2VkLCA0NDAgaW5zZXJ0 -aW9ucygrKQogY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5k -aW5ncy9od21vbi9pYm1wb3dlcm52LnR4dAogY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRp -b24vaHdtb24vaWJtcG93ZXJudgogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvaHdtb24vaWJt -cG93ZXJudi5jCgpkaWZmIC0tZ2l0IGEvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdz -L2h3bW9uL2libXBvd2VybnYudHh0IGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdz -L2h3bW9uL2libXBvd2VybnYudHh0Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAu -LmY5MzI0MmIKLS0tIC9kZXYvbnVsbAorKysgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmlu -ZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQKQEAgLTAsMCArMSwyMyBAQAorSUJNIFBPV0VSTlYg -cGxhdGZvcm0gc2Vuc29ycworLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorCitSZXF1aXJl -ZCBub2RlIHByb3BlcnRpZXM6CistIGNvbXBhdGlibGU6IG11c3QgYmUgb25lIG9mCisJCSJpYm0s -b3BhbC1zZW5zb3ItY29vbGluZy1mYW4iCisJCSJpYm0sb3BhbC1zZW5zb3ItYW1iLXRlbXAiCisJ -CSJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3VwcGx5IgorCQkiaWJtLG9wYWwtc2Vuc29yLXBvd2Vy -IgorLSBzZW5zb3ItaWQ6IGFuIG9wYXF1ZSBpZCBwcm92aWRlZCBieSB0aGUgZmlybXdhcmUgdG8g -dGhlIGtlcm5lbCwgaWRlbnRpZmllcyBhCisJICAgICBnaXZlbiBzZW5zb3IgYW5kIGl0cyBhdHRy -aWJ1dGUgZGF0YQorCitFeGFtcGxlIHNlbnNvcnMgbm9kZToKKworY29vbGluZy1mYW4jOC1kYXRh -IHsKKwlzZW5zb3ItaWQgPSA8MHg3MDUyMTA3PjsKKwljb21wYXRpYmxlID0gImlibSxvcGFsLXNl -bnNvci1jb29saW5nLWZhbiI7Cit9OworCithbWItdGVtcCMxLXRocnMgeworCXNlbnNvci1pZCA9 -IDwweDUwOTYwMDA+OworCWNvbXBhdGlibGUgPSAiaWJtLG9wYWwtc2Vuc29yLWFtYi10ZW1wIjsK -K307CmRpZmYgLS1naXQgYS9Eb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYgYi9Eb2N1bWVu -dGF0aW9uL2h3bW9uL2libXBvd2VybnYKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAw -MC4uNjQ0MjQ1YQotLS0gL2Rldi9udWxsCisrKyBiL0RvY3VtZW50YXRpb24vaHdtb24vaWJtcG93 -ZXJudgpAQCAtMCwwICsxLDQxIEBACitLZXJuZWwgRHJpdmVyIElCTVBPV0VOVgorPT09PT09PT09 -PT09PT09PT09PT09PT0KKworU3VwcG9ydGVkIHN5c3RlbXM6CisgICogQW55IHJlY2VudCBJQk0g -UCBzZXJ2ZXJzIGJhc2VkIG9uIFBPV0VSTlYgcGxhdGZvcm0KKworQXV0aG9yOiBOZWVsZXNoIEd1 -cHRhCisKK0Rlc2NyaXB0aW9uCistLS0tLS0tLS0tLQorCitUaGlzIGRyaXZlciBpbXBsZW1lbnRz -IHJlYWRpbmcgdGhlIHBsYXRmb3JtIHNlbnNvcnMgZGF0YSBsaWtlIHRlbXBlcmF0dXJlL2Zhbi8K -K3ZvbHRhZ2UvcG93ZXIgZm9yICdQT1dFUk5WJyBwbGF0Zm9ybS4KKworVGhlIGRyaXZlciB1c2Vz -IHRoZSBwbGF0Zm9ybSBkZXZpY2UgaW5mcmFzdHJ1Y3R1cmUuIEl0IHByb2JlcyB0aGUgZGV2aWNl -IHRyZWUKK2ZvciBzZW5zb3IgZGV2aWNlcyBkdXJpbmcgdGhlIF9faW5pdCBwaGFzZSBhbmQgcmVn -aXN0ZXJzIHRoZW0gd2l0aCB0aGUgJ2h3bW9uJy4KKydod21vbicgcG9wdWxhdGVzIHRoZSAnc3lz -ZnMnIHRyZWUgaGF2aW5nIGF0dHJpYnV0ZSBmaWxlcywgZWFjaCBmb3IgYSBnaXZlbgorc2Vuc29y -IHR5cGUgYW5kIGl0cyBhdHRyaWJ1dGUgZGF0YS4KKworQWxsIHRoZSBub2RlcyBpbiB0aGUgRFQg -YXBwZWFyIHVuZGVyICIvaWJtLG9wYWwvc2Vuc29ycyIgYW5kIGVhY2ggdmFsaWQgbm9kZSBpbgor -dGhlIERUIG1hcHMgdG8gYW4gYXR0cmlidXRlIGZpbGUgaW4gJ3N5c2ZzJy4gVGhlIG5vZGUgZXhw -b3J0cyB1bmlxdWUgJ3NlbnNvci1pZCcKK3doaWNoIHRoZSBkcml2ZXIgdXNlcyB0byBtYWtlIGFu -IE9QQUwgY2FsbCB0byB0aGUgZmlybXdhcmUuCisKK1VzYWdlIG5vdGVzCistLS0tLS0tLS0tLQor -VGhlIGRyaXZlciBpcyBidWlsdCBzdGF0aWNhbGx5IHdpdGggdGhlIGtlcm5lbCBieSBlbmFibGlu -ZyB0aGUgY29uZmlnCitDT05GSUdfU0VOU09SU19JQk1QT1dFUk5WLiBJdCBjYW4gYWxzbyBiZSBi -dWlsdCBhcyBtb2R1bGUgJ2libXBvd2VybnYnLgorCitTeXNmcyBhdHRyaWJ1dGVzCistLS0tLS0t -LS0tLS0tLS0tCisKK2ZhblhfaW5wdXQJCU1lYXN1cmVkIFJQTSB2YWx1ZS4KK2ZhblhfbWluCQlU -aHJlc2hvbGQgUlBNIGZvciBhbGVydCBnZW5lcmF0aW9uLgorZmFuWF9mYXVsdAkJMDogTm8gZmFp -bCBjb25kaXRpb24KKwkJCTE6IEZhaWxpbmcgZmFuCit0ZW1wWF9pbnB1dAkJTWVhc3VyZWQgYW1i -aWVudCB0ZW1wZXJhdHVyZS4KK3RlbXBYX21heAkJVGhyZXNob2xkIGFtYmllbnQgdGVtcGVyYXR1 -cmUgZm9yIGFsZXJ0IGdlbmVyYXRpb24uCitpblhfaW5wdXQJCU1lYXN1cmVkIHBvd2VyIHN1cHBs -eSB2b2x0YWdlCitpblhfZmF1bHQJCTA6IE5vIGZhaWwgY29uZGl0aW9uLgorCQkJMTogRmFpbGlu -ZyBwb3dlciBzdXBwbHkuCitwb3dlcjFfaW5wdXQJCVN5c3RlbSBwb3dlciBjb25zdW1wdGlvbiAo -bWljcm9XYXR0KQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmlnIGIvZHJpdmVycy9o -d21vbi9LY29uZmlnCmluZGV4IDAyZDNkODUuLjI5YzNmY2IgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMv -aHdtb24vS2NvbmZpZworKysgYi9kcml2ZXJzL2h3bW9uL0tjb25maWcKQEAgLTU1NCw2ICs1NTQs -MTcgQEAgY29uZmlnIFNFTlNPUlNfSUJNUEVYCiAJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBi -dWlsdCBhcyBhIG1vZHVsZS4gIElmIHNvLCB0aGUgbW9kdWxlCiAJICB3aWxsIGJlIGNhbGxlZCBp -Ym1wZXguCiAKK2NvbmZpZyBTRU5TT1JTX0lCTVBPV0VSTlYKKwl0cmlzdGF0ZSAiSUJNIFBPV0VS -TlYgcGxhdGZvcm0gc2Vuc29ycyIKKwlkZXBlbmRzIG9uIFBQQ19QT1dFUk5WCisJZGVmYXVsdCB5 -CisJaGVscAorCSAgSWYgeW91IHNheSB5ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIHRoZSB0 -ZW1wZXJhdHVyZS9mYW4vcG93ZXIKKwkgIHNlbnNvcnMgb24geW91ciBQb3dlck5WIHBsYXRmb3Jt -LgorCisJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1vZHVsZS4gSWYgc28s -IHRoZSBtb2R1bGUKKwkgIHdpbGwgYmUgY2FsbGVkIGlibXBvd2VybnYuCisKIGNvbmZpZyBTRU5T -T1JTX0lJT19IV01PTgogCXRyaXN0YXRlICJId21vbiBkcml2ZXIgdGhhdCB1c2VzIGNoYW5uZWxz -IHNwZWNpZmllZCB2aWEgaWlvIG1hcHMiCiAJZGVwZW5kcyBvbiBJSU8KZGlmZiAtLWdpdCBhL2Ry -aXZlcnMvaHdtb24vTWFrZWZpbGUgYi9kcml2ZXJzL2h3bW9uL01ha2VmaWxlCmluZGV4IDNkYzBm -MDIuLmZjNGVkMjYgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKKysrIGIvZHJp -dmVycy9od21vbi9NYWtlZmlsZQpAQCAtNzEsNiArNzEsNyBAQCBvYmotJChDT05GSUdfU0VOU09S -U19VTFRSQTQ1KQkrPSB1bHRyYTQ1X2Vudi5vCiBvYmotJChDT05GSUdfU0VOU09SU19JNUtfQU1C -KQkrPSBpNWtfYW1iLm8KIG9iai0kKENPTkZJR19TRU5TT1JTX0lCTUFFTSkJKz0gaWJtYWVtLm8K -IG9iai0kKENPTkZJR19TRU5TT1JTX0lCTVBFWCkJKz0gaWJtcGV4Lm8KK29iai0kKENPTkZJR19T -RU5TT1JTX0lCTVBPV0VSTlYpKz0gaWJtcG93ZXJudi5vCiBvYmotJChDT05GSUdfU0VOU09SU19J -SU9fSFdNT04pICs9IGlpb19od21vbi5vCiBvYmotJChDT05GSUdfU0VOU09SU19JTkEyMDkpCSs9 -IGluYTIwOS5vCiBvYmotJChDT05GSUdfU0VOU09SU19JTkEyWFgpCSs9IGluYTJ4eC5vCmRpZmYg -LS1naXQgYS9kcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYyBiL2RyaXZlcnMvaHdtb24vaWJtcG93 -ZXJudi5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmU2YjY1MmEKLS0tIC9k -ZXYvbnVsbAorKysgYi9kcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYwpAQCAtMCwwICsxLDM2NCBA -QAorLyoKKyAqIElCTSBQb3dlck5WIHBsYXRmb3JtIHNlbnNvcnMgZm9yIHRlbXBlcmF0dXJlL2Zh -bi92b2x0YWdlL3Bvd2VyCisgKiBDb3B5cmlnaHQgKEMpIDIwMTQgSUJNCisgKgorICogVGhpcyBw -cm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBt -b2RpZnkKKyAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExp -Y2Vuc2UgYXMgcHVibGlzaGVkIGJ5CisgKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBl -aXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgorICogKGF0IHlvdXIgb3B0aW9uKSBh -bnkgbGF0ZXIgdmVyc2lvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4g -dGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKKyAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJS -QU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCisgKiBNRVJDSEFOVEFC -SUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCisgKiBH -TlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgorICoKKyAqIFlvdSBz -aG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNl -bnNlCisgKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS4KKyAqLworCisjZGVmaW5lIERSVk5BTUUJ -CSJpYm1wb3dlcm52IgorI2RlZmluZSBwcl9mbXQoZm10KQlEUlZOQU1FICI6ICIgZm10CisKKyNp -bmNsdWRlIDxsaW51eC9pbml0Lmg+CisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVk -ZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvaHdtb24uaD4KKyNpbmNsdWRlIDxs -aW51eC9od21vbi1zeXNmcy5oPgorI2luY2x1ZGUgPGxpbnV4L29mLmg+CisjaW5jbHVkZSA8bGlu -dXgvc2xhYi5oPgorCisjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+CisjaW5jbHVk -ZSA8YXNtL29wYWwuaD4KKyNpbmNsdWRlIDxsaW51eC9lcnIuaD4KKworI2RlZmluZSBNQVhfQVRU -Ul9MRU4JMzIKKworLyogU2Vuc29yIHN1ZmZpeCBuYW1lIGZyb20gRFQgKi8KKyNkZWZpbmUgRFRf -RkFVTFRfQVRUUl9TVUZGSVgJCSJmYXVsdGVkIgorI2RlZmluZSBEVF9EQVRBX0FUVFJfU1VGRklY -CQkiZGF0YSIKKyNkZWZpbmUgRFRfVEhSRVNIT0xEX0FUVFJfU1VGRklYCSJ0aHJzIgorCisvKgor -ICogRW51bWVyYXRlcyBhbGwgdGhlIHR5cGVzIG9mIHNlbnNvcnMgaW4gdGhlIFBPV0VSTlYgcGxh -dGZvcm0gYW5kIGRvZXMgaW5kZXgKKyAqIGludG8gJ3N0cnVjdCBzZW5zb3JfZ3JvdXAnCisgKi8K -K2VudW0gc2Vuc29ycyB7CisJRkFOLAorCUFNQklFTlRfVEVNUCwKKwlQT1dFUl9TVVBQTFksCisJ -UE9XRVJfSU5QVVQsCisJTUFYX1NFTlNPUl9UWVBFLAorfTsKKworc3RhdGljIHN0cnVjdCBzZW5z -b3JfZ3JvdXAgeworCWNvbnN0IGNoYXIgKm5hbWU7CisJY29uc3QgY2hhciAqY29tcGF0aWJsZTsK -KwlzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIGdyb3VwOworCXUzMiBhdHRyX2NvdW50OworfSBzZW5z -b3JfZ3JvdXBzW10gPSB7CisJeyJmYW4iLCAiaWJtLG9wYWwtc2Vuc29yLWNvb2xpbmctZmFuIn0s -CisJeyJ0ZW1wIiwgImlibSxvcGFsLXNlbnNvci1hbWItdGVtcCJ9LAorCXsiaW4iLCAiaWJtLG9w -YWwtc2Vuc29yLXBvd2VyLXN1cHBseSJ9LAorCXsicG93ZXIiLCAiaWJtLG9wYWwtc2Vuc29yLXBv -d2VyIn0KK307CisKK3N0cnVjdCBzZW5zb3JfZGF0YSB7CisJdTMyIGlkOyAvKiBBbiBvcGFxdWUg -aWQgb2YgdGhlIGZpcm13YXJlIGZvciBlYWNoIHNlbnNvciAqLworCWVudW0gc2Vuc29ycyB0eXBl -OworCWNoYXIgbmFtZVtNQVhfQVRUUl9MRU5dOworCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlIGRl -dl9hdHRyOworfTsKKworc3RydWN0IHBsYXRmb3JtX2RhdGEgeworCWNvbnN0IHN0cnVjdCBhdHRy -aWJ1dGVfZ3JvdXAgKmF0dHJfZ3JvdXBzW01BWF9TRU5TT1JfVFlQRSArIDFdOworCXUzMiBzZW5z -b3JzX2NvdW50OyAvKiBUb3RhbCBjb3VudCBvZiBzZW5zb3JzIGZyb20gZWFjaCBncm91cCAqLwor -fTsKKworLyogUGxhdGZvcm0gZGV2aWNlIHJlcHJlc2VudGluZyBhbGwgdGhlIGlibXBvd2VybnYg -c2Vuc29ycyAqLworc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXZpY2U7CisKK3N0 -YXRpYyBzc2l6ZV90IHNob3dfc2Vuc29yKHN0cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IGRldmlj -ZV9hdHRyaWJ1dGUgKmRldmF0dHIsCisJCQkgICBjaGFyICpidWYpCit7CisJc3RydWN0IHNlbnNv -cl9kYXRhICpzZGF0YSA9IGNvbnRhaW5lcl9vZihkZXZhdHRyLCBzdHJ1Y3Qgc2Vuc29yX2RhdGEs -CisJCQkJCQkgZGV2X2F0dHIpOworCXNzaXplX3QgcmV0OworCXUzMiB4OworCisJcmV0ID0gb3Bh -bF9nZXRfc2Vuc29yX2RhdGEoc2RhdGEtPmlkLCAmeCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJl -dDsKKworCS8qIENvbnZlcnQgdGVtcGVyYXR1cmUgdG8gbWlsbGktZGVncmVlcyAqLworCWlmIChz -ZGF0YS0+dHlwZSA9PSBBTUJJRU5UX1RFTVApCisJCXggKj0gMTAwMDsKKwkvKiBDb252ZXJ0IHBv -d2VyIHRvIG1pY3JvLXdhdHRzICovCisJZWxzZSBpZiAoc2RhdGEtPnR5cGUgPT0gUE9XRVJfSU5Q -VVQpCisJCXggKj0gMTAwMDAwMDsKKworCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiV1XG4iLCB4KTsK -K30KKworc3RhdGljIGludCBfX2luaXQgZ2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0IGNoYXIg -Km5hbWUsIHUzMiAqaW5kZXgsCisJCQkJCWNoYXIgKmF0dHIpCit7CisJY2hhciAqaGFzaF9wb3Mg -PSBzdHJjaHIobmFtZSwgJyMnKTsKKwljaGFyIGJ1Zls4XSA9IHsgMCB9OworCWNoYXIgKmRhc2hf -cG9zOworCXUzMiBjb3B5X2xlbjsKKwlpbnQgZXJyOworCisJaWYgKCFoYXNoX3BvcykKKwkJcmV0 -dXJuIC1FSU5WQUw7CisKKwlkYXNoX3BvcyA9IHN0cmNocihoYXNoX3BvcywgJy0nKTsKKwlpZiAo -IWRhc2hfcG9zKQorCQlyZXR1cm4gLUVJTlZBTDsKKworCWNvcHlfbGVuID0gZGFzaF9wb3MgLSBo -YXNoX3BvcyAtIDE7CisJaWYgKGNvcHlfbGVuID49IHNpemVvZihidWYpKQorCQlyZXR1cm4gLUVJ -TlZBTDsKKworCXN0cm5jcHkoYnVmLCBoYXNoX3BvcyArIDEsIGNvcHlfbGVuKTsKKworCWVyciA9 -IGtzdHJ0b3UzMihidWYsIDEwLCBpbmRleCk7CisJaWYgKGVycikKKwkJcmV0dXJuIGVycjsKKwor -CXN0cm5jcHkoYXR0ciwgZGFzaF9wb3MgKyAxLCBNQVhfQVRUUl9MRU4pOworCisJcmV0dXJuIDA7 -Cit9CisKKy8qCisgKiBUaGlzIGZ1bmN0aW9uIHRyYW5zbGF0ZXMgdGhlIERUIG5vZGUgbmFtZSBp -bnRvIHRoZSAnaHdtb24nIGF0dHJpYnV0ZSBuYW1lLgorICogSUJNUE9XRVJOViBkZXZpY2Ugbm9k -ZSBhcHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIGFtYi10ZW1wIzEtdGhycyBldGMuCisg -KiB3aGljaCBuZWVkIHRvIGJlIG1hcHBlZCBhcyBmYW4yX2lucHV0LCB0ZW1wMV9tYXggcmVzcGVj -dGl2ZWx5IGJlZm9yZQorICogcG9wdWxhdGluZyB0aGVtIGluc2lkZSBod21vbiBkZXZpY2UgY2xh -c3MuCisgKi8KK3N0YXRpYyBpbnQgX19pbml0IGNyZWF0ZV9od21vbl9hdHRyX25hbWUoc3RydWN0 -IGRldmljZSAqZGV2LCBlbnVtIHNlbnNvcnMgdHlwZSwKKwkJCQkJIGNvbnN0IGNoYXIgKm5vZGVf -bmFtZSwKKwkJCQkJIGNoYXIgKmh3bW9uX2F0dHJfbmFtZSkKK3sKKwljaGFyIGF0dHJfc3VmZml4 -W01BWF9BVFRSX0xFTl07CisJY2hhciAqYXR0cl9uYW1lOworCXUzMiBpbmRleDsKKwlpbnQgZXJy -OworCisJZXJyID0gZ2V0X3NlbnNvcl9pbmRleF9hdHRyKG5vZGVfbmFtZSwgJmluZGV4LCBhdHRy -X3N1ZmZpeCk7CisJaWYgKGVycikgeworCQlkZXZfZXJyKGRldiwgIlNlbnNvciBkZXZpY2Ugbm9k -ZSBuYW1lICclcycgaXMgaW52YWxpZFxuIiwKKwkJCW5vZGVfbmFtZSk7CisJCXJldHVybiBlcnI7 -CisJfQorCisJaWYgKCFzdHJjbXAoYXR0cl9zdWZmaXgsIERUX0ZBVUxUX0FUVFJfU1VGRklYKSkg -eworCQlhdHRyX25hbWUgPSAiZmF1bHQiOworCX0gZWxzZSBpZiAoIXN0cmNtcChhdHRyX3N1ZmZp -eCwgRFRfREFUQV9BVFRSX1NVRkZJWCkpIHsKKwkJYXR0cl9uYW1lID0gImlucHV0IjsKKwl9IGVs -c2UgaWYgKCFzdHJjbXAoYXR0cl9zdWZmaXgsIERUX1RIUkVTSE9MRF9BVFRSX1NVRkZJWCkpIHsK -KwkJaWYgKHR5cGUgPT0gQU1CSUVOVF9URU1QKQorCQkJYXR0cl9uYW1lID0gIm1heCI7CisJCWVs -c2UgaWYgKHR5cGUgPT0gRkFOKQorCQkJYXR0cl9uYW1lID0gIm1pbiI7CisJCWVsc2UKKwkJCXJl -dHVybiAtRU5PRU5UOworCX0gZWxzZSB7CisJCXJldHVybiAtRU5PRU5UOworCX0KKworCXNucHJp -bnRmKGh3bW9uX2F0dHJfbmFtZSwgTUFYX0FUVFJfTEVOLCAiJXMlZF8lcyIsCisJCSBzZW5zb3Jf -Z3JvdXBzW3R5cGVdLm5hbWUsIGluZGV4LCBhdHRyX25hbWUpOworCXJldHVybiAwOworfQorCitz -dGF0aWMgaW50IF9faW5pdCBwb3B1bGF0ZV9hdHRyX2dyb3VwcyhzdHJ1Y3QgcGxhdGZvcm1fZGV2 -aWNlICpwZGV2KQoreworCXN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YSA9IHBsYXRmb3JtX2dl -dF9kcnZkYXRhKHBkZXYpOworCWNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgKipwZ3JvdXBz -ID0gcGRhdGEtPmF0dHJfZ3JvdXBzOworCXN0cnVjdCBkZXZpY2Vfbm9kZSAqb3BhbCwgKm5wOwor -CWVudW0gc2Vuc29ycyB0eXBlOworCisJb3BhbCA9IG9mX2ZpbmRfbm9kZV9ieV9wYXRoKCIvaWJt -LG9wYWwvc2Vuc29ycyIpOworCWlmICghb3BhbCkgeworCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJP -cGFsIG5vZGUgJ3NlbnNvcnMnIG5vdCBmb3VuZFxuIik7CisJCXJldHVybiAtRU5PREVWOworCX0K -KworCWZvcl9lYWNoX2NoaWxkX29mX25vZGUob3BhbCwgbnApIHsKKwkJaWYgKG5wLT5uYW1lID09 -IE5VTEwpCisJCQljb250aW51ZTsKKworCQlmb3IgKHR5cGUgPSAwOyB0eXBlIDwgTUFYX1NFTlNP -Ul9UWVBFOyB0eXBlKyspCisJCQlpZiAob2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCisJCQkJ -CXNlbnNvcl9ncm91cHNbdHlwZV0uY29tcGF0aWJsZSkpIHsKKwkJCQlzZW5zb3JfZ3JvdXBzW3R5 -cGVdLmF0dHJfY291bnQrKzsKKwkJCQlicmVhazsKKwkJCX0KKwl9CisKKwlvZl9ub2RlX3B1dChv -cGFsKTsKKworCWZvciAodHlwZSA9IDA7IHR5cGUgPCBNQVhfU0VOU09SX1RZUEU7IHR5cGUrKykg -eworCQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJzID0gZGV2bV9remFsbG9jKCZwZGV2 -LT5kZXYsCisJCQkJCXNpemVvZihzdHJ1Y3QgYXR0cmlidXRlICopICoKKwkJCQkJKHNlbnNvcl9n -cm91cHNbdHlwZV0uYXR0cl9jb3VudCArIDEpLAorCQkJCQlHRlBfS0VSTkVMKTsKKwkJaWYgKCFz -ZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJzKQorCQkJcmV0dXJuIC1FTk9NRU07CisKKwkJ -cGdyb3Vwc1t0eXBlXSA9ICZzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwOworCQlwZGF0YS0+c2Vu -c29yc19jb3VudCArPSBzZW5zb3JfZ3JvdXBzW3R5cGVdLmF0dHJfY291bnQ7CisJCXNlbnNvcl9n -cm91cHNbdHlwZV0uYXR0cl9jb3VudCA9IDA7CisJfQorCisJcmV0dXJuIDA7Cit9CisKKy8qCisg -KiBJdGVyYXRlIHRocm91Z2ggdGhlIGRldmljZSB0cmVlIGZvciBlYWNoIGNoaWxkIG9mICdzZW5z -b3JzJyBub2RlLCBjcmVhdGUKKyAqIGEgc3lzZnMgYXR0cmlidXRlIGZpbGUsIHRoZSBmaWxlIGlz -IG5hbWVkIGJ5IHRyYW5zbGF0aW5nIHRoZSBEVCBub2RlIG5hbWUKKyAqIHRvIHRoZSBuYW1lIHJl -cXVpcmVkIGJ5IHRoZSBoaWdoZXIgJ2h3bW9uJyBkcml2ZXIgbGlrZSBmYW4xX2lucHV0LCB0ZW1w -MV9tYXgKKyAqIGV0Yy4uCisgKi8KK3N0YXRpYyBpbnQgX19pbml0IGNyZWF0ZV9kZXZpY2VfYXR0 -cnMoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKK3sKKwlzdHJ1Y3QgcGxhdGZvcm1fZGF0 -YSAqcGRhdGEgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKKwljb25zdCBzdHJ1Y3QgYXR0 -cmlidXRlX2dyb3VwICoqcGdyb3VwcyA9IHBkYXRhLT5hdHRyX2dyb3VwczsKKwlzdHJ1Y3QgZGV2 -aWNlX25vZGUgKm9wYWwsICpucDsKKwlzdHJ1Y3Qgc2Vuc29yX2RhdGEgKnNkYXRhOworCWNvbnN0 -IF9fYmUzMiAqc2Vuc29yX2lkOworCWVudW0gc2Vuc29ycyB0eXBlOworCXUzMiBjb3VudCA9IDA7 -CisJaW50IGVyciA9IDA7CisKKwlvcGFsID0gb2ZfZmluZF9ub2RlX2J5X3BhdGgoIi9pYm0sb3Bh -bC9zZW5zb3JzIik7CisJc2RhdGEgPSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRldiwgcGRhdGEtPnNl -bnNvcnNfY291bnQgKiBzaXplb2YoKnNkYXRhKSwKKwkJCSAgICAgR0ZQX0tFUk5FTCk7CisJaWYg -KCFzZGF0YSkgeworCQllcnIgPSAtRU5PTUVNOworCQlnb3RvIGV4aXRfcHV0X25vZGU7CisJfQor -CisJZm9yX2VhY2hfY2hpbGRfb2Zfbm9kZShvcGFsLCBucCkgeworCQlpZiAobnAtPm5hbWUgPT0g -TlVMTCkKKwkJCWNvbnRpbnVlOworCisJCWZvciAodHlwZSA9IDA7IHR5cGUgPCBNQVhfU0VOU09S -X1RZUEU7IHR5cGUrKykKKwkJCWlmIChvZl9kZXZpY2VfaXNfY29tcGF0aWJsZShucCwKKwkJCQkJ -c2Vuc29yX2dyb3Vwc1t0eXBlXS5jb21wYXRpYmxlKSkKKwkJCQlicmVhazsKKworCQlpZiAodHlw -ZSA9PSBNQVhfU0VOU09SX1RZUEUpCisJCQljb250aW51ZTsKKworCQlzZW5zb3JfaWQgPSBvZl9n -ZXRfcHJvcGVydHkobnAsICJzZW5zb3ItaWQiLCBOVUxMKTsKKwkJaWYgKCFzZW5zb3JfaWQpIHsK -KwkJCWRldl9pbmZvKCZwZGV2LT5kZXYsCisJCQkJICInc2Vuc29yLWlkJyBtaXNzaW5nIGluIHRo -ZSBub2RlICclcydcbiIsCisJCQkJIG5wLT5uYW1lKTsKKwkJCWNvbnRpbnVlOworCQl9CisKKwkJ -c2RhdGFbY291bnRdLmlkID0gYmUzMl90b19jcHVwKHNlbnNvcl9pZCk7CisJCXNkYXRhW2NvdW50 -XS50eXBlID0gdHlwZTsKKwkJZXJyID0gY3JlYXRlX2h3bW9uX2F0dHJfbmFtZSgmcGRldi0+ZGV2 -LCB0eXBlLCBucC0+bmFtZSwKKwkJCQkJICAgICBzZGF0YVtjb3VudF0ubmFtZSk7CisJCWlmIChl -cnIpCisJCQlnb3RvIGV4aXRfcHV0X25vZGU7CisKKwkJc3lzZnNfYXR0cl9pbml0KCZzZGF0YVtj -b3VudF0uZGV2X2F0dHIuYXR0cik7CisJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5hdHRyLm5hbWUg -PSBzZGF0YVtjb3VudF0ubmFtZTsKKwkJc2RhdGFbY291bnRdLmRldl9hdHRyLmF0dHIubW9kZSA9 -IFNfSVJVR087CisJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5zaG93ID0gc2hvd19zZW5zb3I7CisK -KwkJcGdyb3Vwc1t0eXBlXS0+YXR0cnNbc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRyX2NvdW50Kytd -ID0KKwkJCQkmc2RhdGFbY291bnQrK10uZGV2X2F0dHIuYXR0cjsKKwl9CisKK2V4aXRfcHV0X25v -ZGU6CisJb2Zfbm9kZV9wdXQob3BhbCk7CisJcmV0dXJuIGVycjsKK30KKworc3RhdGljIGludCBf -X2luaXQgaWJtcG93ZXJudl9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQorewor -CXN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YTsKKwlzdHJ1Y3QgZGV2aWNlICpod21vbl9kZXY7 -CisJaW50IGVycjsKKworCXBkYXRhID0gZGV2bV9remFsbG9jKCZwZGV2LT5kZXYsIHNpemVvZigq -cGRhdGEpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIXBkYXRhKQorCQlyZXR1cm4gLUVOT01FTTsKKwor -CXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIHBkYXRhKTsKKwlwZGF0YS0+c2Vuc29yc19jb3Vu -dCA9IDA7CisJZXJyID0gcG9wdWxhdGVfYXR0cl9ncm91cHMocGRldik7CisJaWYgKGVycikKKwkJ -cmV0dXJuIGVycjsKKworCS8qIENyZWF0ZSBzeXNmcyBhdHRyaWJ1dGUgZGF0YSBmb3IgZWFjaCBz -ZW5zb3IgZm91bmQgaW4gdGhlIERUICovCisJZXJyID0gY3JlYXRlX2RldmljZV9hdHRycyhwZGV2 -KTsKKwlpZiAoZXJyKQorCQlyZXR1cm4gZXJyOworCisJLyogRmluYWxseSwgcmVnaXN0ZXIgd2l0 -aCBod21vbiAqLworCWh3bW9uX2RldiA9IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhf -Z3JvdXBzKCZwZGV2LT5kZXYsIERSVk5BTUUsCisJCQkJCQkJICAgcGRhdGEsCisJCQkJCQkJICAg -cGRhdGEtPmF0dHJfZ3JvdXBzKTsKKworCXJldHVybiBQVFJfRVJSX09SX1pFUk8oaHdtb25fZGV2 -KTsKK30KKworc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgaWJtcG93ZXJudl9kcml2ZXIg -PSB7CisJLmRyaXZlciA9IHsKKwkJLm93bmVyID0gVEhJU19NT0RVTEUsCisJCS5uYW1lID0gRFJW -TkFNRSwKKwl9LAorfTsKKworc3RhdGljIGludCBfX2luaXQgaWJtcG93ZXJudl9pbml0KHZvaWQp -Cit7CisJaW50IGVycjsKKworCXBkZXZpY2UgPSBwbGF0Zm9ybV9kZXZpY2VfYWxsb2MoRFJWTkFN -RSwgMCk7CisJaWYgKCFwZGV2aWNlKSB7CisJCXByX2VycigiRGV2aWNlIGFsbG9jYXRpb24gZmFp -bGVkXG4iKTsKKwkJZXJyID0gLUVOT01FTTsKKwkJZ290byBleGl0OworCX0KKworCWVyciA9IHBs -YXRmb3JtX2RldmljZV9hZGQocGRldmljZSk7CisJaWYgKGVycikgeworCQlwcl9lcnIoIkRldmlj -ZSBhZGRpdGlvbiBmYWlsZWQgKCVkKVxuIiwgZXJyKTsKKwkJZ290byBleGl0X2RldmljZV9wdXQ7 -CisJfQorCisJZXJyID0gcGxhdGZvcm1fZHJpdmVyX3Byb2JlKCZpYm1wb3dlcm52X2RyaXZlciwg -aWJtcG93ZXJudl9wcm9iZSk7CisJaWYgKGVycikgeworCQlwcl9lcnIoIlBsYXRmcm9tIGRyaXZl -ciBwcm9iZSBmYWlsZWRcbiIpOworCQlnb3RvIGV4aXRfZGV2aWNlX2RlbDsKKwl9CisKKwlyZXR1 -cm4gMDsKKworZXhpdF9kZXZpY2VfZGVsOgorCXBsYXRmb3JtX2RldmljZV9kZWwocGRldmljZSk7 -CitleGl0X2RldmljZV9wdXQ6CisJcGxhdGZvcm1fZGV2aWNlX3B1dChwZGV2aWNlKTsKK2V4aXQ6 -CisJcmV0dXJuIGVycjsKK30KKworc3RhdGljIHZvaWQgX19leGl0IGlibXBvd2VybnZfZXhpdCh2 -b2lkKQoreworCXBsYXRmb3JtX2RyaXZlcl91bnJlZ2lzdGVyKCZpYm1wb3dlcm52X2RyaXZlcik7 -CisJcGxhdGZvcm1fZGV2aWNlX3VucmVnaXN0ZXIocGRldmljZSk7Cit9CisKK01PRFVMRV9BVVRI -T1IoIk5lZWxlc2ggR3VwdGEgPG5lZWxlZ3VwQGxpbnV4LnZuZXQuaWJtLmNvbT4iKTsKK01PRFVM -RV9ERVNDUklQVElPTigiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIpOworTU9EVUxFX0xJ -Q0VOU0UoIkdQTCIpOworCittb2R1bGVfaW5pdChpYm1wb3dlcm52X2luaXQpOworbW9kdWxlX2V4 -aXQoaWJtcG93ZXJudl9leGl0KTsKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f -X19fX19fX19fX19fXwpsbS1zZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3JzQGxtLXNlbnNv -cnMub3JnCmh0dHA6Ly9saXN0cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xtLXNl -bnNvcnM +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. + +Test results: +------------- +[root@tul163p1 ~]# sensors +ibmpowernv-isa-0000 +Adapter: ISA adapter +fan1: 5465 RPM (min = 0 RPM) +fan2: 5152 RPM (min = 0 RPM) +fan3: 5521 RPM (min = 0 RPM) +fan4: 4891 RPM (min = 0 RPM) +fan5: 0 RPM (min = 0 RPM) +fan6: 0 RPM (min = 0 RPM) +fan7: 7480 RPM (min = 0 RPM) +fan8: 7944 RPM (min = 0 RPM) +temp1: +39.0°C (high = +0.0°C) +power1: 190.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 ~]# 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> +Reviewed-by: Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> +--- + +Changes in v5 +============= +- Addressed couple minor comments in v4. + +Changes in v4 +============= +- Replaced pr_err() with dev_err() for logging 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 | 23 + + Documentation/hwmon/ibmpowernv | 41 ++ + drivers/hwmon/Kconfig | 11 + + drivers/hwmon/Makefile | 1 + drivers/hwmon/ibmpowernv.c | 364 ++++++++++++++++++++ + 5 files changed, 440 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..f93242b +--- /dev/null ++++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt +@@ -0,0 +1,23 @@ ++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>; ++ compatible = "ibm,opal-sensor-cooling-fan"; ++}; ++ ++amb-temp#1-thrs { ++ sensor-id = <0x5096000>; ++ 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..e6b652a +--- /dev/null ++++ b/drivers/hwmon/ibmpowernv.c +@@ -0,0 +1,364 @@ ++/* ++ * 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; ++ int err; ++ ++ 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); ++ ++ 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 9d1a780..fa124fc 100644 --- a/a/content_digest +++ b/N2/content_digest @@ -1,6 +1,6 @@ - "From\0Neelesh Gupta <neelegup@linux.vnet.ibm.com>\0" - "Subject\0[lm-sensors] [PATCH v5] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature\0" - "Date\0Tue, 08 Jul 2014 09:20:38 +0000\0" + "From\0Neelesh Gupta <neelegup-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>\0" + "Subject\0[PATCH v5] powerpc/powernv: hwmon driver for power, fan rpm, voltage and temperature\0" + "Date\0Tue, 08 Jul 2014 14:38:38 +0530\0" "To\0devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org" linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org " lm-sensors-GZX6beZjE8VD60Wz+7aTrA@public.gmane.org\0" @@ -11,305 +11,578 @@ " linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org\0" "\00:1\0" "b\0" - "VGhpcyBwYXRjaCBhZGRzIGJhc2ljIGtlcm5lbCBzdXBwb3J0IGZvciByZWFkaW5nIHBvd2VyIHZh\n" - "bHVlcywgZmFuCnNwZWVkIHJwbSwgdm9sdGFnZSBhbmQgdGVtcGVyYXR1cmUgZGF0YSBvbiBwb3dl\n" - "cm52IHBsYXRmb3JtcyB3aGljaAp3aWxsIGJlIGV4cG9ydGVkIHRvIHVzZXIgc3BhY2UgdGhyb3Vn\n" - "aCBzeXNmcyBpbnRlcmZhY2UuCgpUZXN0IHJlc3VsdHM6Ci0tLS0tLS0tLS0tLS0KW3Jvb3RAdHVs\n" - "MTYzcDEgfl0jIHNlbnNvcnMKaWJtcG93ZXJudi1pc2EtMDAwMApBZGFwdGVyOiBJU0EgYWRhcHRl\n" - "cgpmYW4xOiAgICAgICAgNTQ2NSBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFuMjogICAgICAgIDUx\n" - "NTIgUlBNICAobWluID0gICAgMCBSUE0pCmZhbjM6ICAgICAgICA1NTIxIFJQTSAgKG1pbiA9ICAg\n" - "IDAgUlBNKQpmYW40OiAgICAgICAgNDg5MSBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFuNTogICAg\n" - "ICAgICAgIDAgUlBNICAobWluID0gICAgMCBSUE0pCmZhbjY6ICAgICAgICAgICAwIFJQTSAgKG1p\n" - "biA9ICAgIDAgUlBNKQpmYW43OiAgICAgICAgNzQ4MCBSUE0gIChtaW4gPSAgICAwIFJQTSkKZmFu\n" - "ODogICAgICAgIDc5NDQgUlBNICAobWluID0gICAgMCBSUE0pCnRlbXAxOiAgICAgICAgKzM5LjDC\n" - "sEMgIChoaWdoID0gICswLjDCsEMpCnBvd2VyMTogICAgICAxOTAuMDAgVyAgCgpbcm9vdEB0dWwx\n" - "NjNwMSB+XSMgbHMgL3N5cy9kZXZpY2VzL3BsYXRmb3JtLwphbGFybXRpbWVyICBpYm1wb3dlcm52\n" - "LjAgIHBvd2VyICBydGMtZ2VuZXJpYyAgc2VyaWFsODI1MCAgdWV2ZW50Cltyb290QHR1bDE2M3Ax\n" - "IH5dIyBscyAvc3lzL2RldmljZXMvcGxhdGZvcm0vaWJtcG93ZXJudi4wL2h3bW9uL2h3bW9uMC8K\n" - "ZGV2aWNlCSAgICBmYW4yX21pbglmYW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAgIHBvd2Vy\n" - "CmZhbjFfZmF1bHQgIGZhbjNfZmF1bHQJZmFuNV9mYXVsdCAgZmFuN19mYXVsdAlpbjFfZmF1bHQg\n" - "IHBvd2VyMV9pbnB1dApmYW4xX2lucHV0ICBmYW4zX2lucHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5w\n" - "dXQJaW4yX2ZhdWx0ICBzdWJzeXN0ZW0KZmFuMV9taW4gICAgZmFuM19taW4JZmFuNV9taW4gICAg\n" - "ZmFuN19taW4JaW4zX2ZhdWx0ICB0ZW1wMV9pbnB1dApmYW4yX2ZhdWx0ICBmYW40X2ZhdWx0CWZh\n" - "bjZfZmF1bHQgIGZhbjhfZmF1bHQJaW40X2ZhdWx0ICB0ZW1wMV9tYXgKZmFuMl9pbnB1dCAgZmFu\n" - "NF9pbnB1dAlmYW42X2lucHV0ICBmYW44X2lucHV0CW5hbWUJICAgdWV2ZW50Cltyb290QHR1bDE2\n" - "M3AxIH5dIyBscyAvc3lzL2NsYXNzL2h3bW9uL2h3bW9uMC8KZGV2aWNlCSAgICBmYW4yX21pbglm\n" - "YW40X21pbiAgICBmYW42X21pbglmYW44X21pbiAgIHBvd2VyCmZhbjFfZmF1bHQgIGZhbjNfZmF1\n" - "bHQJZmFuNV9mYXVsdCAgZmFuN19mYXVsdAlpbjFfZmF1bHQgIHBvd2VyMV9pbnB1dApmYW4xX2lu\n" - "cHV0ICBmYW4zX2lucHV0CWZhbjVfaW5wdXQgIGZhbjdfaW5wdXQJaW4yX2ZhdWx0ICBzdWJzeXN0\n" - "ZW0KZmFuMV9taW4gICAgZmFuM19taW4JZmFuNV9taW4gICAgZmFuN19taW4JaW4zX2ZhdWx0ICB0\n" - "ZW1wMV9pbnB1dApmYW4yX2ZhdWx0ICBmYW40X2ZhdWx0CWZhbjZfZmF1bHQgIGZhbjhfZmF1bHQJ\n" - "aW40X2ZhdWx0ICB0ZW1wMV9tYXgKZmFuMl9pbnB1dCAgZmFuNF9pbnB1dAlmYW42X2lucHV0ICBm\n" - "YW44X2lucHV0CW5hbWUJICAgdWV2ZW50Cltyb290QHR1bDE2M3AxIH5dIwoKU2lnbmVkLW9mZi1i\n" - "eTogTmVlbGVzaCBHdXB0YSA8bmVlbGVndXBAbGludXgudm5ldC5pYm0uY29tPgpSZXZpZXdlZC1i\n" - "eTogR3VlbnRlciBSb2VjayA8bGludXhAcm9lY2stdXMubmV0PgotLS0KCkNoYW5nZXMgaW4gdjUK\n" - "PT09PT09PT09PT09PQotIEFkZHJlc3NlZCBjb3VwbGUgbWlub3IgY29tbWVudHMgaW4gdjQuCgpD\n" - "aGFuZ2VzIGluIHY0Cj09PT09PT09PT09PT0KLSBSZXBsYWNlZCBwcl9lcnIoKSB3aXRoIGRldl9l\n" - "cnIoKSBmb3IgbG9nZ2luZyBwcmludCBtZXNzYWdlcy4KLSBVc2luZyBrc3RydG91MzIoKSBmdW5j\n" - "dGlvbiBmb3IgY29udmVydGluZyBzdHJpbmcgdG8gdTMyIGluc3RlYWQgb2Ygc3NjYW5mKCkuCgpD\n" - "aGFuZ2VzIGluIHYzCj09PT09PT09PT09PT0KLSBGaXhlZCBhbiBlbmRpYW5uZXNzIGJ1ZyBsZWFk\n" - "aW5nIHRoZSBkcml2ZXIgdG8gYnJlYWsgb24gTEUuCi0gRml4ZWQgYSBidWcgdGhhdCB3aGVuIG9u\n" - "ZSBvZiB0aGUgJ2F0dHJpYnV0ZV9ncm91cCcgbm90IHBvcHVsYXRlZCwgZm9sbG93aW5nCiAgZ3Jv\n" - "dXBzIGF0dHJpYnV0ZXMgd2VyZSBkcm9wcGVkLgotIFJld3JpdGUgdGhlIGdldF9zZW5zb3JfaW5k\n" - "ZXhfYXR0cigpIGZ1bmN0aW9uIHRvIGhhbmRsZSBhbGwgdGhlIGVycm9yIHNjZW5hcmlvcwogIGxp\n" - "a2UgJ3NzY2FuZicgZXRjLgotIEZpeGVkIGFsbCB0aGUgZXJyb3JzL3dhcm5pbmdzIHJlbGF0ZWQg\n" - "dG8gY29kaW5nIHN0eWxlL3doaXRlc3BhY2UuCi0gQWRkZWQgJ0RvY3VtZW50YXRpb24nIGZpbGVz\n" - "LgotIEFkZHJlc3NlZCByZW1haW5pbmcgcmV2aWV3IGNvbW1lbnRzIG9uIFYyLgoKQ2hhbmdlcyBp\n" - "biB2Mgo9PT09PT09PT09PT09Ci0gR2VuZXJpYyB1c2Ugb2YgZGV2bV8qIGZ1bmN0aW9ucyBpbiBo\n" - "d21vbiBsaWtlIHVzaW5nIGRldm1fa3phbGxvYygpIGZvciBkeW5hbWljCiAgbWVtb3J5IHJlcXVl\n" - "c3QsIGF2b2lkaW5nIHRoZSBuZWVkIHRvIGV4cGxpY2l0IGZyZWUgb2YgbWVtb3J5LgogIEFkZGlu\n" - "ZyAnc3RydWN0IGF0dHJpYnV0ZV9ncm91cCcgYXMgbWVtYmVyIG9mIHBsYXRmb3JtIGRhdGEgc3Ry\n" - "dWN0dXJlIHRvIGJlCiAgcG9wdWxhdGVkIGFuZCB0aGVuIHBhc3NlZCB0byBkZXZtX2h3bW9uX2Rl\n" - "dmljZV9yZWdpc3Rlcl93aXRoX2dyb3VwcygpLgoKICBOb3RlOiBIYXZpbmcgYW4gYXJyYXkgb2Yg\n" - "cG9pbnRlcnMgb2YgJ2F0dHJpYnV0ZV9ncm91cCcgYW5kIGVhY2ggZ3JvdXAKICBjb3JyZXNwb25k\n" - "cyB0byAnZW51bSBzZW5zb3JzJyB0eXBlLiBOb3QgY29tcGxldGVseSBzdXJlLCBpZiBpdCdzIGlk\n" - "ZWFsIG9yCiAgY291bGQgaGF2ZSBqdXN0IG9uZSBncm91cCBwb3B1bGF0ZWQgd2l0aCBhdHRyaWJ1\n" - "dGVzIG9mIHNlbnNvciB0eXBlcz8KCi0gJ2libXBvd2VybnYnIGlzIG5vdCBob3QtcGx1Z2dhYmxl\n" - "IGRldmljZSBzbyBtb3ZpbmcgJ3BsYXRmb3JtX2RyaXZlcicgY2FsbGJhY2sKICBmdW5jdGlvbiAo\n" - "cHJvYmUpIGFzIHBhcnQgb2YgX19pbml0IGNvZGUuCi0gRml4ZWQgaXNzdWVzIHJlbGF0ZWQgdG8g\n" - "Y29kaW5nIHN0eWxlLgotIE90aGVyIGdlbmVyYWwgY29tbWVudHMgaW4gdjEuCgogLi4uL2Rldmlj\n" - "ZXRyZWUvYmluZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQgICAgICAgfCAgIDIzICsKIERvY3Vt\n" - "ZW50YXRpb24vaHdtb24vaWJtcG93ZXJudiAgICAgICAgICAgICAgICAgICAgIHwgICA0MSArKwog\n" - "ZHJpdmVycy9od21vbi9LY29uZmlnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgIDEx\n" - "ICsKIGRyaXZlcnMvaHdtb24vTWFrZWZpbGUgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwg\n" - "ICAgMSAKIGRyaXZlcnMvaHdtb24vaWJtcG93ZXJudi5jICAgICAgICAgICAgICAgICAgICAgICAg\n" - "IHwgIDM2NCArKysrKysrKysrKysrKysrKysrKwogNSBmaWxlcyBjaGFuZ2VkLCA0NDAgaW5zZXJ0\n" - "aW9ucygrKQogY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRpb24vZGV2aWNldHJlZS9iaW5k\n" - "aW5ncy9od21vbi9pYm1wb3dlcm52LnR4dAogY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRp\n" - "b24vaHdtb24vaWJtcG93ZXJudgogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvaHdtb24vaWJt\n" - "cG93ZXJudi5jCgpkaWZmIC0tZ2l0IGEvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdz\n" - "L2h3bW9uL2libXBvd2VybnYudHh0IGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdz\n" - "L2h3bW9uL2libXBvd2VybnYudHh0Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAu\n" - "LmY5MzI0MmIKLS0tIC9kZXYvbnVsbAorKysgYi9Eb2N1bWVudGF0aW9uL2RldmljZXRyZWUvYmlu\n" - "ZGluZ3MvaHdtb24vaWJtcG93ZXJudi50eHQKQEAgLTAsMCArMSwyMyBAQAorSUJNIFBPV0VSTlYg\n" - "cGxhdGZvcm0gc2Vuc29ycworLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQorCitSZXF1aXJl\n" - "ZCBub2RlIHByb3BlcnRpZXM6CistIGNvbXBhdGlibGU6IG11c3QgYmUgb25lIG9mCisJCSJpYm0s\n" - "b3BhbC1zZW5zb3ItY29vbGluZy1mYW4iCisJCSJpYm0sb3BhbC1zZW5zb3ItYW1iLXRlbXAiCisJ\n" - "CSJpYm0sb3BhbC1zZW5zb3ItcG93ZXItc3VwcGx5IgorCQkiaWJtLG9wYWwtc2Vuc29yLXBvd2Vy\n" - "IgorLSBzZW5zb3ItaWQ6IGFuIG9wYXF1ZSBpZCBwcm92aWRlZCBieSB0aGUgZmlybXdhcmUgdG8g\n" - "dGhlIGtlcm5lbCwgaWRlbnRpZmllcyBhCisJICAgICBnaXZlbiBzZW5zb3IgYW5kIGl0cyBhdHRy\n" - "aWJ1dGUgZGF0YQorCitFeGFtcGxlIHNlbnNvcnMgbm9kZToKKworY29vbGluZy1mYW4jOC1kYXRh\n" - "IHsKKwlzZW5zb3ItaWQgPSA8MHg3MDUyMTA3PjsKKwljb21wYXRpYmxlID0gImlibSxvcGFsLXNl\n" - "bnNvci1jb29saW5nLWZhbiI7Cit9OworCithbWItdGVtcCMxLXRocnMgeworCXNlbnNvci1pZCA9\n" - "IDwweDUwOTYwMDA+OworCWNvbXBhdGlibGUgPSAiaWJtLG9wYWwtc2Vuc29yLWFtYi10ZW1wIjsK\n" - "K307CmRpZmYgLS1naXQgYS9Eb2N1bWVudGF0aW9uL2h3bW9uL2libXBvd2VybnYgYi9Eb2N1bWVu\n" - "dGF0aW9uL2h3bW9uL2libXBvd2VybnYKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAw\n" - "MC4uNjQ0MjQ1YQotLS0gL2Rldi9udWxsCisrKyBiL0RvY3VtZW50YXRpb24vaHdtb24vaWJtcG93\n" - "ZXJudgpAQCAtMCwwICsxLDQxIEBACitLZXJuZWwgRHJpdmVyIElCTVBPV0VOVgorPT09PT09PT09\n" - "PT09PT09PT09PT09PT0KKworU3VwcG9ydGVkIHN5c3RlbXM6CisgICogQW55IHJlY2VudCBJQk0g\n" - "UCBzZXJ2ZXJzIGJhc2VkIG9uIFBPV0VSTlYgcGxhdGZvcm0KKworQXV0aG9yOiBOZWVsZXNoIEd1\n" - "cHRhCisKK0Rlc2NyaXB0aW9uCistLS0tLS0tLS0tLQorCitUaGlzIGRyaXZlciBpbXBsZW1lbnRz\n" - "IHJlYWRpbmcgdGhlIHBsYXRmb3JtIHNlbnNvcnMgZGF0YSBsaWtlIHRlbXBlcmF0dXJlL2Zhbi8K\n" - "K3ZvbHRhZ2UvcG93ZXIgZm9yICdQT1dFUk5WJyBwbGF0Zm9ybS4KKworVGhlIGRyaXZlciB1c2Vz\n" - "IHRoZSBwbGF0Zm9ybSBkZXZpY2UgaW5mcmFzdHJ1Y3R1cmUuIEl0IHByb2JlcyB0aGUgZGV2aWNl\n" - "IHRyZWUKK2ZvciBzZW5zb3IgZGV2aWNlcyBkdXJpbmcgdGhlIF9faW5pdCBwaGFzZSBhbmQgcmVn\n" - "aXN0ZXJzIHRoZW0gd2l0aCB0aGUgJ2h3bW9uJy4KKydod21vbicgcG9wdWxhdGVzIHRoZSAnc3lz\n" - "ZnMnIHRyZWUgaGF2aW5nIGF0dHJpYnV0ZSBmaWxlcywgZWFjaCBmb3IgYSBnaXZlbgorc2Vuc29y\n" - "IHR5cGUgYW5kIGl0cyBhdHRyaWJ1dGUgZGF0YS4KKworQWxsIHRoZSBub2RlcyBpbiB0aGUgRFQg\n" - "YXBwZWFyIHVuZGVyICIvaWJtLG9wYWwvc2Vuc29ycyIgYW5kIGVhY2ggdmFsaWQgbm9kZSBpbgor\n" - "dGhlIERUIG1hcHMgdG8gYW4gYXR0cmlidXRlIGZpbGUgaW4gJ3N5c2ZzJy4gVGhlIG5vZGUgZXhw\n" - "b3J0cyB1bmlxdWUgJ3NlbnNvci1pZCcKK3doaWNoIHRoZSBkcml2ZXIgdXNlcyB0byBtYWtlIGFu\n" - "IE9QQUwgY2FsbCB0byB0aGUgZmlybXdhcmUuCisKK1VzYWdlIG5vdGVzCistLS0tLS0tLS0tLQor\n" - "VGhlIGRyaXZlciBpcyBidWlsdCBzdGF0aWNhbGx5IHdpdGggdGhlIGtlcm5lbCBieSBlbmFibGlu\n" - "ZyB0aGUgY29uZmlnCitDT05GSUdfU0VOU09SU19JQk1QT1dFUk5WLiBJdCBjYW4gYWxzbyBiZSBi\n" - "dWlsdCBhcyBtb2R1bGUgJ2libXBvd2VybnYnLgorCitTeXNmcyBhdHRyaWJ1dGVzCistLS0tLS0t\n" - "LS0tLS0tLS0tCisKK2ZhblhfaW5wdXQJCU1lYXN1cmVkIFJQTSB2YWx1ZS4KK2ZhblhfbWluCQlU\n" - "aHJlc2hvbGQgUlBNIGZvciBhbGVydCBnZW5lcmF0aW9uLgorZmFuWF9mYXVsdAkJMDogTm8gZmFp\n" - "bCBjb25kaXRpb24KKwkJCTE6IEZhaWxpbmcgZmFuCit0ZW1wWF9pbnB1dAkJTWVhc3VyZWQgYW1i\n" - "aWVudCB0ZW1wZXJhdHVyZS4KK3RlbXBYX21heAkJVGhyZXNob2xkIGFtYmllbnQgdGVtcGVyYXR1\n" - "cmUgZm9yIGFsZXJ0IGdlbmVyYXRpb24uCitpblhfaW5wdXQJCU1lYXN1cmVkIHBvd2VyIHN1cHBs\n" - "eSB2b2x0YWdlCitpblhfZmF1bHQJCTA6IE5vIGZhaWwgY29uZGl0aW9uLgorCQkJMTogRmFpbGlu\n" - "ZyBwb3dlciBzdXBwbHkuCitwb3dlcjFfaW5wdXQJCVN5c3RlbSBwb3dlciBjb25zdW1wdGlvbiAo\n" - "bWljcm9XYXR0KQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9od21vbi9LY29uZmlnIGIvZHJpdmVycy9o\n" - "d21vbi9LY29uZmlnCmluZGV4IDAyZDNkODUuLjI5YzNmY2IgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMv\n" - "aHdtb24vS2NvbmZpZworKysgYi9kcml2ZXJzL2h3bW9uL0tjb25maWcKQEAgLTU1NCw2ICs1NTQs\n" - "MTcgQEAgY29uZmlnIFNFTlNPUlNfSUJNUEVYCiAJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBi\n" - "dWlsdCBhcyBhIG1vZHVsZS4gIElmIHNvLCB0aGUgbW9kdWxlCiAJICB3aWxsIGJlIGNhbGxlZCBp\n" - "Ym1wZXguCiAKK2NvbmZpZyBTRU5TT1JTX0lCTVBPV0VSTlYKKwl0cmlzdGF0ZSAiSUJNIFBPV0VS\n" - "TlYgcGxhdGZvcm0gc2Vuc29ycyIKKwlkZXBlbmRzIG9uIFBQQ19QT1dFUk5WCisJZGVmYXVsdCB5\n" - "CisJaGVscAorCSAgSWYgeW91IHNheSB5ZXMgaGVyZSB5b3UgZ2V0IHN1cHBvcnQgZm9yIHRoZSB0\n" - "ZW1wZXJhdHVyZS9mYW4vcG93ZXIKKwkgIHNlbnNvcnMgb24geW91ciBQb3dlck5WIHBsYXRmb3Jt\n" - "LgorCisJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1vZHVsZS4gSWYgc28s\n" - "IHRoZSBtb2R1bGUKKwkgIHdpbGwgYmUgY2FsbGVkIGlibXBvd2VybnYuCisKIGNvbmZpZyBTRU5T\n" - "T1JTX0lJT19IV01PTgogCXRyaXN0YXRlICJId21vbiBkcml2ZXIgdGhhdCB1c2VzIGNoYW5uZWxz\n" - "IHNwZWNpZmllZCB2aWEgaWlvIG1hcHMiCiAJZGVwZW5kcyBvbiBJSU8KZGlmZiAtLWdpdCBhL2Ry\n" - "aXZlcnMvaHdtb24vTWFrZWZpbGUgYi9kcml2ZXJzL2h3bW9uL01ha2VmaWxlCmluZGV4IDNkYzBm\n" - "MDIuLmZjNGVkMjYgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKKysrIGIvZHJp\n" - "dmVycy9od21vbi9NYWtlZmlsZQpAQCAtNzEsNiArNzEsNyBAQCBvYmotJChDT05GSUdfU0VOU09S\n" - "U19VTFRSQTQ1KQkrPSB1bHRyYTQ1X2Vudi5vCiBvYmotJChDT05GSUdfU0VOU09SU19JNUtfQU1C\n" - "KQkrPSBpNWtfYW1iLm8KIG9iai0kKENPTkZJR19TRU5TT1JTX0lCTUFFTSkJKz0gaWJtYWVtLm8K\n" - "IG9iai0kKENPTkZJR19TRU5TT1JTX0lCTVBFWCkJKz0gaWJtcGV4Lm8KK29iai0kKENPTkZJR19T\n" - "RU5TT1JTX0lCTVBPV0VSTlYpKz0gaWJtcG93ZXJudi5vCiBvYmotJChDT05GSUdfU0VOU09SU19J\n" - "SU9fSFdNT04pICs9IGlpb19od21vbi5vCiBvYmotJChDT05GSUdfU0VOU09SU19JTkEyMDkpCSs9\n" - "IGluYTIwOS5vCiBvYmotJChDT05GSUdfU0VOU09SU19JTkEyWFgpCSs9IGluYTJ4eC5vCmRpZmYg\n" - "LS1naXQgYS9kcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYyBiL2RyaXZlcnMvaHdtb24vaWJtcG93\n" - "ZXJudi5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLmU2YjY1MmEKLS0tIC9k\n" - "ZXYvbnVsbAorKysgYi9kcml2ZXJzL2h3bW9uL2libXBvd2VybnYuYwpAQCAtMCwwICsxLDM2NCBA\n" - "QAorLyoKKyAqIElCTSBQb3dlck5WIHBsYXRmb3JtIHNlbnNvcnMgZm9yIHRlbXBlcmF0dXJlL2Zh\n" - "bi92b2x0YWdlL3Bvd2VyCisgKiBDb3B5cmlnaHQgKEMpIDIwMTQgSUJNCisgKgorICogVGhpcyBw\n" - "cm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBt\n" - "b2RpZnkKKyAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExp\n" - "Y2Vuc2UgYXMgcHVibGlzaGVkIGJ5CisgKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBl\n" - "aXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvcgorICogKGF0IHlvdXIgb3B0aW9uKSBh\n" - "bnkgbGF0ZXIgdmVyc2lvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4g\n" - "dGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKKyAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJS\n" - "QU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCisgKiBNRVJDSEFOVEFC\n" - "SUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCisgKiBH\n" - "TlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgorICoKKyAqIFlvdSBz\n" - "aG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNl\n" - "bnNlCisgKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS4KKyAqLworCisjZGVmaW5lIERSVk5BTUUJ\n" - "CSJpYm1wb3dlcm52IgorI2RlZmluZSBwcl9mbXQoZm10KQlEUlZOQU1FICI6ICIgZm10CisKKyNp\n" - "bmNsdWRlIDxsaW51eC9pbml0Lmg+CisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVk\n" - "ZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvaHdtb24uaD4KKyNpbmNsdWRlIDxs\n" - "aW51eC9od21vbi1zeXNmcy5oPgorI2luY2x1ZGUgPGxpbnV4L29mLmg+CisjaW5jbHVkZSA8bGlu\n" - "dXgvc2xhYi5oPgorCisjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+CisjaW5jbHVk\n" - "ZSA8YXNtL29wYWwuaD4KKyNpbmNsdWRlIDxsaW51eC9lcnIuaD4KKworI2RlZmluZSBNQVhfQVRU\n" - "Ul9MRU4JMzIKKworLyogU2Vuc29yIHN1ZmZpeCBuYW1lIGZyb20gRFQgKi8KKyNkZWZpbmUgRFRf\n" - "RkFVTFRfQVRUUl9TVUZGSVgJCSJmYXVsdGVkIgorI2RlZmluZSBEVF9EQVRBX0FUVFJfU1VGRklY\n" - "CQkiZGF0YSIKKyNkZWZpbmUgRFRfVEhSRVNIT0xEX0FUVFJfU1VGRklYCSJ0aHJzIgorCisvKgor\n" - "ICogRW51bWVyYXRlcyBhbGwgdGhlIHR5cGVzIG9mIHNlbnNvcnMgaW4gdGhlIFBPV0VSTlYgcGxh\n" - "dGZvcm0gYW5kIGRvZXMgaW5kZXgKKyAqIGludG8gJ3N0cnVjdCBzZW5zb3JfZ3JvdXAnCisgKi8K\n" - "K2VudW0gc2Vuc29ycyB7CisJRkFOLAorCUFNQklFTlRfVEVNUCwKKwlQT1dFUl9TVVBQTFksCisJ\n" - "UE9XRVJfSU5QVVQsCisJTUFYX1NFTlNPUl9UWVBFLAorfTsKKworc3RhdGljIHN0cnVjdCBzZW5z\n" - "b3JfZ3JvdXAgeworCWNvbnN0IGNoYXIgKm5hbWU7CisJY29uc3QgY2hhciAqY29tcGF0aWJsZTsK\n" - "KwlzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIGdyb3VwOworCXUzMiBhdHRyX2NvdW50OworfSBzZW5z\n" - "b3JfZ3JvdXBzW10gPSB7CisJeyJmYW4iLCAiaWJtLG9wYWwtc2Vuc29yLWNvb2xpbmctZmFuIn0s\n" - "CisJeyJ0ZW1wIiwgImlibSxvcGFsLXNlbnNvci1hbWItdGVtcCJ9LAorCXsiaW4iLCAiaWJtLG9w\n" - "YWwtc2Vuc29yLXBvd2VyLXN1cHBseSJ9LAorCXsicG93ZXIiLCAiaWJtLG9wYWwtc2Vuc29yLXBv\n" - "d2VyIn0KK307CisKK3N0cnVjdCBzZW5zb3JfZGF0YSB7CisJdTMyIGlkOyAvKiBBbiBvcGFxdWUg\n" - "aWQgb2YgdGhlIGZpcm13YXJlIGZvciBlYWNoIHNlbnNvciAqLworCWVudW0gc2Vuc29ycyB0eXBl\n" - "OworCWNoYXIgbmFtZVtNQVhfQVRUUl9MRU5dOworCXN0cnVjdCBkZXZpY2VfYXR0cmlidXRlIGRl\n" - "dl9hdHRyOworfTsKKworc3RydWN0IHBsYXRmb3JtX2RhdGEgeworCWNvbnN0IHN0cnVjdCBhdHRy\n" - "aWJ1dGVfZ3JvdXAgKmF0dHJfZ3JvdXBzW01BWF9TRU5TT1JfVFlQRSArIDFdOworCXUzMiBzZW5z\n" - "b3JzX2NvdW50OyAvKiBUb3RhbCBjb3VudCBvZiBzZW5zb3JzIGZyb20gZWFjaCBncm91cCAqLwor\n" - "fTsKKworLyogUGxhdGZvcm0gZGV2aWNlIHJlcHJlc2VudGluZyBhbGwgdGhlIGlibXBvd2VybnYg\n" - "c2Vuc29ycyAqLworc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXZpY2U7CisKK3N0\n" - "YXRpYyBzc2l6ZV90IHNob3dfc2Vuc29yKHN0cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IGRldmlj\n" - "ZV9hdHRyaWJ1dGUgKmRldmF0dHIsCisJCQkgICBjaGFyICpidWYpCit7CisJc3RydWN0IHNlbnNv\n" - "cl9kYXRhICpzZGF0YSA9IGNvbnRhaW5lcl9vZihkZXZhdHRyLCBzdHJ1Y3Qgc2Vuc29yX2RhdGEs\n" - "CisJCQkJCQkgZGV2X2F0dHIpOworCXNzaXplX3QgcmV0OworCXUzMiB4OworCisJcmV0ID0gb3Bh\n" - "bF9nZXRfc2Vuc29yX2RhdGEoc2RhdGEtPmlkLCAmeCk7CisJaWYgKHJldCkKKwkJcmV0dXJuIHJl\n" - "dDsKKworCS8qIENvbnZlcnQgdGVtcGVyYXR1cmUgdG8gbWlsbGktZGVncmVlcyAqLworCWlmIChz\n" - "ZGF0YS0+dHlwZSA9PSBBTUJJRU5UX1RFTVApCisJCXggKj0gMTAwMDsKKwkvKiBDb252ZXJ0IHBv\n" - "d2VyIHRvIG1pY3JvLXdhdHRzICovCisJZWxzZSBpZiAoc2RhdGEtPnR5cGUgPT0gUE9XRVJfSU5Q\n" - "VVQpCisJCXggKj0gMTAwMDAwMDsKKworCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiV1XG4iLCB4KTsK\n" - "K30KKworc3RhdGljIGludCBfX2luaXQgZ2V0X3NlbnNvcl9pbmRleF9hdHRyKGNvbnN0IGNoYXIg\n" - "Km5hbWUsIHUzMiAqaW5kZXgsCisJCQkJCWNoYXIgKmF0dHIpCit7CisJY2hhciAqaGFzaF9wb3Mg\n" - "PSBzdHJjaHIobmFtZSwgJyMnKTsKKwljaGFyIGJ1Zls4XSA9IHsgMCB9OworCWNoYXIgKmRhc2hf\n" - "cG9zOworCXUzMiBjb3B5X2xlbjsKKwlpbnQgZXJyOworCisJaWYgKCFoYXNoX3BvcykKKwkJcmV0\n" - "dXJuIC1FSU5WQUw7CisKKwlkYXNoX3BvcyA9IHN0cmNocihoYXNoX3BvcywgJy0nKTsKKwlpZiAo\n" - "IWRhc2hfcG9zKQorCQlyZXR1cm4gLUVJTlZBTDsKKworCWNvcHlfbGVuID0gZGFzaF9wb3MgLSBo\n" - "YXNoX3BvcyAtIDE7CisJaWYgKGNvcHlfbGVuID49IHNpemVvZihidWYpKQorCQlyZXR1cm4gLUVJ\n" - "TlZBTDsKKworCXN0cm5jcHkoYnVmLCBoYXNoX3BvcyArIDEsIGNvcHlfbGVuKTsKKworCWVyciA9\n" - "IGtzdHJ0b3UzMihidWYsIDEwLCBpbmRleCk7CisJaWYgKGVycikKKwkJcmV0dXJuIGVycjsKKwor\n" - "CXN0cm5jcHkoYXR0ciwgZGFzaF9wb3MgKyAxLCBNQVhfQVRUUl9MRU4pOworCisJcmV0dXJuIDA7\n" - "Cit9CisKKy8qCisgKiBUaGlzIGZ1bmN0aW9uIHRyYW5zbGF0ZXMgdGhlIERUIG5vZGUgbmFtZSBp\n" - "bnRvIHRoZSAnaHdtb24nIGF0dHJpYnV0ZSBuYW1lLgorICogSUJNUE9XRVJOViBkZXZpY2Ugbm9k\n" - "ZSBhcHBlYXIgbGlrZSBjb29saW5nLWZhbiMyLWRhdGEsIGFtYi10ZW1wIzEtdGhycyBldGMuCisg\n" - "KiB3aGljaCBuZWVkIHRvIGJlIG1hcHBlZCBhcyBmYW4yX2lucHV0LCB0ZW1wMV9tYXggcmVzcGVj\n" - "dGl2ZWx5IGJlZm9yZQorICogcG9wdWxhdGluZyB0aGVtIGluc2lkZSBod21vbiBkZXZpY2UgY2xh\n" - "c3MuCisgKi8KK3N0YXRpYyBpbnQgX19pbml0IGNyZWF0ZV9od21vbl9hdHRyX25hbWUoc3RydWN0\n" - "IGRldmljZSAqZGV2LCBlbnVtIHNlbnNvcnMgdHlwZSwKKwkJCQkJIGNvbnN0IGNoYXIgKm5vZGVf\n" - "bmFtZSwKKwkJCQkJIGNoYXIgKmh3bW9uX2F0dHJfbmFtZSkKK3sKKwljaGFyIGF0dHJfc3VmZml4\n" - "W01BWF9BVFRSX0xFTl07CisJY2hhciAqYXR0cl9uYW1lOworCXUzMiBpbmRleDsKKwlpbnQgZXJy\n" - "OworCisJZXJyID0gZ2V0X3NlbnNvcl9pbmRleF9hdHRyKG5vZGVfbmFtZSwgJmluZGV4LCBhdHRy\n" - "X3N1ZmZpeCk7CisJaWYgKGVycikgeworCQlkZXZfZXJyKGRldiwgIlNlbnNvciBkZXZpY2Ugbm9k\n" - "ZSBuYW1lICclcycgaXMgaW52YWxpZFxuIiwKKwkJCW5vZGVfbmFtZSk7CisJCXJldHVybiBlcnI7\n" - "CisJfQorCisJaWYgKCFzdHJjbXAoYXR0cl9zdWZmaXgsIERUX0ZBVUxUX0FUVFJfU1VGRklYKSkg\n" - "eworCQlhdHRyX25hbWUgPSAiZmF1bHQiOworCX0gZWxzZSBpZiAoIXN0cmNtcChhdHRyX3N1ZmZp\n" - "eCwgRFRfREFUQV9BVFRSX1NVRkZJWCkpIHsKKwkJYXR0cl9uYW1lID0gImlucHV0IjsKKwl9IGVs\n" - "c2UgaWYgKCFzdHJjbXAoYXR0cl9zdWZmaXgsIERUX1RIUkVTSE9MRF9BVFRSX1NVRkZJWCkpIHsK\n" - "KwkJaWYgKHR5cGUgPT0gQU1CSUVOVF9URU1QKQorCQkJYXR0cl9uYW1lID0gIm1heCI7CisJCWVs\n" - "c2UgaWYgKHR5cGUgPT0gRkFOKQorCQkJYXR0cl9uYW1lID0gIm1pbiI7CisJCWVsc2UKKwkJCXJl\n" - "dHVybiAtRU5PRU5UOworCX0gZWxzZSB7CisJCXJldHVybiAtRU5PRU5UOworCX0KKworCXNucHJp\n" - "bnRmKGh3bW9uX2F0dHJfbmFtZSwgTUFYX0FUVFJfTEVOLCAiJXMlZF8lcyIsCisJCSBzZW5zb3Jf\n" - "Z3JvdXBzW3R5cGVdLm5hbWUsIGluZGV4LCBhdHRyX25hbWUpOworCXJldHVybiAwOworfQorCitz\n" - "dGF0aWMgaW50IF9faW5pdCBwb3B1bGF0ZV9hdHRyX2dyb3VwcyhzdHJ1Y3QgcGxhdGZvcm1fZGV2\n" - "aWNlICpwZGV2KQoreworCXN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YSA9IHBsYXRmb3JtX2dl\n" - "dF9kcnZkYXRhKHBkZXYpOworCWNvbnN0IHN0cnVjdCBhdHRyaWJ1dGVfZ3JvdXAgKipwZ3JvdXBz\n" - "ID0gcGRhdGEtPmF0dHJfZ3JvdXBzOworCXN0cnVjdCBkZXZpY2Vfbm9kZSAqb3BhbCwgKm5wOwor\n" - "CWVudW0gc2Vuc29ycyB0eXBlOworCisJb3BhbCA9IG9mX2ZpbmRfbm9kZV9ieV9wYXRoKCIvaWJt\n" - "LG9wYWwvc2Vuc29ycyIpOworCWlmICghb3BhbCkgeworCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJP\n" - "cGFsIG5vZGUgJ3NlbnNvcnMnIG5vdCBmb3VuZFxuIik7CisJCXJldHVybiAtRU5PREVWOworCX0K\n" - "KworCWZvcl9lYWNoX2NoaWxkX29mX25vZGUob3BhbCwgbnApIHsKKwkJaWYgKG5wLT5uYW1lID09\n" - "IE5VTEwpCisJCQljb250aW51ZTsKKworCQlmb3IgKHR5cGUgPSAwOyB0eXBlIDwgTUFYX1NFTlNP\n" - "Ul9UWVBFOyB0eXBlKyspCisJCQlpZiAob2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsCisJCQkJ\n" - "CXNlbnNvcl9ncm91cHNbdHlwZV0uY29tcGF0aWJsZSkpIHsKKwkJCQlzZW5zb3JfZ3JvdXBzW3R5\n" - "cGVdLmF0dHJfY291bnQrKzsKKwkJCQlicmVhazsKKwkJCX0KKwl9CisKKwlvZl9ub2RlX3B1dChv\n" - "cGFsKTsKKworCWZvciAodHlwZSA9IDA7IHR5cGUgPCBNQVhfU0VOU09SX1RZUEU7IHR5cGUrKykg\n" - "eworCQlzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJzID0gZGV2bV9remFsbG9jKCZwZGV2\n" - "LT5kZXYsCisJCQkJCXNpemVvZihzdHJ1Y3QgYXR0cmlidXRlICopICoKKwkJCQkJKHNlbnNvcl9n\n" - "cm91cHNbdHlwZV0uYXR0cl9jb3VudCArIDEpLAorCQkJCQlHRlBfS0VSTkVMKTsKKwkJaWYgKCFz\n" - "ZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwLmF0dHJzKQorCQkJcmV0dXJuIC1FTk9NRU07CisKKwkJ\n" - "cGdyb3Vwc1t0eXBlXSA9ICZzZW5zb3JfZ3JvdXBzW3R5cGVdLmdyb3VwOworCQlwZGF0YS0+c2Vu\n" - "c29yc19jb3VudCArPSBzZW5zb3JfZ3JvdXBzW3R5cGVdLmF0dHJfY291bnQ7CisJCXNlbnNvcl9n\n" - "cm91cHNbdHlwZV0uYXR0cl9jb3VudCA9IDA7CisJfQorCisJcmV0dXJuIDA7Cit9CisKKy8qCisg\n" - "KiBJdGVyYXRlIHRocm91Z2ggdGhlIGRldmljZSB0cmVlIGZvciBlYWNoIGNoaWxkIG9mICdzZW5z\n" - "b3JzJyBub2RlLCBjcmVhdGUKKyAqIGEgc3lzZnMgYXR0cmlidXRlIGZpbGUsIHRoZSBmaWxlIGlz\n" - "IG5hbWVkIGJ5IHRyYW5zbGF0aW5nIHRoZSBEVCBub2RlIG5hbWUKKyAqIHRvIHRoZSBuYW1lIHJl\n" - "cXVpcmVkIGJ5IHRoZSBoaWdoZXIgJ2h3bW9uJyBkcml2ZXIgbGlrZSBmYW4xX2lucHV0LCB0ZW1w\n" - "MV9tYXgKKyAqIGV0Yy4uCisgKi8KK3N0YXRpYyBpbnQgX19pbml0IGNyZWF0ZV9kZXZpY2VfYXR0\n" - "cnMoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKK3sKKwlzdHJ1Y3QgcGxhdGZvcm1fZGF0\n" - "YSAqcGRhdGEgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKKwljb25zdCBzdHJ1Y3QgYXR0\n" - "cmlidXRlX2dyb3VwICoqcGdyb3VwcyA9IHBkYXRhLT5hdHRyX2dyb3VwczsKKwlzdHJ1Y3QgZGV2\n" - "aWNlX25vZGUgKm9wYWwsICpucDsKKwlzdHJ1Y3Qgc2Vuc29yX2RhdGEgKnNkYXRhOworCWNvbnN0\n" - "IF9fYmUzMiAqc2Vuc29yX2lkOworCWVudW0gc2Vuc29ycyB0eXBlOworCXUzMiBjb3VudCA9IDA7\n" - "CisJaW50IGVyciA9IDA7CisKKwlvcGFsID0gb2ZfZmluZF9ub2RlX2J5X3BhdGgoIi9pYm0sb3Bh\n" - "bC9zZW5zb3JzIik7CisJc2RhdGEgPSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRldiwgcGRhdGEtPnNl\n" - "bnNvcnNfY291bnQgKiBzaXplb2YoKnNkYXRhKSwKKwkJCSAgICAgR0ZQX0tFUk5FTCk7CisJaWYg\n" - "KCFzZGF0YSkgeworCQllcnIgPSAtRU5PTUVNOworCQlnb3RvIGV4aXRfcHV0X25vZGU7CisJfQor\n" - "CisJZm9yX2VhY2hfY2hpbGRfb2Zfbm9kZShvcGFsLCBucCkgeworCQlpZiAobnAtPm5hbWUgPT0g\n" - "TlVMTCkKKwkJCWNvbnRpbnVlOworCisJCWZvciAodHlwZSA9IDA7IHR5cGUgPCBNQVhfU0VOU09S\n" - "X1RZUEU7IHR5cGUrKykKKwkJCWlmIChvZl9kZXZpY2VfaXNfY29tcGF0aWJsZShucCwKKwkJCQkJ\n" - "c2Vuc29yX2dyb3Vwc1t0eXBlXS5jb21wYXRpYmxlKSkKKwkJCQlicmVhazsKKworCQlpZiAodHlw\n" - "ZSA9PSBNQVhfU0VOU09SX1RZUEUpCisJCQljb250aW51ZTsKKworCQlzZW5zb3JfaWQgPSBvZl9n\n" - "ZXRfcHJvcGVydHkobnAsICJzZW5zb3ItaWQiLCBOVUxMKTsKKwkJaWYgKCFzZW5zb3JfaWQpIHsK\n" - "KwkJCWRldl9pbmZvKCZwZGV2LT5kZXYsCisJCQkJICInc2Vuc29yLWlkJyBtaXNzaW5nIGluIHRo\n" - "ZSBub2RlICclcydcbiIsCisJCQkJIG5wLT5uYW1lKTsKKwkJCWNvbnRpbnVlOworCQl9CisKKwkJ\n" - "c2RhdGFbY291bnRdLmlkID0gYmUzMl90b19jcHVwKHNlbnNvcl9pZCk7CisJCXNkYXRhW2NvdW50\n" - "XS50eXBlID0gdHlwZTsKKwkJZXJyID0gY3JlYXRlX2h3bW9uX2F0dHJfbmFtZSgmcGRldi0+ZGV2\n" - "LCB0eXBlLCBucC0+bmFtZSwKKwkJCQkJICAgICBzZGF0YVtjb3VudF0ubmFtZSk7CisJCWlmIChl\n" - "cnIpCisJCQlnb3RvIGV4aXRfcHV0X25vZGU7CisKKwkJc3lzZnNfYXR0cl9pbml0KCZzZGF0YVtj\n" - "b3VudF0uZGV2X2F0dHIuYXR0cik7CisJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5hdHRyLm5hbWUg\n" - "PSBzZGF0YVtjb3VudF0ubmFtZTsKKwkJc2RhdGFbY291bnRdLmRldl9hdHRyLmF0dHIubW9kZSA9\n" - "IFNfSVJVR087CisJCXNkYXRhW2NvdW50XS5kZXZfYXR0ci5zaG93ID0gc2hvd19zZW5zb3I7CisK\n" - "KwkJcGdyb3Vwc1t0eXBlXS0+YXR0cnNbc2Vuc29yX2dyb3Vwc1t0eXBlXS5hdHRyX2NvdW50Kytd\n" - "ID0KKwkJCQkmc2RhdGFbY291bnQrK10uZGV2X2F0dHIuYXR0cjsKKwl9CisKK2V4aXRfcHV0X25v\n" - "ZGU6CisJb2Zfbm9kZV9wdXQob3BhbCk7CisJcmV0dXJuIGVycjsKK30KKworc3RhdGljIGludCBf\n" - "X2luaXQgaWJtcG93ZXJudl9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQorewor\n" - "CXN0cnVjdCBwbGF0Zm9ybV9kYXRhICpwZGF0YTsKKwlzdHJ1Y3QgZGV2aWNlICpod21vbl9kZXY7\n" - "CisJaW50IGVycjsKKworCXBkYXRhID0gZGV2bV9remFsbG9jKCZwZGV2LT5kZXYsIHNpemVvZigq\n" - "cGRhdGEpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIXBkYXRhKQorCQlyZXR1cm4gLUVOT01FTTsKKwor\n" - "CXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIHBkYXRhKTsKKwlwZGF0YS0+c2Vuc29yc19jb3Vu\n" - "dCA9IDA7CisJZXJyID0gcG9wdWxhdGVfYXR0cl9ncm91cHMocGRldik7CisJaWYgKGVycikKKwkJ\n" - "cmV0dXJuIGVycjsKKworCS8qIENyZWF0ZSBzeXNmcyBhdHRyaWJ1dGUgZGF0YSBmb3IgZWFjaCBz\n" - "ZW5zb3IgZm91bmQgaW4gdGhlIERUICovCisJZXJyID0gY3JlYXRlX2RldmljZV9hdHRycyhwZGV2\n" - "KTsKKwlpZiAoZXJyKQorCQlyZXR1cm4gZXJyOworCisJLyogRmluYWxseSwgcmVnaXN0ZXIgd2l0\n" - "aCBod21vbiAqLworCWh3bW9uX2RldiA9IGRldm1faHdtb25fZGV2aWNlX3JlZ2lzdGVyX3dpdGhf\n" - "Z3JvdXBzKCZwZGV2LT5kZXYsIERSVk5BTUUsCisJCQkJCQkJICAgcGRhdGEsCisJCQkJCQkJICAg\n" - "cGRhdGEtPmF0dHJfZ3JvdXBzKTsKKworCXJldHVybiBQVFJfRVJSX09SX1pFUk8oaHdtb25fZGV2\n" - "KTsKK30KKworc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgaWJtcG93ZXJudl9kcml2ZXIg\n" - "PSB7CisJLmRyaXZlciA9IHsKKwkJLm93bmVyID0gVEhJU19NT0RVTEUsCisJCS5uYW1lID0gRFJW\n" - "TkFNRSwKKwl9LAorfTsKKworc3RhdGljIGludCBfX2luaXQgaWJtcG93ZXJudl9pbml0KHZvaWQp\n" - "Cit7CisJaW50IGVycjsKKworCXBkZXZpY2UgPSBwbGF0Zm9ybV9kZXZpY2VfYWxsb2MoRFJWTkFN\n" - "RSwgMCk7CisJaWYgKCFwZGV2aWNlKSB7CisJCXByX2VycigiRGV2aWNlIGFsbG9jYXRpb24gZmFp\n" - "bGVkXG4iKTsKKwkJZXJyID0gLUVOT01FTTsKKwkJZ290byBleGl0OworCX0KKworCWVyciA9IHBs\n" - "YXRmb3JtX2RldmljZV9hZGQocGRldmljZSk7CisJaWYgKGVycikgeworCQlwcl9lcnIoIkRldmlj\n" - "ZSBhZGRpdGlvbiBmYWlsZWQgKCVkKVxuIiwgZXJyKTsKKwkJZ290byBleGl0X2RldmljZV9wdXQ7\n" - "CisJfQorCisJZXJyID0gcGxhdGZvcm1fZHJpdmVyX3Byb2JlKCZpYm1wb3dlcm52X2RyaXZlciwg\n" - "aWJtcG93ZXJudl9wcm9iZSk7CisJaWYgKGVycikgeworCQlwcl9lcnIoIlBsYXRmcm9tIGRyaXZl\n" - "ciBwcm9iZSBmYWlsZWRcbiIpOworCQlnb3RvIGV4aXRfZGV2aWNlX2RlbDsKKwl9CisKKwlyZXR1\n" - "cm4gMDsKKworZXhpdF9kZXZpY2VfZGVsOgorCXBsYXRmb3JtX2RldmljZV9kZWwocGRldmljZSk7\n" - "CitleGl0X2RldmljZV9wdXQ6CisJcGxhdGZvcm1fZGV2aWNlX3B1dChwZGV2aWNlKTsKK2V4aXQ6\n" - "CisJcmV0dXJuIGVycjsKK30KKworc3RhdGljIHZvaWQgX19leGl0IGlibXBvd2VybnZfZXhpdCh2\n" - "b2lkKQoreworCXBsYXRmb3JtX2RyaXZlcl91bnJlZ2lzdGVyKCZpYm1wb3dlcm52X2RyaXZlcik7\n" - "CisJcGxhdGZvcm1fZGV2aWNlX3VucmVnaXN0ZXIocGRldmljZSk7Cit9CisKK01PRFVMRV9BVVRI\n" - "T1IoIk5lZWxlc2ggR3VwdGEgPG5lZWxlZ3VwQGxpbnV4LnZuZXQuaWJtLmNvbT4iKTsKK01PRFVM\n" - "RV9ERVNDUklQVElPTigiSUJNIFBPV0VSTlYgcGxhdGZvcm0gc2Vuc29ycyIpOworTU9EVUxFX0xJ\n" - "Q0VOU0UoIkdQTCIpOworCittb2R1bGVfaW5pdChpYm1wb3dlcm52X2luaXQpOworbW9kdWxlX2V4\n" - "aXQoaWJtcG93ZXJudl9leGl0KTsKCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f\n" - "X19fX19fX19fX19fXwpsbS1zZW5zb3JzIG1haWxpbmcgbGlzdApsbS1zZW5zb3JzQGxtLXNlbnNv\n" - "cnMub3JnCmh0dHA6Ly9saXN0cy5sbS1zZW5zb3JzLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xtLXNl\n" - bnNvcnM + "This patch adds basic kernel support for reading power values, fan\n" + "speed rpm, voltage and temperature data on powernv platforms which\n" + "will be exported to user space through sysfs interface.\n" + "\n" + "Test results:\n" + "-------------\n" + "[root@tul163p1 ~]# sensors\n" + "ibmpowernv-isa-0000\n" + "Adapter: ISA adapter\n" + "fan1: 5465 RPM (min = 0 RPM)\n" + "fan2: 5152 RPM (min = 0 RPM)\n" + "fan3: 5521 RPM (min = 0 RPM)\n" + "fan4: 4891 RPM (min = 0 RPM)\n" + "fan5: 0 RPM (min = 0 RPM)\n" + "fan6: 0 RPM (min = 0 RPM)\n" + "fan7: 7480 RPM (min = 0 RPM)\n" + "fan8: 7944 RPM (min = 0 RPM)\n" + "temp1: +39.0\302\260C (high = +0.0\302\260C)\n" + "power1: 190.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 ~]# 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" + "Reviewed-by: Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>\n" + "---\n" + "\n" + "Changes in v5\n" + "=============\n" + "- Addressed couple minor comments in v4.\n" + "\n" + "Changes in v4\n" + "=============\n" + "- Replaced pr_err() with dev_err() for logging 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 | 23 +\n" + " Documentation/hwmon/ibmpowernv | 41 ++\n" + " drivers/hwmon/Kconfig | 11 +\n" + " drivers/hwmon/Makefile | 1 \n" + " drivers/hwmon/ibmpowernv.c | 364 ++++++++++++++++++++\n" + " 5 files changed, 440 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..f93242b\n" + "--- /dev/null\n" + "+++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt\n" + "@@ -0,0 +1,23 @@\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" + "+\tcompatible = \"ibm,opal-sensor-cooling-fan\";\n" + "+};\n" + "+\n" + "+amb-temp#1-thrs {\n" + "+\tsensor-id = <0x5096000>;\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..e6b652a\n" + "--- /dev/null\n" + "+++ b/drivers/hwmon/ibmpowernv.c\n" + "@@ -0,0 +1,364 @@\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" + "+\tint err;\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" + "+\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" + "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 -f99de827708da98eed28b6adde09d30b1a31d6a06d37cee5bb5aaa5c9ecec889 +0343a3b3380c8135e584c358cb20f69bbe6e6dde14fa5aa0ff122f60778cf61d
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.