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,v5,1/6] dmaengine: Add Synopsys eDMA IP core driver From: Andy Shevchenko Message-Id: <20190211184944.GH9224@smile.fi.intel.com> Date: Mon, 11 Feb 2019 20:49:44 +0200 To: Gustavo Pimentel Cc: linux-pci@vger.kernel.org, dmaengine@vger.kernel.org, Vinod Koul , Dan Williams , Eugeniy Paltsev , Russell King , Niklas Cassel , Joao Pinto , Jose Abreu , Luis Oliveira , Vitor Soares , Nelson Costa , Pedro Sousa List-ID: T24gTW9uLCBGZWIgMTEsIDIwMTkgYXQgMDY6MzQ6MzBQTSArMDEwMCwgR3VzdGF2byBQaW1lbnRl bCB3cm90ZToKPiBBZGQgU3lub3BzeXMgUENJZSBFbmRwb2ludCBlRE1BIElQIGNvcmUgZHJpdmVy IHRvIGtlcm5lbC4KPiAKPiBUaGlzIElQIGlzIGdlbmVyYWxseSBkaXN0cmlidXRlZCB3aXRoIFN5 bm9wc3lzIFBDSWUgRW5kcG9pbnQgSVAgKGRlcGVuZHMKPiBvZiB0aGUgdXNlIGFuZCBsaWNlbnNp bmcgYWdyZWVtZW50KS4KPiAKPiBUaGlzIGNvcmUgZHJpdmVyLCBpbml0aWFsaXplcyBhbmQgY29u ZmlndXJlcyB0aGUgZURNQSBJUCB1c2luZyB2bWEtaGVscGVycwo+IGZ1bmN0aW9ucyBhbmQgZG1h LWVuZ2luZSBzdWJzeXN0ZW0uCj4gCj4gVGhpcyBkcml2ZXIgY2FuIGJlIGNvbXBpbGUgYXMgYnVp bHQtaW4gb3IgZXh0ZXJuYWwgbW9kdWxlIGluIGtlcm5lbC4KPiAKPiBUbyBlbmFibGUgdGhpcyBk cml2ZXIganVzdCBzZWxlY3QgRFdfRURNQSBvcHRpb24gaW4ga2VybmVsIGNvbmZpZ3VyYXRpb24s Cj4gaG93ZXZlciBpdCByZXF1aXJlcyBhbmQgc2VsZWN0cyBhdXRvbWF0aWNhbGx5IERNQV9FTkdJ TkUgYW5kCj4gRE1BX1ZJUlRVQUxfQ0hBTk5FTFMgb3B0aW9uIHRvby4KCkZpcnN0IGNvbW1lbnQg aGVyZSBpcyB0aGF0OiB0cnkgdG8gc2hyaW5rIHlvdXIgY29kZSBiYXNlIGJ5IGxldCdzIHNheSAx NSUuCkkgYmVsaWV2ZSBzb21ldGhpbmcgaGVyZSBpcyBkb25lIGlzIHN1Ym9wdGltYWwgd2F5IG9y IGRvZXNuJ3QgdGFrZSBpbnRvCmNvbnNpZGVyYXRpb24gZXhpc3RpbmcgZmFjaWxpdGllcyBpbiB0 aGUga2VybmVsLgoKPiArc3RhdGljIHZvaWQgZHdfZWRtYV9mcmVlX2NodW5rKHN0cnVjdCBkd19l ZG1hX2Rlc2MgKmRlc2MpCj4gK3sKPiArCXN0cnVjdCBkd19lZG1hX2NoYW4gKmNoYW4gPSBkZXNj LT5jaGFuOwo+ICsJc3RydWN0IGR3X2VkbWFfY2h1bmsgKmNoaWxkLCAqX25leHQ7Cj4gKwoKPiAr CWlmICghZGVzYy0+Y2h1bmspCj4gKwkJcmV0dXJuOwoKSXMgaXQgbmVjZXNzYXJ5IGNoZWNrPyBX aHk/Cgo+ICsKPiArCS8qIFJlbW92ZSBhbGwgdGhlIGxpc3QgZWxlbWVudHMgKi8KPiArCWxpc3Rf Zm9yX2VhY2hfZW50cnlfc2FmZShjaGlsZCwgX25leHQsICZkZXNjLT5jaHVuay0+bGlzdCwgbGlz dCkgewo+ICsJCWR3X2VkbWFfZnJlZV9idXJzdChjaGlsZCk7Cj4gKwkJaWYgKGNoaWxkLT5idXJz dHNfYWxsb2MpCj4gKwkJCWRldl9kYmcoY2hhbjJkZXYoY2hhbiksCSIldSBidXJzdHMgc3RpbGwg YWxsb2NhdGVkXG4iLAo+ICsJCQkJY2hpbGQtPmJ1cnN0c19hbGxvYyk7Cj4gKwkJbGlzdF9kZWwo JmNoaWxkLT5saXN0KTsKPiArCQlrZnJlZShjaGlsZCk7Cj4gKwkJZGVzYy0+Y2h1bmtzX2FsbG9j LS07Cj4gKwl9Cj4gKwo+ICsJLyogUmVtb3ZlIHRoZSBsaXN0IGhlYWQgKi8KPiArCWtmcmVlKGNo aWxkKTsKPiArCWRlc2MtPmNodW5rID0gTlVMTDsKPiArfQoKPiArc3RhdGljIGludCBkd19lZG1h X2RldmljZV9jb25maWcoc3RydWN0IGRtYV9jaGFuICpkY2hhbiwKPiArCQkJCSBzdHJ1Y3QgZG1h X3NsYXZlX2NvbmZpZyAqY29uZmlnKQo+ICt7Cj4gKwlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFu ID0gZGNoYW4yZHdfZWRtYV9jaGFuKGRjaGFuKTsKPiArCXVuc2lnbmVkIGxvbmcgZmxhZ3M7Cj4g KwlpbnQgZXJyID0gMDsKPiArCj4gKwlzcGluX2xvY2tfaXJxc2F2ZSgmY2hhbi0+dmMubG9jaywg ZmxhZ3MpOwo+ICsKCj4gKwlpZiAoIWNvbmZpZykgewo+ICsJCWVyciA9IC1FSU5WQUw7Cj4gKwkJ Z290byBlcnJfY29uZmlnOwo+ICsJfQoKSXMgaXQgbmVjZXNzYXJ5IGNoZWNrPyBXaHk/CgpXaHkg dGhpcyBpcyB1bmRlciBzcGluIGxvY2s/Cgo+ICsJZGV2X2RiZyhjaGFuMmRldihjaGFuKSwgImFk ZHIocGh5c2ljYWwpIHNyYz0lcGEsIGRzdD0lcGFcbiIsCj4gKwkJJmNvbmZpZy0+c3JjX2FkZHIs ICZjb25maWctPmRzdF9hZGRyKTsKCkFuZCB0aGlzLgoKV2hhdCBkbyB5b3UgcHJvdGVjdCBieSBs b2Nrcz8gQ2hlY2sgYWxsIHlvdXIgbG9ja2luZyBjYXJlZnVsbHkuCgo+ICsKPiArCWNoYW4tPnNy Y19hZGRyID0gY29uZmlnLT5zcmNfYWRkcjsKPiArCWNoYW4tPmRzdF9hZGRyID0gY29uZmlnLT5k c3RfYWRkcjsKPiArCj4gKwljaGFuLT5jb25maWd1cmVkID0gdHJ1ZTsKPiArCWRldl9kYmcoY2hh bjJkZXYoY2hhbiksCSJjaGFubmVsIGNvbmZpZ3VyZWRcbiIpOwo+ICsKPiArZXJyX2NvbmZpZzoK PiArCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsKPiArCXJl dHVybiBlcnI7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgZHdfZWRtYV9kZXZpY2VfcGF1c2Uoc3Ry dWN0IGRtYV9jaGFuICpkY2hhbikKPiArewo+ICsJc3RydWN0IGR3X2VkbWFfY2hhbiAqY2hhbiA9 IGRjaGFuMmR3X2VkbWFfY2hhbihkY2hhbik7Cj4gKwl1bnNpZ25lZCBsb25nIGZsYWdzOwo+ICsJ aW50IGVyciA9IDA7Cj4gKwo+ICsJc3Bpbl9sb2NrX2lycXNhdmUoJmNoYW4tPnZjLmxvY2ssIGZs YWdzKTsKPiArCj4gKwlpZiAoIWNoYW4tPmNvbmZpZ3VyZWQpIHsKCj4gKwkJZGV2X2VycihjaGFu MmRldihjaGFuKSwgIihwYXVzZSkgY2hhbm5lbCBub3QgY29uZmlndXJlZFxuIik7CgpXaHkgdGhp cyBpcyB1bmRlciBzcGlubG9jaz8KCj4gKwkJZXJyID0gLUVQRVJNOwo+ICsJCWdvdG8gZXJyX3Bh dXNlOwo+ICsJfQo+ICsKPiArCWlmIChjaGFuLT5zdGF0dXMgIT0gRURNQV9TVF9CVVNZKSB7Cj4g KwkJZXJyID0gLUVQRVJNOwo+ICsJCWdvdG8gZXJyX3BhdXNlOwo+ICsJfQo+ICsKPiArCWlmIChj aGFuLT5yZXF1ZXN0ICE9IEVETUFfUkVRX05PTkUpIHsKPiArCQllcnIgPSAtRVBFUk07Cj4gKwkJ Z290byBlcnJfcGF1c2U7Cj4gKwl9Cj4gKwo+ICsJY2hhbi0+cmVxdWVzdCA9IEVETUFfUkVRX1BB VVNFOwoKPiArCWRldl9kYmcoY2hhbjJkZXYoY2hhbiksICJwYXVzZSByZXF1ZXN0ZWRcbiIpOwoK RGl0dG8uCgpNb3Jlb3ZlciwgY2hlY2sgd2hhdCBmdW5jdGlvbmFsIHRyYWNlciBjYW4gcHJvdmlk ZSB5b3UgZm9yIGRlYnVnZ2luZy4KCj4gKwo+ICtlcnJfcGF1c2U6Cj4gKwlzcGluX3VubG9ja19p cnFyZXN0b3JlKCZjaGFuLT52Yy5sb2NrLCBmbGFncyk7Cj4gKwlyZXR1cm4gZXJyOwo+ICt9Cgo+ ICt7Cj4gKwlzdHJ1Y3QgZHdfZWRtYV9jaGFuICpjaGFuID0gZGNoYW4yZHdfZWRtYV9jaGFuKGRj aGFuKTsKPiArCXN0cnVjdCBkd19lZG1hX2Rlc2MgKmRlc2M7Cj4gKwlzdHJ1Y3QgdmlydF9kbWFf ZGVzYyAqdmQ7Cj4gKwl1bnNpZ25lZCBsb25nIGZsYWdzOwo+ICsJZW51bSBkbWFfc3RhdHVzIHJl dDsKPiArCXUzMiByZXNpZHVlID0gMDsKPiArCj4gKwlyZXQgPSBkbWFfY29va2llX3N0YXR1cyhk Y2hhbiwgY29va2llLCB0eHN0YXRlKTsKPiArCWlmIChyZXQgPT0gRE1BX0NPTVBMRVRFKQo+ICsJ CXJldHVybiByZXQ7Cj4gKwoKPiArCWlmICghdHhzdGF0ZSkKPiArCQlyZXR1cm4gcmV0OwoKU28s IGlmIHRoZXJlIGlzIG5vIHR4c3RhdGUsIHlvdSBjYW4ndCByZXR1cm4gUEFVU0VEIHN0YXRlPyBX aHk/Cgo+ICsKPiArCXNwaW5fbG9ja19pcnFzYXZlKCZjaGFuLT52Yy5sb2NrLCBmbGFncyk7Cj4g Kwo+ICsJaWYgKHJldCA9PSBETUFfSU5fUFJPR1JFU1MgJiYgY2hhbi0+c3RhdHVzID09IEVETUFf U1RfUEFVU0UpCj4gKwkJcmV0ID0gRE1BX1BBVVNFRDsKPiArCj4gKwl2ZCA9IHZjaGFuX2ZpbmRf ZGVzYygmY2hhbi0+dmMsIGNvb2tpZSk7Cj4gKwlpZiAoIXZkKQo+ICsJCWdvdG8gcmV0X3N0YXR1 czsKPiArCj4gKwlkZXNjID0gdmQyZHdfZWRtYV9kZXNjKHZkKTsKPiArCWlmIChkZXNjKQo+ICsJ CXJlc2lkdWUgPSBkZXNjLT5hbGxvY19zeiAtIGRlc2MtPnhmZXJfc3o7Cj4gKwo+ICtyZXRfc3Rh dHVzOgo+ICsJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmY2hhbi0+dmMubG9jaywgZmxhZ3MpOwo+ ICsJZG1hX3NldF9yZXNpZHVlKHR4c3RhdGUsIHJlc2lkdWUpOwo+ICsKPiArCXJldHVybiByZXQ7 Cj4gK30KCj4gKwlmb3IgKGkgPSAwOyBpIDwgY250OyBpKyspIHsKPiArCQlpZiAoIXhmZXItPmN5 Y2xpYyAmJiAhc2cpCj4gKwkJCWJyZWFrOwo+ICsKPiArCQlpZiAoY2h1bmstPmJ1cnN0c19hbGxv YyA9PSBjaGFuLT5sbF9tYXgpIHsKPiArCQkJY2h1bmsgPSBkd19lZG1hX2FsbG9jX2NodW5rKGRl c2MpOwo+ICsJCQlpZiAodW5saWtlbHkoIWNodW5rKSkKPiArCQkJCWdvdG8gZXJyX2FsbG9jOwo+ ICsJCX0KPiArCj4gKwkJYnVyc3QgPSBkd19lZG1hX2FsbG9jX2J1cnN0KGNodW5rKTsKPiArCj4g KwkJaWYgKHVubGlrZWx5KCFidXJzdCkpCj4gKwkJCWdvdG8gZXJyX2FsbG9jOwo+ICsKPiArCQlp ZiAoeGZlci0+Y3ljbGljKQo+ICsJCQlidXJzdC0+c3ogPSB4ZmVyLT54ZmVyLmN5Y2xpYy5sZW47 Cj4gKwkJZWxzZQo+ICsJCQlidXJzdC0+c3ogPSBzZ19kbWFfbGVuKHNnKTsKPiArCj4gKwkJY2h1 bmstPmxsX3JlZ2lvbi5zeiArPSBidXJzdC0+c3o7Cj4gKwkJZGVzYy0+YWxsb2Nfc3ogKz0gYnVy c3QtPnN6Owo+ICsKPiArCQlpZiAoZGlyZWN0aW9uID09IERNQV9ERVZfVE9fTUVNKSB7Cj4gKwkJ CWJ1cnN0LT5zYXIgPSBzcmNfYWRkcjsKPiArCQkJaWYgKHhmZXItPmN5Y2xpYykgewo+ICsJCQkJ YnVyc3QtPmRhciA9IHhmZXItPnhmZXIuY3ljbGljLnBhZGRyOwo+ICsJCQl9IGVsc2Ugewo+ICsJ CQkJYnVyc3QtPmRhciA9IHNnX2RtYV9hZGRyZXNzKHNnKTsKPiArCQkJCXNyY19hZGRyICs9IHNn X2RtYV9sZW4oc2cpOwo+ICsJCQl9Cj4gKwkJfSBlbHNlIHsKPiArCQkJYnVyc3QtPmRhciA9IGRz dF9hZGRyOwo+ICsJCQlpZiAoeGZlci0+Y3ljbGljKSB7Cj4gKwkJCQlidXJzdC0+c2FyID0geGZl ci0+eGZlci5jeWNsaWMucGFkZHI7Cj4gKwkJCX0gZWxzZSB7Cj4gKwkJCQlidXJzdC0+c2FyID0g c2dfZG1hX2FkZHJlc3Moc2cpOwo+ICsJCQkJZHN0X2FkZHIgKz0gc2dfZG1hX2xlbihzZyk7Cj4g KwkJCX0KPiArCQl9Cj4gKwo+ICsJCWRldl9kYmcoY2hhbjJkZXYoY2hhbiksICJsbGkgJXUvJXUs IHNhcj0weCUuOGxseCwgZGFyPTB4JS44bGx4LCBzaXplPSV1IGJ5dGVzXG4iLAo+ICsJCQlpICsg MSwgY250LCBidXJzdC0+c2FyLCBidXJzdC0+ZGFyLCBidXJzdC0+c3opOwo+ICsKPiArCQlpZiAo IXhmZXItPmN5Y2xpYykKPiArCQkJc2cgPSBzZ19uZXh0KHNnKTsKClNob3VsZG4ndCB5b3UgcmF0 aGVyIHRvIHVzZSBmb3JfZWFjaF9zZygpPwoKPiArCX0KCgo+ICsJc3Bpbl9sb2NrX2lycXNhdmUo JmNoYW4tPnZjLmxvY2ssIGZsYWdzKTsKPiArCXZkID0gdmNoYW5fbmV4dF9kZXNjKCZjaGFuLT52 Yyk7Cj4gKwlzd2l0Y2ggKGNoYW4tPnJlcXVlc3QpIHsKPiArCWNhc2UgRURNQV9SRVFfTk9ORToK Cj4gKwkJaWYgKCF2ZCkKPiArCQkJYnJlYWs7CgpTaG91bGRuJ3QgYmUgb3V0c2lkZSBvZiBzd2l0 Y2g/Cgo+ICsKPiArCQlkZXNjID0gdmQyZHdfZWRtYV9kZXNjKHZkKTsKPiArCQlpZiAoZGVzYy0+ Y2h1bmtzX2FsbG9jKSB7Cj4gKwkJCWRldl9kYmcoY2hhbjJkZXYoY2hhbiksICJzdWItdHJhbnNm ZXIgY29tcGxldGVcbiIpOwo+ICsJCQljaGFuLT5zdGF0dXMgPSBFRE1BX1NUX0JVU1k7Cj4gKwkJ CWRldl9kYmcoY2hhbjJkZXYoY2hhbiksICJ0cmFuc2ZlcnJlZCAldSBieXRlc1xuIiwKPiArCQkJ CWRlc2MtPnhmZXJfc3opOwo+ICsJCQlkd19lZG1hX3N0YXJ0X3RyYW5zZmVyKGNoYW4pOwo+ICsJ CX0gZWxzZSB7Cj4gKwkJCWxpc3RfZGVsKCZ2ZC0+bm9kZSk7Cj4gKwkJCXZjaGFuX2Nvb2tpZV9j b21wbGV0ZSh2ZCk7Cj4gKwkJCWNoYW4tPnN0YXR1cyA9IEVETUFfU1RfSURMRTsKPiArCQkJZGV2 X2RiZyhjaGFuMmRldihjaGFuKSwgInRyYW5zZmVyIGNvbXBsZXRlXG4iKTsKPiArCQl9Cj4gKwkJ YnJlYWs7Cj4gKwljYXNlIEVETUFfUkVRX1NUT1A6Cj4gKwkJaWYgKCF2ZCkKPiArCQkJYnJlYWs7 Cj4gKwo+ICsJCWxpc3RfZGVsKCZ2ZC0+bm9kZSk7Cj4gKwkJdmNoYW5fY29va2llX2NvbXBsZXRl KHZkKTsKPiArCQljaGFuLT5yZXF1ZXN0ID0gRURNQV9SRVFfTk9ORTsKPiArCQljaGFuLT5zdGF0 dXMgPSBFRE1BX1NUX0lETEU7Cj4gKwkJZGV2X2RiZyhjaGFuMmRldihjaGFuKSwgInRyYW5zZmVy IHN0b3BcbiIpOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBFRE1BX1JFUV9QQVVTRToKPiArCQljaGFu LT5yZXF1ZXN0ID0gRURNQV9SRVFfTk9ORTsKPiArCQljaGFuLT5zdGF0dXMgPSBFRE1BX1NUX1BB VVNFOwo+ICsJCWJyZWFrOwo+ICsJZGVmYXVsdDoKPiArCQlkZXZfZXJyKGNoYW4yZGV2KGNoYW4p LCAiaW52YWxpZCBzdGF0dXMgc3RhdGVcbiIpOwo+ICsJCWJyZWFrOwo+ICsJfQo+ICsJc3Bpbl91 bmxvY2tfaXJxcmVzdG9yZSgmY2hhbi0+dmMubG9jaywgZmxhZ3MpOwo+ICt9Cgo+ICtzdGF0aWMg aXJxcmV0dXJuX3QgZHdfZWRtYV9pbnRlcnJ1cHQoaW50IGlycSwgdm9pZCAqZGF0YSwgYm9vbCB3 cml0ZSkKPiArewo+ICsJc3RydWN0IGR3X2VkbWFfaXJxICpkd19pcnEgPSBkYXRhOwo+ICsJc3Ry dWN0IGR3X2VkbWEgKmR3ID0gZHdfaXJxLT5kdzsKPiArCXVuc2lnbmVkIGxvbmcgdG90YWwsIHBv cywgdmFsOwo+ICsJdW5zaWduZWQgbG9uZyBvZmY7Cj4gKwl1MzIgbWFzazsKPiArCj4gKwlpZiAo d3JpdGUpIHsKPiArCQl0b3RhbCA9IGR3LT53cl9jaF9jbnQ7Cj4gKwkJb2ZmID0gMDsKPiArCQlt YXNrID0gZHdfaXJxLT53cl9tYXNrOwo+ICsJfSBlbHNlIHsKPiArCQl0b3RhbCA9IGR3LT5yZF9j aF9jbnQ7Cj4gKwkJb2ZmID0gZHctPndyX2NoX2NudDsKPiArCQltYXNrID0gZHdfaXJxLT5yZF9t YXNrOwo+ICsJfQo+ICsKPiArCXBvcyA9IDA7Cj4gKwl2YWwgPSBkd19lZG1hX3YwX2NvcmVfc3Rh dHVzX2RvbmVfaW50KGR3LCB3cml0ZSA/Cj4gKwkJCQkJICAgICAgRURNQV9ESVJfV1JJVEUgOgo+ ICsJCQkJCSAgICAgIEVETUFfRElSX1JFQUQpOwo+ICsJdmFsICY9IG1hc2s7Cj4gKwl3aGlsZSAo KHBvcyA9IGZpbmRfbmV4dF9iaXQoJnZhbCwgdG90YWwsIHBvcykpICE9IHRvdGFsKSB7CgpJcyB0 aGlzIGZ1bm55IHZlcnNpb24gb2YgZm9yX2VhY2hfc2V0X2JpdCgpPwoKPiArCQlzdHJ1Y3QgZHdf ZWRtYV9jaGFuICpjaGFuID0gJmR3LT5jaGFuW3BvcyArIG9mZl07Cj4gKwo+ICsJCWR3X2VkbWFf ZG9uZV9pbnRlcnJ1cHQoY2hhbik7Cj4gKwkJcG9zKys7Cj4gKwl9Cj4gKwo+ICsJcG9zID0gMDsK PiArCXZhbCA9IGR3X2VkbWFfdjBfY29yZV9zdGF0dXNfYWJvcnRfaW50KGR3LCB3cml0ZSA/Cj4g KwkJCQkJICAgICAgIEVETUFfRElSX1dSSVRFIDoKPiArCQkJCQkgICAgICAgRURNQV9ESVJfUkVB RCk7Cj4gKwl2YWwgJj0gbWFzazsKCj4gKwl3aGlsZSAoKHBvcyA9IGZpbmRfbmV4dF9iaXQoJnZh bCwgdG90YWwsIHBvcykpICE9IHRvdGFsKSB7CgpEaXR0by4KCj4gKwkJc3RydWN0IGR3X2VkbWFf Y2hhbiAqY2hhbiA9ICZkdy0+Y2hhbltwb3MgKyBvZmZdOwo+ICsKPiArCQlkd19lZG1hX2Fib3J0 X2ludGVycnVwdChjaGFuKTsKPiArCQlwb3MrKzsKPiArCX0KPiArCj4gKwlyZXR1cm4gSVJRX0hB TkRMRUQ7Cj4gK30KCj4gKwlkbyB7Cj4gKwkJcmV0ID0gZHdfZWRtYV9kZXZpY2VfdGVybWluYXRl X2FsbChkY2hhbik7Cj4gKwkJaWYgKCFyZXQpCj4gKwkJCWJyZWFrOwo+ICsKPiArCQlpZiAodGlt ZV9hZnRlcl9lcShqaWZmaWVzLCB0aW1lb3V0KSkgewo+ICsJCQlkZXZfZXJyKGNoYW4yZGV2KGNo YW4pLCAiZnJlZSB0aW1lb3V0XG4iKTsKPiArCQkJcmV0dXJuOwo+ICsJCX0KPiArCj4gKwkJY3B1 X3JlbGF4KCk7Cgo+ICsJfSB3aGlsZSAoMSk7CgpTbywgd2hhdCBwcmV2ZW50cyB5b3UgdG8gZG8g d2hpbGUgKHRpbWVfYmVmb3JlKC4uLikpOyBoZXJlPwoKPiArCj4gKwlkZXZfZGJnKGRjaGFuMmRl dihkY2hhbiksICJjaGFubmVsIGZyZWVkXG4iKTsKPiArCj4gKwlwbV9ydW50aW1lX3B1dChjaGFu LT5jaGlwLT5kZXYpOwo+ICt9Cgo+ICtzdGF0aWMgaW50IGR3X2VkbWFfY2hhbm5lbF9zZXR1cChz dHJ1Y3QgZHdfZWRtYV9jaGlwICpjaGlwLCBib29sIHdyaXRlLAo+ICsJCQkJIHUzMiB3cl9hbGxv YywgdTMyIHJkX2FsbG9jKQo+ICt7Cj4gKwlzdHJ1Y3QgZHdfZWRtYV9yZWdpb24gKmR0X3JlZ2lv bjsKPiArCXN0cnVjdCBkZXZpY2UgKmRldiA9IGNoaXAtPmRldjsKPiArCXN0cnVjdCBkd19lZG1h ICpkdyA9IGNoaXAtPmR3Owo+ICsJc3RydWN0IGR3X2VkbWFfY2hhbiAqY2hhbjsKPiArCXNpemVf dCBsbF9jaHVuaywgZHRfY2h1bms7Cj4gKwlzdHJ1Y3QgZHdfZWRtYV9pcnEgKmlycTsKPiArCXN0 cnVjdCBkbWFfZGV2aWNlICpkbWE7Cj4gKwl1MzIgaSwgaiwgY250LCBjaF9jbnQ7Cj4gKwl1MzIg YWxsb2MsIG9mZl9hbGxvYzsKPiArCWludCBlcnIgPSAwOwo+ICsJdTMyIHBvczsKPiArCj4gKwlj aF9jbnQgPSBkdy0+d3JfY2hfY250ICsgZHctPnJkX2NoX2NudDsKPiArCWxsX2NodW5rID0gZHct PmxsX3JlZ2lvbi5zejsKPiArCWR0X2NodW5rID0gZHctPmR0X3JlZ2lvbi5zejsKPiArCj4gKwkv KiBDYWxjdWxhdGUgbGlua2VkIGxpc3QgY2h1bmsgZm9yIGVhY2ggY2hhbm5lbCAqLwo+ICsJbGxf Y2h1bmsgLz0gcm91bmR1cF9wb3dfb2ZfdHdvKGNoX2NudCk7Cj4gKwo+ICsJLyogQ2FsY3VsYXRl IGxpbmtlZCBsaXN0IGNodW5rIGZvciBlYWNoIGNoYW5uZWwgKi8KPiArCWR0X2NodW5rIC89IHJv dW5kdXBfcG93X29mX3R3byhjaF9jbnQpOwoKPiArCUlOSVRfTElTVF9IRUFEKCZkbWEtPmNoYW5u ZWxzKTsKPiArCj4gKwlmb3IgKGogPSAwOyAoYWxsb2MgfHwgZHctPm5yX2lycXMgPT0gMSkgJiYg aiA8IGNudDsgaisrLCBpKyspIHsKPiArCQljaGFuID0gJmR3LT5jaGFuW2ldOwo+ICsKPiArCQlk dF9yZWdpb24gPSBkZXZtX2t6YWxsb2MoZGV2LCBzaXplb2YoKmR0X3JlZ2lvbiksIEdGUF9LRVJO RUwpOwo+ICsJCWlmICghZHRfcmVnaW9uKQo+ICsJCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwkJ Y2hhbi0+dmMuY2hhbi5wcml2YXRlID0gZHRfcmVnaW9uOwo+ICsKPiArCQljaGFuLT5jaGlwID0g Y2hpcDsKPiArCQljaGFuLT5pZCA9IGo7Cj4gKwkJY2hhbi0+ZGlyID0gd3JpdGUgPyBFRE1BX0RJ Ul9XUklURSA6IEVETUFfRElSX1JFQUQ7Cj4gKwkJY2hhbi0+Y29uZmlndXJlZCA9IGZhbHNlOwo+ ICsJCWNoYW4tPnJlcXVlc3QgPSBFRE1BX1JFUV9OT05FOwo+ICsJCWNoYW4tPnN0YXR1cyA9IEVE TUFfU1RfSURMRTsKPiArCj4gKwkJY2hhbi0+bGxfb2ZmID0gKGxsX2NodW5rICogaSk7Cj4gKwkJ Y2hhbi0+bGxfbWF4ID0gKGxsX2NodW5rIC8gRURNQV9MTF9TWikgLSAxOwo+ICsKPiArCQljaGFu LT5kdF9vZmYgPSAoZHRfY2h1bmsgKiBpKTsKPiArCj4gKwkJZGV2X2RiZyhkZXYsICJMLiBMaXN0 Olx0Q2hhbm5lbCAlc1sldV0gb2ZmPTB4JS44bHgsIG1heF9jbnQ9JXVcbiIsCj4gKwkJCXdyaXRl ID8gIndyaXRlIiA6ICJyZWFkIiwgaiwKPiArCQkJY2hhbi0+bGxfb2ZmLCBjaGFuLT5sbF9tYXgp Owo+ICsKPiArCQlpZiAoZHctPm5yX2lycXMgPT0gMSkKPiArCQkJcG9zID0gMDsKPiArCQllbHNl Cj4gKwkJCXBvcyA9IG9mZl9hbGxvYyArIChqICUgYWxsb2MpOwo+ICsKPiArCQlpcnEgPSAmZHct PmlycVtwb3NdOwo+ICsKPiArCQlpZiAod3JpdGUpCj4gKwkJCWlycS0+d3JfbWFzayB8PSBCSVQo aik7Cj4gKwkJZWxzZQo+ICsJCQlpcnEtPnJkX21hc2sgfD0gQklUKGopOwo+ICsKPiArCQlpcnEt PmR3ID0gZHc7Cj4gKwkJbWVtY3B5KCZjaGFuLT5tc2ksICZpcnEtPm1zaSwgc2l6ZW9mKGNoYW4t Pm1zaSkpOwo+ICsKPiArCQlkZXZfZGJnKGRldiwgIk1TSTpcdFx0Q2hhbm5lbCAlc1sldV0gYWRk cj0weCUuOHglLjh4LCBkYXRhPTB4JS44eFxuIiwKPiArCQkJd3JpdGUgPyAid3JpdGUiIDogInJl YWQiLCBqLAo+ICsJCQljaGFuLT5tc2kuYWRkcmVzc19oaSwgY2hhbi0+bXNpLmFkZHJlc3NfbG8s Cj4gKwkJCWNoYW4tPm1zaS5kYXRhKTsKPiArCj4gKwkJY2hhbi0+dmMuZGVzY19mcmVlID0gdmNo YW5fZnJlZV9kZXNjOwo+ICsJCXZjaGFuX2luaXQoJmNoYW4tPnZjLCBkbWEpOwo+ICsKPiArCQlk dF9yZWdpb24tPnBhZGRyID0gZHctPmR0X3JlZ2lvbi5wYWRkciArIGNoYW4tPmR0X29mZjsKPiAr CQlkdF9yZWdpb24tPnZhZGRyID0gZHctPmR0X3JlZ2lvbi52YWRkciArIGNoYW4tPmR0X29mZjsK PiArCQlkdF9yZWdpb24tPnN6ID0gZHRfY2h1bms7Cj4gKwo+ICsJCWRldl9kYmcoZGV2LCAiRGF0 YTpcdENoYW5uZWwgJXNbJXVdIG9mZj0weCUuOGx4XG4iLAo+ICsJCQl3cml0ZSA/ICJ3cml0ZSIg OiAicmVhZCIsIGosIGNoYW4tPmR0X29mZik7Cj4gKwo+ICsJCWR3X2VkbWFfdjBfY29yZV9kZXZp Y2VfY29uZmlnKGNoYW4pOwo+ICsJfQo+ICsKPiArCS8qIFNldCBETUEgY2hhbm5lbCBjYXBhYmls aXRpZXMgKi8KPiArCWRtYV9jYXBfemVybyhkbWEtPmNhcF9tYXNrKTsKPiArCWRtYV9jYXBfc2V0 KERNQV9TTEFWRSwgZG1hLT5jYXBfbWFzayk7Cj4gKwlkbWFfY2FwX3NldChETUFfQ1lDTElDLCBk bWEtPmNhcF9tYXNrKTsKCkRvZXNuJ3QgaXQgdXNlZCBmb3Igc2xhdmUgdHJhbnNmZXJzPwpETUFf UFJJVkFURSBpcyBnb29kIHRvIGJlIHNldCBmb3IgdGhpcy4KCj4gKwlyZXR1cm4gZXJyOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW5saW5lIHZvaWQgZHdfZWRtYV9kZWNfaXJxX2FsbG9jKGludCAqbnJf aXJxcywgdTMyICphbGxvYywgdTE2IGNudCkKPiArewo+ICsJaWYgKCpucl9pcnFzICYmICphbGxv YyA8IGNudCkgewo+ICsJCSgqYWxsb2MpKys7Cj4gKwkJKCpucl9pcnFzKS0tOwo+ICsJfQoKSSBk b24ndCBzZWUgYW55IGFsbG9jYXRpb24gaGVyZS4KCj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUg dm9pZCBkd19lZG1hX2FkZF9pcnFfbWFzayh1MzIgKm1hc2ssIHUzMiBhbGxvYywgdTE2IGNudCkK PiArewoKPiArCXdoaWxlICgqbWFzayAqIGFsbG9jIDwgY250KQo+ICsJCSgqbWFzaykrKzsKCkRv IHlvdSByZWFsbHkgbmVlZCBhIGxvb3AgaGVyZT8KCj4gK30KPiArCj4gK3N0YXRpYyBpbnQgZHdf ZWRtYV9pcnFfcmVxdWVzdChzdHJ1Y3QgZHdfZWRtYV9jaGlwICpjaGlwLAo+ICsJCQkgICAgICAg dTMyICp3cl9hbGxvYywgdTMyICpyZF9hbGxvYykKPiArewo+ICsJc3RydWN0IGRldmljZSAqZGV2 ID0gY2hpcC0+ZGV2Owo+ICsJc3RydWN0IGR3X2VkbWEgKmR3ID0gY2hpcC0+ZHc7Cj4gKwl1MzIg d3JfbWFzayA9IDE7Cj4gKwl1MzIgcmRfbWFzayA9IDE7Cj4gKwlpbnQgaSwgZXJyID0gMDsKPiAr CXUzMiBjaF9jbnQ7Cj4gKwo+ICsJY2hfY250ID0gZHctPndyX2NoX2NudCArIGR3LT5yZF9jaF9j bnQ7Cj4gKwo+ICsJaWYgKGR3LT5ucl9pcnFzIDwgMSkgewo+ICsJCWRldl9lcnIoZGV2LCAiaW52 YWxpZCBudW1iZXIgb2YgaXJxcyAoJXUpXG4iLCBkdy0+bnJfaXJxcyk7Cj4gKwkJcmV0dXJuIC1F SU5WQUw7Cj4gKwl9Cj4gKwo+ICsJaWYgKGR3LT5ucl9pcnFzID09IDEpIHsKPiArCQkvKiBDb21t b24gSVJRIHNoYXJlZCBhbW9uZyBhbGwgY2hhbm5lbHMgKi8KPiArCQllcnIgPSByZXF1ZXN0X2ly cShwY2lfaXJxX3ZlY3Rvcih0b19wY2lfZGV2KGRldiksIDApLAo+ICsJCQkJICBkd19lZG1hX2lu dGVycnVwdF9jb21tb24sCj4gKwkJCQkgIElSUUZfU0hBUkVELCBkdy0+bmFtZSwgJmR3LT5pcnFb MF0pOwo+ICsJCWlmIChlcnIpIHsKPiArCQkJZHctPm5yX2lycXMgPSAwOwo+ICsJCQlyZXR1cm4g ZXJyOwo+ICsJCX0KPiArCj4gKwkJZ2V0X2NhY2hlZF9tc2lfbXNnKHBjaV9pcnFfdmVjdG9yKHRv X3BjaV9kZXYoZGV2KSwgMCksCj4gKwkJCQkgICAmZHctPmlycVswXS5tc2kpOwoKQXJlIHlvdSBn b2luZyB0byBjYWxsIGVhY2ggdGltZSB0byBwY2lfaXJxX3ZlY3RvcigpPyBCdHcsIGFtIEkgbWlz c2VkIHBjaV9pcnFfYWxsb2MoKT8KCj4gKwl9IGVsc2UgewoKPiArCQkvKiBEaXN0cmlidXRlIElS UXMgZXF1YWxseSBhbW9uZyBhbGwgY2hhbm5lbHMgKi8KPiArCQlpbnQgdG1wID0gZHctPm5yX2ly cXM7CgpJcyBpdCBhbHdheXMgYWNoaWV2YWJsZT8KCj4gKwo+ICsJCXdoaWxlICh0bXAgJiYgKCp3 cl9hbGxvYyArICpyZF9hbGxvYykgPCBjaF9jbnQpIHsKPiArCQkJZHdfZWRtYV9kZWNfaXJxX2Fs bG9jKCZ0bXAsIHdyX2FsbG9jLCBkdy0+d3JfY2hfY250KTsKPiArCQkJZHdfZWRtYV9kZWNfaXJx X2FsbG9jKCZ0bXAsIHJkX2FsbG9jLCBkdy0+cmRfY2hfY250KTsKPiArCQl9Cj4gKwo+ICsJCWR3 X2VkbWFfYWRkX2lycV9tYXNrKCZ3cl9tYXNrLCAqd3JfYWxsb2MsIGR3LT53cl9jaF9jbnQpOwo+ ICsJCWR3X2VkbWFfYWRkX2lycV9tYXNrKCZyZF9tYXNrLCAqcmRfYWxsb2MsIGR3LT5yZF9jaF9j bnQpOwo+ICsKPiArCQlmb3IgKGkgPSAwOyBpIDwgKCp3cl9hbGxvYyArICpyZF9hbGxvYyk7IGkr Kykgewo+ICsJCQllcnIgPSByZXF1ZXN0X2lycShwY2lfaXJxX3ZlY3Rvcih0b19wY2lfZGV2KGRl diksIGkpLAo+ICsJCQkJCSAgaSA8ICp3cl9hbGxvYyA/Cj4gKwkJCQkJCWR3X2VkbWFfaW50ZXJy dXB0X3dyaXRlIDoKPiArCQkJCQkJZHdfZWRtYV9pbnRlcnJ1cHRfcmVhZCwKPiArCQkJCQkgIElS UUZfU0hBUkVELCBkdy0+bmFtZSwKPiArCQkJCQkgICZkdy0+aXJxW2ldKTsKPiArCQkJaWYgKGVy cikgewo+ICsJCQkJZHctPm5yX2lycXMgPSBpOwo+ICsJCQkJcmV0dXJuIGVycjsKPiArCQkJfQo+ ICsKPiArCQkJZ2V0X2NhY2hlZF9tc2lfbXNnKHBjaV9pcnFfdmVjdG9yKHRvX3BjaV9kZXYoZGV2 KSwgaSksCj4gKwkJCQkJICAgJmR3LT5pcnFbaV0ubXNpKTsKPiArCQl9Cj4gKwo+ICsJCWR3LT5u cl9pcnFzID0gaTsKPiArCX0KPiArCj4gKwlyZXR1cm4gZXJyOwo+ICt9Cj4gKwo+ICtpbnQgZHdf ZWRtYV9wcm9iZShzdHJ1Y3QgZHdfZWRtYV9jaGlwICpjaGlwKQo+ICt7Cj4gKwlzdHJ1Y3QgZGV2 aWNlICpkZXYgPSBjaGlwLT5kZXY7Cj4gKwlzdHJ1Y3QgZHdfZWRtYSAqZHcgPSBjaGlwLT5kdzsK PiArCXUzMiB3cl9hbGxvYyA9IDA7Cj4gKwl1MzIgcmRfYWxsb2MgPSAwOwo+ICsJaW50IGksIGVy cjsKPiArCj4gKwlyYXdfc3Bpbl9sb2NrX2luaXQoJmR3LT5sb2NrKTsKPiArCj4gKwkvKiBGaW5k IG91dCBob3cgbWFueSB3cml0ZSBjaGFubmVscyBhcmUgc3VwcG9ydGVkIGJ5IGhhcmR3YXJlICov Cj4gKwlkdy0+d3JfY2hfY250ID0gZHdfZWRtYV92MF9jb3JlX2NoX2NvdW50KGR3LCBFRE1BX0RJ Ul9XUklURSk7Cj4gKwlpZiAoIWR3LT53cl9jaF9jbnQpIHsKPiArCQlkZXZfZXJyKGRldiwgImlu dmFsaWQgbnVtYmVyIG9mIHdyaXRlIGNoYW5uZWxzKDApXG4iKTsKPiArCQlyZXR1cm4gLUVJTlZB TDsKPiArCX0KPiArCj4gKwkvKiBGaW5kIG91dCBob3cgbWFueSByZWFkIGNoYW5uZWxzIGFyZSBz dXBwb3J0ZWQgYnkgaGFyZHdhcmUgKi8KPiArCWR3LT5yZF9jaF9jbnQgPSBkd19lZG1hX3YwX2Nv cmVfY2hfY291bnQoZHcsIEVETUFfRElSX1JFQUQpOwo+ICsJaWYgKCFkdy0+cmRfY2hfY250KSB7 Cj4gKwkJZGV2X2VycihkZXYsICJpbnZhbGlkIG51bWJlciBvZiByZWFkIGNoYW5uZWxzKDApXG4i KTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlkZXZfZGJnKGRldiwgIkNoYW5u ZWxzOlx0d3JpdGU9JWQsIHJlYWQ9JWRcbiIsCj4gKwkJZHctPndyX2NoX2NudCwgZHctPnJkX2No X2NudCk7Cj4gKwo+ICsJLyogQWxsb2NhdGUgY2hhbm5lbHMgKi8KPiArCWR3LT5jaGFuID0gZGV2 bV9rY2FsbG9jKGRldiwgZHctPndyX2NoX2NudCArIGR3LT5yZF9jaF9jbnQsCj4gKwkJCQlzaXpl b2YoKmR3LT5jaGFuKSwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIWR3LT5jaGFuKQo+ICsJCXJldHVy biAtRU5PTUVNOwo+ICsKPiArCXNucHJpbnRmKGR3LT5uYW1lLCBzaXplb2YoZHctPm5hbWUpLCAi ZHctZWRtYS1jb3JlOiVkIiwgY2hpcC0+aWQpOwo+ICsKPiArCS8qIERpc2FibGUgZURNQSwgb25s eSB0byBlc3RhYmxpc2ggdGhlIGlkZWFsIGluaXRpYWwgY29uZGl0aW9ucyAqLwo+ICsJZHdfZWRt YV92MF9jb3JlX29mZihkdyk7Cj4gKwo+ICsJLyogUmVxdWVzdCBJUlFzICovCj4gKwllcnIgPSBk d19lZG1hX2lycV9yZXF1ZXN0KGNoaXAsICZ3cl9hbGxvYywgJnJkX2FsbG9jKTsKPiArCWlmIChl cnIpCj4gKwkJcmV0dXJuIGVycjsKPiArCgo+ICsJLyogU2V0dXAgd3JpdGUgY2hhbm5lbHMgKi8K PiArCWVyciA9IGR3X2VkbWFfY2hhbm5lbF9zZXR1cChjaGlwLCB0cnVlLCB3cl9hbGxvYywgcmRf YWxsb2MpOwo+ICsJaWYgKGVycikKPiArCQlnb3RvIGVycl9pcnFfZnJlZTsKPiArCj4gKwkvKiBT ZXR1cCByZWFkIGNoYW5uZWxzICovCj4gKwllcnIgPSBkd19lZG1hX2NoYW5uZWxfc2V0dXAoY2hp cCwgZmFsc2UsIHdyX2FsbG9jLCByZF9hbGxvYyk7Cj4gKwlpZiAoZXJyKQo+ICsJCWdvdG8gZXJy X2lycV9mcmVlOwoKSSB0aGluayB5b3UgbWF5IGxvb2sgaW50byBlcDkzeHggZHJpdmVyIHRvIHNl ZSBob3cgZGlmZmVyZW50IHR5cGUgb2YgY2hhbm5lbHMKYXJlIGFsbG9jYXRlZCBhbmQgYmUgc2V0 IHVwLgoKPiArCj4gKwkvKiBQb3dlciBtYW5hZ2VtZW50ICovCj4gKwlwbV9ydW50aW1lX2VuYWJs ZShkZXYpOwo+ICsKPiArCS8qIFR1cm4gZGVidWdmcyBvbiAqLwo+ICsJZXJyID0gZHdfZWRtYV92 MF9jb3JlX2RlYnVnZnNfb24oY2hpcCk7Cj4gKwlpZiAoZXJyKSB7Cj4gKwkJZGV2X2VycihkZXYs ICJ1bmFibGUgdG8gY3JlYXRlIGRlYnVnZnMgc3RydWN0dXJlXG4iKTsKPiArCQlnb3RvIGVycl9w bV9kaXNhYmxlOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICsKPiArZXJyX3BtX2Rpc2FibGU6 Cj4gKwlwbV9ydW50aW1lX2Rpc2FibGUoZGV2KTsKPiArZXJyX2lycV9mcmVlOgo+ICsJZm9yIChp ID0gKGR3LT5ucl9pcnFzIC0gMSk7IGkgPj0gMDsgaS0tKQo+ICsJCWZyZWVfaXJxKHBjaV9pcnFf dmVjdG9yKHRvX3BjaV9kZXYoZGV2KSwgaSksICZkdy0+aXJxW2ldKTsKPiArCj4gKwlkdy0+bnJf aXJxcyA9IDA7Cj4gKwo+ICsJcmV0dXJuIGVycjsKPiArfQo+ICtFWFBPUlRfU1lNQk9MX0dQTChk d19lZG1hX3Byb2JlKTsKCj4gKy8qKgo+ICsgKiBzdHJ1Y3QgZHdfZWRtYV9jaGlwIC0gcmVwcmVz ZW50YXRpb24gb2YgRGVzaWduV2FyZSBlRE1BIGNvbnRyb2xsZXIgaGFyZHdhcmUKPiArICogQGRl djoJCSBzdHJ1Y3QgZGV2aWNlIG9mIHRoZSBlRE1BIGNvbnRyb2xsZXIKPiArICogQGlkOgkJCSBp bnN0YW5jZSBJRAo+ICsgKiBAaXJxOgkJIGlycSBsaW5lCj4gKyAqIEBkdzoJCQkgc3RydWN0IGR3 X2VkbWEgdGhhdCBpcyBmaWxlZCBieSBkd19lZG1hX3Byb2JlKCkKPiArICovCj4gK3N0cnVjdCBk d19lZG1hX2NoaXAgewo+ICsJc3RydWN0IGRldmljZQkJKmRldjsKPiArCWludAkJCWlkOwo+ICsJ aW50CQkJaXJxOwo+ICsJc3RydWN0IGR3X2VkbWEJCSpkdzsKPiArfTsKPiArCj4gKy8qIEV4cG9y dCB0byB0aGUgcGxhdGZvcm0gZHJpdmVycyAqLwo+ICsjaWYgSVNfRU5BQkxFRChDT05GSUdfRFdf RURNQSkKPiAraW50IGR3X2VkbWFfcHJvYmUoc3RydWN0IGR3X2VkbWFfY2hpcCAqY2hpcCk7Cj4g K2ludCBkd19lZG1hX3JlbW92ZShzdHJ1Y3QgZHdfZWRtYV9jaGlwICpjaGlwKTsKPiArI2Vsc2UK PiArc3RhdGljIGlubGluZSBpbnQgZHdfZWRtYV9wcm9iZShzdHJ1Y3QgZHdfZWRtYV9jaGlwICpj aGlwKQo+ICt7Cj4gKwlyZXR1cm4gLUVOT0RFVjsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSBp bnQgZHdfZWRtYV9yZW1vdmUoc3RydWN0IGR3X2VkbWFfY2hpcCAqY2hpcCkKPiArewo+ICsJcmV0 dXJuIDA7Cj4gK30KPiArI2VuZGlmIC8qIENPTkZJR19EV19FRE1BICovCgpJcyBpdCBnb2luZyB0 byBiZSB1c2VkIGFzIGEgbGlicmFyeT8K 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=-2.5 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_PASS,USER_AGENT_MUTT 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 17D40C169C4 for ; Mon, 11 Feb 2019 18:49:52 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C9D1821B68 for ; Mon, 11 Feb 2019 18:49:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727485AbfBKStv (ORCPT ); Mon, 11 Feb 2019 13:49:51 -0500 Received: from mga05.intel.com ([192.55.52.43]:56943 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727314AbfBKStv (ORCPT ); Mon, 11 Feb 2019 13:49:51 -0500 X-Amp-Result: UNKNOWN X-Amp-Original-Verdict: FILE UNKNOWN X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 11 Feb 2019 10:49:50 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.58,359,1544515200"; d="scan'208";a="298915257" Received: from smile.fi.intel.com (HELO smile) ([10.237.72.86]) by orsmga005.jf.intel.com with ESMTP; 11 Feb 2019 10:49:45 -0800 Received: from andy by smile with local (Exim 4.92-RC5) (envelope-from ) id 1gtGeG-0007DA-Fo; Mon, 11 Feb 2019 20:49:44 +0200 Date: Mon, 11 Feb 2019 20:49:44 +0200 From: Andy Shevchenko To: Gustavo Pimentel Cc: linux-pci@vger.kernel.org, dmaengine@vger.kernel.org, Vinod Koul , Dan Williams , Eugeniy Paltsev , Russell King , Niklas Cassel , Joao Pinto , Jose Abreu , Luis Oliveira , Vitor Soares , Nelson Costa , Pedro Sousa Subject: Re: [RFC v5 1/6] dmaengine: Add Synopsys eDMA IP core driver Message-ID: <20190211184944.GH9224@smile.fi.intel.com> References: <19f8b7128b658821f7c4b0196ef5c958b640de55.1549905325.git.gustavo.pimentel@synopsys.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <19f8b7128b658821f7c4b0196ef5c958b640de55.1549905325.git.gustavo.pimentel@synopsys.com> Organization: Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org On Mon, Feb 11, 2019 at 06:34:30PM +0100, Gustavo Pimentel wrote: > 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. First comment here is that: try to shrink your code base by let's say 15%. I believe something here is done is suboptimal way or doesn't take into consideration existing facilities in the kernel. > +static void dw_edma_free_chunk(struct dw_edma_desc *desc) > +{ > + struct dw_edma_chan *chan = desc->chan; > + struct dw_edma_chunk *child, *_next; > + > + if (!desc->chunk) > + return; Is it necessary check? Why? > + > + /* Remove all the list elements */ > + list_for_each_entry_safe(child, _next, &desc->chunk->list, list) { > + dw_edma_free_burst(child); > + if (child->bursts_alloc) > + dev_dbg(chan2dev(chan), "%u bursts still allocated\n", > + child->bursts_alloc); > + list_del(&child->list); > + kfree(child); > + desc->chunks_alloc--; > + } > + > + /* Remove the list head */ > + kfree(child); > + desc->chunk = NULL; > +} > +static int dw_edma_device_config(struct dma_chan *dchan, > + struct dma_slave_config *config) > +{ > + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); > + unsigned long flags; > + int err = 0; > + > + spin_lock_irqsave(&chan->vc.lock, flags); > + > + if (!config) { > + err = -EINVAL; > + goto err_config; > + } Is it necessary check? Why? Why this is under spin lock? > + dev_dbg(chan2dev(chan), "addr(physical) src=%pa, dst=%pa\n", > + &config->src_addr, &config->dst_addr); And this. What do you protect by locks? Check all your locking carefully. > + > + chan->src_addr = config->src_addr; > + chan->dst_addr = config->dst_addr; > + > + chan->configured = true; > + dev_dbg(chan2dev(chan), "channel configured\n"); > + > +err_config: > + spin_unlock_irqrestore(&chan->vc.lock, flags); > + return err; > +} > + > +static int dw_edma_device_pause(struct dma_chan *dchan) > +{ > + struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan); > + unsigned long flags; > + int err = 0; > + > + spin_lock_irqsave(&chan->vc.lock, flags); > + > + if (!chan->configured) { > + dev_err(chan2dev(chan), "(pause) channel not configured\n"); Why this is under spinlock? > + err = -EPERM; > + goto err_pause; > + } > + > + if (chan->status != EDMA_ST_BUSY) { > + err = -EPERM; > + goto err_pause; > + } > + > + if (chan->request != EDMA_REQ_NONE) { > + err = -EPERM; > + goto err_pause; > + } > + > + chan->request = EDMA_REQ_PAUSE; > + dev_dbg(chan2dev(chan), "pause requested\n"); Ditto. Moreover, check what functional tracer can provide you for debugging. > + > +err_pause: > + spin_unlock_irqrestore(&chan->vc.lock, flags); > + return err; > +} > +{ > + 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 (!txstate) > + return ret; So, if there is no txstate, you can't return PAUSED state? Why? > + > + spin_lock_irqsave(&chan->vc.lock, flags); > + > + if (ret == DMA_IN_PROGRESS && chan->status == EDMA_ST_PAUSE) > + ret = DMA_PAUSED; > + > + vd = vchan_find_desc(&chan->vc, cookie); > + if (!vd) > + goto ret_status; > + > + desc = vd2dw_edma_desc(vd); > + if (desc) > + residue = desc->alloc_sz - desc->xfer_sz; > + > +ret_status: > + spin_unlock_irqrestore(&chan->vc.lock, flags); > + dma_set_residue(txstate, residue); > + > + return ret; > +} > + 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); > + } > + } > + > + dev_dbg(chan2dev(chan), "lli %u/%u, sar=0x%.8llx, dar=0x%.8llx, size=%u bytes\n", > + i + 1, cnt, burst->sar, burst->dar, burst->sz); > + > + if (!xfer->cyclic) > + sg = sg_next(sg); Shouldn't you rather to use for_each_sg()? > + } > + spin_lock_irqsave(&chan->vc.lock, flags); > + vd = vchan_next_desc(&chan->vc); > + switch (chan->request) { > + case EDMA_REQ_NONE: > + if (!vd) > + break; Shouldn't be outside of switch? > + > + 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; > + dev_dbg(chan2dev(chan), "transfer stop\n"); > + break; > + case EDMA_REQ_PAUSE: > + chan->request = EDMA_REQ_NONE; > + chan->status = EDMA_ST_PAUSE; > + break; > + default: > + dev_err(chan2dev(chan), "invalid status state\n"); > + break; > + } > + spin_unlock_irqrestore(&chan->vc.lock, flags); > +} > +static 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; > + } > + > + pos = 0; > + val = dw_edma_v0_core_status_done_int(dw, write ? > + EDMA_DIR_WRITE : > + EDMA_DIR_READ); > + val &= mask; > + while ((pos = find_next_bit(&val, total, pos)) != total) { Is this funny version of for_each_set_bit()? > + struct dw_edma_chan *chan = &dw->chan[pos + off]; > + > + dw_edma_done_interrupt(chan); > + pos++; > + } > + > + pos = 0; > + val = dw_edma_v0_core_status_abort_int(dw, write ? > + EDMA_DIR_WRITE : > + EDMA_DIR_READ); > + val &= mask; > + while ((pos = find_next_bit(&val, total, pos)) != total) { Ditto. > + struct dw_edma_chan *chan = &dw->chan[pos + off]; > + > + dw_edma_abort_interrupt(chan); > + pos++; > + } > + > + return IRQ_HANDLED; > +} > + do { > + ret = dw_edma_device_terminate_all(dchan); > + if (!ret) > + break; > + > + if (time_after_eq(jiffies, timeout)) { > + dev_err(chan2dev(chan), "free timeout\n"); > + return; > + } > + > + cpu_relax(); > + } while (1); So, what prevents you to do while (time_before(...)); here? > + > + dev_dbg(dchan2dev(dchan), "channel freed\n"); > + > + 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); > + 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_dbg(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_dbg(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_dbg(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); Doesn't it used for slave transfers? DMA_PRIVATE is good to be set for this. > + 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)--; > + } I don't see any allocation here. > +} > + > +static inline void dw_edma_add_irq_mask(u32 *mask, u32 alloc, u16 cnt) > +{ > + while (*mask * alloc < cnt) > + (*mask)++; Do you really need a loop here? > +} > + > +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) { > + dev_err(dev, "invalid number of irqs (%u)\n", dw->nr_irqs); > + 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); Are you going to call each time to pci_irq_vector()? Btw, am I missed pci_irq_alloc()? > + } else { > + /* Distribute IRQs equally among all channels */ > + int tmp = dw->nr_irqs; Is it always achievable? > + > + 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) { > + 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 = dw_edma_v0_core_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); > + > + /* 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; I think you may look into ep93xx driver to see how different type of channels are allocated and be set up. > + > + /* Power management */ > + pm_runtime_enable(dev); > + > + /* Turn debugfs on */ > + err = dw_edma_v0_core_debugfs_on(chip); > + if (err) { > + dev_err(dev, "unable to create debugfs structure\n"); > + 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); > +/** > + * 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 */ Is it going to be used as a library? -- With Best Regards, Andy Shevchenko