All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <1427633859-18596-2-git-send-email-pali.rohar@gmail.com>

diff --git a/a/1.txt b/N1/1.txt
index 2004e55..e4aa265 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -1,924 +1,2085 @@
-VGhpcyBjb21taXQgbW92ZXMgaThrIGRyaXZlciB0byBod21vbiB0cmVlIHVuZGVyIG5hbWUgZGVs
-bC1zbW0taHdtb24gd2hpY2ggaXMKYmV0dGVyIG5hbWUgdGhlbiBhYmJyZXZpYXRpb24gaThrLiBG
-b3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eSBpcyBhZGRlZCBtYWNybwpNT0RVTEVfQUxJQVMoImk4
-ayIpIHNvIG1vZHByb2JlIHdpbGwgbG9hZCBkcml2ZXIgYWxzbyBvbGQgbmFtZSBpOGsuIENPTkZJ
-R19JOEsKY29tcGlsZSBvcHRpb24gd2FzIG5vdCBjaGFuZ2VkLgoKVGhpcyBjb21taXQgYWxzbyBh
-ZGRzIG1lIGFzIG1haW50YWluZXIgb2YgdGhpcyBuZXcgZGVsbC1zbW0taHdtb24gZHJpdmVyIGFu
-ZApyZW1vdmUgR3VlbnRlciBSb2VjayBmcm9tIGxpc3Qgd2hvIGlzIGltcGxpY2l0IG1haW50YWlu
-ZXIgYWxsIGh3bW9uIGRyaXZlcnMuCgpTaWduZWQtb2ZmLWJ5OiBQYWxpIFJvaMOhciA8cGFsaS5y
-b2hhckBnbWFpbC5jb20+Ci0tLQogTUFJTlRBSU5FUlMgICAgICAgICAgICAgICAgICAgIHwgICAg
-NCArLQogZHJpdmVycy9jaGFyL01ha2VmaWxlICAgICAgICAgIHwgICAgMSAtCiBkcml2ZXJzL2No
-YXIvaThrLmMgICAgICAgICAgICAgfCAxMDA1IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t
-LS0tLS0tLS0tLQogZHJpdmVycy9od21vbi9NYWtlZmlsZSAgICAgICAgIHwgICAgMSArCiBkcml2
-ZXJzL2h3bW9uL2RlbGwtc21tLWh3bW9uLmMgfCAxMDA3ICsrKysrKysrKysrKysrKysrKysrKysr
-KysrKysrKysrKysrKysrKysKIDUgZmlsZXMgY2hhbmdlZCwgMTAxMCBpbnNlcnRpb25zKCspLCAx
-MDA4IGRlbGV0aW9ucygtKQogZGVsZXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvY2hhci9pOGsuYwog
-Y3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvaHdtb24vZGVsbC1zbW0taHdtb24uYwoKZGlmZiAt
-LWdpdCBhL01BSU5UQUlORVJTIGIvTUFJTlRBSU5FUlMKaW5kZXggODhjMDljYS4uZTU0YTA3ZSAx
-MDA2NDQKLS0tIGEvTUFJTlRBSU5FUlMKKysrIGIvTUFJTlRBSU5FUlMKQEAgLTMwNjMsOSArMzA2
-Myw5IEBAIFM6CU1haW50YWluZWQKIEY6CWRyaXZlcnMvcGxhdGZvcm0veDg2L2RlbGwtbGFwdG9w
-LmMKIAogREVMTCBMQVBUT1AgU01NIERSSVZFUgotTToJR3VlbnRlciBSb2VjayA8bGludXhAcm9l
-Y2stdXMubmV0PgorTToJUGFsaSBSb2jDoXIgPHBhbGkucm9oYXJAZ21haWwuY29tPgogUzoJTWFp
-bnRhaW5lZAotRjoJZHJpdmVycy9jaGFyL2k4ay5jCitGOglkcml2ZXJzL2h3bW9uL2RlbGwtc21t
-LWh3bW9uLmMKIEY6CWluY2x1ZGUvdWFwaS9saW51eC9pOGsuaAogCiBERUxMIFNZU1RFTVMgTUFO
-QUdFTUVOVCBCQVNFIERSSVZFUiAoZGNkYmFzKQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9jaGFyL01h
-a2VmaWxlIGIvZHJpdmVycy9jaGFyL01ha2VmaWxlCmluZGV4IGQwNmNkZTI2Li4xZDljZjAwIDEw
-MDY0NAotLS0gYS9kcml2ZXJzL2NoYXIvTWFrZWZpbGUKKysrIGIvZHJpdmVycy9jaGFyL01ha2Vm
-aWxlCkBAIC0zNiw3ICszNiw2IEBAIGVsc2UKICAgb2JqLSQoQ09ORklHX05WUkFNKQkrPSBudnJh
-bS5vCiBlbmRpZgogb2JqLSQoQ09ORklHX1RPU0hJQkEpCQkrPSB0b3NoaWJhLm8KLW9iai0kKENP
-TkZJR19JOEspCQkrPSBpOGsubwogb2JqLSQoQ09ORklHX0RTMTYyMCkJCSs9IGRzMTYyMC5vCiBv
-YmotJChDT05GSUdfSFdfUkFORE9NKQkJKz0gaHdfcmFuZG9tLwogb2JqLSQoQ09ORklHX1BQREVW
-KQkJKz0gcHBkZXYubwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9jaGFyL2k4ay5jIGIvZHJpdmVycy9j
-aGFyL2k4ay5jCmRlbGV0ZWQgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAyNGNjNGVkLi4wMDAwMDAw
-Ci0tLSBhL2RyaXZlcnMvY2hhci9pOGsuYworKysgL2Rldi9udWxsCkBAIC0xLDEwMDUgKzAsMCBA
-QAotLyoKLSAqIGk4ay5jIC0tIExpbnV4IGRyaXZlciBmb3IgYWNjZXNzaW5nIHRoZSBTTU0gQklP
-UyBvbiBEZWxsIGxhcHRvcHMuCi0gKgotICogQ29weXJpZ2h0IChDKSAyMDAxICBNYXNzaW1vIERh
-bCBab3R0byA8ZHpAZGViaWFuLm9yZz4KLSAqCi0gKiBId21vbiBpbnRlZ3JhdGlvbjoKLSAqIENv
-cHlyaWdodCAoQykgMjAxMSAgSmVhbiBEZWx2YXJlIDxqZGVsdmFyZUBzdXNlLmRlPgotICogQ29w
-eXJpZ2h0IChDKSAyMDEzLCAyMDE0ICBHdWVudGVyIFJvZWNrIDxsaW51eEByb2Vjay11cy5uZXQ+
-Ci0gKiBDb3B5cmlnaHQgKEMpIDIwMTQgIFBhbGkgUm9ow6FyIDxwYWxpLnJvaGFyQGdtYWlsLmNv
-bT4KLSAqCi0gKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3Ry
-aWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdAotICogdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUg
-R2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlCi0gKiBGcmVlIFNvZnR3
-YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55
-Ci0gKiBsYXRlciB2ZXJzaW9uLgotICoKLSAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBp
-biB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQKLSAqIFdJVEhPVVQgQU5ZIFdB
-UlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKLSAqIE1FUkNIQU5U
-QUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05V
-Ci0gKiBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCi0gKi8KLQotI2Rl
-ZmluZSBwcl9mbXQoZm10KSBLQlVJTERfTU9ETkFNRSAiOiAiIGZtdAotCi0jaW5jbHVkZSA8bGlu
-dXgvZGVsYXkuaD4KLSNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KLSNpbmNsdWRlIDxsaW51eC90
-eXBlcy5oPgotI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KLSNpbmNsdWRlIDxsaW51eC9wcm9jX2Zz
-Lmg+Ci0jaW5jbHVkZSA8bGludXgvc2VxX2ZpbGUuaD4KLSNpbmNsdWRlIDxsaW51eC9kbWkuaD4K
-LSNpbmNsdWRlIDxsaW51eC9jYXBhYmlsaXR5Lmg+Ci0jaW5jbHVkZSA8bGludXgvbXV0ZXguaD4K
-LSNpbmNsdWRlIDxsaW51eC9od21vbi5oPgotI2luY2x1ZGUgPGxpbnV4L2h3bW9uLXN5c2ZzLmg+
-Ci0jaW5jbHVkZSA8bGludXgvdWFjY2Vzcy5oPgotI2luY2x1ZGUgPGxpbnV4L2lvLmg+Ci0jaW5j
-bHVkZSA8bGludXgvc2NoZWQuaD4KLQotI2luY2x1ZGUgPGxpbnV4L2k4ay5oPgotCi0jZGVmaW5l
-IEk4S19TTU1fRk5fU1RBVFVTCTB4MDAyNQotI2RlZmluZSBJOEtfU01NX1BPV0VSX1NUQVRVUwkw
-eDAwNjkKLSNkZWZpbmUgSThLX1NNTV9TRVRfRkFOCQkweDAxYTMKLSNkZWZpbmUgSThLX1NNTV9H
-RVRfRkFOCQkweDAwYTMKLSNkZWZpbmUgSThLX1NNTV9HRVRfU1BFRUQJMHgwMmEzCi0jZGVmaW5l
-IEk4S19TTU1fR0VUX0ZBTl9UWVBFCTB4MDNhMwotI2RlZmluZSBJOEtfU01NX0dFVF9OT01fU1BF
-RUQJMHgwNGEzCi0jZGVmaW5lIEk4S19TTU1fR0VUX1RFTVAJMHgxMGEzCi0jZGVmaW5lIEk4S19T
-TU1fR0VUX1RFTVBfVFlQRQkweDExYTMKLSNkZWZpbmUgSThLX1NNTV9HRVRfREVMTF9TSUcxCTB4
-ZmVhMwotI2RlZmluZSBJOEtfU01NX0dFVF9ERUxMX1NJRzIJMHhmZmEzCi0KLSNkZWZpbmUgSThL
-X0ZBTl9NVUxUCQkzMAotI2RlZmluZSBJOEtfRkFOX01BWF9SUE0JCTMwMDAwCi0jZGVmaW5lIEk4
-S19NQVhfVEVNUAkJMTI3Ci0KLSNkZWZpbmUgSThLX0ZOX05PTkUJCTB4MDAKLSNkZWZpbmUgSThL
-X0ZOX1VQCQkweDAxCi0jZGVmaW5lIEk4S19GTl9ET1dOCQkweDAyCi0jZGVmaW5lIEk4S19GTl9N
-VVRFCQkweDA0Ci0jZGVmaW5lIEk4S19GTl9NQVNLCQkweDA3Ci0jZGVmaW5lIEk4S19GTl9TSElG
-VAkJOAotCi0jZGVmaW5lIEk4S19QT1dFUl9BQwkJMHgwNQotI2RlZmluZSBJOEtfUE9XRVJfQkFU
-VEVSWQkweDAxCi0KLXN0YXRpYyBERUZJTkVfTVVURVgoaThrX211dGV4KTsKLXN0YXRpYyBjaGFy
-IGJpb3NfdmVyc2lvbls0XTsKLXN0YXRpYyBzdHJ1Y3QgZGV2aWNlICppOGtfaHdtb25fZGV2Owot
-c3RhdGljIHUzMiBpOGtfaHdtb25fZmxhZ3M7Ci1zdGF0aWMgdWludCBpOGtfZmFuX211bHQgPSBJ
-OEtfRkFOX01VTFQ7Ci1zdGF0aWMgdWludCBpOGtfcHdtX211bHQ7Ci1zdGF0aWMgdWludCBpOGtf
-ZmFuX21heCA9IEk4S19GQU5fSElHSDsKLQotI2RlZmluZSBJOEtfSFdNT05fSEFWRV9URU1QMQko
-MSA8PCAwKQotI2RlZmluZSBJOEtfSFdNT05fSEFWRV9URU1QMgkoMSA8PCAxKQotI2RlZmluZSBJ
-OEtfSFdNT05fSEFWRV9URU1QMwkoMSA8PCAyKQotI2RlZmluZSBJOEtfSFdNT05fSEFWRV9URU1Q
-NAkoMSA8PCAzKQotI2RlZmluZSBJOEtfSFdNT05fSEFWRV9GQU4xCSgxIDw8IDQpCi0jZGVmaW5l
-IEk4S19IV01PTl9IQVZFX0ZBTjIJKDEgPDwgNSkKLQotTU9EVUxFX0FVVEhPUigiTWFzc2ltbyBE
-YWwgWm90dG8gKGR6QGRlYmlhbi5vcmcpIik7Ci1NT0RVTEVfREVTQ1JJUFRJT04oIkRyaXZlciBm
-b3IgYWNjZXNzaW5nIFNNTSBCSU9TIG9uIERlbGwgbGFwdG9wcyIpOwotTU9EVUxFX0xJQ0VOU0Uo
-IkdQTCIpOwotCi1zdGF0aWMgYm9vbCBmb3JjZTsKLW1vZHVsZV9wYXJhbShmb3JjZSwgYm9vbCwg
-MCk7Ci1NT0RVTEVfUEFSTV9ERVNDKGZvcmNlLCAiRm9yY2UgbG9hZGluZyB3aXRob3V0IGNoZWNr
-aW5nIGZvciBzdXBwb3J0ZWQgbW9kZWxzIik7Ci0KLXN0YXRpYyBib29sIGlnbm9yZV9kbWk7Ci1t
-b2R1bGVfcGFyYW0oaWdub3JlX2RtaSwgYm9vbCwgMCk7Ci1NT0RVTEVfUEFSTV9ERVNDKGlnbm9y
-ZV9kbWksICJDb250aW51ZSBwcm9iaW5nIGhhcmR3YXJlIGV2ZW4gaWYgRE1JIGRhdGEgZG9lcyBu
-b3QgbWF0Y2giKTsKLQotc3RhdGljIGJvb2wgcmVzdHJpY3RlZDsKLW1vZHVsZV9wYXJhbShyZXN0
-cmljdGVkLCBib29sLCAwKTsKLU1PRFVMRV9QQVJNX0RFU0MocmVzdHJpY3RlZCwgIkFsbG93IGZh
-biBjb250cm9sIGlmIFNZU19BRE1JTiBjYXBhYmlsaXR5IHNldCIpOwotCi1zdGF0aWMgYm9vbCBw
-b3dlcl9zdGF0dXM7Ci1tb2R1bGVfcGFyYW0ocG93ZXJfc3RhdHVzLCBib29sLCAwNjAwKTsKLU1P
-RFVMRV9QQVJNX0RFU0MocG93ZXJfc3RhdHVzLCAiUmVwb3J0IHBvd2VyIHN0YXR1cyBpbiAvcHJv
-Yy9pOGsiKTsKLQotc3RhdGljIHVpbnQgZmFuX211bHQ7Ci1tb2R1bGVfcGFyYW0oZmFuX211bHQs
-IHVpbnQsIDApOwotTU9EVUxFX1BBUk1fREVTQyhmYW5fbXVsdCwgIkZhY3RvciB0byBtdWx0aXBs
-eSBmYW4gc3BlZWQgd2l0aCAoZGVmYXVsdDogYXV0b2RldGVjdCkiKTsKLQotc3RhdGljIHVpbnQg
-ZmFuX21heDsKLW1vZHVsZV9wYXJhbShmYW5fbWF4LCB1aW50LCAwKTsKLU1PRFVMRV9QQVJNX0RF
-U0MoZmFuX21heCwgIk1heGltdW0gY29uZmlndXJhYmxlIGZhbiBzcGVlZCAoZGVmYXVsdDogYXV0
-b2RldGVjdCkiKTsKLQotc3RhdGljIGludCBpOGtfb3Blbl9mcyhzdHJ1Y3QgaW5vZGUgKmlub2Rl
-LCBzdHJ1Y3QgZmlsZSAqZmlsZSk7Ci1zdGF0aWMgbG9uZyBpOGtfaW9jdGwoc3RydWN0IGZpbGUg
-KiwgdW5zaWduZWQgaW50LCB1bnNpZ25lZCBsb25nKTsKLQotc3RhdGljIGNvbnN0IHN0cnVjdCBm
-aWxlX29wZXJhdGlvbnMgaThrX2ZvcHMgPSB7Ci0JLm93bmVyCQk9IFRISVNfTU9EVUxFLAotCS5v
-cGVuCQk9IGk4a19vcGVuX2ZzLAotCS5yZWFkCQk9IHNlcV9yZWFkLAotCS5sbHNlZWsJCT0gc2Vx
-X2xzZWVrLAotCS5yZWxlYXNlCT0gc2luZ2xlX3JlbGVhc2UsCi0JLnVubG9ja2VkX2lvY3RsCT0g
-aThrX2lvY3RsLAotfTsKLQotc3RydWN0IHNtbV9yZWdzIHsKLQl1bnNpZ25lZCBpbnQgZWF4Owot
-CXVuc2lnbmVkIGludCBlYnggX19wYWNrZWQ7Ci0JdW5zaWduZWQgaW50IGVjeCBfX3BhY2tlZDsK
-LQl1bnNpZ25lZCBpbnQgZWR4IF9fcGFja2VkOwotCXVuc2lnbmVkIGludCBlc2kgX19wYWNrZWQ7
-Ci0JdW5zaWduZWQgaW50IGVkaSBfX3BhY2tlZDsKLX07Ci0KLXN0YXRpYyBpbmxpbmUgY29uc3Qg
-Y2hhciAqaThrX2dldF9kbWlfZGF0YShpbnQgZmllbGQpCi17Ci0JY29uc3QgY2hhciAqZG1pX2Rh
-dGEgPSBkbWlfZ2V0X3N5c3RlbV9pbmZvKGZpZWxkKTsKLQotCXJldHVybiBkbWlfZGF0YSAmJiAq
-ZG1pX2RhdGEgPyBkbWlfZGF0YSA6ICI/IjsKLX0KLQotLyoKLSAqIENhbGwgdGhlIFN5c3RlbSBN
-YW5hZ2VtZW50IE1vZGUgQklPUy4gQ29kZSBwcm92aWRlZCBieSBKb25hdGhhbiBCdXp6YXJkLgot
-ICovCi1zdGF0aWMgaW50IGk4a19zbW0oc3RydWN0IHNtbV9yZWdzICpyZWdzKQotewotCWludCBy
-YzsKLQlpbnQgZWF4ID0gcmVncy0+ZWF4OwotCWNwdW1hc2tfdmFyX3Qgb2xkX21hc2s7Ci0KLQkv
-KiBTTU0gcmVxdWlyZXMgQ1BVIDAgKi8KLQlpZiAoIWFsbG9jX2NwdW1hc2tfdmFyKCZvbGRfbWFz
-aywgR0ZQX0tFUk5FTCkpCi0JCXJldHVybiAtRU5PTUVNOwotCWNwdW1hc2tfY29weShvbGRfbWFz
-aywgJmN1cnJlbnQtPmNwdXNfYWxsb3dlZCk7Ci0JcmMgPSBzZXRfY3B1c19hbGxvd2VkX3B0cihj
-dXJyZW50LCBjcHVtYXNrX29mKDApKTsKLQlpZiAocmMpCi0JCWdvdG8gb3V0OwotCWlmIChzbXBf
-cHJvY2Vzc29yX2lkKCkgIT0gMCkgewotCQlyYyA9IC1FQlVTWTsKLQkJZ290byBvdXQ7Ci0JfQot
-Ci0jaWYgZGVmaW5lZChDT05GSUdfWDg2XzY0KQotCWFzbSB2b2xhdGlsZSgicHVzaHEgJSVyYXhc
-blx0IgotCQkibW92bCAwKCUlcmF4KSwlJWVkeFxuXHQiCi0JCSJwdXNocSAlJXJkeFxuXHQiCi0J
-CSJtb3ZsIDQoJSVyYXgpLCUlZWJ4XG5cdCIKLQkJIm1vdmwgOCglJXJheCksJSVlY3hcblx0Igot
-CQkibW92bCAxMiglJXJheCksJSVlZHhcblx0IgotCQkibW92bCAxNiglJXJheCksJSVlc2lcblx0
-IgotCQkibW92bCAyMCglJXJheCksJSVlZGlcblx0IgotCQkicG9wcSAlJXJheFxuXHQiCi0JCSJv
-dXQgJSVhbCwkMHhiMlxuXHQiCi0JCSJvdXQgJSVhbCwkMHg4NFxuXHQiCi0JCSJ4Y2hncSAlJXJh
-eCwoJSVyc3ApXG5cdCIKLQkJIm1vdmwgJSVlYngsNCglJXJheClcblx0IgotCQkibW92bCAlJWVj
-eCw4KCUlcmF4KVxuXHQiCi0JCSJtb3ZsICUlZWR4LDEyKCUlcmF4KVxuXHQiCi0JCSJtb3ZsICUl
-ZXNpLDE2KCUlcmF4KVxuXHQiCi0JCSJtb3ZsICUlZWRpLDIwKCUlcmF4KVxuXHQiCi0JCSJwb3Bx
-ICUlcmR4XG5cdCIKLQkJIm1vdmwgJSVlZHgsMCglJXJheClcblx0IgotCQkicHVzaGZxXG5cdCIK
-LQkJInBvcHEgJSVyYXhcblx0IgotCQkiYW5kbCAkMSwlJWVheFxuIgotCQk6ICI9YSIocmMpCi0J
-CTogICAgImEiKHJlZ3MpCi0JCTogICAgIiVlYngiLCAiJWVjeCIsICIlZWR4IiwgIiVlc2kiLCAi
-JWVkaSIsICJtZW1vcnkiKTsKLSNlbHNlCi0JYXNtIHZvbGF0aWxlKCJwdXNobCAlJWVheFxuXHQi
-Ci0JICAgICJtb3ZsIDAoJSVlYXgpLCUlZWR4XG5cdCIKLQkgICAgInB1c2ggJSVlZHhcblx0Igot
-CSAgICAibW92bCA0KCUlZWF4KSwlJWVieFxuXHQiCi0JICAgICJtb3ZsIDgoJSVlYXgpLCUlZWN4
-XG5cdCIKLQkgICAgIm1vdmwgMTIoJSVlYXgpLCUlZWR4XG5cdCIKLQkgICAgIm1vdmwgMTYoJSVl
-YXgpLCUlZXNpXG5cdCIKLQkgICAgIm1vdmwgMjAoJSVlYXgpLCUlZWRpXG5cdCIKLQkgICAgInBv
-cGwgJSVlYXhcblx0IgotCSAgICAib3V0ICUlYWwsJDB4YjJcblx0IgotCSAgICAib3V0ICUlYWws
-JDB4ODRcblx0IgotCSAgICAieGNoZ2wgJSVlYXgsKCUlZXNwKVxuXHQiCi0JICAgICJtb3ZsICUl
-ZWJ4LDQoJSVlYXgpXG5cdCIKLQkgICAgIm1vdmwgJSVlY3gsOCglJWVheClcblx0IgotCSAgICAi
-bW92bCAlJWVkeCwxMiglJWVheClcblx0IgotCSAgICAibW92bCAlJWVzaSwxNiglJWVheClcblx0
-IgotCSAgICAibW92bCAlJWVkaSwyMCglJWVheClcblx0IgotCSAgICAicG9wbCAlJWVkeFxuXHQi
-Ci0JICAgICJtb3ZsICUlZWR4LDAoJSVlYXgpXG5cdCIKLQkgICAgImxhaGZcblx0IgotCSAgICAi
-c2hybCAkOCwlJWVheFxuXHQiCi0JICAgICJhbmRsICQxLCUlZWF4XG4iCi0JICAgIDogIj1hIihy
-YykKLQkgICAgOiAgICAiYSIocmVncykKLQkgICAgOiAgICAiJWVieCIsICIlZWN4IiwgIiVlZHgi
-LCAiJWVzaSIsICIlZWRpIiwgIm1lbW9yeSIpOwotI2VuZGlmCi0JaWYgKHJjICE9IDAgfHwgKHJl
-Z3MtPmVheCAmIDB4ZmZmZikgPT0gMHhmZmZmIHx8IHJlZ3MtPmVheCA9PSBlYXgpCi0JCXJjID0g
-LUVJTlZBTDsKLQotb3V0OgotCXNldF9jcHVzX2FsbG93ZWRfcHRyKGN1cnJlbnQsIG9sZF9tYXNr
-KTsKLQlmcmVlX2NwdW1hc2tfdmFyKG9sZF9tYXNrKTsKLQlyZXR1cm4gcmM7Ci19Ci0KLS8qCi0g
-KiBSZWFkIHRoZSBGbiBrZXkgc3RhdHVzLgotICovCi1zdGF0aWMgaW50IGk4a19nZXRfZm5fc3Rh
-dHVzKHZvaWQpCi17Ci0Jc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01NX0ZO
-X1NUQVRVUywgfTsKLQlpbnQgcmM7Ci0KLQlyYyA9IGk4a19zbW0oJnJlZ3MpOwotCWlmIChyYyA8
-IDApCi0JCXJldHVybiByYzsKLQotCXN3aXRjaCAoKHJlZ3MuZWF4ID4+IEk4S19GTl9TSElGVCkg
-JiBJOEtfRk5fTUFTSykgewotCWNhc2UgSThLX0ZOX1VQOgotCQlyZXR1cm4gSThLX1ZPTF9VUDsK
-LQljYXNlIEk4S19GTl9ET1dOOgotCQlyZXR1cm4gSThLX1ZPTF9ET1dOOwotCWNhc2UgSThLX0ZO
-X01VVEU6Ci0JCXJldHVybiBJOEtfVk9MX01VVEU7Ci0JZGVmYXVsdDoKLQkJcmV0dXJuIDA7Ci0J
-fQotfQotCi0vKgotICogUmVhZCB0aGUgcG93ZXIgc3RhdHVzLgotICovCi1zdGF0aWMgaW50IGk4
-a19nZXRfcG93ZXJfc3RhdHVzKHZvaWQpCi17Ci0Jc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5l
-YXggPSBJOEtfU01NX1BPV0VSX1NUQVRVUywgfTsKLQlpbnQgcmM7Ci0KLQlyYyA9IGk4a19zbW0o
-JnJlZ3MpOwotCWlmIChyYyA8IDApCi0JCXJldHVybiByYzsKLQotCXJldHVybiAocmVncy5lYXgg
-JiAweGZmKSA9PSBJOEtfUE9XRVJfQUMgPyBJOEtfQUMgOiBJOEtfQkFUVEVSWTsKLX0KLQotLyoK
-LSAqIFJlYWQgdGhlIGZhbiBzdGF0dXMuCi0gKi8KLXN0YXRpYyBpbnQgaThrX2dldF9mYW5fc3Rh
-dHVzKGludCBmYW4pCi17Ci0Jc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01N
-X0dFVF9GQU4sIH07Ci0KLQlyZWdzLmVieCA9IGZhbiAmIDB4ZmY7Ci0JcmV0dXJuIGk4a19zbW0o
-JnJlZ3MpID8gOiByZWdzLmVheCAmIDB4ZmY7Ci19Ci0KLS8qCi0gKiBSZWFkIHRoZSBmYW4gc3Bl
-ZWQgaW4gUlBNLgotICovCi1zdGF0aWMgaW50IGk4a19nZXRfZmFuX3NwZWVkKGludCBmYW4pCi17
-Ci0Jc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01NX0dFVF9TUEVFRCwgfTsK
-LQotCXJlZ3MuZWJ4ID0gZmFuICYgMHhmZjsKLQlyZXR1cm4gaThrX3NtbSgmcmVncykgPyA6IChy
-ZWdzLmVheCAmIDB4ZmZmZikgKiBpOGtfZmFuX211bHQ7Ci19Ci0KLS8qCi0gKiBSZWFkIHRoZSBm
-YW4gdHlwZS4KLSAqLwotc3RhdGljIGludCBpOGtfZ2V0X2Zhbl90eXBlKGludCBmYW4pCi17Ci0J
-c3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01NX0dFVF9GQU5fVFlQRSwgfTsK
-LQotCXJlZ3MuZWJ4ID0gZmFuICYgMHhmZjsKLQlyZXR1cm4gaThrX3NtbSgmcmVncykgPyA6IHJl
-Z3MuZWF4ICYgMHhmZjsKLX0KLQotLyoKLSAqIFJlYWQgdGhlIGZhbiBub21pbmFsIHJwbSBmb3Ig
-c3BlY2lmaWMgZmFuIHNwZWVkLgotICovCi1zdGF0aWMgaW50IGk4a19nZXRfZmFuX25vbWluYWxf
-c3BlZWQoaW50IGZhbiwgaW50IHNwZWVkKQotewotCXN0cnVjdCBzbW1fcmVncyByZWdzID0geyAu
-ZWF4ID0gSThLX1NNTV9HRVRfTk9NX1NQRUVELCB9OwotCi0JcmVncy5lYnggPSAoZmFuICYgMHhm
-ZikgfCAoc3BlZWQgPDwgOCk7Ci0JcmV0dXJuIGk4a19zbW0oJnJlZ3MpID8gOiAocmVncy5lYXgg
-JiAweGZmZmYpICogaThrX2Zhbl9tdWx0OwotfQotCi0vKgotICogU2V0IHRoZSBmYW4gc3BlZWQg
-KG9mZiwgbG93LCBoaWdoKS4gUmV0dXJucyB0aGUgbmV3IGZhbiBzdGF0dXMuCi0gKi8KLXN0YXRp
-YyBpbnQgaThrX3NldF9mYW4oaW50IGZhbiwgaW50IHNwZWVkKQotewotCXN0cnVjdCBzbW1fcmVn
-cyByZWdzID0geyAuZWF4ID0gSThLX1NNTV9TRVRfRkFOLCB9OwotCi0Jc3BlZWQgPSAoc3BlZWQg
-PCAwKSA/IDAgOiAoKHNwZWVkID4gaThrX2Zhbl9tYXgpID8gaThrX2Zhbl9tYXggOiBzcGVlZCk7
-Ci0JcmVncy5lYnggPSAoZmFuICYgMHhmZikgfCAoc3BlZWQgPDwgOCk7Ci0KLQlyZXR1cm4gaThr
-X3NtbSgmcmVncykgPyA6IGk4a19nZXRfZmFuX3N0YXR1cyhmYW4pOwotfQotCi1zdGF0aWMgaW50
-IGk4a19nZXRfdGVtcF90eXBlKGludCBzZW5zb3IpCi17Ci0Jc3RydWN0IHNtbV9yZWdzIHJlZ3Mg
-PSB7IC5lYXggPSBJOEtfU01NX0dFVF9URU1QX1RZUEUsIH07Ci0KLQlyZWdzLmVieCA9IHNlbnNv
-ciAmIDB4ZmY7Ci0JcmV0dXJuIGk4a19zbW0oJnJlZ3MpID8gOiByZWdzLmVheCAmIDB4ZmY7Ci19
-Ci0KLS8qCi0gKiBSZWFkIHRoZSBjcHUgdGVtcGVyYXR1cmUuCi0gKi8KLXN0YXRpYyBpbnQgX2k4
-a19nZXRfdGVtcChpbnQgc2Vuc29yKQotewotCXN0cnVjdCBzbW1fcmVncyByZWdzID0gewotCQku
-ZWF4ID0gSThLX1NNTV9HRVRfVEVNUCwKLQkJLmVieCA9IHNlbnNvciAmIDB4ZmYsCi0JfTsKLQot
-CXJldHVybiBpOGtfc21tKCZyZWdzKSA/IDogcmVncy5lYXggJiAweGZmOwotfQotCi1zdGF0aWMg
-aW50IGk4a19nZXRfdGVtcChpbnQgc2Vuc29yKQotewotCWludCB0ZW1wID0gX2k4a19nZXRfdGVt
-cChzZW5zb3IpOwotCi0JLyoKLQkgKiBTb21ldGltZXMgdGhlIHRlbXBlcmF0dXJlIHNlbnNvciBy
-ZXR1cm5zIDB4OTksIHdoaWNoIGlzIG91dCBvZiByYW5nZS4KLQkgKiBJbiB0aGlzIGNhc2Ugd2Ug
-cmV0cnkgKG9uY2UpIGJlZm9yZSByZXR1cm5pbmcgYW4gZXJyb3IuCi0JICMgMTAwMzY1NTEzNyAw
-MDAwMDA1OCAwMDAwNWE0YgotCSAjIDEwMDM2NTUxMzggMDAwMDAwOTkgMDAwMDNhODAgPC0tLSAw
-eDk5ID0gMTUzIGRlZ3JlZXMKLQkgIyAxMDAzNjU1MTM5IDAwMDAwMDU0IDAwMDA1YzUyCi0JICov
-Ci0JaWYgKHRlbXAgPT0gMHg5OSkgewotCQltc2xlZXAoMTAwKTsKLQkJdGVtcCA9IF9pOGtfZ2V0
-X3RlbXAoc2Vuc29yKTsKLQl9Ci0JLyoKLQkgKiBSZXR1cm4gLUVOT0RBVEEgZm9yIGFsbCBpbnZh
-bGlkIHRlbXBlcmF0dXJlcy4KLQkgKgotCSAqIEtub3duIGluc3RhbmNlcyBhcmUgdGhlIDB4OTkg
-dmFsdWUgYXMgc2VlbiBhYm92ZSBhcyB3ZWxsIGFzCi0JICogMHhjMSAoMTkzKSwgd2hpY2ggbWF5
-IGJlIHJldHVybmVkIHdoZW4gdHJ5aW5nIHRvIHJlYWQgdGhlIEdQVQotCSAqIHRlbXBlcmF0dXJl
-IGlmIHRoZSBzeXN0ZW0gc3VwcG9ydHMgYSBHUFUgYW5kIGl0IGlzIGN1cnJlbnRseQotCSAqIHR1
-cm5lZCBvZmYuCi0JICovCi0JaWYgKHRlbXAgPiBJOEtfTUFYX1RFTVApCi0JCXJldHVybiAtRU5P
-REFUQTsKLQotCXJldHVybiB0ZW1wOwotfQotCi1zdGF0aWMgaW50IGk4a19nZXRfZGVsbF9zaWdu
-YXR1cmUoaW50IHJlcV9mbikKLXsKLQlzdHJ1Y3Qgc21tX3JlZ3MgcmVncyA9IHsgLmVheCA9IHJl
-cV9mbiwgfTsKLQlpbnQgcmM7Ci0KLQlyYyA9IGk4a19zbW0oJnJlZ3MpOwotCWlmIChyYyA8IDAp
-Ci0JCXJldHVybiByYzsKLQotCXJldHVybiByZWdzLmVheCA9PSAxMTQ1NjUxNTI3ICYmIHJlZ3Mu
-ZWR4ID09IDExNDUzOTIyMDQgPyAwIDogLTE7Ci19Ci0KLXN0YXRpYyBpbnQKLWk4a19pb2N0bF91
-bmxvY2tlZChzdHJ1Y3QgZmlsZSAqZnAsIHVuc2lnbmVkIGludCBjbWQsIHVuc2lnbmVkIGxvbmcg
-YXJnKQotewotCWludCB2YWwgPSAwOwotCWludCBzcGVlZDsKLQl1bnNpZ25lZCBjaGFyIGJ1ZmZb
-MTZdOwotCWludCBfX3VzZXIgKmFyZ3AgPSAoaW50IF9fdXNlciAqKWFyZzsKLQotCWlmICghYXJn
-cCkKLQkJcmV0dXJuIC1FSU5WQUw7Ci0KLQlzd2l0Y2ggKGNtZCkgewotCWNhc2UgSThLX0JJT1Nf
-VkVSU0lPTjoKLQkJdmFsID0gKGJpb3NfdmVyc2lvblswXSA8PCAxNikgfAotCQkJCShiaW9zX3Zl
-cnNpb25bMV0gPDwgOCkgfCBiaW9zX3ZlcnNpb25bMl07Ci0JCWJyZWFrOwotCi0JY2FzZSBJOEtf
-TUFDSElORV9JRDoKLQkJbWVtc2V0KGJ1ZmYsIDAsIDE2KTsKLQkJc3RybGNweShidWZmLCBpOGtf
-Z2V0X2RtaV9kYXRhKERNSV9QUk9EVUNUX1NFUklBTCksCi0JCQlzaXplb2YoYnVmZikpOwotCQli
-cmVhazsKLQotCWNhc2UgSThLX0ZOX1NUQVRVUzoKLQkJdmFsID0gaThrX2dldF9mbl9zdGF0dXMo
-KTsKLQkJYnJlYWs7Ci0KLQljYXNlIEk4S19QT1dFUl9TVEFUVVM6Ci0JCXZhbCA9IGk4a19nZXRf
-cG93ZXJfc3RhdHVzKCk7Ci0JCWJyZWFrOwotCi0JY2FzZSBJOEtfR0VUX1RFTVA6Ci0JCXZhbCA9
-IGk4a19nZXRfdGVtcCgwKTsKLQkJYnJlYWs7Ci0KLQljYXNlIEk4S19HRVRfU1BFRUQ6Ci0JCWlm
-IChjb3B5X2Zyb21fdXNlcigmdmFsLCBhcmdwLCBzaXplb2YoaW50KSkpCi0JCQlyZXR1cm4gLUVG
-QVVMVDsKLQotCQl2YWwgPSBpOGtfZ2V0X2Zhbl9zcGVlZCh2YWwpOwotCQlicmVhazsKLQotCWNh
-c2UgSThLX0dFVF9GQU46Ci0JCWlmIChjb3B5X2Zyb21fdXNlcigmdmFsLCBhcmdwLCBzaXplb2Yo
-aW50KSkpCi0JCQlyZXR1cm4gLUVGQVVMVDsKLQotCQl2YWwgPSBpOGtfZ2V0X2Zhbl9zdGF0dXMo
-dmFsKTsKLQkJYnJlYWs7Ci0KLQljYXNlIEk4S19TRVRfRkFOOgotCQlpZiAocmVzdHJpY3RlZCAm
-JiAhY2FwYWJsZShDQVBfU1lTX0FETUlOKSkKLQkJCXJldHVybiAtRVBFUk07Ci0KLQkJaWYgKGNv
-cHlfZnJvbV91c2VyKCZ2YWwsIGFyZ3AsIHNpemVvZihpbnQpKSkKLQkJCXJldHVybiAtRUZBVUxU
-OwotCi0JCWlmIChjb3B5X2Zyb21fdXNlcigmc3BlZWQsIGFyZ3AgKyAxLCBzaXplb2YoaW50KSkp
-Ci0JCQlyZXR1cm4gLUVGQVVMVDsKLQotCQl2YWwgPSBpOGtfc2V0X2Zhbih2YWwsIHNwZWVkKTsK
-LQkJYnJlYWs7Ci0KLQlkZWZhdWx0OgotCQlyZXR1cm4gLUVJTlZBTDsKLQl9Ci0KLQlpZiAodmFs
-IDwgMCkKLQkJcmV0dXJuIHZhbDsKLQotCXN3aXRjaCAoY21kKSB7Ci0JY2FzZSBJOEtfQklPU19W
-RVJTSU9OOgotCQlpZiAoY29weV90b191c2VyKGFyZ3AsICZ2YWwsIDQpKQotCQkJcmV0dXJuIC1F
-RkFVTFQ7Ci0KLQkJYnJlYWs7Ci0JY2FzZSBJOEtfTUFDSElORV9JRDoKLQkJaWYgKGNvcHlfdG9f
-dXNlcihhcmdwLCBidWZmLCAxNikpCi0JCQlyZXR1cm4gLUVGQVVMVDsKLQotCQlicmVhazsKLQlk
-ZWZhdWx0OgotCQlpZiAoY29weV90b191c2VyKGFyZ3AsICZ2YWwsIHNpemVvZihpbnQpKSkKLQkJ
-CXJldHVybiAtRUZBVUxUOwotCi0JCWJyZWFrOwotCX0KLQotCXJldHVybiAwOwotfQotCi1zdGF0
-aWMgbG9uZyBpOGtfaW9jdGwoc3RydWN0IGZpbGUgKmZwLCB1bnNpZ25lZCBpbnQgY21kLCB1bnNp
-Z25lZCBsb25nIGFyZykKLXsKLQlsb25nIHJldDsKLQotCW11dGV4X2xvY2soJmk4a19tdXRleCk7
-Ci0JcmV0ID0gaThrX2lvY3RsX3VubG9ja2VkKGZwLCBjbWQsIGFyZyk7Ci0JbXV0ZXhfdW5sb2Nr
-KCZpOGtfbXV0ZXgpOwotCi0JcmV0dXJuIHJldDsKLX0KLQotLyoKLSAqIFByaW50IHRoZSBpbmZv
-cm1hdGlvbiBmb3IgL3Byb2MvaThrLgotICovCi1zdGF0aWMgaW50IGk4a19wcm9jX3Nob3coc3Ry
-dWN0IHNlcV9maWxlICpzZXEsIHZvaWQgKm9mZnNldCkKLXsKLQlpbnQgZm5fa2V5LCBjcHVfdGVt
-cCwgYWNfcG93ZXI7Ci0JaW50IGxlZnRfZmFuLCByaWdodF9mYW4sIGxlZnRfc3BlZWQsIHJpZ2h0
-X3NwZWVkOwotCi0JY3B1X3RlbXAJPSBpOGtfZ2V0X3RlbXAoMCk7CQkJLyogMTExMDAgwrVzICov
-Ci0JbGVmdF9mYW4JPSBpOGtfZ2V0X2Zhbl9zdGF0dXMoSThLX0ZBTl9MRUZUKTsJLyogICA1ODAg
-wrVzICovCi0JcmlnaHRfZmFuCT0gaThrX2dldF9mYW5fc3RhdHVzKEk4S19GQU5fUklHSFQpOwkv
-KiAgIDU4MCDCtXMgKi8KLQlsZWZ0X3NwZWVkCT0gaThrX2dldF9mYW5fc3BlZWQoSThLX0ZBTl9M
-RUZUKTsJLyogICA1ODAgwrVzICovCi0JcmlnaHRfc3BlZWQJPSBpOGtfZ2V0X2Zhbl9zcGVlZChJ
-OEtfRkFOX1JJR0hUKTsJLyogICA1ODAgwrVzICovCi0JZm5fa2V5CQk9IGk4a19nZXRfZm5fc3Rh
-dHVzKCk7CQkJLyogICA3NTAgwrVzICovCi0JaWYgKHBvd2VyX3N0YXR1cykKLQkJYWNfcG93ZXIg
-PSBpOGtfZ2V0X3Bvd2VyX3N0YXR1cygpOwkJLyogMTQ3MDAgwrVzICovCi0JZWxzZQotCQlhY19w
-b3dlciA9IC0xOwotCi0JLyoKLQkgKiBJbmZvOgotCSAqCi0JICogMSkgIEZvcm1hdCB2ZXJzaW9u
-ICh0aGlzIHdpbGwgY2hhbmdlIGlmIGZvcm1hdCBjaGFuZ2VzKQotCSAqIDIpICBCSU9TIHZlcnNp
-b24KLQkgKiAzKSAgQklPUyBtYWNoaW5lIElECi0JICogNCkgIENwdSB0ZW1wZXJhdHVyZQotCSAq
-IDUpICBMZWZ0IGZhbiBzdGF0dXMKLQkgKiA2KSAgUmlnaHQgZmFuIHN0YXR1cwotCSAqIDcpICBM
-ZWZ0IGZhbiBzcGVlZAotCSAqIDgpICBSaWdodCBmYW4gc3BlZWQKLQkgKiA5KSAgQUMgcG93ZXIK
-LQkgKiAxMCkgRm4gS2V5IHN0YXR1cwotCSAqLwotCXJldHVybiBzZXFfcHJpbnRmKHNlcSwgIiVz
-ICVzICVzICVkICVkICVkICVkICVkICVkICVkXG4iLAotCQkJICBJOEtfUFJPQ19GTVQsCi0JCQkg
-IGJpb3NfdmVyc2lvbiwKLQkJCSAgaThrX2dldF9kbWlfZGF0YShETUlfUFJPRFVDVF9TRVJJQUwp
-LAotCQkJICBjcHVfdGVtcCwKLQkJCSAgbGVmdF9mYW4sIHJpZ2h0X2ZhbiwgbGVmdF9zcGVlZCwg
-cmlnaHRfc3BlZWQsCi0JCQkgIGFjX3Bvd2VyLCBmbl9rZXkpOwotfQotCi1zdGF0aWMgaW50IGk4
-a19vcGVuX2ZzKHN0cnVjdCBpbm9kZSAqaW5vZGUsIHN0cnVjdCBmaWxlICpmaWxlKQotewotCXJl
-dHVybiBzaW5nbGVfb3BlbihmaWxlLCBpOGtfcHJvY19zaG93LCBOVUxMKTsKLX0KLQotCi0vKgot
-ICogSHdtb24gaW50ZXJmYWNlCi0gKi8KLQotc3RhdGljIHNzaXplX3QgaThrX2h3bW9uX3Nob3df
-dGVtcF9sYWJlbChzdHJ1Y3QgZGV2aWNlICpkZXYsCi0JCQkJCSBzdHJ1Y3QgZGV2aWNlX2F0dHJp
-YnV0ZSAqZGV2YXR0ciwKLQkJCQkJIGNoYXIgKmJ1ZikKLXsKLQlzdGF0aWMgY29uc3QgY2hhciAq
-IGNvbnN0IGxhYmVsc1tdID0gewotCQkiQ1BVIiwKLQkJIkdQVSIsCi0JCSJTT0RJTU0iLAotCQki
-T3RoZXIiLAotCQkiQW1iaWVudCIsCi0JCSJPdGhlciIsCi0JfTsKLQlpbnQgaW5kZXggPSB0b19z
-ZW5zb3JfZGV2X2F0dHIoZGV2YXR0ciktPmluZGV4OwotCWludCB0eXBlOwotCi0JdHlwZSA9IGk4
-a19nZXRfdGVtcF90eXBlKGluZGV4KTsKLQlpZiAodHlwZSA8IDApCi0JCXJldHVybiB0eXBlOwot
-CWlmICh0eXBlID49IEFSUkFZX1NJWkUobGFiZWxzKSkKLQkJdHlwZSA9IEFSUkFZX1NJWkUobGFi
-ZWxzKSAtIDE7Ci0JcmV0dXJuIHNwcmludGYoYnVmLCAiJXNcbiIsIGxhYmVsc1t0eXBlXSk7Ci19
-Ci0KLXN0YXRpYyBzc2l6ZV90IGk4a19od21vbl9zaG93X3RlbXAoc3RydWN0IGRldmljZSAqZGV2
-LAotCQkJCSAgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkZXZhdHRyLAotCQkJCSAgIGNoYXIg
-KmJ1ZikKLXsKLQlpbnQgaW5kZXggPSB0b19zZW5zb3JfZGV2X2F0dHIoZGV2YXR0ciktPmluZGV4
-OwotCWludCB0ZW1wOwotCi0JdGVtcCA9IGk4a19nZXRfdGVtcChpbmRleCk7Ci0JaWYgKHRlbXAg
-PCAwKQotCQlyZXR1cm4gdGVtcDsKLQlyZXR1cm4gc3ByaW50ZihidWYsICIlZFxuIiwgdGVtcCAq
-IDEwMDApOwotfQotCi1zdGF0aWMgc3NpemVfdCBpOGtfaHdtb25fc2hvd19mYW5fbGFiZWwoc3Ry
-dWN0IGRldmljZSAqZGV2LAotCQkJCQlzdHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZSAqZGV2YXR0ciwK
-LQkJCQkJY2hhciAqYnVmKQotewotCXN0YXRpYyBjb25zdCBjaGFyICogY29uc3QgbGFiZWxzW10g
-PSB7Ci0JCSJQcm9jZXNzb3IgRmFuIiwKLQkJIk1vdGhlcmJvYXJkIEZhbiIsCi0JCSJWaWRlbyBG
-YW4iLAotCQkiUG93ZXIgU3VwcGx5IEZhbiIsCi0JCSJDaGlwc2V0IEZhbiIsCi0JCSJPdGhlciBG
-YW4iLAotCX07Ci0JaW50IGluZGV4ID0gdG9fc2Vuc29yX2Rldl9hdHRyKGRldmF0dHIpLT5pbmRl
-eDsKLQlib29sIGRvY2sgPSBmYWxzZTsKLQlpbnQgdHlwZTsKLQotCXR5cGUgPSBpOGtfZ2V0X2Zh
-bl90eXBlKGluZGV4KTsKLQlpZiAodHlwZSA8IDApCi0JCXJldHVybiB0eXBlOwotCi0JaWYgKHR5
-cGUgJiAweDEwKSB7Ci0JCWRvY2sgPSB0cnVlOwotCQl0eXBlICY9IDB4MEY7Ci0JfQotCi0JaWYg
-KHR5cGUgPj0gQVJSQVlfU0laRShsYWJlbHMpKQotCQl0eXBlID0gKEFSUkFZX1NJWkUobGFiZWxz
-KSAtIDEpOwotCi0JcmV0dXJuIHNwcmludGYoYnVmLCAiJXMlc1xuIiwgKGRvY2sgPyAiRG9ja2lu
-ZyAiIDogIiIpLCBsYWJlbHNbdHlwZV0pOwotfQotCi1zdGF0aWMgc3NpemVfdCBpOGtfaHdtb25f
-c2hvd19mYW4oc3RydWN0IGRldmljZSAqZGV2LAotCQkJCSAgc3RydWN0IGRldmljZV9hdHRyaWJ1
-dGUgKmRldmF0dHIsCi0JCQkJICBjaGFyICpidWYpCi17Ci0JaW50IGluZGV4ID0gdG9fc2Vuc29y
-X2Rldl9hdHRyKGRldmF0dHIpLT5pbmRleDsKLQlpbnQgZmFuX3NwZWVkOwotCi0JZmFuX3NwZWVk
-ID0gaThrX2dldF9mYW5fc3BlZWQoaW5kZXgpOwotCWlmIChmYW5fc3BlZWQgPCAwKQotCQlyZXR1
-cm4gZmFuX3NwZWVkOwotCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiVkXG4iLCBmYW5fc3BlZWQpOwot
-fQotCi1zdGF0aWMgc3NpemVfdCBpOGtfaHdtb25fc2hvd19wd20oc3RydWN0IGRldmljZSAqZGV2
-LAotCQkJCSAgc3RydWN0IGRldmljZV9hdHRyaWJ1dGUgKmRldmF0dHIsCi0JCQkJICBjaGFyICpi
-dWYpCi17Ci0JaW50IGluZGV4ID0gdG9fc2Vuc29yX2Rldl9hdHRyKGRldmF0dHIpLT5pbmRleDsK
-LQlpbnQgc3RhdHVzOwotCi0Jc3RhdHVzID0gaThrX2dldF9mYW5fc3RhdHVzKGluZGV4KTsKLQlp
-ZiAoc3RhdHVzIDwgMCkKLQkJcmV0dXJuIC1FSU87Ci0JcmV0dXJuIHNwcmludGYoYnVmLCAiJWRc
-biIsIGNsYW1wX3ZhbChzdGF0dXMgKiBpOGtfcHdtX211bHQsIDAsIDI1NSkpOwotfQotCi1zdGF0
-aWMgc3NpemVfdCBpOGtfaHdtb25fc2V0X3B3bShzdHJ1Y3QgZGV2aWNlICpkZXYsCi0JCQkJIHN0
-cnVjdCBkZXZpY2VfYXR0cmlidXRlICphdHRyLAotCQkJCSBjb25zdCBjaGFyICpidWYsIHNpemVf
-dCBjb3VudCkKLXsKLQlpbnQgaW5kZXggPSB0b19zZW5zb3JfZGV2X2F0dHIoYXR0ciktPmluZGV4
-OwotCXVuc2lnbmVkIGxvbmcgdmFsOwotCWludCBlcnI7Ci0KLQllcnIgPSBrc3RydG91bChidWYs
-IDEwLCAmdmFsKTsKLQlpZiAoZXJyKQotCQlyZXR1cm4gZXJyOwotCXZhbCA9IGNsYW1wX3ZhbChE
-SVZfUk9VTkRfQ0xPU0VTVCh2YWwsIGk4a19wd21fbXVsdCksIDAsIGk4a19mYW5fbWF4KTsKLQot
-CW11dGV4X2xvY2soJmk4a19tdXRleCk7Ci0JZXJyID0gaThrX3NldF9mYW4oaW5kZXgsIHZhbCk7
-Ci0JbXV0ZXhfdW5sb2NrKCZpOGtfbXV0ZXgpOwotCi0JcmV0dXJuIGVyciA8IDAgPyAtRUlPIDog
-Y291bnQ7Ci19Ci0KLXN0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfaW5wdXQsIFNfSVJV
-R08sIGk4a19od21vbl9zaG93X3RlbXAsIE5VTEwsIDApOwotc3RhdGljIFNFTlNPUl9ERVZJQ0Vf
-QVRUUih0ZW1wMV9sYWJlbCwgU19JUlVHTywgaThrX2h3bW9uX3Nob3dfdGVtcF9sYWJlbCwgTlVM
-TCwKLQkJCSAgMCk7Ci1zdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHRlbXAyX2lucHV0LCBTX0lS
-VUdPLCBpOGtfaHdtb25fc2hvd190ZW1wLCBOVUxMLCAxKTsKLXN0YXRpYyBTRU5TT1JfREVWSUNF
-X0FUVFIodGVtcDJfbGFiZWwsIFNfSVJVR08sIGk4a19od21vbl9zaG93X3RlbXBfbGFiZWwsIE5V
-TEwsCi0JCQkgIDEpOwotc3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wM19pbnB1dCwgU19J
-UlVHTywgaThrX2h3bW9uX3Nob3dfdGVtcCwgTlVMTCwgMik7Ci1zdGF0aWMgU0VOU09SX0RFVklD
-RV9BVFRSKHRlbXAzX2xhYmVsLCBTX0lSVUdPLCBpOGtfaHdtb25fc2hvd190ZW1wX2xhYmVsLCBO
-VUxMLAotCQkJICAyKTsKLXN0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDRfaW5wdXQsIFNf
-SVJVR08sIGk4a19od21vbl9zaG93X3RlbXAsIE5VTEwsIDMpOwotc3RhdGljIFNFTlNPUl9ERVZJ
-Q0VfQVRUUih0ZW1wNF9sYWJlbCwgU19JUlVHTywgaThrX2h3bW9uX3Nob3dfdGVtcF9sYWJlbCwg
-TlVMTCwKLQkJCSAgMyk7Ci1zdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKGZhbjFfaW5wdXQsIFNf
-SVJVR08sIGk4a19od21vbl9zaG93X2ZhbiwgTlVMTCwgMCk7Ci1zdGF0aWMgU0VOU09SX0RFVklD
-RV9BVFRSKGZhbjFfbGFiZWwsIFNfSVJVR08sIGk4a19od21vbl9zaG93X2Zhbl9sYWJlbCwgTlVM
-TCwKLQkJCSAgMCk7Ci1zdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHB3bTEsIFNfSVJVR08gfCBT
-X0lXVVNSLCBpOGtfaHdtb25fc2hvd19wd20sCi0JCQkgIGk4a19od21vbl9zZXRfcHdtLCAwKTsK
-LXN0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIoZmFuMl9pbnB1dCwgU19JUlVHTywgaThrX2h3bW9u
-X3Nob3dfZmFuLCBOVUxMLAotCQkJICAxKTsKLXN0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIoZmFu
-Ml9sYWJlbCwgU19JUlVHTywgaThrX2h3bW9uX3Nob3dfZmFuX2xhYmVsLCBOVUxMLAotCQkJICAx
-KTsKLXN0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIocHdtMiwgU19JUlVHTyB8IFNfSVdVU1IsIGk4
-a19od21vbl9zaG93X3B3bSwKLQkJCSAgaThrX2h3bW9uX3NldF9wd20sIDEpOwotCi1zdGF0aWMg
-c3RydWN0IGF0dHJpYnV0ZSAqaThrX2F0dHJzW10gPSB7Ci0JJnNlbnNvcl9kZXZfYXR0cl90ZW1w
-MV9pbnB1dC5kZXZfYXR0ci5hdHRyLAkvKiAwICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9s
-YWJlbC5kZXZfYXR0ci5hdHRyLAkvKiAxICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wMl9pbnB1
-dC5kZXZfYXR0ci5hdHRyLAkvKiAyICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wMl9sYWJlbC5k
-ZXZfYXR0ci5hdHRyLAkvKiAzICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wM19pbnB1dC5kZXZf
-YXR0ci5hdHRyLAkvKiA0ICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wM19sYWJlbC5kZXZfYXR0
-ci5hdHRyLAkvKiA1ICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wNF9pbnB1dC5kZXZfYXR0ci5h
-dHRyLAkvKiA2ICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wNF9sYWJlbC5kZXZfYXR0ci5hdHRy
-LAkvKiA3ICovCi0JJnNlbnNvcl9kZXZfYXR0cl9mYW4xX2lucHV0LmRldl9hdHRyLmF0dHIsCS8q
-IDggKi8KLQkmc2Vuc29yX2Rldl9hdHRyX2ZhbjFfbGFiZWwuZGV2X2F0dHIuYXR0ciwJLyogOSAq
-LwotCSZzZW5zb3JfZGV2X2F0dHJfcHdtMS5kZXZfYXR0ci5hdHRyLAkJLyogMTAgKi8KLQkmc2Vu
-c29yX2Rldl9hdHRyX2ZhbjJfaW5wdXQuZGV2X2F0dHIuYXR0ciwJLyogMTEgKi8KLQkmc2Vuc29y
-X2Rldl9hdHRyX2ZhbjJfbGFiZWwuZGV2X2F0dHIuYXR0ciwJLyogMTIgKi8KLQkmc2Vuc29yX2Rl
-dl9hdHRyX3B3bTIuZGV2X2F0dHIuYXR0ciwJCS8qIDEzICovCi0JTlVMTAotfTsKLQotc3RhdGlj
-IHVtb2RlX3QgaThrX2lzX3Zpc2libGUoc3RydWN0IGtvYmplY3QgKmtvYmosIHN0cnVjdCBhdHRy
-aWJ1dGUgKmF0dHIsCi0JCQkgICAgICBpbnQgaW5kZXgpCi17Ci0JaWYgKGluZGV4ID49IDAgJiYg
-aW5kZXggPD0gMSAmJgotCSAgICAhKGk4a19od21vbl9mbGFncyAmIEk4S19IV01PTl9IQVZFX1RF
-TVAxKSkKLQkJcmV0dXJuIDA7Ci0JaWYgKGluZGV4ID49IDIgJiYgaW5kZXggPD0gMyAmJgotCSAg
-ICAhKGk4a19od21vbl9mbGFncyAmIEk4S19IV01PTl9IQVZFX1RFTVAyKSkKLQkJcmV0dXJuIDA7
-Ci0JaWYgKGluZGV4ID49IDQgJiYgaW5kZXggPD0gNSAmJgotCSAgICAhKGk4a19od21vbl9mbGFn
-cyAmIEk4S19IV01PTl9IQVZFX1RFTVAzKSkKLQkJcmV0dXJuIDA7Ci0JaWYgKGluZGV4ID49IDYg
-JiYgaW5kZXggPD0gNyAmJgotCSAgICAhKGk4a19od21vbl9mbGFncyAmIEk4S19IV01PTl9IQVZF
-X1RFTVA0KSkKLQkJcmV0dXJuIDA7Ci0JaWYgKGluZGV4ID49IDggJiYgaW5kZXggPD0gMTAgJiYK
-LQkgICAgIShpOGtfaHdtb25fZmxhZ3MgJiBJOEtfSFdNT05fSEFWRV9GQU4xKSkKLQkJcmV0dXJu
-IDA7Ci0JaWYgKGluZGV4ID49IDExICYmIGluZGV4IDw9IDEzICYmCi0JICAgICEoaThrX2h3bW9u
-X2ZsYWdzICYgSThLX0hXTU9OX0hBVkVfRkFOMikpCi0JCXJldHVybiAwOwotCi0JcmV0dXJuIGF0
-dHItPm1vZGU7Ci19Ci0KLXN0YXRpYyBjb25zdCBzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIGk4a19n
-cm91cCA9IHsKLQkuYXR0cnMgPSBpOGtfYXR0cnMsCi0JLmlzX3Zpc2libGUgPSBpOGtfaXNfdmlz
-aWJsZSwKLX07Ci1fX0FUVFJJQlVURV9HUk9VUFMoaThrKTsKLQotc3RhdGljIGludCBfX2luaXQg
-aThrX2luaXRfaHdtb24odm9pZCkKLXsKLQlpbnQgZXJyOwotCi0JaThrX2h3bW9uX2ZsYWdzID0g
-MDsKLQotCS8qIENQVSB0ZW1wZXJhdHVyZSBhdHRyaWJ1dGVzLCBpZiB0ZW1wZXJhdHVyZSB0eXBl
-IGlzIE9LICovCi0JZXJyID0gaThrX2dldF90ZW1wX3R5cGUoMCk7Ci0JaWYgKGVyciA+PSAwKQot
-CQlpOGtfaHdtb25fZmxhZ3MgfD0gSThLX0hXTU9OX0hBVkVfVEVNUDE7Ci0JLyogY2hlY2sgZm9y
-IGFkZGl0aW9uYWwgdGVtcGVyYXR1cmUgc2Vuc29ycyAqLwotCWVyciA9IGk4a19nZXRfdGVtcF90
-eXBlKDEpOwotCWlmIChlcnIgPj0gMCkKLQkJaThrX2h3bW9uX2ZsYWdzIHw9IEk4S19IV01PTl9I
-QVZFX1RFTVAyOwotCWVyciA9IGk4a19nZXRfdGVtcF90eXBlKDIpOwotCWlmIChlcnIgPj0gMCkK
-LQkJaThrX2h3bW9uX2ZsYWdzIHw9IEk4S19IV01PTl9IQVZFX1RFTVAzOwotCWVyciA9IGk4a19n
-ZXRfdGVtcF90eXBlKDMpOwotCWlmIChlcnIgPj0gMCkKLQkJaThrX2h3bW9uX2ZsYWdzIHw9IEk4
-S19IV01PTl9IQVZFX1RFTVA0OwotCi0JLyogRmlyc3QgZmFuIGF0dHJpYnV0ZXMsIGlmIGZhbiB0
-eXBlIGlzIE9LICovCi0JZXJyID0gaThrX2dldF9mYW5fdHlwZSgwKTsKLQlpZiAoZXJyID49IDAp
-Ci0JCWk4a19od21vbl9mbGFncyB8PSBJOEtfSFdNT05fSEFWRV9GQU4xOwotCi0JLyogU2Vjb25k
-IGZhbiBhdHRyaWJ1dGVzLCBpZiBmYW4gdHlwZSBpcyBPSyAqLwotCWVyciA9IGk4a19nZXRfZmFu
-X3R5cGUoMSk7Ci0JaWYgKGVyciA+PSAwKQotCQlpOGtfaHdtb25fZmxhZ3MgfD0gSThLX0hXTU9O
-X0hBVkVfRkFOMjsKLQotCWk4a19od21vbl9kZXYgPSBod21vbl9kZXZpY2VfcmVnaXN0ZXJfd2l0
-aF9ncm91cHMoTlVMTCwgImk4ayIsIE5VTEwsCi0JCQkJCQkJICBpOGtfZ3JvdXBzKTsKLQlpZiAo
-SVNfRVJSKGk4a19od21vbl9kZXYpKSB7Ci0JCWVyciA9IFBUUl9FUlIoaThrX2h3bW9uX2Rldik7
-Ci0JCWk4a19od21vbl9kZXYgPSBOVUxMOwotCQlwcl9lcnIoImh3bW9uIHJlZ2lzdHJhdGlvbiBm
-YWlsZWQgKCVkKVxuIiwgZXJyKTsKLQkJcmV0dXJuIGVycjsKLQl9Ci0JcmV0dXJuIDA7Ci19Ci0K
-LXN0cnVjdCBpOGtfY29uZmlnX2RhdGEgewotCXVpbnQgZmFuX211bHQ7Ci0JdWludCBmYW5fbWF4
-OwotfTsKLQotZW51bSBpOGtfY29uZmlncyB7Ci0JREVMTF9MQVRJVFVERV9ENTIwLAotCURFTExf
-UFJFQ0lTSU9OXzQ5MCwKLQlERUxMX1NUVURJTywKLQlERUxMX1hQUywKLX07Ci0KLXN0YXRpYyBj
-b25zdCBzdHJ1Y3QgaThrX2NvbmZpZ19kYXRhIGk4a19jb25maWdfZGF0YVtdID0gewotCVtERUxM
-X0xBVElUVURFX0Q1MjBdID0gewotCQkuZmFuX211bHQgPSAxLAotCQkuZmFuX21heCA9IEk4S19G
-QU5fVFVSQk8sCi0JfSwKLQlbREVMTF9QUkVDSVNJT05fNDkwXSA9IHsKLQkJLmZhbl9tdWx0ID0g
-MSwKLQkJLmZhbl9tYXggPSBJOEtfRkFOX1RVUkJPLAotCX0sCi0JW0RFTExfU1RVRElPXSA9IHsK
-LQkJLmZhbl9tdWx0ID0gMSwKLQkJLmZhbl9tYXggPSBJOEtfRkFOX0hJR0gsCi0JfSwKLQlbREVM
-TF9YUFNdID0gewotCQkuZmFuX211bHQgPSAxLAotCQkuZmFuX21heCA9IEk4S19GQU5fSElHSCwK
-LQl9LAotfTsKLQotc3RhdGljIHN0cnVjdCBkbWlfc3lzdGVtX2lkIGk4a19kbWlfdGFibGVbXSBf
-X2luaXRkYXRhID0gewotCXsKLQkJLmlkZW50ID0gIkRlbGwgSW5zcGlyb24iLAotCQkubWF0Y2hl
-cyA9IHsKLQkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgQ29tcHV0ZXIiKSwKLQkJ
-CURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1FLCAiSW5zcGlyb24iKSwKLQkJfSwKLQl9LAotCXsK
-LQkJLmlkZW50ID0gIkRlbGwgTGF0aXR1ZGUiLAotCQkubWF0Y2hlcyA9IHsKLQkJCURNSV9NQVRD
-SChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgQ29tcHV0ZXIiKSwKLQkJCURNSV9NQVRDSChETUlfUFJP
-RFVDVF9OQU1FLCAiTGF0aXR1ZGUiKSwKLQkJfSwKLQl9LAotCXsKLQkJLmlkZW50ID0gIkRlbGwg
-SW5zcGlyb24gMiIsCi0JCS5tYXRjaGVzID0gewotCQkJRE1JX01BVENIKERNSV9TWVNfVkVORE9S
-LCAiRGVsbCBJbmMuIiksCi0JCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIkluc3Bpcm9u
-IiksCi0JCX0sCi0JfSwKLQl7Ci0JCS5pZGVudCA9ICJEZWxsIExhdGl0dWRlIEQ1MjAiLAotCQku
-bWF0Y2hlcyA9IHsKLQkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgSW5jLiIpLAot
-CQkJRE1JX01BVENIKERNSV9QUk9EVUNUX05BTUUsICJMYXRpdHVkZSBENTIwIiksCi0JCX0sCi0J
-CS5kcml2ZXJfZGF0YSA9ICh2b2lkICopJmk4a19jb25maWdfZGF0YVtERUxMX0xBVElUVURFX0Q1
-MjBdLAotCX0sCi0JewotCQkuaWRlbnQgPSAiRGVsbCBMYXRpdHVkZSAyIiwKLQkJLm1hdGNoZXMg
-PSB7Ci0JCQlETUlfTUFUQ0goRE1JX1NZU19WRU5ET1IsICJEZWxsIEluYy4iKSwKLQkJCURNSV9N
-QVRDSChETUlfUFJPRFVDVF9OQU1FLCAiTGF0aXR1ZGUiKSwKLQkJfSwKLQl9LAotCXsJLyogVUsg
-SW5zcGlyb24gNjQwMCAgKi8KLQkJLmlkZW50ID0gIkRlbGwgSW5zcGlyb24gMyIsCi0JCS5tYXRj
-aGVzID0gewotCQkJRE1JX01BVENIKERNSV9TWVNfVkVORE9SLCAiRGVsbCBJbmMuIiksCi0JCQlE
-TUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIk1NMDYxIiksCi0JCX0sCi0JfSwKLQl7Ci0JCS5p
-ZGVudCA9ICJEZWxsIEluc3Bpcm9uIDMiLAotCQkubWF0Y2hlcyA9IHsKLQkJCURNSV9NQVRDSChE
-TUlfU1lTX1ZFTkRPUiwgIkRlbGwgSW5jLiIpLAotCQkJRE1JX01BVENIKERNSV9QUk9EVUNUX05B
-TUUsICJNUDA2MSIpLAotCQl9LAotCX0sCi0JewotCQkuaWRlbnQgPSAiRGVsbCBQcmVjaXNpb24g
-NDkwIiwKLQkJLm1hdGNoZXMgPSB7Ci0JCQlETUlfTUFUQ0goRE1JX1NZU19WRU5ET1IsICJEZWxs
-IEluYy4iKSwKLQkJCURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1FLAotCQkJCSAgIlByZWNpc2lv
-biBXb3JrU3RhdGlvbiA0OTAiKSwKLQkJfSwKLQkJLmRyaXZlcl9kYXRhID0gKHZvaWQgKikmaThr
-X2NvbmZpZ19kYXRhW0RFTExfUFJFQ0lTSU9OXzQ5MF0sCi0JfSwKLQl7Ci0JCS5pZGVudCA9ICJE
-ZWxsIFByZWNpc2lvbiIsCi0JCS5tYXRjaGVzID0gewotCQkJRE1JX01BVENIKERNSV9TWVNfVkVO
-RE9SLCAiRGVsbCBJbmMuIiksCi0JCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIlByZWNp
-c2lvbiIpLAotCQl9LAotCX0sCi0JewotCQkuaWRlbnQgPSAiRGVsbCBWb3N0cm8iLAotCQkubWF0
-Y2hlcyA9IHsKLQkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgSW5jLiIpLAotCQkJ
-RE1JX01BVENIKERNSV9QUk9EVUNUX05BTUUsICJWb3N0cm8iKSwKLQkJfSwKLQl9LAotCXsKLQkJ
-LmlkZW50ID0gIkRlbGwgWFBTNDIxIiwKLQkJLm1hdGNoZXMgPSB7Ci0JCQlETUlfTUFUQ0goRE1J
-X1NZU19WRU5ET1IsICJEZWxsIEluYy4iKSwKLQkJCURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1F
-LCAiWFBTIEw0MjFYIiksCi0JCX0sCi0JfSwKLQl7Ci0JCS5pZGVudCA9ICJEZWxsIFN0dWRpbyIs
-Ci0JCS5tYXRjaGVzID0gewotCQkJRE1JX01BVENIKERNSV9TWVNfVkVORE9SLCAiRGVsbCBJbmMu
-IiksCi0JCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIlN0dWRpbyIpLAotCQl9LAotCQku
-ZHJpdmVyX2RhdGEgPSAodm9pZCAqKSZpOGtfY29uZmlnX2RhdGFbREVMTF9TVFVESU9dLAotCX0s
-Ci0JewotCQkuaWRlbnQgPSAiRGVsbCBYUFMgMTMiLAotCQkubWF0Y2hlcyA9IHsKLQkJCURNSV9N
-QVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgSW5jLiIpLAotCQkJRE1JX01BVENIKERNSV9QUk9E
-VUNUX05BTUUsICJYUFMxMyIpLAotCQl9LAotCQkuZHJpdmVyX2RhdGEgPSAodm9pZCAqKSZpOGtf
-Y29uZmlnX2RhdGFbREVMTF9YUFNdLAotCX0sCi0JewotCQkuaWRlbnQgPSAiRGVsbCBYUFMgTTE0
-MCIsCi0JCS5tYXRjaGVzID0gewotCQkJRE1JX01BVENIKERNSV9TWVNfVkVORE9SLCAiRGVsbCBJ
-bmMuIiksCi0JCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIk1YQzA1MSIpLAotCQl9LAot
-CQkuZHJpdmVyX2RhdGEgPSAodm9pZCAqKSZpOGtfY29uZmlnX2RhdGFbREVMTF9YUFNdLAotCX0s
-Ci0JeyB9Ci19OwotCi1NT0RVTEVfREVWSUNFX1RBQkxFKGRtaSwgaThrX2RtaV90YWJsZSk7Ci0K
-LS8qCi0gKiBQcm9iZSBmb3IgdGhlIHByZXNlbmNlIG9mIGEgc3VwcG9ydGVkIGxhcHRvcC4KLSAq
-Lwotc3RhdGljIGludCBfX2luaXQgaThrX3Byb2JlKHZvaWQpCi17Ci0JY29uc3Qgc3RydWN0IGRt
-aV9zeXN0ZW1faWQgKmlkOwotCWludCBmYW4sIHJldDsKLQotCS8qCi0JICogR2V0IERNSSBpbmZv
-cm1hdGlvbgotCSAqLwotCWlmICghZG1pX2NoZWNrX3N5c3RlbShpOGtfZG1pX3RhYmxlKSkgewot
-CQlpZiAoIWlnbm9yZV9kbWkgJiYgIWZvcmNlKQotCQkJcmV0dXJuIC1FTk9ERVY7Ci0KLQkJcHJf
-aW5mbygibm90IHJ1bm5pbmcgb24gYSBzdXBwb3J0ZWQgRGVsbCBzeXN0ZW0uXG4iKTsKLQkJcHJf
-aW5mbygidmVuZG9yPSVzLCBtb2RlbD0lcywgdmVyc2lvbj0lc1xuIiwKLQkJCWk4a19nZXRfZG1p
-X2RhdGEoRE1JX1NZU19WRU5ET1IpLAotCQkJaThrX2dldF9kbWlfZGF0YShETUlfUFJPRFVDVF9O
-QU1FKSwKLQkJCWk4a19nZXRfZG1pX2RhdGEoRE1JX0JJT1NfVkVSU0lPTikpOwotCX0KLQotCXN0
-cmxjcHkoYmlvc192ZXJzaW9uLCBpOGtfZ2V0X2RtaV9kYXRhKERNSV9CSU9TX1ZFUlNJT04pLAot
-CQlzaXplb2YoYmlvc192ZXJzaW9uKSk7Ci0KLQkvKgotCSAqIEdldCBTTU0gRGVsbCBzaWduYXR1
-cmUKLQkgKi8KLQlpZiAoaThrX2dldF9kZWxsX3NpZ25hdHVyZShJOEtfU01NX0dFVF9ERUxMX1NJ
-RzEpICYmCi0JICAgIGk4a19nZXRfZGVsbF9zaWduYXR1cmUoSThLX1NNTV9HRVRfREVMTF9TSUcy
-KSkgewotCQlwcl9lcnIoInVuYWJsZSB0byBnZXQgU01NIERlbGwgc2lnbmF0dXJlXG4iKTsKLQkJ
-aWYgKCFmb3JjZSkKLQkJCXJldHVybiAtRU5PREVWOwotCX0KLQotCS8qCi0JICogU2V0IGZhbiBt
-dWx0aXBsaWVyIGFuZCBtYXhpbWFsIGZhbiBzcGVlZCBmcm9tIGRtaSBjb25maWcKLQkgKiBWYWx1
-ZXMgc3BlY2lmaWVkIGluIG1vZHVsZSBwYXJhbWV0ZXJzIG92ZXJyaWRlIHZhbHVlcyBmcm9tIGRt
-aQotCSAqLwotCWlkID0gZG1pX2ZpcnN0X21hdGNoKGk4a19kbWlfdGFibGUpOwotCWlmIChpZCAm
-JiBpZC0+ZHJpdmVyX2RhdGEpIHsKLQkJY29uc3Qgc3RydWN0IGk4a19jb25maWdfZGF0YSAqY29u
-ZiA9IGlkLT5kcml2ZXJfZGF0YTsKLQkJaWYgKCFmYW5fbXVsdCAmJiBjb25mLT5mYW5fbXVsdCkK
-LQkJCWZhbl9tdWx0ID0gY29uZi0+ZmFuX211bHQ7Ci0JCWlmICghZmFuX21heCAmJiBjb25mLT5m
-YW5fbWF4KQotCQkJZmFuX21heCA9IGNvbmYtPmZhbl9tYXg7Ci0JfQotCi0JaThrX2Zhbl9tYXgg
-PSBmYW5fbWF4ID8gOiBJOEtfRkFOX0hJR0g7CS8qIE11c3Qgbm90IGJlIDAgKi8KLQlpOGtfcHdt
-X211bHQgPSBESVZfUk9VTkRfVVAoMjU1LCBpOGtfZmFuX21heCk7Ci0KLQlpZiAoIWZhbl9tdWx0
-KSB7Ci0JCS8qCi0JCSAqIEF1dG9kZXRlY3QgZmFuIG11bHRpcGxpZXIgYmFzZWQgb24gbm9taW5h
-bCBycG0KLQkJICogSWYgZmFuIHJlcG9ydHMgcnBtIHZhbHVlIHRvbyBoaWdoIHRoZW4gc2V0IG11
-bHRpcGxpZXIgdG8gMQotCQkgKi8KLQkJZm9yIChmYW4gPSAwOyBmYW4gPCAyOyArK2Zhbikgewot
-CQkJcmV0ID0gaThrX2dldF9mYW5fbm9taW5hbF9zcGVlZChmYW4sIGk4a19mYW5fbWF4KTsKLQkJ
-CWlmIChyZXQgPCAwKQotCQkJCWNvbnRpbnVlOwotCQkJaWYgKHJldCA+IEk4S19GQU5fTUFYX1JQ
-TSkKLQkJCQlpOGtfZmFuX211bHQgPSAxOwotCQkJYnJlYWs7Ci0JCX0KLQl9IGVsc2UgewotCQkv
-KiBGYW4gbXVsdGlwbGllciB3YXMgc3BlY2lmaWVkIGluIG1vZHVsZSBwYXJhbSBvciBpbiBkbWkg
-Ki8KLQkJaThrX2Zhbl9tdWx0ID0gZmFuX211bHQ7Ci0JfQotCi0JcmV0dXJuIDA7Ci19Ci0KLXN0
-YXRpYyBpbnQgX19pbml0IGk4a19pbml0KHZvaWQpCi17Ci0Jc3RydWN0IHByb2NfZGlyX2VudHJ5
-ICpwcm9jX2k4azsKLQlpbnQgZXJyOwotCi0JLyogQXJlIHdlIHJ1bm5pbmcgb24gYW4gc3VwcG9y
-dGVkIGxhcHRvcD8gKi8KLQlpZiAoaThrX3Byb2JlKCkpCi0JCXJldHVybiAtRU5PREVWOwotCi0J
-LyogUmVnaXN0ZXIgdGhlIHByb2MgZW50cnkgKi8KLQlwcm9jX2k4ayA9IHByb2NfY3JlYXRlKCJp
-OGsiLCAwLCBOVUxMLCAmaThrX2ZvcHMpOwotCWlmICghcHJvY19pOGspCi0JCXJldHVybiAtRU5P
-RU5UOwotCi0JZXJyID0gaThrX2luaXRfaHdtb24oKTsKLQlpZiAoZXJyKQotCQlnb3RvIGV4aXRf
-cmVtb3ZlX3Byb2M7Ci0KLQlyZXR1cm4gMDsKLQotIGV4aXRfcmVtb3ZlX3Byb2M6Ci0JcmVtb3Zl
-X3Byb2NfZW50cnkoImk4ayIsIE5VTEwpOwotCXJldHVybiBlcnI7Ci19Ci0KLXN0YXRpYyB2b2lk
-IF9fZXhpdCBpOGtfZXhpdCh2b2lkKQotewotCWh3bW9uX2RldmljZV91bnJlZ2lzdGVyKGk4a19o
-d21vbl9kZXYpOwotCXJlbW92ZV9wcm9jX2VudHJ5KCJpOGsiLCBOVUxMKTsKLX0KLQotbW9kdWxl
-X2luaXQoaThrX2luaXQpOwotbW9kdWxlX2V4aXQoaThrX2V4aXQpOwpkaWZmIC0tZ2l0IGEvZHJp
-dmVycy9od21vbi9NYWtlZmlsZSBiL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKaW5kZXggNmM5NDE0
-Ny4uMWMzZTQ1OCAxMDA2NDQKLS0tIGEvZHJpdmVycy9od21vbi9NYWtlZmlsZQorKysgYi9kcml2
-ZXJzL2h3bW9uL01ha2VmaWxlCkBAIC0xNTUsNiArMTU1LDcgQEAgb2JqLSQoQ09ORklHX1NFTlNP
-UlNfVzgzTDc4NVRTKQkrPSB3ODNsNzg1dHMubwogb2JqLSQoQ09ORklHX1NFTlNPUlNfVzgzTDc4
-Nk5HKQkrPSB3ODNsNzg2bmcubwogb2JqLSQoQ09ORklHX1NFTlNPUlNfV004MzFYKQkrPSB3bTgz
-MXgtaHdtb24ubwogb2JqLSQoQ09ORklHX1NFTlNPUlNfV004MzUwKQkrPSB3bTgzNTAtaHdtb24u
-bworb2JqLSQoQ09ORklHX0k4SykJCSs9IGRlbGwtc21tLWh3bW9uLm8KIAogb2JqLSQoQ09ORklH
-X1BNQlVTKQkJKz0gcG1idXMvCiAKZGlmZiAtLWdpdCBhL2RyaXZlcnMvaHdtb24vZGVsbC1zbW0t
-aHdtb24uYyBiL2RyaXZlcnMvaHdtb24vZGVsbC1zbW0taHdtb24uYwpuZXcgZmlsZSBtb2RlIDEw
-MDY0NAppbmRleCAwMDAwMDAwLi4yYjA0ZTRmCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9o
-d21vbi9kZWxsLXNtbS1od21vbi5jCkBAIC0wLDAgKzEsMTAwNyBAQAorLyoKKyAqIGRlbGwtc21t
-LWh3bW9uLmMgLS0gTGludXggZHJpdmVyIGZvciBhY2Nlc3NpbmcgdGhlIFNNTSBCSU9TIG9uIERl
-bGwgbGFwdG9wcy4KKyAqCisgKiBDb3B5cmlnaHQgKEMpIDIwMDEgIE1hc3NpbW8gRGFsIFpvdHRv
-IDxkekBkZWJpYW4ub3JnPgorICoKKyAqIEh3bW9uIGludGVncmF0aW9uOgorICogQ29weXJpZ2h0
-IChDKSAyMDExICBKZWFuIERlbHZhcmUgPGpkZWx2YXJlQHN1c2UuZGU+CisgKiBDb3B5cmlnaHQg
-KEMpIDIwMTMsIDIwMTQgIEd1ZW50ZXIgUm9lY2sgPGxpbnV4QHJvZWNrLXVzLm5ldD4KKyAqIENv
-cHlyaWdodCAoQykgMjAxNCwgMjAxNSAgUGFsaSBSb2jDoXIgPHBhbGkucm9oYXJAZ21haWwuY29t
-PgorICoKKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJp
-YnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0CisgKiB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBH
-ZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUKKyAqIEZyZWUgU29mdHdh
-cmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMiwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkK
-KyAqIGxhdGVyIHZlcnNpb24uCisgKgorICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGlu
-IHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dAorICogV0lUSE9VVCBBTlkgV0FS
-UkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgorICogTUVSQ0hBTlRB
-QklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUK
-KyAqIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KKyAqLworCisjZGVm
-aW5lIHByX2ZtdChmbXQpIEtCVUlMRF9NT0ROQU1FICI6ICIgZm10CisKKyNpbmNsdWRlIDxsaW51
-eC9kZWxheS5oPgorI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgorI2luY2x1ZGUgPGxpbnV4L3R5
-cGVzLmg+CisjaW5jbHVkZSA8bGludXgvaW5pdC5oPgorI2luY2x1ZGUgPGxpbnV4L3Byb2NfZnMu
-aD4KKyNpbmNsdWRlIDxsaW51eC9zZXFfZmlsZS5oPgorI2luY2x1ZGUgPGxpbnV4L2RtaS5oPgor
-I2luY2x1ZGUgPGxpbnV4L2NhcGFiaWxpdHkuaD4KKyNpbmNsdWRlIDxsaW51eC9tdXRleC5oPgor
-I2luY2x1ZGUgPGxpbnV4L2h3bW9uLmg+CisjaW5jbHVkZSA8bGludXgvaHdtb24tc3lzZnMuaD4K
-KyNpbmNsdWRlIDxsaW51eC91YWNjZXNzLmg+CisjaW5jbHVkZSA8bGludXgvaW8uaD4KKyNpbmNs
-dWRlIDxsaW51eC9zY2hlZC5oPgorCisjaW5jbHVkZSA8bGludXgvaThrLmg+CisKKyNkZWZpbmUg
-SThLX1NNTV9GTl9TVEFUVVMJMHgwMDI1CisjZGVmaW5lIEk4S19TTU1fUE9XRVJfU1RBVFVTCTB4
-MDA2OQorI2RlZmluZSBJOEtfU01NX1NFVF9GQU4JCTB4MDFhMworI2RlZmluZSBJOEtfU01NX0dF
-VF9GQU4JCTB4MDBhMworI2RlZmluZSBJOEtfU01NX0dFVF9TUEVFRAkweDAyYTMKKyNkZWZpbmUg
-SThLX1NNTV9HRVRfRkFOX1RZUEUJMHgwM2EzCisjZGVmaW5lIEk4S19TTU1fR0VUX05PTV9TUEVF
-RAkweDA0YTMKKyNkZWZpbmUgSThLX1NNTV9HRVRfVEVNUAkweDEwYTMKKyNkZWZpbmUgSThLX1NN
-TV9HRVRfVEVNUF9UWVBFCTB4MTFhMworI2RlZmluZSBJOEtfU01NX0dFVF9ERUxMX1NJRzEJMHhm
-ZWEzCisjZGVmaW5lIEk4S19TTU1fR0VUX0RFTExfU0lHMgkweGZmYTMKKworI2RlZmluZSBJOEtf
-RkFOX01VTFQJCTMwCisjZGVmaW5lIEk4S19GQU5fTUFYX1JQTQkJMzAwMDAKKyNkZWZpbmUgSThL
-X01BWF9URU1QCQkxMjcKKworI2RlZmluZSBJOEtfRk5fTk9ORQkJMHgwMAorI2RlZmluZSBJOEtf
-Rk5fVVAJCTB4MDEKKyNkZWZpbmUgSThLX0ZOX0RPV04JCTB4MDIKKyNkZWZpbmUgSThLX0ZOX01V
-VEUJCTB4MDQKKyNkZWZpbmUgSThLX0ZOX01BU0sJCTB4MDcKKyNkZWZpbmUgSThLX0ZOX1NISUZU
-CQk4CisKKyNkZWZpbmUgSThLX1BPV0VSX0FDCQkweDA1CisjZGVmaW5lIEk4S19QT1dFUl9CQVRU
-RVJZCTB4MDEKKworc3RhdGljIERFRklORV9NVVRFWChpOGtfbXV0ZXgpOworc3RhdGljIGNoYXIg
-Ymlvc192ZXJzaW9uWzRdOworc3RhdGljIHN0cnVjdCBkZXZpY2UgKmk4a19od21vbl9kZXY7Citz
-dGF0aWMgdTMyIGk4a19od21vbl9mbGFnczsKK3N0YXRpYyB1aW50IGk4a19mYW5fbXVsdCA9IEk4
-S19GQU5fTVVMVDsKK3N0YXRpYyB1aW50IGk4a19wd21fbXVsdDsKK3N0YXRpYyB1aW50IGk4a19m
-YW5fbWF4ID0gSThLX0ZBTl9ISUdIOworCisjZGVmaW5lIEk4S19IV01PTl9IQVZFX1RFTVAxCSgx
-IDw8IDApCisjZGVmaW5lIEk4S19IV01PTl9IQVZFX1RFTVAyCSgxIDw8IDEpCisjZGVmaW5lIEk4
-S19IV01PTl9IQVZFX1RFTVAzCSgxIDw8IDIpCisjZGVmaW5lIEk4S19IV01PTl9IQVZFX1RFTVA0
-CSgxIDw8IDMpCisjZGVmaW5lIEk4S19IV01PTl9IQVZFX0ZBTjEJKDEgPDwgNCkKKyNkZWZpbmUg
-SThLX0hXTU9OX0hBVkVfRkFOMgkoMSA8PCA1KQorCitNT0RVTEVfQVVUSE9SKCJNYXNzaW1vIERh
-bCBab3R0byAoZHpAZGViaWFuLm9yZykiKTsKK01PRFVMRV9BVVRIT1IoIlBhbGkgUm9ow6FyIDxw
-YWxpLnJvaGFyQGdtYWlsLmNvbT4iKTsKK01PRFVMRV9ERVNDUklQVElPTigiRHJpdmVyIGZvciBh
-Y2Nlc3NpbmcgU01NIEJJT1Mgb24gRGVsbCBsYXB0b3BzIik7CitNT0RVTEVfTElDRU5TRSgiR1BM
-Iik7CitNT0RVTEVfQUxJQVMoImk4ayIpOworCitzdGF0aWMgYm9vbCBmb3JjZTsKK21vZHVsZV9w
-YXJhbShmb3JjZSwgYm9vbCwgMCk7CitNT0RVTEVfUEFSTV9ERVNDKGZvcmNlLCAiRm9yY2UgbG9h
-ZGluZyB3aXRob3V0IGNoZWNraW5nIGZvciBzdXBwb3J0ZWQgbW9kZWxzIik7CisKK3N0YXRpYyBi
-b29sIGlnbm9yZV9kbWk7Cittb2R1bGVfcGFyYW0oaWdub3JlX2RtaSwgYm9vbCwgMCk7CitNT0RV
-TEVfUEFSTV9ERVNDKGlnbm9yZV9kbWksICJDb250aW51ZSBwcm9iaW5nIGhhcmR3YXJlIGV2ZW4g
-aWYgRE1JIGRhdGEgZG9lcyBub3QgbWF0Y2giKTsKKworc3RhdGljIGJvb2wgcmVzdHJpY3RlZDsK
-K21vZHVsZV9wYXJhbShyZXN0cmljdGVkLCBib29sLCAwKTsKK01PRFVMRV9QQVJNX0RFU0MocmVz
-dHJpY3RlZCwgIkFsbG93IGZhbiBjb250cm9sIGlmIFNZU19BRE1JTiBjYXBhYmlsaXR5IHNldCIp
-OworCitzdGF0aWMgYm9vbCBwb3dlcl9zdGF0dXM7Cittb2R1bGVfcGFyYW0ocG93ZXJfc3RhdHVz
-LCBib29sLCAwNjAwKTsKK01PRFVMRV9QQVJNX0RFU0MocG93ZXJfc3RhdHVzLCAiUmVwb3J0IHBv
-d2VyIHN0YXR1cyBpbiAvcHJvYy9pOGsiKTsKKworc3RhdGljIHVpbnQgZmFuX211bHQ7Cittb2R1
-bGVfcGFyYW0oZmFuX211bHQsIHVpbnQsIDApOworTU9EVUxFX1BBUk1fREVTQyhmYW5fbXVsdCwg
-IkZhY3RvciB0byBtdWx0aXBseSBmYW4gc3BlZWQgd2l0aCAoZGVmYXVsdDogYXV0b2RldGVjdCki
-KTsKKworc3RhdGljIHVpbnQgZmFuX21heDsKK21vZHVsZV9wYXJhbShmYW5fbWF4LCB1aW50LCAw
-KTsKK01PRFVMRV9QQVJNX0RFU0MoZmFuX21heCwgIk1heGltdW0gY29uZmlndXJhYmxlIGZhbiBz
-cGVlZCAoZGVmYXVsdDogYXV0b2RldGVjdCkiKTsKKworc3RhdGljIGludCBpOGtfb3Blbl9mcyhz
-dHJ1Y3QgaW5vZGUgKmlub2RlLCBzdHJ1Y3QgZmlsZSAqZmlsZSk7CitzdGF0aWMgbG9uZyBpOGtf
-aW9jdGwoc3RydWN0IGZpbGUgKiwgdW5zaWduZWQgaW50LCB1bnNpZ25lZCBsb25nKTsKKworc3Rh
-dGljIGNvbnN0IHN0cnVjdCBmaWxlX29wZXJhdGlvbnMgaThrX2ZvcHMgPSB7CisJLm93bmVyCQk9
-IFRISVNfTU9EVUxFLAorCS5vcGVuCQk9IGk4a19vcGVuX2ZzLAorCS5yZWFkCQk9IHNlcV9yZWFk
-LAorCS5sbHNlZWsJCT0gc2VxX2xzZWVrLAorCS5yZWxlYXNlCT0gc2luZ2xlX3JlbGVhc2UsCisJ
-LnVubG9ja2VkX2lvY3RsCT0gaThrX2lvY3RsLAorfTsKKworc3RydWN0IHNtbV9yZWdzIHsKKwl1
-bnNpZ25lZCBpbnQgZWF4OworCXVuc2lnbmVkIGludCBlYnggX19wYWNrZWQ7CisJdW5zaWduZWQg
-aW50IGVjeCBfX3BhY2tlZDsKKwl1bnNpZ25lZCBpbnQgZWR4IF9fcGFja2VkOworCXVuc2lnbmVk
-IGludCBlc2kgX19wYWNrZWQ7CisJdW5zaWduZWQgaW50IGVkaSBfX3BhY2tlZDsKK307CisKK3N0
-YXRpYyBpbmxpbmUgY29uc3QgY2hhciAqaThrX2dldF9kbWlfZGF0YShpbnQgZmllbGQpCit7CisJ
-Y29uc3QgY2hhciAqZG1pX2RhdGEgPSBkbWlfZ2V0X3N5c3RlbV9pbmZvKGZpZWxkKTsKKworCXJl
-dHVybiBkbWlfZGF0YSAmJiAqZG1pX2RhdGEgPyBkbWlfZGF0YSA6ICI/IjsKK30KKworLyoKKyAq
-IENhbGwgdGhlIFN5c3RlbSBNYW5hZ2VtZW50IE1vZGUgQklPUy4gQ29kZSBwcm92aWRlZCBieSBK
-b25hdGhhbiBCdXp6YXJkLgorICovCitzdGF0aWMgaW50IGk4a19zbW0oc3RydWN0IHNtbV9yZWdz
-ICpyZWdzKQoreworCWludCByYzsKKwlpbnQgZWF4ID0gcmVncy0+ZWF4OworCWNwdW1hc2tfdmFy
-X3Qgb2xkX21hc2s7CisKKwkvKiBTTU0gcmVxdWlyZXMgQ1BVIDAgKi8KKwlpZiAoIWFsbG9jX2Nw
-dW1hc2tfdmFyKCZvbGRfbWFzaywgR0ZQX0tFUk5FTCkpCisJCXJldHVybiAtRU5PTUVNOworCWNw
-dW1hc2tfY29weShvbGRfbWFzaywgJmN1cnJlbnQtPmNwdXNfYWxsb3dlZCk7CisJcmMgPSBzZXRf
-Y3B1c19hbGxvd2VkX3B0cihjdXJyZW50LCBjcHVtYXNrX29mKDApKTsKKwlpZiAocmMpCisJCWdv
-dG8gb3V0OworCWlmIChzbXBfcHJvY2Vzc29yX2lkKCkgIT0gMCkgeworCQlyYyA9IC1FQlVTWTsK
-KwkJZ290byBvdXQ7CisJfQorCisjaWYgZGVmaW5lZChDT05GSUdfWDg2XzY0KQorCWFzbSB2b2xh
-dGlsZSgicHVzaHEgJSVyYXhcblx0IgorCQkibW92bCAwKCUlcmF4KSwlJWVkeFxuXHQiCisJCSJw
-dXNocSAlJXJkeFxuXHQiCisJCSJtb3ZsIDQoJSVyYXgpLCUlZWJ4XG5cdCIKKwkJIm1vdmwgOCgl
-JXJheCksJSVlY3hcblx0IgorCQkibW92bCAxMiglJXJheCksJSVlZHhcblx0IgorCQkibW92bCAx
-NiglJXJheCksJSVlc2lcblx0IgorCQkibW92bCAyMCglJXJheCksJSVlZGlcblx0IgorCQkicG9w
-cSAlJXJheFxuXHQiCisJCSJvdXQgJSVhbCwkMHhiMlxuXHQiCisJCSJvdXQgJSVhbCwkMHg4NFxu
-XHQiCisJCSJ4Y2hncSAlJXJheCwoJSVyc3ApXG5cdCIKKwkJIm1vdmwgJSVlYngsNCglJXJheClc
-blx0IgorCQkibW92bCAlJWVjeCw4KCUlcmF4KVxuXHQiCisJCSJtb3ZsICUlZWR4LDEyKCUlcmF4
-KVxuXHQiCisJCSJtb3ZsICUlZXNpLDE2KCUlcmF4KVxuXHQiCisJCSJtb3ZsICUlZWRpLDIwKCUl
-cmF4KVxuXHQiCisJCSJwb3BxICUlcmR4XG5cdCIKKwkJIm1vdmwgJSVlZHgsMCglJXJheClcblx0
-IgorCQkicHVzaGZxXG5cdCIKKwkJInBvcHEgJSVyYXhcblx0IgorCQkiYW5kbCAkMSwlJWVheFxu
-IgorCQk6ICI9YSIocmMpCisJCTogICAgImEiKHJlZ3MpCisJCTogICAgIiVlYngiLCAiJWVjeCIs
-ICIlZWR4IiwgIiVlc2kiLCAiJWVkaSIsICJtZW1vcnkiKTsKKyNlbHNlCisJYXNtIHZvbGF0aWxl
-KCJwdXNobCAlJWVheFxuXHQiCisJICAgICJtb3ZsIDAoJSVlYXgpLCUlZWR4XG5cdCIKKwkgICAg
-InB1c2ggJSVlZHhcblx0IgorCSAgICAibW92bCA0KCUlZWF4KSwlJWVieFxuXHQiCisJICAgICJt
-b3ZsIDgoJSVlYXgpLCUlZWN4XG5cdCIKKwkgICAgIm1vdmwgMTIoJSVlYXgpLCUlZWR4XG5cdCIK
-KwkgICAgIm1vdmwgMTYoJSVlYXgpLCUlZXNpXG5cdCIKKwkgICAgIm1vdmwgMjAoJSVlYXgpLCUl
-ZWRpXG5cdCIKKwkgICAgInBvcGwgJSVlYXhcblx0IgorCSAgICAib3V0ICUlYWwsJDB4YjJcblx0
-IgorCSAgICAib3V0ICUlYWwsJDB4ODRcblx0IgorCSAgICAieGNoZ2wgJSVlYXgsKCUlZXNwKVxu
-XHQiCisJICAgICJtb3ZsICUlZWJ4LDQoJSVlYXgpXG5cdCIKKwkgICAgIm1vdmwgJSVlY3gsOCgl
-JWVheClcblx0IgorCSAgICAibW92bCAlJWVkeCwxMiglJWVheClcblx0IgorCSAgICAibW92bCAl
-JWVzaSwxNiglJWVheClcblx0IgorCSAgICAibW92bCAlJWVkaSwyMCglJWVheClcblx0IgorCSAg
-ICAicG9wbCAlJWVkeFxuXHQiCisJICAgICJtb3ZsICUlZWR4LDAoJSVlYXgpXG5cdCIKKwkgICAg
-ImxhaGZcblx0IgorCSAgICAic2hybCAkOCwlJWVheFxuXHQiCisJICAgICJhbmRsICQxLCUlZWF4
-XG4iCisJICAgIDogIj1hIihyYykKKwkgICAgOiAgICAiYSIocmVncykKKwkgICAgOiAgICAiJWVi
-eCIsICIlZWN4IiwgIiVlZHgiLCAiJWVzaSIsICIlZWRpIiwgIm1lbW9yeSIpOworI2VuZGlmCisJ
-aWYgKHJjICE9IDAgfHwgKHJlZ3MtPmVheCAmIDB4ZmZmZikgPT0gMHhmZmZmIHx8IHJlZ3MtPmVh
-eCA9PSBlYXgpCisJCXJjID0gLUVJTlZBTDsKKworb3V0OgorCXNldF9jcHVzX2FsbG93ZWRfcHRy
-KGN1cnJlbnQsIG9sZF9tYXNrKTsKKwlmcmVlX2NwdW1hc2tfdmFyKG9sZF9tYXNrKTsKKwlyZXR1
-cm4gcmM7Cit9CisKKy8qCisgKiBSZWFkIHRoZSBGbiBrZXkgc3RhdHVzLgorICovCitzdGF0aWMg
-aW50IGk4a19nZXRfZm5fc3RhdHVzKHZvaWQpCit7CisJc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7
-IC5lYXggPSBJOEtfU01NX0ZOX1NUQVRVUywgfTsKKwlpbnQgcmM7CisKKwlyYyA9IGk4a19zbW0o
-JnJlZ3MpOworCWlmIChyYyA8IDApCisJCXJldHVybiByYzsKKworCXN3aXRjaCAoKHJlZ3MuZWF4
-ID4+IEk4S19GTl9TSElGVCkgJiBJOEtfRk5fTUFTSykgeworCWNhc2UgSThLX0ZOX1VQOgorCQly
-ZXR1cm4gSThLX1ZPTF9VUDsKKwljYXNlIEk4S19GTl9ET1dOOgorCQlyZXR1cm4gSThLX1ZPTF9E
-T1dOOworCWNhc2UgSThLX0ZOX01VVEU6CisJCXJldHVybiBJOEtfVk9MX01VVEU7CisJZGVmYXVs
-dDoKKwkJcmV0dXJuIDA7CisJfQorfQorCisvKgorICogUmVhZCB0aGUgcG93ZXIgc3RhdHVzLgor
-ICovCitzdGF0aWMgaW50IGk4a19nZXRfcG93ZXJfc3RhdHVzKHZvaWQpCit7CisJc3RydWN0IHNt
-bV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01NX1BPV0VSX1NUQVRVUywgfTsKKwlpbnQgcmM7
-CisKKwlyYyA9IGk4a19zbW0oJnJlZ3MpOworCWlmIChyYyA8IDApCisJCXJldHVybiByYzsKKwor
-CXJldHVybiAocmVncy5lYXggJiAweGZmKSA9PSBJOEtfUE9XRVJfQUMgPyBJOEtfQUMgOiBJOEtf
-QkFUVEVSWTsKK30KKworLyoKKyAqIFJlYWQgdGhlIGZhbiBzdGF0dXMuCisgKi8KK3N0YXRpYyBp
-bnQgaThrX2dldF9mYW5fc3RhdHVzKGludCBmYW4pCit7CisJc3RydWN0IHNtbV9yZWdzIHJlZ3Mg
-PSB7IC5lYXggPSBJOEtfU01NX0dFVF9GQU4sIH07CisKKwlyZWdzLmVieCA9IGZhbiAmIDB4ZmY7
-CisJcmV0dXJuIGk4a19zbW0oJnJlZ3MpID8gOiByZWdzLmVheCAmIDB4ZmY7Cit9CisKKy8qCisg
-KiBSZWFkIHRoZSBmYW4gc3BlZWQgaW4gUlBNLgorICovCitzdGF0aWMgaW50IGk4a19nZXRfZmFu
-X3NwZWVkKGludCBmYW4pCit7CisJc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtf
-U01NX0dFVF9TUEVFRCwgfTsKKworCXJlZ3MuZWJ4ID0gZmFuICYgMHhmZjsKKwlyZXR1cm4gaThr
-X3NtbSgmcmVncykgPyA6IChyZWdzLmVheCAmIDB4ZmZmZikgKiBpOGtfZmFuX211bHQ7Cit9CisK
-Ky8qCisgKiBSZWFkIHRoZSBmYW4gdHlwZS4KKyAqLworc3RhdGljIGludCBpOGtfZ2V0X2Zhbl90
-eXBlKGludCBmYW4pCit7CisJc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01N
-X0dFVF9GQU5fVFlQRSwgfTsKKworCXJlZ3MuZWJ4ID0gZmFuICYgMHhmZjsKKwlyZXR1cm4gaThr
-X3NtbSgmcmVncykgPyA6IHJlZ3MuZWF4ICYgMHhmZjsKK30KKworLyoKKyAqIFJlYWQgdGhlIGZh
-biBub21pbmFsIHJwbSBmb3Igc3BlY2lmaWMgZmFuIHNwZWVkLgorICovCitzdGF0aWMgaW50IGk4
-a19nZXRfZmFuX25vbWluYWxfc3BlZWQoaW50IGZhbiwgaW50IHNwZWVkKQoreworCXN0cnVjdCBz
-bW1fcmVncyByZWdzID0geyAuZWF4ID0gSThLX1NNTV9HRVRfTk9NX1NQRUVELCB9OworCisJcmVn
-cy5lYnggPSAoZmFuICYgMHhmZikgfCAoc3BlZWQgPDwgOCk7CisJcmV0dXJuIGk4a19zbW0oJnJl
-Z3MpID8gOiAocmVncy5lYXggJiAweGZmZmYpICogaThrX2Zhbl9tdWx0OworfQorCisvKgorICog
-U2V0IHRoZSBmYW4gc3BlZWQgKG9mZiwgbG93LCBoaWdoKS4gUmV0dXJucyB0aGUgbmV3IGZhbiBz
-dGF0dXMuCisgKi8KK3N0YXRpYyBpbnQgaThrX3NldF9mYW4oaW50IGZhbiwgaW50IHNwZWVkKQor
-eworCXN0cnVjdCBzbW1fcmVncyByZWdzID0geyAuZWF4ID0gSThLX1NNTV9TRVRfRkFOLCB9Owor
-CisJc3BlZWQgPSAoc3BlZWQgPCAwKSA/IDAgOiAoKHNwZWVkID4gaThrX2Zhbl9tYXgpID8gaThr
-X2Zhbl9tYXggOiBzcGVlZCk7CisJcmVncy5lYnggPSAoZmFuICYgMHhmZikgfCAoc3BlZWQgPDwg
-OCk7CisKKwlyZXR1cm4gaThrX3NtbSgmcmVncykgPyA6IGk4a19nZXRfZmFuX3N0YXR1cyhmYW4p
-OworfQorCitzdGF0aWMgaW50IGk4a19nZXRfdGVtcF90eXBlKGludCBzZW5zb3IpCit7CisJc3Ry
-dWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01NX0dFVF9URU1QX1RZUEUsIH07CisK
-KwlyZWdzLmVieCA9IHNlbnNvciAmIDB4ZmY7CisJcmV0dXJuIGk4a19zbW0oJnJlZ3MpID8gOiBy
-ZWdzLmVheCAmIDB4ZmY7Cit9CisKKy8qCisgKiBSZWFkIHRoZSBjcHUgdGVtcGVyYXR1cmUuCisg
-Ki8KK3N0YXRpYyBpbnQgX2k4a19nZXRfdGVtcChpbnQgc2Vuc29yKQoreworCXN0cnVjdCBzbW1f
-cmVncyByZWdzID0geworCQkuZWF4ID0gSThLX1NNTV9HRVRfVEVNUCwKKwkJLmVieCA9IHNlbnNv
-ciAmIDB4ZmYsCisJfTsKKworCXJldHVybiBpOGtfc21tKCZyZWdzKSA/IDogcmVncy5lYXggJiAw
-eGZmOworfQorCitzdGF0aWMgaW50IGk4a19nZXRfdGVtcChpbnQgc2Vuc29yKQoreworCWludCB0
-ZW1wID0gX2k4a19nZXRfdGVtcChzZW5zb3IpOworCisJLyoKKwkgKiBTb21ldGltZXMgdGhlIHRl
-bXBlcmF0dXJlIHNlbnNvciByZXR1cm5zIDB4OTksIHdoaWNoIGlzIG91dCBvZiByYW5nZS4KKwkg
-KiBJbiB0aGlzIGNhc2Ugd2UgcmV0cnkgKG9uY2UpIGJlZm9yZSByZXR1cm5pbmcgYW4gZXJyb3Iu
-CisJICMgMTAwMzY1NTEzNyAwMDAwMDA1OCAwMDAwNWE0YgorCSAjIDEwMDM2NTUxMzggMDAwMDAw
-OTkgMDAwMDNhODAgPC0tLSAweDk5ID0gMTUzIGRlZ3JlZXMKKwkgIyAxMDAzNjU1MTM5IDAwMDAw
-MDU0IDAwMDA1YzUyCisJICovCisJaWYgKHRlbXAgPT0gMHg5OSkgeworCQltc2xlZXAoMTAwKTsK
-KwkJdGVtcCA9IF9pOGtfZ2V0X3RlbXAoc2Vuc29yKTsKKwl9CisJLyoKKwkgKiBSZXR1cm4gLUVO
-T0RBVEEgZm9yIGFsbCBpbnZhbGlkIHRlbXBlcmF0dXJlcy4KKwkgKgorCSAqIEtub3duIGluc3Rh
-bmNlcyBhcmUgdGhlIDB4OTkgdmFsdWUgYXMgc2VlbiBhYm92ZSBhcyB3ZWxsIGFzCisJICogMHhj
-MSAoMTkzKSwgd2hpY2ggbWF5IGJlIHJldHVybmVkIHdoZW4gdHJ5aW5nIHRvIHJlYWQgdGhlIEdQ
-VQorCSAqIHRlbXBlcmF0dXJlIGlmIHRoZSBzeXN0ZW0gc3VwcG9ydHMgYSBHUFUgYW5kIGl0IGlz
-IGN1cnJlbnRseQorCSAqIHR1cm5lZCBvZmYuCisJICovCisJaWYgKHRlbXAgPiBJOEtfTUFYX1RF
-TVApCisJCXJldHVybiAtRU5PREFUQTsKKworCXJldHVybiB0ZW1wOworfQorCitzdGF0aWMgaW50
-IGk4a19nZXRfZGVsbF9zaWduYXR1cmUoaW50IHJlcV9mbikKK3sKKwlzdHJ1Y3Qgc21tX3JlZ3Mg
-cmVncyA9IHsgLmVheCA9IHJlcV9mbiwgfTsKKwlpbnQgcmM7CisKKwlyYyA9IGk4a19zbW0oJnJl
-Z3MpOworCWlmIChyYyA8IDApCisJCXJldHVybiByYzsKKworCXJldHVybiByZWdzLmVheCA9PSAx
-MTQ1NjUxNTI3ICYmIHJlZ3MuZWR4ID09IDExNDUzOTIyMDQgPyAwIDogLTE7Cit9CisKK3N0YXRp
-YyBpbnQKK2k4a19pb2N0bF91bmxvY2tlZChzdHJ1Y3QgZmlsZSAqZnAsIHVuc2lnbmVkIGludCBj
-bWQsIHVuc2lnbmVkIGxvbmcgYXJnKQoreworCWludCB2YWwgPSAwOworCWludCBzcGVlZDsKKwl1
-bnNpZ25lZCBjaGFyIGJ1ZmZbMTZdOworCWludCBfX3VzZXIgKmFyZ3AgPSAoaW50IF9fdXNlciAq
-KWFyZzsKKworCWlmICghYXJncCkKKwkJcmV0dXJuIC1FSU5WQUw7CisKKwlzd2l0Y2ggKGNtZCkg
-eworCWNhc2UgSThLX0JJT1NfVkVSU0lPTjoKKwkJdmFsID0gKGJpb3NfdmVyc2lvblswXSA8PCAx
-NikgfAorCQkJCShiaW9zX3ZlcnNpb25bMV0gPDwgOCkgfCBiaW9zX3ZlcnNpb25bMl07CisJCWJy
-ZWFrOworCisJY2FzZSBJOEtfTUFDSElORV9JRDoKKwkJbWVtc2V0KGJ1ZmYsIDAsIDE2KTsKKwkJ
-c3RybGNweShidWZmLCBpOGtfZ2V0X2RtaV9kYXRhKERNSV9QUk9EVUNUX1NFUklBTCksCisJCQlz
-aXplb2YoYnVmZikpOworCQlicmVhazsKKworCWNhc2UgSThLX0ZOX1NUQVRVUzoKKwkJdmFsID0g
-aThrX2dldF9mbl9zdGF0dXMoKTsKKwkJYnJlYWs7CisKKwljYXNlIEk4S19QT1dFUl9TVEFUVVM6
-CisJCXZhbCA9IGk4a19nZXRfcG93ZXJfc3RhdHVzKCk7CisJCWJyZWFrOworCisJY2FzZSBJOEtf
-R0VUX1RFTVA6CisJCXZhbCA9IGk4a19nZXRfdGVtcCgwKTsKKwkJYnJlYWs7CisKKwljYXNlIEk4
-S19HRVRfU1BFRUQ6CisJCWlmIChjb3B5X2Zyb21fdXNlcigmdmFsLCBhcmdwLCBzaXplb2YoaW50
-KSkpCisJCQlyZXR1cm4gLUVGQVVMVDsKKworCQl2YWwgPSBpOGtfZ2V0X2Zhbl9zcGVlZCh2YWwp
-OworCQlicmVhazsKKworCWNhc2UgSThLX0dFVF9GQU46CisJCWlmIChjb3B5X2Zyb21fdXNlcigm
-dmFsLCBhcmdwLCBzaXplb2YoaW50KSkpCisJCQlyZXR1cm4gLUVGQVVMVDsKKworCQl2YWwgPSBp
-OGtfZ2V0X2Zhbl9zdGF0dXModmFsKTsKKwkJYnJlYWs7CisKKwljYXNlIEk4S19TRVRfRkFOOgor
-CQlpZiAocmVzdHJpY3RlZCAmJiAhY2FwYWJsZShDQVBfU1lTX0FETUlOKSkKKwkJCXJldHVybiAt
-RVBFUk07CisKKwkJaWYgKGNvcHlfZnJvbV91c2VyKCZ2YWwsIGFyZ3AsIHNpemVvZihpbnQpKSkK
-KwkJCXJldHVybiAtRUZBVUxUOworCisJCWlmIChjb3B5X2Zyb21fdXNlcigmc3BlZWQsIGFyZ3Ag
-KyAxLCBzaXplb2YoaW50KSkpCisJCQlyZXR1cm4gLUVGQVVMVDsKKworCQl2YWwgPSBpOGtfc2V0
-X2Zhbih2YWwsIHNwZWVkKTsKKwkJYnJlYWs7CisKKwlkZWZhdWx0OgorCQlyZXR1cm4gLUVJTlZB
-TDsKKwl9CisKKwlpZiAodmFsIDwgMCkKKwkJcmV0dXJuIHZhbDsKKworCXN3aXRjaCAoY21kKSB7
-CisJY2FzZSBJOEtfQklPU19WRVJTSU9OOgorCQlpZiAoY29weV90b191c2VyKGFyZ3AsICZ2YWws
-IDQpKQorCQkJcmV0dXJuIC1FRkFVTFQ7CisKKwkJYnJlYWs7CisJY2FzZSBJOEtfTUFDSElORV9J
-RDoKKwkJaWYgKGNvcHlfdG9fdXNlcihhcmdwLCBidWZmLCAxNikpCisJCQlyZXR1cm4gLUVGQVVM
-VDsKKworCQlicmVhazsKKwlkZWZhdWx0OgorCQlpZiAoY29weV90b191c2VyKGFyZ3AsICZ2YWws
-IHNpemVvZihpbnQpKSkKKwkJCXJldHVybiAtRUZBVUxUOworCisJCWJyZWFrOworCX0KKworCXJl
-dHVybiAwOworfQorCitzdGF0aWMgbG9uZyBpOGtfaW9jdGwoc3RydWN0IGZpbGUgKmZwLCB1bnNp
-Z25lZCBpbnQgY21kLCB1bnNpZ25lZCBsb25nIGFyZykKK3sKKwlsb25nIHJldDsKKworCW11dGV4
-X2xvY2soJmk4a19tdXRleCk7CisJcmV0ID0gaThrX2lvY3RsX3VubG9ja2VkKGZwLCBjbWQsIGFy
-Zyk7CisJbXV0ZXhfdW5sb2NrKCZpOGtfbXV0ZXgpOworCisJcmV0dXJuIHJldDsKK30KKworLyoK
-KyAqIFByaW50IHRoZSBpbmZvcm1hdGlvbiBmb3IgL3Byb2MvaThrLgorICovCitzdGF0aWMgaW50
-IGk4a19wcm9jX3Nob3coc3RydWN0IHNlcV9maWxlICpzZXEsIHZvaWQgKm9mZnNldCkKK3sKKwlp
-bnQgZm5fa2V5LCBjcHVfdGVtcCwgYWNfcG93ZXI7CisJaW50IGxlZnRfZmFuLCByaWdodF9mYW4s
-IGxlZnRfc3BlZWQsIHJpZ2h0X3NwZWVkOworCisJY3B1X3RlbXAJPSBpOGtfZ2V0X3RlbXAoMCk7
-CQkJLyogMTExMDAgwrVzICovCisJbGVmdF9mYW4JPSBpOGtfZ2V0X2Zhbl9zdGF0dXMoSThLX0ZB
-Tl9MRUZUKTsJLyogICA1ODAgwrVzICovCisJcmlnaHRfZmFuCT0gaThrX2dldF9mYW5fc3RhdHVz
-KEk4S19GQU5fUklHSFQpOwkvKiAgIDU4MCDCtXMgKi8KKwlsZWZ0X3NwZWVkCT0gaThrX2dldF9m
-YW5fc3BlZWQoSThLX0ZBTl9MRUZUKTsJLyogICA1ODAgwrVzICovCisJcmlnaHRfc3BlZWQJPSBp
-OGtfZ2V0X2Zhbl9zcGVlZChJOEtfRkFOX1JJR0hUKTsJLyogICA1ODAgwrVzICovCisJZm5fa2V5
-CQk9IGk4a19nZXRfZm5fc3RhdHVzKCk7CQkJLyogICA3NTAgwrVzICovCisJaWYgKHBvd2VyX3N0
-YXR1cykKKwkJYWNfcG93ZXIgPSBpOGtfZ2V0X3Bvd2VyX3N0YXR1cygpOwkJLyogMTQ3MDAgwrVz
-ICovCisJZWxzZQorCQlhY19wb3dlciA9IC0xOworCisJLyoKKwkgKiBJbmZvOgorCSAqCisJICog
-MSkgIEZvcm1hdCB2ZXJzaW9uICh0aGlzIHdpbGwgY2hhbmdlIGlmIGZvcm1hdCBjaGFuZ2VzKQor
-CSAqIDIpICBCSU9TIHZlcnNpb24KKwkgKiAzKSAgQklPUyBtYWNoaW5lIElECisJICogNCkgIENw
-dSB0ZW1wZXJhdHVyZQorCSAqIDUpICBMZWZ0IGZhbiBzdGF0dXMKKwkgKiA2KSAgUmlnaHQgZmFu
-IHN0YXR1cworCSAqIDcpICBMZWZ0IGZhbiBzcGVlZAorCSAqIDgpICBSaWdodCBmYW4gc3BlZWQK
-KwkgKiA5KSAgQUMgcG93ZXIKKwkgKiAxMCkgRm4gS2V5IHN0YXR1cworCSAqLworCXJldHVybiBz
-ZXFfcHJpbnRmKHNlcSwgIiVzICVzICVzICVkICVkICVkICVkICVkICVkICVkXG4iLAorCQkJICBJ
-OEtfUFJPQ19GTVQsCisJCQkgIGJpb3NfdmVyc2lvbiwKKwkJCSAgaThrX2dldF9kbWlfZGF0YShE
-TUlfUFJPRFVDVF9TRVJJQUwpLAorCQkJICBjcHVfdGVtcCwKKwkJCSAgbGVmdF9mYW4sIHJpZ2h0
-X2ZhbiwgbGVmdF9zcGVlZCwgcmlnaHRfc3BlZWQsCisJCQkgIGFjX3Bvd2VyLCBmbl9rZXkpOwor
-fQorCitzdGF0aWMgaW50IGk4a19vcGVuX2ZzKHN0cnVjdCBpbm9kZSAqaW5vZGUsIHN0cnVjdCBm
-aWxlICpmaWxlKQoreworCXJldHVybiBzaW5nbGVfb3BlbihmaWxlLCBpOGtfcHJvY19zaG93LCBO
-VUxMKTsKK30KKworCisvKgorICogSHdtb24gaW50ZXJmYWNlCisgKi8KKworc3RhdGljIHNzaXpl
-X3QgaThrX2h3bW9uX3Nob3dfdGVtcF9sYWJlbChzdHJ1Y3QgZGV2aWNlICpkZXYsCisJCQkJCSBz
-dHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZSAqZGV2YXR0ciwKKwkJCQkJIGNoYXIgKmJ1ZikKK3sKKwlz
-dGF0aWMgY29uc3QgY2hhciAqIGNvbnN0IGxhYmVsc1tdID0geworCQkiQ1BVIiwKKwkJIkdQVSIs
-CisJCSJTT0RJTU0iLAorCQkiT3RoZXIiLAorCQkiQW1iaWVudCIsCisJCSJPdGhlciIsCisJfTsK
-KwlpbnQgaW5kZXggPSB0b19zZW5zb3JfZGV2X2F0dHIoZGV2YXR0ciktPmluZGV4OworCWludCB0
-eXBlOworCisJdHlwZSA9IGk4a19nZXRfdGVtcF90eXBlKGluZGV4KTsKKwlpZiAodHlwZSA8IDAp
-CisJCXJldHVybiB0eXBlOworCWlmICh0eXBlID49IEFSUkFZX1NJWkUobGFiZWxzKSkKKwkJdHlw
-ZSA9IEFSUkFZX1NJWkUobGFiZWxzKSAtIDE7CisJcmV0dXJuIHNwcmludGYoYnVmLCAiJXNcbiIs
-IGxhYmVsc1t0eXBlXSk7Cit9CisKK3N0YXRpYyBzc2l6ZV90IGk4a19od21vbl9zaG93X3RlbXAo
-c3RydWN0IGRldmljZSAqZGV2LAorCQkJCSAgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkZXZh
-dHRyLAorCQkJCSAgIGNoYXIgKmJ1ZikKK3sKKwlpbnQgaW5kZXggPSB0b19zZW5zb3JfZGV2X2F0
-dHIoZGV2YXR0ciktPmluZGV4OworCWludCB0ZW1wOworCisJdGVtcCA9IGk4a19nZXRfdGVtcChp
-bmRleCk7CisJaWYgKHRlbXAgPCAwKQorCQlyZXR1cm4gdGVtcDsKKwlyZXR1cm4gc3ByaW50Zihi
-dWYsICIlZFxuIiwgdGVtcCAqIDEwMDApOworfQorCitzdGF0aWMgc3NpemVfdCBpOGtfaHdtb25f
-c2hvd19mYW5fbGFiZWwoc3RydWN0IGRldmljZSAqZGV2LAorCQkJCQlzdHJ1Y3QgZGV2aWNlX2F0
-dHJpYnV0ZSAqZGV2YXR0ciwKKwkJCQkJY2hhciAqYnVmKQoreworCXN0YXRpYyBjb25zdCBjaGFy
-ICogY29uc3QgbGFiZWxzW10gPSB7CisJCSJQcm9jZXNzb3IgRmFuIiwKKwkJIk1vdGhlcmJvYXJk
-IEZhbiIsCisJCSJWaWRlbyBGYW4iLAorCQkiUG93ZXIgU3VwcGx5IEZhbiIsCisJCSJDaGlwc2V0
-IEZhbiIsCisJCSJPdGhlciBGYW4iLAorCX07CisJaW50IGluZGV4ID0gdG9fc2Vuc29yX2Rldl9h
-dHRyKGRldmF0dHIpLT5pbmRleDsKKwlib29sIGRvY2sgPSBmYWxzZTsKKwlpbnQgdHlwZTsKKwor
-CXR5cGUgPSBpOGtfZ2V0X2Zhbl90eXBlKGluZGV4KTsKKwlpZiAodHlwZSA8IDApCisJCXJldHVy
-biB0eXBlOworCisJaWYgKHR5cGUgJiAweDEwKSB7CisJCWRvY2sgPSB0cnVlOworCQl0eXBlICY9
-IDB4MEY7CisJfQorCisJaWYgKHR5cGUgPj0gQVJSQVlfU0laRShsYWJlbHMpKQorCQl0eXBlID0g
-KEFSUkFZX1NJWkUobGFiZWxzKSAtIDEpOworCisJcmV0dXJuIHNwcmludGYoYnVmLCAiJXMlc1xu
-IiwgKGRvY2sgPyAiRG9ja2luZyAiIDogIiIpLCBsYWJlbHNbdHlwZV0pOworfQorCitzdGF0aWMg
-c3NpemVfdCBpOGtfaHdtb25fc2hvd19mYW4oc3RydWN0IGRldmljZSAqZGV2LAorCQkJCSAgc3Ry
-dWN0IGRldmljZV9hdHRyaWJ1dGUgKmRldmF0dHIsCisJCQkJICBjaGFyICpidWYpCit7CisJaW50
-IGluZGV4ID0gdG9fc2Vuc29yX2Rldl9hdHRyKGRldmF0dHIpLT5pbmRleDsKKwlpbnQgZmFuX3Nw
-ZWVkOworCisJZmFuX3NwZWVkID0gaThrX2dldF9mYW5fc3BlZWQoaW5kZXgpOworCWlmIChmYW5f
-c3BlZWQgPCAwKQorCQlyZXR1cm4gZmFuX3NwZWVkOworCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiVk
-XG4iLCBmYW5fc3BlZWQpOworfQorCitzdGF0aWMgc3NpemVfdCBpOGtfaHdtb25fc2hvd19wd20o
-c3RydWN0IGRldmljZSAqZGV2LAorCQkJCSAgc3RydWN0IGRldmljZV9hdHRyaWJ1dGUgKmRldmF0
-dHIsCisJCQkJICBjaGFyICpidWYpCit7CisJaW50IGluZGV4ID0gdG9fc2Vuc29yX2Rldl9hdHRy
-KGRldmF0dHIpLT5pbmRleDsKKwlpbnQgc3RhdHVzOworCisJc3RhdHVzID0gaThrX2dldF9mYW5f
-c3RhdHVzKGluZGV4KTsKKwlpZiAoc3RhdHVzIDwgMCkKKwkJcmV0dXJuIC1FSU87CisJcmV0dXJu
-IHNwcmludGYoYnVmLCAiJWRcbiIsIGNsYW1wX3ZhbChzdGF0dXMgKiBpOGtfcHdtX211bHQsIDAs
-IDI1NSkpOworfQorCitzdGF0aWMgc3NpemVfdCBpOGtfaHdtb25fc2V0X3B3bShzdHJ1Y3QgZGV2
-aWNlICpkZXYsCisJCQkJIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICphdHRyLAorCQkJCSBjb25z
-dCBjaGFyICpidWYsIHNpemVfdCBjb3VudCkKK3sKKwlpbnQgaW5kZXggPSB0b19zZW5zb3JfZGV2
-X2F0dHIoYXR0ciktPmluZGV4OworCXVuc2lnbmVkIGxvbmcgdmFsOworCWludCBlcnI7CisKKwll
-cnIgPSBrc3RydG91bChidWYsIDEwLCAmdmFsKTsKKwlpZiAoZXJyKQorCQlyZXR1cm4gZXJyOwor
-CXZhbCA9IGNsYW1wX3ZhbChESVZfUk9VTkRfQ0xPU0VTVCh2YWwsIGk4a19wd21fbXVsdCksIDAs
-IGk4a19mYW5fbWF4KTsKKworCW11dGV4X2xvY2soJmk4a19tdXRleCk7CisJZXJyID0gaThrX3Nl
-dF9mYW4oaW5kZXgsIHZhbCk7CisJbXV0ZXhfdW5sb2NrKCZpOGtfbXV0ZXgpOworCisJcmV0dXJu
-IGVyciA8IDAgPyAtRUlPIDogY291bnQ7Cit9CisKK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIo
-dGVtcDFfaW5wdXQsIFNfSVJVR08sIGk4a19od21vbl9zaG93X3RlbXAsIE5VTEwsIDApOworc3Rh
-dGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9sYWJlbCwgU19JUlVHTywgaThrX2h3bW9uX3No
-b3dfdGVtcF9sYWJlbCwgTlVMTCwKKwkJCSAgMCk7CitzdGF0aWMgU0VOU09SX0RFVklDRV9BVFRS
-KHRlbXAyX2lucHV0LCBTX0lSVUdPLCBpOGtfaHdtb25fc2hvd190ZW1wLCBOVUxMLCAxKTsKK3N0
-YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDJfbGFiZWwsIFNfSVJVR08sIGk4a19od21vbl9z
-aG93X3RlbXBfbGFiZWwsIE5VTEwsCisJCQkgIDEpOworc3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRU
-Uih0ZW1wM19pbnB1dCwgU19JUlVHTywgaThrX2h3bW9uX3Nob3dfdGVtcCwgTlVMTCwgMik7Citz
-dGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHRlbXAzX2xhYmVsLCBTX0lSVUdPLCBpOGtfaHdtb25f
-c2hvd190ZW1wX2xhYmVsLCBOVUxMLAorCQkJICAyKTsKK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FU
-VFIodGVtcDRfaW5wdXQsIFNfSVJVR08sIGk4a19od21vbl9zaG93X3RlbXAsIE5VTEwsIDMpOwor
-c3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wNF9sYWJlbCwgU19JUlVHTywgaThrX2h3bW9u
-X3Nob3dfdGVtcF9sYWJlbCwgTlVMTCwKKwkJCSAgMyk7CitzdGF0aWMgU0VOU09SX0RFVklDRV9B
-VFRSKGZhbjFfaW5wdXQsIFNfSVJVR08sIGk4a19od21vbl9zaG93X2ZhbiwgTlVMTCwgMCk7Citz
-dGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKGZhbjFfbGFiZWwsIFNfSVJVR08sIGk4a19od21vbl9z
-aG93X2Zhbl9sYWJlbCwgTlVMTCwKKwkJCSAgMCk7CitzdGF0aWMgU0VOU09SX0RFVklDRV9BVFRS
-KHB3bTEsIFNfSVJVR08gfCBTX0lXVVNSLCBpOGtfaHdtb25fc2hvd19wd20sCisJCQkgIGk4a19o
-d21vbl9zZXRfcHdtLCAwKTsKK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIoZmFuMl9pbnB1dCwg
-U19JUlVHTywgaThrX2h3bW9uX3Nob3dfZmFuLCBOVUxMLAorCQkJICAxKTsKK3N0YXRpYyBTRU5T
-T1JfREVWSUNFX0FUVFIoZmFuMl9sYWJlbCwgU19JUlVHTywgaThrX2h3bW9uX3Nob3dfZmFuX2xh
-YmVsLCBOVUxMLAorCQkJICAxKTsKK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIocHdtMiwgU19J
-UlVHTyB8IFNfSVdVU1IsIGk4a19od21vbl9zaG93X3B3bSwKKwkJCSAgaThrX2h3bW9uX3NldF9w
-d20sIDEpOworCitzdGF0aWMgc3RydWN0IGF0dHJpYnV0ZSAqaThrX2F0dHJzW10gPSB7CisJJnNl
-bnNvcl9kZXZfYXR0cl90ZW1wMV9pbnB1dC5kZXZfYXR0ci5hdHRyLAkvKiAwICovCisJJnNlbnNv
-cl9kZXZfYXR0cl90ZW1wMV9sYWJlbC5kZXZfYXR0ci5hdHRyLAkvKiAxICovCisJJnNlbnNvcl9k
-ZXZfYXR0cl90ZW1wMl9pbnB1dC5kZXZfYXR0ci5hdHRyLAkvKiAyICovCisJJnNlbnNvcl9kZXZf
-YXR0cl90ZW1wMl9sYWJlbC5kZXZfYXR0ci5hdHRyLAkvKiAzICovCisJJnNlbnNvcl9kZXZfYXR0
-cl90ZW1wM19pbnB1dC5kZXZfYXR0ci5hdHRyLAkvKiA0ICovCisJJnNlbnNvcl9kZXZfYXR0cl90
-ZW1wM19sYWJlbC5kZXZfYXR0ci5hdHRyLAkvKiA1ICovCisJJnNlbnNvcl9kZXZfYXR0cl90ZW1w
-NF9pbnB1dC5kZXZfYXR0ci5hdHRyLAkvKiA2ICovCisJJnNlbnNvcl9kZXZfYXR0cl90ZW1wNF9s
-YWJlbC5kZXZfYXR0ci5hdHRyLAkvKiA3ICovCisJJnNlbnNvcl9kZXZfYXR0cl9mYW4xX2lucHV0
-LmRldl9hdHRyLmF0dHIsCS8qIDggKi8KKwkmc2Vuc29yX2Rldl9hdHRyX2ZhbjFfbGFiZWwuZGV2
-X2F0dHIuYXR0ciwJLyogOSAqLworCSZzZW5zb3JfZGV2X2F0dHJfcHdtMS5kZXZfYXR0ci5hdHRy
-LAkJLyogMTAgKi8KKwkmc2Vuc29yX2Rldl9hdHRyX2ZhbjJfaW5wdXQuZGV2X2F0dHIuYXR0ciwJ
-LyogMTEgKi8KKwkmc2Vuc29yX2Rldl9hdHRyX2ZhbjJfbGFiZWwuZGV2X2F0dHIuYXR0ciwJLyog
-MTIgKi8KKwkmc2Vuc29yX2Rldl9hdHRyX3B3bTIuZGV2X2F0dHIuYXR0ciwJCS8qIDEzICovCisJ
-TlVMTAorfTsKKworc3RhdGljIHVtb2RlX3QgaThrX2lzX3Zpc2libGUoc3RydWN0IGtvYmplY3Qg
-KmtvYmosIHN0cnVjdCBhdHRyaWJ1dGUgKmF0dHIsCisJCQkgICAgICBpbnQgaW5kZXgpCit7CisJ
-aWYgKGluZGV4ID49IDAgJiYgaW5kZXggPD0gMSAmJgorCSAgICAhKGk4a19od21vbl9mbGFncyAm
-IEk4S19IV01PTl9IQVZFX1RFTVAxKSkKKwkJcmV0dXJuIDA7CisJaWYgKGluZGV4ID49IDIgJiYg
-aW5kZXggPD0gMyAmJgorCSAgICAhKGk4a19od21vbl9mbGFncyAmIEk4S19IV01PTl9IQVZFX1RF
-TVAyKSkKKwkJcmV0dXJuIDA7CisJaWYgKGluZGV4ID49IDQgJiYgaW5kZXggPD0gNSAmJgorCSAg
-ICAhKGk4a19od21vbl9mbGFncyAmIEk4S19IV01PTl9IQVZFX1RFTVAzKSkKKwkJcmV0dXJuIDA7
-CisJaWYgKGluZGV4ID49IDYgJiYgaW5kZXggPD0gNyAmJgorCSAgICAhKGk4a19od21vbl9mbGFn
-cyAmIEk4S19IV01PTl9IQVZFX1RFTVA0KSkKKwkJcmV0dXJuIDA7CisJaWYgKGluZGV4ID49IDgg
-JiYgaW5kZXggPD0gMTAgJiYKKwkgICAgIShpOGtfaHdtb25fZmxhZ3MgJiBJOEtfSFdNT05fSEFW
-RV9GQU4xKSkKKwkJcmV0dXJuIDA7CisJaWYgKGluZGV4ID49IDExICYmIGluZGV4IDw9IDEzICYm
-CisJICAgICEoaThrX2h3bW9uX2ZsYWdzICYgSThLX0hXTU9OX0hBVkVfRkFOMikpCisJCXJldHVy
-biAwOworCisJcmV0dXJuIGF0dHItPm1vZGU7Cit9CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgYXR0
-cmlidXRlX2dyb3VwIGk4a19ncm91cCA9IHsKKwkuYXR0cnMgPSBpOGtfYXR0cnMsCisJLmlzX3Zp
-c2libGUgPSBpOGtfaXNfdmlzaWJsZSwKK307CitfX0FUVFJJQlVURV9HUk9VUFMoaThrKTsKKwor
-c3RhdGljIGludCBfX2luaXQgaThrX2luaXRfaHdtb24odm9pZCkKK3sKKwlpbnQgZXJyOworCisJ
-aThrX2h3bW9uX2ZsYWdzID0gMDsKKworCS8qIENQVSB0ZW1wZXJhdHVyZSBhdHRyaWJ1dGVzLCBp
-ZiB0ZW1wZXJhdHVyZSB0eXBlIGlzIE9LICovCisJZXJyID0gaThrX2dldF90ZW1wX3R5cGUoMCk7
-CisJaWYgKGVyciA+PSAwKQorCQlpOGtfaHdtb25fZmxhZ3MgfD0gSThLX0hXTU9OX0hBVkVfVEVN
-UDE7CisJLyogY2hlY2sgZm9yIGFkZGl0aW9uYWwgdGVtcGVyYXR1cmUgc2Vuc29ycyAqLworCWVy
-ciA9IGk4a19nZXRfdGVtcF90eXBlKDEpOworCWlmIChlcnIgPj0gMCkKKwkJaThrX2h3bW9uX2Zs
-YWdzIHw9IEk4S19IV01PTl9IQVZFX1RFTVAyOworCWVyciA9IGk4a19nZXRfdGVtcF90eXBlKDIp
-OworCWlmIChlcnIgPj0gMCkKKwkJaThrX2h3bW9uX2ZsYWdzIHw9IEk4S19IV01PTl9IQVZFX1RF
-TVAzOworCWVyciA9IGk4a19nZXRfdGVtcF90eXBlKDMpOworCWlmIChlcnIgPj0gMCkKKwkJaThr
-X2h3bW9uX2ZsYWdzIHw9IEk4S19IV01PTl9IQVZFX1RFTVA0OworCisJLyogRmlyc3QgZmFuIGF0
-dHJpYnV0ZXMsIGlmIGZhbiB0eXBlIGlzIE9LICovCisJZXJyID0gaThrX2dldF9mYW5fdHlwZSgw
-KTsKKwlpZiAoZXJyID49IDApCisJCWk4a19od21vbl9mbGFncyB8PSBJOEtfSFdNT05fSEFWRV9G
-QU4xOworCisJLyogU2Vjb25kIGZhbiBhdHRyaWJ1dGVzLCBpZiBmYW4gdHlwZSBpcyBPSyAqLwor
-CWVyciA9IGk4a19nZXRfZmFuX3R5cGUoMSk7CisJaWYgKGVyciA+PSAwKQorCQlpOGtfaHdtb25f
-ZmxhZ3MgfD0gSThLX0hXTU9OX0hBVkVfRkFOMjsKKworCWk4a19od21vbl9kZXYgPSBod21vbl9k
-ZXZpY2VfcmVnaXN0ZXJfd2l0aF9ncm91cHMoTlVMTCwgImk4ayIsIE5VTEwsCisJCQkJCQkJICBp
-OGtfZ3JvdXBzKTsKKwlpZiAoSVNfRVJSKGk4a19od21vbl9kZXYpKSB7CisJCWVyciA9IFBUUl9F
-UlIoaThrX2h3bW9uX2Rldik7CisJCWk4a19od21vbl9kZXYgPSBOVUxMOworCQlwcl9lcnIoImh3
-bW9uIHJlZ2lzdHJhdGlvbiBmYWlsZWQgKCVkKVxuIiwgZXJyKTsKKwkJcmV0dXJuIGVycjsKKwl9
-CisJcmV0dXJuIDA7Cit9CisKK3N0cnVjdCBpOGtfY29uZmlnX2RhdGEgeworCXVpbnQgZmFuX211
-bHQ7CisJdWludCBmYW5fbWF4OworfTsKKworZW51bSBpOGtfY29uZmlncyB7CisJREVMTF9MQVRJ
-VFVERV9ENTIwLAorCURFTExfUFJFQ0lTSU9OXzQ5MCwKKwlERUxMX1NUVURJTywKKwlERUxMX1hQ
-UywKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgaThrX2NvbmZpZ19kYXRhIGk4a19jb25maWdf
-ZGF0YVtdID0geworCVtERUxMX0xBVElUVURFX0Q1MjBdID0geworCQkuZmFuX211bHQgPSAxLAor
-CQkuZmFuX21heCA9IEk4S19GQU5fVFVSQk8sCisJfSwKKwlbREVMTF9QUkVDSVNJT05fNDkwXSA9
-IHsKKwkJLmZhbl9tdWx0ID0gMSwKKwkJLmZhbl9tYXggPSBJOEtfRkFOX1RVUkJPLAorCX0sCisJ
-W0RFTExfU1RVRElPXSA9IHsKKwkJLmZhbl9tdWx0ID0gMSwKKwkJLmZhbl9tYXggPSBJOEtfRkFO
-X0hJR0gsCisJfSwKKwlbREVMTF9YUFNdID0geworCQkuZmFuX211bHQgPSAxLAorCQkuZmFuX21h
-eCA9IEk4S19GQU5fSElHSCwKKwl9LAorfTsKKworc3RhdGljIHN0cnVjdCBkbWlfc3lzdGVtX2lk
-IGk4a19kbWlfdGFibGVbXSBfX2luaXRkYXRhID0geworCXsKKwkJLmlkZW50ID0gIkRlbGwgSW5z
-cGlyb24iLAorCQkubWF0Y2hlcyA9IHsKKwkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRl
-bGwgQ29tcHV0ZXIiKSwKKwkJCURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1FLCAiSW5zcGlyb24i
-KSwKKwkJfSwKKwl9LAorCXsKKwkJLmlkZW50ID0gIkRlbGwgTGF0aXR1ZGUiLAorCQkubWF0Y2hl
-cyA9IHsKKwkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgQ29tcHV0ZXIiKSwKKwkJ
-CURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1FLCAiTGF0aXR1ZGUiKSwKKwkJfSwKKwl9LAorCXsK
-KwkJLmlkZW50ID0gIkRlbGwgSW5zcGlyb24gMiIsCisJCS5tYXRjaGVzID0geworCQkJRE1JX01B
-VENIKERNSV9TWVNfVkVORE9SLCAiRGVsbCBJbmMuIiksCisJCQlETUlfTUFUQ0goRE1JX1BST0RV
-Q1RfTkFNRSwgIkluc3Bpcm9uIiksCisJCX0sCisJfSwKKwl7CisJCS5pZGVudCA9ICJEZWxsIExh
-dGl0dWRlIEQ1MjAiLAorCQkubWF0Y2hlcyA9IHsKKwkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRP
-UiwgIkRlbGwgSW5jLiIpLAorCQkJRE1JX01BVENIKERNSV9QUk9EVUNUX05BTUUsICJMYXRpdHVk
-ZSBENTIwIiksCisJCX0sCisJCS5kcml2ZXJfZGF0YSA9ICh2b2lkICopJmk4a19jb25maWdfZGF0
-YVtERUxMX0xBVElUVURFX0Q1MjBdLAorCX0sCisJeworCQkuaWRlbnQgPSAiRGVsbCBMYXRpdHVk
-ZSAyIiwKKwkJLm1hdGNoZXMgPSB7CisJCQlETUlfTUFUQ0goRE1JX1NZU19WRU5ET1IsICJEZWxs
-IEluYy4iKSwKKwkJCURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1FLCAiTGF0aXR1ZGUiKSwKKwkJ
-fSwKKwl9LAorCXsJLyogVUsgSW5zcGlyb24gNjQwMCAgKi8KKwkJLmlkZW50ID0gIkRlbGwgSW5z
-cGlyb24gMyIsCisJCS5tYXRjaGVzID0geworCQkJRE1JX01BVENIKERNSV9TWVNfVkVORE9SLCAi
-RGVsbCBJbmMuIiksCisJCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIk1NMDYxIiksCisJ
-CX0sCisJfSwKKwl7CisJCS5pZGVudCA9ICJEZWxsIEluc3Bpcm9uIDMiLAorCQkubWF0Y2hlcyA9
-IHsKKwkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgSW5jLiIpLAorCQkJRE1JX01B
-VENIKERNSV9QUk9EVUNUX05BTUUsICJNUDA2MSIpLAorCQl9LAorCX0sCisJeworCQkuaWRlbnQg
-PSAiRGVsbCBQcmVjaXNpb24gNDkwIiwKKwkJLm1hdGNoZXMgPSB7CisJCQlETUlfTUFUQ0goRE1J
-X1NZU19WRU5ET1IsICJEZWxsIEluYy4iKSwKKwkJCURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1F
-LAorCQkJCSAgIlByZWNpc2lvbiBXb3JrU3RhdGlvbiA0OTAiKSwKKwkJfSwKKwkJLmRyaXZlcl9k
-YXRhID0gKHZvaWQgKikmaThrX2NvbmZpZ19kYXRhW0RFTExfUFJFQ0lTSU9OXzQ5MF0sCisJfSwK
-Kwl7CisJCS5pZGVudCA9ICJEZWxsIFByZWNpc2lvbiIsCisJCS5tYXRjaGVzID0geworCQkJRE1J
-X01BVENIKERNSV9TWVNfVkVORE9SLCAiRGVsbCBJbmMuIiksCisJCQlETUlfTUFUQ0goRE1JX1BS
-T0RVQ1RfTkFNRSwgIlByZWNpc2lvbiIpLAorCQl9LAorCX0sCisJeworCQkuaWRlbnQgPSAiRGVs
-bCBWb3N0cm8iLAorCQkubWF0Y2hlcyA9IHsKKwkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwg
-IkRlbGwgSW5jLiIpLAorCQkJRE1JX01BVENIKERNSV9QUk9EVUNUX05BTUUsICJWb3N0cm8iKSwK
-KwkJfSwKKwl9LAorCXsKKwkJLmlkZW50ID0gIkRlbGwgWFBTNDIxIiwKKwkJLm1hdGNoZXMgPSB7
-CisJCQlETUlfTUFUQ0goRE1JX1NZU19WRU5ET1IsICJEZWxsIEluYy4iKSwKKwkJCURNSV9NQVRD
-SChETUlfUFJPRFVDVF9OQU1FLCAiWFBTIEw0MjFYIiksCisJCX0sCisJfSwKKwl7CisJCS5pZGVu
-dCA9ICJEZWxsIFN0dWRpbyIsCisJCS5tYXRjaGVzID0geworCQkJRE1JX01BVENIKERNSV9TWVNf
-VkVORE9SLCAiRGVsbCBJbmMuIiksCisJCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIlN0
-dWRpbyIpLAorCQl9LAorCQkuZHJpdmVyX2RhdGEgPSAodm9pZCAqKSZpOGtfY29uZmlnX2RhdGFb
-REVMTF9TVFVESU9dLAorCX0sCisJeworCQkuaWRlbnQgPSAiRGVsbCBYUFMgMTMiLAorCQkubWF0
-Y2hlcyA9IHsKKwkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgSW5jLiIpLAorCQkJ
-RE1JX01BVENIKERNSV9QUk9EVUNUX05BTUUsICJYUFMxMyIpLAorCQl9LAorCQkuZHJpdmVyX2Rh
-dGEgPSAodm9pZCAqKSZpOGtfY29uZmlnX2RhdGFbREVMTF9YUFNdLAorCX0sCisJeworCQkuaWRl
-bnQgPSAiRGVsbCBYUFMgTTE0MCIsCisJCS5tYXRjaGVzID0geworCQkJRE1JX01BVENIKERNSV9T
-WVNfVkVORE9SLCAiRGVsbCBJbmMuIiksCisJCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwg
-Ik1YQzA1MSIpLAorCQl9LAorCQkuZHJpdmVyX2RhdGEgPSAodm9pZCAqKSZpOGtfY29uZmlnX2Rh
-dGFbREVMTF9YUFNdLAorCX0sCisJeyB9Cit9OworCitNT0RVTEVfREVWSUNFX1RBQkxFKGRtaSwg
-aThrX2RtaV90YWJsZSk7CisKKy8qCisgKiBQcm9iZSBmb3IgdGhlIHByZXNlbmNlIG9mIGEgc3Vw
-cG9ydGVkIGxhcHRvcC4KKyAqLworc3RhdGljIGludCBfX2luaXQgaThrX3Byb2JlKHZvaWQpCit7
-CisJY29uc3Qgc3RydWN0IGRtaV9zeXN0ZW1faWQgKmlkOworCWludCBmYW4sIHJldDsKKworCS8q
-CisJICogR2V0IERNSSBpbmZvcm1hdGlvbgorCSAqLworCWlmICghZG1pX2NoZWNrX3N5c3RlbShp
-OGtfZG1pX3RhYmxlKSkgeworCQlpZiAoIWlnbm9yZV9kbWkgJiYgIWZvcmNlKQorCQkJcmV0dXJu
-IC1FTk9ERVY7CisKKwkJcHJfaW5mbygibm90IHJ1bm5pbmcgb24gYSBzdXBwb3J0ZWQgRGVsbCBz
-eXN0ZW0uXG4iKTsKKwkJcHJfaW5mbygidmVuZG9yPSVzLCBtb2RlbD0lcywgdmVyc2lvbj0lc1xu
-IiwKKwkJCWk4a19nZXRfZG1pX2RhdGEoRE1JX1NZU19WRU5ET1IpLAorCQkJaThrX2dldF9kbWlf
-ZGF0YShETUlfUFJPRFVDVF9OQU1FKSwKKwkJCWk4a19nZXRfZG1pX2RhdGEoRE1JX0JJT1NfVkVS
-U0lPTikpOworCX0KKworCXN0cmxjcHkoYmlvc192ZXJzaW9uLCBpOGtfZ2V0X2RtaV9kYXRhKERN
-SV9CSU9TX1ZFUlNJT04pLAorCQlzaXplb2YoYmlvc192ZXJzaW9uKSk7CisKKwkvKgorCSAqIEdl
-dCBTTU0gRGVsbCBzaWduYXR1cmUKKwkgKi8KKwlpZiAoaThrX2dldF9kZWxsX3NpZ25hdHVyZShJ
-OEtfU01NX0dFVF9ERUxMX1NJRzEpICYmCisJICAgIGk4a19nZXRfZGVsbF9zaWduYXR1cmUoSThL
-X1NNTV9HRVRfREVMTF9TSUcyKSkgeworCQlwcl9lcnIoInVuYWJsZSB0byBnZXQgU01NIERlbGwg
-c2lnbmF0dXJlXG4iKTsKKwkJaWYgKCFmb3JjZSkKKwkJCXJldHVybiAtRU5PREVWOworCX0KKwor
-CS8qCisJICogU2V0IGZhbiBtdWx0aXBsaWVyIGFuZCBtYXhpbWFsIGZhbiBzcGVlZCBmcm9tIGRt
-aSBjb25maWcKKwkgKiBWYWx1ZXMgc3BlY2lmaWVkIGluIG1vZHVsZSBwYXJhbWV0ZXJzIG92ZXJy
-aWRlIHZhbHVlcyBmcm9tIGRtaQorCSAqLworCWlkID0gZG1pX2ZpcnN0X21hdGNoKGk4a19kbWlf
-dGFibGUpOworCWlmIChpZCAmJiBpZC0+ZHJpdmVyX2RhdGEpIHsKKwkJY29uc3Qgc3RydWN0IGk4
-a19jb25maWdfZGF0YSAqY29uZiA9IGlkLT5kcml2ZXJfZGF0YTsKKwkJaWYgKCFmYW5fbXVsdCAm
-JiBjb25mLT5mYW5fbXVsdCkKKwkJCWZhbl9tdWx0ID0gY29uZi0+ZmFuX211bHQ7CisJCWlmICgh
-ZmFuX21heCAmJiBjb25mLT5mYW5fbWF4KQorCQkJZmFuX21heCA9IGNvbmYtPmZhbl9tYXg7CisJ
-fQorCisJaThrX2Zhbl9tYXggPSBmYW5fbWF4ID8gOiBJOEtfRkFOX0hJR0g7CS8qIE11c3Qgbm90
-IGJlIDAgKi8KKwlpOGtfcHdtX211bHQgPSBESVZfUk9VTkRfVVAoMjU1LCBpOGtfZmFuX21heCk7
-CisKKwlpZiAoIWZhbl9tdWx0KSB7CisJCS8qCisJCSAqIEF1dG9kZXRlY3QgZmFuIG11bHRpcGxp
-ZXIgYmFzZWQgb24gbm9taW5hbCBycG0KKwkJICogSWYgZmFuIHJlcG9ydHMgcnBtIHZhbHVlIHRv
-byBoaWdoIHRoZW4gc2V0IG11bHRpcGxpZXIgdG8gMQorCQkgKi8KKwkJZm9yIChmYW4gPSAwOyBm
-YW4gPCAyOyArK2ZhbikgeworCQkJcmV0ID0gaThrX2dldF9mYW5fbm9taW5hbF9zcGVlZChmYW4s
-IGk4a19mYW5fbWF4KTsKKwkJCWlmIChyZXQgPCAwKQorCQkJCWNvbnRpbnVlOworCQkJaWYgKHJl
-dCA+IEk4S19GQU5fTUFYX1JQTSkKKwkJCQlpOGtfZmFuX211bHQgPSAxOworCQkJYnJlYWs7CisJ
-CX0KKwl9IGVsc2UgeworCQkvKiBGYW4gbXVsdGlwbGllciB3YXMgc3BlY2lmaWVkIGluIG1vZHVs
-ZSBwYXJhbSBvciBpbiBkbWkgKi8KKwkJaThrX2Zhbl9tdWx0ID0gZmFuX211bHQ7CisJfQorCisJ
-cmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgX19pbml0IGk4a19pbml0KHZvaWQpCit7CisJc3Ry
-dWN0IHByb2NfZGlyX2VudHJ5ICpwcm9jX2k4azsKKwlpbnQgZXJyOworCisJLyogQXJlIHdlIHJ1
-bm5pbmcgb24gYW4gc3VwcG9ydGVkIGxhcHRvcD8gKi8KKwlpZiAoaThrX3Byb2JlKCkpCisJCXJl
-dHVybiAtRU5PREVWOworCisJLyogUmVnaXN0ZXIgdGhlIHByb2MgZW50cnkgKi8KKwlwcm9jX2k4
-ayA9IHByb2NfY3JlYXRlKCJpOGsiLCAwLCBOVUxMLCAmaThrX2ZvcHMpOworCWlmICghcHJvY19p
-OGspCisJCXJldHVybiAtRU5PRU5UOworCisJZXJyID0gaThrX2luaXRfaHdtb24oKTsKKwlpZiAo
-ZXJyKQorCQlnb3RvIGV4aXRfcmVtb3ZlX3Byb2M7CisKKwlyZXR1cm4gMDsKKworIGV4aXRfcmVt
-b3ZlX3Byb2M6CisJcmVtb3ZlX3Byb2NfZW50cnkoImk4ayIsIE5VTEwpOworCXJldHVybiBlcnI7
-Cit9CisKK3N0YXRpYyB2b2lkIF9fZXhpdCBpOGtfZXhpdCh2b2lkKQoreworCWh3bW9uX2Rldmlj
-ZV91bnJlZ2lzdGVyKGk4a19od21vbl9kZXYpOworCXJlbW92ZV9wcm9jX2VudHJ5KCJpOGsiLCBO
-VUxMKTsKK30KKworbW9kdWxlX2luaXQoaThrX2luaXQpOworbW9kdWxlX2V4aXQoaThrX2V4aXQp
-OwotLSAKMS43LjkuNQoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
-X19fX19fCmxtLXNlbnNvcnMgbWFpbGluZyBsaXN0CmxtLXNlbnNvcnNAbG0tc2Vuc29ycy5vcmcK
-aHR0cDovL2xpc3RzLmxtLXNlbnNvcnMub3JnL21haWxtYW4vbGlzdGluZm8vbG0tc2Vuc29ycw=
+This commit moves i8k driver to hwmon tree under name dell-smm-hwmon which is
+better name then abbreviation i8k. For backward compatibility is added macro
+MODULE_ALIAS("i8k") so modprobe will load driver also old name i8k. CONFIG_I8K
+compile option was not changed.
+
+This commit also adds me as maintainer of this new dell-smm-hwmon driver and
+remove Guenter Roeck from list who is implicit maintainer all hwmon drivers.
+
+Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
+---
+ MAINTAINERS                    |    4 +-
+ drivers/char/Makefile          |    1 -
+ drivers/char/i8k.c             | 1005 ---------------------------------------
+ drivers/hwmon/Makefile         |    1 +
+ drivers/hwmon/dell-smm-hwmon.c | 1007 ++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 1010 insertions(+), 1008 deletions(-)
+ delete mode 100644 drivers/char/i8k.c
+ create mode 100644 drivers/hwmon/dell-smm-hwmon.c
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 88c09ca..e54a07e 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -3063,9 +3063,9 @@ S:	Maintained
+ F:	drivers/platform/x86/dell-laptop.c
+ 
+ DELL LAPTOP SMM DRIVER
+-M:	Guenter Roeck <linux@roeck-us.net>
++M:	Pali Rohár <pali.rohar@gmail.com>
+ S:	Maintained
+-F:	drivers/char/i8k.c
++F:	drivers/hwmon/dell-smm-hwmon.c
+ F:	include/uapi/linux/i8k.h
+ 
+ DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)
+diff --git a/drivers/char/Makefile b/drivers/char/Makefile
+index d06cde26..1d9cf00 100644
+--- a/drivers/char/Makefile
++++ b/drivers/char/Makefile
+@@ -36,7 +36,6 @@ else
+   obj-$(CONFIG_NVRAM)	+= nvram.o
+ endif
+ obj-$(CONFIG_TOSHIBA)		+= toshiba.o
+-obj-$(CONFIG_I8K)		+= i8k.o
+ obj-$(CONFIG_DS1620)		+= ds1620.o
+ obj-$(CONFIG_HW_RANDOM)		+= hw_random/
+ obj-$(CONFIG_PPDEV)		+= ppdev.o
+diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
+deleted file mode 100644
+index 24cc4ed..0000000
+--- a/drivers/char/i8k.c
++++ /dev/null
+@@ -1,1005 +0,0 @@
+-/*
+- * i8k.c -- Linux driver for accessing the SMM BIOS on Dell laptops.
+- *
+- * Copyright (C) 2001  Massimo Dal Zotto <dz@debian.org>
+- *
+- * Hwmon integration:
+- * Copyright (C) 2011  Jean Delvare <jdelvare@suse.de>
+- * Copyright (C) 2013, 2014  Guenter Roeck <linux@roeck-us.net>
+- * Copyright (C) 2014  Pali Rohár <pali.rohar@gmail.com>
+- *
+- * 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, 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.
+- */
+-
+-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+-
+-#include <linux/delay.h>
+-#include <linux/module.h>
+-#include <linux/types.h>
+-#include <linux/init.h>
+-#include <linux/proc_fs.h>
+-#include <linux/seq_file.h>
+-#include <linux/dmi.h>
+-#include <linux/capability.h>
+-#include <linux/mutex.h>
+-#include <linux/hwmon.h>
+-#include <linux/hwmon-sysfs.h>
+-#include <linux/uaccess.h>
+-#include <linux/io.h>
+-#include <linux/sched.h>
+-
+-#include <linux/i8k.h>
+-
+-#define I8K_SMM_FN_STATUS	0x0025
+-#define I8K_SMM_POWER_STATUS	0x0069
+-#define I8K_SMM_SET_FAN		0x01a3
+-#define I8K_SMM_GET_FAN		0x00a3
+-#define I8K_SMM_GET_SPEED	0x02a3
+-#define I8K_SMM_GET_FAN_TYPE	0x03a3
+-#define I8K_SMM_GET_NOM_SPEED	0x04a3
+-#define I8K_SMM_GET_TEMP	0x10a3
+-#define I8K_SMM_GET_TEMP_TYPE	0x11a3
+-#define I8K_SMM_GET_DELL_SIG1	0xfea3
+-#define I8K_SMM_GET_DELL_SIG2	0xffa3
+-
+-#define I8K_FAN_MULT		30
+-#define I8K_FAN_MAX_RPM		30000
+-#define I8K_MAX_TEMP		127
+-
+-#define I8K_FN_NONE		0x00
+-#define I8K_FN_UP		0x01
+-#define I8K_FN_DOWN		0x02
+-#define I8K_FN_MUTE		0x04
+-#define I8K_FN_MASK		0x07
+-#define I8K_FN_SHIFT		8
+-
+-#define I8K_POWER_AC		0x05
+-#define I8K_POWER_BATTERY	0x01
+-
+-static DEFINE_MUTEX(i8k_mutex);
+-static char bios_version[4];
+-static struct device *i8k_hwmon_dev;
+-static u32 i8k_hwmon_flags;
+-static uint i8k_fan_mult = I8K_FAN_MULT;
+-static uint i8k_pwm_mult;
+-static uint i8k_fan_max = I8K_FAN_HIGH;
+-
+-#define I8K_HWMON_HAVE_TEMP1	(1 << 0)
+-#define I8K_HWMON_HAVE_TEMP2	(1 << 1)
+-#define I8K_HWMON_HAVE_TEMP3	(1 << 2)
+-#define I8K_HWMON_HAVE_TEMP4	(1 << 3)
+-#define I8K_HWMON_HAVE_FAN1	(1 << 4)
+-#define I8K_HWMON_HAVE_FAN2	(1 << 5)
+-
+-MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
+-MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops");
+-MODULE_LICENSE("GPL");
+-
+-static bool force;
+-module_param(force, bool, 0);
+-MODULE_PARM_DESC(force, "Force loading without checking for supported models");
+-
+-static bool ignore_dmi;
+-module_param(ignore_dmi, bool, 0);
+-MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
+-
+-static bool restricted;
+-module_param(restricted, bool, 0);
+-MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set");
+-
+-static bool power_status;
+-module_param(power_status, bool, 0600);
+-MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
+-
+-static uint fan_mult;
+-module_param(fan_mult, uint, 0);
+-MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with (default: autodetect)");
+-
+-static uint fan_max;
+-module_param(fan_max, uint, 0);
+-MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed (default: autodetect)");
+-
+-static int i8k_open_fs(struct inode *inode, struct file *file);
+-static long i8k_ioctl(struct file *, unsigned int, unsigned long);
+-
+-static const struct file_operations i8k_fops = {
+-	.owner		= THIS_MODULE,
+-	.open		= i8k_open_fs,
+-	.read		= seq_read,
+-	.llseek		= seq_lseek,
+-	.release	= single_release,
+-	.unlocked_ioctl	= i8k_ioctl,
+-};
+-
+-struct smm_regs {
+-	unsigned int eax;
+-	unsigned int ebx __packed;
+-	unsigned int ecx __packed;
+-	unsigned int edx __packed;
+-	unsigned int esi __packed;
+-	unsigned int edi __packed;
+-};
+-
+-static inline const char *i8k_get_dmi_data(int field)
+-{
+-	const char *dmi_data = dmi_get_system_info(field);
+-
+-	return dmi_data && *dmi_data ? dmi_data : "?";
+-}
+-
+-/*
+- * Call the System Management Mode BIOS. Code provided by Jonathan Buzzard.
+- */
+-static int i8k_smm(struct smm_regs *regs)
+-{
+-	int rc;
+-	int eax = regs->eax;
+-	cpumask_var_t old_mask;
+-
+-	/* SMM requires CPU 0 */
+-	if (!alloc_cpumask_var(&old_mask, GFP_KERNEL))
+-		return -ENOMEM;
+-	cpumask_copy(old_mask, &current->cpus_allowed);
+-	rc = set_cpus_allowed_ptr(current, cpumask_of(0));
+-	if (rc)
+-		goto out;
+-	if (smp_processor_id() != 0) {
+-		rc = -EBUSY;
+-		goto out;
+-	}
+-
+-#if defined(CONFIG_X86_64)
+-	asm volatile("pushq %%rax\n\t"
+-		"movl 0(%%rax),%%edx\n\t"
+-		"pushq %%rdx\n\t"
+-		"movl 4(%%rax),%%ebx\n\t"
+-		"movl 8(%%rax),%%ecx\n\t"
+-		"movl 12(%%rax),%%edx\n\t"
+-		"movl 16(%%rax),%%esi\n\t"
+-		"movl 20(%%rax),%%edi\n\t"
+-		"popq %%rax\n\t"
+-		"out %%al,$0xb2\n\t"
+-		"out %%al,$0x84\n\t"
+-		"xchgq %%rax,(%%rsp)\n\t"
+-		"movl %%ebx,4(%%rax)\n\t"
+-		"movl %%ecx,8(%%rax)\n\t"
+-		"movl %%edx,12(%%rax)\n\t"
+-		"movl %%esi,16(%%rax)\n\t"
+-		"movl %%edi,20(%%rax)\n\t"
+-		"popq %%rdx\n\t"
+-		"movl %%edx,0(%%rax)\n\t"
+-		"pushfq\n\t"
+-		"popq %%rax\n\t"
+-		"andl $1,%%eax\n"
+-		: "=a"(rc)
+-		:    "a"(regs)
+-		:    "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
+-#else
+-	asm volatile("pushl %%eax\n\t"
+-	    "movl 0(%%eax),%%edx\n\t"
+-	    "push %%edx\n\t"
+-	    "movl 4(%%eax),%%ebx\n\t"
+-	    "movl 8(%%eax),%%ecx\n\t"
+-	    "movl 12(%%eax),%%edx\n\t"
+-	    "movl 16(%%eax),%%esi\n\t"
+-	    "movl 20(%%eax),%%edi\n\t"
+-	    "popl %%eax\n\t"
+-	    "out %%al,$0xb2\n\t"
+-	    "out %%al,$0x84\n\t"
+-	    "xchgl %%eax,(%%esp)\n\t"
+-	    "movl %%ebx,4(%%eax)\n\t"
+-	    "movl %%ecx,8(%%eax)\n\t"
+-	    "movl %%edx,12(%%eax)\n\t"
+-	    "movl %%esi,16(%%eax)\n\t"
+-	    "movl %%edi,20(%%eax)\n\t"
+-	    "popl %%edx\n\t"
+-	    "movl %%edx,0(%%eax)\n\t"
+-	    "lahf\n\t"
+-	    "shrl $8,%%eax\n\t"
+-	    "andl $1,%%eax\n"
+-	    : "=a"(rc)
+-	    :    "a"(regs)
+-	    :    "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
+-#endif
+-	if (rc != 0 || (regs->eax & 0xffff) == 0xffff || regs->eax == eax)
+-		rc = -EINVAL;
+-
+-out:
+-	set_cpus_allowed_ptr(current, old_mask);
+-	free_cpumask_var(old_mask);
+-	return rc;
+-}
+-
+-/*
+- * Read the Fn key status.
+- */
+-static int i8k_get_fn_status(void)
+-{
+-	struct smm_regs regs = { .eax = I8K_SMM_FN_STATUS, };
+-	int rc;
+-
+-	rc = i8k_smm(&regs);
+-	if (rc < 0)
+-		return rc;
+-
+-	switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {
+-	case I8K_FN_UP:
+-		return I8K_VOL_UP;
+-	case I8K_FN_DOWN:
+-		return I8K_VOL_DOWN;
+-	case I8K_FN_MUTE:
+-		return I8K_VOL_MUTE;
+-	default:
+-		return 0;
+-	}
+-}
+-
+-/*
+- * Read the power status.
+- */
+-static int i8k_get_power_status(void)
+-{
+-	struct smm_regs regs = { .eax = I8K_SMM_POWER_STATUS, };
+-	int rc;
+-
+-	rc = i8k_smm(&regs);
+-	if (rc < 0)
+-		return rc;
+-
+-	return (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY;
+-}
+-
+-/*
+- * Read the fan status.
+- */
+-static int i8k_get_fan_status(int fan)
+-{
+-	struct smm_regs regs = { .eax = I8K_SMM_GET_FAN, };
+-
+-	regs.ebx = fan & 0xff;
+-	return i8k_smm(&regs) ? : regs.eax & 0xff;
+-}
+-
+-/*
+- * Read the fan speed in RPM.
+- */
+-static int i8k_get_fan_speed(int fan)
+-{
+-	struct smm_regs regs = { .eax = I8K_SMM_GET_SPEED, };
+-
+-	regs.ebx = fan & 0xff;
+-	return i8k_smm(&regs) ? : (regs.eax & 0xffff) * i8k_fan_mult;
+-}
+-
+-/*
+- * Read the fan type.
+- */
+-static int i8k_get_fan_type(int fan)
+-{
+-	struct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, };
+-
+-	regs.ebx = fan & 0xff;
+-	return i8k_smm(&regs) ? : regs.eax & 0xff;
+-}
+-
+-/*
+- * Read the fan nominal rpm for specific fan speed.
+- */
+-static int i8k_get_fan_nominal_speed(int fan, int speed)
+-{
+-	struct smm_regs regs = { .eax = I8K_SMM_GET_NOM_SPEED, };
+-
+-	regs.ebx = (fan & 0xff) | (speed << 8);
+-	return i8k_smm(&regs) ? : (regs.eax & 0xffff) * i8k_fan_mult;
+-}
+-
+-/*
+- * Set the fan speed (off, low, high). Returns the new fan status.
+- */
+-static int i8k_set_fan(int fan, int speed)
+-{
+-	struct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };
+-
+-	speed = (speed < 0) ? 0 : ((speed > i8k_fan_max) ? i8k_fan_max : speed);
+-	regs.ebx = (fan & 0xff) | (speed << 8);
+-
+-	return i8k_smm(&regs) ? : i8k_get_fan_status(fan);
+-}
+-
+-static int i8k_get_temp_type(int sensor)
+-{
+-	struct smm_regs regs = { .eax = I8K_SMM_GET_TEMP_TYPE, };
+-
+-	regs.ebx = sensor & 0xff;
+-	return i8k_smm(&regs) ? : regs.eax & 0xff;
+-}
+-
+-/*
+- * Read the cpu temperature.
+- */
+-static int _i8k_get_temp(int sensor)
+-{
+-	struct smm_regs regs = {
+-		.eax = I8K_SMM_GET_TEMP,
+-		.ebx = sensor & 0xff,
+-	};
+-
+-	return i8k_smm(&regs) ? : regs.eax & 0xff;
+-}
+-
+-static int i8k_get_temp(int sensor)
+-{
+-	int temp = _i8k_get_temp(sensor);
+-
+-	/*
+-	 * Sometimes the temperature sensor returns 0x99, which is out of range.
+-	 * In this case we retry (once) before returning an error.
+-	 # 1003655137 00000058 00005a4b
+-	 # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees
+-	 # 1003655139 00000054 00005c52
+-	 */
+-	if (temp == 0x99) {
+-		msleep(100);
+-		temp = _i8k_get_temp(sensor);
+-	}
+-	/*
+-	 * Return -ENODATA for all invalid temperatures.
+-	 *
+-	 * Known instances are the 0x99 value as seen above as well as
+-	 * 0xc1 (193), which may be returned when trying to read the GPU
+-	 * temperature if the system supports a GPU and it is currently
+-	 * turned off.
+-	 */
+-	if (temp > I8K_MAX_TEMP)
+-		return -ENODATA;
+-
+-	return temp;
+-}
+-
+-static int i8k_get_dell_signature(int req_fn)
+-{
+-	struct smm_regs regs = { .eax = req_fn, };
+-	int rc;
+-
+-	rc = i8k_smm(&regs);
+-	if (rc < 0)
+-		return rc;
+-
+-	return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1;
+-}
+-
+-static int
+-i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg)
+-{
+-	int val = 0;
+-	int speed;
+-	unsigned char buff[16];
+-	int __user *argp = (int __user *)arg;
+-
+-	if (!argp)
+-		return -EINVAL;
+-
+-	switch (cmd) {
+-	case I8K_BIOS_VERSION:
+-		val = (bios_version[0] << 16) |
+-				(bios_version[1] << 8) | bios_version[2];
+-		break;
+-
+-	case I8K_MACHINE_ID:
+-		memset(buff, 0, 16);
+-		strlcpy(buff, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
+-			sizeof(buff));
+-		break;
+-
+-	case I8K_FN_STATUS:
+-		val = i8k_get_fn_status();
+-		break;
+-
+-	case I8K_POWER_STATUS:
+-		val = i8k_get_power_status();
+-		break;
+-
+-	case I8K_GET_TEMP:
+-		val = i8k_get_temp(0);
+-		break;
+-
+-	case I8K_GET_SPEED:
+-		if (copy_from_user(&val, argp, sizeof(int)))
+-			return -EFAULT;
+-
+-		val = i8k_get_fan_speed(val);
+-		break;
+-
+-	case I8K_GET_FAN:
+-		if (copy_from_user(&val, argp, sizeof(int)))
+-			return -EFAULT;
+-
+-		val = i8k_get_fan_status(val);
+-		break;
+-
+-	case I8K_SET_FAN:
+-		if (restricted && !capable(CAP_SYS_ADMIN))
+-			return -EPERM;
+-
+-		if (copy_from_user(&val, argp, sizeof(int)))
+-			return -EFAULT;
+-
+-		if (copy_from_user(&speed, argp + 1, sizeof(int)))
+-			return -EFAULT;
+-
+-		val = i8k_set_fan(val, speed);
+-		break;
+-
+-	default:
+-		return -EINVAL;
+-	}
+-
+-	if (val < 0)
+-		return val;
+-
+-	switch (cmd) {
+-	case I8K_BIOS_VERSION:
+-		if (copy_to_user(argp, &val, 4))
+-			return -EFAULT;
+-
+-		break;
+-	case I8K_MACHINE_ID:
+-		if (copy_to_user(argp, buff, 16))
+-			return -EFAULT;
+-
+-		break;
+-	default:
+-		if (copy_to_user(argp, &val, sizeof(int)))
+-			return -EFAULT;
+-
+-		break;
+-	}
+-
+-	return 0;
+-}
+-
+-static long i8k_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
+-{
+-	long ret;
+-
+-	mutex_lock(&i8k_mutex);
+-	ret = i8k_ioctl_unlocked(fp, cmd, arg);
+-	mutex_unlock(&i8k_mutex);
+-
+-	return ret;
+-}
+-
+-/*
+- * Print the information for /proc/i8k.
+- */
+-static int i8k_proc_show(struct seq_file *seq, void *offset)
+-{
+-	int fn_key, cpu_temp, ac_power;
+-	int left_fan, right_fan, left_speed, right_speed;
+-
+-	cpu_temp	= i8k_get_temp(0);			/* 11100 µs */
+-	left_fan	= i8k_get_fan_status(I8K_FAN_LEFT);	/*   580 µs */
+-	right_fan	= i8k_get_fan_status(I8K_FAN_RIGHT);	/*   580 µs */
+-	left_speed	= i8k_get_fan_speed(I8K_FAN_LEFT);	/*   580 µs */
+-	right_speed	= i8k_get_fan_speed(I8K_FAN_RIGHT);	/*   580 µs */
+-	fn_key		= i8k_get_fn_status();			/*   750 µs */
+-	if (power_status)
+-		ac_power = i8k_get_power_status();		/* 14700 µs */
+-	else
+-		ac_power = -1;
+-
+-	/*
+-	 * Info:
+-	 *
+-	 * 1)  Format version (this will change if format changes)
+-	 * 2)  BIOS version
+-	 * 3)  BIOS machine ID
+-	 * 4)  Cpu temperature
+-	 * 5)  Left fan status
+-	 * 6)  Right fan status
+-	 * 7)  Left fan speed
+-	 * 8)  Right fan speed
+-	 * 9)  AC power
+-	 * 10) Fn Key status
+-	 */
+-	return seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
+-			  I8K_PROC_FMT,
+-			  bios_version,
+-			  i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
+-			  cpu_temp,
+-			  left_fan, right_fan, left_speed, right_speed,
+-			  ac_power, fn_key);
+-}
+-
+-static int i8k_open_fs(struct inode *inode, struct file *file)
+-{
+-	return single_open(file, i8k_proc_show, NULL);
+-}
+-
+-
+-/*
+- * Hwmon interface
+- */
+-
+-static ssize_t i8k_hwmon_show_temp_label(struct device *dev,
+-					 struct device_attribute *devattr,
+-					 char *buf)
+-{
+-	static const char * const labels[] = {
+-		"CPU",
+-		"GPU",
+-		"SODIMM",
+-		"Other",
+-		"Ambient",
+-		"Other",
+-	};
+-	int index = to_sensor_dev_attr(devattr)->index;
+-	int type;
+-
+-	type = i8k_get_temp_type(index);
+-	if (type < 0)
+-		return type;
+-	if (type >= ARRAY_SIZE(labels))
+-		type = ARRAY_SIZE(labels) - 1;
+-	return sprintf(buf, "%s\n", labels[type]);
+-}
+-
+-static ssize_t i8k_hwmon_show_temp(struct device *dev,
+-				   struct device_attribute *devattr,
+-				   char *buf)
+-{
+-	int index = to_sensor_dev_attr(devattr)->index;
+-	int temp;
+-
+-	temp = i8k_get_temp(index);
+-	if (temp < 0)
+-		return temp;
+-	return sprintf(buf, "%d\n", temp * 1000);
+-}
+-
+-static ssize_t i8k_hwmon_show_fan_label(struct device *dev,
+-					struct device_attribute *devattr,
+-					char *buf)
+-{
+-	static const char * const labels[] = {
+-		"Processor Fan",
+-		"Motherboard Fan",
+-		"Video Fan",
+-		"Power Supply Fan",
+-		"Chipset Fan",
+-		"Other Fan",
+-	};
+-	int index = to_sensor_dev_attr(devattr)->index;
+-	bool dock = false;
+-	int type;
+-
+-	type = i8k_get_fan_type(index);
+-	if (type < 0)
+-		return type;
+-
+-	if (type & 0x10) {
+-		dock = true;
+-		type &= 0x0F;
+-	}
+-
+-	if (type >= ARRAY_SIZE(labels))
+-		type = (ARRAY_SIZE(labels) - 1);
+-
+-	return sprintf(buf, "%s%s\n", (dock ? "Docking " : ""), labels[type]);
+-}
+-
+-static ssize_t i8k_hwmon_show_fan(struct device *dev,
+-				  struct device_attribute *devattr,
+-				  char *buf)
+-{
+-	int index = to_sensor_dev_attr(devattr)->index;
+-	int fan_speed;
+-
+-	fan_speed = i8k_get_fan_speed(index);
+-	if (fan_speed < 0)
+-		return fan_speed;
+-	return sprintf(buf, "%d\n", fan_speed);
+-}
+-
+-static ssize_t i8k_hwmon_show_pwm(struct device *dev,
+-				  struct device_attribute *devattr,
+-				  char *buf)
+-{
+-	int index = to_sensor_dev_attr(devattr)->index;
+-	int status;
+-
+-	status = i8k_get_fan_status(index);
+-	if (status < 0)
+-		return -EIO;
+-	return sprintf(buf, "%d\n", clamp_val(status * i8k_pwm_mult, 0, 255));
+-}
+-
+-static ssize_t i8k_hwmon_set_pwm(struct device *dev,
+-				 struct device_attribute *attr,
+-				 const char *buf, size_t count)
+-{
+-	int index = to_sensor_dev_attr(attr)->index;
+-	unsigned long val;
+-	int err;
+-
+-	err = kstrtoul(buf, 10, &val);
+-	if (err)
+-		return err;
+-	val = clamp_val(DIV_ROUND_CLOSEST(val, i8k_pwm_mult), 0, i8k_fan_max);
+-
+-	mutex_lock(&i8k_mutex);
+-	err = i8k_set_fan(index, val);
+-	mutex_unlock(&i8k_mutex);
+-
+-	return err < 0 ? -EIO : count;
+-}
+-
+-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 0);
+-static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
+-			  0);
+-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 1);
+-static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
+-			  1);
+-static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 2);
+-static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
+-			  2);
+-static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 3);
+-static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
+-			  3);
+-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, 0);
+-static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL,
+-			  0);
+-static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,
+-			  i8k_hwmon_set_pwm, 0);
+-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL,
+-			  1);
+-static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL,
+-			  1);
+-static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,
+-			  i8k_hwmon_set_pwm, 1);
+-
+-static struct attribute *i8k_attrs[] = {
+-	&sensor_dev_attr_temp1_input.dev_attr.attr,	/* 0 */
+-	&sensor_dev_attr_temp1_label.dev_attr.attr,	/* 1 */
+-	&sensor_dev_attr_temp2_input.dev_attr.attr,	/* 2 */
+-	&sensor_dev_attr_temp2_label.dev_attr.attr,	/* 3 */
+-	&sensor_dev_attr_temp3_input.dev_attr.attr,	/* 4 */
+-	&sensor_dev_attr_temp3_label.dev_attr.attr,	/* 5 */
+-	&sensor_dev_attr_temp4_input.dev_attr.attr,	/* 6 */
+-	&sensor_dev_attr_temp4_label.dev_attr.attr,	/* 7 */
+-	&sensor_dev_attr_fan1_input.dev_attr.attr,	/* 8 */
+-	&sensor_dev_attr_fan1_label.dev_attr.attr,	/* 9 */
+-	&sensor_dev_attr_pwm1.dev_attr.attr,		/* 10 */
+-	&sensor_dev_attr_fan2_input.dev_attr.attr,	/* 11 */
+-	&sensor_dev_attr_fan2_label.dev_attr.attr,	/* 12 */
+-	&sensor_dev_attr_pwm2.dev_attr.attr,		/* 13 */
+-	NULL
+-};
+-
+-static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
+-			      int index)
+-{
+-	if (index >= 0 && index <= 1 &&
+-	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
+-		return 0;
+-	if (index >= 2 && index <= 3 &&
+-	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2))
+-		return 0;
+-	if (index >= 4 && index <= 5 &&
+-	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3))
+-		return 0;
+-	if (index >= 6 && index <= 7 &&
+-	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4))
+-		return 0;
+-	if (index >= 8 && index <= 10 &&
+-	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1))
+-		return 0;
+-	if (index >= 11 && index <= 13 &&
+-	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2))
+-		return 0;
+-
+-	return attr->mode;
+-}
+-
+-static const struct attribute_group i8k_group = {
+-	.attrs = i8k_attrs,
+-	.is_visible = i8k_is_visible,
+-};
+-__ATTRIBUTE_GROUPS(i8k);
+-
+-static int __init i8k_init_hwmon(void)
+-{
+-	int err;
+-
+-	i8k_hwmon_flags = 0;
+-
+-	/* CPU temperature attributes, if temperature type is OK */
+-	err = i8k_get_temp_type(0);
+-	if (err >= 0)
+-		i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP1;
+-	/* check for additional temperature sensors */
+-	err = i8k_get_temp_type(1);
+-	if (err >= 0)
+-		i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP2;
+-	err = i8k_get_temp_type(2);
+-	if (err >= 0)
+-		i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP3;
+-	err = i8k_get_temp_type(3);
+-	if (err >= 0)
+-		i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4;
+-
+-	/* First fan attributes, if fan type is OK */
+-	err = i8k_get_fan_type(0);
+-	if (err >= 0)
+-		i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1;
+-
+-	/* Second fan attributes, if fan type is OK */
+-	err = i8k_get_fan_type(1);
+-	if (err >= 0)
+-		i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2;
+-
+-	i8k_hwmon_dev = hwmon_device_register_with_groups(NULL, "i8k", NULL,
+-							  i8k_groups);
+-	if (IS_ERR(i8k_hwmon_dev)) {
+-		err = PTR_ERR(i8k_hwmon_dev);
+-		i8k_hwmon_dev = NULL;
+-		pr_err("hwmon registration failed (%d)\n", err);
+-		return err;
+-	}
+-	return 0;
+-}
+-
+-struct i8k_config_data {
+-	uint fan_mult;
+-	uint fan_max;
+-};
+-
+-enum i8k_configs {
+-	DELL_LATITUDE_D520,
+-	DELL_PRECISION_490,
+-	DELL_STUDIO,
+-	DELL_XPS,
+-};
+-
+-static const struct i8k_config_data i8k_config_data[] = {
+-	[DELL_LATITUDE_D520] = {
+-		.fan_mult = 1,
+-		.fan_max = I8K_FAN_TURBO,
+-	},
+-	[DELL_PRECISION_490] = {
+-		.fan_mult = 1,
+-		.fan_max = I8K_FAN_TURBO,
+-	},
+-	[DELL_STUDIO] = {
+-		.fan_mult = 1,
+-		.fan_max = I8K_FAN_HIGH,
+-	},
+-	[DELL_XPS] = {
+-		.fan_mult = 1,
+-		.fan_max = I8K_FAN_HIGH,
+-	},
+-};
+-
+-static struct dmi_system_id i8k_dmi_table[] __initdata = {
+-	{
+-		.ident = "Dell Inspiron",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
+-		},
+-	},
+-	{
+-		.ident = "Dell Latitude",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
+-		},
+-	},
+-	{
+-		.ident = "Dell Inspiron 2",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
+-		},
+-	},
+-	{
+-		.ident = "Dell Latitude D520",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D520"),
+-		},
+-		.driver_data = (void *)&i8k_config_data[DELL_LATITUDE_D520],
+-	},
+-	{
+-		.ident = "Dell Latitude 2",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
+-		},
+-	},
+-	{	/* UK Inspiron 6400  */
+-		.ident = "Dell Inspiron 3",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "MM061"),
+-		},
+-	},
+-	{
+-		.ident = "Dell Inspiron 3",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "MP061"),
+-		},
+-	},
+-	{
+-		.ident = "Dell Precision 490",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+-			DMI_MATCH(DMI_PRODUCT_NAME,
+-				  "Precision WorkStation 490"),
+-		},
+-		.driver_data = (void *)&i8k_config_data[DELL_PRECISION_490],
+-	},
+-	{
+-		.ident = "Dell Precision",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "Precision"),
+-		},
+-	},
+-	{
+-		.ident = "Dell Vostro",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro"),
+-		},
+-	},
+-	{
+-		.ident = "Dell XPS421",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
+-		},
+-	},
+-	{
+-		.ident = "Dell Studio",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "Studio"),
+-		},
+-		.driver_data = (void *)&i8k_config_data[DELL_STUDIO],
+-	},
+-	{
+-		.ident = "Dell XPS 13",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "XPS13"),
+-		},
+-		.driver_data = (void *)&i8k_config_data[DELL_XPS],
+-	},
+-	{
+-		.ident = "Dell XPS M140",
+-		.matches = {
+-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+-			DMI_MATCH(DMI_PRODUCT_NAME, "MXC051"),
+-		},
+-		.driver_data = (void *)&i8k_config_data[DELL_XPS],
+-	},
+-	{ }
+-};
+-
+-MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);
+-
+-/*
+- * Probe for the presence of a supported laptop.
+- */
+-static int __init i8k_probe(void)
+-{
+-	const struct dmi_system_id *id;
+-	int fan, ret;
+-
+-	/*
+-	 * Get DMI information
+-	 */
+-	if (!dmi_check_system(i8k_dmi_table)) {
+-		if (!ignore_dmi && !force)
+-			return -ENODEV;
+-
+-		pr_info("not running on a supported Dell system.\n");
+-		pr_info("vendor=%s, model=%s, version=%s\n",
+-			i8k_get_dmi_data(DMI_SYS_VENDOR),
+-			i8k_get_dmi_data(DMI_PRODUCT_NAME),
+-			i8k_get_dmi_data(DMI_BIOS_VERSION));
+-	}
+-
+-	strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION),
+-		sizeof(bios_version));
+-
+-	/*
+-	 * Get SMM Dell signature
+-	 */
+-	if (i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG1) &&
+-	    i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG2)) {
+-		pr_err("unable to get SMM Dell signature\n");
+-		if (!force)
+-			return -ENODEV;
+-	}
+-
+-	/*
+-	 * Set fan multiplier and maximal fan speed from dmi config
+-	 * Values specified in module parameters override values from dmi
+-	 */
+-	id = dmi_first_match(i8k_dmi_table);
+-	if (id && id->driver_data) {
+-		const struct i8k_config_data *conf = id->driver_data;
+-		if (!fan_mult && conf->fan_mult)
+-			fan_mult = conf->fan_mult;
+-		if (!fan_max && conf->fan_max)
+-			fan_max = conf->fan_max;
+-	}
+-
+-	i8k_fan_max = fan_max ? : I8K_FAN_HIGH;	/* Must not be 0 */
+-	i8k_pwm_mult = DIV_ROUND_UP(255, i8k_fan_max);
+-
+-	if (!fan_mult) {
+-		/*
+-		 * Autodetect fan multiplier based on nominal rpm
+-		 * If fan reports rpm value too high then set multiplier to 1
+-		 */
+-		for (fan = 0; fan < 2; ++fan) {
+-			ret = i8k_get_fan_nominal_speed(fan, i8k_fan_max);
+-			if (ret < 0)
+-				continue;
+-			if (ret > I8K_FAN_MAX_RPM)
+-				i8k_fan_mult = 1;
+-			break;
+-		}
+-	} else {
+-		/* Fan multiplier was specified in module param or in dmi */
+-		i8k_fan_mult = fan_mult;
+-	}
+-
+-	return 0;
+-}
+-
+-static int __init i8k_init(void)
+-{
+-	struct proc_dir_entry *proc_i8k;
+-	int err;
+-
+-	/* Are we running on an supported laptop? */
+-	if (i8k_probe())
+-		return -ENODEV;
+-
+-	/* Register the proc entry */
+-	proc_i8k = proc_create("i8k", 0, NULL, &i8k_fops);
+-	if (!proc_i8k)
+-		return -ENOENT;
+-
+-	err = i8k_init_hwmon();
+-	if (err)
+-		goto exit_remove_proc;
+-
+-	return 0;
+-
+- exit_remove_proc:
+-	remove_proc_entry("i8k", NULL);
+-	return err;
+-}
+-
+-static void __exit i8k_exit(void)
+-{
+-	hwmon_device_unregister(i8k_hwmon_dev);
+-	remove_proc_entry("i8k", NULL);
+-}
+-
+-module_init(i8k_init);
+-module_exit(i8k_exit);
+diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
+index 6c94147..1c3e458 100644
+--- a/drivers/hwmon/Makefile
++++ b/drivers/hwmon/Makefile
+@@ -155,6 +155,7 @@ obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
+ obj-$(CONFIG_SENSORS_W83L786NG)	+= w83l786ng.o
+ obj-$(CONFIG_SENSORS_WM831X)	+= wm831x-hwmon.o
+ obj-$(CONFIG_SENSORS_WM8350)	+= wm8350-hwmon.o
++obj-$(CONFIG_I8K)		+= dell-smm-hwmon.o
+ 
+ obj-$(CONFIG_PMBUS)		+= pmbus/
+ 
+diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c
+new file mode 100644
+index 0000000..2b04e4f
+--- /dev/null
++++ b/drivers/hwmon/dell-smm-hwmon.c
+@@ -0,0 +1,1007 @@
++/*
++ * dell-smm-hwmon.c -- Linux driver for accessing the SMM BIOS on Dell laptops.
++ *
++ * Copyright (C) 2001  Massimo Dal Zotto <dz@debian.org>
++ *
++ * Hwmon integration:
++ * Copyright (C) 2011  Jean Delvare <jdelvare@suse.de>
++ * Copyright (C) 2013, 2014  Guenter Roeck <linux@roeck-us.net>
++ * Copyright (C) 2014, 2015  Pali Rohár <pali.rohar@gmail.com>
++ *
++ * 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, 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.
++ */
++
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
++#include <linux/delay.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/proc_fs.h>
++#include <linux/seq_file.h>
++#include <linux/dmi.h>
++#include <linux/capability.h>
++#include <linux/mutex.h>
++#include <linux/hwmon.h>
++#include <linux/hwmon-sysfs.h>
++#include <linux/uaccess.h>
++#include <linux/io.h>
++#include <linux/sched.h>
++
++#include <linux/i8k.h>
++
++#define I8K_SMM_FN_STATUS	0x0025
++#define I8K_SMM_POWER_STATUS	0x0069
++#define I8K_SMM_SET_FAN		0x01a3
++#define I8K_SMM_GET_FAN		0x00a3
++#define I8K_SMM_GET_SPEED	0x02a3
++#define I8K_SMM_GET_FAN_TYPE	0x03a3
++#define I8K_SMM_GET_NOM_SPEED	0x04a3
++#define I8K_SMM_GET_TEMP	0x10a3
++#define I8K_SMM_GET_TEMP_TYPE	0x11a3
++#define I8K_SMM_GET_DELL_SIG1	0xfea3
++#define I8K_SMM_GET_DELL_SIG2	0xffa3
++
++#define I8K_FAN_MULT		30
++#define I8K_FAN_MAX_RPM		30000
++#define I8K_MAX_TEMP		127
++
++#define I8K_FN_NONE		0x00
++#define I8K_FN_UP		0x01
++#define I8K_FN_DOWN		0x02
++#define I8K_FN_MUTE		0x04
++#define I8K_FN_MASK		0x07
++#define I8K_FN_SHIFT		8
++
++#define I8K_POWER_AC		0x05
++#define I8K_POWER_BATTERY	0x01
++
++static DEFINE_MUTEX(i8k_mutex);
++static char bios_version[4];
++static struct device *i8k_hwmon_dev;
++static u32 i8k_hwmon_flags;
++static uint i8k_fan_mult = I8K_FAN_MULT;
++static uint i8k_pwm_mult;
++static uint i8k_fan_max = I8K_FAN_HIGH;
++
++#define I8K_HWMON_HAVE_TEMP1	(1 << 0)
++#define I8K_HWMON_HAVE_TEMP2	(1 << 1)
++#define I8K_HWMON_HAVE_TEMP3	(1 << 2)
++#define I8K_HWMON_HAVE_TEMP4	(1 << 3)
++#define I8K_HWMON_HAVE_FAN1	(1 << 4)
++#define I8K_HWMON_HAVE_FAN2	(1 << 5)
++
++MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
++MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
++MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("i8k");
++
++static bool force;
++module_param(force, bool, 0);
++MODULE_PARM_DESC(force, "Force loading without checking for supported models");
++
++static bool ignore_dmi;
++module_param(ignore_dmi, bool, 0);
++MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
++
++static bool restricted;
++module_param(restricted, bool, 0);
++MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set");
++
++static bool power_status;
++module_param(power_status, bool, 0600);
++MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
++
++static uint fan_mult;
++module_param(fan_mult, uint, 0);
++MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with (default: autodetect)");
++
++static uint fan_max;
++module_param(fan_max, uint, 0);
++MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed (default: autodetect)");
++
++static int i8k_open_fs(struct inode *inode, struct file *file);
++static long i8k_ioctl(struct file *, unsigned int, unsigned long);
++
++static const struct file_operations i8k_fops = {
++	.owner		= THIS_MODULE,
++	.open		= i8k_open_fs,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++	.unlocked_ioctl	= i8k_ioctl,
++};
++
++struct smm_regs {
++	unsigned int eax;
++	unsigned int ebx __packed;
++	unsigned int ecx __packed;
++	unsigned int edx __packed;
++	unsigned int esi __packed;
++	unsigned int edi __packed;
++};
++
++static inline const char *i8k_get_dmi_data(int field)
++{
++	const char *dmi_data = dmi_get_system_info(field);
++
++	return dmi_data && *dmi_data ? dmi_data : "?";
++}
++
++/*
++ * Call the System Management Mode BIOS. Code provided by Jonathan Buzzard.
++ */
++static int i8k_smm(struct smm_regs *regs)
++{
++	int rc;
++	int eax = regs->eax;
++	cpumask_var_t old_mask;
++
++	/* SMM requires CPU 0 */
++	if (!alloc_cpumask_var(&old_mask, GFP_KERNEL))
++		return -ENOMEM;
++	cpumask_copy(old_mask, &current->cpus_allowed);
++	rc = set_cpus_allowed_ptr(current, cpumask_of(0));
++	if (rc)
++		goto out;
++	if (smp_processor_id() != 0) {
++		rc = -EBUSY;
++		goto out;
++	}
++
++#if defined(CONFIG_X86_64)
++	asm volatile("pushq %%rax\n\t"
++		"movl 0(%%rax),%%edx\n\t"
++		"pushq %%rdx\n\t"
++		"movl 4(%%rax),%%ebx\n\t"
++		"movl 8(%%rax),%%ecx\n\t"
++		"movl 12(%%rax),%%edx\n\t"
++		"movl 16(%%rax),%%esi\n\t"
++		"movl 20(%%rax),%%edi\n\t"
++		"popq %%rax\n\t"
++		"out %%al,$0xb2\n\t"
++		"out %%al,$0x84\n\t"
++		"xchgq %%rax,(%%rsp)\n\t"
++		"movl %%ebx,4(%%rax)\n\t"
++		"movl %%ecx,8(%%rax)\n\t"
++		"movl %%edx,12(%%rax)\n\t"
++		"movl %%esi,16(%%rax)\n\t"
++		"movl %%edi,20(%%rax)\n\t"
++		"popq %%rdx\n\t"
++		"movl %%edx,0(%%rax)\n\t"
++		"pushfq\n\t"
++		"popq %%rax\n\t"
++		"andl $1,%%eax\n"
++		: "=a"(rc)
++		:    "a"(regs)
++		:    "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
++#else
++	asm volatile("pushl %%eax\n\t"
++	    "movl 0(%%eax),%%edx\n\t"
++	    "push %%edx\n\t"
++	    "movl 4(%%eax),%%ebx\n\t"
++	    "movl 8(%%eax),%%ecx\n\t"
++	    "movl 12(%%eax),%%edx\n\t"
++	    "movl 16(%%eax),%%esi\n\t"
++	    "movl 20(%%eax),%%edi\n\t"
++	    "popl %%eax\n\t"
++	    "out %%al,$0xb2\n\t"
++	    "out %%al,$0x84\n\t"
++	    "xchgl %%eax,(%%esp)\n\t"
++	    "movl %%ebx,4(%%eax)\n\t"
++	    "movl %%ecx,8(%%eax)\n\t"
++	    "movl %%edx,12(%%eax)\n\t"
++	    "movl %%esi,16(%%eax)\n\t"
++	    "movl %%edi,20(%%eax)\n\t"
++	    "popl %%edx\n\t"
++	    "movl %%edx,0(%%eax)\n\t"
++	    "lahf\n\t"
++	    "shrl $8,%%eax\n\t"
++	    "andl $1,%%eax\n"
++	    : "=a"(rc)
++	    :    "a"(regs)
++	    :    "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
++#endif
++	if (rc != 0 || (regs->eax & 0xffff) == 0xffff || regs->eax == eax)
++		rc = -EINVAL;
++
++out:
++	set_cpus_allowed_ptr(current, old_mask);
++	free_cpumask_var(old_mask);
++	return rc;
++}
++
++/*
++ * Read the Fn key status.
++ */
++static int i8k_get_fn_status(void)
++{
++	struct smm_regs regs = { .eax = I8K_SMM_FN_STATUS, };
++	int rc;
++
++	rc = i8k_smm(&regs);
++	if (rc < 0)
++		return rc;
++
++	switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {
++	case I8K_FN_UP:
++		return I8K_VOL_UP;
++	case I8K_FN_DOWN:
++		return I8K_VOL_DOWN;
++	case I8K_FN_MUTE:
++		return I8K_VOL_MUTE;
++	default:
++		return 0;
++	}
++}
++
++/*
++ * Read the power status.
++ */
++static int i8k_get_power_status(void)
++{
++	struct smm_regs regs = { .eax = I8K_SMM_POWER_STATUS, };
++	int rc;
++
++	rc = i8k_smm(&regs);
++	if (rc < 0)
++		return rc;
++
++	return (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY;
++}
++
++/*
++ * Read the fan status.
++ */
++static int i8k_get_fan_status(int fan)
++{
++	struct smm_regs regs = { .eax = I8K_SMM_GET_FAN, };
++
++	regs.ebx = fan & 0xff;
++	return i8k_smm(&regs) ? : regs.eax & 0xff;
++}
++
++/*
++ * Read the fan speed in RPM.
++ */
++static int i8k_get_fan_speed(int fan)
++{
++	struct smm_regs regs = { .eax = I8K_SMM_GET_SPEED, };
++
++	regs.ebx = fan & 0xff;
++	return i8k_smm(&regs) ? : (regs.eax & 0xffff) * i8k_fan_mult;
++}
++
++/*
++ * Read the fan type.
++ */
++static int i8k_get_fan_type(int fan)
++{
++	struct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, };
++
++	regs.ebx = fan & 0xff;
++	return i8k_smm(&regs) ? : regs.eax & 0xff;
++}
++
++/*
++ * Read the fan nominal rpm for specific fan speed.
++ */
++static int i8k_get_fan_nominal_speed(int fan, int speed)
++{
++	struct smm_regs regs = { .eax = I8K_SMM_GET_NOM_SPEED, };
++
++	regs.ebx = (fan & 0xff) | (speed << 8);
++	return i8k_smm(&regs) ? : (regs.eax & 0xffff) * i8k_fan_mult;
++}
++
++/*
++ * Set the fan speed (off, low, high). Returns the new fan status.
++ */
++static int i8k_set_fan(int fan, int speed)
++{
++	struct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };
++
++	speed = (speed < 0) ? 0 : ((speed > i8k_fan_max) ? i8k_fan_max : speed);
++	regs.ebx = (fan & 0xff) | (speed << 8);
++
++	return i8k_smm(&regs) ? : i8k_get_fan_status(fan);
++}
++
++static int i8k_get_temp_type(int sensor)
++{
++	struct smm_regs regs = { .eax = I8K_SMM_GET_TEMP_TYPE, };
++
++	regs.ebx = sensor & 0xff;
++	return i8k_smm(&regs) ? : regs.eax & 0xff;
++}
++
++/*
++ * Read the cpu temperature.
++ */
++static int _i8k_get_temp(int sensor)
++{
++	struct smm_regs regs = {
++		.eax = I8K_SMM_GET_TEMP,
++		.ebx = sensor & 0xff,
++	};
++
++	return i8k_smm(&regs) ? : regs.eax & 0xff;
++}
++
++static int i8k_get_temp(int sensor)
++{
++	int temp = _i8k_get_temp(sensor);
++
++	/*
++	 * Sometimes the temperature sensor returns 0x99, which is out of range.
++	 * In this case we retry (once) before returning an error.
++	 # 1003655137 00000058 00005a4b
++	 # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees
++	 # 1003655139 00000054 00005c52
++	 */
++	if (temp == 0x99) {
++		msleep(100);
++		temp = _i8k_get_temp(sensor);
++	}
++	/*
++	 * Return -ENODATA for all invalid temperatures.
++	 *
++	 * Known instances are the 0x99 value as seen above as well as
++	 * 0xc1 (193), which may be returned when trying to read the GPU
++	 * temperature if the system supports a GPU and it is currently
++	 * turned off.
++	 */
++	if (temp > I8K_MAX_TEMP)
++		return -ENODATA;
++
++	return temp;
++}
++
++static int i8k_get_dell_signature(int req_fn)
++{
++	struct smm_regs regs = { .eax = req_fn, };
++	int rc;
++
++	rc = i8k_smm(&regs);
++	if (rc < 0)
++		return rc;
++
++	return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1;
++}
++
++static int
++i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg)
++{
++	int val = 0;
++	int speed;
++	unsigned char buff[16];
++	int __user *argp = (int __user *)arg;
++
++	if (!argp)
++		return -EINVAL;
++
++	switch (cmd) {
++	case I8K_BIOS_VERSION:
++		val = (bios_version[0] << 16) |
++				(bios_version[1] << 8) | bios_version[2];
++		break;
++
++	case I8K_MACHINE_ID:
++		memset(buff, 0, 16);
++		strlcpy(buff, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
++			sizeof(buff));
++		break;
++
++	case I8K_FN_STATUS:
++		val = i8k_get_fn_status();
++		break;
++
++	case I8K_POWER_STATUS:
++		val = i8k_get_power_status();
++		break;
++
++	case I8K_GET_TEMP:
++		val = i8k_get_temp(0);
++		break;
++
++	case I8K_GET_SPEED:
++		if (copy_from_user(&val, argp, sizeof(int)))
++			return -EFAULT;
++
++		val = i8k_get_fan_speed(val);
++		break;
++
++	case I8K_GET_FAN:
++		if (copy_from_user(&val, argp, sizeof(int)))
++			return -EFAULT;
++
++		val = i8k_get_fan_status(val);
++		break;
++
++	case I8K_SET_FAN:
++		if (restricted && !capable(CAP_SYS_ADMIN))
++			return -EPERM;
++
++		if (copy_from_user(&val, argp, sizeof(int)))
++			return -EFAULT;
++
++		if (copy_from_user(&speed, argp + 1, sizeof(int)))
++			return -EFAULT;
++
++		val = i8k_set_fan(val, speed);
++		break;
++
++	default:
++		return -EINVAL;
++	}
++
++	if (val < 0)
++		return val;
++
++	switch (cmd) {
++	case I8K_BIOS_VERSION:
++		if (copy_to_user(argp, &val, 4))
++			return -EFAULT;
++
++		break;
++	case I8K_MACHINE_ID:
++		if (copy_to_user(argp, buff, 16))
++			return -EFAULT;
++
++		break;
++	default:
++		if (copy_to_user(argp, &val, sizeof(int)))
++			return -EFAULT;
++
++		break;
++	}
++
++	return 0;
++}
++
++static long i8k_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
++{
++	long ret;
++
++	mutex_lock(&i8k_mutex);
++	ret = i8k_ioctl_unlocked(fp, cmd, arg);
++	mutex_unlock(&i8k_mutex);
++
++	return ret;
++}
++
++/*
++ * Print the information for /proc/i8k.
++ */
++static int i8k_proc_show(struct seq_file *seq, void *offset)
++{
++	int fn_key, cpu_temp, ac_power;
++	int left_fan, right_fan, left_speed, right_speed;
++
++	cpu_temp	= i8k_get_temp(0);			/* 11100 µs */
++	left_fan	= i8k_get_fan_status(I8K_FAN_LEFT);	/*   580 µs */
++	right_fan	= i8k_get_fan_status(I8K_FAN_RIGHT);	/*   580 µs */
++	left_speed	= i8k_get_fan_speed(I8K_FAN_LEFT);	/*   580 µs */
++	right_speed	= i8k_get_fan_speed(I8K_FAN_RIGHT);	/*   580 µs */
++	fn_key		= i8k_get_fn_status();			/*   750 µs */
++	if (power_status)
++		ac_power = i8k_get_power_status();		/* 14700 µs */
++	else
++		ac_power = -1;
++
++	/*
++	 * Info:
++	 *
++	 * 1)  Format version (this will change if format changes)
++	 * 2)  BIOS version
++	 * 3)  BIOS machine ID
++	 * 4)  Cpu temperature
++	 * 5)  Left fan status
++	 * 6)  Right fan status
++	 * 7)  Left fan speed
++	 * 8)  Right fan speed
++	 * 9)  AC power
++	 * 10) Fn Key status
++	 */
++	return seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
++			  I8K_PROC_FMT,
++			  bios_version,
++			  i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
++			  cpu_temp,
++			  left_fan, right_fan, left_speed, right_speed,
++			  ac_power, fn_key);
++}
++
++static int i8k_open_fs(struct inode *inode, struct file *file)
++{
++	return single_open(file, i8k_proc_show, NULL);
++}
++
++
++/*
++ * Hwmon interface
++ */
++
++static ssize_t i8k_hwmon_show_temp_label(struct device *dev,
++					 struct device_attribute *devattr,
++					 char *buf)
++{
++	static const char * const labels[] = {
++		"CPU",
++		"GPU",
++		"SODIMM",
++		"Other",
++		"Ambient",
++		"Other",
++	};
++	int index = to_sensor_dev_attr(devattr)->index;
++	int type;
++
++	type = i8k_get_temp_type(index);
++	if (type < 0)
++		return type;
++	if (type >= ARRAY_SIZE(labels))
++		type = ARRAY_SIZE(labels) - 1;
++	return sprintf(buf, "%s\n", labels[type]);
++}
++
++static ssize_t i8k_hwmon_show_temp(struct device *dev,
++				   struct device_attribute *devattr,
++				   char *buf)
++{
++	int index = to_sensor_dev_attr(devattr)->index;
++	int temp;
++
++	temp = i8k_get_temp(index);
++	if (temp < 0)
++		return temp;
++	return sprintf(buf, "%d\n", temp * 1000);
++}
++
++static ssize_t i8k_hwmon_show_fan_label(struct device *dev,
++					struct device_attribute *devattr,
++					char *buf)
++{
++	static const char * const labels[] = {
++		"Processor Fan",
++		"Motherboard Fan",
++		"Video Fan",
++		"Power Supply Fan",
++		"Chipset Fan",
++		"Other Fan",
++	};
++	int index = to_sensor_dev_attr(devattr)->index;
++	bool dock = false;
++	int type;
++
++	type = i8k_get_fan_type(index);
++	if (type < 0)
++		return type;
++
++	if (type & 0x10) {
++		dock = true;
++		type &= 0x0F;
++	}
++
++	if (type >= ARRAY_SIZE(labels))
++		type = (ARRAY_SIZE(labels) - 1);
++
++	return sprintf(buf, "%s%s\n", (dock ? "Docking " : ""), labels[type]);
++}
++
++static ssize_t i8k_hwmon_show_fan(struct device *dev,
++				  struct device_attribute *devattr,
++				  char *buf)
++{
++	int index = to_sensor_dev_attr(devattr)->index;
++	int fan_speed;
++
++	fan_speed = i8k_get_fan_speed(index);
++	if (fan_speed < 0)
++		return fan_speed;
++	return sprintf(buf, "%d\n", fan_speed);
++}
++
++static ssize_t i8k_hwmon_show_pwm(struct device *dev,
++				  struct device_attribute *devattr,
++				  char *buf)
++{
++	int index = to_sensor_dev_attr(devattr)->index;
++	int status;
++
++	status = i8k_get_fan_status(index);
++	if (status < 0)
++		return -EIO;
++	return sprintf(buf, "%d\n", clamp_val(status * i8k_pwm_mult, 0, 255));
++}
++
++static ssize_t i8k_hwmon_set_pwm(struct device *dev,
++				 struct device_attribute *attr,
++				 const char *buf, size_t count)
++{
++	int index = to_sensor_dev_attr(attr)->index;
++	unsigned long val;
++	int err;
++
++	err = kstrtoul(buf, 10, &val);
++	if (err)
++		return err;
++	val = clamp_val(DIV_ROUND_CLOSEST(val, i8k_pwm_mult), 0, i8k_fan_max);
++
++	mutex_lock(&i8k_mutex);
++	err = i8k_set_fan(index, val);
++	mutex_unlock(&i8k_mutex);
++
++	return err < 0 ? -EIO : count;
++}
++
++static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 0);
++static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
++			  0);
++static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 1);
++static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
++			  1);
++static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 2);
++static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
++			  2);
++static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 3);
++static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
++			  3);
++static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, 0);
++static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL,
++			  0);
++static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,
++			  i8k_hwmon_set_pwm, 0);
++static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL,
++			  1);
++static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL,
++			  1);
++static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,
++			  i8k_hwmon_set_pwm, 1);
++
++static struct attribute *i8k_attrs[] = {
++	&sensor_dev_attr_temp1_input.dev_attr.attr,	/* 0 */
++	&sensor_dev_attr_temp1_label.dev_attr.attr,	/* 1 */
++	&sensor_dev_attr_temp2_input.dev_attr.attr,	/* 2 */
++	&sensor_dev_attr_temp2_label.dev_attr.attr,	/* 3 */
++	&sensor_dev_attr_temp3_input.dev_attr.attr,	/* 4 */
++	&sensor_dev_attr_temp3_label.dev_attr.attr,	/* 5 */
++	&sensor_dev_attr_temp4_input.dev_attr.attr,	/* 6 */
++	&sensor_dev_attr_temp4_label.dev_attr.attr,	/* 7 */
++	&sensor_dev_attr_fan1_input.dev_attr.attr,	/* 8 */
++	&sensor_dev_attr_fan1_label.dev_attr.attr,	/* 9 */
++	&sensor_dev_attr_pwm1.dev_attr.attr,		/* 10 */
++	&sensor_dev_attr_fan2_input.dev_attr.attr,	/* 11 */
++	&sensor_dev_attr_fan2_label.dev_attr.attr,	/* 12 */
++	&sensor_dev_attr_pwm2.dev_attr.attr,		/* 13 */
++	NULL
++};
++
++static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
++			      int index)
++{
++	if (index >= 0 && index <= 1 &&
++	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
++		return 0;
++	if (index >= 2 && index <= 3 &&
++	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2))
++		return 0;
++	if (index >= 4 && index <= 5 &&
++	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3))
++		return 0;
++	if (index >= 6 && index <= 7 &&
++	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4))
++		return 0;
++	if (index >= 8 && index <= 10 &&
++	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1))
++		return 0;
++	if (index >= 11 && index <= 13 &&
++	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2))
++		return 0;
++
++	return attr->mode;
++}
++
++static const struct attribute_group i8k_group = {
++	.attrs = i8k_attrs,
++	.is_visible = i8k_is_visible,
++};
++__ATTRIBUTE_GROUPS(i8k);
++
++static int __init i8k_init_hwmon(void)
++{
++	int err;
++
++	i8k_hwmon_flags = 0;
++
++	/* CPU temperature attributes, if temperature type is OK */
++	err = i8k_get_temp_type(0);
++	if (err >= 0)
++		i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP1;
++	/* check for additional temperature sensors */
++	err = i8k_get_temp_type(1);
++	if (err >= 0)
++		i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP2;
++	err = i8k_get_temp_type(2);
++	if (err >= 0)
++		i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP3;
++	err = i8k_get_temp_type(3);
++	if (err >= 0)
++		i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4;
++
++	/* First fan attributes, if fan type is OK */
++	err = i8k_get_fan_type(0);
++	if (err >= 0)
++		i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1;
++
++	/* Second fan attributes, if fan type is OK */
++	err = i8k_get_fan_type(1);
++	if (err >= 0)
++		i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2;
++
++	i8k_hwmon_dev = hwmon_device_register_with_groups(NULL, "i8k", NULL,
++							  i8k_groups);
++	if (IS_ERR(i8k_hwmon_dev)) {
++		err = PTR_ERR(i8k_hwmon_dev);
++		i8k_hwmon_dev = NULL;
++		pr_err("hwmon registration failed (%d)\n", err);
++		return err;
++	}
++	return 0;
++}
++
++struct i8k_config_data {
++	uint fan_mult;
++	uint fan_max;
++};
++
++enum i8k_configs {
++	DELL_LATITUDE_D520,
++	DELL_PRECISION_490,
++	DELL_STUDIO,
++	DELL_XPS,
++};
++
++static const struct i8k_config_data i8k_config_data[] = {
++	[DELL_LATITUDE_D520] = {
++		.fan_mult = 1,
++		.fan_max = I8K_FAN_TURBO,
++	},
++	[DELL_PRECISION_490] = {
++		.fan_mult = 1,
++		.fan_max = I8K_FAN_TURBO,
++	},
++	[DELL_STUDIO] = {
++		.fan_mult = 1,
++		.fan_max = I8K_FAN_HIGH,
++	},
++	[DELL_XPS] = {
++		.fan_mult = 1,
++		.fan_max = I8K_FAN_HIGH,
++	},
++};
++
++static struct dmi_system_id i8k_dmi_table[] __initdata = {
++	{
++		.ident = "Dell Inspiron",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
++			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
++		},
++	},
++	{
++		.ident = "Dell Latitude",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
++			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
++		},
++	},
++	{
++		.ident = "Dell Inspiron 2",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
++		},
++	},
++	{
++		.ident = "Dell Latitude D520",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D520"),
++		},
++		.driver_data = (void *)&i8k_config_data[DELL_LATITUDE_D520],
++	},
++	{
++		.ident = "Dell Latitude 2",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
++		},
++	},
++	{	/* UK Inspiron 6400  */
++		.ident = "Dell Inspiron 3",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "MM061"),
++		},
++	},
++	{
++		.ident = "Dell Inspiron 3",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "MP061"),
++		},
++	},
++	{
++		.ident = "Dell Precision 490",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME,
++				  "Precision WorkStation 490"),
++		},
++		.driver_data = (void *)&i8k_config_data[DELL_PRECISION_490],
++	},
++	{
++		.ident = "Dell Precision",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "Precision"),
++		},
++	},
++	{
++		.ident = "Dell Vostro",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro"),
++		},
++	},
++	{
++		.ident = "Dell XPS421",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
++		},
++	},
++	{
++		.ident = "Dell Studio",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "Studio"),
++		},
++		.driver_data = (void *)&i8k_config_data[DELL_STUDIO],
++	},
++	{
++		.ident = "Dell XPS 13",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "XPS13"),
++		},
++		.driver_data = (void *)&i8k_config_data[DELL_XPS],
++	},
++	{
++		.ident = "Dell XPS M140",
++		.matches = {
++			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++			DMI_MATCH(DMI_PRODUCT_NAME, "MXC051"),
++		},
++		.driver_data = (void *)&i8k_config_data[DELL_XPS],
++	},
++	{ }
++};
++
++MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);
++
++/*
++ * Probe for the presence of a supported laptop.
++ */
++static int __init i8k_probe(void)
++{
++	const struct dmi_system_id *id;
++	int fan, ret;
++
++	/*
++	 * Get DMI information
++	 */
++	if (!dmi_check_system(i8k_dmi_table)) {
++		if (!ignore_dmi && !force)
++			return -ENODEV;
++
++		pr_info("not running on a supported Dell system.\n");
++		pr_info("vendor=%s, model=%s, version=%s\n",
++			i8k_get_dmi_data(DMI_SYS_VENDOR),
++			i8k_get_dmi_data(DMI_PRODUCT_NAME),
++			i8k_get_dmi_data(DMI_BIOS_VERSION));
++	}
++
++	strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION),
++		sizeof(bios_version));
++
++	/*
++	 * Get SMM Dell signature
++	 */
++	if (i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG1) &&
++	    i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG2)) {
++		pr_err("unable to get SMM Dell signature\n");
++		if (!force)
++			return -ENODEV;
++	}
++
++	/*
++	 * Set fan multiplier and maximal fan speed from dmi config
++	 * Values specified in module parameters override values from dmi
++	 */
++	id = dmi_first_match(i8k_dmi_table);
++	if (id && id->driver_data) {
++		const struct i8k_config_data *conf = id->driver_data;
++		if (!fan_mult && conf->fan_mult)
++			fan_mult = conf->fan_mult;
++		if (!fan_max && conf->fan_max)
++			fan_max = conf->fan_max;
++	}
++
++	i8k_fan_max = fan_max ? : I8K_FAN_HIGH;	/* Must not be 0 */
++	i8k_pwm_mult = DIV_ROUND_UP(255, i8k_fan_max);
++
++	if (!fan_mult) {
++		/*
++		 * Autodetect fan multiplier based on nominal rpm
++		 * If fan reports rpm value too high then set multiplier to 1
++		 */
++		for (fan = 0; fan < 2; ++fan) {
++			ret = i8k_get_fan_nominal_speed(fan, i8k_fan_max);
++			if (ret < 0)
++				continue;
++			if (ret > I8K_FAN_MAX_RPM)
++				i8k_fan_mult = 1;
++			break;
++		}
++	} else {
++		/* Fan multiplier was specified in module param or in dmi */
++		i8k_fan_mult = fan_mult;
++	}
++
++	return 0;
++}
++
++static int __init i8k_init(void)
++{
++	struct proc_dir_entry *proc_i8k;
++	int err;
++
++	/* Are we running on an supported laptop? */
++	if (i8k_probe())
++		return -ENODEV;
++
++	/* Register the proc entry */
++	proc_i8k = proc_create("i8k", 0, NULL, &i8k_fops);
++	if (!proc_i8k)
++		return -ENOENT;
++
++	err = i8k_init_hwmon();
++	if (err)
++		goto exit_remove_proc;
++
++	return 0;
++
++ exit_remove_proc:
++	remove_proc_entry("i8k", NULL);
++	return err;
++}
++
++static void __exit i8k_exit(void)
++{
++	hwmon_device_unregister(i8k_hwmon_dev);
++	remove_proc_entry("i8k", NULL);
++}
++
++module_init(i8k_init);
++module_exit(i8k_exit);
+-- 
+1.7.9.5
diff --git a/a/content_digest b/N1/content_digest
index f0ecf52..b06c53f 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -1,8 +1,8 @@
  "ref\01427538255-10860-1-git-send-email-pali.rohar@gmail.com\0"
  "ref\01427633859-18596-1-git-send-email-pali.rohar@gmail.com\0"
  "From\0Pali Roh\303\241r <pali.rohar@gmail.com>\0"
- "Subject\0[lm-sensors] [PATCH v2 1/2] hwmon: Rename i8k driver to dell-smm-hwmon and move it to hwmon tree\0"
- "Date\0Sun, 29 Mar 2015 12:57:38 +0000\0"
+ "Subject\0[PATCH v2 1/2] hwmon: Rename i8k driver to dell-smm-hwmon and move it to hwmon tree\0"
+ "Date\0Sun, 29 Mar 2015 14:57:38 +0200\0"
  "To\0Guenter Roeck <linux@roeck-us.net>"
   Arnd Bergmann <arnd@arndb.de>
   Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -16,929 +16,2090 @@
  " Pali Roh\303\241r <pali.rohar@gmail.com>\0"
  "\00:1\0"
  "b\0"
- "VGhpcyBjb21taXQgbW92ZXMgaThrIGRyaXZlciB0byBod21vbiB0cmVlIHVuZGVyIG5hbWUgZGVs\n"
- "bC1zbW0taHdtb24gd2hpY2ggaXMKYmV0dGVyIG5hbWUgdGhlbiBhYmJyZXZpYXRpb24gaThrLiBG\n"
- "b3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eSBpcyBhZGRlZCBtYWNybwpNT0RVTEVfQUxJQVMoImk4\n"
- "ayIpIHNvIG1vZHByb2JlIHdpbGwgbG9hZCBkcml2ZXIgYWxzbyBvbGQgbmFtZSBpOGsuIENPTkZJ\n"
- "R19JOEsKY29tcGlsZSBvcHRpb24gd2FzIG5vdCBjaGFuZ2VkLgoKVGhpcyBjb21taXQgYWxzbyBh\n"
- "ZGRzIG1lIGFzIG1haW50YWluZXIgb2YgdGhpcyBuZXcgZGVsbC1zbW0taHdtb24gZHJpdmVyIGFu\n"
- "ZApyZW1vdmUgR3VlbnRlciBSb2VjayBmcm9tIGxpc3Qgd2hvIGlzIGltcGxpY2l0IG1haW50YWlu\n"
- "ZXIgYWxsIGh3bW9uIGRyaXZlcnMuCgpTaWduZWQtb2ZmLWJ5OiBQYWxpIFJvaMOhciA8cGFsaS5y\n"
- "b2hhckBnbWFpbC5jb20+Ci0tLQogTUFJTlRBSU5FUlMgICAgICAgICAgICAgICAgICAgIHwgICAg\n"
- "NCArLQogZHJpdmVycy9jaGFyL01ha2VmaWxlICAgICAgICAgIHwgICAgMSAtCiBkcml2ZXJzL2No\n"
- "YXIvaThrLmMgICAgICAgICAgICAgfCAxMDA1IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t\n"
- "LS0tLS0tLS0tLQogZHJpdmVycy9od21vbi9NYWtlZmlsZSAgICAgICAgIHwgICAgMSArCiBkcml2\n"
- "ZXJzL2h3bW9uL2RlbGwtc21tLWh3bW9uLmMgfCAxMDA3ICsrKysrKysrKysrKysrKysrKysrKysr\n"
- "KysrKysrKysrKysrKysrKysKIDUgZmlsZXMgY2hhbmdlZCwgMTAxMCBpbnNlcnRpb25zKCspLCAx\n"
- "MDA4IGRlbGV0aW9ucygtKQogZGVsZXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvY2hhci9pOGsuYwog\n"
- "Y3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvaHdtb24vZGVsbC1zbW0taHdtb24uYwoKZGlmZiAt\n"
- "LWdpdCBhL01BSU5UQUlORVJTIGIvTUFJTlRBSU5FUlMKaW5kZXggODhjMDljYS4uZTU0YTA3ZSAx\n"
- "MDA2NDQKLS0tIGEvTUFJTlRBSU5FUlMKKysrIGIvTUFJTlRBSU5FUlMKQEAgLTMwNjMsOSArMzA2\n"
- "Myw5IEBAIFM6CU1haW50YWluZWQKIEY6CWRyaXZlcnMvcGxhdGZvcm0veDg2L2RlbGwtbGFwdG9w\n"
- "LmMKIAogREVMTCBMQVBUT1AgU01NIERSSVZFUgotTToJR3VlbnRlciBSb2VjayA8bGludXhAcm9l\n"
- "Y2stdXMubmV0PgorTToJUGFsaSBSb2jDoXIgPHBhbGkucm9oYXJAZ21haWwuY29tPgogUzoJTWFp\n"
- "bnRhaW5lZAotRjoJZHJpdmVycy9jaGFyL2k4ay5jCitGOglkcml2ZXJzL2h3bW9uL2RlbGwtc21t\n"
- "LWh3bW9uLmMKIEY6CWluY2x1ZGUvdWFwaS9saW51eC9pOGsuaAogCiBERUxMIFNZU1RFTVMgTUFO\n"
- "QUdFTUVOVCBCQVNFIERSSVZFUiAoZGNkYmFzKQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9jaGFyL01h\n"
- "a2VmaWxlIGIvZHJpdmVycy9jaGFyL01ha2VmaWxlCmluZGV4IGQwNmNkZTI2Li4xZDljZjAwIDEw\n"
- "MDY0NAotLS0gYS9kcml2ZXJzL2NoYXIvTWFrZWZpbGUKKysrIGIvZHJpdmVycy9jaGFyL01ha2Vm\n"
- "aWxlCkBAIC0zNiw3ICszNiw2IEBAIGVsc2UKICAgb2JqLSQoQ09ORklHX05WUkFNKQkrPSBudnJh\n"
- "bS5vCiBlbmRpZgogb2JqLSQoQ09ORklHX1RPU0hJQkEpCQkrPSB0b3NoaWJhLm8KLW9iai0kKENP\n"
- "TkZJR19JOEspCQkrPSBpOGsubwogb2JqLSQoQ09ORklHX0RTMTYyMCkJCSs9IGRzMTYyMC5vCiBv\n"
- "YmotJChDT05GSUdfSFdfUkFORE9NKQkJKz0gaHdfcmFuZG9tLwogb2JqLSQoQ09ORklHX1BQREVW\n"
- "KQkJKz0gcHBkZXYubwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9jaGFyL2k4ay5jIGIvZHJpdmVycy9j\n"
- "aGFyL2k4ay5jCmRlbGV0ZWQgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAyNGNjNGVkLi4wMDAwMDAw\n"
- "Ci0tLSBhL2RyaXZlcnMvY2hhci9pOGsuYworKysgL2Rldi9udWxsCkBAIC0xLDEwMDUgKzAsMCBA\n"
- "QAotLyoKLSAqIGk4ay5jIC0tIExpbnV4IGRyaXZlciBmb3IgYWNjZXNzaW5nIHRoZSBTTU0gQklP\n"
- "UyBvbiBEZWxsIGxhcHRvcHMuCi0gKgotICogQ29weXJpZ2h0IChDKSAyMDAxICBNYXNzaW1vIERh\n"
- "bCBab3R0byA8ZHpAZGViaWFuLm9yZz4KLSAqCi0gKiBId21vbiBpbnRlZ3JhdGlvbjoKLSAqIENv\n"
- "cHlyaWdodCAoQykgMjAxMSAgSmVhbiBEZWx2YXJlIDxqZGVsdmFyZUBzdXNlLmRlPgotICogQ29w\n"
- "eXJpZ2h0IChDKSAyMDEzLCAyMDE0ICBHdWVudGVyIFJvZWNrIDxsaW51eEByb2Vjay11cy5uZXQ+\n"
- "Ci0gKiBDb3B5cmlnaHQgKEMpIDIwMTQgIFBhbGkgUm9ow6FyIDxwYWxpLnJvaGFyQGdtYWlsLmNv\n"
- "bT4KLSAqCi0gKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3Ry\n"
- "aWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdAotICogdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUg\n"
- "R2VuZXJhbCBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlCi0gKiBGcmVlIFNvZnR3\n"
- "YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDIsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55\n"
- "Ci0gKiBsYXRlciB2ZXJzaW9uLgotICoKLSAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBp\n"
- "biB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQKLSAqIFdJVEhPVVQgQU5ZIFdB\n"
- "UlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKLSAqIE1FUkNIQU5U\n"
- "QUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05V\n"
- "Ci0gKiBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuCi0gKi8KLQotI2Rl\n"
- "ZmluZSBwcl9mbXQoZm10KSBLQlVJTERfTU9ETkFNRSAiOiAiIGZtdAotCi0jaW5jbHVkZSA8bGlu\n"
- "dXgvZGVsYXkuaD4KLSNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KLSNpbmNsdWRlIDxsaW51eC90\n"
- "eXBlcy5oPgotI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KLSNpbmNsdWRlIDxsaW51eC9wcm9jX2Zz\n"
- "Lmg+Ci0jaW5jbHVkZSA8bGludXgvc2VxX2ZpbGUuaD4KLSNpbmNsdWRlIDxsaW51eC9kbWkuaD4K\n"
- "LSNpbmNsdWRlIDxsaW51eC9jYXBhYmlsaXR5Lmg+Ci0jaW5jbHVkZSA8bGludXgvbXV0ZXguaD4K\n"
- "LSNpbmNsdWRlIDxsaW51eC9od21vbi5oPgotI2luY2x1ZGUgPGxpbnV4L2h3bW9uLXN5c2ZzLmg+\n"
- "Ci0jaW5jbHVkZSA8bGludXgvdWFjY2Vzcy5oPgotI2luY2x1ZGUgPGxpbnV4L2lvLmg+Ci0jaW5j\n"
- "bHVkZSA8bGludXgvc2NoZWQuaD4KLQotI2luY2x1ZGUgPGxpbnV4L2k4ay5oPgotCi0jZGVmaW5l\n"
- "IEk4S19TTU1fRk5fU1RBVFVTCTB4MDAyNQotI2RlZmluZSBJOEtfU01NX1BPV0VSX1NUQVRVUwkw\n"
- "eDAwNjkKLSNkZWZpbmUgSThLX1NNTV9TRVRfRkFOCQkweDAxYTMKLSNkZWZpbmUgSThLX1NNTV9H\n"
- "RVRfRkFOCQkweDAwYTMKLSNkZWZpbmUgSThLX1NNTV9HRVRfU1BFRUQJMHgwMmEzCi0jZGVmaW5l\n"
- "IEk4S19TTU1fR0VUX0ZBTl9UWVBFCTB4MDNhMwotI2RlZmluZSBJOEtfU01NX0dFVF9OT01fU1BF\n"
- "RUQJMHgwNGEzCi0jZGVmaW5lIEk4S19TTU1fR0VUX1RFTVAJMHgxMGEzCi0jZGVmaW5lIEk4S19T\n"
- "TU1fR0VUX1RFTVBfVFlQRQkweDExYTMKLSNkZWZpbmUgSThLX1NNTV9HRVRfREVMTF9TSUcxCTB4\n"
- "ZmVhMwotI2RlZmluZSBJOEtfU01NX0dFVF9ERUxMX1NJRzIJMHhmZmEzCi0KLSNkZWZpbmUgSThL\n"
- "X0ZBTl9NVUxUCQkzMAotI2RlZmluZSBJOEtfRkFOX01BWF9SUE0JCTMwMDAwCi0jZGVmaW5lIEk4\n"
- "S19NQVhfVEVNUAkJMTI3Ci0KLSNkZWZpbmUgSThLX0ZOX05PTkUJCTB4MDAKLSNkZWZpbmUgSThL\n"
- "X0ZOX1VQCQkweDAxCi0jZGVmaW5lIEk4S19GTl9ET1dOCQkweDAyCi0jZGVmaW5lIEk4S19GTl9N\n"
- "VVRFCQkweDA0Ci0jZGVmaW5lIEk4S19GTl9NQVNLCQkweDA3Ci0jZGVmaW5lIEk4S19GTl9TSElG\n"
- "VAkJOAotCi0jZGVmaW5lIEk4S19QT1dFUl9BQwkJMHgwNQotI2RlZmluZSBJOEtfUE9XRVJfQkFU\n"
- "VEVSWQkweDAxCi0KLXN0YXRpYyBERUZJTkVfTVVURVgoaThrX211dGV4KTsKLXN0YXRpYyBjaGFy\n"
- "IGJpb3NfdmVyc2lvbls0XTsKLXN0YXRpYyBzdHJ1Y3QgZGV2aWNlICppOGtfaHdtb25fZGV2Owot\n"
- "c3RhdGljIHUzMiBpOGtfaHdtb25fZmxhZ3M7Ci1zdGF0aWMgdWludCBpOGtfZmFuX211bHQgPSBJ\n"
- "OEtfRkFOX01VTFQ7Ci1zdGF0aWMgdWludCBpOGtfcHdtX211bHQ7Ci1zdGF0aWMgdWludCBpOGtf\n"
- "ZmFuX21heCA9IEk4S19GQU5fSElHSDsKLQotI2RlZmluZSBJOEtfSFdNT05fSEFWRV9URU1QMQko\n"
- "MSA8PCAwKQotI2RlZmluZSBJOEtfSFdNT05fSEFWRV9URU1QMgkoMSA8PCAxKQotI2RlZmluZSBJ\n"
- "OEtfSFdNT05fSEFWRV9URU1QMwkoMSA8PCAyKQotI2RlZmluZSBJOEtfSFdNT05fSEFWRV9URU1Q\n"
- "NAkoMSA8PCAzKQotI2RlZmluZSBJOEtfSFdNT05fSEFWRV9GQU4xCSgxIDw8IDQpCi0jZGVmaW5l\n"
- "IEk4S19IV01PTl9IQVZFX0ZBTjIJKDEgPDwgNSkKLQotTU9EVUxFX0FVVEhPUigiTWFzc2ltbyBE\n"
- "YWwgWm90dG8gKGR6QGRlYmlhbi5vcmcpIik7Ci1NT0RVTEVfREVTQ1JJUFRJT04oIkRyaXZlciBm\n"
- "b3IgYWNjZXNzaW5nIFNNTSBCSU9TIG9uIERlbGwgbGFwdG9wcyIpOwotTU9EVUxFX0xJQ0VOU0Uo\n"
- "IkdQTCIpOwotCi1zdGF0aWMgYm9vbCBmb3JjZTsKLW1vZHVsZV9wYXJhbShmb3JjZSwgYm9vbCwg\n"
- "MCk7Ci1NT0RVTEVfUEFSTV9ERVNDKGZvcmNlLCAiRm9yY2UgbG9hZGluZyB3aXRob3V0IGNoZWNr\n"
- "aW5nIGZvciBzdXBwb3J0ZWQgbW9kZWxzIik7Ci0KLXN0YXRpYyBib29sIGlnbm9yZV9kbWk7Ci1t\n"
- "b2R1bGVfcGFyYW0oaWdub3JlX2RtaSwgYm9vbCwgMCk7Ci1NT0RVTEVfUEFSTV9ERVNDKGlnbm9y\n"
- "ZV9kbWksICJDb250aW51ZSBwcm9iaW5nIGhhcmR3YXJlIGV2ZW4gaWYgRE1JIGRhdGEgZG9lcyBu\n"
- "b3QgbWF0Y2giKTsKLQotc3RhdGljIGJvb2wgcmVzdHJpY3RlZDsKLW1vZHVsZV9wYXJhbShyZXN0\n"
- "cmljdGVkLCBib29sLCAwKTsKLU1PRFVMRV9QQVJNX0RFU0MocmVzdHJpY3RlZCwgIkFsbG93IGZh\n"
- "biBjb250cm9sIGlmIFNZU19BRE1JTiBjYXBhYmlsaXR5IHNldCIpOwotCi1zdGF0aWMgYm9vbCBw\n"
- "b3dlcl9zdGF0dXM7Ci1tb2R1bGVfcGFyYW0ocG93ZXJfc3RhdHVzLCBib29sLCAwNjAwKTsKLU1P\n"
- "RFVMRV9QQVJNX0RFU0MocG93ZXJfc3RhdHVzLCAiUmVwb3J0IHBvd2VyIHN0YXR1cyBpbiAvcHJv\n"
- "Yy9pOGsiKTsKLQotc3RhdGljIHVpbnQgZmFuX211bHQ7Ci1tb2R1bGVfcGFyYW0oZmFuX211bHQs\n"
- "IHVpbnQsIDApOwotTU9EVUxFX1BBUk1fREVTQyhmYW5fbXVsdCwgIkZhY3RvciB0byBtdWx0aXBs\n"
- "eSBmYW4gc3BlZWQgd2l0aCAoZGVmYXVsdDogYXV0b2RldGVjdCkiKTsKLQotc3RhdGljIHVpbnQg\n"
- "ZmFuX21heDsKLW1vZHVsZV9wYXJhbShmYW5fbWF4LCB1aW50LCAwKTsKLU1PRFVMRV9QQVJNX0RF\n"
- "U0MoZmFuX21heCwgIk1heGltdW0gY29uZmlndXJhYmxlIGZhbiBzcGVlZCAoZGVmYXVsdDogYXV0\n"
- "b2RldGVjdCkiKTsKLQotc3RhdGljIGludCBpOGtfb3Blbl9mcyhzdHJ1Y3QgaW5vZGUgKmlub2Rl\n"
- "LCBzdHJ1Y3QgZmlsZSAqZmlsZSk7Ci1zdGF0aWMgbG9uZyBpOGtfaW9jdGwoc3RydWN0IGZpbGUg\n"
- "KiwgdW5zaWduZWQgaW50LCB1bnNpZ25lZCBsb25nKTsKLQotc3RhdGljIGNvbnN0IHN0cnVjdCBm\n"
- "aWxlX29wZXJhdGlvbnMgaThrX2ZvcHMgPSB7Ci0JLm93bmVyCQk9IFRISVNfTU9EVUxFLAotCS5v\n"
- "cGVuCQk9IGk4a19vcGVuX2ZzLAotCS5yZWFkCQk9IHNlcV9yZWFkLAotCS5sbHNlZWsJCT0gc2Vx\n"
- "X2xzZWVrLAotCS5yZWxlYXNlCT0gc2luZ2xlX3JlbGVhc2UsCi0JLnVubG9ja2VkX2lvY3RsCT0g\n"
- "aThrX2lvY3RsLAotfTsKLQotc3RydWN0IHNtbV9yZWdzIHsKLQl1bnNpZ25lZCBpbnQgZWF4Owot\n"
- "CXVuc2lnbmVkIGludCBlYnggX19wYWNrZWQ7Ci0JdW5zaWduZWQgaW50IGVjeCBfX3BhY2tlZDsK\n"
- "LQl1bnNpZ25lZCBpbnQgZWR4IF9fcGFja2VkOwotCXVuc2lnbmVkIGludCBlc2kgX19wYWNrZWQ7\n"
- "Ci0JdW5zaWduZWQgaW50IGVkaSBfX3BhY2tlZDsKLX07Ci0KLXN0YXRpYyBpbmxpbmUgY29uc3Qg\n"
- "Y2hhciAqaThrX2dldF9kbWlfZGF0YShpbnQgZmllbGQpCi17Ci0JY29uc3QgY2hhciAqZG1pX2Rh\n"
- "dGEgPSBkbWlfZ2V0X3N5c3RlbV9pbmZvKGZpZWxkKTsKLQotCXJldHVybiBkbWlfZGF0YSAmJiAq\n"
- "ZG1pX2RhdGEgPyBkbWlfZGF0YSA6ICI/IjsKLX0KLQotLyoKLSAqIENhbGwgdGhlIFN5c3RlbSBN\n"
- "YW5hZ2VtZW50IE1vZGUgQklPUy4gQ29kZSBwcm92aWRlZCBieSBKb25hdGhhbiBCdXp6YXJkLgot\n"
- "ICovCi1zdGF0aWMgaW50IGk4a19zbW0oc3RydWN0IHNtbV9yZWdzICpyZWdzKQotewotCWludCBy\n"
- "YzsKLQlpbnQgZWF4ID0gcmVncy0+ZWF4OwotCWNwdW1hc2tfdmFyX3Qgb2xkX21hc2s7Ci0KLQkv\n"
- "KiBTTU0gcmVxdWlyZXMgQ1BVIDAgKi8KLQlpZiAoIWFsbG9jX2NwdW1hc2tfdmFyKCZvbGRfbWFz\n"
- "aywgR0ZQX0tFUk5FTCkpCi0JCXJldHVybiAtRU5PTUVNOwotCWNwdW1hc2tfY29weShvbGRfbWFz\n"
- "aywgJmN1cnJlbnQtPmNwdXNfYWxsb3dlZCk7Ci0JcmMgPSBzZXRfY3B1c19hbGxvd2VkX3B0cihj\n"
- "dXJyZW50LCBjcHVtYXNrX29mKDApKTsKLQlpZiAocmMpCi0JCWdvdG8gb3V0OwotCWlmIChzbXBf\n"
- "cHJvY2Vzc29yX2lkKCkgIT0gMCkgewotCQlyYyA9IC1FQlVTWTsKLQkJZ290byBvdXQ7Ci0JfQot\n"
- "Ci0jaWYgZGVmaW5lZChDT05GSUdfWDg2XzY0KQotCWFzbSB2b2xhdGlsZSgicHVzaHEgJSVyYXhc\n"
- "blx0IgotCQkibW92bCAwKCUlcmF4KSwlJWVkeFxuXHQiCi0JCSJwdXNocSAlJXJkeFxuXHQiCi0J\n"
- "CSJtb3ZsIDQoJSVyYXgpLCUlZWJ4XG5cdCIKLQkJIm1vdmwgOCglJXJheCksJSVlY3hcblx0Igot\n"
- "CQkibW92bCAxMiglJXJheCksJSVlZHhcblx0IgotCQkibW92bCAxNiglJXJheCksJSVlc2lcblx0\n"
- "IgotCQkibW92bCAyMCglJXJheCksJSVlZGlcblx0IgotCQkicG9wcSAlJXJheFxuXHQiCi0JCSJv\n"
- "dXQgJSVhbCwkMHhiMlxuXHQiCi0JCSJvdXQgJSVhbCwkMHg4NFxuXHQiCi0JCSJ4Y2hncSAlJXJh\n"
- "eCwoJSVyc3ApXG5cdCIKLQkJIm1vdmwgJSVlYngsNCglJXJheClcblx0IgotCQkibW92bCAlJWVj\n"
- "eCw4KCUlcmF4KVxuXHQiCi0JCSJtb3ZsICUlZWR4LDEyKCUlcmF4KVxuXHQiCi0JCSJtb3ZsICUl\n"
- "ZXNpLDE2KCUlcmF4KVxuXHQiCi0JCSJtb3ZsICUlZWRpLDIwKCUlcmF4KVxuXHQiCi0JCSJwb3Bx\n"
- "ICUlcmR4XG5cdCIKLQkJIm1vdmwgJSVlZHgsMCglJXJheClcblx0IgotCQkicHVzaGZxXG5cdCIK\n"
- "LQkJInBvcHEgJSVyYXhcblx0IgotCQkiYW5kbCAkMSwlJWVheFxuIgotCQk6ICI9YSIocmMpCi0J\n"
- "CTogICAgImEiKHJlZ3MpCi0JCTogICAgIiVlYngiLCAiJWVjeCIsICIlZWR4IiwgIiVlc2kiLCAi\n"
- "JWVkaSIsICJtZW1vcnkiKTsKLSNlbHNlCi0JYXNtIHZvbGF0aWxlKCJwdXNobCAlJWVheFxuXHQi\n"
- "Ci0JICAgICJtb3ZsIDAoJSVlYXgpLCUlZWR4XG5cdCIKLQkgICAgInB1c2ggJSVlZHhcblx0Igot\n"
- "CSAgICAibW92bCA0KCUlZWF4KSwlJWVieFxuXHQiCi0JICAgICJtb3ZsIDgoJSVlYXgpLCUlZWN4\n"
- "XG5cdCIKLQkgICAgIm1vdmwgMTIoJSVlYXgpLCUlZWR4XG5cdCIKLQkgICAgIm1vdmwgMTYoJSVl\n"
- "YXgpLCUlZXNpXG5cdCIKLQkgICAgIm1vdmwgMjAoJSVlYXgpLCUlZWRpXG5cdCIKLQkgICAgInBv\n"
- "cGwgJSVlYXhcblx0IgotCSAgICAib3V0ICUlYWwsJDB4YjJcblx0IgotCSAgICAib3V0ICUlYWws\n"
- "JDB4ODRcblx0IgotCSAgICAieGNoZ2wgJSVlYXgsKCUlZXNwKVxuXHQiCi0JICAgICJtb3ZsICUl\n"
- "ZWJ4LDQoJSVlYXgpXG5cdCIKLQkgICAgIm1vdmwgJSVlY3gsOCglJWVheClcblx0IgotCSAgICAi\n"
- "bW92bCAlJWVkeCwxMiglJWVheClcblx0IgotCSAgICAibW92bCAlJWVzaSwxNiglJWVheClcblx0\n"
- "IgotCSAgICAibW92bCAlJWVkaSwyMCglJWVheClcblx0IgotCSAgICAicG9wbCAlJWVkeFxuXHQi\n"
- "Ci0JICAgICJtb3ZsICUlZWR4LDAoJSVlYXgpXG5cdCIKLQkgICAgImxhaGZcblx0IgotCSAgICAi\n"
- "c2hybCAkOCwlJWVheFxuXHQiCi0JICAgICJhbmRsICQxLCUlZWF4XG4iCi0JICAgIDogIj1hIihy\n"
- "YykKLQkgICAgOiAgICAiYSIocmVncykKLQkgICAgOiAgICAiJWVieCIsICIlZWN4IiwgIiVlZHgi\n"
- "LCAiJWVzaSIsICIlZWRpIiwgIm1lbW9yeSIpOwotI2VuZGlmCi0JaWYgKHJjICE9IDAgfHwgKHJl\n"
- "Z3MtPmVheCAmIDB4ZmZmZikgPT0gMHhmZmZmIHx8IHJlZ3MtPmVheCA9PSBlYXgpCi0JCXJjID0g\n"
- "LUVJTlZBTDsKLQotb3V0OgotCXNldF9jcHVzX2FsbG93ZWRfcHRyKGN1cnJlbnQsIG9sZF9tYXNr\n"
- "KTsKLQlmcmVlX2NwdW1hc2tfdmFyKG9sZF9tYXNrKTsKLQlyZXR1cm4gcmM7Ci19Ci0KLS8qCi0g\n"
- "KiBSZWFkIHRoZSBGbiBrZXkgc3RhdHVzLgotICovCi1zdGF0aWMgaW50IGk4a19nZXRfZm5fc3Rh\n"
- "dHVzKHZvaWQpCi17Ci0Jc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01NX0ZO\n"
- "X1NUQVRVUywgfTsKLQlpbnQgcmM7Ci0KLQlyYyA9IGk4a19zbW0oJnJlZ3MpOwotCWlmIChyYyA8\n"
- "IDApCi0JCXJldHVybiByYzsKLQotCXN3aXRjaCAoKHJlZ3MuZWF4ID4+IEk4S19GTl9TSElGVCkg\n"
- "JiBJOEtfRk5fTUFTSykgewotCWNhc2UgSThLX0ZOX1VQOgotCQlyZXR1cm4gSThLX1ZPTF9VUDsK\n"
- "LQljYXNlIEk4S19GTl9ET1dOOgotCQlyZXR1cm4gSThLX1ZPTF9ET1dOOwotCWNhc2UgSThLX0ZO\n"
- "X01VVEU6Ci0JCXJldHVybiBJOEtfVk9MX01VVEU7Ci0JZGVmYXVsdDoKLQkJcmV0dXJuIDA7Ci0J\n"
- "fQotfQotCi0vKgotICogUmVhZCB0aGUgcG93ZXIgc3RhdHVzLgotICovCi1zdGF0aWMgaW50IGk4\n"
- "a19nZXRfcG93ZXJfc3RhdHVzKHZvaWQpCi17Ci0Jc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5l\n"
- "YXggPSBJOEtfU01NX1BPV0VSX1NUQVRVUywgfTsKLQlpbnQgcmM7Ci0KLQlyYyA9IGk4a19zbW0o\n"
- "JnJlZ3MpOwotCWlmIChyYyA8IDApCi0JCXJldHVybiByYzsKLQotCXJldHVybiAocmVncy5lYXgg\n"
- "JiAweGZmKSA9PSBJOEtfUE9XRVJfQUMgPyBJOEtfQUMgOiBJOEtfQkFUVEVSWTsKLX0KLQotLyoK\n"
- "LSAqIFJlYWQgdGhlIGZhbiBzdGF0dXMuCi0gKi8KLXN0YXRpYyBpbnQgaThrX2dldF9mYW5fc3Rh\n"
- "dHVzKGludCBmYW4pCi17Ci0Jc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01N\n"
- "X0dFVF9GQU4sIH07Ci0KLQlyZWdzLmVieCA9IGZhbiAmIDB4ZmY7Ci0JcmV0dXJuIGk4a19zbW0o\n"
- "JnJlZ3MpID8gOiByZWdzLmVheCAmIDB4ZmY7Ci19Ci0KLS8qCi0gKiBSZWFkIHRoZSBmYW4gc3Bl\n"
- "ZWQgaW4gUlBNLgotICovCi1zdGF0aWMgaW50IGk4a19nZXRfZmFuX3NwZWVkKGludCBmYW4pCi17\n"
- "Ci0Jc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01NX0dFVF9TUEVFRCwgfTsK\n"
- "LQotCXJlZ3MuZWJ4ID0gZmFuICYgMHhmZjsKLQlyZXR1cm4gaThrX3NtbSgmcmVncykgPyA6IChy\n"
- "ZWdzLmVheCAmIDB4ZmZmZikgKiBpOGtfZmFuX211bHQ7Ci19Ci0KLS8qCi0gKiBSZWFkIHRoZSBm\n"
- "YW4gdHlwZS4KLSAqLwotc3RhdGljIGludCBpOGtfZ2V0X2Zhbl90eXBlKGludCBmYW4pCi17Ci0J\n"
- "c3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01NX0dFVF9GQU5fVFlQRSwgfTsK\n"
- "LQotCXJlZ3MuZWJ4ID0gZmFuICYgMHhmZjsKLQlyZXR1cm4gaThrX3NtbSgmcmVncykgPyA6IHJl\n"
- "Z3MuZWF4ICYgMHhmZjsKLX0KLQotLyoKLSAqIFJlYWQgdGhlIGZhbiBub21pbmFsIHJwbSBmb3Ig\n"
- "c3BlY2lmaWMgZmFuIHNwZWVkLgotICovCi1zdGF0aWMgaW50IGk4a19nZXRfZmFuX25vbWluYWxf\n"
- "c3BlZWQoaW50IGZhbiwgaW50IHNwZWVkKQotewotCXN0cnVjdCBzbW1fcmVncyByZWdzID0geyAu\n"
- "ZWF4ID0gSThLX1NNTV9HRVRfTk9NX1NQRUVELCB9OwotCi0JcmVncy5lYnggPSAoZmFuICYgMHhm\n"
- "ZikgfCAoc3BlZWQgPDwgOCk7Ci0JcmV0dXJuIGk4a19zbW0oJnJlZ3MpID8gOiAocmVncy5lYXgg\n"
- "JiAweGZmZmYpICogaThrX2Zhbl9tdWx0OwotfQotCi0vKgotICogU2V0IHRoZSBmYW4gc3BlZWQg\n"
- "KG9mZiwgbG93LCBoaWdoKS4gUmV0dXJucyB0aGUgbmV3IGZhbiBzdGF0dXMuCi0gKi8KLXN0YXRp\n"
- "YyBpbnQgaThrX3NldF9mYW4oaW50IGZhbiwgaW50IHNwZWVkKQotewotCXN0cnVjdCBzbW1fcmVn\n"
- "cyByZWdzID0geyAuZWF4ID0gSThLX1NNTV9TRVRfRkFOLCB9OwotCi0Jc3BlZWQgPSAoc3BlZWQg\n"
- "PCAwKSA/IDAgOiAoKHNwZWVkID4gaThrX2Zhbl9tYXgpID8gaThrX2Zhbl9tYXggOiBzcGVlZCk7\n"
- "Ci0JcmVncy5lYnggPSAoZmFuICYgMHhmZikgfCAoc3BlZWQgPDwgOCk7Ci0KLQlyZXR1cm4gaThr\n"
- "X3NtbSgmcmVncykgPyA6IGk4a19nZXRfZmFuX3N0YXR1cyhmYW4pOwotfQotCi1zdGF0aWMgaW50\n"
- "IGk4a19nZXRfdGVtcF90eXBlKGludCBzZW5zb3IpCi17Ci0Jc3RydWN0IHNtbV9yZWdzIHJlZ3Mg\n"
- "PSB7IC5lYXggPSBJOEtfU01NX0dFVF9URU1QX1RZUEUsIH07Ci0KLQlyZWdzLmVieCA9IHNlbnNv\n"
- "ciAmIDB4ZmY7Ci0JcmV0dXJuIGk4a19zbW0oJnJlZ3MpID8gOiByZWdzLmVheCAmIDB4ZmY7Ci19\n"
- "Ci0KLS8qCi0gKiBSZWFkIHRoZSBjcHUgdGVtcGVyYXR1cmUuCi0gKi8KLXN0YXRpYyBpbnQgX2k4\n"
- "a19nZXRfdGVtcChpbnQgc2Vuc29yKQotewotCXN0cnVjdCBzbW1fcmVncyByZWdzID0gewotCQku\n"
- "ZWF4ID0gSThLX1NNTV9HRVRfVEVNUCwKLQkJLmVieCA9IHNlbnNvciAmIDB4ZmYsCi0JfTsKLQot\n"
- "CXJldHVybiBpOGtfc21tKCZyZWdzKSA/IDogcmVncy5lYXggJiAweGZmOwotfQotCi1zdGF0aWMg\n"
- "aW50IGk4a19nZXRfdGVtcChpbnQgc2Vuc29yKQotewotCWludCB0ZW1wID0gX2k4a19nZXRfdGVt\n"
- "cChzZW5zb3IpOwotCi0JLyoKLQkgKiBTb21ldGltZXMgdGhlIHRlbXBlcmF0dXJlIHNlbnNvciBy\n"
- "ZXR1cm5zIDB4OTksIHdoaWNoIGlzIG91dCBvZiByYW5nZS4KLQkgKiBJbiB0aGlzIGNhc2Ugd2Ug\n"
- "cmV0cnkgKG9uY2UpIGJlZm9yZSByZXR1cm5pbmcgYW4gZXJyb3IuCi0JICMgMTAwMzY1NTEzNyAw\n"
- "MDAwMDA1OCAwMDAwNWE0YgotCSAjIDEwMDM2NTUxMzggMDAwMDAwOTkgMDAwMDNhODAgPC0tLSAw\n"
- "eDk5ID0gMTUzIGRlZ3JlZXMKLQkgIyAxMDAzNjU1MTM5IDAwMDAwMDU0IDAwMDA1YzUyCi0JICov\n"
- "Ci0JaWYgKHRlbXAgPT0gMHg5OSkgewotCQltc2xlZXAoMTAwKTsKLQkJdGVtcCA9IF9pOGtfZ2V0\n"
- "X3RlbXAoc2Vuc29yKTsKLQl9Ci0JLyoKLQkgKiBSZXR1cm4gLUVOT0RBVEEgZm9yIGFsbCBpbnZh\n"
- "bGlkIHRlbXBlcmF0dXJlcy4KLQkgKgotCSAqIEtub3duIGluc3RhbmNlcyBhcmUgdGhlIDB4OTkg\n"
- "dmFsdWUgYXMgc2VlbiBhYm92ZSBhcyB3ZWxsIGFzCi0JICogMHhjMSAoMTkzKSwgd2hpY2ggbWF5\n"
- "IGJlIHJldHVybmVkIHdoZW4gdHJ5aW5nIHRvIHJlYWQgdGhlIEdQVQotCSAqIHRlbXBlcmF0dXJl\n"
- "IGlmIHRoZSBzeXN0ZW0gc3VwcG9ydHMgYSBHUFUgYW5kIGl0IGlzIGN1cnJlbnRseQotCSAqIHR1\n"
- "cm5lZCBvZmYuCi0JICovCi0JaWYgKHRlbXAgPiBJOEtfTUFYX1RFTVApCi0JCXJldHVybiAtRU5P\n"
- "REFUQTsKLQotCXJldHVybiB0ZW1wOwotfQotCi1zdGF0aWMgaW50IGk4a19nZXRfZGVsbF9zaWdu\n"
- "YXR1cmUoaW50IHJlcV9mbikKLXsKLQlzdHJ1Y3Qgc21tX3JlZ3MgcmVncyA9IHsgLmVheCA9IHJl\n"
- "cV9mbiwgfTsKLQlpbnQgcmM7Ci0KLQlyYyA9IGk4a19zbW0oJnJlZ3MpOwotCWlmIChyYyA8IDAp\n"
- "Ci0JCXJldHVybiByYzsKLQotCXJldHVybiByZWdzLmVheCA9PSAxMTQ1NjUxNTI3ICYmIHJlZ3Mu\n"
- "ZWR4ID09IDExNDUzOTIyMDQgPyAwIDogLTE7Ci19Ci0KLXN0YXRpYyBpbnQKLWk4a19pb2N0bF91\n"
- "bmxvY2tlZChzdHJ1Y3QgZmlsZSAqZnAsIHVuc2lnbmVkIGludCBjbWQsIHVuc2lnbmVkIGxvbmcg\n"
- "YXJnKQotewotCWludCB2YWwgPSAwOwotCWludCBzcGVlZDsKLQl1bnNpZ25lZCBjaGFyIGJ1ZmZb\n"
- "MTZdOwotCWludCBfX3VzZXIgKmFyZ3AgPSAoaW50IF9fdXNlciAqKWFyZzsKLQotCWlmICghYXJn\n"
- "cCkKLQkJcmV0dXJuIC1FSU5WQUw7Ci0KLQlzd2l0Y2ggKGNtZCkgewotCWNhc2UgSThLX0JJT1Nf\n"
- "VkVSU0lPTjoKLQkJdmFsID0gKGJpb3NfdmVyc2lvblswXSA8PCAxNikgfAotCQkJCShiaW9zX3Zl\n"
- "cnNpb25bMV0gPDwgOCkgfCBiaW9zX3ZlcnNpb25bMl07Ci0JCWJyZWFrOwotCi0JY2FzZSBJOEtf\n"
- "TUFDSElORV9JRDoKLQkJbWVtc2V0KGJ1ZmYsIDAsIDE2KTsKLQkJc3RybGNweShidWZmLCBpOGtf\n"
- "Z2V0X2RtaV9kYXRhKERNSV9QUk9EVUNUX1NFUklBTCksCi0JCQlzaXplb2YoYnVmZikpOwotCQli\n"
- "cmVhazsKLQotCWNhc2UgSThLX0ZOX1NUQVRVUzoKLQkJdmFsID0gaThrX2dldF9mbl9zdGF0dXMo\n"
- "KTsKLQkJYnJlYWs7Ci0KLQljYXNlIEk4S19QT1dFUl9TVEFUVVM6Ci0JCXZhbCA9IGk4a19nZXRf\n"
- "cG93ZXJfc3RhdHVzKCk7Ci0JCWJyZWFrOwotCi0JY2FzZSBJOEtfR0VUX1RFTVA6Ci0JCXZhbCA9\n"
- "IGk4a19nZXRfdGVtcCgwKTsKLQkJYnJlYWs7Ci0KLQljYXNlIEk4S19HRVRfU1BFRUQ6Ci0JCWlm\n"
- "IChjb3B5X2Zyb21fdXNlcigmdmFsLCBhcmdwLCBzaXplb2YoaW50KSkpCi0JCQlyZXR1cm4gLUVG\n"
- "QVVMVDsKLQotCQl2YWwgPSBpOGtfZ2V0X2Zhbl9zcGVlZCh2YWwpOwotCQlicmVhazsKLQotCWNh\n"
- "c2UgSThLX0dFVF9GQU46Ci0JCWlmIChjb3B5X2Zyb21fdXNlcigmdmFsLCBhcmdwLCBzaXplb2Yo\n"
- "aW50KSkpCi0JCQlyZXR1cm4gLUVGQVVMVDsKLQotCQl2YWwgPSBpOGtfZ2V0X2Zhbl9zdGF0dXMo\n"
- "dmFsKTsKLQkJYnJlYWs7Ci0KLQljYXNlIEk4S19TRVRfRkFOOgotCQlpZiAocmVzdHJpY3RlZCAm\n"
- "JiAhY2FwYWJsZShDQVBfU1lTX0FETUlOKSkKLQkJCXJldHVybiAtRVBFUk07Ci0KLQkJaWYgKGNv\n"
- "cHlfZnJvbV91c2VyKCZ2YWwsIGFyZ3AsIHNpemVvZihpbnQpKSkKLQkJCXJldHVybiAtRUZBVUxU\n"
- "OwotCi0JCWlmIChjb3B5X2Zyb21fdXNlcigmc3BlZWQsIGFyZ3AgKyAxLCBzaXplb2YoaW50KSkp\n"
- "Ci0JCQlyZXR1cm4gLUVGQVVMVDsKLQotCQl2YWwgPSBpOGtfc2V0X2Zhbih2YWwsIHNwZWVkKTsK\n"
- "LQkJYnJlYWs7Ci0KLQlkZWZhdWx0OgotCQlyZXR1cm4gLUVJTlZBTDsKLQl9Ci0KLQlpZiAodmFs\n"
- "IDwgMCkKLQkJcmV0dXJuIHZhbDsKLQotCXN3aXRjaCAoY21kKSB7Ci0JY2FzZSBJOEtfQklPU19W\n"
- "RVJTSU9OOgotCQlpZiAoY29weV90b191c2VyKGFyZ3AsICZ2YWwsIDQpKQotCQkJcmV0dXJuIC1F\n"
- "RkFVTFQ7Ci0KLQkJYnJlYWs7Ci0JY2FzZSBJOEtfTUFDSElORV9JRDoKLQkJaWYgKGNvcHlfdG9f\n"
- "dXNlcihhcmdwLCBidWZmLCAxNikpCi0JCQlyZXR1cm4gLUVGQVVMVDsKLQotCQlicmVhazsKLQlk\n"
- "ZWZhdWx0OgotCQlpZiAoY29weV90b191c2VyKGFyZ3AsICZ2YWwsIHNpemVvZihpbnQpKSkKLQkJ\n"
- "CXJldHVybiAtRUZBVUxUOwotCi0JCWJyZWFrOwotCX0KLQotCXJldHVybiAwOwotfQotCi1zdGF0\n"
- "aWMgbG9uZyBpOGtfaW9jdGwoc3RydWN0IGZpbGUgKmZwLCB1bnNpZ25lZCBpbnQgY21kLCB1bnNp\n"
- "Z25lZCBsb25nIGFyZykKLXsKLQlsb25nIHJldDsKLQotCW11dGV4X2xvY2soJmk4a19tdXRleCk7\n"
- "Ci0JcmV0ID0gaThrX2lvY3RsX3VubG9ja2VkKGZwLCBjbWQsIGFyZyk7Ci0JbXV0ZXhfdW5sb2Nr\n"
- "KCZpOGtfbXV0ZXgpOwotCi0JcmV0dXJuIHJldDsKLX0KLQotLyoKLSAqIFByaW50IHRoZSBpbmZv\n"
- "cm1hdGlvbiBmb3IgL3Byb2MvaThrLgotICovCi1zdGF0aWMgaW50IGk4a19wcm9jX3Nob3coc3Ry\n"
- "dWN0IHNlcV9maWxlICpzZXEsIHZvaWQgKm9mZnNldCkKLXsKLQlpbnQgZm5fa2V5LCBjcHVfdGVt\n"
- "cCwgYWNfcG93ZXI7Ci0JaW50IGxlZnRfZmFuLCByaWdodF9mYW4sIGxlZnRfc3BlZWQsIHJpZ2h0\n"
- "X3NwZWVkOwotCi0JY3B1X3RlbXAJPSBpOGtfZ2V0X3RlbXAoMCk7CQkJLyogMTExMDAgwrVzICov\n"
- "Ci0JbGVmdF9mYW4JPSBpOGtfZ2V0X2Zhbl9zdGF0dXMoSThLX0ZBTl9MRUZUKTsJLyogICA1ODAg\n"
- "wrVzICovCi0JcmlnaHRfZmFuCT0gaThrX2dldF9mYW5fc3RhdHVzKEk4S19GQU5fUklHSFQpOwkv\n"
- "KiAgIDU4MCDCtXMgKi8KLQlsZWZ0X3NwZWVkCT0gaThrX2dldF9mYW5fc3BlZWQoSThLX0ZBTl9M\n"
- "RUZUKTsJLyogICA1ODAgwrVzICovCi0JcmlnaHRfc3BlZWQJPSBpOGtfZ2V0X2Zhbl9zcGVlZChJ\n"
- "OEtfRkFOX1JJR0hUKTsJLyogICA1ODAgwrVzICovCi0JZm5fa2V5CQk9IGk4a19nZXRfZm5fc3Rh\n"
- "dHVzKCk7CQkJLyogICA3NTAgwrVzICovCi0JaWYgKHBvd2VyX3N0YXR1cykKLQkJYWNfcG93ZXIg\n"
- "PSBpOGtfZ2V0X3Bvd2VyX3N0YXR1cygpOwkJLyogMTQ3MDAgwrVzICovCi0JZWxzZQotCQlhY19w\n"
- "b3dlciA9IC0xOwotCi0JLyoKLQkgKiBJbmZvOgotCSAqCi0JICogMSkgIEZvcm1hdCB2ZXJzaW9u\n"
- "ICh0aGlzIHdpbGwgY2hhbmdlIGlmIGZvcm1hdCBjaGFuZ2VzKQotCSAqIDIpICBCSU9TIHZlcnNp\n"
- "b24KLQkgKiAzKSAgQklPUyBtYWNoaW5lIElECi0JICogNCkgIENwdSB0ZW1wZXJhdHVyZQotCSAq\n"
- "IDUpICBMZWZ0IGZhbiBzdGF0dXMKLQkgKiA2KSAgUmlnaHQgZmFuIHN0YXR1cwotCSAqIDcpICBM\n"
- "ZWZ0IGZhbiBzcGVlZAotCSAqIDgpICBSaWdodCBmYW4gc3BlZWQKLQkgKiA5KSAgQUMgcG93ZXIK\n"
- "LQkgKiAxMCkgRm4gS2V5IHN0YXR1cwotCSAqLwotCXJldHVybiBzZXFfcHJpbnRmKHNlcSwgIiVz\n"
- "ICVzICVzICVkICVkICVkICVkICVkICVkICVkXG4iLAotCQkJICBJOEtfUFJPQ19GTVQsCi0JCQkg\n"
- "IGJpb3NfdmVyc2lvbiwKLQkJCSAgaThrX2dldF9kbWlfZGF0YShETUlfUFJPRFVDVF9TRVJJQUwp\n"
- "LAotCQkJICBjcHVfdGVtcCwKLQkJCSAgbGVmdF9mYW4sIHJpZ2h0X2ZhbiwgbGVmdF9zcGVlZCwg\n"
- "cmlnaHRfc3BlZWQsCi0JCQkgIGFjX3Bvd2VyLCBmbl9rZXkpOwotfQotCi1zdGF0aWMgaW50IGk4\n"
- "a19vcGVuX2ZzKHN0cnVjdCBpbm9kZSAqaW5vZGUsIHN0cnVjdCBmaWxlICpmaWxlKQotewotCXJl\n"
- "dHVybiBzaW5nbGVfb3BlbihmaWxlLCBpOGtfcHJvY19zaG93LCBOVUxMKTsKLX0KLQotCi0vKgot\n"
- "ICogSHdtb24gaW50ZXJmYWNlCi0gKi8KLQotc3RhdGljIHNzaXplX3QgaThrX2h3bW9uX3Nob3df\n"
- "dGVtcF9sYWJlbChzdHJ1Y3QgZGV2aWNlICpkZXYsCi0JCQkJCSBzdHJ1Y3QgZGV2aWNlX2F0dHJp\n"
- "YnV0ZSAqZGV2YXR0ciwKLQkJCQkJIGNoYXIgKmJ1ZikKLXsKLQlzdGF0aWMgY29uc3QgY2hhciAq\n"
- "IGNvbnN0IGxhYmVsc1tdID0gewotCQkiQ1BVIiwKLQkJIkdQVSIsCi0JCSJTT0RJTU0iLAotCQki\n"
- "T3RoZXIiLAotCQkiQW1iaWVudCIsCi0JCSJPdGhlciIsCi0JfTsKLQlpbnQgaW5kZXggPSB0b19z\n"
- "ZW5zb3JfZGV2X2F0dHIoZGV2YXR0ciktPmluZGV4OwotCWludCB0eXBlOwotCi0JdHlwZSA9IGk4\n"
- "a19nZXRfdGVtcF90eXBlKGluZGV4KTsKLQlpZiAodHlwZSA8IDApCi0JCXJldHVybiB0eXBlOwot\n"
- "CWlmICh0eXBlID49IEFSUkFZX1NJWkUobGFiZWxzKSkKLQkJdHlwZSA9IEFSUkFZX1NJWkUobGFi\n"
- "ZWxzKSAtIDE7Ci0JcmV0dXJuIHNwcmludGYoYnVmLCAiJXNcbiIsIGxhYmVsc1t0eXBlXSk7Ci19\n"
- "Ci0KLXN0YXRpYyBzc2l6ZV90IGk4a19od21vbl9zaG93X3RlbXAoc3RydWN0IGRldmljZSAqZGV2\n"
- "LAotCQkJCSAgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkZXZhdHRyLAotCQkJCSAgIGNoYXIg\n"
- "KmJ1ZikKLXsKLQlpbnQgaW5kZXggPSB0b19zZW5zb3JfZGV2X2F0dHIoZGV2YXR0ciktPmluZGV4\n"
- "OwotCWludCB0ZW1wOwotCi0JdGVtcCA9IGk4a19nZXRfdGVtcChpbmRleCk7Ci0JaWYgKHRlbXAg\n"
- "PCAwKQotCQlyZXR1cm4gdGVtcDsKLQlyZXR1cm4gc3ByaW50ZihidWYsICIlZFxuIiwgdGVtcCAq\n"
- "IDEwMDApOwotfQotCi1zdGF0aWMgc3NpemVfdCBpOGtfaHdtb25fc2hvd19mYW5fbGFiZWwoc3Ry\n"
- "dWN0IGRldmljZSAqZGV2LAotCQkJCQlzdHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZSAqZGV2YXR0ciwK\n"
- "LQkJCQkJY2hhciAqYnVmKQotewotCXN0YXRpYyBjb25zdCBjaGFyICogY29uc3QgbGFiZWxzW10g\n"
- "PSB7Ci0JCSJQcm9jZXNzb3IgRmFuIiwKLQkJIk1vdGhlcmJvYXJkIEZhbiIsCi0JCSJWaWRlbyBG\n"
- "YW4iLAotCQkiUG93ZXIgU3VwcGx5IEZhbiIsCi0JCSJDaGlwc2V0IEZhbiIsCi0JCSJPdGhlciBG\n"
- "YW4iLAotCX07Ci0JaW50IGluZGV4ID0gdG9fc2Vuc29yX2Rldl9hdHRyKGRldmF0dHIpLT5pbmRl\n"
- "eDsKLQlib29sIGRvY2sgPSBmYWxzZTsKLQlpbnQgdHlwZTsKLQotCXR5cGUgPSBpOGtfZ2V0X2Zh\n"
- "bl90eXBlKGluZGV4KTsKLQlpZiAodHlwZSA8IDApCi0JCXJldHVybiB0eXBlOwotCi0JaWYgKHR5\n"
- "cGUgJiAweDEwKSB7Ci0JCWRvY2sgPSB0cnVlOwotCQl0eXBlICY9IDB4MEY7Ci0JfQotCi0JaWYg\n"
- "KHR5cGUgPj0gQVJSQVlfU0laRShsYWJlbHMpKQotCQl0eXBlID0gKEFSUkFZX1NJWkUobGFiZWxz\n"
- "KSAtIDEpOwotCi0JcmV0dXJuIHNwcmludGYoYnVmLCAiJXMlc1xuIiwgKGRvY2sgPyAiRG9ja2lu\n"
- "ZyAiIDogIiIpLCBsYWJlbHNbdHlwZV0pOwotfQotCi1zdGF0aWMgc3NpemVfdCBpOGtfaHdtb25f\n"
- "c2hvd19mYW4oc3RydWN0IGRldmljZSAqZGV2LAotCQkJCSAgc3RydWN0IGRldmljZV9hdHRyaWJ1\n"
- "dGUgKmRldmF0dHIsCi0JCQkJICBjaGFyICpidWYpCi17Ci0JaW50IGluZGV4ID0gdG9fc2Vuc29y\n"
- "X2Rldl9hdHRyKGRldmF0dHIpLT5pbmRleDsKLQlpbnQgZmFuX3NwZWVkOwotCi0JZmFuX3NwZWVk\n"
- "ID0gaThrX2dldF9mYW5fc3BlZWQoaW5kZXgpOwotCWlmIChmYW5fc3BlZWQgPCAwKQotCQlyZXR1\n"
- "cm4gZmFuX3NwZWVkOwotCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiVkXG4iLCBmYW5fc3BlZWQpOwot\n"
- "fQotCi1zdGF0aWMgc3NpemVfdCBpOGtfaHdtb25fc2hvd19wd20oc3RydWN0IGRldmljZSAqZGV2\n"
- "LAotCQkJCSAgc3RydWN0IGRldmljZV9hdHRyaWJ1dGUgKmRldmF0dHIsCi0JCQkJICBjaGFyICpi\n"
- "dWYpCi17Ci0JaW50IGluZGV4ID0gdG9fc2Vuc29yX2Rldl9hdHRyKGRldmF0dHIpLT5pbmRleDsK\n"
- "LQlpbnQgc3RhdHVzOwotCi0Jc3RhdHVzID0gaThrX2dldF9mYW5fc3RhdHVzKGluZGV4KTsKLQlp\n"
- "ZiAoc3RhdHVzIDwgMCkKLQkJcmV0dXJuIC1FSU87Ci0JcmV0dXJuIHNwcmludGYoYnVmLCAiJWRc\n"
- "biIsIGNsYW1wX3ZhbChzdGF0dXMgKiBpOGtfcHdtX211bHQsIDAsIDI1NSkpOwotfQotCi1zdGF0\n"
- "aWMgc3NpemVfdCBpOGtfaHdtb25fc2V0X3B3bShzdHJ1Y3QgZGV2aWNlICpkZXYsCi0JCQkJIHN0\n"
- "cnVjdCBkZXZpY2VfYXR0cmlidXRlICphdHRyLAotCQkJCSBjb25zdCBjaGFyICpidWYsIHNpemVf\n"
- "dCBjb3VudCkKLXsKLQlpbnQgaW5kZXggPSB0b19zZW5zb3JfZGV2X2F0dHIoYXR0ciktPmluZGV4\n"
- "OwotCXVuc2lnbmVkIGxvbmcgdmFsOwotCWludCBlcnI7Ci0KLQllcnIgPSBrc3RydG91bChidWYs\n"
- "IDEwLCAmdmFsKTsKLQlpZiAoZXJyKQotCQlyZXR1cm4gZXJyOwotCXZhbCA9IGNsYW1wX3ZhbChE\n"
- "SVZfUk9VTkRfQ0xPU0VTVCh2YWwsIGk4a19wd21fbXVsdCksIDAsIGk4a19mYW5fbWF4KTsKLQot\n"
- "CW11dGV4X2xvY2soJmk4a19tdXRleCk7Ci0JZXJyID0gaThrX3NldF9mYW4oaW5kZXgsIHZhbCk7\n"
- "Ci0JbXV0ZXhfdW5sb2NrKCZpOGtfbXV0ZXgpOwotCi0JcmV0dXJuIGVyciA8IDAgPyAtRUlPIDog\n"
- "Y291bnQ7Ci19Ci0KLXN0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDFfaW5wdXQsIFNfSVJV\n"
- "R08sIGk4a19od21vbl9zaG93X3RlbXAsIE5VTEwsIDApOwotc3RhdGljIFNFTlNPUl9ERVZJQ0Vf\n"
- "QVRUUih0ZW1wMV9sYWJlbCwgU19JUlVHTywgaThrX2h3bW9uX3Nob3dfdGVtcF9sYWJlbCwgTlVM\n"
- "TCwKLQkJCSAgMCk7Ci1zdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHRlbXAyX2lucHV0LCBTX0lS\n"
- "VUdPLCBpOGtfaHdtb25fc2hvd190ZW1wLCBOVUxMLCAxKTsKLXN0YXRpYyBTRU5TT1JfREVWSUNF\n"
- "X0FUVFIodGVtcDJfbGFiZWwsIFNfSVJVR08sIGk4a19od21vbl9zaG93X3RlbXBfbGFiZWwsIE5V\n"
- "TEwsCi0JCQkgIDEpOwotc3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wM19pbnB1dCwgU19J\n"
- "UlVHTywgaThrX2h3bW9uX3Nob3dfdGVtcCwgTlVMTCwgMik7Ci1zdGF0aWMgU0VOU09SX0RFVklD\n"
- "RV9BVFRSKHRlbXAzX2xhYmVsLCBTX0lSVUdPLCBpOGtfaHdtb25fc2hvd190ZW1wX2xhYmVsLCBO\n"
- "VUxMLAotCQkJICAyKTsKLXN0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDRfaW5wdXQsIFNf\n"
- "SVJVR08sIGk4a19od21vbl9zaG93X3RlbXAsIE5VTEwsIDMpOwotc3RhdGljIFNFTlNPUl9ERVZJ\n"
- "Q0VfQVRUUih0ZW1wNF9sYWJlbCwgU19JUlVHTywgaThrX2h3bW9uX3Nob3dfdGVtcF9sYWJlbCwg\n"
- "TlVMTCwKLQkJCSAgMyk7Ci1zdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKGZhbjFfaW5wdXQsIFNf\n"
- "SVJVR08sIGk4a19od21vbl9zaG93X2ZhbiwgTlVMTCwgMCk7Ci1zdGF0aWMgU0VOU09SX0RFVklD\n"
- "RV9BVFRSKGZhbjFfbGFiZWwsIFNfSVJVR08sIGk4a19od21vbl9zaG93X2Zhbl9sYWJlbCwgTlVM\n"
- "TCwKLQkJCSAgMCk7Ci1zdGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHB3bTEsIFNfSVJVR08gfCBT\n"
- "X0lXVVNSLCBpOGtfaHdtb25fc2hvd19wd20sCi0JCQkgIGk4a19od21vbl9zZXRfcHdtLCAwKTsK\n"
- "LXN0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIoZmFuMl9pbnB1dCwgU19JUlVHTywgaThrX2h3bW9u\n"
- "X3Nob3dfZmFuLCBOVUxMLAotCQkJICAxKTsKLXN0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIoZmFu\n"
- "Ml9sYWJlbCwgU19JUlVHTywgaThrX2h3bW9uX3Nob3dfZmFuX2xhYmVsLCBOVUxMLAotCQkJICAx\n"
- "KTsKLXN0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIocHdtMiwgU19JUlVHTyB8IFNfSVdVU1IsIGk4\n"
- "a19od21vbl9zaG93X3B3bSwKLQkJCSAgaThrX2h3bW9uX3NldF9wd20sIDEpOwotCi1zdGF0aWMg\n"
- "c3RydWN0IGF0dHJpYnV0ZSAqaThrX2F0dHJzW10gPSB7Ci0JJnNlbnNvcl9kZXZfYXR0cl90ZW1w\n"
- "MV9pbnB1dC5kZXZfYXR0ci5hdHRyLAkvKiAwICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wMV9s\n"
- "YWJlbC5kZXZfYXR0ci5hdHRyLAkvKiAxICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wMl9pbnB1\n"
- "dC5kZXZfYXR0ci5hdHRyLAkvKiAyICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wMl9sYWJlbC5k\n"
- "ZXZfYXR0ci5hdHRyLAkvKiAzICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wM19pbnB1dC5kZXZf\n"
- "YXR0ci5hdHRyLAkvKiA0ICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wM19sYWJlbC5kZXZfYXR0\n"
- "ci5hdHRyLAkvKiA1ICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wNF9pbnB1dC5kZXZfYXR0ci5h\n"
- "dHRyLAkvKiA2ICovCi0JJnNlbnNvcl9kZXZfYXR0cl90ZW1wNF9sYWJlbC5kZXZfYXR0ci5hdHRy\n"
- "LAkvKiA3ICovCi0JJnNlbnNvcl9kZXZfYXR0cl9mYW4xX2lucHV0LmRldl9hdHRyLmF0dHIsCS8q\n"
- "IDggKi8KLQkmc2Vuc29yX2Rldl9hdHRyX2ZhbjFfbGFiZWwuZGV2X2F0dHIuYXR0ciwJLyogOSAq\n"
- "LwotCSZzZW5zb3JfZGV2X2F0dHJfcHdtMS5kZXZfYXR0ci5hdHRyLAkJLyogMTAgKi8KLQkmc2Vu\n"
- "c29yX2Rldl9hdHRyX2ZhbjJfaW5wdXQuZGV2X2F0dHIuYXR0ciwJLyogMTEgKi8KLQkmc2Vuc29y\n"
- "X2Rldl9hdHRyX2ZhbjJfbGFiZWwuZGV2X2F0dHIuYXR0ciwJLyogMTIgKi8KLQkmc2Vuc29yX2Rl\n"
- "dl9hdHRyX3B3bTIuZGV2X2F0dHIuYXR0ciwJCS8qIDEzICovCi0JTlVMTAotfTsKLQotc3RhdGlj\n"
- "IHVtb2RlX3QgaThrX2lzX3Zpc2libGUoc3RydWN0IGtvYmplY3QgKmtvYmosIHN0cnVjdCBhdHRy\n"
- "aWJ1dGUgKmF0dHIsCi0JCQkgICAgICBpbnQgaW5kZXgpCi17Ci0JaWYgKGluZGV4ID49IDAgJiYg\n"
- "aW5kZXggPD0gMSAmJgotCSAgICAhKGk4a19od21vbl9mbGFncyAmIEk4S19IV01PTl9IQVZFX1RF\n"
- "TVAxKSkKLQkJcmV0dXJuIDA7Ci0JaWYgKGluZGV4ID49IDIgJiYgaW5kZXggPD0gMyAmJgotCSAg\n"
- "ICAhKGk4a19od21vbl9mbGFncyAmIEk4S19IV01PTl9IQVZFX1RFTVAyKSkKLQkJcmV0dXJuIDA7\n"
- "Ci0JaWYgKGluZGV4ID49IDQgJiYgaW5kZXggPD0gNSAmJgotCSAgICAhKGk4a19od21vbl9mbGFn\n"
- "cyAmIEk4S19IV01PTl9IQVZFX1RFTVAzKSkKLQkJcmV0dXJuIDA7Ci0JaWYgKGluZGV4ID49IDYg\n"
- "JiYgaW5kZXggPD0gNyAmJgotCSAgICAhKGk4a19od21vbl9mbGFncyAmIEk4S19IV01PTl9IQVZF\n"
- "X1RFTVA0KSkKLQkJcmV0dXJuIDA7Ci0JaWYgKGluZGV4ID49IDggJiYgaW5kZXggPD0gMTAgJiYK\n"
- "LQkgICAgIShpOGtfaHdtb25fZmxhZ3MgJiBJOEtfSFdNT05fSEFWRV9GQU4xKSkKLQkJcmV0dXJu\n"
- "IDA7Ci0JaWYgKGluZGV4ID49IDExICYmIGluZGV4IDw9IDEzICYmCi0JICAgICEoaThrX2h3bW9u\n"
- "X2ZsYWdzICYgSThLX0hXTU9OX0hBVkVfRkFOMikpCi0JCXJldHVybiAwOwotCi0JcmV0dXJuIGF0\n"
- "dHItPm1vZGU7Ci19Ci0KLXN0YXRpYyBjb25zdCBzdHJ1Y3QgYXR0cmlidXRlX2dyb3VwIGk4a19n\n"
- "cm91cCA9IHsKLQkuYXR0cnMgPSBpOGtfYXR0cnMsCi0JLmlzX3Zpc2libGUgPSBpOGtfaXNfdmlz\n"
- "aWJsZSwKLX07Ci1fX0FUVFJJQlVURV9HUk9VUFMoaThrKTsKLQotc3RhdGljIGludCBfX2luaXQg\n"
- "aThrX2luaXRfaHdtb24odm9pZCkKLXsKLQlpbnQgZXJyOwotCi0JaThrX2h3bW9uX2ZsYWdzID0g\n"
- "MDsKLQotCS8qIENQVSB0ZW1wZXJhdHVyZSBhdHRyaWJ1dGVzLCBpZiB0ZW1wZXJhdHVyZSB0eXBl\n"
- "IGlzIE9LICovCi0JZXJyID0gaThrX2dldF90ZW1wX3R5cGUoMCk7Ci0JaWYgKGVyciA+PSAwKQot\n"
- "CQlpOGtfaHdtb25fZmxhZ3MgfD0gSThLX0hXTU9OX0hBVkVfVEVNUDE7Ci0JLyogY2hlY2sgZm9y\n"
- "IGFkZGl0aW9uYWwgdGVtcGVyYXR1cmUgc2Vuc29ycyAqLwotCWVyciA9IGk4a19nZXRfdGVtcF90\n"
- "eXBlKDEpOwotCWlmIChlcnIgPj0gMCkKLQkJaThrX2h3bW9uX2ZsYWdzIHw9IEk4S19IV01PTl9I\n"
- "QVZFX1RFTVAyOwotCWVyciA9IGk4a19nZXRfdGVtcF90eXBlKDIpOwotCWlmIChlcnIgPj0gMCkK\n"
- "LQkJaThrX2h3bW9uX2ZsYWdzIHw9IEk4S19IV01PTl9IQVZFX1RFTVAzOwotCWVyciA9IGk4a19n\n"
- "ZXRfdGVtcF90eXBlKDMpOwotCWlmIChlcnIgPj0gMCkKLQkJaThrX2h3bW9uX2ZsYWdzIHw9IEk4\n"
- "S19IV01PTl9IQVZFX1RFTVA0OwotCi0JLyogRmlyc3QgZmFuIGF0dHJpYnV0ZXMsIGlmIGZhbiB0\n"
- "eXBlIGlzIE9LICovCi0JZXJyID0gaThrX2dldF9mYW5fdHlwZSgwKTsKLQlpZiAoZXJyID49IDAp\n"
- "Ci0JCWk4a19od21vbl9mbGFncyB8PSBJOEtfSFdNT05fSEFWRV9GQU4xOwotCi0JLyogU2Vjb25k\n"
- "IGZhbiBhdHRyaWJ1dGVzLCBpZiBmYW4gdHlwZSBpcyBPSyAqLwotCWVyciA9IGk4a19nZXRfZmFu\n"
- "X3R5cGUoMSk7Ci0JaWYgKGVyciA+PSAwKQotCQlpOGtfaHdtb25fZmxhZ3MgfD0gSThLX0hXTU9O\n"
- "X0hBVkVfRkFOMjsKLQotCWk4a19od21vbl9kZXYgPSBod21vbl9kZXZpY2VfcmVnaXN0ZXJfd2l0\n"
- "aF9ncm91cHMoTlVMTCwgImk4ayIsIE5VTEwsCi0JCQkJCQkJICBpOGtfZ3JvdXBzKTsKLQlpZiAo\n"
- "SVNfRVJSKGk4a19od21vbl9kZXYpKSB7Ci0JCWVyciA9IFBUUl9FUlIoaThrX2h3bW9uX2Rldik7\n"
- "Ci0JCWk4a19od21vbl9kZXYgPSBOVUxMOwotCQlwcl9lcnIoImh3bW9uIHJlZ2lzdHJhdGlvbiBm\n"
- "YWlsZWQgKCVkKVxuIiwgZXJyKTsKLQkJcmV0dXJuIGVycjsKLQl9Ci0JcmV0dXJuIDA7Ci19Ci0K\n"
- "LXN0cnVjdCBpOGtfY29uZmlnX2RhdGEgewotCXVpbnQgZmFuX211bHQ7Ci0JdWludCBmYW5fbWF4\n"
- "OwotfTsKLQotZW51bSBpOGtfY29uZmlncyB7Ci0JREVMTF9MQVRJVFVERV9ENTIwLAotCURFTExf\n"
- "UFJFQ0lTSU9OXzQ5MCwKLQlERUxMX1NUVURJTywKLQlERUxMX1hQUywKLX07Ci0KLXN0YXRpYyBj\n"
- "b25zdCBzdHJ1Y3QgaThrX2NvbmZpZ19kYXRhIGk4a19jb25maWdfZGF0YVtdID0gewotCVtERUxM\n"
- "X0xBVElUVURFX0Q1MjBdID0gewotCQkuZmFuX211bHQgPSAxLAotCQkuZmFuX21heCA9IEk4S19G\n"
- "QU5fVFVSQk8sCi0JfSwKLQlbREVMTF9QUkVDSVNJT05fNDkwXSA9IHsKLQkJLmZhbl9tdWx0ID0g\n"
- "MSwKLQkJLmZhbl9tYXggPSBJOEtfRkFOX1RVUkJPLAotCX0sCi0JW0RFTExfU1RVRElPXSA9IHsK\n"
- "LQkJLmZhbl9tdWx0ID0gMSwKLQkJLmZhbl9tYXggPSBJOEtfRkFOX0hJR0gsCi0JfSwKLQlbREVM\n"
- "TF9YUFNdID0gewotCQkuZmFuX211bHQgPSAxLAotCQkuZmFuX21heCA9IEk4S19GQU5fSElHSCwK\n"
- "LQl9LAotfTsKLQotc3RhdGljIHN0cnVjdCBkbWlfc3lzdGVtX2lkIGk4a19kbWlfdGFibGVbXSBf\n"
- "X2luaXRkYXRhID0gewotCXsKLQkJLmlkZW50ID0gIkRlbGwgSW5zcGlyb24iLAotCQkubWF0Y2hl\n"
- "cyA9IHsKLQkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgQ29tcHV0ZXIiKSwKLQkJ\n"
- "CURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1FLCAiSW5zcGlyb24iKSwKLQkJfSwKLQl9LAotCXsK\n"
- "LQkJLmlkZW50ID0gIkRlbGwgTGF0aXR1ZGUiLAotCQkubWF0Y2hlcyA9IHsKLQkJCURNSV9NQVRD\n"
- "SChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgQ29tcHV0ZXIiKSwKLQkJCURNSV9NQVRDSChETUlfUFJP\n"
- "RFVDVF9OQU1FLCAiTGF0aXR1ZGUiKSwKLQkJfSwKLQl9LAotCXsKLQkJLmlkZW50ID0gIkRlbGwg\n"
- "SW5zcGlyb24gMiIsCi0JCS5tYXRjaGVzID0gewotCQkJRE1JX01BVENIKERNSV9TWVNfVkVORE9S\n"
- "LCAiRGVsbCBJbmMuIiksCi0JCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIkluc3Bpcm9u\n"
- "IiksCi0JCX0sCi0JfSwKLQl7Ci0JCS5pZGVudCA9ICJEZWxsIExhdGl0dWRlIEQ1MjAiLAotCQku\n"
- "bWF0Y2hlcyA9IHsKLQkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgSW5jLiIpLAot\n"
- "CQkJRE1JX01BVENIKERNSV9QUk9EVUNUX05BTUUsICJMYXRpdHVkZSBENTIwIiksCi0JCX0sCi0J\n"
- "CS5kcml2ZXJfZGF0YSA9ICh2b2lkICopJmk4a19jb25maWdfZGF0YVtERUxMX0xBVElUVURFX0Q1\n"
- "MjBdLAotCX0sCi0JewotCQkuaWRlbnQgPSAiRGVsbCBMYXRpdHVkZSAyIiwKLQkJLm1hdGNoZXMg\n"
- "PSB7Ci0JCQlETUlfTUFUQ0goRE1JX1NZU19WRU5ET1IsICJEZWxsIEluYy4iKSwKLQkJCURNSV9N\n"
- "QVRDSChETUlfUFJPRFVDVF9OQU1FLCAiTGF0aXR1ZGUiKSwKLQkJfSwKLQl9LAotCXsJLyogVUsg\n"
- "SW5zcGlyb24gNjQwMCAgKi8KLQkJLmlkZW50ID0gIkRlbGwgSW5zcGlyb24gMyIsCi0JCS5tYXRj\n"
- "aGVzID0gewotCQkJRE1JX01BVENIKERNSV9TWVNfVkVORE9SLCAiRGVsbCBJbmMuIiksCi0JCQlE\n"
- "TUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIk1NMDYxIiksCi0JCX0sCi0JfSwKLQl7Ci0JCS5p\n"
- "ZGVudCA9ICJEZWxsIEluc3Bpcm9uIDMiLAotCQkubWF0Y2hlcyA9IHsKLQkJCURNSV9NQVRDSChE\n"
- "TUlfU1lTX1ZFTkRPUiwgIkRlbGwgSW5jLiIpLAotCQkJRE1JX01BVENIKERNSV9QUk9EVUNUX05B\n"
- "TUUsICJNUDA2MSIpLAotCQl9LAotCX0sCi0JewotCQkuaWRlbnQgPSAiRGVsbCBQcmVjaXNpb24g\n"
- "NDkwIiwKLQkJLm1hdGNoZXMgPSB7Ci0JCQlETUlfTUFUQ0goRE1JX1NZU19WRU5ET1IsICJEZWxs\n"
- "IEluYy4iKSwKLQkJCURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1FLAotCQkJCSAgIlByZWNpc2lv\n"
- "biBXb3JrU3RhdGlvbiA0OTAiKSwKLQkJfSwKLQkJLmRyaXZlcl9kYXRhID0gKHZvaWQgKikmaThr\n"
- "X2NvbmZpZ19kYXRhW0RFTExfUFJFQ0lTSU9OXzQ5MF0sCi0JfSwKLQl7Ci0JCS5pZGVudCA9ICJE\n"
- "ZWxsIFByZWNpc2lvbiIsCi0JCS5tYXRjaGVzID0gewotCQkJRE1JX01BVENIKERNSV9TWVNfVkVO\n"
- "RE9SLCAiRGVsbCBJbmMuIiksCi0JCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIlByZWNp\n"
- "c2lvbiIpLAotCQl9LAotCX0sCi0JewotCQkuaWRlbnQgPSAiRGVsbCBWb3N0cm8iLAotCQkubWF0\n"
- "Y2hlcyA9IHsKLQkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgSW5jLiIpLAotCQkJ\n"
- "RE1JX01BVENIKERNSV9QUk9EVUNUX05BTUUsICJWb3N0cm8iKSwKLQkJfSwKLQl9LAotCXsKLQkJ\n"
- "LmlkZW50ID0gIkRlbGwgWFBTNDIxIiwKLQkJLm1hdGNoZXMgPSB7Ci0JCQlETUlfTUFUQ0goRE1J\n"
- "X1NZU19WRU5ET1IsICJEZWxsIEluYy4iKSwKLQkJCURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1F\n"
- "LCAiWFBTIEw0MjFYIiksCi0JCX0sCi0JfSwKLQl7Ci0JCS5pZGVudCA9ICJEZWxsIFN0dWRpbyIs\n"
- "Ci0JCS5tYXRjaGVzID0gewotCQkJRE1JX01BVENIKERNSV9TWVNfVkVORE9SLCAiRGVsbCBJbmMu\n"
- "IiksCi0JCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIlN0dWRpbyIpLAotCQl9LAotCQku\n"
- "ZHJpdmVyX2RhdGEgPSAodm9pZCAqKSZpOGtfY29uZmlnX2RhdGFbREVMTF9TVFVESU9dLAotCX0s\n"
- "Ci0JewotCQkuaWRlbnQgPSAiRGVsbCBYUFMgMTMiLAotCQkubWF0Y2hlcyA9IHsKLQkJCURNSV9N\n"
- "QVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgSW5jLiIpLAotCQkJRE1JX01BVENIKERNSV9QUk9E\n"
- "VUNUX05BTUUsICJYUFMxMyIpLAotCQl9LAotCQkuZHJpdmVyX2RhdGEgPSAodm9pZCAqKSZpOGtf\n"
- "Y29uZmlnX2RhdGFbREVMTF9YUFNdLAotCX0sCi0JewotCQkuaWRlbnQgPSAiRGVsbCBYUFMgTTE0\n"
- "MCIsCi0JCS5tYXRjaGVzID0gewotCQkJRE1JX01BVENIKERNSV9TWVNfVkVORE9SLCAiRGVsbCBJ\n"
- "bmMuIiksCi0JCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIk1YQzA1MSIpLAotCQl9LAot\n"
- "CQkuZHJpdmVyX2RhdGEgPSAodm9pZCAqKSZpOGtfY29uZmlnX2RhdGFbREVMTF9YUFNdLAotCX0s\n"
- "Ci0JeyB9Ci19OwotCi1NT0RVTEVfREVWSUNFX1RBQkxFKGRtaSwgaThrX2RtaV90YWJsZSk7Ci0K\n"
- "LS8qCi0gKiBQcm9iZSBmb3IgdGhlIHByZXNlbmNlIG9mIGEgc3VwcG9ydGVkIGxhcHRvcC4KLSAq\n"
- "Lwotc3RhdGljIGludCBfX2luaXQgaThrX3Byb2JlKHZvaWQpCi17Ci0JY29uc3Qgc3RydWN0IGRt\n"
- "aV9zeXN0ZW1faWQgKmlkOwotCWludCBmYW4sIHJldDsKLQotCS8qCi0JICogR2V0IERNSSBpbmZv\n"
- "cm1hdGlvbgotCSAqLwotCWlmICghZG1pX2NoZWNrX3N5c3RlbShpOGtfZG1pX3RhYmxlKSkgewot\n"
- "CQlpZiAoIWlnbm9yZV9kbWkgJiYgIWZvcmNlKQotCQkJcmV0dXJuIC1FTk9ERVY7Ci0KLQkJcHJf\n"
- "aW5mbygibm90IHJ1bm5pbmcgb24gYSBzdXBwb3J0ZWQgRGVsbCBzeXN0ZW0uXG4iKTsKLQkJcHJf\n"
- "aW5mbygidmVuZG9yPSVzLCBtb2RlbD0lcywgdmVyc2lvbj0lc1xuIiwKLQkJCWk4a19nZXRfZG1p\n"
- "X2RhdGEoRE1JX1NZU19WRU5ET1IpLAotCQkJaThrX2dldF9kbWlfZGF0YShETUlfUFJPRFVDVF9O\n"
- "QU1FKSwKLQkJCWk4a19nZXRfZG1pX2RhdGEoRE1JX0JJT1NfVkVSU0lPTikpOwotCX0KLQotCXN0\n"
- "cmxjcHkoYmlvc192ZXJzaW9uLCBpOGtfZ2V0X2RtaV9kYXRhKERNSV9CSU9TX1ZFUlNJT04pLAot\n"
- "CQlzaXplb2YoYmlvc192ZXJzaW9uKSk7Ci0KLQkvKgotCSAqIEdldCBTTU0gRGVsbCBzaWduYXR1\n"
- "cmUKLQkgKi8KLQlpZiAoaThrX2dldF9kZWxsX3NpZ25hdHVyZShJOEtfU01NX0dFVF9ERUxMX1NJ\n"
- "RzEpICYmCi0JICAgIGk4a19nZXRfZGVsbF9zaWduYXR1cmUoSThLX1NNTV9HRVRfREVMTF9TSUcy\n"
- "KSkgewotCQlwcl9lcnIoInVuYWJsZSB0byBnZXQgU01NIERlbGwgc2lnbmF0dXJlXG4iKTsKLQkJ\n"
- "aWYgKCFmb3JjZSkKLQkJCXJldHVybiAtRU5PREVWOwotCX0KLQotCS8qCi0JICogU2V0IGZhbiBt\n"
- "dWx0aXBsaWVyIGFuZCBtYXhpbWFsIGZhbiBzcGVlZCBmcm9tIGRtaSBjb25maWcKLQkgKiBWYWx1\n"
- "ZXMgc3BlY2lmaWVkIGluIG1vZHVsZSBwYXJhbWV0ZXJzIG92ZXJyaWRlIHZhbHVlcyBmcm9tIGRt\n"
- "aQotCSAqLwotCWlkID0gZG1pX2ZpcnN0X21hdGNoKGk4a19kbWlfdGFibGUpOwotCWlmIChpZCAm\n"
- "JiBpZC0+ZHJpdmVyX2RhdGEpIHsKLQkJY29uc3Qgc3RydWN0IGk4a19jb25maWdfZGF0YSAqY29u\n"
- "ZiA9IGlkLT5kcml2ZXJfZGF0YTsKLQkJaWYgKCFmYW5fbXVsdCAmJiBjb25mLT5mYW5fbXVsdCkK\n"
- "LQkJCWZhbl9tdWx0ID0gY29uZi0+ZmFuX211bHQ7Ci0JCWlmICghZmFuX21heCAmJiBjb25mLT5m\n"
- "YW5fbWF4KQotCQkJZmFuX21heCA9IGNvbmYtPmZhbl9tYXg7Ci0JfQotCi0JaThrX2Zhbl9tYXgg\n"
- "PSBmYW5fbWF4ID8gOiBJOEtfRkFOX0hJR0g7CS8qIE11c3Qgbm90IGJlIDAgKi8KLQlpOGtfcHdt\n"
- "X211bHQgPSBESVZfUk9VTkRfVVAoMjU1LCBpOGtfZmFuX21heCk7Ci0KLQlpZiAoIWZhbl9tdWx0\n"
- "KSB7Ci0JCS8qCi0JCSAqIEF1dG9kZXRlY3QgZmFuIG11bHRpcGxpZXIgYmFzZWQgb24gbm9taW5h\n"
- "bCBycG0KLQkJICogSWYgZmFuIHJlcG9ydHMgcnBtIHZhbHVlIHRvbyBoaWdoIHRoZW4gc2V0IG11\n"
- "bHRpcGxpZXIgdG8gMQotCQkgKi8KLQkJZm9yIChmYW4gPSAwOyBmYW4gPCAyOyArK2Zhbikgewot\n"
- "CQkJcmV0ID0gaThrX2dldF9mYW5fbm9taW5hbF9zcGVlZChmYW4sIGk4a19mYW5fbWF4KTsKLQkJ\n"
- "CWlmIChyZXQgPCAwKQotCQkJCWNvbnRpbnVlOwotCQkJaWYgKHJldCA+IEk4S19GQU5fTUFYX1JQ\n"
- "TSkKLQkJCQlpOGtfZmFuX211bHQgPSAxOwotCQkJYnJlYWs7Ci0JCX0KLQl9IGVsc2UgewotCQkv\n"
- "KiBGYW4gbXVsdGlwbGllciB3YXMgc3BlY2lmaWVkIGluIG1vZHVsZSBwYXJhbSBvciBpbiBkbWkg\n"
- "Ki8KLQkJaThrX2Zhbl9tdWx0ID0gZmFuX211bHQ7Ci0JfQotCi0JcmV0dXJuIDA7Ci19Ci0KLXN0\n"
- "YXRpYyBpbnQgX19pbml0IGk4a19pbml0KHZvaWQpCi17Ci0Jc3RydWN0IHByb2NfZGlyX2VudHJ5\n"
- "ICpwcm9jX2k4azsKLQlpbnQgZXJyOwotCi0JLyogQXJlIHdlIHJ1bm5pbmcgb24gYW4gc3VwcG9y\n"
- "dGVkIGxhcHRvcD8gKi8KLQlpZiAoaThrX3Byb2JlKCkpCi0JCXJldHVybiAtRU5PREVWOwotCi0J\n"
- "LyogUmVnaXN0ZXIgdGhlIHByb2MgZW50cnkgKi8KLQlwcm9jX2k4ayA9IHByb2NfY3JlYXRlKCJp\n"
- "OGsiLCAwLCBOVUxMLCAmaThrX2ZvcHMpOwotCWlmICghcHJvY19pOGspCi0JCXJldHVybiAtRU5P\n"
- "RU5UOwotCi0JZXJyID0gaThrX2luaXRfaHdtb24oKTsKLQlpZiAoZXJyKQotCQlnb3RvIGV4aXRf\n"
- "cmVtb3ZlX3Byb2M7Ci0KLQlyZXR1cm4gMDsKLQotIGV4aXRfcmVtb3ZlX3Byb2M6Ci0JcmVtb3Zl\n"
- "X3Byb2NfZW50cnkoImk4ayIsIE5VTEwpOwotCXJldHVybiBlcnI7Ci19Ci0KLXN0YXRpYyB2b2lk\n"
- "IF9fZXhpdCBpOGtfZXhpdCh2b2lkKQotewotCWh3bW9uX2RldmljZV91bnJlZ2lzdGVyKGk4a19o\n"
- "d21vbl9kZXYpOwotCXJlbW92ZV9wcm9jX2VudHJ5KCJpOGsiLCBOVUxMKTsKLX0KLQotbW9kdWxl\n"
- "X2luaXQoaThrX2luaXQpOwotbW9kdWxlX2V4aXQoaThrX2V4aXQpOwpkaWZmIC0tZ2l0IGEvZHJp\n"
- "dmVycy9od21vbi9NYWtlZmlsZSBiL2RyaXZlcnMvaHdtb24vTWFrZWZpbGUKaW5kZXggNmM5NDE0\n"
- "Ny4uMWMzZTQ1OCAxMDA2NDQKLS0tIGEvZHJpdmVycy9od21vbi9NYWtlZmlsZQorKysgYi9kcml2\n"
- "ZXJzL2h3bW9uL01ha2VmaWxlCkBAIC0xNTUsNiArMTU1LDcgQEAgb2JqLSQoQ09ORklHX1NFTlNP\n"
- "UlNfVzgzTDc4NVRTKQkrPSB3ODNsNzg1dHMubwogb2JqLSQoQ09ORklHX1NFTlNPUlNfVzgzTDc4\n"
- "Nk5HKQkrPSB3ODNsNzg2bmcubwogb2JqLSQoQ09ORklHX1NFTlNPUlNfV004MzFYKQkrPSB3bTgz\n"
- "MXgtaHdtb24ubwogb2JqLSQoQ09ORklHX1NFTlNPUlNfV004MzUwKQkrPSB3bTgzNTAtaHdtb24u\n"
- "bworb2JqLSQoQ09ORklHX0k4SykJCSs9IGRlbGwtc21tLWh3bW9uLm8KIAogb2JqLSQoQ09ORklH\n"
- "X1BNQlVTKQkJKz0gcG1idXMvCiAKZGlmZiAtLWdpdCBhL2RyaXZlcnMvaHdtb24vZGVsbC1zbW0t\n"
- "aHdtb24uYyBiL2RyaXZlcnMvaHdtb24vZGVsbC1zbW0taHdtb24uYwpuZXcgZmlsZSBtb2RlIDEw\n"
- "MDY0NAppbmRleCAwMDAwMDAwLi4yYjA0ZTRmCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9o\n"
- "d21vbi9kZWxsLXNtbS1od21vbi5jCkBAIC0wLDAgKzEsMTAwNyBAQAorLyoKKyAqIGRlbGwtc21t\n"
- "LWh3bW9uLmMgLS0gTGludXggZHJpdmVyIGZvciBhY2Nlc3NpbmcgdGhlIFNNTSBCSU9TIG9uIERl\n"
- "bGwgbGFwdG9wcy4KKyAqCisgKiBDb3B5cmlnaHQgKEMpIDIwMDEgIE1hc3NpbW8gRGFsIFpvdHRv\n"
- "IDxkekBkZWJpYW4ub3JnPgorICoKKyAqIEh3bW9uIGludGVncmF0aW9uOgorICogQ29weXJpZ2h0\n"
- "IChDKSAyMDExICBKZWFuIERlbHZhcmUgPGpkZWx2YXJlQHN1c2UuZGU+CisgKiBDb3B5cmlnaHQg\n"
- "KEMpIDIwMTMsIDIwMTQgIEd1ZW50ZXIgUm9lY2sgPGxpbnV4QHJvZWNrLXVzLm5ldD4KKyAqIENv\n"
- "cHlyaWdodCAoQykgMjAxNCwgMjAxNSAgUGFsaSBSb2jDoXIgPHBhbGkucm9oYXJAZ21haWwuY29t\n"
- "PgorICoKKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJp\n"
- "YnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0CisgKiB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBH\n"
- "ZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUKKyAqIEZyZWUgU29mdHdh\n"
- "cmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMiwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkK\n"
- "KyAqIGxhdGVyIHZlcnNpb24uCisgKgorICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGlu\n"
- "IHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dAorICogV0lUSE9VVCBBTlkgV0FS\n"
- "UkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZgorICogTUVSQ0hBTlRB\n"
- "QklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUK\n"
- "KyAqIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KKyAqLworCisjZGVm\n"
- "aW5lIHByX2ZtdChmbXQpIEtCVUlMRF9NT0ROQU1FICI6ICIgZm10CisKKyNpbmNsdWRlIDxsaW51\n"
- "eC9kZWxheS5oPgorI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgorI2luY2x1ZGUgPGxpbnV4L3R5\n"
- "cGVzLmg+CisjaW5jbHVkZSA8bGludXgvaW5pdC5oPgorI2luY2x1ZGUgPGxpbnV4L3Byb2NfZnMu\n"
- "aD4KKyNpbmNsdWRlIDxsaW51eC9zZXFfZmlsZS5oPgorI2luY2x1ZGUgPGxpbnV4L2RtaS5oPgor\n"
- "I2luY2x1ZGUgPGxpbnV4L2NhcGFiaWxpdHkuaD4KKyNpbmNsdWRlIDxsaW51eC9tdXRleC5oPgor\n"
- "I2luY2x1ZGUgPGxpbnV4L2h3bW9uLmg+CisjaW5jbHVkZSA8bGludXgvaHdtb24tc3lzZnMuaD4K\n"
- "KyNpbmNsdWRlIDxsaW51eC91YWNjZXNzLmg+CisjaW5jbHVkZSA8bGludXgvaW8uaD4KKyNpbmNs\n"
- "dWRlIDxsaW51eC9zY2hlZC5oPgorCisjaW5jbHVkZSA8bGludXgvaThrLmg+CisKKyNkZWZpbmUg\n"
- "SThLX1NNTV9GTl9TVEFUVVMJMHgwMDI1CisjZGVmaW5lIEk4S19TTU1fUE9XRVJfU1RBVFVTCTB4\n"
- "MDA2OQorI2RlZmluZSBJOEtfU01NX1NFVF9GQU4JCTB4MDFhMworI2RlZmluZSBJOEtfU01NX0dF\n"
- "VF9GQU4JCTB4MDBhMworI2RlZmluZSBJOEtfU01NX0dFVF9TUEVFRAkweDAyYTMKKyNkZWZpbmUg\n"
- "SThLX1NNTV9HRVRfRkFOX1RZUEUJMHgwM2EzCisjZGVmaW5lIEk4S19TTU1fR0VUX05PTV9TUEVF\n"
- "RAkweDA0YTMKKyNkZWZpbmUgSThLX1NNTV9HRVRfVEVNUAkweDEwYTMKKyNkZWZpbmUgSThLX1NN\n"
- "TV9HRVRfVEVNUF9UWVBFCTB4MTFhMworI2RlZmluZSBJOEtfU01NX0dFVF9ERUxMX1NJRzEJMHhm\n"
- "ZWEzCisjZGVmaW5lIEk4S19TTU1fR0VUX0RFTExfU0lHMgkweGZmYTMKKworI2RlZmluZSBJOEtf\n"
- "RkFOX01VTFQJCTMwCisjZGVmaW5lIEk4S19GQU5fTUFYX1JQTQkJMzAwMDAKKyNkZWZpbmUgSThL\n"
- "X01BWF9URU1QCQkxMjcKKworI2RlZmluZSBJOEtfRk5fTk9ORQkJMHgwMAorI2RlZmluZSBJOEtf\n"
- "Rk5fVVAJCTB4MDEKKyNkZWZpbmUgSThLX0ZOX0RPV04JCTB4MDIKKyNkZWZpbmUgSThLX0ZOX01V\n"
- "VEUJCTB4MDQKKyNkZWZpbmUgSThLX0ZOX01BU0sJCTB4MDcKKyNkZWZpbmUgSThLX0ZOX1NISUZU\n"
- "CQk4CisKKyNkZWZpbmUgSThLX1BPV0VSX0FDCQkweDA1CisjZGVmaW5lIEk4S19QT1dFUl9CQVRU\n"
- "RVJZCTB4MDEKKworc3RhdGljIERFRklORV9NVVRFWChpOGtfbXV0ZXgpOworc3RhdGljIGNoYXIg\n"
- "Ymlvc192ZXJzaW9uWzRdOworc3RhdGljIHN0cnVjdCBkZXZpY2UgKmk4a19od21vbl9kZXY7Citz\n"
- "dGF0aWMgdTMyIGk4a19od21vbl9mbGFnczsKK3N0YXRpYyB1aW50IGk4a19mYW5fbXVsdCA9IEk4\n"
- "S19GQU5fTVVMVDsKK3N0YXRpYyB1aW50IGk4a19wd21fbXVsdDsKK3N0YXRpYyB1aW50IGk4a19m\n"
- "YW5fbWF4ID0gSThLX0ZBTl9ISUdIOworCisjZGVmaW5lIEk4S19IV01PTl9IQVZFX1RFTVAxCSgx\n"
- "IDw8IDApCisjZGVmaW5lIEk4S19IV01PTl9IQVZFX1RFTVAyCSgxIDw8IDEpCisjZGVmaW5lIEk4\n"
- "S19IV01PTl9IQVZFX1RFTVAzCSgxIDw8IDIpCisjZGVmaW5lIEk4S19IV01PTl9IQVZFX1RFTVA0\n"
- "CSgxIDw8IDMpCisjZGVmaW5lIEk4S19IV01PTl9IQVZFX0ZBTjEJKDEgPDwgNCkKKyNkZWZpbmUg\n"
- "SThLX0hXTU9OX0hBVkVfRkFOMgkoMSA8PCA1KQorCitNT0RVTEVfQVVUSE9SKCJNYXNzaW1vIERh\n"
- "bCBab3R0byAoZHpAZGViaWFuLm9yZykiKTsKK01PRFVMRV9BVVRIT1IoIlBhbGkgUm9ow6FyIDxw\n"
- "YWxpLnJvaGFyQGdtYWlsLmNvbT4iKTsKK01PRFVMRV9ERVNDUklQVElPTigiRHJpdmVyIGZvciBh\n"
- "Y2Nlc3NpbmcgU01NIEJJT1Mgb24gRGVsbCBsYXB0b3BzIik7CitNT0RVTEVfTElDRU5TRSgiR1BM\n"
- "Iik7CitNT0RVTEVfQUxJQVMoImk4ayIpOworCitzdGF0aWMgYm9vbCBmb3JjZTsKK21vZHVsZV9w\n"
- "YXJhbShmb3JjZSwgYm9vbCwgMCk7CitNT0RVTEVfUEFSTV9ERVNDKGZvcmNlLCAiRm9yY2UgbG9h\n"
- "ZGluZyB3aXRob3V0IGNoZWNraW5nIGZvciBzdXBwb3J0ZWQgbW9kZWxzIik7CisKK3N0YXRpYyBi\n"
- "b29sIGlnbm9yZV9kbWk7Cittb2R1bGVfcGFyYW0oaWdub3JlX2RtaSwgYm9vbCwgMCk7CitNT0RV\n"
- "TEVfUEFSTV9ERVNDKGlnbm9yZV9kbWksICJDb250aW51ZSBwcm9iaW5nIGhhcmR3YXJlIGV2ZW4g\n"
- "aWYgRE1JIGRhdGEgZG9lcyBub3QgbWF0Y2giKTsKKworc3RhdGljIGJvb2wgcmVzdHJpY3RlZDsK\n"
- "K21vZHVsZV9wYXJhbShyZXN0cmljdGVkLCBib29sLCAwKTsKK01PRFVMRV9QQVJNX0RFU0MocmVz\n"
- "dHJpY3RlZCwgIkFsbG93IGZhbiBjb250cm9sIGlmIFNZU19BRE1JTiBjYXBhYmlsaXR5IHNldCIp\n"
- "OworCitzdGF0aWMgYm9vbCBwb3dlcl9zdGF0dXM7Cittb2R1bGVfcGFyYW0ocG93ZXJfc3RhdHVz\n"
- "LCBib29sLCAwNjAwKTsKK01PRFVMRV9QQVJNX0RFU0MocG93ZXJfc3RhdHVzLCAiUmVwb3J0IHBv\n"
- "d2VyIHN0YXR1cyBpbiAvcHJvYy9pOGsiKTsKKworc3RhdGljIHVpbnQgZmFuX211bHQ7Cittb2R1\n"
- "bGVfcGFyYW0oZmFuX211bHQsIHVpbnQsIDApOworTU9EVUxFX1BBUk1fREVTQyhmYW5fbXVsdCwg\n"
- "IkZhY3RvciB0byBtdWx0aXBseSBmYW4gc3BlZWQgd2l0aCAoZGVmYXVsdDogYXV0b2RldGVjdCki\n"
- "KTsKKworc3RhdGljIHVpbnQgZmFuX21heDsKK21vZHVsZV9wYXJhbShmYW5fbWF4LCB1aW50LCAw\n"
- "KTsKK01PRFVMRV9QQVJNX0RFU0MoZmFuX21heCwgIk1heGltdW0gY29uZmlndXJhYmxlIGZhbiBz\n"
- "cGVlZCAoZGVmYXVsdDogYXV0b2RldGVjdCkiKTsKKworc3RhdGljIGludCBpOGtfb3Blbl9mcyhz\n"
- "dHJ1Y3QgaW5vZGUgKmlub2RlLCBzdHJ1Y3QgZmlsZSAqZmlsZSk7CitzdGF0aWMgbG9uZyBpOGtf\n"
- "aW9jdGwoc3RydWN0IGZpbGUgKiwgdW5zaWduZWQgaW50LCB1bnNpZ25lZCBsb25nKTsKKworc3Rh\n"
- "dGljIGNvbnN0IHN0cnVjdCBmaWxlX29wZXJhdGlvbnMgaThrX2ZvcHMgPSB7CisJLm93bmVyCQk9\n"
- "IFRISVNfTU9EVUxFLAorCS5vcGVuCQk9IGk4a19vcGVuX2ZzLAorCS5yZWFkCQk9IHNlcV9yZWFk\n"
- "LAorCS5sbHNlZWsJCT0gc2VxX2xzZWVrLAorCS5yZWxlYXNlCT0gc2luZ2xlX3JlbGVhc2UsCisJ\n"
- "LnVubG9ja2VkX2lvY3RsCT0gaThrX2lvY3RsLAorfTsKKworc3RydWN0IHNtbV9yZWdzIHsKKwl1\n"
- "bnNpZ25lZCBpbnQgZWF4OworCXVuc2lnbmVkIGludCBlYnggX19wYWNrZWQ7CisJdW5zaWduZWQg\n"
- "aW50IGVjeCBfX3BhY2tlZDsKKwl1bnNpZ25lZCBpbnQgZWR4IF9fcGFja2VkOworCXVuc2lnbmVk\n"
- "IGludCBlc2kgX19wYWNrZWQ7CisJdW5zaWduZWQgaW50IGVkaSBfX3BhY2tlZDsKK307CisKK3N0\n"
- "YXRpYyBpbmxpbmUgY29uc3QgY2hhciAqaThrX2dldF9kbWlfZGF0YShpbnQgZmllbGQpCit7CisJ\n"
- "Y29uc3QgY2hhciAqZG1pX2RhdGEgPSBkbWlfZ2V0X3N5c3RlbV9pbmZvKGZpZWxkKTsKKworCXJl\n"
- "dHVybiBkbWlfZGF0YSAmJiAqZG1pX2RhdGEgPyBkbWlfZGF0YSA6ICI/IjsKK30KKworLyoKKyAq\n"
- "IENhbGwgdGhlIFN5c3RlbSBNYW5hZ2VtZW50IE1vZGUgQklPUy4gQ29kZSBwcm92aWRlZCBieSBK\n"
- "b25hdGhhbiBCdXp6YXJkLgorICovCitzdGF0aWMgaW50IGk4a19zbW0oc3RydWN0IHNtbV9yZWdz\n"
- "ICpyZWdzKQoreworCWludCByYzsKKwlpbnQgZWF4ID0gcmVncy0+ZWF4OworCWNwdW1hc2tfdmFy\n"
- "X3Qgb2xkX21hc2s7CisKKwkvKiBTTU0gcmVxdWlyZXMgQ1BVIDAgKi8KKwlpZiAoIWFsbG9jX2Nw\n"
- "dW1hc2tfdmFyKCZvbGRfbWFzaywgR0ZQX0tFUk5FTCkpCisJCXJldHVybiAtRU5PTUVNOworCWNw\n"
- "dW1hc2tfY29weShvbGRfbWFzaywgJmN1cnJlbnQtPmNwdXNfYWxsb3dlZCk7CisJcmMgPSBzZXRf\n"
- "Y3B1c19hbGxvd2VkX3B0cihjdXJyZW50LCBjcHVtYXNrX29mKDApKTsKKwlpZiAocmMpCisJCWdv\n"
- "dG8gb3V0OworCWlmIChzbXBfcHJvY2Vzc29yX2lkKCkgIT0gMCkgeworCQlyYyA9IC1FQlVTWTsK\n"
- "KwkJZ290byBvdXQ7CisJfQorCisjaWYgZGVmaW5lZChDT05GSUdfWDg2XzY0KQorCWFzbSB2b2xh\n"
- "dGlsZSgicHVzaHEgJSVyYXhcblx0IgorCQkibW92bCAwKCUlcmF4KSwlJWVkeFxuXHQiCisJCSJw\n"
- "dXNocSAlJXJkeFxuXHQiCisJCSJtb3ZsIDQoJSVyYXgpLCUlZWJ4XG5cdCIKKwkJIm1vdmwgOCgl\n"
- "JXJheCksJSVlY3hcblx0IgorCQkibW92bCAxMiglJXJheCksJSVlZHhcblx0IgorCQkibW92bCAx\n"
- "NiglJXJheCksJSVlc2lcblx0IgorCQkibW92bCAyMCglJXJheCksJSVlZGlcblx0IgorCQkicG9w\n"
- "cSAlJXJheFxuXHQiCisJCSJvdXQgJSVhbCwkMHhiMlxuXHQiCisJCSJvdXQgJSVhbCwkMHg4NFxu\n"
- "XHQiCisJCSJ4Y2hncSAlJXJheCwoJSVyc3ApXG5cdCIKKwkJIm1vdmwgJSVlYngsNCglJXJheClc\n"
- "blx0IgorCQkibW92bCAlJWVjeCw4KCUlcmF4KVxuXHQiCisJCSJtb3ZsICUlZWR4LDEyKCUlcmF4\n"
- "KVxuXHQiCisJCSJtb3ZsICUlZXNpLDE2KCUlcmF4KVxuXHQiCisJCSJtb3ZsICUlZWRpLDIwKCUl\n"
- "cmF4KVxuXHQiCisJCSJwb3BxICUlcmR4XG5cdCIKKwkJIm1vdmwgJSVlZHgsMCglJXJheClcblx0\n"
- "IgorCQkicHVzaGZxXG5cdCIKKwkJInBvcHEgJSVyYXhcblx0IgorCQkiYW5kbCAkMSwlJWVheFxu\n"
- "IgorCQk6ICI9YSIocmMpCisJCTogICAgImEiKHJlZ3MpCisJCTogICAgIiVlYngiLCAiJWVjeCIs\n"
- "ICIlZWR4IiwgIiVlc2kiLCAiJWVkaSIsICJtZW1vcnkiKTsKKyNlbHNlCisJYXNtIHZvbGF0aWxl\n"
- "KCJwdXNobCAlJWVheFxuXHQiCisJICAgICJtb3ZsIDAoJSVlYXgpLCUlZWR4XG5cdCIKKwkgICAg\n"
- "InB1c2ggJSVlZHhcblx0IgorCSAgICAibW92bCA0KCUlZWF4KSwlJWVieFxuXHQiCisJICAgICJt\n"
- "b3ZsIDgoJSVlYXgpLCUlZWN4XG5cdCIKKwkgICAgIm1vdmwgMTIoJSVlYXgpLCUlZWR4XG5cdCIK\n"
- "KwkgICAgIm1vdmwgMTYoJSVlYXgpLCUlZXNpXG5cdCIKKwkgICAgIm1vdmwgMjAoJSVlYXgpLCUl\n"
- "ZWRpXG5cdCIKKwkgICAgInBvcGwgJSVlYXhcblx0IgorCSAgICAib3V0ICUlYWwsJDB4YjJcblx0\n"
- "IgorCSAgICAib3V0ICUlYWwsJDB4ODRcblx0IgorCSAgICAieGNoZ2wgJSVlYXgsKCUlZXNwKVxu\n"
- "XHQiCisJICAgICJtb3ZsICUlZWJ4LDQoJSVlYXgpXG5cdCIKKwkgICAgIm1vdmwgJSVlY3gsOCgl\n"
- "JWVheClcblx0IgorCSAgICAibW92bCAlJWVkeCwxMiglJWVheClcblx0IgorCSAgICAibW92bCAl\n"
- "JWVzaSwxNiglJWVheClcblx0IgorCSAgICAibW92bCAlJWVkaSwyMCglJWVheClcblx0IgorCSAg\n"
- "ICAicG9wbCAlJWVkeFxuXHQiCisJICAgICJtb3ZsICUlZWR4LDAoJSVlYXgpXG5cdCIKKwkgICAg\n"
- "ImxhaGZcblx0IgorCSAgICAic2hybCAkOCwlJWVheFxuXHQiCisJICAgICJhbmRsICQxLCUlZWF4\n"
- "XG4iCisJICAgIDogIj1hIihyYykKKwkgICAgOiAgICAiYSIocmVncykKKwkgICAgOiAgICAiJWVi\n"
- "eCIsICIlZWN4IiwgIiVlZHgiLCAiJWVzaSIsICIlZWRpIiwgIm1lbW9yeSIpOworI2VuZGlmCisJ\n"
- "aWYgKHJjICE9IDAgfHwgKHJlZ3MtPmVheCAmIDB4ZmZmZikgPT0gMHhmZmZmIHx8IHJlZ3MtPmVh\n"
- "eCA9PSBlYXgpCisJCXJjID0gLUVJTlZBTDsKKworb3V0OgorCXNldF9jcHVzX2FsbG93ZWRfcHRy\n"
- "KGN1cnJlbnQsIG9sZF9tYXNrKTsKKwlmcmVlX2NwdW1hc2tfdmFyKG9sZF9tYXNrKTsKKwlyZXR1\n"
- "cm4gcmM7Cit9CisKKy8qCisgKiBSZWFkIHRoZSBGbiBrZXkgc3RhdHVzLgorICovCitzdGF0aWMg\n"
- "aW50IGk4a19nZXRfZm5fc3RhdHVzKHZvaWQpCit7CisJc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7\n"
- "IC5lYXggPSBJOEtfU01NX0ZOX1NUQVRVUywgfTsKKwlpbnQgcmM7CisKKwlyYyA9IGk4a19zbW0o\n"
- "JnJlZ3MpOworCWlmIChyYyA8IDApCisJCXJldHVybiByYzsKKworCXN3aXRjaCAoKHJlZ3MuZWF4\n"
- "ID4+IEk4S19GTl9TSElGVCkgJiBJOEtfRk5fTUFTSykgeworCWNhc2UgSThLX0ZOX1VQOgorCQly\n"
- "ZXR1cm4gSThLX1ZPTF9VUDsKKwljYXNlIEk4S19GTl9ET1dOOgorCQlyZXR1cm4gSThLX1ZPTF9E\n"
- "T1dOOworCWNhc2UgSThLX0ZOX01VVEU6CisJCXJldHVybiBJOEtfVk9MX01VVEU7CisJZGVmYXVs\n"
- "dDoKKwkJcmV0dXJuIDA7CisJfQorfQorCisvKgorICogUmVhZCB0aGUgcG93ZXIgc3RhdHVzLgor\n"
- "ICovCitzdGF0aWMgaW50IGk4a19nZXRfcG93ZXJfc3RhdHVzKHZvaWQpCit7CisJc3RydWN0IHNt\n"
- "bV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01NX1BPV0VSX1NUQVRVUywgfTsKKwlpbnQgcmM7\n"
- "CisKKwlyYyA9IGk4a19zbW0oJnJlZ3MpOworCWlmIChyYyA8IDApCisJCXJldHVybiByYzsKKwor\n"
- "CXJldHVybiAocmVncy5lYXggJiAweGZmKSA9PSBJOEtfUE9XRVJfQUMgPyBJOEtfQUMgOiBJOEtf\n"
- "QkFUVEVSWTsKK30KKworLyoKKyAqIFJlYWQgdGhlIGZhbiBzdGF0dXMuCisgKi8KK3N0YXRpYyBp\n"
- "bnQgaThrX2dldF9mYW5fc3RhdHVzKGludCBmYW4pCit7CisJc3RydWN0IHNtbV9yZWdzIHJlZ3Mg\n"
- "PSB7IC5lYXggPSBJOEtfU01NX0dFVF9GQU4sIH07CisKKwlyZWdzLmVieCA9IGZhbiAmIDB4ZmY7\n"
- "CisJcmV0dXJuIGk4a19zbW0oJnJlZ3MpID8gOiByZWdzLmVheCAmIDB4ZmY7Cit9CisKKy8qCisg\n"
- "KiBSZWFkIHRoZSBmYW4gc3BlZWQgaW4gUlBNLgorICovCitzdGF0aWMgaW50IGk4a19nZXRfZmFu\n"
- "X3NwZWVkKGludCBmYW4pCit7CisJc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtf\n"
- "U01NX0dFVF9TUEVFRCwgfTsKKworCXJlZ3MuZWJ4ID0gZmFuICYgMHhmZjsKKwlyZXR1cm4gaThr\n"
- "X3NtbSgmcmVncykgPyA6IChyZWdzLmVheCAmIDB4ZmZmZikgKiBpOGtfZmFuX211bHQ7Cit9CisK\n"
- "Ky8qCisgKiBSZWFkIHRoZSBmYW4gdHlwZS4KKyAqLworc3RhdGljIGludCBpOGtfZ2V0X2Zhbl90\n"
- "eXBlKGludCBmYW4pCit7CisJc3RydWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01N\n"
- "X0dFVF9GQU5fVFlQRSwgfTsKKworCXJlZ3MuZWJ4ID0gZmFuICYgMHhmZjsKKwlyZXR1cm4gaThr\n"
- "X3NtbSgmcmVncykgPyA6IHJlZ3MuZWF4ICYgMHhmZjsKK30KKworLyoKKyAqIFJlYWQgdGhlIGZh\n"
- "biBub21pbmFsIHJwbSBmb3Igc3BlY2lmaWMgZmFuIHNwZWVkLgorICovCitzdGF0aWMgaW50IGk4\n"
- "a19nZXRfZmFuX25vbWluYWxfc3BlZWQoaW50IGZhbiwgaW50IHNwZWVkKQoreworCXN0cnVjdCBz\n"
- "bW1fcmVncyByZWdzID0geyAuZWF4ID0gSThLX1NNTV9HRVRfTk9NX1NQRUVELCB9OworCisJcmVn\n"
- "cy5lYnggPSAoZmFuICYgMHhmZikgfCAoc3BlZWQgPDwgOCk7CisJcmV0dXJuIGk4a19zbW0oJnJl\n"
- "Z3MpID8gOiAocmVncy5lYXggJiAweGZmZmYpICogaThrX2Zhbl9tdWx0OworfQorCisvKgorICog\n"
- "U2V0IHRoZSBmYW4gc3BlZWQgKG9mZiwgbG93LCBoaWdoKS4gUmV0dXJucyB0aGUgbmV3IGZhbiBz\n"
- "dGF0dXMuCisgKi8KK3N0YXRpYyBpbnQgaThrX3NldF9mYW4oaW50IGZhbiwgaW50IHNwZWVkKQor\n"
- "eworCXN0cnVjdCBzbW1fcmVncyByZWdzID0geyAuZWF4ID0gSThLX1NNTV9TRVRfRkFOLCB9Owor\n"
- "CisJc3BlZWQgPSAoc3BlZWQgPCAwKSA/IDAgOiAoKHNwZWVkID4gaThrX2Zhbl9tYXgpID8gaThr\n"
- "X2Zhbl9tYXggOiBzcGVlZCk7CisJcmVncy5lYnggPSAoZmFuICYgMHhmZikgfCAoc3BlZWQgPDwg\n"
- "OCk7CisKKwlyZXR1cm4gaThrX3NtbSgmcmVncykgPyA6IGk4a19nZXRfZmFuX3N0YXR1cyhmYW4p\n"
- "OworfQorCitzdGF0aWMgaW50IGk4a19nZXRfdGVtcF90eXBlKGludCBzZW5zb3IpCit7CisJc3Ry\n"
- "dWN0IHNtbV9yZWdzIHJlZ3MgPSB7IC5lYXggPSBJOEtfU01NX0dFVF9URU1QX1RZUEUsIH07CisK\n"
- "KwlyZWdzLmVieCA9IHNlbnNvciAmIDB4ZmY7CisJcmV0dXJuIGk4a19zbW0oJnJlZ3MpID8gOiBy\n"
- "ZWdzLmVheCAmIDB4ZmY7Cit9CisKKy8qCisgKiBSZWFkIHRoZSBjcHUgdGVtcGVyYXR1cmUuCisg\n"
- "Ki8KK3N0YXRpYyBpbnQgX2k4a19nZXRfdGVtcChpbnQgc2Vuc29yKQoreworCXN0cnVjdCBzbW1f\n"
- "cmVncyByZWdzID0geworCQkuZWF4ID0gSThLX1NNTV9HRVRfVEVNUCwKKwkJLmVieCA9IHNlbnNv\n"
- "ciAmIDB4ZmYsCisJfTsKKworCXJldHVybiBpOGtfc21tKCZyZWdzKSA/IDogcmVncy5lYXggJiAw\n"
- "eGZmOworfQorCitzdGF0aWMgaW50IGk4a19nZXRfdGVtcChpbnQgc2Vuc29yKQoreworCWludCB0\n"
- "ZW1wID0gX2k4a19nZXRfdGVtcChzZW5zb3IpOworCisJLyoKKwkgKiBTb21ldGltZXMgdGhlIHRl\n"
- "bXBlcmF0dXJlIHNlbnNvciByZXR1cm5zIDB4OTksIHdoaWNoIGlzIG91dCBvZiByYW5nZS4KKwkg\n"
- "KiBJbiB0aGlzIGNhc2Ugd2UgcmV0cnkgKG9uY2UpIGJlZm9yZSByZXR1cm5pbmcgYW4gZXJyb3Iu\n"
- "CisJICMgMTAwMzY1NTEzNyAwMDAwMDA1OCAwMDAwNWE0YgorCSAjIDEwMDM2NTUxMzggMDAwMDAw\n"
- "OTkgMDAwMDNhODAgPC0tLSAweDk5ID0gMTUzIGRlZ3JlZXMKKwkgIyAxMDAzNjU1MTM5IDAwMDAw\n"
- "MDU0IDAwMDA1YzUyCisJICovCisJaWYgKHRlbXAgPT0gMHg5OSkgeworCQltc2xlZXAoMTAwKTsK\n"
- "KwkJdGVtcCA9IF9pOGtfZ2V0X3RlbXAoc2Vuc29yKTsKKwl9CisJLyoKKwkgKiBSZXR1cm4gLUVO\n"
- "T0RBVEEgZm9yIGFsbCBpbnZhbGlkIHRlbXBlcmF0dXJlcy4KKwkgKgorCSAqIEtub3duIGluc3Rh\n"
- "bmNlcyBhcmUgdGhlIDB4OTkgdmFsdWUgYXMgc2VlbiBhYm92ZSBhcyB3ZWxsIGFzCisJICogMHhj\n"
- "MSAoMTkzKSwgd2hpY2ggbWF5IGJlIHJldHVybmVkIHdoZW4gdHJ5aW5nIHRvIHJlYWQgdGhlIEdQ\n"
- "VQorCSAqIHRlbXBlcmF0dXJlIGlmIHRoZSBzeXN0ZW0gc3VwcG9ydHMgYSBHUFUgYW5kIGl0IGlz\n"
- "IGN1cnJlbnRseQorCSAqIHR1cm5lZCBvZmYuCisJICovCisJaWYgKHRlbXAgPiBJOEtfTUFYX1RF\n"
- "TVApCisJCXJldHVybiAtRU5PREFUQTsKKworCXJldHVybiB0ZW1wOworfQorCitzdGF0aWMgaW50\n"
- "IGk4a19nZXRfZGVsbF9zaWduYXR1cmUoaW50IHJlcV9mbikKK3sKKwlzdHJ1Y3Qgc21tX3JlZ3Mg\n"
- "cmVncyA9IHsgLmVheCA9IHJlcV9mbiwgfTsKKwlpbnQgcmM7CisKKwlyYyA9IGk4a19zbW0oJnJl\n"
- "Z3MpOworCWlmIChyYyA8IDApCisJCXJldHVybiByYzsKKworCXJldHVybiByZWdzLmVheCA9PSAx\n"
- "MTQ1NjUxNTI3ICYmIHJlZ3MuZWR4ID09IDExNDUzOTIyMDQgPyAwIDogLTE7Cit9CisKK3N0YXRp\n"
- "YyBpbnQKK2k4a19pb2N0bF91bmxvY2tlZChzdHJ1Y3QgZmlsZSAqZnAsIHVuc2lnbmVkIGludCBj\n"
- "bWQsIHVuc2lnbmVkIGxvbmcgYXJnKQoreworCWludCB2YWwgPSAwOworCWludCBzcGVlZDsKKwl1\n"
- "bnNpZ25lZCBjaGFyIGJ1ZmZbMTZdOworCWludCBfX3VzZXIgKmFyZ3AgPSAoaW50IF9fdXNlciAq\n"
- "KWFyZzsKKworCWlmICghYXJncCkKKwkJcmV0dXJuIC1FSU5WQUw7CisKKwlzd2l0Y2ggKGNtZCkg\n"
- "eworCWNhc2UgSThLX0JJT1NfVkVSU0lPTjoKKwkJdmFsID0gKGJpb3NfdmVyc2lvblswXSA8PCAx\n"
- "NikgfAorCQkJCShiaW9zX3ZlcnNpb25bMV0gPDwgOCkgfCBiaW9zX3ZlcnNpb25bMl07CisJCWJy\n"
- "ZWFrOworCisJY2FzZSBJOEtfTUFDSElORV9JRDoKKwkJbWVtc2V0KGJ1ZmYsIDAsIDE2KTsKKwkJ\n"
- "c3RybGNweShidWZmLCBpOGtfZ2V0X2RtaV9kYXRhKERNSV9QUk9EVUNUX1NFUklBTCksCisJCQlz\n"
- "aXplb2YoYnVmZikpOworCQlicmVhazsKKworCWNhc2UgSThLX0ZOX1NUQVRVUzoKKwkJdmFsID0g\n"
- "aThrX2dldF9mbl9zdGF0dXMoKTsKKwkJYnJlYWs7CisKKwljYXNlIEk4S19QT1dFUl9TVEFUVVM6\n"
- "CisJCXZhbCA9IGk4a19nZXRfcG93ZXJfc3RhdHVzKCk7CisJCWJyZWFrOworCisJY2FzZSBJOEtf\n"
- "R0VUX1RFTVA6CisJCXZhbCA9IGk4a19nZXRfdGVtcCgwKTsKKwkJYnJlYWs7CisKKwljYXNlIEk4\n"
- "S19HRVRfU1BFRUQ6CisJCWlmIChjb3B5X2Zyb21fdXNlcigmdmFsLCBhcmdwLCBzaXplb2YoaW50\n"
- "KSkpCisJCQlyZXR1cm4gLUVGQVVMVDsKKworCQl2YWwgPSBpOGtfZ2V0X2Zhbl9zcGVlZCh2YWwp\n"
- "OworCQlicmVhazsKKworCWNhc2UgSThLX0dFVF9GQU46CisJCWlmIChjb3B5X2Zyb21fdXNlcigm\n"
- "dmFsLCBhcmdwLCBzaXplb2YoaW50KSkpCisJCQlyZXR1cm4gLUVGQVVMVDsKKworCQl2YWwgPSBp\n"
- "OGtfZ2V0X2Zhbl9zdGF0dXModmFsKTsKKwkJYnJlYWs7CisKKwljYXNlIEk4S19TRVRfRkFOOgor\n"
- "CQlpZiAocmVzdHJpY3RlZCAmJiAhY2FwYWJsZShDQVBfU1lTX0FETUlOKSkKKwkJCXJldHVybiAt\n"
- "RVBFUk07CisKKwkJaWYgKGNvcHlfZnJvbV91c2VyKCZ2YWwsIGFyZ3AsIHNpemVvZihpbnQpKSkK\n"
- "KwkJCXJldHVybiAtRUZBVUxUOworCisJCWlmIChjb3B5X2Zyb21fdXNlcigmc3BlZWQsIGFyZ3Ag\n"
- "KyAxLCBzaXplb2YoaW50KSkpCisJCQlyZXR1cm4gLUVGQVVMVDsKKworCQl2YWwgPSBpOGtfc2V0\n"
- "X2Zhbih2YWwsIHNwZWVkKTsKKwkJYnJlYWs7CisKKwlkZWZhdWx0OgorCQlyZXR1cm4gLUVJTlZB\n"
- "TDsKKwl9CisKKwlpZiAodmFsIDwgMCkKKwkJcmV0dXJuIHZhbDsKKworCXN3aXRjaCAoY21kKSB7\n"
- "CisJY2FzZSBJOEtfQklPU19WRVJTSU9OOgorCQlpZiAoY29weV90b191c2VyKGFyZ3AsICZ2YWws\n"
- "IDQpKQorCQkJcmV0dXJuIC1FRkFVTFQ7CisKKwkJYnJlYWs7CisJY2FzZSBJOEtfTUFDSElORV9J\n"
- "RDoKKwkJaWYgKGNvcHlfdG9fdXNlcihhcmdwLCBidWZmLCAxNikpCisJCQlyZXR1cm4gLUVGQVVM\n"
- "VDsKKworCQlicmVhazsKKwlkZWZhdWx0OgorCQlpZiAoY29weV90b191c2VyKGFyZ3AsICZ2YWws\n"
- "IHNpemVvZihpbnQpKSkKKwkJCXJldHVybiAtRUZBVUxUOworCisJCWJyZWFrOworCX0KKworCXJl\n"
- "dHVybiAwOworfQorCitzdGF0aWMgbG9uZyBpOGtfaW9jdGwoc3RydWN0IGZpbGUgKmZwLCB1bnNp\n"
- "Z25lZCBpbnQgY21kLCB1bnNpZ25lZCBsb25nIGFyZykKK3sKKwlsb25nIHJldDsKKworCW11dGV4\n"
- "X2xvY2soJmk4a19tdXRleCk7CisJcmV0ID0gaThrX2lvY3RsX3VubG9ja2VkKGZwLCBjbWQsIGFy\n"
- "Zyk7CisJbXV0ZXhfdW5sb2NrKCZpOGtfbXV0ZXgpOworCisJcmV0dXJuIHJldDsKK30KKworLyoK\n"
- "KyAqIFByaW50IHRoZSBpbmZvcm1hdGlvbiBmb3IgL3Byb2MvaThrLgorICovCitzdGF0aWMgaW50\n"
- "IGk4a19wcm9jX3Nob3coc3RydWN0IHNlcV9maWxlICpzZXEsIHZvaWQgKm9mZnNldCkKK3sKKwlp\n"
- "bnQgZm5fa2V5LCBjcHVfdGVtcCwgYWNfcG93ZXI7CisJaW50IGxlZnRfZmFuLCByaWdodF9mYW4s\n"
- "IGxlZnRfc3BlZWQsIHJpZ2h0X3NwZWVkOworCisJY3B1X3RlbXAJPSBpOGtfZ2V0X3RlbXAoMCk7\n"
- "CQkJLyogMTExMDAgwrVzICovCisJbGVmdF9mYW4JPSBpOGtfZ2V0X2Zhbl9zdGF0dXMoSThLX0ZB\n"
- "Tl9MRUZUKTsJLyogICA1ODAgwrVzICovCisJcmlnaHRfZmFuCT0gaThrX2dldF9mYW5fc3RhdHVz\n"
- "KEk4S19GQU5fUklHSFQpOwkvKiAgIDU4MCDCtXMgKi8KKwlsZWZ0X3NwZWVkCT0gaThrX2dldF9m\n"
- "YW5fc3BlZWQoSThLX0ZBTl9MRUZUKTsJLyogICA1ODAgwrVzICovCisJcmlnaHRfc3BlZWQJPSBp\n"
- "OGtfZ2V0X2Zhbl9zcGVlZChJOEtfRkFOX1JJR0hUKTsJLyogICA1ODAgwrVzICovCisJZm5fa2V5\n"
- "CQk9IGk4a19nZXRfZm5fc3RhdHVzKCk7CQkJLyogICA3NTAgwrVzICovCisJaWYgKHBvd2VyX3N0\n"
- "YXR1cykKKwkJYWNfcG93ZXIgPSBpOGtfZ2V0X3Bvd2VyX3N0YXR1cygpOwkJLyogMTQ3MDAgwrVz\n"
- "ICovCisJZWxzZQorCQlhY19wb3dlciA9IC0xOworCisJLyoKKwkgKiBJbmZvOgorCSAqCisJICog\n"
- "MSkgIEZvcm1hdCB2ZXJzaW9uICh0aGlzIHdpbGwgY2hhbmdlIGlmIGZvcm1hdCBjaGFuZ2VzKQor\n"
- "CSAqIDIpICBCSU9TIHZlcnNpb24KKwkgKiAzKSAgQklPUyBtYWNoaW5lIElECisJICogNCkgIENw\n"
- "dSB0ZW1wZXJhdHVyZQorCSAqIDUpICBMZWZ0IGZhbiBzdGF0dXMKKwkgKiA2KSAgUmlnaHQgZmFu\n"
- "IHN0YXR1cworCSAqIDcpICBMZWZ0IGZhbiBzcGVlZAorCSAqIDgpICBSaWdodCBmYW4gc3BlZWQK\n"
- "KwkgKiA5KSAgQUMgcG93ZXIKKwkgKiAxMCkgRm4gS2V5IHN0YXR1cworCSAqLworCXJldHVybiBz\n"
- "ZXFfcHJpbnRmKHNlcSwgIiVzICVzICVzICVkICVkICVkICVkICVkICVkICVkXG4iLAorCQkJICBJ\n"
- "OEtfUFJPQ19GTVQsCisJCQkgIGJpb3NfdmVyc2lvbiwKKwkJCSAgaThrX2dldF9kbWlfZGF0YShE\n"
- "TUlfUFJPRFVDVF9TRVJJQUwpLAorCQkJICBjcHVfdGVtcCwKKwkJCSAgbGVmdF9mYW4sIHJpZ2h0\n"
- "X2ZhbiwgbGVmdF9zcGVlZCwgcmlnaHRfc3BlZWQsCisJCQkgIGFjX3Bvd2VyLCBmbl9rZXkpOwor\n"
- "fQorCitzdGF0aWMgaW50IGk4a19vcGVuX2ZzKHN0cnVjdCBpbm9kZSAqaW5vZGUsIHN0cnVjdCBm\n"
- "aWxlICpmaWxlKQoreworCXJldHVybiBzaW5nbGVfb3BlbihmaWxlLCBpOGtfcHJvY19zaG93LCBO\n"
- "VUxMKTsKK30KKworCisvKgorICogSHdtb24gaW50ZXJmYWNlCisgKi8KKworc3RhdGljIHNzaXpl\n"
- "X3QgaThrX2h3bW9uX3Nob3dfdGVtcF9sYWJlbChzdHJ1Y3QgZGV2aWNlICpkZXYsCisJCQkJCSBz\n"
- "dHJ1Y3QgZGV2aWNlX2F0dHJpYnV0ZSAqZGV2YXR0ciwKKwkJCQkJIGNoYXIgKmJ1ZikKK3sKKwlz\n"
- "dGF0aWMgY29uc3QgY2hhciAqIGNvbnN0IGxhYmVsc1tdID0geworCQkiQ1BVIiwKKwkJIkdQVSIs\n"
- "CisJCSJTT0RJTU0iLAorCQkiT3RoZXIiLAorCQkiQW1iaWVudCIsCisJCSJPdGhlciIsCisJfTsK\n"
- "KwlpbnQgaW5kZXggPSB0b19zZW5zb3JfZGV2X2F0dHIoZGV2YXR0ciktPmluZGV4OworCWludCB0\n"
- "eXBlOworCisJdHlwZSA9IGk4a19nZXRfdGVtcF90eXBlKGluZGV4KTsKKwlpZiAodHlwZSA8IDAp\n"
- "CisJCXJldHVybiB0eXBlOworCWlmICh0eXBlID49IEFSUkFZX1NJWkUobGFiZWxzKSkKKwkJdHlw\n"
- "ZSA9IEFSUkFZX1NJWkUobGFiZWxzKSAtIDE7CisJcmV0dXJuIHNwcmludGYoYnVmLCAiJXNcbiIs\n"
- "IGxhYmVsc1t0eXBlXSk7Cit9CisKK3N0YXRpYyBzc2l6ZV90IGk4a19od21vbl9zaG93X3RlbXAo\n"
- "c3RydWN0IGRldmljZSAqZGV2LAorCQkJCSAgIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICpkZXZh\n"
- "dHRyLAorCQkJCSAgIGNoYXIgKmJ1ZikKK3sKKwlpbnQgaW5kZXggPSB0b19zZW5zb3JfZGV2X2F0\n"
- "dHIoZGV2YXR0ciktPmluZGV4OworCWludCB0ZW1wOworCisJdGVtcCA9IGk4a19nZXRfdGVtcChp\n"
- "bmRleCk7CisJaWYgKHRlbXAgPCAwKQorCQlyZXR1cm4gdGVtcDsKKwlyZXR1cm4gc3ByaW50Zihi\n"
- "dWYsICIlZFxuIiwgdGVtcCAqIDEwMDApOworfQorCitzdGF0aWMgc3NpemVfdCBpOGtfaHdtb25f\n"
- "c2hvd19mYW5fbGFiZWwoc3RydWN0IGRldmljZSAqZGV2LAorCQkJCQlzdHJ1Y3QgZGV2aWNlX2F0\n"
- "dHJpYnV0ZSAqZGV2YXR0ciwKKwkJCQkJY2hhciAqYnVmKQoreworCXN0YXRpYyBjb25zdCBjaGFy\n"
- "ICogY29uc3QgbGFiZWxzW10gPSB7CisJCSJQcm9jZXNzb3IgRmFuIiwKKwkJIk1vdGhlcmJvYXJk\n"
- "IEZhbiIsCisJCSJWaWRlbyBGYW4iLAorCQkiUG93ZXIgU3VwcGx5IEZhbiIsCisJCSJDaGlwc2V0\n"
- "IEZhbiIsCisJCSJPdGhlciBGYW4iLAorCX07CisJaW50IGluZGV4ID0gdG9fc2Vuc29yX2Rldl9h\n"
- "dHRyKGRldmF0dHIpLT5pbmRleDsKKwlib29sIGRvY2sgPSBmYWxzZTsKKwlpbnQgdHlwZTsKKwor\n"
- "CXR5cGUgPSBpOGtfZ2V0X2Zhbl90eXBlKGluZGV4KTsKKwlpZiAodHlwZSA8IDApCisJCXJldHVy\n"
- "biB0eXBlOworCisJaWYgKHR5cGUgJiAweDEwKSB7CisJCWRvY2sgPSB0cnVlOworCQl0eXBlICY9\n"
- "IDB4MEY7CisJfQorCisJaWYgKHR5cGUgPj0gQVJSQVlfU0laRShsYWJlbHMpKQorCQl0eXBlID0g\n"
- "KEFSUkFZX1NJWkUobGFiZWxzKSAtIDEpOworCisJcmV0dXJuIHNwcmludGYoYnVmLCAiJXMlc1xu\n"
- "IiwgKGRvY2sgPyAiRG9ja2luZyAiIDogIiIpLCBsYWJlbHNbdHlwZV0pOworfQorCitzdGF0aWMg\n"
- "c3NpemVfdCBpOGtfaHdtb25fc2hvd19mYW4oc3RydWN0IGRldmljZSAqZGV2LAorCQkJCSAgc3Ry\n"
- "dWN0IGRldmljZV9hdHRyaWJ1dGUgKmRldmF0dHIsCisJCQkJICBjaGFyICpidWYpCit7CisJaW50\n"
- "IGluZGV4ID0gdG9fc2Vuc29yX2Rldl9hdHRyKGRldmF0dHIpLT5pbmRleDsKKwlpbnQgZmFuX3Nw\n"
- "ZWVkOworCisJZmFuX3NwZWVkID0gaThrX2dldF9mYW5fc3BlZWQoaW5kZXgpOworCWlmIChmYW5f\n"
- "c3BlZWQgPCAwKQorCQlyZXR1cm4gZmFuX3NwZWVkOworCXJldHVybiBzcHJpbnRmKGJ1ZiwgIiVk\n"
- "XG4iLCBmYW5fc3BlZWQpOworfQorCitzdGF0aWMgc3NpemVfdCBpOGtfaHdtb25fc2hvd19wd20o\n"
- "c3RydWN0IGRldmljZSAqZGV2LAorCQkJCSAgc3RydWN0IGRldmljZV9hdHRyaWJ1dGUgKmRldmF0\n"
- "dHIsCisJCQkJICBjaGFyICpidWYpCit7CisJaW50IGluZGV4ID0gdG9fc2Vuc29yX2Rldl9hdHRy\n"
- "KGRldmF0dHIpLT5pbmRleDsKKwlpbnQgc3RhdHVzOworCisJc3RhdHVzID0gaThrX2dldF9mYW5f\n"
- "c3RhdHVzKGluZGV4KTsKKwlpZiAoc3RhdHVzIDwgMCkKKwkJcmV0dXJuIC1FSU87CisJcmV0dXJu\n"
- "IHNwcmludGYoYnVmLCAiJWRcbiIsIGNsYW1wX3ZhbChzdGF0dXMgKiBpOGtfcHdtX211bHQsIDAs\n"
- "IDI1NSkpOworfQorCitzdGF0aWMgc3NpemVfdCBpOGtfaHdtb25fc2V0X3B3bShzdHJ1Y3QgZGV2\n"
- "aWNlICpkZXYsCisJCQkJIHN0cnVjdCBkZXZpY2VfYXR0cmlidXRlICphdHRyLAorCQkJCSBjb25z\n"
- "dCBjaGFyICpidWYsIHNpemVfdCBjb3VudCkKK3sKKwlpbnQgaW5kZXggPSB0b19zZW5zb3JfZGV2\n"
- "X2F0dHIoYXR0ciktPmluZGV4OworCXVuc2lnbmVkIGxvbmcgdmFsOworCWludCBlcnI7CisKKwll\n"
- "cnIgPSBrc3RydG91bChidWYsIDEwLCAmdmFsKTsKKwlpZiAoZXJyKQorCQlyZXR1cm4gZXJyOwor\n"
- "CXZhbCA9IGNsYW1wX3ZhbChESVZfUk9VTkRfQ0xPU0VTVCh2YWwsIGk4a19wd21fbXVsdCksIDAs\n"
- "IGk4a19mYW5fbWF4KTsKKworCW11dGV4X2xvY2soJmk4a19tdXRleCk7CisJZXJyID0gaThrX3Nl\n"
- "dF9mYW4oaW5kZXgsIHZhbCk7CisJbXV0ZXhfdW5sb2NrKCZpOGtfbXV0ZXgpOworCisJcmV0dXJu\n"
- "IGVyciA8IDAgPyAtRUlPIDogY291bnQ7Cit9CisKK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIo\n"
- "dGVtcDFfaW5wdXQsIFNfSVJVR08sIGk4a19od21vbl9zaG93X3RlbXAsIE5VTEwsIDApOworc3Rh\n"
- "dGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wMV9sYWJlbCwgU19JUlVHTywgaThrX2h3bW9uX3No\n"
- "b3dfdGVtcF9sYWJlbCwgTlVMTCwKKwkJCSAgMCk7CitzdGF0aWMgU0VOU09SX0RFVklDRV9BVFRS\n"
- "KHRlbXAyX2lucHV0LCBTX0lSVUdPLCBpOGtfaHdtb25fc2hvd190ZW1wLCBOVUxMLCAxKTsKK3N0\n"
- "YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIodGVtcDJfbGFiZWwsIFNfSVJVR08sIGk4a19od21vbl9z\n"
- "aG93X3RlbXBfbGFiZWwsIE5VTEwsCisJCQkgIDEpOworc3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRU\n"
- "Uih0ZW1wM19pbnB1dCwgU19JUlVHTywgaThrX2h3bW9uX3Nob3dfdGVtcCwgTlVMTCwgMik7Citz\n"
- "dGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKHRlbXAzX2xhYmVsLCBTX0lSVUdPLCBpOGtfaHdtb25f\n"
- "c2hvd190ZW1wX2xhYmVsLCBOVUxMLAorCQkJICAyKTsKK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FU\n"
- "VFIodGVtcDRfaW5wdXQsIFNfSVJVR08sIGk4a19od21vbl9zaG93X3RlbXAsIE5VTEwsIDMpOwor\n"
- "c3RhdGljIFNFTlNPUl9ERVZJQ0VfQVRUUih0ZW1wNF9sYWJlbCwgU19JUlVHTywgaThrX2h3bW9u\n"
- "X3Nob3dfdGVtcF9sYWJlbCwgTlVMTCwKKwkJCSAgMyk7CitzdGF0aWMgU0VOU09SX0RFVklDRV9B\n"
- "VFRSKGZhbjFfaW5wdXQsIFNfSVJVR08sIGk4a19od21vbl9zaG93X2ZhbiwgTlVMTCwgMCk7Citz\n"
- "dGF0aWMgU0VOU09SX0RFVklDRV9BVFRSKGZhbjFfbGFiZWwsIFNfSVJVR08sIGk4a19od21vbl9z\n"
- "aG93X2Zhbl9sYWJlbCwgTlVMTCwKKwkJCSAgMCk7CitzdGF0aWMgU0VOU09SX0RFVklDRV9BVFRS\n"
- "KHB3bTEsIFNfSVJVR08gfCBTX0lXVVNSLCBpOGtfaHdtb25fc2hvd19wd20sCisJCQkgIGk4a19o\n"
- "d21vbl9zZXRfcHdtLCAwKTsKK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIoZmFuMl9pbnB1dCwg\n"
- "U19JUlVHTywgaThrX2h3bW9uX3Nob3dfZmFuLCBOVUxMLAorCQkJICAxKTsKK3N0YXRpYyBTRU5T\n"
- "T1JfREVWSUNFX0FUVFIoZmFuMl9sYWJlbCwgU19JUlVHTywgaThrX2h3bW9uX3Nob3dfZmFuX2xh\n"
- "YmVsLCBOVUxMLAorCQkJICAxKTsKK3N0YXRpYyBTRU5TT1JfREVWSUNFX0FUVFIocHdtMiwgU19J\n"
- "UlVHTyB8IFNfSVdVU1IsIGk4a19od21vbl9zaG93X3B3bSwKKwkJCSAgaThrX2h3bW9uX3NldF9w\n"
- "d20sIDEpOworCitzdGF0aWMgc3RydWN0IGF0dHJpYnV0ZSAqaThrX2F0dHJzW10gPSB7CisJJnNl\n"
- "bnNvcl9kZXZfYXR0cl90ZW1wMV9pbnB1dC5kZXZfYXR0ci5hdHRyLAkvKiAwICovCisJJnNlbnNv\n"
- "cl9kZXZfYXR0cl90ZW1wMV9sYWJlbC5kZXZfYXR0ci5hdHRyLAkvKiAxICovCisJJnNlbnNvcl9k\n"
- "ZXZfYXR0cl90ZW1wMl9pbnB1dC5kZXZfYXR0ci5hdHRyLAkvKiAyICovCisJJnNlbnNvcl9kZXZf\n"
- "YXR0cl90ZW1wMl9sYWJlbC5kZXZfYXR0ci5hdHRyLAkvKiAzICovCisJJnNlbnNvcl9kZXZfYXR0\n"
- "cl90ZW1wM19pbnB1dC5kZXZfYXR0ci5hdHRyLAkvKiA0ICovCisJJnNlbnNvcl9kZXZfYXR0cl90\n"
- "ZW1wM19sYWJlbC5kZXZfYXR0ci5hdHRyLAkvKiA1ICovCisJJnNlbnNvcl9kZXZfYXR0cl90ZW1w\n"
- "NF9pbnB1dC5kZXZfYXR0ci5hdHRyLAkvKiA2ICovCisJJnNlbnNvcl9kZXZfYXR0cl90ZW1wNF9s\n"
- "YWJlbC5kZXZfYXR0ci5hdHRyLAkvKiA3ICovCisJJnNlbnNvcl9kZXZfYXR0cl9mYW4xX2lucHV0\n"
- "LmRldl9hdHRyLmF0dHIsCS8qIDggKi8KKwkmc2Vuc29yX2Rldl9hdHRyX2ZhbjFfbGFiZWwuZGV2\n"
- "X2F0dHIuYXR0ciwJLyogOSAqLworCSZzZW5zb3JfZGV2X2F0dHJfcHdtMS5kZXZfYXR0ci5hdHRy\n"
- "LAkJLyogMTAgKi8KKwkmc2Vuc29yX2Rldl9hdHRyX2ZhbjJfaW5wdXQuZGV2X2F0dHIuYXR0ciwJ\n"
- "LyogMTEgKi8KKwkmc2Vuc29yX2Rldl9hdHRyX2ZhbjJfbGFiZWwuZGV2X2F0dHIuYXR0ciwJLyog\n"
- "MTIgKi8KKwkmc2Vuc29yX2Rldl9hdHRyX3B3bTIuZGV2X2F0dHIuYXR0ciwJCS8qIDEzICovCisJ\n"
- "TlVMTAorfTsKKworc3RhdGljIHVtb2RlX3QgaThrX2lzX3Zpc2libGUoc3RydWN0IGtvYmplY3Qg\n"
- "KmtvYmosIHN0cnVjdCBhdHRyaWJ1dGUgKmF0dHIsCisJCQkgICAgICBpbnQgaW5kZXgpCit7CisJ\n"
- "aWYgKGluZGV4ID49IDAgJiYgaW5kZXggPD0gMSAmJgorCSAgICAhKGk4a19od21vbl9mbGFncyAm\n"
- "IEk4S19IV01PTl9IQVZFX1RFTVAxKSkKKwkJcmV0dXJuIDA7CisJaWYgKGluZGV4ID49IDIgJiYg\n"
- "aW5kZXggPD0gMyAmJgorCSAgICAhKGk4a19od21vbl9mbGFncyAmIEk4S19IV01PTl9IQVZFX1RF\n"
- "TVAyKSkKKwkJcmV0dXJuIDA7CisJaWYgKGluZGV4ID49IDQgJiYgaW5kZXggPD0gNSAmJgorCSAg\n"
- "ICAhKGk4a19od21vbl9mbGFncyAmIEk4S19IV01PTl9IQVZFX1RFTVAzKSkKKwkJcmV0dXJuIDA7\n"
- "CisJaWYgKGluZGV4ID49IDYgJiYgaW5kZXggPD0gNyAmJgorCSAgICAhKGk4a19od21vbl9mbGFn\n"
- "cyAmIEk4S19IV01PTl9IQVZFX1RFTVA0KSkKKwkJcmV0dXJuIDA7CisJaWYgKGluZGV4ID49IDgg\n"
- "JiYgaW5kZXggPD0gMTAgJiYKKwkgICAgIShpOGtfaHdtb25fZmxhZ3MgJiBJOEtfSFdNT05fSEFW\n"
- "RV9GQU4xKSkKKwkJcmV0dXJuIDA7CisJaWYgKGluZGV4ID49IDExICYmIGluZGV4IDw9IDEzICYm\n"
- "CisJICAgICEoaThrX2h3bW9uX2ZsYWdzICYgSThLX0hXTU9OX0hBVkVfRkFOMikpCisJCXJldHVy\n"
- "biAwOworCisJcmV0dXJuIGF0dHItPm1vZGU7Cit9CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgYXR0\n"
- "cmlidXRlX2dyb3VwIGk4a19ncm91cCA9IHsKKwkuYXR0cnMgPSBpOGtfYXR0cnMsCisJLmlzX3Zp\n"
- "c2libGUgPSBpOGtfaXNfdmlzaWJsZSwKK307CitfX0FUVFJJQlVURV9HUk9VUFMoaThrKTsKKwor\n"
- "c3RhdGljIGludCBfX2luaXQgaThrX2luaXRfaHdtb24odm9pZCkKK3sKKwlpbnQgZXJyOworCisJ\n"
- "aThrX2h3bW9uX2ZsYWdzID0gMDsKKworCS8qIENQVSB0ZW1wZXJhdHVyZSBhdHRyaWJ1dGVzLCBp\n"
- "ZiB0ZW1wZXJhdHVyZSB0eXBlIGlzIE9LICovCisJZXJyID0gaThrX2dldF90ZW1wX3R5cGUoMCk7\n"
- "CisJaWYgKGVyciA+PSAwKQorCQlpOGtfaHdtb25fZmxhZ3MgfD0gSThLX0hXTU9OX0hBVkVfVEVN\n"
- "UDE7CisJLyogY2hlY2sgZm9yIGFkZGl0aW9uYWwgdGVtcGVyYXR1cmUgc2Vuc29ycyAqLworCWVy\n"
- "ciA9IGk4a19nZXRfdGVtcF90eXBlKDEpOworCWlmIChlcnIgPj0gMCkKKwkJaThrX2h3bW9uX2Zs\n"
- "YWdzIHw9IEk4S19IV01PTl9IQVZFX1RFTVAyOworCWVyciA9IGk4a19nZXRfdGVtcF90eXBlKDIp\n"
- "OworCWlmIChlcnIgPj0gMCkKKwkJaThrX2h3bW9uX2ZsYWdzIHw9IEk4S19IV01PTl9IQVZFX1RF\n"
- "TVAzOworCWVyciA9IGk4a19nZXRfdGVtcF90eXBlKDMpOworCWlmIChlcnIgPj0gMCkKKwkJaThr\n"
- "X2h3bW9uX2ZsYWdzIHw9IEk4S19IV01PTl9IQVZFX1RFTVA0OworCisJLyogRmlyc3QgZmFuIGF0\n"
- "dHJpYnV0ZXMsIGlmIGZhbiB0eXBlIGlzIE9LICovCisJZXJyID0gaThrX2dldF9mYW5fdHlwZSgw\n"
- "KTsKKwlpZiAoZXJyID49IDApCisJCWk4a19od21vbl9mbGFncyB8PSBJOEtfSFdNT05fSEFWRV9G\n"
- "QU4xOworCisJLyogU2Vjb25kIGZhbiBhdHRyaWJ1dGVzLCBpZiBmYW4gdHlwZSBpcyBPSyAqLwor\n"
- "CWVyciA9IGk4a19nZXRfZmFuX3R5cGUoMSk7CisJaWYgKGVyciA+PSAwKQorCQlpOGtfaHdtb25f\n"
- "ZmxhZ3MgfD0gSThLX0hXTU9OX0hBVkVfRkFOMjsKKworCWk4a19od21vbl9kZXYgPSBod21vbl9k\n"
- "ZXZpY2VfcmVnaXN0ZXJfd2l0aF9ncm91cHMoTlVMTCwgImk4ayIsIE5VTEwsCisJCQkJCQkJICBp\n"
- "OGtfZ3JvdXBzKTsKKwlpZiAoSVNfRVJSKGk4a19od21vbl9kZXYpKSB7CisJCWVyciA9IFBUUl9F\n"
- "UlIoaThrX2h3bW9uX2Rldik7CisJCWk4a19od21vbl9kZXYgPSBOVUxMOworCQlwcl9lcnIoImh3\n"
- "bW9uIHJlZ2lzdHJhdGlvbiBmYWlsZWQgKCVkKVxuIiwgZXJyKTsKKwkJcmV0dXJuIGVycjsKKwl9\n"
- "CisJcmV0dXJuIDA7Cit9CisKK3N0cnVjdCBpOGtfY29uZmlnX2RhdGEgeworCXVpbnQgZmFuX211\n"
- "bHQ7CisJdWludCBmYW5fbWF4OworfTsKKworZW51bSBpOGtfY29uZmlncyB7CisJREVMTF9MQVRJ\n"
- "VFVERV9ENTIwLAorCURFTExfUFJFQ0lTSU9OXzQ5MCwKKwlERUxMX1NUVURJTywKKwlERUxMX1hQ\n"
- "UywKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgaThrX2NvbmZpZ19kYXRhIGk4a19jb25maWdf\n"
- "ZGF0YVtdID0geworCVtERUxMX0xBVElUVURFX0Q1MjBdID0geworCQkuZmFuX211bHQgPSAxLAor\n"
- "CQkuZmFuX21heCA9IEk4S19GQU5fVFVSQk8sCisJfSwKKwlbREVMTF9QUkVDSVNJT05fNDkwXSA9\n"
- "IHsKKwkJLmZhbl9tdWx0ID0gMSwKKwkJLmZhbl9tYXggPSBJOEtfRkFOX1RVUkJPLAorCX0sCisJ\n"
- "W0RFTExfU1RVRElPXSA9IHsKKwkJLmZhbl9tdWx0ID0gMSwKKwkJLmZhbl9tYXggPSBJOEtfRkFO\n"
- "X0hJR0gsCisJfSwKKwlbREVMTF9YUFNdID0geworCQkuZmFuX211bHQgPSAxLAorCQkuZmFuX21h\n"
- "eCA9IEk4S19GQU5fSElHSCwKKwl9LAorfTsKKworc3RhdGljIHN0cnVjdCBkbWlfc3lzdGVtX2lk\n"
- "IGk4a19kbWlfdGFibGVbXSBfX2luaXRkYXRhID0geworCXsKKwkJLmlkZW50ID0gIkRlbGwgSW5z\n"
- "cGlyb24iLAorCQkubWF0Y2hlcyA9IHsKKwkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRl\n"
- "bGwgQ29tcHV0ZXIiKSwKKwkJCURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1FLCAiSW5zcGlyb24i\n"
- "KSwKKwkJfSwKKwl9LAorCXsKKwkJLmlkZW50ID0gIkRlbGwgTGF0aXR1ZGUiLAorCQkubWF0Y2hl\n"
- "cyA9IHsKKwkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgQ29tcHV0ZXIiKSwKKwkJ\n"
- "CURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1FLCAiTGF0aXR1ZGUiKSwKKwkJfSwKKwl9LAorCXsK\n"
- "KwkJLmlkZW50ID0gIkRlbGwgSW5zcGlyb24gMiIsCisJCS5tYXRjaGVzID0geworCQkJRE1JX01B\n"
- "VENIKERNSV9TWVNfVkVORE9SLCAiRGVsbCBJbmMuIiksCisJCQlETUlfTUFUQ0goRE1JX1BST0RV\n"
- "Q1RfTkFNRSwgIkluc3Bpcm9uIiksCisJCX0sCisJfSwKKwl7CisJCS5pZGVudCA9ICJEZWxsIExh\n"
- "dGl0dWRlIEQ1MjAiLAorCQkubWF0Y2hlcyA9IHsKKwkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRP\n"
- "UiwgIkRlbGwgSW5jLiIpLAorCQkJRE1JX01BVENIKERNSV9QUk9EVUNUX05BTUUsICJMYXRpdHVk\n"
- "ZSBENTIwIiksCisJCX0sCisJCS5kcml2ZXJfZGF0YSA9ICh2b2lkICopJmk4a19jb25maWdfZGF0\n"
- "YVtERUxMX0xBVElUVURFX0Q1MjBdLAorCX0sCisJeworCQkuaWRlbnQgPSAiRGVsbCBMYXRpdHVk\n"
- "ZSAyIiwKKwkJLm1hdGNoZXMgPSB7CisJCQlETUlfTUFUQ0goRE1JX1NZU19WRU5ET1IsICJEZWxs\n"
- "IEluYy4iKSwKKwkJCURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1FLCAiTGF0aXR1ZGUiKSwKKwkJ\n"
- "fSwKKwl9LAorCXsJLyogVUsgSW5zcGlyb24gNjQwMCAgKi8KKwkJLmlkZW50ID0gIkRlbGwgSW5z\n"
- "cGlyb24gMyIsCisJCS5tYXRjaGVzID0geworCQkJRE1JX01BVENIKERNSV9TWVNfVkVORE9SLCAi\n"
- "RGVsbCBJbmMuIiksCisJCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIk1NMDYxIiksCisJ\n"
- "CX0sCisJfSwKKwl7CisJCS5pZGVudCA9ICJEZWxsIEluc3Bpcm9uIDMiLAorCQkubWF0Y2hlcyA9\n"
- "IHsKKwkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgSW5jLiIpLAorCQkJRE1JX01B\n"
- "VENIKERNSV9QUk9EVUNUX05BTUUsICJNUDA2MSIpLAorCQl9LAorCX0sCisJeworCQkuaWRlbnQg\n"
- "PSAiRGVsbCBQcmVjaXNpb24gNDkwIiwKKwkJLm1hdGNoZXMgPSB7CisJCQlETUlfTUFUQ0goRE1J\n"
- "X1NZU19WRU5ET1IsICJEZWxsIEluYy4iKSwKKwkJCURNSV9NQVRDSChETUlfUFJPRFVDVF9OQU1F\n"
- "LAorCQkJCSAgIlByZWNpc2lvbiBXb3JrU3RhdGlvbiA0OTAiKSwKKwkJfSwKKwkJLmRyaXZlcl9k\n"
- "YXRhID0gKHZvaWQgKikmaThrX2NvbmZpZ19kYXRhW0RFTExfUFJFQ0lTSU9OXzQ5MF0sCisJfSwK\n"
- "Kwl7CisJCS5pZGVudCA9ICJEZWxsIFByZWNpc2lvbiIsCisJCS5tYXRjaGVzID0geworCQkJRE1J\n"
- "X01BVENIKERNSV9TWVNfVkVORE9SLCAiRGVsbCBJbmMuIiksCisJCQlETUlfTUFUQ0goRE1JX1BS\n"
- "T0RVQ1RfTkFNRSwgIlByZWNpc2lvbiIpLAorCQl9LAorCX0sCisJeworCQkuaWRlbnQgPSAiRGVs\n"
- "bCBWb3N0cm8iLAorCQkubWF0Y2hlcyA9IHsKKwkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwg\n"
- "IkRlbGwgSW5jLiIpLAorCQkJRE1JX01BVENIKERNSV9QUk9EVUNUX05BTUUsICJWb3N0cm8iKSwK\n"
- "KwkJfSwKKwl9LAorCXsKKwkJLmlkZW50ID0gIkRlbGwgWFBTNDIxIiwKKwkJLm1hdGNoZXMgPSB7\n"
- "CisJCQlETUlfTUFUQ0goRE1JX1NZU19WRU5ET1IsICJEZWxsIEluYy4iKSwKKwkJCURNSV9NQVRD\n"
- "SChETUlfUFJPRFVDVF9OQU1FLCAiWFBTIEw0MjFYIiksCisJCX0sCisJfSwKKwl7CisJCS5pZGVu\n"
- "dCA9ICJEZWxsIFN0dWRpbyIsCisJCS5tYXRjaGVzID0geworCQkJRE1JX01BVENIKERNSV9TWVNf\n"
- "VkVORE9SLCAiRGVsbCBJbmMuIiksCisJCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwgIlN0\n"
- "dWRpbyIpLAorCQl9LAorCQkuZHJpdmVyX2RhdGEgPSAodm9pZCAqKSZpOGtfY29uZmlnX2RhdGFb\n"
- "REVMTF9TVFVESU9dLAorCX0sCisJeworCQkuaWRlbnQgPSAiRGVsbCBYUFMgMTMiLAorCQkubWF0\n"
- "Y2hlcyA9IHsKKwkJCURNSV9NQVRDSChETUlfU1lTX1ZFTkRPUiwgIkRlbGwgSW5jLiIpLAorCQkJ\n"
- "RE1JX01BVENIKERNSV9QUk9EVUNUX05BTUUsICJYUFMxMyIpLAorCQl9LAorCQkuZHJpdmVyX2Rh\n"
- "dGEgPSAodm9pZCAqKSZpOGtfY29uZmlnX2RhdGFbREVMTF9YUFNdLAorCX0sCisJeworCQkuaWRl\n"
- "bnQgPSAiRGVsbCBYUFMgTTE0MCIsCisJCS5tYXRjaGVzID0geworCQkJRE1JX01BVENIKERNSV9T\n"
- "WVNfVkVORE9SLCAiRGVsbCBJbmMuIiksCisJCQlETUlfTUFUQ0goRE1JX1BST0RVQ1RfTkFNRSwg\n"
- "Ik1YQzA1MSIpLAorCQl9LAorCQkuZHJpdmVyX2RhdGEgPSAodm9pZCAqKSZpOGtfY29uZmlnX2Rh\n"
- "dGFbREVMTF9YUFNdLAorCX0sCisJeyB9Cit9OworCitNT0RVTEVfREVWSUNFX1RBQkxFKGRtaSwg\n"
- "aThrX2RtaV90YWJsZSk7CisKKy8qCisgKiBQcm9iZSBmb3IgdGhlIHByZXNlbmNlIG9mIGEgc3Vw\n"
- "cG9ydGVkIGxhcHRvcC4KKyAqLworc3RhdGljIGludCBfX2luaXQgaThrX3Byb2JlKHZvaWQpCit7\n"
- "CisJY29uc3Qgc3RydWN0IGRtaV9zeXN0ZW1faWQgKmlkOworCWludCBmYW4sIHJldDsKKworCS8q\n"
- "CisJICogR2V0IERNSSBpbmZvcm1hdGlvbgorCSAqLworCWlmICghZG1pX2NoZWNrX3N5c3RlbShp\n"
- "OGtfZG1pX3RhYmxlKSkgeworCQlpZiAoIWlnbm9yZV9kbWkgJiYgIWZvcmNlKQorCQkJcmV0dXJu\n"
- "IC1FTk9ERVY7CisKKwkJcHJfaW5mbygibm90IHJ1bm5pbmcgb24gYSBzdXBwb3J0ZWQgRGVsbCBz\n"
- "eXN0ZW0uXG4iKTsKKwkJcHJfaW5mbygidmVuZG9yPSVzLCBtb2RlbD0lcywgdmVyc2lvbj0lc1xu\n"
- "IiwKKwkJCWk4a19nZXRfZG1pX2RhdGEoRE1JX1NZU19WRU5ET1IpLAorCQkJaThrX2dldF9kbWlf\n"
- "ZGF0YShETUlfUFJPRFVDVF9OQU1FKSwKKwkJCWk4a19nZXRfZG1pX2RhdGEoRE1JX0JJT1NfVkVS\n"
- "U0lPTikpOworCX0KKworCXN0cmxjcHkoYmlvc192ZXJzaW9uLCBpOGtfZ2V0X2RtaV9kYXRhKERN\n"
- "SV9CSU9TX1ZFUlNJT04pLAorCQlzaXplb2YoYmlvc192ZXJzaW9uKSk7CisKKwkvKgorCSAqIEdl\n"
- "dCBTTU0gRGVsbCBzaWduYXR1cmUKKwkgKi8KKwlpZiAoaThrX2dldF9kZWxsX3NpZ25hdHVyZShJ\n"
- "OEtfU01NX0dFVF9ERUxMX1NJRzEpICYmCisJICAgIGk4a19nZXRfZGVsbF9zaWduYXR1cmUoSThL\n"
- "X1NNTV9HRVRfREVMTF9TSUcyKSkgeworCQlwcl9lcnIoInVuYWJsZSB0byBnZXQgU01NIERlbGwg\n"
- "c2lnbmF0dXJlXG4iKTsKKwkJaWYgKCFmb3JjZSkKKwkJCXJldHVybiAtRU5PREVWOworCX0KKwor\n"
- "CS8qCisJICogU2V0IGZhbiBtdWx0aXBsaWVyIGFuZCBtYXhpbWFsIGZhbiBzcGVlZCBmcm9tIGRt\n"
- "aSBjb25maWcKKwkgKiBWYWx1ZXMgc3BlY2lmaWVkIGluIG1vZHVsZSBwYXJhbWV0ZXJzIG92ZXJy\n"
- "aWRlIHZhbHVlcyBmcm9tIGRtaQorCSAqLworCWlkID0gZG1pX2ZpcnN0X21hdGNoKGk4a19kbWlf\n"
- "dGFibGUpOworCWlmIChpZCAmJiBpZC0+ZHJpdmVyX2RhdGEpIHsKKwkJY29uc3Qgc3RydWN0IGk4\n"
- "a19jb25maWdfZGF0YSAqY29uZiA9IGlkLT5kcml2ZXJfZGF0YTsKKwkJaWYgKCFmYW5fbXVsdCAm\n"
- "JiBjb25mLT5mYW5fbXVsdCkKKwkJCWZhbl9tdWx0ID0gY29uZi0+ZmFuX211bHQ7CisJCWlmICgh\n"
- "ZmFuX21heCAmJiBjb25mLT5mYW5fbWF4KQorCQkJZmFuX21heCA9IGNvbmYtPmZhbl9tYXg7CisJ\n"
- "fQorCisJaThrX2Zhbl9tYXggPSBmYW5fbWF4ID8gOiBJOEtfRkFOX0hJR0g7CS8qIE11c3Qgbm90\n"
- "IGJlIDAgKi8KKwlpOGtfcHdtX211bHQgPSBESVZfUk9VTkRfVVAoMjU1LCBpOGtfZmFuX21heCk7\n"
- "CisKKwlpZiAoIWZhbl9tdWx0KSB7CisJCS8qCisJCSAqIEF1dG9kZXRlY3QgZmFuIG11bHRpcGxp\n"
- "ZXIgYmFzZWQgb24gbm9taW5hbCBycG0KKwkJICogSWYgZmFuIHJlcG9ydHMgcnBtIHZhbHVlIHRv\n"
- "byBoaWdoIHRoZW4gc2V0IG11bHRpcGxpZXIgdG8gMQorCQkgKi8KKwkJZm9yIChmYW4gPSAwOyBm\n"
- "YW4gPCAyOyArK2ZhbikgeworCQkJcmV0ID0gaThrX2dldF9mYW5fbm9taW5hbF9zcGVlZChmYW4s\n"
- "IGk4a19mYW5fbWF4KTsKKwkJCWlmIChyZXQgPCAwKQorCQkJCWNvbnRpbnVlOworCQkJaWYgKHJl\n"
- "dCA+IEk4S19GQU5fTUFYX1JQTSkKKwkJCQlpOGtfZmFuX211bHQgPSAxOworCQkJYnJlYWs7CisJ\n"
- "CX0KKwl9IGVsc2UgeworCQkvKiBGYW4gbXVsdGlwbGllciB3YXMgc3BlY2lmaWVkIGluIG1vZHVs\n"
- "ZSBwYXJhbSBvciBpbiBkbWkgKi8KKwkJaThrX2Zhbl9tdWx0ID0gZmFuX211bHQ7CisJfQorCisJ\n"
- "cmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgX19pbml0IGk4a19pbml0KHZvaWQpCit7CisJc3Ry\n"
- "dWN0IHByb2NfZGlyX2VudHJ5ICpwcm9jX2k4azsKKwlpbnQgZXJyOworCisJLyogQXJlIHdlIHJ1\n"
- "bm5pbmcgb24gYW4gc3VwcG9ydGVkIGxhcHRvcD8gKi8KKwlpZiAoaThrX3Byb2JlKCkpCisJCXJl\n"
- "dHVybiAtRU5PREVWOworCisJLyogUmVnaXN0ZXIgdGhlIHByb2MgZW50cnkgKi8KKwlwcm9jX2k4\n"
- "ayA9IHByb2NfY3JlYXRlKCJpOGsiLCAwLCBOVUxMLCAmaThrX2ZvcHMpOworCWlmICghcHJvY19p\n"
- "OGspCisJCXJldHVybiAtRU5PRU5UOworCisJZXJyID0gaThrX2luaXRfaHdtb24oKTsKKwlpZiAo\n"
- "ZXJyKQorCQlnb3RvIGV4aXRfcmVtb3ZlX3Byb2M7CisKKwlyZXR1cm4gMDsKKworIGV4aXRfcmVt\n"
- "b3ZlX3Byb2M6CisJcmVtb3ZlX3Byb2NfZW50cnkoImk4ayIsIE5VTEwpOworCXJldHVybiBlcnI7\n"
- "Cit9CisKK3N0YXRpYyB2b2lkIF9fZXhpdCBpOGtfZXhpdCh2b2lkKQoreworCWh3bW9uX2Rldmlj\n"
- "ZV91bnJlZ2lzdGVyKGk4a19od21vbl9kZXYpOworCXJlbW92ZV9wcm9jX2VudHJ5KCJpOGsiLCBO\n"
- "VUxMKTsKK30KKworbW9kdWxlX2luaXQoaThrX2luaXQpOworbW9kdWxlX2V4aXQoaThrX2V4aXQp\n"
- "OwotLSAKMS43LjkuNQoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f\n"
- "X19fX19fCmxtLXNlbnNvcnMgbWFpbGluZyBsaXN0CmxtLXNlbnNvcnNAbG0tc2Vuc29ycy5vcmcK\n"
- aHR0cDovL2xpc3RzLmxtLXNlbnNvcnMub3JnL21haWxtYW4vbGlzdGluZm8vbG0tc2Vuc29ycw=
+ "This commit moves i8k driver to hwmon tree under name dell-smm-hwmon which is\n"
+ "better name then abbreviation i8k. For backward compatibility is added macro\n"
+ "MODULE_ALIAS(\"i8k\") so modprobe will load driver also old name i8k. CONFIG_I8K\n"
+ "compile option was not changed.\n"
+ "\n"
+ "This commit also adds me as maintainer of this new dell-smm-hwmon driver and\n"
+ "remove Guenter Roeck from list who is implicit maintainer all hwmon drivers.\n"
+ "\n"
+ "Signed-off-by: Pali Roh\303\241r <pali.rohar@gmail.com>\n"
+ "---\n"
+ " MAINTAINERS                    |    4 +-\n"
+ " drivers/char/Makefile          |    1 -\n"
+ " drivers/char/i8k.c             | 1005 ---------------------------------------\n"
+ " drivers/hwmon/Makefile         |    1 +\n"
+ " drivers/hwmon/dell-smm-hwmon.c | 1007 ++++++++++++++++++++++++++++++++++++++++\n"
+ " 5 files changed, 1010 insertions(+), 1008 deletions(-)\n"
+ " delete mode 100644 drivers/char/i8k.c\n"
+ " create mode 100644 drivers/hwmon/dell-smm-hwmon.c\n"
+ "\n"
+ "diff --git a/MAINTAINERS b/MAINTAINERS\n"
+ "index 88c09ca..e54a07e 100644\n"
+ "--- a/MAINTAINERS\n"
+ "+++ b/MAINTAINERS\n"
+ "@@ -3063,9 +3063,9 @@ S:\tMaintained\n"
+ " F:\tdrivers/platform/x86/dell-laptop.c\n"
+ " \n"
+ " DELL LAPTOP SMM DRIVER\n"
+ "-M:\tGuenter Roeck <linux@roeck-us.net>\n"
+ "+M:\tPali Roh\303\241r <pali.rohar@gmail.com>\n"
+ " S:\tMaintained\n"
+ "-F:\tdrivers/char/i8k.c\n"
+ "+F:\tdrivers/hwmon/dell-smm-hwmon.c\n"
+ " F:\tinclude/uapi/linux/i8k.h\n"
+ " \n"
+ " DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas)\n"
+ "diff --git a/drivers/char/Makefile b/drivers/char/Makefile\n"
+ "index d06cde26..1d9cf00 100644\n"
+ "--- a/drivers/char/Makefile\n"
+ "+++ b/drivers/char/Makefile\n"
+ "@@ -36,7 +36,6 @@ else\n"
+ "   obj-$(CONFIG_NVRAM)\t+= nvram.o\n"
+ " endif\n"
+ " obj-$(CONFIG_TOSHIBA)\t\t+= toshiba.o\n"
+ "-obj-$(CONFIG_I8K)\t\t+= i8k.o\n"
+ " obj-$(CONFIG_DS1620)\t\t+= ds1620.o\n"
+ " obj-$(CONFIG_HW_RANDOM)\t\t+= hw_random/\n"
+ " obj-$(CONFIG_PPDEV)\t\t+= ppdev.o\n"
+ "diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c\n"
+ "deleted file mode 100644\n"
+ "index 24cc4ed..0000000\n"
+ "--- a/drivers/char/i8k.c\n"
+ "+++ /dev/null\n"
+ "@@ -1,1005 +0,0 @@\n"
+ "-/*\n"
+ "- * i8k.c -- Linux driver for accessing the SMM BIOS on Dell laptops.\n"
+ "- *\n"
+ "- * Copyright (C) 2001  Massimo Dal Zotto <dz@debian.org>\n"
+ "- *\n"
+ "- * Hwmon integration:\n"
+ "- * Copyright (C) 2011  Jean Delvare <jdelvare@suse.de>\n"
+ "- * Copyright (C) 2013, 2014  Guenter Roeck <linux@roeck-us.net>\n"
+ "- * Copyright (C) 2014  Pali Roh\303\241r <pali.rohar@gmail.com>\n"
+ "- *\n"
+ "- * This program is free software; you can redistribute it and/or modify it\n"
+ "- * under the terms of the GNU General Public License as published by the\n"
+ "- * Free Software Foundation; either version 2, or (at your option) any\n"
+ "- * later version.\n"
+ "- *\n"
+ "- * This program is distributed in the hope that it will be useful, but\n"
+ "- * WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
+ "- * General Public License for more details.\n"
+ "- */\n"
+ "-\n"
+ "-#define pr_fmt(fmt) KBUILD_MODNAME \": \" fmt\n"
+ "-\n"
+ "-#include <linux/delay.h>\n"
+ "-#include <linux/module.h>\n"
+ "-#include <linux/types.h>\n"
+ "-#include <linux/init.h>\n"
+ "-#include <linux/proc_fs.h>\n"
+ "-#include <linux/seq_file.h>\n"
+ "-#include <linux/dmi.h>\n"
+ "-#include <linux/capability.h>\n"
+ "-#include <linux/mutex.h>\n"
+ "-#include <linux/hwmon.h>\n"
+ "-#include <linux/hwmon-sysfs.h>\n"
+ "-#include <linux/uaccess.h>\n"
+ "-#include <linux/io.h>\n"
+ "-#include <linux/sched.h>\n"
+ "-\n"
+ "-#include <linux/i8k.h>\n"
+ "-\n"
+ "-#define I8K_SMM_FN_STATUS\t0x0025\n"
+ "-#define I8K_SMM_POWER_STATUS\t0x0069\n"
+ "-#define I8K_SMM_SET_FAN\t\t0x01a3\n"
+ "-#define I8K_SMM_GET_FAN\t\t0x00a3\n"
+ "-#define I8K_SMM_GET_SPEED\t0x02a3\n"
+ "-#define I8K_SMM_GET_FAN_TYPE\t0x03a3\n"
+ "-#define I8K_SMM_GET_NOM_SPEED\t0x04a3\n"
+ "-#define I8K_SMM_GET_TEMP\t0x10a3\n"
+ "-#define I8K_SMM_GET_TEMP_TYPE\t0x11a3\n"
+ "-#define I8K_SMM_GET_DELL_SIG1\t0xfea3\n"
+ "-#define I8K_SMM_GET_DELL_SIG2\t0xffa3\n"
+ "-\n"
+ "-#define I8K_FAN_MULT\t\t30\n"
+ "-#define I8K_FAN_MAX_RPM\t\t30000\n"
+ "-#define I8K_MAX_TEMP\t\t127\n"
+ "-\n"
+ "-#define I8K_FN_NONE\t\t0x00\n"
+ "-#define I8K_FN_UP\t\t0x01\n"
+ "-#define I8K_FN_DOWN\t\t0x02\n"
+ "-#define I8K_FN_MUTE\t\t0x04\n"
+ "-#define I8K_FN_MASK\t\t0x07\n"
+ "-#define I8K_FN_SHIFT\t\t8\n"
+ "-\n"
+ "-#define I8K_POWER_AC\t\t0x05\n"
+ "-#define I8K_POWER_BATTERY\t0x01\n"
+ "-\n"
+ "-static DEFINE_MUTEX(i8k_mutex);\n"
+ "-static char bios_version[4];\n"
+ "-static struct device *i8k_hwmon_dev;\n"
+ "-static u32 i8k_hwmon_flags;\n"
+ "-static uint i8k_fan_mult = I8K_FAN_MULT;\n"
+ "-static uint i8k_pwm_mult;\n"
+ "-static uint i8k_fan_max = I8K_FAN_HIGH;\n"
+ "-\n"
+ "-#define I8K_HWMON_HAVE_TEMP1\t(1 << 0)\n"
+ "-#define I8K_HWMON_HAVE_TEMP2\t(1 << 1)\n"
+ "-#define I8K_HWMON_HAVE_TEMP3\t(1 << 2)\n"
+ "-#define I8K_HWMON_HAVE_TEMP4\t(1 << 3)\n"
+ "-#define I8K_HWMON_HAVE_FAN1\t(1 << 4)\n"
+ "-#define I8K_HWMON_HAVE_FAN2\t(1 << 5)\n"
+ "-\n"
+ "-MODULE_AUTHOR(\"Massimo Dal Zotto (dz@debian.org)\");\n"
+ "-MODULE_DESCRIPTION(\"Driver for accessing SMM BIOS on Dell laptops\");\n"
+ "-MODULE_LICENSE(\"GPL\");\n"
+ "-\n"
+ "-static bool force;\n"
+ "-module_param(force, bool, 0);\n"
+ "-MODULE_PARM_DESC(force, \"Force loading without checking for supported models\");\n"
+ "-\n"
+ "-static bool ignore_dmi;\n"
+ "-module_param(ignore_dmi, bool, 0);\n"
+ "-MODULE_PARM_DESC(ignore_dmi, \"Continue probing hardware even if DMI data does not match\");\n"
+ "-\n"
+ "-static bool restricted;\n"
+ "-module_param(restricted, bool, 0);\n"
+ "-MODULE_PARM_DESC(restricted, \"Allow fan control if SYS_ADMIN capability set\");\n"
+ "-\n"
+ "-static bool power_status;\n"
+ "-module_param(power_status, bool, 0600);\n"
+ "-MODULE_PARM_DESC(power_status, \"Report power status in /proc/i8k\");\n"
+ "-\n"
+ "-static uint fan_mult;\n"
+ "-module_param(fan_mult, uint, 0);\n"
+ "-MODULE_PARM_DESC(fan_mult, \"Factor to multiply fan speed with (default: autodetect)\");\n"
+ "-\n"
+ "-static uint fan_max;\n"
+ "-module_param(fan_max, uint, 0);\n"
+ "-MODULE_PARM_DESC(fan_max, \"Maximum configurable fan speed (default: autodetect)\");\n"
+ "-\n"
+ "-static int i8k_open_fs(struct inode *inode, struct file *file);\n"
+ "-static long i8k_ioctl(struct file *, unsigned int, unsigned long);\n"
+ "-\n"
+ "-static const struct file_operations i8k_fops = {\n"
+ "-\t.owner\t\t= THIS_MODULE,\n"
+ "-\t.open\t\t= i8k_open_fs,\n"
+ "-\t.read\t\t= seq_read,\n"
+ "-\t.llseek\t\t= seq_lseek,\n"
+ "-\t.release\t= single_release,\n"
+ "-\t.unlocked_ioctl\t= i8k_ioctl,\n"
+ "-};\n"
+ "-\n"
+ "-struct smm_regs {\n"
+ "-\tunsigned int eax;\n"
+ "-\tunsigned int ebx __packed;\n"
+ "-\tunsigned int ecx __packed;\n"
+ "-\tunsigned int edx __packed;\n"
+ "-\tunsigned int esi __packed;\n"
+ "-\tunsigned int edi __packed;\n"
+ "-};\n"
+ "-\n"
+ "-static inline const char *i8k_get_dmi_data(int field)\n"
+ "-{\n"
+ "-\tconst char *dmi_data = dmi_get_system_info(field);\n"
+ "-\n"
+ "-\treturn dmi_data && *dmi_data ? dmi_data : \"?\";\n"
+ "-}\n"
+ "-\n"
+ "-/*\n"
+ "- * Call the System Management Mode BIOS. Code provided by Jonathan Buzzard.\n"
+ "- */\n"
+ "-static int i8k_smm(struct smm_regs *regs)\n"
+ "-{\n"
+ "-\tint rc;\n"
+ "-\tint eax = regs->eax;\n"
+ "-\tcpumask_var_t old_mask;\n"
+ "-\n"
+ "-\t/* SMM requires CPU 0 */\n"
+ "-\tif (!alloc_cpumask_var(&old_mask, GFP_KERNEL))\n"
+ "-\t\treturn -ENOMEM;\n"
+ "-\tcpumask_copy(old_mask, &current->cpus_allowed);\n"
+ "-\trc = set_cpus_allowed_ptr(current, cpumask_of(0));\n"
+ "-\tif (rc)\n"
+ "-\t\tgoto out;\n"
+ "-\tif (smp_processor_id() != 0) {\n"
+ "-\t\trc = -EBUSY;\n"
+ "-\t\tgoto out;\n"
+ "-\t}\n"
+ "-\n"
+ "-#if defined(CONFIG_X86_64)\n"
+ "-\tasm volatile(\"pushq %%rax\\n\\t\"\n"
+ "-\t\t\"movl 0(%%rax),%%edx\\n\\t\"\n"
+ "-\t\t\"pushq %%rdx\\n\\t\"\n"
+ "-\t\t\"movl 4(%%rax),%%ebx\\n\\t\"\n"
+ "-\t\t\"movl 8(%%rax),%%ecx\\n\\t\"\n"
+ "-\t\t\"movl 12(%%rax),%%edx\\n\\t\"\n"
+ "-\t\t\"movl 16(%%rax),%%esi\\n\\t\"\n"
+ "-\t\t\"movl 20(%%rax),%%edi\\n\\t\"\n"
+ "-\t\t\"popq %%rax\\n\\t\"\n"
+ "-\t\t\"out %%al,$0xb2\\n\\t\"\n"
+ "-\t\t\"out %%al,$0x84\\n\\t\"\n"
+ "-\t\t\"xchgq %%rax,(%%rsp)\\n\\t\"\n"
+ "-\t\t\"movl %%ebx,4(%%rax)\\n\\t\"\n"
+ "-\t\t\"movl %%ecx,8(%%rax)\\n\\t\"\n"
+ "-\t\t\"movl %%edx,12(%%rax)\\n\\t\"\n"
+ "-\t\t\"movl %%esi,16(%%rax)\\n\\t\"\n"
+ "-\t\t\"movl %%edi,20(%%rax)\\n\\t\"\n"
+ "-\t\t\"popq %%rdx\\n\\t\"\n"
+ "-\t\t\"movl %%edx,0(%%rax)\\n\\t\"\n"
+ "-\t\t\"pushfq\\n\\t\"\n"
+ "-\t\t\"popq %%rax\\n\\t\"\n"
+ "-\t\t\"andl $1,%%eax\\n\"\n"
+ "-\t\t: \"=a\"(rc)\n"
+ "-\t\t:    \"a\"(regs)\n"
+ "-\t\t:    \"%ebx\", \"%ecx\", \"%edx\", \"%esi\", \"%edi\", \"memory\");\n"
+ "-#else\n"
+ "-\tasm volatile(\"pushl %%eax\\n\\t\"\n"
+ "-\t    \"movl 0(%%eax),%%edx\\n\\t\"\n"
+ "-\t    \"push %%edx\\n\\t\"\n"
+ "-\t    \"movl 4(%%eax),%%ebx\\n\\t\"\n"
+ "-\t    \"movl 8(%%eax),%%ecx\\n\\t\"\n"
+ "-\t    \"movl 12(%%eax),%%edx\\n\\t\"\n"
+ "-\t    \"movl 16(%%eax),%%esi\\n\\t\"\n"
+ "-\t    \"movl 20(%%eax),%%edi\\n\\t\"\n"
+ "-\t    \"popl %%eax\\n\\t\"\n"
+ "-\t    \"out %%al,$0xb2\\n\\t\"\n"
+ "-\t    \"out %%al,$0x84\\n\\t\"\n"
+ "-\t    \"xchgl %%eax,(%%esp)\\n\\t\"\n"
+ "-\t    \"movl %%ebx,4(%%eax)\\n\\t\"\n"
+ "-\t    \"movl %%ecx,8(%%eax)\\n\\t\"\n"
+ "-\t    \"movl %%edx,12(%%eax)\\n\\t\"\n"
+ "-\t    \"movl %%esi,16(%%eax)\\n\\t\"\n"
+ "-\t    \"movl %%edi,20(%%eax)\\n\\t\"\n"
+ "-\t    \"popl %%edx\\n\\t\"\n"
+ "-\t    \"movl %%edx,0(%%eax)\\n\\t\"\n"
+ "-\t    \"lahf\\n\\t\"\n"
+ "-\t    \"shrl $8,%%eax\\n\\t\"\n"
+ "-\t    \"andl $1,%%eax\\n\"\n"
+ "-\t    : \"=a\"(rc)\n"
+ "-\t    :    \"a\"(regs)\n"
+ "-\t    :    \"%ebx\", \"%ecx\", \"%edx\", \"%esi\", \"%edi\", \"memory\");\n"
+ "-#endif\n"
+ "-\tif (rc != 0 || (regs->eax & 0xffff) == 0xffff || regs->eax == eax)\n"
+ "-\t\trc = -EINVAL;\n"
+ "-\n"
+ "-out:\n"
+ "-\tset_cpus_allowed_ptr(current, old_mask);\n"
+ "-\tfree_cpumask_var(old_mask);\n"
+ "-\treturn rc;\n"
+ "-}\n"
+ "-\n"
+ "-/*\n"
+ "- * Read the Fn key status.\n"
+ "- */\n"
+ "-static int i8k_get_fn_status(void)\n"
+ "-{\n"
+ "-\tstruct smm_regs regs = { .eax = I8K_SMM_FN_STATUS, };\n"
+ "-\tint rc;\n"
+ "-\n"
+ "-\trc = i8k_smm(&regs);\n"
+ "-\tif (rc < 0)\n"
+ "-\t\treturn rc;\n"
+ "-\n"
+ "-\tswitch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {\n"
+ "-\tcase I8K_FN_UP:\n"
+ "-\t\treturn I8K_VOL_UP;\n"
+ "-\tcase I8K_FN_DOWN:\n"
+ "-\t\treturn I8K_VOL_DOWN;\n"
+ "-\tcase I8K_FN_MUTE:\n"
+ "-\t\treturn I8K_VOL_MUTE;\n"
+ "-\tdefault:\n"
+ "-\t\treturn 0;\n"
+ "-\t}\n"
+ "-}\n"
+ "-\n"
+ "-/*\n"
+ "- * Read the power status.\n"
+ "- */\n"
+ "-static int i8k_get_power_status(void)\n"
+ "-{\n"
+ "-\tstruct smm_regs regs = { .eax = I8K_SMM_POWER_STATUS, };\n"
+ "-\tint rc;\n"
+ "-\n"
+ "-\trc = i8k_smm(&regs);\n"
+ "-\tif (rc < 0)\n"
+ "-\t\treturn rc;\n"
+ "-\n"
+ "-\treturn (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY;\n"
+ "-}\n"
+ "-\n"
+ "-/*\n"
+ "- * Read the fan status.\n"
+ "- */\n"
+ "-static int i8k_get_fan_status(int fan)\n"
+ "-{\n"
+ "-\tstruct smm_regs regs = { .eax = I8K_SMM_GET_FAN, };\n"
+ "-\n"
+ "-\tregs.ebx = fan & 0xff;\n"
+ "-\treturn i8k_smm(&regs) ? : regs.eax & 0xff;\n"
+ "-}\n"
+ "-\n"
+ "-/*\n"
+ "- * Read the fan speed in RPM.\n"
+ "- */\n"
+ "-static int i8k_get_fan_speed(int fan)\n"
+ "-{\n"
+ "-\tstruct smm_regs regs = { .eax = I8K_SMM_GET_SPEED, };\n"
+ "-\n"
+ "-\tregs.ebx = fan & 0xff;\n"
+ "-\treturn i8k_smm(&regs) ? : (regs.eax & 0xffff) * i8k_fan_mult;\n"
+ "-}\n"
+ "-\n"
+ "-/*\n"
+ "- * Read the fan type.\n"
+ "- */\n"
+ "-static int i8k_get_fan_type(int fan)\n"
+ "-{\n"
+ "-\tstruct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, };\n"
+ "-\n"
+ "-\tregs.ebx = fan & 0xff;\n"
+ "-\treturn i8k_smm(&regs) ? : regs.eax & 0xff;\n"
+ "-}\n"
+ "-\n"
+ "-/*\n"
+ "- * Read the fan nominal rpm for specific fan speed.\n"
+ "- */\n"
+ "-static int i8k_get_fan_nominal_speed(int fan, int speed)\n"
+ "-{\n"
+ "-\tstruct smm_regs regs = { .eax = I8K_SMM_GET_NOM_SPEED, };\n"
+ "-\n"
+ "-\tregs.ebx = (fan & 0xff) | (speed << 8);\n"
+ "-\treturn i8k_smm(&regs) ? : (regs.eax & 0xffff) * i8k_fan_mult;\n"
+ "-}\n"
+ "-\n"
+ "-/*\n"
+ "- * Set the fan speed (off, low, high). Returns the new fan status.\n"
+ "- */\n"
+ "-static int i8k_set_fan(int fan, int speed)\n"
+ "-{\n"
+ "-\tstruct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };\n"
+ "-\n"
+ "-\tspeed = (speed < 0) ? 0 : ((speed > i8k_fan_max) ? i8k_fan_max : speed);\n"
+ "-\tregs.ebx = (fan & 0xff) | (speed << 8);\n"
+ "-\n"
+ "-\treturn i8k_smm(&regs) ? : i8k_get_fan_status(fan);\n"
+ "-}\n"
+ "-\n"
+ "-static int i8k_get_temp_type(int sensor)\n"
+ "-{\n"
+ "-\tstruct smm_regs regs = { .eax = I8K_SMM_GET_TEMP_TYPE, };\n"
+ "-\n"
+ "-\tregs.ebx = sensor & 0xff;\n"
+ "-\treturn i8k_smm(&regs) ? : regs.eax & 0xff;\n"
+ "-}\n"
+ "-\n"
+ "-/*\n"
+ "- * Read the cpu temperature.\n"
+ "- */\n"
+ "-static int _i8k_get_temp(int sensor)\n"
+ "-{\n"
+ "-\tstruct smm_regs regs = {\n"
+ "-\t\t.eax = I8K_SMM_GET_TEMP,\n"
+ "-\t\t.ebx = sensor & 0xff,\n"
+ "-\t};\n"
+ "-\n"
+ "-\treturn i8k_smm(&regs) ? : regs.eax & 0xff;\n"
+ "-}\n"
+ "-\n"
+ "-static int i8k_get_temp(int sensor)\n"
+ "-{\n"
+ "-\tint temp = _i8k_get_temp(sensor);\n"
+ "-\n"
+ "-\t/*\n"
+ "-\t * Sometimes the temperature sensor returns 0x99, which is out of range.\n"
+ "-\t * In this case we retry (once) before returning an error.\n"
+ "-\t # 1003655137 00000058 00005a4b\n"
+ "-\t # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees\n"
+ "-\t # 1003655139 00000054 00005c52\n"
+ "-\t */\n"
+ "-\tif (temp == 0x99) {\n"
+ "-\t\tmsleep(100);\n"
+ "-\t\ttemp = _i8k_get_temp(sensor);\n"
+ "-\t}\n"
+ "-\t/*\n"
+ "-\t * Return -ENODATA for all invalid temperatures.\n"
+ "-\t *\n"
+ "-\t * Known instances are the 0x99 value as seen above as well as\n"
+ "-\t * 0xc1 (193), which may be returned when trying to read the GPU\n"
+ "-\t * temperature if the system supports a GPU and it is currently\n"
+ "-\t * turned off.\n"
+ "-\t */\n"
+ "-\tif (temp > I8K_MAX_TEMP)\n"
+ "-\t\treturn -ENODATA;\n"
+ "-\n"
+ "-\treturn temp;\n"
+ "-}\n"
+ "-\n"
+ "-static int i8k_get_dell_signature(int req_fn)\n"
+ "-{\n"
+ "-\tstruct smm_regs regs = { .eax = req_fn, };\n"
+ "-\tint rc;\n"
+ "-\n"
+ "-\trc = i8k_smm(&regs);\n"
+ "-\tif (rc < 0)\n"
+ "-\t\treturn rc;\n"
+ "-\n"
+ "-\treturn regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1;\n"
+ "-}\n"
+ "-\n"
+ "-static int\n"
+ "-i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg)\n"
+ "-{\n"
+ "-\tint val = 0;\n"
+ "-\tint speed;\n"
+ "-\tunsigned char buff[16];\n"
+ "-\tint __user *argp = (int __user *)arg;\n"
+ "-\n"
+ "-\tif (!argp)\n"
+ "-\t\treturn -EINVAL;\n"
+ "-\n"
+ "-\tswitch (cmd) {\n"
+ "-\tcase I8K_BIOS_VERSION:\n"
+ "-\t\tval = (bios_version[0] << 16) |\n"
+ "-\t\t\t\t(bios_version[1] << 8) | bios_version[2];\n"
+ "-\t\tbreak;\n"
+ "-\n"
+ "-\tcase I8K_MACHINE_ID:\n"
+ "-\t\tmemset(buff, 0, 16);\n"
+ "-\t\tstrlcpy(buff, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),\n"
+ "-\t\t\tsizeof(buff));\n"
+ "-\t\tbreak;\n"
+ "-\n"
+ "-\tcase I8K_FN_STATUS:\n"
+ "-\t\tval = i8k_get_fn_status();\n"
+ "-\t\tbreak;\n"
+ "-\n"
+ "-\tcase I8K_POWER_STATUS:\n"
+ "-\t\tval = i8k_get_power_status();\n"
+ "-\t\tbreak;\n"
+ "-\n"
+ "-\tcase I8K_GET_TEMP:\n"
+ "-\t\tval = i8k_get_temp(0);\n"
+ "-\t\tbreak;\n"
+ "-\n"
+ "-\tcase I8K_GET_SPEED:\n"
+ "-\t\tif (copy_from_user(&val, argp, sizeof(int)))\n"
+ "-\t\t\treturn -EFAULT;\n"
+ "-\n"
+ "-\t\tval = i8k_get_fan_speed(val);\n"
+ "-\t\tbreak;\n"
+ "-\n"
+ "-\tcase I8K_GET_FAN:\n"
+ "-\t\tif (copy_from_user(&val, argp, sizeof(int)))\n"
+ "-\t\t\treturn -EFAULT;\n"
+ "-\n"
+ "-\t\tval = i8k_get_fan_status(val);\n"
+ "-\t\tbreak;\n"
+ "-\n"
+ "-\tcase I8K_SET_FAN:\n"
+ "-\t\tif (restricted && !capable(CAP_SYS_ADMIN))\n"
+ "-\t\t\treturn -EPERM;\n"
+ "-\n"
+ "-\t\tif (copy_from_user(&val, argp, sizeof(int)))\n"
+ "-\t\t\treturn -EFAULT;\n"
+ "-\n"
+ "-\t\tif (copy_from_user(&speed, argp + 1, sizeof(int)))\n"
+ "-\t\t\treturn -EFAULT;\n"
+ "-\n"
+ "-\t\tval = i8k_set_fan(val, speed);\n"
+ "-\t\tbreak;\n"
+ "-\n"
+ "-\tdefault:\n"
+ "-\t\treturn -EINVAL;\n"
+ "-\t}\n"
+ "-\n"
+ "-\tif (val < 0)\n"
+ "-\t\treturn val;\n"
+ "-\n"
+ "-\tswitch (cmd) {\n"
+ "-\tcase I8K_BIOS_VERSION:\n"
+ "-\t\tif (copy_to_user(argp, &val, 4))\n"
+ "-\t\t\treturn -EFAULT;\n"
+ "-\n"
+ "-\t\tbreak;\n"
+ "-\tcase I8K_MACHINE_ID:\n"
+ "-\t\tif (copy_to_user(argp, buff, 16))\n"
+ "-\t\t\treturn -EFAULT;\n"
+ "-\n"
+ "-\t\tbreak;\n"
+ "-\tdefault:\n"
+ "-\t\tif (copy_to_user(argp, &val, sizeof(int)))\n"
+ "-\t\t\treturn -EFAULT;\n"
+ "-\n"
+ "-\t\tbreak;\n"
+ "-\t}\n"
+ "-\n"
+ "-\treturn 0;\n"
+ "-}\n"
+ "-\n"
+ "-static long i8k_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)\n"
+ "-{\n"
+ "-\tlong ret;\n"
+ "-\n"
+ "-\tmutex_lock(&i8k_mutex);\n"
+ "-\tret = i8k_ioctl_unlocked(fp, cmd, arg);\n"
+ "-\tmutex_unlock(&i8k_mutex);\n"
+ "-\n"
+ "-\treturn ret;\n"
+ "-}\n"
+ "-\n"
+ "-/*\n"
+ "- * Print the information for /proc/i8k.\n"
+ "- */\n"
+ "-static int i8k_proc_show(struct seq_file *seq, void *offset)\n"
+ "-{\n"
+ "-\tint fn_key, cpu_temp, ac_power;\n"
+ "-\tint left_fan, right_fan, left_speed, right_speed;\n"
+ "-\n"
+ "-\tcpu_temp\t= i8k_get_temp(0);\t\t\t/* 11100 \302\265s */\n"
+ "-\tleft_fan\t= i8k_get_fan_status(I8K_FAN_LEFT);\t/*   580 \302\265s */\n"
+ "-\tright_fan\t= i8k_get_fan_status(I8K_FAN_RIGHT);\t/*   580 \302\265s */\n"
+ "-\tleft_speed\t= i8k_get_fan_speed(I8K_FAN_LEFT);\t/*   580 \302\265s */\n"
+ "-\tright_speed\t= i8k_get_fan_speed(I8K_FAN_RIGHT);\t/*   580 \302\265s */\n"
+ "-\tfn_key\t\t= i8k_get_fn_status();\t\t\t/*   750 \302\265s */\n"
+ "-\tif (power_status)\n"
+ "-\t\tac_power = i8k_get_power_status();\t\t/* 14700 \302\265s */\n"
+ "-\telse\n"
+ "-\t\tac_power = -1;\n"
+ "-\n"
+ "-\t/*\n"
+ "-\t * Info:\n"
+ "-\t *\n"
+ "-\t * 1)  Format version (this will change if format changes)\n"
+ "-\t * 2)  BIOS version\n"
+ "-\t * 3)  BIOS machine ID\n"
+ "-\t * 4)  Cpu temperature\n"
+ "-\t * 5)  Left fan status\n"
+ "-\t * 6)  Right fan status\n"
+ "-\t * 7)  Left fan speed\n"
+ "-\t * 8)  Right fan speed\n"
+ "-\t * 9)  AC power\n"
+ "-\t * 10) Fn Key status\n"
+ "-\t */\n"
+ "-\treturn seq_printf(seq, \"%s %s %s %d %d %d %d %d %d %d\\n\",\n"
+ "-\t\t\t  I8K_PROC_FMT,\n"
+ "-\t\t\t  bios_version,\n"
+ "-\t\t\t  i8k_get_dmi_data(DMI_PRODUCT_SERIAL),\n"
+ "-\t\t\t  cpu_temp,\n"
+ "-\t\t\t  left_fan, right_fan, left_speed, right_speed,\n"
+ "-\t\t\t  ac_power, fn_key);\n"
+ "-}\n"
+ "-\n"
+ "-static int i8k_open_fs(struct inode *inode, struct file *file)\n"
+ "-{\n"
+ "-\treturn single_open(file, i8k_proc_show, NULL);\n"
+ "-}\n"
+ "-\n"
+ "-\n"
+ "-/*\n"
+ "- * Hwmon interface\n"
+ "- */\n"
+ "-\n"
+ "-static ssize_t i8k_hwmon_show_temp_label(struct device *dev,\n"
+ "-\t\t\t\t\t struct device_attribute *devattr,\n"
+ "-\t\t\t\t\t char *buf)\n"
+ "-{\n"
+ "-\tstatic const char * const labels[] = {\n"
+ "-\t\t\"CPU\",\n"
+ "-\t\t\"GPU\",\n"
+ "-\t\t\"SODIMM\",\n"
+ "-\t\t\"Other\",\n"
+ "-\t\t\"Ambient\",\n"
+ "-\t\t\"Other\",\n"
+ "-\t};\n"
+ "-\tint index = to_sensor_dev_attr(devattr)->index;\n"
+ "-\tint type;\n"
+ "-\n"
+ "-\ttype = i8k_get_temp_type(index);\n"
+ "-\tif (type < 0)\n"
+ "-\t\treturn type;\n"
+ "-\tif (type >= ARRAY_SIZE(labels))\n"
+ "-\t\ttype = ARRAY_SIZE(labels) - 1;\n"
+ "-\treturn sprintf(buf, \"%s\\n\", labels[type]);\n"
+ "-}\n"
+ "-\n"
+ "-static ssize_t i8k_hwmon_show_temp(struct device *dev,\n"
+ "-\t\t\t\t   struct device_attribute *devattr,\n"
+ "-\t\t\t\t   char *buf)\n"
+ "-{\n"
+ "-\tint index = to_sensor_dev_attr(devattr)->index;\n"
+ "-\tint temp;\n"
+ "-\n"
+ "-\ttemp = i8k_get_temp(index);\n"
+ "-\tif (temp < 0)\n"
+ "-\t\treturn temp;\n"
+ "-\treturn sprintf(buf, \"%d\\n\", temp * 1000);\n"
+ "-}\n"
+ "-\n"
+ "-static ssize_t i8k_hwmon_show_fan_label(struct device *dev,\n"
+ "-\t\t\t\t\tstruct device_attribute *devattr,\n"
+ "-\t\t\t\t\tchar *buf)\n"
+ "-{\n"
+ "-\tstatic const char * const labels[] = {\n"
+ "-\t\t\"Processor Fan\",\n"
+ "-\t\t\"Motherboard Fan\",\n"
+ "-\t\t\"Video Fan\",\n"
+ "-\t\t\"Power Supply Fan\",\n"
+ "-\t\t\"Chipset Fan\",\n"
+ "-\t\t\"Other Fan\",\n"
+ "-\t};\n"
+ "-\tint index = to_sensor_dev_attr(devattr)->index;\n"
+ "-\tbool dock = false;\n"
+ "-\tint type;\n"
+ "-\n"
+ "-\ttype = i8k_get_fan_type(index);\n"
+ "-\tif (type < 0)\n"
+ "-\t\treturn type;\n"
+ "-\n"
+ "-\tif (type & 0x10) {\n"
+ "-\t\tdock = true;\n"
+ "-\t\ttype &= 0x0F;\n"
+ "-\t}\n"
+ "-\n"
+ "-\tif (type >= ARRAY_SIZE(labels))\n"
+ "-\t\ttype = (ARRAY_SIZE(labels) - 1);\n"
+ "-\n"
+ "-\treturn sprintf(buf, \"%s%s\\n\", (dock ? \"Docking \" : \"\"), labels[type]);\n"
+ "-}\n"
+ "-\n"
+ "-static ssize_t i8k_hwmon_show_fan(struct device *dev,\n"
+ "-\t\t\t\t  struct device_attribute *devattr,\n"
+ "-\t\t\t\t  char *buf)\n"
+ "-{\n"
+ "-\tint index = to_sensor_dev_attr(devattr)->index;\n"
+ "-\tint fan_speed;\n"
+ "-\n"
+ "-\tfan_speed = i8k_get_fan_speed(index);\n"
+ "-\tif (fan_speed < 0)\n"
+ "-\t\treturn fan_speed;\n"
+ "-\treturn sprintf(buf, \"%d\\n\", fan_speed);\n"
+ "-}\n"
+ "-\n"
+ "-static ssize_t i8k_hwmon_show_pwm(struct device *dev,\n"
+ "-\t\t\t\t  struct device_attribute *devattr,\n"
+ "-\t\t\t\t  char *buf)\n"
+ "-{\n"
+ "-\tint index = to_sensor_dev_attr(devattr)->index;\n"
+ "-\tint status;\n"
+ "-\n"
+ "-\tstatus = i8k_get_fan_status(index);\n"
+ "-\tif (status < 0)\n"
+ "-\t\treturn -EIO;\n"
+ "-\treturn sprintf(buf, \"%d\\n\", clamp_val(status * i8k_pwm_mult, 0, 255));\n"
+ "-}\n"
+ "-\n"
+ "-static ssize_t i8k_hwmon_set_pwm(struct device *dev,\n"
+ "-\t\t\t\t struct device_attribute *attr,\n"
+ "-\t\t\t\t const char *buf, size_t count)\n"
+ "-{\n"
+ "-\tint index = to_sensor_dev_attr(attr)->index;\n"
+ "-\tunsigned long val;\n"
+ "-\tint err;\n"
+ "-\n"
+ "-\terr = kstrtoul(buf, 10, &val);\n"
+ "-\tif (err)\n"
+ "-\t\treturn err;\n"
+ "-\tval = clamp_val(DIV_ROUND_CLOSEST(val, i8k_pwm_mult), 0, i8k_fan_max);\n"
+ "-\n"
+ "-\tmutex_lock(&i8k_mutex);\n"
+ "-\terr = i8k_set_fan(index, val);\n"
+ "-\tmutex_unlock(&i8k_mutex);\n"
+ "-\n"
+ "-\treturn err < 0 ? -EIO : count;\n"
+ "-}\n"
+ "-\n"
+ "-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 0);\n"
+ "-static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,\n"
+ "-\t\t\t  0);\n"
+ "-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 1);\n"
+ "-static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,\n"
+ "-\t\t\t  1);\n"
+ "-static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 2);\n"
+ "-static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,\n"
+ "-\t\t\t  2);\n"
+ "-static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 3);\n"
+ "-static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,\n"
+ "-\t\t\t  3);\n"
+ "-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, 0);\n"
+ "-static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL,\n"
+ "-\t\t\t  0);\n"
+ "-static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,\n"
+ "-\t\t\t  i8k_hwmon_set_pwm, 0);\n"
+ "-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL,\n"
+ "-\t\t\t  1);\n"
+ "-static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL,\n"
+ "-\t\t\t  1);\n"
+ "-static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,\n"
+ "-\t\t\t  i8k_hwmon_set_pwm, 1);\n"
+ "-\n"
+ "-static struct attribute *i8k_attrs[] = {\n"
+ "-\t&sensor_dev_attr_temp1_input.dev_attr.attr,\t/* 0 */\n"
+ "-\t&sensor_dev_attr_temp1_label.dev_attr.attr,\t/* 1 */\n"
+ "-\t&sensor_dev_attr_temp2_input.dev_attr.attr,\t/* 2 */\n"
+ "-\t&sensor_dev_attr_temp2_label.dev_attr.attr,\t/* 3 */\n"
+ "-\t&sensor_dev_attr_temp3_input.dev_attr.attr,\t/* 4 */\n"
+ "-\t&sensor_dev_attr_temp3_label.dev_attr.attr,\t/* 5 */\n"
+ "-\t&sensor_dev_attr_temp4_input.dev_attr.attr,\t/* 6 */\n"
+ "-\t&sensor_dev_attr_temp4_label.dev_attr.attr,\t/* 7 */\n"
+ "-\t&sensor_dev_attr_fan1_input.dev_attr.attr,\t/* 8 */\n"
+ "-\t&sensor_dev_attr_fan1_label.dev_attr.attr,\t/* 9 */\n"
+ "-\t&sensor_dev_attr_pwm1.dev_attr.attr,\t\t/* 10 */\n"
+ "-\t&sensor_dev_attr_fan2_input.dev_attr.attr,\t/* 11 */\n"
+ "-\t&sensor_dev_attr_fan2_label.dev_attr.attr,\t/* 12 */\n"
+ "-\t&sensor_dev_attr_pwm2.dev_attr.attr,\t\t/* 13 */\n"
+ "-\tNULL\n"
+ "-};\n"
+ "-\n"
+ "-static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,\n"
+ "-\t\t\t      int index)\n"
+ "-{\n"
+ "-\tif (index >= 0 && index <= 1 &&\n"
+ "-\t    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))\n"
+ "-\t\treturn 0;\n"
+ "-\tif (index >= 2 && index <= 3 &&\n"
+ "-\t    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2))\n"
+ "-\t\treturn 0;\n"
+ "-\tif (index >= 4 && index <= 5 &&\n"
+ "-\t    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3))\n"
+ "-\t\treturn 0;\n"
+ "-\tif (index >= 6 && index <= 7 &&\n"
+ "-\t    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4))\n"
+ "-\t\treturn 0;\n"
+ "-\tif (index >= 8 && index <= 10 &&\n"
+ "-\t    !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1))\n"
+ "-\t\treturn 0;\n"
+ "-\tif (index >= 11 && index <= 13 &&\n"
+ "-\t    !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2))\n"
+ "-\t\treturn 0;\n"
+ "-\n"
+ "-\treturn attr->mode;\n"
+ "-}\n"
+ "-\n"
+ "-static const struct attribute_group i8k_group = {\n"
+ "-\t.attrs = i8k_attrs,\n"
+ "-\t.is_visible = i8k_is_visible,\n"
+ "-};\n"
+ "-__ATTRIBUTE_GROUPS(i8k);\n"
+ "-\n"
+ "-static int __init i8k_init_hwmon(void)\n"
+ "-{\n"
+ "-\tint err;\n"
+ "-\n"
+ "-\ti8k_hwmon_flags = 0;\n"
+ "-\n"
+ "-\t/* CPU temperature attributes, if temperature type is OK */\n"
+ "-\terr = i8k_get_temp_type(0);\n"
+ "-\tif (err >= 0)\n"
+ "-\t\ti8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP1;\n"
+ "-\t/* check for additional temperature sensors */\n"
+ "-\terr = i8k_get_temp_type(1);\n"
+ "-\tif (err >= 0)\n"
+ "-\t\ti8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP2;\n"
+ "-\terr = i8k_get_temp_type(2);\n"
+ "-\tif (err >= 0)\n"
+ "-\t\ti8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP3;\n"
+ "-\terr = i8k_get_temp_type(3);\n"
+ "-\tif (err >= 0)\n"
+ "-\t\ti8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4;\n"
+ "-\n"
+ "-\t/* First fan attributes, if fan type is OK */\n"
+ "-\terr = i8k_get_fan_type(0);\n"
+ "-\tif (err >= 0)\n"
+ "-\t\ti8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1;\n"
+ "-\n"
+ "-\t/* Second fan attributes, if fan type is OK */\n"
+ "-\terr = i8k_get_fan_type(1);\n"
+ "-\tif (err >= 0)\n"
+ "-\t\ti8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2;\n"
+ "-\n"
+ "-\ti8k_hwmon_dev = hwmon_device_register_with_groups(NULL, \"i8k\", NULL,\n"
+ "-\t\t\t\t\t\t\t  i8k_groups);\n"
+ "-\tif (IS_ERR(i8k_hwmon_dev)) {\n"
+ "-\t\terr = PTR_ERR(i8k_hwmon_dev);\n"
+ "-\t\ti8k_hwmon_dev = NULL;\n"
+ "-\t\tpr_err(\"hwmon registration failed (%d)\\n\", err);\n"
+ "-\t\treturn err;\n"
+ "-\t}\n"
+ "-\treturn 0;\n"
+ "-}\n"
+ "-\n"
+ "-struct i8k_config_data {\n"
+ "-\tuint fan_mult;\n"
+ "-\tuint fan_max;\n"
+ "-};\n"
+ "-\n"
+ "-enum i8k_configs {\n"
+ "-\tDELL_LATITUDE_D520,\n"
+ "-\tDELL_PRECISION_490,\n"
+ "-\tDELL_STUDIO,\n"
+ "-\tDELL_XPS,\n"
+ "-};\n"
+ "-\n"
+ "-static const struct i8k_config_data i8k_config_data[] = {\n"
+ "-\t[DELL_LATITUDE_D520] = {\n"
+ "-\t\t.fan_mult = 1,\n"
+ "-\t\t.fan_max = I8K_FAN_TURBO,\n"
+ "-\t},\n"
+ "-\t[DELL_PRECISION_490] = {\n"
+ "-\t\t.fan_mult = 1,\n"
+ "-\t\t.fan_max = I8K_FAN_TURBO,\n"
+ "-\t},\n"
+ "-\t[DELL_STUDIO] = {\n"
+ "-\t\t.fan_mult = 1,\n"
+ "-\t\t.fan_max = I8K_FAN_HIGH,\n"
+ "-\t},\n"
+ "-\t[DELL_XPS] = {\n"
+ "-\t\t.fan_mult = 1,\n"
+ "-\t\t.fan_max = I8K_FAN_HIGH,\n"
+ "-\t},\n"
+ "-};\n"
+ "-\n"
+ "-static struct dmi_system_id i8k_dmi_table[] __initdata = {\n"
+ "-\t{\n"
+ "-\t\t.ident = \"Dell Inspiron\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Computer\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Inspiron\"),\n"
+ "-\t\t},\n"
+ "-\t},\n"
+ "-\t{\n"
+ "-\t\t.ident = \"Dell Latitude\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Computer\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Latitude\"),\n"
+ "-\t\t},\n"
+ "-\t},\n"
+ "-\t{\n"
+ "-\t\t.ident = \"Dell Inspiron 2\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Inspiron\"),\n"
+ "-\t\t},\n"
+ "-\t},\n"
+ "-\t{\n"
+ "-\t\t.ident = \"Dell Latitude D520\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Latitude D520\"),\n"
+ "-\t\t},\n"
+ "-\t\t.driver_data = (void *)&i8k_config_data[DELL_LATITUDE_D520],\n"
+ "-\t},\n"
+ "-\t{\n"
+ "-\t\t.ident = \"Dell Latitude 2\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Latitude\"),\n"
+ "-\t\t},\n"
+ "-\t},\n"
+ "-\t{\t/* UK Inspiron 6400  */\n"
+ "-\t\t.ident = \"Dell Inspiron 3\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"MM061\"),\n"
+ "-\t\t},\n"
+ "-\t},\n"
+ "-\t{\n"
+ "-\t\t.ident = \"Dell Inspiron 3\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"MP061\"),\n"
+ "-\t\t},\n"
+ "-\t},\n"
+ "-\t{\n"
+ "-\t\t.ident = \"Dell Precision 490\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME,\n"
+ "-\t\t\t\t  \"Precision WorkStation 490\"),\n"
+ "-\t\t},\n"
+ "-\t\t.driver_data = (void *)&i8k_config_data[DELL_PRECISION_490],\n"
+ "-\t},\n"
+ "-\t{\n"
+ "-\t\t.ident = \"Dell Precision\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Precision\"),\n"
+ "-\t\t},\n"
+ "-\t},\n"
+ "-\t{\n"
+ "-\t\t.ident = \"Dell Vostro\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Vostro\"),\n"
+ "-\t\t},\n"
+ "-\t},\n"
+ "-\t{\n"
+ "-\t\t.ident = \"Dell XPS421\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"XPS L421X\"),\n"
+ "-\t\t},\n"
+ "-\t},\n"
+ "-\t{\n"
+ "-\t\t.ident = \"Dell Studio\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Studio\"),\n"
+ "-\t\t},\n"
+ "-\t\t.driver_data = (void *)&i8k_config_data[DELL_STUDIO],\n"
+ "-\t},\n"
+ "-\t{\n"
+ "-\t\t.ident = \"Dell XPS 13\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"XPS13\"),\n"
+ "-\t\t},\n"
+ "-\t\t.driver_data = (void *)&i8k_config_data[DELL_XPS],\n"
+ "-\t},\n"
+ "-\t{\n"
+ "-\t\t.ident = \"Dell XPS M140\",\n"
+ "-\t\t.matches = {\n"
+ "-\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "-\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"MXC051\"),\n"
+ "-\t\t},\n"
+ "-\t\t.driver_data = (void *)&i8k_config_data[DELL_XPS],\n"
+ "-\t},\n"
+ "-\t{ }\n"
+ "-};\n"
+ "-\n"
+ "-MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);\n"
+ "-\n"
+ "-/*\n"
+ "- * Probe for the presence of a supported laptop.\n"
+ "- */\n"
+ "-static int __init i8k_probe(void)\n"
+ "-{\n"
+ "-\tconst struct dmi_system_id *id;\n"
+ "-\tint fan, ret;\n"
+ "-\n"
+ "-\t/*\n"
+ "-\t * Get DMI information\n"
+ "-\t */\n"
+ "-\tif (!dmi_check_system(i8k_dmi_table)) {\n"
+ "-\t\tif (!ignore_dmi && !force)\n"
+ "-\t\t\treturn -ENODEV;\n"
+ "-\n"
+ "-\t\tpr_info(\"not running on a supported Dell system.\\n\");\n"
+ "-\t\tpr_info(\"vendor=%s, model=%s, version=%s\\n\",\n"
+ "-\t\t\ti8k_get_dmi_data(DMI_SYS_VENDOR),\n"
+ "-\t\t\ti8k_get_dmi_data(DMI_PRODUCT_NAME),\n"
+ "-\t\t\ti8k_get_dmi_data(DMI_BIOS_VERSION));\n"
+ "-\t}\n"
+ "-\n"
+ "-\tstrlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION),\n"
+ "-\t\tsizeof(bios_version));\n"
+ "-\n"
+ "-\t/*\n"
+ "-\t * Get SMM Dell signature\n"
+ "-\t */\n"
+ "-\tif (i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG1) &&\n"
+ "-\t    i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG2)) {\n"
+ "-\t\tpr_err(\"unable to get SMM Dell signature\\n\");\n"
+ "-\t\tif (!force)\n"
+ "-\t\t\treturn -ENODEV;\n"
+ "-\t}\n"
+ "-\n"
+ "-\t/*\n"
+ "-\t * Set fan multiplier and maximal fan speed from dmi config\n"
+ "-\t * Values specified in module parameters override values from dmi\n"
+ "-\t */\n"
+ "-\tid = dmi_first_match(i8k_dmi_table);\n"
+ "-\tif (id && id->driver_data) {\n"
+ "-\t\tconst struct i8k_config_data *conf = id->driver_data;\n"
+ "-\t\tif (!fan_mult && conf->fan_mult)\n"
+ "-\t\t\tfan_mult = conf->fan_mult;\n"
+ "-\t\tif (!fan_max && conf->fan_max)\n"
+ "-\t\t\tfan_max = conf->fan_max;\n"
+ "-\t}\n"
+ "-\n"
+ "-\ti8k_fan_max = fan_max ? : I8K_FAN_HIGH;\t/* Must not be 0 */\n"
+ "-\ti8k_pwm_mult = DIV_ROUND_UP(255, i8k_fan_max);\n"
+ "-\n"
+ "-\tif (!fan_mult) {\n"
+ "-\t\t/*\n"
+ "-\t\t * Autodetect fan multiplier based on nominal rpm\n"
+ "-\t\t * If fan reports rpm value too high then set multiplier to 1\n"
+ "-\t\t */\n"
+ "-\t\tfor (fan = 0; fan < 2; ++fan) {\n"
+ "-\t\t\tret = i8k_get_fan_nominal_speed(fan, i8k_fan_max);\n"
+ "-\t\t\tif (ret < 0)\n"
+ "-\t\t\t\tcontinue;\n"
+ "-\t\t\tif (ret > I8K_FAN_MAX_RPM)\n"
+ "-\t\t\t\ti8k_fan_mult = 1;\n"
+ "-\t\t\tbreak;\n"
+ "-\t\t}\n"
+ "-\t} else {\n"
+ "-\t\t/* Fan multiplier was specified in module param or in dmi */\n"
+ "-\t\ti8k_fan_mult = fan_mult;\n"
+ "-\t}\n"
+ "-\n"
+ "-\treturn 0;\n"
+ "-}\n"
+ "-\n"
+ "-static int __init i8k_init(void)\n"
+ "-{\n"
+ "-\tstruct proc_dir_entry *proc_i8k;\n"
+ "-\tint err;\n"
+ "-\n"
+ "-\t/* Are we running on an supported laptop? */\n"
+ "-\tif (i8k_probe())\n"
+ "-\t\treturn -ENODEV;\n"
+ "-\n"
+ "-\t/* Register the proc entry */\n"
+ "-\tproc_i8k = proc_create(\"i8k\", 0, NULL, &i8k_fops);\n"
+ "-\tif (!proc_i8k)\n"
+ "-\t\treturn -ENOENT;\n"
+ "-\n"
+ "-\terr = i8k_init_hwmon();\n"
+ "-\tif (err)\n"
+ "-\t\tgoto exit_remove_proc;\n"
+ "-\n"
+ "-\treturn 0;\n"
+ "-\n"
+ "- exit_remove_proc:\n"
+ "-\tremove_proc_entry(\"i8k\", NULL);\n"
+ "-\treturn err;\n"
+ "-}\n"
+ "-\n"
+ "-static void __exit i8k_exit(void)\n"
+ "-{\n"
+ "-\thwmon_device_unregister(i8k_hwmon_dev);\n"
+ "-\tremove_proc_entry(\"i8k\", NULL);\n"
+ "-}\n"
+ "-\n"
+ "-module_init(i8k_init);\n"
+ "-module_exit(i8k_exit);\n"
+ "diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile\n"
+ "index 6c94147..1c3e458 100644\n"
+ "--- a/drivers/hwmon/Makefile\n"
+ "+++ b/drivers/hwmon/Makefile\n"
+ "@@ -155,6 +155,7 @@ obj-$(CONFIG_SENSORS_W83L785TS)\t+= w83l785ts.o\n"
+ " obj-$(CONFIG_SENSORS_W83L786NG)\t+= w83l786ng.o\n"
+ " obj-$(CONFIG_SENSORS_WM831X)\t+= wm831x-hwmon.o\n"
+ " obj-$(CONFIG_SENSORS_WM8350)\t+= wm8350-hwmon.o\n"
+ "+obj-$(CONFIG_I8K)\t\t+= dell-smm-hwmon.o\n"
+ " \n"
+ " obj-$(CONFIG_PMBUS)\t\t+= pmbus/\n"
+ " \n"
+ "diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c\n"
+ "new file mode 100644\n"
+ "index 0000000..2b04e4f\n"
+ "--- /dev/null\n"
+ "+++ b/drivers/hwmon/dell-smm-hwmon.c\n"
+ "@@ -0,0 +1,1007 @@\n"
+ "+/*\n"
+ "+ * dell-smm-hwmon.c -- Linux driver for accessing the SMM BIOS on Dell laptops.\n"
+ "+ *\n"
+ "+ * Copyright (C) 2001  Massimo Dal Zotto <dz@debian.org>\n"
+ "+ *\n"
+ "+ * Hwmon integration:\n"
+ "+ * Copyright (C) 2011  Jean Delvare <jdelvare@suse.de>\n"
+ "+ * Copyright (C) 2013, 2014  Guenter Roeck <linux@roeck-us.net>\n"
+ "+ * Copyright (C) 2014, 2015  Pali Roh\303\241r <pali.rohar@gmail.com>\n"
+ "+ *\n"
+ "+ * This program is free software; you can redistribute it and/or modify it\n"
+ "+ * under the terms of the GNU General Public License as published by the\n"
+ "+ * Free Software Foundation; either version 2, or (at your option) any\n"
+ "+ * later version.\n"
+ "+ *\n"
+ "+ * This program is distributed in the hope that it will be useful, but\n"
+ "+ * WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
+ "+ * General Public License for more details.\n"
+ "+ */\n"
+ "+\n"
+ "+#define pr_fmt(fmt) KBUILD_MODNAME \": \" fmt\n"
+ "+\n"
+ "+#include <linux/delay.h>\n"
+ "+#include <linux/module.h>\n"
+ "+#include <linux/types.h>\n"
+ "+#include <linux/init.h>\n"
+ "+#include <linux/proc_fs.h>\n"
+ "+#include <linux/seq_file.h>\n"
+ "+#include <linux/dmi.h>\n"
+ "+#include <linux/capability.h>\n"
+ "+#include <linux/mutex.h>\n"
+ "+#include <linux/hwmon.h>\n"
+ "+#include <linux/hwmon-sysfs.h>\n"
+ "+#include <linux/uaccess.h>\n"
+ "+#include <linux/io.h>\n"
+ "+#include <linux/sched.h>\n"
+ "+\n"
+ "+#include <linux/i8k.h>\n"
+ "+\n"
+ "+#define I8K_SMM_FN_STATUS\t0x0025\n"
+ "+#define I8K_SMM_POWER_STATUS\t0x0069\n"
+ "+#define I8K_SMM_SET_FAN\t\t0x01a3\n"
+ "+#define I8K_SMM_GET_FAN\t\t0x00a3\n"
+ "+#define I8K_SMM_GET_SPEED\t0x02a3\n"
+ "+#define I8K_SMM_GET_FAN_TYPE\t0x03a3\n"
+ "+#define I8K_SMM_GET_NOM_SPEED\t0x04a3\n"
+ "+#define I8K_SMM_GET_TEMP\t0x10a3\n"
+ "+#define I8K_SMM_GET_TEMP_TYPE\t0x11a3\n"
+ "+#define I8K_SMM_GET_DELL_SIG1\t0xfea3\n"
+ "+#define I8K_SMM_GET_DELL_SIG2\t0xffa3\n"
+ "+\n"
+ "+#define I8K_FAN_MULT\t\t30\n"
+ "+#define I8K_FAN_MAX_RPM\t\t30000\n"
+ "+#define I8K_MAX_TEMP\t\t127\n"
+ "+\n"
+ "+#define I8K_FN_NONE\t\t0x00\n"
+ "+#define I8K_FN_UP\t\t0x01\n"
+ "+#define I8K_FN_DOWN\t\t0x02\n"
+ "+#define I8K_FN_MUTE\t\t0x04\n"
+ "+#define I8K_FN_MASK\t\t0x07\n"
+ "+#define I8K_FN_SHIFT\t\t8\n"
+ "+\n"
+ "+#define I8K_POWER_AC\t\t0x05\n"
+ "+#define I8K_POWER_BATTERY\t0x01\n"
+ "+\n"
+ "+static DEFINE_MUTEX(i8k_mutex);\n"
+ "+static char bios_version[4];\n"
+ "+static struct device *i8k_hwmon_dev;\n"
+ "+static u32 i8k_hwmon_flags;\n"
+ "+static uint i8k_fan_mult = I8K_FAN_MULT;\n"
+ "+static uint i8k_pwm_mult;\n"
+ "+static uint i8k_fan_max = I8K_FAN_HIGH;\n"
+ "+\n"
+ "+#define I8K_HWMON_HAVE_TEMP1\t(1 << 0)\n"
+ "+#define I8K_HWMON_HAVE_TEMP2\t(1 << 1)\n"
+ "+#define I8K_HWMON_HAVE_TEMP3\t(1 << 2)\n"
+ "+#define I8K_HWMON_HAVE_TEMP4\t(1 << 3)\n"
+ "+#define I8K_HWMON_HAVE_FAN1\t(1 << 4)\n"
+ "+#define I8K_HWMON_HAVE_FAN2\t(1 << 5)\n"
+ "+\n"
+ "+MODULE_AUTHOR(\"Massimo Dal Zotto (dz@debian.org)\");\n"
+ "+MODULE_AUTHOR(\"Pali Roh\303\241r <pali.rohar@gmail.com>\");\n"
+ "+MODULE_DESCRIPTION(\"Driver for accessing SMM BIOS on Dell laptops\");\n"
+ "+MODULE_LICENSE(\"GPL\");\n"
+ "+MODULE_ALIAS(\"i8k\");\n"
+ "+\n"
+ "+static bool force;\n"
+ "+module_param(force, bool, 0);\n"
+ "+MODULE_PARM_DESC(force, \"Force loading without checking for supported models\");\n"
+ "+\n"
+ "+static bool ignore_dmi;\n"
+ "+module_param(ignore_dmi, bool, 0);\n"
+ "+MODULE_PARM_DESC(ignore_dmi, \"Continue probing hardware even if DMI data does not match\");\n"
+ "+\n"
+ "+static bool restricted;\n"
+ "+module_param(restricted, bool, 0);\n"
+ "+MODULE_PARM_DESC(restricted, \"Allow fan control if SYS_ADMIN capability set\");\n"
+ "+\n"
+ "+static bool power_status;\n"
+ "+module_param(power_status, bool, 0600);\n"
+ "+MODULE_PARM_DESC(power_status, \"Report power status in /proc/i8k\");\n"
+ "+\n"
+ "+static uint fan_mult;\n"
+ "+module_param(fan_mult, uint, 0);\n"
+ "+MODULE_PARM_DESC(fan_mult, \"Factor to multiply fan speed with (default: autodetect)\");\n"
+ "+\n"
+ "+static uint fan_max;\n"
+ "+module_param(fan_max, uint, 0);\n"
+ "+MODULE_PARM_DESC(fan_max, \"Maximum configurable fan speed (default: autodetect)\");\n"
+ "+\n"
+ "+static int i8k_open_fs(struct inode *inode, struct file *file);\n"
+ "+static long i8k_ioctl(struct file *, unsigned int, unsigned long);\n"
+ "+\n"
+ "+static const struct file_operations i8k_fops = {\n"
+ "+\t.owner\t\t= THIS_MODULE,\n"
+ "+\t.open\t\t= i8k_open_fs,\n"
+ "+\t.read\t\t= seq_read,\n"
+ "+\t.llseek\t\t= seq_lseek,\n"
+ "+\t.release\t= single_release,\n"
+ "+\t.unlocked_ioctl\t= i8k_ioctl,\n"
+ "+};\n"
+ "+\n"
+ "+struct smm_regs {\n"
+ "+\tunsigned int eax;\n"
+ "+\tunsigned int ebx __packed;\n"
+ "+\tunsigned int ecx __packed;\n"
+ "+\tunsigned int edx __packed;\n"
+ "+\tunsigned int esi __packed;\n"
+ "+\tunsigned int edi __packed;\n"
+ "+};\n"
+ "+\n"
+ "+static inline const char *i8k_get_dmi_data(int field)\n"
+ "+{\n"
+ "+\tconst char *dmi_data = dmi_get_system_info(field);\n"
+ "+\n"
+ "+\treturn dmi_data && *dmi_data ? dmi_data : \"?\";\n"
+ "+}\n"
+ "+\n"
+ "+/*\n"
+ "+ * Call the System Management Mode BIOS. Code provided by Jonathan Buzzard.\n"
+ "+ */\n"
+ "+static int i8k_smm(struct smm_regs *regs)\n"
+ "+{\n"
+ "+\tint rc;\n"
+ "+\tint eax = regs->eax;\n"
+ "+\tcpumask_var_t old_mask;\n"
+ "+\n"
+ "+\t/* SMM requires CPU 0 */\n"
+ "+\tif (!alloc_cpumask_var(&old_mask, GFP_KERNEL))\n"
+ "+\t\treturn -ENOMEM;\n"
+ "+\tcpumask_copy(old_mask, &current->cpus_allowed);\n"
+ "+\trc = set_cpus_allowed_ptr(current, cpumask_of(0));\n"
+ "+\tif (rc)\n"
+ "+\t\tgoto out;\n"
+ "+\tif (smp_processor_id() != 0) {\n"
+ "+\t\trc = -EBUSY;\n"
+ "+\t\tgoto out;\n"
+ "+\t}\n"
+ "+\n"
+ "+#if defined(CONFIG_X86_64)\n"
+ "+\tasm volatile(\"pushq %%rax\\n\\t\"\n"
+ "+\t\t\"movl 0(%%rax),%%edx\\n\\t\"\n"
+ "+\t\t\"pushq %%rdx\\n\\t\"\n"
+ "+\t\t\"movl 4(%%rax),%%ebx\\n\\t\"\n"
+ "+\t\t\"movl 8(%%rax),%%ecx\\n\\t\"\n"
+ "+\t\t\"movl 12(%%rax),%%edx\\n\\t\"\n"
+ "+\t\t\"movl 16(%%rax),%%esi\\n\\t\"\n"
+ "+\t\t\"movl 20(%%rax),%%edi\\n\\t\"\n"
+ "+\t\t\"popq %%rax\\n\\t\"\n"
+ "+\t\t\"out %%al,$0xb2\\n\\t\"\n"
+ "+\t\t\"out %%al,$0x84\\n\\t\"\n"
+ "+\t\t\"xchgq %%rax,(%%rsp)\\n\\t\"\n"
+ "+\t\t\"movl %%ebx,4(%%rax)\\n\\t\"\n"
+ "+\t\t\"movl %%ecx,8(%%rax)\\n\\t\"\n"
+ "+\t\t\"movl %%edx,12(%%rax)\\n\\t\"\n"
+ "+\t\t\"movl %%esi,16(%%rax)\\n\\t\"\n"
+ "+\t\t\"movl %%edi,20(%%rax)\\n\\t\"\n"
+ "+\t\t\"popq %%rdx\\n\\t\"\n"
+ "+\t\t\"movl %%edx,0(%%rax)\\n\\t\"\n"
+ "+\t\t\"pushfq\\n\\t\"\n"
+ "+\t\t\"popq %%rax\\n\\t\"\n"
+ "+\t\t\"andl $1,%%eax\\n\"\n"
+ "+\t\t: \"=a\"(rc)\n"
+ "+\t\t:    \"a\"(regs)\n"
+ "+\t\t:    \"%ebx\", \"%ecx\", \"%edx\", \"%esi\", \"%edi\", \"memory\");\n"
+ "+#else\n"
+ "+\tasm volatile(\"pushl %%eax\\n\\t\"\n"
+ "+\t    \"movl 0(%%eax),%%edx\\n\\t\"\n"
+ "+\t    \"push %%edx\\n\\t\"\n"
+ "+\t    \"movl 4(%%eax),%%ebx\\n\\t\"\n"
+ "+\t    \"movl 8(%%eax),%%ecx\\n\\t\"\n"
+ "+\t    \"movl 12(%%eax),%%edx\\n\\t\"\n"
+ "+\t    \"movl 16(%%eax),%%esi\\n\\t\"\n"
+ "+\t    \"movl 20(%%eax),%%edi\\n\\t\"\n"
+ "+\t    \"popl %%eax\\n\\t\"\n"
+ "+\t    \"out %%al,$0xb2\\n\\t\"\n"
+ "+\t    \"out %%al,$0x84\\n\\t\"\n"
+ "+\t    \"xchgl %%eax,(%%esp)\\n\\t\"\n"
+ "+\t    \"movl %%ebx,4(%%eax)\\n\\t\"\n"
+ "+\t    \"movl %%ecx,8(%%eax)\\n\\t\"\n"
+ "+\t    \"movl %%edx,12(%%eax)\\n\\t\"\n"
+ "+\t    \"movl %%esi,16(%%eax)\\n\\t\"\n"
+ "+\t    \"movl %%edi,20(%%eax)\\n\\t\"\n"
+ "+\t    \"popl %%edx\\n\\t\"\n"
+ "+\t    \"movl %%edx,0(%%eax)\\n\\t\"\n"
+ "+\t    \"lahf\\n\\t\"\n"
+ "+\t    \"shrl $8,%%eax\\n\\t\"\n"
+ "+\t    \"andl $1,%%eax\\n\"\n"
+ "+\t    : \"=a\"(rc)\n"
+ "+\t    :    \"a\"(regs)\n"
+ "+\t    :    \"%ebx\", \"%ecx\", \"%edx\", \"%esi\", \"%edi\", \"memory\");\n"
+ "+#endif\n"
+ "+\tif (rc != 0 || (regs->eax & 0xffff) == 0xffff || regs->eax == eax)\n"
+ "+\t\trc = -EINVAL;\n"
+ "+\n"
+ "+out:\n"
+ "+\tset_cpus_allowed_ptr(current, old_mask);\n"
+ "+\tfree_cpumask_var(old_mask);\n"
+ "+\treturn rc;\n"
+ "+}\n"
+ "+\n"
+ "+/*\n"
+ "+ * Read the Fn key status.\n"
+ "+ */\n"
+ "+static int i8k_get_fn_status(void)\n"
+ "+{\n"
+ "+\tstruct smm_regs regs = { .eax = I8K_SMM_FN_STATUS, };\n"
+ "+\tint rc;\n"
+ "+\n"
+ "+\trc = i8k_smm(&regs);\n"
+ "+\tif (rc < 0)\n"
+ "+\t\treturn rc;\n"
+ "+\n"
+ "+\tswitch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {\n"
+ "+\tcase I8K_FN_UP:\n"
+ "+\t\treturn I8K_VOL_UP;\n"
+ "+\tcase I8K_FN_DOWN:\n"
+ "+\t\treturn I8K_VOL_DOWN;\n"
+ "+\tcase I8K_FN_MUTE:\n"
+ "+\t\treturn I8K_VOL_MUTE;\n"
+ "+\tdefault:\n"
+ "+\t\treturn 0;\n"
+ "+\t}\n"
+ "+}\n"
+ "+\n"
+ "+/*\n"
+ "+ * Read the power status.\n"
+ "+ */\n"
+ "+static int i8k_get_power_status(void)\n"
+ "+{\n"
+ "+\tstruct smm_regs regs = { .eax = I8K_SMM_POWER_STATUS, };\n"
+ "+\tint rc;\n"
+ "+\n"
+ "+\trc = i8k_smm(&regs);\n"
+ "+\tif (rc < 0)\n"
+ "+\t\treturn rc;\n"
+ "+\n"
+ "+\treturn (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY;\n"
+ "+}\n"
+ "+\n"
+ "+/*\n"
+ "+ * Read the fan status.\n"
+ "+ */\n"
+ "+static int i8k_get_fan_status(int fan)\n"
+ "+{\n"
+ "+\tstruct smm_regs regs = { .eax = I8K_SMM_GET_FAN, };\n"
+ "+\n"
+ "+\tregs.ebx = fan & 0xff;\n"
+ "+\treturn i8k_smm(&regs) ? : regs.eax & 0xff;\n"
+ "+}\n"
+ "+\n"
+ "+/*\n"
+ "+ * Read the fan speed in RPM.\n"
+ "+ */\n"
+ "+static int i8k_get_fan_speed(int fan)\n"
+ "+{\n"
+ "+\tstruct smm_regs regs = { .eax = I8K_SMM_GET_SPEED, };\n"
+ "+\n"
+ "+\tregs.ebx = fan & 0xff;\n"
+ "+\treturn i8k_smm(&regs) ? : (regs.eax & 0xffff) * i8k_fan_mult;\n"
+ "+}\n"
+ "+\n"
+ "+/*\n"
+ "+ * Read the fan type.\n"
+ "+ */\n"
+ "+static int i8k_get_fan_type(int fan)\n"
+ "+{\n"
+ "+\tstruct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, };\n"
+ "+\n"
+ "+\tregs.ebx = fan & 0xff;\n"
+ "+\treturn i8k_smm(&regs) ? : regs.eax & 0xff;\n"
+ "+}\n"
+ "+\n"
+ "+/*\n"
+ "+ * Read the fan nominal rpm for specific fan speed.\n"
+ "+ */\n"
+ "+static int i8k_get_fan_nominal_speed(int fan, int speed)\n"
+ "+{\n"
+ "+\tstruct smm_regs regs = { .eax = I8K_SMM_GET_NOM_SPEED, };\n"
+ "+\n"
+ "+\tregs.ebx = (fan & 0xff) | (speed << 8);\n"
+ "+\treturn i8k_smm(&regs) ? : (regs.eax & 0xffff) * i8k_fan_mult;\n"
+ "+}\n"
+ "+\n"
+ "+/*\n"
+ "+ * Set the fan speed (off, low, high). Returns the new fan status.\n"
+ "+ */\n"
+ "+static int i8k_set_fan(int fan, int speed)\n"
+ "+{\n"
+ "+\tstruct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };\n"
+ "+\n"
+ "+\tspeed = (speed < 0) ? 0 : ((speed > i8k_fan_max) ? i8k_fan_max : speed);\n"
+ "+\tregs.ebx = (fan & 0xff) | (speed << 8);\n"
+ "+\n"
+ "+\treturn i8k_smm(&regs) ? : i8k_get_fan_status(fan);\n"
+ "+}\n"
+ "+\n"
+ "+static int i8k_get_temp_type(int sensor)\n"
+ "+{\n"
+ "+\tstruct smm_regs regs = { .eax = I8K_SMM_GET_TEMP_TYPE, };\n"
+ "+\n"
+ "+\tregs.ebx = sensor & 0xff;\n"
+ "+\treturn i8k_smm(&regs) ? : regs.eax & 0xff;\n"
+ "+}\n"
+ "+\n"
+ "+/*\n"
+ "+ * Read the cpu temperature.\n"
+ "+ */\n"
+ "+static int _i8k_get_temp(int sensor)\n"
+ "+{\n"
+ "+\tstruct smm_regs regs = {\n"
+ "+\t\t.eax = I8K_SMM_GET_TEMP,\n"
+ "+\t\t.ebx = sensor & 0xff,\n"
+ "+\t};\n"
+ "+\n"
+ "+\treturn i8k_smm(&regs) ? : regs.eax & 0xff;\n"
+ "+}\n"
+ "+\n"
+ "+static int i8k_get_temp(int sensor)\n"
+ "+{\n"
+ "+\tint temp = _i8k_get_temp(sensor);\n"
+ "+\n"
+ "+\t/*\n"
+ "+\t * Sometimes the temperature sensor returns 0x99, which is out of range.\n"
+ "+\t * In this case we retry (once) before returning an error.\n"
+ "+\t # 1003655137 00000058 00005a4b\n"
+ "+\t # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees\n"
+ "+\t # 1003655139 00000054 00005c52\n"
+ "+\t */\n"
+ "+\tif (temp == 0x99) {\n"
+ "+\t\tmsleep(100);\n"
+ "+\t\ttemp = _i8k_get_temp(sensor);\n"
+ "+\t}\n"
+ "+\t/*\n"
+ "+\t * Return -ENODATA for all invalid temperatures.\n"
+ "+\t *\n"
+ "+\t * Known instances are the 0x99 value as seen above as well as\n"
+ "+\t * 0xc1 (193), which may be returned when trying to read the GPU\n"
+ "+\t * temperature if the system supports a GPU and it is currently\n"
+ "+\t * turned off.\n"
+ "+\t */\n"
+ "+\tif (temp > I8K_MAX_TEMP)\n"
+ "+\t\treturn -ENODATA;\n"
+ "+\n"
+ "+\treturn temp;\n"
+ "+}\n"
+ "+\n"
+ "+static int i8k_get_dell_signature(int req_fn)\n"
+ "+{\n"
+ "+\tstruct smm_regs regs = { .eax = req_fn, };\n"
+ "+\tint rc;\n"
+ "+\n"
+ "+\trc = i8k_smm(&regs);\n"
+ "+\tif (rc < 0)\n"
+ "+\t\treturn rc;\n"
+ "+\n"
+ "+\treturn regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1;\n"
+ "+}\n"
+ "+\n"
+ "+static int\n"
+ "+i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg)\n"
+ "+{\n"
+ "+\tint val = 0;\n"
+ "+\tint speed;\n"
+ "+\tunsigned char buff[16];\n"
+ "+\tint __user *argp = (int __user *)arg;\n"
+ "+\n"
+ "+\tif (!argp)\n"
+ "+\t\treturn -EINVAL;\n"
+ "+\n"
+ "+\tswitch (cmd) {\n"
+ "+\tcase I8K_BIOS_VERSION:\n"
+ "+\t\tval = (bios_version[0] << 16) |\n"
+ "+\t\t\t\t(bios_version[1] << 8) | bios_version[2];\n"
+ "+\t\tbreak;\n"
+ "+\n"
+ "+\tcase I8K_MACHINE_ID:\n"
+ "+\t\tmemset(buff, 0, 16);\n"
+ "+\t\tstrlcpy(buff, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),\n"
+ "+\t\t\tsizeof(buff));\n"
+ "+\t\tbreak;\n"
+ "+\n"
+ "+\tcase I8K_FN_STATUS:\n"
+ "+\t\tval = i8k_get_fn_status();\n"
+ "+\t\tbreak;\n"
+ "+\n"
+ "+\tcase I8K_POWER_STATUS:\n"
+ "+\t\tval = i8k_get_power_status();\n"
+ "+\t\tbreak;\n"
+ "+\n"
+ "+\tcase I8K_GET_TEMP:\n"
+ "+\t\tval = i8k_get_temp(0);\n"
+ "+\t\tbreak;\n"
+ "+\n"
+ "+\tcase I8K_GET_SPEED:\n"
+ "+\t\tif (copy_from_user(&val, argp, sizeof(int)))\n"
+ "+\t\t\treturn -EFAULT;\n"
+ "+\n"
+ "+\t\tval = i8k_get_fan_speed(val);\n"
+ "+\t\tbreak;\n"
+ "+\n"
+ "+\tcase I8K_GET_FAN:\n"
+ "+\t\tif (copy_from_user(&val, argp, sizeof(int)))\n"
+ "+\t\t\treturn -EFAULT;\n"
+ "+\n"
+ "+\t\tval = i8k_get_fan_status(val);\n"
+ "+\t\tbreak;\n"
+ "+\n"
+ "+\tcase I8K_SET_FAN:\n"
+ "+\t\tif (restricted && !capable(CAP_SYS_ADMIN))\n"
+ "+\t\t\treturn -EPERM;\n"
+ "+\n"
+ "+\t\tif (copy_from_user(&val, argp, sizeof(int)))\n"
+ "+\t\t\treturn -EFAULT;\n"
+ "+\n"
+ "+\t\tif (copy_from_user(&speed, argp + 1, sizeof(int)))\n"
+ "+\t\t\treturn -EFAULT;\n"
+ "+\n"
+ "+\t\tval = i8k_set_fan(val, speed);\n"
+ "+\t\tbreak;\n"
+ "+\n"
+ "+\tdefault:\n"
+ "+\t\treturn -EINVAL;\n"
+ "+\t}\n"
+ "+\n"
+ "+\tif (val < 0)\n"
+ "+\t\treturn val;\n"
+ "+\n"
+ "+\tswitch (cmd) {\n"
+ "+\tcase I8K_BIOS_VERSION:\n"
+ "+\t\tif (copy_to_user(argp, &val, 4))\n"
+ "+\t\t\treturn -EFAULT;\n"
+ "+\n"
+ "+\t\tbreak;\n"
+ "+\tcase I8K_MACHINE_ID:\n"
+ "+\t\tif (copy_to_user(argp, buff, 16))\n"
+ "+\t\t\treturn -EFAULT;\n"
+ "+\n"
+ "+\t\tbreak;\n"
+ "+\tdefault:\n"
+ "+\t\tif (copy_to_user(argp, &val, sizeof(int)))\n"
+ "+\t\t\treturn -EFAULT;\n"
+ "+\n"
+ "+\t\tbreak;\n"
+ "+\t}\n"
+ "+\n"
+ "+\treturn 0;\n"
+ "+}\n"
+ "+\n"
+ "+static long i8k_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)\n"
+ "+{\n"
+ "+\tlong ret;\n"
+ "+\n"
+ "+\tmutex_lock(&i8k_mutex);\n"
+ "+\tret = i8k_ioctl_unlocked(fp, cmd, arg);\n"
+ "+\tmutex_unlock(&i8k_mutex);\n"
+ "+\n"
+ "+\treturn ret;\n"
+ "+}\n"
+ "+\n"
+ "+/*\n"
+ "+ * Print the information for /proc/i8k.\n"
+ "+ */\n"
+ "+static int i8k_proc_show(struct seq_file *seq, void *offset)\n"
+ "+{\n"
+ "+\tint fn_key, cpu_temp, ac_power;\n"
+ "+\tint left_fan, right_fan, left_speed, right_speed;\n"
+ "+\n"
+ "+\tcpu_temp\t= i8k_get_temp(0);\t\t\t/* 11100 \302\265s */\n"
+ "+\tleft_fan\t= i8k_get_fan_status(I8K_FAN_LEFT);\t/*   580 \302\265s */\n"
+ "+\tright_fan\t= i8k_get_fan_status(I8K_FAN_RIGHT);\t/*   580 \302\265s */\n"
+ "+\tleft_speed\t= i8k_get_fan_speed(I8K_FAN_LEFT);\t/*   580 \302\265s */\n"
+ "+\tright_speed\t= i8k_get_fan_speed(I8K_FAN_RIGHT);\t/*   580 \302\265s */\n"
+ "+\tfn_key\t\t= i8k_get_fn_status();\t\t\t/*   750 \302\265s */\n"
+ "+\tif (power_status)\n"
+ "+\t\tac_power = i8k_get_power_status();\t\t/* 14700 \302\265s */\n"
+ "+\telse\n"
+ "+\t\tac_power = -1;\n"
+ "+\n"
+ "+\t/*\n"
+ "+\t * Info:\n"
+ "+\t *\n"
+ "+\t * 1)  Format version (this will change if format changes)\n"
+ "+\t * 2)  BIOS version\n"
+ "+\t * 3)  BIOS machine ID\n"
+ "+\t * 4)  Cpu temperature\n"
+ "+\t * 5)  Left fan status\n"
+ "+\t * 6)  Right fan status\n"
+ "+\t * 7)  Left fan speed\n"
+ "+\t * 8)  Right fan speed\n"
+ "+\t * 9)  AC power\n"
+ "+\t * 10) Fn Key status\n"
+ "+\t */\n"
+ "+\treturn seq_printf(seq, \"%s %s %s %d %d %d %d %d %d %d\\n\",\n"
+ "+\t\t\t  I8K_PROC_FMT,\n"
+ "+\t\t\t  bios_version,\n"
+ "+\t\t\t  i8k_get_dmi_data(DMI_PRODUCT_SERIAL),\n"
+ "+\t\t\t  cpu_temp,\n"
+ "+\t\t\t  left_fan, right_fan, left_speed, right_speed,\n"
+ "+\t\t\t  ac_power, fn_key);\n"
+ "+}\n"
+ "+\n"
+ "+static int i8k_open_fs(struct inode *inode, struct file *file)\n"
+ "+{\n"
+ "+\treturn single_open(file, i8k_proc_show, NULL);\n"
+ "+}\n"
+ "+\n"
+ "+\n"
+ "+/*\n"
+ "+ * Hwmon interface\n"
+ "+ */\n"
+ "+\n"
+ "+static ssize_t i8k_hwmon_show_temp_label(struct device *dev,\n"
+ "+\t\t\t\t\t struct device_attribute *devattr,\n"
+ "+\t\t\t\t\t char *buf)\n"
+ "+{\n"
+ "+\tstatic const char * const labels[] = {\n"
+ "+\t\t\"CPU\",\n"
+ "+\t\t\"GPU\",\n"
+ "+\t\t\"SODIMM\",\n"
+ "+\t\t\"Other\",\n"
+ "+\t\t\"Ambient\",\n"
+ "+\t\t\"Other\",\n"
+ "+\t};\n"
+ "+\tint index = to_sensor_dev_attr(devattr)->index;\n"
+ "+\tint type;\n"
+ "+\n"
+ "+\ttype = i8k_get_temp_type(index);\n"
+ "+\tif (type < 0)\n"
+ "+\t\treturn type;\n"
+ "+\tif (type >= ARRAY_SIZE(labels))\n"
+ "+\t\ttype = ARRAY_SIZE(labels) - 1;\n"
+ "+\treturn sprintf(buf, \"%s\\n\", labels[type]);\n"
+ "+}\n"
+ "+\n"
+ "+static ssize_t i8k_hwmon_show_temp(struct device *dev,\n"
+ "+\t\t\t\t   struct device_attribute *devattr,\n"
+ "+\t\t\t\t   char *buf)\n"
+ "+{\n"
+ "+\tint index = to_sensor_dev_attr(devattr)->index;\n"
+ "+\tint temp;\n"
+ "+\n"
+ "+\ttemp = i8k_get_temp(index);\n"
+ "+\tif (temp < 0)\n"
+ "+\t\treturn temp;\n"
+ "+\treturn sprintf(buf, \"%d\\n\", temp * 1000);\n"
+ "+}\n"
+ "+\n"
+ "+static ssize_t i8k_hwmon_show_fan_label(struct device *dev,\n"
+ "+\t\t\t\t\tstruct device_attribute *devattr,\n"
+ "+\t\t\t\t\tchar *buf)\n"
+ "+{\n"
+ "+\tstatic const char * const labels[] = {\n"
+ "+\t\t\"Processor Fan\",\n"
+ "+\t\t\"Motherboard Fan\",\n"
+ "+\t\t\"Video Fan\",\n"
+ "+\t\t\"Power Supply Fan\",\n"
+ "+\t\t\"Chipset Fan\",\n"
+ "+\t\t\"Other Fan\",\n"
+ "+\t};\n"
+ "+\tint index = to_sensor_dev_attr(devattr)->index;\n"
+ "+\tbool dock = false;\n"
+ "+\tint type;\n"
+ "+\n"
+ "+\ttype = i8k_get_fan_type(index);\n"
+ "+\tif (type < 0)\n"
+ "+\t\treturn type;\n"
+ "+\n"
+ "+\tif (type & 0x10) {\n"
+ "+\t\tdock = true;\n"
+ "+\t\ttype &= 0x0F;\n"
+ "+\t}\n"
+ "+\n"
+ "+\tif (type >= ARRAY_SIZE(labels))\n"
+ "+\t\ttype = (ARRAY_SIZE(labels) - 1);\n"
+ "+\n"
+ "+\treturn sprintf(buf, \"%s%s\\n\", (dock ? \"Docking \" : \"\"), labels[type]);\n"
+ "+}\n"
+ "+\n"
+ "+static ssize_t i8k_hwmon_show_fan(struct device *dev,\n"
+ "+\t\t\t\t  struct device_attribute *devattr,\n"
+ "+\t\t\t\t  char *buf)\n"
+ "+{\n"
+ "+\tint index = to_sensor_dev_attr(devattr)->index;\n"
+ "+\tint fan_speed;\n"
+ "+\n"
+ "+\tfan_speed = i8k_get_fan_speed(index);\n"
+ "+\tif (fan_speed < 0)\n"
+ "+\t\treturn fan_speed;\n"
+ "+\treturn sprintf(buf, \"%d\\n\", fan_speed);\n"
+ "+}\n"
+ "+\n"
+ "+static ssize_t i8k_hwmon_show_pwm(struct device *dev,\n"
+ "+\t\t\t\t  struct device_attribute *devattr,\n"
+ "+\t\t\t\t  char *buf)\n"
+ "+{\n"
+ "+\tint index = to_sensor_dev_attr(devattr)->index;\n"
+ "+\tint status;\n"
+ "+\n"
+ "+\tstatus = i8k_get_fan_status(index);\n"
+ "+\tif (status < 0)\n"
+ "+\t\treturn -EIO;\n"
+ "+\treturn sprintf(buf, \"%d\\n\", clamp_val(status * i8k_pwm_mult, 0, 255));\n"
+ "+}\n"
+ "+\n"
+ "+static ssize_t i8k_hwmon_set_pwm(struct device *dev,\n"
+ "+\t\t\t\t struct device_attribute *attr,\n"
+ "+\t\t\t\t const char *buf, size_t count)\n"
+ "+{\n"
+ "+\tint index = to_sensor_dev_attr(attr)->index;\n"
+ "+\tunsigned long val;\n"
+ "+\tint err;\n"
+ "+\n"
+ "+\terr = kstrtoul(buf, 10, &val);\n"
+ "+\tif (err)\n"
+ "+\t\treturn err;\n"
+ "+\tval = clamp_val(DIV_ROUND_CLOSEST(val, i8k_pwm_mult), 0, i8k_fan_max);\n"
+ "+\n"
+ "+\tmutex_lock(&i8k_mutex);\n"
+ "+\terr = i8k_set_fan(index, val);\n"
+ "+\tmutex_unlock(&i8k_mutex);\n"
+ "+\n"
+ "+\treturn err < 0 ? -EIO : count;\n"
+ "+}\n"
+ "+\n"
+ "+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 0);\n"
+ "+static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,\n"
+ "+\t\t\t  0);\n"
+ "+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 1);\n"
+ "+static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,\n"
+ "+\t\t\t  1);\n"
+ "+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 2);\n"
+ "+static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,\n"
+ "+\t\t\t  2);\n"
+ "+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 3);\n"
+ "+static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,\n"
+ "+\t\t\t  3);\n"
+ "+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, 0);\n"
+ "+static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL,\n"
+ "+\t\t\t  0);\n"
+ "+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,\n"
+ "+\t\t\t  i8k_hwmon_set_pwm, 0);\n"
+ "+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL,\n"
+ "+\t\t\t  1);\n"
+ "+static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL,\n"
+ "+\t\t\t  1);\n"
+ "+static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,\n"
+ "+\t\t\t  i8k_hwmon_set_pwm, 1);\n"
+ "+\n"
+ "+static struct attribute *i8k_attrs[] = {\n"
+ "+\t&sensor_dev_attr_temp1_input.dev_attr.attr,\t/* 0 */\n"
+ "+\t&sensor_dev_attr_temp1_label.dev_attr.attr,\t/* 1 */\n"
+ "+\t&sensor_dev_attr_temp2_input.dev_attr.attr,\t/* 2 */\n"
+ "+\t&sensor_dev_attr_temp2_label.dev_attr.attr,\t/* 3 */\n"
+ "+\t&sensor_dev_attr_temp3_input.dev_attr.attr,\t/* 4 */\n"
+ "+\t&sensor_dev_attr_temp3_label.dev_attr.attr,\t/* 5 */\n"
+ "+\t&sensor_dev_attr_temp4_input.dev_attr.attr,\t/* 6 */\n"
+ "+\t&sensor_dev_attr_temp4_label.dev_attr.attr,\t/* 7 */\n"
+ "+\t&sensor_dev_attr_fan1_input.dev_attr.attr,\t/* 8 */\n"
+ "+\t&sensor_dev_attr_fan1_label.dev_attr.attr,\t/* 9 */\n"
+ "+\t&sensor_dev_attr_pwm1.dev_attr.attr,\t\t/* 10 */\n"
+ "+\t&sensor_dev_attr_fan2_input.dev_attr.attr,\t/* 11 */\n"
+ "+\t&sensor_dev_attr_fan2_label.dev_attr.attr,\t/* 12 */\n"
+ "+\t&sensor_dev_attr_pwm2.dev_attr.attr,\t\t/* 13 */\n"
+ "+\tNULL\n"
+ "+};\n"
+ "+\n"
+ "+static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,\n"
+ "+\t\t\t      int index)\n"
+ "+{\n"
+ "+\tif (index >= 0 && index <= 1 &&\n"
+ "+\t    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))\n"
+ "+\t\treturn 0;\n"
+ "+\tif (index >= 2 && index <= 3 &&\n"
+ "+\t    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP2))\n"
+ "+\t\treturn 0;\n"
+ "+\tif (index >= 4 && index <= 5 &&\n"
+ "+\t    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP3))\n"
+ "+\t\treturn 0;\n"
+ "+\tif (index >= 6 && index <= 7 &&\n"
+ "+\t    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4))\n"
+ "+\t\treturn 0;\n"
+ "+\tif (index >= 8 && index <= 10 &&\n"
+ "+\t    !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1))\n"
+ "+\t\treturn 0;\n"
+ "+\tif (index >= 11 && index <= 13 &&\n"
+ "+\t    !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2))\n"
+ "+\t\treturn 0;\n"
+ "+\n"
+ "+\treturn attr->mode;\n"
+ "+}\n"
+ "+\n"
+ "+static const struct attribute_group i8k_group = {\n"
+ "+\t.attrs = i8k_attrs,\n"
+ "+\t.is_visible = i8k_is_visible,\n"
+ "+};\n"
+ "+__ATTRIBUTE_GROUPS(i8k);\n"
+ "+\n"
+ "+static int __init i8k_init_hwmon(void)\n"
+ "+{\n"
+ "+\tint err;\n"
+ "+\n"
+ "+\ti8k_hwmon_flags = 0;\n"
+ "+\n"
+ "+\t/* CPU temperature attributes, if temperature type is OK */\n"
+ "+\terr = i8k_get_temp_type(0);\n"
+ "+\tif (err >= 0)\n"
+ "+\t\ti8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP1;\n"
+ "+\t/* check for additional temperature sensors */\n"
+ "+\terr = i8k_get_temp_type(1);\n"
+ "+\tif (err >= 0)\n"
+ "+\t\ti8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP2;\n"
+ "+\terr = i8k_get_temp_type(2);\n"
+ "+\tif (err >= 0)\n"
+ "+\t\ti8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP3;\n"
+ "+\terr = i8k_get_temp_type(3);\n"
+ "+\tif (err >= 0)\n"
+ "+\t\ti8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4;\n"
+ "+\n"
+ "+\t/* First fan attributes, if fan type is OK */\n"
+ "+\terr = i8k_get_fan_type(0);\n"
+ "+\tif (err >= 0)\n"
+ "+\t\ti8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1;\n"
+ "+\n"
+ "+\t/* Second fan attributes, if fan type is OK */\n"
+ "+\terr = i8k_get_fan_type(1);\n"
+ "+\tif (err >= 0)\n"
+ "+\t\ti8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2;\n"
+ "+\n"
+ "+\ti8k_hwmon_dev = hwmon_device_register_with_groups(NULL, \"i8k\", NULL,\n"
+ "+\t\t\t\t\t\t\t  i8k_groups);\n"
+ "+\tif (IS_ERR(i8k_hwmon_dev)) {\n"
+ "+\t\terr = PTR_ERR(i8k_hwmon_dev);\n"
+ "+\t\ti8k_hwmon_dev = NULL;\n"
+ "+\t\tpr_err(\"hwmon registration failed (%d)\\n\", err);\n"
+ "+\t\treturn err;\n"
+ "+\t}\n"
+ "+\treturn 0;\n"
+ "+}\n"
+ "+\n"
+ "+struct i8k_config_data {\n"
+ "+\tuint fan_mult;\n"
+ "+\tuint fan_max;\n"
+ "+};\n"
+ "+\n"
+ "+enum i8k_configs {\n"
+ "+\tDELL_LATITUDE_D520,\n"
+ "+\tDELL_PRECISION_490,\n"
+ "+\tDELL_STUDIO,\n"
+ "+\tDELL_XPS,\n"
+ "+};\n"
+ "+\n"
+ "+static const struct i8k_config_data i8k_config_data[] = {\n"
+ "+\t[DELL_LATITUDE_D520] = {\n"
+ "+\t\t.fan_mult = 1,\n"
+ "+\t\t.fan_max = I8K_FAN_TURBO,\n"
+ "+\t},\n"
+ "+\t[DELL_PRECISION_490] = {\n"
+ "+\t\t.fan_mult = 1,\n"
+ "+\t\t.fan_max = I8K_FAN_TURBO,\n"
+ "+\t},\n"
+ "+\t[DELL_STUDIO] = {\n"
+ "+\t\t.fan_mult = 1,\n"
+ "+\t\t.fan_max = I8K_FAN_HIGH,\n"
+ "+\t},\n"
+ "+\t[DELL_XPS] = {\n"
+ "+\t\t.fan_mult = 1,\n"
+ "+\t\t.fan_max = I8K_FAN_HIGH,\n"
+ "+\t},\n"
+ "+};\n"
+ "+\n"
+ "+static struct dmi_system_id i8k_dmi_table[] __initdata = {\n"
+ "+\t{\n"
+ "+\t\t.ident = \"Dell Inspiron\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Computer\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Inspiron\"),\n"
+ "+\t\t},\n"
+ "+\t},\n"
+ "+\t{\n"
+ "+\t\t.ident = \"Dell Latitude\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Computer\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Latitude\"),\n"
+ "+\t\t},\n"
+ "+\t},\n"
+ "+\t{\n"
+ "+\t\t.ident = \"Dell Inspiron 2\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Inspiron\"),\n"
+ "+\t\t},\n"
+ "+\t},\n"
+ "+\t{\n"
+ "+\t\t.ident = \"Dell Latitude D520\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Latitude D520\"),\n"
+ "+\t\t},\n"
+ "+\t\t.driver_data = (void *)&i8k_config_data[DELL_LATITUDE_D520],\n"
+ "+\t},\n"
+ "+\t{\n"
+ "+\t\t.ident = \"Dell Latitude 2\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Latitude\"),\n"
+ "+\t\t},\n"
+ "+\t},\n"
+ "+\t{\t/* UK Inspiron 6400  */\n"
+ "+\t\t.ident = \"Dell Inspiron 3\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"MM061\"),\n"
+ "+\t\t},\n"
+ "+\t},\n"
+ "+\t{\n"
+ "+\t\t.ident = \"Dell Inspiron 3\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"MP061\"),\n"
+ "+\t\t},\n"
+ "+\t},\n"
+ "+\t{\n"
+ "+\t\t.ident = \"Dell Precision 490\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME,\n"
+ "+\t\t\t\t  \"Precision WorkStation 490\"),\n"
+ "+\t\t},\n"
+ "+\t\t.driver_data = (void *)&i8k_config_data[DELL_PRECISION_490],\n"
+ "+\t},\n"
+ "+\t{\n"
+ "+\t\t.ident = \"Dell Precision\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Precision\"),\n"
+ "+\t\t},\n"
+ "+\t},\n"
+ "+\t{\n"
+ "+\t\t.ident = \"Dell Vostro\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Vostro\"),\n"
+ "+\t\t},\n"
+ "+\t},\n"
+ "+\t{\n"
+ "+\t\t.ident = \"Dell XPS421\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"XPS L421X\"),\n"
+ "+\t\t},\n"
+ "+\t},\n"
+ "+\t{\n"
+ "+\t\t.ident = \"Dell Studio\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"Studio\"),\n"
+ "+\t\t},\n"
+ "+\t\t.driver_data = (void *)&i8k_config_data[DELL_STUDIO],\n"
+ "+\t},\n"
+ "+\t{\n"
+ "+\t\t.ident = \"Dell XPS 13\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"XPS13\"),\n"
+ "+\t\t},\n"
+ "+\t\t.driver_data = (void *)&i8k_config_data[DELL_XPS],\n"
+ "+\t},\n"
+ "+\t{\n"
+ "+\t\t.ident = \"Dell XPS M140\",\n"
+ "+\t\t.matches = {\n"
+ "+\t\t\tDMI_MATCH(DMI_SYS_VENDOR, \"Dell Inc.\"),\n"
+ "+\t\t\tDMI_MATCH(DMI_PRODUCT_NAME, \"MXC051\"),\n"
+ "+\t\t},\n"
+ "+\t\t.driver_data = (void *)&i8k_config_data[DELL_XPS],\n"
+ "+\t},\n"
+ "+\t{ }\n"
+ "+};\n"
+ "+\n"
+ "+MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);\n"
+ "+\n"
+ "+/*\n"
+ "+ * Probe for the presence of a supported laptop.\n"
+ "+ */\n"
+ "+static int __init i8k_probe(void)\n"
+ "+{\n"
+ "+\tconst struct dmi_system_id *id;\n"
+ "+\tint fan, ret;\n"
+ "+\n"
+ "+\t/*\n"
+ "+\t * Get DMI information\n"
+ "+\t */\n"
+ "+\tif (!dmi_check_system(i8k_dmi_table)) {\n"
+ "+\t\tif (!ignore_dmi && !force)\n"
+ "+\t\t\treturn -ENODEV;\n"
+ "+\n"
+ "+\t\tpr_info(\"not running on a supported Dell system.\\n\");\n"
+ "+\t\tpr_info(\"vendor=%s, model=%s, version=%s\\n\",\n"
+ "+\t\t\ti8k_get_dmi_data(DMI_SYS_VENDOR),\n"
+ "+\t\t\ti8k_get_dmi_data(DMI_PRODUCT_NAME),\n"
+ "+\t\t\ti8k_get_dmi_data(DMI_BIOS_VERSION));\n"
+ "+\t}\n"
+ "+\n"
+ "+\tstrlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION),\n"
+ "+\t\tsizeof(bios_version));\n"
+ "+\n"
+ "+\t/*\n"
+ "+\t * Get SMM Dell signature\n"
+ "+\t */\n"
+ "+\tif (i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG1) &&\n"
+ "+\t    i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG2)) {\n"
+ "+\t\tpr_err(\"unable to get SMM Dell signature\\n\");\n"
+ "+\t\tif (!force)\n"
+ "+\t\t\treturn -ENODEV;\n"
+ "+\t}\n"
+ "+\n"
+ "+\t/*\n"
+ "+\t * Set fan multiplier and maximal fan speed from dmi config\n"
+ "+\t * Values specified in module parameters override values from dmi\n"
+ "+\t */\n"
+ "+\tid = dmi_first_match(i8k_dmi_table);\n"
+ "+\tif (id && id->driver_data) {\n"
+ "+\t\tconst struct i8k_config_data *conf = id->driver_data;\n"
+ "+\t\tif (!fan_mult && conf->fan_mult)\n"
+ "+\t\t\tfan_mult = conf->fan_mult;\n"
+ "+\t\tif (!fan_max && conf->fan_max)\n"
+ "+\t\t\tfan_max = conf->fan_max;\n"
+ "+\t}\n"
+ "+\n"
+ "+\ti8k_fan_max = fan_max ? : I8K_FAN_HIGH;\t/* Must not be 0 */\n"
+ "+\ti8k_pwm_mult = DIV_ROUND_UP(255, i8k_fan_max);\n"
+ "+\n"
+ "+\tif (!fan_mult) {\n"
+ "+\t\t/*\n"
+ "+\t\t * Autodetect fan multiplier based on nominal rpm\n"
+ "+\t\t * If fan reports rpm value too high then set multiplier to 1\n"
+ "+\t\t */\n"
+ "+\t\tfor (fan = 0; fan < 2; ++fan) {\n"
+ "+\t\t\tret = i8k_get_fan_nominal_speed(fan, i8k_fan_max);\n"
+ "+\t\t\tif (ret < 0)\n"
+ "+\t\t\t\tcontinue;\n"
+ "+\t\t\tif (ret > I8K_FAN_MAX_RPM)\n"
+ "+\t\t\t\ti8k_fan_mult = 1;\n"
+ "+\t\t\tbreak;\n"
+ "+\t\t}\n"
+ "+\t} else {\n"
+ "+\t\t/* Fan multiplier was specified in module param or in dmi */\n"
+ "+\t\ti8k_fan_mult = fan_mult;\n"
+ "+\t}\n"
+ "+\n"
+ "+\treturn 0;\n"
+ "+}\n"
+ "+\n"
+ "+static int __init i8k_init(void)\n"
+ "+{\n"
+ "+\tstruct proc_dir_entry *proc_i8k;\n"
+ "+\tint err;\n"
+ "+\n"
+ "+\t/* Are we running on an supported laptop? */\n"
+ "+\tif (i8k_probe())\n"
+ "+\t\treturn -ENODEV;\n"
+ "+\n"
+ "+\t/* Register the proc entry */\n"
+ "+\tproc_i8k = proc_create(\"i8k\", 0, NULL, &i8k_fops);\n"
+ "+\tif (!proc_i8k)\n"
+ "+\t\treturn -ENOENT;\n"
+ "+\n"
+ "+\terr = i8k_init_hwmon();\n"
+ "+\tif (err)\n"
+ "+\t\tgoto exit_remove_proc;\n"
+ "+\n"
+ "+\treturn 0;\n"
+ "+\n"
+ "+ exit_remove_proc:\n"
+ "+\tremove_proc_entry(\"i8k\", NULL);\n"
+ "+\treturn err;\n"
+ "+}\n"
+ "+\n"
+ "+static void __exit i8k_exit(void)\n"
+ "+{\n"
+ "+\thwmon_device_unregister(i8k_hwmon_dev);\n"
+ "+\tremove_proc_entry(\"i8k\", NULL);\n"
+ "+}\n"
+ "+\n"
+ "+module_init(i8k_init);\n"
+ "+module_exit(i8k_exit);\n"
+ "-- \n"
+ 1.7.9.5
 
-19f91de87c929a4c3d42fe6dbd83f3420bfb75e4ea1859e8ada7cbeba06c04a7
+3399d7ff90d35b97828b6dbb0a78706c83ef15cc7cfa95d2a99f023fb273644a

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.