From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [RFC,v3,7/7] dmaengine: Add Synopsys eDMA IP test and sample driver From: Gustavo Pimentel Message-Id: Date: Fri, 11 Jan 2019 19:33:43 +0100 To: linux-pci@vger.kernel.org, dmaengine@vger.kernel.org Cc: Gustavo Pimentel , Vinod Koul , Dan Williams , Eugeniy Paltsev , Andy Shevchenko , Russell King , Niklas Cassel , Joao Pinto , Jose Abreu , Luis Oliveira , Vitor Soares , Nelson Costa , Pedro Sousa List-ID: QWRkIFN5bm9wc3lzIGVETUEgSVAgdGVzdCBhbmQgc2FtcGxlIGRyaXZlciB0byBiZSB1c2UgZm9y IHRlc3RpbmcKcHVycG9zZXMgYW5kIGFsc28gYXMgYSByZWZlcmVuY2UgZm9yIGFueSBkZXZlbG9w ZXIgd2hvIG5lZWRzIHRvCmltcGxlbWVudCBhbmQgdXNlIFN5bm9wc3lzIGVETUEuCgpUaGlzIGRy aXZlciBjYW4gYmUgY29tcGlsZSBhcyBidWlsdC1pbiBvciBleHRlcm5hbCBtb2R1bGUgaW4ga2Vy bmVsLgoKVG8gZW5hYmxlIHRoaXMgZHJpdmVyIGp1c3Qgc2VsZWN0IERXX0VETUFfVEVTVCBvcHRp b24gaW4ga2VybmVsCmNvbmZpZ3VyYXRpb24sIGhvd2V2ZXIgaXQgcmVxdWlyZXMgYW5kIHNlbGVj dHMgYXV0b21hdGljYWxseSBEV19FRE1BCm9wdGlvbiB0b28uCgpDaGFuZ2VzOgpSRkMgdjEtPlJG QyB2MjoKIC0gTm8gY2hhbmdlcwpSRkMgdjItPlJGQyB2MzoKIC0gQWRkIHRlc3QgbW9kdWxlCgpT aWduZWQtb2ZmLWJ5OiBHdXN0YXZvIFBpbWVudGVsIDxndXN0YXZvLnBpbWVudGVsQHN5bm9wc3lz LmNvbT4KQ2M6IFZpbm9kIEtvdWwgPHZrb3VsQGtlcm5lbC5vcmc+CkNjOiBEYW4gV2lsbGlhbXMg PGRhbi5qLndpbGxpYW1zQGludGVsLmNvbT4KQ2M6IEV1Z2VuaXkgUGFsdHNldiA8cGFsdHNldkBz eW5vcHN5cy5jb20+CkNjOiBBbmR5IFNoZXZjaGVua28gPGFuZHJpeS5zaGV2Y2hlbmtvQGxpbnV4 LmludGVsLmNvbT4KQ2M6IFJ1c3NlbGwgS2luZyA8cm1rK2tlcm5lbEBhcm1saW51eC5vcmcudWs+ CkNjOiBOaWtsYXMgQ2Fzc2VsIDxuaWtsYXMuY2Fzc2VsQGxpbmFyby5vcmc+CkNjOiBKb2FvIFBp bnRvIDxqcGludG9Ac3lub3BzeXMuY29tPgpDYzogSm9zZSBBYnJldSA8am9zZS5hYnJldUBzeW5v cHN5cy5jb20+CkNjOiBMdWlzIE9saXZlaXJhIDxsb2xpdmVpQHN5bm9wc3lzLmNvbT4KQ2M6IFZp dG9yIFNvYXJlcyA8dml0b3Iuc29hcmVzQHN5bm9wc3lzLmNvbT4KQ2M6IE5lbHNvbiBDb3N0YSA8 bmVsc29uLmNvc3RhQHN5bm9wc3lzLmNvbT4KQ2M6IFBlZHJvIFNvdXNhIDxwZWRyb20uc291c2FA c3lub3BzeXMuY29tPgotLS0KIGRyaXZlcnMvZG1hL2R3LWVkbWEvS2NvbmZpZyAgICAgICAgfCAg IDcgKwogZHJpdmVycy9kbWEvZHctZWRtYS9NYWtlZmlsZSAgICAgICB8ICAgMSArCiBkcml2ZXJz L2RtYS9kdy1lZG1hL2R3LWVkbWEtdGVzdC5jIHwgODk3ICsrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysKIDMgZmlsZXMgY2hhbmdlZCwgOTA1IGluc2VydGlvbnMoKykKIGNyZWF0 ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2RtYS9kdy1lZG1hL2R3LWVkbWEtdGVzdC5jCgpkaWZmIC0t Z2l0IGEvZHJpdmVycy9kbWEvZHctZWRtYS9LY29uZmlnIGIvZHJpdmVycy9kbWEvZHctZWRtYS9L Y29uZmlnCmluZGV4IGMwODM4Y2UuLmZlMmIxMjkgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvZG1hL2R3 LWVkbWEvS2NvbmZpZworKysgYi9kcml2ZXJzL2RtYS9kdy1lZG1hL0tjb25maWcKQEAgLTE2LDMg KzE2LDEwIEBAIGNvbmZpZyBEV19FRE1BX1BDSUUKIAkgIFByb3ZpZGVzIGEgZ2x1ZS1sb2dpYyBi ZXR3ZWVuIHRoZSBTeW5vcHN5cyBEZXNpZ25XYXJlCiAJICBlRE1BIGNvbnRyb2xsZXIgYW5kIGFu IGVuZHBvaW50IFBDSWUgZGV2aWNlLiBUaGlzIGFsc28gc2VydmVzCiAJICBhcyBhIHJlZmVyZW5j ZSBkZXNpZ24gdG8gd2hvbSBkZXNpcmVzIHRvIHVzZSB0aGlzIElQLgorCitjb25maWcgRFdfRURN QV9URVNUCisJdHJpc3RhdGUgIlN5bm9wc3lzIERlc2lnbldhcmUgZURNQSB0ZXN0IGRyaXZlciIK KwlzZWxlY3QgRFdfRURNQQorCWhlbHAKKwkgIFNpbXBsZSBETUEgdGVzdCBjbGllbnQuIFNheSBO IHVubGVzcyB5b3UncmUgZGVidWdnaW5nIGEKKwkgIFN5bm9wc3lzIGVETUEgZGV2aWNlIGRyaXZl ci4KZGlmZiAtLWdpdCBhL2RyaXZlcnMvZG1hL2R3LWVkbWEvTWFrZWZpbGUgYi9kcml2ZXJzL2Rt YS9kdy1lZG1hL01ha2VmaWxlCmluZGV4IDhkNDVjMGQuLjc2ZTFlNzMgMTAwNjQ0Ci0tLSBhL2Ry aXZlcnMvZG1hL2R3LWVkbWEvTWFrZWZpbGUKKysrIGIvZHJpdmVycy9kbWEvZHctZWRtYS9NYWtl ZmlsZQpAQCAtNSwzICs1LDQgQEAgZHctZWRtYS0kKENPTkZJR19ERUJVR19GUykJOj0gZHctZWRt YS12MC1kZWJ1Z2ZzLm8KIGR3LWVkbWEtb2JqcwkJCTo9IGR3LWVkbWEtY29yZS5vIFwKIAkJCQkJ ZHctZWRtYS12MC1jb3JlLm8gJChkdy1lZG1hLXkpCiBvYmotJChDT05GSUdfRFdfRURNQV9QQ0lF KQkrPSBkdy1lZG1hLXBjaWUubworb2JqLSQoQ09ORklHX0RXX0VETUFfVEVTVCkJKz0gZHctZWRt YS10ZXN0Lm8KZGlmZiAtLWdpdCBhL2RyaXZlcnMvZG1hL2R3LWVkbWEvZHctZWRtYS10ZXN0LmMg Yi9kcml2ZXJzL2RtYS9kdy1lZG1hL2R3LWVkbWEtdGVzdC5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0 CmluZGV4IDAwMDAwMDAuLjIzZjhjMjMKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2RtYS9k dy1lZG1hL2R3LWVkbWEtdGVzdC5jCkBAIC0wLDAgKzEsODk3IEBACisvLyBTUERYLUxpY2Vuc2Ut SWRlbnRpZmllcjogR1BMLTIuMAorLyoKKyAqIENvcHlyaWdodCAoYykgMjAxOCBTeW5vcHN5cywg SW5jLiBhbmQvb3IgaXRzIGFmZmlsaWF0ZXMuCisgKiBTeW5vcHN5cyBEZXNpZ25XYXJlIGVETUEg dGVzdCBkcml2ZXIKKyAqLworCisjaW5jbHVkZSA8bGludXgvZGVsYXkuaD4KKyNpbmNsdWRlIDxs aW51eC9kbWEtbWFwcGluZy5oPgorI2luY2x1ZGUgPGxpbnV4L2RtYWVuZ2luZS5oPgorI2luY2x1 ZGUgPGxpbnV4L2ZyZWV6ZXIuaD4KKyNpbmNsdWRlIDxsaW51eC9rdGhyZWFkLmg+CisjaW5jbHVk ZSA8bGludXgvc2NoZWQvdGFzay5oPgorI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgorI2luY2x1 ZGUgPGxpbnV4L21vZHVsZXBhcmFtLmg+CisjaW5jbHVkZSA8bGludXgvc2xhYi5oPgorI2luY2x1 ZGUgPGxpbnV4L3dhaXQuaD4KKworI2luY2x1ZGUgImR3LWVkbWEtY29yZS5oIgorCitlbnVtIGNo YW5uZWxfaWQgeworCUVETUFfQ0hfV1IgPSAwLAorCUVETUFfQ0hfUkQsCisJRURNQV9DSF9FTkQK K307CisKK3N0YXRpYyBjb25zdCBjaGFyICogY29uc3QgY2hhbm5lbF9uYW1lW10gPSB7IldSSVRF IiwgIlJFQUQifTsKKworI2RlZmluZSBFRE1BX1RFU1RfTUFYX1RIUkVBRFNfQ0hBTk5FTAkJOAor I2RlZmluZSBFRE1BX1RFU1RfREVWSUNFX05BTUUJCQkiMDAwMDowMTowMC4wIgorI2RlZmluZSBF RE1BX1RFU1RfQ0hBTk5FTF9OQU1FCQkJImRtYSV1Y2hhbiV1IgorCitzdGF0aWMgdTMyIGJ1Zl9z eiA9IDE0ICogMTAyNCAqIDEwMjQ7CQkvKiAxNCBNYnl0ZXMgKi8KK21vZHVsZV9wYXJhbShidWZf c3osIHVpbnQsIDA2NDQpOworTU9EVUxFX1BBUk1fREVTQyhidWZfc3osICJCdWZmZXIgdGVzdCBz aXplIGluIGJ5dGVzIik7CisKK3N0YXRpYyB1MzIgYnVmX3NlZyA9IDIgKiAxMDI0ICogMTAyNDsJ CS8qICAyIE1ieXRlcyAqLworbW9kdWxlX3BhcmFtKGJ1Zl9zZWcsIHVpbnQsIDA2NDQpOworTU9E VUxFX1BBUk1fREVTQyhidWZfc2VnLCAiQnVmZmVyIHRlc3Qgc2l6ZSBzZWdtZW50cyBpbiBieXRl cyIpOworCitzdGF0aWMgdTMyIHdyX3RocmVhZHMgPSBFRE1BX1RFU1RfTUFYX1RIUkVBRFNfQ0hB Tk5FTDsKK21vZHVsZV9wYXJhbSh3cl90aHJlYWRzLCB1aW50LCAwNjQ0KTsKK01PRFVMRV9QQVJN X0RFU0Mod3JfdGhyZWFkcywgIk51bWJlciBvZiB3cml0ZSB0aHJlYWRzIik7CisKK3N0YXRpYyB1 MzIgcmRfdGhyZWFkcyA9IEVETUFfVEVTVF9NQVhfVEhSRUFEU19DSEFOTkVMOworbW9kdWxlX3Bh cmFtKHJkX3RocmVhZHMsIHVpbnQsIDA2NDQpOworTU9EVUxFX1BBUk1fREVTQyhyZF90aHJlYWRz LCAiTnVtYmVyIG9mIHJlYWRzIHRocmVhZHMiKTsKKworc3RhdGljIHUzMiByZXBldGl0aW9uczsK K21vZHVsZV9wYXJhbShyZXBldGl0aW9ucywgdWludCwgMDY0NCk7CitNT0RVTEVfUEFSTV9ERVND KHJlcGV0aXRpb25zLCAiTnVtYmVyIG9mIHJlcGV0aXRpb25zIik7CisKK3N0YXRpYyB1MzIgdGlt ZW91dCA9IDUwMDA7Cittb2R1bGVfcGFyYW0odGltZW91dCwgdWludCwgMDY0NCk7CitNT0RVTEVf UEFSTV9ERVNDKHRpbWVvdXQsICJUcmFuc2ZlciB0aW1lb3V0IGluIG1zZWMiKTsKKworc3RhdGlj IGJvb2wgcGF0dGVybjsKK21vZHVsZV9wYXJhbShwYXR0ZXJuLCBib29sLCAwNjQ0KTsKK01PRFVM RV9QQVJNX0RFU0MocGF0dGVybiwgIlNldCBDUFUgbWVtb3J5IHdpdGggYSBwYXR0ZXJuIGJlZm9y ZSB0aGUgdHJhbnNmZXIiKTsKKworc3RhdGljIGJvb2wgZHVtcF9tZW07Cittb2R1bGVfcGFyYW0o ZHVtcF9tZW0sIGJvb2wsIDA2NDQpOworTU9EVUxFX1BBUk1fREVTQyhkdW1wX21lbSwgIlByaW50 cyBvbiBjb25zb2xlIHRoZSBDUFUgYW5kIEVuZHBvaW50IG1lbW9yeSBiZWZvcmUgYW5kIGFmdGVy IHRoZSB0cmFuc2ZlciIpOworCitzdGF0aWMgdTMyIGR1bXBfc3ogPSA1OworbW9kdWxlX3BhcmFt KGR1bXBfc3osIHVpbnQsIDA2NDQpOworTU9EVUxFX1BBUk1fREVTQyhkdW1wX3N6LCAiU2l6ZSBv ZiBtZW1vcnkgZHVtcCIpOworCitzdGF0aWMgYm9vbCBjaGVjazsKK21vZHVsZV9wYXJhbShjaGVj aywgYm9vbCwgMDY0NCk7CitNT0RVTEVfUEFSTV9ERVNDKGNoZWNrLCAiUGVyZm9ybXMgYSB2ZXJp ZmljYXRpb24gYWZ0ZXIgdGhlIHRyYW5zZmVyIHRvIHZhbGlkYXRlIGRhdGEiKTsKKworc3RhdGlj IGludCBkd19lZG1hX3Rlc3RfcnVuX3NldChjb25zdCBjaGFyICp2YWwsIGNvbnN0IHN0cnVjdCBr ZXJuZWxfcGFyYW0gKmtwKTsKKworc3RhdGljIGludCBkd19lZG1hX3Rlc3RfcnVuX3NldChjb25z dCBjaGFyICp2YWwsIGNvbnN0IHN0cnVjdCBrZXJuZWxfcGFyYW0gKmtwKTsKK3N0YXRpYyBpbnQg ZHdfZWRtYV90ZXN0X3J1bl9nZXQoY2hhciAqdmFsLCBjb25zdCBzdHJ1Y3Qga2VybmVsX3BhcmFt ICprcCk7CitzdGF0aWMgY29uc3Qgc3RydWN0IGtlcm5lbF9wYXJhbV9vcHMgcnVuX29wcyA9IHsK Kwkuc2V0ID0gZHdfZWRtYV90ZXN0X3J1bl9zZXQsCisJLmdldCA9IGR3X2VkbWFfdGVzdF9ydW5f Z2V0LAorfTsKKworc3RhdGljIGJvb2wgcnVuX3Rlc3Q7Cittb2R1bGVfcGFyYW1fY2IocnVuX3Rl c3QsICZydW5fb3BzLCAmcnVuX3Rlc3QsIDA2NDQpOworTU9EVUxFX1BBUk1fREVTQyhydW5fdGVz dCwgIlJ1biB0ZXN0Iik7CisKK3N0cnVjdCBkd19lZG1hX3Rlc3RfcGFyYW1zIHsKKwl1MzIJCQkJ YnVmX3N6OworCXUzMgkJCQlidWZfc2VnOworCXUzMgkJCQludW1fdGhyZWFkc1tFRE1BX0NIX0VO RF07CisJdTMyCQkJCXJlcGV0aXRpb25zOworCXUzMgkJCQl0aW1lb3V0OworCXU4CQkJCXBhdHRl cm47CisJdTgJCQkJZHVtcF9tZW07CisJdTMyCQkJCWR1bXBfc3o7CisJdTgJCQkJY2hlY2s7Cit9 OworCitzdGF0aWMgc3RydWN0IGR3X2VkbWFfdGVzdF9pbmZvIHsKKwlzdHJ1Y3QgZHdfZWRtYV90 ZXN0X3BhcmFtcwlwYXJhbXM7CisJc3RydWN0IGxpc3RfaGVhZAkJY2hhbm5lbHM7CisJc3RydWN0 IG11dGV4CQkJbG9jazsKKwlib29sCQkJCWluaXQ7Cit9IHRlc3RfaW5mbyA9IHsKKwkuY2hhbm5l bHMgPSBMSVNUX0hFQURfSU5JVCh0ZXN0X2luZm8uY2hhbm5lbHMpLAorCS5sb2NrID0gX19NVVRF WF9JTklUSUFMSVpFUih0ZXN0X2luZm8ubG9jayksCit9OworCitzdHJ1Y3QgZHdfZWRtYV90ZXN0 X2RvbmUgeworCWJvb2wJCQkJZG9uZTsKKwl3YWl0X3F1ZXVlX2hlYWRfdAkJKndhaXQ7Cit9Owor CitzdHJ1Y3QgZHdfZWRtYV90ZXN0X3RocmVhZCB7CisJc3RydWN0IGR3X2VkbWFfdGVzdF9pbmZv CSppbmZvOworCXN0cnVjdCB0YXNrX3N0cnVjdAkJKnRhc2s7CisJc3RydWN0IGRtYV9jaGFuCQkJ KmNoYW47CisJZW51bSBkbWFfdHJhbnNmZXJfZGlyZWN0aW9uCWRpcmVjdGlvbjsKKwl3YWl0X3F1 ZXVlX2hlYWRfdAkJZG9uZV93YWl0OworCXN0cnVjdCBkd19lZG1hX3Rlc3RfZG9uZQl0ZXN0X2Rv bmU7CisJYm9vbAkJCQlkb25lOworfTsKKworc3RydWN0IGR3X2VkbWFfdGVzdF9jaGFuIHsKKwlz dHJ1Y3QgbGlzdF9oZWFkCQlub2RlOworCXN0cnVjdCBkbWFfY2hhbgkJCSpjaGFuOworCXN0cnVj dCBkd19lZG1hX3Rlc3RfdGhyZWFkCSp0aHJlYWQ7Cit9OworCitzdGF0aWMgREVDTEFSRV9XQUlU X1FVRVVFX0hFQUQodGhyZWFkX3dhaXQpOworCitzdGF0aWMgdm9pZCBkd19lZG1hX3Rlc3RfY2Fs bGJhY2sodm9pZCAqYXJnKQoreworCXN0cnVjdCBkd19lZG1hX3Rlc3RfZG9uZSAqZG9uZSA9IGFy ZzsKKwlzdHJ1Y3QgZHdfZWRtYV90ZXN0X3RocmVhZCAqdGhyZWFkID0KKwkJY29udGFpbmVyX29m KGRvbmUsIHN0cnVjdCBkd19lZG1hX3Rlc3RfdGhyZWFkLCB0ZXN0X2RvbmUpOworCWlmICghdGhy ZWFkLT5kb25lKSB7CisJCWRvbmUtPmRvbmUgPSB0cnVlOworCQl3YWtlX3VwX2FsbChkb25lLT53 YWl0KTsKKwl9IGVsc2UgeworCQlXQVJOKDEsICJkd19lZG1hX3Rlc3Q6IEtlcm5lbCBtZW1vcnkg bWF5IGJlIGNvcnJ1cHRlZCEhXG4iKTsKKwl9Cit9CisKK3N0YXRpYyB2b2lkIGR3X2VkbWFfdGVz dF9tZW1zZXQoZG1hX2FkZHJfdCBhZGRyLCBpbnQgc3opCit7CisJdm9pZCBfX2lvbWVtICpwdHIg PSAodm9pZCBfX2lvbWVtICopYWRkcjsKKwlpbnQgcmVtX3N6ID0gc3osIHN0ZXAgPSAwOworCisJ d2hpbGUgKHJlbV9zeiA+PSAwKSB7CisjaWZkZWYgQ09ORklHXzY0QklUCisJCWlmIChyZW1fc3og Pj0gOCkgeworCQkJc3RlcCA9IDg7CisJCQl3cml0ZXEoMHgwMTIzNDU2Nzg5QUJDREVGLCBwdHIp OworCQl9IGVsc2UgaWYgKHJlbV9zeiA+PSA0KSB7CisjZWxzZQorCQlpZiAocmVtX3N6ID49IDQp IHsKKyNlbmRpZgorCQkJc3RlcCA9IDQ7CisJCQl3cml0ZWwoMHgwMTIzNDU2NywgcHRyKTsKKwkJ fSBlbHNlIGlmIChyZW1fc3ogPj0gMikgeworCQkJc3RlcCA9IDI7CisJCQl3cml0ZXcoMHgwMTIz LCBwdHIpOworCQl9IGVsc2UgeworCQkJc3RlcCA9IDE7CisJCQl3cml0ZWIoMHgwMSwgcHRyKTsK KwkJfQorCQlwdHIgKz0gc3RlcDsKKwkJcmVtX3N6IC09IHN0ZXA7CisJfQorfQorCitzdGF0aWMg Ym9vbCBkd19lZG1hX3Rlc3RfY2hlY2soZG1hX2FkZHJfdCB2MSwgZG1hX2FkZHJfdCB2MiwgaW50 IHN6KQoreworCXZvaWQgX19pb21lbSAqcHRyMSA9ICh2b2lkIF9faW9tZW0gKil2MTsKKwl2b2lk IF9faW9tZW0gKnB0cjIgPSAodm9pZCBfX2lvbWVtICopdjI7CisJaW50IHJlbV9zeiA9IHN6LCBz dGVwID0gMDsKKworCXdoaWxlIChyZW1fc3ogPj0gMCkgeworI2lmZGVmIENPTkZJR182NEJJVAor CQlpZiAocmVtX3N6ID49IDgpIHsKKwkJCXN0ZXAgPSA4OworCQkJaWYgKHJlYWRxKHB0cjEpICE9 IHJlYWRxKHB0cjIpKQorCQkJCXJldHVybiBmYWxzZTsKKwkJfSBlbHNlIGlmIChyZW1fc3ogPj0g NCkgeworI2Vsc2UKKwkJaWYgKHJlbV9zeiA+PSA0KSB7CisjZW5kaWYKKwkJCXN0ZXAgPSA0Owor CQkJaWYgKHJlYWRsKHB0cjEpICE9IHJlYWRsKHB0cjIpKQorCQkJCXJldHVybiBmYWxzZTsKKwkJ fSBlbHNlIGlmIChyZW1fc3ogPj0gMikgeworCQkJc3RlcCA9IDI7CisJCQlpZiAocmVhZHcocHRy MSkgIT0gcmVhZHcocHRyMikpCisJCQkJcmV0dXJuIGZhbHNlOworCQl9IGVsc2UgeworCQkJc3Rl cCA9IDE7CisJCQlpZiAocmVhZGIocHRyMSkgIT0gcmVhZGIocHRyMikpCisJCQkJcmV0dXJuIGZh bHNlOworCQl9CisJCXB0cjEgKz0gc3RlcDsKKwkJcHRyMiArPSBzdGVwOworCQlyZW1fc3ogLT0g c3RlcDsKKwl9CisKKwlyZXR1cm4gdHJ1ZTsKK30KKworc3RhdGljIHZvaWQgZHdfZWRtYV90ZXN0 X2R1bXAoc3RydWN0IGRldmljZSAqZGV2LAorCQkJICAgICAgZW51bSBkbWFfdHJhbnNmZXJfZGly ZWN0aW9uIGRpcmVjdGlvbiwgaW50IHN6LAorCQkJICAgICAgc3RydWN0IGR3X2VkbWFfcmVnaW9u ICpyMSwKKwkJCSAgICAgIHN0cnVjdCBkd19lZG1hX3JlZ2lvbiAqcjIpCit7CisJdTMyICpwdHIx LCAqcHRyMiwgKnB0cjMsICpwdHI0OworCWludCBpLCBjbnQgPSBtaW4ocjEtPnN6LCByMi0+c3op OworCisJY250ID0gbWluKGNudCwgc3opOworCWNudCAtPSBjbnQgJSA0OworCisJaWYgKGRpcmVj dGlvbiA9PSBETUFfREVWX1RPX01FTSkgeworCQlwdHIxID0gKHUzMiAqKXIxLT52YWRkcjsKKwkJ cHRyMiA9ICh1MzIgKilyMS0+cGFkZHI7CisJCXB0cjMgPSAodTMyICopcjItPnZhZGRyOworCQlw dHI0ID0gKHUzMiAqKXIyLT5wYWRkcjsKKwkJZGV2X2luZm8oZGV2LCAiICAgICAgPT09PT09PT09 PT09PSBFUCBtZW1vcnkgPT09PT09PT09PT09PVx0PT09PT09PT09PT09PSBDUFUgbWVtb3J5ID09 PT09PT09PT09PVxuIik7CisJfSBlbHNlIHsKKwkJcHRyMSA9ICh1MzIgKilyMi0+dmFkZHI7CisJ CXB0cjIgPSAodTMyICopcjItPnBhZGRyOworCQlwdHIzID0gKHUzMiAqKXIxLT52YWRkcjsKKwkJ cHRyNCA9ICh1MzIgKilyMS0+cGFkZHI7CisJCWRldl9pbmZvKGRldiwgIiAgICAgID09PT09PT09 PT09PT0gQ1BVIG1lbW9yeSA9PT09PT09PT09PT1cdD09PT09PT09PT09PT0gRVAgbWVtb3J5ID09 PT09PT09PT09PT1cbiIpOworCX0KKwlkZXZfaW5mbyhkZXYsICIgICAgICA9PT09PT09PT09PT09 PSBTb3VyY2UgPT09PT09PT09PT09PT09XHQ9PT09PT09PT09PT0gRGVzdGluYXRpb24gPT09PT09 PT09PT09XG4iKTsKKwlkZXZfaW5mbyhkZXYsICIgICAgICBbVmlydC4gQWRkcl1bUGh5cy4gQWRk cl09WyAgIFZhbHVlICBdXHRbVmlydC4gQWRkcl1bUGh5cy4gQWRkcl09WyAgIFZhbHVlICBdXG4i KTsKKwlmb3IgKGkgPSAwOyBpIDwgY250OyBpKyssIHB0cjErKywgcHRyMisrLCBwdHIzKyssIHB0 cjQrKykKKwkJZGV2X2luZm8oZGV2LCAiWyUuM3VdIFslcGFdWyVwYV09WzB4JS44eF1cdFslcGFd WyVwYV09WzB4JS44eF1cbiIsCisJCQkgaSwKKwkJCSAmcHRyMSwgJnB0cjIsIHJlYWRsKHB0cjEp LAorCQkJICZwdHIzLCAmcHRyNCwgcmVhZGwocHRyMykpOworfQorCitzdGF0aWMgaW50IGR3X2Vk bWFfdGVzdF9zZyh2b2lkICpkYXRhKQoreworCXN0cnVjdCBkd19lZG1hX3Rlc3RfdGhyZWFkICp0 aHJlYWQgPSBkYXRhOworCXN0cnVjdCBkd19lZG1hX3Rlc3RfZG9uZSAqZG9uZSA9ICZ0aHJlYWQt PnRlc3RfZG9uZTsKKwlzdHJ1Y3QgZHdfZWRtYV90ZXN0X2luZm8gKmluZm8gPSB0aHJlYWQtPmlu Zm87CisJc3RydWN0IGR3X2VkbWFfdGVzdF9wYXJhbXMgKnBhcmFtcyA9ICZpbmZvLT5wYXJhbXM7 CisJc3RydWN0IGRtYV9jaGFuCSpjaGFuID0gdGhyZWFkLT5jaGFuOworCXN0cnVjdCBkZXZpY2Ug KmRldiA9IGNoYW4tPmRldmljZS0+ZGV2OworCXN0cnVjdCBkd19lZG1hX3JlZ2lvbiAqZHRfcmVn aW9uID0gY2hhbi0+cHJpdmF0ZTsKKwl1MzIgcmVtX2xlbiA9IHBhcmFtcy0+YnVmX3N6OworCXUz MiBmX3BycF9jbnQgPSAwOworCXUzMiBmX3NidF9jbnQgPSAwOworCXUzMiBmX3RtX2NudCA9IDA7 CisJdTMyIGZfY3BsX2VyciA9IDA7CisJdTMyIGZfY3BsX2JzeSA9IDA7CisJZG1hX2Nvb2tpZV90 IGNvb2tpZTsKKwllbnVtIGRtYV9zdGF0dXMgc3RhdHVzOworCXN0cnVjdCBkd19lZG1hX3JlZ2lv biAqZGVzY3M7CisJc3RydWN0IHNnX3RhYmxlCSpzZ3Q7CisJc3RydWN0IHNjYXR0ZXJsaXN0ICpz ZzsKKwlzdHJ1Y3QgZG1hX3NsYXZlX2NvbmZpZwlzY29uZjsKKwlzdHJ1Y3QgZG1hX2FzeW5jX3R4 X2Rlc2NyaXB0b3IgKnR4ZGVzYzsKKwlpbnQgaSwgc2dzLCBlcnIgPSAwOworCisJc2V0X2ZyZWV6 YWJsZSgpOworCXNldF91c2VyX25pY2UoY3VycmVudCwgMTApOworCisJLyogQ2FsY3VsYXRlcyB0 aGUgbWF4aW11bSBudW1iZXIgb2Ygc2VnbWVudHMgKi8KKwlzZ3MgPSBESVZfUk9VTkRfVVAocGFy YW1zLT5idWZfc3osIHBhcmFtcy0+YnVmX3NlZyk7CisKKwlpZiAoIXNncykKKwkJZ290byBlcnJf ZW5kOworCisJLyogQWxsb2NhdGUgc2NhdHRlci1nYXRoZXIgdGFibGUgKi8KKwlzZ3QgPSBrdm1h bGxvYyhzaXplb2YoKnNndCksIEdGUF9LRVJORUwpOworCWlmICghc2d0KQorCQlnb3RvIGVycl9l bmQ7CisKKwllcnIgPSBzZ19hbGxvY190YWJsZShzZ3QsIHNncywgR0ZQX0tFUk5FTCk7CisJaWYg KGVycikKKwkJZ290byBlcnJfc2dfYWxsb2NfdGFibGU7CisKKwlzZyA9ICZzZ3QtPnNnbFswXTsK KwlpZiAoIXNnKQorCQlnb3RvIGVycl9hbGxvY19kZXNjczsKKworCS8qCisJICogQWxsb2NhdGUg c3RydWN0dXJlIHRvIGhvbGQgYWxsIHNjYXR0ZXItZ2F0aGVyIHNlZ21lbnRzIChzaXplLAorCSAq IHZpcnR1YWwgYW5kIHBoeXNpY2FsIGFkZHJlc3NlcykKKwkgKi8KKwlkZXNjcyA9IGRldm1fa2Nh bGxvYyhkZXYsIHNncywgc2l6ZW9mKCpkZXNjcyksIEdGUF9LRVJORUwpOworCWlmICghZGVzY3Mp CisJCWdvdG8gZXJyX2FsbG9jX2Rlc2NzOworCisJZm9yIChpID0gMDsgc2cgJiYgaSA8IHNnczsg aSsrKSB7CisJCWRlc2NzW2ldLnBhZGRyID0gMDsKKwkJZGVzY3NbaV0uc3ogPSBtaW4ocmVtX2xl biwgcGFyYW1zLT5idWZfc2VnKTsKKwkJcmVtX2xlbiAtPSBkZXNjc1tpXS5zejsKKworCQlkZXNj c1tpXS52YWRkciA9IChkbWFfYWRkcl90KWRtYV9hbGxvY19jb2hlcmVudChkZXYsCisJCQkJCQkJ CWRlc2NzW2ldLnN6LAorCQkJCQkJCQkmZGVzY3NbaV0ucGFkZHIsCisJCQkJCQkJCUdGUF9LRVJO RUwpOworCQlpZiAoIWRlc2NzW2ldLnZhZGRyIHx8ICFkZXNjc1tpXS5wYWRkcikgeworCQkJZGV2 X2VycihkZXYsICIlczogKCV1KWZhaWwgdG8gYWxsb2NhdGUgJXUgYnl0ZXNcbiIsCisJCQkJZG1h X2NoYW5fbmFtZShjaGFuKSwgaSwJZGVzY3NbaV0uc3opOworCQkJZ290byBlcnJfZGVzY3M7CisJ CX0KKworCQlkZXZfZGJnKGRldiwgIiVzOiBDUFU6IHNlZ21lbnQgJXUsIGFkZHIodj0lcGEsIHA9 JXBhKVxuIiwKKwkJCWRtYV9jaGFuX25hbWUoY2hhbiksIGksCisJCQkmZGVzY3NbaV0udmFkZHIs ICZkZXNjc1tpXS5wYWRkcik7CisKKwkJc2dfc2V0X2J1ZihzZywgKHZvaWQgKilkZXNjc1tpXS5w YWRkciwgZGVzY3NbaV0uc3opOworCQlzZyA9IHNnX25leHQoc2cpOworCX0KKworCS8qIER1bXBz IHRoZSBmaXJzdCBzZWdtZW50IG1lbW9yeSAqLworCWlmIChwYXJhbXMtPmR1bXBfbWVtKQorCQlk d19lZG1hX3Rlc3RfZHVtcChkZXYsIHRocmVhZC0+ZGlyZWN0aW9uLCBwYXJhbXMtPmR1bXBfc3os CisJCQkJICBkdF9yZWdpb24sICZkZXNjc1swXSk7CisKKwkvKiBGaWxscyBDUFUgbWVtb3J5IHdp dGggYSBrbm93biBwYXR0ZXJuICovCisJaWYgKHBhcmFtcy0+cGF0dGVybikKKwkJZHdfZWRtYV90 ZXN0X21lbXNldChkZXNjc1swXS52YWRkciwgcGFyYW1zLT5idWZfc3opOworCisJLyoKKwkgKiBD b25maWd1cmVzIERNQSBjaGFubmVsIGFjY29yZGluZyB0byB0aGUgZGlyZWN0aW9uCisJICogIC0g ZmxhZ3MKKwkgKiAgLSBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGFkZHJlc3NlcworCSAqLworCWlm ICh0aHJlYWQtPmRpcmVjdGlvbiA9PSBETUFfREVWX1RPX01FTSkgeworCQkvKiBETUFfREVWX1RP X01FTSAtIFdSSVRFIC0gRE1BX0ZST01fREVWSUNFICovCisJCWRldl9kYmcoZGV2LCAiJXM6IERN QV9ERVZfVE9fTUVNIC0gV1JJVEUgLSBETUFfRlJPTV9ERVZJQ0VcbiIsCisJCQlkbWFfY2hhbl9u YW1lKGNoYW4pKTsKKwkJZXJyID0gZG1hX21hcF9zZyhkZXYsIHNndC0+c2dsLCBzZ3QtPm5lbnRz LCBETUFfRlJPTV9ERVZJQ0UpOworCQlpZiAoIWVycikKKwkJCWdvdG8gZXJyX2Rlc2NzOworCisJ CXNndC0+bmVudHMgPSBlcnI7CisJCS8qIEVuZHBvaW50IG1lbW9yeSAqLworCQlzY29uZi5zcmNf YWRkciA9IGR0X3JlZ2lvbi0+cGFkZHI7CisJCS8qIENQVSBtZW1vcnkgKi8KKwkJc2NvbmYuZHN0 X2FkZHIgPSBkZXNjc1swXS5wYWRkcjsKKwl9IGVsc2UgeworCQkvKiBETUFfTUVNX1RPX0RFViAt IFJFQUQgLSBETUFfVE9fREVWSUNFICovCisJCWRldl9kYmcoZGV2LCAiJXM6IERNQV9NRU1fVE9f REVWIC0gUkVBRCAtIERNQV9UT19ERVZJQ0VcbiIsCisJCQlkbWFfY2hhbl9uYW1lKGNoYW4pKTsK KwkJZXJyID0gZG1hX21hcF9zZyhkZXYsIHNndC0+c2dsLCBzZ3QtPm5lbnRzLCBETUFfVE9fREVW SUNFKTsKKwkJaWYgKCFlcnIpCisJCQlnb3RvIGVycl9kZXNjczsKKworCQlzZ3QtPm5lbnRzID0g ZXJyOworCQkvKiBDUFUgbWVtb3J5ICovCisJCXNjb25mLnNyY19hZGRyID0gZGVzY3NbMF0ucGFk ZHI7CisJCS8qIEVuZHBvaW50IG1lbW9yeSAqLworCQlzY29uZi5kc3RfYWRkciA9IGR0X3JlZ2lv bi0+cGFkZHI7CisJfQorCisJZG1hZW5naW5lX3NsYXZlX2NvbmZpZyhjaGFuLCAmc2NvbmYpOwor CWRldl9kYmcoZGV2LCAiJXM6IGFkZHIocGh5c2ljYWwpIHNyYz0lcGEsIGRzdD0lcGFcbiIsCisJ CWRtYV9jaGFuX25hbWUoY2hhbiksICZzY29uZi5zcmNfYWRkciwgJnNjb25mLmRzdF9hZGRyKTsK KwlkZXZfZGJnKGRldiwgIiVzOiBsZW49JXUgYnl0ZXMsIHNncz0ldSwgc2VnX3N6PSV1IGJ5dGVz XG4iLAorCQlkbWFfY2hhbl9uYW1lKGNoYW4pLCBwYXJhbXMtPmJ1Zl9zeiwgc2dzLCBwYXJhbXMt PmJ1Zl9zZWcpOworCisJLyoKKwkgKiBQcmVwYXJlIHRoZSBETUEgY2hhbm5lbCBmb3IgdGhlIHRy YW5zZmVyCisJICogIC0gcHJvdmlkZSBzY2F0dGVyLWdhdGhlciBsaXN0CisJICogIC0gY29uZmln dXJlIHRvIHRyaWdnZXIgYW4gaW50ZXJydXB0IGFmdGVyIHRoZSB0cmFuc2ZlcgorCSAqLworCXR4 ZGVzYyA9IGRtYWVuZ2luZV9wcmVwX3NsYXZlX3NnKGNoYW4sIHNndC0+c2dsLCBzZ3QtPm5lbnRz LAorCQkJCQkgdGhyZWFkLT5kaXJlY3Rpb24sCisJCQkJCSBETUFfUFJFUF9JTlRFUlJVUFQpOwor CWlmICghdHhkZXNjKSB7CisJCWRldl9kYmcoZGV2LCAiJXM6IGRtYWVuZ2luZV9wcmVwX3NsYXZl X3NnXG4iLAorCQkJZG1hX2NoYW5fbmFtZShjaGFuKSk7CisJCWZfcHJwX2NudCsrOworCQlnb3Rv IGVycl9zdGF0czsKKwl9CisKKwlkb25lLT5kb25lID0gZmFsc2U7CisJdHhkZXNjLT5jYWxsYmFj ayA9IGR3X2VkbWFfdGVzdF9jYWxsYmFjazsKKwl0eGRlc2MtPmNhbGxiYWNrX3BhcmFtID0gZG9u ZTsKKwljb29raWUgPSBkbWFlbmdpbmVfc3VibWl0KHR4ZGVzYyk7CisJaWYgKGRtYV9zdWJtaXRf ZXJyb3IoY29va2llKSkgeworCQlkZXZfZGJnKGRldiwgIiVzOiBkbWFfc3VibWl0X2Vycm9yXG4i LCBkbWFfY2hhbl9uYW1lKGNoYW4pKTsKKwkJZl9zYnRfY250Kys7CisJCWdvdG8gZXJyX3N0YXRz OworCX0KKworCS8qIFN0YXJ0IERNQSB0cmFuc2ZlciAqLworCWRtYV9hc3luY19pc3N1ZV9wZW5k aW5nKGNoYW4pOworCisJLyogVGhyZWFkIHdhaXRzIGhlcmUgZm9yIHRyYW5zZmVyIGNvbXBsZXRp b24gb3IgZXhpc3RzIGJ5IHRpbWVvdXQgKi8KKwl3YWl0X2V2ZW50X2ZyZWV6YWJsZV90aW1lb3V0 KHRocmVhZC0+ZG9uZV93YWl0LCBkb25lLT5kb25lLAorCQkJCSAgICAgbXNlY3NfdG9famlmZmll cyhwYXJhbXMtPnRpbWVvdXQpKTsKKworCS8qIENoZWNrIERNQSB0cmFuc2ZlciBzdGF0dXMgYW5k IGFjdCB1cG9uIGl0ICAqLworCXN0YXR1cyA9IGRtYV9hc3luY19pc190eF9jb21wbGV0ZShjaGFu LCBjb29raWUsIE5VTEwsIE5VTEwpOworCWlmICghZG9uZS0+ZG9uZSkgeworCQlkZXZfZGJnKGRl diwgIiVzOiB0aW1lb3V0XG4iLCBkbWFfY2hhbl9uYW1lKGNoYW4pKTsKKwkJZl90bV9jbnQrKzsK Kwl9IGVsc2UgaWYgKHN0YXR1cyAhPSBETUFfQ09NUExFVEUpIHsKKwkJaWYgKHN0YXR1cyA9PSBE TUFfRVJST1IpIHsKKwkJCWRldl9kYmcoZGV2LCAiJXM6ICBjb21wbGV0aW9uIGVycm9yIHN0YXR1 c1xuIiwKKwkJCQlkbWFfY2hhbl9uYW1lKGNoYW4pKTsKKwkJCWZfY3BsX2VycisrOworCQl9IGVs c2UgeworCQkJZGV2X2RiZyhkZXYsICIlczogY29tcGxldGlvbiBidXN5IHN0YXR1c1xuIiwKKwkJ CQlkbWFfY2hhbl9uYW1lKGNoYW4pKTsKKwkJCWZfY3BsX2JzeSsrOworCQl9CisJfQorCitlcnJf c3RhdHM6CisJLyogRGlzcGxheSBzb21lIHN0YXRzIGluZm9ybWF0aW9uICovCisJaWYgKGZfcHJw X2NudCB8fCBmX3NidF9jbnQgfHwgZl90bV9jbnQgfHwgZl9jcGxfZXJyIHx8IGZfY3BsX2JzeSkg eworCQlkZXZfaW5mbyhkZXYsICIlczogdGVzdCBmYWlsZWQgLSBkbWFlbmdpbmVfcHJlcF9zbGF2 ZV9zZz0ldSwgZG1hX3N1Ym1pdF9lcnJvcj0ldSwgdGltZW91dD0ldSwgY29tcGxldGlvbiBlcnJv ciBzdGF0dXM9JXUsIGNvbXBsZXRpb24gYnVzeSBzdGF0dXM9JXVcbiIsCisJCQkgZG1hX2NoYW5f bmFtZShjaGFuKSwgZl9wcnBfY250LCBmX3NidF9jbnQsCisJCQkgZl90bV9jbnQsIGZfY3BsX2Vy ciwgZl9jcGxfYnN5KTsKKwl9IGVsc2UgeworCQlkZXZfaW5mbyhkZXYsICIlczogdGVzdCBwYXNz ZWRcbiIsIGRtYV9jaGFuX25hbWUoY2hhbikpOworCX0KKworCS8qIER1bXBzIHRoZSBmaXJzdCBz ZWdtZW50IG1lbW9yeSAqLworCWlmIChwYXJhbXMtPmR1bXBfbWVtKQorCQlkd19lZG1hX3Rlc3Rf ZHVtcChkZXYsIHRocmVhZC0+ZGlyZWN0aW9uLCBwYXJhbXMtPmR1bXBfc3osCisJCQkJICBkdF9y ZWdpb24sICZkZXNjc1swXSk7CisKKwkvKiBDaGVjayBpZiB0aGUgZGF0YSB3YXMgY29ycmVjdGx5 IHRyYW5zZmVyICovCisJaWYgKHBhcmFtcy0+Y2hlY2spIHsKKwkJZGV2X2luZm8oZGV2LCAiJXM6 IHBlcmZvcm1pbmcgY2hlY2tcbiIsIGRtYV9jaGFuX25hbWUoY2hhbikpOworCQllcnIgPSBkd19l ZG1hX3Rlc3RfY2hlY2soZGVzY3NbaV0udmFkZHIsIGR0X3JlZ2lvbi0+dmFkZHIsCisJCQkJCSBw YXJhbXMtPmJ1Zl9zeik7CisJCWlmIChlcnIpCisJCQlkZXZfaW5mbyhkZXYsICIlczogY2hlY2sg cGFzc1xuIiwgZG1hX2NoYW5fbmFtZShjaGFuKSk7CisJCWVsc2UKKwkJCWRldl9pbmZvKGRldiwg IiVzOiBjaGVjayBmYWlsXG4iLCBkbWFfY2hhbl9uYW1lKGNoYW4pKTsKKwl9CisKKwkvKiBUZXJt aW5hdGUgYW55IERNQSBvcGVyYXRpb24sIChmYWlsIHNhZmUpICovCisJZG1hZW5naW5lX3Rlcm1p bmF0ZV9hbGwoY2hhbik7CisKK2Vycl9kZXNjczoKKwlmb3IgKGkgPSAwOyBpIDwgc2dzICYmIGRl c2NzW2ldLnZhZGRyICYmIGRlc2NzW2ldLnBhZGRyOyBpKyspCisJCWRtYV9mcmVlX2NvaGVyZW50 KGRldiwgZGVzY3NbaV0uc3osICh2b2lkICopZGVzY3NbaV0udmFkZHIsCisJCQkJICBkZXNjc1tp XS5wYWRkcik7CisJZGV2bV9rZnJlZShkZXYsIGRlc2NzKTsKK2Vycl9hbGxvY19kZXNjczoKKwlz Z19mcmVlX3RhYmxlKHNndCk7CitlcnJfc2dfYWxsb2NfdGFibGU6CisJa3ZmcmVlKHNndCk7Citl cnJfZW5kOgorCXRocmVhZC0+ZG9uZSA9IHRydWU7CisJd2FrZV91cCgmdGhyZWFkX3dhaXQpOwor CisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgZHdfZWRtYV90ZXN0X2N5Y2xpYyh2b2lkICpk YXRhKQoreworCXN0cnVjdCBkd19lZG1hX3Rlc3RfdGhyZWFkICp0aHJlYWQgPSBkYXRhOworCXN0 cnVjdCBkd19lZG1hX3Rlc3RfZG9uZSAqZG9uZSA9ICZ0aHJlYWQtPnRlc3RfZG9uZTsKKwlzdHJ1 Y3QgZHdfZWRtYV90ZXN0X2luZm8gKmluZm8gPSB0aHJlYWQtPmluZm87CisJc3RydWN0IGR3X2Vk bWFfdGVzdF9wYXJhbXMgKnBhcmFtcyA9ICZpbmZvLT5wYXJhbXM7CisJc3RydWN0IGRtYV9jaGFu CSpjaGFuID0gdGhyZWFkLT5jaGFuOworCXN0cnVjdCBkZXZpY2UgKmRldiA9IGNoYW4tPmRldmlj ZS0+ZGV2OworCXN0cnVjdCBkd19lZG1hX3JlZ2lvbiAqZHRfcmVnaW9uID0gY2hhbi0+cHJpdmF0 ZTsKKwl1MzIgZl9wcnBfY250ID0gMDsKKwl1MzIgZl9zYnRfY250ID0gMDsKKwl1MzIgZl90bV9j bnQgPSAwOworCXUzMiBmX2NwbF9lcnIgPSAwOworCXUzMiBmX2NwbF9ic3kgPSAwOworCWRtYV9j b29raWVfdCBjb29raWU7CisJZW51bSBkbWFfc3RhdHVzIHN0YXR1czsKKwlzdHJ1Y3QgZHdfZWRt YV9yZWdpb24gZGVzYzsKKwlzdHJ1Y3QgZG1hX3NsYXZlX2NvbmZpZwlzY29uZjsKKwlzdHJ1Y3Qg ZG1hX2FzeW5jX3R4X2Rlc2NyaXB0b3IgKnR4ZGVzYzsKKwlpbnQgZXJyID0gMDsKKworCXNldF9m cmVlemFibGUoKTsKKwlzZXRfdXNlcl9uaWNlKGN1cnJlbnQsIDEwKTsKKworCWRlc2MucGFkZHIg PSAwOworCWRlc2Muc3ogPSBwYXJhbXMtPmJ1Zl9zZWc7CisJZGVzYy52YWRkciA9IChkbWFfYWRk cl90KWRtYV9hbGxvY19jb2hlcmVudChkZXYsIGRlc2Muc3osICZkZXNjLnBhZGRyLAorCQkJCQkJ ICAgIEdGUF9LRVJORUwpOworCWlmICghZGVzYy52YWRkciB8fCAhZGVzYy5wYWRkcikgeworCQlk ZXZfZXJyKGRldiwgIiVzOiBmYWlsIHRvIGFsbG9jYXRlICV1IGJ5dGVzXG4iLAorCQkJZG1hX2No YW5fbmFtZShjaGFuKSwgZGVzYy5zeik7CisJCWdvdG8gZXJyX2VuZDsKKwl9CisKKwlkZXZfZGJn KGRldiwgIiVzOiBDUFU6IGFkZHIodj0lcGEsIHA9JXBhKVxuIiwKKwkJZG1hX2NoYW5fbmFtZShj aGFuKSwgJmRlc2MudmFkZHIsICZkZXNjLnBhZGRyKTsKKworCS8qIER1bXBzIHRoZSBmaXJzdCBz ZWdtZW50IG1lbW9yeSAqLworCWlmIChwYXJhbXMtPmR1bXBfbWVtKQorCQlkd19lZG1hX3Rlc3Rf ZHVtcChkZXYsIHRocmVhZC0+ZGlyZWN0aW9uLCBwYXJhbXMtPmR1bXBfc3osCisJCQkJICBkdF9y ZWdpb24sICZkZXNjKTsKKworCS8qIEZpbGxzIENQVSBtZW1vcnkgd2l0aCBhIGtub3duIHBhdHRl cm4gKi8KKwlpZiAocGFyYW1zLT5wYXR0ZXJuKQorCQlkd19lZG1hX3Rlc3RfbWVtc2V0KGRlc2Mu dmFkZHIsIHBhcmFtcy0+YnVmX3N6KTsKKworCS8qCisJICogQ29uZmlndXJlcyBETUEgY2hhbm5l bCBhY2NvcmRpbmcgdG8gdGhlIGRpcmVjdGlvbgorCSAqICAtIGZsYWdzCisJICogIC0gc291cmNl IGFuZCBkZXN0aW5hdGlvbiBhZGRyZXNzZXMKKwkgKi8KKwlpZiAodGhyZWFkLT5kaXJlY3Rpb24g PT0gRE1BX0RFVl9UT19NRU0pIHsKKwkJLyogRE1BX0RFVl9UT19NRU0gLSBXUklURSAtIERNQV9G Uk9NX0RFVklDRSAqLworCQlkZXZfZGJnKGRldiwgIiVzOiBETUFfREVWX1RPX01FTSAtIFdSSVRF IC0gRE1BX0ZST01fREVWSUNFXG4iLAorCQkJZG1hX2NoYW5fbmFtZShjaGFuKSk7CisKKwkJLyog RW5kcG9pbnQgbWVtb3J5ICovCisJCXNjb25mLnNyY19hZGRyID0gZHRfcmVnaW9uLT5wYWRkcjsK KwkJLyogQ1BVIG1lbW9yeSAqLworCQlzY29uZi5kc3RfYWRkciA9IGRlc2MucGFkZHI7CisJfSBl bHNlIHsKKwkJLyogRE1BX01FTV9UT19ERVYgLSBSRUFEIC0gRE1BX1RPX0RFVklDRSAqLworCQlk ZXZfZGJnKGRldiwgIiVzOiBETUFfTUVNX1RPX0RFViAtIFJFQUQgLSBETUFfVE9fREVWSUNFXG4i LAorCQkJZG1hX2NoYW5fbmFtZShjaGFuKSk7CisKKwkJLyogQ1BVIG1lbW9yeSAqLworCQlzY29u Zi5zcmNfYWRkciA9IGRlc2MucGFkZHI7CisJCS8qIEVuZHBvaW50IG1lbW9yeSAqLworCQlzY29u Zi5kc3RfYWRkciA9IGR0X3JlZ2lvbi0+cGFkZHI7CisJfQorCisJZG1hZW5naW5lX3NsYXZlX2Nv bmZpZyhjaGFuLCAmc2NvbmYpOworCWRldl9kYmcoZGV2LCAiJXM6IGFkZHIocGh5c2ljYWwpIHNy Yz0lcGEsIGRzdD0lcGFcbiIsCisJCWRtYV9jaGFuX25hbWUoY2hhbiksICZzY29uZi5zcmNfYWRk ciwgJnNjb25mLmRzdF9hZGRyKTsKKwlkZXZfZGJnKGRldiwgIiVzOiBsZW49JXUgYnl0ZXNcbiIs CisJCWRtYV9jaGFuX25hbWUoY2hhbiksIHBhcmFtcy0+YnVmX3N6KTsKKworCS8qCisJICogUHJl cGFyZSB0aGUgRE1BIGNoYW5uZWwgZm9yIHRoZSB0cmFuc2ZlcgorCSAqICAtIHByb3ZpZGUgYnVm ZmVyLCBzaXplIGFuZCBudW1iZXIgb2YgcmVwZXRpdGlvbnMKKwkgKiAgLSBjb25maWd1cmUgdG8g dHJpZ2dlciBhbiBpbnRlcnJ1cHQgYWZ0ZXIgdGhlIHRyYW5zZmVyCisJICovCisJdHhkZXNjID0g ZG1hZW5naW5lX3ByZXBfZG1hX2N5Y2xpYyhjaGFuLCBkZXNjLnZhZGRyLCBkZXNjLnN6LAorCQkJ CQkgICBwYXJhbXMtPnJlcGV0aXRpb25zLAorCQkJCQkgICB0aHJlYWQtPmRpcmVjdGlvbiwKKwkJ CQkJICAgRE1BX1BSRVBfSU5URVJSVVBUKTsKKwlpZiAoIXR4ZGVzYykgeworCQlkZXZfZGJnKGRl diwgIiVzOiBkbWFlbmdpbmVfcHJlcF9zbGF2ZV9zZ1xuIiwKKwkJCWRtYV9jaGFuX25hbWUoY2hh bikpOworCQlmX3BycF9jbnQrKzsKKwkJZ290byBlcnJfc3RhdHM7CisJfQorCisJZG9uZS0+ZG9u ZSA9IGZhbHNlOworCXR4ZGVzYy0+Y2FsbGJhY2sgPSBkd19lZG1hX3Rlc3RfY2FsbGJhY2s7CisJ dHhkZXNjLT5jYWxsYmFja19wYXJhbSA9IGRvbmU7CisJY29va2llID0gZG1hZW5naW5lX3N1Ym1p dCh0eGRlc2MpOworCWlmIChkbWFfc3VibWl0X2Vycm9yKGNvb2tpZSkpIHsKKwkJZGV2X2RiZyhk ZXYsICIlczogZG1hX3N1Ym1pdF9lcnJvclxuIiwgZG1hX2NoYW5fbmFtZShjaGFuKSk7CisJCWZf c2J0X2NudCsrOworCQlnb3RvIGVycl9zdGF0czsKKwl9CisKKwkvKiBTdGFydCBETUEgdHJhbnNm ZXIgKi8KKwlkbWFfYXN5bmNfaXNzdWVfcGVuZGluZyhjaGFuKTsKKworCS8qIFRocmVhZCB3YWl0 cyBoZXJlIGZvciB0cmFuc2ZlciBjb21wbGV0aW9uIG9yIGV4aXN0cyBieSB0aW1lb3V0ICovCisJ d2FpdF9ldmVudF9mcmVlemFibGVfdGltZW91dCh0aHJlYWQtPmRvbmVfd2FpdCwgZG9uZS0+ZG9u ZSwKKwkJCQkgICAgIG1zZWNzX3RvX2ppZmZpZXMocGFyYW1zLT50aW1lb3V0KSk7CisKKwkvKiBD aGVjayBETUEgdHJhbnNmZXIgc3RhdHVzIGFuZCBhY3QgdXBvbiBpdCAqLworCXN0YXR1cyA9IGRt YV9hc3luY19pc190eF9jb21wbGV0ZShjaGFuLCBjb29raWUsIE5VTEwsIE5VTEwpOworCWlmICgh ZG9uZS0+ZG9uZSkgeworCQlkZXZfZGJnKGRldiwgIiVzOiB0aW1lb3V0XG4iLCBkbWFfY2hhbl9u YW1lKGNoYW4pKTsKKwkJZl90bV9jbnQrKzsKKwl9IGVsc2UgaWYgKHN0YXR1cyAhPSBETUFfQ09N UExFVEUpIHsKKwkJaWYgKHN0YXR1cyA9PSBETUFfRVJST1IpIHsKKwkJCWRldl9kYmcoZGV2LCAi JXM6ICBjb21wbGV0aW9uIGVycm9yIHN0YXR1c1xuIiwKKwkJCQlkbWFfY2hhbl9uYW1lKGNoYW4p KTsKKwkJCWZfY3BsX2VycisrOworCQl9IGVsc2UgeworCQkJZGV2X2RiZyhkZXYsICIlczogY29t cGxldGlvbiBidXN5IHN0YXR1c1xuIiwKKwkJCQlkbWFfY2hhbl9uYW1lKGNoYW4pKTsKKwkJCWZf Y3BsX2JzeSsrOworCQl9CisJfQorCitlcnJfc3RhdHM6CisJLyogRGlzcGxheSBzb21lIHN0YXRz IGluZm9ybWF0aW9uICovCisJaWYgKGZfcHJwX2NudCB8fCBmX3NidF9jbnQgfHwgZl90bV9jbnQg fHwgZl9jcGxfZXJyIHx8IGZfY3BsX2JzeSkgeworCQlkZXZfaW5mbyhkZXYsICIlczogdGVzdCBm YWlsZWQgLSBkbWFlbmdpbmVfcHJlcF9zbGF2ZV9zZz0ldSwgZG1hX3N1Ym1pdF9lcnJvcj0ldSwg dGltZW91dD0ldSwgY29tcGxldGlvbiBlcnJvciBzdGF0dXM9JXUsIGNvbXBsZXRpb24gYnVzeSBz dGF0dXM9JXVcbiIsCisJCQkgZG1hX2NoYW5fbmFtZShjaGFuKSwgZl9wcnBfY250LCBmX3NidF9j bnQsCisJCQkgZl90bV9jbnQsIGZfY3BsX2VyciwgZl9jcGxfYnN5KTsKKwl9IGVsc2UgeworCQlk ZXZfaW5mbyhkZXYsICIlczogdGVzdCBwYXNzZWRcbiIsIGRtYV9jaGFuX25hbWUoY2hhbikpOwor CX0KKworCS8qIER1bXBzIHRoZSBmaXJzdCBzZWdtZW50IG1lbW9yeSAqLworCWlmIChwYXJhbXMt PmR1bXBfbWVtKQorCQlkd19lZG1hX3Rlc3RfZHVtcChkZXYsIHRocmVhZC0+ZGlyZWN0aW9uLCBw YXJhbXMtPmR1bXBfc3osCisJCQkJICBkdF9yZWdpb24sICZkZXNjKTsKKworCS8qIENoZWNrIGlm IHRoZSBkYXRhIHdhcyBjb3JyZWN0bHkgdHJhbnNmZXIgKi8KKwlpZiAocGFyYW1zLT5jaGVjaykg eworCQlkZXZfaW5mbyhkZXYsICIlczogcGVyZm9ybWluZyBjaGVja1xuIiwgZG1hX2NoYW5fbmFt ZShjaGFuKSk7CisJCWVyciA9IGR3X2VkbWFfdGVzdF9jaGVjayhkZXNjLnZhZGRyLCBkdF9yZWdp b24tPnZhZGRyLAorCQkJCQkgcGFyYW1zLT5idWZfc3opOworCQlpZiAoZXJyKQorCQkJZGV2X2lu Zm8oZGV2LCAiJXM6IGNoZWNrIHBhc3NcbiIsIGRtYV9jaGFuX25hbWUoY2hhbikpOworCQllbHNl CisJCQlkZXZfaW5mbyhkZXYsICIlczogY2hlY2sgZmFpbFxuIiwgZG1hX2NoYW5fbmFtZShjaGFu KSk7CisJfQorCisJLyogVGVybWluYXRlIGFueSBETUEgb3BlcmF0aW9uLCAoZmFpbCBzYWZlKSAq LworCWRtYWVuZ2luZV90ZXJtaW5hdGVfYWxsKGNoYW4pOworCisJZG1hX2ZyZWVfY29oZXJlbnQo ZGV2LCBkZXNjLnN6LCAodm9pZCAqKWRlc2MudmFkZHIsIGRlc2MucGFkZHIpOworZXJyX2VuZDoK Kwl0aHJlYWQtPmRvbmUgPSB0cnVlOworCXdha2VfdXAoJnRocmVhZF93YWl0KTsKKworCXJldHVy biAwOworfQorCitzdGF0aWMgaW50IGR3X2VkbWFfdGVzdF9hZGRfY2hhbm5lbChzdHJ1Y3QgZHdf ZWRtYV90ZXN0X2luZm8gKmluZm8sCisJCQkJICAgIHN0cnVjdCBkbWFfY2hhbiAqY2hhbiwKKwkJ CQkgICAgdTMyIGNoYW5uZWwpCit7CisJc3RydWN0IGR3X2VkbWFfdGVzdF9wYXJhbXMgKnBhcmFt cyA9ICZpbmZvLT5wYXJhbXM7CisJc3RydWN0IGR3X2VkbWFfdGVzdF90aHJlYWQgKnRocmVhZDsK KwlzdHJ1Y3QgZHdfZWRtYV90ZXN0X2NoYW4gKnRjaGFuOworCisJdGNoYW4gPSBrdm1hbGxvYyhz aXplb2YoKnRjaGFuKSwgR0ZQX0tFUk5FTCk7CisJaWYgKCF0Y2hhbikKKwkJcmV0dXJuIC1FTk9N RU07CisKKwl0Y2hhbi0+Y2hhbiA9IGNoYW47CisKKwl0aHJlYWQgPSBrdnphbGxvYyhzaXplb2Yo KnRocmVhZCksIEdGUF9LRVJORUwpOworCWlmICghdGhyZWFkKSB7CisJCWt2ZnJlZSh0Y2hhbik7 CisJCXJldHVybiAtRU5PTUVNOworCX0KKworCXRocmVhZC0+aW5mbyA9IGluZm87CisJdGhyZWFk LT5jaGFuID0gdGNoYW4tPmNoYW47CisJc3dpdGNoIChjaGFubmVsKSB7CisJY2FzZSBFRE1BX0NI X1dSOgorCQl0aHJlYWQtPmRpcmVjdGlvbiA9IERNQV9ERVZfVE9fTUVNOworCQlicmVhazsKKwlj YXNlIEVETUFfQ0hfUkQ6CisJCXRocmVhZC0+ZGlyZWN0aW9uID0gRE1BX01FTV9UT19ERVY7CisJ CWJyZWFrOworCWRlZmF1bHQ6CisJCWt2ZnJlZSh0Y2hhbik7CisJCXJldHVybiAtRVBFUk07CisJ fQorCXRocmVhZC0+dGVzdF9kb25lLndhaXQgPSAmdGhyZWFkLT5kb25lX3dhaXQ7CisJaW5pdF93 YWl0cXVldWVfaGVhZCgmdGhyZWFkLT5kb25lX3dhaXQpOworCisJaWYgKCFwYXJhbXMtPnJlcGV0 aXRpb25zKQorCQl0aHJlYWQtPnRhc2sgPSBrdGhyZWFkX2NyZWF0ZShkd19lZG1hX3Rlc3Rfc2cs IHRocmVhZCwgIiVzIiwKKwkJCQkJICAgICAgZG1hX2NoYW5fbmFtZShjaGFuKSk7CisJZWxzZQor CQl0aHJlYWQtPnRhc2sgPSBrdGhyZWFkX2NyZWF0ZShkd19lZG1hX3Rlc3RfY3ljbGljLCB0aHJl YWQsICIlcyIsCisJCQkJCSAgICAgIGRtYV9jaGFuX25hbWUoY2hhbikpOworCisJaWYgKElTX0VS Uih0aHJlYWQtPnRhc2spKSB7CisJCXByX2VycigiZmFpbGVkIHRvIGNyZWF0ZSB0aHJlYWQgJXNc biIsIGRtYV9jaGFuX25hbWUoY2hhbikpOworCQlrdmZyZWUodGNoYW4pOworCQlrdmZyZWUodGhy ZWFkKTsKKwkJcmV0dXJuIC1FUEVSTTsKKwl9CisKKwl0Y2hhbi0+dGhyZWFkID0gdGhyZWFkOwor CWRldl9kYmcoY2hhbi0+ZGV2aWNlLT5kZXYsICJhZGQgdGhyZWFkICVzXG4iLCBkbWFfY2hhbl9u YW1lKGNoYW4pKTsKKwlsaXN0X2FkZF90YWlsKCZ0Y2hhbi0+bm9kZSwgJmluZm8tPmNoYW5uZWxz KTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgdm9pZCBkd19lZG1hX3Rlc3RfZGVsX2NoYW5u ZWwoc3RydWN0IGR3X2VkbWFfdGVzdF9jaGFuICp0Y2hhbikKK3sKKwlzdHJ1Y3QgZHdfZWRtYV90 ZXN0X3RocmVhZCAqdGhyZWFkID0gdGNoYW4tPnRocmVhZDsKKworCWt0aHJlYWRfc3RvcCh0aHJl YWQtPnRhc2spOworCWRldl9kYmcodGNoYW4tPmNoYW4tPmRldmljZS0+ZGV2LCAidGhyZWFkICVz IGV4aXRlZFxuIiwKKwkJdGhyZWFkLT50YXNrLT5jb21tKTsKKwlwdXRfdGFza19zdHJ1Y3QodGhy ZWFkLT50YXNrKTsKKwlrdmZyZWUodGhyZWFkKTsKKwl0Y2hhbi0+dGhyZWFkID0gTlVMTDsKKwor CWRtYWVuZ2luZV90ZXJtaW5hdGVfYWxsKHRjaGFuLT5jaGFuKTsKKwlrdmZyZWUodGNoYW4pOwor fQorCitzdGF0aWMgdm9pZCBkd19lZG1hX3Rlc3RfcnVuX2NoYW5uZWwoc3RydWN0IGR3X2VkbWFf dGVzdF9jaGFuICp0Y2hhbikKK3sKKwlzdHJ1Y3QgZHdfZWRtYV90ZXN0X3RocmVhZCAqdGhyZWFk ID0gdGNoYW4tPnRocmVhZDsKKworCWdldF90YXNrX3N0cnVjdCh0aHJlYWQtPnRhc2spOworCXdh a2VfdXBfcHJvY2Vzcyh0aHJlYWQtPnRhc2spOworCWRldl9kYmcodGNoYW4tPmNoYW4tPmRldmlj ZS0+ZGV2LCAidGhyZWFkICVzIHN0YXJ0ZWRcbiIsCisJCXRocmVhZC0+dGFzay0+Y29tbSk7Cit9 CisKK3N0YXRpYyBib29sIGR3X2VkbWFfdGVzdF9maWx0ZXIoc3RydWN0IGRtYV9jaGFuICpjaGFu LCB2b2lkICpmaWx0ZXIpCit7CisJaWYgKHN0cmNtcChkZXZfbmFtZShjaGFuLT5kZXZpY2UtPmRl diksIEVETUFfVEVTVF9ERVZJQ0VfTkFNRSkgfHwKKwkgICAgc3RyY21wKGRtYV9jaGFuX25hbWUo Y2hhbiksIGZpbHRlcikpCisJCXJldHVybiBmYWxzZTsKKworCXJldHVybiB0cnVlOworfQorCitz dGF0aWMgdm9pZCBkd19lZG1hX3Rlc3RfdGhyZWFkX2NyZWF0ZShzdHJ1Y3QgZHdfZWRtYV90ZXN0 X2luZm8gKmluZm8pCit7CisJc3RydWN0IGR3X2VkbWFfdGVzdF9wYXJhbXMgKnBhcmFtcyA9ICZp bmZvLT5wYXJhbXM7CisJc3RydWN0IGRtYV9jaGFuICpjaGFuOworCXN0cnVjdCBkd19lZG1hX3Jl Z2lvbiAqZHRfcmVnaW9uOworCWRtYV9jYXBfbWFza190IG1hc2s7CisJY2hhciBmaWx0ZXJbMjBd OworCWludCBpLCBqOworCisJcGFyYW1zLT5udW1fdGhyZWFkc1tFRE1BX0NIX1dSXSA9IG1pbl90 KHUzMiwKKwkJCQkJCUVETUFfVEVTVF9NQVhfVEhSRUFEU19DSEFOTkVMLAorCQkJCQkJd3JfdGhy ZWFkcyk7CisJcGFyYW1zLT5udW1fdGhyZWFkc1tFRE1BX0NIX1JEXSA9IG1pbl90KHUzMiwKKwkJ CQkJCUVETUFfVEVTVF9NQVhfVEhSRUFEU19DSEFOTkVMLAorCQkJCQkJcmRfdGhyZWFkcyk7CisJ cGFyYW1zLT5yZXBldGl0aW9ucyA9IHJlcGV0aXRpb25zOworCXBhcmFtcy0+dGltZW91dCA9IHRp bWVvdXQ7CisJcGFyYW1zLT5wYXR0ZXJuID0gcGF0dGVybjsKKwlwYXJhbXMtPmR1bXBfbWVtID0g ZHVtcF9tZW07CisJcGFyYW1zLT5kdW1wX3N6ID0gZHVtcF9zejsKKwlwYXJhbXMtPmNoZWNrID0g Y2hlY2s7CisJcGFyYW1zLT5idWZfc3ogPSBidWZfc3o7CisJcGFyYW1zLT5idWZfc2VnID0gbWlu KGJ1Zl9zZWcsIGJ1Zl9zeik7CisKKyNpZm5kZWYgQ09ORklHX0NNQV9TSVpFX01CWVRFUworCXBy X3dhcm4oIkNNQSBub3QgcHJlc2VudC9hY3RpdmF0ZWQhIENvbnRpZ3VvdXMgTWVtb3J5IG1heSBm YWlsIHRvIGJlIGFsbG9jdGVkXG4iKTsKKyNlbmRpZgorCisJcHJfaW5mbygiTnVtYmVyIG9mIHdy aXRlIHRocmVhZHMgPSAldVxuIiwgd3JfdGhyZWFkcyk7CisJcHJfaW5mbygiTnVtYmVyIG9mIHJl YWQgdGhyZWFkcyA9ICV1XG4iLCByZF90aHJlYWRzKTsKKwlpZiAoIXBhcmFtcy0+cmVwZXRpdGlv bnMpCisJCXByX2luZm8oIlNjYXR0ZXItZ2F0aGVyIG1vZGVcbiIpOworCWVsc2UKKwkJcHJfaW5m bygiQ3ljbGljIG1vZGUgKHJlcGV0aXRpb25zIHBlciB0aHJlYWQgJXUpXG4iLAorCQkJcGFyYW1z LT5yZXBldGl0aW9ucyk7CisJcHJfaW5mbygiVGltZW91dCA9ICV1IG1zXG4iLCBwYXJhbXMtPnRp bWVvdXQpOworCXByX2luZm8oIlVzZSBwYXR0ZXJuID0gJXNcbiIsIHBhcmFtcy0+cGF0dGVybiA/ ICJ0cnVlIiA6ICJmYWxzZSIpOworCXByX2luZm8oIkR1bXAgbWVtb3J5ID0gJXNcbiIsIHBhcmFt cy0+ZHVtcF9tZW0gPyAidHJ1ZSIgOiAiZmFsc2UiKTsKKwlwcl9pbmZvKCJQZXJmb3JtIGNoZWNr ID0gJXNcbiIsIHBhcmFtcy0+Y2hlY2sgPyAidHJ1ZSIgOiAiZmFsc2UiKTsKKworCWRtYV9jYXBf emVybyhtYXNrKTsKKwlkbWFfY2FwX3NldChETUFfU0xBVkUsIG1hc2spOworCWRtYV9jYXBfc2V0 KERNQV9DWUNMSUMsIG1hc2spOworCisJZm9yIChpID0gMDsgaSA8IEVETUFfQ0hfRU5EOyBpKysp IHsKKwkJZm9yIChqID0gMDsgaiA8IHBhcmFtcy0+bnVtX3RocmVhZHNbaV07IGorKykgeworCQkJ c25wcmludGYoZmlsdGVyLCBzaXplb2YoZmlsdGVyKSwKKwkJCQkgRURNQV9URVNUX0NIQU5ORUxf TkFNRSwgaSwgaik7CisKKwkJCWNoYW4gPSBkbWFfcmVxdWVzdF9jaGFubmVsKG1hc2ssIGR3X2Vk bWFfdGVzdF9maWx0ZXIsCisJCQkJCQkgICBmaWx0ZXIpOworCQkJaWYgKCFjaGFuKQorCQkJCWNv bnRpbnVlOworCisJCQlpZiAoZHdfZWRtYV90ZXN0X2FkZF9jaGFubmVsKGluZm8sIGNoYW4sIGkp KSB7CisJCQkJZG1hX3JlbGVhc2VfY2hhbm5lbChjaGFuKTsKKwkJCQlwcl9lcnIoImVycm9yIGFk ZGluZyAlcyBjaGFubmVsIHRocmVhZCAldVxuIiwKKwkJCQkgICAgICAgY2hhbm5lbF9uYW1lW2ld LCBqKTsKKwkJCQljb250aW51ZTsKKwkJCX0KKworCQkJZHRfcmVnaW9uID0gY2hhbi0+cHJpdmF0 ZTsKKwkJCXBhcmFtcy0+YnVmX3N6ID0gbWluKHBhcmFtcy0+YnVmX3N6LCBkdF9yZWdpb24tPnN6 KTsKKwkJCXBhcmFtcy0+YnVmX3NlZyA9IG1pbihwYXJhbXMtPmJ1Zl9zZWcsIGR0X3JlZ2lvbi0+ c3opOworCQl9CisJfQorfQorCitzdGF0aWMgdm9pZCBkd19lZG1hX3Rlc3RfdGhyZWFkX3J1bihz dHJ1Y3QgZHdfZWRtYV90ZXN0X2luZm8gKmluZm8pCit7CisJc3RydWN0IGR3X2VkbWFfdGVzdF9j aGFuICp0Y2hhbiwgKl90Y2hhbjsKKworCWxpc3RfZm9yX2VhY2hfZW50cnlfc2FmZSh0Y2hhbiwg X3RjaGFuLCAmaW5mby0+Y2hhbm5lbHMsIG5vZGUpCisJCWR3X2VkbWFfdGVzdF9ydW5fY2hhbm5l bCh0Y2hhbik7Cit9CisKK3N0YXRpYyB2b2lkIGR3X2VkbWFfdGVzdF90aHJlYWRfc3RvcChzdHJ1 Y3QgZHdfZWRtYV90ZXN0X2luZm8gKmluZm8pCit7CisJc3RydWN0IGR3X2VkbWFfdGVzdF9jaGFu ICp0Y2hhbiwgKl90Y2hhbjsKKwlzdHJ1Y3QgZG1hX2NoYW4gKmNoYW47CisKKwlsaXN0X2Zvcl9l YWNoX2VudHJ5X3NhZmUodGNoYW4sIF90Y2hhbiwgJmluZm8tPmNoYW5uZWxzLCBub2RlKSB7CisJ CWxpc3RfZGVsKCZ0Y2hhbi0+bm9kZSk7CisJCWNoYW4gPSB0Y2hhbi0+Y2hhbjsKKwkJZHdfZWRt YV90ZXN0X2RlbF9jaGFubmVsKHRjaGFuKTsKKwkJZG1hX3JlbGVhc2VfY2hhbm5lbChjaGFuKTsK KwkJcHJfaW5mbygiZGVsZXRlZCBjaGFubmVsICVzXG4iLCBkbWFfY2hhbl9uYW1lKGNoYW4pKTsK Kwl9Cit9CisKK3N0YXRpYyBib29sIGR3X2VkbWFfdGVzdF9pc190aHJlYWRfcnVuKHN0cnVjdCBk d19lZG1hX3Rlc3RfaW5mbyAqaW5mbykKK3sKKwlzdHJ1Y3QgZHdfZWRtYV90ZXN0X2NoYW4gKnRj aGFuOworCisJbGlzdF9mb3JfZWFjaF9lbnRyeSh0Y2hhbiwgJmluZm8tPmNoYW5uZWxzLCBub2Rl KSB7CisJCXN0cnVjdCBkd19lZG1hX3Rlc3RfdGhyZWFkICp0aHJlYWQgPSB0Y2hhbi0+dGhyZWFk OworCisJCWlmICghdGhyZWFkLT5kb25lKQorCQkJcmV0dXJuIHRydWU7CisJfQorCisJcmV0dXJu IGZhbHNlOworfQorCitzdGF0aWMgdm9pZCBkd19lZG1hX3Rlc3RfdGhyZWFkX3Jlc3RhcnQoc3Ry dWN0IGR3X2VkbWFfdGVzdF9pbmZvICppbmZvLAorCQkJCQlib29sIHJ1bikKK3sKKwlpZiAoIWlu Zm8tPmluaXQpCisJCXJldHVybjsKKworCWR3X2VkbWFfdGVzdF90aHJlYWRfc3RvcChpbmZvKTsK Kwlkd19lZG1hX3Rlc3RfdGhyZWFkX2NyZWF0ZShpbmZvKTsKKwlkd19lZG1hX3Rlc3RfdGhyZWFk X3J1bihpbmZvKTsKK30KKworc3RhdGljIGludCBkd19lZG1hX3Rlc3RfcnVuX2dldChjaGFyICp2 YWwsIGNvbnN0IHN0cnVjdCBrZXJuZWxfcGFyYW0gKmtwKQoreworCXN0cnVjdCBkd19lZG1hX3Rl c3RfaW5mbyAqaW5mbyA9ICZ0ZXN0X2luZm87CisKKwltdXRleF9sb2NrKCZpbmZvLT5sb2NrKTsK KworCXJ1bl90ZXN0ID0gZHdfZWRtYV90ZXN0X2lzX3RocmVhZF9ydW4oaW5mbyk7CisJaWYgKCFy dW5fdGVzdCkKKwkJZHdfZWRtYV90ZXN0X3RocmVhZF9zdG9wKGluZm8pOworCisJbXV0ZXhfdW5s b2NrKCZpbmZvLT5sb2NrKTsKKworCXJldHVybiBwYXJhbV9nZXRfYm9vbCh2YWwsIGtwKTsKK30K Kworc3RhdGljIGludCBkd19lZG1hX3Rlc3RfcnVuX3NldChjb25zdCBjaGFyICp2YWwsIGNvbnN0 IHN0cnVjdCBrZXJuZWxfcGFyYW0gKmtwKQoreworCXN0cnVjdCBkd19lZG1hX3Rlc3RfaW5mbyAq aW5mbyA9ICZ0ZXN0X2luZm87CisJaW50IHJldDsKKworCW11dGV4X2xvY2soJmluZm8tPmxvY2sp OworCisJcmV0ID0gcGFyYW1fc2V0X2Jvb2wodmFsLCBrcCk7CisJaWYgKHJldCkKKwkJZ290byBl cnJfc2V0OworCisJaWYgKGR3X2VkbWFfdGVzdF9pc190aHJlYWRfcnVuKGluZm8pKQorCQlyZXQg PSAtRUJVU1k7CisJZWxzZSBpZiAocnVuX3Rlc3QpCisJCWR3X2VkbWFfdGVzdF90aHJlYWRfcmVz dGFydChpbmZvLCBydW5fdGVzdCk7CisKK2Vycl9zZXQ6CisJbXV0ZXhfdW5sb2NrKCZpbmZvLT5s b2NrKTsKKworCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBpbnQgX19pbml0IGR3X2VkbWFfdGVz dF9pbml0KHZvaWQpCit7CisJc3RydWN0IGR3X2VkbWFfdGVzdF9pbmZvICppbmZvID0gJnRlc3Rf aW5mbzsKKworCWlmIChydW5fdGVzdCkgeworCQltdXRleF9sb2NrKCZpbmZvLT5sb2NrKTsKKwkJ ZHdfZWRtYV90ZXN0X3RocmVhZF9jcmVhdGUoaW5mbyk7CisJCWR3X2VkbWFfdGVzdF90aHJlYWRf cnVuKGluZm8pOworCQltdXRleF91bmxvY2soJmluZm8tPmxvY2spOworCX0KKworCXdhaXRfZXZl bnQodGhyZWFkX3dhaXQsICFkd19lZG1hX3Rlc3RfaXNfdGhyZWFkX3J1bihpbmZvKSk7CisKKwlp bmZvLT5pbml0ID0gdHJ1ZTsKKworCXJldHVybiAwOworfQorbGF0ZV9pbml0Y2FsbChkd19lZG1h X3Rlc3RfaW5pdCk7CisKK3N0YXRpYyB2b2lkIF9fZXhpdCBkd19lZG1hX3Rlc3RfZXhpdCh2b2lk KQoreworCXN0cnVjdCBkd19lZG1hX3Rlc3RfaW5mbyAqaW5mbyA9ICZ0ZXN0X2luZm87CisKKwlt dXRleF9sb2NrKCZpbmZvLT5sb2NrKTsKKwlkd19lZG1hX3Rlc3RfdGhyZWFkX3N0b3AoaW5mbyk7 CisJbXV0ZXhfdW5sb2NrKCZpbmZvLT5sb2NrKTsKK30KK21vZHVsZV9leGl0KGR3X2VkbWFfdGVz dF9leGl0KTsKKworTU9EVUxFX0xJQ0VOU0UoIkdQTCB2MiIpOworTU9EVUxFX0RFU0NSSVBUSU9O KCJTeW5vcHN5cyBEZXNpZ25XYXJlIGVETUEgdGVzdCBkcml2ZXIiKTsKK01PRFVMRV9BVVRIT1Io Ikd1c3Rhdm8gUGltZW50ZWwgPGd1c3Rhdm8ucGltZW50ZWxAc3lub3BzeXMuY29tPiIpOwo= From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.1 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id F053CC43612 for ; Fri, 11 Jan 2019 18:33:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B66D120872 for ; Fri, 11 Jan 2019 18:33:55 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=synopsys.com header.i=@synopsys.com header.b="MzfvWKVw" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387775AbfAKSdy (ORCPT ); Fri, 11 Jan 2019 13:33:54 -0500 Received: from smtprelay4.synopsys.com ([198.182.47.9]:34066 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731132AbfAKSdy (ORCPT ); Fri, 11 Jan 2019 13:33:54 -0500 Received: from mailhost.synopsys.com (mailhost3.synopsys.com [10.12.238.238]) by smtprelay.synopsys.com (Postfix) with ESMTP id C5C0324E1024; Fri, 11 Jan 2019 10:33:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1547231633; bh=+oUR13qvMOeEsx3qmHg/8RuzP9PYlojCOtUYY5nbkBc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:In-Reply-To: References:From; b=MzfvWKVwBaPhSjoLAKeuvM9UNyuOqRJZh6OyOAFPe5916vD4GrfE0ut9oQkCBKV4y oaQHPXTOcW6c4XKbDhzcyI5AqhoU0VqR8PTO6yluBVQ1GoeLGzY2JFTQrV4YAX0Lfn FE4LYg6ZVUseDU+6zegSueDRAVFo/P4CViziYNHJP6j55gYIhb5CVcH5LEykzleBTV 0HLQ5HADKDSgeR9/s6UeVh/Vej9XmqdnYA7pEACi4L69WYwLs+HLE5AmwckAS96z/d AiuKYph8mNJer1g9UpERIYd6oSfS8SEFqzkluuJd5L+G+/gTvofQekK+4E1ZfAySFu Nw7bexVGoi59Q== Received: from de02.synopsys.com (de02.internal.synopsys.com [10.225.17.21]) by mailhost.synopsys.com (Postfix) with ESMTP id 583173F0A; Fri, 11 Jan 2019 10:33:53 -0800 (PST) Received: from de02dwia024.internal.synopsys.com (de02dwia024.internal.synopsys.com [10.225.19.81]) by de02.synopsys.com (Postfix) with ESMTP id 386BF3EDC4; Fri, 11 Jan 2019 19:33:51 +0100 (CET) From: Gustavo Pimentel To: linux-pci@vger.kernel.org, dmaengine@vger.kernel.org Cc: Gustavo Pimentel , Vinod Koul , Dan Williams , Eugeniy Paltsev , Andy Shevchenko , Russell King , Niklas Cassel , Joao Pinto , Jose Abreu , Luis Oliveira , Vitor Soares , Nelson Costa , Pedro Sousa Subject: [RFC v3 7/7] dmaengine: Add Synopsys eDMA IP test and sample driver Date: Fri, 11 Jan 2019 19:33:43 +0100 Message-Id: X-Mailer: git-send-email 2.7.4 In-Reply-To: References: In-Reply-To: References: Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Add Synopsys eDMA IP test and sample driver to be use for testing purposes and also as a reference for any developer who needs to implement and use Synopsys eDMA. This driver can be compile as built-in or external module in kernel. To enable this driver just select DW_EDMA_TEST option in kernel configuration, however it requires and selects automatically DW_EDMA option too. Changes: RFC v1->RFC v2: - No changes RFC v2->RFC v3: - Add test module Signed-off-by: Gustavo Pimentel Cc: Vinod Koul Cc: Dan Williams Cc: Eugeniy Paltsev Cc: Andy Shevchenko Cc: Russell King Cc: Niklas Cassel Cc: Joao Pinto Cc: Jose Abreu Cc: Luis Oliveira Cc: Vitor Soares Cc: Nelson Costa Cc: Pedro Sousa --- drivers/dma/dw-edma/Kconfig | 7 + drivers/dma/dw-edma/Makefile | 1 + drivers/dma/dw-edma/dw-edma-test.c | 897 +++++++++++++++++++++++++++++++++++++ 3 files changed, 905 insertions(+) create mode 100644 drivers/dma/dw-edma/dw-edma-test.c diff --git a/drivers/dma/dw-edma/Kconfig b/drivers/dma/dw-edma/Kconfig index c0838ce..fe2b129 100644 --- a/drivers/dma/dw-edma/Kconfig +++ b/drivers/dma/dw-edma/Kconfig @@ -16,3 +16,10 @@ config DW_EDMA_PCIE Provides a glue-logic between the Synopsys DesignWare eDMA controller and an endpoint PCIe device. This also serves as a reference design to whom desires to use this IP. + +config DW_EDMA_TEST + tristate "Synopsys DesignWare eDMA test driver" + select DW_EDMA + help + Simple DMA test client. Say N unless you're debugging a + Synopsys eDMA device driver. diff --git a/drivers/dma/dw-edma/Makefile b/drivers/dma/dw-edma/Makefile index 8d45c0d..76e1e73 100644 --- a/drivers/dma/dw-edma/Makefile +++ b/drivers/dma/dw-edma/Makefile @@ -5,3 +5,4 @@ dw-edma-$(CONFIG_DEBUG_FS) := dw-edma-v0-debugfs.o dw-edma-objs := dw-edma-core.o \ dw-edma-v0-core.o $(dw-edma-y) obj-$(CONFIG_DW_EDMA_PCIE) += dw-edma-pcie.o +obj-$(CONFIG_DW_EDMA_TEST) += dw-edma-test.o diff --git a/drivers/dma/dw-edma/dw-edma-test.c b/drivers/dma/dw-edma/dw-edma-test.c new file mode 100644 index 0000000..23f8c23 --- /dev/null +++ b/drivers/dma/dw-edma/dw-edma-test.c @@ -0,0 +1,897 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates. + * Synopsys DesignWare eDMA test driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dw-edma-core.h" + +enum channel_id { + EDMA_CH_WR = 0, + EDMA_CH_RD, + EDMA_CH_END +}; + +static const char * const channel_name[] = {"WRITE", "READ"}; + +#define EDMA_TEST_MAX_THREADS_CHANNEL 8 +#define EDMA_TEST_DEVICE_NAME "0000:01:00.0" +#define EDMA_TEST_CHANNEL_NAME "dma%uchan%u" + +static u32 buf_sz = 14 * 1024 * 1024; /* 14 Mbytes */ +module_param(buf_sz, uint, 0644); +MODULE_PARM_DESC(buf_sz, "Buffer test size in bytes"); + +static u32 buf_seg = 2 * 1024 * 1024; /* 2 Mbytes */ +module_param(buf_seg, uint, 0644); +MODULE_PARM_DESC(buf_seg, "Buffer test size segments in bytes"); + +static u32 wr_threads = EDMA_TEST_MAX_THREADS_CHANNEL; +module_param(wr_threads, uint, 0644); +MODULE_PARM_DESC(wr_threads, "Number of write threads"); + +static u32 rd_threads = EDMA_TEST_MAX_THREADS_CHANNEL; +module_param(rd_threads, uint, 0644); +MODULE_PARM_DESC(rd_threads, "Number of reads threads"); + +static u32 repetitions; +module_param(repetitions, uint, 0644); +MODULE_PARM_DESC(repetitions, "Number of repetitions"); + +static u32 timeout = 5000; +module_param(timeout, uint, 0644); +MODULE_PARM_DESC(timeout, "Transfer timeout in msec"); + +static bool pattern; +module_param(pattern, bool, 0644); +MODULE_PARM_DESC(pattern, "Set CPU memory with a pattern before the transfer"); + +static bool dump_mem; +module_param(dump_mem, bool, 0644); +MODULE_PARM_DESC(dump_mem, "Prints on console the CPU and Endpoint memory before and after the transfer"); + +static u32 dump_sz = 5; +module_param(dump_sz, uint, 0644); +MODULE_PARM_DESC(dump_sz, "Size of memory dump"); + +static bool check; +module_param(check, bool, 0644); +MODULE_PARM_DESC(check, "Performs a verification after the transfer to validate data"); + +static int dw_edma_test_run_set(const char *val, const struct kernel_param *kp); + +static int dw_edma_test_run_set(const char *val, const struct kernel_param *kp); +static int dw_edma_test_run_get(char *val, const struct kernel_param *kp); +static const struct kernel_param_ops run_ops = { + .set = dw_edma_test_run_set, + .get = dw_edma_test_run_get, +}; + +static bool run_test; +module_param_cb(run_test, &run_ops, &run_test, 0644); +MODULE_PARM_DESC(run_test, "Run test"); + +struct dw_edma_test_params { + u32 buf_sz; + u32 buf_seg; + u32 num_threads[EDMA_CH_END]; + u32 repetitions; + u32 timeout; + u8 pattern; + u8 dump_mem; + u32 dump_sz; + u8 check; +}; + +static struct dw_edma_test_info { + struct dw_edma_test_params params; + struct list_head channels; + struct mutex lock; + bool init; +} test_info = { + .channels = LIST_HEAD_INIT(test_info.channels), + .lock = __MUTEX_INITIALIZER(test_info.lock), +}; + +struct dw_edma_test_done { + bool done; + wait_queue_head_t *wait; +}; + +struct dw_edma_test_thread { + struct dw_edma_test_info *info; + struct task_struct *task; + struct dma_chan *chan; + enum dma_transfer_direction direction; + wait_queue_head_t done_wait; + struct dw_edma_test_done test_done; + bool done; +}; + +struct dw_edma_test_chan { + struct list_head node; + struct dma_chan *chan; + struct dw_edma_test_thread *thread; +}; + +static DECLARE_WAIT_QUEUE_HEAD(thread_wait); + +static void dw_edma_test_callback(void *arg) +{ + struct dw_edma_test_done *done = arg; + struct dw_edma_test_thread *thread = + container_of(done, struct dw_edma_test_thread, test_done); + if (!thread->done) { + done->done = true; + wake_up_all(done->wait); + } else { + WARN(1, "dw_edma_test: Kernel memory may be corrupted!!\n"); + } +} + +static void dw_edma_test_memset(dma_addr_t addr, int sz) +{ + void __iomem *ptr = (void __iomem *)addr; + int rem_sz = sz, step = 0; + + while (rem_sz >= 0) { +#ifdef CONFIG_64BIT + if (rem_sz >= 8) { + step = 8; + writeq(0x0123456789ABCDEF, ptr); + } else if (rem_sz >= 4) { +#else + if (rem_sz >= 4) { +#endif + step = 4; + writel(0x01234567, ptr); + } else if (rem_sz >= 2) { + step = 2; + writew(0x0123, ptr); + } else { + step = 1; + writeb(0x01, ptr); + } + ptr += step; + rem_sz -= step; + } +} + +static bool dw_edma_test_check(dma_addr_t v1, dma_addr_t v2, int sz) +{ + void __iomem *ptr1 = (void __iomem *)v1; + void __iomem *ptr2 = (void __iomem *)v2; + int rem_sz = sz, step = 0; + + while (rem_sz >= 0) { +#ifdef CONFIG_64BIT + if (rem_sz >= 8) { + step = 8; + if (readq(ptr1) != readq(ptr2)) + return false; + } else if (rem_sz >= 4) { +#else + if (rem_sz >= 4) { +#endif + step = 4; + if (readl(ptr1) != readl(ptr2)) + return false; + } else if (rem_sz >= 2) { + step = 2; + if (readw(ptr1) != readw(ptr2)) + return false; + } else { + step = 1; + if (readb(ptr1) != readb(ptr2)) + return false; + } + ptr1 += step; + ptr2 += step; + rem_sz -= step; + } + + return true; +} + +static void dw_edma_test_dump(struct device *dev, + enum dma_transfer_direction direction, int sz, + struct dw_edma_region *r1, + struct dw_edma_region *r2) +{ + u32 *ptr1, *ptr2, *ptr3, *ptr4; + int i, cnt = min(r1->sz, r2->sz); + + cnt = min(cnt, sz); + cnt -= cnt % 4; + + if (direction == DMA_DEV_TO_MEM) { + ptr1 = (u32 *)r1->vaddr; + ptr2 = (u32 *)r1->paddr; + ptr3 = (u32 *)r2->vaddr; + ptr4 = (u32 *)r2->paddr; + dev_info(dev, " ============= EP memory =============\t============= CPU memory ============\n"); + } else { + ptr1 = (u32 *)r2->vaddr; + ptr2 = (u32 *)r2->paddr; + ptr3 = (u32 *)r1->vaddr; + ptr4 = (u32 *)r1->paddr; + dev_info(dev, " ============= CPU memory ============\t============= EP memory =============\n"); + } + dev_info(dev, " ============== Source ===============\t============ Destination ============\n"); + dev_info(dev, " [Virt. Addr][Phys. Addr]=[ Value ]\t[Virt. Addr][Phys. Addr]=[ Value ]\n"); + for (i = 0; i < cnt; i++, ptr1++, ptr2++, ptr3++, ptr4++) + dev_info(dev, "[%.3u] [%pa][%pa]=[0x%.8x]\t[%pa][%pa]=[0x%.8x]\n", + i, + &ptr1, &ptr2, readl(ptr1), + &ptr3, &ptr4, readl(ptr3)); +} + +static int dw_edma_test_sg(void *data) +{ + struct dw_edma_test_thread *thread = data; + struct dw_edma_test_done *done = &thread->test_done; + struct dw_edma_test_info *info = thread->info; + struct dw_edma_test_params *params = &info->params; + struct dma_chan *chan = thread->chan; + struct device *dev = chan->device->dev; + struct dw_edma_region *dt_region = chan->private; + u32 rem_len = params->buf_sz; + u32 f_prp_cnt = 0; + u32 f_sbt_cnt = 0; + u32 f_tm_cnt = 0; + u32 f_cpl_err = 0; + u32 f_cpl_bsy = 0; + dma_cookie_t cookie; + enum dma_status status; + struct dw_edma_region *descs; + struct sg_table *sgt; + struct scatterlist *sg; + struct dma_slave_config sconf; + struct dma_async_tx_descriptor *txdesc; + int i, sgs, err = 0; + + set_freezable(); + set_user_nice(current, 10); + + /* Calculates the maximum number of segments */ + sgs = DIV_ROUND_UP(params->buf_sz, params->buf_seg); + + if (!sgs) + goto err_end; + + /* Allocate scatter-gather table */ + sgt = kvmalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) + goto err_end; + + err = sg_alloc_table(sgt, sgs, GFP_KERNEL); + if (err) + goto err_sg_alloc_table; + + sg = &sgt->sgl[0]; + if (!sg) + goto err_alloc_descs; + + /* + * Allocate structure to hold all scatter-gather segments (size, + * virtual and physical addresses) + */ + descs = devm_kcalloc(dev, sgs, sizeof(*descs), GFP_KERNEL); + if (!descs) + goto err_alloc_descs; + + for (i = 0; sg && i < sgs; i++) { + descs[i].paddr = 0; + descs[i].sz = min(rem_len, params->buf_seg); + rem_len -= descs[i].sz; + + descs[i].vaddr = (dma_addr_t)dma_alloc_coherent(dev, + descs[i].sz, + &descs[i].paddr, + GFP_KERNEL); + if (!descs[i].vaddr || !descs[i].paddr) { + dev_err(dev, "%s: (%u)fail to allocate %u bytes\n", + dma_chan_name(chan), i, descs[i].sz); + goto err_descs; + } + + dev_dbg(dev, "%s: CPU: segment %u, addr(v=%pa, p=%pa)\n", + dma_chan_name(chan), i, + &descs[i].vaddr, &descs[i].paddr); + + sg_set_buf(sg, (void *)descs[i].paddr, descs[i].sz); + sg = sg_next(sg); + } + + /* Dumps the first segment memory */ + if (params->dump_mem) + dw_edma_test_dump(dev, thread->direction, params->dump_sz, + dt_region, &descs[0]); + + /* Fills CPU memory with a known pattern */ + if (params->pattern) + dw_edma_test_memset(descs[0].vaddr, params->buf_sz); + + /* + * Configures DMA channel according to the direction + * - flags + * - source and destination addresses + */ + if (thread->direction == DMA_DEV_TO_MEM) { + /* DMA_DEV_TO_MEM - WRITE - DMA_FROM_DEVICE */ + dev_dbg(dev, "%s: DMA_DEV_TO_MEM - WRITE - DMA_FROM_DEVICE\n", + dma_chan_name(chan)); + err = dma_map_sg(dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE); + if (!err) + goto err_descs; + + sgt->nents = err; + /* Endpoint memory */ + sconf.src_addr = dt_region->paddr; + /* CPU memory */ + sconf.dst_addr = descs[0].paddr; + } else { + /* DMA_MEM_TO_DEV - READ - DMA_TO_DEVICE */ + dev_dbg(dev, "%s: DMA_MEM_TO_DEV - READ - DMA_TO_DEVICE\n", + dma_chan_name(chan)); + err = dma_map_sg(dev, sgt->sgl, sgt->nents, DMA_TO_DEVICE); + if (!err) + goto err_descs; + + sgt->nents = err; + /* CPU memory */ + sconf.src_addr = descs[0].paddr; + /* Endpoint memory */ + sconf.dst_addr = dt_region->paddr; + } + + dmaengine_slave_config(chan, &sconf); + dev_dbg(dev, "%s: addr(physical) src=%pa, dst=%pa\n", + dma_chan_name(chan), &sconf.src_addr, &sconf.dst_addr); + dev_dbg(dev, "%s: len=%u bytes, sgs=%u, seg_sz=%u bytes\n", + dma_chan_name(chan), params->buf_sz, sgs, params->buf_seg); + + /* + * Prepare the DMA channel for the transfer + * - provide scatter-gather list + * - configure to trigger an interrupt after the transfer + */ + txdesc = dmaengine_prep_slave_sg(chan, sgt->sgl, sgt->nents, + thread->direction, + DMA_PREP_INTERRUPT); + if (!txdesc) { + dev_dbg(dev, "%s: dmaengine_prep_slave_sg\n", + dma_chan_name(chan)); + f_prp_cnt++; + goto err_stats; + } + + done->done = false; + txdesc->callback = dw_edma_test_callback; + txdesc->callback_param = done; + cookie = dmaengine_submit(txdesc); + if (dma_submit_error(cookie)) { + dev_dbg(dev, "%s: dma_submit_error\n", dma_chan_name(chan)); + f_sbt_cnt++; + goto err_stats; + } + + /* Start DMA transfer */ + dma_async_issue_pending(chan); + + /* Thread waits here for transfer completion or exists by timeout */ + wait_event_freezable_timeout(thread->done_wait, done->done, + msecs_to_jiffies(params->timeout)); + + /* Check DMA transfer status and act upon it */ + status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); + if (!done->done) { + dev_dbg(dev, "%s: timeout\n", dma_chan_name(chan)); + f_tm_cnt++; + } else if (status != DMA_COMPLETE) { + if (status == DMA_ERROR) { + dev_dbg(dev, "%s: completion error status\n", + dma_chan_name(chan)); + f_cpl_err++; + } else { + dev_dbg(dev, "%s: completion busy status\n", + dma_chan_name(chan)); + f_cpl_bsy++; + } + } + +err_stats: + /* Display some stats information */ + if (f_prp_cnt || f_sbt_cnt || f_tm_cnt || f_cpl_err || f_cpl_bsy) { + dev_info(dev, "%s: test failed - dmaengine_prep_slave_sg=%u, dma_submit_error=%u, timeout=%u, completion error status=%u, completion busy status=%u\n", + dma_chan_name(chan), f_prp_cnt, f_sbt_cnt, + f_tm_cnt, f_cpl_err, f_cpl_bsy); + } else { + dev_info(dev, "%s: test passed\n", dma_chan_name(chan)); + } + + /* Dumps the first segment memory */ + if (params->dump_mem) + dw_edma_test_dump(dev, thread->direction, params->dump_sz, + dt_region, &descs[0]); + + /* Check if the data was correctly transfer */ + if (params->check) { + dev_info(dev, "%s: performing check\n", dma_chan_name(chan)); + err = dw_edma_test_check(descs[i].vaddr, dt_region->vaddr, + params->buf_sz); + if (err) + dev_info(dev, "%s: check pass\n", dma_chan_name(chan)); + else + dev_info(dev, "%s: check fail\n", dma_chan_name(chan)); + } + + /* Terminate any DMA operation, (fail safe) */ + dmaengine_terminate_all(chan); + +err_descs: + for (i = 0; i < sgs && descs[i].vaddr && descs[i].paddr; i++) + dma_free_coherent(dev, descs[i].sz, (void *)descs[i].vaddr, + descs[i].paddr); + devm_kfree(dev, descs); +err_alloc_descs: + sg_free_table(sgt); +err_sg_alloc_table: + kvfree(sgt); +err_end: + thread->done = true; + wake_up(&thread_wait); + + return 0; +} + +static int dw_edma_test_cyclic(void *data) +{ + struct dw_edma_test_thread *thread = data; + struct dw_edma_test_done *done = &thread->test_done; + struct dw_edma_test_info *info = thread->info; + struct dw_edma_test_params *params = &info->params; + struct dma_chan *chan = thread->chan; + struct device *dev = chan->device->dev; + struct dw_edma_region *dt_region = chan->private; + u32 f_prp_cnt = 0; + u32 f_sbt_cnt = 0; + u32 f_tm_cnt = 0; + u32 f_cpl_err = 0; + u32 f_cpl_bsy = 0; + dma_cookie_t cookie; + enum dma_status status; + struct dw_edma_region desc; + struct dma_slave_config sconf; + struct dma_async_tx_descriptor *txdesc; + int err = 0; + + set_freezable(); + set_user_nice(current, 10); + + desc.paddr = 0; + desc.sz = params->buf_seg; + desc.vaddr = (dma_addr_t)dma_alloc_coherent(dev, desc.sz, &desc.paddr, + GFP_KERNEL); + if (!desc.vaddr || !desc.paddr) { + dev_err(dev, "%s: fail to allocate %u bytes\n", + dma_chan_name(chan), desc.sz); + goto err_end; + } + + dev_dbg(dev, "%s: CPU: addr(v=%pa, p=%pa)\n", + dma_chan_name(chan), &desc.vaddr, &desc.paddr); + + /* Dumps the first segment memory */ + if (params->dump_mem) + dw_edma_test_dump(dev, thread->direction, params->dump_sz, + dt_region, &desc); + + /* Fills CPU memory with a known pattern */ + if (params->pattern) + dw_edma_test_memset(desc.vaddr, params->buf_sz); + + /* + * Configures DMA channel according to the direction + * - flags + * - source and destination addresses + */ + if (thread->direction == DMA_DEV_TO_MEM) { + /* DMA_DEV_TO_MEM - WRITE - DMA_FROM_DEVICE */ + dev_dbg(dev, "%s: DMA_DEV_TO_MEM - WRITE - DMA_FROM_DEVICE\n", + dma_chan_name(chan)); + + /* Endpoint memory */ + sconf.src_addr = dt_region->paddr; + /* CPU memory */ + sconf.dst_addr = desc.paddr; + } else { + /* DMA_MEM_TO_DEV - READ - DMA_TO_DEVICE */ + dev_dbg(dev, "%s: DMA_MEM_TO_DEV - READ - DMA_TO_DEVICE\n", + dma_chan_name(chan)); + + /* CPU memory */ + sconf.src_addr = desc.paddr; + /* Endpoint memory */ + sconf.dst_addr = dt_region->paddr; + } + + dmaengine_slave_config(chan, &sconf); + dev_dbg(dev, "%s: addr(physical) src=%pa, dst=%pa\n", + dma_chan_name(chan), &sconf.src_addr, &sconf.dst_addr); + dev_dbg(dev, "%s: len=%u bytes\n", + dma_chan_name(chan), params->buf_sz); + + /* + * Prepare the DMA channel for the transfer + * - provide buffer, size and number of repetitions + * - configure to trigger an interrupt after the transfer + */ + txdesc = dmaengine_prep_dma_cyclic(chan, desc.vaddr, desc.sz, + params->repetitions, + thread->direction, + DMA_PREP_INTERRUPT); + if (!txdesc) { + dev_dbg(dev, "%s: dmaengine_prep_slave_sg\n", + dma_chan_name(chan)); + f_prp_cnt++; + goto err_stats; + } + + done->done = false; + txdesc->callback = dw_edma_test_callback; + txdesc->callback_param = done; + cookie = dmaengine_submit(txdesc); + if (dma_submit_error(cookie)) { + dev_dbg(dev, "%s: dma_submit_error\n", dma_chan_name(chan)); + f_sbt_cnt++; + goto err_stats; + } + + /* Start DMA transfer */ + dma_async_issue_pending(chan); + + /* Thread waits here for transfer completion or exists by timeout */ + wait_event_freezable_timeout(thread->done_wait, done->done, + msecs_to_jiffies(params->timeout)); + + /* Check DMA transfer status and act upon it */ + status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); + if (!done->done) { + dev_dbg(dev, "%s: timeout\n", dma_chan_name(chan)); + f_tm_cnt++; + } else if (status != DMA_COMPLETE) { + if (status == DMA_ERROR) { + dev_dbg(dev, "%s: completion error status\n", + dma_chan_name(chan)); + f_cpl_err++; + } else { + dev_dbg(dev, "%s: completion busy status\n", + dma_chan_name(chan)); + f_cpl_bsy++; + } + } + +err_stats: + /* Display some stats information */ + if (f_prp_cnt || f_sbt_cnt || f_tm_cnt || f_cpl_err || f_cpl_bsy) { + dev_info(dev, "%s: test failed - dmaengine_prep_slave_sg=%u, dma_submit_error=%u, timeout=%u, completion error status=%u, completion busy status=%u\n", + dma_chan_name(chan), f_prp_cnt, f_sbt_cnt, + f_tm_cnt, f_cpl_err, f_cpl_bsy); + } else { + dev_info(dev, "%s: test passed\n", dma_chan_name(chan)); + } + + /* Dumps the first segment memory */ + if (params->dump_mem) + dw_edma_test_dump(dev, thread->direction, params->dump_sz, + dt_region, &desc); + + /* Check if the data was correctly transfer */ + if (params->check) { + dev_info(dev, "%s: performing check\n", dma_chan_name(chan)); + err = dw_edma_test_check(desc.vaddr, dt_region->vaddr, + params->buf_sz); + if (err) + dev_info(dev, "%s: check pass\n", dma_chan_name(chan)); + else + dev_info(dev, "%s: check fail\n", dma_chan_name(chan)); + } + + /* Terminate any DMA operation, (fail safe) */ + dmaengine_terminate_all(chan); + + dma_free_coherent(dev, desc.sz, (void *)desc.vaddr, desc.paddr); +err_end: + thread->done = true; + wake_up(&thread_wait); + + return 0; +} + +static int dw_edma_test_add_channel(struct dw_edma_test_info *info, + struct dma_chan *chan, + u32 channel) +{ + struct dw_edma_test_params *params = &info->params; + struct dw_edma_test_thread *thread; + struct dw_edma_test_chan *tchan; + + tchan = kvmalloc(sizeof(*tchan), GFP_KERNEL); + if (!tchan) + return -ENOMEM; + + tchan->chan = chan; + + thread = kvzalloc(sizeof(*thread), GFP_KERNEL); + if (!thread) { + kvfree(tchan); + return -ENOMEM; + } + + thread->info = info; + thread->chan = tchan->chan; + switch (channel) { + case EDMA_CH_WR: + thread->direction = DMA_DEV_TO_MEM; + break; + case EDMA_CH_RD: + thread->direction = DMA_MEM_TO_DEV; + break; + default: + kvfree(tchan); + return -EPERM; + } + thread->test_done.wait = &thread->done_wait; + init_waitqueue_head(&thread->done_wait); + + if (!params->repetitions) + thread->task = kthread_create(dw_edma_test_sg, thread, "%s", + dma_chan_name(chan)); + else + thread->task = kthread_create(dw_edma_test_cyclic, thread, "%s", + dma_chan_name(chan)); + + if (IS_ERR(thread->task)) { + pr_err("failed to create thread %s\n", dma_chan_name(chan)); + kvfree(tchan); + kvfree(thread); + return -EPERM; + } + + tchan->thread = thread; + dev_dbg(chan->device->dev, "add thread %s\n", dma_chan_name(chan)); + list_add_tail(&tchan->node, &info->channels); + + return 0; +} + +static void dw_edma_test_del_channel(struct dw_edma_test_chan *tchan) +{ + struct dw_edma_test_thread *thread = tchan->thread; + + kthread_stop(thread->task); + dev_dbg(tchan->chan->device->dev, "thread %s exited\n", + thread->task->comm); + put_task_struct(thread->task); + kvfree(thread); + tchan->thread = NULL; + + dmaengine_terminate_all(tchan->chan); + kvfree(tchan); +} + +static void dw_edma_test_run_channel(struct dw_edma_test_chan *tchan) +{ + struct dw_edma_test_thread *thread = tchan->thread; + + get_task_struct(thread->task); + wake_up_process(thread->task); + dev_dbg(tchan->chan->device->dev, "thread %s started\n", + thread->task->comm); +} + +static bool dw_edma_test_filter(struct dma_chan *chan, void *filter) +{ + if (strcmp(dev_name(chan->device->dev), EDMA_TEST_DEVICE_NAME) || + strcmp(dma_chan_name(chan), filter)) + return false; + + return true; +} + +static void dw_edma_test_thread_create(struct dw_edma_test_info *info) +{ + struct dw_edma_test_params *params = &info->params; + struct dma_chan *chan; + struct dw_edma_region *dt_region; + dma_cap_mask_t mask; + char filter[20]; + int i, j; + + params->num_threads[EDMA_CH_WR] = min_t(u32, + EDMA_TEST_MAX_THREADS_CHANNEL, + wr_threads); + params->num_threads[EDMA_CH_RD] = min_t(u32, + EDMA_TEST_MAX_THREADS_CHANNEL, + rd_threads); + params->repetitions = repetitions; + params->timeout = timeout; + params->pattern = pattern; + params->dump_mem = dump_mem; + params->dump_sz = dump_sz; + params->check = check; + params->buf_sz = buf_sz; + params->buf_seg = min(buf_seg, buf_sz); + +#ifndef CONFIG_CMA_SIZE_MBYTES + pr_warn("CMA not present/activated! Contiguous Memory may fail to be allocted\n"); +#endif + + pr_info("Number of write threads = %u\n", wr_threads); + pr_info("Number of read threads = %u\n", rd_threads); + if (!params->repetitions) + pr_info("Scatter-gather mode\n"); + else + pr_info("Cyclic mode (repetitions per thread %u)\n", + params->repetitions); + pr_info("Timeout = %u ms\n", params->timeout); + pr_info("Use pattern = %s\n", params->pattern ? "true" : "false"); + pr_info("Dump memory = %s\n", params->dump_mem ? "true" : "false"); + pr_info("Perform check = %s\n", params->check ? "true" : "false"); + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_cap_set(DMA_CYCLIC, mask); + + for (i = 0; i < EDMA_CH_END; i++) { + for (j = 0; j < params->num_threads[i]; j++) { + snprintf(filter, sizeof(filter), + EDMA_TEST_CHANNEL_NAME, i, j); + + chan = dma_request_channel(mask, dw_edma_test_filter, + filter); + if (!chan) + continue; + + if (dw_edma_test_add_channel(info, chan, i)) { + dma_release_channel(chan); + pr_err("error adding %s channel thread %u\n", + channel_name[i], j); + continue; + } + + dt_region = chan->private; + params->buf_sz = min(params->buf_sz, dt_region->sz); + params->buf_seg = min(params->buf_seg, dt_region->sz); + } + } +} + +static void dw_edma_test_thread_run(struct dw_edma_test_info *info) +{ + struct dw_edma_test_chan *tchan, *_tchan; + + list_for_each_entry_safe(tchan, _tchan, &info->channels, node) + dw_edma_test_run_channel(tchan); +} + +static void dw_edma_test_thread_stop(struct dw_edma_test_info *info) +{ + struct dw_edma_test_chan *tchan, *_tchan; + struct dma_chan *chan; + + list_for_each_entry_safe(tchan, _tchan, &info->channels, node) { + list_del(&tchan->node); + chan = tchan->chan; + dw_edma_test_del_channel(tchan); + dma_release_channel(chan); + pr_info("deleted channel %s\n", dma_chan_name(chan)); + } +} + +static bool dw_edma_test_is_thread_run(struct dw_edma_test_info *info) +{ + struct dw_edma_test_chan *tchan; + + list_for_each_entry(tchan, &info->channels, node) { + struct dw_edma_test_thread *thread = tchan->thread; + + if (!thread->done) + return true; + } + + return false; +} + +static void dw_edma_test_thread_restart(struct dw_edma_test_info *info, + bool run) +{ + if (!info->init) + return; + + dw_edma_test_thread_stop(info); + dw_edma_test_thread_create(info); + dw_edma_test_thread_run(info); +} + +static int dw_edma_test_run_get(char *val, const struct kernel_param *kp) +{ + struct dw_edma_test_info *info = &test_info; + + mutex_lock(&info->lock); + + run_test = dw_edma_test_is_thread_run(info); + if (!run_test) + dw_edma_test_thread_stop(info); + + mutex_unlock(&info->lock); + + return param_get_bool(val, kp); +} + +static int dw_edma_test_run_set(const char *val, const struct kernel_param *kp) +{ + struct dw_edma_test_info *info = &test_info; + int ret; + + mutex_lock(&info->lock); + + ret = param_set_bool(val, kp); + if (ret) + goto err_set; + + if (dw_edma_test_is_thread_run(info)) + ret = -EBUSY; + else if (run_test) + dw_edma_test_thread_restart(info, run_test); + +err_set: + mutex_unlock(&info->lock); + + return ret; +} + +static int __init dw_edma_test_init(void) +{ + struct dw_edma_test_info *info = &test_info; + + if (run_test) { + mutex_lock(&info->lock); + dw_edma_test_thread_create(info); + dw_edma_test_thread_run(info); + mutex_unlock(&info->lock); + } + + wait_event(thread_wait, !dw_edma_test_is_thread_run(info)); + + info->init = true; + + return 0; +} +late_initcall(dw_edma_test_init); + +static void __exit dw_edma_test_exit(void) +{ + struct dw_edma_test_info *info = &test_info; + + mutex_lock(&info->lock); + dw_edma_test_thread_stop(info); + mutex_unlock(&info->lock); +} +module_exit(dw_edma_test_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Synopsys DesignWare eDMA test driver"); +MODULE_AUTHOR("Gustavo Pimentel "); -- 2.7.4