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,v6,1/6] dmaengine: Add Synopsys eDMA IP core driver From: Gustavo Pimentel Message-Id: <0e877ac0115d37e466ac234f47c51cb1cae7f292.1556043127.git.gustavo.pimentel@synopsys.com> Date: Tue, 23 Apr 2019 20:30:08 +0200 To: linux-pci@vger.kernel.org, dmaengine@vger.kernel.org Cc: Gustavo Pimentel , Vinod Koul , Dan Williams , Andy Shevchenko , Russell King , Joao Pinto List-ID: QWRkIFN5bm9wc3lzIFBDSWUgRW5kcG9pbnQgZURNQSBJUCBjb3JlIGRyaXZlciB0byBrZXJuZWwu CgpUaGlzIElQIGlzIGdlbmVyYWxseSBkaXN0cmlidXRlZCB3aXRoIFN5bm9wc3lzIFBDSWUgRW5k cG9pbnQgSVAgKGRlcGVuZHMKb2YgdGhlIHVzZSBhbmQgbGljZW5zaW5nIGFncmVlbWVudCkuCgpU aGlzIGNvcmUgZHJpdmVyLCBpbml0aWFsaXplcyBhbmQgY29uZmlndXJlcyB0aGUgZURNQSBJUCB1 c2luZyB2bWEtaGVscGVycwpmdW5jdGlvbnMgYW5kIGRtYS1lbmdpbmUgc3Vic3lzdGVtLgoKVGhp cyBkcml2ZXIgY2FuIGJlIGNvbXBpbGUgYXMgYnVpbHQtaW4gb3IgZXh0ZXJuYWwgbW9kdWxlIGlu IGtlcm5lbC4KClRvIGVuYWJsZSB0aGlzIGRyaXZlciBqdXN0IHNlbGVjdCBEV19FRE1BIG9wdGlv biBpbiBrZXJuZWwgY29uZmlndXJhdGlvbiwKaG93ZXZlciBpdCByZXF1aXJlcyBhbmQgc2VsZWN0 cyBhdXRvbWF0aWNhbGx5IERNQV9FTkdJTkUgYW5kCkRNQV9WSVJUVUFMX0NIQU5ORUxTIG9wdGlv biB0b28uCgpJbiBvcmRlciB0byB0cmFuc2ZlciBkYXRhIGZyb20gcG9pbnQgQSB0byBCIGFzIGZh c3QgYXMgcG9zc2libGUgdGhpcyBJUApyZXF1aXJlcyBhIGRlZGljYXRlZCBtZW1vcnkgc3BhY2Ug Y29udGFpbmluZyBsaW5rZWQgbGlzdCBvZiBlbGVtZW50cy4KCkFsbCBlbGVtZW50cyBvZiB0aGlz IGxpbmtlZCBsaXN0IGFyZSBjb250aW51b3VzIGFuZCBlYWNoIG9uZSBkZXNjcmliZXMgYQpkYXRh IHRyYW5zZmVyIChzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGFkZHJlc3NlcywgbGVuZ3RoIGFuZCBh IGNvbnRyb2wKdmFyaWFibGUpLgoKRm9yIHRoZSBzYWtlIG9mIHNpbXBsaWNpdHksIGxldHMgYXNz dW1lIGEgbWVtb3J5IHNwYWNlIGZvciBjaGFubmVsIHdyaXRlCjAgd2hpY2ggYWxsb3dzIGFib3V0 IDQyIGVsZW1lbnRzLgoKKy0tLS0tLS0tLSsKfCBEZXNjICMwIHwtKworLS0tLS0tLS0tKyB8CiAg ICAgICAgICAgIFYKICAgICAgICstLS0tLS0tLS0tKwogICAgICAgfCBDaHVuayAjMCB8LSsKICAg ICAgIHwgIENCID0gMSAgfCB8ICArLS0tLS0tLS0tLSsgICstLS0tLSsgICstLS0tLS0tLS0tLSsg ICstLS0tLSsKICAgICAgICstLS0tLS0tLS0tKyArLT58IEJ1cnN0ICMwIHwtPnwgLi4uIHwtPnwg QnVyc3QgIzQxIHwtPnwgbGxwIHwKICAgICAgICAgICAgfCAgICAgICAgICArLS0tLS0tLS0tLSsg ICstLS0tLSsgICstLS0tLS0tLS0tLSsgICstLS0tLSsKICAgICAgICAgICAgVgogICAgICAgKy0t LS0tLS0tLS0rCiAgICAgICB8IENodW5rICMxIHwtKwogICAgICAgfCAgQ0IgPSAwICB8IHwgICst LS0tLS0tLS0tLSsgICstLS0tLSsgICstLS0tLS0tLS0tLSsgICstLS0tLSsKICAgICAgICstLS0t LS0tLS0tKyArLT58IEJ1cnN0ICM0MiB8LT58IC4uLiB8LT58IEJ1cnN0ICM4MyB8LT58IGxscCB8 CiAgICAgICAgICAgIHwgICAgICAgICAgKy0tLS0tLS0tLS0tKyAgKy0tLS0tKyAgKy0tLS0tLS0t LS0tKyAgKy0tLS0tKwogICAgICAgICAgICBWCiAgICAgICArLS0tLS0tLS0tLSsKICAgICAgIHwg Q2h1bmsgIzIgfC0rCiAgICAgICB8ICBDQiA9IDEgIHwgfCAgKy0tLS0tLS0tLS0tKyAgKy0tLS0t KyAgKy0tLS0tLS0tLS0tLSsgICstLS0tLSsKICAgICAgICstLS0tLS0tLS0tKyArLT58IEJ1cnN0 ICM4NCB8LT58IC4uLiB8LT58IEJ1cnN0ICMxMjUgfC0+fCBsbHAgfAogICAgICAgICAgICB8ICAg ICAgICAgICstLS0tLS0tLS0tLSsgICstLS0tLSsgICstLS0tLS0tLS0tLS0rICArLS0tLS0rCiAg ICAgICAgICAgIFYKICAgICAgICstLS0tLS0tLS0tKwogICAgICAgfCBDaHVuayAjMyB8LSsKICAg ICAgIHwgIENCID0gMCAgfCB8ICArLS0tLS0tLS0tLS0tKyAgKy0tLS0tKyAgKy0tLS0tLS0tLS0t LSsgICstLS0tLSsKICAgICAgICstLS0tLS0tLS0tKyArLT58IEJ1cnN0ICMxMjYgfC0+fCAuLi4g fC0+fCBCdXJzdCAjMTI5IHwtPnwgbGxwIHwKICAgICAgICAgICAgICAgICAgICAgICArLS0tLS0t LS0tLS0tKyAgKy0tLS0tKyAgKy0tLS0tLS0tLS0tLSsgICstLS0tLSsKCkxlZ2VuZDoKIC0gTGlu a2VkIGxpc3QsIGFsc28ga25vdyBhcyBDaHVuawogLSBMaW5rZWQgbGlzdCBlbGVtZW50KiwgYWxz byBrbm93IGFzIEJ1cnN0ICpDQiosIGFsc28ga25vdyBhcyBDaGFuZ2UgQml0LAppdCdzIGEgY29u dHJvbCBiaXQgKGFuZCB0eXBpY2FsbHkgaXMgdG9nZ2xlZCkgdGhhdCBhbGxvd3MgdG8gZWFzaWx5 CmlkZW50aWZ5IGFuZCBkaWZmZXJlbnRpYXRlIGJldHdlZW4gdGhlIGN1cnJlbnQgbGlua2VkIGxp c3QgYW5kIHRoZQpwcmV2aW91cyBvciB0aGUgbmV4dCBvbmUuCiAtIExMUCwgaXMgYSBzcGVjaWFs IGVsZW1lbnQgdGhhdCBpbmRpY2F0ZXMgdGhlIGVuZCBvZiB0aGUgbGlua2VkIGxpc3QKZWxlbWVu dCBzdHJlYW0gYWxzbyBpbmZvcm1zIHRoYXQgdGhlIG5leHQgQ0Igc2hvdWxkIGJlIHRvZ2dsZQoK T24gZXZlcnkgbGFzdCBCdXJzdCBvZiB0aGUgQ2h1bmsgKEJ1cnN0ICM0MSwgQnVyc3QgIzgzLCBC dXJzdCAjMTI1IG9yCmV2ZW4gQnVyc3QgIzEyOSkgaXMgc2V0IHNvbWUgZmxhZ3Mgb24gdGhlaXIg Y29udHJvbCB2YXJpYWJsZSAoUklFIGFuZApMSUUgYml0cykgdGhhdCB3aWxsIHRyaWdnZXIgdGhl IHNlbmQgb2YgImRvbmUiIGludGVycnVwdGlvbi4KCk9uIHRoZSBpbnRlcnJ1cHRpb25zIGNhbGxi YWNrLCBpcyBkZWNpZGVkIHdoZXRoZXIgdG8gcmVjeWNsZSB0aGUgbGlua2VkCmxpc3QgbWVtb3J5 IHNwYWNlIGJ5IHdyaXRpbmcgYSBuZXcgc2V0IG9mIEJ1cnN0cyBlbGVtZW50cyAoaWYgc3RpbGwK ZXhpc3RzIENodW5rcyB0byB0cmFuc2Zlcikgb3IgaXMgY29uc2lkZXJlZCBjb21wbGV0ZWQgKGlm IHRoZXJlIGlzIG5vCkNodW5rcyBhdmFpbGFibGUgdG8gdHJhbnNmZXIpLgoKT24gc2NhdHRlci1n YXRoZXIgdHJhbnNmZXIgbW9kZSwgdGhlIGNsaWVudCB3aWxsIHN1Ym1pdCBhIHNjYXR0ZXItZ2F0 aGVyCmxpc3Qgb2YgbiAob24gdGhpcyBjYXNlIDEzMCkgZWxlbWVudHMsIHRoYXQgd2lsbCBiZSBk aXZpZGUgaW4gbXVsdGlwbGUKQ2h1bmtzLCBlYWNoIENodW5rIHdpbGwgaGF2ZSAob24gdGhpcyBj YXNlIDQyKSBhIGxpbWl0ZWQgbnVtYmVyIG9mCkJ1cnN0cyBhbmQgYWZ0ZXIgdHJhbnNmZXJyaW5n IGFsbCBCdXJzdHMsIGFuIGludGVycnVwdCB3aWxsIGJlCnRyaWdnZXJlZCwgd2hpY2ggd2lsbCBh bGxvdyB0byByZWN5Y2xlIHRoZSBhbGwgbGlua2VkIGxpc3QgZGVkaWNhdGVkCm1lbW9yeSBhZ2Fp biB3aXRoIHRoZSBuZXcgaW5mb3JtYXRpb24gcmVsYXRpdmUgdG8gdGhlIG5leHQgQ2h1bmsgYW5k CnJlc3BlY3RpdmUgQnVyc3QgYXNzb2NpYXRlZCBhbmQgcmVwZWF0IHRoZSB3aG9sZSBjeWNsZSBh Z2Fpbi4KCk9uIGN5Y2xpYyB0cmFuc2ZlciBtb2RlLCB0aGUgY2xpZW50IHdpbGwgc3VibWl0IGEg YnVmZmVyIHBvaW50ZXIsIGxlbmd0aApvZiBpdCBhbmQgbnVtYmVyIG9mIHJlcGV0aXRpb25zLCBp biB0aGlzIGNhc2UgZWFjaCBidXJzdCB3aWxsIGNvcnJlc3BvbmQKZGlyZWN0bHkgdG8gZWFjaCBy ZXBldGl0aW9uLgoKRWFjaCBCdXJzdCBjYW4gZGVzY3JpYmVzIGEgZGF0YSB0cmFuc2ZlciBmcm9t IHBvaW50IEEoc291cmNlKSB0byBwb2ludApCKGRlc3RpbmF0aW9uKSB3aXRoIGEgbGVuZ3RoIHRo YXQgY2FuIGJlIGZyb20gMSBieXRlIHVwIHRvIDQgR0IuIFNpbmNlCmRlZGljYXRlZCB0aGUgbWVt b3J5IHNwYWNlIHdoZXJlIHRoZSBsaW5rZWQgbGlzdCB3aWxsIHJlc2lkZSBpcyBsaW1pdGVkLAp0 aGUgd2hvbGUgbiBidXJzdCBlbGVtZW50cyB3aWxsIGJlIG9yZ2FuaXplZCBpbiBzZXZlcmFsIENo dW5rcywgdGhhdAp3aWxsIGJlIHVzZWQgbGF0ZXIgdG8gcmVjeWNsZSB0aGUgZGVkaWNhdGVkIG1l bW9yeSBzcGFjZSB0byBpbml0aWF0ZSBhCm5ldyBzZXF1ZW5jZSBvZiBkYXRhIHRyYW5zZmVycy4K ClRoZSB3aG9sZSB0cmFuc2ZlciBpcyBjb25zaWRlcmVkIGhhcyBjb21wbGV0ZWQgd2hlbiBpdCB3 YXMgdHJhbnNmZXJyZWQKYWxsIGJ1cnN0cy4KCkN1cnJlbnRseSB0aGlzIElQIGhhcyBhIHNldCB3 ZWxsLWtub3duIHJlZ2lzdGVyIG1hcCwgd2hpY2ggaW5jbHVkZXMKc3VwcG9ydCBmb3IgbGVnYWN5 IGFuZCB1bnJvbGwgbW9kZXMuIExlZ2FjeSBtb2RlIGlzIHZlcnNpb24gb2YgdGhpcwpyZWdpc3Rl ciBtYXAgdGhhdCBoYXMgbXVsdGlwbGV4ZXIgcmVnaXN0ZXIgdGhhdCBhbGxvd3MgdG8gc3dpdGNo CnJlZ2lzdGVycyBiZXR3ZWVuIGFsbCB3cml0ZSBhbmQgcmVhZCBjaGFubmVscyBhbmQgdGhlIHVu cm9sbCBtb2RlcwpyZXBlYXRzIGFsbCB3cml0ZSBhbmQgcmVhZCBjaGFubmVscyByZWdpc3RlcnMg d2l0aCBhbiBvZmZzZXQgYmV0d2Vlbgp0aGVtLiBUaGlzIHJlZ2lzdGVyIG1hcCBpcyBjYWxsZWQg djAuCgpUaGUgSVAgdGVhbSBpcyBjcmVhdGluZyBhIG5ldyByZWdpc3RlciBtYXAgbW9yZSBzdWl0 YWJsZSB0byB0aGUgbGF0ZXN0ClBDSWUgZmVhdHVyZXMsIHRoYXQgdmVyeSBsaWtlbHkgd2lsbCBj aGFuZ2UgdGhlIG1hcCByZWdpc3Rlciwgd2hpY2ggdGhpcwp2ZXJzaW9uIHdpbGwgYmUgY2FsbGVk IHYxLiBBcyBzb29uIGFzIHRoaXMgbmV3IHZlcnNpb24gaXMgcmVsZWFzZWQgYnkKdGhlIElQIHRl YW0gdGhlIHN1cHBvcnQgZm9yIHRoaXMgdmVyc2lvbiBpbiBiZSBpbmNsdWRlZCBvbiB0aGlzIGRy aXZlci4KClRoaXMgcGF0Y2ggaGFzIGEgZGlyZWN0IGRlcGVuZGVuY3kgb2YgdGhlIHBhdGNoICgi W1JGQyAyLzddIGRtYWVuZ2luZToKQWRkIFN5bm9wc3lzIGVETUEgSVAgdmVyc2lvbiAwIHN1cHBv cnQiKS4KCkFjY29yZGluZyB0byB0aGUgbG9naWMsIHBhdGNoZXMgMSwgMiBhbmQgMyBzaG91bGQg YmUgc3F1YXNoZWQgaW50byAxCnVuaXF1ZSBwYXRjaCwgYnV0IGZvciB0aGUgc2FrZSBvZiBzaW1w bGljaXR5IG9mIHJldmlldywgaXQgd2FzIGRpdmlkZWQKaW4gdGhpcyAzIHBhdGNoZXMgZmlsZXMu CgpTaWduZWQtb2ZmLWJ5OiBHdXN0YXZvIFBpbWVudGVsIDxndXN0YXZvLnBpbWVudGVsQHN5bm9w c3lzLmNvbT4KQ2M6IFZpbm9kIEtvdWwgPHZrb3VsQGtlcm5lbC5vcmc+CkNjOiBEYW4gV2lsbGlh bXMgPGRhbi5qLndpbGxpYW1zQGludGVsLmNvbT4KQ2M6IEFuZHkgU2hldmNoZW5rbyA8YW5kcml5 LnNoZXZjaGVua29AbGludXguaW50ZWwuY29tPgpDYzogUnVzc2VsbCBLaW5nIDxybWsra2VybmVs QGFybWxpbnV4Lm9yZy51az4KQ2M6IEpvYW8gUGludG8gPGpwaW50b0BzeW5vcHN5cy5jb20+Ci0t LQpDaGFuZ2VzOgpSRkMgdjEtPlJGQyB2MjoKIC0gUmVwbGFjZSBjb21tZW50cyAvLyAoQzk5IHN0 eWxlKSBieSAvKiovCiAtIEZpeCB0aGUgaGVhZGVycyBvZiB0aGUgLmMgYW5kIC5oIGZpbGVzIGFj Y29yZGluZyB0byB0aGUgbW9zdCByZWNlbnQKICAgY29udmVudGlvbgogLSBGaXggZXJyb3JzIGFu ZCBjaGVja3MgcG9pbnRlZCBvdXQgYnkgY2hlY2twYXRjaCB3aXRoIC0tc3RyaWN0IG9wdGlvbgog LSBSZXBsYWNlIHBhdGNoIHNtYWxsIGRlc2NyaXB0aW9uIHRhZyBmcm9tIGRtYSBieSBkbWFlbmdp bmUKIC0gQ2hhbmdlIHNvbWUgZGV2X2luZm8oKSBpbnRvIGRldl9kYmcoKQogLSBSZW1vdmUgdW5u ZWNlc3NhcnkgemVybyBpbml0aWFsaXphdGlvbiBhZnRlciBremFsbG9jCiAtIFJlbW92ZSBkaXJl Y3Rpb24gdmFsaWRhdGlvbiBvbiBjb25maWcoKSBBUEksIHNpbmNlIHRoZSBkaXJlY3Rpb24KICAg cGFyYW1ldGVyIGlzIGRlcHJlY2F0ZWQKIC0gUmVmYWN0b3IgY29kZSB0byByZXBsYWNlIGF0b21p Y190IGJ5IHUzMiB2YXJpYWJsZSB0eXBlCiAtIFJlcGxhY2Ugc3RhcnRfdHJhbnNmZXIoKSBuYW1l IGJ5IGR3X2VkbWFfc3RhcnRfdHJhbnNmZXIoKQogLSBBZGQgc3BpbmxvY2sgdG8gZHdfZWRtYV9k ZXZpY2VfcHJlcF9zbGF2ZV9zZygpCiAtIEFkZCBzcGlubG9jayB0byBkd19lZG1hX2ZyZWVfY2h1 bmsoKQogLSBTaW1wbGlmeSBzd2l0Y2ggY2FzZSBpbnRvIGlmIG9uIGR3X2VkbWFfZGV2aWNlX3Bh dXNlKCksCiAgIGR3X2VkbWFfZGV2aWNlX3Jlc3VtZSgpIGFuZCBkd19lZG1hX2RldmljZV90ZXJt aW5hdGVfYWxsKCkKUkZDIHYyLT5SRkMgdjM6CiAtIEFkZCBkcml2ZXIgcGFyYW1ldGVyIHRvIGRp c2FibGUgbXNpeCBmZWF0dXJlCiAtIEZpeCBwcmludGsgdmFyaWFibGUgb2YgcGh5c19hZGRyX3Qg dHlwZQogLSBGaXggcHJpbnRrIHZhcmlhYmxlIG9mIF9faW9tZW0gdHlwZQogLSBGaXggcHJpbnRr IHZhcmlhYmxlIG9mIHNpemVfdCB0eXBlCiAtIEFkZCBjb21tZW50cyBvciBpbXByb3ZlIGV4aXN0 aW5nIG9uZXMKIC0gQWRkIHBvc3NpYmlsaXR5IHRvIHdvcmsgd2l0aCBtdWx0aXBsZSBJUlFzIGZl YXR1cmUKIC0gRml4IHNvdXJjZSBhbmQgZGVzdGluYXRpb24gYWRkcmVzc2VzCiAtIEFkZCBkZWZp bmUgdG8gbWFnaWMgbnVtYmVycwogLSBBZGQgRE1BIGN5Y2xpYyB0cmFuc2ZlciBmZWF0dXJlCiAt IFJlYmFzZSB0byB2NS4wLXJjMQpSRkMgdjMtPlJGQyB2NDoKIC0gUmVtb3ZlIHVubmVjZXNzYXJ5 IGRldl9pbmZvKCkgY2FsbHMKIC0gQWRkIG11bHRpcGxlIElSUSBhdXRvbWF0aWMgYWRhcHRpb24g ZmVhdHVyZQogLSBSZW9yZGVyIHZhcmlhYmxlcyBkZWNsYXJhdGlvbiBpbiByZXZlcnNlIHRyZWUg b3JkZXIgb24gc2V2ZXJhbAogICBmdW5jdGlvbnMKIC0gQWRkIHJldHVybiBjaGVjayBvZiBkd19l ZG1hX2FsbG9jX2J1cnN0KCkgaW4gZHdfZWRtYV9hbGxvY19jaHVuaygpCiAtIEFkZCByZXR1cm4g Y2hlY2sgb2YgZHdfZWRtYV9hbGxvY19jaHVuaygpIGluIGR3X2VkbWFfYWxsb2NfZGVzYygpCiAt IFJlbW92ZSBwbV9ydW50aW1lX2dldF9zeW5jKCkgY2FsbCBpbiBwcm9iZSgpCiAtIEZpeCBkbWFf Y3ljbGljKCkgYnVmZmVyIGFkZHJlc3MKIC0gUmVwbGFjZSBkZXZtXypfaXJxKCkgYnkgKl9pcnEo KSBhbmQgcmVjb2RlIGFjY29yZGluZ2x5CiAtIEZpeCBsaWNlbnNlIGhlYWRlcgogLSBSZXBsYWNl IGt2emFsbG9jKCkgYnkga3phbGxvYygpIGFuZCBrdmZyZWUoKSBieSBrZnJlZSgpCiAtIE1vdmUg b3BzLT5kZXZpY2VfY29uZmlnIGNhbGxiYWNrIGZyb20gY29uZmlnKCkgdG8gcHJvYmUoKQogLSBS ZW1vdmUgcmVzdHJpY3Rpb24gdG8gcGVyZm9ybSBvcGVyYXRpb24gb25seSBpbiBJRExFIHN0YXRl IG9uCiAgIGR3X2VkbWFfZGV2aWNlX2NvbmZpZygpLCBkd19lZG1hX2RldmljZV9wcmVwX3NsYXZl X3NnKCksCiAgIGR3X2VkbWFfZGV2aWNlX3ByZXBfZG1hX2N5Y2xpYygpCiAtIFJlY29kZSBhbmQg c2ltcGxpZnkgc2xhdmVfc2coKSBhbmQgZG1hX2N5Y2xpYygpCiAtIFJlY29kZSBhbmQgc2ltcGxp ZnkgaW50ZXJydXB0cyBhbmQgY2hhbm5lbCBzZXR1cAogLSBSZWNvZGUgZHdfZWRtYV9kZXZpY2Vf dHhfc3RhdHVzKCkKIC0gTW92ZSBnZXRfY2FjaGVkX21zaV9tc2coKSB0byBoZXJlCiAtIENvZGUg cmV3cml0ZSB0byB1c2UgZGlyZWN0IGR3LWVkbWEtdjAtY29yZSBmdW5jdGlvbnMgaW5zdGVhZCBv ZgogY2FsbGJhY2tzClJGQyB2NC0+UkZDIHY1OgogLSBQYXRjaCByZXNlbmRlZCwgZm9yZ290IHRv IHJlcGxhY2Ugb2YgJ19fXycgYnkgJy0tLScgYW5kIHRvIHJlbW92ZQogZHVwbGljYXRlIHNpZ25l ZC1vZmYKUkZDIHY1LT5SRkMgdjY6CiAtIEFkZCBhdXRob3Igb24gZmlsZSBoZWFkZXIKIC0gUmVt b3ZlIGRlYnVnIHByaW50cwogLSBDb2RlIHJld3JpdGUgZm9sbG93aW5nIEFuZHkncyBzdWdnZXN0 YXRpb25zCgogZHJpdmVycy9kbWEvS2NvbmZpZyAgICAgICAgICAgICAgICB8ICAgMiArCiBkcml2 ZXJzL2RtYS9NYWtlZmlsZSAgICAgICAgICAgICAgIHwgICAxICsKIGRyaXZlcnMvZG1hL2R3LWVk bWEvS2NvbmZpZyAgICAgICAgfCAgIDkgKwogZHJpdmVycy9kbWEvZHctZWRtYS9NYWtlZmlsZSAg ICAgICB8ICAgNCArCiBkcml2ZXJzL2RtYS9kdy1lZG1hL2R3LWVkbWEtY29yZS5jIHwgOTE5ICsr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKIGRyaXZlcnMvZG1hL2R3LWVkbWEv ZHctZWRtYS1jb3JlLmggfCAxNjUgKysrKysrKwogaW5jbHVkZS9saW51eC9kbWEvZWRtYS5oICAg ICAgICAgICB8ICA0NyArKwogNyBmaWxlcyBjaGFuZ2VkLCAxMTQ3IGluc2VydGlvbnMoKykKIGNy ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2RtYS9kdy1lZG1hL0tjb25maWcKIGNyZWF0ZSBtb2Rl IDEwMDY0NCBkcml2ZXJzL2RtYS9kdy1lZG1hL01ha2VmaWxlCiBjcmVhdGUgbW9kZSAxMDA2NDQg ZHJpdmVycy9kbWEvZHctZWRtYS9kdy1lZG1hLWNvcmUuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRy aXZlcnMvZG1hL2R3LWVkbWEvZHctZWRtYS1jb3JlLmgKIGNyZWF0ZSBtb2RlIDEwMDY0NCBpbmNs dWRlL2xpbnV4L2RtYS9lZG1hLmgKCmRpZmYgLS1naXQgYS9kcml2ZXJzL2RtYS9LY29uZmlnIGIv ZHJpdmVycy9kbWEvS2NvbmZpZwppbmRleCAwYjFkZmI1Li41OGI3OGQyIDEwMDY0NAotLS0gYS9k cml2ZXJzL2RtYS9LY29uZmlnCisrKyBiL2RyaXZlcnMvZG1hL0tjb25maWcKQEAgLTY2NSw2ICs2 NjUsOCBAQCBzb3VyY2UgImRyaXZlcnMvZG1hL3Fjb20vS2NvbmZpZyIKIAogc291cmNlICJkcml2 ZXJzL2RtYS9kdy9LY29uZmlnIgogCitzb3VyY2UgImRyaXZlcnMvZG1hL2R3LWVkbWEvS2NvbmZp ZyIKKwogc291cmNlICJkcml2ZXJzL2RtYS9oc3UvS2NvbmZpZyIKIAogc291cmNlICJkcml2ZXJz L2RtYS9zaC9LY29uZmlnIgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9kbWEvTWFrZWZpbGUgYi9kcml2 ZXJzL2RtYS9NYWtlZmlsZQppbmRleCA2MTI2ZTFjLi41YmRkZjZmIDEwMDY0NAotLS0gYS9kcml2 ZXJzL2RtYS9NYWtlZmlsZQorKysgYi9kcml2ZXJzL2RtYS9NYWtlZmlsZQpAQCAtMjksNiArMjks NyBAQCBvYmotJChDT05GSUdfRE1BX1NVTjRJKSArPSBzdW40aS1kbWEubwogb2JqLSQoQ09ORklH X0RNQV9TVU42SSkgKz0gc3VuNmktZG1hLm8KIG9iai0kKENPTkZJR19EV19BWElfRE1BQykgKz0g ZHctYXhpLWRtYWMvCiBvYmotJChDT05GSUdfRFdfRE1BQ19DT1JFKSArPSBkdy8KK29iai0kKENP TkZJR19EV19FRE1BKSArPSBkdy1lZG1hLwogb2JqLSQoQ09ORklHX0VQOTNYWF9ETUEpICs9IGVw OTN4eF9kbWEubwogb2JqLSQoQ09ORklHX0ZTTF9ETUEpICs9IGZzbGRtYS5vCiBvYmotJChDT05G SUdfRlNMX0VETUEpICs9IGZzbC1lZG1hLm8gZnNsLWVkbWEtY29tbW9uLm8KZGlmZiAtLWdpdCBh L2RyaXZlcnMvZG1hL2R3LWVkbWEvS2NvbmZpZyBiL2RyaXZlcnMvZG1hL2R3LWVkbWEvS2NvbmZp ZwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi4zMDE2YmVkCi0tLSAvZGV2L251 bGwKKysrIGIvZHJpdmVycy9kbWEvZHctZWRtYS9LY29uZmlnCkBAIC0wLDAgKzEsOSBAQAorIyBT UERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAorCitjb25maWcgRFdfRURNQQorCXRyaXN0 YXRlICJTeW5vcHN5cyBEZXNpZ25XYXJlIGVETUEgY29udHJvbGxlciBkcml2ZXIiCisJc2VsZWN0 IERNQV9FTkdJTkUKKwlzZWxlY3QgRE1BX1ZJUlRVQUxfQ0hBTk5FTFMKKwloZWxwCisJICBTdXBw b3J0IHRoZSBTeW5vcHN5cyBEZXNpZ25XYXJlIGVETUEgY29udHJvbGxlciwgbm9ybWFsbHkKKwkg IGltcGxlbWVudGVkIG9uIGVuZHBvaW50cyBTb0NzLgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9kbWEv ZHctZWRtYS9NYWtlZmlsZSBiL2RyaXZlcnMvZG1hL2R3LWVkbWEvTWFrZWZpbGUKbmV3IGZpbGUg bW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uMzIyNDAxMAotLS0gL2Rldi9udWxsCisrKyBiL2Ry aXZlcnMvZG1hL2R3LWVkbWEvTWFrZWZpbGUKQEAgLTAsMCArMSw0IEBACisjIFNQRFgtTGljZW5z ZS1JZGVudGlmaWVyOiBHUEwtMi4wCisKK29iai0kKENPTkZJR19EV19FRE1BKQkJKz0gZHctZWRt YS5vCitkdy1lZG1hLW9ianMJCQk6PSBkdy1lZG1hLWNvcmUubwpkaWZmIC0tZ2l0IGEvZHJpdmVy cy9kbWEvZHctZWRtYS9kdy1lZG1hLWNvcmUuYyBiL2RyaXZlcnMvZG1hL2R3LWVkbWEvZHctZWRt YS1jb3JlLmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMC4uNTRjZDUzMQotLS0g L2Rldi9udWxsCisrKyBiL2RyaXZlcnMvZG1hL2R3LWVkbWEvZHctZWRtYS1jb3JlLmMKQEAgLTAs MCArMSw5MTkgQEAKKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wCisvKgorICog Q29weXJpZ2h0IChjKSAyMDE4LTIwMTkgU3lub3BzeXMsIEluYy4gYW5kL29yIGl0cyBhZmZpbGlh dGVzLgorICogU3lub3BzeXMgRGVzaWduV2FyZSBlRE1BIGNvcmUgZHJpdmVyCisgKgorICogQXV0 aG9yOiBHdXN0YXZvIFBpbWVudGVsIDxndXN0YXZvLnBpbWVudGVsQHN5bm9wc3lzLmNvbT4KKyAq LworCisjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+CisjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+ CisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+CisjaW5jbHVkZSA8bGludXgvcG1fcnVudGltZS5o PgorI2luY2x1ZGUgPGxpbnV4L2RtYWVuZ2luZS5oPgorI2luY2x1ZGUgPGxpbnV4L2Vyci5oPgor I2luY2x1ZGUgPGxpbnV4L2ludGVycnVwdC5oPgorI2luY2x1ZGUgPGxpbnV4L2RtYS9lZG1hLmg+ CisjaW5jbHVkZSA8bGludXgvcGNpLmg+CisKKyNpbmNsdWRlICJkdy1lZG1hLWNvcmUuaCIKKyNp bmNsdWRlICIuLi9kbWFlbmdpbmUuaCIKKyNpbmNsdWRlICIuLi92aXJ0LWRtYS5oIgorCitzdGF0 aWMgaW5saW5lCitzdHJ1Y3QgZGV2aWNlICpkY2hhbjJkZXYoc3RydWN0IGRtYV9jaGFuICpkY2hh bikKK3sKKwlyZXR1cm4gJmRjaGFuLT5kZXYtPmRldmljZTsKK30KKworc3RhdGljIGlubGluZQor c3RydWN0IGRldmljZSAqY2hhbjJkZXYoc3RydWN0IGR3X2VkbWFfY2hhbiAqY2hhbikKK3sKKwly ZXR1cm4gJmNoYW4tPnZjLmNoYW4uZGV2LT5kZXZpY2U7Cit9CisKK3N0YXRpYyBpbmxpbmUKK3N0 cnVjdCBkd19lZG1hX2Rlc2MgKnZkMmR3X2VkbWFfZGVzYyhzdHJ1Y3QgdmlydF9kbWFfZGVzYyAq dmQpCit7CisJcmV0dXJuIGNvbnRhaW5lcl9vZih2ZCwgc3RydWN0IGR3X2VkbWFfZGVzYywgdmQp OworfQorCitzdGF0aWMgc3RydWN0IGR3X2VkbWFfYnVyc3QgKmR3X2VkbWFfYWxsb2NfYnVyc3Qo c3RydWN0IGR3X2VkbWFfY2h1bmsgKmNodW5rKQoreworCXN0cnVjdCBkd19lZG1hX2J1cnN0ICpi dXJzdDsKKworCWJ1cnN0ID0ga3phbGxvYyhzaXplb2YoKmJ1cnN0KSwgR0ZQX0tFUk5FTCk7CisJ aWYgKHVubGlrZWx5KCFidXJzdCkpCisJCXJldHVybiBOVUxMOworCisJSU5JVF9MSVNUX0hFQUQo JmJ1cnN0LT5saXN0KTsKKwlpZiAoY2h1bmstPmJ1cnN0KSB7CisJCS8qIENyZWF0ZSBhbmQgYWRk IG5ldyBlbGVtZW50IGludG8gdGhlIGxpbmtlZCBsaXN0ICovCisJCWNodW5rLT5idXJzdHNfYWxs b2MrKzsKKwkJbGlzdF9hZGRfdGFpbCgmYnVyc3QtPmxpc3QsICZjaHVuay0+YnVyc3QtPmxpc3Qp OworCX0gZWxzZSB7CisJCS8qIExpc3QgaGVhZCAqLworCQljaHVuay0+YnVyc3RzX2FsbG9jID0g MDsKKwkJY2h1bmstPmJ1cnN0ID0gYnVyc3Q7CisJfQorCisJcmV0dXJuIGJ1cnN0OworfQorCitz dGF0aWMgc3RydWN0IGR3X2VkbWFfY2h1bmsgKmR3X2VkbWFfYWxsb2NfY2h1bmsoc3RydWN0IGR3 X2VkbWFfZGVzYyAqZGVzYykKK3sKKwlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuID0gZGVzYy0+ Y2hhbjsKKwlzdHJ1Y3QgZHdfZWRtYSAqZHcgPSBjaGFuLT5jaGlwLT5kdzsKKwlzdHJ1Y3QgZHdf ZWRtYV9jaHVuayAqY2h1bms7CisKKwljaHVuayA9IGt6YWxsb2Moc2l6ZW9mKCpjaHVuayksIEdG UF9LRVJORUwpOworCWlmICh1bmxpa2VseSghY2h1bmspKQorCQlyZXR1cm4gTlVMTDsKKworCUlO SVRfTElTVF9IRUFEKCZjaHVuay0+bGlzdCk7CisJY2h1bmstPmNoYW4gPSBjaGFuOworCWNodW5r LT5jYiA9ICEoZGVzYy0+Y2h1bmtzX2FsbG9jICUgMik7CisJY2h1bmstPmxsX3JlZ2lvbi5wYWRk ciA9IGR3LT5sbF9yZWdpb24ucGFkZHIgKyBjaGFuLT5sbF9vZmY7CisJY2h1bmstPmxsX3JlZ2lv bi52YWRkciA9IGR3LT5sbF9yZWdpb24udmFkZHIgKyBjaGFuLT5sbF9vZmY7CisKKwlpZiAoZGVz Yy0+Y2h1bmspIHsKKwkJLyogQ3JlYXRlIGFuZCBhZGQgbmV3IGVsZW1lbnQgaW50byB0aGUgbGlu a2VkIGxpc3QgKi8KKwkJZGVzYy0+Y2h1bmtzX2FsbG9jKys7CisJCWxpc3RfYWRkX3RhaWwoJmNo dW5rLT5saXN0LCAmZGVzYy0+Y2h1bmstPmxpc3QpOworCQlpZiAoIWR3X2VkbWFfYWxsb2NfYnVy c3QoY2h1bmspKSB7CisJCQlrZnJlZShjaHVuayk7CisJCQlyZXR1cm4gTlVMTDsKKwkJfQorCX0g ZWxzZSB7CisJCS8qIExpc3QgaGVhZCAqLworCQljaHVuay0+YnVyc3QgPSBOVUxMOworCQlkZXNj LT5jaHVua3NfYWxsb2MgPSAwOworCQlkZXNjLT5jaHVuayA9IGNodW5rOworCX0KKworCXJldHVy biBjaHVuazsKK30KKworc3RhdGljIHN0cnVjdCBkd19lZG1hX2Rlc2MgKmR3X2VkbWFfYWxsb2Nf ZGVzYyhzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuKQoreworCXN0cnVjdCBkd19lZG1hX2Rlc2Mg KmRlc2M7CisKKwlkZXNjID0ga3phbGxvYyhzaXplb2YoKmRlc2MpLCBHRlBfS0VSTkVMKTsKKwlp ZiAodW5saWtlbHkoIWRlc2MpKQorCQlyZXR1cm4gTlVMTDsKKworCWRlc2MtPmNoYW4gPSBjaGFu OworCWlmICghZHdfZWRtYV9hbGxvY19jaHVuayhkZXNjKSkgeworCQlrZnJlZShkZXNjKTsKKwkJ cmV0dXJuIE5VTEw7CisJfQorCisJcmV0dXJuIGRlc2M7Cit9CisKK3N0YXRpYyB2b2lkIGR3X2Vk bWFfZnJlZV9idXJzdChzdHJ1Y3QgZHdfZWRtYV9jaHVuayAqY2h1bmspCit7CisJc3RydWN0IGR3 X2VkbWFfYnVyc3QgKmNoaWxkLCAqX25leHQ7CisKKwkvKiBSZW1vdmUgYWxsIHRoZSBsaXN0IGVs ZW1lbnRzICovCisJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKGNoaWxkLCBfbmV4dCwgJmNodW5r LT5idXJzdC0+bGlzdCwgbGlzdCkgeworCQlsaXN0X2RlbCgmY2hpbGQtPmxpc3QpOworCQlrZnJl ZShjaGlsZCk7CisJCWNodW5rLT5idXJzdHNfYWxsb2MtLTsKKwl9CisKKwkvKiBSZW1vdmUgdGhl IGxpc3QgaGVhZCAqLworCWtmcmVlKGNoaWxkKTsKKwljaHVuay0+YnVyc3QgPSBOVUxMOworfQor CitzdGF0aWMgdm9pZCBkd19lZG1hX2ZyZWVfY2h1bmsoc3RydWN0IGR3X2VkbWFfZGVzYyAqZGVz YykKK3sKKwlzdHJ1Y3QgZHdfZWRtYV9jaHVuayAqY2hpbGQsICpfbmV4dDsKKworCWlmICghZGVz Yy0+Y2h1bmspCisJCXJldHVybjsKKworCS8qIFJlbW92ZSBhbGwgdGhlIGxpc3QgZWxlbWVudHMg Ki8KKwlsaXN0X2Zvcl9lYWNoX2VudHJ5X3NhZmUoY2hpbGQsIF9uZXh0LCAmZGVzYy0+Y2h1bmst Pmxpc3QsIGxpc3QpIHsKKwkJZHdfZWRtYV9mcmVlX2J1cnN0KGNoaWxkKTsKKwkJbGlzdF9kZWwo JmNoaWxkLT5saXN0KTsKKwkJa2ZyZWUoY2hpbGQpOworCQlkZXNjLT5jaHVua3NfYWxsb2MtLTsK Kwl9CisKKwkvKiBSZW1vdmUgdGhlIGxpc3QgaGVhZCAqLworCWtmcmVlKGNoaWxkKTsKKwlkZXNj LT5jaHVuayA9IE5VTEw7Cit9CisKK3N0YXRpYyB2b2lkIGR3X2VkbWFfZnJlZV9kZXNjKHN0cnVj dCBkd19lZG1hX2Rlc2MgKmRlc2MpCit7CisJZHdfZWRtYV9mcmVlX2NodW5rKGRlc2MpOworCWtm cmVlKGRlc2MpOworfQorCitzdGF0aWMgdm9pZCB2Y2hhbl9mcmVlX2Rlc2Moc3RydWN0IHZpcnRf ZG1hX2Rlc2MgKnZkZXNjKQoreworCWR3X2VkbWFfZnJlZV9kZXNjKHZkMmR3X2VkbWFfZGVzYyh2 ZGVzYykpOworfQorCitzdGF0aWMgdm9pZCBkd19lZG1hX3N0YXJ0X3RyYW5zZmVyKHN0cnVjdCBk d19lZG1hX2NoYW4gKmNoYW4pCit7CisJc3RydWN0IGR3X2VkbWFfY2h1bmsgKmNoaWxkOworCXN0 cnVjdCBkd19lZG1hX2Rlc2MgKmRlc2M7CisJc3RydWN0IHZpcnRfZG1hX2Rlc2MgKnZkOworCisJ dmQgPSB2Y2hhbl9uZXh0X2Rlc2MoJmNoYW4tPnZjKTsKKwlpZiAoIXZkKQorCQlyZXR1cm47CisK KwlkZXNjID0gdmQyZHdfZWRtYV9kZXNjKHZkKTsKKwlpZiAoIWRlc2MpCisJCXJldHVybjsKKwor CWNoaWxkID0gbGlzdF9maXJzdF9lbnRyeV9vcl9udWxsKCZkZXNjLT5jaHVuay0+bGlzdCwKKwkJ CQkJIHN0cnVjdCBkd19lZG1hX2NodW5rLCBsaXN0KTsKKwlpZiAoIWNoaWxkKQorCQlyZXR1cm47 CisKKwlkd19lZG1hX3YwX2NvcmVfc3RhcnQoY2hpbGQsICFkZXNjLT54ZmVyX3N6KTsKKwlkZXNj LT54ZmVyX3N6ICs9IGNoaWxkLT5sbF9yZWdpb24uc3o7CisJZHdfZWRtYV9mcmVlX2J1cnN0KGNo aWxkKTsKKwlsaXN0X2RlbCgmY2hpbGQtPmxpc3QpOworCWtmcmVlKGNoaWxkKTsKKwlkZXNjLT5j aHVua3NfYWxsb2MtLTsKK30KKworc3RhdGljIGludCBkd19lZG1hX2RldmljZV9jb25maWcoc3Ry dWN0IGRtYV9jaGFuICpkY2hhbiwKKwkJCQkgc3RydWN0IGRtYV9zbGF2ZV9jb25maWcgKmNvbmZp ZykKK3sKKwlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuID0gZGNoYW4yZHdfZWRtYV9jaGFuKGRj aGFuKTsKKworCW1lbWNweSgmY2hhbi0+Y29uZmlnLCBjb25maWcsIHNpemVvZigqY29uZmlnKSk7 CisJY2hhbi0+Y29uZmlndXJlZCA9IHRydWU7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGlu dCBkd19lZG1hX2RldmljZV9wYXVzZShzdHJ1Y3QgZG1hX2NoYW4gKmRjaGFuKQoreworCXN0cnVj dCBkd19lZG1hX2NoYW4gKmNoYW4gPSBkY2hhbjJkd19lZG1hX2NoYW4oZGNoYW4pOworCWludCBl cnIgPSAwOworCisJaWYgKCFjaGFuLT5jb25maWd1cmVkKQorCQllcnIgPSAtRVBFUk07CisJZWxz ZSBpZiAoY2hhbi0+c3RhdHVzICE9IEVETUFfU1RfQlVTWSkKKwkJZXJyID0gLUVQRVJNOworCWVs c2UgaWYgKGNoYW4tPnJlcXVlc3QgIT0gRURNQV9SRVFfTk9ORSkKKwkJZXJyID0gLUVQRVJNOwor CWVsc2UKKwkJY2hhbi0+cmVxdWVzdCA9IEVETUFfUkVRX1BBVVNFOworCisJcmV0dXJuIGVycjsK K30KKworc3RhdGljIGludCBkd19lZG1hX2RldmljZV9yZXN1bWUoc3RydWN0IGRtYV9jaGFuICpk Y2hhbikKK3sKKwlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuID0gZGNoYW4yZHdfZWRtYV9jaGFu KGRjaGFuKTsKKwlpbnQgZXJyID0gMDsKKworCWlmICghY2hhbi0+Y29uZmlndXJlZCkgeworCQll cnIgPSAtRVBFUk07CisJfSBlbHNlIGlmIChjaGFuLT5zdGF0dXMgIT0gRURNQV9TVF9QQVVTRSkg eworCQllcnIgPSAtRVBFUk07CisJfSBlbHNlIGlmIChjaGFuLT5yZXF1ZXN0ICE9IEVETUFfUkVR X05PTkUpIHsKKwkJZXJyID0gLUVQRVJNOworCX0gZWxzZSB7CisJCWNoYW4tPnN0YXR1cyA9IEVE TUFfU1RfQlVTWTsKKwkJZHdfZWRtYV9zdGFydF90cmFuc2ZlcihjaGFuKTsKKwl9CisKKwlyZXR1 cm4gZXJyOworfQorCitzdGF0aWMgaW50IGR3X2VkbWFfZGV2aWNlX3Rlcm1pbmF0ZV9hbGwoc3Ry dWN0IGRtYV9jaGFuICpkY2hhbikKK3sKKwlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuID0gZGNo YW4yZHdfZWRtYV9jaGFuKGRjaGFuKTsKKwlpbnQgZXJyID0gMDsKKwlMSVNUX0hFQUQoaGVhZCk7 CisKKwlpZiAoIWNoYW4tPmNvbmZpZ3VyZWQpIHsKKwkJLyogRG8gbm90aGluZyAqLworCX0gZWxz ZSBpZiAoY2hhbi0+c3RhdHVzID09IEVETUFfU1RfUEFVU0UpIHsKKwkJY2hhbi0+c3RhdHVzID0g RURNQV9TVF9JRExFOworCQljaGFuLT5jb25maWd1cmVkID0gZmFsc2U7CisJfSBlbHNlIGlmIChj aGFuLT5zdGF0dXMgPT0gRURNQV9TVF9JRExFKSB7CisJCWNoYW4tPmNvbmZpZ3VyZWQgPSBmYWxz ZTsKKwl9IGVsc2UgaWYgKGR3X2VkbWFfdjBfY29yZV9jaF9zdGF0dXMoY2hhbikgPT0gRE1BX0NP TVBMRVRFKSB7CisJCS8qCisJCSAqIFRoZSBjaGFubmVsIGlzIGluIGEgZmFsc2UgQlVTWSBzdGF0 ZSwgcHJvYmFibHkgZGlkbid0CisJCSAqIHJlY2VpdmUgb3IgbG9zdCBhbiBpbnRlcnJ1cHQKKwkJ ICovCisJCWNoYW4tPnN0YXR1cyA9IEVETUFfU1RfSURMRTsKKwkJY2hhbi0+Y29uZmlndXJlZCA9 IGZhbHNlOworCX0gZWxzZSBpZiAoY2hhbi0+cmVxdWVzdCA+IEVETUFfUkVRX1BBVVNFKSB7CisJ CWVyciA9IC1FUEVSTTsKKwl9IGVsc2UgeworCQljaGFuLT5yZXF1ZXN0ID0gRURNQV9SRVFfU1RP UDsKKwl9CisKKwlyZXR1cm4gZXJyOworfQorCitzdGF0aWMgdm9pZCBkd19lZG1hX2RldmljZV9p c3N1ZV9wZW5kaW5nKHN0cnVjdCBkbWFfY2hhbiAqZGNoYW4pCit7CisJc3RydWN0IGR3X2VkbWFf Y2hhbiAqY2hhbiA9IGRjaGFuMmR3X2VkbWFfY2hhbihkY2hhbik7CisJdW5zaWduZWQgbG9uZyBm bGFnczsKKworCXNwaW5fbG9ja19pcnFzYXZlKCZjaGFuLT52Yy5sb2NrLCBmbGFncyk7CisJaWYg KGNoYW4tPmNvbmZpZ3VyZWQgJiYgY2hhbi0+cmVxdWVzdCA9PSBFRE1BX1JFUV9OT05FICYmCisJ ICAgIGNoYW4tPnN0YXR1cyA9PSBFRE1BX1NUX0lETEUgJiYgdmNoYW5faXNzdWVfcGVuZGluZygm Y2hhbi0+dmMpKSB7CisJCWNoYW4tPnN0YXR1cyA9IEVETUFfU1RfQlVTWTsKKwkJZHdfZWRtYV9z dGFydF90cmFuc2ZlcihjaGFuKTsKKwl9CisJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmY2hhbi0+ dmMubG9jaywgZmxhZ3MpOworfQorCitzdGF0aWMgZW51bSBkbWFfc3RhdHVzCitkd19lZG1hX2Rl dmljZV90eF9zdGF0dXMoc3RydWN0IGRtYV9jaGFuICpkY2hhbiwgZG1hX2Nvb2tpZV90IGNvb2tp ZSwKKwkJCSBzdHJ1Y3QgZG1hX3R4X3N0YXRlICp0eHN0YXRlKQoreworCXN0cnVjdCBkd19lZG1h X2NoYW4gKmNoYW4gPSBkY2hhbjJkd19lZG1hX2NoYW4oZGNoYW4pOworCXN0cnVjdCBkd19lZG1h X2Rlc2MgKmRlc2M7CisJc3RydWN0IHZpcnRfZG1hX2Rlc2MgKnZkOworCXVuc2lnbmVkIGxvbmcg ZmxhZ3M7CisJZW51bSBkbWFfc3RhdHVzIHJldDsKKwl1MzIgcmVzaWR1ZSA9IDA7CisKKwlyZXQg PSBkbWFfY29va2llX3N0YXR1cyhkY2hhbiwgY29va2llLCB0eHN0YXRlKTsKKwlpZiAocmV0ID09 IERNQV9DT01QTEVURSkKKwkJcmV0dXJuIHJldDsKKworCWlmIChyZXQgPT0gRE1BX0lOX1BST0dS RVNTICYmIGNoYW4tPnN0YXR1cyA9PSBFRE1BX1NUX1BBVVNFKQorCQlyZXQgPSBETUFfUEFVU0VE OworCisJaWYgKCF0eHN0YXRlKQorCQlnb3RvIHJldF9yZXNpZHVlOworCisJc3Bpbl9sb2NrX2ly cXNhdmUoJmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsKKwl2ZCA9IHZjaGFuX2ZpbmRfZGVzYygmY2hh bi0+dmMsIGNvb2tpZSk7CisJaWYgKHZkKSB7CisJCWRlc2MgPSB2ZDJkd19lZG1hX2Rlc2ModmQp OworCQlpZiAoZGVzYykKKwkJCXJlc2lkdWUgPSBkZXNjLT5hbGxvY19zeiAtIGRlc2MtPnhmZXJf c3o7CisJfQorCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsK KworcmV0X3Jlc2lkdWU6CisJZG1hX3NldF9yZXNpZHVlKHR4c3RhdGUsIHJlc2lkdWUpOworCisJ cmV0dXJuIHJldDsKK30KKworc3RhdGljIHN0cnVjdCBkbWFfYXN5bmNfdHhfZGVzY3JpcHRvciAq Citkd19lZG1hX2RldmljZV90cmFuc2ZlcihzdHJ1Y3QgZHdfZWRtYV90cmFuc2ZlciAqeGZlcikK K3sKKwlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuID0gZGNoYW4yZHdfZWRtYV9jaGFuKHhmZXIt PmRjaGFuKTsKKwllbnVtIGRtYV90cmFuc2Zlcl9kaXJlY3Rpb24gZGlyZWN0aW9uID0geGZlci0+ ZGlyZWN0aW9uOworCXBoeXNfYWRkcl90IHNyY19hZGRyLCBkc3RfYWRkcjsKKwlzdHJ1Y3Qgc2Nh dHRlcmxpc3QgKnNnID0gTlVMTDsKKwlzdHJ1Y3QgZHdfZWRtYV9jaHVuayAqY2h1bms7CisJc3Ry dWN0IGR3X2VkbWFfYnVyc3QgKmJ1cnN0OworCXN0cnVjdCBkd19lZG1hX2Rlc2MgKmRlc2M7CisJ dTMyIGNudDsKKwlpbnQgaTsKKworCWlmICgoZGlyZWN0aW9uID09IERNQV9NRU1fVE9fREVWICYm IGNoYW4tPmRpciA9PSBFRE1BX0RJUl9XUklURSkgfHwKKwkgICAgKGRpcmVjdGlvbiA9PSBETUFf REVWX1RPX01FTSAmJiBjaGFuLT5kaXIgPT0gRURNQV9ESVJfUkVBRCkpCisJCXJldHVybiBOVUxM OworCisJaWYgKHhmZXItPmN5Y2xpYykgeworCQlpZiAoIXhmZXItPnhmZXIuY3ljbGljLmxlbiB8 fCAheGZlci0+eGZlci5jeWNsaWMuY250KQorCQkJcmV0dXJuIE5VTEw7CisJfSBlbHNlIHsKKwkJ aWYgKHhmZXItPnhmZXIuc2cubGVuIDwgMSkKKwkJCXJldHVybiBOVUxMOworCX0KKworCWlmICgh Y2hhbi0+Y29uZmlndXJlZCkKKwkJcmV0dXJuIE5VTEw7CisKKwlkZXNjID0gZHdfZWRtYV9hbGxv Y19kZXNjKGNoYW4pOworCWlmICh1bmxpa2VseSghZGVzYykpCisJCWdvdG8gZXJyX2FsbG9jOwor CisJY2h1bmsgPSBkd19lZG1hX2FsbG9jX2NodW5rKGRlc2MpOworCWlmICh1bmxpa2VseSghY2h1 bmspKQorCQlnb3RvIGVycl9hbGxvYzsKKworCXNyY19hZGRyID0gY2hhbi0+Y29uZmlnLnNyY19h ZGRyOworCWRzdF9hZGRyID0gY2hhbi0+Y29uZmlnLmRzdF9hZGRyOworCisJaWYgKHhmZXItPmN5 Y2xpYykgeworCQljbnQgPSB4ZmVyLT54ZmVyLmN5Y2xpYy5jbnQ7CisJfSBlbHNlIHsKKwkJY250 ID0geGZlci0+eGZlci5zZy5sZW47CisJCXNnID0geGZlci0+eGZlci5zZy5zZ2w7CisJfQorCisJ Zm9yIChpID0gMDsgaSA8IGNudDsgaSsrKSB7CisJCWlmICgheGZlci0+Y3ljbGljICYmICFzZykK KwkJCWJyZWFrOworCisJCWlmIChjaHVuay0+YnVyc3RzX2FsbG9jID09IGNoYW4tPmxsX21heCkg eworCQkJY2h1bmsgPSBkd19lZG1hX2FsbG9jX2NodW5rKGRlc2MpOworCQkJaWYgKHVubGlrZWx5 KCFjaHVuaykpCisJCQkJZ290byBlcnJfYWxsb2M7CisJCX0KKworCQlidXJzdCA9IGR3X2VkbWFf YWxsb2NfYnVyc3QoY2h1bmspOworCQlpZiAodW5saWtlbHkoIWJ1cnN0KSkKKwkJCWdvdG8gZXJy X2FsbG9jOworCisJCWlmICh4ZmVyLT5jeWNsaWMpCisJCQlidXJzdC0+c3ogPSB4ZmVyLT54ZmVy LmN5Y2xpYy5sZW47CisJCWVsc2UKKwkJCWJ1cnN0LT5zeiA9IHNnX2RtYV9sZW4oc2cpOworCisJ CWNodW5rLT5sbF9yZWdpb24uc3ogKz0gYnVyc3QtPnN6OworCQlkZXNjLT5hbGxvY19zeiArPSBi dXJzdC0+c3o7CisKKwkJaWYgKGRpcmVjdGlvbiA9PSBETUFfREVWX1RPX01FTSkgeworCQkJYnVy c3QtPnNhciA9IHNyY19hZGRyOworCQkJaWYgKHhmZXItPmN5Y2xpYykgeworCQkJCWJ1cnN0LT5k YXIgPSB4ZmVyLT54ZmVyLmN5Y2xpYy5wYWRkcjsKKwkJCX0gZWxzZSB7CisJCQkJYnVyc3QtPmRh ciA9IHNnX2RtYV9hZGRyZXNzKHNnKTsKKwkJCQlzcmNfYWRkciArPSBzZ19kbWFfbGVuKHNnKTsK KwkJCX0KKwkJfSBlbHNlIHsKKwkJCWJ1cnN0LT5kYXIgPSBkc3RfYWRkcjsKKwkJCWlmICh4ZmVy LT5jeWNsaWMpIHsKKwkJCQlidXJzdC0+c2FyID0geGZlci0+eGZlci5jeWNsaWMucGFkZHI7CisJ CQl9IGVsc2UgeworCQkJCWJ1cnN0LT5zYXIgPSBzZ19kbWFfYWRkcmVzcyhzZyk7CisJCQkJZHN0 X2FkZHIgKz0gc2dfZG1hX2xlbihzZyk7CisJCQl9CisJCX0KKworCQlpZiAoIXhmZXItPmN5Y2xp YykKKwkJCXNnID0gc2dfbmV4dChzZyk7CisJfQorCisJcmV0dXJuIHZjaGFuX3R4X3ByZXAoJmNo YW4tPnZjLCAmZGVzYy0+dmQsIHhmZXItPmZsYWdzKTsKKworZXJyX2FsbG9jOgorCWlmIChkZXNj KQorCQlkd19lZG1hX2ZyZWVfZGVzYyhkZXNjKTsKKworCXJldHVybiBOVUxMOworfQorCitzdGF0 aWMgc3RydWN0IGRtYV9hc3luY190eF9kZXNjcmlwdG9yICoKK2R3X2VkbWFfZGV2aWNlX3ByZXBf c2xhdmVfc2coc3RydWN0IGRtYV9jaGFuICpkY2hhbiwgc3RydWN0IHNjYXR0ZXJsaXN0ICpzZ2ws CisJCQkgICAgIHVuc2lnbmVkIGludCBsZW4sCisJCQkgICAgIGVudW0gZG1hX3RyYW5zZmVyX2Rp cmVjdGlvbiBkaXJlY3Rpb24sCisJCQkgICAgIHVuc2lnbmVkIGxvbmcgZmxhZ3MsIHZvaWQgKmNv bnRleHQpCit7CisJc3RydWN0IGR3X2VkbWFfdHJhbnNmZXIgeGZlcjsKKworCXhmZXIuZGNoYW4g PSBkY2hhbjsKKwl4ZmVyLmRpcmVjdGlvbiA9IGRpcmVjdGlvbjsKKwl4ZmVyLnhmZXIuc2cuc2ds ID0gc2dsOworCXhmZXIueGZlci5zZy5sZW4gPSBsZW47CisJeGZlci5mbGFncyA9IGZsYWdzOwor CXhmZXIuY3ljbGljID0gZmFsc2U7CisKKwlyZXR1cm4gZHdfZWRtYV9kZXZpY2VfdHJhbnNmZXIo JnhmZXIpOworfQorCitzdGF0aWMgc3RydWN0IGRtYV9hc3luY190eF9kZXNjcmlwdG9yICoKK2R3 X2VkbWFfZGV2aWNlX3ByZXBfZG1hX2N5Y2xpYyhzdHJ1Y3QgZG1hX2NoYW4gKmRjaGFuLCBkbWFf YWRkcl90IHBhZGRyLAorCQkJICAgICAgIHNpemVfdCBsZW4sIHNpemVfdCBjb3VudCwKKwkJCSAg ICAgICBlbnVtIGRtYV90cmFuc2Zlcl9kaXJlY3Rpb24gZGlyZWN0aW9uLAorCQkJICAgICAgIHVu c2lnbmVkIGxvbmcgZmxhZ3MpCit7CisJc3RydWN0IGR3X2VkbWFfdHJhbnNmZXIgeGZlcjsKKwor CXhmZXIuZGNoYW4gPSBkY2hhbjsKKwl4ZmVyLmRpcmVjdGlvbiA9IGRpcmVjdGlvbjsKKwl4ZmVy LnhmZXIuY3ljbGljLnBhZGRyID0gcGFkZHI7CisJeGZlci54ZmVyLmN5Y2xpYy5sZW4gPSBsZW47 CisJeGZlci54ZmVyLmN5Y2xpYy5jbnQgPSBjb3VudDsKKwl4ZmVyLmZsYWdzID0gZmxhZ3M7CisJ eGZlci5jeWNsaWMgPSB0cnVlOworCisJcmV0dXJuIGR3X2VkbWFfZGV2aWNlX3RyYW5zZmVyKCZ4 ZmVyKTsKK30KKworc3RhdGljIHZvaWQgZHdfZWRtYV9kb25lX2ludGVycnVwdChzdHJ1Y3QgZHdf ZWRtYV9jaGFuICpjaGFuKQoreworCXN0cnVjdCBkd19lZG1hX2Rlc2MgKmRlc2M7CisJc3RydWN0 IHZpcnRfZG1hX2Rlc2MgKnZkOworCXVuc2lnbmVkIGxvbmcgZmxhZ3M7CisKKwlkd19lZG1hX3Yw X2NvcmVfY2xlYXJfZG9uZV9pbnQoY2hhbik7CisKKwlzcGluX2xvY2tfaXJxc2F2ZSgmY2hhbi0+ dmMubG9jaywgZmxhZ3MpOworCXZkID0gdmNoYW5fbmV4dF9kZXNjKCZjaGFuLT52Yyk7CisJaWYg KHZkKSB7CisJCXN3aXRjaCAoY2hhbi0+cmVxdWVzdCkgeworCQljYXNlIEVETUFfUkVRX05PTkU6 CisJCQlkZXNjID0gdmQyZHdfZWRtYV9kZXNjKHZkKTsKKwkJCWlmIChkZXNjLT5jaHVua3NfYWxs b2MpIHsKKwkJCQljaGFuLT5zdGF0dXMgPSBFRE1BX1NUX0JVU1k7CisJCQkJZHdfZWRtYV9zdGFy dF90cmFuc2ZlcihjaGFuKTsKKwkJCX0gZWxzZSB7CisJCQkJbGlzdF9kZWwoJnZkLT5ub2RlKTsK KwkJCQl2Y2hhbl9jb29raWVfY29tcGxldGUodmQpOworCQkJCWNoYW4tPnN0YXR1cyA9IEVETUFf U1RfSURMRTsKKwkJCX0KKwkJCWJyZWFrOworCQljYXNlIEVETUFfUkVRX1NUT1A6CisJCQlsaXN0 X2RlbCgmdmQtPm5vZGUpOworCQkJdmNoYW5fY29va2llX2NvbXBsZXRlKHZkKTsKKwkJCWNoYW4t PnJlcXVlc3QgPSBFRE1BX1JFUV9OT05FOworCQkJY2hhbi0+c3RhdHVzID0gRURNQV9TVF9JRExF OworCQkJYnJlYWs7CisJCWNhc2UgRURNQV9SRVFfUEFVU0U6CisJCQljaGFuLT5yZXF1ZXN0ID0g RURNQV9SRVFfTk9ORTsKKwkJCWNoYW4tPnN0YXR1cyA9IEVETUFfU1RfUEFVU0U7CisJCQlicmVh azsKKwkJZGVmYXVsdDoKKwkJCWJyZWFrOworCQl9CisJfQorCXNwaW5fdW5sb2NrX2lycXJlc3Rv cmUoJmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsKK30KKworc3RhdGljIHZvaWQgZHdfZWRtYV9hYm9y dF9pbnRlcnJ1cHQoc3RydWN0IGR3X2VkbWFfY2hhbiAqY2hhbikKK3sKKwlzdHJ1Y3QgdmlydF9k bWFfZGVzYyAqdmQ7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKworCWR3X2VkbWFfdjBfY29yZV9j bGVhcl9hYm9ydF9pbnQoY2hhbik7CisKKwlzcGluX2xvY2tfaXJxc2F2ZSgmY2hhbi0+dmMubG9j aywgZmxhZ3MpOworCXZkID0gdmNoYW5fbmV4dF9kZXNjKCZjaGFuLT52Yyk7CisJaWYgKHZkKSB7 CisJCWxpc3RfZGVsKCZ2ZC0+bm9kZSk7CisJCXZjaGFuX2Nvb2tpZV9jb21wbGV0ZSh2ZCk7CisJ fQorCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsKKwljaGFu LT5yZXF1ZXN0ID0gRURNQV9SRVFfTk9ORTsKKwljaGFuLT5zdGF0dXMgPSBFRE1BX1NUX0lETEU7 Cit9CisKK3N0YXRpYyBpcnFyZXR1cm5fdCBkd19lZG1hX2ludGVycnVwdChpbnQgaXJxLCB2b2lk ICpkYXRhLCBib29sIHdyaXRlKQoreworCXN0cnVjdCBkd19lZG1hX2lycSAqZHdfaXJxID0gZGF0 YTsKKwlzdHJ1Y3QgZHdfZWRtYSAqZHcgPSBkd19pcnEtPmR3OworCXVuc2lnbmVkIGxvbmcgdG90 YWwsIHBvcywgdmFsOworCXVuc2lnbmVkIGxvbmcgb2ZmOworCXUzMiBtYXNrOworCisJaWYgKHdy aXRlKSB7CisJCXRvdGFsID0gZHctPndyX2NoX2NudDsKKwkJb2ZmID0gMDsKKwkJbWFzayA9IGR3 X2lycS0+d3JfbWFzazsKKwl9IGVsc2UgeworCQl0b3RhbCA9IGR3LT5yZF9jaF9jbnQ7CisJCW9m ZiA9IGR3LT53cl9jaF9jbnQ7CisJCW1hc2sgPSBkd19pcnEtPnJkX21hc2s7CisJfQorCisJdmFs ID0gZHdfZWRtYV92MF9jb3JlX3N0YXR1c19kb25lX2ludChkdywgd3JpdGUgPworCQkJCQkJCSAg RURNQV9ESVJfV1JJVEUgOgorCQkJCQkJCSAgRURNQV9ESVJfUkVBRCk7CisJdmFsICY9IG1hc2s7 CisJZm9yX2VhY2hfc2V0X2JpdChwb3MsICZ2YWwsIHRvdGFsKSB7CisJCXN0cnVjdCBkd19lZG1h X2NoYW4gKmNoYW4gPSAmZHctPmNoYW5bcG9zICsgb2ZmXTsKKworCQlkd19lZG1hX2RvbmVfaW50 ZXJydXB0KGNoYW4pOworCX0KKworCXZhbCA9IGR3X2VkbWFfdjBfY29yZV9zdGF0dXNfYWJvcnRf aW50KGR3LCB3cml0ZSA/CisJCQkJCQkJICAgRURNQV9ESVJfV1JJVEUgOgorCQkJCQkJCSAgIEVE TUFfRElSX1JFQUQpOworCXZhbCAmPSBtYXNrOworCWZvcl9lYWNoX3NldF9iaXQocG9zLCAmdmFs LCB0b3RhbCkgeworCQlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuID0gJmR3LT5jaGFuW3BvcyAr IG9mZl07CisKKwkJZHdfZWRtYV9hYm9ydF9pbnRlcnJ1cHQoY2hhbik7CisJfQorCisJcmV0dXJu IElSUV9IQU5ETEVEOworfQorCitzdGF0aWMgaW5saW5lIGlycXJldHVybl90IGR3X2VkbWFfaW50 ZXJydXB0X3dyaXRlKGludCBpcnEsIHZvaWQgKmRhdGEpCit7CisJcmV0dXJuIGR3X2VkbWFfaW50 ZXJydXB0KGlycSwgZGF0YSwgdHJ1ZSk7Cit9CisKK3N0YXRpYyBpbmxpbmUgaXJxcmV0dXJuX3Qg ZHdfZWRtYV9pbnRlcnJ1cHRfcmVhZChpbnQgaXJxLCB2b2lkICpkYXRhKQoreworCXJldHVybiBk d19lZG1hX2ludGVycnVwdChpcnEsIGRhdGEsIGZhbHNlKTsKK30KKworc3RhdGljIGlycXJldHVy bl90IGR3X2VkbWFfaW50ZXJydXB0X2NvbW1vbihpbnQgaXJxLCB2b2lkICpkYXRhKQoreworCWR3 X2VkbWFfaW50ZXJydXB0KGlycSwgZGF0YSwgdHJ1ZSk7CisJZHdfZWRtYV9pbnRlcnJ1cHQoaXJx LCBkYXRhLCBmYWxzZSk7CisKKwlyZXR1cm4gSVJRX0hBTkRMRUQ7Cit9CisKK3N0YXRpYyBpbnQg ZHdfZWRtYV9hbGxvY19jaGFuX3Jlc291cmNlcyhzdHJ1Y3QgZG1hX2NoYW4gKmRjaGFuKQorewor CXN0cnVjdCBkd19lZG1hX2NoYW4gKmNoYW4gPSBkY2hhbjJkd19lZG1hX2NoYW4oZGNoYW4pOwor CisJaWYgKGNoYW4tPnN0YXR1cyAhPSBFRE1BX1NUX0lETEUpCisJCXJldHVybiAtRUJVU1k7CisK KwlkbWFfY29va2llX2luaXQoZGNoYW4pOworCisJcG1fcnVudGltZV9nZXQoY2hhbi0+Y2hpcC0+ ZGV2KTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgdm9pZCBkd19lZG1hX2ZyZWVfY2hhbl9y ZXNvdXJjZXMoc3RydWN0IGRtYV9jaGFuICpkY2hhbikKK3sKKwl1bnNpZ25lZCBsb25nIHRpbWVv dXQgPSBqaWZmaWVzICsgbXNlY3NfdG9famlmZmllcyg1MDAwKTsKKwlzdHJ1Y3QgZHdfZWRtYV9j aGFuICpjaGFuID0gZGNoYW4yZHdfZWRtYV9jaGFuKGRjaGFuKTsKKwlpbnQgcmV0OworCisJd2hp bGUgKHRpbWVfYmVmb3JlKGppZmZpZXMsIHRpbWVvdXQpKSB7CisJCXJldCA9IGR3X2VkbWFfZGV2 aWNlX3Rlcm1pbmF0ZV9hbGwoZGNoYW4pOworCQlpZiAoIXJldCkKKwkJCWJyZWFrOworCisJCWlm ICh0aW1lX2FmdGVyX2VxKGppZmZpZXMsIHRpbWVvdXQpKQorCQkJcmV0dXJuOworCisJCWNwdV9y ZWxheCgpOworCX07CisKKwlwbV9ydW50aW1lX3B1dChjaGFuLT5jaGlwLT5kZXYpOworfQorCitz dGF0aWMgaW50IGR3X2VkbWFfY2hhbm5lbF9zZXR1cChzdHJ1Y3QgZHdfZWRtYV9jaGlwICpjaGlw LCBib29sIHdyaXRlLAorCQkJCSB1MzIgd3JfYWxsb2MsIHUzMiByZF9hbGxvYykKK3sKKwlzdHJ1 Y3QgZHdfZWRtYV9yZWdpb24gKmR0X3JlZ2lvbjsKKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSBjaGlw LT5kZXY7CisJc3RydWN0IGR3X2VkbWEgKmR3ID0gY2hpcC0+ZHc7CisJc3RydWN0IGR3X2VkbWFf Y2hhbiAqY2hhbjsKKwlzaXplX3QgbGxfY2h1bmssIGR0X2NodW5rOworCXN0cnVjdCBkd19lZG1h X2lycSAqaXJxOworCXN0cnVjdCBkbWFfZGV2aWNlICpkbWE7CisJdTMyIGksIGosIGNudCwgY2hf Y250OworCXUzMiBhbGxvYywgb2ZmX2FsbG9jOworCWludCBlcnIgPSAwOworCXUzMiBwb3M7CisK KwljaF9jbnQgPSBkdy0+d3JfY2hfY250ICsgZHctPnJkX2NoX2NudDsKKwlsbF9jaHVuayA9IGR3 LT5sbF9yZWdpb24uc3o7CisJZHRfY2h1bmsgPSBkdy0+ZHRfcmVnaW9uLnN6OworCisJLyogQ2Fs Y3VsYXRlIGxpbmtlZCBsaXN0IGNodW5rIGZvciBlYWNoIGNoYW5uZWwgKi8KKwlsbF9jaHVuayAv PSByb3VuZHVwX3Bvd19vZl90d28oY2hfY250KTsKKworCS8qIENhbGN1bGF0ZSBsaW5rZWQgbGlz dCBjaHVuayBmb3IgZWFjaCBjaGFubmVsICovCisJZHRfY2h1bmsgLz0gcm91bmR1cF9wb3dfb2Zf dHdvKGNoX2NudCk7CisKKwlpZiAod3JpdGUpIHsKKwkJaSA9IDA7CisJCWNudCA9IGR3LT53cl9j aF9jbnQ7CisJCWRtYSA9ICZkdy0+d3JfZWRtYTsKKwkJYWxsb2MgPSB3cl9hbGxvYzsKKwkJb2Zm X2FsbG9jID0gMDsKKwl9IGVsc2UgeworCQlpID0gZHctPndyX2NoX2NudDsKKwkJY250ID0gZHct PnJkX2NoX2NudDsKKwkJZG1hID0gJmR3LT5yZF9lZG1hOworCQlhbGxvYyA9IHJkX2FsbG9jOwor CQlvZmZfYWxsb2MgPSB3cl9hbGxvYzsKKwl9CisKKwlJTklUX0xJU1RfSEVBRCgmZG1hLT5jaGFu bmVscyk7CisJZm9yIChqID0gMDsgKGFsbG9jIHx8IGR3LT5ucl9pcnFzID09IDEpICYmIGogPCBj bnQ7IGorKywgaSsrKSB7CisJCWNoYW4gPSAmZHctPmNoYW5baV07CisKKwkJZHRfcmVnaW9uID0g ZGV2bV9remFsbG9jKGRldiwgc2l6ZW9mKCpkdF9yZWdpb24pLCBHRlBfS0VSTkVMKTsKKwkJaWYg KCFkdF9yZWdpb24pCisJCQlyZXR1cm4gLUVOT01FTTsKKworCQljaGFuLT52Yy5jaGFuLnByaXZh dGUgPSBkdF9yZWdpb247CisKKwkJY2hhbi0+Y2hpcCA9IGNoaXA7CisJCWNoYW4tPmlkID0gajsK KwkJY2hhbi0+ZGlyID0gd3JpdGUgPyBFRE1BX0RJUl9XUklURSA6IEVETUFfRElSX1JFQUQ7CisJ CWNoYW4tPmNvbmZpZ3VyZWQgPSBmYWxzZTsKKwkJY2hhbi0+cmVxdWVzdCA9IEVETUFfUkVRX05P TkU7CisJCWNoYW4tPnN0YXR1cyA9IEVETUFfU1RfSURMRTsKKworCQljaGFuLT5sbF9vZmYgPSAo bGxfY2h1bmsgKiBpKTsKKwkJY2hhbi0+bGxfbWF4ID0gKGxsX2NodW5rIC8gRURNQV9MTF9TWikg LSAxOworCisJCWNoYW4tPmR0X29mZiA9IChkdF9jaHVuayAqIGkpOworCisJCWRldl92ZGJnKGRl diwgIkwuIExpc3Q6XHRDaGFubmVsICVzWyV1XSBvZmY9MHglLjhseCwgbWF4X2NudD0ldVxuIiwK KwkJCSB3cml0ZSA/ICJ3cml0ZSIgOiAicmVhZCIsIGosCisJCQkgY2hhbi0+bGxfb2ZmLCBjaGFu LT5sbF9tYXgpOworCisJCWlmIChkdy0+bnJfaXJxcyA9PSAxKQorCQkJcG9zID0gMDsKKwkJZWxz ZQorCQkJcG9zID0gb2ZmX2FsbG9jICsgKGogJSBhbGxvYyk7CisKKwkJaXJxID0gJmR3LT5pcnFb cG9zXTsKKworCQlpZiAod3JpdGUpCisJCQlpcnEtPndyX21hc2sgfD0gQklUKGopOworCQllbHNl CisJCQlpcnEtPnJkX21hc2sgfD0gQklUKGopOworCisJCWlycS0+ZHcgPSBkdzsKKwkJbWVtY3B5 KCZjaGFuLT5tc2ksICZpcnEtPm1zaSwgc2l6ZW9mKGNoYW4tPm1zaSkpOworCisJCWRldl92ZGJn KGRldiwgIk1TSTpcdFx0Q2hhbm5lbCAlc1sldV0gYWRkcj0weCUuOHglLjh4LCBkYXRhPTB4JS44 eFxuIiwKKwkJCSB3cml0ZSA/ICJ3cml0ZSIgOiAicmVhZCIsIGosCisJCQkgY2hhbi0+bXNpLmFk ZHJlc3NfaGksIGNoYW4tPm1zaS5hZGRyZXNzX2xvLAorCQkJIGNoYW4tPm1zaS5kYXRhKTsKKwor CQljaGFuLT52Yy5kZXNjX2ZyZWUgPSB2Y2hhbl9mcmVlX2Rlc2M7CisJCXZjaGFuX2luaXQoJmNo YW4tPnZjLCBkbWEpOworCisJCWR0X3JlZ2lvbi0+cGFkZHIgPSBkdy0+ZHRfcmVnaW9uLnBhZGRy ICsgY2hhbi0+ZHRfb2ZmOworCQlkdF9yZWdpb24tPnZhZGRyID0gZHctPmR0X3JlZ2lvbi52YWRk ciArIGNoYW4tPmR0X29mZjsKKwkJZHRfcmVnaW9uLT5zeiA9IGR0X2NodW5rOworCisJCWRldl92 ZGJnKGRldiwgIkRhdGE6XHRDaGFubmVsICVzWyV1XSBvZmY9MHglLjhseFxuIiwKKwkJCSB3cml0 ZSA/ICJ3cml0ZSIgOiAicmVhZCIsIGosIGNoYW4tPmR0X29mZik7CisKKwkJZHdfZWRtYV92MF9j b3JlX2RldmljZV9jb25maWcoY2hhbik7CisJfQorCisJLyogU2V0IERNQSBjaGFubmVsIGNhcGFi aWxpdGllcyAqLworCWRtYV9jYXBfemVybyhkbWEtPmNhcF9tYXNrKTsKKwlkbWFfY2FwX3NldChE TUFfU0xBVkUsIGRtYS0+Y2FwX21hc2spOworCWRtYV9jYXBfc2V0KERNQV9DWUNMSUMsIGRtYS0+ Y2FwX21hc2spOworCWRtYV9jYXBfc2V0KERNQV9QUklWQVRFLCBkbWEtPmNhcF9tYXNrKTsKKwlk bWEtPmRpcmVjdGlvbnMgPSBCSVQod3JpdGUgPyBETUFfREVWX1RPX01FTSA6IERNQV9NRU1fVE9f REVWKTsKKwlkbWEtPnNyY19hZGRyX3dpZHRocyA9IEJJVChETUFfU0xBVkVfQlVTV0lEVEhfNF9C WVRFUyk7CisJZG1hLT5kc3RfYWRkcl93aWR0aHMgPSBCSVQoRE1BX1NMQVZFX0JVU1dJRFRIXzRf QllURVMpOworCWRtYS0+cmVzaWR1ZV9ncmFudWxhcml0eSA9IERNQV9SRVNJRFVFX0dSQU5VTEFS SVRZX0RFU0NSSVBUT1I7CisJZG1hLT5jaGFuY250ID0gY250OworCisJLyogU2V0IERNQSBjaGFu bmVsIGNhbGxiYWNrcyAqLworCWRtYS0+ZGV2ID0gY2hpcC0+ZGV2OworCWRtYS0+ZGV2aWNlX2Fs bG9jX2NoYW5fcmVzb3VyY2VzID0gZHdfZWRtYV9hbGxvY19jaGFuX3Jlc291cmNlczsKKwlkbWEt PmRldmljZV9mcmVlX2NoYW5fcmVzb3VyY2VzID0gZHdfZWRtYV9mcmVlX2NoYW5fcmVzb3VyY2Vz OworCWRtYS0+ZGV2aWNlX2NvbmZpZyA9IGR3X2VkbWFfZGV2aWNlX2NvbmZpZzsKKwlkbWEtPmRl dmljZV9wYXVzZSA9IGR3X2VkbWFfZGV2aWNlX3BhdXNlOworCWRtYS0+ZGV2aWNlX3Jlc3VtZSA9 IGR3X2VkbWFfZGV2aWNlX3Jlc3VtZTsKKwlkbWEtPmRldmljZV90ZXJtaW5hdGVfYWxsID0gZHdf ZWRtYV9kZXZpY2VfdGVybWluYXRlX2FsbDsKKwlkbWEtPmRldmljZV9pc3N1ZV9wZW5kaW5nID0g ZHdfZWRtYV9kZXZpY2VfaXNzdWVfcGVuZGluZzsKKwlkbWEtPmRldmljZV90eF9zdGF0dXMgPSBk d19lZG1hX2RldmljZV90eF9zdGF0dXM7CisJZG1hLT5kZXZpY2VfcHJlcF9zbGF2ZV9zZyA9IGR3 X2VkbWFfZGV2aWNlX3ByZXBfc2xhdmVfc2c7CisJZG1hLT5kZXZpY2VfcHJlcF9kbWFfY3ljbGlj ID0gZHdfZWRtYV9kZXZpY2VfcHJlcF9kbWFfY3ljbGljOworCisJZG1hX3NldF9tYXhfc2VnX3Np emUoZG1hLT5kZXYsIFUzMl9NQVgpOworCisJLyogUmVnaXN0ZXIgRE1BIGRldmljZSAqLworCWVy ciA9IGRtYV9hc3luY19kZXZpY2VfcmVnaXN0ZXIoZG1hKTsKKworCXJldHVybiBlcnI7Cit9CisK K3N0YXRpYyBpbmxpbmUgdm9pZCBkd19lZG1hX2RlY19pcnFfYWxsb2MoaW50ICpucl9pcnFzLCB1 MzIgKmFsbG9jLCB1MTYgY250KQoreworCWlmICgqbnJfaXJxcyAmJiAqYWxsb2MgPCBjbnQpIHsK KwkJKCphbGxvYykrKzsKKwkJKCpucl9pcnFzKS0tOworCX0KK30KKworc3RhdGljIGlubGluZSB2 b2lkIGR3X2VkbWFfYWRkX2lycV9tYXNrKHUzMiAqbWFzaywgdTMyIGFsbG9jLCB1MTYgY250KQor eworCXdoaWxlICgqbWFzayAqIGFsbG9jIDwgY250KQorCQkoKm1hc2spKys7Cit9CisKK3N0YXRp YyBpbnQgZHdfZWRtYV9pcnFfcmVxdWVzdChzdHJ1Y3QgZHdfZWRtYV9jaGlwICpjaGlwLAorCQkJ ICAgICAgIHUzMiAqd3JfYWxsb2MsIHUzMiAqcmRfYWxsb2MpCit7CisJc3RydWN0IGRldmljZSAq ZGV2ID0gY2hpcC0+ZGV2OworCXN0cnVjdCBkd19lZG1hICpkdyA9IGNoaXAtPmR3OworCXUzMiB3 cl9tYXNrID0gMTsKKwl1MzIgcmRfbWFzayA9IDE7CisJaW50IGksIGVyciA9IDA7CisJdTMyIGNo X2NudDsKKworCWNoX2NudCA9IGR3LT53cl9jaF9jbnQgKyBkdy0+cmRfY2hfY250OworCisJaWYg KGR3LT5ucl9pcnFzIDwgMSkKKwkJcmV0dXJuIC1FSU5WQUw7CisKKwlpZiAoZHctPm5yX2lycXMg PT0gMSkgeworCQkvKiBDb21tb24gSVJRIHNoYXJlZCBhbW9uZyBhbGwgY2hhbm5lbHMgKi8KKwkJ ZXJyID0gcmVxdWVzdF9pcnEocGNpX2lycV92ZWN0b3IodG9fcGNpX2RldihkZXYpLCAwKSwKKwkJ CQkgIGR3X2VkbWFfaW50ZXJydXB0X2NvbW1vbiwKKwkJCQkgIElSUUZfU0hBUkVELCBkdy0+bmFt ZSwgJmR3LT5pcnFbMF0pOworCQlpZiAoZXJyKSB7CisJCQlkdy0+bnJfaXJxcyA9IDA7CisJCQly ZXR1cm4gZXJyOworCQl9CisKKwkJZ2V0X2NhY2hlZF9tc2lfbXNnKHBjaV9pcnFfdmVjdG9yKHRv X3BjaV9kZXYoZGV2KSwgMCksCisJCQkJICAgJmR3LT5pcnFbMF0ubXNpKTsKKwl9IGVsc2Ugewor CQkvKiBEaXN0cmlidXRlIElSUXMgZXF1YWxseSBhbW9uZyBhbGwgY2hhbm5lbHMgKi8KKwkJaW50 IHRtcCA9IGR3LT5ucl9pcnFzOworCisJCXdoaWxlICh0bXAgJiYgKCp3cl9hbGxvYyArICpyZF9h bGxvYykgPCBjaF9jbnQpIHsKKwkJCWR3X2VkbWFfZGVjX2lycV9hbGxvYygmdG1wLCB3cl9hbGxv YywgZHctPndyX2NoX2NudCk7CisJCQlkd19lZG1hX2RlY19pcnFfYWxsb2MoJnRtcCwgcmRfYWxs b2MsIGR3LT5yZF9jaF9jbnQpOworCQl9CisKKwkJZHdfZWRtYV9hZGRfaXJxX21hc2soJndyX21h c2ssICp3cl9hbGxvYywgZHctPndyX2NoX2NudCk7CisJCWR3X2VkbWFfYWRkX2lycV9tYXNrKCZy ZF9tYXNrLCAqcmRfYWxsb2MsIGR3LT5yZF9jaF9jbnQpOworCisJCWZvciAoaSA9IDA7IGkgPCAo KndyX2FsbG9jICsgKnJkX2FsbG9jKTsgaSsrKSB7CisJCQllcnIgPSByZXF1ZXN0X2lycShwY2lf aXJxX3ZlY3Rvcih0b19wY2lfZGV2KGRldiksIGkpLAorCQkJCQkgIGkgPCAqd3JfYWxsb2MgPwor CQkJCQkJZHdfZWRtYV9pbnRlcnJ1cHRfd3JpdGUgOgorCQkJCQkJZHdfZWRtYV9pbnRlcnJ1cHRf cmVhZCwKKwkJCQkJICBJUlFGX1NIQVJFRCwgZHctPm5hbWUsCisJCQkJCSAgJmR3LT5pcnFbaV0p OworCQkJaWYgKGVycikgeworCQkJCWR3LT5ucl9pcnFzID0gaTsKKwkJCQlyZXR1cm4gZXJyOwor CQkJfQorCisJCQlnZXRfY2FjaGVkX21zaV9tc2cocGNpX2lycV92ZWN0b3IodG9fcGNpX2Rldihk ZXYpLCBpKSwKKwkJCQkJICAgJmR3LT5pcnFbaV0ubXNpKTsKKwkJfQorCisJCWR3LT5ucl9pcnFz ID0gaTsKKwl9CisKKwlyZXR1cm4gZXJyOworfQorCitpbnQgZHdfZWRtYV9wcm9iZShzdHJ1Y3Qg ZHdfZWRtYV9jaGlwICpjaGlwKQoreworCXN0cnVjdCBkZXZpY2UgKmRldiA9IGNoaXAtPmRldjsK KwlzdHJ1Y3QgZHdfZWRtYSAqZHcgPSBjaGlwLT5kdzsKKwl1MzIgd3JfYWxsb2MgPSAwOworCXUz MiByZF9hbGxvYyA9IDA7CisJaW50IGksIGVycjsKKworCXJhd19zcGluX2xvY2tfaW5pdCgmZHct PmxvY2spOworCisJLyogRmluZCBvdXQgaG93IG1hbnkgd3JpdGUgY2hhbm5lbHMgYXJlIHN1cHBv cnRlZCBieSBoYXJkd2FyZSAqLworCWR3LT53cl9jaF9jbnQgPSBkd19lZG1hX3YwX2NvcmVfY2hf Y291bnQoZHcsIEVETUFfRElSX1dSSVRFKTsKKwlpZiAoIWR3LT53cl9jaF9jbnQpCisJCXJldHVy biAtRUlOVkFMOworCisJLyogRmluZCBvdXQgaG93IG1hbnkgcmVhZCBjaGFubmVscyBhcmUgc3Vw cG9ydGVkIGJ5IGhhcmR3YXJlICovCisJZHctPnJkX2NoX2NudCA9IGR3X2VkbWFfdjBfY29yZV9j aF9jb3VudChkdywgRURNQV9ESVJfUkVBRCk7CisJaWYgKCFkdy0+cmRfY2hfY250KQorCQlyZXR1 cm4gLUVJTlZBTDsKKworCWRldl92ZGJnKGRldiwgIkNoYW5uZWxzOlx0d3JpdGU9JWQsIHJlYWQ9 JWRcbiIsCisJCSBkdy0+d3JfY2hfY250LCBkdy0+cmRfY2hfY250KTsKKworCS8qIEFsbG9jYXRl IGNoYW5uZWxzICovCisJZHctPmNoYW4gPSBkZXZtX2tjYWxsb2MoZGV2LCBkdy0+d3JfY2hfY250 ICsgZHctPnJkX2NoX2NudCwKKwkJCQlzaXplb2YoKmR3LT5jaGFuKSwgR0ZQX0tFUk5FTCk7CisJ aWYgKCFkdy0+Y2hhbikKKwkJcmV0dXJuIC1FTk9NRU07CisKKwlzbnByaW50Zihkdy0+bmFtZSwg c2l6ZW9mKGR3LT5uYW1lKSwgImR3LWVkbWEtY29yZTolZCIsIGNoaXAtPmlkKTsKKworCS8qIERp c2FibGUgZURNQSwgb25seSB0byBlc3RhYmxpc2ggdGhlIGlkZWFsIGluaXRpYWwgY29uZGl0aW9u cyAqLworCWR3X2VkbWFfdjBfY29yZV9vZmYoZHcpOworCisJLyogUmVxdWVzdCBJUlFzICovCisJ ZXJyID0gZHdfZWRtYV9pcnFfcmVxdWVzdChjaGlwLCAmd3JfYWxsb2MsICZyZF9hbGxvYyk7CisJ aWYgKGVycikKKwkJcmV0dXJuIGVycjsKKworCS8qIFNldHVwIHdyaXRlIGNoYW5uZWxzICovCisJ ZXJyID0gZHdfZWRtYV9jaGFubmVsX3NldHVwKGNoaXAsIHRydWUsIHdyX2FsbG9jLCByZF9hbGxv Yyk7CisJaWYgKGVycikKKwkJZ290byBlcnJfaXJxX2ZyZWU7CisKKwkvKiBTZXR1cCByZWFkIGNo YW5uZWxzICovCisJZXJyID0gZHdfZWRtYV9jaGFubmVsX3NldHVwKGNoaXAsIGZhbHNlLCB3cl9h bGxvYywgcmRfYWxsb2MpOworCWlmIChlcnIpCisJCWdvdG8gZXJyX2lycV9mcmVlOworCisJLyog UG93ZXIgbWFuYWdlbWVudCAqLworCXBtX3J1bnRpbWVfZW5hYmxlKGRldik7CisKKwkvKiBUdXJu IGRlYnVnZnMgb24gKi8KKwllcnIgPSBkd19lZG1hX3YwX2NvcmVfZGVidWdmc19vbihjaGlwKTsK KwlpZiAoZXJyKQorCQlnb3RvIGVycl9wbV9kaXNhYmxlOworCisJcmV0dXJuIDA7CisKK2Vycl9w bV9kaXNhYmxlOgorCXBtX3J1bnRpbWVfZGlzYWJsZShkZXYpOworZXJyX2lycV9mcmVlOgorCWZv ciAoaSA9IChkdy0+bnJfaXJxcyAtIDEpOyBpID49IDA7IGktLSkKKwkJZnJlZV9pcnEocGNpX2ly cV92ZWN0b3IodG9fcGNpX2RldihkZXYpLCBpKSwgJmR3LT5pcnFbaV0pOworCisJZHctPm5yX2ly cXMgPSAwOworCisJcmV0dXJuIGVycjsKK30KK0VYUE9SVF9TWU1CT0xfR1BMKGR3X2VkbWFfcHJv YmUpOworCitpbnQgZHdfZWRtYV9yZW1vdmUoc3RydWN0IGR3X2VkbWFfY2hpcCAqY2hpcCkKK3sK KwlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuLCAqX2NoYW47CisJc3RydWN0IGRldmljZSAqZGV2 ID0gY2hpcC0+ZGV2OworCXN0cnVjdCBkd19lZG1hICpkdyA9IGNoaXAtPmR3OworCWludCBpOwor CisJLyogRGlzYWJsZSBlRE1BICovCisJZHdfZWRtYV92MF9jb3JlX29mZihkdyk7CisKKwkvKiBG cmVlIGlycXMgKi8KKwlmb3IgKGkgPSAoZHctPm5yX2lycXMgLSAxKTsgaSA+PSAwOyBpLS0pCisJ CWZyZWVfaXJxKHBjaV9pcnFfdmVjdG9yKHRvX3BjaV9kZXYoZGV2KSwgaSksICZkdy0+aXJxW2ld KTsKKworCS8qIFBvd2VyIG1hbmFnZW1lbnQgKi8KKwlwbV9ydW50aW1lX2Rpc2FibGUoZGV2KTsK KworCWxpc3RfZm9yX2VhY2hfZW50cnlfc2FmZShjaGFuLCBfY2hhbiwgJmR3LT53cl9lZG1hLmNo YW5uZWxzLAorCQkJCSB2Yy5jaGFuLmRldmljZV9ub2RlKSB7CisJCWxpc3RfZGVsKCZjaGFuLT52 Yy5jaGFuLmRldmljZV9ub2RlKTsKKwkJdGFza2xldF9raWxsKCZjaGFuLT52Yy50YXNrKTsKKwl9 CisKKwlsaXN0X2Zvcl9lYWNoX2VudHJ5X3NhZmUoY2hhbiwgX2NoYW4sICZkdy0+cmRfZWRtYS5j aGFubmVscywKKwkJCQkgdmMuY2hhbi5kZXZpY2Vfbm9kZSkgeworCQlsaXN0X2RlbCgmY2hhbi0+ dmMuY2hhbi5kZXZpY2Vfbm9kZSk7CisJCXRhc2tsZXRfa2lsbCgmY2hhbi0+dmMudGFzayk7CisJ fQorCisJLyogRGVyZWdpc3RlciBlRE1BIGRldmljZSAqLworCWRtYV9hc3luY19kZXZpY2VfdW5y ZWdpc3RlcigmZHctPndyX2VkbWEpOworCWRtYV9hc3luY19kZXZpY2VfdW5yZWdpc3RlcigmZHct PnJkX2VkbWEpOworCisJLyogVHVybiBkZWJ1Z2ZzIG9mZiAqLworCWR3X2VkbWFfdjBfY29yZV9k ZWJ1Z2ZzX29mZigpOworCisJcmV0dXJuIDA7Cit9CitFWFBPUlRfU1lNQk9MX0dQTChkd19lZG1h X3JlbW92ZSk7CisKK01PRFVMRV9MSUNFTlNFKCJHUEwgdjIiKTsKK01PRFVMRV9ERVNDUklQVElP TigiU3lub3BzeXMgRGVzaWduV2FyZSBlRE1BIGNvbnRyb2xsZXIgY29yZSBkcml2ZXIiKTsKK01P RFVMRV9BVVRIT1IoIkd1c3Rhdm8gUGltZW50ZWwgPGd1c3Rhdm8ucGltZW50ZWxAc3lub3BzeXMu Y29tPiIpOwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9kbWEvZHctZWRtYS9kdy1lZG1hLWNvcmUuaCBi L2RyaXZlcnMvZG1hL2R3LWVkbWEvZHctZWRtYS1jb3JlLmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQK aW5kZXggMDAwMDAwMC4uOGEzYTBhNAotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZlcnMvZG1hL2R3 LWVkbWEvZHctZWRtYS1jb3JlLmgKQEAgLTAsMCArMSwxNjUgQEAKKy8qIFNQRFgtTGljZW5zZS1J ZGVudGlmaWVyOiBHUEwtMi4wICovCisvKgorICogQ29weXJpZ2h0IChjKSAyMDE4LTIwMTkgU3lu b3BzeXMsIEluYy4gYW5kL29yIGl0cyBhZmZpbGlhdGVzLgorICogU3lub3BzeXMgRGVzaWduV2Fy ZSBlRE1BIGNvcmUgZHJpdmVyCisgKgorICogQXV0aG9yOiBHdXN0YXZvIFBpbWVudGVsIDxndXN0 YXZvLnBpbWVudGVsQHN5bm9wc3lzLmNvbT4KKyAqLworCisjaWZuZGVmIF9EV19FRE1BX0NPUkVf SAorI2RlZmluZSBfRFdfRURNQV9DT1JFX0gKKworI2luY2x1ZGUgPGxpbnV4L21zaS5oPgorI2lu Y2x1ZGUgPGxpbnV4L2RtYS9lZG1hLmg+CisKKyNpbmNsdWRlICIuLi92aXJ0LWRtYS5oIgorCisj ZGVmaW5lIEVETUFfTExfU1oJCQkJCTI0CisKK2VudW0gZHdfZWRtYV9kaXIgeworCUVETUFfRElS X1dSSVRFID0gMCwKKwlFRE1BX0RJUl9SRUFECit9OworCitlbnVtIGR3X2VkbWFfbW9kZSB7CisJ RURNQV9NT0RFX0xFR0FDWSA9IDAsCisJRURNQV9NT0RFX1VOUk9MTAorfTsKKworZW51bSBkd19l ZG1hX3JlcXVlc3QgeworCUVETUFfUkVRX05PTkUgPSAwLAorCUVETUFfUkVRX1NUT1AsCisJRURN QV9SRVFfUEFVU0UKK307CisKK2VudW0gZHdfZWRtYV9zdGF0dXMgeworCUVETUFfU1RfSURMRSA9 IDAsCisJRURNQV9TVF9QQVVTRSwKKwlFRE1BX1NUX0JVU1kKK307CisKK3N0cnVjdCBkd19lZG1h X2NoYW47CitzdHJ1Y3QgZHdfZWRtYV9jaHVuazsKKworc3RydWN0IGR3X2VkbWFfYnVyc3Qgewor CXN0cnVjdCBsaXN0X2hlYWQJCWxpc3Q7CisJdTY0CQkJCXNhcjsKKwl1NjQJCQkJZGFyOworCXUz MgkJCQlzejsKK307CisKK3N0cnVjdCBkd19lZG1hX3JlZ2lvbiB7CisJcGh5c19hZGRyX3QJCQlw YWRkcjsKKwlkbWFfYWRkcl90CQkJdmFkZHI7CisJc2l6ZV90CQkJCXN6OworfTsKKworc3RydWN0 IGR3X2VkbWFfY2h1bmsgeworCXN0cnVjdCBsaXN0X2hlYWQJCWxpc3Q7CisJc3RydWN0IGR3X2Vk bWFfY2hhbgkJKmNoYW47CisJc3RydWN0IGR3X2VkbWFfYnVyc3QJCSpidXJzdDsKKworCXUzMgkJ CQlidXJzdHNfYWxsb2M7CisKKwl1OAkJCQljYjsKKwlzdHJ1Y3QgZHdfZWRtYV9yZWdpb24JCWxs X3JlZ2lvbjsJLyogTGlua2VkIGxpc3QgKi8KK307CisKK3N0cnVjdCBkd19lZG1hX2Rlc2Mgewor CXN0cnVjdCB2aXJ0X2RtYV9kZXNjCQl2ZDsKKwlzdHJ1Y3QgZHdfZWRtYV9jaGFuCQkqY2hhbjsK KwlzdHJ1Y3QgZHdfZWRtYV9jaHVuawkJKmNodW5rOworCisJdTMyCQkJCWNodW5rc19hbGxvYzsK KworCXUzMgkJCQlhbGxvY19zejsKKwl1MzIJCQkJeGZlcl9zejsKK307CisKK3N0cnVjdCBkd19l ZG1hX2NoYW4geworCXN0cnVjdCB2aXJ0X2RtYV9jaGFuCQl2YzsKKwlzdHJ1Y3QgZHdfZWRtYV9j aGlwCQkqY2hpcDsKKwlpbnQJCQkJaWQ7CisJZW51bSBkd19lZG1hX2RpcgkJZGlyOworCisJb2Zm X3QJCQkJbGxfb2ZmOworCXUzMgkJCQlsbF9tYXg7CisKKwlvZmZfdAkJCQlkdF9vZmY7CisKKwlz dHJ1Y3QgbXNpX21zZwkJCW1zaTsKKworCWVudW0gZHdfZWRtYV9yZXF1ZXN0CQlyZXF1ZXN0Owor CWVudW0gZHdfZWRtYV9zdGF0dXMJCXN0YXR1czsKKwl1OAkJCQljb25maWd1cmVkOworCisJc3Ry dWN0IGRtYV9zbGF2ZV9jb25maWcJCWNvbmZpZzsKK307CisKK3N0cnVjdCBkd19lZG1hX2lycSB7 CisJc3RydWN0IG1zaV9tc2cgICAgICAgICAgICAgICAgICBtc2k7CisJdTMyCQkJCXdyX21hc2s7 CisJdTMyCQkJCXJkX21hc2s7CisJc3RydWN0IGR3X2VkbWEJCQkqZHc7Cit9OworCitzdHJ1Y3Qg ZHdfZWRtYSB7CisJY2hhcgkJCQluYW1lWzIwXTsKKworCXN0cnVjdCBkbWFfZGV2aWNlCQl3cl9l ZG1hOworCXUxNgkJCQl3cl9jaF9jbnQ7CisKKwlzdHJ1Y3QgZG1hX2RldmljZQkJcmRfZWRtYTsK Kwl1MTYJCQkJcmRfY2hfY250OworCisJc3RydWN0IGR3X2VkbWFfcmVnaW9uCQlyZ19yZWdpb247 CS8qIFJlZ2lzdGVycyAqLworCXN0cnVjdCBkd19lZG1hX3JlZ2lvbgkJbGxfcmVnaW9uOwkvKiBM aW5rZWQgbGlzdCAqLworCXN0cnVjdCBkd19lZG1hX3JlZ2lvbgkJZHRfcmVnaW9uOwkvKiBEYXRh ICovCisKKwlzdHJ1Y3QgZHdfZWRtYV9pcnEJCSppcnE7CisJaW50CQkJCW5yX2lycXM7CisKKwl1 MzIJCQkJdmVyc2lvbjsKKwllbnVtIGR3X2VkbWFfbW9kZQkJbW9kZTsKKworCXN0cnVjdCBkd19l ZG1hX2NoYW4JCSpjaGFuOworCWNvbnN0IHN0cnVjdCBkd19lZG1hX2NvcmVfb3BzCSpvcHM7CisK KwlyYXdfc3BpbmxvY2tfdAkJCWxvY2s7CQkvKiBPbmx5IGZvciBsZWdhY3kgKi8KK307CisKK3N0 cnVjdCBkd19lZG1hX3NnIHsKKwlzdHJ1Y3Qgc2NhdHRlcmxpc3QJCSpzZ2w7CisJdW5zaWduZWQg aW50CQkJbGVuOworfTsKKworc3RydWN0IGR3X2VkbWFfY3ljbGljIHsKKwlkbWFfYWRkcl90CQkJ cGFkZHI7CisJc2l6ZV90CQkJCWxlbjsKKwlzaXplX3QJCQkJY250OworfTsKKworc3RydWN0IGR3 X2VkbWFfdHJhbnNmZXIgeworCXN0cnVjdCBkbWFfY2hhbgkJCSpkY2hhbjsKKwl1bmlvbiBYZmVy IHsKKwkJc3RydWN0IGR3X2VkbWFfc2cJc2c7CisJCXN0cnVjdCBkd19lZG1hX2N5Y2xpYwljeWNs aWM7CisJfSB4ZmVyOworCWVudW0gZG1hX3RyYW5zZmVyX2RpcmVjdGlvbglkaXJlY3Rpb247CisJ dW5zaWduZWQgbG9uZwkJCWZsYWdzOworCWJvb2wJCQkJY3ljbGljOworfTsKKworc3RhdGljIGlu bGluZQorc3RydWN0IGR3X2VkbWFfY2hhbiAqdmMyZHdfZWRtYV9jaGFuKHN0cnVjdCB2aXJ0X2Rt YV9jaGFuICp2YykKK3sKKwlyZXR1cm4gY29udGFpbmVyX29mKHZjLCBzdHJ1Y3QgZHdfZWRtYV9j aGFuLCB2Yyk7Cit9CisKK3N0YXRpYyBpbmxpbmUKK3N0cnVjdCBkd19lZG1hX2NoYW4gKmRjaGFu MmR3X2VkbWFfY2hhbihzdHJ1Y3QgZG1hX2NoYW4gKmRjaGFuKQoreworCXJldHVybiB2YzJkd19l ZG1hX2NoYW4odG9fdmlydF9jaGFuKGRjaGFuKSk7Cit9CisKKyNlbmRpZiAvKiBfRFdfRURNQV9D T1JFX0ggKi8KZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvZG1hL2VkbWEuaCBiL2luY2x1ZGUv bGludXgvZG1hL2VkbWEuaApuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi5jYWI2 ZTE4Ci0tLSAvZGV2L251bGwKKysrIGIvaW5jbHVkZS9saW51eC9kbWEvZWRtYS5oCkBAIC0wLDAg KzEsNDcgQEAKKy8qIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wICovCisvKgorICog Q29weXJpZ2h0IChjKSAyMDE4LTIwMTkgU3lub3BzeXMsIEluYy4gYW5kL29yIGl0cyBhZmZpbGlh dGVzLgorICogU3lub3BzeXMgRGVzaWduV2FyZSBlRE1BIGNvcmUgZHJpdmVyCisgKgorICogQXV0 aG9yOiBHdXN0YXZvIFBpbWVudGVsIDxndXN0YXZvLnBpbWVudGVsQHN5bm9wc3lzLmNvbT4KKyAq LworCisjaWZuZGVmIF9EV19FRE1BX0gKKyNkZWZpbmUgX0RXX0VETUFfSAorCisjaW5jbHVkZSA8 bGludXgvZGV2aWNlLmg+CisjaW5jbHVkZSA8bGludXgvZG1hZW5naW5lLmg+CisKK3N0cnVjdCBk d19lZG1hOworCisvKioKKyAqIHN0cnVjdCBkd19lZG1hX2NoaXAgLSByZXByZXNlbnRhdGlvbiBv ZiBEZXNpZ25XYXJlIGVETUEgY29udHJvbGxlciBoYXJkd2FyZQorICogQGRldjoJCSBzdHJ1Y3Qg ZGV2aWNlIG9mIHRoZSBlRE1BIGNvbnRyb2xsZXIKKyAqIEBpZDoJCQkgaW5zdGFuY2UgSUQKKyAq IEBpcnE6CQkgaXJxIGxpbmUKKyAqIEBkdzoJCQkgc3RydWN0IGR3X2VkbWEgdGhhdCBpcyBmaWxl ZCBieSBkd19lZG1hX3Byb2JlKCkKKyAqLworc3RydWN0IGR3X2VkbWFfY2hpcCB7CisJc3RydWN0 IGRldmljZQkJKmRldjsKKwlpbnQJCQlpZDsKKwlpbnQJCQlpcnE7CisJc3RydWN0IGR3X2VkbWEJ CSpkdzsKK307CisKKy8qIEV4cG9ydCB0byB0aGUgcGxhdGZvcm0gZHJpdmVycyAqLworI2lmIElT X0VOQUJMRUQoQ09ORklHX0RXX0VETUEpCitpbnQgZHdfZWRtYV9wcm9iZShzdHJ1Y3QgZHdfZWRt YV9jaGlwICpjaGlwKTsKK2ludCBkd19lZG1hX3JlbW92ZShzdHJ1Y3QgZHdfZWRtYV9jaGlwICpj aGlwKTsKKyNlbHNlCitzdGF0aWMgaW5saW5lIGludCBkd19lZG1hX3Byb2JlKHN0cnVjdCBkd19l ZG1hX2NoaXAgKmNoaXApCit7CisJcmV0dXJuIC1FTk9ERVY7Cit9CisKK3N0YXRpYyBpbmxpbmUg aW50IGR3X2VkbWFfcmVtb3ZlKHN0cnVjdCBkd19lZG1hX2NoaXAgKmNoaXApCit7CisJcmV0dXJu IDA7Cit9CisjZW5kaWYgLyogQ09ORklHX0RXX0VETUEgKi8KKworI2VuZGlmIC8qIF9EV19FRE1B X0ggKi8K 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=unavailable 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 A74E0C282E1 for ; Tue, 23 Apr 2019 18:30:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 653DB217D9 for ; Tue, 23 Apr 2019 18:30:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=synopsys.com header.i=@synopsys.com header.b="KFEhbnfJ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726181AbfDWSa1 (ORCPT ); Tue, 23 Apr 2019 14:30:27 -0400 Received: from dc2-smtprelay2.synopsys.com ([198.182.61.142]:60420 "EHLO smtprelay-out1.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726136AbfDWSa0 (ORCPT ); Tue, 23 Apr 2019 14:30:26 -0400 Received: from mailhost.synopsys.com (dc2-mailhost2.synopsys.com [10.12.135.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by smtprelay-out1.synopsys.com (Postfix) with ESMTPS id 86314C0B12; Tue, 23 Apr 2019 18:30:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1556044224; bh=5ucPZ2Vmwv/w6xssI35vG3bXVA//9941qXlSBu60J+E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:In-Reply-To: References:From; b=KFEhbnfJBgbqqKEVplwbNIY0/MU2ZIsY5oBTUvfJ+E8tv3g3n3FNqC4/vCo4+I5LN hCm3ihJzsABtN6fMmWAcENryhjBmmScB5/jrWOIADGDrPuO0Hl5+Mamq22zzaKkFso pLBBV4yBdYwDvAIxFiza+AcyNj9p8ZqX6vDR49aIRcnumEf1M5KecaUNHSUKIeBPwp plAbUWbJ00DmxvWYf2xtX6lCvyBgmuZxzRLwCtuxp2rTH3ZMYyQ+v2iUAmoACTb7hJ xVTB8YXXZthIpoGDFkh8kbJ4PBosC+R9miiFWK4wAk0rm3fyf/CCsiht6MLhnTuALP /pnPDxIK74jpQ== Received: from de02.synopsys.com (de02.internal.synopsys.com [10.225.17.21]) by mailhost.synopsys.com (Postfix) with ESMTP id D37F6A0091; Tue, 23 Apr 2019 18:30:24 +0000 (UTC) Received: from de02dwia024.internal.synopsys.com (de02dwia024.internal.synopsys.com [10.225.19.81]) by de02.synopsys.com (Postfix) with ESMTP id 920C43F824; Tue, 23 Apr 2019 20:30:23 +0200 (CEST) From: Gustavo Pimentel To: linux-pci@vger.kernel.org, dmaengine@vger.kernel.org Cc: Gustavo Pimentel , Vinod Koul , Dan Williams , Andy Shevchenko , Russell King , Joao Pinto Subject: [RFC v6 1/6] dmaengine: Add Synopsys eDMA IP core driver Date: Tue, 23 Apr 2019 20:30:08 +0200 Message-Id: <0e877ac0115d37e466ac234f47c51cb1cae7f292.1556043127.git.gustavo.pimentel@synopsys.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: References: In-Reply-To: References: Sender: dmaengine-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dmaengine@vger.kernel.org Content-Type: text/plain; charset="UTF-8" Message-ID: <20190423183008.KUpoSRqLcdasXuRxoNjEIYBOLymz87Z_RzX72ObyYm4@z> Add Synopsys PCIe Endpoint eDMA IP core driver to kernel. This IP is generally distributed with Synopsys PCIe Endpoint IP (depends of the use and licensing agreement). This core driver, initializes and configures the eDMA IP using vma-helpers functions and dma-engine subsystem. 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. In order to transfer data from point A to B as fast as possible this IP requires a dedicated memory space containing linked list of elements. All elements of this linked list are continuous and each one describes a data transfer (source and destination addresses, length and a control variable). For the sake of simplicity, lets assume a memory space for channel write 0 which allows about 42 elements. +---------+ | Desc #0 |-+ +---------+ | V +----------+ | Chunk #0 |-+ | CB = 1 | | +----------+ +-----+ +-----------+ +-----+ +----------+ +->| Burst #0 |->| ... |->| Burst #41 |->| llp | | +----------+ +-----+ +-----------+ +-----+ V +----------+ | Chunk #1 |-+ | CB = 0 | | +-----------+ +-----+ +-----------+ +-----+ +----------+ +->| Burst #42 |->| ... |->| Burst #83 |->| llp | | +-----------+ +-----+ +-----------+ +-----+ V +----------+ | Chunk #2 |-+ | CB = 1 | | +-----------+ +-----+ +------------+ +-----+ +----------+ +->| Burst #84 |->| ... |->| Burst #125 |->| llp | | +-----------+ +-----+ +------------+ +-----+ V +----------+ | Chunk #3 |-+ | CB = 0 | | +------------+ +-----+ +------------+ +-----+ +----------+ +->| Burst #126 |->| ... |->| Burst #129 |->| llp | +------------+ +-----+ +------------+ +-----+ Legend: - Linked list, also know as Chunk - Linked list element*, also know as Burst *CB*, also know as Change Bit, it's a control bit (and typically is toggled) that allows to easily identify and differentiate between the current linked list and the previous or the next one. - LLP, is a special element that indicates the end of the linked list element stream also informs that the next CB should be toggle On every last Burst of the Chunk (Burst #41, Burst #83, Burst #125 or even Burst #129) is set some flags on their control variable (RIE and LIE bits) that will trigger the send of "done" interruption. On the interruptions callback, is decided whether to recycle the linked list memory space by writing a new set of Bursts elements (if still exists Chunks to transfer) or is considered completed (if there is no Chunks available to transfer). On scatter-gather transfer mode, the client will submit a scatter-gather list of n (on this case 130) elements, that will be divide in multiple Chunks, each Chunk will have (on this case 42) a limited number of Bursts and after transferring all Bursts, an interrupt will be triggered, which will allow to recycle the all linked list dedicated memory again with the new information relative to the next Chunk and respective Burst associated and repeat the whole cycle again. On cyclic transfer mode, the client will submit a buffer pointer, length of it and number of repetitions, in this case each burst will correspond directly to each repetition. Each Burst can describes a data transfer from point A(source) to point B(destination) with a length that can be from 1 byte up to 4 GB. Since dedicated the memory space where the linked list will reside is limited, the whole n burst elements will be organized in several Chunks, that will be used later to recycle the dedicated memory space to initiate a new sequence of data transfers. The whole transfer is considered has completed when it was transferred all bursts. Currently this IP has a set well-known register map, which includes support for legacy and unroll modes. Legacy mode is version of this register map that has multiplexer register that allows to switch registers between all write and read channels and the unroll modes repeats all write and read channels registers with an offset between them. This register map is called v0. The IP team is creating a new register map more suitable to the latest PCIe features, that very likely will change the map register, which this version will be called v1. As soon as this new version is released by the IP team the support for this version in be included on this driver. This patch has a direct dependency of the patch ("[RFC 2/7] dmaengine: Add Synopsys eDMA IP version 0 support"). According to the logic, patches 1, 2 and 3 should be squashed into 1 unique patch, but for the sake of simplicity of review, it was divided in this 3 patches files. Signed-off-by: Gustavo Pimentel Cc: Vinod Koul Cc: Dan Williams Cc: Andy Shevchenko Cc: Russell King Cc: Joao Pinto --- 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() RFC v2->RFC v3: - Add driver parameter to disable msix feature - Fix printk variable of phys_addr_t type - Fix printk variable of __iomem type - Fix printk variable of size_t type - Add comments or improve existing ones - Add possibility to work with multiple IRQs feature - Fix source and destination addresses - Add define to magic numbers - Add DMA cyclic transfer feature - Rebase to v5.0-rc1 RFC v3->RFC v4: - Remove unnecessary dev_info() calls - Add multiple IRQ automatic adaption feature - Reorder variables declaration in reverse tree order on several functions - Add return check of dw_edma_alloc_burst() in dw_edma_alloc_chunk() - Add return check of dw_edma_alloc_chunk() in dw_edma_alloc_desc() - Remove pm_runtime_get_sync() call in probe() - Fix dma_cyclic() buffer address - Replace devm_*_irq() by *_irq() and recode accordingly - Fix license header - Replace kvzalloc() by kzalloc() and kvfree() by kfree() - Move ops->device_config callback from config() to probe() - Remove restriction to perform operation only in IDLE state on dw_edma_device_config(), dw_edma_device_prep_slave_sg(), dw_edma_device_prep_dma_cyclic() - Recode and simplify slave_sg() and dma_cyclic() - Recode and simplify interrupts and channel setup - Recode dw_edma_device_tx_status() - Move get_cached_msi_msg() to here - Code rewrite to use direct dw-edma-v0-core functions instead of callbacks RFC v4->RFC v5: - Patch resended, forgot to replace of '___' by '---' and to remove duplicate signed-off RFC v5->RFC v6: - Add author on file header - Remove debug prints - Code rewrite following Andy's suggestations 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 | 919 +++++++++++++++++++++++++++++++++++++ drivers/dma/dw-edma/dw-edma-core.h | 165 +++++++ include/linux/dma/edma.h | 47 ++ 7 files changed, 1147 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 0b1dfb5..58b78d2 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -665,6 +665,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 6126e1c..5bddf6f 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..54cd531 --- /dev/null +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -0,0 +1,919 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates. + * Synopsys DesignWare eDMA core driver + * + * Author: Gustavo Pimentel + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dw-edma-core.h" +#include "../dmaengine.h" +#include "../virt-dma.h" + +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 +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_burst *burst; + + burst = kzalloc(sizeof(*burst), GFP_KERNEL); + if (unlikely(!burst)) + return NULL; + + INIT_LIST_HEAD(&burst->list); + if (chunk->burst) { + /* Create and add new element into the linked list */ + chunk->bursts_alloc++; + list_add_tail(&burst->list, &chunk->burst->list); + } else { + /* List head */ + chunk->bursts_alloc = 0; + chunk->burst = burst; + } + + 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_KERNEL); + if (unlikely(!chunk)) + return NULL; + + INIT_LIST_HEAD(&chunk->list); + chunk->chan = chan; + chunk->cb = !(desc->chunks_alloc % 2); + chunk->ll_region.paddr = dw->ll_region.paddr + chan->ll_off; + chunk->ll_region.vaddr = dw->ll_region.vaddr + chan->ll_off; + + if (desc->chunk) { + /* Create and add new element into the linked list */ + desc->chunks_alloc++; + list_add_tail(&chunk->list, &desc->chunk->list); + if (!dw_edma_alloc_burst(chunk)) { + kfree(chunk); + return NULL; + } + } else { + /* List head */ + chunk->burst = NULL; + desc->chunks_alloc = 0; + desc->chunk = chunk; + } + + return chunk; +} + +static struct dw_edma_desc *dw_edma_alloc_desc(struct dw_edma_chan *chan) +{ + struct dw_edma_desc *desc; + + desc = kzalloc(sizeof(*desc), GFP_KERNEL); + if (unlikely(!desc)) + return NULL; + + desc->chan = chan; + if (!dw_edma_alloc_chunk(desc)) { + kfree(desc); + return NULL; + } + + return desc; +} + +static void dw_edma_free_burst(struct dw_edma_chunk *chunk) +{ + struct dw_edma_burst *child, *_next; + + /* 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_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); + 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) +{ + dw_edma_free_chunk(desc); + kfree(desc); +} + +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 dw_edma_chunk *child; + struct dw_edma_desc *desc; + struct virt_dma_desc *vd; + + vd = vchan_next_desc(&chan->vc); + if (!vd) + return; + + desc = vd2dw_edma_desc(vd); + if (!desc) + return; + + child = list_first_entry_or_null(&desc->chunk->list, + struct dw_edma_chunk, list); + if (!child) + return; + + dw_edma_v0_core_start(child, !desc->xfer_sz); + desc->xfer_sz += child->ll_region.sz; + dw_edma_free_burst(child); + list_del(&child->list); + kfree(child); + desc->chunks_alloc--; +} + +static int dw_edma_device_config(struct dma_chan *dchan, + struct dma_slave_config *config) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + + memcpy(&chan->config, config, sizeof(*config)); + chan->configured = true; + + return 0; +} + +static int dw_edma_device_pause(struct dma_chan *dchan) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + int err = 0; + + if (!chan->configured) + err = -EPERM; + else if (chan->status != EDMA_ST_BUSY) + err = -EPERM; + else if (chan->request != EDMA_REQ_NONE) + err = -EPERM; + else + chan->request = EDMA_REQ_PAUSE; + + return err; +} + +static int dw_edma_device_resume(struct dma_chan *dchan) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + int err = 0; + + if (!chan->configured) { + err = -EPERM; + } else if (chan->status != EDMA_ST_PAUSE) { + err = -EPERM; + } else if (chan->request != EDMA_REQ_NONE) { + err = -EPERM; + } else { + chan->status = EDMA_ST_BUSY; + dw_edma_start_transfer(chan); + } + + return err; +} + +static int dw_edma_device_terminate_all(struct dma_chan *dchan) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + int err = 0; + LIST_HEAD(head); + + if (!chan->configured) { + /* Do nothing */ + } else if (chan->status == EDMA_ST_PAUSE) { + chan->status = EDMA_ST_IDLE; + chan->configured = false; + } else if (chan->status == EDMA_ST_IDLE) { + chan->configured = false; + } else if (dw_edma_v0_core_ch_status(chan) == DMA_COMPLETE) { + /* + * The channel is in a false BUSY state, probably didn't + * receive or lost an interrupt + */ + chan->status = EDMA_ST_IDLE; + chan->configured = false; + } else if (chan->request > EDMA_REQ_PAUSE) { + err = -EPERM; + } else { + chan->request = EDMA_REQ_STOP; + } + + 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)) { + 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); + struct dw_edma_desc *desc; + struct virt_dma_desc *vd; + unsigned long flags; + enum dma_status ret; + u32 residue = 0; + + ret = dma_cookie_status(dchan, cookie, txstate); + if (ret == DMA_COMPLETE) + return ret; + + if (ret == DMA_IN_PROGRESS && chan->status == EDMA_ST_PAUSE) + ret = DMA_PAUSED; + + if (!txstate) + goto ret_residue; + + spin_lock_irqsave(&chan->vc.lock, flags); + vd = vchan_find_desc(&chan->vc, cookie); + if (vd) { + desc = vd2dw_edma_desc(vd); + if (desc) + residue = desc->alloc_sz - desc->xfer_sz; + } + spin_unlock_irqrestore(&chan->vc.lock, flags); + +ret_residue: + dma_set_residue(txstate, residue); + + return ret; +} + +static struct dma_async_tx_descriptor * +dw_edma_device_transfer(struct dw_edma_transfer *xfer) +{ + struct dw_edma_chan *chan = dchan2dw_edma_chan(xfer->dchan); + enum dma_transfer_direction direction = xfer->direction; + phys_addr_t src_addr, dst_addr; + struct scatterlist *sg = NULL; + struct dw_edma_chunk *chunk; + struct dw_edma_burst *burst; + struct dw_edma_desc *desc; + u32 cnt; + int i; + + if ((direction == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_WRITE) || + (direction == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_READ)) + return NULL; + + if (xfer->cyclic) { + if (!xfer->xfer.cyclic.len || !xfer->xfer.cyclic.cnt) + return NULL; + } else { + if (xfer->xfer.sg.len < 1) + return NULL; + } + + if (!chan->configured) + return NULL; + + desc = dw_edma_alloc_desc(chan); + if (unlikely(!desc)) + goto err_alloc; + + chunk = dw_edma_alloc_chunk(desc); + if (unlikely(!chunk)) + goto err_alloc; + + src_addr = chan->config.src_addr; + dst_addr = chan->config.dst_addr; + + if (xfer->cyclic) { + cnt = xfer->xfer.cyclic.cnt; + } else { + cnt = xfer->xfer.sg.len; + sg = xfer->xfer.sg.sgl; + } + + for (i = 0; i < cnt; i++) { + if (!xfer->cyclic && !sg) + break; + + 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 (xfer->cyclic) + burst->sz = xfer->xfer.cyclic.len; + else + burst->sz = sg_dma_len(sg); + + chunk->ll_region.sz += burst->sz; + desc->alloc_sz += burst->sz; + + if (direction == DMA_DEV_TO_MEM) { + burst->sar = src_addr; + if (xfer->cyclic) { + burst->dar = xfer->xfer.cyclic.paddr; + } else { + burst->dar = sg_dma_address(sg); + src_addr += sg_dma_len(sg); + } + } else { + burst->dar = dst_addr; + if (xfer->cyclic) { + burst->sar = xfer->xfer.cyclic.paddr; + } else { + burst->sar = sg_dma_address(sg); + dst_addr += sg_dma_len(sg); + } + } + + if (!xfer->cyclic) + sg = sg_next(sg); + } + + return vchan_tx_prep(&chan->vc, &desc->vd, xfer->flags); + +err_alloc: + if (desc) + dw_edma_free_desc(desc); + + return NULL; +} + +static struct dma_async_tx_descriptor * +dw_edma_device_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl, + unsigned int len, + enum dma_transfer_direction direction, + unsigned long flags, void *context) +{ + struct dw_edma_transfer xfer; + + xfer.dchan = dchan; + xfer.direction = direction; + xfer.xfer.sg.sgl = sgl; + xfer.xfer.sg.len = len; + xfer.flags = flags; + xfer.cyclic = false; + + return dw_edma_device_transfer(&xfer); +} + +static struct dma_async_tx_descriptor * +dw_edma_device_prep_dma_cyclic(struct dma_chan *dchan, dma_addr_t paddr, + size_t len, size_t count, + enum dma_transfer_direction direction, + unsigned long flags) +{ + struct dw_edma_transfer xfer; + + xfer.dchan = dchan; + xfer.direction = direction; + xfer.xfer.cyclic.paddr = paddr; + xfer.xfer.cyclic.len = len; + xfer.xfer.cyclic.cnt = count; + xfer.flags = flags; + xfer.cyclic = true; + + return dw_edma_device_transfer(&xfer); +} + +static void dw_edma_done_interrupt(struct dw_edma_chan *chan) +{ + struct dw_edma_desc *desc; + struct virt_dma_desc *vd; + unsigned long flags; + + dw_edma_v0_core_clear_done_int(chan); + + spin_lock_irqsave(&chan->vc.lock, flags); + vd = vchan_next_desc(&chan->vc); + if (vd) { + switch (chan->request) { + case EDMA_REQ_NONE: + desc = vd2dw_edma_desc(vd); + if (desc->chunks_alloc) { + chan->status = EDMA_ST_BUSY; + dw_edma_start_transfer(chan); + } else { + list_del(&vd->node); + vchan_cookie_complete(vd); + chan->status = EDMA_ST_IDLE; + } + break; + case EDMA_REQ_STOP: + list_del(&vd->node); + vchan_cookie_complete(vd); + chan->request = EDMA_REQ_NONE; + chan->status = EDMA_ST_IDLE; + break; + case EDMA_REQ_PAUSE: + chan->request = EDMA_REQ_NONE; + chan->status = EDMA_ST_PAUSE; + break; + default: + break; + } + } + spin_unlock_irqrestore(&chan->vc.lock, flags); +} + +static void dw_edma_abort_interrupt(struct dw_edma_chan *chan) +{ + struct virt_dma_desc *vd; + unsigned long flags; + + dw_edma_v0_core_clear_abort_int(chan); + + spin_lock_irqsave(&chan->vc.lock, flags); + vd = vchan_next_desc(&chan->vc); + if (vd) { + list_del(&vd->node); + vchan_cookie_complete(vd); + } + spin_unlock_irqrestore(&chan->vc.lock, flags); + chan->request = EDMA_REQ_NONE; + chan->status = EDMA_ST_IDLE; +} + +static irqreturn_t dw_edma_interrupt(int irq, void *data, bool write) +{ + struct dw_edma_irq *dw_irq = data; + struct dw_edma *dw = dw_irq->dw; + unsigned long total, pos, val; + unsigned long off; + u32 mask; + + if (write) { + total = dw->wr_ch_cnt; + off = 0; + mask = dw_irq->wr_mask; + } else { + total = dw->rd_ch_cnt; + off = dw->wr_ch_cnt; + mask = dw_irq->rd_mask; + } + + val = dw_edma_v0_core_status_done_int(dw, write ? + EDMA_DIR_WRITE : + EDMA_DIR_READ); + val &= mask; + for_each_set_bit(pos, &val, total) { + struct dw_edma_chan *chan = &dw->chan[pos + off]; + + dw_edma_done_interrupt(chan); + } + + val = dw_edma_v0_core_status_abort_int(dw, write ? + EDMA_DIR_WRITE : + EDMA_DIR_READ); + val &= mask; + for_each_set_bit(pos, &val, total) { + struct dw_edma_chan *chan = &dw->chan[pos + off]; + + dw_edma_abort_interrupt(chan); + } + + return IRQ_HANDLED; +} + +static inline irqreturn_t dw_edma_interrupt_write(int irq, void *data) +{ + return dw_edma_interrupt(irq, data, true); +} + +static inline irqreturn_t dw_edma_interrupt_read(int irq, void *data) +{ + return dw_edma_interrupt(irq, data, false); +} + +static irqreturn_t dw_edma_interrupt_common(int irq, void *data) +{ + dw_edma_interrupt(irq, data, true); + dw_edma_interrupt(irq, data, false); + + 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) + return -EBUSY; + + dma_cookie_init(dchan); + + pm_runtime_get(chan->chip->dev); + + return 0; +} + +static void dw_edma_free_chan_resources(struct dma_chan *dchan) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(5000); + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); + int ret; + + while (time_before(jiffies, timeout)) { + ret = dw_edma_device_terminate_all(dchan); + if (!ret) + break; + + if (time_after_eq(jiffies, timeout)) + return; + + cpu_relax(); + }; + + pm_runtime_put(chan->chip->dev); +} + +static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write, + u32 wr_alloc, u32 rd_alloc) +{ + struct dw_edma_region *dt_region; + struct device *dev = chip->dev; + struct dw_edma *dw = chip->dw; + struct dw_edma_chan *chan; + size_t ll_chunk, dt_chunk; + struct dw_edma_irq *irq; + struct dma_device *dma; + u32 i, j, cnt, ch_cnt; + u32 alloc, off_alloc; + int err = 0; + u32 pos; + + ch_cnt = dw->wr_ch_cnt + dw->rd_ch_cnt; + ll_chunk = dw->ll_region.sz; + dt_chunk = dw->dt_region.sz; + + /* Calculate linked list chunk for each channel */ + ll_chunk /= roundup_pow_of_two(ch_cnt); + + /* Calculate linked list chunk for each channel */ + dt_chunk /= roundup_pow_of_two(ch_cnt); + + if (write) { + i = 0; + cnt = dw->wr_ch_cnt; + dma = &dw->wr_edma; + alloc = wr_alloc; + off_alloc = 0; + } else { + i = dw->wr_ch_cnt; + cnt = dw->rd_ch_cnt; + dma = &dw->rd_edma; + alloc = rd_alloc; + off_alloc = wr_alloc; + } + + INIT_LIST_HEAD(&dma->channels); + for (j = 0; (alloc || dw->nr_irqs == 1) && j < cnt; j++, i++) { + chan = &dw->chan[i]; + + dt_region = devm_kzalloc(dev, sizeof(*dt_region), GFP_KERNEL); + if (!dt_region) + return -ENOMEM; + + chan->vc.chan.private = dt_region; + + chan->chip = chip; + chan->id = j; + chan->dir = write ? EDMA_DIR_WRITE : EDMA_DIR_READ; + chan->configured = false; + chan->request = EDMA_REQ_NONE; + chan->status = EDMA_ST_IDLE; + + chan->ll_off = (ll_chunk * i); + chan->ll_max = (ll_chunk / EDMA_LL_SZ) - 1; + + chan->dt_off = (dt_chunk * i); + + dev_vdbg(dev, "L. List:\tChannel %s[%u] off=0x%.8lx, max_cnt=%u\n", + write ? "write" : "read", j, + chan->ll_off, chan->ll_max); + + if (dw->nr_irqs == 1) + pos = 0; + else + pos = off_alloc + (j % alloc); + + irq = &dw->irq[pos]; + + if (write) + irq->wr_mask |= BIT(j); + else + irq->rd_mask |= BIT(j); + + irq->dw = dw; + memcpy(&chan->msi, &irq->msi, sizeof(chan->msi)); + + dev_vdbg(dev, "MSI:\t\tChannel %s[%u] addr=0x%.8x%.8x, data=0x%.8x\n", + write ? "write" : "read", j, + chan->msi.address_hi, chan->msi.address_lo, + chan->msi.data); + + chan->vc.desc_free = vchan_free_desc; + vchan_init(&chan->vc, dma); + + dt_region->paddr = dw->dt_region.paddr + chan->dt_off; + dt_region->vaddr = dw->dt_region.vaddr + chan->dt_off; + dt_region->sz = dt_chunk; + + dev_vdbg(dev, "Data:\tChannel %s[%u] off=0x%.8lx\n", + write ? "write" : "read", j, chan->dt_off); + + dw_edma_v0_core_device_config(chan); + } + + /* Set DMA channel capabilities */ + dma_cap_zero(dma->cap_mask); + dma_cap_set(DMA_SLAVE, dma->cap_mask); + dma_cap_set(DMA_CYCLIC, dma->cap_mask); + dma_cap_set(DMA_PRIVATE, dma->cap_mask); + dma->directions = BIT(write ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV); + dma->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + dma->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + dma->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR; + dma->chancnt = cnt; + + /* Set DMA channel callbacks */ + dma->dev = chip->dev; + dma->device_alloc_chan_resources = dw_edma_alloc_chan_resources; + dma->device_free_chan_resources = dw_edma_free_chan_resources; + dma->device_config = dw_edma_device_config; + dma->device_pause = dw_edma_device_pause; + dma->device_resume = dw_edma_device_resume; + dma->device_terminate_all = dw_edma_device_terminate_all; + dma->device_issue_pending = dw_edma_device_issue_pending; + dma->device_tx_status = dw_edma_device_tx_status; + dma->device_prep_slave_sg = dw_edma_device_prep_slave_sg; + dma->device_prep_dma_cyclic = dw_edma_device_prep_dma_cyclic; + + dma_set_max_seg_size(dma->dev, U32_MAX); + + /* Register DMA device */ + err = dma_async_device_register(dma); + + return err; +} + +static inline void dw_edma_dec_irq_alloc(int *nr_irqs, u32 *alloc, u16 cnt) +{ + if (*nr_irqs && *alloc < cnt) { + (*alloc)++; + (*nr_irqs)--; + } +} + +static inline void dw_edma_add_irq_mask(u32 *mask, u32 alloc, u16 cnt) +{ + while (*mask * alloc < cnt) + (*mask)++; +} + +static int dw_edma_irq_request(struct dw_edma_chip *chip, + u32 *wr_alloc, u32 *rd_alloc) +{ + struct device *dev = chip->dev; + struct dw_edma *dw = chip->dw; + u32 wr_mask = 1; + u32 rd_mask = 1; + int i, err = 0; + u32 ch_cnt; + + ch_cnt = dw->wr_ch_cnt + dw->rd_ch_cnt; + + if (dw->nr_irqs < 1) + return -EINVAL; + + if (dw->nr_irqs == 1) { + /* Common IRQ shared among all channels */ + err = request_irq(pci_irq_vector(to_pci_dev(dev), 0), + dw_edma_interrupt_common, + IRQF_SHARED, dw->name, &dw->irq[0]); + if (err) { + dw->nr_irqs = 0; + return err; + } + + get_cached_msi_msg(pci_irq_vector(to_pci_dev(dev), 0), + &dw->irq[0].msi); + } else { + /* Distribute IRQs equally among all channels */ + int tmp = dw->nr_irqs; + + while (tmp && (*wr_alloc + *rd_alloc) < ch_cnt) { + dw_edma_dec_irq_alloc(&tmp, wr_alloc, dw->wr_ch_cnt); + dw_edma_dec_irq_alloc(&tmp, rd_alloc, dw->rd_ch_cnt); + } + + dw_edma_add_irq_mask(&wr_mask, *wr_alloc, dw->wr_ch_cnt); + dw_edma_add_irq_mask(&rd_mask, *rd_alloc, dw->rd_ch_cnt); + + for (i = 0; i < (*wr_alloc + *rd_alloc); i++) { + err = request_irq(pci_irq_vector(to_pci_dev(dev), i), + i < *wr_alloc ? + dw_edma_interrupt_write : + dw_edma_interrupt_read, + IRQF_SHARED, dw->name, + &dw->irq[i]); + if (err) { + dw->nr_irqs = i; + return err; + } + + get_cached_msi_msg(pci_irq_vector(to_pci_dev(dev), i), + &dw->irq[i].msi); + } + + dw->nr_irqs = i; + } + + return err; +} + +int dw_edma_probe(struct dw_edma_chip *chip) +{ + struct device *dev = chip->dev; + struct dw_edma *dw = chip->dw; + u32 wr_alloc = 0; + u32 rd_alloc = 0; + int i, err; + + raw_spin_lock_init(&dw->lock); + + /* Find out how many write channels are supported by hardware */ + dw->wr_ch_cnt = dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE); + if (!dw->wr_ch_cnt) + return -EINVAL; + + /* Find out how many read channels are supported by hardware */ + dw->rd_ch_cnt = dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ); + if (!dw->rd_ch_cnt) + return -EINVAL; + + dev_vdbg(dev, "Channels:\twrite=%d, read=%d\n", + dw->wr_ch_cnt, dw->rd_ch_cnt); + + /* Allocate channels */ + dw->chan = devm_kcalloc(dev, dw->wr_ch_cnt + dw->rd_ch_cnt, + sizeof(*dw->chan), GFP_KERNEL); + if (!dw->chan) + return -ENOMEM; + + snprintf(dw->name, sizeof(dw->name), "dw-edma-core:%d", chip->id); + + /* Disable eDMA, only to establish the ideal initial conditions */ + dw_edma_v0_core_off(dw); + + /* Request IRQs */ + err = dw_edma_irq_request(chip, &wr_alloc, &rd_alloc); + if (err) + return err; + + /* Setup write channels */ + err = dw_edma_channel_setup(chip, true, wr_alloc, rd_alloc); + if (err) + goto err_irq_free; + + /* Setup read channels */ + err = dw_edma_channel_setup(chip, false, wr_alloc, rd_alloc); + if (err) + goto err_irq_free; + + /* Power management */ + pm_runtime_enable(dev); + + /* Turn debugfs on */ + err = dw_edma_v0_core_debugfs_on(chip); + if (err) + goto err_pm_disable; + + return 0; + +err_pm_disable: + pm_runtime_disable(dev); +err_irq_free: + for (i = (dw->nr_irqs - 1); i >= 0; i--) + free_irq(pci_irq_vector(to_pci_dev(dev), i), &dw->irq[i]); + + dw->nr_irqs = 0; + + return err; +} +EXPORT_SYMBOL_GPL(dw_edma_probe); + +int dw_edma_remove(struct dw_edma_chip *chip) +{ + struct dw_edma_chan *chan, *_chan; + struct device *dev = chip->dev; + struct dw_edma *dw = chip->dw; + int i; + + /* Disable eDMA */ + dw_edma_v0_core_off(dw); + + /* Free irqs */ + for (i = (dw->nr_irqs - 1); i >= 0; i--) + free_irq(pci_irq_vector(to_pci_dev(dev), i), &dw->irq[i]); + + /* Power management */ + pm_runtime_disable(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 */ + dw_edma_v0_core_debugfs_off(); + + 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..8a3a0a4 --- /dev/null +++ b/drivers/dma/dw-edma/dw-edma-core.h @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates. + * Synopsys DesignWare eDMA core driver + * + * Author: Gustavo Pimentel + */ + +#ifndef _DW_EDMA_CORE_H +#define _DW_EDMA_CORE_H + +#include +#include + +#include "../virt-dma.h" + +#define EDMA_LL_SZ 24 + +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_burst { + struct list_head list; + u64 sar; + u64 dar; + u32 sz; +}; + +struct dw_edma_region { + phys_addr_t paddr; + dma_addr_t vaddr; + size_t sz; +}; + +struct dw_edma_chunk { + struct list_head list; + struct dw_edma_chan *chan; + struct dw_edma_burst *burst; + + u32 bursts_alloc; + + u8 cb; + struct dw_edma_region ll_region; /* 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; + + off_t ll_off; + u32 ll_max; + + off_t dt_off; + + struct msi_msg msi; + + enum dw_edma_request request; + enum dw_edma_status status; + u8 configured; + + struct dma_slave_config config; +}; + +struct dw_edma_irq { + struct msi_msg msi; + u32 wr_mask; + u32 rd_mask; + struct dw_edma *dw; +}; + +struct dw_edma { + char name[20]; + + struct dma_device wr_edma; + u16 wr_ch_cnt; + + struct dma_device rd_edma; + u16 rd_ch_cnt; + + struct dw_edma_region rg_region; /* Registers */ + struct dw_edma_region ll_region; /* Linked list */ + struct dw_edma_region dt_region; /* Data */ + + struct dw_edma_irq *irq; + int nr_irqs; + + 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 */ +}; + +struct dw_edma_sg { + struct scatterlist *sgl; + unsigned int len; +}; + +struct dw_edma_cyclic { + dma_addr_t paddr; + size_t len; + size_t cnt; +}; + +struct dw_edma_transfer { + struct dma_chan *dchan; + union Xfer { + struct dw_edma_sg sg; + struct dw_edma_cyclic cyclic; + } xfer; + enum dma_transfer_direction direction; + unsigned long flags; + bool cyclic; +}; + +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..cab6e18 --- /dev/null +++ b/include/linux/dma/edma.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates. + * Synopsys DesignWare eDMA core driver + * + * Author: Gustavo Pimentel + */ + +#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