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,v2,1/6] dmaengine: Add Synopsys eDMA IP core driver From: Gustavo Pimentel Message-Id: <62a724afddb39cc241fbd769e0d93aa9e07e923f.1545066805.git.gustavo.pimentel@synopsys.com> Date: Mon, 17 Dec 2018 18:19:33 +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: QWRkIFN5bm9wc3lzIGVETUEgSVAgY29yZSBkcml2ZXIgdG8ga2VybmVsLgoKVGhpcyBjb3JlIGRy aXZlciwgaW5pdGlhbGl6ZXMgYW5kIGNvbmZpZ3VyZXMgdGhlIGVETUEgSVAgdXNpbmcgdm1hLWhl bHBlcnMKZnVuY3Rpb25zIGFuZCBkbWEtZW5naW5lIHN1YnN5c3RlbS4KCkFsc28gY3JlYXRlcyBh biBhYnN0cmF0aW9uIGxheWVyIHRocm91Z2ggY2FsbGJhY2tzIGFsbG93aW5nIGRpZmZlcmVudApy ZWdpc3RlcnMgbWFwcGluZ3MgaW4gdGhlIGZ1dHVyZSwgb3JnYW5pemVkIGluIHRvIHZlcnNpb25z LgoKVGhpcyBkcml2ZXIgY2FuIGJlIGNvbXBpbGUgYXMgYnVpbHQtaW4gb3IgZXh0ZXJuYWwgbW9k dWxlIGluIGtlcm5lbC4KClRvIGVuYWJsZSB0aGlzIGRyaXZlciBqdXN0IHNlbGVjdCBEV19FRE1B IG9wdGlvbiBpbiBrZXJuZWwgY29uZmlndXJhdGlvbiwKaG93ZXZlciBpdCByZXF1aXJlcyBhbmQg c2VsZWN0cyBhdXRvbWF0aWNhbGx5IERNQV9FTkdJTkUgYW5kCkRNQV9WSVJUVUFMX0NIQU5ORUxT IG9wdGlvbiB0b28uCgpDaGFuZ2VzOgpSRkMgdjEtPlJGQyB2MjoKIC0gUmVwbGFjZSBjb21tZW50 cyAvLyAoQzk5IHN0eWxlKSBieSAvKiovCiAtIEZpeCB0aGUgaGVhZGVycyBvZiB0aGUgLmMgYW5k IC5oIGZpbGVzIGFjY29yZGluZyB0byB0aGUgbW9zdCByZWNlbnQKICAgY29udmVudGlvbgogLSBG aXggZXJyb3JzIGFuZCBjaGVja3MgcG9pbnRlZCBvdXQgYnkgY2hlY2twYXRjaCB3aXRoIC0tc3Ry aWN0IG9wdGlvbgogLSBSZXBsYWNlIHBhdGNoIHNtYWxsIGRlc2NyaXB0aW9uIHRhZyBmcm9tIGRt YSBieSBkbWFlbmdpbmUKIC0gQ2hhbmdlIHNvbWUgZGV2X2luZm8oKSBpbnRvIGRldl9kYmcoKQog LSBSZW1vdmUgdW5uZWNlc3NhcnkgemVybyBpbml0aWFsaXphdGlvbiBhZnRlciBremFsbG9jCiAt IFJlbW92ZSBkaXJlY3Rpb24gdmFsaWRhdGlvbiBvbiBjb25maWcoKSBBUEksIHNpbmNlIHRoZSBk aXJlY3Rpb24KICAgcGFyYW1ldGVyIGlzIGRlcHJlY2F0ZWQKIC0gUmVmYWN0b3IgY29kZSB0byBy ZXBsYWNlIGF0b21pY190IGJ5IHUzMiB2YXJpYWJsZSB0eXBlCiAtIFJlcGxhY2Ugc3RhcnRfdHJh bnNmZXIoKSBuYW1lIGJ5IGR3X2VkbWFfc3RhcnRfdHJhbnNmZXIoKQogLSBBZGQgc3BpbmxvY2sg dG8gZHdfZWRtYV9kZXZpY2VfcHJlcF9zbGF2ZV9zZygpCiAtIEFkZCBzcGlubG9jayB0byBkd19l ZG1hX2ZyZWVfY2h1bmsoKQogLSBTaW1wbGlmeSBzd2l0Y2ggY2FzZSBpbnRvIGlmIG9uIGR3X2Vk bWFfZGV2aWNlX3BhdXNlKCksCiAgIGR3X2VkbWFfZGV2aWNlX3Jlc3VtZSgpIGFuZCBkd19lZG1h X2RldmljZV90ZXJtaW5hdGVfYWxsKCkKClNpZ25lZC1vZmYtYnk6IEd1c3Rhdm8gUGltZW50ZWwg PGd1c3Rhdm8ucGltZW50ZWxAc3lub3BzeXMuY29tPgpDYzogVmlub2QgS291bCA8dmtvdWxAa2Vy bmVsLm9yZz4KQ2M6IERhbiBXaWxsaWFtcyA8ZGFuLmoud2lsbGlhbXNAaW50ZWwuY29tPgpDYzog RXVnZW5peSBQYWx0c2V2IDxwYWx0c2V2QHN5bm9wc3lzLmNvbT4KQ2M6IEFuZHkgU2hldmNoZW5r byA8YW5kcml5LnNoZXZjaGVua29AbGludXguaW50ZWwuY29tPgpDYzogUnVzc2VsbCBLaW5nIDxy bWsra2VybmVsQGFybWxpbnV4Lm9yZy51az4KQ2M6IE5pa2xhcyBDYXNzZWwgPG5pa2xhcy5jYXNz ZWxAbGluYXJvLm9yZz4KQ2M6IEpvYW8gUGludG8gPGpwaW50b0BzeW5vcHN5cy5jb20+CkNjOiBK b3NlIEFicmV1IDxqb3NlLmFicmV1QHN5bm9wc3lzLmNvbT4KQ2M6IEx1aXMgT2xpdmVpcmEgPGxv bGl2ZWlAc3lub3BzeXMuY29tPgpDYzogVml0b3IgU29hcmVzIDx2aXRvci5zb2FyZXNAc3lub3Bz eXMuY29tPgpDYzogTmVsc29uIENvc3RhIDxuZWxzb24uY29zdGFAc3lub3BzeXMuY29tPgpDYzog UGVkcm8gU291c2EgPHBlZHJvbS5zb3VzYUBzeW5vcHN5cy5jb20+Ci0tLQogZHJpdmVycy9kbWEv S2NvbmZpZyAgICAgICAgICAgICAgICB8ICAgMiArCiBkcml2ZXJzL2RtYS9NYWtlZmlsZSAgICAg ICAgICAgICAgIHwgICAxICsKIGRyaXZlcnMvZG1hL2R3LWVkbWEvS2NvbmZpZyAgICAgICAgfCAg IDkgKwogZHJpdmVycy9kbWEvZHctZWRtYS9NYWtlZmlsZSAgICAgICB8ICAgNCArCiBkcml2ZXJz L2RtYS9kdy1lZG1hL2R3LWVkbWEtY29yZS5jIHwgODI0ICsrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysKIGRyaXZlcnMvZG1hL2R3LWVkbWEvZHctZWRtYS1jb3JlLmggfCAxNDcg KysrKysrKwogaW5jbHVkZS9saW51eC9kbWEvZWRtYS5oICAgICAgICAgICB8ICA0MyArKwogNyBm aWxlcyBjaGFuZ2VkLCAxMDMwIGluc2VydGlvbnMoKykKIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2 ZXJzL2RtYS9kdy1lZG1hL0tjb25maWcKIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2RtYS9k dy1lZG1hL01ha2VmaWxlCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9kbWEvZHctZWRtYS9k dy1lZG1hLWNvcmUuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvZG1hL2R3LWVkbWEvZHct ZWRtYS1jb3JlLmgKIGNyZWF0ZSBtb2RlIDEwMDY0NCBpbmNsdWRlL2xpbnV4L2RtYS9lZG1hLmgK CmRpZmYgLS1naXQgYS9kcml2ZXJzL2RtYS9LY29uZmlnIGIvZHJpdmVycy9kbWEvS2NvbmZpZwpp bmRleCBkZTUxMWRiLi40MDUxN2Y4IDEwMDY0NAotLS0gYS9kcml2ZXJzL2RtYS9LY29uZmlnCisr KyBiL2RyaXZlcnMvZG1hL0tjb25maWcKQEAgLTY0MCw2ICs2NDAsOCBAQCBzb3VyY2UgImRyaXZl cnMvZG1hL3Fjb20vS2NvbmZpZyIKIAogc291cmNlICJkcml2ZXJzL2RtYS9kdy9LY29uZmlnIgog Citzb3VyY2UgImRyaXZlcnMvZG1hL2R3LWVkbWEvS2NvbmZpZyIKKwogc291cmNlICJkcml2ZXJz L2RtYS9oc3UvS2NvbmZpZyIKIAogc291cmNlICJkcml2ZXJzL2RtYS9zaC9LY29uZmlnIgpkaWZm IC0tZ2l0IGEvZHJpdmVycy9kbWEvTWFrZWZpbGUgYi9kcml2ZXJzL2RtYS9NYWtlZmlsZQppbmRl eCA3ZmNjNGQ4Li4zZWJmYWIwIDEwMDY0NAotLS0gYS9kcml2ZXJzL2RtYS9NYWtlZmlsZQorKysg Yi9kcml2ZXJzL2RtYS9NYWtlZmlsZQpAQCAtMjksNiArMjksNyBAQCBvYmotJChDT05GSUdfRE1B X1NVTjRJKSArPSBzdW40aS1kbWEubwogb2JqLSQoQ09ORklHX0RNQV9TVU42SSkgKz0gc3VuNmkt ZG1hLm8KIG9iai0kKENPTkZJR19EV19BWElfRE1BQykgKz0gZHctYXhpLWRtYWMvCiBvYmotJChD T05GSUdfRFdfRE1BQ19DT1JFKSArPSBkdy8KK29iai0kKENPTkZJR19EV19FRE1BKSArPSBkdy1l ZG1hLwogb2JqLSQoQ09ORklHX0VQOTNYWF9ETUEpICs9IGVwOTN4eF9kbWEubwogb2JqLSQoQ09O RklHX0ZTTF9ETUEpICs9IGZzbGRtYS5vCiBvYmotJChDT05GSUdfRlNMX0VETUEpICs9IGZzbC1l ZG1hLm8gZnNsLWVkbWEtY29tbW9uLm8KZGlmZiAtLWdpdCBhL2RyaXZlcnMvZG1hL2R3LWVkbWEv S2NvbmZpZyBiL2RyaXZlcnMvZG1hL2R3LWVkbWEvS2NvbmZpZwpuZXcgZmlsZSBtb2RlIDEwMDY0 NAppbmRleCAwMDAwMDAwLi4zMDE2YmVkCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9kbWEv ZHctZWRtYS9LY29uZmlnCkBAIC0wLDAgKzEsOSBAQAorIyBTUERYLUxpY2Vuc2UtSWRlbnRpZmll cjogR1BMLTIuMAorCitjb25maWcgRFdfRURNQQorCXRyaXN0YXRlICJTeW5vcHN5cyBEZXNpZ25X YXJlIGVETUEgY29udHJvbGxlciBkcml2ZXIiCisJc2VsZWN0IERNQV9FTkdJTkUKKwlzZWxlY3Qg RE1BX1ZJUlRVQUxfQ0hBTk5FTFMKKwloZWxwCisJICBTdXBwb3J0IHRoZSBTeW5vcHN5cyBEZXNp Z25XYXJlIGVETUEgY29udHJvbGxlciwgbm9ybWFsbHkKKwkgIGltcGxlbWVudGVkIG9uIGVuZHBv aW50cyBTb0NzLgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9kbWEvZHctZWRtYS9NYWtlZmlsZSBiL2Ry aXZlcnMvZG1hL2R3LWVkbWEvTWFrZWZpbGUKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAw MDAwMC4uMzIyNDAxMAotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZlcnMvZG1hL2R3LWVkbWEvTWFr ZWZpbGUKQEAgLTAsMCArMSw0IEBACisjIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4w CisKK29iai0kKENPTkZJR19EV19FRE1BKQkJKz0gZHctZWRtYS5vCitkdy1lZG1hLW9ianMJCQk6 PSBkdy1lZG1hLWNvcmUubwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9kbWEvZHctZWRtYS9kdy1lZG1h LWNvcmUuYyBiL2RyaXZlcnMvZG1hL2R3LWVkbWEvZHctZWRtYS1jb3JlLmMKbmV3IGZpbGUgbW9k ZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uYmQxZDhjMAotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZl cnMvZG1hL2R3LWVkbWEvZHctZWRtYS1jb3JlLmMKQEAgLTAsMCArMSw4MjQgQEAKKy8vIFNQRFgt TGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wCisvKgorICogQ29weXJpZ2h0IChjKSAyMDE4IFN5 bm9wc3lzLCBJbmMuIGFuZC9vciBpdHMgYWZmaWxpYXRlcy4KKyAqIFN5bm9wc3lzIERlc2lnbldh cmUgZURNQSBjb3JlIGRyaXZlcgorICovCisKKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KKyNp bmNsdWRlIDxsaW51eC9kZXZpY2UuaD4KKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4KKyNpbmNs dWRlIDxsaW51eC9wbV9ydW50aW1lLmg+CisjaW5jbHVkZSA8bGludXgvZG1hZW5naW5lLmg+Cisj aW5jbHVkZSA8bGludXgvZXJyLmg+CisjaW5jbHVkZSA8bGludXgvaW50ZXJydXB0Lmg+CisjaW5j bHVkZSA8bGludXgvZG1hL2VkbWEuaD4KKworI2luY2x1ZGUgImR3LWVkbWEtY29yZS5oIgorI2lu Y2x1ZGUgIi4uL2RtYWVuZ2luZS5oIgorI2luY2x1ZGUgIi4uL3ZpcnQtZG1hLmgiCisKKyNkZWZp bmUgU0VUKHJlZywgbmFtZSwgdmFsKQkJCVwKKwlyZWcubmFtZSA9IHZhbAorCisjZGVmaW5lIFNF VF9CT1RIX0NIKG5hbWUsIHZhbHVlKQkJXAorCWRvIHsJCQkJCVwKKwkJU0VUKGR3LT53cl9lZG1h LCBuYW1lLCB2YWx1ZSk7CVwKKwkJU0VUKGR3LT5yZF9lZG1hLCBuYW1lLCB2YWx1ZSk7CVwKKwl9 IHdoaWxlICgwKQorCitzdGF0aWMgaW5saW5lCitzdHJ1Y3QgZGV2aWNlICpkY2hhbjJkZXYoc3Ry dWN0IGRtYV9jaGFuICpkY2hhbikKK3sKKwlyZXR1cm4gJmRjaGFuLT5kZXYtPmRldmljZTsKK30K Kworc3RhdGljIGlubGluZQorc3RydWN0IGRldmljZSAqY2hhbjJkZXYoc3RydWN0IGR3X2VkbWFf Y2hhbiAqY2hhbikKK3sKKwlyZXR1cm4gJmNoYW4tPnZjLmNoYW4uZGV2LT5kZXZpY2U7Cit9CisK K3N0YXRpYyBpbmxpbmUKK2NvbnN0IHN0cnVjdCBkd19lZG1hX2NvcmVfb3BzICpjaGFuMm9wcyhz dHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuKQoreworCXJldHVybiBjaGFuLT5jaGlwLT5kdy0+b3Bz OworfQorCitzdGF0aWMgaW5saW5lCitzdHJ1Y3QgZHdfZWRtYV9kZXNjICp2ZDJkd19lZG1hX2Rl c2Moc3RydWN0IHZpcnRfZG1hX2Rlc2MgKnZkKQoreworCXJldHVybiBjb250YWluZXJfb2YodmQs IHN0cnVjdCBkd19lZG1hX2Rlc2MsIHZkKTsKK30KKworc3RhdGljIHN0cnVjdCBkd19lZG1hX2J1 cnN0ICpkd19lZG1hX2FsbG9jX2J1cnN0KHN0cnVjdCBkd19lZG1hX2NodW5rICpjaHVuaykKK3sK KwlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuID0gY2h1bmstPmNoYW47CisJc3RydWN0IGR3X2Vk bWFfYnVyc3QgKmJ1cnN0OworCisJYnVyc3QgPSBremFsbG9jKHNpemVvZigqYnVyc3QpLCBHRlBf Tk9XQUlUKTsKKwlpZiAodW5saWtlbHkoIWJ1cnN0KSkKKwkJcmV0dXJuIE5VTEw7CisKKwlJTklU X0xJU1RfSEVBRCgmYnVyc3QtPmxpc3QpOworCisJaWYgKGNodW5rLT5idXJzdCkgeworCQljaHVu ay0+YnVyc3RzX2FsbG9jKys7CisJCWRldl9kYmcoY2hhbjJkZXYoY2hhbiksICI6IGFsbG9jIG5l dyBidXJzdCBlbGVtZW50ICglZClcbiIsCisJCQljaHVuay0+YnVyc3RzX2FsbG9jKTsKKwkJbGlz dF9hZGRfdGFpbCgmYnVyc3QtPmxpc3QsICZjaHVuay0+YnVyc3QtPmxpc3QpOworCX0gZWxzZSB7 CisJCWNodW5rLT5idXJzdHNfYWxsb2MgPSAwOworCQljaHVuay0+YnVyc3QgPSBidXJzdDsKKwkJ ZGV2X2RiZyhjaGFuMmRldihjaGFuKSwgIjogYWxsb2MgbmV3IGJ1cnN0IGhlYWRcbiIpOworCX0K KworCXJldHVybiBidXJzdDsKK30KKworc3RhdGljIHN0cnVjdCBkd19lZG1hX2NodW5rICpkd19l ZG1hX2FsbG9jX2NodW5rKHN0cnVjdCBkd19lZG1hX2Rlc2MgKmRlc2MpCit7CisJc3RydWN0IGR3 X2VkbWFfY2hhbiAqY2hhbiA9IGRlc2MtPmNoYW47CisJc3RydWN0IGR3X2VkbWEgKmR3ID0gY2hh bi0+Y2hpcC0+ZHc7CisJc3RydWN0IGR3X2VkbWFfY2h1bmsgKmNodW5rOworCisJY2h1bmsgPSBr emFsbG9jKHNpemVvZigqY2h1bmspLCBHRlBfTk9XQUlUKTsKKwlpZiAodW5saWtlbHkoIWNodW5r KSkKKwkJcmV0dXJuIE5VTEw7CisKKwlJTklUX0xJU1RfSEVBRCgmY2h1bmstPmxpc3QpOworCWNo dW5rLT5jaGFuID0gY2hhbjsKKwljaHVuay0+Y2IgPSAhKGRlc2MtPmNodW5rc19hbGxvYyAlIDIp OworCWNodW5rLT5wX2FkZHIgPSAoZG1hX2FkZHJfdCkoZHctPnBhX2xsICsgY2hhbi0+bGxfb2Zm KTsKKwljaHVuay0+dl9hZGRyID0gKGRtYV9hZGRyX3QpKGR3LT52YV9sbCArIGNoYW4tPmxsX29m Zik7CisKKwlpZiAoZGVzYy0+Y2h1bmspIHsKKwkJZGVzYy0+Y2h1bmtzX2FsbG9jKys7CisJCWRl dl9kYmcoY2hhbjJkZXYoY2hhbiksICI6IGFsbG9jIG5ldyBjaHVuayBlbGVtZW50ICglZClcbiIs CisJCQlkZXNjLT5jaHVua3NfYWxsb2MpOworCQlsaXN0X2FkZF90YWlsKCZjaHVuay0+bGlzdCwg JmRlc2MtPmNodW5rLT5saXN0KTsKKwkJZHdfZWRtYV9hbGxvY19idXJzdChjaHVuayk7CisJfSBl bHNlIHsKKwkJY2h1bmstPmJ1cnN0ID0gTlVMTDsKKwkJZGVzYy0+Y2h1bmtzX2FsbG9jID0gMDsK KwkJZGVzYy0+Y2h1bmsgPSBjaHVuazsKKwkJZGV2X2RiZyhjaGFuMmRldihjaGFuKSwgIjogYWxs b2MgbmV3IGNodW5rIGhlYWRcbiIpOworCX0KKworCXJldHVybiBjaHVuazsKK30KKworc3RhdGlj IHN0cnVjdCBkd19lZG1hX2Rlc2MgKmR3X2VkbWFfYWxsb2NfZGVzYyhzdHJ1Y3QgZHdfZWRtYV9j aGFuICpjaGFuKQoreworCXN0cnVjdCBkd19lZG1hX2Rlc2MgKmRlc2M7CisKKwlkZXZfZGJnKGNo YW4yZGV2KGNoYW4pLCAiOiBhbGxvYyBuZXcgZGVzY3JpcHRvclxuIik7CisKKwlkZXNjID0ga3ph bGxvYyhzaXplb2YoKmRlc2MpLCBHRlBfTk9XQUlUKTsKKwlpZiAodW5saWtlbHkoIWRlc2MpKQor CQlyZXR1cm4gTlVMTDsKKworCWRlc2MtPmNoYW4gPSBjaGFuOworCWR3X2VkbWFfYWxsb2NfY2h1 bmsoZGVzYyk7CisKKwlyZXR1cm4gZGVzYzsKK30KKworc3RhdGljIHZvaWQgZHdfZWRtYV9mcmVl X2J1cnN0KHN0cnVjdCBkd19lZG1hX2NodW5rICpjaHVuaykKK3sKKwlzdHJ1Y3QgZHdfZWRtYV9i dXJzdCAqY2hpbGQsICpfbmV4dDsKKworCWlmICghY2h1bmstPmJ1cnN0KQorCQlyZXR1cm47CisK KwkvKiBSZW1vdmUgYWxsIHRoZSBsaXN0IGVsZW1lbnRzICovCisJbGlzdF9mb3JfZWFjaF9lbnRy eV9zYWZlKGNoaWxkLCBfbmV4dCwgJmNodW5rLT5idXJzdC0+bGlzdCwgbGlzdCkgeworCQlsaXN0 X2RlbCgmY2hpbGQtPmxpc3QpOworCQlrZnJlZShjaGlsZCk7CisJCWNodW5rLT5idXJzdHNfYWxs b2MtLTsKKwl9CisKKwkvKiBSZW1vdmUgdGhlIGxpc3QgaGVhZCAqLworCWtmcmVlKGNoaWxkKTsK KwljaHVuay0+YnVyc3QgPSBOVUxMOworfQorCitzdGF0aWMgdm9pZCBkd19lZG1hX2ZyZWVfY2h1 bmsoc3RydWN0IGR3X2VkbWFfZGVzYyAqZGVzYykKK3sKKwlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpj aGFuID0gZGVzYy0+Y2hhbjsKKwlzdHJ1Y3QgZHdfZWRtYV9jaHVuayAqY2hpbGQsICpfbmV4dDsK KworCWlmICghZGVzYy0+Y2h1bmspCisJCXJldHVybjsKKworCS8qIFJlbW92ZSBhbGwgdGhlIGxp c3QgZWxlbWVudHMgKi8KKwlsaXN0X2Zvcl9lYWNoX2VudHJ5X3NhZmUoY2hpbGQsIF9uZXh0LCAm ZGVzYy0+Y2h1bmstPmxpc3QsIGxpc3QpIHsKKwkJZHdfZWRtYV9mcmVlX2J1cnN0KGNoaWxkKTsK KwkJaWYgKGNoaWxkLT5idXJzdHNfYWxsb2MpCisJCQlkZXZfZGJnKGNoYW4yZGV2KGNoYW4pLAki OiAlZCBidXJzdHMgc3RpbGwgYWxsb2NhdGVkXG4iLAorCQkJCWNoaWxkLT5idXJzdHNfYWxsb2Mp OworCQlsaXN0X2RlbCgmY2hpbGQtPmxpc3QpOworCQlrZnJlZShjaGlsZCk7CisJCWRlc2MtPmNo dW5rc19hbGxvYy0tOworCX0KKworCS8qIFJlbW92ZSB0aGUgbGlzdCBoZWFkICovCisJa2ZyZWUo Y2hpbGQpOworCWRlc2MtPmNodW5rID0gTlVMTDsKK30KKworc3RhdGljIHZvaWQgZHdfZWRtYV9m cmVlX2Rlc2Moc3RydWN0IGR3X2VkbWFfZGVzYyAqZGVzYykKK3sKKwlzdHJ1Y3QgZHdfZWRtYV9j aGFuICpjaGFuID0gZGVzYy0+Y2hhbjsKKwl1bnNpZ25lZCBsb25nIGZsYWdzOworCisJc3Bpbl9s b2NrX2lycXNhdmUoJmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsKKworCWR3X2VkbWFfZnJlZV9jaHVu ayhkZXNjKTsKKwlpZiAoZGVzYy0+Y2h1bmtzX2FsbG9jKQorCQlkZXZfZGJnKGNoYW4yZGV2KGNo YW4pLCAiOiAlZCBjaHVua3Mgc3RpbGwgYWxsb2NhdGVkXG4iLAorCQkJZGVzYy0+Y2h1bmtzX2Fs bG9jKTsKKworCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsK K30KKworc3RhdGljIHZvaWQgdmNoYW5fZnJlZV9kZXNjKHN0cnVjdCB2aXJ0X2RtYV9kZXNjICp2 ZGVzYykKK3sKKwlkd19lZG1hX2ZyZWVfZGVzYyh2ZDJkd19lZG1hX2Rlc2ModmRlc2MpKTsKK30K Kworc3RhdGljIHZvaWQgZHdfZWRtYV9zdGFydF90cmFuc2ZlcihzdHJ1Y3QgZHdfZWRtYV9jaGFu ICpjaGFuKQoreworCXN0cnVjdCB2aXJ0X2RtYV9kZXNjICp2ZDsKKwlzdHJ1Y3QgZHdfZWRtYV9k ZXNjICpkZXNjOworCXN0cnVjdCBkd19lZG1hX2NodW5rICpjaGlsZCwgKl9uZXh0OworCWNvbnN0 IHN0cnVjdCBkd19lZG1hX2NvcmVfb3BzICpvcHMgPSBjaGFuMm9wcyhjaGFuKTsKKworCXZkID0g dmNoYW5fbmV4dF9kZXNjKCZjaGFuLT52Yyk7CisJaWYgKCF2ZCkKKwkJcmV0dXJuOworCisJZGVz YyA9IHZkMmR3X2VkbWFfZGVzYyh2ZCk7CisJaWYgKCFkZXNjKQorCQlyZXR1cm47CisKKwlsaXN0 X2Zvcl9lYWNoX2VudHJ5X3NhZmUoY2hpbGQsIF9uZXh0LCAmZGVzYy0+Y2h1bmstPmxpc3QsIGxp c3QpIHsKKwkJb3BzLT5zdGFydChjaGlsZCwgIWRlc2MtPnhmZXJfc3opOworCQlkZXNjLT54ZmVy X3N6ICs9IGNoaWxkLT5zejsKKwkJZGV2X2RiZyhjaGFuMmRldihjaGFuKSwgIjogdHJhbnNmZXIg b2YgJXUgYnl0ZXMgc3RhcnRlZFxuIiwgY2hpbGQtPnN6KTsKKworCQlkd19lZG1hX2ZyZWVfYnVy c3QoY2hpbGQpOworCQlpZiAoY2hpbGQtPmJ1cnN0c19hbGxvYykKKwkJCWRldl9kYmcoY2hhbjJk ZXYoY2hhbiksCSI6ICVkIGJ1cnN0cyBzdGlsbCBhbGxvY2F0ZWRcbiIsCisJCQkJY2hpbGQtPmJ1 cnN0c19hbGxvYyk7CisJCWxpc3RfZGVsKCZjaGlsZC0+bGlzdCk7CisJCWtmcmVlKGNoaWxkKTsK KwkJZGVzYy0+Y2h1bmtzX2FsbG9jLS07CisKKwkJcmV0dXJuOworCX0KK30KKworc3RhdGljIGlu dCBkd19lZG1hX2RldmljZV9jb25maWcoc3RydWN0IGRtYV9jaGFuICpkY2hhbiwKKwkJCQkgc3Ry dWN0IGRtYV9zbGF2ZV9jb25maWcgKmNvbmZpZykKK3sKKwlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpj aGFuID0gZGNoYW4yZHdfZWRtYV9jaGFuKGRjaGFuKTsKKwljb25zdCBzdHJ1Y3QgZHdfZWRtYV9j b3JlX29wcyAqb3BzID0gY2hhbjJvcHMoY2hhbik7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKwlp bnQgZXJyID0gMDsKKworCXNwaW5fbG9ja19pcnFzYXZlKCZjaGFuLT52Yy5sb2NrLCBmbGFncyk7 CisKKwlpZiAoIWNvbmZpZykgeworCQllcnIgPSAtRUlOVkFMOworCQlnb3RvIGVycl9jb25maWc7 CisJfQorCisJaWYgKGNoYW4tPmNvbmZpZ3VyZWQpIHsKKwkJZGV2X2VycihjaGFuMmRldihjaGFu KSwgIjogY2hhbm5lbCBhbHJlYWR5IGNvbmZpZ3VyZWRcbiIpOworCQllcnIgPSAtRVBFUk07CisJ CWdvdG8gZXJyX2NvbmZpZzsKKwl9CisKKwlkZXZfZGJnKGNoYW4yZGV2KGNoYW4pLCAiOiBzcmNf YWRkcihwaHlzaWNhbCkgPSAweCUuMTZ4XG4iLAorCQljb25maWctPnNyY19hZGRyKTsKKwlkZXZf ZGJnKGNoYW4yZGV2KGNoYW4pLCAiOiBkc3RfYWRkcihwaHlzaWNhbCkgPSAweCUuMTZ4XG4iLAor CQljb25maWctPmRzdF9hZGRyKTsKKworCWVyciA9IG9wcy0+ZGV2aWNlX2NvbmZpZyhkY2hhbik7 CisJaWYgKCFlcnIpIHsKKwkJY2hhbi0+Y29uZmlndXJlZCA9IHRydWU7CisJCWRldl9kYmcoY2hh bjJkZXYoY2hhbiksCSI6IGNoYW5uZWwgY29uZmlndXJlZFxuIik7CisJfQorCitlcnJfY29uZmln OgorCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsKKwlyZXR1 cm4gZXJyOworfQorCitzdGF0aWMgaW50IGR3X2VkbWFfZGV2aWNlX3BhdXNlKHN0cnVjdCBkbWFf Y2hhbiAqZGNoYW4pCit7CisJc3RydWN0IGR3X2VkbWFfY2hhbiAqY2hhbiA9IGRjaGFuMmR3X2Vk bWFfY2hhbihkY2hhbik7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKwlpbnQgZXJyID0gMDsKKwor CXNwaW5fbG9ja19pcnFzYXZlKCZjaGFuLT52Yy5sb2NrLCBmbGFncyk7CisKKwlpZiAoIWNoYW4t PmNvbmZpZ3VyZWQpIHsKKwkJZGV2X2VycihkY2hhbjJkZXYoZGNoYW4pLCAiOiBjaGFubmVsIG5v dCBjb25maWd1cmVkXG4iKTsKKwkJZXJyID0gLUVQRVJNOworCQlnb3RvIGVycl9wYXVzZTsKKwl9 CisKKwlpZiAoY2hhbi0+c3RhdHVzICE9IEVETUFfU1RfQlVTWSkgeworCQllcnIgPSAtRVBFUk07 CisJCWdvdG8gZXJyX3BhdXNlOworCX0KKworCWlmIChjaGFuLT5yZXF1ZXN0ICE9IEVETUFfUkVR X05PTkUpIHsKKwkJZXJyID0gLUVQRVJNOworCQlnb3RvIGVycl9wYXVzZTsKKwl9CisKKwljaGFu LT5yZXF1ZXN0ID0gRURNQV9SRVFfUEFVU0U7CisJZGV2X2RiZyhkY2hhbjJkZXYoZGNoYW4pLCAi OiBwYXVzZSByZXF1ZXN0ZWRcbiIpOworCitlcnJfcGF1c2U6CisJc3Bpbl91bmxvY2tfaXJxcmVz dG9yZSgmY2hhbi0+dmMubG9jaywgZmxhZ3MpOworCXJldHVybiBlcnI7Cit9CisKK3N0YXRpYyBp bnQgZHdfZWRtYV9kZXZpY2VfcmVzdW1lKHN0cnVjdCBkbWFfY2hhbiAqZGNoYW4pCit7CisJc3Ry dWN0IGR3X2VkbWFfY2hhbiAqY2hhbiA9IGRjaGFuMmR3X2VkbWFfY2hhbihkY2hhbik7CisJdW5z aWduZWQgbG9uZyBmbGFnczsKKwlpbnQgZXJyID0gMDsKKworCXNwaW5fbG9ja19pcnFzYXZlKCZj aGFuLT52Yy5sb2NrLCBmbGFncyk7CisKKwlpZiAoIWNoYW4tPmNvbmZpZ3VyZWQpIHsKKwkJZGV2 X2VycihkY2hhbjJkZXYoZGNoYW4pLCAiOiBjaGFubmVsIG5vdCBjb25maWd1cmVkXG4iKTsKKwkJ ZXJyID0gLUVQRVJNOworCQlnb3RvIGVycl9yZXN1bWU7CisJfQorCisJaWYgKGNoYW4tPnN0YXR1 cyAhPSBFRE1BX1NUX1BBVVNFKSB7CisJCWVyciA9IC1FUEVSTTsKKwkJZ290byBlcnJfcmVzdW1l OworCX0KKworCWlmIChjaGFuLT5yZXF1ZXN0ICE9IEVETUFfUkVRX05PTkUpIHsKKwkJZXJyID0g LUVQRVJNOworCQlnb3RvIGVycl9yZXN1bWU7CisJfQorCisJY2hhbi0+c3RhdHVzID0gRURNQV9T VF9CVVNZOworCWRldl9kYmcoZGNoYW4yZGV2KGRjaGFuKSwgIjogdHJhbnNmZXIgcmVzdW1lZFxu Iik7CisJZHdfZWRtYV9zdGFydF90cmFuc2ZlcihjaGFuKTsKKworZXJyX3Jlc3VtZToKKwlzcGlu X3VubG9ja19pcnFyZXN0b3JlKCZjaGFuLT52Yy5sb2NrLCBmbGFncyk7CisJcmV0dXJuIGVycjsK K30KKworc3RhdGljIGludCBkd19lZG1hX2RldmljZV90ZXJtaW5hdGVfYWxsKHN0cnVjdCBkbWFf Y2hhbiAqZGNoYW4pCit7CisJc3RydWN0IGR3X2VkbWFfY2hhbiAqY2hhbiA9IGRjaGFuMmR3X2Vk bWFfY2hhbihkY2hhbik7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKwlpbnQgZXJyID0gMDsKKwlM SVNUX0hFQUQoaGVhZCk7CisKKwlzcGluX2xvY2tfaXJxc2F2ZSgmY2hhbi0+dmMubG9jaywgZmxh Z3MpOworCisJaWYgKCFjaGFuLT5jb25maWd1cmVkKSB7CisJCWRldl9lcnIoZGNoYW4yZGV2KGRj aGFuKSwgIjogY2hhbm5lbCBub3QgY29uZmlndXJlZFxuIik7CisJCWVyciA9IC1FUEVSTTsKKwkJ Z290byBlcnJfdGVybWluYXRlOworCX0KKworCWlmIChjaGFuLT5zdGF0dXMgPT0gRURNQV9TVF9Q QVVTRSkgeworCQlkZXZfZGJnKGRjaGFuMmRldihkY2hhbiksICI6IGNoYW5uZWwgaXMgcGF1c2Vk LCBzdG9wcGluZyBpbW1lZGlhdGVseVxuIik7CisJCXZjaGFuX2dldF9hbGxfZGVzY3JpcHRvcnMo JmNoYW4tPnZjLCAmaGVhZCk7CisJCXZjaGFuX2RtYV9kZXNjX2ZyZWVfbGlzdCgmY2hhbi0+dmMs ICZoZWFkKTsKKwkJY2hhbi0+c3RhdHVzID0gRURNQV9TVF9JRExFOworCQlnb3RvIGVycl90ZXJt aW5hdGU7CisJfSBlbHNlIGlmIChjaGFuLT5zdGF0dXMgIT0gRURNQV9TVF9CVVNZKSB7CisJCWVy ciA9IC1FUEVSTTsKKwkJZ290byBlcnJfdGVybWluYXRlOworCX0KKworCWlmIChjaGFuLT5yZXF1 ZXN0ID4gRURNQV9SRVFfUEFVU0UpIHsKKwkJZXJyID0gLUVQRVJNOworCQlnb3RvIGVycl90ZXJt aW5hdGU7CisJfQorCisJY2hhbi0+cmVxdWVzdCA9IEVETUFfUkVRX1NUT1A7CisJZGV2X2RiZyhk Y2hhbjJkZXYoZGNoYW4pLCAiOiB0ZXJtaW5hdGlvbiByZXF1ZXN0ZWRcbiIpOworCitlcnJfdGVy bWluYXRlOgorCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsK KwlyZXR1cm4gZXJyOworfQorCitzdGF0aWMgdm9pZCBkd19lZG1hX2RldmljZV9pc3N1ZV9wZW5k aW5nKHN0cnVjdCBkbWFfY2hhbiAqZGNoYW4pCit7CisJc3RydWN0IGR3X2VkbWFfY2hhbiAqY2hh biA9IGRjaGFuMmR3X2VkbWFfY2hhbihkY2hhbik7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKwor CXNwaW5fbG9ja19pcnFzYXZlKCZjaGFuLT52Yy5sb2NrLCBmbGFncyk7CisKKwlpZiAoY2hhbi0+ Y29uZmlndXJlZCAmJiBjaGFuLT5yZXF1ZXN0ID09IEVETUFfUkVRX05PTkUgJiYKKwkgICAgY2hh bi0+c3RhdHVzID09IEVETUFfU1RfSURMRSAmJiB2Y2hhbl9pc3N1ZV9wZW5kaW5nKCZjaGFuLT52 YykpIHsKKwkJZGV2X2RiZyhkY2hhbjJkZXYoZGNoYW4pLCAiOiB0cmFuc2ZlciBpc3N1ZWRcbiIp OworCQljaGFuLT5zdGF0dXMgPSBFRE1BX1NUX0JVU1k7CisJCWR3X2VkbWFfc3RhcnRfdHJhbnNm ZXIoY2hhbik7CisJfQorCisJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmY2hhbi0+dmMubG9jaywg ZmxhZ3MpOworfQorCitzdGF0aWMgZW51bSBkbWFfc3RhdHVzCitkd19lZG1hX2RldmljZV90eF9z dGF0dXMoc3RydWN0IGRtYV9jaGFuICpkY2hhbiwgZG1hX2Nvb2tpZV90IGNvb2tpZSwKKwkJCSBz dHJ1Y3QgZG1hX3R4X3N0YXRlICp0eHN0YXRlKQoreworCXN0cnVjdCBkd19lZG1hX2NoYW4gKmNo YW4gPSBkY2hhbjJkd19lZG1hX2NoYW4oZGNoYW4pOworCWNvbnN0IHN0cnVjdCBkd19lZG1hX2Nv cmVfb3BzICpvcHMgPSBjaGFuMm9wcyhjaGFuKTsKKwl1bnNpZ25lZCBsb25nIGZsYWdzOworCWVu dW0gZG1hX3N0YXR1cyByZXQ7CisKKwlzcGluX2xvY2tfaXJxc2F2ZSgmY2hhbi0+dmMubG9jaywg ZmxhZ3MpOworCisJcmV0ID0gb3BzLT5jaF9zdGF0dXMoY2hhbik7CisJaWYgKHJldCA9PSBETUFf RVJST1IpIHsKKwkJZ290byByZXRfc3RhdHVzOworCX0gZWxzZSBpZiAocmV0ID09IERNQV9JTl9Q Uk9HUkVTUykgeworCQljaGFuLT5zdGF0dXMgPSBFRE1BX1NUX0JVU1k7CisJCWdvdG8gcmV0X3N0 YXR1czsKKwl9IGVsc2UgeworCQkvKiBETUFfQ09NUExFVEUgKi8KKwkJaWYgKGNoYW4tPnN0YXR1 cyA9PSBFRE1BX1NUX1BBVVNFKQorCQkJcmV0ID0gRE1BX1BBVVNFRDsKKwkJZWxzZSBpZiAoY2hh bi0+c3RhdHVzID09IEVETUFfU1RfQlVTWSkKKwkJCXJldCA9IERNQV9JTl9QUk9HUkVTUzsKKwkJ ZWxzZQorCQkJcmV0ID0gRE1BX0NPTVBMRVRFOworCX0KKworcmV0X3N0YXR1czoKKwlzcGluX3Vu bG9ja19pcnFyZXN0b3JlKCZjaGFuLT52Yy5sb2NrLCBmbGFncyk7CisJZG1hX3NldF9yZXNpZHVl KHR4c3RhdGUsIDApOworCisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIHN0cnVjdCBkbWFfYXN5 bmNfdHhfZGVzY3JpcHRvciAqCitkd19lZG1hX2RldmljZV9wcmVwX3NsYXZlX3NnKHN0cnVjdCBk bWFfY2hhbiAqZGNoYW4sIHN0cnVjdCBzY2F0dGVybGlzdCAqc2dsLAorCQkJICAgICB1bnNpZ25l ZCBpbnQgc2dfbGVuLAorCQkJICAgICBlbnVtIGRtYV90cmFuc2Zlcl9kaXJlY3Rpb24gZGlyZWN0 aW9uLAorCQkJICAgICB1bnNpZ25lZCBsb25nIGZsYWdzLCB2b2lkICpjb250ZXh0KQoreworCXN0 cnVjdCBkd19lZG1hX2NoYW4gKmNoYW4gPSBkY2hhbjJkd19lZG1hX2NoYW4oZGNoYW4pOworCXN0 cnVjdCBkd19lZG1hX2Rlc2MgKmRlc2M7CisJc3RydWN0IGR3X2VkbWFfY2h1bmsgKmNodW5rOwor CXN0cnVjdCBkd19lZG1hX2J1cnN0ICpidXJzdDsKKwlzdHJ1Y3Qgc2NhdHRlcmxpc3QgKnNnOwor CWRtYV9hZGRyX3QgZGV2X2FkZHIgPSBjaGFuLT5wX2FkZHI7CisJdW5zaWduZWQgbG9uZyBzZmxh Z3M7CisJaW50IGk7CisKKwlpZiAoc2dfbGVuIDwgMSkgeworCQlkZXZfZXJyKGNoYW4yZGV2KGNo YW4pLCAiOiBpbnZhbGlkIHNnIGxlbmd0aCAldVxuIiwgc2dfbGVuKTsKKwkJcmV0dXJuIE5VTEw7 CisJfQorCisJaWYgKGRpcmVjdGlvbiA9PSBETUFfREVWX1RPX01FTSAmJiBjaGFuLT5kaXIgPT0g RURNQV9ESVJfV1JJVEUpIHsKKwkJZGV2X2RiZyhjaGFuMmRldihjaGFuKSwJIjogcHJlcGFyZSBv cGVyYXRpb24gKFdSSVRFKVxuIik7CisJfSBlbHNlIGlmIChkaXJlY3Rpb24gPT0gRE1BX01FTV9U T19ERVYgJiYgY2hhbi0+ZGlyID09IEVETUFfRElSX1JFQUQpIHsKKwkJZGV2X2RiZyhjaGFuMmRl dihjaGFuKSwJIjogcHJlcGFyZSBvcGVyYXRpb24gKFJFQUQpXG4iKTsKKwl9IGVsc2UgeworCQlk ZXZfZXJyKGNoYW4yZGV2KGNoYW4pLCAiOiBpbnZhbGlkIGRpcmVjdGlvblxuIik7CisJCXJldHVy biBOVUxMOworCX0KKworCWlmICghY2hhbi0+Y29uZmlndXJlZCkgeworCQlkZXZfZXJyKGRjaGFu MmRldihkY2hhbiksICI6IGNoYW5uZWwgbm90IGNvbmZpZ3VyZWRcbiIpOworCQlyZXR1cm4gTlVM TDsKKwl9CisJaWYgKGNoYW4tPnN0YXR1cyA9PSBFRE1BX1NUX0JVU1kpIHsKKwkJZGV2X2Vycihj aGFuMmRldihjaGFuKSwgIjogY2hhbm5lbCBpcyBidXN5IG9yIHBhdXNlZFxuIik7CisJCXJldHVy biBOVUxMOworCX0KKworCXNwaW5fbG9ja19pcnFzYXZlKCZjaGFuLT52Yy5sb2NrLCBzZmxhZ3Mp OworCisJZGVzYyA9IGR3X2VkbWFfYWxsb2NfZGVzYyhjaGFuKTsKKwlpZiAodW5saWtlbHkoIWRl c2MpKQorCQlnb3RvIGVycl9hbGxvYzsKKworCWNodW5rID0gZHdfZWRtYV9hbGxvY19jaHVuayhk ZXNjKTsKKwlpZiAodW5saWtlbHkoIWNodW5rKSkKKwkJZ290byBlcnJfYWxsb2M7CisKKwlmb3Jf ZWFjaF9zZyhzZ2wsIHNnLCBzZ19sZW4sIGkpIHsKKwkJaWYgKGNodW5rLT5idXJzdHNfYWxsb2Mg PT0gY2hhbi0+bGxfbWF4KSB7CisJCQljaHVuayA9IGR3X2VkbWFfYWxsb2NfY2h1bmsoZGVzYyk7 CisJCQlpZiAodW5saWtlbHkoIWNodW5rKSkKKwkJCQlnb3RvIGVycl9hbGxvYzsKKwkJfQorCisJ CWJ1cnN0ID0gZHdfZWRtYV9hbGxvY19idXJzdChjaHVuayk7CisKKwkJaWYgKHVubGlrZWx5KCFi dXJzdCkpCisJCQlnb3RvIGVycl9hbGxvYzsKKworCQlpZiAoZGlyZWN0aW9uID09IERNQV9NRU1f VE9fREVWKSB7CisJCQlidXJzdC0+c2FyID0gc2dfZG1hX2FkZHJlc3Moc2cpOworCQkJYnVyc3Qt PmRhciA9IGRldl9hZGRyOworCQl9IGVsc2UgeworCQkJYnVyc3QtPnNhciA9IGRldl9hZGRyOwor CQkJYnVyc3QtPmRhciA9IHNnX2RtYV9hZGRyZXNzKHNnKTsKKwkJfQorCisJCWJ1cnN0LT5zeiA9 IHNnX2RtYV9sZW4oc2cpOworCQljaHVuay0+c3ogKz0gYnVyc3QtPnN6OworCQlkZXNjLT5hbGxv Y19zeiArPSBidXJzdC0+c3o7CisJCWRldl9hZGRyICs9IGJ1cnN0LT5zejsKKworCQlkZXZfZGJn KGNoYW4yZGV2KGNoYW4pLCAibGxpICV1LyV1LCBzYXI9MHglLjE2bGx4LCBkYXI9MHglLjE2bGx4 LCBzaXplPSV1IGJ5dGVzXG4iLAorCQkJaSArIDEsIHNnX2xlbiwKKwkJCWJ1cnN0LT5zYXIsIGJ1 cnN0LT5kYXIsCisJCQlidXJzdC0+c3opOworCX0KKworCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUo JmNoYW4tPnZjLmxvY2ssIHNmbGFncyk7CisJcmV0dXJuIHZjaGFuX3R4X3ByZXAoJmNoYW4tPnZj LCAmZGVzYy0+dmQsIGZsYWdzKTsKKworZXJyX2FsbG9jOgorCXNwaW5fdW5sb2NrX2lycXJlc3Rv cmUoJmNoYW4tPnZjLmxvY2ssIHNmbGFncyk7CisJaWYgKGRlc2MpCisJCWR3X2VkbWFfZnJlZV9k ZXNjKGRlc2MpOworCXJldHVybiBOVUxMOworfQorCitzdGF0aWMgdm9pZCBkd19lZG1hX2RvbmVf aW50ZXJydXB0KHN0cnVjdCBkd19lZG1hX2NoYW4gKmNoYW4pCit7CisJc3RydWN0IGR3X2VkbWEg KmR3ID0gY2hhbi0+Y2hpcC0+ZHc7CisJY29uc3Qgc3RydWN0IGR3X2VkbWFfY29yZV9vcHMgKm9w cyA9IGR3LT5vcHM7CisJc3RydWN0IHZpcnRfZG1hX2Rlc2MgKnZkOworCXN0cnVjdCBkd19lZG1h X2Rlc2MgKmRlc2M7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKworCW9wcy0+Y2xlYXJfZG9uZV9p bnQoY2hhbik7CisJZGV2X2RiZyhjaGFuMmRldihjaGFuKSwgIjogY2xlYXIgZG9uZSBpbnRlcnJ1 cHRcbiIpOworCisJc3Bpbl9sb2NrX2lycXNhdmUoJmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsKKwl2 ZCA9IHZjaGFuX25leHRfZGVzYygmY2hhbi0+dmMpOworCXN3aXRjaCAoY2hhbi0+cmVxdWVzdCkg eworCWNhc2UgRURNQV9SRVFfTk9ORToKKwkJZGVzYyA9IHZkMmR3X2VkbWFfZGVzYyh2ZCk7CisJ CWlmIChkZXNjLT5jaHVua3NfYWxsb2MpIHsKKwkJCWRldl9kYmcoY2hhbjJkZXYoY2hhbiksCSI6 IHN1Yi10cmFuc2ZlciBjb21wbGV0ZVxuIik7CisJCQljaGFuLT5zdGF0dXMgPSBFRE1BX1NUX0JV U1k7CisJCQlkZXZfZGJnKGNoYW4yZGV2KGNoYW4pLCAiOiB0cmFuc2ZlcnJlZCAldSBieXRlc1xu IiwKKwkJCQlkZXNjLT54ZmVyX3N6KTsKKwkJCWR3X2VkbWFfc3RhcnRfdHJhbnNmZXIoY2hhbik7 CisJCX0gZWxzZSB7CisJCQlsaXN0X2RlbCgmdmQtPm5vZGUpOworCQkJdmNoYW5fY29va2llX2Nv bXBsZXRlKHZkKTsKKwkJCWNoYW4tPnN0YXR1cyA9IEVETUFfU1RfSURMRTsKKwkJCWRldl9kYmco Y2hhbjJkZXYoY2hhbiksCSI6IHRyYW5zZmVyIGNvbXBsZXRlXG4iKTsKKwkJfQorCQlicmVhazsK KwljYXNlIEVETUFfUkVRX1NUT1A6CisJCWxpc3RfZGVsKCZ2ZC0+bm9kZSk7CisJCXZjaGFuX2Nv b2tpZV9jb21wbGV0ZSh2ZCk7CisJCWNoYW4tPnJlcXVlc3QgPSBFRE1BX1JFUV9OT05FOworCQlj aGFuLT5zdGF0dXMgPSBFRE1BX1NUX0lETEU7CisJCWRldl9kYmcoY2hhbjJkZXYoY2hhbiksCSI6 IHRyYW5zZmVyIHN0b3BcbiIpOworCQlicmVhazsKKwljYXNlIEVETUFfUkVRX1BBVVNFOgorCQlj aGFuLT5yZXF1ZXN0ID0gRURNQV9SRVFfTk9ORTsKKwkJY2hhbi0+c3RhdHVzID0gRURNQV9TVF9Q QVVTRTsKKwkJYnJlYWs7CisJZGVmYXVsdDoKKwkJZGV2X2VycihjaGFuMmRldihjaGFuKSwgIjog aW52YWxpZCBzdGF0dXMgc3RhdGVcbiIpOworCQlicmVhazsKKwl9CisJc3Bpbl91bmxvY2tfaXJx cmVzdG9yZSgmY2hhbi0+dmMubG9jaywgZmxhZ3MpOworfQorCitzdGF0aWMgdm9pZCBkd19lZG1h X2Fib3J0X2ludGVycnVwdChzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuKQoreworCXN0cnVjdCBk d19lZG1hICpkdyA9IGNoYW4tPmNoaXAtPmR3OworCWNvbnN0IHN0cnVjdCBkd19lZG1hX2NvcmVf b3BzICpvcHMgPSBkdy0+b3BzOworCXN0cnVjdCB2aXJ0X2RtYV9kZXNjICp2ZDsKKwl1bnNpZ25l ZCBsb25nIGZsYWdzOworCisJb3BzLT5jbGVhcl9hYm9ydF9pbnQoY2hhbik7CisJZGV2X2RiZyhj aGFuMmRldihjaGFuKSwgIjogY2xlYXIgYWJvcnQgaW50ZXJydXB0XG4iKTsKKworCXNwaW5fbG9j a19pcnFzYXZlKCZjaGFuLT52Yy5sb2NrLCBmbGFncyk7CisJdmQgPSB2Y2hhbl9uZXh0X2Rlc2Mo JmNoYW4tPnZjKTsKKwlsaXN0X2RlbCgmdmQtPm5vZGUpOworCXZjaGFuX2Nvb2tpZV9jb21wbGV0 ZSh2ZCk7CisJY2hhbi0+cmVxdWVzdCA9IEVETUFfUkVRX05PTkU7CisJY2hhbi0+c3RhdHVzID0g RURNQV9TVF9JRExFOworCisJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmY2hhbi0+dmMubG9jaywg ZmxhZ3MpOworfQorCitzdGF0aWMgaXJxcmV0dXJuX3QgZHdfZWRtYV9pbnRlcnJ1cHQoaW50IGly cSwgdm9pZCAqZGF0YSkKK3sKKwlzdHJ1Y3QgZHdfZWRtYV9jaGlwICpjaGlwID0gZGF0YTsKKwlz dHJ1Y3QgZHdfZWRtYSAqZHcgPSBjaGlwLT5kdzsKKwljb25zdCBzdHJ1Y3QgZHdfZWRtYV9jb3Jl X29wcyAqb3BzID0gZHctPm9wczsKKwlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuOworCXUzMiBp OworCisJLyogUG9sbCwgY2xlYXIgYW5kIHByb2Nlc3MgZXZlcnkgY2hhbmVsIGludGVycnVwdCBz dGF0dXMgKi8KKwlmb3IgKGkgPSAwOyBpIDwgKGR3LT53cl9jaF9jb3VudCArIGR3LT5yZF9jaF9j b3VudCk7IGkrKykgeworCQljaGFuID0gJmR3LT5jaGFuW2ldOworCisJCWlmIChvcHMtPnN0YXR1 c19kb25lX2ludChjaGFuKSkKKwkJCWR3X2VkbWFfZG9uZV9pbnRlcnJ1cHQoY2hhbik7CisKKwkJ aWYgKG9wcy0+c3RhdHVzX2Fib3J0X2ludChjaGFuKSkKKwkJCWR3X2VkbWFfYWJvcnRfaW50ZXJy dXB0KGNoYW4pOworCX0KKworCXJldHVybiBJUlFfSEFORExFRDsKK30KKworc3RhdGljIGludCBk d19lZG1hX2FsbG9jX2NoYW5fcmVzb3VyY2VzKHN0cnVjdCBkbWFfY2hhbiAqZGNoYW4pCit7CisJ c3RydWN0IGR3X2VkbWFfY2hhbiAqY2hhbiA9IGRjaGFuMmR3X2VkbWFfY2hhbihkY2hhbik7CisK KwlpZiAoY2hhbi0+c3RhdHVzICE9IEVETUFfU1RfSURMRSkgeworCQlkZXZfZXJyKGNoYW4yZGV2 KGNoYW4pLCAiOiBjaGFubmVsIGlzIGJ1c3lcbiIpOworCQlyZXR1cm4gLUVCVVNZOworCX0KKwor CWRldl9kYmcoZGNoYW4yZGV2KGRjaGFuKSwgIjogYWxsb2NhdGVkXG4iKTsKKworCXBtX3J1bnRp bWVfZ2V0KGNoYW4tPmNoaXAtPmRldik7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIHZvaWQg ZHdfZWRtYV9mcmVlX2NoYW5fcmVzb3VyY2VzKHN0cnVjdCBkbWFfY2hhbiAqZGNoYW4pCit7CisJ c3RydWN0IGR3X2VkbWFfY2hhbiAqY2hhbiA9IGRjaGFuMmR3X2VkbWFfY2hhbihkY2hhbik7CisJ dW5zaWduZWQgbG9uZyB0aW1lb3V0ID0gamlmZmllcyArIG1zZWNzX3RvX2ppZmZpZXMoNTAwMCk7 CisJaW50IHJldDsKKworCWlmIChjaGFuLT5zdGF0dXMgIT0gRURNQV9TVF9JRExFKQorCQlkZXZf ZXJyKGNoYW4yZGV2KGNoYW4pLCAiOiBjaGFubmVsIGlzIGJ1c3lcbiIpOworCisJZG8geworCQly ZXQgPSBkd19lZG1hX2RldmljZV90ZXJtaW5hdGVfYWxsKGRjaGFuKTsKKwkJaWYgKCFyZXQpCisJ CQlicmVhazsKKworCQlpZiAodGltZV9hZnRlcl9lcShqaWZmaWVzLCB0aW1lb3V0KSkgeworCQkJ ZGV2X2VycihjaGFuMmRldihjaGFuKSwgIjogdGltZW91dFxuIik7CisJCQlyZXR1cm47CisJCX0K KworCQljcHVfcmVsYXgoKTsKKwl9IHdoaWxlICgxKTsKKworCWRldl9kYmcoZGNoYW4yZGV2KGRj aGFuKSwgIjogZnJlZWRcbiIpOworCisJcG1fcnVudGltZV9wdXQoY2hhbi0+Y2hpcC0+ZGV2KTsK K30KKworaW50IGR3X2VkbWFfcHJvYmUoc3RydWN0IGR3X2VkbWFfY2hpcCAqY2hpcCkKK3sKKwlz dHJ1Y3QgZHdfZWRtYSAqZHcgPSBjaGlwLT5kdzsKKwljb25zdCBzdHJ1Y3QgZHdfZWRtYV9jb3Jl X29wcyAqb3BzOworCXNpemVfdCBsbF9jaHVuayA9IGR3LT5sbF9zejsKKwlpbnQgaSwgaiwgZXJy OworCisJcmF3X3NwaW5fbG9ja19pbml0KCZkdy0+bG9jayk7CisKKwlzd2l0Y2ggKGR3LT52ZXJz aW9uKSB7CisJZGVmYXVsdDoKKwkJZGV2X2VycihjaGlwLT5kZXYsICI6IHVuc3VwcG9ydGVkIHZl cnNpb25cbiIpOworCQlyZXR1cm4gLUVQRVJNOworCX0KKworCXBtX3J1bnRpbWVfZ2V0X3N5bmMo Y2hpcC0+ZGV2KTsKKworCWR3LT53cl9jaF9jb3VudCA9IG9wcy0+Y2hfY291bnQoZHcsIFdSSVRF KTsKKwlpZiAoIWR3LT53cl9jaF9jb3VudCkgeworCQlkZXZfZXJyKGNoaXAtPmRldiwgIjogaW52 YWxpZCBudW1iZXIgb2Ygd3JpdGUgY2hhbm5lbHMoMClcbiIpOworCQlyZXR1cm4gLUVJTlZBTDsK Kwl9CisKKwlkdy0+cmRfY2hfY291bnQgPSBvcHMtPmNoX2NvdW50KGR3LCBSRUFEKTsKKwlpZiAo IWR3LT5yZF9jaF9jb3VudCkgeworCQlkZXZfZXJyKGNoaXAtPmRldiwgIjogaW52YWxpZCBudW1i ZXIgb2YgcmVhZCBjaGFubmVscygwKVxuIik7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWRl dl9kYmcoY2hpcC0+ZGV2LCAiQ2hhbm5lbHM6XHR3cml0ZT0lZCwgcmVhZD0lZFxuIiwKKwkJZHct PndyX2NoX2NvdW50LCBkdy0+cmRfY2hfY291bnQpOworCisJZHctPmNoYW4gPSBkZXZtX2tjYWxs b2MoY2hpcC0+ZGV2LCBkdy0+d3JfY2hfY291bnQgKyBkdy0+cmRfY2hfY291bnQsCisJCQkJc2l6 ZW9mKCpkdy0+Y2hhbiksIEdGUF9LRVJORUwpOworCWlmICghZHctPmNoYW4pCisJCXJldHVybiAt RU5PTUVNOworCisJbGxfY2h1bmsgLz0gcm91bmR1cF9wb3dfb2ZfdHdvKGR3LT53cl9jaF9jb3Vu dCArIGR3LT5yZF9jaF9jb3VudCk7CisKKwkvKiBEaXNhYmxlIGVETUEsIG9ubHkgdG8gZXN0YWJs aXNoIHRoZSBpZGVhbCBpbml0aWFsIGNvbmRpdGlvbnMgKi8KKwlvcHMtPm9mZihkdyk7CisKKwlz bnByaW50Zihkdy0+bmFtZSwgc2l6ZW9mKGR3LT5uYW1lKSwgImR3LWVkbWEtY29yZTolZCIsIGNo aXAtPmlkKTsKKworCWVyciA9IGRldm1fcmVxdWVzdF9pcnEoY2hpcC0+ZGV2LCBjaGlwLT5pcnEs IGR3X2VkbWFfaW50ZXJydXB0LAorCQkJICAgICAgIElSUUZfU0hBUkVELCBkdy0+bmFtZSwgY2hp cCk7CisJaWYgKGVycikKKwkJcmV0dXJuIGVycjsKKworCUlOSVRfTElTVF9IRUFEKCZkdy0+d3Jf ZWRtYS5jaGFubmVscyk7CisJZm9yIChpID0gMDsgaSA8IGR3LT53cl9jaF9jb3VudDsgaSsrKSB7 CisJCXN0cnVjdCBkd19lZG1hX2NoYW4gKmNoYW4gPSAmZHctPmNoYW5baV07CisKKwkJY2hhbi0+ Y2hpcCA9IGNoaXA7CisJCWNoYW4tPmlkID0gaTsKKwkJY2hhbi0+ZGlyID0gRURNQV9ESVJfV1JJ VEU7CisJCWNoYW4tPmNvbmZpZ3VyZWQgPSBmYWxzZTsKKwkJY2hhbi0+cmVxdWVzdCA9IEVETUFf UkVRX05PTkU7CisJCWNoYW4tPnN0YXR1cyA9IEVETUFfU1RfSURMRTsKKworCQljaGFuLT5sbF9v ZmYgPSAobGxfY2h1bmsgKiBpKTsKKwkJY2hhbi0+bGxfbWF4ID0gKGxsX2NodW5rIC8gMjQpIC0g MTsKKworCQljaGFuLT5tc2lfZG9uZV9hZGRyID0gZHctPm1zaV9hZGRyOworCQljaGFuLT5tc2lf YWJvcnRfYWRkciA9IGR3LT5tc2lfYWRkcjsKKwkJY2hhbi0+bXNpX2RhdGEgPSBkdy0+bXNpX2Rh dGE7CisKKwkJY2hhbi0+dmMuZGVzY19mcmVlID0gdmNoYW5fZnJlZV9kZXNjOworCQl2Y2hhbl9p bml0KCZjaGFuLT52YywgJmR3LT53cl9lZG1hKTsKKwl9CisJZG1hX2NhcF9zZXQoRE1BX1NMQVZF LCBkdy0+d3JfZWRtYS5jYXBfbWFzayk7CisJZHctPndyX2VkbWEuZGlyZWN0aW9ucyA9IEJJVChE TUFfTUVNX1RPX0RFVik7CisJZHctPndyX2VkbWEuY2hhbmNudCA9IGR3LT53cl9jaF9jb3VudDsK KworCUlOSVRfTElTVF9IRUFEKCZkdy0+cmRfZWRtYS5jaGFubmVscyk7CisJZm9yIChqID0gMDsg aiA8IGR3LT5yZF9jaF9jb3VudDsgaisrLCBpKyspIHsKKwkJc3RydWN0IGR3X2VkbWFfY2hhbiAq Y2hhbiA9ICZkdy0+Y2hhbltpXTsKKworCQljaGFuLT5jaGlwID0gY2hpcDsKKwkJY2hhbi0+aWQg PSBqOworCQljaGFuLT5kaXIgPSBFRE1BX0RJUl9SRUFEOworCQljaGFuLT5yZXF1ZXN0ID0gRURN QV9SRVFfTk9ORTsKKwkJY2hhbi0+c3RhdHVzID0gRURNQV9TVF9JRExFOworCisJCWNoYW4tPmxs X29mZiA9IChsbF9jaHVuayAqIGkpOworCQljaGFuLT5sbF9tYXggPSAobGxfY2h1bmsgLyAyNCkg LSAxOworCisJCWNoYW4tPm1zaV9kb25lX2FkZHIgPSBkdy0+bXNpX2FkZHI7CisJCWNoYW4tPm1z aV9hYm9ydF9hZGRyID0gZHctPm1zaV9hZGRyOworCQljaGFuLT5tc2lfZGF0YSA9IGR3LT5tc2lf ZGF0YTsKKworCQljaGFuLT52Yy5kZXNjX2ZyZWUgPSB2Y2hhbl9mcmVlX2Rlc2M7CisJCXZjaGFu X2luaXQoJmNoYW4tPnZjLCAmZHctPnJkX2VkbWEpOworCX0KKwlkbWFfY2FwX3NldChETUFfU0xB VkUsIGR3LT5yZF9lZG1hLmNhcF9tYXNrKTsKKwlkdy0+cmRfZWRtYS5kaXJlY3Rpb25zID0gQklU KERNQV9ERVZfVE9fTUVNKTsKKwlkdy0+cmRfZWRtYS5jaGFuY250ID0gZHctPnJkX2NoX2NvdW50 OworCisJLyogU2V0IERNQSBjYXBhYmlsaXRpZXMgKi8KKwlTRVRfQk9USF9DSChzcmNfYWRkcl93 aWR0aHMsIEJJVChETUFfU0xBVkVfQlVTV0lEVEhfNF9CWVRFUykpOworCVNFVF9CT1RIX0NIKGRz dF9hZGRyX3dpZHRocywgQklUKERNQV9TTEFWRV9CVVNXSURUSF80X0JZVEVTKSk7CisJU0VUX0JP VEhfQ0gocmVzaWR1ZV9ncmFudWxhcml0eSwgRE1BX1JFU0lEVUVfR1JBTlVMQVJJVFlfREVTQ1JJ UFRPUik7CisKKwlTRVRfQk9USF9DSChkZXYsIGNoaXAtPmRldik7CisKKwlTRVRfQk9USF9DSChk ZXZpY2VfYWxsb2NfY2hhbl9yZXNvdXJjZXMsIGR3X2VkbWFfYWxsb2NfY2hhbl9yZXNvdXJjZXMp OworCVNFVF9CT1RIX0NIKGRldmljZV9mcmVlX2NoYW5fcmVzb3VyY2VzLCBkd19lZG1hX2ZyZWVf Y2hhbl9yZXNvdXJjZXMpOworCisJU0VUX0JPVEhfQ0goZGV2aWNlX2NvbmZpZywgZHdfZWRtYV9k ZXZpY2VfY29uZmlnKTsKKwlTRVRfQk9USF9DSChkZXZpY2VfcGF1c2UsIGR3X2VkbWFfZGV2aWNl X3BhdXNlKTsKKwlTRVRfQk9USF9DSChkZXZpY2VfcmVzdW1lLCBkd19lZG1hX2RldmljZV9yZXN1 bWUpOworCVNFVF9CT1RIX0NIKGRldmljZV90ZXJtaW5hdGVfYWxsLCBkd19lZG1hX2RldmljZV90 ZXJtaW5hdGVfYWxsKTsKKwlTRVRfQk9USF9DSChkZXZpY2VfaXNzdWVfcGVuZGluZywgZHdfZWRt YV9kZXZpY2VfaXNzdWVfcGVuZGluZyk7CisJU0VUX0JPVEhfQ0goZGV2aWNlX3R4X3N0YXR1cywg ZHdfZWRtYV9kZXZpY2VfdHhfc3RhdHVzKTsKKwlTRVRfQk9USF9DSChkZXZpY2VfcHJlcF9zbGF2 ZV9zZywgZHdfZWRtYV9kZXZpY2VfcHJlcF9zbGF2ZV9zZyk7CisKKwkvKiBQb3dlciBtYW5hZ2Vt ZW50ICovCisJcG1fcnVudGltZV9lbmFibGUoY2hpcC0+ZGV2KTsKKworCS8qIFJlZ2lzdGVyIERN QSBkZXZpY2UgKi8KKwllcnIgPSBkbWFfYXN5bmNfZGV2aWNlX3JlZ2lzdGVyKCZkdy0+d3JfZWRt YSk7CisJaWYgKGVycikKKwkJZ290byBlcnJfcG1fZGlzYWJsZTsKKworCWVyciA9IGRtYV9hc3lu Y19kZXZpY2VfcmVnaXN0ZXIoJmR3LT5yZF9lZG1hKTsKKwlpZiAoZXJyKQorCQlnb3RvIGVycl9w bV9kaXNhYmxlOworCisJLyogVHVybiBkZWJ1Z2ZzIG9uICovCisJZXJyID0gb3BzLT5kZWJ1Z2Zz X29uKGNoaXApOworCWlmIChlcnIpIHsKKwkJZGV2X2VycihjaGlwLT5kZXYsICI6IHVuYWJsZSB0 byBjcmVhdGUgZGVidWdmcyBzdHJ1Y3R1cmVcbiIpOworCQlnb3RvIGVycl9wbV9kaXNhYmxlOwor CX0KKworCWRldl9pbmZvKGNoaXAtPmRldiwgIkRlc2lnbldhcmUgZURNQSBjb250cm9sbGVyIGRy aXZlciBsb2FkZWQgY29tcGxldGVseVxuIik7CisKKwlyZXR1cm4gMDsKKworZXJyX3BtX2Rpc2Fi bGU6CisJcG1fcnVudGltZV9kaXNhYmxlKGNoaXAtPmRldik7CisKKwlyZXR1cm4gZXJyOworfQor RVhQT1JUX1NZTUJPTF9HUEwoZHdfZWRtYV9wcm9iZSk7CisKK2ludCBkd19lZG1hX3JlbW92ZShz dHJ1Y3QgZHdfZWRtYV9jaGlwICpjaGlwKQoreworCXN0cnVjdCBkd19lZG1hICpkdyA9IGNoaXAt PmR3OworCWNvbnN0IHN0cnVjdCBkd19lZG1hX2NvcmVfb3BzICpvcHMgPSBkdy0+b3BzOworCXN0 cnVjdCBkd19lZG1hX2NoYW4gKmNoYW4sICpfY2hhbjsKKworCS8qIERpc2FibGUgZURNQSAqLwor CWlmIChvcHMpCisJCW9wcy0+b2ZmKGR3KTsKKworCS8qIEZyZWUgaXJxICovCisJZGV2bV9mcmVl X2lycShjaGlwLT5kZXYsIGNoaXAtPmlycSwgY2hpcCk7CisKKwkvKiBQb3dlciBtYW5hZ2VtZW50 ICovCisJcG1fcnVudGltZV9kaXNhYmxlKGNoaXAtPmRldik7CisKKwlsaXN0X2Zvcl9lYWNoX2Vu dHJ5X3NhZmUoY2hhbiwgX2NoYW4sICZkdy0+d3JfZWRtYS5jaGFubmVscywKKwkJCQkgdmMuY2hh bi5kZXZpY2Vfbm9kZSkgeworCQlsaXN0X2RlbCgmY2hhbi0+dmMuY2hhbi5kZXZpY2Vfbm9kZSk7 CisJCXRhc2tsZXRfa2lsbCgmY2hhbi0+dmMudGFzayk7CisJfQorCisJbGlzdF9mb3JfZWFjaF9l bnRyeV9zYWZlKGNoYW4sIF9jaGFuLCAmZHctPnJkX2VkbWEuY2hhbm5lbHMsCisJCQkJIHZjLmNo YW4uZGV2aWNlX25vZGUpIHsKKwkJbGlzdF9kZWwoJmNoYW4tPnZjLmNoYW4uZGV2aWNlX25vZGUp OworCQl0YXNrbGV0X2tpbGwoJmNoYW4tPnZjLnRhc2spOworCX0KKworCS8qIERlcmVnaXN0ZXIg ZURNQSBkZXZpY2UgKi8KKwlkbWFfYXN5bmNfZGV2aWNlX3VucmVnaXN0ZXIoJmR3LT53cl9lZG1h KTsKKwlkbWFfYXN5bmNfZGV2aWNlX3VucmVnaXN0ZXIoJmR3LT5yZF9lZG1hKTsKKworCS8qIFR1 cm4gZGVidWdmcyBvZmYgKi8KKwlpZiAob3BzKQorCQlvcHMtPmRlYnVnZnNfb2ZmKCk7CisKKwlk ZXZfaW5mbyhjaGlwLT5kZXYsICI6IERlc2lnbldhcmUgZURNQSBjb250cm9sbGVyIGRyaXZlciB1 bmxvYWRlZCBjb21wbGV0ZVxuIik7CisKKwlyZXR1cm4gMDsKK30KK0VYUE9SVF9TWU1CT0xfR1BM KGR3X2VkbWFfcmVtb3ZlKTsKKworTU9EVUxFX0xJQ0VOU0UoIkdQTCB2MiIpOworTU9EVUxFX0RF U0NSSVBUSU9OKCJTeW5vcHN5cyBEZXNpZ25XYXJlIGVETUEgY29udHJvbGxlciBjb3JlIGRyaXZl ciIpOworTU9EVUxFX0FVVEhPUigiR3VzdGF2byBQaW1lbnRlbCA8Z3VzdGF2by5waW1lbnRlbEBz eW5vcHN5cy5jb20+Iik7CmRpZmYgLS1naXQgYS9kcml2ZXJzL2RtYS9kdy1lZG1hL2R3LWVkbWEt Y29yZS5oIGIvZHJpdmVycy9kbWEvZHctZWRtYS9kdy1lZG1hLWNvcmUuaApuZXcgZmlsZSBtb2Rl IDEwMDY0NAppbmRleCAwMDAwMDAwLi44N2QwMDlmCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVy cy9kbWEvZHctZWRtYS9kdy1lZG1hLWNvcmUuaApAQCAtMCwwICsxLDE0NyBAQAorLyogU1BEWC1M aWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAgKi8KKy8qCisgKiBDb3B5cmlnaHQgKGMpIDIwMTgg U3lub3BzeXMsIEluYy4gYW5kL29yIGl0cyBhZmZpbGlhdGVzLgorICogU3lub3BzeXMgRGVzaWdu V2FyZSBlRE1BIGNvcmUgZHJpdmVyCisgKi8KKworI2lmbmRlZiBfRFdfRURNQV9DT1JFX0gKKyNk ZWZpbmUgX0RXX0VETUFfQ09SRV9ICisKKyNpbmNsdWRlIDxsaW51eC9kbWEvZWRtYS5oPgorCisj aW5jbHVkZSAiLi4vdmlydC1kbWEuaCIKKworI2RlZmluZSBEUlZfTkFNRQkJCQkiZHctZWRtYSIK KworZW51bSBkd19lZG1hX2RpciB7CisJRURNQV9ESVJfV1JJVEUgPSAwLAorCUVETUFfRElSX1JF QUQKK307CisKK2VudW0gZHdfZWRtYV9tb2RlIHsKKwlFRE1BX01PREVfTEVHQUNZID0gMCwKKwlF RE1BX01PREVfVU5ST0xMCit9OworCitlbnVtIGR3X2VkbWFfcmVxdWVzdCB7CisJRURNQV9SRVFf Tk9ORSA9IDAsCisJRURNQV9SRVFfU1RPUCwKKwlFRE1BX1JFUV9QQVVTRQorfTsKKworZW51bSBk d19lZG1hX3N0YXR1cyB7CisJRURNQV9TVF9JRExFID0gMCwKKwlFRE1BX1NUX1BBVVNFLAorCUVE TUFfU1RfQlVTWQorfTsKKworc3RydWN0IGR3X2VkbWFfY2hhbjsKK3N0cnVjdCBkd19lZG1hX2No dW5rOworCitzdHJ1Y3QgZHdfZWRtYV9jb3JlX29wcyB7CisJLyogZURNQSBtYW5hZ2VtZW50IGNh bGxiYWNrcyAqLworCXZvaWQgKCpvZmYpKHN0cnVjdCBkd19lZG1hICpkdyk7CisJdTE2ICgqY2hf Y291bnQpKHN0cnVjdCBkd19lZG1hICpkdywgZW51bSBkd19lZG1hX2RpciBkaXIpOworCWVudW0g ZG1hX3N0YXR1cyAoKmNoX3N0YXR1cykoc3RydWN0IGR3X2VkbWFfY2hhbiAqY2hhbik7CisJdm9p ZCAoKmNsZWFyX2RvbmVfaW50KShzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuKTsKKwl2b2lkICgq Y2xlYXJfYWJvcnRfaW50KShzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuKTsKKwlib29sICgqc3Rh dHVzX2RvbmVfaW50KShzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuKTsKKwlib29sICgqc3RhdHVz X2Fib3J0X2ludCkoc3RydWN0IGR3X2VkbWFfY2hhbiAqY2hhbik7CisJdm9pZCAoKnN0YXJ0KShz dHJ1Y3QgZHdfZWRtYV9jaHVuayAqY2h1bmssIGJvb2wgZmlyc3QpOworCWludCAoKmRldmljZV9j b25maWcpKHN0cnVjdCBkbWFfY2hhbiAqZGNoYW4pOworCS8qIGVETUEgZGVidWcgZnMgY2FsbGJh Y2tzICovCisJaW50ICgqZGVidWdmc19vbikoc3RydWN0IGR3X2VkbWFfY2hpcCAqY2hpcCk7CisJ dm9pZCAoKmRlYnVnZnNfb2ZmKSh2b2lkKTsKK307CisKK3N0cnVjdCBkd19lZG1hX2J1cnN0IHsK KwlzdHJ1Y3QgbGlzdF9oZWFkCQlsaXN0OworCXU2NAkJCQlzYXI7CisJdTY0CQkJCWRhcjsKKwl1 MzIJCQkJc3o7Cit9OworCitzdHJ1Y3QgZHdfZWRtYV9jaHVuayB7CisJc3RydWN0IGxpc3RfaGVh ZAkJbGlzdDsKKwlzdHJ1Y3QgZHdfZWRtYV9jaGFuCQkqY2hhbjsKKwlzdHJ1Y3QgZHdfZWRtYV9i dXJzdAkJKmJ1cnN0OworCisJdTMyCQkJCWJ1cnN0c19hbGxvYzsKKworCXU4CQkJCWNiOworCXUz MgkJCQlzejsKKworCWRtYV9hZGRyX3QJCQlwX2FkZHI7CQkvKiBMaW5rZWQgbGlzdCAqLworCWRt YV9hZGRyX3QJCQl2X2FkZHI7CQkvKiBMaW5rZWQgbGlzdCAqLworfTsKKworc3RydWN0IGR3X2Vk bWFfZGVzYyB7CisJc3RydWN0IHZpcnRfZG1hX2Rlc2MJCXZkOworCXN0cnVjdCBkd19lZG1hX2No YW4JCSpjaGFuOworCXN0cnVjdCBkd19lZG1hX2NodW5rCQkqY2h1bms7CisKKwl1MzIJCQkJY2h1 bmtzX2FsbG9jOworCisJdTMyCQkJCWFsbG9jX3N6OworCXUzMgkJCQl4ZmVyX3N6OworfTsKKwor c3RydWN0IGR3X2VkbWFfY2hhbiB7CisJc3RydWN0IHZpcnRfZG1hX2NoYW4JCXZjOworCXN0cnVj dCBkd19lZG1hX2NoaXAJCSpjaGlwOworCWludAkJCQlpZDsKKwllbnVtIGR3X2VkbWFfZGlyCQlk aXI7CisKKwl1NjQJCQkJbGxfb2ZmOworCXUzMgkJCQlsbF9tYXg7CisKKwl1NjQJCQkJbXNpX2Rv bmVfYWRkcjsKKwl1NjQJCQkJbXNpX2Fib3J0X2FkZHI7CisJdTMyCQkJCW1zaV9kYXRhOworCisJ ZW51bSBkd19lZG1hX3JlcXVlc3QJCXJlcXVlc3Q7CisJZW51bSBkd19lZG1hX3N0YXR1cwkJc3Rh dHVzOworCXU4CQkJCWNvbmZpZ3VyZWQ7CisKKwlkbWFfYWRkcl90CQkJcF9hZGRyOwkJLyogRGF0 YSAqLworfTsKKworc3RydWN0IGR3X2VkbWEgeworCWNoYXIJCQkJbmFtZVsyMF07CisKKwlzdHJ1 Y3QgZG1hX2RldmljZQkJd3JfZWRtYTsKKwl1MTYJCQkJd3JfY2hfY291bnQ7CisJc3RydWN0IGRt YV9kZXZpY2UJCXJkX2VkbWE7CisJdTE2CQkJCXJkX2NoX2NvdW50OworCisJdm9pZCBfX2lvbWVt CQkJKnJlZ3M7CisKKwl2b2lkIF9faW9tZW0JCQkqdmFfbGw7CisJcmVzb3VyY2Vfc2l6ZV90CQkJ cGFfbGw7CisJc2l6ZV90CQkJCWxsX3N6OworCisJdTY0CQkJCW1zaV9hZGRyOworCXUzMgkJCQlt c2lfZGF0YTsKKworCXUzMgkJCQl2ZXJzaW9uOworCWVudW0gZHdfZWRtYV9tb2RlCQltb2RlOwor CisJc3RydWN0IGR3X2VkbWFfY2hhbgkJKmNoYW47CisJY29uc3Qgc3RydWN0IGR3X2VkbWFfY29y ZV9vcHMJKm9wczsKKworCXJhd19zcGlubG9ja190CQkJbG9jazsJCS8qIE9ubHkgZm9yIGxlZ2Fj eSAqLworfTsKKworc3RhdGljIGlubGluZQorc3RydWN0IGR3X2VkbWFfY2hhbiAqdmMyZHdfZWRt YV9jaGFuKHN0cnVjdCB2aXJ0X2RtYV9jaGFuICp2YykKK3sKKwlyZXR1cm4gY29udGFpbmVyX29m KHZjLCBzdHJ1Y3QgZHdfZWRtYV9jaGFuLCB2Yyk7Cit9CisKK3N0YXRpYyBpbmxpbmUKK3N0cnVj dCBkd19lZG1hX2NoYW4gKmRjaGFuMmR3X2VkbWFfY2hhbihzdHJ1Y3QgZG1hX2NoYW4gKmRjaGFu KQoreworCXJldHVybiB2YzJkd19lZG1hX2NoYW4odG9fdmlydF9jaGFuKGRjaGFuKSk7Cit9CisK KyNlbmRpZiAvKiBfRFdfRURNQV9DT1JFX0ggKi8KZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgv ZG1hL2VkbWEuaCBiL2luY2x1ZGUvbGludXgvZG1hL2VkbWEuaApuZXcgZmlsZSBtb2RlIDEwMDY0 NAppbmRleCAwMDAwMDAwLi4zNDllNTQyCi0tLSAvZGV2L251bGwKKysrIGIvaW5jbHVkZS9saW51 eC9kbWEvZWRtYS5oCkBAIC0wLDAgKzEsNDMgQEAKKy8qIFNQRFgtTGljZW5zZS1JZGVudGlmaWVy OiBHUEwtMi4wICovCisvLyBDb3B5cmlnaHQgKGMpIDIwMTggU3lub3BzeXMsIEluYy4gYW5kL29y IGl0cyBhZmZpbGlhdGVzLgorLy8gU3lub3BzeXMgRGVzaWduV2FyZSBlRE1BIGNvcmUgZHJpdmVy CisKKyNpZm5kZWYgX0RXX0VETUFfSAorI2RlZmluZSBfRFdfRURNQV9ICisKKyNpbmNsdWRlIDxs aW51eC9kZXZpY2UuaD4KKyNpbmNsdWRlIDxsaW51eC9kbWFlbmdpbmUuaD4KKworc3RydWN0IGR3 X2VkbWE7CisKKy8qKgorICogc3RydWN0IGR3X2VkbWFfY2hpcCAtIHJlcHJlc2VudGF0aW9uIG9m IERlc2lnbldhcmUgZURNQSBjb250cm9sbGVyIGhhcmR3YXJlCisgKiBAZGV2OgkJIHN0cnVjdCBk ZXZpY2Ugb2YgdGhlIGVETUEgY29udHJvbGxlcgorICogQGlkOgkJCSBpbnN0YW5jZSBJRAorICog QGlycToJCSBpcnEgbGluZQorICogQGR3OgkJCSBzdHJ1Y3QgZHdfZWRtYSB0aGF0IGlzIGZpbGVk IGJ5IGR3X2VkbWFfcHJvYmUoKQorICovCitzdHJ1Y3QgZHdfZWRtYV9jaGlwIHsKKwlzdHJ1Y3Qg ZGV2aWNlCQkqZGV2OworCWludAkJCWlkOworCWludAkJCWlycTsKKwlzdHJ1Y3QgZHdfZWRtYQkJ KmR3OworfTsKKworLyogRXhwb3J0IHRvIHRoZSBwbGF0Zm9ybSBkcml2ZXJzICovCisjaWYgSVNf RU5BQkxFRChDT05GSUdfRFdfRURNQSkKK2ludCBkd19lZG1hX3Byb2JlKHN0cnVjdCBkd19lZG1h X2NoaXAgKmNoaXApOworaW50IGR3X2VkbWFfcmVtb3ZlKHN0cnVjdCBkd19lZG1hX2NoaXAgKmNo aXApOworI2Vsc2UKK3N0YXRpYyBpbmxpbmUgaW50IGR3X2VkbWFfcHJvYmUoc3RydWN0IGR3X2Vk bWFfY2hpcCAqY2hpcCkKK3sKKwlyZXR1cm4gLUVOT0RFVjsKK30KKworc3RhdGljIGlubGluZSBp bnQgZHdfZWRtYV9yZW1vdmUoc3RydWN0IGR3X2VkbWFfY2hpcCAqY2hpcCkKK3sKKwlyZXR1cm4g MDsKK30KKyNlbmRpZiAvKiBDT05GSUdfRFdfRURNQSAqLworCisjZW5kaWYgLyogX0RXX0VETUFf SCAqLwo= 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 BDD81C43387 for ; Mon, 17 Dec 2018 17:19:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7A2EF2146F for ; Mon, 17 Dec 2018 17:19:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=synopsys.com header.i=@synopsys.com header.b="jvIfZtfO" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387865AbeLQRTs (ORCPT ); Mon, 17 Dec 2018 12:19:48 -0500 Received: from us01smtprelay-2.synopsys.com ([198.182.47.9]:56504 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732987AbeLQRTs (ORCPT ); Mon, 17 Dec 2018 12:19:48 -0500 Received: from mailhost.synopsys.com (mailhost3.synopsys.com [10.12.238.238]) by smtprelay.synopsys.com (Postfix) with ESMTP id 3464E24E27BA; Mon, 17 Dec 2018 09:19:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1545067187; bh=7KQAvHz5HG7UzoE6ILSIJ+2jojQ6F+vkeD8FAvEL+0w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:In-Reply-To: References:From; b=jvIfZtfO/77r8rjfVOAvxXf6yzqae+Wd/Nx63uwvbMyIvYPZcpnZQhwg2anAa+N2A wzjz/H5dig9HdUIyJe8C3LD+8ceGJOdTLs8lejl93dQtBkK47RtoNoS8iEe3+Aoan/ aTxFshtCoOTdkwRldco2iM1JaQhGoEPd2T46zGgdkkUS/B2qzbhm8Bq0Jn8X/WhJ2x zOS9pt9hj1Qj4NJoz8FyvfF9fJbFpNEMVmkFrrJu/9XM6yG4WF3F3OCkFxXRTlQ6oc F1WX5tY3CQcrux3I8Fn+vn6QFMj8H+nWrJqmT+e2qGjrbkvKxHWX7RErErkpzmMOZr cxe7jIvMnXFrg== Received: from de02.synopsys.com (de02.internal.synopsys.com [10.225.17.21]) by mailhost.synopsys.com (Postfix) with ESMTP id 4EEBC30B5; Mon, 17 Dec 2018 09:19:45 -0800 (PST) Received: from de02dwia024.internal.synopsys.com (de02dwia024.internal.synopsys.com [10.225.19.81]) by de02.synopsys.com (Postfix) with ESMTP id 1ED787F08; Mon, 17 Dec 2018 18:19:45 +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 v2 1/6] dmaengine: Add Synopsys eDMA IP core driver Date: Mon, 17 Dec 2018 18:19:33 +0100 Message-Id: <62a724afddb39cc241fbd769e0d93aa9e07e923f.1545066805.git.gustavo.pimentel@synopsys.com> 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 core driver to kernel. This core driver, initializes and configures the eDMA IP using vma-helpers functions and dma-engine subsystem. Also creates an abstration layer through callbacks allowing different registers mappings in the future, organized in to versions. This driver can be compile as built-in or external module in kernel. To enable this driver just select DW_EDMA option in kernel configuration, however it requires and selects automatically DMA_ENGINE and DMA_VIRTUAL_CHANNELS option too. Changes: RFC v1->RFC v2: - Replace comments // (C99 style) by /**/ - Fix the headers of the .c and .h files according to the most recent convention - Fix errors and checks pointed out by checkpatch with --strict option - Replace patch small description tag from dma by dmaengine - Change some dev_info() into dev_dbg() - Remove unnecessary zero initialization after kzalloc - Remove direction validation on config() API, since the direction parameter is deprecated - Refactor code to replace atomic_t by u32 variable type - Replace start_transfer() name by dw_edma_start_transfer() - Add spinlock to dw_edma_device_prep_slave_sg() - Add spinlock to dw_edma_free_chunk() - Simplify switch case into if on dw_edma_device_pause(), dw_edma_device_resume() and dw_edma_device_terminate_all() 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/Kconfig | 2 + drivers/dma/Makefile | 1 + drivers/dma/dw-edma/Kconfig | 9 + drivers/dma/dw-edma/Makefile | 4 + drivers/dma/dw-edma/dw-edma-core.c | 824 +++++++++++++++++++++++++++++++++++++ drivers/dma/dw-edma/dw-edma-core.h | 147 +++++++ include/linux/dma/edma.h | 43 ++ 7 files changed, 1030 insertions(+) create mode 100644 drivers/dma/dw-edma/Kconfig create mode 100644 drivers/dma/dw-edma/Makefile create mode 100644 drivers/dma/dw-edma/dw-edma-core.c create mode 100644 drivers/dma/dw-edma/dw-edma-core.h create mode 100644 include/linux/dma/edma.h diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index de511db..40517f8 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -640,6 +640,8 @@ source "drivers/dma/qcom/Kconfig" source "drivers/dma/dw/Kconfig" +source "drivers/dma/dw-edma/Kconfig" + source "drivers/dma/hsu/Kconfig" source "drivers/dma/sh/Kconfig" diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 7fcc4d8..3ebfab0 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_DMA_SUN4I) += sun4i-dma.o obj-$(CONFIG_DMA_SUN6I) += sun6i-dma.o obj-$(CONFIG_DW_AXI_DMAC) += dw-axi-dmac/ obj-$(CONFIG_DW_DMAC_CORE) += dw/ +obj-$(CONFIG_DW_EDMA) += dw-edma/ obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o obj-$(CONFIG_FSL_DMA) += fsldma.o obj-$(CONFIG_FSL_EDMA) += fsl-edma.o fsl-edma-common.o diff --git a/drivers/dma/dw-edma/Kconfig b/drivers/dma/dw-edma/Kconfig new file mode 100644 index 0000000..3016bed --- /dev/null +++ b/drivers/dma/dw-edma/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 + +config DW_EDMA + tristate "Synopsys DesignWare eDMA controller driver" + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + help + Support the Synopsys DesignWare eDMA controller, normally + implemented on endpoints SoCs. diff --git a/drivers/dma/dw-edma/Makefile b/drivers/dma/dw-edma/Makefile new file mode 100644 index 0000000..3224010 --- /dev/null +++ b/drivers/dma/dw-edma/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_DW_EDMA) += dw-edma.o +dw-edma-objs := dw-edma-core.o diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c new file mode 100644 index 0000000..bd1d8c0 --- /dev/null +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -0,0 +1,824 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates. + * Synopsys DesignWare eDMA core driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dw-edma-core.h" +#include "../dmaengine.h" +#include "../virt-dma.h" + +#define SET(reg, name, val) \ + reg.name = val + +#define SET_BOTH_CH(name, value) \ + do { \ + SET(dw->wr_edma, name, value); \ + SET(dw->rd_edma, name, value); \ + } while (0) + +static inline +struct device *dchan2dev(struct dma_chan *dchan) +{ + return &dchan->dev->device; +} + +static inline +struct device *chan2dev(struct dw_edma_chan *chan) +{ + return &chan->vc.chan.dev->device; +} + +static inline +const struct dw_edma_core_ops *chan2ops(struct dw_edma_chan *chan) +{ + return chan->chip->dw->ops; +} + +static inline +struct dw_edma_desc *vd2dw_edma_desc(struct virt_dma_desc *vd) +{ + return container_of(vd, struct dw_edma_desc, vd); +} + +static struct dw_edma_burst *dw_edma_alloc_burst(struct dw_edma_chunk *chunk) +{ + struct dw_edma_chan *chan = chunk->chan; + struct dw_edma_burst *burst; + + burst = kzalloc(sizeof(*burst), GFP_NOWAIT); + if (unlikely(!burst)) + return NULL; + + INIT_LIST_HEAD(&burst->list); + + if (chunk->burst) { + chunk->bursts_alloc++; + dev_dbg(chan2dev(chan), ": alloc new burst element (%d)\n", + chunk->bursts_alloc); + list_add_tail(&burst->list, &chunk->burst->list); + } else { + chunk->bursts_alloc = 0; + chunk->burst = burst; + dev_dbg(chan2dev(chan), ": alloc new burst head\n"); + } + + return burst; +} + +static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc) +{ + struct dw_edma_chan *chan = desc->chan; + struct dw_edma *dw = chan->chip->dw; + struct dw_edma_chunk *chunk; + + chunk = kzalloc(sizeof(*chunk), GFP_NOWAIT); + if (unlikely(!chunk)) + return NULL; + + INIT_LIST_HEAD(&chunk->list); + chunk->chan = chan; + chunk->cb = !(desc->chunks_alloc % 2); + chunk->p_addr = (dma_addr_t)(dw->pa_ll + chan->ll_off); + chunk->v_addr = (dma_addr_t)(dw->va_ll + chan->ll_off); + + if (desc->chunk) { + desc->chunks_alloc++; + dev_dbg(chan2dev(chan), ": alloc new chunk element (%d)\n", + desc->chunks_alloc); + list_add_tail(&chunk->list, &desc->chunk->list); + dw_edma_alloc_burst(chunk); + } else { + chunk->burst = NULL; + desc->chunks_alloc = 0; + desc->chunk = chunk; + dev_dbg(chan2dev(chan), ": alloc new chunk head\n"); + } + + return chunk; +} + +static struct dw_edma_desc *dw_edma_alloc_desc(struct dw_edma_chan *chan) +{ + struct dw_edma_desc *desc; + + dev_dbg(chan2dev(chan), ": alloc new descriptor\n"); + + desc = kzalloc(sizeof(*desc), GFP_NOWAIT); + if (unlikely(!desc)) + return NULL; + + desc->chan = chan; + dw_edma_alloc_chunk(desc); + + return desc; +} + +static void dw_edma_free_burst(struct dw_edma_chunk *chunk) +{ + struct dw_edma_burst *child, *_next; + + if (!chunk->burst) + return; + + /* Remove all the list elements */ + list_for_each_entry_safe(child, _next, &chunk->burst->list, list) { + list_del(&child->list); + kfree(child); + chunk->bursts_alloc--; + } + + /* Remove the list head */ + kfree(child); + chunk->burst = NULL; +} + +static void dw_edma_free_chunk(struct dw_edma_desc *desc) +{ + struct dw_edma_chan *chan = desc->chan; + struct dw_edma_chunk *child, *_next; + + if (!desc->chunk) + return; + + /* Remove all the list elements */ + list_for_each_entry_safe(child, _next, &desc->chunk->list, list) { + dw_edma_free_burst(child); + if (child->bursts_alloc) + dev_dbg(chan2dev(chan), ": %d bursts still allocated\n", + child->bursts_alloc); + list_del(&child->list); + kfree(child); + desc->chunks_alloc--; + } + + /* Remove the list head */ + kfree(child); + desc->chunk = NULL; +} + +static void dw_edma_free_desc(struct dw_edma_desc *desc) +{ + struct dw_edma_chan *chan = desc->chan; + unsigned long flags; + + spin_lock_irqsave(&chan->vc.lock, flags); + + dw_edma_free_chunk(desc); + if (desc->chunks_alloc) + dev_dbg(chan2dev(chan), ": %d chunks still allocated\n", + desc->chunks_alloc); + + spin_unlock_irqrestore(&chan->vc.lock, flags); +} + +static void vchan_free_desc(struct virt_dma_desc *vdesc) +{ + dw_edma_free_desc(vd2dw_edma_desc(vdesc)); +} + +static void dw_edma_start_transfer(struct dw_edma_chan *chan) +{ + struct virt_dma_desc *vd; + struct dw_edma_desc *desc; + struct dw_edma_chunk *child, *_next; + const struct dw_edma_core_ops *ops = chan2ops(chan); + + vd = vchan_next_desc(&chan->vc); + if (!vd) + return; + + desc = vd2dw_edma_desc(vd); + if (!desc) + return; + + list_for_each_entry_safe(child, _next, &desc->chunk->list, list) { + ops->start(child, !desc->xfer_sz); + desc->xfer_sz += child->sz; + dev_dbg(chan2dev(chan), ": transfer of %u bytes started\n", child->sz); + + dw_edma_free_burst(child); + if (child->bursts_alloc) + dev_dbg(chan2dev(chan), ": %d bursts still allocated\n", + child->bursts_alloc); + list_del(&child->list); + kfree(child); + desc->chunks_alloc--; + + return; + } +} + +static int dw_edma_device_config(struct dma_chan *dchan, + struct dma_slave_config *config) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + const struct dw_edma_core_ops *ops = chan2ops(chan); + unsigned long flags; + int err = 0; + + spin_lock_irqsave(&chan->vc.lock, flags); + + if (!config) { + err = -EINVAL; + goto err_config; + } + + if (chan->configured) { + dev_err(chan2dev(chan), ": channel already configured\n"); + err = -EPERM; + goto err_config; + } + + dev_dbg(chan2dev(chan), ": src_addr(physical) = 0x%.16x\n", + config->src_addr); + dev_dbg(chan2dev(chan), ": dst_addr(physical) = 0x%.16x\n", + config->dst_addr); + + err = ops->device_config(dchan); + if (!err) { + chan->configured = true; + dev_dbg(chan2dev(chan), ": channel configured\n"); + } + +err_config: + spin_unlock_irqrestore(&chan->vc.lock, flags); + return err; +} + +static int dw_edma_device_pause(struct dma_chan *dchan) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + unsigned long flags; + int err = 0; + + spin_lock_irqsave(&chan->vc.lock, flags); + + if (!chan->configured) { + dev_err(dchan2dev(dchan), ": channel not configured\n"); + err = -EPERM; + goto err_pause; + } + + if (chan->status != EDMA_ST_BUSY) { + err = -EPERM; + goto err_pause; + } + + if (chan->request != EDMA_REQ_NONE) { + err = -EPERM; + goto err_pause; + } + + chan->request = EDMA_REQ_PAUSE; + dev_dbg(dchan2dev(dchan), ": pause requested\n"); + +err_pause: + spin_unlock_irqrestore(&chan->vc.lock, flags); + return err; +} + +static int dw_edma_device_resume(struct dma_chan *dchan) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + unsigned long flags; + int err = 0; + + spin_lock_irqsave(&chan->vc.lock, flags); + + if (!chan->configured) { + dev_err(dchan2dev(dchan), ": channel not configured\n"); + err = -EPERM; + goto err_resume; + } + + if (chan->status != EDMA_ST_PAUSE) { + err = -EPERM; + goto err_resume; + } + + if (chan->request != EDMA_REQ_NONE) { + err = -EPERM; + goto err_resume; + } + + chan->status = EDMA_ST_BUSY; + dev_dbg(dchan2dev(dchan), ": transfer resumed\n"); + dw_edma_start_transfer(chan); + +err_resume: + spin_unlock_irqrestore(&chan->vc.lock, flags); + return err; +} + +static int dw_edma_device_terminate_all(struct dma_chan *dchan) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + unsigned long flags; + int err = 0; + LIST_HEAD(head); + + spin_lock_irqsave(&chan->vc.lock, flags); + + if (!chan->configured) { + dev_err(dchan2dev(dchan), ": channel not configured\n"); + err = -EPERM; + goto err_terminate; + } + + if (chan->status == EDMA_ST_PAUSE) { + dev_dbg(dchan2dev(dchan), ": channel is paused, stopping immediately\n"); + vchan_get_all_descriptors(&chan->vc, &head); + vchan_dma_desc_free_list(&chan->vc, &head); + chan->status = EDMA_ST_IDLE; + goto err_terminate; + } else if (chan->status != EDMA_ST_BUSY) { + err = -EPERM; + goto err_terminate; + } + + if (chan->request > EDMA_REQ_PAUSE) { + err = -EPERM; + goto err_terminate; + } + + chan->request = EDMA_REQ_STOP; + dev_dbg(dchan2dev(dchan), ": termination requested\n"); + +err_terminate: + spin_unlock_irqrestore(&chan->vc.lock, flags); + return err; +} + +static void dw_edma_device_issue_pending(struct dma_chan *dchan) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + unsigned long flags; + + spin_lock_irqsave(&chan->vc.lock, flags); + + if (chan->configured && chan->request == EDMA_REQ_NONE && + chan->status == EDMA_ST_IDLE && vchan_issue_pending(&chan->vc)) { + dev_dbg(dchan2dev(dchan), ": transfer issued\n"); + chan->status = EDMA_ST_BUSY; + dw_edma_start_transfer(chan); + } + + spin_unlock_irqrestore(&chan->vc.lock, flags); +} + +static enum dma_status +dw_edma_device_tx_status(struct dma_chan *dchan, dma_cookie_t cookie, + struct dma_tx_state *txstate) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + const struct dw_edma_core_ops *ops = chan2ops(chan); + unsigned long flags; + enum dma_status ret; + + spin_lock_irqsave(&chan->vc.lock, flags); + + ret = ops->ch_status(chan); + if (ret == DMA_ERROR) { + goto ret_status; + } else if (ret == DMA_IN_PROGRESS) { + chan->status = EDMA_ST_BUSY; + goto ret_status; + } else { + /* DMA_COMPLETE */ + if (chan->status == EDMA_ST_PAUSE) + ret = DMA_PAUSED; + else if (chan->status == EDMA_ST_BUSY) + ret = DMA_IN_PROGRESS; + else + ret = DMA_COMPLETE; + } + +ret_status: + spin_unlock_irqrestore(&chan->vc.lock, flags); + dma_set_residue(txstate, 0); + + return ret; +} + +static struct dma_async_tx_descriptor * +dw_edma_device_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl, + unsigned int sg_len, + enum dma_transfer_direction direction, + unsigned long flags, void *context) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + struct dw_edma_desc *desc; + struct dw_edma_chunk *chunk; + struct dw_edma_burst *burst; + struct scatterlist *sg; + dma_addr_t dev_addr = chan->p_addr; + unsigned long sflags; + int i; + + if (sg_len < 1) { + dev_err(chan2dev(chan), ": invalid sg length %u\n", sg_len); + return NULL; + } + + if (direction == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_WRITE) { + dev_dbg(chan2dev(chan), ": prepare operation (WRITE)\n"); + } else if (direction == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_READ) { + dev_dbg(chan2dev(chan), ": prepare operation (READ)\n"); + } else { + dev_err(chan2dev(chan), ": invalid direction\n"); + return NULL; + } + + if (!chan->configured) { + dev_err(dchan2dev(dchan), ": channel not configured\n"); + return NULL; + } + if (chan->status == EDMA_ST_BUSY) { + dev_err(chan2dev(chan), ": channel is busy or paused\n"); + return NULL; + } + + spin_lock_irqsave(&chan->vc.lock, sflags); + + desc = dw_edma_alloc_desc(chan); + if (unlikely(!desc)) + goto err_alloc; + + chunk = dw_edma_alloc_chunk(desc); + if (unlikely(!chunk)) + goto err_alloc; + + for_each_sg(sgl, sg, sg_len, i) { + if (chunk->bursts_alloc == chan->ll_max) { + chunk = dw_edma_alloc_chunk(desc); + if (unlikely(!chunk)) + goto err_alloc; + } + + burst = dw_edma_alloc_burst(chunk); + + if (unlikely(!burst)) + goto err_alloc; + + if (direction == DMA_MEM_TO_DEV) { + burst->sar = sg_dma_address(sg); + burst->dar = dev_addr; + } else { + burst->sar = dev_addr; + burst->dar = sg_dma_address(sg); + } + + burst->sz = sg_dma_len(sg); + chunk->sz += burst->sz; + desc->alloc_sz += burst->sz; + dev_addr += burst->sz; + + dev_dbg(chan2dev(chan), "lli %u/%u, sar=0x%.16llx, dar=0x%.16llx, size=%u bytes\n", + i + 1, sg_len, + burst->sar, burst->dar, + burst->sz); + } + + spin_unlock_irqrestore(&chan->vc.lock, sflags); + return vchan_tx_prep(&chan->vc, &desc->vd, flags); + +err_alloc: + spin_unlock_irqrestore(&chan->vc.lock, sflags); + if (desc) + dw_edma_free_desc(desc); + return NULL; +} + +static void dw_edma_done_interrupt(struct dw_edma_chan *chan) +{ + struct dw_edma *dw = chan->chip->dw; + const struct dw_edma_core_ops *ops = dw->ops; + struct virt_dma_desc *vd; + struct dw_edma_desc *desc; + unsigned long flags; + + ops->clear_done_int(chan); + dev_dbg(chan2dev(chan), ": clear done interrupt\n"); + + spin_lock_irqsave(&chan->vc.lock, flags); + vd = vchan_next_desc(&chan->vc); + switch (chan->request) { + case EDMA_REQ_NONE: + desc = vd2dw_edma_desc(vd); + if (desc->chunks_alloc) { + dev_dbg(chan2dev(chan), ": sub-transfer complete\n"); + chan->status = EDMA_ST_BUSY; + dev_dbg(chan2dev(chan), ": transferred %u bytes\n", + desc->xfer_sz); + dw_edma_start_transfer(chan); + } else { + list_del(&vd->node); + vchan_cookie_complete(vd); + chan->status = EDMA_ST_IDLE; + dev_dbg(chan2dev(chan), ": transfer complete\n"); + } + break; + case EDMA_REQ_STOP: + list_del(&vd->node); + vchan_cookie_complete(vd); + chan->request = EDMA_REQ_NONE; + chan->status = EDMA_ST_IDLE; + dev_dbg(chan2dev(chan), ": transfer stop\n"); + break; + case EDMA_REQ_PAUSE: + chan->request = EDMA_REQ_NONE; + chan->status = EDMA_ST_PAUSE; + break; + default: + dev_err(chan2dev(chan), ": invalid status state\n"); + break; + } + spin_unlock_irqrestore(&chan->vc.lock, flags); +} + +static void dw_edma_abort_interrupt(struct dw_edma_chan *chan) +{ + struct dw_edma *dw = chan->chip->dw; + const struct dw_edma_core_ops *ops = dw->ops; + struct virt_dma_desc *vd; + unsigned long flags; + + ops->clear_abort_int(chan); + dev_dbg(chan2dev(chan), ": clear abort interrupt\n"); + + spin_lock_irqsave(&chan->vc.lock, flags); + vd = vchan_next_desc(&chan->vc); + list_del(&vd->node); + vchan_cookie_complete(vd); + chan->request = EDMA_REQ_NONE; + chan->status = EDMA_ST_IDLE; + + spin_unlock_irqrestore(&chan->vc.lock, flags); +} + +static irqreturn_t dw_edma_interrupt(int irq, void *data) +{ + struct dw_edma_chip *chip = data; + struct dw_edma *dw = chip->dw; + const struct dw_edma_core_ops *ops = dw->ops; + struct dw_edma_chan *chan; + u32 i; + + /* Poll, clear and process every chanel interrupt status */ + for (i = 0; i < (dw->wr_ch_count + dw->rd_ch_count); i++) { + chan = &dw->chan[i]; + + if (ops->status_done_int(chan)) + dw_edma_done_interrupt(chan); + + if (ops->status_abort_int(chan)) + dw_edma_abort_interrupt(chan); + } + + return IRQ_HANDLED; +} + +static int dw_edma_alloc_chan_resources(struct dma_chan *dchan) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + + if (chan->status != EDMA_ST_IDLE) { + dev_err(chan2dev(chan), ": channel is busy\n"); + return -EBUSY; + } + + dev_dbg(dchan2dev(dchan), ": allocated\n"); + + pm_runtime_get(chan->chip->dev); + + return 0; +} + +static void dw_edma_free_chan_resources(struct dma_chan *dchan) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + unsigned long timeout = jiffies + msecs_to_jiffies(5000); + int ret; + + if (chan->status != EDMA_ST_IDLE) + dev_err(chan2dev(chan), ": channel is busy\n"); + + do { + ret = dw_edma_device_terminate_all(dchan); + if (!ret) + break; + + if (time_after_eq(jiffies, timeout)) { + dev_err(chan2dev(chan), ": timeout\n"); + return; + } + + cpu_relax(); + } while (1); + + dev_dbg(dchan2dev(dchan), ": freed\n"); + + pm_runtime_put(chan->chip->dev); +} + +int dw_edma_probe(struct dw_edma_chip *chip) +{ + struct dw_edma *dw = chip->dw; + const struct dw_edma_core_ops *ops; + size_t ll_chunk = dw->ll_sz; + int i, j, err; + + raw_spin_lock_init(&dw->lock); + + switch (dw->version) { + default: + dev_err(chip->dev, ": unsupported version\n"); + return -EPERM; + } + + pm_runtime_get_sync(chip->dev); + + dw->wr_ch_count = ops->ch_count(dw, WRITE); + if (!dw->wr_ch_count) { + dev_err(chip->dev, ": invalid number of write channels(0)\n"); + return -EINVAL; + } + + dw->rd_ch_count = ops->ch_count(dw, READ); + if (!dw->rd_ch_count) { + dev_err(chip->dev, ": invalid number of read channels(0)\n"); + return -EINVAL; + } + + dev_dbg(chip->dev, "Channels:\twrite=%d, read=%d\n", + dw->wr_ch_count, dw->rd_ch_count); + + dw->chan = devm_kcalloc(chip->dev, dw->wr_ch_count + dw->rd_ch_count, + sizeof(*dw->chan), GFP_KERNEL); + if (!dw->chan) + return -ENOMEM; + + ll_chunk /= roundup_pow_of_two(dw->wr_ch_count + dw->rd_ch_count); + + /* Disable eDMA, only to establish the ideal initial conditions */ + ops->off(dw); + + snprintf(dw->name, sizeof(dw->name), "dw-edma-core:%d", chip->id); + + err = devm_request_irq(chip->dev, chip->irq, dw_edma_interrupt, + IRQF_SHARED, dw->name, chip); + if (err) + return err; + + INIT_LIST_HEAD(&dw->wr_edma.channels); + for (i = 0; i < dw->wr_ch_count; i++) { + struct dw_edma_chan *chan = &dw->chan[i]; + + chan->chip = chip; + chan->id = i; + chan->dir = EDMA_DIR_WRITE; + chan->configured = false; + chan->request = EDMA_REQ_NONE; + chan->status = EDMA_ST_IDLE; + + chan->ll_off = (ll_chunk * i); + chan->ll_max = (ll_chunk / 24) - 1; + + chan->msi_done_addr = dw->msi_addr; + chan->msi_abort_addr = dw->msi_addr; + chan->msi_data = dw->msi_data; + + chan->vc.desc_free = vchan_free_desc; + vchan_init(&chan->vc, &dw->wr_edma); + } + dma_cap_set(DMA_SLAVE, dw->wr_edma.cap_mask); + dw->wr_edma.directions = BIT(DMA_MEM_TO_DEV); + dw->wr_edma.chancnt = dw->wr_ch_count; + + INIT_LIST_HEAD(&dw->rd_edma.channels); + for (j = 0; j < dw->rd_ch_count; j++, i++) { + struct dw_edma_chan *chan = &dw->chan[i]; + + chan->chip = chip; + chan->id = j; + chan->dir = EDMA_DIR_READ; + chan->request = EDMA_REQ_NONE; + chan->status = EDMA_ST_IDLE; + + chan->ll_off = (ll_chunk * i); + chan->ll_max = (ll_chunk / 24) - 1; + + chan->msi_done_addr = dw->msi_addr; + chan->msi_abort_addr = dw->msi_addr; + chan->msi_data = dw->msi_data; + + chan->vc.desc_free = vchan_free_desc; + vchan_init(&chan->vc, &dw->rd_edma); + } + dma_cap_set(DMA_SLAVE, dw->rd_edma.cap_mask); + dw->rd_edma.directions = BIT(DMA_DEV_TO_MEM); + dw->rd_edma.chancnt = dw->rd_ch_count; + + /* Set DMA capabilities */ + SET_BOTH_CH(src_addr_widths, BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)); + SET_BOTH_CH(dst_addr_widths, BIT(DMA_SLAVE_BUSWIDTH_4_BYTES)); + SET_BOTH_CH(residue_granularity, DMA_RESIDUE_GRANULARITY_DESCRIPTOR); + + SET_BOTH_CH(dev, chip->dev); + + SET_BOTH_CH(device_alloc_chan_resources, dw_edma_alloc_chan_resources); + SET_BOTH_CH(device_free_chan_resources, dw_edma_free_chan_resources); + + SET_BOTH_CH(device_config, dw_edma_device_config); + SET_BOTH_CH(device_pause, dw_edma_device_pause); + SET_BOTH_CH(device_resume, dw_edma_device_resume); + SET_BOTH_CH(device_terminate_all, dw_edma_device_terminate_all); + SET_BOTH_CH(device_issue_pending, dw_edma_device_issue_pending); + SET_BOTH_CH(device_tx_status, dw_edma_device_tx_status); + SET_BOTH_CH(device_prep_slave_sg, dw_edma_device_prep_slave_sg); + + /* Power management */ + pm_runtime_enable(chip->dev); + + /* Register DMA device */ + err = dma_async_device_register(&dw->wr_edma); + if (err) + goto err_pm_disable; + + err = dma_async_device_register(&dw->rd_edma); + if (err) + goto err_pm_disable; + + /* Turn debugfs on */ + err = ops->debugfs_on(chip); + if (err) { + dev_err(chip->dev, ": unable to create debugfs structure\n"); + goto err_pm_disable; + } + + dev_info(chip->dev, "DesignWare eDMA controller driver loaded completely\n"); + + return 0; + +err_pm_disable: + pm_runtime_disable(chip->dev); + + return err; +} +EXPORT_SYMBOL_GPL(dw_edma_probe); + +int dw_edma_remove(struct dw_edma_chip *chip) +{ + struct dw_edma *dw = chip->dw; + const struct dw_edma_core_ops *ops = dw->ops; + struct dw_edma_chan *chan, *_chan; + + /* Disable eDMA */ + if (ops) + ops->off(dw); + + /* Free irq */ + devm_free_irq(chip->dev, chip->irq, chip); + + /* Power management */ + pm_runtime_disable(chip->dev); + + list_for_each_entry_safe(chan, _chan, &dw->wr_edma.channels, + vc.chan.device_node) { + list_del(&chan->vc.chan.device_node); + tasklet_kill(&chan->vc.task); + } + + list_for_each_entry_safe(chan, _chan, &dw->rd_edma.channels, + vc.chan.device_node) { + list_del(&chan->vc.chan.device_node); + tasklet_kill(&chan->vc.task); + } + + /* Deregister eDMA device */ + dma_async_device_unregister(&dw->wr_edma); + dma_async_device_unregister(&dw->rd_edma); + + /* Turn debugfs off */ + if (ops) + ops->debugfs_off(); + + dev_info(chip->dev, ": DesignWare eDMA controller driver unloaded complete\n"); + + return 0; +} +EXPORT_SYMBOL_GPL(dw_edma_remove); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Synopsys DesignWare eDMA controller core driver"); +MODULE_AUTHOR("Gustavo Pimentel "); diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h new file mode 100644 index 0000000..87d009f --- /dev/null +++ b/drivers/dma/dw-edma/dw-edma-core.h @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates. + * Synopsys DesignWare eDMA core driver + */ + +#ifndef _DW_EDMA_CORE_H +#define _DW_EDMA_CORE_H + +#include + +#include "../virt-dma.h" + +#define DRV_NAME "dw-edma" + +enum dw_edma_dir { + EDMA_DIR_WRITE = 0, + EDMA_DIR_READ +}; + +enum dw_edma_mode { + EDMA_MODE_LEGACY = 0, + EDMA_MODE_UNROLL +}; + +enum dw_edma_request { + EDMA_REQ_NONE = 0, + EDMA_REQ_STOP, + EDMA_REQ_PAUSE +}; + +enum dw_edma_status { + EDMA_ST_IDLE = 0, + EDMA_ST_PAUSE, + EDMA_ST_BUSY +}; + +struct dw_edma_chan; +struct dw_edma_chunk; + +struct dw_edma_core_ops { + /* eDMA management callbacks */ + void (*off)(struct dw_edma *dw); + u16 (*ch_count)(struct dw_edma *dw, enum dw_edma_dir dir); + enum dma_status (*ch_status)(struct dw_edma_chan *chan); + void (*clear_done_int)(struct dw_edma_chan *chan); + void (*clear_abort_int)(struct dw_edma_chan *chan); + bool (*status_done_int)(struct dw_edma_chan *chan); + bool (*status_abort_int)(struct dw_edma_chan *chan); + void (*start)(struct dw_edma_chunk *chunk, bool first); + int (*device_config)(struct dma_chan *dchan); + /* eDMA debug fs callbacks */ + int (*debugfs_on)(struct dw_edma_chip *chip); + void (*debugfs_off)(void); +}; + +struct dw_edma_burst { + struct list_head list; + u64 sar; + u64 dar; + u32 sz; +}; + +struct dw_edma_chunk { + struct list_head list; + struct dw_edma_chan *chan; + struct dw_edma_burst *burst; + + u32 bursts_alloc; + + u8 cb; + u32 sz; + + dma_addr_t p_addr; /* Linked list */ + dma_addr_t v_addr; /* Linked list */ +}; + +struct dw_edma_desc { + struct virt_dma_desc vd; + struct dw_edma_chan *chan; + struct dw_edma_chunk *chunk; + + u32 chunks_alloc; + + u32 alloc_sz; + u32 xfer_sz; +}; + +struct dw_edma_chan { + struct virt_dma_chan vc; + struct dw_edma_chip *chip; + int id; + enum dw_edma_dir dir; + + u64 ll_off; + u32 ll_max; + + u64 msi_done_addr; + u64 msi_abort_addr; + u32 msi_data; + + enum dw_edma_request request; + enum dw_edma_status status; + u8 configured; + + dma_addr_t p_addr; /* Data */ +}; + +struct dw_edma { + char name[20]; + + struct dma_device wr_edma; + u16 wr_ch_count; + struct dma_device rd_edma; + u16 rd_ch_count; + + void __iomem *regs; + + void __iomem *va_ll; + resource_size_t pa_ll; + size_t ll_sz; + + u64 msi_addr; + u32 msi_data; + + u32 version; + enum dw_edma_mode mode; + + struct dw_edma_chan *chan; + const struct dw_edma_core_ops *ops; + + raw_spinlock_t lock; /* Only for legacy */ +}; + +static inline +struct dw_edma_chan *vc2dw_edma_chan(struct virt_dma_chan *vc) +{ + return container_of(vc, struct dw_edma_chan, vc); +} + +static inline +struct dw_edma_chan *dchan2dw_edma_chan(struct dma_chan *dchan) +{ + return vc2dw_edma_chan(to_virt_chan(dchan)); +} + +#endif /* _DW_EDMA_CORE_H */ diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h new file mode 100644 index 0000000..349e542 --- /dev/null +++ b/include/linux/dma/edma.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// Copyright (c) 2018 Synopsys, Inc. and/or its affiliates. +// Synopsys DesignWare eDMA core driver + +#ifndef _DW_EDMA_H +#define _DW_EDMA_H + +#include +#include + +struct dw_edma; + +/** + * struct dw_edma_chip - representation of DesignWare eDMA controller hardware + * @dev: struct device of the eDMA controller + * @id: instance ID + * @irq: irq line + * @dw: struct dw_edma that is filed by dw_edma_probe() + */ +struct dw_edma_chip { + struct device *dev; + int id; + int irq; + struct dw_edma *dw; +}; + +/* Export to the platform drivers */ +#if IS_ENABLED(CONFIG_DW_EDMA) +int dw_edma_probe(struct dw_edma_chip *chip); +int dw_edma_remove(struct dw_edma_chip *chip); +#else +static inline int dw_edma_probe(struct dw_edma_chip *chip) +{ + return -ENODEV; +} + +static inline int dw_edma_remove(struct dw_edma_chip *chip) +{ + return 0; +} +#endif /* CONFIG_DW_EDMA */ + +#endif /* _DW_EDMA_H */ -- 2.7.4