Message ID | 817309867.28473523.1511156807466.JavaMail.zimbra@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBMZWlmIFNhaGxiZXJnIFttYWls dG86bHNhaGxiZXJAcmVkaGF0LmNvbV0NCj4gU2VudDogU3VuZGF5LCBOb3ZlbWJlciAxOSwgMjAx NyA5OjQ3IFBNDQo+IFRvOiBMb25nIExpIDxsb25nbGlAbWljcm9zb2Z0LmNvbT4NCj4gQ2M6IFN0 ZXZlIEZyZW5jaCA8c2ZyZW5jaEBzYW1iYS5vcmc+OyBsaW51eC1jaWZzQHZnZXIua2VybmVsLm9y ZzsgbGludXgtDQo+IGtlcm5lbEB2Z2VyLmtlcm5lbC5vcmc7IGxpbnV4LXJkbWFAdmdlci5rZXJu ZWwub3JnOyBDaHJpc3RvcGggSGVsbHdpZw0KPiA8aGNoQGluZnJhZGVhZC5vcmc+OyBUb20gVGFs cGV5IDx0dGFscGV5QG1pY3Jvc29mdC5jb20+OyBNYXR0aGV3DQo+IFdpbGNveCA8bWF3aWxjb3hA bWljcm9zb2Z0LmNvbT47IFN0ZXBoZW4gSGVtbWluZ2VyDQo+IDxzdGhlbW1pbkBtaWNyb3NvZnQu Y29tPjsgTG9uZyBMaSA8bG9uZ2xpQG1pY3Jvc29mdC5jb20+DQo+IFN1YmplY3Q6IFJlOiBbUGF0 Y2ggdjcgMDUvMjJdIENJRlM6IFNNQkQ6IEVzdGFibGlzaCBTTUIgRGlyZWN0IGNvbm5lY3Rpb24N Cj4gDQo+IEFja2VkLWJ5OiBSb25uaWUgU2FobGJlcmcgPGxzYWhsYmVyQGdtYWlsLmNvbT4NCj4g DQo+IEJ1dCB0d28gdGlueSBuaXRzOg0KPiArICogZS5nLiBjaWZzLnNtYmRfbG9nZ2luZ19jbGFz cz0weDUwMCB3aWxsIGxvZyBhbGwgbG9nX3JkbWFfcmVjdigpIGFuZA0KPiBTaG91bGQgYmUgMHhh MA0KPiANCj4gKy8vCXF1ZXVlX3dvcmsoaW5mby0+d29ya3F1ZXVlLCAmaW5mby0+ZGVzdHJveV93 b3JrKTsNCj4gRG9uJ3QgbGVhdmUgY29tbWVudGVkIG91dCBjb2RlIGluIHRoZXJlLg0KDQpJIHdp bGwgYWRkcmVzcyB0aG9zZS4gVGhhbmtzIQ0KDQo+IA0KPiANCj4gLS0tLS0gT3JpZ2luYWwgTWVz c2FnZSAtLS0tLQ0KPiBGcm9tOiAiTG9uZyBMaSIgPGxvbmdsaUBleGNoYW5nZS5taWNyb3NvZnQu Y29tPg0KPiBUbzogIlN0ZXZlIEZyZW5jaCIgPHNmcmVuY2hAc2FtYmEub3JnPiwgbGludXgtY2lm c0B2Z2VyLmtlcm5lbC5vcmcsDQo+IHNhbWJhLXRlY2huaWNhbEBsaXN0cy5zYW1iYS5vcmcsIGxp bnV4LWtlcm5lbEB2Z2VyLmtlcm5lbC5vcmcsIGxpbnV4LQ0KPiByZG1hQHZnZXIua2VybmVsLm9y ZywgIkNocmlzdG9waCBIZWxsd2lnIiA8aGNoQGluZnJhZGVhZC5vcmc+LCAiVG9tDQo+IFRhbHBl eSIgPHR0YWxwZXlAbWljcm9zb2Z0LmNvbT4sICJNYXR0aGV3IFdpbGNveCINCj4gPG1hd2lsY294 QG1pY3Jvc29mdC5jb20+LCAiU3RlcGhlbiBIZW1taW5nZXIiDQo+IDxzdGhlbW1pbkBtaWNyb3Nv ZnQuY29tPg0KPiBDYzogIkxvbmcgTGkiIDxsb25nbGlAbWljcm9zb2Z0LmNvbT4NCj4gU2VudDog VHVlc2RheSwgNyBOb3ZlbWJlciwgMjAxNyA3OjU0OjU3IFBNDQo+IFN1YmplY3Q6IFtQYXRjaCB2 NyAwNS8yMl0gQ0lGUzogU01CRDogRXN0YWJsaXNoIFNNQiBEaXJlY3QgY29ubmVjdGlvbg0KPiAN Cj4gRnJvbTogTG9uZyBMaSA8bG9uZ2xpQG1pY3Jvc29mdC5jb20+DQo+IA0KPiBBZGQgY29kZSB0 byBpbXBsZW1lbnQgdGhlIGNvcmUgZnVuY3Rpb25zIHRvIGVzdGFibGlzaCBhIFNNQiBEaXJlY3QN Cj4gY29ubmVjdGlvbi4NCj4gDQo+IDEuIEVzdGFibGlzaCBhbiBSRE1BIGNvbm5lY3Rpb24gdG8g U01CIHNlcnZlci4NCj4gMi4gTmVnb3RpYXRlIGFuZCBzZXR1cCBTTUIgRGlyZWN0IHByb3RvY29s Lg0KPiAzLiBJbXBsZW1lbnQgaWRsZSBjb25uZWN0aW9uIHRpbWVyIGFuZCBjcmVkaXQgbWFuYWdl bWVudC4NCj4gDQo+IFNNQiBEaXJlY3QgaXMgZW5hYmxlZCBieSBzZXR0aW5nIENPTkZJR19DSUZT X1NNQl9ESVJFQ1QuDQo+IA0KPiBBZGQgdG8gTWFrZWZpbGUgdG8gZW5hYmxlIGJ1aWxkaW5nIFNN QiBEaXJlY3QuDQo+IA0KPiBTaWduZWQtb2ZmLWJ5OiBMb25nIExpIDxsb25nbGlAbWljcm9zb2Z0 LmNvbT4NCj4gLS0tDQo+ICBmcy9jaWZzL01ha2VmaWxlICAgIHwgICAgMiArDQo+ICBmcy9jaWZz L3NtYmRpcmVjdC5jIHwgMTU3Ng0KPiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysNCj4gIGZzL2NpZnMvc21iZGlyZWN0LmggfCAgMjgwICsrKysrKysr Kw0KPiAgMyBmaWxlcyBjaGFuZ2VkLCAxODU4IGluc2VydGlvbnMoKykNCj4gDQo+IGRpZmYgLS1n aXQgYS9mcy9jaWZzL01ha2VmaWxlIGIvZnMvY2lmcy9NYWtlZmlsZQ0KPiBpbmRleCA1ZTg1M2Ez Li5hZDAwODczIDEwMDY0NA0KPiAtLS0gYS9mcy9jaWZzL01ha2VmaWxlDQo+ICsrKyBiL2ZzL2Np ZnMvTWFrZWZpbGUNCj4gQEAgLTE4LDMgKzE4LDUgQEAgY2lmcy0kKENPTkZJR19DSUZTX1VQQ0FM TCkgKz0gY2lmc19zcG5lZ28ubw0KPiAgY2lmcy0kKENPTkZJR19DSUZTX0RGU19VUENBTEwpICs9 IGRuc19yZXNvbHZlLm8gY2lmc19kZnNfcmVmLm8NCj4gDQo+ICBjaWZzLSQoQ09ORklHX0NJRlNf RlNDQUNIRSkgKz0gZnNjYWNoZS5vIGNhY2hlLm8NCj4gKw0KPiArY2lmcy0kKENPTkZJR19DSUZT X1NNQl9ESVJFQ1QpICs9IHNtYmRpcmVjdC5vDQo+IGRpZmYgLS1naXQgYS9mcy9jaWZzL3NtYmRp cmVjdC5jIGIvZnMvY2lmcy9zbWJkaXJlY3QuYw0KPiBpbmRleCBkM2MxNmY4Li4wMjFkNTI3IDEw MDY0NA0KPiAtLS0gYS9mcy9jaWZzL3NtYmRpcmVjdC5jDQo+ICsrKyBiL2ZzL2NpZnMvc21iZGly ZWN0LmMNCj4gQEAgLTEzLDcgKzEzLDM0IEBADQo+ICAgKiAgIE1FUkNIQU5UQUJJTElUWSBvciBG SVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZQ0KPiAgICogICB0aGUgR05VIEdl bmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4NCj4gICAqLw0KPiArI2luY2x1 ZGUgPGxpbnV4L21vZHVsZS5oPg0KPiAgI2luY2x1ZGUgInNtYmRpcmVjdC5oIg0KPiArI2luY2x1 ZGUgImNpZnNfZGVidWcuaCINCj4gKw0KPiArc3RhdGljIHN0cnVjdCBzbWJkX3Jlc3BvbnNlICpn ZXRfZW1wdHlfcXVldWVfYnVmZmVyKA0KPiArCQlzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZv KTsNCj4gK3N0YXRpYyBzdHJ1Y3Qgc21iZF9yZXNwb25zZSAqZ2V0X3JlY2VpdmVfYnVmZmVyKA0K PiArCQlzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvKTsNCj4gK3N0YXRpYyB2b2lkIHB1dF9y ZWNlaXZlX2J1ZmZlcigNCj4gKwkJc3RydWN0IHNtYmRfY29ubmVjdGlvbiAqaW5mbywNCj4gKwkJ c3RydWN0IHNtYmRfcmVzcG9uc2UgKnJlc3BvbnNlLA0KPiArCQlib29sIGxvY2spOw0KPiArc3Rh dGljIGludCBhbGxvY2F0ZV9yZWNlaXZlX2J1ZmZlcnMoc3RydWN0IHNtYmRfY29ubmVjdGlvbiAq aW5mbywgaW50DQo+IG51bV9idWYpOw0KPiArc3RhdGljIHZvaWQgZGVzdHJveV9yZWNlaXZlX2J1 ZmZlcnMoc3RydWN0IHNtYmRfY29ubmVjdGlvbiAqaW5mbyk7DQo+ICsNCj4gK3N0YXRpYyB2b2lk IHB1dF9lbXB0eV9wYWNrZXQoDQo+ICsJCXN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24gKmluZm8sIHN0 cnVjdCBzbWJkX3Jlc3BvbnNlDQo+ICpyZXNwb25zZSk7DQo+ICtzdGF0aWMgdm9pZCBlbnF1ZXVl X3JlYXNzZW1ibHkoDQo+ICsJCXN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24gKmluZm8sDQo+ICsJCXN0 cnVjdCBzbWJkX3Jlc3BvbnNlICpyZXNwb25zZSwgaW50IGRhdGFfbGVuZ3RoKTsNCj4gK3N0YXRp YyBzdHJ1Y3Qgc21iZF9yZXNwb25zZSAqX2dldF9maXJzdF9yZWFzc2VtYmx5KA0KPiArCQlzdHJ1 Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvKTsNCj4gKw0KPiArc3RhdGljIGludCBzbWJkX3Bvc3Rf cmVjdigNCj4gKwkJc3RydWN0IHNtYmRfY29ubmVjdGlvbiAqaW5mbywNCj4gKwkJc3RydWN0IHNt YmRfcmVzcG9uc2UgKnJlc3BvbnNlKTsNCj4gKw0KPiArc3RhdGljIGludCBzbWJkX3Bvc3Rfc2Vu ZF9lbXB0eShzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvKTsNCj4gDQo+ICAvKiBTTUJEIHZl cnNpb24gbnVtYmVyICovDQo+ICAjZGVmaW5lIFNNQkRfVjEJMHgwMTAwDQo+IEBAIC03NSwzICsx MDIsMTU1MiBAQCBpbnQgc21iZF9tYXhfZnJtcl9kZXB0aCA9IDIwNDg7DQo+IA0KPiAgLyogSWYg cGF5bG9hZCBpcyBsZXNzIHRoYW4gdGhpcyBieXRlLCB1c2UgUkRNQSBzZW5kL3JlY3Ygbm90IHJl YWQvd3JpdGUgKi8NCj4gIGludCByZG1hX3JlYWR3cml0ZV90aHJlc2hvbGQgPSA0MDk2Ow0KPiAr DQo+ICsvKiBUcmFuc3BvcnQgbG9nZ2luZyBmdW5jdGlvbnMNCj4gKyAqIExvZ2dpbmcgYXJlIGRl ZmluZWQgYXMgY2xhc3Nlcy4gVGhleSBjYW4gYmUgT1InZWQgdG8gZGVmaW5lIHRoZSBhY3R1YWwN Cj4gKyAqIGxvZ2dpbmcgbGV2ZWwgdmlhIG1vZHVsZSBwYXJhbWV0ZXIgc21iZF9sb2dnaW5nX2Ns YXNzDQo+ICsgKiBlLmcuIGNpZnMuc21iZF9sb2dnaW5nX2NsYXNzPTB4NTAwIHdpbGwgbG9nIGFs bCBsb2dfcmRtYV9yZWN2KCkgYW5kDQo+ICsgKiBsb2dfcmRtYV9ldmVudCgpDQo+ICsgKi8NCj4g KyNkZWZpbmUgTE9HX09VVEdPSU5HCQkJMHgxDQo+ICsjZGVmaW5lIExPR19JTkNPTUlORwkJCTB4 Mg0KPiArI2RlZmluZSBMT0dfUkVBRAkJCTB4NA0KPiArI2RlZmluZSBMT0dfV1JJVEUJCQkweDgN Cj4gKyNkZWZpbmUgTE9HX1JETUFfU0VORAkJCTB4MTANCj4gKyNkZWZpbmUgTE9HX1JETUFfUkVD VgkJCTB4MjANCj4gKyNkZWZpbmUgTE9HX0tFRVBfQUxJVkUJCQkweDQwDQo+ICsjZGVmaW5lIExP R19SRE1BX0VWRU5UCQkJMHg4MA0KPiArI2RlZmluZSBMT0dfUkRNQV9NUgkJCTB4MTAwDQo+ICtz dGF0aWMgdW5zaWduZWQgaW50IHNtYmRfbG9nZ2luZ19jbGFzcyA9IDA7DQo+ICttb2R1bGVfcGFy YW0oc21iZF9sb2dnaW5nX2NsYXNzLCB1aW50LCAwNjQ0KTsNCj4gK01PRFVMRV9QQVJNX0RFU0Mo c21iZF9sb2dnaW5nX2NsYXNzLA0KPiArCSJMb2dnaW5nIGNsYXNzIGZvciBTTUJEIHRyYW5zcG9y dCAweDAgdG8gMHgxMDAiKTsNCj4gKw0KPiArI2RlZmluZSBFUlIJCTB4MA0KPiArI2RlZmluZSBJ TkZPCQkweDENCj4gK3N0YXRpYyB1bnNpZ25lZCBpbnQgc21iZF9sb2dnaW5nX2xldmVsID0gRVJS Ow0KPiArbW9kdWxlX3BhcmFtKHNtYmRfbG9nZ2luZ19sZXZlbCwgdWludCwgMDY0NCk7DQo+ICtN T0RVTEVfUEFSTV9ERVNDKHNtYmRfbG9nZ2luZ19sZXZlbCwNCj4gKwkiTG9nZ2luZyBsZXZlbCBm b3IgU01CRCB0cmFuc3BvcnQsIDAgKGRlZmF1bHQpOiBlcnJvciwgMTogaW5mbyIpOw0KPiArDQo+ ICsjZGVmaW5lIGxvZ19yZG1hKGxldmVsLCBjbGFzcywgZm10LCBhcmdzLi4uKQkJCQlcDQo+ICtk byB7CQkJCQkJCQkJXA0KPiArCWlmIChsZXZlbCA8PSBzbWJkX2xvZ2dpbmdfbGV2ZWwgfHwgY2xh c3MgJiBzbWJkX2xvZ2dpbmdfY2xhc3MpCVwNCj4gKwkJY2lmc19kYmcoVkZTLCAiJXM6JWQgIiBm bXQsIF9fZnVuY19fLCBfX0xJTkVfXywgIyNhcmdzKTtcDQo+ICt9IHdoaWxlICgwKQ0KPiArDQo+ ICsjZGVmaW5lIGxvZ19vdXRnb2luZyhsZXZlbCwgZm10LCBhcmdzLi4uKSBcDQo+ICsJCWxvZ19y ZG1hKGxldmVsLCBMT0dfT1VUR09JTkcsIGZtdCwgIyNhcmdzKQ0KPiArI2RlZmluZSBsb2dfaW5j b21pbmcobGV2ZWwsIGZtdCwgYXJncy4uLikgXA0KPiArCQlsb2dfcmRtYShsZXZlbCwgTE9HX0lO Q09NSU5HLCBmbXQsICMjYXJncykNCj4gKyNkZWZpbmUgbG9nX3JlYWQobGV2ZWwsIGZtdCwgYXJn cy4uLikJbG9nX3JkbWEobGV2ZWwsIExPR19SRUFELCBmbXQsDQo+ICMjYXJncykNCj4gKyNkZWZp bmUgbG9nX3dyaXRlKGxldmVsLCBmbXQsIGFyZ3MuLi4pCWxvZ19yZG1hKGxldmVsLCBMT0dfV1JJ VEUsIGZtdCwNCj4gIyNhcmdzKQ0KPiArI2RlZmluZSBsb2dfcmRtYV9zZW5kKGxldmVsLCBmbXQs IGFyZ3MuLi4pIFwNCj4gKwkJbG9nX3JkbWEobGV2ZWwsIExPR19SRE1BX1NFTkQsIGZtdCwgIyNh cmdzKQ0KPiArI2RlZmluZSBsb2dfcmRtYV9yZWN2KGxldmVsLCBmbXQsIGFyZ3MuLi4pIFwNCj4g KwkJbG9nX3JkbWEobGV2ZWwsIExPR19SRE1BX1JFQ1YsIGZtdCwgIyNhcmdzKQ0KPiArI2RlZmlu ZSBsb2dfa2VlcF9hbGl2ZShsZXZlbCwgZm10LCBhcmdzLi4uKSBcDQo+ICsJCWxvZ19yZG1hKGxl dmVsLCBMT0dfS0VFUF9BTElWRSwgZm10LCAjI2FyZ3MpDQo+ICsjZGVmaW5lIGxvZ19yZG1hX2V2 ZW50KGxldmVsLCBmbXQsIGFyZ3MuLi4pIFwNCj4gKwkJbG9nX3JkbWEobGV2ZWwsIExPR19SRE1B X0VWRU5ULCBmbXQsICMjYXJncykNCj4gKyNkZWZpbmUgbG9nX3JkbWFfbXIobGV2ZWwsIGZtdCwg YXJncy4uLikgXA0KPiArCQlsb2dfcmRtYShsZXZlbCwgTE9HX1JETUFfTVIsIGZtdCwgIyNhcmdz KQ0KPiArDQo+ICsvKg0KPiArICogRGVzdHJveSB0aGUgdHJhbnNwb3J0IGFuZCByZWxhdGVkIFJE TUEgYW5kIG1lbW9yeSByZXNvdXJjZXMNCj4gKyAqIE5lZWQgdG8gZ28gdGhyb3VnaCBhbGwgdGhl IHBlbmRpbmcgY291bnRlcnMgYW5kIG1ha2Ugc3VyZSBvbiBvbmUgaXMNCj4gdXNpbmcNCj4gKyAq IHRoZSB0cmFuc3BvcnQgd2hpbGUgaXQgaXMgZGVzdHJveWVkDQo+ICsgKi8NCj4gK3N0YXRpYyB2 b2lkIHNtYmRfZGVzdHJveV9yZG1hX3dvcmsoc3RydWN0IHdvcmtfc3RydWN0ICp3b3JrKQ0KPiAr ew0KPiArCXN0cnVjdCBzbWJkX3Jlc3BvbnNlICpyZXNwb25zZTsNCj4gKwlzdHJ1Y3Qgc21iZF9j b25uZWN0aW9uICppbmZvID0NCj4gKwkJY29udGFpbmVyX29mKHdvcmssIHN0cnVjdCBzbWJkX2Nv bm5lY3Rpb24sIGRlc3Ryb3lfd29yayk7DQo+ICsJdW5zaWduZWQgbG9uZyBmbGFnczsNCj4gKw0K PiArCWxvZ19yZG1hX2V2ZW50KElORk8sICJkZXN0cm95aW5nIHFwXG4iKTsNCj4gKwlpYl9kcmFp bl9xcChpbmZvLT5pZC0+cXApOw0KPiArCXJkbWFfZGVzdHJveV9xcChpbmZvLT5pZCk7DQo+ICsN Cj4gKwkvKiBVbmJsb2NrIGFsbCBJL08gd2FpdGluZyBvbiB0aGUgc2VuZCBxdWV1ZSAqLw0KPiAr CXdha2VfdXBfaW50ZXJydXB0aWJsZV9hbGwoJmluZm8tPndhaXRfc2VuZF9xdWV1ZSk7DQo+ICsN Cj4gKwlsb2dfcmRtYV9ldmVudChJTkZPLCAiY2FuY2VsbGluZyBpZGxlIHRpbWVyXG4iKTsNCj4g KwljYW5jZWxfZGVsYXllZF93b3JrX3N5bmMoJmluZm8tPmlkbGVfdGltZXJfd29yayk7DQo+ICsJ bG9nX3JkbWFfZXZlbnQoSU5GTywgImNhbmNlbGxpbmcgc2VuZCBpbW1lZGlhdGUgd29ya1xuIik7 DQo+ICsJY2FuY2VsX2RlbGF5ZWRfd29ya19zeW5jKCZpbmZvLT5zZW5kX2ltbWVkaWF0ZV93b3Jr KTsNCj4gKw0KPiArCWxvZ19yZG1hX2V2ZW50KElORk8sICJ3YWl0IGZvciBhbGwgcmVjdiB0byBm aW5pc2hcbiIpOw0KPiArCXdha2VfdXBfaW50ZXJydXB0aWJsZSgmaW5mby0+d2FpdF9yZWFzc2Vt Ymx5X3F1ZXVlKTsNCj4gKw0KPiArCWxvZ19yZG1hX2V2ZW50KElORk8sICJ3YWl0IGZvciBhbGwg c2VuZCBwb3N0ZWQgdG8gSUIgdG8gZmluaXNoXG4iKTsNCj4gKwl3YWl0X2V2ZW50KGluZm8tPndh aXRfc2VuZF9wZW5kaW5nLA0KPiArCQlhdG9taWNfcmVhZCgmaW5mby0+c2VuZF9wZW5kaW5nKSA9 PSAwKTsNCj4gKwl3YWl0X2V2ZW50KGluZm8tPndhaXRfc2VuZF9wYXlsb2FkX3BlbmRpbmcsDQo+ ICsJCWF0b21pY19yZWFkKCZpbmZvLT5zZW5kX3BheWxvYWRfcGVuZGluZykgPT0gMCk7DQo+ICsN Cj4gKwkvKiBJdCdzIG5vdCBwb3Nzc2libGUgZm9yIHVwcGVyIGxheWVyIHRvIGdldCB0byByZWFz c2VtYmx5ICovDQo+ICsJbG9nX3JkbWFfZXZlbnQoSU5GTywgImRyYWluIHRoZSByZWFzc2VtYmx5 IHF1ZXVlXG4iKTsNCj4gKwlkbyB7DQo+ICsJCXNwaW5fbG9ja19pcnFzYXZlKCZpbmZvLT5yZWFz c2VtYmx5X3F1ZXVlX2xvY2ssIGZsYWdzKTsNCj4gKwkJcmVzcG9uc2UgPSBfZ2V0X2ZpcnN0X3Jl YXNzZW1ibHkoaW5mbyk7DQo+ICsJCWlmIChyZXNwb25zZSkgew0KPiArCQkJbGlzdF9kZWwoJnJl c3BvbnNlLT5saXN0KTsNCj4gKwkJCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoDQo+ICsJCQkJJmlu Zm8tPnJlYXNzZW1ibHlfcXVldWVfbG9jaywgZmxhZ3MpOw0KPiArCQkJcHV0X3JlY2VpdmVfYnVm ZmVyKGluZm8sIHJlc3BvbnNlLCB0cnVlKTsNCj4gKwkJfQ0KPiArCX0gd2hpbGUgKHJlc3BvbnNl KTsNCj4gKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZpbmZvLT5yZWFzc2VtYmx5X3F1ZXVlX2xv Y2ssIGZsYWdzKTsNCj4gKwlpbmZvLT5yZWFzc2VtYmx5X2RhdGFfbGVuZ3RoID0gMDsNCj4gKw0K PiArCWxvZ19yZG1hX2V2ZW50KElORk8sICJmcmVlIHJlY2VpdmUgYnVmZmVyc1xuIik7DQo+ICsJ d2FpdF9ldmVudChpbmZvLT53YWl0X3JlY2VpdmVfcXVldWVzLA0KPiArCQlpbmZvLT5jb3VudF9y ZWNlaXZlX3F1ZXVlICsgaW5mby0NCj4gPmNvdW50X2VtcHR5X3BhY2tldF9xdWV1ZQ0KPiArCQkJ PT0gaW5mby0+cmVjZWl2ZV9jcmVkaXRfbWF4KTsNCj4gKwlkZXN0cm95X3JlY2VpdmVfYnVmZmVy cyhpbmZvKTsNCj4gKw0KPiArCWliX2ZyZWVfY3EoaW5mby0+c2VuZF9jcSk7DQo+ICsJaWJfZnJl ZV9jcShpbmZvLT5yZWN2X2NxKTsNCj4gKwlpYl9kZWFsbG9jX3BkKGluZm8tPnBkKTsNCj4gKwly ZG1hX2Rlc3Ryb3lfaWQoaW5mby0+aWQpOw0KPiArDQo+ICsJLyogZnJlZSBtZW1wb29scyAqLw0K PiArCW1lbXBvb2xfZGVzdHJveShpbmZvLT5yZXF1ZXN0X21lbXBvb2wpOw0KPiArCWttZW1fY2Fj aGVfZGVzdHJveShpbmZvLT5yZXF1ZXN0X2NhY2hlKTsNCj4gKw0KPiArCW1lbXBvb2xfZGVzdHJv eShpbmZvLT5yZXNwb25zZV9tZW1wb29sKTsNCj4gKwlrbWVtX2NhY2hlX2Rlc3Ryb3koaW5mby0+ cmVzcG9uc2VfY2FjaGUpOw0KPiArDQo+ICsJaW5mby0+dHJhbnNwb3J0X3N0YXR1cyA9IFNNQkRf REVTVFJPWUVEOw0KPiArCXdha2VfdXBfYWxsKCZpbmZvLT53YWl0X2Rlc3Ryb3kpOw0KPiArfQ0K PiArDQo+ICtzdGF0aWMgaW50IHNtYmRfcHJvY2Vzc19kaXNjb25uZWN0ZWQoc3RydWN0IHNtYmRf Y29ubmVjdGlvbiAqaW5mbykNCj4gK3sNCj4gKy8vCXF1ZXVlX3dvcmsoaW5mby0+d29ya3F1ZXVl LCAmaW5mby0+ZGVzdHJveV93b3JrKTsNCj4gKwlzY2hlZHVsZV93b3JrKCZpbmZvLT5kZXN0cm95 X3dvcmspOw0KPiArCXJldHVybiAwOw0KPiArfQ0KPiArDQo+ICtzdGF0aWMgdm9pZCBzbWJkX2Rp c2Nvbm5lY3RfcmRtYV93b3JrKHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yaykNCj4gK3sNCj4gKwlz dHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvID0NCj4gKwkJY29udGFpbmVyX29mKHdvcmssIHN0 cnVjdCBzbWJkX2Nvbm5lY3Rpb24sDQo+IGRpc2Nvbm5lY3Rfd29yayk7DQo+ICsNCj4gKwlpZiAo aW5mby0+dHJhbnNwb3J0X3N0YXR1cyA9PSBTTUJEX0NPTk5FQ1RFRCkgew0KPiArCQlpbmZvLT50 cmFuc3BvcnRfc3RhdHVzID0gU01CRF9ESVNDT05ORUNUSU5HOw0KPiArCQlyZG1hX2Rpc2Nvbm5l Y3QoaW5mby0+aWQpOw0KPiArCX0NCj4gK30NCj4gKw0KPiArc3RhdGljIHZvaWQgc21iZF9kaXNj b25uZWN0X3JkbWFfY29ubmVjdGlvbihzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uDQo+ICppbmZvKQ0K PiArew0KPiArCXF1ZXVlX3dvcmsoaW5mby0+d29ya3F1ZXVlLCAmaW5mby0+ZGlzY29ubmVjdF93 b3JrKTsNCj4gK30NCj4gKw0KPiArLyogVXBjYWxsIGZyb20gUkRNQSBDTSAqLw0KPiArc3RhdGlj IGludCBzbWJkX2Nvbm5fdXBjYWxsKA0KPiArCQlzdHJ1Y3QgcmRtYV9jbV9pZCAqaWQsIHN0cnVj dCByZG1hX2NtX2V2ZW50ICpldmVudCkNCj4gK3sNCj4gKwlzdHJ1Y3Qgc21iZF9jb25uZWN0aW9u ICppbmZvID0gaWQtPmNvbnRleHQ7DQo+ICsNCj4gKwlsb2dfcmRtYV9ldmVudChJTkZPLCAiZXZl bnQ9JWQgc3RhdHVzPSVkXG4iLA0KPiArCQlldmVudC0+ZXZlbnQsIGV2ZW50LT5zdGF0dXMpOw0K PiArDQo+ICsJc3dpdGNoIChldmVudC0+ZXZlbnQpIHsNCj4gKwljYXNlIFJETUFfQ01fRVZFTlRf QUREUl9SRVNPTFZFRDoNCj4gKwljYXNlIFJETUFfQ01fRVZFTlRfUk9VVEVfUkVTT0xWRUQ6DQo+ ICsJCWluZm8tPnJpX3JjID0gMDsNCj4gKwkJY29tcGxldGUoJmluZm8tPnJpX2RvbmUpOw0KPiAr CQlicmVhazsNCj4gKw0KPiArCWNhc2UgUkRNQV9DTV9FVkVOVF9BRERSX0VSUk9SOg0KPiArCQlp bmZvLT5yaV9yYyA9IC1FSE9TVFVOUkVBQ0g7DQo+ICsJCWNvbXBsZXRlKCZpbmZvLT5yaV9kb25l KTsNCj4gKwkJYnJlYWs7DQo+ICsNCj4gKwljYXNlIFJETUFfQ01fRVZFTlRfUk9VVEVfRVJST1I6 DQo+ICsJCWluZm8tPnJpX3JjID0gLUVORVRVTlJFQUNIOw0KPiArCQljb21wbGV0ZSgmaW5mby0+ cmlfZG9uZSk7DQo+ICsJCWJyZWFrOw0KPiArDQo+ICsJY2FzZSBSRE1BX0NNX0VWRU5UX0VTVEFC TElTSEVEOg0KPiArCQlsb2dfcmRtYV9ldmVudChJTkZPLCAiY29ubmVjdGVkIGV2ZW50PSVkXG4i LCBldmVudC0NCj4gPmV2ZW50KTsNCj4gKwkJaW5mby0+dHJhbnNwb3J0X3N0YXR1cyA9IFNNQkRf Q09OTkVDVEVEOw0KPiArCQl3YWtlX3VwX2ludGVycnVwdGlibGUoJmluZm8tPmNvbm5fd2FpdCk7 DQo+ICsJCWJyZWFrOw0KPiArDQo+ICsJY2FzZSBSRE1BX0NNX0VWRU5UX0NPTk5FQ1RfRVJST1I6 DQo+ICsJY2FzZSBSRE1BX0NNX0VWRU5UX1VOUkVBQ0hBQkxFOg0KPiArCWNhc2UgUkRNQV9DTV9F VkVOVF9SRUpFQ1RFRDoNCj4gKwkJbG9nX3JkbWFfZXZlbnQoSU5GTywgImNvbm5lY3RpbmcgZmFp bGVkIGV2ZW50PSVkXG4iLA0KPiBldmVudC0+ZXZlbnQpOw0KPiArCQlpbmZvLT50cmFuc3BvcnRf c3RhdHVzID0gU01CRF9ESVNDT05ORUNURUQ7DQo+ICsJCXdha2VfdXBfaW50ZXJydXB0aWJsZSgm aW5mby0+Y29ubl93YWl0KTsNCj4gKwkJYnJlYWs7DQo+ICsNCj4gKwljYXNlIFJETUFfQ01fRVZF TlRfREVWSUNFX1JFTU9WQUw6DQo+ICsJY2FzZSBSRE1BX0NNX0VWRU5UX0RJU0NPTk5FQ1RFRDoN Cj4gKwkJLyogVGhpcyBoYXBwZW5lcyB3aGVuIHdlIGZhaWwgdGhlIG5lZ290aWF0aW9uICovDQo+ ICsJCWlmIChpbmZvLT50cmFuc3BvcnRfc3RhdHVzID09IFNNQkRfTkVHT1RJQVRFX0ZBSUxFRCkg ew0KPiArCQkJaW5mby0+dHJhbnNwb3J0X3N0YXR1cyA9IFNNQkRfRElTQ09OTkVDVEVEOw0KPiAr CQkJd2FrZV91cCgmaW5mby0+Y29ubl93YWl0KTsNCj4gKwkJCWJyZWFrOw0KPiArCQl9DQo+ICsN Cj4gKwkJaW5mby0+dHJhbnNwb3J0X3N0YXR1cyA9IFNNQkRfRElTQ09OTkVDVEVEOw0KPiArCQlz bWJkX3Byb2Nlc3NfZGlzY29ubmVjdGVkKGluZm8pOw0KPiArCQlicmVhazsNCj4gKw0KPiArCWRl ZmF1bHQ6DQo+ICsJCWJyZWFrOw0KPiArCX0NCj4gKw0KPiArCXJldHVybiAwOw0KPiArfQ0KPiAr DQo+ICsvKiBVcGNhbGwgZnJvbSBSRE1BIFFQICovDQo+ICtzdGF0aWMgdm9pZA0KPiArc21iZF9x cF9hc3luY19lcnJvcl91cGNhbGwoc3RydWN0IGliX2V2ZW50ICpldmVudCwgdm9pZCAqY29udGV4 dCkNCj4gK3sNCj4gKwlzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvID0gY29udGV4dDsNCj4g Kw0KPiArCWxvZ19yZG1hX2V2ZW50KEVSUiwgIiVzIG9uIGRldmljZSAlcyBpbmZvICVwXG4iLA0K PiArCQlpYl9ldmVudF9tc2coZXZlbnQtPmV2ZW50KSwgZXZlbnQtPmRldmljZS0+bmFtZSwgaW5m byk7DQo+ICsNCj4gKwlzd2l0Y2ggKGV2ZW50LT5ldmVudCkgew0KPiArCWNhc2UgSUJfRVZFTlRf Q1FfRVJSOg0KPiArCWNhc2UgSUJfRVZFTlRfUVBfRkFUQUw6DQo+ICsJCXNtYmRfZGlzY29ubmVj dF9yZG1hX2Nvbm5lY3Rpb24oaW5mbyk7DQo+ICsNCj4gKwlkZWZhdWx0Og0KPiArCQlicmVhazsN Cj4gKwl9DQo+ICt9DQo+ICsNCj4gK3N0YXRpYyBpbmxpbmUgdm9pZCAqc21iZF9yZXF1ZXN0X3Bh eWxvYWQoc3RydWN0IHNtYmRfcmVxdWVzdCAqcmVxdWVzdCkNCj4gK3sNCj4gKwlyZXR1cm4gKHZv aWQgKilyZXF1ZXN0LT5wYWNrZXQ7DQo+ICt9DQo+ICsNCj4gK3N0YXRpYyBpbmxpbmUgdm9pZCAq c21iZF9yZXNwb25zZV9wYXlsb2FkKHN0cnVjdCBzbWJkX3Jlc3BvbnNlDQo+ICpyZXNwb25zZSkN Cj4gK3sNCj4gKwlyZXR1cm4gKHZvaWQgKilyZXNwb25zZS0+cGFja2V0Ow0KPiArfQ0KPiArDQo+ ICsvKiBDYWxsZWQgd2hlbiBhIFJETUEgc2VuZCBpcyBkb25lICovDQo+ICtzdGF0aWMgdm9pZCBz ZW5kX2RvbmUoc3RydWN0IGliX2NxICpjcSwgc3RydWN0IGliX3djICp3YykNCj4gK3sNCj4gKwlp bnQgaTsNCj4gKwlzdHJ1Y3Qgc21iZF9yZXF1ZXN0ICpyZXF1ZXN0ID0NCj4gKwkJY29udGFpbmVy X29mKHdjLT53cl9jcWUsIHN0cnVjdCBzbWJkX3JlcXVlc3QsIGNxZSk7DQo+ICsNCj4gKwlsb2df cmRtYV9zZW5kKElORk8sICJzbWJkX3JlcXVlc3QgJXAgY29tcGxldGVkIHdjLQ0KPiA+c3RhdHVz PSVkXG4iLA0KPiArCQlyZXF1ZXN0LCB3Yy0+c3RhdHVzKTsNCj4gKw0KPiArCWlmICh3Yy0+c3Rh dHVzICE9IElCX1dDX1NVQ0NFU1MgfHwgd2MtPm9wY29kZSAhPSBJQl9XQ19TRU5EKSB7DQo+ICsJ CWxvZ19yZG1hX3NlbmQoRVJSLCAid2MtPnN0YXR1cz0lZCB3Yy0+b3Bjb2RlPSVkXG4iLA0KPiAr CQkJd2MtPnN0YXR1cywgd2MtPm9wY29kZSk7DQo+ICsJCXNtYmRfZGlzY29ubmVjdF9yZG1hX2Nv bm5lY3Rpb24ocmVxdWVzdC0+aW5mbyk7DQo+ICsJfQ0KPiArDQo+ICsJZm9yIChpID0gMDsgaSA8 IHJlcXVlc3QtPm51bV9zZ2U7IGkrKykNCj4gKwkJaWJfZG1hX3VubWFwX3NpbmdsZShyZXF1ZXN0 LT5pbmZvLT5pZC0+ZGV2aWNlLA0KPiArCQkJcmVxdWVzdC0+c2dlW2ldLmFkZHIsDQo+ICsJCQly ZXF1ZXN0LT5zZ2VbaV0ubGVuZ3RoLA0KPiArCQkJRE1BX1RPX0RFVklDRSk7DQo+ICsNCj4gKwlp ZiAocmVxdWVzdC0+aGFzX3BheWxvYWQpIHsNCj4gKwkJaWYgKGF0b21pY19kZWNfYW5kX3Rlc3Qo JnJlcXVlc3QtPmluZm8tDQo+ID5zZW5kX3BheWxvYWRfcGVuZGluZykpDQo+ICsJCQl3YWtlX3Vw KCZyZXF1ZXN0LT5pbmZvLQ0KPiA+d2FpdF9zZW5kX3BheWxvYWRfcGVuZGluZyk7DQo+ICsJfSBl bHNlIHsNCj4gKwkJaWYgKGF0b21pY19kZWNfYW5kX3Rlc3QoJnJlcXVlc3QtPmluZm8tPnNlbmRf cGVuZGluZykpDQo+ICsJCQl3YWtlX3VwKCZyZXF1ZXN0LT5pbmZvLT53YWl0X3NlbmRfcGVuZGlu Zyk7DQo+ICsJfQ0KPiArDQo+ICsJbWVtcG9vbF9mcmVlKHJlcXVlc3QsIHJlcXVlc3QtPmluZm8t PnJlcXVlc3RfbWVtcG9vbCk7DQo+ICt9DQo+ICsNCj4gK3N0YXRpYyB2b2lkIGR1bXBfc21iZF9u ZWdvdGlhdGVfcmVzcChzdHJ1Y3Qgc21iZF9uZWdvdGlhdGVfcmVzcA0KPiAqcmVzcCkNCj4gK3sN Cj4gKwlsb2dfcmRtYV9ldmVudChJTkZPLCAicmVzcCBtZXNzYWdlIG1pbl92ZXJzaW9uICV1IG1h eF92ZXJzaW9uDQo+ICV1ICINCj4gKwkJIm5lZ290aWF0ZWRfdmVyc2lvbiAldSBjcmVkaXRzX3Jl cXVlc3RlZCAldSAiDQo+ICsJCSJjcmVkaXRzX2dyYW50ZWQgJXUgc3RhdHVzICV1IG1heF9yZWFk d3JpdGVfc2l6ZSAldSAiDQo+ICsJCSJwcmVmZXJyZWRfc2VuZF9zaXplICV1IG1heF9yZWNlaXZl X3NpemUgJXUgIg0KPiArCQkibWF4X2ZyYWdtZW50ZWRfc2l6ZSAldVxuIiwNCj4gKwkJcmVzcC0+ bWluX3ZlcnNpb24sIHJlc3AtPm1heF92ZXJzaW9uLCByZXNwLQ0KPiA+bmVnb3RpYXRlZF92ZXJz aW9uLA0KPiArCQlyZXNwLT5jcmVkaXRzX3JlcXVlc3RlZCwgcmVzcC0+Y3JlZGl0c19ncmFudGVk LCByZXNwLQ0KPiA+c3RhdHVzLA0KPiArCQlyZXNwLT5tYXhfcmVhZHdyaXRlX3NpemUsIHJlc3At PnByZWZlcnJlZF9zZW5kX3NpemUsDQo+ICsJCXJlc3AtPm1heF9yZWNlaXZlX3NpemUsIHJlc3At Pm1heF9mcmFnbWVudGVkX3NpemUpOw0KPiArfQ0KPiArDQo+ICsvKg0KPiArICogUHJvY2VzcyBh IG5lZ290aWF0aW9uIHJlc3BvbnNlIG1lc3NhZ2UsIGFjY29yZGluZyB0byBbTVMtU01CRF0zLjEu NS43DQo+ICsgKiByZXNwb25zZSwgcGFja2V0X2xlbmd0aDogdGhlIG5lZ290aWF0aW9uIHJlc3Bv bnNlIG1lc3NhZ2UNCj4gKyAqIHJldHVybiB2YWx1ZTogdHJ1ZSBpZiBuZWdvdGlhdGlvbiBpcyBh IHN1Y2Nlc3MsIGZhbHNlIGlmIGZhaWxlZA0KPiArICovDQo+ICtzdGF0aWMgYm9vbCBwcm9jZXNz X25lZ290aWF0aW9uX3Jlc3BvbnNlKA0KPiArCQlzdHJ1Y3Qgc21iZF9yZXNwb25zZSAqcmVzcG9u c2UsIGludCBwYWNrZXRfbGVuZ3RoKQ0KPiArew0KPiArCXN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24g KmluZm8gPSByZXNwb25zZS0+aW5mbzsNCj4gKwlzdHJ1Y3Qgc21iZF9uZWdvdGlhdGVfcmVzcCAq cGFja2V0ID0NCj4gc21iZF9yZXNwb25zZV9wYXlsb2FkKHJlc3BvbnNlKTsNCj4gKw0KPiArCWlm IChwYWNrZXRfbGVuZ3RoIDwgc2l6ZW9mKHN0cnVjdCBzbWJkX25lZ290aWF0ZV9yZXNwKSkgew0K PiArCQlsb2dfcmRtYV9ldmVudChFUlIsDQo+ICsJCQkiZXJyb3I6IHBhY2tldF9sZW5ndGg9JWRc biIsIHBhY2tldF9sZW5ndGgpOw0KPiArCQlyZXR1cm4gZmFsc2U7DQo+ICsJfQ0KPiArDQo+ICsJ aWYgKGxlMTZfdG9fY3B1KHBhY2tldC0+bmVnb3RpYXRlZF92ZXJzaW9uKSAhPSBTTUJEX1YxKSB7 DQo+ICsJCWxvZ19yZG1hX2V2ZW50KEVSUiwgImVycm9yOiBuZWdvdGlhdGVkX3ZlcnNpb249JXhc biIsDQo+ICsJCQlsZTE2X3RvX2NwdShwYWNrZXQtPm5lZ290aWF0ZWRfdmVyc2lvbikpOw0KPiAr CQlyZXR1cm4gZmFsc2U7DQo+ICsJfQ0KPiArCWluZm8tPnByb3RvY29sID0gbGUxNl90b19jcHUo cGFja2V0LT5uZWdvdGlhdGVkX3ZlcnNpb24pOw0KPiArDQo+ICsJaWYgKHBhY2tldC0+Y3JlZGl0 c19yZXF1ZXN0ZWQgPT0gMCkgew0KPiArCQlsb2dfcmRtYV9ldmVudChFUlIsICJlcnJvcjogY3Jl ZGl0c19yZXF1ZXN0ZWQ9PTBcbiIpOw0KPiArCQlyZXR1cm4gZmFsc2U7DQo+ICsJfQ0KPiArCWlu Zm8tPnJlY2VpdmVfY3JlZGl0X3RhcmdldCA9IGxlMTZfdG9fY3B1KHBhY2tldC0NCj4gPmNyZWRp dHNfcmVxdWVzdGVkKTsNCj4gKw0KPiArCWlmIChwYWNrZXQtPmNyZWRpdHNfZ3JhbnRlZCA9PSAw KSB7DQo+ICsJCWxvZ19yZG1hX2V2ZW50KEVSUiwgImVycm9yOiBjcmVkaXRzX2dyYW50ZWQ9PTBc biIpOw0KPiArCQlyZXR1cm4gZmFsc2U7DQo+ICsJfQ0KPiArCWF0b21pY19zZXQoJmluZm8tPnNl bmRfY3JlZGl0cywgbGUxNl90b19jcHUocGFja2V0LQ0KPiA+Y3JlZGl0c19ncmFudGVkKSk7DQo+ ICsNCj4gKwlhdG9taWNfc2V0KCZpbmZvLT5yZWNlaXZlX2NyZWRpdHMsIDApOw0KPiArDQo+ICsJ aWYgKGxlMzJfdG9fY3B1KHBhY2tldC0+cHJlZmVycmVkX3NlbmRfc2l6ZSkgPiBpbmZvLQ0KPiA+ bWF4X3JlY2VpdmVfc2l6ZSkgew0KPiArCQlsb2dfcmRtYV9ldmVudChFUlIsICJlcnJvcjogcHJl ZmVycmVkX3NlbmRfc2l6ZT0lZFxuIiwNCj4gKwkJCWxlMzJfdG9fY3B1KHBhY2tldC0+cHJlZmVy cmVkX3NlbmRfc2l6ZSkpOw0KPiArCQlyZXR1cm4gZmFsc2U7DQo+ICsJfQ0KPiArCWluZm8tPm1h eF9yZWNlaXZlX3NpemUgPSBsZTMyX3RvX2NwdShwYWNrZXQtDQo+ID5wcmVmZXJyZWRfc2VuZF9z aXplKTsNCj4gKw0KPiArCWlmIChsZTMyX3RvX2NwdShwYWNrZXQtPm1heF9yZWNlaXZlX3NpemUp IDwNCj4gU01CRF9NSU5fUkVDRUlWRV9TSVpFKSB7DQo+ICsJCWxvZ19yZG1hX2V2ZW50KEVSUiwg ImVycm9yOiBtYXhfcmVjZWl2ZV9zaXplPSVkXG4iLA0KPiArCQkJbGUzMl90b19jcHUocGFja2V0 LT5tYXhfcmVjZWl2ZV9zaXplKSk7DQo+ICsJCXJldHVybiBmYWxzZTsNCj4gKwl9DQo+ICsJaW5m by0+bWF4X3NlbmRfc2l6ZSA9IG1pbl90KGludCwgaW5mby0+bWF4X3NlbmRfc2l6ZSwNCj4gKwkJ CQkJbGUzMl90b19jcHUocGFja2V0LQ0KPiA+bWF4X3JlY2VpdmVfc2l6ZSkpOw0KPiArDQo+ICsJ aWYgKGxlMzJfdG9fY3B1KHBhY2tldC0+bWF4X2ZyYWdtZW50ZWRfc2l6ZSkgPA0KPiArCQkJU01C RF9NSU5fRlJBR01FTlRFRF9TSVpFKSB7DQo+ICsJCWxvZ19yZG1hX2V2ZW50KEVSUiwgImVycm9y OiBtYXhfZnJhZ21lbnRlZF9zaXplPSVkXG4iLA0KPiArCQkJbGUzMl90b19jcHUocGFja2V0LT5t YXhfZnJhZ21lbnRlZF9zaXplKSk7DQo+ICsJCXJldHVybiBmYWxzZTsNCj4gKwl9DQo+ICsJaW5m by0+bWF4X2ZyYWdtZW50ZWRfc2VuZF9zaXplID0NCj4gKwkJbGUzMl90b19jcHUocGFja2V0LT5t YXhfZnJhZ21lbnRlZF9zaXplKTsNCj4gKw0KPiArCXJldHVybiB0cnVlOw0KPiArfQ0KPiArDQo+ ICsvKg0KPiArICogQ2hlY2sgYW5kIHNjaGVkdWxlIHRvIHNlbmQgYW4gaW1tZWRpYXRlIHBhY2tl dA0KPiArICogVGhpcyBpcyB1c2VkIHRvIGV4dGVuZCBjcmVkdGlzIHRvIHJlbW90ZSBwZWVyIHRv IGtlZXAgdGhlIHRyYW5zcG9ydCBidXN5DQo+ICsgKi8NCj4gK3N0YXRpYyB2b2lkIGNoZWNrX2Fu ZF9zZW5kX2ltbWVkaWF0ZShzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvKQ0KPiArew0KPiAr CWlmIChpbmZvLT50cmFuc3BvcnRfc3RhdHVzICE9IFNNQkRfQ09OTkVDVEVEKQ0KPiArCQlyZXR1 cm47DQo+ICsNCj4gKwlpbmZvLT5zZW5kX2ltbWVkaWF0ZSA9IHRydWU7DQo+ICsNCj4gKwkvKg0K PiArCSAqIFByb21wdGx5IHNlbmQgYSBwYWNrZXQgaWYgb3VyIHBlZXIgaXMgcnVubmluZyBsb3cg b24gcmVjZWl2ZQ0KPiArCSAqIGNyZWRpdHMNCj4gKwkgKi8NCj4gKwlpZiAoYXRvbWljX3JlYWQo JmluZm8tPnJlY2VpdmVfY3JlZGl0cykgPA0KPiArCQlpbmZvLT5yZWNlaXZlX2NyZWRpdF90YXJn ZXQgLSAxKQ0KPiArCQlxdWV1ZV9kZWxheWVkX3dvcmsoDQo+ICsJCQlpbmZvLT53b3JrcXVldWUs ICZpbmZvLT5zZW5kX2ltbWVkaWF0ZV93b3JrLA0KPiAwKTsNCj4gK30NCj4gKw0KPiArc3RhdGlj IHZvaWQgc21iZF9wb3N0X3NlbmRfY3JlZGl0cyhzdHJ1Y3Qgd29ya19zdHJ1Y3QgKndvcmspDQo+ ICt7DQo+ICsJaW50IHJldCA9IDA7DQo+ICsJaW50IHVzZV9yZWNlaXZlX3F1ZXVlID0gMTsNCj4g KwlpbnQgcmM7DQo+ICsJc3RydWN0IHNtYmRfcmVzcG9uc2UgKnJlc3BvbnNlOw0KPiArCXN0cnVj dCBzbWJkX2Nvbm5lY3Rpb24gKmluZm8gPQ0KPiArCQljb250YWluZXJfb2Yod29yaywgc3RydWN0 IHNtYmRfY29ubmVjdGlvbiwNCj4gKwkJCXBvc3Rfc2VuZF9jcmVkaXRzX3dvcmspOw0KPiArDQo+ ICsJaWYgKGluZm8tPnRyYW5zcG9ydF9zdGF0dXMgIT0gU01CRF9DT05ORUNURUQpIHsNCj4gKwkJ d2FrZV91cCgmaW5mby0+d2FpdF9yZWNlaXZlX3F1ZXVlcyk7DQo+ICsJCXJldHVybjsNCj4gKwl9 DQo+ICsNCj4gKwlpZiAoaW5mby0+cmVjZWl2ZV9jcmVkaXRfdGFyZ2V0ID4NCj4gKwkJYXRvbWlj X3JlYWQoJmluZm8tPnJlY2VpdmVfY3JlZGl0cykpIHsNCj4gKwkJd2hpbGUgKHRydWUpIHsNCj4g KwkJCWlmICh1c2VfcmVjZWl2ZV9xdWV1ZSkNCj4gKwkJCQlyZXNwb25zZSA9IGdldF9yZWNlaXZl X2J1ZmZlcihpbmZvKTsNCj4gKwkJCWVsc2UNCj4gKwkJCQlyZXNwb25zZSA9IGdldF9lbXB0eV9x dWV1ZV9idWZmZXIoaW5mbyk7DQo+ICsJCQlpZiAoIXJlc3BvbnNlKSB7DQo+ICsJCQkJLyogbm93 IHN3aXRjaCB0byBlbXRweSBwYWNrZXQgcXVldWUgKi8NCj4gKwkJCQlpZiAodXNlX3JlY2VpdmVf cXVldWUpIHsNCj4gKwkJCQkJdXNlX3JlY2VpdmVfcXVldWUgPSAwOw0KPiArCQkJCQljb250aW51 ZTsNCj4gKwkJCQl9IGVsc2UNCj4gKwkJCQkJYnJlYWs7DQo+ICsJCQl9DQo+ICsNCj4gKwkJCXJl c3BvbnNlLT50eXBlID0gU01CRF9UUkFOU0ZFUl9EQVRBOw0KPiArCQkJcmVzcG9uc2UtPmZpcnN0 X3NlZ21lbnQgPSBmYWxzZTsNCj4gKwkJCXJjID0gc21iZF9wb3N0X3JlY3YoaW5mbywgcmVzcG9u c2UpOw0KPiArCQkJaWYgKHJjKSB7DQo+ICsJCQkJbG9nX3JkbWFfcmVjdihFUlIsDQo+ICsJCQkJ CSJwb3N0X3JlY3YgZmFpbGVkIHJjPSVkXG4iLCByYyk7DQo+ICsJCQkJcHV0X3JlY2VpdmVfYnVm ZmVyKGluZm8sIHJlc3BvbnNlLCB0cnVlKTsNCj4gKwkJCQlicmVhazsNCj4gKwkJCX0NCj4gKw0K PiArCQkJcmV0Kys7DQo+ICsJCX0NCj4gKwl9DQo+ICsNCj4gKwlzcGluX2xvY2soJmluZm8tPmxv Y2tfbmV3X2NyZWRpdHNfb2ZmZXJlZCk7DQo+ICsJaW5mby0+bmV3X2NyZWRpdHNfb2ZmZXJlZCAr PSByZXQ7DQo+ICsJc3Bpbl91bmxvY2soJmluZm8tPmxvY2tfbmV3X2NyZWRpdHNfb2ZmZXJlZCk7 DQo+ICsNCj4gKwlhdG9taWNfYWRkKHJldCwgJmluZm8tPnJlY2VpdmVfY3JlZGl0cyk7DQo+ICsN Cj4gKwkvKiBDaGVjayBpZiB3ZSBjYW4gcG9zdCBuZXcgcmVjZWl2ZSBhbmQgZ3JhbnQgY3JlZGl0 cyB0byBwZWVyICovDQo+ICsJY2hlY2tfYW5kX3NlbmRfaW1tZWRpYXRlKGluZm8pOw0KPiArfQ0K PiArDQo+ICtzdGF0aWMgdm9pZCBzbWJkX3JlY3ZfZG9uZV93b3JrKHN0cnVjdCB3b3JrX3N0cnVj dCAqd29yaykNCj4gK3sNCj4gKwlzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvID0NCj4gKwkJ Y29udGFpbmVyX29mKHdvcmssIHN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24sDQo+IHJlY3ZfZG9uZV93 b3JrKTsNCj4gKw0KPiArCS8qDQo+ICsJICogV2UgbWF5IGhhdmUgbmV3IHNlbmQgY3JlZGl0cyBn cmFudGVkIGZyb20gcmVtb3RlIHBlZXINCj4gKwkgKiBJZiBhbnkgc2VuZGVyIGlzIGJsY29rZWQg b24gbGFjayBvZiBjcmVkZXRzLCB1bmJsb2NrIGl0DQo+ICsJICovDQo+ICsJaWYgKGF0b21pY19y ZWFkKCZpbmZvLT5zZW5kX2NyZWRpdHMpKQ0KPiArCQl3YWtlX3VwX2ludGVycnVwdGlibGUoJmlu Zm8tPndhaXRfc2VuZF9xdWV1ZSk7DQo+ICsNCj4gKwkvKg0KPiArCSAqIENoZWNrIGlmIHdlIG5l ZWQgdG8gc2VuZCBzb21ldGhpbmcgdG8gcmVtb3RlIHBlZXIgdG8NCj4gKwkgKiBncmFudCBtb3Jl IGNyZWRpdHMgb3IgcmVzcG9uZCB0byBLRUVQX0FMSVZFIHBhY2tldA0KPiArCSAqLw0KPiArCWNo ZWNrX2FuZF9zZW5kX2ltbWVkaWF0ZShpbmZvKTsNCj4gK30NCj4gKw0KPiArLyogQ2FsbGVkIGZy b20gc29mdGlycSwgd2hlbiByZWN2IGlzIGRvbmUgKi8NCj4gK3N0YXRpYyB2b2lkIHJlY3ZfZG9u ZShzdHJ1Y3QgaWJfY3EgKmNxLCBzdHJ1Y3QgaWJfd2MgKndjKQ0KPiArew0KPiArCXN0cnVjdCBz bWJkX2RhdGFfdHJhbnNmZXIgKmRhdGFfdHJhbnNmZXI7DQo+ICsJc3RydWN0IHNtYmRfcmVzcG9u c2UgKnJlc3BvbnNlID0NCj4gKwkJY29udGFpbmVyX29mKHdjLT53cl9jcWUsIHN0cnVjdCBzbWJk X3Jlc3BvbnNlLCBjcWUpOw0KPiArCXN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24gKmluZm8gPSByZXNw b25zZS0+aW5mbzsNCj4gKwlpbnQgZGF0YV9sZW5ndGggPSAwOw0KPiArDQo+ICsJbG9nX3JkbWFf cmVjdihJTkZPLCAicmVzcG9uc2U9JXAgdHlwZT0lZCB3YyBzdGF0dXM9JWQgd2MNCj4gb3Bjb2Rl ICVkICINCj4gKwkJICAgICAgImJ5dGVfbGVuPSVkIHBrZXlfaW5kZXg9JXhcbiIsDQo+ICsJCXJl c3BvbnNlLCByZXNwb25zZS0+dHlwZSwgd2MtPnN0YXR1cywgd2MtPm9wY29kZSwNCj4gKwkJd2Mt PmJ5dGVfbGVuLCB3Yy0+cGtleV9pbmRleCk7DQo+ICsNCj4gKwlpZiAod2MtPnN0YXR1cyAhPSBJ Ql9XQ19TVUNDRVNTIHx8IHdjLT5vcGNvZGUgIT0gSUJfV0NfUkVDVikgew0KPiArCQlsb2dfcmRt YV9yZWN2KElORk8sICJ3Yy0+c3RhdHVzPSVkIG9wY29kZT0lZFxuIiwNCj4gKwkJCXdjLT5zdGF0 dXMsIHdjLT5vcGNvZGUpOw0KPiArCQlzbWJkX2Rpc2Nvbm5lY3RfcmRtYV9jb25uZWN0aW9uKGlu Zm8pOw0KPiArCQlnb3RvIGVycm9yOw0KPiArCX0NCj4gKw0KPiArCWliX2RtYV9zeW5jX3Npbmds ZV9mb3JfY3B1KA0KPiArCQl3Yy0+cXAtPmRldmljZSwNCj4gKwkJcmVzcG9uc2UtPnNnZS5hZGRy LA0KPiArCQlyZXNwb25zZS0+c2dlLmxlbmd0aCwNCj4gKwkJRE1BX0ZST01fREVWSUNFKTsNCj4g Kw0KPiArCXN3aXRjaCAocmVzcG9uc2UtPnR5cGUpIHsNCj4gKwkvKiBTTUJEIG5lZ290aWF0aW9u IHJlc3BvbnNlICovDQo+ICsJY2FzZSBTTUJEX05FR09USUFURV9SRVNQOg0KPiArDQo+IAlkdW1w X3NtYmRfbmVnb3RpYXRlX3Jlc3Aoc21iZF9yZXNwb25zZV9wYXlsb2FkKHJlc3BvbnNlKSk7DQo+ ICsJCWluZm8tPmZ1bGxfcGFja2V0X3JlY2VpdmVkID0gdHJ1ZTsNCj4gKwkJaW5mby0+bmVnb3Rp YXRlX2RvbmUgPQ0KPiArCQkJcHJvY2Vzc19uZWdvdGlhdGlvbl9yZXNwb25zZShyZXNwb25zZSwg d2MtDQo+ID5ieXRlX2xlbik7DQo+ICsJCWNvbXBsZXRlKCZpbmZvLT5uZWdvdGlhdGVfY29tcGxl dGlvbik7DQo+ICsJCWJyZWFrOw0KPiArDQo+ICsJLyogU01CRCBkYXRhIHRyYW5zZmVyIHBhY2tl dCAqLw0KPiArCWNhc2UgU01CRF9UUkFOU0ZFUl9EQVRBOg0KPiArCQlkYXRhX3RyYW5zZmVyID0g c21iZF9yZXNwb25zZV9wYXlsb2FkKHJlc3BvbnNlKTsNCj4gKwkJZGF0YV9sZW5ndGggPSBsZTMy X3RvX2NwdShkYXRhX3RyYW5zZmVyLT5kYXRhX2xlbmd0aCk7DQo+ICsNCj4gKwkJLyoNCj4gKwkJ ICogSWYgdGhpcyBpcyBhIHBhY2tldCB3aXRoIGRhdGEgcGxheWxvYWQgcGxhY2UgdGhlIGRhdGEg aW4NCj4gKwkJICogcmVhc3NlbWJseSBxdWV1ZSBhbmQgd2FrZSB1cCB0aGUgcmVhZGluZyB0aHJl YWQNCj4gKwkJICovDQo+ICsJCWlmIChkYXRhX2xlbmd0aCkgew0KPiArCQkJaWYgKGluZm8tPmZ1 bGxfcGFja2V0X3JlY2VpdmVkKQ0KPiArCQkJCXJlc3BvbnNlLT5maXJzdF9zZWdtZW50ID0gdHJ1 ZTsNCj4gKw0KPiArCQkJaWYgKGxlMzJfdG9fY3B1KGRhdGFfdHJhbnNmZXItDQo+ID5yZW1haW5p bmdfZGF0YV9sZW5ndGgpKQ0KPiArCQkJCWluZm8tPmZ1bGxfcGFja2V0X3JlY2VpdmVkID0gZmFs c2U7DQo+ICsJCQllbHNlDQo+ICsJCQkJaW5mby0+ZnVsbF9wYWNrZXRfcmVjZWl2ZWQgPSB0cnVl Ow0KPiArDQo+ICsJCQllbnF1ZXVlX3JlYXNzZW1ibHkoDQo+ICsJCQkJaW5mbywNCj4gKwkJCQly ZXNwb25zZSwNCj4gKwkJCQlkYXRhX2xlbmd0aCk7DQo+ICsJCX0gZWxzZQ0KPiArCQkJcHV0X2Vt cHR5X3BhY2tldChpbmZvLCByZXNwb25zZSk7DQo+ICsNCj4gKwkJaWYgKGRhdGFfbGVuZ3RoKQ0K PiArCQkJd2FrZV91cF9pbnRlcnJ1cHRpYmxlKCZpbmZvLQ0KPiA+d2FpdF9yZWFzc2VtYmx5X3F1 ZXVlKTsNCj4gKw0KPiArCQlhdG9taWNfZGVjKCZpbmZvLT5yZWNlaXZlX2NyZWRpdHMpOw0KPiAr CQlpbmZvLT5yZWNlaXZlX2NyZWRpdF90YXJnZXQgPQ0KPiArCQkJbGUxNl90b19jcHUoZGF0YV90 cmFuc2Zlci0+Y3JlZGl0c19yZXF1ZXN0ZWQpOw0KPiArCQlhdG9taWNfYWRkKGxlMTZfdG9fY3B1 KGRhdGFfdHJhbnNmZXItPmNyZWRpdHNfZ3JhbnRlZCksDQo+ICsJCQkmaW5mby0+c2VuZF9jcmVk aXRzKTsNCj4gKw0KPiArCQlsb2dfaW5jb21pbmcoSU5GTywgImRhdGEgZmxhZ3MgJWQgZGF0YV9v ZmZzZXQgJWQgIg0KPiArCQkJImRhdGFfbGVuZ3RoICVkIHJlbWFpbmluZ19kYXRhX2xlbmd0aCAl ZFxuIiwNCj4gKwkJCWxlMTZfdG9fY3B1KGRhdGFfdHJhbnNmZXItPmZsYWdzKSwNCj4gKwkJCWxl MzJfdG9fY3B1KGRhdGFfdHJhbnNmZXItPmRhdGFfb2Zmc2V0KSwNCj4gKwkJCWxlMzJfdG9fY3B1 KGRhdGFfdHJhbnNmZXItPmRhdGFfbGVuZ3RoKSwNCj4gKwkJCWxlMzJfdG9fY3B1KGRhdGFfdHJh bnNmZXItDQo+ID5yZW1haW5pbmdfZGF0YV9sZW5ndGgpKTsNCj4gKw0KPiArCQkvKiBTZW5kIGEg S0VFUF9BTElWRSByZXNwb25zZSByaWdodCBhd2F5IGlmIHJlcXVlc3RlZCAqLw0KPiArCQlpbmZv LT5rZWVwX2FsaXZlX3JlcXVlc3RlZCA9IEtFRVBfQUxJVkVfTk9ORTsNCj4gKwkJaWYgKGxlMTZf dG9fY3B1KGRhdGFfdHJhbnNmZXItPmZsYWdzKSAmDQo+ICsJCQkJU01CX0RJUkVDVF9SRVNQT05T RV9SRVFVRVNURUQpIHsNCj4gKwkJCWluZm8tPmtlZXBfYWxpdmVfcmVxdWVzdGVkID0NCj4gS0VF UF9BTElWRV9QRU5ESU5HOw0KPiArCQl9DQo+ICsNCj4gKwkJcXVldWVfd29yayhpbmZvLT53b3Jr cXVldWUsICZpbmZvLT5yZWN2X2RvbmVfd29yayk7DQo+ICsJCXJldHVybjsNCj4gKw0KPiArCWRl ZmF1bHQ6DQo+ICsJCWxvZ19yZG1hX3JlY3YoRVJSLA0KPiArCQkJInVuZXhwZWN0ZWQgcmVzcG9u c2UgdHlwZT0lZFxuIiwgcmVzcG9uc2UtDQo+ID50eXBlKTsNCj4gKwl9DQo+ICsNCj4gK2Vycm9y Og0KPiArCXB1dF9yZWNlaXZlX2J1ZmZlcihpbmZvLCByZXNwb25zZSwgdHJ1ZSk7DQo+ICt9DQo+ ICsNCj4gK3N0YXRpYyBzdHJ1Y3QgcmRtYV9jbV9pZCAqc21iZF9jcmVhdGVfaWQoDQo+ICsJCXN0 cnVjdCBzbWJkX2Nvbm5lY3Rpb24gKmluZm8sDQo+ICsJCXN0cnVjdCBzb2NrYWRkciAqZHN0YWRk ciwgaW50IHBvcnQpDQo+ICt7DQo+ICsJc3RydWN0IHJkbWFfY21faWQgKmlkOw0KPiArCWludCBy YzsNCj4gKwlfX2JlMTYgKnNwb3J0Ow0KPiArDQo+ICsJaWQgPSByZG1hX2NyZWF0ZV9pZCgmaW5p dF9uZXQsIHNtYmRfY29ubl91cGNhbGwsIGluZm8sDQo+ICsJCVJETUFfUFNfVENQLCBJQl9RUFRf UkMpOw0KPiArCWlmIChJU19FUlIoaWQpKSB7DQo+ICsJCXJjID0gUFRSX0VSUihpZCk7DQo+ICsJ CWxvZ19yZG1hX2V2ZW50KEVSUiwgInJkbWFfY3JlYXRlX2lkKCkgZmFpbGVkICVpXG4iLCByYyk7 DQo+ICsJCXJldHVybiBpZDsNCj4gKwl9DQo+ICsNCj4gKwlpZiAoZHN0YWRkci0+c2FfZmFtaWx5 ID09IEFGX0lORVQ2KQ0KPiArCQlzcG9ydCA9ICYoKHN0cnVjdCBzb2NrYWRkcl9pbjYgKilkc3Rh ZGRyKS0+c2luNl9wb3J0Ow0KPiArCWVsc2UNCj4gKwkJc3BvcnQgPSAmKChzdHJ1Y3Qgc29ja2Fk ZHJfaW4gKilkc3RhZGRyKS0+c2luX3BvcnQ7DQo+ICsNCj4gKwkqc3BvcnQgPSBodG9ucyhwb3J0 KTsNCj4gKw0KPiArCWluaXRfY29tcGxldGlvbigmaW5mby0+cmlfZG9uZSk7DQo+ICsJaW5mby0+ cmlfcmMgPSAtRVRJTUVET1VUOw0KPiArDQo+ICsJcmMgPSByZG1hX3Jlc29sdmVfYWRkcihpZCwg TlVMTCwgKHN0cnVjdCBzb2NrYWRkciAqKWRzdGFkZHIsDQo+ICsJCVJETUFfUkVTT0xWRV9USU1F T1VUKTsNCj4gKwlpZiAocmMpIHsNCj4gKwkJbG9nX3JkbWFfZXZlbnQoRVJSLCAicmRtYV9yZXNv bHZlX2FkZHIoKSBmYWlsZWQgJWlcbiIsDQo+IHJjKTsNCj4gKwkJZ290byBvdXQ7DQo+ICsJfQ0K PiArCXdhaXRfZm9yX2NvbXBsZXRpb25faW50ZXJydXB0aWJsZV90aW1lb3V0KA0KPiArCQkmaW5m by0+cmlfZG9uZSwNCj4gbXNlY3NfdG9famlmZmllcyhSRE1BX1JFU09MVkVfVElNRU9VVCkpOw0K PiArCXJjID0gaW5mby0+cmlfcmM7DQo+ICsJaWYgKHJjKSB7DQo+ICsJCWxvZ19yZG1hX2V2ZW50 KEVSUiwgInJkbWFfcmVzb2x2ZV9hZGRyKCkgY29tcGxldGVkDQo+ICVpXG4iLCByYyk7DQo+ICsJ CWdvdG8gb3V0Ow0KPiArCX0NCj4gKw0KPiArCWluZm8tPnJpX3JjID0gLUVUSU1FRE9VVDsNCj4g KwlyYyA9IHJkbWFfcmVzb2x2ZV9yb3V0ZShpZCwgUkRNQV9SRVNPTFZFX1RJTUVPVVQpOw0KPiAr CWlmIChyYykgew0KPiArCQlsb2dfcmRtYV9ldmVudChFUlIsICJyZG1hX3Jlc29sdmVfcm91dGUo KSBmYWlsZWQgJWlcbiIsDQo+IHJjKTsNCj4gKwkJZ290byBvdXQ7DQo+ICsJfQ0KPiArCXdhaXRf Zm9yX2NvbXBsZXRpb25faW50ZXJydXB0aWJsZV90aW1lb3V0KA0KPiArCQkmaW5mby0+cmlfZG9u ZSwNCj4gbXNlY3NfdG9famlmZmllcyhSRE1BX1JFU09MVkVfVElNRU9VVCkpOw0KPiArCXJjID0g aW5mby0+cmlfcmM7DQo+ICsJaWYgKHJjKSB7DQo+ICsJCWxvZ19yZG1hX2V2ZW50KEVSUiwgInJk bWFfcmVzb2x2ZV9yb3V0ZSgpIGNvbXBsZXRlZA0KPiAlaVxuIiwgcmMpOw0KPiArCQlnb3RvIG91 dDsNCj4gKwl9DQo+ICsNCj4gKwlyZXR1cm4gaWQ7DQo+ICsNCj4gK291dDoNCj4gKwlyZG1hX2Rl c3Ryb3lfaWQoaWQpOw0KPiArCXJldHVybiBFUlJfUFRSKHJjKTsNCj4gK30NCj4gKw0KPiArLyoN Cj4gKyAqIFRlc3QgaWYgRlJXUiAoRmFzdCBSZWdpc3RyYXRpb24gV29yayBSZXF1ZXN0cykgaXMg c3VwcG9ydGVkIG9uIHRoZQ0KPiBkZXZpY2UNCj4gKyAqIFRoaXMgaW1wbGVtZW50YXRpb24gcmVx dXJpZXMgRlJXUiBvbiBSRE1BIHJlYWQvd3JpdGUNCj4gKyAqIHJldHVybiB2YWx1ZTogdHJ1ZSBp ZiBpdCBpcyBzdXBwb3J0ZWQNCj4gKyAqLw0KPiArc3RhdGljIGJvb2wgZnJ3cl9pc19zdXBwb3J0 ZWQoc3RydWN0IGliX2RldmljZV9hdHRyICphdHRycykNCj4gK3sNCj4gKwlpZiAoIShhdHRycy0+ ZGV2aWNlX2NhcF9mbGFncyAmDQo+IElCX0RFVklDRV9NRU1fTUdUX0VYVEVOU0lPTlMpKQ0KPiAr CQlyZXR1cm4gZmFsc2U7DQo+ICsJaWYgKGF0dHJzLT5tYXhfZmFzdF9yZWdfcGFnZV9saXN0X2xl biA9PSAwKQ0KPiArCQlyZXR1cm4gZmFsc2U7DQo+ICsJcmV0dXJuIHRydWU7DQo+ICt9DQo+ICsN Cj4gK3N0YXRpYyBpbnQgc21iZF9pYV9vcGVuKA0KPiArCQlzdHJ1Y3Qgc21iZF9jb25uZWN0aW9u ICppbmZvLA0KPiArCQlzdHJ1Y3Qgc29ja2FkZHIgKmRzdGFkZHIsIGludCBwb3J0KQ0KPiArew0K PiArCWludCByYzsNCj4gKw0KPiArCWluZm8tPmlkID0gc21iZF9jcmVhdGVfaWQoaW5mbywgZHN0 YWRkciwgcG9ydCk7DQo+ICsJaWYgKElTX0VSUihpbmZvLT5pZCkpIHsNCj4gKwkJcmMgPSBQVFJf RVJSKGluZm8tPmlkKTsNCj4gKwkJZ290byBvdXQxOw0KPiArCX0NCj4gKw0KPiArCWlmICghZnJ3 cl9pc19zdXBwb3J0ZWQoJmluZm8tPmlkLT5kZXZpY2UtPmF0dHJzKSkgew0KPiArCQlsb2dfcmRt YV9ldmVudChFUlIsDQo+ICsJCQkiRmFzdCBSZWdpc3RyYXRpb24gV29yayBSZXF1ZXN0cyAiDQo+ ICsJCQkiKEZSV1IpIGlzIG5vdCBzdXBwb3J0ZWRcbiIpOw0KPiArCQlsb2dfcmRtYV9ldmVudChF UlIsDQo+ICsJCQkiRGV2aWNlIGNhcGFiaWxpdHkgZmxhZ3MgPSAlbGx4ICINCj4gKwkJCSJtYXhf ZmFzdF9yZWdfcGFnZV9saXN0X2xlbiA9ICV1XG4iLA0KPiArCQkJaW5mby0+aWQtPmRldmljZS0+ YXR0cnMuZGV2aWNlX2NhcF9mbGFncywNCj4gKwkJCWluZm8tPmlkLT5kZXZpY2UtDQo+ID5hdHRy cy5tYXhfZmFzdF9yZWdfcGFnZV9saXN0X2xlbik7DQo+ICsJCXJjID0gLUVQUk9UT05PU1VQUE9S VDsNCj4gKwkJZ290byBvdXQyOw0KPiArCX0NCj4gKw0KPiArCWluZm8tPnBkID0gaWJfYWxsb2Nf cGQoaW5mby0+aWQtPmRldmljZSwgMCk7DQo+ICsJaWYgKElTX0VSUihpbmZvLT5wZCkpIHsNCj4g KwkJcmMgPSBQVFJfRVJSKGluZm8tPnBkKTsNCj4gKwkJbG9nX3JkbWFfZXZlbnQoRVJSLCAiaWJf YWxsb2NfcGQoKSByZXR1cm5lZCAlZFxuIiwgcmMpOw0KPiArCQlnb3RvIG91dDI7DQo+ICsJfQ0K PiArDQo+ICsJcmV0dXJuIDA7DQo+ICsNCj4gK291dDI6DQo+ICsJcmRtYV9kZXN0cm95X2lkKGlu Zm8tPmlkKTsNCj4gKwlpbmZvLT5pZCA9IE5VTEw7DQo+ICsNCj4gK291dDE6DQo+ICsJcmV0dXJu IHJjOw0KPiArfQ0KPiArDQo+ICsvKg0KPiArICogU2VuZCBhIG5lZ290aWF0aW9uIHJlcXVlc3Qg bWVzc2FnZSB0byB0aGUgcGVlcg0KPiArICogVGhlIG5lZ290aWF0aW9uIHByb2NlZHVyZSBpcyBp biBbTVMtU01CRF0gMy4xLjUuMiBhbmQgMy4xLjUuMw0KPiArICogQWZ0ZXIgbmVnb3RpYXRpb24s IHRoZSB0cmFuc3BvcnQgaXMgY29ubmVjdGVkIGFuZCByZWFkeSBmb3INCj4gKyAqIGNhcnJ5aW5n IHVwcGVyIGxheWVyIFNNQiBwYXlsb2FkDQo+ICsgKi8NCj4gK3N0YXRpYyBpbnQgc21iZF9wb3N0 X3NlbmRfbmVnb3RpYXRlX3JlcShzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvKQ0KPiArew0K PiArCXN0cnVjdCBpYl9zZW5kX3dyIHNlbmRfd3IsICpzZW5kX3dyX2ZhaWw7DQo+ICsJaW50IHJj ID0gLUVOT01FTTsNCj4gKwlzdHJ1Y3Qgc21iZF9yZXF1ZXN0ICpyZXF1ZXN0Ow0KPiArCXN0cnVj dCBzbWJkX25lZ290aWF0ZV9yZXEgKnBhY2tldDsNCj4gKw0KPiArCXJlcXVlc3QgPSBtZW1wb29s X2FsbG9jKGluZm8tPnJlcXVlc3RfbWVtcG9vbCwgR0ZQX0tFUk5FTCk7DQo+ICsJaWYgKCFyZXF1 ZXN0KQ0KPiArCQlyZXR1cm4gcmM7DQo+ICsNCj4gKwlyZXF1ZXN0LT5pbmZvID0gaW5mbzsNCj4g Kw0KPiArCXBhY2tldCA9IHNtYmRfcmVxdWVzdF9wYXlsb2FkKHJlcXVlc3QpOw0KPiArCXBhY2tl dC0+bWluX3ZlcnNpb24gPSBjcHVfdG9fbGUxNihTTUJEX1YxKTsNCj4gKwlwYWNrZXQtPm1heF92 ZXJzaW9uID0gY3B1X3RvX2xlMTYoU01CRF9WMSk7DQo+ICsJcGFja2V0LT5yZXNlcnZlZCA9IDA7 DQo+ICsJcGFja2V0LT5jcmVkaXRzX3JlcXVlc3RlZCA9IGNwdV90b19sZTE2KGluZm8tDQo+ID5z ZW5kX2NyZWRpdF90YXJnZXQpOw0KPiArCXBhY2tldC0+cHJlZmVycmVkX3NlbmRfc2l6ZSA9IGNw dV90b19sZTMyKGluZm8tPm1heF9zZW5kX3NpemUpOw0KPiArCXBhY2tldC0+bWF4X3JlY2VpdmVf c2l6ZSA9IGNwdV90b19sZTMyKGluZm8tPm1heF9yZWNlaXZlX3NpemUpOw0KPiArCXBhY2tldC0+ bWF4X2ZyYWdtZW50ZWRfc2l6ZSA9DQo+ICsJCWNwdV90b19sZTMyKGluZm8tPm1heF9mcmFnbWVu dGVkX3JlY3Zfc2l6ZSk7DQo+ICsNCj4gKwlyZXF1ZXN0LT5udW1fc2dlID0gMTsNCj4gKwlyZXF1 ZXN0LT5zZ2VbMF0uYWRkciA9IGliX2RtYV9tYXBfc2luZ2xlKA0KPiArCQkJCWluZm8tPmlkLT5k ZXZpY2UsICh2b2lkICopcGFja2V0LA0KPiArCQkJCXNpemVvZigqcGFja2V0KSwgRE1BX1RPX0RF VklDRSk7DQo+ICsJaWYgKGliX2RtYV9tYXBwaW5nX2Vycm9yKGluZm8tPmlkLT5kZXZpY2UsIHJl cXVlc3QtPnNnZVswXS5hZGRyKSkNCj4gew0KPiArCQlyYyA9IC1FSU87DQo+ICsJCWdvdG8gZG1h X21hcHBpbmdfZmFpbGVkOw0KPiArCX0NCj4gKw0KPiArCXJlcXVlc3QtPnNnZVswXS5sZW5ndGgg PSBzaXplb2YoKnBhY2tldCk7DQo+ICsJcmVxdWVzdC0+c2dlWzBdLmxrZXkgPSBpbmZvLT5wZC0+ bG9jYWxfZG1hX2xrZXk7DQo+ICsNCj4gKwlpYl9kbWFfc3luY19zaW5nbGVfZm9yX2RldmljZSgN Cj4gKwkJaW5mby0+aWQtPmRldmljZSwgcmVxdWVzdC0+c2dlWzBdLmFkZHIsDQo+ICsJCXJlcXVl c3QtPnNnZVswXS5sZW5ndGgsIERNQV9UT19ERVZJQ0UpOw0KPiArDQo+ICsJcmVxdWVzdC0+Y3Fl LmRvbmUgPSBzZW5kX2RvbmU7DQo+ICsNCj4gKwlzZW5kX3dyLm5leHQgPSBOVUxMOw0KPiArCXNl bmRfd3Iud3JfY3FlID0gJnJlcXVlc3QtPmNxZTsNCj4gKwlzZW5kX3dyLnNnX2xpc3QgPSByZXF1 ZXN0LT5zZ2U7DQo+ICsJc2VuZF93ci5udW1fc2dlID0gcmVxdWVzdC0+bnVtX3NnZTsNCj4gKwlz ZW5kX3dyLm9wY29kZSA9IElCX1dSX1NFTkQ7DQo+ICsJc2VuZF93ci5zZW5kX2ZsYWdzID0gSUJf U0VORF9TSUdOQUxFRDsNCj4gKw0KPiArCWxvZ19yZG1hX3NlbmQoSU5GTywgInNnZSBhZGRyPSVs bHggbGVuZ3RoPSV4IGxrZXk9JXhcbiIsDQo+ICsJCXJlcXVlc3QtPnNnZVswXS5hZGRyLA0KPiAr CQlyZXF1ZXN0LT5zZ2VbMF0ubGVuZ3RoLCByZXF1ZXN0LT5zZ2VbMF0ubGtleSk7DQo+ICsNCj4g KwlyZXF1ZXN0LT5oYXNfcGF5bG9hZCA9IGZhbHNlOw0KPiArCWF0b21pY19pbmMoJmluZm8tPnNl bmRfcGVuZGluZyk7DQo+ICsJcmMgPSBpYl9wb3N0X3NlbmQoaW5mby0+aWQtPnFwLCAmc2VuZF93 ciwgJnNlbmRfd3JfZmFpbCk7DQo+ICsJaWYgKCFyYykNCj4gKwkJcmV0dXJuIDA7DQo+ICsNCj4g KwkvKiBpZiB3ZSByZWFjaCBoZXJlLCBwb3N0IHNlbmQgZmFpbGVkICovDQo+ICsJbG9nX3JkbWFf c2VuZChFUlIsICJpYl9wb3N0X3NlbmQgZmFpbGVkIHJjPSVkXG4iLCByYyk7DQo+ICsJYXRvbWlj X2RlYygmaW5mby0+c2VuZF9wZW5kaW5nKTsNCj4gKwlpYl9kbWFfdW5tYXBfc2luZ2xlKGluZm8t PmlkLT5kZXZpY2UsIHJlcXVlc3QtPnNnZVswXS5hZGRyLA0KPiArCQlyZXF1ZXN0LT5zZ2VbMF0u bGVuZ3RoLCBETUFfVE9fREVWSUNFKTsNCj4gKw0KPiArZG1hX21hcHBpbmdfZmFpbGVkOg0KPiAr CW1lbXBvb2xfZnJlZShyZXF1ZXN0LCBpbmZvLT5yZXF1ZXN0X21lbXBvb2wpOw0KPiArCXJldHVy biByYzsNCj4gK30NCj4gKw0KPiArLyoNCj4gKyAqIEV4dGVuZCB0aGUgY3JlZGl0cyB0byByZW1v dGUgcGVlcg0KPiArICogVGhpcyBpbXBsZW1lbnRzIFtNUy1TTUJEXSAzLjEuNS45DQo+ICsgKiBU aGUgaWRlYSBpcyB0aGF0IHdlIHNob3VsZCBleHRlbmQgY3JlZGl0cyB0byByZW1vdGUgcGVlciBh cyBxdWlja2x5IGFzDQo+ICsgKiBpdCdzIGFsbG93ZWQsIHRvIG1haW50YWluIGRhdGEgZmxvdy4g V2UgYWxsb2NhdGUgYXMgbXVjaCByZWNlaXZlDQo+ICsgKiBidWZmZXIgYXMgcG9zc2libGUsIGFu ZCBleHRlbmQgdGhlIHJlY2VpdmUgY3JlZGl0cyB0byByZW1vdGUgcGVlcg0KPiArICogcmV0dXJu IHZhbHVlOiB0aGUgbmV3IGNyZWR0aXMgYmVpbmcgZ3JhbnRlZC4NCj4gKyAqLw0KPiArc3RhdGlj IGludCBtYW5hZ2VfY3JlZGl0c19wcmlvcl9zZW5kaW5nKHN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24g KmluZm8pDQo+ICt7DQo+ICsJaW50IG5ld19jcmVkaXRzOw0KPiArDQo+ICsJc3Bpbl9sb2NrKCZp bmZvLT5sb2NrX25ld19jcmVkaXRzX29mZmVyZWQpOw0KPiArCW5ld19jcmVkaXRzID0gaW5mby0+ bmV3X2NyZWRpdHNfb2ZmZXJlZDsNCj4gKwlpbmZvLT5uZXdfY3JlZGl0c19vZmZlcmVkID0gMDsN Cj4gKwlzcGluX3VubG9jaygmaW5mby0+bG9ja19uZXdfY3JlZGl0c19vZmZlcmVkKTsNCj4gKw0K PiArCXJldHVybiBuZXdfY3JlZGl0czsNCj4gK30NCj4gKw0KPiArLyoNCj4gKyAqIENoZWNrIGlm IHdlIG5lZWQgdG8gc2VuZCBhIEtFRVBfQUxJVkUgbWVzc2FnZQ0KPiArICogVGhlIGlkbGUgY29u bmVjdGlvbiB0aW1lciB0cmlnZ2VycyBhIEtFRVBfQUxJVkUgbWVzc2FnZSB3aGVuIGV4cGlyZXMN Cj4gKyAqIFNNQl9ESVJFQ1RfUkVTUE9OU0VfUkVRVUVTVEVEIGlzIHNldCBpbiB0aGUgbWVzc2Fn ZSBmbGFnIHRvIGhhdmUNCj4gcGVlciBzZW5kDQo+ICsgKiBiYWNrIGEgcmVzcG9uc2UuDQo+ICsg KiByZXR1cm4gdmFsdWU6DQo+ICsgKiAxIGlmIFNNQl9ESVJFQ1RfUkVTUE9OU0VfUkVRVUVTVEVE IG5lZWRzIHRvIGJlIHNldA0KPiArICogMDogb3RoZXJ3aXNlDQo+ICsgKi8NCj4gK3N0YXRpYyBp bnQgbWFuYWdlX2tlZXBfYWxpdmVfYmVmb3JlX3NlbmRpbmcoc3RydWN0IHNtYmRfY29ubmVjdGlv bg0KPiAqaW5mbykNCj4gK3sNCj4gKwlpZiAoaW5mby0+a2VlcF9hbGl2ZV9yZXF1ZXN0ZWQgPT0g S0VFUF9BTElWRV9QRU5ESU5HKSB7DQo+ICsJCWluZm8tPmtlZXBfYWxpdmVfcmVxdWVzdGVkID0g S0VFUF9BTElWRV9TRU5UOw0KPiArCQlyZXR1cm4gMTsNCj4gKwl9DQo+ICsJcmV0dXJuIDA7DQo+ ICt9DQo+ICsNCj4gKy8qDQo+ICsgKiBCdWlsZCBhbmQgcHJlcGFyZSB0aGUgU01CRCBwYWNrZXQg aGVhZGVyDQo+ICsgKiBUaGlzIGZ1bmN0aW9uIHdhaXRzIGZvciBhdmFpYWxiZSBzZW5kIGNyZWRp dHMgYW5kIGJ1aWxkIGEgU01CRCBwYWNrZXQNCj4gKyAqIGhlYWRlci4gVGhlIGNhbGxlciB0aGVu IG9wdGlvbmFsIGFwcGVuZCBwYXlsb2FkIHRvIHRoZSBwYWNrZXQgYWZ0ZXINCj4gKyAqIHRoZSBo ZWFkZXINCj4gKyAqIGludHB1dCB2YWx1ZXMNCj4gKyAqIHNpemU6IHRoZSBzaXplIG9mIHRoZSBw YXlsb2FkDQo+ICsgKiByZW1haW5pbmdfZGF0YV9sZW5ndGg6IHJlbWFpbmluZyBkYXRhIHRvIHNl bmQgaWYgdGhpcyBpcyBwYXJ0IG9mIGENCj4gKyAqIGZyYWdtZW50ZWQgcGFja2V0DQo+ICsgKiBv dXRwdXQgdmFsdWVzDQo+ICsgKiByZXF1ZXN0X291dDogdGhlIHJlcXVlc3QgYWxsb2NhdGVkIGZy b20gdGhpcyBmdW5jdGlvbg0KPiArICogcmV0dXJuIHZhbHVlczogMCBvbiBzdWNjZXNzLCBvdGhl cndpc2UgYWN0dWFsIGVycm9yIGNvZGUgcmV0dXJuZWQNCj4gKyAqLw0KPiArc3RhdGljIGludCBz bWJkX2NyZWF0ZV9oZWFkZXIoc3RydWN0IHNtYmRfY29ubmVjdGlvbiAqaW5mbywNCj4gKwkJaW50 IHNpemUsIGludCByZW1haW5pbmdfZGF0YV9sZW5ndGgsDQo+ICsJCXN0cnVjdCBzbWJkX3JlcXVl c3QgKipyZXF1ZXN0X291dCkNCj4gK3sNCj4gKwlzdHJ1Y3Qgc21iZF9yZXF1ZXN0ICpyZXF1ZXN0 Ow0KPiArCXN0cnVjdCBzbWJkX2RhdGFfdHJhbnNmZXIgKnBhY2tldDsNCj4gKwlpbnQgaGVhZGVy X2xlbmd0aDsNCj4gKwlpbnQgcmM7DQo+ICsNCj4gKwkvKiBXYWl0IGZvciBzZW5kIGNyZWRpdHMu IEEgU01CRCBwYWNrZXQgbmVlZHMgb25lIGNyZWRpdCAqLw0KPiArCXJjID0gd2FpdF9ldmVudF9p bnRlcnJ1cHRpYmxlKGluZm8tPndhaXRfc2VuZF9xdWV1ZSwNCj4gKwkJYXRvbWljX3JlYWQoJmlu Zm8tPnNlbmRfY3JlZGl0cykgPiAwIHx8DQo+ICsJCWluZm8tPnRyYW5zcG9ydF9zdGF0dXMgIT0g U01CRF9DT05ORUNURUQpOw0KPiArCWlmIChyYykNCj4gKwkJcmV0dXJuIHJjOw0KPiArDQo+ICsJ aWYgKGluZm8tPnRyYW5zcG9ydF9zdGF0dXMgIT0gU01CRF9DT05ORUNURUQpIHsNCj4gKwkJbG9n X291dGdvaW5nKEVSUiwgImRpc2Nvbm5lY3RlZCBub3Qgc2VuZGluZ1xuIik7DQo+ICsJCXJldHVy biAtRU5PRU5UOw0KPiArCX0NCj4gKwlhdG9taWNfZGVjKCZpbmZvLT5zZW5kX2NyZWRpdHMpOw0K PiArDQo+ICsJcmVxdWVzdCA9IG1lbXBvb2xfYWxsb2MoaW5mby0+cmVxdWVzdF9tZW1wb29sLCBH RlBfS0VSTkVMKTsNCj4gKwlpZiAoIXJlcXVlc3QpIHsNCj4gKwkJcmMgPSAtRU5PTUVNOw0KPiAr CQlnb3RvIGVycjsNCj4gKwl9DQo+ICsNCj4gKwlyZXF1ZXN0LT5pbmZvID0gaW5mbzsNCj4gKw0K PiArCS8qIEZpbGwgaW4gdGhlIHBhY2tldCBoZWFkZXIgKi8NCj4gKwlwYWNrZXQgPSBzbWJkX3Jl cXVlc3RfcGF5bG9hZChyZXF1ZXN0KTsNCj4gKwlwYWNrZXQtPmNyZWRpdHNfcmVxdWVzdGVkID0g Y3B1X3RvX2xlMTYoaW5mby0NCj4gPnNlbmRfY3JlZGl0X3RhcmdldCk7DQo+ICsJcGFja2V0LT5j cmVkaXRzX2dyYW50ZWQgPQ0KPiArCQljcHVfdG9fbGUxNihtYW5hZ2VfY3JlZGl0c19wcmlvcl9z ZW5kaW5nKGluZm8pKTsNCj4gKwlpbmZvLT5zZW5kX2ltbWVkaWF0ZSA9IGZhbHNlOw0KPiArDQo+ ICsJcGFja2V0LT5mbGFncyA9IDA7DQo+ICsJaWYgKG1hbmFnZV9rZWVwX2FsaXZlX2JlZm9yZV9z ZW5kaW5nKGluZm8pKQ0KPiArCQlwYWNrZXQtPmZsYWdzIHw9DQo+IGNwdV90b19sZTE2KFNNQl9E SVJFQ1RfUkVTUE9OU0VfUkVRVUVTVEVEKTsNCj4gKw0KPiArCXBhY2tldC0+cmVzZXJ2ZWQgPSAw Ow0KPiArCWlmICghc2l6ZSkNCj4gKwkJcGFja2V0LT5kYXRhX29mZnNldCA9IDA7DQo+ICsJZWxz ZQ0KPiArCQlwYWNrZXQtPmRhdGFfb2Zmc2V0ID0gY3B1X3RvX2xlMzIoMjQpOw0KPiArCXBhY2tl dC0+ZGF0YV9sZW5ndGggPSBjcHVfdG9fbGUzMihzaXplKTsNCj4gKwlwYWNrZXQtPnJlbWFpbmlu Z19kYXRhX2xlbmd0aCA9DQo+IGNwdV90b19sZTMyKHJlbWFpbmluZ19kYXRhX2xlbmd0aCk7DQo+ ICsJcGFja2V0LT5wYWRkaW5nID0gMDsNCj4gKw0KPiArCWxvZ19vdXRnb2luZyhJTkZPLCAiY3Jl ZGl0c19yZXF1ZXN0ZWQ9JWQgY3JlZGl0c19ncmFudGVkPSVkICINCj4gKwkJImRhdGFfb2Zmc2V0 PSVkIGRhdGFfbGVuZ3RoPSVkDQo+IHJlbWFpbmluZ19kYXRhX2xlbmd0aD0lZFxuIiwNCj4gKwkJ bGUxNl90b19jcHUocGFja2V0LT5jcmVkaXRzX3JlcXVlc3RlZCksDQo+ICsJCWxlMTZfdG9fY3B1 KHBhY2tldC0+Y3JlZGl0c19ncmFudGVkKSwNCj4gKwkJbGUzMl90b19jcHUocGFja2V0LT5kYXRh X29mZnNldCksDQo+ICsJCWxlMzJfdG9fY3B1KHBhY2tldC0+ZGF0YV9sZW5ndGgpLA0KPiArCQls ZTMyX3RvX2NwdShwYWNrZXQtPnJlbWFpbmluZ19kYXRhX2xlbmd0aCkpOw0KPiArDQo+ICsJLyog TWFwIHRoZSBwYWNrZXQgdG8gRE1BICovDQo+ICsJaGVhZGVyX2xlbmd0aCA9IHNpemVvZihzdHJ1 Y3Qgc21iZF9kYXRhX3RyYW5zZmVyKTsNCj4gKwkvKiBJZiB0aGlzIGlzIGEgcGFja2V0IHdpdGhv dXQgcGF5bG9hZCwgZG9uJ3Qgc2VuZCBwYWRkaW5nICovDQo+ICsJaWYgKCFzaXplKQ0KPiArCQlo ZWFkZXJfbGVuZ3RoID0gb2Zmc2V0b2Yoc3RydWN0IHNtYmRfZGF0YV90cmFuc2ZlciwNCj4gcGFk ZGluZyk7DQo+ICsNCj4gKwlyZXF1ZXN0LT5udW1fc2dlID0gMTsNCj4gKwlyZXF1ZXN0LT5zZ2Vb MF0uYWRkciA9IGliX2RtYV9tYXBfc2luZ2xlKGluZm8tPmlkLT5kZXZpY2UsDQo+ICsJCQkJCQkg KHZvaWQgKilwYWNrZXQsDQo+ICsJCQkJCQkgaGVhZGVyX2xlbmd0aCwNCj4gKwkJCQkJCSBETUFf QklESVJFQ1RJT05BTCk7DQo+ICsJaWYgKGliX2RtYV9tYXBwaW5nX2Vycm9yKGluZm8tPmlkLT5k ZXZpY2UsIHJlcXVlc3QtPnNnZVswXS5hZGRyKSkNCj4gew0KPiArCQltZW1wb29sX2ZyZWUocmVx dWVzdCwgaW5mby0+cmVxdWVzdF9tZW1wb29sKTsNCj4gKwkJcmMgPSAtRUlPOw0KPiArCQlnb3Rv IGVycjsNCj4gKwl9DQo+ICsNCj4gKwlyZXF1ZXN0LT5zZ2VbMF0ubGVuZ3RoID0gaGVhZGVyX2xl bmd0aDsNCj4gKwlyZXF1ZXN0LT5zZ2VbMF0ubGtleSA9IGluZm8tPnBkLT5sb2NhbF9kbWFfbGtl eTsNCj4gKw0KPiArCSpyZXF1ZXN0X291dCA9IHJlcXVlc3Q7DQo+ICsJcmV0dXJuIDA7DQo+ICsN Cj4gK2VycjoNCj4gKwlhdG9taWNfaW5jKCZpbmZvLT5zZW5kX2NyZWRpdHMpOw0KPiArCXJldHVy biByYzsNCj4gK30NCj4gKw0KPiArc3RhdGljIHZvaWQgc21iZF9kZXN0cm95X2hlYWRlcihzdHJ1 Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvLA0KPiArCQlzdHJ1Y3Qgc21iZF9yZXF1ZXN0ICpyZXF1 ZXN0KQ0KPiArew0KPiArDQo+ICsJaWJfZG1hX3VubWFwX3NpbmdsZShpbmZvLT5pZC0+ZGV2aWNl LA0KPiArCQkJICAgIHJlcXVlc3QtPnNnZVswXS5hZGRyLA0KPiArCQkJICAgIHJlcXVlc3QtPnNn ZVswXS5sZW5ndGgsDQo+ICsJCQkgICAgRE1BX1RPX0RFVklDRSk7DQo+ICsJbWVtcG9vbF9mcmVl KHJlcXVlc3QsIGluZm8tPnJlcXVlc3RfbWVtcG9vbCk7DQo+ICsJYXRvbWljX2luYygmaW5mby0+ c2VuZF9jcmVkaXRzKTsNCj4gK30NCj4gKw0KPiArLyogUG9zdCB0aGUgc2VuZCByZXF1ZXN0ICov DQo+ICtzdGF0aWMgaW50IHNtYmRfcG9zdF9zZW5kKHN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24gKmlu Zm8sDQo+ICsJCXN0cnVjdCBzbWJkX3JlcXVlc3QgKnJlcXVlc3QsIGJvb2wgaGFzX3BheWxvYWQp DQo+ICt7DQo+ICsJc3RydWN0IGliX3NlbmRfd3Igc2VuZF93ciwgKnNlbmRfd3JfZmFpbDsNCj4g KwlpbnQgcmMsIGk7DQo+ICsNCj4gKwlmb3IgKGkgPSAwOyBpIDwgcmVxdWVzdC0+bnVtX3NnZTsg aSsrKSB7DQo+ICsJCWxvZ19yZG1hX3NlbmQoSU5GTywNCj4gKwkJCSJyZG1hX3JlcXVlc3Qgc2dl WyVkXSBhZGRyPSVsbHUgbGVnbnRoPSV1XG4iLA0KPiArCQkJaSwgcmVxdWVzdC0+c2dlWzBdLmFk ZHIsIHJlcXVlc3QtPnNnZVswXS5sZW5ndGgpOw0KPiArCQlpYl9kbWFfc3luY19zaW5nbGVfZm9y X2RldmljZSgNCj4gKwkJCWluZm8tPmlkLT5kZXZpY2UsDQo+ICsJCQlyZXF1ZXN0LT5zZ2VbaV0u YWRkciwNCj4gKwkJCXJlcXVlc3QtPnNnZVtpXS5sZW5ndGgsDQo+ICsJCQlETUFfVE9fREVWSUNF KTsNCj4gKwl9DQo+ICsNCj4gKwlyZXF1ZXN0LT5jcWUuZG9uZSA9IHNlbmRfZG9uZTsNCj4gKw0K PiArCXNlbmRfd3IubmV4dCA9IE5VTEw7DQo+ICsJc2VuZF93ci53cl9jcWUgPSAmcmVxdWVzdC0+ Y3FlOw0KPiArCXNlbmRfd3Iuc2dfbGlzdCA9IHJlcXVlc3QtPnNnZTsNCj4gKwlzZW5kX3dyLm51 bV9zZ2UgPSByZXF1ZXN0LT5udW1fc2dlOw0KPiArCXNlbmRfd3Iub3Bjb2RlID0gSUJfV1JfU0VO RDsNCj4gKwlzZW5kX3dyLnNlbmRfZmxhZ3MgPSBJQl9TRU5EX1NJR05BTEVEOw0KPiArDQo+ICsJ aWYgKGhhc19wYXlsb2FkKSB7DQo+ICsJCXJlcXVlc3QtPmhhc19wYXlsb2FkID0gdHJ1ZTsNCj4g KwkJYXRvbWljX2luYygmaW5mby0+c2VuZF9wYXlsb2FkX3BlbmRpbmcpOw0KPiArCX0gZWxzZSB7 DQo+ICsJCXJlcXVlc3QtPmhhc19wYXlsb2FkID0gZmFsc2U7DQo+ICsJCWF0b21pY19pbmMoJmlu Zm8tPnNlbmRfcGVuZGluZyk7DQo+ICsJfQ0KPiArDQo+ICsJcmMgPSBpYl9wb3N0X3NlbmQoaW5m by0+aWQtPnFwLCAmc2VuZF93ciwgJnNlbmRfd3JfZmFpbCk7DQo+ICsJaWYgKHJjKSB7DQo+ICsJ CWxvZ19yZG1hX3NlbmQoRVJSLCAiaWJfcG9zdF9zZW5kIGZhaWxlZCByYz0lZFxuIiwgcmMpOw0K PiArCQlpZiAoaGFzX3BheWxvYWQpIHsNCj4gKwkJCWlmIChhdG9taWNfZGVjX2FuZF90ZXN0KCZp bmZvLQ0KPiA+c2VuZF9wYXlsb2FkX3BlbmRpbmcpKQ0KPiArCQkJCXdha2VfdXAoJmluZm8tDQo+ ID53YWl0X3NlbmRfcGF5bG9hZF9wZW5kaW5nKTsNCj4gKwkJfSBlbHNlIHsNCj4gKwkJCWlmIChh dG9taWNfZGVjX2FuZF90ZXN0KCZpbmZvLT5zZW5kX3BlbmRpbmcpKQ0KPiArCQkJCXdha2VfdXAo JmluZm8tPndhaXRfc2VuZF9wZW5kaW5nKTsNCj4gKwkJfQ0KPiArCX0gZWxzZQ0KPiArCQkvKiBS ZXNldCB0aW1lciBmb3IgaWRsZSBjb25uZWN0aW9uIGFmdGVyIHBhY2tldCBpcyBzZW50ICovDQo+ ICsJCW1vZF9kZWxheWVkX3dvcmsoaW5mby0+d29ya3F1ZXVlLCAmaW5mby0NCj4gPmlkbGVfdGlt ZXJfd29yaywNCj4gKwkJCWluZm8tPmtlZXBfYWxpdmVfaW50ZXJ2YWwqSFopOw0KPiArDQo+ICsJ cmV0dXJuIHJjOw0KPiArfQ0KPiArDQo+ICtzdGF0aWMgaW50IHNtYmRfcG9zdF9zZW5kX3NnbChz dHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvLA0KPiArCXN0cnVjdCBzY2F0dGVybGlzdCAqc2ds LCBpbnQgZGF0YV9sZW5ndGgsIGludCByZW1haW5pbmdfZGF0YV9sZW5ndGgpDQo+ICt7DQo+ICsJ aW50IG51bV9zZ3M7DQo+ICsJaW50IGksIHJjOw0KPiArCXN0cnVjdCBzbWJkX3JlcXVlc3QgKnJl cXVlc3Q7DQo+ICsJc3RydWN0IHNjYXR0ZXJsaXN0ICpzZzsNCj4gKw0KPiArCXJjID0gc21iZF9j cmVhdGVfaGVhZGVyKA0KPiArCQlpbmZvLCBkYXRhX2xlbmd0aCwgcmVtYWluaW5nX2RhdGFfbGVu Z3RoLCAmcmVxdWVzdCk7DQo+ICsJaWYgKHJjKQ0KPiArCQlyZXR1cm4gcmM7DQo+ICsNCj4gKwlu dW1fc2dzID0gc2dsID8gc2dfbmVudHMoc2dsKSA6IDA7DQo+ICsJZm9yX2VhY2hfc2coc2dsLCBz ZywgbnVtX3NncywgaSkgew0KPiArCQlyZXF1ZXN0LT5zZ2VbaSsxXS5hZGRyID0NCj4gKwkJCWli X2RtYV9tYXBfcGFnZShpbmZvLT5pZC0+ZGV2aWNlLCBzZ19wYWdlKHNnKSwNCj4gKwkJCSAgICAg ICBzZy0+b2Zmc2V0LCBzZy0+bGVuZ3RoLCBETUFfQklESVJFQ1RJT05BTCk7DQo+ICsJCWlmIChp Yl9kbWFfbWFwcGluZ19lcnJvcigNCj4gKwkJCQlpbmZvLT5pZC0+ZGV2aWNlLCByZXF1ZXN0LT5z Z2VbaSsxXS5hZGRyKSkgew0KPiArCQkJcmMgPSAtRUlPOw0KPiArCQkJcmVxdWVzdC0+c2dlW2kr MV0uYWRkciA9IDA7DQo+ICsJCQlnb3RvIGRtYV9tYXBwaW5nX2ZhaWx1cmU7DQo+ICsJCX0NCj4g KwkJcmVxdWVzdC0+c2dlW2krMV0ubGVuZ3RoID0gc2ctPmxlbmd0aDsNCj4gKwkJcmVxdWVzdC0+ c2dlW2krMV0ubGtleSA9IGluZm8tPnBkLT5sb2NhbF9kbWFfbGtleTsNCj4gKwkJcmVxdWVzdC0+ bnVtX3NnZSsrOw0KPiArCX0NCj4gKw0KPiArCXJjID0gc21iZF9wb3N0X3NlbmQoaW5mbywgcmVx dWVzdCwgZGF0YV9sZW5ndGgpOw0KPiArCWlmICghcmMpDQo+ICsJCXJldHVybiAwOw0KPiArDQo+ ICtkbWFfbWFwcGluZ19mYWlsdXJlOg0KPiArCWZvciAoaSA9IDE7IGkgPCByZXF1ZXN0LT5udW1f c2dlOyBpKyspDQo+ICsJCWlmIChyZXF1ZXN0LT5zZ2VbaV0uYWRkcikNCj4gKwkJCWliX2RtYV91 bm1hcF9zaW5nbGUoaW5mby0+aWQtPmRldmljZSwNCj4gKwkJCQkJICAgIHJlcXVlc3QtPnNnZVtp XS5hZGRyLA0KPiArCQkJCQkgICAgcmVxdWVzdC0+c2dlW2ldLmxlbmd0aCwNCj4gKwkJCQkJICAg IERNQV9UT19ERVZJQ0UpOw0KPiArCXNtYmRfZGVzdHJveV9oZWFkZXIoaW5mbywgcmVxdWVzdCk7 DQo+ICsJcmV0dXJuIHJjOw0KPiArfQ0KPiArDQo+ICsvKg0KPiArICogU2VuZCBhbiBlbXB0eSBt ZXNzYWdlDQo+ICsgKiBFbXB0eSBtZXNzYWdlIGlzIHVzZWQgdG8gZXh0ZW5kIGNyZWRpdHMgdG8g cGVlciB0byBmb3Iga2VlcCBsaXZlDQo+ICsgKiB3aGlsZSB0aGVyZSBpcyBubyB1cHBlciBsYXll ciBwYXlsb2FkIHRvIHNlbmQgYXQgdGhlIHRpbWUNCj4gKyAqLw0KPiArc3RhdGljIGludCBzbWJk X3Bvc3Rfc2VuZF9lbXB0eShzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvKQ0KPiArew0KPiAr CWluZm8tPmNvdW50X3NlbmRfZW1wdHkrKzsNCj4gKwlyZXR1cm4gc21iZF9wb3N0X3NlbmRfc2ds KGluZm8sIE5VTEwsIDAsIDApOw0KPiArfQ0KPiArDQo+ICsvKg0KPiArICogUG9zdCBhIHJlY2Vp dmUgcmVxdWVzdCB0byB0aGUgdHJhbnNwb3J0DQo+ICsgKiBUaGUgcmVtb3RlIHBlZXIgY2FuIG9u bHkgc2VuZCBkYXRhIHdoZW4gYSByZWNlaXZlIHJlcXVlc3QgaXMgcG9zdGVkDQo+ICsgKiBUaGUg aW50ZXJhY3Rpb24gaXMgY29udHJvbGxlZCBieSBzZW5kL3JlY2VpdmUgY3JlZGl0IHN5c3RlbQ0K PiArICovDQo+ICtzdGF0aWMgaW50IHNtYmRfcG9zdF9yZWN2KA0KPiArCQlzdHJ1Y3Qgc21iZF9j b25uZWN0aW9uICppbmZvLCBzdHJ1Y3Qgc21iZF9yZXNwb25zZQ0KPiAqcmVzcG9uc2UpDQo+ICt7 DQo+ICsJc3RydWN0IGliX3JlY3Zfd3IgcmVjdl93ciwgKnJlY3Zfd3JfZmFpbCA9IE5VTEw7DQo+ ICsJaW50IHJjID0gLUVJTzsNCj4gKw0KPiArCXJlc3BvbnNlLT5zZ2UuYWRkciA9IGliX2RtYV9t YXBfc2luZ2xlKA0KPiArCQkJCWluZm8tPmlkLT5kZXZpY2UsIHJlc3BvbnNlLT5wYWNrZXQsDQo+ ICsJCQkJaW5mby0+bWF4X3JlY2VpdmVfc2l6ZSwNCj4gRE1BX0ZST01fREVWSUNFKTsNCj4gKwlp ZiAoaWJfZG1hX21hcHBpbmdfZXJyb3IoaW5mby0+aWQtPmRldmljZSwgcmVzcG9uc2UtPnNnZS5h ZGRyKSkNCj4gKwkJcmV0dXJuIHJjOw0KPiArDQo+ICsJcmVzcG9uc2UtPnNnZS5sZW5ndGggPSBp bmZvLT5tYXhfcmVjZWl2ZV9zaXplOw0KPiArCXJlc3BvbnNlLT5zZ2UubGtleSA9IGluZm8tPnBk LT5sb2NhbF9kbWFfbGtleTsNCj4gKw0KPiArCXJlc3BvbnNlLT5jcWUuZG9uZSA9IHJlY3ZfZG9u ZTsNCj4gKw0KPiArCXJlY3Zfd3Iud3JfY3FlID0gJnJlc3BvbnNlLT5jcWU7DQo+ICsJcmVjdl93 ci5uZXh0ID0gTlVMTDsNCj4gKwlyZWN2X3dyLnNnX2xpc3QgPSAmcmVzcG9uc2UtPnNnZTsNCj4g KwlyZWN2X3dyLm51bV9zZ2UgPSAxOw0KPiArDQo+ICsJcmMgPSBpYl9wb3N0X3JlY3YoaW5mby0+ aWQtPnFwLCAmcmVjdl93ciwgJnJlY3Zfd3JfZmFpbCk7DQo+ICsJaWYgKHJjKSB7DQo+ICsJCWli X2RtYV91bm1hcF9zaW5nbGUoaW5mby0+aWQtPmRldmljZSwgcmVzcG9uc2UtDQo+ID5zZ2UuYWRk ciwNCj4gKwkJCQkgICAgcmVzcG9uc2UtPnNnZS5sZW5ndGgsDQo+IERNQV9GUk9NX0RFVklDRSk7 DQo+ICsNCj4gKwkJbG9nX3JkbWFfcmVjdihFUlIsICJpYl9wb3N0X3JlY3YgZmFpbGVkIHJjPSVk XG4iLCByYyk7DQo+ICsJfQ0KPiArDQo+ICsJcmV0dXJuIHJjOw0KPiArfQ0KPiArDQo+ICsvKiBQ ZXJmb3JtIFNNQkQgbmVnb3RpYXRlIGFjY29yZGluZyB0byBbTVMtU01CRF0gMy4xLjUuMiAqLw0K PiArc3RhdGljIGludCBzbWJkX25lZ290aWF0ZShzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZv KQ0KPiArew0KPiArCWludCByYzsNCj4gKwlzdHJ1Y3Qgc21iZF9yZXNwb25zZSAqcmVzcG9uc2Ug PSBnZXRfcmVjZWl2ZV9idWZmZXIoaW5mbyk7DQo+ICsNCj4gKwlyZXNwb25zZS0+dHlwZSA9IFNN QkRfTkVHT1RJQVRFX1JFU1A7DQo+ICsJcmMgPSBzbWJkX3Bvc3RfcmVjdihpbmZvLCByZXNwb25z ZSk7DQo+ICsJbG9nX3JkbWFfZXZlbnQoSU5GTywNCj4gKwkJInNtYmRfcG9zdF9yZWN2IHJjPSVk IGlvdi5hZGRyPSVsbHggaW92Lmxlbmd0aD0leCAiDQo+ICsJCSJpb3YubGtleT0leFxuIiwNCj4g KwkJcmMsIHJlc3BvbnNlLT5zZ2UuYWRkciwNCj4gKwkJcmVzcG9uc2UtPnNnZS5sZW5ndGgsIHJl c3BvbnNlLT5zZ2UubGtleSk7DQo+ICsJaWYgKHJjKQ0KPiArCQlyZXR1cm4gcmM7DQo+ICsNCj4g Kwlpbml0X2NvbXBsZXRpb24oJmluZm8tPm5lZ290aWF0ZV9jb21wbGV0aW9uKTsNCj4gKwlpbmZv LT5uZWdvdGlhdGVfZG9uZSA9IGZhbHNlOw0KPiArCXJjID0gc21iZF9wb3N0X3NlbmRfbmVnb3Rp YXRlX3JlcShpbmZvKTsNCj4gKwlpZiAocmMpDQo+ICsJCXJldHVybiByYzsNCj4gKw0KPiArCXJj ID0gd2FpdF9mb3JfY29tcGxldGlvbl9pbnRlcnJ1cHRpYmxlX3RpbWVvdXQoDQo+ICsJCSZpbmZv LT5uZWdvdGlhdGVfY29tcGxldGlvbiwgU01CRF9ORUdPVElBVEVfVElNRU9VVA0KPiAqIEhaKTsN Cj4gKwlsb2dfcmRtYV9ldmVudChJTkZPLCAid2FpdF9mb3JfY29tcGxldGlvbl90aW1lb3V0IHJj PSVkXG4iLA0KPiByYyk7DQo+ICsNCj4gKwlpZiAoaW5mby0+bmVnb3RpYXRlX2RvbmUpDQo+ICsJ CXJldHVybiAwOw0KPiArDQo+ICsJaWYgKHJjID09IDApDQo+ICsJCXJjID0gLUVUSU1FRE9VVDsN Cj4gKwllbHNlIGlmIChyYyA9PSAtRVJFU1RBUlRTWVMpDQo+ICsJCXJjID0gLUVJTlRSOw0KPiAr CWVsc2UNCj4gKwkJcmMgPSAtRU5PVENPTk47DQo+ICsNCj4gKwlyZXR1cm4gcmM7DQo+ICt9DQo+ ICsNCj4gK3N0YXRpYyB2b2lkIHB1dF9lbXB0eV9wYWNrZXQoDQo+ICsJCXN0cnVjdCBzbWJkX2Nv bm5lY3Rpb24gKmluZm8sIHN0cnVjdCBzbWJkX3Jlc3BvbnNlDQo+ICpyZXNwb25zZSkNCj4gK3sN Cj4gKwlzcGluX2xvY2soJmluZm8tPmVtcHR5X3BhY2tldF9xdWV1ZV9sb2NrKTsNCj4gKwlsaXN0 X2FkZF90YWlsKCZyZXNwb25zZS0+bGlzdCwgJmluZm8tPmVtcHR5X3BhY2tldF9xdWV1ZSk7DQo+ ICsJaW5mby0+Y291bnRfZW1wdHlfcGFja2V0X3F1ZXVlKys7DQo+ICsJc3Bpbl91bmxvY2soJmlu Zm8tPmVtcHR5X3BhY2tldF9xdWV1ZV9sb2NrKTsNCj4gKw0KPiArCXF1ZXVlX3dvcmsoaW5mby0+ d29ya3F1ZXVlLCAmaW5mby0+cG9zdF9zZW5kX2NyZWRpdHNfd29yayk7DQo+ICt9DQo+ICsNCj4g Ky8qDQo+ICsgKiBJbXBsZW1lbnQgQ29ubmVjdGlvbi5GcmFnbWVudFJlYXNzZW1ibHlCdWZmZXIg ZGVmaW5lZCBpbiBbTVMtDQo+IFNNQkRdIDMuMS4xLjENCj4gKyAqIFRoaXMgaXMgYSBxdWV1ZSBm b3IgcmVhc3NlbWJsaW5nIHVwcGVyIGxheWVyIHBheWxvYWQgYW5kIHByZXNlbnQgdG8NCj4gdXBw ZXINCj4gKyAqIGxheWVyLiBBbGwgdGhlIGlubmNvbWluZyBwYXlsb2FkIGdvIHRvIHRoZSByZWFz c2VtYmx5IHF1ZXVlLCByZWdhcmRsZXNzDQo+IG9mDQo+ICsgKiBpZiByZWFzc2VtYmx5IGlzIHJl cXVpcmVkLiBUaGUgdXVwZXIgbGF5ZXIgY29kZSByZWFkcyBmcm9tIHRoZSBxdWV1ZSBmb3INCj4g YWxsDQo+ICsgKiBpbmNvbWluZyBwYXlsb2Fkcy4NCj4gKyAqIFB1dCBhIHJlY2VpdmVkIHBhY2tl dCB0byB0aGUgcmVhc3NlbWJseSBxdWV1ZQ0KPiArICogcmVzcG9uc2U6IHRoZSBwYWNrZXQgcmVj ZWl2ZWQNCj4gKyAqIGRhdGFfbGVuZ3RoOiB0aGUgc2l6ZSBvZiBwYXlsb2FkIGluIHRoaXMgcGFj a2V0DQo+ICsgKi8NCj4gK3N0YXRpYyB2b2lkIGVucXVldWVfcmVhc3NlbWJseSgNCj4gKwlzdHJ1 Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvLA0KPiArCXN0cnVjdCBzbWJkX3Jlc3BvbnNlICpyZXNw b25zZSwNCj4gKwlpbnQgZGF0YV9sZW5ndGgpDQo+ICt7DQo+ICsJc3Bpbl9sb2NrKCZpbmZvLT5y ZWFzc2VtYmx5X3F1ZXVlX2xvY2spOw0KPiArCWxpc3RfYWRkX3RhaWwoJnJlc3BvbnNlLT5saXN0 LCAmaW5mby0+cmVhc3NlbWJseV9xdWV1ZSk7DQo+ICsJaW5mby0+cmVhc3NlbWJseV9xdWV1ZV9s ZW5ndGgrKzsNCj4gKwkvKg0KPiArCSAqIE1ha2Ugc3VyZSByZWFzc2VtYmx5X2RhdGFfbGVuZ3Ro IGlzIHVwZGF0ZWQgYWZ0ZXIgbGlzdCBhbmQNCj4gKwkgKiByZWFzc2VtYmx5X3F1ZXVlX2xlbmd0 aCBhcmUgdXBkYXRlZC4gT24gdGhlIGRlcXVldWUgc2lkZQ0KPiArCSAqIHJlYXNzZW1ibHlfZGF0 YV9sZW5ndGggaXMgY2hlY2tlZCB3aXRob3V0IGEgbG9jayB0byBkZXRlcm1pbmUNCj4gKwkgKiBp ZiByZWFzc2VtYmx5X3F1ZXVlX2xlbmd0aCBhbmQgbGlzdCBpcyB1cCB0byBkYXRlDQo+ICsJICov DQo+ICsJdmlydF93bWIoKTsNCj4gKwlpbmZvLT5yZWFzc2VtYmx5X2RhdGFfbGVuZ3RoICs9IGRh dGFfbGVuZ3RoOw0KPiArCXNwaW5fdW5sb2NrKCZpbmZvLT5yZWFzc2VtYmx5X3F1ZXVlX2xvY2sp Ow0KPiArCWluZm8tPmNvdW50X3JlYXNzZW1ibHlfcXVldWUrKzsNCj4gKwlpbmZvLT5jb3VudF9l bnF1ZXVlX3JlYXNzZW1ibHlfcXVldWUrKzsNCj4gK30NCj4gKw0KPiArLyoNCj4gKyAqIEdldCB0 aGUgZmlyc3QgZW50cnkgYXQgdGhlIGZyb250IG9mIHJlYXNzZW1ibHkgcXVldWUNCj4gKyAqIENh bGxlciBpcyByZXNwb25zaWJsZSBmb3IgbG9ja2luZw0KPiArICogcmV0dXJuIHZhbHVlOiB0aGUg Zmlyc3QgZW50cnkgaWYgYW55LCBOVUxMIGlmIHF1ZXVlIGlzIGVtcHR5DQo+ICsgKi8NCj4gK3N0 YXRpYyBzdHJ1Y3Qgc21iZF9yZXNwb25zZSAqX2dldF9maXJzdF9yZWFzc2VtYmx5KHN0cnVjdA0K PiBzbWJkX2Nvbm5lY3Rpb24gKmluZm8pDQo+ICt7DQo+ICsJc3RydWN0IHNtYmRfcmVzcG9uc2Ug KnJldCA9IE5VTEw7DQo+ICsNCj4gKwlpZiAoIWxpc3RfZW1wdHkoJmluZm8tPnJlYXNzZW1ibHlf cXVldWUpKSB7DQo+ICsJCXJldCA9IGxpc3RfZmlyc3RfZW50cnkoDQo+ICsJCQkmaW5mby0+cmVh c3NlbWJseV9xdWV1ZSwNCj4gKwkJCXN0cnVjdCBzbWJkX3Jlc3BvbnNlLCBsaXN0KTsNCj4gKwl9 DQo+ICsJcmV0dXJuIHJldDsNCj4gK30NCj4gKw0KPiArc3RhdGljIHN0cnVjdCBzbWJkX3Jlc3Bv bnNlICpnZXRfZW1wdHlfcXVldWVfYnVmZmVyKA0KPiArCQlzdHJ1Y3Qgc21iZF9jb25uZWN0aW9u ICppbmZvKQ0KPiArew0KPiArCXN0cnVjdCBzbWJkX3Jlc3BvbnNlICpyZXQgPSBOVUxMOw0KPiAr CXVuc2lnbmVkIGxvbmcgZmxhZ3M7DQo+ICsNCj4gKwlzcGluX2xvY2tfaXJxc2F2ZSgmaW5mby0+ ZW1wdHlfcGFja2V0X3F1ZXVlX2xvY2ssIGZsYWdzKTsNCj4gKwlpZiAoIWxpc3RfZW1wdHkoJmlu Zm8tPmVtcHR5X3BhY2tldF9xdWV1ZSkpIHsNCj4gKwkJcmV0ID0gbGlzdF9maXJzdF9lbnRyeSgN Cj4gKwkJCSZpbmZvLT5lbXB0eV9wYWNrZXRfcXVldWUsDQo+ICsJCQlzdHJ1Y3Qgc21iZF9yZXNw b25zZSwgbGlzdCk7DQo+ICsJCWxpc3RfZGVsKCZyZXQtPmxpc3QpOw0KPiArCQlpbmZvLT5jb3Vu dF9lbXB0eV9wYWNrZXRfcXVldWUtLTsNCj4gKwl9DQo+ICsJc3Bpbl91bmxvY2tfaXJxcmVzdG9y ZSgmaW5mby0+ZW1wdHlfcGFja2V0X3F1ZXVlX2xvY2ssIGZsYWdzKTsNCj4gKw0KPiArCXJldHVy biByZXQ7DQo+ICt9DQo+ICsNCj4gKy8qDQo+ICsgKiBHZXQgYSByZWNlaXZlIGJ1ZmZlcg0KPiAr ICogRm9yIGVhY2ggcmVtb3RlIHNlbmQsIHdlIG5lZWQgdG8gcG9zdCBhIHJlY2VpdmUuIFRoZSBy ZWNlaXZlIGJ1ZmZlcnMgYXJlDQo+ICsgKiBwcmUtYWxsb2NhdGVkIGluIGFkdmFuY2UuDQo+ICsg KiByZXR1cm4gdmFsdWU6IHRoZSByZWNlaXZlIGJ1ZmZlciwgTlVMTCBpZiBub25lIGlzIGF2YWls YWJsZQ0KPiArICovDQo+ICtzdGF0aWMgc3RydWN0IHNtYmRfcmVzcG9uc2UgKmdldF9yZWNlaXZl X2J1ZmZlcihzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uDQo+ICppbmZvKQ0KPiArew0KPiArCXN0cnVj dCBzbWJkX3Jlc3BvbnNlICpyZXQgPSBOVUxMOw0KPiArCXVuc2lnbmVkIGxvbmcgZmxhZ3M7DQo+ ICsNCj4gKwlzcGluX2xvY2tfaXJxc2F2ZSgmaW5mby0+cmVjZWl2ZV9xdWV1ZV9sb2NrLCBmbGFn cyk7DQo+ICsJaWYgKCFsaXN0X2VtcHR5KCZpbmZvLT5yZWNlaXZlX3F1ZXVlKSkgew0KPiArCQly ZXQgPSBsaXN0X2ZpcnN0X2VudHJ5KA0KPiArCQkJJmluZm8tPnJlY2VpdmVfcXVldWUsDQo+ICsJ CQlzdHJ1Y3Qgc21iZF9yZXNwb25zZSwgbGlzdCk7DQo+ICsJCWxpc3RfZGVsKCZyZXQtPmxpc3Qp Ow0KPiArCQlpbmZvLT5jb3VudF9yZWNlaXZlX3F1ZXVlLS07DQo+ICsJCWluZm8tPmNvdW50X2dl dF9yZWNlaXZlX2J1ZmZlcisrOw0KPiArCX0NCj4gKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZp bmZvLT5yZWNlaXZlX3F1ZXVlX2xvY2ssIGZsYWdzKTsNCj4gKw0KPiArCXJldHVybiByZXQ7DQo+ ICt9DQo+ICsNCj4gKy8qDQo+ICsgKiBSZXR1cm4gYSByZWNlaXZlIGJ1ZmZlcg0KPiArICogVXBv biByZXR1cm5pbmcgb2YgYSByZWNlaXZlIGJ1ZmZlciwgd2UgY2FuIHBvc3QgbmV3IHJlY2VpdmUg YW5kIGV4dGVuZA0KPiArICogbW9yZSByZWNlaXZlIGNyZWRpdHMgdG8gcmVtb3RlIHBlZXIuIFRo aXMgaXMgZG9uZSBpbW1lZGlhdGVseSBhZnRlciBhDQo+ICsgKiByZWNlaXZlIGJ1ZmZlciBpcyBy ZXR1cm5lZC4NCj4gKyAqLw0KPiArc3RhdGljIHZvaWQgcHV0X3JlY2VpdmVfYnVmZmVyKA0KPiAr CXN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24gKmluZm8sIHN0cnVjdCBzbWJkX3Jlc3BvbnNlICpyZXNw b25zZSwNCj4gKwlib29sIGxvY2spDQo+ICt7DQo+ICsJdW5zaWduZWQgbG9uZyBmbGFnczsNCj4g Kw0KPiArCWliX2RtYV91bm1hcF9zaW5nbGUoaW5mby0+aWQtPmRldmljZSwgcmVzcG9uc2UtPnNn ZS5hZGRyLA0KPiArCQlyZXNwb25zZS0+c2dlLmxlbmd0aCwgRE1BX0ZST01fREVWSUNFKTsNCj4g Kw0KPiArCWlmIChsb2NrKQ0KPiArCQlzcGluX2xvY2tfaXJxc2F2ZSgmaW5mby0+cmVjZWl2ZV9x dWV1ZV9sb2NrLCBmbGFncyk7DQo+ICsJbGlzdF9hZGRfdGFpbCgmcmVzcG9uc2UtPmxpc3QsICZp bmZvLT5yZWNlaXZlX3F1ZXVlKTsNCj4gKwlpbmZvLT5jb3VudF9yZWNlaXZlX3F1ZXVlKys7DQo+ ICsJaW5mby0+Y291bnRfcHV0X3JlY2VpdmVfYnVmZmVyKys7DQo+ICsJaWYgKGxvY2spDQo+ICsJ CXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmluZm8tPnJlY2VpdmVfcXVldWVfbG9jaywgZmxhZ3Mp Ow0KPiArDQo+ICsJcXVldWVfd29yayhpbmZvLT53b3JrcXVldWUsICZpbmZvLT5wb3N0X3NlbmRf Y3JlZGl0c193b3JrKTsNCj4gK30NCj4gKw0KPiArLyogUHJlYWxsb2NhdGUgYWxsIHJlY2VpdmUg YnVmZmVyIG9uIHRyYW5zcG9ydCBlc3RhYmxpc2htZW50ICovDQo+ICtzdGF0aWMgaW50IGFsbG9j YXRlX3JlY2VpdmVfYnVmZmVycyhzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvLCBpbnQNCj4g bnVtX2J1ZikNCj4gK3sNCj4gKwlpbnQgaTsNCj4gKwlzdHJ1Y3Qgc21iZF9yZXNwb25zZSAqcmVz cG9uc2U7DQo+ICsNCj4gKwlJTklUX0xJU1RfSEVBRCgmaW5mby0+cmVhc3NlbWJseV9xdWV1ZSk7 DQo+ICsJc3Bpbl9sb2NrX2luaXQoJmluZm8tPnJlYXNzZW1ibHlfcXVldWVfbG9jayk7DQo+ICsJ aW5mby0+cmVhc3NlbWJseV9kYXRhX2xlbmd0aCA9IDA7DQo+ICsJaW5mby0+cmVhc3NlbWJseV9x dWV1ZV9sZW5ndGggPSAwOw0KPiArDQo+ICsJSU5JVF9MSVNUX0hFQUQoJmluZm8tPnJlY2VpdmVf cXVldWUpOw0KPiArCXNwaW5fbG9ja19pbml0KCZpbmZvLT5yZWNlaXZlX3F1ZXVlX2xvY2spOw0K PiArCWluZm8tPmNvdW50X3JlY2VpdmVfcXVldWUgPSAwOw0KPiArDQo+ICsJSU5JVF9MSVNUX0hF QUQoJmluZm8tPmVtcHR5X3BhY2tldF9xdWV1ZSk7DQo+ICsJc3Bpbl9sb2NrX2luaXQoJmluZm8t PmVtcHR5X3BhY2tldF9xdWV1ZV9sb2NrKTsNCj4gKwlpbmZvLT5jb3VudF9lbXB0eV9wYWNrZXRf cXVldWUgPSAwOw0KPiArDQo+ICsJaW5pdF93YWl0cXVldWVfaGVhZCgmaW5mby0+d2FpdF9yZWNl aXZlX3F1ZXVlcyk7DQo+ICsNCj4gKwlmb3IgKGkgPSAwOyBpIDwgbnVtX2J1ZjsgaSsrKSB7DQo+ ICsJCXJlc3BvbnNlID0gbWVtcG9vbF9hbGxvYyhpbmZvLT5yZXNwb25zZV9tZW1wb29sLA0KPiBH RlBfS0VSTkVMKTsNCj4gKwkJaWYgKCFyZXNwb25zZSkNCj4gKwkJCWdvdG8gYWxsb2NhdGVfZmFp bGVkOw0KPiArDQo+ICsJCXJlc3BvbnNlLT5pbmZvID0gaW5mbzsNCj4gKwkJbGlzdF9hZGRfdGFp bCgmcmVzcG9uc2UtPmxpc3QsICZpbmZvLT5yZWNlaXZlX3F1ZXVlKTsNCj4gKwkJaW5mby0+Y291 bnRfcmVjZWl2ZV9xdWV1ZSsrOw0KPiArCX0NCj4gKw0KPiArCXJldHVybiAwOw0KPiArDQo+ICth bGxvY2F0ZV9mYWlsZWQ6DQo+ICsJd2hpbGUgKCFsaXN0X2VtcHR5KCZpbmZvLT5yZWNlaXZlX3F1 ZXVlKSkgew0KPiArCQlyZXNwb25zZSA9IGxpc3RfZmlyc3RfZW50cnkoDQo+ICsJCQkJJmluZm8t PnJlY2VpdmVfcXVldWUsDQo+ICsJCQkJc3RydWN0IHNtYmRfcmVzcG9uc2UsIGxpc3QpOw0KPiAr CQlsaXN0X2RlbCgmcmVzcG9uc2UtPmxpc3QpOw0KPiArCQlpbmZvLT5jb3VudF9yZWNlaXZlX3F1 ZXVlLS07DQo+ICsNCj4gKwkJbWVtcG9vbF9mcmVlKHJlc3BvbnNlLCBpbmZvLT5yZXNwb25zZV9t ZW1wb29sKTsNCj4gKwl9DQo+ICsJcmV0dXJuIC1FTk9NRU07DQo+ICt9DQo+ICsNCj4gK3N0YXRp YyB2b2lkIGRlc3Ryb3lfcmVjZWl2ZV9idWZmZXJzKHN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24gKmlu Zm8pDQo+ICt7DQo+ICsJc3RydWN0IHNtYmRfcmVzcG9uc2UgKnJlc3BvbnNlOw0KPiArDQo+ICsJ d2hpbGUgKChyZXNwb25zZSA9IGdldF9yZWNlaXZlX2J1ZmZlcihpbmZvKSkpDQo+ICsJCW1lbXBv b2xfZnJlZShyZXNwb25zZSwgaW5mby0+cmVzcG9uc2VfbWVtcG9vbCk7DQo+ICsNCj4gKwl3aGls ZSAoKHJlc3BvbnNlID0gZ2V0X2VtcHR5X3F1ZXVlX2J1ZmZlcihpbmZvKSkpDQo+ICsJCW1lbXBv b2xfZnJlZShyZXNwb25zZSwgaW5mby0+cmVzcG9uc2VfbWVtcG9vbCk7DQo+ICt9DQo+ICsNCj4g Ky8qDQo+ICsgKiBDaGVjayBhbmQgc2VuZCBhbiBpbW1lZGlhdGUgb3Iga2VlcCBhbGl2ZSBwYWNr ZXQNCj4gKyAqIFRoZSBjb25kaXRpb24gdG8gc2VuZCB0aG9zZSBwYWNrZXRzIGFyZSBkZWZpbmVk IGluIFtNUy1TTUJEXSAzLjEuMS4xDQo+ICsgKiBDb25uZWN0aW9uLktlZXBhbGl2ZVJlcXVlc3Rl ZCBhbmQgQ29ubmVjdGlvbi5TZW5kSW1tZWRpYXRlDQo+ICsgKiBUaGUgaWRlYSBpcyB0byBleHRl bmQgY3JlZGl0cyB0byBzZXJ2ZXIgYXMgc29vbiBhcyBpdCBiZWNvbWVzIGF2YWlsYWJsZQ0KPiAr ICovDQo+ICtzdGF0aWMgdm9pZCBzZW5kX2ltbWVkaWF0ZV93b3JrKHN0cnVjdCB3b3JrX3N0cnVj dCAqd29yaykNCj4gK3sNCj4gKwlzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvID0gY29udGFp bmVyX29mKA0KPiArCQkJCQl3b3JrLCBzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uLA0KPiArCQkJCQlz ZW5kX2ltbWVkaWF0ZV93b3JrLndvcmspOw0KPiArDQo+ICsJaWYgKGluZm8tPmtlZXBfYWxpdmVf cmVxdWVzdGVkID09IEtFRVBfQUxJVkVfUEVORElORyB8fA0KPiArCSAgICBpbmZvLT5zZW5kX2lt bWVkaWF0ZSkgew0KPiArCQlsb2dfa2VlcF9hbGl2ZShJTkZPLCAic2VuZCBhbiBlbXB0eSBtZXNz YWdlXG4iKTsNCj4gKwkJc21iZF9wb3N0X3NlbmRfZW1wdHkoaW5mbyk7DQo+ICsJfQ0KPiArfQ0K PiArDQo+ICsvKiBJbXBsZW1lbnQgaWRsZSBjb25uZWN0aW9uIHRpbWVyIFtNUy1TTUJEXSAzLjEu Ni4yICovDQo+ICtzdGF0aWMgdm9pZCBpZGxlX2Nvbm5lY3Rpb25fdGltZXIoc3RydWN0IHdvcmtf c3RydWN0ICp3b3JrKQ0KPiArew0KPiArCXN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24gKmluZm8gPSBj b250YWluZXJfb2YoDQo+ICsJCQkJCXdvcmssIHN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24sDQo+ICsJ CQkJCWlkbGVfdGltZXJfd29yay53b3JrKTsNCj4gKw0KPiArCWlmIChpbmZvLT5rZWVwX2FsaXZl X3JlcXVlc3RlZCAhPSBLRUVQX0FMSVZFX05PTkUpIHsNCj4gKwkJbG9nX2tlZXBfYWxpdmUoRVJS LA0KPiArCQkJImVycm9yIHN0YXR1cyBpbmZvLT5rZWVwX2FsaXZlX3JlcXVlc3RlZD0lZFxuIiwN Cj4gKwkJCWluZm8tPmtlZXBfYWxpdmVfcmVxdWVzdGVkKTsNCj4gKwkJc21iZF9kaXNjb25uZWN0 X3JkbWFfY29ubmVjdGlvbihpbmZvKTsNCj4gKwkJcmV0dXJuOw0KPiArCX0NCj4gKw0KPiArCWxv Z19rZWVwX2FsaXZlKElORk8sICJhYm91dCB0byBzZW5kIGFuIGVtcHR5IGlkbGUgbWVzc2FnZVxu Iik7DQo+ICsJc21iZF9wb3N0X3NlbmRfZW1wdHkoaW5mbyk7DQo+ICsNCj4gKwkvKiBTZXR1cCB0 aGUgbmV4dCBpZGxlIHRpbWVvdXQgd29yayAqLw0KPiArCXF1ZXVlX2RlbGF5ZWRfd29yayhpbmZv LT53b3JrcXVldWUsICZpbmZvLT5pZGxlX3RpbWVyX3dvcmssDQo+ICsJCQlpbmZvLT5rZWVwX2Fs aXZlX2ludGVydmFsKkhaKTsNCj4gK30NCj4gKw0KPiArc3RhdGljIHZvaWQgZGVzdHJveV9jYWNo ZXNfYW5kX3dvcmtxdWV1ZShzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uDQo+ICppbmZvKQ0KPiArew0K PiArCWRlc3Ryb3lfcmVjZWl2ZV9idWZmZXJzKGluZm8pOw0KPiArCWRlc3Ryb3lfd29ya3F1ZXVl KGluZm8tPndvcmtxdWV1ZSk7DQo+ICsJbWVtcG9vbF9kZXN0cm95KGluZm8tPnJlc3BvbnNlX21l bXBvb2wpOw0KPiArCWttZW1fY2FjaGVfZGVzdHJveShpbmZvLT5yZXNwb25zZV9jYWNoZSk7DQo+ ICsJbWVtcG9vbF9kZXN0cm95KGluZm8tPnJlcXVlc3RfbWVtcG9vbCk7DQo+ICsJa21lbV9jYWNo ZV9kZXN0cm95KGluZm8tPnJlcXVlc3RfY2FjaGUpOw0KPiArfQ0KPiArDQo+ICsjZGVmaW5lIE1B WF9OQU1FX0xFTgk4MA0KPiArc3RhdGljIGludCBhbGxvY2F0ZV9jYWNoZXNfYW5kX3dvcmtxdWV1 ZShzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvKQ0KPiArew0KPiArCWNoYXIgbmFtZVtNQVhf TkFNRV9MRU5dOw0KPiArCWludCByYzsNCj4gKw0KPiArCXNucHJpbnRmKG5hbWUsIE1BWF9OQU1F X0xFTiwgInNtYmRfcmVxdWVzdF8lcCIsIGluZm8pOw0KPiArCWluZm8tPnJlcXVlc3RfY2FjaGUg PQ0KPiArCQlrbWVtX2NhY2hlX2NyZWF0ZSgNCj4gKwkJCW5hbWUsDQo+ICsJCQlzaXplb2Yoc3Ry dWN0IHNtYmRfcmVxdWVzdCkgKw0KPiArCQkJCXNpemVvZihzdHJ1Y3Qgc21iZF9kYXRhX3RyYW5z ZmVyKSwNCj4gKwkJCTAsIFNMQUJfSFdDQUNIRV9BTElHTiwgTlVMTCk7DQo+ICsJaWYgKCFpbmZv LT5yZXF1ZXN0X2NhY2hlKQ0KPiArCQlyZXR1cm4gLUVOT01FTTsNCj4gKw0KPiArCWluZm8tPnJl cXVlc3RfbWVtcG9vbCA9DQo+ICsJCW1lbXBvb2xfY3JlYXRlKGluZm8tPnNlbmRfY3JlZGl0X3Rh cmdldCwNCj4gbWVtcG9vbF9hbGxvY19zbGFiLA0KPiArCQkJbWVtcG9vbF9mcmVlX3NsYWIsIGlu Zm8tPnJlcXVlc3RfY2FjaGUpOw0KPiArCWlmICghaW5mby0+cmVxdWVzdF9tZW1wb29sKQ0KPiAr CQlnb3RvIG91dDE7DQo+ICsNCj4gKwlzbnByaW50ZihuYW1lLCBNQVhfTkFNRV9MRU4sICJzbWJk X3Jlc3BvbnNlXyVwIiwgaW5mbyk7DQo+ICsJaW5mby0+cmVzcG9uc2VfY2FjaGUgPQ0KPiArCQlr bWVtX2NhY2hlX2NyZWF0ZSgNCj4gKwkJCW5hbWUsDQo+ICsJCQlzaXplb2Yoc3RydWN0IHNtYmRf cmVzcG9uc2UpICsNCj4gKwkJCQlpbmZvLT5tYXhfcmVjZWl2ZV9zaXplLA0KPiArCQkJMCwgU0xB Ql9IV0NBQ0hFX0FMSUdOLCBOVUxMKTsNCj4gKwlpZiAoIWluZm8tPnJlc3BvbnNlX2NhY2hlKQ0K PiArCQlnb3RvIG91dDI7DQo+ICsNCj4gKwlpbmZvLT5yZXNwb25zZV9tZW1wb29sID0NCj4gKwkJ bWVtcG9vbF9jcmVhdGUoaW5mby0+cmVjZWl2ZV9jcmVkaXRfbWF4LA0KPiBtZW1wb29sX2FsbG9j X3NsYWIsDQo+ICsJCSAgICAgICBtZW1wb29sX2ZyZWVfc2xhYiwgaW5mby0+cmVzcG9uc2VfY2Fj aGUpOw0KPiArCWlmICghaW5mby0+cmVzcG9uc2VfbWVtcG9vbCkNCj4gKwkJZ290byBvdXQzOw0K PiArDQo+ICsJc25wcmludGYobmFtZSwgTUFYX05BTUVfTEVOLCAic21iZF8lcCIsIGluZm8pOw0K PiArCWluZm8tPndvcmtxdWV1ZSA9IGNyZWF0ZV93b3JrcXVldWUobmFtZSk7DQo+ICsJaWYgKCFp bmZvLT53b3JrcXVldWUpDQo+ICsJCWdvdG8gb3V0NDsNCj4gKw0KPiArCXJjID0gYWxsb2NhdGVf cmVjZWl2ZV9idWZmZXJzKGluZm8sIGluZm8tPnJlY2VpdmVfY3JlZGl0X21heCk7DQo+ICsJaWYg KHJjKSB7DQo+ICsJCWxvZ19yZG1hX2V2ZW50KEVSUiwgImZhaWxlZCB0byBhbGxvY2F0ZSByZWNl aXZlIGJ1ZmZlcnNcbiIpOw0KPiArCQlnb3RvIG91dDU7DQo+ICsJfQ0KPiArDQo+ICsJcmV0dXJu IDA7DQo+ICsNCj4gK291dDU6DQo+ICsJZGVzdHJveV93b3JrcXVldWUoaW5mby0+d29ya3F1ZXVl KTsNCj4gK291dDQ6DQo+ICsJbWVtcG9vbF9kZXN0cm95KGluZm8tPnJlc3BvbnNlX21lbXBvb2wp Ow0KPiArb3V0MzoNCj4gKwlrbWVtX2NhY2hlX2Rlc3Ryb3koaW5mby0+cmVzcG9uc2VfY2FjaGUp Ow0KPiArb3V0MjoNCj4gKwltZW1wb29sX2Rlc3Ryb3koaW5mby0+cmVxdWVzdF9tZW1wb29sKTsN Cj4gK291dDE6DQo+ICsJa21lbV9jYWNoZV9kZXN0cm95KGluZm8tPnJlcXVlc3RfY2FjaGUpOw0K PiArCXJldHVybiAtRU5PTUVNOw0KPiArfQ0KPiArDQo+ICsvKiBDcmVhdGUgYSBTTUJEIGNvbm5l Y3Rpb24sIGNhbGxlZCBieSB1cHBlciBsYXllciAqLw0KPiArc3RydWN0IHNtYmRfY29ubmVjdGlv biAqX3NtYmRfZ2V0X2Nvbm5lY3Rpb24oDQo+ICsJc3RydWN0IFRDUF9TZXJ2ZXJfSW5mbyAqc2Vy dmVyLCBzdHJ1Y3Qgc29ja2FkZHIgKmRzdGFkZHIsIGludCBwb3J0KQ0KPiArew0KPiArCWludCBy YzsNCj4gKwlzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvOw0KPiArCXN0cnVjdCByZG1hX2Nv bm5fcGFyYW0gY29ubl9wYXJhbTsNCj4gKwlzdHJ1Y3QgaWJfcXBfaW5pdF9hdHRyIHFwX2F0dHI7 DQo+ICsJc3RydWN0IHNvY2thZGRyX2luICphZGRyX2luID0gKHN0cnVjdCBzb2NrYWRkcl9pbiAq KSBkc3RhZGRyOw0KPiArDQo+ICsJaW5mbyA9IGt6YWxsb2Moc2l6ZW9mKHN0cnVjdCBzbWJkX2Nv bm5lY3Rpb24pLCBHRlBfS0VSTkVMKTsNCj4gKwlpZiAoIWluZm8pDQo+ICsJCXJldHVybiBOVUxM Ow0KPiArDQo+ICsJaW5mby0+dHJhbnNwb3J0X3N0YXR1cyA9IFNNQkRfQ09OTkVDVElORzsNCj4g KwlyYyA9IHNtYmRfaWFfb3BlbihpbmZvLCBkc3RhZGRyLCBwb3J0KTsNCj4gKwlpZiAocmMpIHsN Cj4gKwkJbG9nX3JkbWFfZXZlbnQoSU5GTywgInNtYmRfaWFfb3BlbiByYz0lZFxuIiwgcmMpOw0K PiArCQlnb3RvIGNyZWF0ZV9pZF9mYWlsZWQ7DQo+ICsJfQ0KPiArDQo+ICsJaWYgKHNtYmRfc2Vu ZF9jcmVkaXRfdGFyZ2V0ID4gaW5mby0+aWQtPmRldmljZS0+YXR0cnMubWF4X2NxZSB8fA0KPiAr CSAgICBzbWJkX3NlbmRfY3JlZGl0X3RhcmdldCA+IGluZm8tPmlkLT5kZXZpY2UtPmF0dHJzLm1h eF9xcF93cikgew0KPiArCQlsb2dfcmRtYV9ldmVudChFUlIsDQo+ICsJCQkiY29uc2lkZXIgbG93 ZXJpbmcgc2VuZF9jcmVkaXRfdGFyZ2V0ID0gJWQuICINCj4gKwkJCSJQb3NzaWJsZSBDUUUgb3Zl cnJ1biwgZGV2aWNlICINCj4gKwkJCSJyZXBvcnRpbmcgbWF4X2NwZSAlZCBtYXhfcXBfd3IgJWRc biIsDQo+ICsJCQlzbWJkX3NlbmRfY3JlZGl0X3RhcmdldCwNCj4gKwkJCWluZm8tPmlkLT5kZXZp Y2UtPmF0dHJzLm1heF9jcWUsDQo+ICsJCQlpbmZvLT5pZC0+ZGV2aWNlLT5hdHRycy5tYXhfcXBf d3IpOw0KPiArCQlnb3RvIGNvbmZpZ19mYWlsZWQ7DQo+ICsJfQ0KPiArDQo+ICsJaWYgKHNtYmRf cmVjZWl2ZV9jcmVkaXRfbWF4ID4gaW5mby0+aWQtPmRldmljZS0+YXR0cnMubWF4X2NxZSB8fA0K PiArCSAgICBzbWJkX3JlY2VpdmVfY3JlZGl0X21heCA+IGluZm8tPmlkLT5kZXZpY2UtPmF0dHJz Lm1heF9xcF93cikNCj4gew0KPiArCQlsb2dfcmRtYV9ldmVudChFUlIsDQo+ICsJCQkiY29uc2lk ZXIgbG93ZXJpbmcgcmVjZWl2ZV9jcmVkaXRfbWF4ID0gJWQuICINCj4gKwkJCSJQb3NzaWJsZSBD UUUgb3ZlcnJ1biwgZGV2aWNlICINCj4gKwkJCSJyZXBvcnRpbmcgbWF4X2NwZSAlZCBtYXhfcXBf d3IgJWRcbiIsDQo+ICsJCQlzbWJkX3JlY2VpdmVfY3JlZGl0X21heCwNCj4gKwkJCWluZm8tPmlk LT5kZXZpY2UtPmF0dHJzLm1heF9jcWUsDQo+ICsJCQlpbmZvLT5pZC0+ZGV2aWNlLT5hdHRycy5t YXhfcXBfd3IpOw0KPiArCQlnb3RvIGNvbmZpZ19mYWlsZWQ7DQo+ICsJfQ0KPiArDQo+ICsJaW5m by0+cmVjZWl2ZV9jcmVkaXRfbWF4ID0gc21iZF9yZWNlaXZlX2NyZWRpdF9tYXg7DQo+ICsJaW5m by0+c2VuZF9jcmVkaXRfdGFyZ2V0ID0gc21iZF9zZW5kX2NyZWRpdF90YXJnZXQ7DQo+ICsJaW5m by0+bWF4X3NlbmRfc2l6ZSA9IHNtYmRfbWF4X3NlbmRfc2l6ZTsNCj4gKwlpbmZvLT5tYXhfZnJh Z21lbnRlZF9yZWN2X3NpemUgPQ0KPiBzbWJkX21heF9mcmFnbWVudGVkX3JlY3Zfc2l6ZTsNCj4g KwlpbmZvLT5tYXhfcmVjZWl2ZV9zaXplID0gc21iZF9tYXhfcmVjZWl2ZV9zaXplOw0KPiArCWlu Zm8tPmtlZXBfYWxpdmVfaW50ZXJ2YWwgPSBzbWJkX2tlZXBfYWxpdmVfaW50ZXJ2YWw7DQo+ICsN Cj4gKwlpZiAoU01CRElSRUNUX01BWF9TR0UgPiBpbmZvLT5pZC0+ZGV2aWNlLT5hdHRycy5tYXhf c2dlKSB7DQo+ICsJCWxvZ19yZG1hX2V2ZW50KEVSUiwgIndhcm5pbmc6IGRldmljZSBtYXhfc2dl ID0gJWQgdG9vDQo+IHNtYWxsXG4iLA0KPiArCQkJaW5mby0+aWQtPmRldmljZS0+YXR0cnMubWF4 X3NnZSk7DQo+ICsJCWxvZ19yZG1hX2V2ZW50KEVSUiwgIlF1ZXVlIFBhaXIgY3JlYXRpb24gbWF5 IGZhaWxcbiIpOw0KPiArCX0NCj4gKw0KPiArCWluZm8tPnNlbmRfY3EgPSBOVUxMOw0KPiArCWlu Zm8tPnJlY3ZfY3EgPSBOVUxMOw0KPiArCWluZm8tPnNlbmRfY3EgPSBpYl9hbGxvY19jcShpbmZv LT5pZC0+ZGV2aWNlLCBpbmZvLA0KPiArCQkJaW5mby0+c2VuZF9jcmVkaXRfdGFyZ2V0LCAwLCBJ Ql9QT0xMX1NPRlRJUlEpOw0KPiArCWlmIChJU19FUlIoaW5mby0+c2VuZF9jcSkpIHsNCj4gKwkJ aW5mby0+c2VuZF9jcSA9IE5VTEw7DQo+ICsJCWdvdG8gYWxsb2NfY3FfZmFpbGVkOw0KPiArCX0N Cj4gKw0KPiArCWluZm8tPnJlY3ZfY3EgPSBpYl9hbGxvY19jcShpbmZvLT5pZC0+ZGV2aWNlLCBp bmZvLA0KPiArCQkJaW5mby0+cmVjZWl2ZV9jcmVkaXRfbWF4LCAwLCBJQl9QT0xMX1NPRlRJUlEp Ow0KPiArCWlmIChJU19FUlIoaW5mby0+cmVjdl9jcSkpIHsNCj4gKwkJaW5mby0+cmVjdl9jcSA9 IE5VTEw7DQo+ICsJCWdvdG8gYWxsb2NfY3FfZmFpbGVkOw0KPiArCX0NCj4gKw0KPiArCW1lbXNl dCgmcXBfYXR0ciwgMCwgc2l6ZW9mKHFwX2F0dHIpKTsNCj4gKwlxcF9hdHRyLmV2ZW50X2hhbmRs ZXIgPSBzbWJkX3FwX2FzeW5jX2Vycm9yX3VwY2FsbDsNCj4gKwlxcF9hdHRyLnFwX2NvbnRleHQg PSBpbmZvOw0KPiArCXFwX2F0dHIuY2FwLm1heF9zZW5kX3dyID0gaW5mby0+c2VuZF9jcmVkaXRf dGFyZ2V0Ow0KPiArCXFwX2F0dHIuY2FwLm1heF9yZWN2X3dyID0gaW5mby0+cmVjZWl2ZV9jcmVk aXRfbWF4Ow0KPiArCXFwX2F0dHIuY2FwLm1heF9zZW5kX3NnZSA9IFNNQkRJUkVDVF9NQVhfU0dF Ow0KPiArCXFwX2F0dHIuY2FwLm1heF9yZWN2X3NnZSA9IFNNQkRJUkVDVF9NQVhfU0dFOw0KPiAr CXFwX2F0dHIuY2FwLm1heF9pbmxpbmVfZGF0YSA9IDA7DQo+ICsJcXBfYXR0ci5zcV9zaWdfdHlw ZSA9IElCX1NJR05BTF9SRVFfV1I7DQo+ICsJcXBfYXR0ci5xcF90eXBlID0gSUJfUVBUX1JDOw0K PiArCXFwX2F0dHIuc2VuZF9jcSA9IGluZm8tPnNlbmRfY3E7DQo+ICsJcXBfYXR0ci5yZWN2X2Nx ID0gaW5mby0+cmVjdl9jcTsNCj4gKwlxcF9hdHRyLnBvcnRfbnVtID0gfjA7DQo+ICsNCj4gKwly YyA9IHJkbWFfY3JlYXRlX3FwKGluZm8tPmlkLCBpbmZvLT5wZCwgJnFwX2F0dHIpOw0KPiArCWlm IChyYykgew0KPiArCQlsb2dfcmRtYV9ldmVudChFUlIsICJyZG1hX2NyZWF0ZV9xcCBmYWlsZWQg JWlcbiIsIHJjKTsNCj4gKwkJZ290byBjcmVhdGVfcXBfZmFpbGVkOw0KPiArCX0NCj4gKw0KPiAr CW1lbXNldCgmY29ubl9wYXJhbSwgMCwgc2l6ZW9mKGNvbm5fcGFyYW0pKTsNCj4gKwljb25uX3Bh cmFtLmluaXRpYXRvcl9kZXB0aCA9IDA7DQo+ICsNCj4gKwljb25uX3BhcmFtLnJldHJ5X2NvdW50 ID0gU01CRF9DTV9SRVRSWTsNCj4gKwljb25uX3BhcmFtLnJucl9yZXRyeV9jb3VudCA9IFNNQkRf Q01fUk5SX1JFVFJZOw0KPiArCWNvbm5fcGFyYW0uZmxvd19jb250cm9sID0gMDsNCj4gKwlpbml0 X3dhaXRxdWV1ZV9oZWFkKCZpbmZvLT53YWl0X2Rlc3Ryb3kpOw0KPiArDQo+ICsJbG9nX3JkbWFf ZXZlbnQoSU5GTywgImNvbm5lY3RpbmcgdG8gSVAgJXBJNCBwb3J0ICVkXG4iLA0KPiArCQkmYWRk cl9pbi0+c2luX2FkZHIsIHBvcnQpOw0KPiArDQo+ICsJaW5pdF93YWl0cXVldWVfaGVhZCgmaW5m by0+Y29ubl93YWl0KTsNCj4gKwlyYyA9IHJkbWFfY29ubmVjdChpbmZvLT5pZCwgJmNvbm5fcGFy YW0pOw0KPiArCWlmIChyYykgew0KPiArCQlsb2dfcmRtYV9ldmVudChFUlIsICJyZG1hX2Nvbm5l Y3QoKSBmYWlsZWQgd2l0aCAlaVxuIiwgcmMpOw0KPiArCQlnb3RvIHJkbWFfY29ubmVjdF9mYWls ZWQ7DQo+ICsJfQ0KPiArDQo+ICsJd2FpdF9ldmVudF9pbnRlcnJ1cHRpYmxlKA0KPiArCQlpbmZv LT5jb25uX3dhaXQsIGluZm8tPnRyYW5zcG9ydF9zdGF0dXMgIT0NCj4gU01CRF9DT05ORUNUSU5H KTsNCj4gKw0KPiArCWlmIChpbmZvLT50cmFuc3BvcnRfc3RhdHVzICE9IFNNQkRfQ09OTkVDVEVE KSB7DQo+ICsJCWxvZ19yZG1hX2V2ZW50KEVSUiwgInJkbWFfY29ubmVjdCBmYWlsZWQgcG9ydD0l ZFxuIiwNCj4gcG9ydCk7DQo+ICsJCWdvdG8gcmRtYV9jb25uZWN0X2ZhaWxlZDsNCj4gKwl9DQo+ ICsNCj4gKwlsb2dfcmRtYV9ldmVudChJTkZPLCAicmRtYV9jb25uZWN0IGNvbm5lY3RlZFxuIik7 DQo+ICsNCj4gKwlyYyA9IGFsbG9jYXRlX2NhY2hlc19hbmRfd29ya3F1ZXVlKGluZm8pOw0KPiAr CWlmIChyYykgew0KPiArCQlsb2dfcmRtYV9ldmVudChFUlIsICJjYWNoZSBhbGxvY2F0aW9uIGZh aWxlZFxuIik7DQo+ICsJCWdvdG8gYWxsb2NhdGVfY2FjaGVfZmFpbGVkOw0KPiArCX0NCj4gKw0K PiArCWluaXRfd2FpdHF1ZXVlX2hlYWQoJmluZm8tPndhaXRfc2VuZF9xdWV1ZSk7DQo+ICsJaW5p dF93YWl0cXVldWVfaGVhZCgmaW5mby0+d2FpdF9yZWFzc2VtYmx5X3F1ZXVlKTsNCj4gKw0KPiAr CUlOSVRfREVMQVlFRF9XT1JLKCZpbmZvLT5pZGxlX3RpbWVyX3dvcmssDQo+IGlkbGVfY29ubmVj dGlvbl90aW1lcik7DQo+ICsJSU5JVF9ERUxBWUVEX1dPUksoJmluZm8tPnNlbmRfaW1tZWRpYXRl X3dvcmssDQo+IHNlbmRfaW1tZWRpYXRlX3dvcmspOw0KPiArCXF1ZXVlX2RlbGF5ZWRfd29yayhp bmZvLT53b3JrcXVldWUsICZpbmZvLT5pZGxlX3RpbWVyX3dvcmssDQo+ICsJCWluZm8tPmtlZXBf YWxpdmVfaW50ZXJ2YWwqSFopOw0KPiArDQo+ICsJaW5pdF93YWl0cXVldWVfaGVhZCgmaW5mby0+ d2FpdF9zZW5kX3BlbmRpbmcpOw0KPiArCWF0b21pY19zZXQoJmluZm8tPnNlbmRfcGVuZGluZywg MCk7DQo+ICsNCj4gKwlpbml0X3dhaXRxdWV1ZV9oZWFkKCZpbmZvLT53YWl0X3NlbmRfcGF5bG9h ZF9wZW5kaW5nKTsNCj4gKwlhdG9taWNfc2V0KCZpbmZvLT5zZW5kX3BheWxvYWRfcGVuZGluZywg MCk7DQo+ICsNCj4gKwlJTklUX1dPUksoJmluZm8tPmRpc2Nvbm5lY3Rfd29yaywNCj4gc21iZF9k aXNjb25uZWN0X3JkbWFfd29yayk7DQo+ICsJSU5JVF9XT1JLKCZpbmZvLT5kZXN0cm95X3dvcmss IHNtYmRfZGVzdHJveV9yZG1hX3dvcmspOw0KPiArCUlOSVRfV09SSygmaW5mby0+cmVjdl9kb25l X3dvcmssIHNtYmRfcmVjdl9kb25lX3dvcmspOw0KPiArCUlOSVRfV09SSygmaW5mby0+cG9zdF9z ZW5kX2NyZWRpdHNfd29yaywNCj4gc21iZF9wb3N0X3NlbmRfY3JlZGl0cyk7DQo+ICsJaW5mby0+ bmV3X2NyZWRpdHNfb2ZmZXJlZCA9IDA7DQo+ICsJc3Bpbl9sb2NrX2luaXQoJmluZm8tPmxvY2tf bmV3X2NyZWRpdHNfb2ZmZXJlZCk7DQo+ICsNCj4gKwlyYyA9IHNtYmRfbmVnb3RpYXRlKGluZm8p Ow0KPiArCWlmIChyYykgew0KPiArCQlsb2dfcmRtYV9ldmVudChFUlIsICJzbWJkX25lZ290aWF0 ZSByYz0lZFxuIiwgcmMpOw0KPiArCQlnb3RvIG5lZ290aWF0aW9uX2ZhaWxlZDsNCj4gKwl9DQo+ ICsNCj4gKwlyZXR1cm4gaW5mbzsNCj4gKw0KPiArbmVnb3RpYXRpb25fZmFpbGVkOg0KPiArCWNh bmNlbF9kZWxheWVkX3dvcmtfc3luYygmaW5mby0+aWRsZV90aW1lcl93b3JrKTsNCj4gKwlkZXN0 cm95X2NhY2hlc19hbmRfd29ya3F1ZXVlKGluZm8pOw0KPiArCWluZm8tPnRyYW5zcG9ydF9zdGF0 dXMgPSBTTUJEX05FR09USUFURV9GQUlMRUQ7DQo+ICsJaW5pdF93YWl0cXVldWVfaGVhZCgmaW5m by0+Y29ubl93YWl0KTsNCj4gKwlyZG1hX2Rpc2Nvbm5lY3QoaW5mby0+aWQpOw0KPiArCXdhaXRf ZXZlbnQoaW5mby0+Y29ubl93YWl0LA0KPiArCQlpbmZvLT50cmFuc3BvcnRfc3RhdHVzID09IFNN QkRfRElTQ09OTkVDVEVEKTsNCj4gKw0KPiArYWxsb2NhdGVfY2FjaGVfZmFpbGVkOg0KPiArcmRt YV9jb25uZWN0X2ZhaWxlZDoNCj4gKwlyZG1hX2Rlc3Ryb3lfcXAoaW5mby0+aWQpOw0KPiArDQo+ ICtjcmVhdGVfcXBfZmFpbGVkOg0KPiArYWxsb2NfY3FfZmFpbGVkOg0KPiArCWlmIChpbmZvLT5z ZW5kX2NxKQ0KPiArCQlpYl9mcmVlX2NxKGluZm8tPnNlbmRfY3EpOw0KPiArCWlmIChpbmZvLT5y ZWN2X2NxKQ0KPiArCQlpYl9mcmVlX2NxKGluZm8tPnJlY3ZfY3EpOw0KPiArDQo+ICtjb25maWdf ZmFpbGVkOg0KPiArCWliX2RlYWxsb2NfcGQoaW5mby0+cGQpOw0KPiArCXJkbWFfZGVzdHJveV9p ZChpbmZvLT5pZCk7DQo+ICsNCj4gK2NyZWF0ZV9pZF9mYWlsZWQ6DQo+ICsJa2ZyZWUoaW5mbyk7 DQo+ICsJcmV0dXJuIE5VTEw7DQo+ICt9DQo+IGRpZmYgLS1naXQgYS9mcy9jaWZzL3NtYmRpcmVj dC5oIGIvZnMvY2lmcy9zbWJkaXJlY3QuaA0KPiBpbmRleCBjNTVmMjhiLi4zNWJjMjViIDEwMDY0 NA0KPiAtLS0gYS9mcy9jaWZzL3NtYmRpcmVjdC5oDQo+ICsrKyBiL2ZzL2NpZnMvc21iZGlyZWN0 LmgNCj4gQEAgLTE2LDYgKzE2LDI4NiBAQA0KPiAgI2lmbmRlZiBfU01CRElSRUNUX0gNCj4gICNk ZWZpbmUgX1NNQkRJUkVDVF9IDQo+IA0KPiArI2lmZGVmIENPTkZJR19DSUZTX1NNQl9ESVJFQ1QN Cj4gKyNkZWZpbmUgY2lmc19yZG1hX2VuYWJsZWQoc2VydmVyKQkoKHNlcnZlciktPnJkbWEpDQo+ ICsNCj4gKyNpbmNsdWRlICJjaWZzZ2xvYi5oIg0KPiArI2luY2x1ZGUgPHJkbWEvaWJfdmVyYnMu aD4NCj4gKyNpbmNsdWRlIDxyZG1hL3JkbWFfY20uaD4NCj4gKyNpbmNsdWRlIDxsaW51eC9tZW1w b29sLmg+DQo+ICsNCj4gK2VudW0ga2VlcF9hbGl2ZV9zdGF0dXMgew0KPiArCUtFRVBfQUxJVkVf Tk9ORSwNCj4gKwlLRUVQX0FMSVZFX1BFTkRJTkcsDQo+ICsJS0VFUF9BTElWRV9TRU5ULA0KPiAr fTsNCj4gKw0KPiArZW51bSBzbWJkX2Nvbm5lY3Rpb25fc3RhdHVzIHsNCj4gKwlTTUJEX0NSRUFU RUQsDQo+ICsJU01CRF9DT05ORUNUSU5HLA0KPiArCVNNQkRfQ09OTkVDVEVELA0KPiArCVNNQkRf TkVHT1RJQVRFX0ZBSUxFRCwNCj4gKwlTTUJEX0RJU0NPTk5FQ1RJTkcsDQo+ICsJU01CRF9ESVND T05ORUNURUQsDQo+ICsJU01CRF9ERVNUUk9ZRUQNCj4gK307DQo+ICsNCj4gKy8qDQo+ICsgKiBU aGUgY29udGV4dCBmb3IgdGhlIFNNQkRpcmVjdCB0cmFuc3BvcnQNCj4gKyAqIEV2ZXJ5dGhpbmcg cmVsYXRlZCB0byB0aGUgdHJhbnNwb3J0IGlzIGhlcmUuIEl0IGhhcyBzZXZlcmFsIGxvZ2ljYWwg cGFydHMNCj4gKyAqIDEuIFJETUEgcmVsYXRlZCBzdHJ1Y3R1cmVzDQo+ICsgKiAyLiBTTUJEaXJl Y3QgY29ubmVjdGlvbiBwYXJhbWV0ZXJzDQo+ICsgKiAzLiBNZW1vcnkgcmVnaXN0cmF0aW9ucw0K PiArICogNC4gUmVjZWl2ZSBhbmQgcmVhc3NlbWJseSBxdWV1ZXMgZm9yIGRhdGEgcmVjZWl2ZSBw YXRoDQo+ICsgKiA1LiBtZW1wb29scyBmb3IgYWxsb2NhdGluZyBwYWNrZXRzDQo+ICsgKi8NCj4g K3N0cnVjdCBzbWJkX2Nvbm5lY3Rpb24gew0KPiArCWVudW0gc21iZF9jb25uZWN0aW9uX3N0YXR1 cyB0cmFuc3BvcnRfc3RhdHVzOw0KPiArDQo+ICsJLyogUkRNQSByZWxhdGVkICovDQo+ICsJc3Ry dWN0IHJkbWFfY21faWQgKmlkOw0KPiArCXN0cnVjdCBpYl9xcF9pbml0X2F0dHIgcXBfYXR0cjsN Cj4gKwlzdHJ1Y3QgaWJfcGQgKnBkOw0KPiArCXN0cnVjdCBpYl9jcSAqc2VuZF9jcSwgKnJlY3Zf Y3E7DQo+ICsJc3RydWN0IGliX2RldmljZV9hdHRyIGRldl9hdHRyOw0KPiArCWludCByaV9yYzsN Cj4gKwlzdHJ1Y3QgY29tcGxldGlvbiByaV9kb25lOw0KPiArCXdhaXRfcXVldWVfaGVhZF90IGNv bm5fd2FpdDsNCj4gKwl3YWl0X3F1ZXVlX2hlYWRfdCB3YWl0X2Rlc3Ryb3k7DQo+ICsNCj4gKwlz dHJ1Y3QgY29tcGxldGlvbiBuZWdvdGlhdGVfY29tcGxldGlvbjsNCj4gKwlib29sIG5lZ290aWF0 ZV9kb25lOw0KPiArDQo+ICsJc3RydWN0IHdvcmtfc3RydWN0IGRlc3Ryb3lfd29yazsNCj4gKwlz dHJ1Y3Qgd29ya19zdHJ1Y3QgZGlzY29ubmVjdF93b3JrOw0KPiArCXN0cnVjdCB3b3JrX3N0cnVj dCByZWN2X2RvbmVfd29yazsNCj4gKwlzdHJ1Y3Qgd29ya19zdHJ1Y3QgcG9zdF9zZW5kX2NyZWRp dHNfd29yazsNCj4gKw0KPiArCXNwaW5sb2NrX3QgbG9ja19uZXdfY3JlZGl0c19vZmZlcmVkOw0K PiArCWludCBuZXdfY3JlZGl0c19vZmZlcmVkOw0KPiArDQo+ICsJLyogQ29ubmVjdGlvbiBwYXJh bWV0ZXJzIGRlZmluZWQgaW4gW01TLVNNQkRdIDMuMS4xLjEgKi8NCj4gKwlpbnQgcmVjZWl2ZV9j cmVkaXRfbWF4Ow0KPiArCWludCBzZW5kX2NyZWRpdF90YXJnZXQ7DQo+ICsJaW50IG1heF9zZW5k X3NpemU7DQo+ICsJaW50IG1heF9mcmFnbWVudGVkX3JlY3Zfc2l6ZTsNCj4gKwlpbnQgbWF4X2Zy YWdtZW50ZWRfc2VuZF9zaXplOw0KPiArCWludCBtYXhfcmVjZWl2ZV9zaXplOw0KPiArCWludCBr ZWVwX2FsaXZlX2ludGVydmFsOw0KPiArCWludCBtYXhfcmVhZHdyaXRlX3NpemU7DQo+ICsJZW51 bSBrZWVwX2FsaXZlX3N0YXR1cyBrZWVwX2FsaXZlX3JlcXVlc3RlZDsNCj4gKwlpbnQgcHJvdG9j b2w7DQo+ICsJYXRvbWljX3Qgc2VuZF9jcmVkaXRzOw0KPiArCWF0b21pY190IHJlY2VpdmVfY3Jl ZGl0czsNCj4gKwlpbnQgcmVjZWl2ZV9jcmVkaXRfdGFyZ2V0Ow0KPiArCWludCBmcmFnbWVudF9y ZWFzc2VtYmx5X3JlbWFpbmluZzsNCj4gKw0KPiArCS8qIEFjdGl2aXR5IGFjY291dG5pbmcgKi8N Cj4gKw0KPiArCWF0b21pY190IHNlbmRfcGVuZGluZzsNCj4gKwl3YWl0X3F1ZXVlX2hlYWRfdCB3 YWl0X3NlbmRfcGVuZGluZzsNCj4gKwlhdG9taWNfdCBzZW5kX3BheWxvYWRfcGVuZGluZzsNCj4g Kwl3YWl0X3F1ZXVlX2hlYWRfdCB3YWl0X3NlbmRfcGF5bG9hZF9wZW5kaW5nOw0KPiArDQo+ICsJ LyogUmVjZWl2ZSBxdWV1ZSAqLw0KPiArCXN0cnVjdCBsaXN0X2hlYWQgcmVjZWl2ZV9xdWV1ZTsN Cj4gKwlpbnQgY291bnRfcmVjZWl2ZV9xdWV1ZTsNCj4gKwlzcGlubG9ja190IHJlY2VpdmVfcXVl dWVfbG9jazsNCj4gKw0KPiArCXN0cnVjdCBsaXN0X2hlYWQgZW1wdHlfcGFja2V0X3F1ZXVlOw0K PiArCWludCBjb3VudF9lbXB0eV9wYWNrZXRfcXVldWU7DQo+ICsJc3BpbmxvY2tfdCBlbXB0eV9w YWNrZXRfcXVldWVfbG9jazsNCj4gKw0KPiArCXdhaXRfcXVldWVfaGVhZF90IHdhaXRfcmVjZWl2 ZV9xdWV1ZXM7DQo+ICsNCj4gKwkvKiBSZWFzc2VtYmx5IHF1ZXVlICovDQo+ICsJc3RydWN0IGxp c3RfaGVhZCByZWFzc2VtYmx5X3F1ZXVlOw0KPiArCXNwaW5sb2NrX3QgcmVhc3NlbWJseV9xdWV1 ZV9sb2NrOw0KPiArCXdhaXRfcXVldWVfaGVhZF90IHdhaXRfcmVhc3NlbWJseV9xdWV1ZTsNCj4g Kw0KPiArCS8qIHRvdGFsIGRhdGEgbGVuZ3RoIG9mIHJlYXNzZW1ibHkgcXVldWUgKi8NCj4gKwlp bnQgcmVhc3NlbWJseV9kYXRhX2xlbmd0aDsNCj4gKwlpbnQgcmVhc3NlbWJseV9xdWV1ZV9sZW5n dGg7DQo+ICsJLyogdGhlIG9mZnNldCB0byBmaXJzdCBidWZmZXIgaW4gcmVhc3NlbWJseSBxdWV1 ZSAqLw0KPiArCWludCBmaXJzdF9lbnRyeV9vZmZzZXQ7DQo+ICsNCj4gKwlib29sIHNlbmRfaW1t ZWRpYXRlOw0KPiArDQo+ICsJd2FpdF9xdWV1ZV9oZWFkX3Qgd2FpdF9zZW5kX3F1ZXVlOw0KPiAr DQo+ICsJLyoNCj4gKwkgKiBJbmRpY2F0ZSBpZiB3ZSBoYXZlIHJlY2VpdmVkIGEgZnVsbCBwYWNr ZXQgb24gdGhlIGNvbm5lY3Rpb24NCj4gKwkgKiBUaGlzIGlzIHVzZWQgdG8gaWRlbnRpZnkgdGhl IGZpcnN0IFNNQkQgcGFja2V0IG9mIGEgYXNzZW1ibGVkDQo+ICsJICogcGF5bG9hZCAoU01CIHBh Y2tldCkgaW4gcmVhc3NlbWJseSBxdWV1ZSBzbyB3ZSBjYW4gcmV0dXJuIGENCj4gKwkgKiBSRkMx MDAyIGxlbmd0aCB0byB1cHBlciBsYXllciB0byBpbmRpY2F0ZSB0aGUgbGVuZ3RoIG9mIHRoZSBT TUINCj4gKwkgKiBwYWNrZXQgcmVjZWl2ZWQNCj4gKwkgKi8NCj4gKwlib29sIGZ1bGxfcGFja2V0 X3JlY2VpdmVkOw0KPiArDQo+ICsJc3RydWN0IHdvcmtxdWV1ZV9zdHJ1Y3QgKndvcmtxdWV1ZTsN Cj4gKwlzdHJ1Y3QgZGVsYXllZF93b3JrIGlkbGVfdGltZXJfd29yazsNCj4gKwlzdHJ1Y3QgZGVs YXllZF93b3JrIHNlbmRfaW1tZWRpYXRlX3dvcms7DQo+ICsNCj4gKwkvKiBNZW1vcnkgcG9vbCBm b3IgcHJlYWxsb2NhdGluZyBidWZmZXJzICovDQo+ICsJLyogcmVxdWVzdCBwb29sIGZvciBSRE1B IHNlbmQgKi8NCj4gKwlzdHJ1Y3Qga21lbV9jYWNoZSAqcmVxdWVzdF9jYWNoZTsNCj4gKwltZW1w b29sX3QgKnJlcXVlc3RfbWVtcG9vbDsNCj4gKw0KPiArCS8qIHJlc3BvbnNlIHBvb2wgZm9yIFJE TUEgcmVjZWl2ZSAqLw0KPiArCXN0cnVjdCBrbWVtX2NhY2hlICpyZXNwb25zZV9jYWNoZTsNCj4g KwltZW1wb29sX3QgKnJlc3BvbnNlX21lbXBvb2w7DQo+ICsNCj4gKwkvKiBmb3IgZGVidWcgcHVy cG9zZXMgKi8NCj4gKwl1bnNpZ25lZCBpbnQgY291bnRfZ2V0X3JlY2VpdmVfYnVmZmVyOw0KPiAr CXVuc2lnbmVkIGludCBjb3VudF9wdXRfcmVjZWl2ZV9idWZmZXI7DQo+ICsJdW5zaWduZWQgaW50 IGNvdW50X3JlYXNzZW1ibHlfcXVldWU7DQo+ICsJdW5zaWduZWQgaW50IGNvdW50X2VucXVldWVf cmVhc3NlbWJseV9xdWV1ZTsNCj4gKwl1bnNpZ25lZCBpbnQgY291bnRfZGVxdWV1ZV9yZWFzc2Vt Ymx5X3F1ZXVlOw0KPiArCXVuc2lnbmVkIGludCBjb3VudF9zZW5kX2VtcHR5Ow0KPiArfTsNCj4g Kw0KPiArZW51bSBzbWJkX21lc3NhZ2VfdHlwZSB7DQo+ICsJU01CRF9ORUdPVElBVEVfUkVTUCwN Cj4gKwlTTUJEX1RSQU5TRkVSX0RBVEEsDQo+ICt9Ow0KPiArDQo+ICsjZGVmaW5lIFNNQl9ESVJF Q1RfUkVTUE9OU0VfUkVRVUVTVEVEIDB4MDAwMQ0KPiArDQo+ICsvKiBTTUJEIG5lZ290aWF0aW9u IHJlcXVlc3QgcGFja2V0IFtNUy1TTUJEXSAyLjIuMSAqLw0KPiArc3RydWN0IHNtYmRfbmVnb3Rp YXRlX3JlcSB7DQo+ICsJX19sZTE2IG1pbl92ZXJzaW9uOw0KPiArCV9fbGUxNiBtYXhfdmVyc2lv bjsNCj4gKwlfX2xlMTYgcmVzZXJ2ZWQ7DQo+ICsJX19sZTE2IGNyZWRpdHNfcmVxdWVzdGVkOw0K PiArCV9fbGUzMiBwcmVmZXJyZWRfc2VuZF9zaXplOw0KPiArCV9fbGUzMiBtYXhfcmVjZWl2ZV9z aXplOw0KPiArCV9fbGUzMiBtYXhfZnJhZ21lbnRlZF9zaXplOw0KPiArfSBfX3BhY2tlZDsNCj4g Kw0KPiArLyogU01CRCBuZWdvdGlhdGlvbiByZXNwb25zZSBwYWNrZXQgW01TLVNNQkRdIDIuMi4y ICovDQo+ICtzdHJ1Y3Qgc21iZF9uZWdvdGlhdGVfcmVzcCB7DQo+ICsJX19sZTE2IG1pbl92ZXJz aW9uOw0KPiArCV9fbGUxNiBtYXhfdmVyc2lvbjsNCj4gKwlfX2xlMTYgbmVnb3RpYXRlZF92ZXJz aW9uOw0KPiArCV9fbGUxNiByZXNlcnZlZDsNCj4gKwlfX2xlMTYgY3JlZGl0c19yZXF1ZXN0ZWQ7 DQo+ICsJX19sZTE2IGNyZWRpdHNfZ3JhbnRlZDsNCj4gKwlfX2xlMzIgc3RhdHVzOw0KPiArCV9f bGUzMiBtYXhfcmVhZHdyaXRlX3NpemU7DQo+ICsJX19sZTMyIHByZWZlcnJlZF9zZW5kX3NpemU7 DQo+ICsJX19sZTMyIG1heF9yZWNlaXZlX3NpemU7DQo+ICsJX19sZTMyIG1heF9mcmFnbWVudGVk X3NpemU7DQo+ICt9IF9fcGFja2VkOw0KPiArDQo+ICsvKiBTTUJEIGRhdGEgdHJhbnNmZXIgcGFj a2V0IHdpdGggcGF5bG9hZCBbTVMtU01CRF0gMi4yLjMgKi8NCj4gK3N0cnVjdCBzbWJkX2RhdGFf dHJhbnNmZXIgew0KPiArCV9fbGUxNiBjcmVkaXRzX3JlcXVlc3RlZDsNCj4gKwlfX2xlMTYgY3Jl ZGl0c19ncmFudGVkOw0KPiArCV9fbGUxNiBmbGFnczsNCj4gKwlfX2xlMTYgcmVzZXJ2ZWQ7DQo+ ICsJX19sZTMyIHJlbWFpbmluZ19kYXRhX2xlbmd0aDsNCj4gKwlfX2xlMzIgZGF0YV9vZmZzZXQ7 DQo+ICsJX19sZTMyIGRhdGFfbGVuZ3RoOw0KPiArCV9fbGUzMiBwYWRkaW5nOw0KPiArCV9fdTgg YnVmZmVyW107DQo+ICt9IF9fcGFja2VkOw0KPiArDQo+ICsvKiBUaGUgcGFja2V0IGZpZWxkcyBm b3IgYSByZWdpc3RlcmVkIFJETUEgYnVmZmVyICovDQo+ICtzdHJ1Y3Qgc21iZF9idWZmZXJfZGVz Y3JpcHRvcl92MSB7DQo+ICsJX19sZTY0IG9mZnNldDsNCj4gKwlfX2xlMzIgdG9rZW47DQo+ICsJ X19sZTMyIGxlbmd0aDsNCj4gK30gX19wYWNrZWQ7DQo+ICsNCj4gIC8qIERlZmF1bHQgbWF4aW11 bSBudW1iZXIgb2YgU0dFcyBpbiBhIFJETUEgc2VuZC9yZWN2ICovDQo+ICAjZGVmaW5lIFNNQkRJ UkVDVF9NQVhfU0dFCTE2DQo+ICsvKiBUaGUgY29udGV4dCBmb3IgYSBTTUJEIHJlcXVlc3QgKi8N Cj4gK3N0cnVjdCBzbWJkX3JlcXVlc3Qgew0KPiArCXN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24gKmlu Zm87DQo+ICsJc3RydWN0IGliX2NxZSBjcWU7DQo+ICsNCj4gKwkvKiB0cnVlIGlmIHRoaXMgcmVx dWVzdCBjYXJyaWVzIHVwcGVyIGxheWVyIHBheWxvYWQgKi8NCj4gKwlib29sIGhhc19wYXlsb2Fk Ow0KPiArDQo+ICsJLyogdGhlIFNHRSBlbnRyaWVzIGZvciB0aGlzIHBhY2tldCAqLw0KPiArCXN0 cnVjdCBpYl9zZ2Ugc2dlW1NNQkRJUkVDVF9NQVhfU0dFXTsNCj4gKwlpbnQgbnVtX3NnZTsNCj4g Kw0KPiArCS8qIFNNQkQgcGFja2V0IGhlYWRlciBmb2xsb3dzIHRoaXMgc3RydWN0dXJlICovDQo+ ICsJdTggcGFja2V0W107DQo+ICt9Ow0KPiArDQo+ICsvKiBUaGUgY29udGV4dCBmb3IgYSBTTUJE IHJlc3BvbnNlICovDQo+ICtzdHJ1Y3Qgc21iZF9yZXNwb25zZSB7DQo+ICsJc3RydWN0IHNtYmRf Y29ubmVjdGlvbiAqaW5mbzsNCj4gKwlzdHJ1Y3QgaWJfY3FlIGNxZTsNCj4gKwlzdHJ1Y3QgaWJf c2dlIHNnZTsNCj4gKw0KPiArCWVudW0gc21iZF9tZXNzYWdlX3R5cGUgdHlwZTsNCj4gKw0KPiAr CS8qIExpbmsgdG8gcmVjZWl2ZSBxdWV1ZSBvciByZWFzc2VtYmx5IHF1ZXVlICovDQo+ICsJc3Ry dWN0IGxpc3RfaGVhZCBsaXN0Ow0KPiArDQo+ICsJLyogSW5kaWNhdGUgaWYgdGhpcyBpcyB0aGUg MXN0IHBhY2tldCBvZiBhIHBheWxvYWQgKi8NCj4gKwlib29sIGZpcnN0X3NlZ21lbnQ7DQo+ICsN Cj4gKwkvKiBTTUJEIHBhY2tldCBoZWFkZXIgYW5kIHBheWxvYWQgZm9sbG93cyB0aGlzIHN0cnVj dHVyZSAqLw0KPiArCXU4IHBhY2tldFtdOw0KPiArfTsNCj4gKw0KPiArLyogQ3JlYXRlIGEgU01C RGlyZWN0IHNlc3Npb24gKi8NCj4gK3N0cnVjdCBzbWJkX2Nvbm5lY3Rpb24gKnNtYmRfZ2V0X2Nv bm5lY3Rpb24oDQo+ICsJc3RydWN0IFRDUF9TZXJ2ZXJfSW5mbyAqc2VydmVyLCBzdHJ1Y3Qgc29j a2FkZHIgKmRzdGFkZHIpOw0KPiArDQo+ICsvKiBSZWNvbm5lY3QgU01CRGlyZWN0IHNlc3Npb24g Ki8NCj4gK2ludCBzbWJkX3JlY29ubmVjdChzdHJ1Y3QgVENQX1NlcnZlcl9JbmZvICpzZXJ2ZXIp Ow0KPiArDQo+ICsvKiBEZXN0cm95IFNNQkRpcmVjdCBzZXNzaW9uICovDQo+ICt2b2lkIHNtYmRf ZGVzdHJveShzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvKTsNCj4gKw0KPiArLyogSW50ZXJm YWNlIGZvciBjYXJyeWluZyB1cHBlciBsYXllciBJL08gdGhyb3VnaCBzZW5kL3JlY3YgKi8NCj4g K2ludCBzbWJkX3JlY3Yoc3RydWN0IHNtYmRfY29ubmVjdGlvbiAqaW5mbywgc3RydWN0IG1zZ2hk ciAqbXNnKTsNCj4gK2ludCBzbWJkX3NlbmQoc3RydWN0IHNtYmRfY29ubmVjdGlvbiAqaW5mbywg c3RydWN0IHNtYl9ycXN0ICpycXN0KTsNCj4gKw0KPiArZW51bSBtcl9zdGF0ZSB7DQo+ICsJTVJf UkVBRFksDQo+ICsJTVJfUkVHSVNURVJFRCwNCj4gKwlNUl9JTlZBTElEQVRFRCwNCj4gKwlNUl9F UlJPUg0KPiArfTsNCj4gKw0KPiArc3RydWN0IHNtYmRfbXIgew0KPiArCXN0cnVjdCBzbWJkX2Nv bm5lY3Rpb24JKmNvbm47DQo+ICsJc3RydWN0IGxpc3RfaGVhZAlsaXN0Ow0KPiArCWVudW0gbXJf c3RhdGUJCXN0YXRlOw0KPiArCXN0cnVjdCBpYl9tcgkJKm1yOw0KPiArCXN0cnVjdCBzY2F0dGVy bGlzdAkqc2dsOw0KPiArCWludAkJCXNnbF9jb3VudDsNCj4gKwllbnVtIGRtYV9kYXRhX2RpcmVj dGlvbglkaXI7DQo+ICsJdW5pb24gew0KPiArCQlzdHJ1Y3QgaWJfcmVnX3dyCXdyOw0KPiArCQlz dHJ1Y3QgaWJfc2VuZF93cglpbnZfd3I7DQo+ICsJfTsNCj4gKwlzdHJ1Y3QgaWJfY3FlCQljcWU7 DQo+ICsJYm9vbAkJCW5lZWRfaW52YWxpZGF0ZTsNCj4gKwlzdHJ1Y3QgY29tcGxldGlvbglpbnZh bGlkYXRlX2RvbmU7DQo+ICt9Ow0KPiArDQo+ICsvKiBJbnRlcmZhY2VzIHRvIHJlZ2lzdGVyIGFu ZCBkZXJlZ2lzdGVyIE1SIGZvciBSRE1BIHJlYWQvd3JpdGUgKi8NCj4gK3N0cnVjdCBzbWJkX21y ICpzbWJkX3JlZ2lzdGVyX21yKA0KPiArCXN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24gKmluZm8sIHN0 cnVjdCBwYWdlICpwYWdlc1tdLCBpbnQgbnVtX3BhZ2VzLA0KPiArCWludCB0YWlsc3osIGJvb2wg d3JpdGluZywgYm9vbCBuZWVkX2ludmFsaWRhdGUpOw0KPiAraW50IHNtYmRfZGVyZWdpc3Rlcl9t cihzdHJ1Y3Qgc21iZF9tciAqbXIpOw0KPiArDQo+ICsjZWxzZQ0KPiArI2RlZmluZSBjaWZzX3Jk bWFfZW5hYmxlZChzZXJ2ZXIpCTANCj4gK3N0cnVjdCBzbWJkX2Nvbm5lY3Rpb257fTsNCj4gK3N0 YXRpYyBpbmxpbmUgdm9pZCAqc21iZF9nZXRfY29ubmVjdGlvbigNCj4gKwlzdHJ1Y3QgVENQX1Nl cnZlcl9JbmZvICpzZXJ2ZXIsIHN0cnVjdCBzb2NrYWRkciAqZHN0YWRkcikge3JldHVybg0KPiBO VUxMO30NCj4gK3N0YXRpYyBpbmxpbmUgaW50IHNtYmRfcmVjb25uZWN0KHN0cnVjdCBUQ1BfU2Vy dmVyX0luZm8gKnNlcnZlcikge3JldHVybiAtDQo+IDE7fQ0KPiArc3RhdGljIGlubGluZSB2b2lk IHNtYmRfZGVzdHJveShzdHJ1Y3Qgc21iZF9jb25uZWN0aW9uICppbmZvKSB7fQ0KPiArc3RhdGlj IGlubGluZSBpbnQgc21iZF9yZWN2KHN0cnVjdCBzbWJkX2Nvbm5lY3Rpb24gKmluZm8sIHN0cnVj dCBtc2doZHINCj4gKm1zZykge3JldHVybiAtMTt9DQo+ICtzdGF0aWMgaW5saW5lIGludCBzbWJk X3NlbmQoc3RydWN0IHNtYmRfY29ubmVjdGlvbiAqaW5mbywgc3RydWN0IHNtYl9ycXN0DQo+ICpy cXN0KSB7cmV0dXJuIC0xO30NCj4gKyNlbmRpZg0KPiArDQo+ICAjZW5kaWYNCj4gLS0NCj4gMi43 LjQNCj4gDQo+IC0tDQo+IFRvIHVuc3Vic2NyaWJlIGZyb20gdGhpcyBsaXN0OiBzZW5kIHRoZSBs aW5lICJ1bnN1YnNjcmliZSBsaW51eC1jaWZzIiBpbg0KPiB0aGUgYm9keSBvZiBhIG1lc3NhZ2Ug dG8gbWFqb3Jkb21vQHZnZXIua2VybmVsLm9yZw0KPiBNb3JlIG1ham9yZG9tbyBpbmZvIGF0DQo+ IGh0dHBzOi8vbmEwMS5zYWZlbGlua3MucHJvdGVjdGlvbi5vdXRsb29rLmNvbS8/dXJsPWh0dHAl M0ElMkYlMkZ2Z2VyLmtlDQo+IHJuZWwub3JnJTJGbWFqb3Jkb21vLQ0KPiBpbmZvLmh0bWwmZGF0 YT0wMiU3QzAxJTdDbG9uZ2xpJTQwbWljcm9zb2Z0LmNvbSU3Q2U3ZGEzOWUzZmY4ZjQwOWVhDQo+ IDI5MjA4ZDUyZmRhMTdhNCU3QzcyZjk4OGJmODZmMTQxYWY5MWFiMmQ3Y2QwMTFkYjQ3JTdDMSU3 QzAlN0M2MzYNCj4gNDY3NTM2MTI0MDkxMjEyJnNkYXRhPWVSQ2lqdVhSMVklMkZzRmRzM1VaRHJk SzZBb0R1dEJCTENRMFVaVTV2DQo+IDVYQWMlM0QmcmVzZXJ2ZWQ9MA0K -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 5e853a3..ad00873 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile @@ -18,3 +18,5 @@ cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o + +cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c index d3c16f8..021d527 100644 --- a/fs/cifs/smbdirect.c +++ b/fs/cifs/smbdirect.c @@ -13,7 +13,34 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. */ +#include <linux/module.h> #include "smbdirect.h" +#include "cifs_debug.h" + +static struct smbd_response *get_empty_queue_buffer( + struct smbd_connection *info); +static struct smbd_response *get_receive_buffer( + struct smbd_connection *info); +static void put_receive_buffer( + struct smbd_connection *info, + struct smbd_response *response, + bool lock); +static int allocate_receive_buffers(struct smbd_connection *info, int num_buf); +static void destroy_receive_buffers(struct smbd_connection *info); + +static void put_empty_packet( + struct smbd_connection *info, struct smbd_response *response); +static void enqueue_reassembly( + struct smbd_connection *info, + struct smbd_response *response, int data_length); +static struct smbd_response *_get_first_reassembly( + struct smbd_connection *info); + +static int smbd_post_recv( + struct smbd_connection *info, + struct smbd_response *response); + +static int smbd_post_send_empty(struct smbd_connection *info); /* SMBD version number */ #define SMBD_V1 0x0100 @@ -75,3 +102,1552 @@ int smbd_max_frmr_depth = 2048; /* If payload is less than this byte, use RDMA send/recv not read/write */ int rdma_readwrite_threshold = 4096; + +/* Transport logging functions + * Logging are defined as classes. They can be OR'ed to define the actual + * logging level via module parameter smbd_logging_class + * e.g. cifs.smbd_logging_class=0x500 will log all log_rdma_recv() and + * log_rdma_event() + */ +#define LOG_OUTGOING 0x1 +#define LOG_INCOMING 0x2 +#define LOG_READ 0x4 +#define LOG_WRITE 0x8 +#define LOG_RDMA_SEND 0x10 +#define LOG_RDMA_RECV 0x20 +#define LOG_KEEP_ALIVE 0x40 +#define LOG_RDMA_EVENT 0x80 +#define LOG_RDMA_MR 0x100 +static unsigned int smbd_logging_class = 0; +module_param(smbd_logging_class, uint, 0644); +MODULE_PARM_DESC(smbd_logging_class, + "Logging class for SMBD transport 0x0 to 0x100"); + +#define ERR 0x0 +#define INFO 0x1 +static unsigned int smbd_logging_level = ERR; +module_param(smbd_logging_level, uint, 0644); +MODULE_PARM_DESC(smbd_logging_level, + "Logging level for SMBD transport, 0 (default): error, 1: info"); + +#define log_rdma(level, class, fmt, args...) \ +do { \ + if (level <= smbd_logging_level || class & smbd_logging_class) \ + cifs_dbg(VFS, "%s:%d " fmt, __func__, __LINE__, ##args);\ +} while (0) + +#define log_outgoing(level, fmt, args...) \ + log_rdma(level, LOG_OUTGOING, fmt, ##args) +#define log_incoming(level, fmt, args...) \ + log_rdma(level, LOG_INCOMING, fmt, ##args) +#define log_read(level, fmt, args...) log_rdma(level, LOG_READ, fmt, ##args) +#define log_write(level, fmt, args...) log_rdma(level, LOG_WRITE, fmt, ##args) +#define log_rdma_send(level, fmt, args...) \ + log_rdma(level, LOG_RDMA_SEND, fmt, ##args) +#define log_rdma_recv(level, fmt, args...) \ + log_rdma(level, LOG_RDMA_RECV, fmt, ##args) +#define log_keep_alive(level, fmt, args...) \ + log_rdma(level, LOG_KEEP_ALIVE, fmt, ##args) +#define log_rdma_event(level, fmt, args...) \ + log_rdma(level, LOG_RDMA_EVENT, fmt, ##args) +#define log_rdma_mr(level, fmt, args...) \ + log_rdma(level, LOG_RDMA_MR, fmt, ##args) + +/* + * Destroy the transport and related RDMA and memory resources + * Need to go through all the pending counters and make sure on one is using + * the transport while it is destroyed + */ +static void smbd_destroy_rdma_work(struct work_struct *work) +{ + struct smbd_response *response; + struct smbd_connection *info = + container_of(work, struct smbd_connection, destroy_work); + unsigned long flags; + + log_rdma_event(INFO, "destroying qp\n"); + ib_drain_qp(info->id->qp); + rdma_destroy_qp(info->id); + + /* Unblock all I/O waiting on the send queue */ + wake_up_interruptible_all(&info->wait_send_queue); + + log_rdma_event(INFO, "cancelling idle timer\n"); + cancel_delayed_work_sync(&info->idle_timer_work); + log_rdma_event(INFO, "cancelling send immediate work\n"); + cancel_delayed_work_sync(&info->send_immediate_work); + + log_rdma_event(INFO, "wait for all recv to finish\n"); + wake_up_interruptible(&info->wait_reassembly_queue); + + log_rdma_event(INFO, "wait for all send posted to IB to finish\n"); + wait_event(info->wait_send_pending, + atomic_read(&info->send_pending) == 0); + wait_event(info->wait_send_payload_pending, + atomic_read(&info->send_payload_pending) == 0); + + /* It's not posssible for upper layer to get to reassembly */ + log_rdma_event(INFO, "drain the reassembly queue\n"); + do { + spin_lock_irqsave(&info->reassembly_queue_lock, flags); + response = _get_first_reassembly(info); + if (response) { + list_del(&response->list); + spin_unlock_irqrestore( + &info->reassembly_queue_lock, flags); + put_receive_buffer(info, response, true); + } + } while (response); + spin_unlock_irqrestore(&info->reassembly_queue_lock, flags); + info->reassembly_data_length = 0; + + log_rdma_event(INFO, "free receive buffers\n"); + wait_event(info->wait_receive_queues, + info->count_receive_queue + info->count_empty_packet_queue + == info->receive_credit_max); + destroy_receive_buffers(info); + + ib_free_cq(info->send_cq); + ib_free_cq(info->recv_cq); + ib_dealloc_pd(info->pd); + rdma_destroy_id(info->id); + + /* free mempools */ + mempool_destroy(info->request_mempool); + kmem_cache_destroy(info->request_cache); + + mempool_destroy(info->response_mempool); + kmem_cache_destroy(info->response_cache); + + info->transport_status = SMBD_DESTROYED; + wake_up_all(&info->wait_destroy); +} + +static int smbd_process_disconnected(struct smbd_connection *info) +{ +// queue_work(info->workqueue, &info->destroy_work); + schedule_work(&info->destroy_work); + return 0; +} + +static void smbd_disconnect_rdma_work(struct work_struct *work) +{ + struct smbd_connection *info = + container_of(work, struct smbd_connection, disconnect_work); + + if (info->transport_status == SMBD_CONNECTED) { + info->transport_status = SMBD_DISCONNECTING; + rdma_disconnect(info->id); + } +} + +static void smbd_disconnect_rdma_connection(struct smbd_connection *info) +{ + queue_work(info->workqueue, &info->disconnect_work); +} + +/* Upcall from RDMA CM */ +static int smbd_conn_upcall( + struct rdma_cm_id *id, struct rdma_cm_event *event) +{ + struct smbd_connection *info = id->context; + + log_rdma_event(INFO, "event=%d status=%d\n", + event->event, event->status); + + switch (event->event) { + case RDMA_CM_EVENT_ADDR_RESOLVED: + case RDMA_CM_EVENT_ROUTE_RESOLVED: + info->ri_rc = 0; + complete(&info->ri_done); + break; + + case RDMA_CM_EVENT_ADDR_ERROR: + info->ri_rc = -EHOSTUNREACH; + complete(&info->ri_done); + break; + + case RDMA_CM_EVENT_ROUTE_ERROR: + info->ri_rc = -ENETUNREACH; + complete(&info->ri_done); + break; + + case RDMA_CM_EVENT_ESTABLISHED: + log_rdma_event(INFO, "connected event=%d\n", event->event); + info->transport_status = SMBD_CONNECTED; + wake_up_interruptible(&info->conn_wait); + break; + + case RDMA_CM_EVENT_CONNECT_ERROR: + case RDMA_CM_EVENT_UNREACHABLE: + case RDMA_CM_EVENT_REJECTED: + log_rdma_event(INFO, "connecting failed event=%d\n", event->event); + info->transport_status = SMBD_DISCONNECTED; + wake_up_interruptible(&info->conn_wait); + break; + + case RDMA_CM_EVENT_DEVICE_REMOVAL: + case RDMA_CM_EVENT_DISCONNECTED: + /* This happenes when we fail the negotiation */ + if (info->transport_status == SMBD_NEGOTIATE_FAILED) { + info->transport_status = SMBD_DISCONNECTED; + wake_up(&info->conn_wait); + break; + } + + info->transport_status = SMBD_DISCONNECTED; + smbd_process_disconnected(info); + break; + + default: + break; + } + + return 0; +} + +/* Upcall from RDMA QP */ +static void +smbd_qp_async_error_upcall(struct ib_event *event, void *context) +{ + struct smbd_connection *info = context; + + log_rdma_event(ERR, "%s on device %s info %p\n", + ib_event_msg(event->event), event->device->name, info); + + switch (event->event) { + case IB_EVENT_CQ_ERR: + case IB_EVENT_QP_FATAL: + smbd_disconnect_rdma_connection(info); + + default: + break; + } +} + +static inline void *smbd_request_payload(struct smbd_request *request) +{ + return (void *)request->packet; +} + +static inline void *smbd_response_payload(struct smbd_response *response) +{ + return (void *)response->packet; +} + +/* Called when a RDMA send is done */ +static void send_done(struct ib_cq *cq, struct ib_wc *wc) +{ + int i; + struct smbd_request *request = + container_of(wc->wr_cqe, struct smbd_request, cqe); + + log_rdma_send(INFO, "smbd_request %p completed wc->status=%d\n", + request, wc->status); + + if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) { + log_rdma_send(ERR, "wc->status=%d wc->opcode=%d\n", + wc->status, wc->opcode); + smbd_disconnect_rdma_connection(request->info); + } + + for (i = 0; i < request->num_sge; i++) + ib_dma_unmap_single(request->info->id->device, + request->sge[i].addr, + request->sge[i].length, + DMA_TO_DEVICE); + + if (request->has_payload) { + if (atomic_dec_and_test(&request->info->send_payload_pending)) + wake_up(&request->info->wait_send_payload_pending); + } else { + if (atomic_dec_and_test(&request->info->send_pending)) + wake_up(&request->info->wait_send_pending); + } + + mempool_free(request, request->info->request_mempool); +} + +static void dump_smbd_negotiate_resp(struct smbd_negotiate_resp *resp) +{ + log_rdma_event(INFO, "resp message min_version %u max_version %u " + "negotiated_version %u credits_requested %u " + "credits_granted %u status %u max_readwrite_size %u " + "preferred_send_size %u max_receive_size %u " + "max_fragmented_size %u\n", + resp->min_version, resp->max_version, resp->negotiated_version, + resp->credits_requested, resp->credits_granted, resp->status, + resp->max_readwrite_size, resp->preferred_send_size, + resp->max_receive_size, resp->max_fragmented_size); +} + +/* + * Process a negotiation response message, according to [MS-SMBD]3.1.5.7 + * response, packet_length: the negotiation response message + * return value: true if negotiation is a success, false if failed + */ +static bool process_negotiation_response( + struct smbd_response *response, int packet_length) +{ + struct smbd_connection *info = response->info; + struct smbd_negotiate_resp *packet = smbd_response_payload(response); + + if (packet_length < sizeof(struct smbd_negotiate_resp)) { + log_rdma_event(ERR, + "error: packet_length=%d\n", packet_length); + return false; + } + + if (le16_to_cpu(packet->negotiated_version) != SMBD_V1) { + log_rdma_event(ERR, "error: negotiated_version=%x\n", + le16_to_cpu(packet->negotiated_version)); + return false; + } + info->protocol = le16_to_cpu(packet->negotiated_version); + + if (packet->credits_requested == 0) { + log_rdma_event(ERR, "error: credits_requested==0\n"); + return false; + } + info->receive_credit_target = le16_to_cpu(packet->credits_requested); + + if (packet->credits_granted == 0) { + log_rdma_event(ERR, "error: credits_granted==0\n"); + return false; + } + atomic_set(&info->send_credits, le16_to_cpu(packet->credits_granted)); + + atomic_set(&info->receive_credits, 0); + + if (le32_to_cpu(packet->preferred_send_size) > info->max_receive_size) { + log_rdma_event(ERR, "error: preferred_send_size=%d\n", + le32_to_cpu(packet->preferred_send_size)); + return false; + } + info->max_receive_size = le32_to_cpu(packet->preferred_send_size); + + if (le32_to_cpu(packet->max_receive_size) < SMBD_MIN_RECEIVE_SIZE) { + log_rdma_event(ERR, "error: max_receive_size=%d\n", + le32_to_cpu(packet->max_receive_size)); + return false; + } + info->max_send_size = min_t(int, info->max_send_size, + le32_to_cpu(packet->max_receive_size)); + + if (le32_to_cpu(packet->max_fragmented_size) < + SMBD_MIN_FRAGMENTED_SIZE) { + log_rdma_event(ERR, "error: max_fragmented_size=%d\n", + le32_to_cpu(packet->max_fragmented_size)); + return false; + } + info->max_fragmented_send_size = + le32_to_cpu(packet->max_fragmented_size); + + return true; +} + +/* + * Check and schedule to send an immediate packet + * This is used to extend credtis to remote peer to keep the transport busy + */ +static void check_and_send_immediate(struct smbd_connection *info) +{ + if (info->transport_status != SMBD_CONNECTED) + return; + + info->send_immediate = true; + + /* + * Promptly send a packet if our peer is running low on receive + * credits + */ + if (atomic_read(&info->receive_credits) < + info->receive_credit_target - 1) + queue_delayed_work( + info->workqueue, &info->send_immediate_work, 0); +} + +static void smbd_post_send_credits(struct work_struct *work) +{ + int ret = 0; + int use_receive_queue = 1; + int rc; + struct smbd_response *response; + struct smbd_connection *info = + container_of(work, struct smbd_connection, + post_send_credits_work); + + if (info->transport_status != SMBD_CONNECTED) { + wake_up(&info->wait_receive_queues); + return; + } + + if (info->receive_credit_target > + atomic_read(&info->receive_credits)) { + while (true) { + if (use_receive_queue) + response = get_receive_buffer(info); + else + response = get_empty_queue_buffer(info); + if (!response) { + /* now switch to emtpy packet queue */ + if (use_receive_queue) { + use_receive_queue = 0; + continue; + } else + break; + } + + response->type = SMBD_TRANSFER_DATA; + response->first_segment = false; + rc = smbd_post_recv(info, response); + if (rc) { + log_rdma_recv(ERR, + "post_recv failed rc=%d\n", rc); + put_receive_buffer(info, response, true); + break; + } + + ret++; + } + } + + spin_lock(&info->lock_new_credits_offered); + info->new_credits_offered += ret; + spin_unlock(&info->lock_new_credits_offered); + + atomic_add(ret, &info->receive_credits); + + /* Check if we can post new receive and grant credits to peer */ + check_and_send_immediate(info); +} + +static void smbd_recv_done_work(struct work_struct *work) +{ + struct smbd_connection *info = + container_of(work, struct smbd_connection, recv_done_work); + + /* + * We may have new send credits granted from remote peer + * If any sender is blcoked on lack of credets, unblock it + */ + if (atomic_read(&info->send_credits)) + wake_up_interruptible(&info->wait_send_queue); + + /* + * Check if we need to send something to remote peer to + * grant more credits or respond to KEEP_ALIVE packet + */ + check_and_send_immediate(info); +} + +/* Called from softirq, when recv is done */ +static void recv_done(struct ib_cq *cq, struct ib_wc *wc) +{ + struct smbd_data_transfer *data_transfer; + struct smbd_response *response = + container_of(wc->wr_cqe, struct smbd_response, cqe); + struct smbd_connection *info = response->info; + int data_length = 0; + + log_rdma_recv(INFO, "response=%p type=%d wc status=%d wc opcode %d " + "byte_len=%d pkey_index=%x\n", + response, response->type, wc->status, wc->opcode, + wc->byte_len, wc->pkey_index); + + if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) { + log_rdma_recv(INFO, "wc->status=%d opcode=%d\n", + wc->status, wc->opcode); + smbd_disconnect_rdma_connection(info); + goto error; + } + + ib_dma_sync_single_for_cpu( + wc->qp->device, + response->sge.addr, + response->sge.length, + DMA_FROM_DEVICE); + + switch (response->type) { + /* SMBD negotiation response */ + case SMBD_NEGOTIATE_RESP: + dump_smbd_negotiate_resp(smbd_response_payload(response)); + info->full_packet_received = true; + info->negotiate_done = + process_negotiation_response(response, wc->byte_len); + complete(&info->negotiate_completion); + break; + + /* SMBD data transfer packet */ + case SMBD_TRANSFER_DATA: + data_transfer = smbd_response_payload(response); + data_length = le32_to_cpu(data_transfer->data_length); + + /* + * If this is a packet with data playload place the data in + * reassembly queue and wake up the reading thread + */ + if (data_length) { + if (info->full_packet_received) + response->first_segment = true; + + if (le32_to_cpu(data_transfer->remaining_data_length)) + info->full_packet_received = false; + else + info->full_packet_received = true; + + enqueue_reassembly( + info, + response, + data_length); + } else + put_empty_packet(info, response); + + if (data_length) + wake_up_interruptible(&info->wait_reassembly_queue); + + atomic_dec(&info->receive_credits); + info->receive_credit_target = + le16_to_cpu(data_transfer->credits_requested); + atomic_add(le16_to_cpu(data_transfer->credits_granted), + &info->send_credits); + + log_incoming(INFO, "data flags %d data_offset %d " + "data_length %d remaining_data_length %d\n", + le16_to_cpu(data_transfer->flags), + le32_to_cpu(data_transfer->data_offset), + le32_to_cpu(data_transfer->data_length), + le32_to_cpu(data_transfer->remaining_data_length)); + + /* Send a KEEP_ALIVE response right away if requested */ + info->keep_alive_requested = KEEP_ALIVE_NONE; + if (le16_to_cpu(data_transfer->flags) & + SMB_DIRECT_RESPONSE_REQUESTED) { + info->keep_alive_requested = KEEP_ALIVE_PENDING; + } + + queue_work(info->workqueue, &info->recv_done_work); + return; + + default: + log_rdma_recv(ERR, + "unexpected response type=%d\n", response->type); + } + +error: + put_receive_buffer(info, response, true); +} + +static struct rdma_cm_id *smbd_create_id( + struct smbd_connection *info, + struct sockaddr *dstaddr, int port) +{ + struct rdma_cm_id *id; + int rc; + __be16 *sport; + + id = rdma_create_id(&init_net, smbd_conn_upcall, info, + RDMA_PS_TCP, IB_QPT_RC); + if (IS_ERR(id)) { + rc = PTR_ERR(id); + log_rdma_event(ERR, "rdma_create_id() failed %i\n", rc); + return id; + } + + if (dstaddr->sa_family == AF_INET6) + sport = &((struct sockaddr_in6 *)dstaddr)->sin6_port; + else + sport = &((struct sockaddr_in *)dstaddr)->sin_port; + + *sport = htons(port); + + init_completion(&info->ri_done); + info->ri_rc = -ETIMEDOUT; + + rc = rdma_resolve_addr(id, NULL, (struct sockaddr *)dstaddr, + RDMA_RESOLVE_TIMEOUT); + if (rc) { + log_rdma_event(ERR, "rdma_resolve_addr() failed %i\n", rc); + goto out; + } + wait_for_completion_interruptible_timeout( + &info->ri_done, msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT)); + rc = info->ri_rc; + if (rc) { + log_rdma_event(ERR, "rdma_resolve_addr() completed %i\n", rc); + goto out; + } + + info->ri_rc = -ETIMEDOUT; + rc = rdma_resolve_route(id, RDMA_RESOLVE_TIMEOUT); + if (rc) { + log_rdma_event(ERR, "rdma_resolve_route() failed %i\n", rc); + goto out; + } + wait_for_completion_interruptible_timeout( + &info->ri_done, msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT)); + rc = info->ri_rc; + if (rc) { + log_rdma_event(ERR, "rdma_resolve_route() completed %i\n", rc); + goto out; + } + + return id; + +out: + rdma_destroy_id(id); + return ERR_PTR(rc); +} + +/* + * Test if FRWR (Fast Registration Work Requests) is supported on the device + * This implementation requries FRWR on RDMA read/write + * return value: true if it is supported + */ +static bool frwr_is_supported(struct ib_device_attr *attrs) +{ + if (!(attrs->device_cap_flags & IB_DEVICE_MEM_MGT_EXTENSIONS)) + return false; + if (attrs->max_fast_reg_page_list_len == 0) + return false; + return true; +} + +static int smbd_ia_open( + struct smbd_connection *info, + struct sockaddr *dstaddr, int port) +{ + int rc; + + info->id = smbd_create_id(info, dstaddr, port); + if (IS_ERR(info->id)) { + rc = PTR_ERR(info->id); + goto out1; + } + + if (!frwr_is_supported(&info->id->device->attrs)) { + log_rdma_event(ERR, + "Fast Registration Work Requests " + "(FRWR) is not supported\n"); + log_rdma_event(ERR, + "Device capability flags = %llx " + "max_fast_reg_page_list_len = %u\n", + info->id->device->attrs.device_cap_flags, + info->id->device->attrs.max_fast_reg_page_list_len); + rc = -EPROTONOSUPPORT; + goto out2; + } + + info->pd = ib_alloc_pd(info->id->device, 0); + if (IS_ERR(info->pd)) { + rc = PTR_ERR(info->pd); + log_rdma_event(ERR, "ib_alloc_pd() returned %d\n", rc); + goto out2; + } + + return 0; + +out2: + rdma_destroy_id(info->id); + info->id = NULL; + +out1: + return rc; +} + +/* + * Send a negotiation request message to the peer + * The negotiation procedure is in [MS-SMBD] 3.1.5.2 and 3.1.5.3 + * After negotiation, the transport is connected and ready for + * carrying upper layer SMB payload + */ +static int smbd_post_send_negotiate_req(struct smbd_connection *info) +{ + struct ib_send_wr send_wr, *send_wr_fail; + int rc = -ENOMEM; + struct smbd_request *request; + struct smbd_negotiate_req *packet; + + request = mempool_alloc(info->request_mempool, GFP_KERNEL); + if (!request) + return rc; + + request->info = info; + + packet = smbd_request_payload(request); + packet->min_version = cpu_to_le16(SMBD_V1); + packet->max_version = cpu_to_le16(SMBD_V1); + packet->reserved = 0; + packet->credits_requested = cpu_to_le16(info->send_credit_target); + packet->preferred_send_size = cpu_to_le32(info->max_send_size); + packet->max_receive_size = cpu_to_le32(info->max_receive_size); + packet->max_fragmented_size = + cpu_to_le32(info->max_fragmented_recv_size); + + request->num_sge = 1; + request->sge[0].addr = ib_dma_map_single( + info->id->device, (void *)packet, + sizeof(*packet), DMA_TO_DEVICE); + if (ib_dma_mapping_error(info->id->device, request->sge[0].addr)) { + rc = -EIO; + goto dma_mapping_failed; + } + + request->sge[0].length = sizeof(*packet); + request->sge[0].lkey = info->pd->local_dma_lkey; + + ib_dma_sync_single_for_device( + info->id->device, request->sge[0].addr, + request->sge[0].length, DMA_TO_DEVICE); + + request->cqe.done = send_done; + + send_wr.next = NULL; + send_wr.wr_cqe = &request->cqe; + send_wr.sg_list = request->sge; + send_wr.num_sge = request->num_sge; + send_wr.opcode = IB_WR_SEND; + send_wr.send_flags = IB_SEND_SIGNALED; + + log_rdma_send(INFO, "sge addr=%llx length=%x lkey=%x\n", + request->sge[0].addr, + request->sge[0].length, request->sge[0].lkey); + + request->has_payload = false; + atomic_inc(&info->send_pending); + rc = ib_post_send(info->id->qp, &send_wr, &send_wr_fail); + if (!rc) + return 0; + + /* if we reach here, post send failed */ + log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc); + atomic_dec(&info->send_pending); + ib_dma_unmap_single(info->id->device, request->sge[0].addr, + request->sge[0].length, DMA_TO_DEVICE); + +dma_mapping_failed: + mempool_free(request, info->request_mempool); + return rc; +} + +/* + * Extend the credits to remote peer + * This implements [MS-SMBD] 3.1.5.9 + * The idea is that we should extend credits to remote peer as quickly as + * it's allowed, to maintain data flow. We allocate as much receive + * buffer as possible, and extend the receive credits to remote peer + * return value: the new credtis being granted. + */ +static int manage_credits_prior_sending(struct smbd_connection *info) +{ + int new_credits; + + spin_lock(&info->lock_new_credits_offered); + new_credits = info->new_credits_offered; + info->new_credits_offered = 0; + spin_unlock(&info->lock_new_credits_offered); + + return new_credits; +} + +/* + * Check if we need to send a KEEP_ALIVE message + * The idle connection timer triggers a KEEP_ALIVE message when expires + * SMB_DIRECT_RESPONSE_REQUESTED is set in the message flag to have peer send + * back a response. + * return value: + * 1 if SMB_DIRECT_RESPONSE_REQUESTED needs to be set + * 0: otherwise + */ +static int manage_keep_alive_before_sending(struct smbd_connection *info) +{ + if (info->keep_alive_requested == KEEP_ALIVE_PENDING) { + info->keep_alive_requested = KEEP_ALIVE_SENT; + return 1; + } + return 0; +} + +/* + * Build and prepare the SMBD packet header + * This function waits for avaialbe send credits and build a SMBD packet + * header. The caller then optional append payload to the packet after + * the header + * intput values + * size: the size of the payload + * remaining_data_length: remaining data to send if this is part of a + * fragmented packet + * output values + * request_out: the request allocated from this function + * return values: 0 on success, otherwise actual error code returned + */ +static int smbd_create_header(struct smbd_connection *info, + int size, int remaining_data_length, + struct smbd_request **request_out) +{ + struct smbd_request *request; + struct smbd_data_transfer *packet; + int header_length; + int rc; + + /* Wait for send credits. A SMBD packet needs one credit */ + rc = wait_event_interruptible(info->wait_send_queue, + atomic_read(&info->send_credits) > 0 || + info->transport_status != SMBD_CONNECTED); + if (rc) + return rc; + + if (info->transport_status != SMBD_CONNECTED) { + log_outgoing(ERR, "disconnected not sending\n"); + return -ENOENT; + } + atomic_dec(&info->send_credits); + + request = mempool_alloc(info->request_mempool, GFP_KERNEL); + if (!request) { + rc = -ENOMEM; + goto err; + } + + request->info = info; + + /* Fill in the packet header */ + packet = smbd_request_payload(request); + packet->credits_requested = cpu_to_le16(info->send_credit_target); + packet->credits_granted = + cpu_to_le16(manage_credits_prior_sending(info)); + info->send_immediate = false; + + packet->flags = 0; + if (manage_keep_alive_before_sending(info)) + packet->flags |= cpu_to_le16(SMB_DIRECT_RESPONSE_REQUESTED); + + packet->reserved = 0; + if (!size) + packet->data_offset = 0; + else + packet->data_offset = cpu_to_le32(24); + packet->data_length = cpu_to_le32(size); + packet->remaining_data_length = cpu_to_le32(remaining_data_length); + packet->padding = 0; + + log_outgoing(INFO, "credits_requested=%d credits_granted=%d " + "data_offset=%d data_length=%d remaining_data_length=%d\n", + le16_to_cpu(packet->credits_requested), + le16_to_cpu(packet->credits_granted), + le32_to_cpu(packet->data_offset), + le32_to_cpu(packet->data_length), + le32_to_cpu(packet->remaining_data_length)); + + /* Map the packet to DMA */ + header_length = sizeof(struct smbd_data_transfer); + /* If this is a packet without payload, don't send padding */ + if (!size) + header_length = offsetof(struct smbd_data_transfer, padding); + + request->num_sge = 1; + request->sge[0].addr = ib_dma_map_single(info->id->device, + (void *)packet, + header_length, + DMA_BIDIRECTIONAL); + if (ib_dma_mapping_error(info->id->device, request->sge[0].addr)) { + mempool_free(request, info->request_mempool); + rc = -EIO; + goto err; + } + + request->sge[0].length = header_length; + request->sge[0].lkey = info->pd->local_dma_lkey; + + *request_out = request; + return 0; + +err: + atomic_inc(&info->send_credits); + return rc; +} + +static void smbd_destroy_header(struct smbd_connection *info, + struct smbd_request *request) +{ + + ib_dma_unmap_single(info->id->device, + request->sge[0].addr, + request->sge[0].length, + DMA_TO_DEVICE); + mempool_free(request, info->request_mempool); + atomic_inc(&info->send_credits); +} + +/* Post the send request */ +static int smbd_post_send(struct smbd_connection *info, + struct smbd_request *request, bool has_payload) +{ + struct ib_send_wr send_wr, *send_wr_fail; + int rc, i; + + for (i = 0; i < request->num_sge; i++) { + log_rdma_send(INFO, + "rdma_request sge[%d] addr=%llu legnth=%u\n", + i, request->sge[0].addr, request->sge[0].length); + ib_dma_sync_single_for_device( + info->id->device, + request->sge[i].addr, + request->sge[i].length, + DMA_TO_DEVICE); + } + + request->cqe.done = send_done; + + send_wr.next = NULL; + send_wr.wr_cqe = &request->cqe; + send_wr.sg_list = request->sge; + send_wr.num_sge = request->num_sge; + send_wr.opcode = IB_WR_SEND; + send_wr.send_flags = IB_SEND_SIGNALED; + + if (has_payload) { + request->has_payload = true; + atomic_inc(&info->send_payload_pending); + } else { + request->has_payload = false; + atomic_inc(&info->send_pending); + } + + rc = ib_post_send(info->id->qp, &send_wr, &send_wr_fail); + if (rc) { + log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc); + if (has_payload) { + if (atomic_dec_and_test(&info->send_payload_pending)) + wake_up(&info->wait_send_payload_pending); + } else { + if (atomic_dec_and_test(&info->send_pending)) + wake_up(&info->wait_send_pending); + } + } else + /* Reset timer for idle connection after packet is sent */ + mod_delayed_work(info->workqueue, &info->idle_timer_work, + info->keep_alive_interval*HZ); + + return rc; +} + +static int smbd_post_send_sgl(struct smbd_connection *info, + struct scatterlist *sgl, int data_length, int remaining_data_length) +{ + int num_sgs; + int i, rc; + struct smbd_request *request; + struct scatterlist *sg; + + rc = smbd_create_header( + info, data_length, remaining_data_length, &request); + if (rc) + return rc; + + num_sgs = sgl ? sg_nents(sgl) : 0; + for_each_sg(sgl, sg, num_sgs, i) { + request->sge[i+1].addr = + ib_dma_map_page(info->id->device, sg_page(sg), + sg->offset, sg->length, DMA_BIDIRECTIONAL); + if (ib_dma_mapping_error( + info->id->device, request->sge[i+1].addr)) { + rc = -EIO; + request->sge[i+1].addr = 0; + goto dma_mapping_failure; + } + request->sge[i+1].length = sg->length; + request->sge[i+1].lkey = info->pd->local_dma_lkey; + request->num_sge++; + } + + rc = smbd_post_send(info, request, data_length); + if (!rc) + return 0; + +dma_mapping_failure: + for (i = 1; i < request->num_sge; i++) + if (request->sge[i].addr) + ib_dma_unmap_single(info->id->device, + request->sge[i].addr, + request->sge[i].length, + DMA_TO_DEVICE); + smbd_destroy_header(info, request); + return rc; +} + +/* + * Send an empty message + * Empty message is used to extend credits to peer to for keep live + * while there is no upper layer payload to send at the time + */ +static int smbd_post_send_empty(struct smbd_connection *info) +{ + info->count_send_empty++; + return smbd_post_send_sgl(info, NULL, 0, 0); +} + +/* + * Post a receive request to the transport + * The remote peer can only send data when a receive request is posted + * The interaction is controlled by send/receive credit system + */ +static int smbd_post_recv( + struct smbd_connection *info, struct smbd_response *response) +{ + struct ib_recv_wr recv_wr, *recv_wr_fail = NULL; + int rc = -EIO; + + response->sge.addr = ib_dma_map_single( + info->id->device, response->packet, + info->max_receive_size, DMA_FROM_DEVICE); + if (ib_dma_mapping_error(info->id->device, response->sge.addr)) + return rc; + + response->sge.length = info->max_receive_size; + response->sge.lkey = info->pd->local_dma_lkey; + + response->cqe.done = recv_done; + + recv_wr.wr_cqe = &response->cqe; + recv_wr.next = NULL; + recv_wr.sg_list = &response->sge; + recv_wr.num_sge = 1; + + rc = ib_post_recv(info->id->qp, &recv_wr, &recv_wr_fail); + if (rc) { + ib_dma_unmap_single(info->id->device, response->sge.addr, + response->sge.length, DMA_FROM_DEVICE); + + log_rdma_recv(ERR, "ib_post_recv failed rc=%d\n", rc); + } + + return rc; +} + +/* Perform SMBD negotiate according to [MS-SMBD] 3.1.5.2 */ +static int smbd_negotiate(struct smbd_connection *info) +{ + int rc; + struct smbd_response *response = get_receive_buffer(info); + + response->type = SMBD_NEGOTIATE_RESP; + rc = smbd_post_recv(info, response); + log_rdma_event(INFO, + "smbd_post_recv rc=%d iov.addr=%llx iov.length=%x " + "iov.lkey=%x\n", + rc, response->sge.addr, + response->sge.length, response->sge.lkey); + if (rc) + return rc; + + init_completion(&info->negotiate_completion); + info->negotiate_done = false; + rc = smbd_post_send_negotiate_req(info); + if (rc) + return rc; + + rc = wait_for_completion_interruptible_timeout( + &info->negotiate_completion, SMBD_NEGOTIATE_TIMEOUT * HZ); + log_rdma_event(INFO, "wait_for_completion_timeout rc=%d\n", rc); + + if (info->negotiate_done) + return 0; + + if (rc == 0) + rc = -ETIMEDOUT; + else if (rc == -ERESTARTSYS) + rc = -EINTR; + else + rc = -ENOTCONN; + + return rc; +} + +static void put_empty_packet( + struct smbd_connection *info, struct smbd_response *response) +{ + spin_lock(&info->empty_packet_queue_lock); + list_add_tail(&response->list, &info->empty_packet_queue); + info->count_empty_packet_queue++; + spin_unlock(&info->empty_packet_queue_lock); + + queue_work(info->workqueue, &info->post_send_credits_work); +} + +/* + * Implement Connection.FragmentReassemblyBuffer defined in [MS-SMBD] 3.1.1.1 + * This is a queue for reassembling upper layer payload and present to upper + * layer. All the inncoming payload go to the reassembly queue, regardless of + * if reassembly is required. The uuper layer code reads from the queue for all + * incoming payloads. + * Put a received packet to the reassembly queue + * response: the packet received + * data_length: the size of payload in this packet + */ +static void enqueue_reassembly( + struct smbd_connection *info, + struct smbd_response *response, + int data_length) +{ + spin_lock(&info->reassembly_queue_lock); + list_add_tail(&response->list, &info->reassembly_queue); + info->reassembly_queue_length++; + /* + * Make sure reassembly_data_length is updated after list and + * reassembly_queue_length are updated. On the dequeue side + * reassembly_data_length is checked without a lock to determine + * if reassembly_queue_length and list is up to date + */ + virt_wmb(); + info->reassembly_data_length += data_length; + spin_unlock(&info->reassembly_queue_lock); + info->count_reassembly_queue++; + info->count_enqueue_reassembly_queue++; +} + +/* + * Get the first entry at the front of reassembly queue + * Caller is responsible for locking + * return value: the first entry if any, NULL if queue is empty + */ +static struct smbd_response *_get_first_reassembly(struct smbd_connection *info) +{ + struct smbd_response *ret = NULL; + + if (!list_empty(&info->reassembly_queue)) { + ret = list_first_entry( + &info->reassembly_queue, + struct smbd_response, list); + } + return ret; +} + +static struct smbd_response *get_empty_queue_buffer( + struct smbd_connection *info) +{ + struct smbd_response *ret = NULL; + unsigned long flags; + + spin_lock_irqsave(&info->empty_packet_queue_lock, flags); + if (!list_empty(&info->empty_packet_queue)) { + ret = list_first_entry( + &info->empty_packet_queue, + struct smbd_response, list); + list_del(&ret->list); + info->count_empty_packet_queue--; + } + spin_unlock_irqrestore(&info->empty_packet_queue_lock, flags); + + return ret; +} + +/* + * Get a receive buffer + * For each remote send, we need to post a receive. The receive buffers are + * pre-allocated in advance. + * return value: the receive buffer, NULL if none is available + */ +static struct smbd_response *get_receive_buffer(struct smbd_connection *info) +{ + struct smbd_response *ret = NULL; + unsigned long flags; + + spin_lock_irqsave(&info->receive_queue_lock, flags); + if (!list_empty(&info->receive_queue)) { + ret = list_first_entry( + &info->receive_queue, + struct smbd_response, list); + list_del(&ret->list); + info->count_receive_queue--; + info->count_get_receive_buffer++; + } + spin_unlock_irqrestore(&info->receive_queue_lock, flags); + + return ret; +} + +/* + * Return a receive buffer + * Upon returning of a receive buffer, we can post new receive and extend + * more receive credits to remote peer. This is done immediately after a + * receive buffer is returned. + */ +static void put_receive_buffer( + struct smbd_connection *info, struct smbd_response *response, + bool lock) +{ + unsigned long flags; + + ib_dma_unmap_single(info->id->device, response->sge.addr, + response->sge.length, DMA_FROM_DEVICE); + + if (lock) + spin_lock_irqsave(&info->receive_queue_lock, flags); + list_add_tail(&response->list, &info->receive_queue); + info->count_receive_queue++; + info->count_put_receive_buffer++; + if (lock) + spin_unlock_irqrestore(&info->receive_queue_lock, flags); + + queue_work(info->workqueue, &info->post_send_credits_work); +} + +/* Preallocate all receive buffer on transport establishment */ +static int allocate_receive_buffers(struct smbd_connection *info, int num_buf) +{ + int i; + struct smbd_response *response; + + INIT_LIST_HEAD(&info->reassembly_queue); + spin_lock_init(&info->reassembly_queue_lock); + info->reassembly_data_length = 0; + info->reassembly_queue_length = 0; + + INIT_LIST_HEAD(&info->receive_queue); + spin_lock_init(&info->receive_queue_lock); + info->count_receive_queue = 0; + + INIT_LIST_HEAD(&info->empty_packet_queue); + spin_lock_init(&info->empty_packet_queue_lock); + info->count_empty_packet_queue = 0; + + init_waitqueue_head(&info->wait_receive_queues); + + for (i = 0; i < num_buf; i++) { + response = mempool_alloc(info->response_mempool, GFP_KERNEL); + if (!response) + goto allocate_failed; + + response->info = info; + list_add_tail(&response->list, &info->receive_queue); + info->count_receive_queue++; + } + + return 0; + +allocate_failed: + while (!list_empty(&info->receive_queue)) { + response = list_first_entry( + &info->receive_queue, + struct smbd_response, list); + list_del(&response->list); + info->count_receive_queue--; + + mempool_free(response, info->response_mempool); + } + return -ENOMEM; +} + +static void destroy_receive_buffers(struct smbd_connection *info) +{ + struct smbd_response *response; + + while ((response = get_receive_buffer(info))) + mempool_free(response, info->response_mempool); + + while ((response = get_empty_queue_buffer(info))) + mempool_free(response, info->response_mempool); +} + +/* + * Check and send an immediate or keep alive packet + * The condition to send those packets are defined in [MS-SMBD] 3.1.1.1 + * Connection.KeepaliveRequested and Connection.SendImmediate + * The idea is to extend credits to server as soon as it becomes available + */ +static void send_immediate_work(struct work_struct *work) +{ + struct smbd_connection *info = container_of( + work, struct smbd_connection, + send_immediate_work.work); + + if (info->keep_alive_requested == KEEP_ALIVE_PENDING || + info->send_immediate) { + log_keep_alive(INFO, "send an empty message\n"); + smbd_post_send_empty(info); + } +} + +/* Implement idle connection timer [MS-SMBD] 3.1.6.2 */ +static void idle_connection_timer(struct work_struct *work) +{ + struct smbd_connection *info = container_of( + work, struct smbd_connection, + idle_timer_work.work); + + if (info->keep_alive_requested != KEEP_ALIVE_NONE) { + log_keep_alive(ERR, + "error status info->keep_alive_requested=%d\n", + info->keep_alive_requested); + smbd_disconnect_rdma_connection(info); + return; + } + + log_keep_alive(INFO, "about to send an empty idle message\n"); + smbd_post_send_empty(info); + + /* Setup the next idle timeout work */ + queue_delayed_work(info->workqueue, &info->idle_timer_work, + info->keep_alive_interval*HZ); +} + +static void destroy_caches_and_workqueue(struct smbd_connection *info) +{ + destroy_receive_buffers(info); + destroy_workqueue(info->workqueue); + mempool_destroy(info->response_mempool); + kmem_cache_destroy(info->response_cache); + mempool_destroy(info->request_mempool); + kmem_cache_destroy(info->request_cache); +} + +#define MAX_NAME_LEN 80 +static int allocate_caches_and_workqueue(struct smbd_connection *info) +{ + char name[MAX_NAME_LEN]; + int rc; + + snprintf(name, MAX_NAME_LEN, "smbd_request_%p", info); + info->request_cache = + kmem_cache_create( + name, + sizeof(struct smbd_request) + + sizeof(struct smbd_data_transfer), + 0, SLAB_HWCACHE_ALIGN, NULL); + if (!info->request_cache) + return -ENOMEM; + + info->request_mempool = + mempool_create(info->send_credit_target, mempool_alloc_slab, + mempool_free_slab, info->request_cache); + if (!info->request_mempool) + goto out1; + + snprintf(name, MAX_NAME_LEN, "smbd_response_%p", info); + info->response_cache = + kmem_cache_create( + name, + sizeof(struct smbd_response) + + info->max_receive_size, + 0, SLAB_HWCACHE_ALIGN, NULL); + if (!info->response_cache) + goto out2; + + info->response_mempool = + mempool_create(info->receive_credit_max, mempool_alloc_slab, + mempool_free_slab, info->response_cache); + if (!info->response_mempool) + goto out3; + + snprintf(name, MAX_NAME_LEN, "smbd_%p", info); + info->workqueue = create_workqueue(name); + if (!info->workqueue) + goto out4; + + rc = allocate_receive_buffers(info, info->receive_credit_max); + if (rc) { + log_rdma_event(ERR, "failed to allocate receive buffers\n"); + goto out5; + } + + return 0; + +out5: + destroy_workqueue(info->workqueue); +out4: + mempool_destroy(info->response_mempool); +out3: + kmem_cache_destroy(info->response_cache); +out2: + mempool_destroy(info->request_mempool); +out1: + kmem_cache_destroy(info->request_cache); + return -ENOMEM; +} + +/* Create a SMBD connection, called by upper layer */ +struct smbd_connection *_smbd_get_connection( + struct TCP_Server_Info *server, struct sockaddr *dstaddr, int port) +{ + int rc; + struct smbd_connection *info; + struct rdma_conn_param conn_param; + struct ib_qp_init_attr qp_attr; + struct sockaddr_in *addr_in = (struct sockaddr_in *) dstaddr; + + info = kzalloc(sizeof(struct smbd_connection), GFP_KERNEL); + if (!info) + return NULL; + + info->transport_status = SMBD_CONNECTING; + rc = smbd_ia_open(info, dstaddr, port); + if (rc) { + log_rdma_event(INFO, "smbd_ia_open rc=%d\n", rc); + goto create_id_failed; + } + + if (smbd_send_credit_target > info->id->device->attrs.max_cqe || + smbd_send_credit_target > info->id->device->attrs.max_qp_wr) { + log_rdma_event(ERR, + "consider lowering send_credit_target = %d. " + "Possible CQE overrun, device " + "reporting max_cpe %d max_qp_wr %d\n", + smbd_send_credit_target, + info->id->device->attrs.max_cqe, + info->id->device->attrs.max_qp_wr); + goto config_failed; + } + + if (smbd_receive_credit_max > info->id->device->attrs.max_cqe || + smbd_receive_credit_max > info->id->device->attrs.max_qp_wr) { + log_rdma_event(ERR, + "consider lowering receive_credit_max = %d. " + "Possible CQE overrun, device " + "reporting max_cpe %d max_qp_wr %d\n", + smbd_receive_credit_max, + info->id->device->attrs.max_cqe, + info->id->device->attrs.max_qp_wr); + goto config_failed; + } + + info->receive_credit_max = smbd_receive_credit_max; + info->send_credit_target = smbd_send_credit_target; + info->max_send_size = smbd_max_send_size; + info->max_fragmented_recv_size = smbd_max_fragmented_recv_size; + info->max_receive_size = smbd_max_receive_size; + info->keep_alive_interval = smbd_keep_alive_interval; + + if (SMBDIRECT_MAX_SGE > info->id->device->attrs.max_sge) { + log_rdma_event(ERR, "warning: device max_sge = %d too small\n", + info->id->device->attrs.max_sge); + log_rdma_event(ERR, "Queue Pair creation may fail\n"); + } + + info->send_cq = NULL; + info->recv_cq = NULL; + info->send_cq = ib_alloc_cq(info->id->device, info, + info->send_credit_target, 0, IB_POLL_SOFTIRQ); + if (IS_ERR(info->send_cq)) { + info->send_cq = NULL; + goto alloc_cq_failed; + } + + info->recv_cq = ib_alloc_cq(info->id->device, info, + info->receive_credit_max, 0, IB_POLL_SOFTIRQ); + if (IS_ERR(info->recv_cq)) { + info->recv_cq = NULL; + goto alloc_cq_failed; + } + + memset(&qp_attr, 0, sizeof(qp_attr)); + qp_attr.event_handler = smbd_qp_async_error_upcall; + qp_attr.qp_context = info; + qp_attr.cap.max_send_wr = info->send_credit_target; + qp_attr.cap.max_recv_wr = info->receive_credit_max; + qp_attr.cap.max_send_sge = SMBDIRECT_MAX_SGE; + qp_attr.cap.max_recv_sge = SMBDIRECT_MAX_SGE; + qp_attr.cap.max_inline_data = 0; + qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR; + qp_attr.qp_type = IB_QPT_RC; + qp_attr.send_cq = info->send_cq; + qp_attr.recv_cq = info->recv_cq; + qp_attr.port_num = ~0; + + rc = rdma_create_qp(info->id, info->pd, &qp_attr); + if (rc) { + log_rdma_event(ERR, "rdma_create_qp failed %i\n", rc); + goto create_qp_failed; + } + + memset(&conn_param, 0, sizeof(conn_param)); + conn_param.initiator_depth = 0; + + conn_param.retry_count = SMBD_CM_RETRY; + conn_param.rnr_retry_count = SMBD_CM_RNR_RETRY; + conn_param.flow_control = 0; + init_waitqueue_head(&info->wait_destroy); + + log_rdma_event(INFO, "connecting to IP %pI4 port %d\n", + &addr_in->sin_addr, port); + + init_waitqueue_head(&info->conn_wait); + rc = rdma_connect(info->id, &conn_param); + if (rc) { + log_rdma_event(ERR, "rdma_connect() failed with %i\n", rc); + goto rdma_connect_failed; + } + + wait_event_interruptible( + info->conn_wait, info->transport_status != SMBD_CONNECTING); + + if (info->transport_status != SMBD_CONNECTED) { + log_rdma_event(ERR, "rdma_connect failed port=%d\n", port); + goto rdma_connect_failed; + } + + log_rdma_event(INFO, "rdma_connect connected\n"); + + rc = allocate_caches_and_workqueue(info); + if (rc) { + log_rdma_event(ERR, "cache allocation failed\n"); + goto allocate_cache_failed; + } + + init_waitqueue_head(&info->wait_send_queue); + init_waitqueue_head(&info->wait_reassembly_queue); + + INIT_DELAYED_WORK(&info->idle_timer_work, idle_connection_timer); + INIT_DELAYED_WORK(&info->send_immediate_work, send_immediate_work); + queue_delayed_work(info->workqueue, &info->idle_timer_work, + info->keep_alive_interval*HZ); + + init_waitqueue_head(&info->wait_send_pending); + atomic_set(&info->send_pending, 0); + + init_waitqueue_head(&info->wait_send_payload_pending); + atomic_set(&info->send_payload_pending, 0); + + INIT_WORK(&info->disconnect_work, smbd_disconnect_rdma_work); + INIT_WORK(&info->destroy_work, smbd_destroy_rdma_work); + INIT_WORK(&info->recv_done_work, smbd_recv_done_work); + INIT_WORK(&info->post_send_credits_work, smbd_post_send_credits); + info->new_credits_offered = 0; + spin_lock_init(&info->lock_new_credits_offered); + + rc = smbd_negotiate(info); + if (rc) { + log_rdma_event(ERR, "smbd_negotiate rc=%d\n", rc); + goto negotiation_failed; + } + + return info; + +negotiation_failed: + cancel_delayed_work_sync(&info->idle_timer_work); + destroy_caches_and_workqueue(info); + info->transport_status = SMBD_NEGOTIATE_FAILED; + init_waitqueue_head(&info->conn_wait); + rdma_disconnect(info->id); + wait_event(info->conn_wait, + info->transport_status == SMBD_DISCONNECTED); + +allocate_cache_failed: +rdma_connect_failed: + rdma_destroy_qp(info->id); + +create_qp_failed: +alloc_cq_failed: + if (info->send_cq) + ib_free_cq(info->send_cq); + if (info->recv_cq) + ib_free_cq(info->recv_cq); + +config_failed: + ib_dealloc_pd(info->pd); + rdma_destroy_id(info->id); + +create_id_failed: + kfree(info); + return NULL; +} diff --git a/fs/cifs/smbdirect.h b/fs/cifs/smbdirect.h index c55f28b..35bc25b 100644 --- a/fs/cifs/smbdirect.h +++ b/fs/cifs/smbdirect.h @@ -16,6 +16,286 @@ #ifndef _SMBDIRECT_H #define _SMBDIRECT_H +#ifdef CONFIG_CIFS_SMB_DIRECT +#define cifs_rdma_enabled(server) ((server)->rdma) + +#include "cifsglob.h" +#include <rdma/ib_verbs.h> +#include <rdma/rdma_cm.h> +#include <linux/mempool.h> + +enum keep_alive_status { + KEEP_ALIVE_NONE, + KEEP_ALIVE_PENDING, + KEEP_ALIVE_SENT, +}; + +enum smbd_connection_status { + SMBD_CREATED, + SMBD_CONNECTING, + SMBD_CONNECTED, + SMBD_NEGOTIATE_FAILED, + SMBD_DISCONNECTING, + SMBD_DISCONNECTED, + SMBD_DESTROYED +}; + +/* + * The context for the SMBDirect transport + * Everything related to the transport is here. It has several logical parts + * 1. RDMA related structures + * 2. SMBDirect connection parameters + * 3. Memory registrations + * 4. Receive and reassembly queues for data receive path + * 5. mempools for allocating packets + */ +struct smbd_connection { + enum smbd_connection_status transport_status; + + /* RDMA related */ + struct rdma_cm_id *id; + struct ib_qp_init_attr qp_attr; + struct ib_pd *pd; + struct ib_cq *send_cq, *recv_cq; + struct ib_device_attr dev_attr; + int ri_rc; + struct completion ri_done; + wait_queue_head_t conn_wait; + wait_queue_head_t wait_destroy; + + struct completion negotiate_completion; + bool negotiate_done; + + struct work_struct destroy_work; + struct work_struct disconnect_work; + struct work_struct recv_done_work; + struct work_struct post_send_credits_work; + + spinlock_t lock_new_credits_offered; + int new_credits_offered; + + /* Connection parameters defined in [MS-SMBD] 3.1.1.1 */ + int receive_credit_max; + int send_credit_target; + int max_send_size; + int max_fragmented_recv_size; + int max_fragmented_send_size; + int max_receive_size; + int keep_alive_interval; + int max_readwrite_size; + enum keep_alive_status keep_alive_requested; + int protocol; + atomic_t send_credits; + atomic_t receive_credits; + int receive_credit_target; + int fragment_reassembly_remaining; + + /* Activity accoutning */ + + atomic_t send_pending; + wait_queue_head_t wait_send_pending; + atomic_t send_payload_pending; + wait_queue_head_t wait_send_payload_pending; + + /* Receive queue */ + struct list_head receive_queue; + int count_receive_queue; + spinlock_t receive_queue_lock; + + struct list_head empty_packet_queue; + int count_empty_packet_queue; + spinlock_t empty_packet_queue_lock; + + wait_queue_head_t wait_receive_queues; + + /* Reassembly queue */ + struct list_head reassembly_queue; + spinlock_t reassembly_queue_lock; + wait_queue_head_t wait_reassembly_queue; + + /* total data length of reassembly queue */ + int reassembly_data_length; + int reassembly_queue_length; + /* the offset to first buffer in reassembly queue */ + int first_entry_offset; + + bool send_immediate; + + wait_queue_head_t wait_send_queue; + + /* + * Indicate if we have received a full packet on the connection + * This is used to identify the first SMBD packet of a assembled + * payload (SMB packet) in reassembly queue so we can return a + * RFC1002 length to upper layer to indicate the length of the SMB + * packet received + */ + bool full_packet_received; + + struct workqueue_struct *workqueue; + struct delayed_work idle_timer_work; + struct delayed_work send_immediate_work; + + /* Memory pool for preallocating buffers */ + /* request pool for RDMA send */ + struct kmem_cache *request_cache; + mempool_t *request_mempool; + + /* response pool for RDMA receive */ + struct kmem_cache *response_cache; + mempool_t *response_mempool; + + /* for debug purposes */ + unsigned int count_get_receive_buffer; + unsigned int count_put_receive_buffer; + unsigned int count_reassembly_queue; + unsigned int count_enqueue_reassembly_queue; + unsigned int count_dequeue_reassembly_queue; + unsigned int count_send_empty; +}; + +enum smbd_message_type { + SMBD_NEGOTIATE_RESP, + SMBD_TRANSFER_DATA, +}; + +#define SMB_DIRECT_RESPONSE_REQUESTED 0x0001 + +/* SMBD negotiation request packet [MS-SMBD] 2.2.1 */ +struct smbd_negotiate_req { + __le16 min_version; + __le16 max_version; + __le16 reserved; + __le16 credits_requested; + __le32 preferred_send_size; + __le32 max_receive_size; + __le32 max_fragmented_size; +} __packed; + +/* SMBD negotiation response packet [MS-SMBD] 2.2.2 */ +struct smbd_negotiate_resp { + __le16 min_version; + __le16 max_version; + __le16 negotiated_version; + __le16 reserved; + __le16 credits_requested; + __le16 credits_granted; + __le32 status; + __le32 max_readwrite_size; + __le32 preferred_send_size; + __le32 max_receive_size; + __le32 max_fragmented_size; +} __packed; + +/* SMBD data transfer packet with payload [MS-SMBD] 2.2.3 */ +struct smbd_data_transfer { + __le16 credits_requested; + __le16 credits_granted; + __le16 flags; + __le16 reserved; + __le32 remaining_data_length; + __le32 data_offset; + __le32 data_length; + __le32 padding; + __u8 buffer[]; +} __packed; + +/* The packet fields for a registered RDMA buffer */ +struct smbd_buffer_descriptor_v1 { + __le64 offset; + __le32 token; + __le32 length; +} __packed; + /* Default maximum number of SGEs in a RDMA send/recv */ #define SMBDIRECT_MAX_SGE 16 +/* The context for a SMBD request */ +struct smbd_request { + struct smbd_connection *info; + struct ib_cqe cqe; + + /* true if this request carries upper layer payload */ + bool has_payload; + + /* the SGE entries for this packet */ + struct ib_sge sge[SMBDIRECT_MAX_SGE]; + int num_sge; + + /* SMBD packet header follows this structure */ + u8 packet[]; +}; + +/* The context for a SMBD response */ +struct smbd_response { + struct smbd_connection *info; + struct ib_cqe cqe; + struct ib_sge sge; + + enum smbd_message_type type; + + /* Link to receive queue or reassembly queue */ + struct list_head list; + + /* Indicate if this is the 1st packet of a payload */ + bool first_segment; + + /* SMBD packet header and payload follows this structure */ + u8 packet[]; +}; + +/* Create a SMBDirect session */ +struct smbd_connection *smbd_get_connection( + struct TCP_Server_Info *server, struct sockaddr *dstaddr); + +/* Reconnect SMBDirect session */ +int smbd_reconnect(struct TCP_Server_Info *server); + +/* Destroy SMBDirect session */ +void smbd_destroy(struct smbd_connection *info); + +/* Interface for carrying upper layer I/O through send/recv */ +int smbd_recv(struct smbd_connection *info, struct msghdr *msg); +int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst); + +enum mr_state { + MR_READY, + MR_REGISTERED, + MR_INVALIDATED, + MR_ERROR +}; + +struct smbd_mr { + struct smbd_connection *conn; + struct list_head list; + enum mr_state state; + struct ib_mr *mr; + struct scatterlist *sgl; + int sgl_count; + enum dma_data_direction dir; + union { + struct ib_reg_wr wr; + struct ib_send_wr inv_wr; + }; + struct ib_cqe cqe; + bool need_invalidate; + struct completion invalidate_done; +}; + +/* Interfaces to register and deregister MR for RDMA read/write */ +struct smbd_mr *smbd_register_mr( + struct smbd_connection *info, struct page *pages[], int num_pages, + int tailsz, bool writing, bool need_invalidate); +int smbd_deregister_mr(struct smbd_mr *mr); + +#else +#define cifs_rdma_enabled(server) 0 +struct smbd_connection{}; +static inline void *smbd_get_connection( + struct TCP_Server_Info *server, struct sockaddr *dstaddr) {return NULL;} +static inline int smbd_reconnect(struct TCP_Server_Info *server) {return -1;} +static inline void smbd_destroy(struct smbd_connection *info) {} +static inline int smbd_recv(struct smbd_connection *info, struct msghdr *msg) {return -1;} +static inline int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst) {return -1;} +#endif + #endif