From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [RFC,v3,1/7] dmaengine: Add Synopsys eDMA IP core driver From: Gustavo Pimentel Message-Id: <14acfcee-b367-be9c-714b-de0508ff1a7d@synopsys.com> Date: Mon, 21 Jan 2019 15:48:14 +0000 To: Vinod Koul , Gustavo Pimentel Cc: "linux-pci@vger.kernel.org" , "dmaengine@vger.kernel.org" , Dan Williams , Eugeniy Paltsev , Andy Shevchenko , Russell King , Niklas Cassel , Joao Pinto , Jose Abreu , Luis Oliveira , Vitor Soares , Nelson Costa , Pedro Sousa List-ID: T24gMjAvMDEvMjAxOSAxMTo0NCwgVmlub2QgS291bCB3cm90ZToKPiBPbiAxMS0wMS0xOSwgMTk6 MzMsIEd1c3Rhdm8gUGltZW50ZWwgd3JvdGU6Cj4+IEFkZCBTeW5vcHN5cyBlRE1BIElQIGNvcmUg ZHJpdmVyIHRvIGtlcm5lbC4KPj4KPj4gVGhpcyBjb3JlIGRyaXZlciwgaW5pdGlhbGl6ZXMgYW5k IGNvbmZpZ3VyZXMgdGhlIGVETUEgSVAgdXNpbmcgdm1hLWhlbHBlcnMKPj4gZnVuY3Rpb25zIGFu ZCBkbWEtZW5naW5lIHN1YnN5c3RlbS4KPiAKPiBBIGRlc2NyaXB0aW9uIG9mIGVETUEgSVAgd2ls bCBoZWxwIHJldmlldyB0aGUgZHJpdmVyCgpJJ3ZlIHRoZSBJUCBkZXNjcmlwdGlvbiBvbiB0aGUg Y292ZXItbGV0dGVyLCBidXQgSSdsbCBicmluZyBpdCB0byB0aGlzIHBhdGNoLCBpZgppdCBoZWxw cy4KCj4gCj4+IEFsc28gY3JlYXRlcyBhbiBhYnN0cmF0aW9uIGxheWVyIHRocm91Z2ggY2FsbGJh Y2tzIGFsbG93aW5nIGRpZmZlcmVudAo+PiByZWdpc3RlcnMgbWFwcGluZ3MgaW4gdGhlIGZ1dHVy ZSwgb3JnYW5pemVkIGluIHRvIHZlcnNpb25zLgo+Pgo+PiBUaGlzIGRyaXZlciBjYW4gYmUgY29t cGlsZSBhcyBidWlsdC1pbiBvciBleHRlcm5hbCBtb2R1bGUgaW4ga2VybmVsLgo+Pgo+PiBUbyBl bmFibGUgdGhpcyBkcml2ZXIganVzdCBzZWxlY3QgRFdfRURNQSBvcHRpb24gaW4ga2VybmVsIGNv bmZpZ3VyYXRpb24sCj4+IGhvd2V2ZXIgaXQgcmVxdWlyZXMgYW5kIHNlbGVjdHMgYXV0b21hdGlj YWxseSBETUFfRU5HSU5FIGFuZAo+PiBETUFfVklSVFVBTF9DSEFOTkVMUyBvcHRpb24gdG9vLgo+ Pgo+PiBDaGFuZ2VzOgo+PiBSRkMgdjEtPlJGQyB2MjoKPiAKPiBUaGVzZSBkbyBub3QgYmVsb25n IHRvIGNoYW5nZSBsb2csIGVpdGhlciBtb3ZlIHRoZW0gdG8gY292ZXItbGV0dGVyIG9yCj4ga2Vl cCB0aGVtIGFmdGVyIHMtby1iIGxpbmVzLi4KCk9rLCBBbmR5IGhhcyBhbHNvIHJlZmVycmVkIHRo YXQuIEknbGwga2VlcCB0aGVtIGFmdGVyIHMtby1iIGxpbmVzLgoKPiAKPj4gQEAgLTAsMCArMSwx MDU5IEBACj4+ICsvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAo+PiArLyoKPj4g KyAqIENvcHlyaWdodCAoYykgMjAxOCBTeW5vcHN5cywgSW5jLiBhbmQvb3IgaXRzIGFmZmlsaWF0 ZXMuCj4gCj4gMjAxOSBub3cKCkkndmUgY2hhbmdlZCB0byAiQ29weXJpZ2h0IChjKSAyMDE4LXBy ZXNlbnQgU3lub3BzeXMsIEluYy4gYW5kL29yIGl0cwphZmZpbGlhdGVzLiIgdGhpcyB3YXkgaXQn cyBhbHdheXMgdXAgdG8gZGF0ZSBhbmQgSSBhbHNvIGtlcHQgMjAxOCwgYmVjYXVzZSBpdAp3YXMg dGhlIGRhdGUgdGhhdCBJIHN0YXJ0ZWQgdG8gZGV2ZWxvcCB0aGlzIGRyaXZlciwgaWYgeW91IGRv bid0IG1pbmQuCgo+IAo+PiArc3RhdGljIHN0cnVjdCBkd19lZG1hX2J1cnN0ICpkd19lZG1hX2Fs bG9jX2J1cnN0KHN0cnVjdCBkd19lZG1hX2NodW5rICpjaHVuaykKPj4gK3sKPj4gKwlzdHJ1Y3Qg ZHdfZWRtYV9jaGFuICpjaGFuID0gY2h1bmstPmNoYW47Cj4+ICsJc3RydWN0IGR3X2VkbWFfYnVy c3QgKmJ1cnN0Owo+PiArCj4+ICsJYnVyc3QgPSBrdnphbGxvYyhzaXplb2YoKmJ1cnN0KSwgR0ZQ X05PV0FJVCk7Cj4gCj4gSXMgdGhlcmUgYSBzcGVjaWZpYyByZWFzb24gZm9yIGt2emFsbG9jKCks ICBkbyB5b3Ugc3VibWl0IHRoaXMgdG8gSFcuLgoKVGhlcmUgaXMgbm90IHJlYXNvbiBmb3IgdGhh dCwgaXQgd2VyZSByZW1haW5zIG9mIGFuIGluaXRpYWwgaW1wbGVtZW50YXRpb24uIEknbGwKcmVw bGFjZSB0aGVtIGJ5IGt6YWxsb2MuCk5pY2VseSBzcG90dGVkIQoKPiAKPj4gK3N0YXRpYyBzdHJ1 Y3QgZHdfZWRtYV9jaHVuayAqZHdfZWRtYV9hbGxvY19jaHVuayhzdHJ1Y3QgZHdfZWRtYV9kZXNj ICpkZXNjKQo+PiArewo+PiArCXN0cnVjdCBkd19lZG1hX2NoYW4gKmNoYW4gPSBkZXNjLT5jaGFu Owo+PiArCXN0cnVjdCBkd19lZG1hICpkdyA9IGNoYW4tPmNoaXAtPmR3Owo+PiArCXN0cnVjdCBk d19lZG1hX2NodW5rICpjaHVuazsKPj4gKwo+PiArCWNodW5rID0ga3Z6YWxsb2Moc2l6ZW9mKCpj aHVuayksIEdGUF9OT1dBSVQpOwo+PiArCWlmICh1bmxpa2VseSghY2h1bmspKQo+PiArCQlyZXR1 cm4gTlVMTDsKPj4gKwo+PiArCUlOSVRfTElTVF9IRUFEKCZjaHVuay0+bGlzdCk7Cj4+ICsJY2h1 bmstPmNoYW4gPSBjaGFuOwo+PiArCWNodW5rLT5jYiA9ICEoZGVzYy0+Y2h1bmtzX2FsbG9jICUg Mik7Cj4gCj4gY2IgLi4/CgpDQiA9IGNoYW5nZSBiaXQsIGlzIGEgcHJvcGVydHkgb2YgdGhpcyBl RE1BIElQLiBCYXNpY2FsbHkgaXQgaXMgYSBraW5kIG9mCmhhbmRzaGFrZSB3aGljaCBzZXJ2ZXMg dG8gdmFsaWRhdGUgd2hldGhlciB0aGUgbGlua2VkIGxpc3QgaGFzIGJlZW4gdXBkYXRlZCBvcgpu b3QsIGVzcGVjaWFsbHkgdXNlZnVsIGluIGNhc2VzIG9mIHJlY3ljbGVkIGxpbmtlZCBsaXN0IGVs ZW1lbnRzIChldmVyeSBsaW5rZWQKbGlzdCByZWN5Y2xlIGlzIGEgbmV3IGNodW5rLCB0aGlzIHdp bGwgYWxsb3cgdG8gZGlmZmVyZW50aWF0ZSBlYWNoIGNodW5rKS4KCj4gCj4+ICtzdGF0aWMgaW50 IGR3X2VkbWFfZGV2aWNlX2NvbmZpZyhzdHJ1Y3QgZG1hX2NoYW4gKmRjaGFuLAo+PiArCQkJCSBz dHJ1Y3QgZG1hX3NsYXZlX2NvbmZpZyAqY29uZmlnKQo+PiArewo+PiArCXN0cnVjdCBkd19lZG1h X2NoYW4gKmNoYW4gPSBkY2hhbjJkd19lZG1hX2NoYW4oZGNoYW4pOwo+PiArCWNvbnN0IHN0cnVj dCBkd19lZG1hX2NvcmVfb3BzICpvcHMgPSBjaGFuMm9wcyhjaGFuKTsKPj4gKwl1bnNpZ25lZCBs b25nIGZsYWdzOwo+PiArCWludCBlcnIgPSAwOwo+PiArCj4+ICsJc3Bpbl9sb2NrX2lycXNhdmUo JmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsKPj4gKwo+PiArCWlmICghY29uZmlnKSB7Cj4+ICsJCWVy ciA9IC1FSU5WQUw7Cj4+ICsJCWdvdG8gZXJyX2NvbmZpZzsKPj4gKwl9Cj4+ICsKPj4gKwlpZiAo Y2hhbi0+c3RhdHVzICE9IEVETUFfU1RfSURMRSkgewo+PiArCQlkZXZfZXJyKGNoYW4yZGV2KGNo YW4pLCAiY2hhbm5lbCBpcyBidXN5IG9yIHBhdXNlZFxuIik7Cj4+ICsJCWVyciA9IC1FUEVSTTsK PiAKPiB0aGlzIGlzIG5vdCBjb3JyZWN0IGJlaGF2aW91ciwgZGV2aWNlX2NvbmZpZyBjYW4gYmUg Y2FsbGVkIGFueXRpbWUgYW5kCj4gdmFsdWVzIGNhbiB0YWtlIGFmZmVjdCBvbiBuZXh0IHRyYW5z YWN0aW9uIHN1Ym1pdHRlZC4uCgpIdW0sIEkgdGhvdWdodCB3ZSBjb3VsZCBvbmx5IHJlY29uZmln dXJlIGFmdGVyIHRyYW5zZmVyIGJlaW5nIGZpbmlzaGVkLgoKPiAKPj4gKwkJZ290byBlcnJfY29u ZmlnOwo+PiArCX0KPj4gKwo+PiArCWRldl9kYmcoY2hhbjJkZXYoY2hhbiksICJhZGRyKHBoeXNp Y2FsKSBzcmM9JXBhLCBkc3Q9JXBhXG4iLAo+PiArCQkmY29uZmlnLT5zcmNfYWRkciwgJmNvbmZp Zy0+ZHN0X2FkZHIpOwo+PiArCj4+ICsJY2hhbi0+c3JjX2FkZHIgPSBjb25maWctPnNyY19hZGRy Owo+PiArCWNoYW4tPmRzdF9hZGRyID0gY29uZmlnLT5kc3RfYWRkcjsKPj4gKwo+PiArCWVyciA9 IG9wcy0+ZGV2aWNlX2NvbmZpZyhkY2hhbik7Cj4gCj4gd2hhdCBkb2VzIHRoaXMgZG8/CgpUaGlz IGlzIGFuIGluaXRpYWxpemF0aW9uIHByb2NlZHVyZSB0byBzZXR1cCBpbnRlcnJ1cHRzIChkYXRh IGFuZCBhZGRyZXNzZXMpIHRvCmVhY2ggY2hhbm5lbCBvbiB0aGUgZURNQSBJUCwgIGluIG9yZGVy IHRvIGJlIHRyaWdnZXJlZCBhZnRlciB0cmFuc2ZlciBiZWluZwpjb21wbGV0ZWQgb3IgYWJvcnRl ZC4gRHVlIHRoZSBmYWN0IHRoZSBjb25maWcoKSBjYW4gYmUgY2FsbGVkIGF0IGFueXRpbWUsCmRv ZXNuJ3QgbWFrZSBzZW5zZSB0byBoYXZlIHRoaXMgcHJvY2VkdXJlIGhlcmUsIEknbGwgbW92ZWQg aXQgdG8gcHJvYmUoKS4KCj4gCj4+ICtzdGF0aWMgZW51bSBkbWFfc3RhdHVzCj4+ICtkd19lZG1h X2RldmljZV90eF9zdGF0dXMoc3RydWN0IGRtYV9jaGFuICpkY2hhbiwgZG1hX2Nvb2tpZV90IGNv b2tpZSwKPj4gKwkJCSBzdHJ1Y3QgZG1hX3R4X3N0YXRlICp0eHN0YXRlKQo+PiArewo+PiArCXN0 cnVjdCBkd19lZG1hX2NoYW4gKmNoYW4gPSBkY2hhbjJkd19lZG1hX2NoYW4oZGNoYW4pOwo+PiAr CWNvbnN0IHN0cnVjdCBkd19lZG1hX2NvcmVfb3BzICpvcHMgPSBjaGFuMm9wcyhjaGFuKTsKPj4g Kwl1bnNpZ25lZCBsb25nIGZsYWdzOwo+PiArCWVudW0gZG1hX3N0YXR1cyByZXQ7Cj4+ICsKPj4g KwlzcGluX2xvY2tfaXJxc2F2ZSgmY2hhbi0+dmMubG9jaywgZmxhZ3MpOwo+PiArCj4+ICsJcmV0 ID0gb3BzLT5jaF9zdGF0dXMoY2hhbik7Cj4+ICsJaWYgKHJldCA9PSBETUFfRVJST1IpIHsKPj4g KwkJZ290byByZXRfc3RhdHVzOwo+PiArCX0gZWxzZSBpZiAocmV0ID09IERNQV9JTl9QUk9HUkVT Uykgewo+PiArCQljaGFuLT5zdGF0dXMgPSBFRE1BX1NUX0JVU1k7Cj4+ICsJCWdvdG8gcmV0X3N0 YXR1czsKPiAKPiBzbyBpbiB0aGlzIGNhc2UgeW91IHNldCByZXNpZHVlIGFzIHplcm8sIHdoaWNo IGlzIG5vdCBjb3JyZWN0CgpPaywgdGhlIHJlc2lkdWUgc2hvdWxkIGJlIHRoZSByZW1haW5pbmcg Ynl0ZXMgdG8gdHJhbnNmZXIsIHJpZ2h0PwoKPiAKPj4gKwl9IGVsc2Ugewo+PiArCQkvKiBETUFf Q09NUExFVEUgKi8KPj4gKwkJaWYgKGNoYW4tPnN0YXR1cyA9PSBFRE1BX1NUX1BBVVNFKQo+PiAr CQkJcmV0ID0gRE1BX1BBVVNFRDsKPj4gKwkJZWxzZSBpZiAoY2hhbi0+c3RhdHVzID09IEVETUFf U1RfQlVTWSkKPj4gKwkJCXJldCA9IERNQV9JTl9QUk9HUkVTUzsKPiAKPiA/PyBpZiB0eG4gaXMg Y29tcGxldGUgaG93IGFyZSB5b3UgcmV0dXJuaW5nIERNQV9JTl9QUk9HUkVTUz8KClRoaXMgSVAg cmVwb3J0cyBETUFfQ09NUExFVEUgd2hlbiBpdCBzdWNjZXNzZnVsbHkgY29tcGxldGVzIHRoZSB0 cmFuc2ZlciBvZiBhbGwKbGlua2VkIGxpc3QgZWxlbWVudHMsIGdpdmVuIHRoYXQgdGhlcmUgbWF5 IGJlIGV2ZW4gbW9yZSBlbGVtZW50cyBvZiB0aGUgbGlua2VkCmxpc3QgdG8gYmUgdHJhbnNmZXJy ZWQgdGhlIG92ZXJhbGwgc3RhdGUgaXMgc2V0IHRvIERNQV9JTl9QUk9HUkVTUy4KPiAKPj4gKwkJ ZWxzZQo+PiArCQkJcmV0ID0gRE1BX0NPTVBMRVRFOwo+PiArCX0KPiAKPiB0aGlzIGxvb2tzIGlu Y29ycmVjdCBpbnRlcnByZXRhdGlvbiB0byBtZS4gVGhlIHN0YXR1cyBpcyB0byBiZSByZXRyaWV2 ZWQKPiBmb3IgdGhlIGdpdmVuIGNvb2tpZSBwYXNzZWQgYW5kIGdpdmVuIHRoYXQgeW91IGRvIG5v dCBldmVuIHVzZSB0aGlzCj4gYXJndW1lbnQgdGVsbHMgbWUgdGhhdCB5b3UgaGF2ZSB1bmRlcnN0 b29kIHRoaXMgYXMgJ2NoYW5uZWwnIHN0YXR1cwo+IHJlcG9ydGluZywgd2hpY2ggaXMgbm90IGNv cnJlY3QKClllcywgeW91J3JlIHJpZ2h0LCBteSBpbnRlcnByZXRhdGlvbiBhc3N1bWVzIHRoaXMg ZnVuY3Rpb24gcmVwb3J0cwpjaGFubmVsL3RyYW5zYWN0aW9uIHN0YXR1cy4gV2hhdCB3b3VsZCBi ZSB0aGUgY29ycmVjdCBpbXBsZW1lbnRhdGlvbj8KU29tZXRoaW5nIGxpa2UgdGhpcz8KCnsKCXN0 cnVjdCBkd19lZG1hX2NoYW4gKmNoYW4gPSBkY2hhbjJkd19lZG1hX2NoYW4oZGNoYW4pOwoJY29u c3Qgc3RydWN0IGR3X2VkbWFfY29yZV9vcHMgKm9wcyA9IGNoYW4yb3BzKGNoYW4pOwoJc3RydWN0 IGR3X2VkbWFfZGVzYyAqZGVzYzsKCXN0cnVjdCB2aXJ0X2RtYV9kZXNjICp2ZDsKCXVuc2lnbmVk IGxvbmcgZmxhZ3M7CgllbnVtIGRtYV9zdGF0dXMgcmV0OwoJdTMyIHJlc2lkdWUgPSAwOwoKCXNw aW5fbG9ja19pcnFzYXZlKCZjaGFuLT52Yy5sb2NrLCBmbGFncyk7CgoJcmV0ID0gZG1hX2Nvb2tp ZV9zdGF0dXMoY2hhbiwgY29va2llLCB0eHN0YXRlKTsKCWlmIChyZXQgPT0gRE1BX0NPTVBMRVRF KQoJCWdvdG8gcmV0X3N0YXR1czsKCgl2ZCA9IHZjaGFuX25leHRfZGVzYygmY2hhbi0+dmMpOwoJ aWYgKCF2ZCkKCQlnb3RvIHJldF9zdGF0dXM7CgoJZGVzYyA9IHZkMmR3X2VkbWFfZGVzYyh2ZCk7 CglpZiAoIWRlc2MpCgkJcmVzaWR1ZSA9IGRlc2MtPmFsbG9jX3N6IC0gZGVzYy0+eGZlcl9zejsK CQkKCWlmIChyZXQgPT0gRE1BX0lOX1BST0dSRVNTICYmIGNoYW4tPnN0YXR1cyA9PSBFRE1BX1NU X1BBVVNFKQoJCXJldCA9IERNQV9QQVVTRUQ7CgpyZXRfc3RhdHVzOgoJc3Bpbl91bmxvY2tfaXJx cmVzdG9yZSgmY2hhbi0+dmMubG9jaywgZmxhZ3MpOwoJZG1hX3NldF9yZXNpZHVlKHR4c3RhdGUs IHJlc2lkdWUpOwoJCglyZXR1cm4gcmV0Owp9Cgo+IAo+PiArc3RhdGljIHN0cnVjdCBkbWFfYXN5 bmNfdHhfZGVzY3JpcHRvciAqCj4+ICtkd19lZG1hX2RldmljZV9wcmVwX3NsYXZlX3NnKHN0cnVj dCBkbWFfY2hhbiAqZGNoYW4sIHN0cnVjdCBzY2F0dGVybGlzdCAqc2dsLAo+PiArCQkJICAgICB1 bnNpZ25lZCBpbnQgc2dfbGVuLAo+PiArCQkJICAgICBlbnVtIGRtYV90cmFuc2Zlcl9kaXJlY3Rp b24gZGlyZWN0aW9uLAo+PiArCQkJICAgICB1bnNpZ25lZCBsb25nIGZsYWdzLCB2b2lkICpjb250 ZXh0KQo+PiArewo+PiArCXN0cnVjdCBkd19lZG1hX2NoYW4gKmNoYW4gPSBkY2hhbjJkd19lZG1h X2NoYW4oZGNoYW4pOwo+PiArCXN0cnVjdCBkd19lZG1hX2Rlc2MgKmRlc2M7Cj4+ICsJc3RydWN0 IGR3X2VkbWFfY2h1bmsgKmNodW5rOwo+PiArCXN0cnVjdCBkd19lZG1hX2J1cnN0ICpidXJzdDsK Pj4gKwlzdHJ1Y3Qgc2NhdHRlcmxpc3QgKnNnOwo+PiArCXVuc2lnbmVkIGxvbmcgc2ZsYWdzOwo+ PiArCXBoeXNfYWRkcl90IHNyY19hZGRyOwo+PiArCXBoeXNfYWRkcl90IGRzdF9hZGRyOwo+PiAr CWludCBpOwo+PiArCj4+ICsJaWYgKHNnX2xlbiA8IDEpIHsKPj4gKwkJZGV2X2VycihjaGFuMmRl dihjaGFuKSwgImludmFsaWQgc2cgbGVuZ3RoICV1XG4iLCBzZ19sZW4pOwo+PiArCQlyZXR1cm4g TlVMTDsKPj4gKwl9Cj4+ICsKPj4gKwlpZiAoZGlyZWN0aW9uID09IERNQV9ERVZfVE9fTUVNICYm IGNoYW4tPmRpciA9PSBFRE1BX0RJUl9XUklURSkgewo+IAo+IHdoYXQgaXMgdGhlIHNlY29uZCBw YXJ0IG9mIHRoZSBjaGVjaywgY2FuIHlvdSBleHBsYWluIHRoYXQsIHdobyBzZXRzCj4gY2hhbi0+ ZGlyPwoKVGhlIGNoYW4tPmRpciBpcyBzZXQgb24gcHJvYmUoKSBkdXJpbmcgdGhlIHByb2Nlc3Mg b2YgY29uZmlndXJpbmcgZWFjaCBjaGFubmVsLgoKPiAKPj4gKwkJZGV2X2RiZyhjaGFuMmRldihj aGFuKSwJInByZXBhcmUgb3BlcmF0aW9uIChXUklURSlcbiIpOwo+PiArCX0gZWxzZSBpZiAoZGly ZWN0aW9uID09IERNQV9NRU1fVE9fREVWICYmIGNoYW4tPmRpciA9PSBFRE1BX0RJUl9SRUFEKSB7 Cj4+ICsJCWRldl9kYmcoY2hhbjJkZXYoY2hhbiksCSJwcmVwYXJlIG9wZXJhdGlvbiAoUkVBRClc biIpOwo+PiArCX0gZWxzZSB7Cj4+ICsJCWRldl9lcnIoY2hhbjJkZXYoY2hhbiksICJpbnZhbGlk IGRpcmVjdGlvblxuIik7Cj4+ICsJCXJldHVybiBOVUxMOwo+PiArCX0KPj4gKwo+PiArCWlmICgh Y2hhbi0+Y29uZmlndXJlZCkgewo+PiArCQlkZXZfZXJyKGNoYW4yZGV2KGNoYW4pLCAiKHByZXBf c2xhdmVfc2cpIGNoYW5uZWwgbm90IGNvbmZpZ3VyZWRcbiIpOwo+PiArCQlyZXR1cm4gTlVMTDsK Pj4gKwl9Cj4+ICsKPj4gKwlpZiAoY2hhbi0+c3RhdHVzICE9IEVETUFfU1RfSURMRSkgewo+PiAr CQlkZXZfZXJyKGNoYW4yZGV2KGNoYW4pLCAiY2hhbm5lbCBpcyBidXN5IG9yIHBhdXNlZFxuIik7 Cj4+ICsJCXJldHVybiBOVUxMOwo+PiArCX0KPiAKPiBObywgd3JvbmcgYWdhaW4uIFRoZSB0eG4g bXVzdCBiZSBwcmVwYXJlZCBhbmQgdGhlbiBvbiBzdWJtaXQgYWRkZWQgdG8gYQo+IHF1ZXVlLiBZ b3UgYXJlIHdyaXRpbmcgYSBkcml2ZXIgZm9yIGRtYWVuZ2luZSwgc3VyZWx5IHlvdSBkb250IGV4 cGVjdAo+IHRoZSBjaGFubmVsIHRvIGJlIGZyZWUgYW5kIHRoZW4gZG8gYSB0eG4uLiB0aGF0IHdv dWxkIGJlIHZlcnkKPiBpbmVmZmljaWVudCEKCkkgZGlkIG5vdCByZWFsaXplIHRoYXQgdGhlIGZs b3cgY291bGQgYmUgYXMgeW91IG1lbnRpb25lZC4gVGhlIGRvY3VtZW50YXRpb24gSQpyZWFkIGFi b3V0IHRoZSBzdWJzeXN0ZW0gZGlkIG5vdCBnaXZlIG1lIHRoaXMgaWRlYS4gVGhhbmsgeW91IGZv ciBjbGFyaWZ5aW5nIG1lLgoKPiAKPj4gK3N0YXRpYyBzdHJ1Y3QgZG1hX2FzeW5jX3R4X2Rlc2Ny aXB0b3IgKgo+PiArZHdfZWRtYV9kZXZpY2VfcHJlcF9kbWFfY3ljbGljKHN0cnVjdCBkbWFfY2hh biAqZGNoYW4sIGRtYV9hZGRyX3QgYnVmX2FkZHIsCj4+ICsJCQkgICAgICAgc2l6ZV90IGxlbiwg c2l6ZV90IGN5Y2xpY19jbnQsCj4+ICsJCQkgICAgICAgZW51bSBkbWFfdHJhbnNmZXJfZGlyZWN0 aW9uIGRpcmVjdGlvbiwKPj4gKwkJCSAgICAgICB1bnNpZ25lZCBsb25nIGZsYWdzKQo+PiArewo+ PiArCXN0cnVjdCBkd19lZG1hX2NoYW4gKmNoYW4gPSBkY2hhbjJkd19lZG1hX2NoYW4oZGNoYW4p Owo+PiArCXN0cnVjdCBkd19lZG1hX2Rlc2MgKmRlc2M7Cj4+ICsJc3RydWN0IGR3X2VkbWFfY2h1 bmsgKmNodW5rOwo+PiArCXN0cnVjdCBkd19lZG1hX2J1cnN0ICpidXJzdDsKPj4gKwl1bnNpZ25l ZCBsb25nIHNmbGFnczsKPj4gKwlwaHlzX2FkZHJfdCBzcmNfYWRkcjsKPj4gKwlwaHlzX2FkZHJf dCBkc3RfYWRkcjsKPj4gKwl1MzIgaTsKPj4gKwo+PiArCWlmICghbGVuIHx8ICFjeWNsaWNfY250 KSB7Cj4+ICsJCWRldl9lcnIoY2hhbjJkZXYoY2hhbiksICJpbnZhbGlkIGxlbiBvciBjeWNsaWMg Y291bnRcbiIpOwo+PiArCQlyZXR1cm4gTlVMTDsKPj4gKwl9Cj4+ICsKPj4gKwlpZiAoZGlyZWN0 aW9uID09IERNQV9ERVZfVE9fTUVNICYmIGNoYW4tPmRpciA9PSBFRE1BX0RJUl9XUklURSkgewo+ PiArCQlkZXZfZGJnKGNoYW4yZGV2KGNoYW4pLAkicHJlcGFyZSBvcGVyYXRpb24gKFdSSVRFKVxu Iik7Cj4+ICsJfSBlbHNlIGlmIChkaXJlY3Rpb24gPT0gRE1BX01FTV9UT19ERVYgJiYgY2hhbi0+ ZGlyID09IEVETUFfRElSX1JFQUQpIHsKPj4gKwkJZGV2X2RiZyhjaGFuMmRldihjaGFuKSwJInBy ZXBhcmUgb3BlcmF0aW9uIChSRUFEKVxuIik7Cj4+ICsJfSBlbHNlIHsKPj4gKwkJZGV2X2Vycihj aGFuMmRldihjaGFuKSwgImludmFsaWQgZGlyZWN0aW9uXG4iKTsKPj4gKwkJcmV0dXJuIE5VTEw7 Cj4+ICsJfQo+PiArCj4+ICsJaWYgKCFjaGFuLT5jb25maWd1cmVkKSB7Cj4+ICsJCWRldl9lcnIo Y2hhbjJkZXYoY2hhbiksICIocHJlcF9kbWFfY3ljbGljKSBjaGFubmVsIG5vdCBjb25maWd1cmVk XG4iKTsKPj4gKwkJcmV0dXJuIE5VTEw7Cj4+ICsJfQo+PiArCj4+ICsJaWYgKGNoYW4tPnN0YXR1 cyAhPSBFRE1BX1NUX0lETEUpIHsKPj4gKwkJZGV2X2VycihjaGFuMmRldihjaGFuKSwgImNoYW5u ZWwgaXMgYnVzeSBvciBwYXVzZWRcbiIpOwo+PiArCQlyZXR1cm4gTlVMTDsKPj4gKwl9Cj4+ICsK Pj4gKwlzcGluX2xvY2tfaXJxc2F2ZSgmY2hhbi0+dmMubG9jaywgc2ZsYWdzKTsKPj4gKwo+PiAr CWRlc2MgPSBkd19lZG1hX2FsbG9jX2Rlc2MoY2hhbik7Cj4+ICsJaWYgKHVubGlrZWx5KCFkZXNj KSkKPj4gKwkJZ290byBlcnJfYWxsb2M7Cj4+ICsKPj4gKwljaHVuayA9IGR3X2VkbWFfYWxsb2Nf Y2h1bmsoZGVzYyk7Cj4+ICsJaWYgKHVubGlrZWx5KCFjaHVuaykpCj4+ICsJCWdvdG8gZXJyX2Fs bG9jOwo+PiArCj4+ICsJc3JjX2FkZHIgPSBjaGFuLT5zcmNfYWRkcjsKPj4gKwlkc3RfYWRkciA9 IGNoYW4tPmRzdF9hZGRyOwo+PiArCj4+ICsJZm9yIChpID0gMDsgaSA8IGN5Y2xpY19jbnQ7IGkr Kykgewo+PiArCQlpZiAoY2h1bmstPmJ1cnN0c19hbGxvYyA9PSBjaGFuLT5sbF9tYXgpIHsKPj4g KwkJCWNodW5rID0gZHdfZWRtYV9hbGxvY19jaHVuayhkZXNjKTsKPj4gKwkJCWlmICh1bmxpa2Vs eSghY2h1bmspKQo+PiArCQkJCWdvdG8gZXJyX2FsbG9jOwo+PiArCQl9Cj4+ICsKPj4gKwkJYnVy c3QgPSBkd19lZG1hX2FsbG9jX2J1cnN0KGNodW5rKTsKPj4gKwo+PiArCQlpZiAodW5saWtlbHko IWJ1cnN0KSkKPj4gKwkJCWdvdG8gZXJyX2FsbG9jOwo+PiArCj4+ICsJCWJ1cnN0LT5zeiA9IGxl bjsKPj4gKwkJY2h1bmstPmxsX3JlZ2lvbi5zeiArPSBidXJzdC0+c3o7Cj4+ICsJCWRlc2MtPmFs bG9jX3N6ICs9IGJ1cnN0LT5zejsKPj4gKwo+PiArCQlidXJzdC0+c2FyID0gc3JjX2FkZHI7Cj4+ ICsJCWJ1cnN0LT5kYXIgPSBkc3RfYWRkcjsKPj4gKwo+PiArCQlkZXZfZGJnKGNoYW4yZGV2KGNo YW4pLCAibGxpICV1LyV1LCBzYXI9MHglLjhsbHgsIGRhcj0weCUuOGxseCwgc2l6ZT0ldSBieXRl c1xuIiwKPj4gKwkJCWkgKyAxLCBjeWNsaWNfY250LCBidXJzdC0+c2FyLCBidXJzdC0+ZGFyLCBi dXJzdC0+c3opOwo+PiArCX0KPj4gKwo+PiArCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmNoYW4t PnZjLmxvY2ssIHNmbGFncyk7Cj4+ICsJcmV0dXJuIHZjaGFuX3R4X3ByZXAoJmNoYW4tPnZjLCAm ZGVzYy0+dmQsIGZsYWdzKTsKPiAKPiBob3cgaXMgaXQgZGlmZmVyZW50IGZyb20gcHJldmlvdXM/ IGFtIHN1cmUgd2UgY2FuIHJldXNlIGJpdHMhCgpUaGVyZSBhcmUgc29tZSBkaWZmZXJlbmNlcywg YnV0IEkgYWdyZWUgSSBjYW4gcmV3cml0ZSB0aGUgY29kZSBvZiB0aGlzIGFuZApwcmV2aW91cyBm dW5jdGlvbiBpbiBvcmRlciB0byByZXVzZSBjb2RlIGJldHdlZW4gdGhlbS4gVGhpcyBmdW5jdGlv biB3YXMgYSBsYXN0Cm1pbnV0ZSBhZGRlZCBmZWF0dXJlIDopLgoKPiAKPj4gK3N0YXRpYyB2b2lk IGR3X2VkbWFfZG9uZV9pbnRlcnJ1cHQoc3RydWN0IGR3X2VkbWFfY2hhbiAqY2hhbikKPj4gK3sK Pj4gKwlzdHJ1Y3QgZHdfZWRtYSAqZHcgPSBjaGFuLT5jaGlwLT5kdzsKPj4gKwljb25zdCBzdHJ1 Y3QgZHdfZWRtYV9jb3JlX29wcyAqb3BzID0gZHctPm9wczsKPj4gKwlzdHJ1Y3QgdmlydF9kbWFf ZGVzYyAqdmQ7Cj4+ICsJc3RydWN0IGR3X2VkbWFfZGVzYyAqZGVzYzsKPj4gKwl1bnNpZ25lZCBs b25nIGZsYWdzOwo+PiArCj4+ICsJb3BzLT5jbGVhcl9kb25lX2ludChjaGFuKTsKPj4gKwlkZXZf ZGJnKGNoYW4yZGV2KGNoYW4pLCAiY2xlYXIgZG9uZSBpbnRlcnJ1cHRcbiIpOwo+PiArCj4+ICsJ c3Bpbl9sb2NrX2lycXNhdmUoJmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsKPj4gKwl2ZCA9IHZjaGFu X25leHRfZGVzYygmY2hhbi0+dmMpOwo+PiArCXN3aXRjaCAoY2hhbi0+cmVxdWVzdCkgewo+PiAr CWNhc2UgRURNQV9SRVFfTk9ORToKPj4gKwkJaWYgKCF2ZCkKPj4gKwkJCWJyZWFrOwo+PiArCj4+ ICsJCWRlc2MgPSB2ZDJkd19lZG1hX2Rlc2ModmQpOwo+PiArCQlpZiAoZGVzYy0+Y2h1bmtzX2Fs bG9jKSB7Cj4+ICsJCQlkZXZfZGJnKGNoYW4yZGV2KGNoYW4pLCAic3ViLXRyYW5zZmVyIGNvbXBs ZXRlXG4iKTsKPj4gKwkJCWNoYW4tPnN0YXR1cyA9IEVETUFfU1RfQlVTWTsKPj4gKwkJCWRldl9k YmcoY2hhbjJkZXYoY2hhbiksICJ0cmFuc2ZlcnJlZCAldSBieXRlc1xuIiwKPj4gKwkJCQlkZXNj LT54ZmVyX3N6KTsKPj4gKwkJCWR3X2VkbWFfc3RhcnRfdHJhbnNmZXIoY2hhbik7Cj4+ICsJCX0g ZWxzZSB7Cj4+ICsJCQlsaXN0X2RlbCgmdmQtPm5vZGUpOwo+PiArCQkJdmNoYW5fY29va2llX2Nv bXBsZXRlKHZkKTsKPj4gKwkJCWNoYW4tPnN0YXR1cyA9IEVETUFfU1RfSURMRTsKPj4gKwkJCWRl dl9kYmcoY2hhbjJkZXYoY2hhbiksICJ0cmFuc2ZlciBjb21wbGV0ZVxuIik7Cj4+ICsJCX0KPj4g KwkJYnJlYWs7Cj4+ICsJY2FzZSBFRE1BX1JFUV9TVE9QOgo+PiArCQlpZiAoIXZkKQo+PiArCQkJ YnJlYWs7Cj4+ICsKPj4gKwkJbGlzdF9kZWwoJnZkLT5ub2RlKTsKPj4gKwkJdmNoYW5fY29va2ll X2NvbXBsZXRlKHZkKTsKPj4gKwkJY2hhbi0+cmVxdWVzdCA9IEVETUFfUkVRX05PTkU7Cj4+ICsJ CWNoYW4tPnN0YXR1cyA9IEVETUFfU1RfSURMRTsKPj4gKwkJY2hhbi0+Y29uZmlndXJlZCA9IGZh bHNlOwo+IAo+IHdoeSBpcyBjb25maWd1cmF0aW9uIGRlZW1lZCBpbnZhbGlkLCBpdCBjYW4gc3Rp bGwgYmUgdXNlZCBhZ2FpbiEKCkF0IHRoZSB0aW1lIEkgdGhvdWdodCwgdGhhdCB3YXMgbmVjZXNz YXJ5IHRvIHJlY29uZmlndXJlIGV2ZXJ5IHRpbWUgdGhhdCB3ZQpyZXF1aXJlZCB0byBkbyBhIG5l dyB0cmFuc2Zlci4gWW91IGFscmVhZHkgZXhwbGFpbmVkIHRvIG1lIHRoYXQgaXMgbm90Cm5lY2Vz c2FyeS4gTXkgYmFkIQoKPiAKPj4gK2ludCBkd19lZG1hX3Byb2JlKHN0cnVjdCBkd19lZG1hX2No aXAgKmNoaXApCj4+ICt7Cj4+ICsJc3RydWN0IGR3X2VkbWEgKmR3ID0gY2hpcC0+ZHc7Cj4+ICsJ c3RydWN0IGRldmljZSAqZGV2ID0gY2hpcC0+ZGV2Owo+PiArCWNvbnN0IHN0cnVjdCBkd19lZG1h X2NvcmVfb3BzICpvcHM7Cj4+ICsJc2l6ZV90IGxsX2NodW5rID0gZHctPmxsX3JlZ2lvbi5zejsK Pj4gKwlzaXplX3QgZHRfY2h1bmsgPSBkdy0+ZHRfcmVnaW9uLnN6Owo+PiArCXUzMiBjaF90b3Q7 Cj4+ICsJaW50IGksIGosIGVycjsKPj4gKwo+PiArCXJhd19zcGluX2xvY2tfaW5pdCgmZHctPmxv Y2spOwo+PiArCj4+ICsJLyogQ2FsbGJhY2sgb3BlcmF0aW9uIHNlbGVjdGlvbiBhY2NvcmRpbmds eSB0byBlRE1BIHZlcnNpb24gKi8KPj4gKwlzd2l0Y2ggKGR3LT52ZXJzaW9uKSB7Cj4+ICsJZGVm YXVsdDoKPj4gKwkJZGV2X2VycihkZXYsICJ1bnN1cHBvcnRlZCB2ZXJzaW9uXG4iKTsKPj4gKwkJ cmV0dXJuIC1FUEVSTTsKPj4gKwl9Cj4gCj4gU28gd2UgaGF2ZSBvbmx5IG9uZSBjYXNlIHdoaWNo IHJldHVybnMgZXJyb3IsIHdhcyB0aGlzIGNvZGUgdGVzdGVkPwoKWWVzIGl0IHdhcywgYnV0IEkg dW5kZXJzdGFuZCB3aGF0IHlvdXIgcG9pbnQgb2Ygdmlldy4KVGhpcyB3YXMgZG9uZSBsaWtlIHRo aXMsIGJlY2F1c2UgSSB3YW5uYSB0byBzZWdtZW50IHRoZSBwYXRjaCBzZXJpZXMgbGlrZSB0aGlz OgogMSkgQWRkaW5nIGVETUEgZHJpdmVyIGNvcmUsIHdoaWNoIGNvbnRhaW5zIHRoZSBkcml2ZXIg c2tlbGV0b24gYW5kIHRoZSB3aG9sZQpsb2dpYyBhc3NvY2lhdGVkLgogMikgYW5kIDMpIEFkZGlu ZyB0aGUgY2FsbGJhY2tzIGZvciB0aGUgZURNQSByZWdpc3RlciBtYXBwaW5nIHZlcnNpb24gMCAo aXQgd2lsbAphcHBlYXIgaW4gdGhlIGZ1dHVyZSBhIG5ldyB2ZXJzaW9uLCBJIHRob3VnaHQgdGhh dCB0aGlzIG5ldyB2ZXJzaW9uIHdvdWxkIGNhbWUKd2hpbGUgSSB3YXMgdHJ5aW5nIHRvIGdldCB0 aGUgZmVlZGJhY2sgYWJvdXQgdGhpcyBwYXRjaCBzZXJpZXMsIHRoZXJlZm9yZSB3b3VsZApoYXZl IGFub3RoZXIgMiBwYXRjaGVzIGZvciB0aGUgdmVyc2lvbiAxIGlzb2xhdGVkIGFuZCBpbmRlcGVu ZGVudCBmcm9tIHRoZQp2ZXJzaW9uIDApLgogNCkgYW5kIDUpIEFkZGluZyB0aGUgUENJZSBnbHVl LWxvZ2ljIGFuZCBkZXZpY2UgSUQgYXNzb2NpYXRlZC4KIDYpIEFkZGluZyBtYWludGFpbmVyIGZv ciB0aGlzIGRyaXZlci4KIDcpIEFkZGluZyBhIHRlc3QgZHJpdmVyLgoKU2luY2UgdGhpcyBzd2l0 Y2ggd2lsbCBvbmx5IGhhdmUgdGhlIGFzc29jaWF0ZWQgY2FzZSBvbiBwYXRjaCAyLCB0aGF0IHdo eSBvbgpwYXRjaCAxIGRvZXNuJ3QgYXBwZWFyIGFueSBwb3NzaWJpbGl0eS4KCklmIHlvdSBmZWVs IGxvZ2ljIHRvIHNxdWFzaCBwYXRjaCAyIHdpdGggcGF0Y2ggMSwganVzdCBzYXkgc29tZXRoaW5n IGFuZCBJJ2xsIGRvCml0IGZvciB5b3UgOikKCj4gCj4+ICsKPj4gKwlwbV9ydW50aW1lX2dldF9z eW5jKGRldik7Cj4+ICsKPj4gKwkvKiBGaW5kIG91dCBob3cgbWFueSB3cml0ZSBjaGFubmVscyBh cmUgc3VwcG9ydGVkIGJ5IGhhcmR3YXJlICovCj4+ICsJZHctPndyX2NoX2NudCA9IG9wcy0+Y2hf Y291bnQoZHcsIEVETUFfRElSX1dSSVRFKTsKPj4gKwlpZiAoIWR3LT53cl9jaF9jbnQpIHsKPj4g KwkJZGV2X2VycihkZXYsICJpbnZhbGlkIG51bWJlciBvZiB3cml0ZSBjaGFubmVscygwKVxuIik7 Cj4+ICsJCXJldHVybiAtRUlOVkFMOwo+PiArCX0KPj4gKwo+PiArCS8qIEZpbmQgb3V0IGhvdyBt YW55IHJlYWQgY2hhbm5lbHMgYXJlIHN1cHBvcnRlZCBieSBoYXJkd2FyZSAqLwo+PiArCWR3LT5y ZF9jaF9jbnQgPSBvcHMtPmNoX2NvdW50KGR3LCBFRE1BX0RJUl9SRUFEKTsKPj4gKwlpZiAoIWR3 LT5yZF9jaF9jbnQpIHsKPj4gKwkJZGV2X2VycihkZXYsICJpbnZhbGlkIG51bWJlciBvZiByZWFk IGNoYW5uZWxzKDApXG4iKTsKPj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4+ICsJfQo+PiArCj4+ICsJ ZGV2X2RiZyhkZXYsICJDaGFubmVsczpcdHdyaXRlPSVkLCByZWFkPSVkXG4iLAo+PiArCQlkdy0+ d3JfY2hfY250LCBkdy0+cmRfY2hfY250KTsKPj4gKwo+PiArCWNoX3RvdCA9IGR3LT53cl9jaF9j bnQgKyBkdy0+cmRfY2hfY250Owo+PiArCj4+ICsJLyogQWxsb2NhdGUgY2hhbm5lbHMgKi8KPj4g Kwlkdy0+Y2hhbiA9IGRldm1fa2NhbGxvYyhkZXYsIGNoX3RvdCwgc2l6ZW9mKCpkdy0+Y2hhbiks IEdGUF9LRVJORUwpOwo+IAo+IHlvdSBtYXkgdXNlIHN0cnVjdF9zaXplKCkgaGVyZQoKSHVtLCB0 aGlzIHdvdWxkIGJlIHVzZWZ1bCBpZiBJIHdhbnRlZCB0byBhbGxvY2F0ZSB0aGUgZHcgc3RydWN0 IGFzIHdlbGwsIHJpZ2h0PwpTaW5jZSBkdyBzdHJ1Y3QgaXMgYWxyZWFkeSBhbGxvY2F0ZWQsIGl0 IGxvb2tzIGxpa2UgdGhpcyBjYW4ndCBiZSB1c2VkLCBvciBhbSBJCm1pc3Npbmcgc29tZXRoaW5n PwoKPiAKPj4gKwlpZiAoIWR3LT5jaGFuKQo+PiArCQlyZXR1cm4gLUVOT01FTTsKPj4gKwo+PiAr CS8qIENhbGN1bGF0ZSB0aGUgbGlua2VkIGxpc3QgY2h1bmsgZm9yIGVhY2ggY2hhbm5lbCAqLwo+ PiArCWxsX2NodW5rIC89IHJvdW5kdXBfcG93X29mX3R3byhjaF90b3QpOwo+PiArCj4+ICsJLyog Q2FsY3VsYXRlIHRoZSBsaW5rZWQgbGlzdCBjaHVuayBmb3IgZWFjaCBjaGFubmVsICovCj4+ICsJ ZHRfY2h1bmsgLz0gcm91bmR1cF9wb3dfb2ZfdHdvKGNoX3RvdCk7Cj4+ICsKPj4gKwkvKiBEaXNh YmxlIGVETUEsIG9ubHkgdG8gZXN0YWJsaXNoIHRoZSBpZGVhbCBpbml0aWFsIGNvbmRpdGlvbnMg Ki8KPj4gKwlvcHMtPm9mZihkdyk7Cj4+ICsKPj4gKwlzbnByaW50Zihkdy0+bmFtZSwgc2l6ZW9m KGR3LT5uYW1lKSwgImR3LWVkbWEtY29yZTolZCIsIGNoaXAtPmlkKTsKPj4gKwo+PiArCS8qIFJl cXVlc3QgSVJRcyAqLwo+PiArCWlmIChkdy0+bnJfaXJxcyAhPSAxKSB7Cj4+ICsJCWRldl9lcnIo ZGV2LCAiaW52YWxpZCBudW1iZXIgb2YgaXJxcyAoJXUpXG4iLCBkdy0+bnJfaXJxcyk7Cj4+ICsJ CXJldHVybiAtRUlOVkFMOwo+PiArCX0KPj4gKwo+PiArCWZvciAoaSA9IDA7IGkgPCBkdy0+bnJf aXJxczsgaSsrKSB7Cj4+ICsJCWVyciA9IGRldm1fcmVxdWVzdF9pcnEoZGV2LCBwY2lfaXJxX3Zl Y3Rvcih0b19wY2lfZGV2KGRldiksIGkpLAo+PiArCQkJCSAgICAgICBkd19lZG1hX2ludGVycnVw dF9hbGwsCj4+ICsJCQkJICAgICAgIElSUUZfU0hBUkVELCBkdy0+bmFtZSwgY2hpcCk7Cj4+ICsJ CWlmIChlcnIpCj4+ICsJCQlyZXR1cm4gZXJyOwo+PiArCX0KPj4gKwo+PiArCS8qIENyZWF0ZSB3 cml0ZSBjaGFubmVscyAqLwo+PiArCUlOSVRfTElTVF9IRUFEKCZkdy0+d3JfZWRtYS5jaGFubmVs cyk7Cj4+ICsJZm9yIChpID0gMDsgaSA8IGR3LT53cl9jaF9jbnQ7IGkrKykgewo+PiArCQlzdHJ1 Y3QgZHdfZWRtYV9jaGFuICpjaGFuID0gJmR3LT5jaGFuW2ldOwo+PiArCQlzdHJ1Y3QgZHdfZWRt YV9yZWdpb24gKmR0X3JlZ2lvbjsKPj4gKwo+PiArCQlkdF9yZWdpb24gPSBkZXZtX2t6YWxsb2Mo ZGV2LCBzaXplb2YoKmR0X3JlZ2lvbiksIEdGUF9LRVJORUwpOwo+PiArCQlpZiAoIWR0X3JlZ2lv bikKPj4gKwkJCXJldHVybiAtRU5PTUVNOwo+PiArCj4+ICsJCWNoYW4tPnZjLmNoYW4ucHJpdmF0 ZSA9IGR0X3JlZ2lvbjsKPj4gKwo+PiArCQljaGFuLT5jaGlwID0gY2hpcDsKPj4gKwkJY2hhbi0+ aWQgPSBpOwo+PiArCQljaGFuLT5kaXIgPSBFRE1BX0RJUl9XUklURTsKPj4gKwkJY2hhbi0+Y29u ZmlndXJlZCA9IGZhbHNlOwo+PiArCQljaGFuLT5yZXF1ZXN0ID0gRURNQV9SRVFfTk9ORTsKPj4g KwkJY2hhbi0+c3RhdHVzID0gRURNQV9TVF9JRExFOwo+PiArCj4+ICsJCWNoYW4tPmxsX29mZiA9 IChsbF9jaHVuayAqIGkpOwo+PiArCQljaGFuLT5sbF9tYXggPSAobGxfY2h1bmsgLyBFRE1BX0xM X1NaKSAtIDE7Cj4+ICsKPj4gKwkJY2hhbi0+ZHRfb2ZmID0gKGR0X2NodW5rICogaSk7Cj4+ICsK Pj4gKwkJZGV2X2RiZyhkZXYsICJMLiBMaXN0Olx0Q2hhbm5lbCB3cml0ZVsldV0gb2ZmPTB4JS44 bHgsIG1heF9jbnQ9JXVcbiIsCj4+ICsJCQlpLCBjaGFuLT5sbF9vZmYsIGNoYW4tPmxsX21heCk7 Cj4+ICsKPj4gKwkJbWVtY3B5KCZjaGFuLT5tc2ksICZkdy0+bXNpWzBdLCBzaXplb2YoY2hhbi0+ bXNpKSk7Cj4+ICsKPj4gKwkJZGV2X2RiZyhkZXYsICJNU0k6XHRcdENoYW5uZWwgd3JpdGVbJXVd IGFkZHI9MHglLjh4JS44eCwgZGF0YT0weCUuOHhcbiIsCj4+ICsJCQlpLCBjaGFuLT5tc2kuYWRk cmVzc19oaSwgY2hhbi0+bXNpLmFkZHJlc3NfbG8sCj4+ICsJCQljaGFuLT5tc2kuZGF0YSk7Cj4+ ICsKPj4gKwkJY2hhbi0+dmMuZGVzY19mcmVlID0gdmNoYW5fZnJlZV9kZXNjOwo+PiArCQl2Y2hh bl9pbml0KCZjaGFuLT52YywgJmR3LT53cl9lZG1hKTsKPj4gKwo+PiArCQlkdF9yZWdpb24tPnBh ZGRyID0gZHctPmR0X3JlZ2lvbi5wYWRkciArIGNoYW4tPmR0X29mZjsKPj4gKwkJZHRfcmVnaW9u LT52YWRkciA9IGR3LT5kdF9yZWdpb24udmFkZHIgKyBjaGFuLT5kdF9vZmY7Cj4+ICsJCWR0X3Jl Z2lvbi0+c3ogPSBkdF9jaHVuazsKPj4gKwo+PiArCQlkZXZfZGJnKGRldiwgIkRhdGE6XHRDaGFu bmVsIHdyaXRlWyV1XSBvZmY9MHglLjhseFxuIiwKPj4gKwkJCWksIGNoYW4tPmR0X29mZik7Cj4+ ICsJfQo+PiArCWRtYV9jYXBfemVybyhkdy0+d3JfZWRtYS5jYXBfbWFzayk7Cj4+ICsJZG1hX2Nh cF9zZXQoRE1BX1NMQVZFLCBkdy0+d3JfZWRtYS5jYXBfbWFzayk7Cj4+ICsJZG1hX2NhcF9zZXQo RE1BX0NZQ0xJQywgZHctPndyX2VkbWEuY2FwX21hc2spOwo+PiArCWR3LT53cl9lZG1hLmRpcmVj dGlvbnMgPSBCSVQoRE1BX0RFVl9UT19NRU0pOwo+PiArCWR3LT53cl9lZG1hLmNoYW5jbnQgPSBk dy0+d3JfY2hfY250Owo+PiArCj4+ICsJLyogQ3JlYXRlIHJlYWQgY2hhbm5lbHMgKi8KPj4gKwlJ TklUX0xJU1RfSEVBRCgmZHctPnJkX2VkbWEuY2hhbm5lbHMpOwo+PiArCWZvciAoaiA9IDA7IGog PCBkdy0+cmRfY2hfY250OyBqKyssIGkrKykgewo+PiArCQlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpj aGFuID0gJmR3LT5jaGFuW2ldOwo+PiArCQlzdHJ1Y3QgZHdfZWRtYV9yZWdpb24gKmR0X3JlZ2lv bjsKPj4gKwo+PiArCQlkdF9yZWdpb24gPSBkZXZtX2t6YWxsb2MoZGV2LCBzaXplb2YoKmR0X3Jl Z2lvbiksIEdGUF9LRVJORUwpOwo+PiArCQlpZiAoIWR0X3JlZ2lvbikKPj4gKwkJCXJldHVybiAt RU5PTUVNOwo+PiArCj4+ICsJCWNoYW4tPnZjLmNoYW4ucHJpdmF0ZSA9IGR0X3JlZ2lvbjsKPj4g Kwo+PiArCQljaGFuLT5jaGlwID0gY2hpcDsKPj4gKwkJY2hhbi0+aWQgPSBqOwo+PiArCQljaGFu LT5kaXIgPSBFRE1BX0RJUl9SRUFEOwo+PiArCQljaGFuLT5jb25maWd1cmVkID0gZmFsc2U7Cj4+ ICsJCWNoYW4tPnJlcXVlc3QgPSBFRE1BX1JFUV9OT05FOwo+PiArCQljaGFuLT5zdGF0dXMgPSBF RE1BX1NUX0lETEU7Cj4+ICsKPj4gKwkJY2hhbi0+bGxfb2ZmID0gKGxsX2NodW5rICogaSk7Cj4+ ICsJCWNoYW4tPmxsX21heCA9IChsbF9jaHVuayAvIEVETUFfTExfU1opIC0gMTsKPj4gKwo+PiAr CQljaGFuLT5kdF9vZmYgPSAoZHRfY2h1bmsgKiBpKTsKPj4gKwo+PiArCQlkZXZfZGJnKGRldiwg IkwuIExpc3Q6XHRDaGFubmVsIHJlYWRbJXVdIG9mZj0weCUuOGx4LCBtYXhfY250PSV1XG4iLAo+ PiArCQkJaiwgY2hhbi0+bGxfb2ZmLCBjaGFuLT5sbF9tYXgpOwo+PiArCj4+ICsJCW1lbWNweSgm Y2hhbi0+bXNpLCAmZHctPm1zaVswXSwgc2l6ZW9mKGNoYW4tPm1zaSkpOwo+PiArCj4+ICsJCWRl dl9kYmcoZGV2LCAiTVNJOlx0XHRDaGFubmVsIHJlYWRbJXVdIGFkZHI9MHglLjh4JS44eCwgZGF0 YT0weCUuOHhcbiIsCj4+ICsJCQlqLCBjaGFuLT5tc2kuYWRkcmVzc19oaSwgY2hhbi0+bXNpLmFk ZHJlc3NfbG8sCj4+ICsJCQljaGFuLT5tc2kuZGF0YSk7Cj4+ICsKPj4gKwkJY2hhbi0+dmMuZGVz Y19mcmVlID0gdmNoYW5fZnJlZV9kZXNjOwo+PiArCQl2Y2hhbl9pbml0KCZjaGFuLT52YywgJmR3 LT5yZF9lZG1hKTsKPj4gKwo+PiArCQlkdF9yZWdpb24tPnBhZGRyID0gZHctPmR0X3JlZ2lvbi5w YWRkciArIGNoYW4tPmR0X29mZjsKPj4gKwkJZHRfcmVnaW9uLT52YWRkciA9IGR3LT5kdF9yZWdp b24udmFkZHIgKyBjaGFuLT5kdF9vZmY7Cj4+ICsJCWR0X3JlZ2lvbi0+c3ogPSBkdF9jaHVuazsK Pj4gKwo+PiArCQlkZXZfZGJnKGRldiwgIkRhdGE6XHRDaGFubmVsIHJlYWRbJXVdIG9mZj0weCUu OGx4XG4iLAo+PiArCQkJaSwgY2hhbi0+ZHRfb2ZmKTsKPiAKPiB0aGlzIGlzIHNpbWlsYXIgdG8g cHJldmlvdXMgd2l0aCBvYnZpb3VzIGNoYW5nZXMsIEkgdGhpbmsgdGhpcyBjYW4gYmUKPiBtYWRl IGNvbW1vbiByb3V0aW5lIGludm9rZSBmb3IgUiBhbmQgVyAuLi4KCk9LLCBJIGNhbiByZXdyaXRl IHRoZSBjb2RlIHRvIHNpbXBsaWZ5IHRoaXMuCgo+IAo+IFNvIEhXIHByb3ZpZGVzIHJlYWQgY2hh bm5lbHMgYW5kIHdyaXRlIGNoYW5uZWxzIGFuZCBub3QgZ2VuZXJpYyBjaGFubmVscwo+IHdoaWNo IGNhbiBiZSB1c2VkIGZvciBlaXRoZXIgUiBvciBXPwo+IAoKVGhlIEhXLCBwcm92aWRlcyBhIHdl bGwgZGVmaW5lZCBjaGFubmVscywgd2l0aCBkaWZmZXJlbnQgcmVnaXN0ZXJzIHNldHMuCkluaXRp YWxseSBJIHRob3VnaHQgdG8gbWFza2FyZWQgaXQsIGJ1dCBzaW5jZSB0aGUgbnVtYmVyIG9mIGNo YW5uZWxzIGNhbiBiZQpjbGllbnQgY29uZmlndXJhYmxlIFswLi44XSBmb3IgZWFjaCB0eXBlIG9m IGNoYW5uZWwgYW5kIGFsc28gYXN5bW1ldHJpYyAod3JpdGUKdnMgcmVhZCksIEkgcHJlZmVyIHRv IGtlcHQgdGhlbiBzZXBhcmF0ZWQuCgoKT25jZSBhZ2FpbiwgdGhhbmtzIFZpbm9kIQo= 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=-1.1 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SPF_PASS, URIBL_BLOCKED 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 D6FB6C2F421 for ; Mon, 21 Jan 2019 15:55:25 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 8FF5620823 for ; Mon, 21 Jan 2019 15:55:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=synopsys.com header.i=@synopsys.com header.b="jPCSeC5g" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729712AbfAUPzZ (ORCPT ); Mon, 21 Jan 2019 10:55:25 -0500 Received: from smtprelay.synopsys.com ([198.182.60.111]:54340 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728761AbfAUPzY (ORCPT ); Mon, 21 Jan 2019 10:55:24 -0500 Received: from mailhost.synopsys.com (dc2-mailhost.synopsys.com [10.12.135.161]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtprelay.synopsys.com (Postfix) with ESMTPS id F0E4610C1101; Mon, 21 Jan 2019 07:55:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1548086124; bh=ALFOt9hd1dJV63poYd9hMBaxvVLTmN4V4hlzCFEpy4M=; h=Subject:To:CC:References:From:Date:In-Reply-To:From; b=jPCSeC5gpTfrbwQ46l/vXbm4spQuG0frc8HzCidKpUfqN6O8j1T1YA1gkPv54aOFg cFlIANwQ90zMo//Sitkz0JGXKmKo9drV+Z+C95jxgtk6wkyaZT80QbTyGhzzyTOFJv 6Lr6y1zxrC4WCD4MqRIGDRJ31liGmY0gvfYuioMw4Kp9zrMwBiMvWhHk8OPkqi0Vlm cvA5MjNccnafEoBWSa8I+fTzFI4pT37ESW61aG0BYzuGWv738lSWStXKZB+Gg1hoi/ RLQXhDLRBlQCSNXMk1NnT8a/pdcpSXCerpbnSet7/tlUwI34mwS3PMKy4WzXgP33sN ydqwlzLHuu0zA== Received: from us01wehtc1.internal.synopsys.com (us01wehtc1-vip.internal.synopsys.com [10.12.239.236]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mailhost.synopsys.com (Postfix) with ESMTPS id 805E3A0407; Mon, 21 Jan 2019 15:55:23 +0000 (UTC) Received: from DE02WEHTCB.internal.synopsys.com (10.225.19.94) by us01wehtc1.internal.synopsys.com (10.12.239.235) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 21 Jan 2019 07:53:01 -0800 Received: from DE02WEHTCA.internal.synopsys.com (10.225.19.92) by DE02WEHTCB.internal.synopsys.com (10.225.19.94) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 21 Jan 2019 16:52:59 +0100 Received: from [10.107.25.131] (10.107.25.131) by DE02WEHTCA.internal.synopsys.com (10.225.19.80) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 21 Jan 2019 16:52:58 +0100 Subject: Re: [RFC v3 1/7] dmaengine: Add Synopsys eDMA IP core driver To: Vinod Koul , Gustavo Pimentel CC: "linux-pci@vger.kernel.org" , "dmaengine@vger.kernel.org" , Dan Williams , Eugeniy Paltsev , Andy Shevchenko , Russell King , Niklas Cassel , Joao Pinto , Jose Abreu , Luis Oliveira , Vitor Soares , Nelson Costa , Pedro Sousa References: <20190120114425.GV4635@vkoul-mobl> From: Gustavo Pimentel Message-ID: <14acfcee-b367-be9c-714b-de0508ff1a7d@synopsys.com> Date: Mon, 21 Jan 2019 15:48:14 +0000 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.4.0 MIME-Version: 1.0 In-Reply-To: <20190120114425.GV4635@vkoul-mobl> Content-Type: text/plain; charset="utf-8" Content-Language: en-US Content-Transfer-Encoding: 7bit X-Originating-IP: [10.107.25.131] Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org On 20/01/2019 11:44, Vinod Koul wrote: > On 11-01-19, 19:33, Gustavo Pimentel wrote: >> 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. > > A description of eDMA IP will help review the driver I've the IP description on the cover-letter, but I'll bring it to this patch, if it helps. > >> 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: > > These do not belong to change log, either move them to cover-letter or > keep them after s-o-b lines.. Ok, Andy has also referred that. I'll keep them after s-o-b lines. > >> @@ -0,0 +1,1059 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> +/* >> + * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates. > > 2019 now I've changed to "Copyright (c) 2018-present Synopsys, Inc. and/or its affiliates." this way it's always up to date and I also kept 2018, because it was the date that I started to develop this driver, if you don't mind. > >> +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 = kvzalloc(sizeof(*burst), GFP_NOWAIT); > > Is there a specific reason for kvzalloc(), do you submit this to HW.. There is not reason for that, it were remains of an initial implementation. I'll replace them by kzalloc. Nicely spotted! > >> +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 = kvzalloc(sizeof(*chunk), GFP_NOWAIT); >> + if (unlikely(!chunk)) >> + return NULL; >> + >> + INIT_LIST_HEAD(&chunk->list); >> + chunk->chan = chan; >> + chunk->cb = !(desc->chunks_alloc % 2); > > cb ..? CB = change bit, is a property of this eDMA IP. Basically it is a kind of handshake which serves to validate whether the linked list has been updated or not, especially useful in cases of recycled linked list elements (every linked list recycle is a new chunk, this will allow to differentiate each chunk). > >> +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->status != EDMA_ST_IDLE) { >> + dev_err(chan2dev(chan), "channel is busy or paused\n"); >> + err = -EPERM; > > this is not correct behaviour, device_config can be called anytime and > values can take affect on next transaction submitted.. Hum, I thought we could only reconfigure after transfer being finished. > >> + goto err_config; >> + } >> + >> + dev_dbg(chan2dev(chan), "addr(physical) src=%pa, dst=%pa\n", >> + &config->src_addr, &config->dst_addr); >> + >> + chan->src_addr = config->src_addr; >> + chan->dst_addr = config->dst_addr; >> + >> + err = ops->device_config(dchan); > > what does this do? This is an initialization procedure to setup interrupts (data and addresses) to each channel on the eDMA IP, in order to be triggered after transfer being completed or aborted. Due the fact the config() can be called at anytime, doesn't make sense to have this procedure here, I'll moved it to probe(). > >> +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; > > so in this case you set residue as zero, which is not correct Ok, the residue should be the remaining bytes to transfer, right? > >> + } else { >> + /* DMA_COMPLETE */ >> + if (chan->status == EDMA_ST_PAUSE) >> + ret = DMA_PAUSED; >> + else if (chan->status == EDMA_ST_BUSY) >> + ret = DMA_IN_PROGRESS; > > ?? if txn is complete how are you returning DMA_IN_PROGRESS? This IP reports DMA_COMPLETE when it successfully completes the transfer of all linked list elements, given that there may be even more elements of the linked list to be transferred the overall state is set to DMA_IN_PROGRESS. > >> + else >> + ret = DMA_COMPLETE; >> + } > > this looks incorrect interpretation to me. The status is to be retrieved > for the given cookie passed and given that you do not even use this > argument tells me that you have understood this as 'channel' status > reporting, which is not correct Yes, you're right, my interpretation assumes this function reports channel/transaction status. What would be the correct implementation? Something like this? { struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); const struct dw_edma_core_ops *ops = chan2ops(chan); struct dw_edma_desc *desc; struct virt_dma_desc *vd; unsigned long flags; enum dma_status ret; u32 residue = 0; spin_lock_irqsave(&chan->vc.lock, flags); ret = dma_cookie_status(chan, cookie, txstate); if (ret == DMA_COMPLETE) goto ret_status; vd = vchan_next_desc(&chan->vc); if (!vd) goto ret_status; desc = vd2dw_edma_desc(vd); if (!desc) residue = desc->alloc_sz - desc->xfer_sz; if (ret == DMA_IN_PROGRESS && chan->status == EDMA_ST_PAUSE) ret = DMA_PAUSED; ret_status: spin_unlock_irqrestore(&chan->vc.lock, flags); dma_set_residue(txstate, residue); 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; >> + unsigned long sflags; >> + phys_addr_t src_addr; >> + phys_addr_t dst_addr; >> + 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) { > > what is the second part of the check, can you explain that, who sets > chan->dir? The chan->dir is set on probe() during the process of configuring each channel. > >> + 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(chan2dev(chan), "(prep_slave_sg) channel not configured\n"); >> + return NULL; >> + } >> + >> + if (chan->status != EDMA_ST_IDLE) { >> + dev_err(chan2dev(chan), "channel is busy or paused\n"); >> + return NULL; >> + } > > No, wrong again. The txn must be prepared and then on submit added to a > queue. You are writing a driver for dmaengine, surely you dont expect > the channel to be free and then do a txn.. that would be very > inefficient! I did not realize that the flow could be as you mentioned. The documentation I read about the subsystem did not give me this idea. Thank you for clarifying me. > >> +static struct dma_async_tx_descriptor * >> +dw_edma_device_prep_dma_cyclic(struct dma_chan *dchan, dma_addr_t buf_addr, >> + size_t len, size_t cyclic_cnt, >> + enum dma_transfer_direction direction, >> + unsigned long flags) >> +{ >> + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); >> + struct dw_edma_desc *desc; >> + struct dw_edma_chunk *chunk; >> + struct dw_edma_burst *burst; >> + unsigned long sflags; >> + phys_addr_t src_addr; >> + phys_addr_t dst_addr; >> + u32 i; >> + >> + if (!len || !cyclic_cnt) { >> + dev_err(chan2dev(chan), "invalid len or cyclic count\n"); >> + 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(chan2dev(chan), "(prep_dma_cyclic) channel not configured\n"); >> + return NULL; >> + } >> + >> + if (chan->status != EDMA_ST_IDLE) { >> + 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; >> + >> + src_addr = chan->src_addr; >> + dst_addr = chan->dst_addr; >> + >> + for (i = 0; i < cyclic_cnt; 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; >> + >> + burst->sz = len; >> + chunk->ll_region.sz += burst->sz; >> + desc->alloc_sz += burst->sz; >> + >> + burst->sar = src_addr; >> + burst->dar = dst_addr; >> + >> + dev_dbg(chan2dev(chan), "lli %u/%u, sar=0x%.8llx, dar=0x%.8llx, size=%u bytes\n", >> + i + 1, cyclic_cnt, burst->sar, burst->dar, burst->sz); >> + } >> + >> + spin_unlock_irqrestore(&chan->vc.lock, sflags); >> + return vchan_tx_prep(&chan->vc, &desc->vd, flags); > > how is it different from previous? am sure we can reuse bits! There are some differences, but I agree I can rewrite the code of this and previous function in order to reuse code between them. This function was a last minute added feature :). > >> +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: >> + if (!vd) >> + break; >> + >> + 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: >> + if (!vd) >> + break; >> + >> + list_del(&vd->node); >> + vchan_cookie_complete(vd); >> + chan->request = EDMA_REQ_NONE; >> + chan->status = EDMA_ST_IDLE; >> + chan->configured = false; > > why is configuration deemed invalid, it can still be used again! At the time I thought, that was necessary to reconfigure every time that we required to do a new transfer. You already explained to me that is not necessary. My bad! > >> +int dw_edma_probe(struct dw_edma_chip *chip) >> +{ >> + struct dw_edma *dw = chip->dw; >> + struct device *dev = chip->dev; >> + const struct dw_edma_core_ops *ops; >> + size_t ll_chunk = dw->ll_region.sz; >> + size_t dt_chunk = dw->dt_region.sz; >> + u32 ch_tot; >> + int i, j, err; >> + >> + raw_spin_lock_init(&dw->lock); >> + >> + /* Callback operation selection accordingly to eDMA version */ >> + switch (dw->version) { >> + default: >> + dev_err(dev, "unsupported version\n"); >> + return -EPERM; >> + } > > So we have only one case which returns error, was this code tested? Yes it was, but I understand what your point of view. This was done like this, because I wanna to segment the patch series like this: 1) Adding eDMA driver core, which contains the driver skeleton and the whole logic associated. 2) and 3) Adding the callbacks for the eDMA register mapping version 0 (it will appear in the future a new version, I thought that this new version would came while I was trying to get the feedback about this patch series, therefore would have another 2 patches for the version 1 isolated and independent from the version 0). 4) and 5) Adding the PCIe glue-logic and device ID associated. 6) Adding maintainer for this driver. 7) Adding a test driver. Since this switch will only have the associated case on patch 2, that why on patch 1 doesn't appear any possibility. If you feel logic to squash patch 2 with patch 1, just say something and I'll do it for you :) > >> + >> + pm_runtime_get_sync(dev); >> + >> + /* Find out how many write channels are supported by hardware */ >> + dw->wr_ch_cnt = ops->ch_count(dw, EDMA_DIR_WRITE); >> + if (!dw->wr_ch_cnt) { >> + dev_err(dev, "invalid number of write channels(0)\n"); >> + return -EINVAL; >> + } >> + >> + /* Find out how many read channels are supported by hardware */ >> + dw->rd_ch_cnt = ops->ch_count(dw, EDMA_DIR_READ); >> + if (!dw->rd_ch_cnt) { >> + dev_err(dev, "invalid number of read channels(0)\n"); >> + return -EINVAL; >> + } >> + >> + dev_dbg(dev, "Channels:\twrite=%d, read=%d\n", >> + dw->wr_ch_cnt, dw->rd_ch_cnt); >> + >> + ch_tot = dw->wr_ch_cnt + dw->rd_ch_cnt; >> + >> + /* Allocate channels */ >> + dw->chan = devm_kcalloc(dev, ch_tot, sizeof(*dw->chan), GFP_KERNEL); > > you may use struct_size() here Hum, this would be useful if I wanted to allocate the dw struct as well, right? Since dw struct is already allocated, it looks like this can't be used, or am I missing something? > >> + if (!dw->chan) >> + return -ENOMEM; >> + >> + /* Calculate the linked list chunk for each channel */ >> + ll_chunk /= roundup_pow_of_two(ch_tot); >> + >> + /* Calculate the linked list chunk for each channel */ >> + dt_chunk /= roundup_pow_of_two(ch_tot); >> + >> + /* Disable eDMA, only to establish the ideal initial conditions */ >> + ops->off(dw); >> + >> + snprintf(dw->name, sizeof(dw->name), "dw-edma-core:%d", chip->id); >> + >> + /* Request IRQs */ >> + if (dw->nr_irqs != 1) { >> + dev_err(dev, "invalid number of irqs (%u)\n", dw->nr_irqs); >> + return -EINVAL; >> + } >> + >> + for (i = 0; i < dw->nr_irqs; i++) { >> + err = devm_request_irq(dev, pci_irq_vector(to_pci_dev(dev), i), >> + dw_edma_interrupt_all, >> + IRQF_SHARED, dw->name, chip); >> + if (err) >> + return err; >> + } >> + >> + /* Create write channels */ >> + INIT_LIST_HEAD(&dw->wr_edma.channels); >> + for (i = 0; i < dw->wr_ch_cnt; i++) { >> + struct dw_edma_chan *chan = &dw->chan[i]; >> + struct dw_edma_region *dt_region; >> + >> + 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 = 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 / EDMA_LL_SZ) - 1; >> + >> + chan->dt_off = (dt_chunk * i); >> + >> + dev_dbg(dev, "L. List:\tChannel write[%u] off=0x%.8lx, max_cnt=%u\n", >> + i, chan->ll_off, chan->ll_max); >> + >> + memcpy(&chan->msi, &dw->msi[0], sizeof(chan->msi)); >> + >> + dev_dbg(dev, "MSI:\t\tChannel write[%u] addr=0x%.8x%.8x, data=0x%.8x\n", >> + i, chan->msi.address_hi, chan->msi.address_lo, >> + chan->msi.data); >> + >> + chan->vc.desc_free = vchan_free_desc; >> + vchan_init(&chan->vc, &dw->wr_edma); >> + >> + 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_dbg(dev, "Data:\tChannel write[%u] off=0x%.8lx\n", >> + i, chan->dt_off); >> + } >> + dma_cap_zero(dw->wr_edma.cap_mask); >> + dma_cap_set(DMA_SLAVE, dw->wr_edma.cap_mask); >> + dma_cap_set(DMA_CYCLIC, dw->wr_edma.cap_mask); >> + dw->wr_edma.directions = BIT(DMA_DEV_TO_MEM); >> + dw->wr_edma.chancnt = dw->wr_ch_cnt; >> + >> + /* Create read channels */ >> + INIT_LIST_HEAD(&dw->rd_edma.channels); >> + for (j = 0; j < dw->rd_ch_cnt; j++, i++) { >> + struct dw_edma_chan *chan = &dw->chan[i]; >> + struct dw_edma_region *dt_region; >> + >> + 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 = 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_dbg(dev, "L. List:\tChannel read[%u] off=0x%.8lx, max_cnt=%u\n", >> + j, chan->ll_off, chan->ll_max); >> + >> + memcpy(&chan->msi, &dw->msi[0], sizeof(chan->msi)); >> + >> + dev_dbg(dev, "MSI:\t\tChannel read[%u] addr=0x%.8x%.8x, data=0x%.8x\n", >> + j, chan->msi.address_hi, chan->msi.address_lo, >> + chan->msi.data); >> + >> + chan->vc.desc_free = vchan_free_desc; >> + vchan_init(&chan->vc, &dw->rd_edma); >> + >> + 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_dbg(dev, "Data:\tChannel read[%u] off=0x%.8lx\n", >> + i, chan->dt_off); > > this is similar to previous with obvious changes, I think this can be > made common routine invoke for R and W ... OK, I can rewrite the code to simplify this. > > So HW provides read channels and write channels and not generic channels > which can be used for either R or W? > The HW, provides a well defined channels, with different registers sets. Initially I thought to maskared it, but since the number of channels can be client configurable [0..8] for each type of channel and also asymmetric (write vs read), I prefer to kept then separated. Once again, thanks Vinod!