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: [v2,2/4] dmaengine: mtk_uart_dma: add Mediatek uart DMA support From: Long Cheng Message-Id: <1544090140.28871.11.camel@mhfsdcap03> Date: Thu, 6 Dec 2018 17:55:40 +0800 To: Sean Wang Cc: vkoul@kernel.org, robh+dt@kernel.org, mark.rutland@arm.com, devicetree@vger.kernel.org, srv_heupstream@mediatek.com, gregkh@linuxfoundation.org, Sean Wang =?UTF-8?Q?=28=E7=8E=8B=E5=BF=97=E4=BA=98=29?= , linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org, linux-mediatek@lists.infradead.org, linux-serial@vger.kernel.org, jslaby@suse.com, Matthias Brugger , yingjoe.chen@mediatek.com, dan.j.williams@intel.com, linux-arm-kernel@lists.infradead.org, yt.shen@mediatek.com List-ID: T24gV2VkLCAyMDE4LTEyLTA1IGF0IDEzOjA3IC0wODAwLCBTZWFuIFdhbmcgd3JvdGU6Cj4gLgo+ IE9uIFdlZCwgRGVjIDUsIDIwMTggYXQgMTozMSBBTSBMb25nIENoZW5nIDxsb25nLmNoZW5nQG1l ZGlhdGVrLmNvbT4gd3JvdGU6Cj4gPgo+ID4gSW4gRE1BIGVuZ2luZSBmcmFtZXdvcmssIGFkZCA4 MjUwIG10ayBkbWEgdG8gc3VwcG9ydCBpdC4KPiA+Cj4gPiBTaWduZWQtb2ZmLWJ5OiBMb25nIENo ZW5nIDxsb25nLmNoZW5nQG1lZGlhdGVrLmNvbT4KPiA+IC0tLQo+ID4gIGRyaXZlcnMvZG1hL21l ZGlhdGVrLzgyNTBfbXRrX2RtYS5jIHwgIDg5NCArKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKwo+ID4gIGRyaXZlcnMvZG1hL21lZGlhdGVrL0tjb25maWcgICAgICAgIHwgICAxMSAr Cj4gPiAgZHJpdmVycy9kbWEvbWVkaWF0ZWsvTWFrZWZpbGUgICAgICAgfCAgICAxICsKPiA+ICAz IGZpbGVzIGNoYW5nZWQsIDkwNiBpbnNlcnRpb25zKCspCj4gPiAgY3JlYXRlIG1vZGUgMTAwNjQ0 IGRyaXZlcnMvZG1hL21lZGlhdGVrLzgyNTBfbXRrX2RtYS5jCj4gPgo+ID4gZGlmZiAtLWdpdCBh L2RyaXZlcnMvZG1hL21lZGlhdGVrLzgyNTBfbXRrX2RtYS5jIGIvZHJpdmVycy9kbWEvbWVkaWF0 ZWsvODI1MF9tdGtfZG1hLmMKPiA+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gPiBpbmRleCAwMDAw MDAwLi4zNDU0Njc5Cj4gPiAtLS0gL2Rldi9udWxsCj4gPiArKysgYi9kcml2ZXJzL2RtYS9tZWRp YXRlay84MjUwX210a19kbWEuYwo+ID4gQEAgLTAsMCArMSw4OTQgQEAKPiA+ICsvLyBTUERYLUxp Y2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAo+ID4gKy8qCj4gPiArICogTWVkaWF0ZWsgODI1MCBE TUEgZHJpdmVyLgo+ID4gKyAqCj4gPiArICogQ29weXJpZ2h0IChjKSAyMDE4IE1lZGlhVGVrIElu Yy4KPiA+ICsgKiBBdXRob3I6IExvbmcgQ2hlbmcgPGxvbmcuY2hlbmdAbWVkaWF0ZWsuY29tPgo+ ID4gKyAqLwo+ID4gKwo+ID4gKyNpbmNsdWRlIDxsaW51eC9jbGsuaD4KPiA+ICsjaW5jbHVkZSA8 bGludXgvZG1hZW5naW5lLmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L2RtYS1tYXBwaW5nLmg+Cj4g PiArI2luY2x1ZGUgPGxpbnV4L2Vyci5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9pbml0Lmg+Cj4g PiArI2luY2x1ZGUgPGxpbnV4L2ludGVycnVwdC5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9saXN0 Lmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9v Zl9kbWEuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgvb2ZfZGV2aWNlLmg+Cj4gPiArI2luY2x1ZGUg PGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cj4g PiArI2luY2x1ZGUgPGxpbnV4L3NwaW5sb2NrLmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L3BtX3J1 bnRpbWUuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgvaW9wb2xsLmg+Cj4gPiArCj4gPiArI2luY2x1 ZGUgIi4uL3ZpcnQtZG1hLmgiCj4gPiArCj4gPiArI2RlZmluZSBNVEtfQVBETUFfREVGQVVMVF9S RVFVRVNUUyAgICAgMTI3Cj4gPiArI2RlZmluZSBNVEtfQVBETUFfQ0hBTk5FTFMgICAgICAgICAg ICAgKENPTkZJR19TRVJJQUxfODI1MF9OUl9VQVJUUyAqIDIpCj4gPiArCj4gPiArI2RlZmluZSBW RkZfRU5fQiAgICAgICAgICAgICAgIEJJVCgwKQo+ID4gKyNkZWZpbmUgVkZGX1NUT1BfQiAgICAg ICAgICAgICBCSVQoMCkKPiA+ICsjZGVmaW5lIFZGRl9GTFVTSF9CICAgICAgICAgICAgQklUKDAp Cj4gPiArI2RlZmluZSBWRkZfNEdfU1VQUE9SVF9CICAgICAgIEJJVCgwKQo+ID4gKyNkZWZpbmUg VkZGX1JYX0lOVF9FTjBfQiAgICAgICBCSVQoMCkgIC8qcnggdmFsaWQgc2l6ZSA+PSAgdmZmIHRo cmUqLwo+ID4gKyNkZWZpbmUgVkZGX1JYX0lOVF9FTjFfQiAgICAgICBCSVQoMSkKPiA+ICsjZGVm aW5lIFZGRl9UWF9JTlRfRU5fQiAgICAgICAgICAgICAgICBCSVQoMCkgIC8qdHggbGVmdCBzaXpl ID49IHZmZiB0aHJlKi8KPiA+ICsjZGVmaW5lIFZGRl9XQVJNX1JTVF9CICAgICAgICAgQklUKDAp Cj4gPiArI2RlZmluZSBWRkZfUlhfSU5UX0ZMQUdfQ0xSX0IgIChCSVQoMCkgfCBCSVQoMSkpCj4g PiArI2RlZmluZSBWRkZfVFhfSU5UX0ZMQUdfQ0xSX0IgIDAKPiA+ICsjZGVmaW5lIFZGRl9TVE9Q X0NMUl9CICAgICAgICAgMAo+ID4gKyNkZWZpbmUgVkZGX0ZMVVNIX0NMUl9CICAgICAgICAgICAg ICAgIDAKPiA+ICsjZGVmaW5lIFZGRl9JTlRfRU5fQ0xSX0IgICAgICAgMAo+ID4gKyNkZWZpbmUg VkZGXzRHX1NVUFBPUlRfQ0xSX0IgICAwCj4gPiArCj4gPiArLyogaW50ZXJydXB0IHRyaWdnZXIg bGV2ZWwgZm9yIHR4ICovCj4gPiArI2RlZmluZSBWRkZfVFhfVEhSRShuKSAgICAgICAgICgobikg KiA3IC8gOCkKPiA+ICsvKiBpbnRlcnJ1cHQgdHJpZ2dlciBsZXZlbCBmb3IgcnggKi8KPiA+ICsj ZGVmaW5lIFZGRl9SWF9USFJFKG4pICAgICAgICAgKChuKSAqIDMgLyA0KQo+ID4gKwo+ID4gKyNk ZWZpbmUgTVRLX0RNQV9SSU5HX1NJWkUgICAgICAweGZmZmZVCj4gPiArLyogaW52ZXJ0IHRoaXMg Yml0IHdoZW4gd3JhcCByaW5nIGhlYWQgYWdhaW4qLwo+ID4gKyNkZWZpbmUgTVRLX0RNQV9SSU5H X1dSQVAgICAgICAweDEwMDAwVQo+ID4gKwo+ID4gKyNkZWZpbmUgVkZGX0lOVF9GTEFHICAgICAg ICAgICAweDAwCj4gPiArI2RlZmluZSBWRkZfSU5UX0VOICAgICAgICAgICAgIDB4MDQKPiA+ICsj ZGVmaW5lIFZGRl9FTiAgICAgICAgICAgICAgICAgMHgwOAo+ID4gKyNkZWZpbmUgVkZGX1JTVCAg ICAgICAgICAgICAgICAgICAgICAgIDB4MGMKPiA+ICsjZGVmaW5lIFZGRl9TVE9QICAgICAgICAg ICAgICAgMHgxMAo+ID4gKyNkZWZpbmUgVkZGX0ZMVVNIICAgICAgICAgICAgICAweDE0Cj4gPiAr I2RlZmluZSBWRkZfQUREUiAgICAgICAgICAgICAgIDB4MWMKPiA+ICsjZGVmaW5lIFZGRl9MRU4g ICAgICAgICAgICAgICAgICAgICAgICAweDI0Cj4gPiArI2RlZmluZSBWRkZfVEhSRSAgICAgICAg ICAgICAgIDB4MjgKPiA+ICsjZGVmaW5lIFZGRl9XUFQgICAgICAgICAgICAgICAgICAgICAgICAw eDJjCj4gPiArI2RlZmluZSBWRkZfUlBUICAgICAgICAgICAgICAgICAgICAgICAgMHgzMAo+ID4g Ky8qVFg6IHRoZSBidWZmZXIgc2l6ZSBIVyBjYW4gcmVhZC4gUlg6IHRoZSBidWZmZXIgc2l6ZSBT VyBjYW4gcmVhZC4qLwo+ID4gKyNkZWZpbmUgVkZGX1ZBTElEX1NJWkUgICAgICAgICAweDNjCj4g PiArLypUWDogdGhlIGJ1ZmZlciBzaXplIFNXIGNhbiB3cml0ZS4gUlg6IHRoZSBidWZmZXIgc2l6 ZSBIVyBjYW4gd3JpdGUuKi8KPiA+ICsjZGVmaW5lIFZGRl9MRUZUX1NJWkUgICAgICAgICAgMHg0 MAo+ID4gKyNkZWZpbmUgVkZGX0RFQlVHX1NUQVRVUyAgICAgICAweDUwCj4gPiArI2RlZmluZSBW RkZfNEdfU1VQUE9SVCAgICAgICAgIDB4NTQKPiA+ICsKPiA+ICtzdHJ1Y3QgbXRrX2RtYWRldiB7 Cj4gPiArICAgICAgIHN0cnVjdCBkbWFfZGV2aWNlIGRkZXY7Cj4gPiArICAgICAgIHZvaWQgX19p b21lbSAqbWVtX2Jhc2VbTVRLX0FQRE1BX0NIQU5ORUxTXTsKPiA+ICsgICAgICAgc3BpbmxvY2tf dCBsb2NrOyAvKiBkbWEgZGV2IGxvY2sgKi8KPiA+ICsgICAgICAgc3RydWN0IHRhc2tsZXRfc3Ry dWN0IHRhc2s7Cj4gPiArICAgICAgIHN0cnVjdCBsaXN0X2hlYWQgcGVuZGluZzsKPiA+ICsgICAg ICAgc3RydWN0IGNsayAqY2xrOwo+ID4gKyAgICAgICB1bnNpZ25lZCBpbnQgZG1hX3JlcXVlc3Rz Owo+ID4gKyAgICAgICBib29sIHN1cHBvcnRfMzNiaXRzOwo+ID4gKyAgICAgICB1bnNpZ25lZCBp bnQgZG1hX2lycVtNVEtfQVBETUFfQ0hBTk5FTFNdOwo+ID4gKyAgICAgICBzdHJ1Y3QgbXRrX2No YW4gKmNoW01US19BUERNQV9DSEFOTkVMU107Cj4gPiArfTsKPiA+ICsKPiA+ICtzdHJ1Y3QgbXRr X2NoYW4gewo+ID4gKyAgICAgICBzdHJ1Y3QgdmlydF9kbWFfY2hhbiB2YzsKPiA+ICsgICAgICAg c3RydWN0IGxpc3RfaGVhZCBub2RlOwo+ID4gKyAgICAgICBzdHJ1Y3QgZG1hX3NsYXZlX2NvbmZp ZyBjZmc7Cj4gPiArICAgICAgIHZvaWQgX19pb21lbSAqYmFzZTsKPiA+ICsgICAgICAgc3RydWN0 IG10a19kbWFfZGVzYyAqZGVzYzsKPiA+ICsKPiA+ICsgICAgICAgYm9vbCBzdG9wOwo+ID4gKyAg ICAgICBib29sIHJlcXVlc3RlZDsKPiA+ICsKPiA+ICsgICAgICAgdW5zaWduZWQgaW50IGRtYV9z aWc7Cj4gCj4gdGhlIG1lbWJlciBjYW4gYmUgcmVtb3ZlZCBhcyBubyByZWFsIHVzZXIgd291bGQg cmVmZXIgdG8gaXQKPiAKCk9rLCBpIHdpbGwgcmVtb3ZlIGl0IGF0IG5leHQgcGF0Y2gKCj4gPiAr ICAgICAgIHVuc2lnbmVkIGludCBkbWFfY2g7Cj4gCj4gYSBjaGFuX2lkIGlzIGFscmVhZHkgaW5j bHVkZWQgaW4gc3RydWN0IGRtYV9jaGFuLCB3ZSBjYW4gcmV1c2UgaXQKPiAKCmNoYW5faWQgaXMg c3RhcnQgZnJvbSAwLiBidXQgaW4gdGhpcyBkcml2ZXIsIGRtYSBpbmZvIGlzIHN0b3JlZCB0byBs aXN0LgppZiB1c2UgcG9ydDEsIGluIGZpbHRlcl9mbiBmdW5jdGlvbiwgd2lsbCBzZXQgZG1hX2No IHRvIDIsIDModHgsIHJ4KS4gU28KY2FuJ3QgdXNpbmcgY2hhbl9pZAoKPiA+ICsgICAgICAgdW5z aWduZWQgaW50IHNnaWR4Owo+IAo+IHRoZSBtZW1iZXIgYWxzbyBjYW4gYmUgcmVtb3ZlZCBhcyBu byByZWFsIHVzZXIgd291bGQgcmVmZXIgdG8gaXQKPiAKCk9rLCBpIHdpbGwgcmVtb3ZlIGl0IGF0 IG5leHQgcGF0Y2gKCj4gPiArICAgICAgIHVuc2lnbmVkIGludCByZW1haW5fc2l6ZTsKPiAKPiBU aGUgbWVtYmVyIHJlbWFpbl9zaXplIHNlZW1zIHVubmVjZXNzYXJ5IGRhdGEgdG8gbWFpbnRhaW4g YSBjaGFubmVsLgo+IFRoZSB2aXJ0dWFsIGNoYW5uZWwgc3RydWN0IHZpcnRfZG1hX2NoYW4gYWxy ZWFkeSBwcm92aWRlIHRoZSB3YXkgdG8KPiBtYW5hZ2UgYWxsIGRlc2NyaXB0b3JzIHlvdSdyZSBv cGVyYXRpbmcgb24sIHlvdSBzaG91bGQgcmV1c2UgcmVsYXRlZAo+IGZ1bmN0aW9ucyB0byB2aXJ0 X2RtYV9jaGFuIGZpcnN0Lgo+IAo+IE9yIGlmIHlvdSBtZWFuIHJlbWFpbl9zaXplIGlzIGFib3V0 IHRoZSByZW1haW5pbmcgc2l6ZSBvZiBjdXJyZW50Cj4gZGVzY3JpcHRvciwgYW5kIHRoZW4gcHV0 dGluZyBpbnRvIHN0cnVjdCBtdGtfZG1hX2Rlc2Mgd291bGQgYmUgYmV0dGVyLgo+IAoKaSB3aWxs IG1vdmUgaXQgdG8gbXRrX2RtYV9kZXNjCgo+ID4gKyAgICAgICB1bnNpZ25lZCBpbnQgcnhfcHRy Owo+ID4gK307Cj4gPiArCj4gPiArc3RydWN0IG10a19kbWFfc2cgewo+ID4gKyAgICAgICBkbWFf YWRkcl90IGFkZHI7Cj4gPiArICAgICAgIHVuc2lnbmVkIGludCBlbjsgICAgICAgICAgICAgICAg LyogbnVtYmVyIG9mIGVsZW1lbnRzICgyNC1iaXQpICovCj4gPiArICAgICAgIHVuc2lnbmVkIGlu dCBmbjsgICAgICAgICAgICAgICAgLyogbnVtYmVyIG9mIGZyYW1lcyAoMTYtYml0KSAqLwo+ID4g K307Cj4gPiArCj4gPiArc3RydWN0IG10a19kbWFfZGVzYyB7Cj4gPiArICAgICAgIHN0cnVjdCB2 aXJ0X2RtYV9kZXNjIHZkOwo+ID4gKyAgICAgICBlbnVtIGRtYV90cmFuc2Zlcl9kaXJlY3Rpb24g ZGlyOwo+ID4gKwo+ID4gKyAgICAgICB1bnNpZ25lZCBpbnQgc2dsZW47Cj4gPiArICAgICAgIHN0 cnVjdCBtdGtfZG1hX3NnIHNnWzBdOwo+ID4gK307Cj4gPiArCj4gPiArc3RhdGljIGJvb2wgbXRr X2RtYV9maWx0ZXJfZm4oc3RydWN0IGRtYV9jaGFuICpjaGFuLCB2b2lkICpwYXJhbSk7Cj4gPiAr c3RhdGljIHN0cnVjdCBvZl9kbWFfZmlsdGVyX2luZm8gbXRrX2RtYV9pbmZvID0gewo+ID4gKyAg ICAgICAuZmlsdGVyX2ZuID0gbXRrX2RtYV9maWx0ZXJfZm4sCj4gPiArfTsKPiA+ICsKPiA+ICtz dGF0aWMgaW5saW5lIHN0cnVjdCBtdGtfZG1hZGV2ICp0b19tdGtfZG1hX2RldihzdHJ1Y3QgZG1h X2RldmljZSAqZCkKPiA+ICt7Cj4gPiArICAgICAgIHJldHVybiBjb250YWluZXJfb2YoZCwgc3Ry dWN0IG10a19kbWFkZXYsIGRkZXYpOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW5saW5lIHN0 cnVjdCBtdGtfY2hhbiAqdG9fbXRrX2RtYV9jaGFuKHN0cnVjdCBkbWFfY2hhbiAqYykKPiA+ICt7 Cj4gPiArICAgICAgIHJldHVybiBjb250YWluZXJfb2YoYywgc3RydWN0IG10a19jaGFuLCB2Yy5j aGFuKTsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGlubGluZSBzdHJ1Y3QgbXRrX2RtYV9kZXNj ICp0b19tdGtfZG1hX2Rlc2MKPiA+ICsgICAgICAgKHN0cnVjdCBkbWFfYXN5bmNfdHhfZGVzY3Jp cHRvciAqdCkKPiA+ICt7Cj4gPiArICAgICAgIHJldHVybiBjb250YWluZXJfb2YodCwgc3RydWN0 IG10a19kbWFfZGVzYywgdmQudHgpOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgdm9pZCBtdGtf ZG1hX2NoYW5fd3JpdGUoc3RydWN0IG10a19jaGFuICpjLAo+ID4gKyAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgIHVuc2lnbmVkIGludCByZWcsIHVuc2lnbmVkIGludCB2YWwpCj4gPiArewo+ ID4gKyAgICAgICB3cml0ZWwodmFsLCBjLT5iYXNlICsgcmVnKTsKPiA+ICt9Cj4gPiArCj4gPiAr c3RhdGljIHVuc2lnbmVkIGludCBtdGtfZG1hX2NoYW5fcmVhZChzdHJ1Y3QgbXRrX2NoYW4gKmMs IHVuc2lnbmVkIGludCByZWcpCj4gPiArewo+ID4gKyAgICAgICByZXR1cm4gcmVhZGwoYy0+YmFz ZSArIHJlZyk7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyB2b2lkIG10a19kbWFfZGVzY19mcmVl KHN0cnVjdCB2aXJ0X2RtYV9kZXNjICp2ZCkKPiA+ICt7Cj4gPiArICAgICAgIHN0cnVjdCBkbWFf Y2hhbiAqY2hhbiA9IHZkLT50eC5jaGFuOwo+ID4gKyAgICAgICBzdHJ1Y3QgbXRrX2NoYW4gKmMg PSB0b19tdGtfZG1hX2NoYW4oY2hhbik7Cj4gPiArCj4gPiArICAgICAgIGtmcmVlKGMtPmRlc2Mp Owo+ID4gKyAgICAgICBjLT5kZXNjID0gTlVMTDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGlu dCBtdGtfZG1hX2Nsa19lbmFibGUoc3RydWN0IG10a19kbWFkZXYgKm10a2QpCj4gPiArewo+ID4g KyAgICAgICBpbnQgcmV0Owo+ID4gKwo+ID4gKyAgICAgICByZXQgPSBjbGtfcHJlcGFyZV9lbmFi bGUobXRrZC0+Y2xrKTsKPiA+ICsgICAgICAgaWYgKHJldCkgewo+ID4gKyAgICAgICAgICAgICAg IGRldl9lcnIobXRrZC0+ZGRldi5kZXYsICJDb3VsZG4ndCBlbmFibGUgdGhlIGNsb2NrXG4iKTsK PiA+ICsgICAgICAgICAgICAgICByZXR1cm4gcmV0Owo+ID4gKyAgICAgICB9Cj4gPiArCj4gPiAr ICAgICAgIHJldHVybiAwOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgdm9pZCBtdGtfZG1hX2Ns a19kaXNhYmxlKHN0cnVjdCBtdGtfZG1hZGV2ICptdGtkKQo+ID4gK3sKPiA+ICsgICAgICAgY2xr X2Rpc2FibGVfdW5wcmVwYXJlKG10a2QtPmNsayk7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyB2 b2lkIG10a19kbWFfcmVtb3ZlX3ZpcnRfbGlzdChkbWFfY29va2llX3QgY29va2llLAo+ID4gKyAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCB2aXJ0X2RtYV9jaGFuICp2 YykKPiA+ICt7Cj4gPiArICAgICAgIHN0cnVjdCB2aXJ0X2RtYV9kZXNjICp2ZDsKPiA+ICsKPiA+ ICsgICAgICAgaWYgKGxpc3RfZW1wdHkoJnZjLT5kZXNjX2lzc3VlZCkgPT0gMCkgewo+ID4gKyAg ICAgICAgICAgICAgIGxpc3RfZm9yX2VhY2hfZW50cnkodmQsICZ2Yy0+ZGVzY19pc3N1ZWQsIG5v ZGUpIHsKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb29raWUgPT0gdmQtPnR4LmNv b2tpZSkgewo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJTklUX0xJU1RfSEVB RCgmdmMtPmRlc2NfaXNzdWVkKTsKPiAKPiBnZW5lcmFsbHksIHdlIGRvbid0IGZvcmNlIGluaXRp YWx6ZSB0aGUgbGlzdCBkZXNjX2lzc3VlZC4gSW5zdGVhZCwKPiB3aGVuIGVhY2ggZGVzY3JpcHRv ciBpcyBjb21wbGV0ZWQsIHdlIG5lZWQgdG8gbW92ZSBlYWNoIGRlc2NyaXB0b3IKPiBmcm9tIHRo ZSBsaXN0IGRlc2NfaXNzdWVkIHRvIHRoZSBsaXN0IGRlc2NfY29tcGxldGVkLgo+IAoKb2ssIGkg d2lsbCBtb2RpZnkgaXQgYXQgbmV4dCBwYXRjaAoKPiA+ICsgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgYnJlYWs7Cj4gPiArICAgICAgICAgICAgICAgICAgICAgICB9Cj4gPiArICAgICAg ICAgICAgICAgfQo+ID4gKyAgICAgICB9Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyB2b2lkIG10 a19kbWFfdHhfZmx1c2goc3RydWN0IGRtYV9jaGFuICpjaGFuKQo+ID4gK3sKPiA+ICsgICAgICAg c3RydWN0IG10a19jaGFuICpjID0gdG9fbXRrX2RtYV9jaGFuKGNoYW4pOwo+ID4gKwo+ID4gKyAg ICAgICBpZiAobXRrX2RtYV9jaGFuX3JlYWQoYywgVkZGX0ZMVVNIKSA9PSAwVSkKPiA+ICsgICAg ICAgICAgICAgICBtdGtfZG1hX2NoYW5fd3JpdGUoYywgVkZGX0ZMVVNILCBWRkZfRkxVU0hfQik7 Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyB2b2lkIG10a19kbWFfdHhfd3JpdGUoc3RydWN0IGRt YV9jaGFuICpjaGFuKQo+ID4gK3sKPiA+ICsgICAgICAgc3RydWN0IG10a19jaGFuICpjID0gdG9f bXRrX2RtYV9jaGFuKGNoYW4pOwo+ID4gKyAgICAgICB1bnNpZ25lZCBpbnQgdHhjb3VudCA9IGMt PnJlbWFpbl9zaXplOwo+ID4gKyAgICAgICB1bnNpZ25lZCBpbnQgbGVuLCBzZW5kLCBsZWZ0LCB3 cHQsIHdyYXA7Cj4gPiArCj4gPiArICAgICAgIGxlbiA9IG10a19kbWFfY2hhbl9yZWFkKGMsIFZG Rl9MRU4pOwo+ID4gKwo+ID4gKyAgICAgICB3aGlsZSAoKGxlZnQgPSBtdGtfZG1hX2NoYW5fcmVh ZChjLCBWRkZfTEVGVF9TSVpFKSkgPiAwVSkgewo+ID4gKyAgICAgICAgICAgICAgIGlmIChjLT5y ZW1haW5fc2l6ZSA9PSAwVSkKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwo+ID4g KyAgICAgICAgICAgICAgIHNlbmQgPSBtaW4obGVmdCwgYy0+cmVtYWluX3NpemUpOwo+IAo+IG1p bl90Cj4gCgpvaywgaSB3aWxsIG1vZGlmeSBpdCBhdCBuZXh0IHBhdGNoCgo+ID4gKyAgICAgICAg ICAgICAgIHdwdCA9IG10a19kbWFfY2hhbl9yZWFkKGMsIFZGRl9XUFQpOwo+ID4gKyAgICAgICAg ICAgICAgIHdyYXAgPSB3cHQgJiBNVEtfRE1BX1JJTkdfV1JBUCA/IDBVIDogTVRLX0RNQV9SSU5H X1dSQVA7Cj4gPiArCj4gPiArICAgICAgICAgICAgICAgaWYgKCh3cHQgJiAobGVuIC0gMVUpKSAr IHNlbmQgPCBsZW4pCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBtdGtfZG1hX2NoYW5fd3Jp dGUoYywgVkZGX1dQVCwgd3B0ICsgc2VuZCk7Cj4gPiArICAgICAgICAgICAgICAgZWxzZQo+ID4g KyAgICAgICAgICAgICAgICAgICAgICAgbXRrX2RtYV9jaGFuX3dyaXRlKGMsIFZGRl9XUFQsCj4g PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKCh3cHQgKyBzZW5k KSAmIChsZW4gLSAxVSkpCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgfCB3cmFwKTsKPiA+ICsKPiA+ICsgICAgICAgICAgICAgICBjLT5yZW1haW5fc2l6ZSAt PSBzZW5kOwo+IAo+IEknbSBjdXJpb3VzIHdoeSB5b3UgZG9uJ3QgbmVlZCB0byBzZXQgdXAgdGhl IGhhcmR3YXJlIGZyb20gdGhlCj4gZGVzY3JpcHRvciBpbmZvcm1hdGlvbgo+IAoKbXRrX2RtYV9j aGFuX3dyaXRlIGlzIHVwZGF0ZSB0aGUgaGFyZHdhcmUuIHJlbWFpbl9zaXplIGlzIGxlbmd0aCBv ZiBUWApkYXRhLgoKPiA+ICsgICAgICAgfQo+ID4gKwo+ID4gKyAgICAgICBpZiAodHhjb3VudCAh PSBjLT5yZW1haW5fc2l6ZSkgewo+ID4gKyAgICAgICAgICAgICAgIG10a19kbWFfY2hhbl93cml0 ZShjLCBWRkZfSU5UX0VOLCBWRkZfVFhfSU5UX0VOX0IpOwo+ID4gKyAgICAgICAgICAgICAgIG10 a19kbWFfdHhfZmx1c2goY2hhbik7Cj4gPiArICAgICAgIH0KPiA+ICt9Cj4gPiArCj4gPiArc3Rh dGljIHZvaWQgbXRrX2RtYV9zdGFydF90eChzdHJ1Y3QgbXRrX2NoYW4gKmMpCj4gPiArewo+ID4g KyAgICAgICBpZiAobXRrX2RtYV9jaGFuX3JlYWQoYywgVkZGX0xFRlRfU0laRSkgPT0gMFUpCj4g PiArICAgICAgICAgICAgICAgbXRrX2RtYV9jaGFuX3dyaXRlKGMsIFZGRl9JTlRfRU4sIFZGRl9U WF9JTlRfRU5fQik7Cj4gPiArICAgICAgIGVsc2UKPiA+ICsgICAgICAgICAgICAgICBtdGtfZG1h X3R4X3dyaXRlKCZjLT52Yy5jaGFuKTsKPiA+ICsKPiA+ICsgICAgICAgYy0+c3RvcCA9IGZhbHNl Owo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgdm9pZCBtdGtfZG1hX2dldF9yeF9zaXplKHN0cnVj dCBtdGtfY2hhbiAqYykKPiA+ICt7Cj4gPiArICAgICAgIHVuc2lnbmVkIGludCByeF9zaXplID0g bXRrX2RtYV9jaGFuX3JlYWQoYywgVkZGX0xFTik7Cj4gPiArICAgICAgIHVuc2lnbmVkIGludCBy ZHB0ciwgd3JwdHIsIHdycmVnLCByZHJlZywgY291bnQ7Cj4gPiArCj4gPiArICAgICAgIHJkcmVn ID0gbXRrX2RtYV9jaGFuX3JlYWQoYywgVkZGX1JQVCk7Cj4gPiArICAgICAgIHdycmVnID0gbXRr X2RtYV9jaGFuX3JlYWQoYywgVkZGX1dQVCk7Cj4gPiArICAgICAgIHJkcHRyID0gcmRyZWcgJiBN VEtfRE1BX1JJTkdfU0laRTsKPiA+ICsgICAgICAgd3JwdHIgPSB3cnJlZyAmIE1US19ETUFfUklO R19TSVpFOwo+ID4gKyAgICAgICBjb3VudCA9ICgocmRyZWcgXiB3cnJlZykgJiBNVEtfRE1BX1JJ TkdfV1JBUCkgPwo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgKHdycHRyICsgcnhfc2l6ZSAt IHJkcHRyKSA6ICh3cnB0ciAtIHJkcHRyKTsKPiA+ICsKPiA+ICsgICAgICAgYy0+cmVtYWluX3Np emUgPSBjb3VudDsKPiA+ICsgICAgICAgYy0+cnhfcHRyID0gcmRwdHI7Cj4gPiArCj4gPiArICAg ICAgIG10a19kbWFfY2hhbl93cml0ZShjLCBWRkZfUlBULCB3cnJlZyk7Cj4gPiArfQo+ID4gKwo+ ID4gK3N0YXRpYyB2b2lkIG10a19kbWFfc3RhcnRfcngoc3RydWN0IG10a19jaGFuICpjKQo+ID4g K3sKPiA+ICsgICAgICAgc3RydWN0IGRtYV9jaGFuICpjaGFuID0gJmMtPnZjLmNoYW47Cj4gPiAr ICAgICAgIHN0cnVjdCBtdGtfZG1hZGV2ICptdGtkID0gdG9fbXRrX2RtYV9kZXYoY2hhbi0+ZGV2 aWNlKTsKPiA+ICsgICAgICAgc3RydWN0IG10a19kbWFfZGVzYyAqZCA9IGMtPmRlc2M7Cj4gPiAr Cj4gPiArICAgICAgIGlmIChtdGtfZG1hX2NoYW5fcmVhZChjLCBWRkZfVkFMSURfU0laRSkgPT0g MFUpCj4gPiArICAgICAgICAgICAgICAgcmV0dXJuOwo+ID4gKwo+ID4gKyAgICAgICBpZiAoZCAm JiBkLT52ZC50eC5jb29raWUgIT0gMCkgewo+IAo+IHRoZSBkcml2ZXIgYmVuZWZpdHMgZnJvbSB2 aXJ0dWFsX2NoYW5uZWwgc28geW91IGNhbiBtYW5hZ2UgdGhlIGxpZmUKPiBjeWNsZSBvZiBlYWNo IGRlc2NyaXB0b3IgYnkgdGhlIHZpcnR1YWwgY2hhbm5lbCByZWxhdGVkIGZ1bmN0aW9ucwo+IHdp dGhvdXQgaGFuZGxpbmcgZGV0YWlscyBhYm91dCB0aGUgY29va2llLgo+IAoKb2ssIGkgd2lsbCBt b2RpZnkgaXQgYXQgbmV4dCBwYXRjaAoKPiA+ICsgICAgICAgICAgICAgICBtdGtfZG1hX2dldF9y eF9zaXplKGMpOwo+ID4gKyAgICAgICAgICAgICAgIG10a19kbWFfcmVtb3ZlX3ZpcnRfbGlzdChk LT52ZC50eC5jb29raWUsICZjLT52Yyk7Cj4gPiArICAgICAgICAgICAgICAgdmNoYW5fY29va2ll X2NvbXBsZXRlKCZkLT52ZCk7Cj4gPiArICAgICAgIH0gZWxzZSB7Cj4gPiArICAgICAgICAgICAg ICAgc3Bpbl9sb2NrKCZtdGtkLT5sb2NrKTsKPiA+ICsgICAgICAgICAgICAgICBpZiAobGlzdF9l bXB0eSgmbXRrZC0+cGVuZGluZykpCj4gPiArICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2Fk ZF90YWlsKCZjLT5ub2RlLCAmbXRrZC0+cGVuZGluZyk7Cj4gPiArICAgICAgICAgICAgICAgc3Bp bl91bmxvY2soJm10a2QtPmxvY2spOwo+ID4gKyAgICAgICAgICAgICAgIHRhc2tsZXRfc2NoZWR1 bGUoJm10a2QtPnRhc2spOwo+ID4gKyAgICAgICB9Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyB2 b2lkIG10a19kbWFfcmVzZXQoc3RydWN0IG10a19jaGFuICpjKQo+ID4gK3sKPiA+ICsgICAgICAg c3RydWN0IG10a19kbWFkZXYgKm10a2QgPSB0b19tdGtfZG1hX2RldihjLT52Yy5jaGFuLmRldmlj ZSk7Cj4gPiArICAgICAgIHUzMiBzdGF0dXM7Cj4gPiArICAgICAgIGludCByZXQ7Cj4gPiArCj4g PiArICAgICAgIG10a19kbWFfY2hhbl93cml0ZShjLCBWRkZfQUREUiwgMCk7Cj4gPiArICAgICAg IG10a19kbWFfY2hhbl93cml0ZShjLCBWRkZfVEhSRSwgMCk7Cj4gPiArICAgICAgIG10a19kbWFf Y2hhbl93cml0ZShjLCBWRkZfTEVOLCAwKTsKPiA+ICsgICAgICAgbXRrX2RtYV9jaGFuX3dyaXRl KGMsIFZGRl9SU1QsIFZGRl9XQVJNX1JTVF9CKTsKPiA+ICsKPiA+ICsgICAgICAgcmV0ID0gcmVh ZHhfcG9sbF90aW1lb3V0KHJlYWRsLAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgYy0+YmFzZSArIFZGRl9FTiwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg IHN0YXR1cywgc3RhdHVzID09IDAsIDEwLCAxMDApOwo+ID4gKyAgICAgICBpZiAocmV0KSB7Cj4g PiArICAgICAgICAgICAgICAgZGV2X2VycihjLT52Yy5jaGFuLmRldmljZS0+ZGV2LAo+ID4gKyAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZG1hIHJlc2V0OiBmYWlsLCB0aW1lb3V0XG4i KTsKPiA+ICsgICAgICAgICAgICAgICByZXR1cm47Cj4gPiArICAgICAgIH0KPiA+ICsKPiA+ICsg ICAgICAgaWYgKGMtPmNmZy5kaXJlY3Rpb24gPT0gRE1BX0RFVl9UT19NRU0pCj4gPiArICAgICAg ICAgICAgICAgbXRrX2RtYV9jaGFuX3dyaXRlKGMsIFZGRl9SUFQsIDApOwo+ID4gKyAgICAgICBl bHNlIGlmIChjLT5jZmcuZGlyZWN0aW9uID09IERNQV9NRU1fVE9fREVWKQo+ID4gKyAgICAgICAg ICAgICAgIG10a19kbWFfY2hhbl93cml0ZShjLCBWRkZfV1BULCAwKTsKPiA+ICsKPiA+ICsgICAg ICAgaWYgKG10a2QtPnN1cHBvcnRfMzNiaXRzKQo+ID4gKyAgICAgICAgICAgICAgIG10a19kbWFf Y2hhbl93cml0ZShjLCBWRkZfNEdfU1VQUE9SVCwgVkZGXzRHX1NVUFBPUlRfQ0xSX0IpOwo+ID4g K30KPiA+ICsKPiA+ICtzdGF0aWMgdm9pZCBtdGtfZG1hX3N0b3Aoc3RydWN0IG10a19jaGFuICpj KQo+ID4gK3sKPiA+ICsgICAgICAgdTMyIHN0YXR1czsKPiA+ICsgICAgICAgaW50IHJldDsKPiA+ ICsKPiA+ICsgICAgICAgbXRrX2RtYV9jaGFuX3dyaXRlKGMsIFZGRl9GTFVTSCwgVkZGX0ZMVVNI X0NMUl9CKTsKPiA+ICsgICAgICAgLyogV2FpdCBmb3IgZmx1c2ggKi8KPiA+ICsgICAgICAgcmV0 ID0gcmVhZHhfcG9sbF90aW1lb3V0KHJlYWRsLAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgYy0+YmFzZSArIFZGRl9GTFVTSCwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIHN0YXR1cywKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChz dGF0dXMgJiBWRkZfRkxVU0hfQikgIT0gVkZGX0ZMVVNIX0IsCj4gPiArICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAxMCwgMTAwKTsKPiA+ICsgICAgICAgaWYgKHJldCkKPiA+ICsgICAg ICAgICAgICAgICBkZXZfZXJyKGMtPnZjLmNoYW4uZGV2aWNlLT5kZXYsCj4gPiArICAgICAgICAg ICAgICAgICAgICAgICAiZG1hIHN0b3A6IHBvbGxpbmcgRkxVU0ggZmFpbCwgREVCVUc9MHgleFxu IiwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIG10a19kbWFfY2hhbl9yZWFkKGMsIFZGRl9E RUJVR19TVEFUVVMpKTsKPiA+ICsKPiA+ICsgICAgICAgLypzZXQgc3RvcCBhcyAxIC0+IHdhaXQg dW50aWwgZW4gaXMgMCAtPiBzZXQgc3RvcCBhcyAwKi8KPiA+ICsgICAgICAgbXRrX2RtYV9jaGFu X3dyaXRlKGMsIFZGRl9TVE9QLCBWRkZfU1RPUF9CKTsKPiA+ICsgICAgICAgcmV0ID0gcmVhZHhf cG9sbF90aW1lb3V0KHJlYWRsLAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg Yy0+YmFzZSArIFZGRl9FTiwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0 YXR1cywgc3RhdHVzID09IDAsIDEwLCAxMDApOwo+ID4gKyAgICAgICBpZiAocmV0KQo+ID4gKyAg ICAgICAgICAgICAgIGRldl9lcnIoYy0+dmMuY2hhbi5kZXZpY2UtPmRldiwKPiA+ICsgICAgICAg ICAgICAgICAgICAgICAgICJkbWEgc3RvcDogcG9sbGluZyBWRkZfRU4gZmFpbCwgREVCVUc9MHgl eFxuIiwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIG10a19kbWFfY2hhbl9yZWFkKGMsIFZG Rl9ERUJVR19TVEFUVVMpKTsKPiA+ICsKPiA+ICsgICAgICAgbXRrX2RtYV9jaGFuX3dyaXRlKGMs IFZGRl9TVE9QLCBWRkZfU1RPUF9DTFJfQik7Cj4gPiArICAgICAgIG10a19kbWFfY2hhbl93cml0 ZShjLCBWRkZfSU5UX0VOLCBWRkZfSU5UX0VOX0NMUl9CKTsKPiA+ICsKPiA+ICsgICAgICAgaWYg KGMtPmNmZy5kaXJlY3Rpb24gPT0gRE1BX0RFVl9UT19NRU0pCj4gPiArICAgICAgICAgICAgICAg bXRrX2RtYV9jaGFuX3dyaXRlKGMsIFZGRl9JTlRfRkxBRywgVkZGX1JYX0lOVF9GTEFHX0NMUl9C KTsKPiA+ICsgICAgICAgZWxzZQo+ID4gKyAgICAgICAgICAgICAgIG10a19kbWFfY2hhbl93cml0 ZShjLCBWRkZfSU5UX0ZMQUcsIFZGRl9UWF9JTlRfRkxBR19DTFJfQik7Cj4gPiArCj4gPiArICAg ICAgIGMtPnN0b3AgPSB0cnVlOwo+ID4gK30KPiA+ICsKPiA+ICsvKgo+ID4gKyAqIFRoaXMgY2Fs bGJhY2sgc2NoZWR1bGVzIGFsbCBwZW5kaW5nIGNoYW5uZWxzLiBXZSBjb3VsZCBiZSBtb3JlCj4g PiArICogY2xldmVyIGhlcmUgYnkgcG9zdHBvbmluZyBhbGxvY2F0aW9uIG9mIHRoZSByZWFsIERN QSBjaGFubmVscyB0bwo+ID4gKyAqIHRoaXMgcG9pbnQsIGFuZCBmcmVlaW5nIHRoZW0gd2hlbiBv dXIgdmlydHVhbCBjaGFubmVsIGJlY29tZXMgaWRsZS4KPiA+ICsgKgo+ID4gKyAqIFdlIHdvdWxk IHRoZW4gbmVlZCB0byBkZWFsIHdpdGggJ2FsbCBjaGFubmVscyBpbi11c2UnCj4gPiArICovCj4g PiArc3RhdGljIHZvaWQgbXRrX2RtYV9zY2hlZCh1bnNpZ25lZCBsb25nIGRhdGEpCj4gPiArewo+ ID4gKyAgICAgICBzdHJ1Y3QgbXRrX2RtYWRldiAqbXRrZCA9IChzdHJ1Y3QgbXRrX2RtYWRldiAq KWRhdGE7Cj4gPiArICAgICAgIHN0cnVjdCB2aXJ0X2RtYV9kZXNjICp2ZDsKPiA+ICsgICAgICAg c3RydWN0IG10a19jaGFuICpjOwo+ID4gKyAgICAgICBkbWFfY29va2llX3QgY29va2llOwo+ID4g KyAgICAgICB1bnNpZ25lZCBsb25nIGZsYWdzOwo+ID4gKyAgICAgICBMSVNUX0hFQUQoaGVhZCk7 Cj4gPiArCj4gPiArICAgICAgIHNwaW5fbG9ja19pcnEoJm10a2QtPmxvY2spOwo+ID4gKyAgICAg ICBsaXN0X3NwbGljZV90YWlsX2luaXQoJm10a2QtPnBlbmRpbmcsICZoZWFkKTsKPiA+ICsgICAg ICAgc3Bpbl91bmxvY2tfaXJxKCZtdGtkLT5sb2NrKTsKPiA+ICsKPiA+ICsgICAgICAgaWYgKCFs aXN0X2VtcHR5KCZoZWFkKSkgewo+ID4gKyAgICAgICAgICAgICAgIGMgPSBsaXN0X2ZpcnN0X2Vu dHJ5KCZoZWFkLCBzdHJ1Y3QgbXRrX2NoYW4sIG5vZGUpOwo+ID4gKyAgICAgICAgICAgICAgIGNv b2tpZSA9IGMtPnZjLmNoYW4uY29va2llOwo+ID4gKwo+ID4gKyAgICAgICAgICAgICAgIHNwaW5f bG9ja19pcnFzYXZlKCZjLT52Yy5sb2NrLCBmbGFncyk7Cj4gPiArICAgICAgICAgICAgICAgaWYg KGMtPmNmZy5kaXJlY3Rpb24gPT0gRE1BX0RFVl9UT19NRU0pIHsKPiA+ICsgICAgICAgICAgICAg ICAgICAgICAgIGxpc3RfZGVsX2luaXQoJmMtPm5vZGUpOwo+ID4gKyAgICAgICAgICAgICAgICAg ICAgICAgbXRrX2RtYV9zdGFydF9yeChjKTsKPiA+ICsgICAgICAgICAgICAgICB9IGVsc2UgaWYg KGMtPmNmZy5kaXJlY3Rpb24gPT0gRE1BX01FTV9UT19ERVYpIHsKPiA+ICsgICAgICAgICAgICAg ICAgICAgICAgIHZkID0gdmNoYW5fZmluZF9kZXNjKCZjLT52YywgY29va2llKTsKPiA+ICsgICAg ICAgICAgICAgICAgICAgICAgIGMtPmRlc2MgPSB0b19tdGtfZG1hX2Rlc2MoJnZkLT50eCk7Cj4g PiArICAgICAgICAgICAgICAgICAgICAgICBsaXN0X2RlbF9pbml0KCZjLT5ub2RlKTsKPiA+ICsg ICAgICAgICAgICAgICAgICAgICAgIG10a19kbWFfc3RhcnRfdHgoYyk7Cj4gPiArICAgICAgICAg ICAgICAgfQo+ID4gKyAgICAgICAgICAgICAgIHNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmMtPnZj LmxvY2ssIGZsYWdzKTsKPiA+ICsgICAgICAgfQo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50 IG10a19kbWFfYWxsb2NfY2hhbl9yZXNvdXJjZXMoc3RydWN0IGRtYV9jaGFuICpjaGFuKQo+ID4g K3sKPiA+ICsgICAgICAgc3RydWN0IG10a19kbWFkZXYgKm10a2QgPSB0b19tdGtfZG1hX2Rldihj aGFuLT5kZXZpY2UpOwo+ID4gKyAgICAgICBzdHJ1Y3QgbXRrX2NoYW4gKmMgPSB0b19tdGtfZG1h X2NoYW4oY2hhbik7Cj4gPiArICAgICAgIGludCByZXQgPSAtRUJVU1k7Cj4gPiArCj4gPiArICAg ICAgIHBtX3J1bnRpbWVfZ2V0X3N5bmMobXRrZC0+ZGRldi5kZXYpOwo+ID4gKwo+ID4gKyAgICAg ICBpZiAoIW10a2QtPmNoW2MtPmRtYV9jaF0pIHsKPiA+ICsgICAgICAgICAgICAgICBjLT5iYXNl ID0gbXRrZC0+bWVtX2Jhc2VbYy0+ZG1hX2NoXTsKPiA+ICsgICAgICAgICAgICAgICBtdGtkLT5j aFtjLT5kbWFfY2hdID0gYzsKPiA+ICsgICAgICAgICAgICAgICByZXQgPSAxOwo+ID4gKyAgICAg ICB9Cj4gPiArICAgICAgIGMtPnJlcXVlc3RlZCA9IGZhbHNlOwo+ID4gKyAgICAgICBtdGtfZG1h X3Jlc2V0KGMpOwo+ID4gKwo+ID4gKyAgICAgICByZXR1cm4gcmV0Owo+ID4gK30KPiA+ICsKPiA+ ICtzdGF0aWMgdm9pZCBtdGtfZG1hX2ZyZWVfY2hhbl9yZXNvdXJjZXMoc3RydWN0IGRtYV9jaGFu ICpjaGFuKQo+ID4gK3sKPiA+ICsgICAgICAgc3RydWN0IG10a19kbWFkZXYgKm10a2QgPSB0b19t dGtfZG1hX2RldihjaGFuLT5kZXZpY2UpOwo+ID4gKyAgICAgICBzdHJ1Y3QgbXRrX2NoYW4gKmMg PSB0b19tdGtfZG1hX2NoYW4oY2hhbik7Cj4gPiArCj4gPiArICAgICAgIGlmIChjLT5yZXF1ZXN0 ZWQpIHsKPiA+ICsgICAgICAgICAgICAgICBjLT5yZXF1ZXN0ZWQgPSBmYWxzZTsKPiA+ICsgICAg ICAgICAgICAgICBmcmVlX2lycShtdGtkLT5kbWFfaXJxW2MtPmRtYV9jaF0sIGNoYW4pOwo+ID4g KyAgICAgICB9Cj4gPiArCj4gPiArICAgICAgIHRhc2tsZXRfa2lsbCgmbXRrZC0+dGFzayk7Cj4g PiArICAgICAgIHRhc2tsZXRfa2lsbCgmYy0+dmMudGFzayk7Cj4gPiArCj4gPiArICAgICAgIGMt PmJhc2UgPSBOVUxMOwo+ID4gKyAgICAgICBtdGtkLT5jaFtjLT5kbWFfY2hdID0gTlVMTDsKPiA+ ICsgICAgICAgdmNoYW5fZnJlZV9jaGFuX3Jlc291cmNlcygmYy0+dmMpOwo+ID4gKwo+ID4gKyAg ICAgICBkZXZfZGJnKG10a2QtPmRkZXYuZGV2LCAiZnJlZWluZyBjaGFubmVsIGZvciAldVxuIiwg Yy0+ZG1hX3NpZyk7Cj4gPiArICAgICAgIGMtPmRtYV9zaWcgPSAwOwo+ID4gKwo+ID4gKyAgICAg ICBwbV9ydW50aW1lX3B1dF9zeW5jKG10a2QtPmRkZXYuZGV2KTsKPiA+ICt9Cj4gPiArCj4gPiAr c3RhdGljIGVudW0gZG1hX3N0YXR1cyBtdGtfZG1hX3R4X3N0YXR1cyhzdHJ1Y3QgZG1hX2NoYW4g KmNoYW4sCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRtYV9j b29raWVfdCBjb29raWUsCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIHN0cnVjdCBkbWFfdHhfc3RhdGUgKnR4c3RhdGUpCj4gPiArewo+ID4gKyAgICAgICBzdHJ1 Y3QgbXRrX2NoYW4gKmMgPSB0b19tdGtfZG1hX2NoYW4oY2hhbik7Cj4gPiArICAgICAgIGVudW0g ZG1hX3N0YXR1cyByZXQ7Cj4gPiArICAgICAgIHVuc2lnbmVkIGxvbmcgZmxhZ3M7Cj4gPiArCj4g PiArICAgICAgIGlmICghdHhzdGF0ZSkKPiA+ICsgICAgICAgICAgICAgICByZXR1cm4gRE1BX0VS Uk9SOwo+ID4gKwo+ID4gKyAgICAgICByZXQgPSBkbWFfY29va2llX3N0YXR1cyhjaGFuLCBjb29r aWUsIHR4c3RhdGUpOwo+ID4gKyAgICAgICBzcGluX2xvY2tfaXJxc2F2ZSgmYy0+dmMubG9jaywg ZmxhZ3MpOwo+ID4gKyAgICAgICBpZiAocmV0ID09IERNQV9JTl9QUk9HUkVTUykgewo+ID4gKyAg ICAgICAgICAgICAgIGMtPnJ4X3B0ciA9IG10a19kbWFfY2hhbl9yZWFkKGMsIFZGRl9SUFQpICYg TVRLX0RNQV9SSU5HX1NJWkU7Cj4gPiArICAgICAgICAgICAgICAgZG1hX3NldF9yZXNpZHVlKHR4 c3RhdGUsIGMtPnJ4X3B0cik7Cj4gPiArICAgICAgIH0gZWxzZSBpZiAocmV0ID09IERNQV9DT01Q TEVURSAmJiBjLT5jZmcuZGlyZWN0aW9uID09IERNQV9ERVZfVE9fTUVNKSB7Cj4gPiArICAgICAg ICAgICAgICAgZG1hX3NldF9yZXNpZHVlKHR4c3RhdGUsIGMtPnJlbWFpbl9zaXplKTsKPiA+ICsg ICAgICAgfSBlbHNlIHsKPiA+ICsgICAgICAgICAgICAgICBkbWFfc2V0X3Jlc2lkdWUodHhzdGF0 ZSwgMCk7Cj4gPiArICAgICAgIH0KPiA+ICsgICAgICAgc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgm Yy0+dmMubG9jaywgZmxhZ3MpOwo+ID4gKwo+ID4gKyAgICAgICByZXR1cm4gcmV0Owo+ID4gK30K PiA+ICsKPiA+ICtzdGF0aWMgc3RydWN0IGRtYV9hc3luY190eF9kZXNjcmlwdG9yICptdGtfZG1h X3ByZXBfc2xhdmVfc2cKPiA+ICsgICAgICAgKHN0cnVjdCBkbWFfY2hhbiAqY2hhbiwgc3RydWN0 IHNjYXR0ZXJsaXN0ICpzZ2wsCj4gPiArICAgICAgIHVuc2lnbmVkIGludCBzZ2xlbiwgICAgIGVu dW0gZG1hX3RyYW5zZmVyX2RpcmVjdGlvbiBkaXIsCj4gPiArICAgICAgIHVuc2lnbmVkIGxvbmcg dHhfZmxhZ3MsIHZvaWQgKmNvbnRleHQpCj4gPiArewo+ID4gKyAgICAgICBzdHJ1Y3QgbXRrX2No YW4gKmMgPSB0b19tdGtfZG1hX2NoYW4oY2hhbik7Cj4gPiArICAgICAgIHN0cnVjdCBzY2F0dGVy bGlzdCAqc2dlbnQ7Cj4gPiArICAgICAgIHN0cnVjdCBtdGtfZG1hX2Rlc2MgKmQ7Cj4gPiArICAg ICAgIHN0cnVjdCBtdGtfZG1hX3NnICpzZzsKPiA+ICsgICAgICAgdW5zaWduZWQgaW50IHNpemUs IGksIGosIGVuOwo+ID4gKwo+ID4gKyAgICAgICBlbiA9IDE7Cj4gPiArCj4gPiArICAgICAgIGlm ICgoZGlyICE9IERNQV9ERVZfVE9fTUVNKSAmJgo+ID4gKyAgICAgICAgICAgICAgIChkaXIgIT0g RE1BX01FTV9UT19ERVYpKSB7Cj4gPiArICAgICAgICAgICAgICAgZGV2X2VycihjaGFuLT5kZXZp Y2UtPmRldiwgImJhZCBkaXJlY3Rpb25cbiIpOwo+ID4gKyAgICAgICAgICAgICAgIHJldHVybiBO VUxMOwo+ID4gKyAgICAgICB9Cj4gPiArCj4gPiArICAgICAgIC8qIE5vdyBhbGxvY2F0ZSBhbmQg c2V0dXAgdGhlIGRlc2NyaXB0b3IuICovCj4gPiArICAgICAgIGQgPSBremFsbG9jKHNpemVvZigq ZCkgKyBzZ2xlbiAqIHNpemVvZihkLT5zZ1swXSksIEdGUF9BVE9NSUMpOwo+ID4gKyAgICAgICBp ZiAoIWQpCj4gPiArICAgICAgICAgICAgICAgcmV0dXJuIE5VTEw7Cj4gPiArCj4gPiArICAgICAg IGQtPmRpciA9IGRpcjsKPiA+ICsKPiA+ICsgICAgICAgaiA9IDA7Cj4gPiArICAgICAgIGZvcl9l YWNoX3NnKHNnbCwgc2dlbnQsIHNnbGVuLCBpKSB7Cj4gPiArICAgICAgICAgICAgICAgZC0+c2db al0uYWRkciA9IHNnX2RtYV9hZGRyZXNzKHNnZW50KTsKPiA+ICsgICAgICAgICAgICAgICBkLT5z Z1tqXS5lbiA9IGVuOwo+ID4gKyAgICAgICAgICAgICAgIGQtPnNnW2pdLmZuID0gc2dfZG1hX2xl bihzZ2VudCkgLyBlbjsKPiA+ICsgICAgICAgICAgICAgICBqKys7Cj4gPiArICAgICAgIH0KPiA+ ICsKPiA+ICsgICAgICAgZC0+c2dsZW4gPSBqOwo+ID4gKwo+ID4gKyAgICAgICBpZiAoZGlyID09 IERNQV9NRU1fVE9fREVWKSB7Cj4gPiArICAgICAgICAgICAgICAgZm9yIChzaXplID0gaSA9IDA7 IGkgPCBkLT5zZ2xlbjsgaSsrKSB7Cj4gPiArICAgICAgICAgICAgICAgICAgICAgICBzZyA9ICZk LT5zZ1tpXTsKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHNpemUgKz0gc2ctPmVuICogc2ct PmZuOwo+ID4gKyAgICAgICAgICAgICAgIH0KPiA+ICsgICAgICAgICAgICAgICBjLT5yZW1haW5f c2l6ZSA9IHNpemU7Cj4gPiArICAgICAgIH0KPiA+ICsKPiA+ICsgICAgICAgcmV0dXJuIHZjaGFu X3R4X3ByZXAoJmMtPnZjLCAmZC0+dmQsIHR4X2ZsYWdzKTsKPiA+ICt9Cj4gPiArCj4gPiArc3Rh dGljIHZvaWQgbXRrX2RtYV9pc3N1ZV9wZW5kaW5nKHN0cnVjdCBkbWFfY2hhbiAqY2hhbikKPiA+ ICt7Cj4gPiArICAgICAgIHN0cnVjdCBtdGtfY2hhbiAqYyA9IHRvX210a19kbWFfY2hhbihjaGFu KTsKPiA+ICsgICAgICAgc3RydWN0IHZpcnRfZG1hX2Rlc2MgKnZkOwo+ID4gKyAgICAgICBzdHJ1 Y3QgbXRrX2RtYWRldiAqbXRrZDsKPiA+ICsgICAgICAgZG1hX2Nvb2tpZV90IGNvb2tpZTsKPiA+ ICsgICAgICAgdW5zaWduZWQgbG9uZyBmbGFnczsKPiA+ICsKPiA+ICsgICAgICAgc3Bpbl9sb2Nr X2lycXNhdmUoJmMtPnZjLmxvY2ssIGZsYWdzKTsKPiA+ICsgICAgICAgaWYgKGMtPmNmZy5kaXJl Y3Rpb24gPT0gRE1BX0RFVl9UT19NRU0pIHsKPiA+ICsgICAgICAgICAgICAgICBjb29raWUgPSBj LT52Yy5jaGFuLmNvb2tpZTsKPiA+ICsgICAgICAgICAgICAgICBtdGtkID0gdG9fbXRrX2RtYV9k ZXYoY2hhbi0+ZGV2aWNlKTsKPiA+ICsgICAgICAgICAgICAgICBpZiAodmNoYW5faXNzdWVfcGVu ZGluZygmYy0+dmMpICYmICFjLT5kZXNjKSB7Cj4gCj4gdmNoYW5faXNzdWVfcGVuZGluZyBtZWFu cyBwdXR0aW5nIGFsbCB0aGUgZGVzY3JpcHRvcnMgdG8gbGlzdAo+IGRlc2NfaXNzdWVkLCBJJ20g c3VwcG9zZWQgc29tZXdoZXJlIHdvdWxkIGl0ZXJhdGUgdGhlIGxpc3QgYnkKPiB2Y2hhbl9uZXh0 X2Rlc2MgYW5kIHByb2dyYW0gZWFjaCBkZXNjLiBpbnRvIGhhcmR3YXJlLiBidXQgSSBkb24ndCBz ZWUKPiB0aGUgc2ltaWxhciBjb2RlLgoKb2ssIGkgd2lsbCBtb2RpZnkgaXQgYXQgbmV4dCBwYXRj aAoKPiAKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHZkID0gdmNoYW5fZmluZF9kZXNjKCZj LT52YywgY29va2llKTsKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIGMtPmRlc2MgPSB0b19t dGtfZG1hX2Rlc2MoJnZkLT50eCk7Cj4gPiArICAgICAgICAgICAgICAgfQo+ID4gKyAgICAgICB9 IGVsc2UgaWYgKGMtPmNmZy5kaXJlY3Rpb24gPT0gRE1BX01FTV9UT19ERVYpIHsKPiA+ICsgICAg ICAgICAgICAgICBjb29raWUgPSBjLT52Yy5jaGFuLmNvb2tpZTsKPiA+ICsgICAgICAgICAgICAg ICBpZiAodmNoYW5faXNzdWVfcGVuZGluZygmYy0+dmMpICYmICFjLT5kZXNjKSB7Cj4gCj4gZGl0 dG8gYXMgdGhlIGFib3ZlCj4gCgpvaywgaSB3aWxsIG1vZGlmeSBpdCBhdCBuZXh0IHBhdGNoCgo+ ID4gKyAgICAgICAgICAgICAgICAgICAgICAgdmQgPSB2Y2hhbl9maW5kX2Rlc2MoJmMtPnZjLCBj b29raWUpOwo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgYy0+ZGVzYyA9IHRvX210a19kbWFf ZGVzYygmdmQtPnR4KTsKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIG10a19kbWFfc3RhcnRf dHgoYyk7Cj4gPiArICAgICAgICAgICAgICAgfQo+ID4gKyAgICAgICB9Cj4gPiArICAgICAgIHNw aW5fdW5sb2NrX2lycXJlc3RvcmUoJmMtPnZjLmxvY2ssIGZsYWdzKTsKPiA+ICt9Cj4gPiArCj4g PiArc3RhdGljIGlycXJldHVybl90IG10a19kbWFfcnhfaW50ZXJydXB0KGludCBpcnEsIHZvaWQg KmRldl9pZCkKPiA+ICt7Cj4gPiArICAgICAgIHN0cnVjdCBkbWFfY2hhbiAqY2hhbiA9IChzdHJ1 Y3QgZG1hX2NoYW4gKilkZXZfaWQ7Cj4gPiArICAgICAgIHN0cnVjdCBtdGtfY2hhbiAqYyA9IHRv X210a19kbWFfY2hhbihjaGFuKTsKPiA+ICsgICAgICAgdW5zaWduZWQgbG9uZyBmbGFnczsKPiA+ ICsKPiA+ICsgICAgICAgc3Bpbl9sb2NrX2lycXNhdmUoJmMtPnZjLmxvY2ssIGZsYWdzKTsKPiA+ ICsgICAgICAgbXRrX2RtYV9jaGFuX3dyaXRlKGMsIFZGRl9JTlRfRkxBRywgVkZGX1JYX0lOVF9G TEFHX0NMUl9CKTsKPiA+ICsKPiA+ICsgICAgICAgbXRrX2RtYV9zdGFydF9yeChjKTsKPiA+ICsK PiA+ICsgICAgICAgc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmYy0+dmMubG9jaywgZmxhZ3MpOwo+ ID4gKwo+ID4gKyAgICAgICByZXR1cm4gSVJRX0hBTkRMRUQ7Cj4gPiArfQo+ID4gKwo+ID4gK3N0 YXRpYyBpcnFyZXR1cm5fdCBtdGtfZG1hX3R4X2ludGVycnVwdChpbnQgaXJxLCB2b2lkICpkZXZf aWQpCj4gPiArewo+ID4gKyAgICAgICBzdHJ1Y3QgZG1hX2NoYW4gKmNoYW4gPSAoc3RydWN0IGRt YV9jaGFuICopZGV2X2lkOwo+ID4gKyAgICAgICBzdHJ1Y3QgbXRrX2RtYWRldiAqbXRrZCA9IHRv X210a19kbWFfZGV2KGNoYW4tPmRldmljZSk7Cj4gPiArICAgICAgIHN0cnVjdCBtdGtfY2hhbiAq YyA9IHRvX210a19kbWFfY2hhbihjaGFuKTsKPiA+ICsgICAgICAgc3RydWN0IG10a19kbWFfZGVz YyAqZCA9IGMtPmRlc2M7Cj4gPiArICAgICAgIHVuc2lnbmVkIGxvbmcgZmxhZ3M7Cj4gPiArCj4g PiArICAgICAgIHNwaW5fbG9ja19pcnFzYXZlKCZjLT52Yy5sb2NrLCBmbGFncyk7Cj4gPiArICAg ICAgIGlmIChjLT5yZW1haW5fc2l6ZSAhPSAwVSkgewo+ID4gKyAgICAgICAgICAgICAgIGxpc3Rf YWRkX3RhaWwoJmMtPm5vZGUsICZtdGtkLT5wZW5kaW5nKTsKPiA+ICsgICAgICAgICAgICAgICB0 YXNrbGV0X3NjaGVkdWxlKCZtdGtkLT50YXNrKTsKPiA+ICsgICAgICAgfSBlbHNlIHsKPiA+ICsg ICAgICAgICAgICAgICBtdGtfZG1hX3JlbW92ZV92aXJ0X2xpc3QoZC0+dmQudHguY29va2llLCAm Yy0+dmMpOwo+ID4gKyAgICAgICAgICAgICAgIHZjaGFuX2Nvb2tpZV9jb21wbGV0ZSgmZC0+dmQp Owo+ID4gKyAgICAgICB9Cj4gPiArICAgICAgIHNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmMtPnZj LmxvY2ssIGZsYWdzKTsKPiA+ICsKPiA+ICsgICAgICAgbXRrX2RtYV9jaGFuX3dyaXRlKGMsIFZG Rl9JTlRfRkxBRywgVkZGX1RYX0lOVF9GTEFHX0NMUl9CKTsKPiA+ICsKPiA+ICsgICAgICAgcmV0 dXJuIElSUV9IQU5ETEVEOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50IG10a19kbWFfc2xh dmVfY29uZmlnKHN0cnVjdCBkbWFfY2hhbiAqY2hhbiwKPiA+ICsgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgc3RydWN0IGRtYV9zbGF2ZV9jb25maWcgKmNmZykKPiA+ICt7Cj4gPiArICAg ICAgIHN0cnVjdCBtdGtfY2hhbiAqYyA9IHRvX210a19kbWFfY2hhbihjaGFuKTsKPiA+ICsgICAg ICAgc3RydWN0IG10a19kbWFkZXYgKm10a2QgPSB0b19tdGtfZG1hX2RldihjLT52Yy5jaGFuLmRl dmljZSk7Cj4gPiArICAgICAgIGludCByZXQ7Cj4gPiArCj4gPiArICAgICAgIGMtPmNmZyA9ICpj Zmc7Cj4gPiArCj4gPiArICAgICAgIGlmIChjZmctPmRpcmVjdGlvbiA9PSBETUFfREVWX1RPX01F TSkgewo+ID4gKyAgICAgICAgICAgICAgIHVuc2lnbmVkIGludCByeF9sZW4gPSBjZmctPnNyY19h ZGRyX3dpZHRoICogMTAyNDsKPiA+ICsKPiA+ICsgICAgICAgICAgICAgICBtdGtfZG1hX2NoYW5f d3JpdGUoYywgVkZGX0FERFIsIGNmZy0+c3JjX2FkZHIpOwo+ID4gKyAgICAgICAgICAgICAgIG10 a19kbWFfY2hhbl93cml0ZShjLCBWRkZfTEVOLCByeF9sZW4pOwo+ID4gKyAgICAgICAgICAgICAg IG10a19kbWFfY2hhbl93cml0ZShjLCBWRkZfVEhSRSwgVkZGX1JYX1RIUkUocnhfbGVuKSk7Cj4g PiArICAgICAgICAgICAgICAgbXRrX2RtYV9jaGFuX3dyaXRlKGMsCj4gPiArICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIFZGRl9JTlRfRU4sIFZGRl9SWF9JTlRfRU4wX0IKPiA+ICsg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCBWRkZfUlhfSU5UX0VOMV9CKTsKPiA+ ICsgICAgICAgICAgICAgICBtdGtfZG1hX2NoYW5fd3JpdGUoYywgVkZGX0lOVF9GTEFHLCBWRkZf UlhfSU5UX0ZMQUdfQ0xSX0IpOwo+ID4gKyAgICAgICAgICAgICAgIG10a19kbWFfY2hhbl93cml0 ZShjLCBWRkZfRU4sIFZGRl9FTl9CKTsKPiA+ICsKPiA+ICsgICAgICAgICAgICAgICBpZiAoIWMt PnJlcXVlc3RlZCkgewo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgYy0+cmVxdWVzdGVkID0g dHJ1ZTsKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJldCA9IHJlcXVlc3RfaXJxKG10a2Qt PmRtYV9pcnFbYy0+ZG1hX2NoXSwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIG10a19kbWFfcnhfaW50ZXJydXB0LAo+ID4gKyAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgSVJRRl9UUklHR0VSX05PTkUsCj4gPiArICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBLQlVJTERfTU9ETkFNRSwgY2hhbik7Cj4gPiAr ICAgICAgICAgICAgICAgICAgICAgICBpZiAocmV0IDwgMCkgewo+ID4gKyAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICBkZXZfZXJyKGNoYW4tPmRldmljZS0+ZGV2LCAiQ2FuJ3QgcmVxdWVz dCByeCBkbWEgSVJRXG4iKTsKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0 dXJuIC1FSU5WQUw7Cj4gPiArICAgICAgICAgICAgICAgICAgICAgICB9Cj4gPiArICAgICAgICAg ICAgICAgfQo+ID4gKyAgICAgICB9IGVsc2UgaWYgKGNmZy0+ZGlyZWN0aW9uID09IERNQV9NRU1f VE9fREVWKSAgICB7Cj4gPiArICAgICAgICAgICAgICAgdW5zaWduZWQgaW50IHR4X2xlbiA9IGNm Zy0+ZHN0X2FkZHJfd2lkdGggKiAxMDI0Owo+ID4gKwo+ID4gKyAgICAgICAgICAgICAgIG10a19k bWFfY2hhbl93cml0ZShjLCBWRkZfQUREUiwgY2ZnLT5kc3RfYWRkcik7Cj4gPiArICAgICAgICAg ICAgICAgbXRrX2RtYV9jaGFuX3dyaXRlKGMsIFZGRl9MRU4sIHR4X2xlbik7Cj4gPiArICAgICAg ICAgICAgICAgbXRrX2RtYV9jaGFuX3dyaXRlKGMsIFZGRl9USFJFLCBWRkZfVFhfVEhSRSh0eF9s ZW4pKTsKPiA+ICsgICAgICAgICAgICAgICBtdGtfZG1hX2NoYW5fd3JpdGUoYywgVkZGX0lOVF9G TEFHLCBWRkZfVFhfSU5UX0ZMQUdfQ0xSX0IpOwo+ID4gKyAgICAgICAgICAgICAgIG10a19kbWFf Y2hhbl93cml0ZShjLCBWRkZfRU4sIFZGRl9FTl9CKTsKPiA+ICsKPiA+ICsgICAgICAgICAgICAg ICBpZiAoIWMtPnJlcXVlc3RlZCkgewo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgYy0+cmVx dWVzdGVkID0gdHJ1ZTsKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJldCA9IHJlcXVlc3Rf aXJxKG10a2QtPmRtYV9pcnFbYy0+ZG1hX2NoXSwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIG10a19kbWFfdHhfaW50ZXJydXB0LAo+ID4gKyAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSVJRRl9UUklHR0VSX05PTkUsCj4gPiArICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBLQlVJTERfTU9ETkFNRSwgY2hh bik7Cj4gPiArICAgICAgICAgICAgICAgICAgICAgICBpZiAocmV0IDwgMCkgewo+ID4gKyAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZfZXJyKGNoYW4tPmRldmljZS0+ZGV2LCAiQ2Fu J3QgcmVxdWVzdCB0eCBkbWEgSVJRXG4iKTsKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgcmV0dXJuIC1FSU5WQUw7Cj4gPiArICAgICAgICAgICAgICAgICAgICAgICB9Cj4gPiAr ICAgICAgICAgICAgICAgfQo+ID4gKyAgICAgICB9Cj4gPiArCj4gPiArICAgICAgIGlmIChtdGtk LT5zdXBwb3J0XzMzYml0cykKPiA+ICsgICAgICAgICAgICAgICBtdGtfZG1hX2NoYW5fd3JpdGUo YywgVkZGXzRHX1NVUFBPUlQsIFZGRl80R19TVVBQT1JUX0IpOwo+ID4gKwo+ID4gKyAgICAgICBp ZiAobXRrX2RtYV9jaGFuX3JlYWQoYywgVkZGX0VOKSAhPSBWRkZfRU5fQikgewo+ID4gKyAgICAg ICAgICAgICAgIGRldl9lcnIoY2hhbi0+ZGV2aWNlLT5kZXYsCj4gPiArICAgICAgICAgICAgICAg ICAgICAgICAiY29uZmlnIGRtYSBkaXJbJWRdIGZhaWxcbiIsIGNmZy0+ZGlyZWN0aW9uKTsKPiA+ ICsgICAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsKPiA+ICsgICAgICAgfQo+ID4gKwo+ID4g KyAgICAgICByZXR1cm4gMDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGludCBtdGtfZG1hX3Rl cm1pbmF0ZV9hbGwoc3RydWN0IGRtYV9jaGFuICpjaGFuKQo+ID4gK3sKPiA+ICsgICAgICAgc3Ry dWN0IG10a19jaGFuICpjID0gdG9fbXRrX2RtYV9jaGFuKGNoYW4pOwo+ID4gKyAgICAgICB1bnNp Z25lZCBsb25nIGZsYWdzOwo+ID4gKwo+ID4gKyAgICAgICBzcGluX2xvY2tfaXJxc2F2ZSgmYy0+ dmMubG9jaywgZmxhZ3MpOwo+ID4gKyAgICAgICBsaXN0X2RlbF9pbml0KCZjLT5ub2RlKTsKPiA+ ICsgICAgICAgbXRrX2RtYV9zdG9wKGMpOwo+ID4gKyAgICAgICBzcGluX3VubG9ja19pcnFyZXN0 b3JlKCZjLT52Yy5sb2NrLCBmbGFncyk7Cj4gPiArCj4gPiArICAgICAgIHJldHVybiAwOwo+ID4g K30KPiA+ICsKPiA+ICtzdGF0aWMgaW50IG10a19kbWFfZGV2aWNlX3BhdXNlKHN0cnVjdCBkbWFf Y2hhbiAqY2hhbikKPiA+ICt7Cj4gPiArICAgICAgIC8qIGp1c3QgZm9yIGNoZWNrIGNhcHMgcGFz cyAqLwo+ID4gKyAgICAgICByZXR1cm4gLUVJTlZBTDsKPiA+ICt9Cj4gCj4gaXQgaXQgcG9zc2li bGUgbm90IHRvIHJlZ2lzdGVyIHRoZSBmdW5jdGlvbiB0byB0aGUgY29yZSBpZiB0aGUKPiBoYXJk d2FyZSBkb2Vzbid0IHN1cHBvcnQgaXQ/Cj4gCgpjYW4ndCBzdXBwb3J0LiB0aGUgZnVuY3Rpb24g d2lsbCBzZXQgdG8gY21kX3BhdXNlLiBpbiA4MjUwIHNlcmlhbCBjb2RlLAp3aWxsIGNoZWNrIGNt ZF9wYXVzZS4gaWYgbm8gdGhlIGZ1bmN0aW9uLCB3aWxsIGNhbid0IGdldCBETUEgY2hhbm5lbC4K U28gCnRoZSBmdW5jdGlvbiBqdXN0IGZvciB0aGlzLgoKPiA+ICsKPiA+ICtzdGF0aWMgaW50IG10 a19kbWFfZGV2aWNlX3Jlc3VtZShzdHJ1Y3QgZG1hX2NoYW4gKmNoYW4pCj4gPiArewo+ID4gKyAg ICAgICAvKiBqdXN0IGZvciBjaGVjayBjYXBzIHBhc3MgKi8KPiA+ICsgICAgICAgcmV0dXJuIC1F SU5WQUw7Cj4gPiArfQo+IAo+IGRpdHRvIGFzIHRoZSBhYm92ZQo+IAo+ID4gKwo+ID4gK3N0YXRp YyB2b2lkIG10a19kbWFfZnJlZShzdHJ1Y3QgbXRrX2RtYWRldiAqbXRrZCkKPiA+ICt7Cj4gPiAr ICAgICAgIHRhc2tsZXRfa2lsbCgmbXRrZC0+dGFzayk7Cj4gPiArICAgICAgIHdoaWxlIChsaXN0 X2VtcHR5KCZtdGtkLT5kZGV2LmNoYW5uZWxzKSA9PSAwKSB7Cj4gPiArICAgICAgICAgICAgICAg c3RydWN0IG10a19jaGFuICpjID0gbGlzdF9maXJzdF9lbnRyeSgmbXRrZC0+ZGRldi5jaGFubmVs cywKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBtdGtfY2hhbiwgdmMuY2hhbi5k ZXZpY2Vfbm9kZSk7Cj4gPiArCj4gPiArICAgICAgICAgICAgICAgbGlzdF9kZWwoJmMtPnZjLmNo YW4uZGV2aWNlX25vZGUpOwo+ID4gKyAgICAgICAgICAgICAgIHRhc2tsZXRfa2lsbCgmYy0+dmMu dGFzayk7Cj4gPiArICAgICAgICAgICAgICAgZGV2bV9rZnJlZShtdGtkLT5kZGV2LmRldiwgYyk7 Cj4gPiArICAgICAgIH0KPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9k ZXZpY2VfaWQgbXRrX3VhcnRfZG1hX21hdGNoW10gPSB7Cj4gPiArICAgICAgIHsgLmNvbXBhdGli bGUgPSAibWVkaWF0ZWssbXQ2NTc3LXVhcnQtZG1hIiwgfSwKPiA+ICsgICAgICAgeyAvKiBzZW50 aW5lbCAqLyB9LAo+ID4gK307Cj4gPiArTU9EVUxFX0RFVklDRV9UQUJMRShvZiwgbXRrX3VhcnRf ZG1hX21hdGNoKTsKPiA+ICsKPiA+ICtzdGF0aWMgaW50IG10a19hcGRtYV9wcm9iZShzdHJ1Y3Qg cGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+ID4gK3sKPiA+ICsgICAgICAgc3RydWN0IG10a19kbWFk ZXYgKm10a2Q7Cj4gPiArICAgICAgIHN0cnVjdCByZXNvdXJjZSAqcmVzOwo+ID4gKyAgICAgICBz dHJ1Y3QgbXRrX2NoYW4gKmM7Cj4gPiArICAgICAgIHVuc2lnbmVkIGludCBpOwo+ID4gKyAgICAg ICBpbnQgcmM7Cj4gPiArCj4gPiArICAgICAgIG10a2QgPSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRl diwgc2l6ZW9mKCptdGtkKSwgR0ZQX0tFUk5FTCk7Cj4gPiArICAgICAgIGlmICghbXRrZCkKPiA+ ICsgICAgICAgICAgICAgICByZXR1cm4gLUVOT01FTTsKPiA+ICsKPiA+ICsgICAgICAgZm9yIChp ID0gMDsgaSA8IE1US19BUERNQV9DSEFOTkVMUzsgaSsrKSB7Cj4gPiArICAgICAgICAgICAgICAg cmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlKHBkZXYsIElPUkVTT1VSQ0VfTUVNLCBpKTsKPiA+ ICsgICAgICAgICAgICAgICBpZiAoIXJlcykKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHJl dHVybiAtRU5PREVWOwo+ID4gKyAgICAgICAgICAgICAgIG10a2QtPm1lbV9iYXNlW2ldID0gZGV2 bV9pb3JlbWFwX3Jlc291cmNlKCZwZGV2LT5kZXYsIHJlcyk7Cj4gPiArICAgICAgICAgICAgICAg aWYgKElTX0VSUihtdGtkLT5tZW1fYmFzZVtpXSkpCj4gPiArICAgICAgICAgICAgICAgICAgICAg ICByZXR1cm4gUFRSX0VSUihtdGtkLT5tZW1fYmFzZVtpXSk7Cj4gPiArICAgICAgIH0KPiA+ICsK PiA+ICsgICAgICAgZm9yIChpID0gMDsgaSA8IE1US19BUERNQV9DSEFOTkVMUzsgaSsrKSB7Cj4g PiArICAgICAgICAgICAgICAgbXRrZC0+ZG1hX2lycVtpXSA9IHBsYXRmb3JtX2dldF9pcnEocGRl diwgaSk7Cj4gPiArICAgICAgICAgICAgICAgaWYgKChpbnQpbXRrZC0+ZG1hX2lycVtpXSA8IDAp IHsKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIGRldl9lcnIoJnBkZXYtPmRldiwgImZhaWxl ZCB0byBnZXQgSVJRWyVkXVxuIiwgaSk7Cj4gPiArICAgICAgICAgICAgICAgICAgICAgICByZXR1 cm4gLUVJTlZBTDsKPiA+ICsgICAgICAgICAgICAgICB9Cj4gPiArICAgICAgIH0KPiA+ICsKPiA+ ICsgICAgICAgbXRrZC0+Y2xrID0gZGV2bV9jbGtfZ2V0KCZwZGV2LT5kZXYsIE5VTEwpOwo+ID4g KyAgICAgICBpZiAoSVNfRVJSKG10a2QtPmNsaykpIHsKPiA+ICsgICAgICAgICAgICAgICBkZXZf ZXJyKCZwZGV2LT5kZXYsICJObyBjbG9jayBzcGVjaWZpZWRcbiIpOwo+ID4gKyAgICAgICAgICAg ICAgIHJldHVybiBQVFJfRVJSKG10a2QtPmNsayk7Cj4gPiArICAgICAgIH0KPiA+ICsKPiA+ICsg ICAgICAgaWYgKG9mX3Byb3BlcnR5X3JlYWRfYm9vbChwZGV2LT5kZXYub2Zfbm9kZSwgImRtYS0z M2JpdHMiKSkgewo+ID4gKyAgICAgICAgICAgICAgIGRldl9pbmZvKCZwZGV2LT5kZXYsICJTdXBw b3J0IGRtYSAzM2JpdHNcbiIpOwo+ID4gKyAgICAgICAgICAgICAgIG10a2QtPnN1cHBvcnRfMzNi aXRzID0gdHJ1ZTsKPiA+ICsgICAgICAgfQo+ID4gKwo+ID4gKyAgICAgICBpZiAobXRrZC0+c3Vw cG9ydF8zM2JpdHMpCj4gPiArICAgICAgICAgICAgICAgcmMgPSBkbWFfc2V0X21hc2tfYW5kX2Nv aGVyZW50KCZwZGV2LT5kZXYsIERNQV9CSVRfTUFTSygzMykpOwo+ID4gKyAgICAgICBlbHNlCj4g PiArICAgICAgICAgICAgICAgcmMgPSBkbWFfc2V0X21hc2tfYW5kX2NvaGVyZW50KCZwZGV2LT5k ZXYsIERNQV9CSVRfTUFTSygzMikpOwo+ID4gKyAgICAgICBpZiAocmMpCj4gPiArICAgICAgICAg ICAgICAgcmV0dXJuIHJjOwo+ID4gKwo+ID4gKyAgICAgICBkbWFfY2FwX3NldChETUFfU0xBVkUs IG10a2QtPmRkZXYuY2FwX21hc2spOwo+ID4gKyAgICAgICBtdGtkLT5kZGV2LmRldmljZV9hbGxv Y19jaGFuX3Jlc291cmNlcyA9IG10a19kbWFfYWxsb2NfY2hhbl9yZXNvdXJjZXM7Cj4gPiArICAg ICAgIG10a2QtPmRkZXYuZGV2aWNlX2ZyZWVfY2hhbl9yZXNvdXJjZXMgPSBtdGtfZG1hX2ZyZWVf Y2hhbl9yZXNvdXJjZXM7Cj4gPiArICAgICAgIG10a2QtPmRkZXYuZGV2aWNlX3R4X3N0YXR1cyA9 IG10a19kbWFfdHhfc3RhdHVzOwo+ID4gKyAgICAgICBtdGtkLT5kZGV2LmRldmljZV9pc3N1ZV9w ZW5kaW5nID0gbXRrX2RtYV9pc3N1ZV9wZW5kaW5nOwo+ID4gKyAgICAgICBtdGtkLT5kZGV2LmRl dmljZV9wcmVwX3NsYXZlX3NnID0gbXRrX2RtYV9wcmVwX3NsYXZlX3NnOwo+ID4gKyAgICAgICBt dGtkLT5kZGV2LmRldmljZV9jb25maWcgPSBtdGtfZG1hX3NsYXZlX2NvbmZpZzsKPiA+ICsgICAg ICAgbXRrZC0+ZGRldi5kZXZpY2VfcGF1c2UgPSBtdGtfZG1hX2RldmljZV9wYXVzZTsKPiA+ICsg ICAgICAgbXRrZC0+ZGRldi5kZXZpY2VfcmVzdW1lID0gbXRrX2RtYV9kZXZpY2VfcmVzdW1lOwo+ ID4gKyAgICAgICBtdGtkLT5kZGV2LmRldmljZV90ZXJtaW5hdGVfYWxsID0gbXRrX2RtYV90ZXJt aW5hdGVfYWxsOwo+ID4gKyAgICAgICBtdGtkLT5kZGV2LnNyY19hZGRyX3dpZHRocyA9IEJJVChE TUFfU0xBVkVfQlVTV0lEVEhfMV9CWVRFKTsKPiA+ICsgICAgICAgbXRrZC0+ZGRldi5kc3RfYWRk cl93aWR0aHMgPSBCSVQoRE1BX1NMQVZFX0JVU1dJRFRIXzFfQllURSk7Cj4gPiArICAgICAgIG10 a2QtPmRkZXYuZGlyZWN0aW9ucyA9IEJJVChETUFfREVWX1RPX01FTSkgfCBCSVQoRE1BX01FTV9U T19ERVYpOwo+ID4gKyAgICAgICBtdGtkLT5kZGV2LnJlc2lkdWVfZ3JhbnVsYXJpdHkgPSBETUFf UkVTSURVRV9HUkFOVUxBUklUWV9TRUdNRU5UOwo+ID4gKyAgICAgICBtdGtkLT5kZGV2LmRldiA9 ICZwZGV2LT5kZXY7Cj4gPiArICAgICAgIElOSVRfTElTVF9IRUFEKCZtdGtkLT5kZGV2LmNoYW5u ZWxzKTsKPiA+ICsgICAgICAgSU5JVF9MSVNUX0hFQUQoJm10a2QtPnBlbmRpbmcpOwo+ID4gKwo+ ID4gKyAgICAgICBzcGluX2xvY2tfaW5pdCgmbXRrZC0+bG9jayk7Cj4gPiArICAgICAgIHRhc2ts ZXRfaW5pdCgmbXRrZC0+dGFzaywgbXRrX2RtYV9zY2hlZCwgKHVuc2lnbmVkIGxvbmcpbXRrZCk7 Cj4gPiArCj4gPiArICAgICAgIG10a2QtPmRtYV9yZXF1ZXN0cyA9IE1US19BUERNQV9ERUZBVUxU X1JFUVVFU1RTOwo+ID4gKyAgICAgICBpZiAob2ZfcHJvcGVydHlfcmVhZF91MzIocGRldi0+ZGV2 Lm9mX25vZGUsCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiZG1hLXJlcXVl c3RzIiwgJm10a2QtPmRtYV9yZXF1ZXN0cykpIHsKPiA+ICsgICAgICAgICAgICAgICBkZXZfaW5m bygmcGRldi0+ZGV2LAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICJNaXNzaW5nIGRtYS1y ZXF1ZXN0cyBwcm9wZXJ0eSwgdXNpbmcgJXUuXG4iLAo+ID4gKyAgICAgICAgICAgICAgICAgICAg ICAgIE1US19BUERNQV9ERUZBVUxUX1JFUVVFU1RTKTsKPiA+ICsgICAgICAgfQo+ID4gKwo+ID4g KyAgICAgICBmb3IgKGkgPSAwOyBpIDwgTVRLX0FQRE1BX0NIQU5ORUxTOyBpKyspIHsKPiA+ICsg ICAgICAgICAgICAgICBjID0gZGV2bV9remFsbG9jKG10a2QtPmRkZXYuZGV2LCBzaXplb2YoKmMp LCBHRlBfS0VSTkVMKTsKPiA+ICsgICAgICAgICAgICAgICBpZiAoIWMpCj4gPiArICAgICAgICAg ICAgICAgICAgICAgICBnb3RvIGVycl9ub19kbWE7Cj4gPiArCj4gPiArICAgICAgICAgICAgICAg Yy0+dmMuZGVzY19mcmVlID0gbXRrX2RtYV9kZXNjX2ZyZWU7Cj4gPiArICAgICAgICAgICAgICAg dmNoYW5faW5pdCgmYy0+dmMsICZtdGtkLT5kZGV2KTsKPiA+ICsgICAgICAgICAgICAgICBJTklU X0xJU1RfSEVBRCgmYy0+bm9kZSk7Cj4gPiArICAgICAgIH0KPiA+ICsKPiA+ICsgICAgICAgcG1f cnVudGltZV9lbmFibGUoJnBkZXYtPmRldik7Cj4gPiArICAgICAgIHBtX3J1bnRpbWVfc2V0X2Fj dGl2ZSgmcGRldi0+ZGV2KTsKPiA+ICsKPiA+ICsgICAgICAgcmMgPSBkbWFfYXN5bmNfZGV2aWNl X3JlZ2lzdGVyKCZtdGtkLT5kZGV2KTsKPiA+ICsgICAgICAgaWYgKHJjKQo+ID4gKyAgICAgICAg ICAgICAgIGdvdG8gcnBtX2Rpc2FibGU7Cj4gPiArCj4gPiArICAgICAgIHBsYXRmb3JtX3NldF9k cnZkYXRhKHBkZXYsIG10a2QpOwo+ID4gKwo+ID4gKyAgICAgICBpZiAocGRldi0+ZGV2Lm9mX25v ZGUpIHsKPiA+ICsgICAgICAgICAgICAgICBtdGtfZG1hX2luZm8uZG1hX2NhcCA9IG10a2QtPmRk ZXYuY2FwX21hc2s7Cj4gPiArCj4gPiArICAgICAgICAgICAgICAgLyogRGV2aWNlLXRyZWUgRE1B IGNvbnRyb2xsZXIgcmVnaXN0cmF0aW9uICovCj4gPiArICAgICAgICAgICAgICAgcmMgPSBvZl9k bWFfY29udHJvbGxlcl9yZWdpc3RlcihwZGV2LT5kZXYub2Zfbm9kZSwKPiA+ICsgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9mX2RtYV9zaW1wbGVfeGxhdGUs Cj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmbXRr X2RtYV9pbmZvKTsKPiAKPiByZXVzaW5nIG9mX2RtYV94bGF0ZV9ieV9jaGFuX2lkIHNlZW0gdGhh dCBhbHNvIHdvcmsgZm9yIHlvdS4KCmluIGZpbHRlcl9mbiBmdW5jdGlvbiwgbmVlZyBnZXQgbnVt YmVyIG9mIGRtYS4KPiAKPiA+ICsgICAgICAgICAgICAgICBpZiAocmMpCj4gPiArICAgICAgICAg ICAgICAgICAgICAgICBnb3RvIGRtYV9yZW1vdmU7Cj4gPiArICAgICAgIH0KPiA+ICsKPiA+ICsg ICAgICAgcmV0dXJuIHJjOwo+ID4gKwo+ID4gK2RtYV9yZW1vdmU6Cj4gPiArICAgICAgIGRtYV9h c3luY19kZXZpY2VfdW5yZWdpc3RlcigmbXRrZC0+ZGRldik7Cj4gPiArcnBtX2Rpc2FibGU6Cj4g PiArICAgICAgIHBtX3J1bnRpbWVfZGlzYWJsZSgmcGRldi0+ZGV2KTsKPiA+ICtlcnJfbm9fZG1h Ogo+ID4gKyAgICAgICBtdGtfZG1hX2ZyZWUobXRrZCk7Cj4gPiArICAgICAgIHJldHVybiByYzsK PiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGludCBtdGtfYXBkbWFfcmVtb3ZlKHN0cnVjdCBwbGF0 Zm9ybV9kZXZpY2UgKnBkZXYpCj4gPiArewo+ID4gKyAgICAgICBzdHJ1Y3QgbXRrX2RtYWRldiAq bXRrZCA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ID4gKwo+ID4gKyAgICAgICBpZiAo cGRldi0+ZGV2Lm9mX25vZGUpCj4gPiArICAgICAgICAgICAgICAgb2ZfZG1hX2NvbnRyb2xsZXJf ZnJlZShwZGV2LT5kZXYub2Zfbm9kZSk7Cj4gPiArCj4gPiArICAgICAgIHBtX3J1bnRpbWVfZGlz YWJsZSgmcGRldi0+ZGV2KTsKPiA+ICsgICAgICAgcG1fcnVudGltZV9wdXRfbm9pZGxlKCZwZGV2 LT5kZXYpOwo+ID4gKwo+ID4gKyAgICAgICBkbWFfYXN5bmNfZGV2aWNlX3VucmVnaXN0ZXIoJm10 a2QtPmRkZXYpOwo+ID4gKwo+ID4gKyAgICAgICBtdGtfZG1hX2ZyZWUobXRrZCk7Cj4gPiArCj4g PiArICAgICAgIHJldHVybiAwOwo+ID4gK30KPiA+ICsKPiA+ICsjaWZkZWYgQ09ORklHX1BNX1NM RUVQCj4gPiArc3RhdGljIGludCBtdGtfZG1hX3N1c3BlbmQoc3RydWN0IGRldmljZSAqZGV2KQo+ ID4gK3sKPiA+ICsgICAgICAgc3RydWN0IG10a19kbWFkZXYgKm10a2QgPSBkZXZfZ2V0X2RydmRh dGEoZGV2KTsKPiA+ICsKPiA+ICsgICAgICAgaWYgKCFwbV9ydW50aW1lX3N1c3BlbmRlZChkZXYp KQo+ID4gKyAgICAgICAgICAgICAgIG10a19kbWFfY2xrX2Rpc2FibGUobXRrZCk7Cj4gPiArCj4g PiArICAgICAgIHJldHVybiAwOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50IG10a19kbWFf cmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRldikKPiA+ICt7Cj4gPiArICAgICAgIGludCByZXQ7Cj4g PiArICAgICAgIHN0cnVjdCBtdGtfZG1hZGV2ICptdGtkID0gZGV2X2dldF9kcnZkYXRhKGRldik7 Cj4gPiArCj4gPiArICAgICAgIGlmICghcG1fcnVudGltZV9zdXNwZW5kZWQoZGV2KSkgewo+ID4g KyAgICAgICAgICAgICAgIHJldCA9IG10a19kbWFfY2xrX2VuYWJsZShtdGtkKTsKPiA+ICsgICAg ICAgICAgICAgICBpZiAocmV0KQo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJl dDsKPiA+ICsgICAgICAgfQo+ID4gKwo+ID4gKyAgICAgICByZXR1cm4gMDsKPiA+ICt9Cj4gPiAr Cj4gPiArc3RhdGljIGludCBtdGtfZG1hX3J1bnRpbWVfc3VzcGVuZChzdHJ1Y3QgZGV2aWNlICpk ZXYpCj4gPiArewo+ID4gKyAgICAgICBzdHJ1Y3QgbXRrX2RtYWRldiAqbXRrZCA9IGRldl9nZXRf ZHJ2ZGF0YShkZXYpOwo+ID4gKwo+ID4gKyAgICAgICBtdGtfZG1hX2Nsa19kaXNhYmxlKG10a2Qp Owo+ID4gKwo+ID4gKyAgICAgICByZXR1cm4gMDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGlu dCBtdGtfZG1hX3J1bnRpbWVfcmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRldikKPiA+ICt7Cj4gPiAr ICAgICAgIGludCByZXQ7Cj4gPiArICAgICAgIHN0cnVjdCBtdGtfZG1hZGV2ICptdGtkID0gZGV2 X2dldF9kcnZkYXRhKGRldik7Cj4gPiArCj4gPiArICAgICAgIHJldCA9IG10a19kbWFfY2xrX2Vu YWJsZShtdGtkKTsKPiA+ICsgICAgICAgaWYgKHJldCkKPiA+ICsgICAgICAgICAgICAgICByZXR1 cm4gcmV0Owo+ID4gKwo+ID4gKyAgICAgICByZXR1cm4gMDsKPiA+ICt9Cj4gPiArCj4gPiArI2Vu ZGlmIC8qIENPTkZJR19QTV9TTEVFUCAqLwo+ID4gKwo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qg ZGV2X3BtX29wcyBtdGtfZG1hX3BtX29wcyA9IHsKPiA+ICsgICAgICAgU0VUX1NZU1RFTV9TTEVF UF9QTV9PUFMobXRrX2RtYV9zdXNwZW5kLCBtdGtfZG1hX3Jlc3VtZSkKPiA+ICsgICAgICAgU0VU X1JVTlRJTUVfUE1fT1BTKG10a19kbWFfcnVudGltZV9zdXNwZW5kLAo+ID4gKyAgICAgICAgICAg ICAgICAgICAgICAgICAgbXRrX2RtYV9ydW50aW1lX3Jlc3VtZSwgTlVMTCkKPiA+ICt9Owo+ID4g Kwo+ID4gK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIG10a19kbWFfZHJpdmVyID0gewo+ ID4gKyAgICAgICAucHJvYmUgID0gbXRrX2FwZG1hX3Byb2JlLAo+ID4gKyAgICAgICAucmVtb3Zl ID0gbXRrX2FwZG1hX3JlbW92ZSwKPiA+ICsgICAgICAgLmRyaXZlciA9IHsKPiA+ICsgICAgICAg ICAgICAgICAubmFtZSAgICAgICAgICAgPSBLQlVJTERfTU9ETkFNRSwKPiA+ICsgICAgICAgICAg ICAgICAucG0gICAgICAgICAgICAgPSAmbXRrX2RtYV9wbV9vcHMsCj4gPiArICAgICAgICAgICAg ICAgLm9mX21hdGNoX3RhYmxlID0gb2ZfbWF0Y2hfcHRyKG10a191YXJ0X2RtYV9tYXRjaCksCj4g PiArICAgICAgIH0sCj4gPiArfTsKPiA+ICsKPiA+ICtzdGF0aWMgYm9vbCBtdGtfZG1hX2ZpbHRl cl9mbihzdHJ1Y3QgZG1hX2NoYW4gKmNoYW4sIHZvaWQgKnBhcmFtKQo+ID4gK3sKPiA+ICsgICAg ICAgaWYgKGNoYW4tPmRldmljZS0+ZGV2LT5kcml2ZXIgPT0gJm10a19kbWFfZHJpdmVyLmRyaXZl cikgewo+ID4gKyAgICAgICAgICAgICAgIHN0cnVjdCBtdGtfZG1hZGV2ICptdGtkID0gdG9fbXRr X2RtYV9kZXYoY2hhbi0+ZGV2aWNlKTsKPiA+ICsgICAgICAgICAgICAgICBzdHJ1Y3QgbXRrX2No YW4gKmMgPSB0b19tdGtfZG1hX2NoYW4oY2hhbik7Cj4gPiArICAgICAgICAgICAgICAgdW5zaWdu ZWQgaW50IHJlcSA9ICoodW5zaWduZWQgaW50ICopcGFyYW07Cj4gPiArCj4gPiArICAgICAgICAg ICAgICAgaWYgKHJlcSA8PSBtdGtkLT5kbWFfcmVxdWVzdHMpIHsKPiA+ICsgICAgICAgICAgICAg ICAgICAgICAgIGMtPmRtYV9zaWcgPSByZXE7Cj4gPiArICAgICAgICAgICAgICAgICAgICAgICBj LT5kbWFfY2ggPSByZXE7Cj4gPiArICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsK PiA+ICsgICAgICAgICAgICAgICB9Cj4gPiArICAgICAgIH0KPiA+ICsgICAgICAgcmV0dXJuIGZh bHNlOwo+ID4gK30KPiA+ICsKPiA+ICttb2R1bGVfcGxhdGZvcm1fZHJpdmVyKG10a19kbWFfZHJp dmVyKTsKPiA+ICsKPiA+ICtNT0RVTEVfREVTQ1JJUFRJT04oIk1lZGlhVGVrIFVBUlQgQVBETUEg Q29udHJvbGxlciBEcml2ZXIiKTsKPiA+ICtNT0RVTEVfQVVUSE9SKCJMb25nIENoZW5nIDxsb25n LmNoZW5nQG1lZGlhdGVrLmNvbT4iKTsKPiA+ICtNT0RVTEVfTElDRU5TRSgiR1BMIHYyIik7Cj4g PiArCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9kbWEvbWVkaWF0ZWsvS2NvbmZpZyBiL2RyaXZl cnMvZG1hL21lZGlhdGVrL0tjb25maWcKPiA+IGluZGV4IDI3YmFjMGIuLmJlZjQzNmUgMTAwNjQ0 Cj4gPiAtLS0gYS9kcml2ZXJzL2RtYS9tZWRpYXRlay9LY29uZmlnCj4gPiArKysgYi9kcml2ZXJz L2RtYS9tZWRpYXRlay9LY29uZmlnCj4gPiBAQCAtMSw0ICsxLDE1IEBACj4gPgo+ID4gK2NvbmZp ZyBETUFfTVRLX1VBUlQKPiA+ICsgICAgICAgdHJpc3RhdGUgIk1lZGlhVGVrIFNvQ3MgQVBETUEg c3VwcG9ydCBmb3IgVUFSVCIKPiA+ICsgICAgICAgZGVwZW5kcyBvbiBPRgo+ID4gKyAgICAgICBz ZWxlY3QgRE1BX0VOR0lORQo+ID4gKyAgICAgICBzZWxlY3QgRE1BX1ZJUlRVQUxfQ0hBTk5FTFMK PiA+ICsgICAgICAgaGVscAo+ID4gKyAgICAgICAgIFN1cHBvcnQgZm9yIHRoZSBVQVJUIERNQSBl bmdpbmUgZm91bmQgb24gTWVkaWFUZWsgTVRLIFNvQ3MuCj4gPiArICAgICAgICAgd2hlbiA4MjUw IG10ayB1YXJ0IGlzIGVuYWJsZWQsIGFuZCBpZiB5b3Ugd2FudCB0byB1c2luZyBETUEsCj4gPiAr ICAgICAgICAgeW91IGNhbiBlbmFibGUgdGhlIGNvbmZpZy4gdGhlIERNQSBlbmdpbmUganVzdCBv bmx5IGJlIHVzZWQKPiA+ICsgICAgICAgICB3aXRoIE1lZGlhVGVrIFNvY3MuCj4gPiArCj4gPiAg Y29uZmlnIE1US19IU0RNQQo+ID4gICAgICAgICB0cmlzdGF0ZSAiTWVkaWFUZWsgSGlnaC1TcGVl ZCBETUEgY29udHJvbGxlciBzdXBwb3J0Igo+ID4gICAgICAgICBkZXBlbmRzIG9uIEFSQ0hfTUVE SUFURUsgfHwgQ09NUElMRV9URVNUCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9kbWEvbWVkaWF0 ZWsvTWFrZWZpbGUgYi9kcml2ZXJzL2RtYS9tZWRpYXRlay9NYWtlZmlsZQo+ID4gaW5kZXggNmU3 NzhmOC4uMmYyZWZkOSAxMDA2NDQKPiA+IC0tLSBhL2RyaXZlcnMvZG1hL21lZGlhdGVrL01ha2Vm aWxlCj4gPiArKysgYi9kcml2ZXJzL2RtYS9tZWRpYXRlay9NYWtlZmlsZQo+ID4gQEAgLTEgKzEs MiBAQAo+ID4gK29iai0kKENPTkZJR19ETUFfTVRLX1VBUlQpICs9IDgyNTBfbXRrX2RtYS5vCj4g PiAgb2JqLSQoQ09ORklHX01US19IU0RNQSkgKz0gbXRrLWhzZG1hLm8KPiA+IC0tCj4gPiAxLjcu OS41Cj4gPgo+ID4KPiA+IF9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fCj4gPiBMaW51eC1tZWRpYXRlayBtYWlsaW5nIGxpc3QKPiA+IExpbnV4LW1lZGlhdGVr QGxpc3RzLmluZnJhZGVhZC5vcmcKPiA+IGh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxt YW4vbGlzdGluZm8vbGludXgtbWVkaWF0ZWsK From mboxrd@z Thu Jan 1 00:00:00 1970 From: Long Cheng Subject: Re: [PATCH v2 2/4] dmaengine: mtk_uart_dma: add Mediatek uart DMA support Date: Thu, 6 Dec 2018 17:55:40 +0800 Message-ID: <1544090140.28871.11.camel@mhfsdcap03> References: <1543999380-7946-1-git-send-email-long.cheng@mediatek.com> <1543999380-7946-3-git-send-email-long.cheng@mediatek.com> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: Sender: linux-kernel-owner@vger.kernel.org To: Sean Wang Cc: vkoul@kernel.org, robh+dt@kernel.org, mark.rutland@arm.com, devicetree@vger.kernel.org, srv_heupstream@mediatek.com, gregkh@linuxfoundation.org, Sean Wang =?UTF-8?Q?=28=E7=8E=8B=E5=BF=97=E4=BA=98=29?= , linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org, linux-mediatek@lists.infradead.org, linux-serial@vger.kernel.org, jslaby@suse.com, Matthias Brugger , yingjoe.chen@mediatek.com, dan.j.williams@intel.com, linux-arm-kernel@lists.infradead.org, yt.shen@mediatek.com List-Id: linux-mediatek@lists.infradead.org On Wed, 2018-12-05 at 13:07 -0800, Sean Wang wrote: > . > On Wed, Dec 5, 2018 at 1:31 AM Long Cheng wrote: > > > > In DMA engine framework, add 8250 mtk dma to support it. > > > > Signed-off-by: Long Cheng > > --- > > drivers/dma/mediatek/8250_mtk_dma.c | 894 +++++++++++++++++++++++++++++++++++ > > drivers/dma/mediatek/Kconfig | 11 + > > drivers/dma/mediatek/Makefile | 1 + > > 3 files changed, 906 insertions(+) > > create mode 100644 drivers/dma/mediatek/8250_mtk_dma.c > > > > diff --git a/drivers/dma/mediatek/8250_mtk_dma.c b/drivers/dma/mediatek/8250_mtk_dma.c > > new file mode 100644 > > index 0000000..3454679 > > --- /dev/null > > +++ b/drivers/dma/mediatek/8250_mtk_dma.c > > @@ -0,0 +1,894 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Mediatek 8250 DMA driver. > > + * > > + * Copyright (c) 2018 MediaTek Inc. > > + * Author: Long Cheng > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "../virt-dma.h" > > + > > +#define MTK_APDMA_DEFAULT_REQUESTS 127 > > +#define MTK_APDMA_CHANNELS (CONFIG_SERIAL_8250_NR_UARTS * 2) > > + > > +#define VFF_EN_B BIT(0) > > +#define VFF_STOP_B BIT(0) > > +#define VFF_FLUSH_B BIT(0) > > +#define VFF_4G_SUPPORT_B BIT(0) > > +#define VFF_RX_INT_EN0_B BIT(0) /*rx valid size >= vff thre*/ > > +#define VFF_RX_INT_EN1_B BIT(1) > > +#define VFF_TX_INT_EN_B BIT(0) /*tx left size >= vff thre*/ > > +#define VFF_WARM_RST_B BIT(0) > > +#define VFF_RX_INT_FLAG_CLR_B (BIT(0) | BIT(1)) > > +#define VFF_TX_INT_FLAG_CLR_B 0 > > +#define VFF_STOP_CLR_B 0 > > +#define VFF_FLUSH_CLR_B 0 > > +#define VFF_INT_EN_CLR_B 0 > > +#define VFF_4G_SUPPORT_CLR_B 0 > > + > > +/* interrupt trigger level for tx */ > > +#define VFF_TX_THRE(n) ((n) * 7 / 8) > > +/* interrupt trigger level for rx */ > > +#define VFF_RX_THRE(n) ((n) * 3 / 4) > > + > > +#define MTK_DMA_RING_SIZE 0xffffU > > +/* invert this bit when wrap ring head again*/ > > +#define MTK_DMA_RING_WRAP 0x10000U > > + > > +#define VFF_INT_FLAG 0x00 > > +#define VFF_INT_EN 0x04 > > +#define VFF_EN 0x08 > > +#define VFF_RST 0x0c > > +#define VFF_STOP 0x10 > > +#define VFF_FLUSH 0x14 > > +#define VFF_ADDR 0x1c > > +#define VFF_LEN 0x24 > > +#define VFF_THRE 0x28 > > +#define VFF_WPT 0x2c > > +#define VFF_RPT 0x30 > > +/*TX: the buffer size HW can read. RX: the buffer size SW can read.*/ > > +#define VFF_VALID_SIZE 0x3c > > +/*TX: the buffer size SW can write. RX: the buffer size HW can write.*/ > > +#define VFF_LEFT_SIZE 0x40 > > +#define VFF_DEBUG_STATUS 0x50 > > +#define VFF_4G_SUPPORT 0x54 > > + > > +struct mtk_dmadev { > > + struct dma_device ddev; > > + void __iomem *mem_base[MTK_APDMA_CHANNELS]; > > + spinlock_t lock; /* dma dev lock */ > > + struct tasklet_struct task; > > + struct list_head pending; > > + struct clk *clk; > > + unsigned int dma_requests; > > + bool support_33bits; > > + unsigned int dma_irq[MTK_APDMA_CHANNELS]; > > + struct mtk_chan *ch[MTK_APDMA_CHANNELS]; > > +}; > > + > > +struct mtk_chan { > > + struct virt_dma_chan vc; > > + struct list_head node; > > + struct dma_slave_config cfg; > > + void __iomem *base; > > + struct mtk_dma_desc *desc; > > + > > + bool stop; > > + bool requested; > > + > > + unsigned int dma_sig; > > the member can be removed as no real user would refer to it > Ok, i will remove it at next patch > > + unsigned int dma_ch; > > a chan_id is already included in struct dma_chan, we can reuse it > chan_id is start from 0. but in this driver, dma info is stored to list. if use port1, in filter_fn function, will set dma_ch to 2, 3(tx, rx). So can't using chan_id > > + unsigned int sgidx; > > the member also can be removed as no real user would refer to it > Ok, i will remove it at next patch > > + unsigned int remain_size; > > The member remain_size seems unnecessary data to maintain a channel. > The virtual channel struct virt_dma_chan already provide the way to > manage all descriptors you're operating on, you should reuse related > functions to virt_dma_chan first. > > Or if you mean remain_size is about the remaining size of current > descriptor, and then putting into struct mtk_dma_desc would be better. > i will move it to mtk_dma_desc > > + unsigned int rx_ptr; > > +}; > > + > > +struct mtk_dma_sg { > > + dma_addr_t addr; > > + unsigned int en; /* number of elements (24-bit) */ > > + unsigned int fn; /* number of frames (16-bit) */ > > +}; > > + > > +struct mtk_dma_desc { > > + struct virt_dma_desc vd; > > + enum dma_transfer_direction dir; > > + > > + unsigned int sglen; > > + struct mtk_dma_sg sg[0]; > > +}; > > + > > +static bool mtk_dma_filter_fn(struct dma_chan *chan, void *param); > > +static struct of_dma_filter_info mtk_dma_info = { > > + .filter_fn = mtk_dma_filter_fn, > > +}; > > + > > +static inline struct mtk_dmadev *to_mtk_dma_dev(struct dma_device *d) > > +{ > > + return container_of(d, struct mtk_dmadev, ddev); > > +} > > + > > +static inline struct mtk_chan *to_mtk_dma_chan(struct dma_chan *c) > > +{ > > + return container_of(c, struct mtk_chan, vc.chan); > > +} > > + > > +static inline struct mtk_dma_desc *to_mtk_dma_desc > > + (struct dma_async_tx_descriptor *t) > > +{ > > + return container_of(t, struct mtk_dma_desc, vd.tx); > > +} > > + > > +static void mtk_dma_chan_write(struct mtk_chan *c, > > + unsigned int reg, unsigned int val) > > +{ > > + writel(val, c->base + reg); > > +} > > + > > +static unsigned int mtk_dma_chan_read(struct mtk_chan *c, unsigned int reg) > > +{ > > + return readl(c->base + reg); > > +} > > + > > +static void mtk_dma_desc_free(struct virt_dma_desc *vd) > > +{ > > + struct dma_chan *chan = vd->tx.chan; > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + > > + kfree(c->desc); > > + c->desc = NULL; > > +} > > + > > +static int mtk_dma_clk_enable(struct mtk_dmadev *mtkd) > > +{ > > + int ret; > > + > > + ret = clk_prepare_enable(mtkd->clk); > > + if (ret) { > > + dev_err(mtkd->ddev.dev, "Couldn't enable the clock\n"); > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > +static void mtk_dma_clk_disable(struct mtk_dmadev *mtkd) > > +{ > > + clk_disable_unprepare(mtkd->clk); > > +} > > + > > +static void mtk_dma_remove_virt_list(dma_cookie_t cookie, > > + struct virt_dma_chan *vc) > > +{ > > + struct virt_dma_desc *vd; > > + > > + if (list_empty(&vc->desc_issued) == 0) { > > + list_for_each_entry(vd, &vc->desc_issued, node) { > > + if (cookie == vd->tx.cookie) { > > + INIT_LIST_HEAD(&vc->desc_issued); > > generally, we don't force initialze the list desc_issued. Instead, > when each descriptor is completed, we need to move each descriptor > from the list desc_issued to the list desc_completed. > ok, i will modify it at next patch > > + break; > > + } > > + } > > + } > > +} > > + > > +static void mtk_dma_tx_flush(struct dma_chan *chan) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + > > + if (mtk_dma_chan_read(c, VFF_FLUSH) == 0U) > > + mtk_dma_chan_write(c, VFF_FLUSH, VFF_FLUSH_B); > > +} > > + > > +static void mtk_dma_tx_write(struct dma_chan *chan) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + unsigned int txcount = c->remain_size; > > + unsigned int len, send, left, wpt, wrap; > > + > > + len = mtk_dma_chan_read(c, VFF_LEN); > > + > > + while ((left = mtk_dma_chan_read(c, VFF_LEFT_SIZE)) > 0U) { > > + if (c->remain_size == 0U) > > + break; > > + send = min(left, c->remain_size); > > min_t > ok, i will modify it at next patch > > + wpt = mtk_dma_chan_read(c, VFF_WPT); > > + wrap = wpt & MTK_DMA_RING_WRAP ? 0U : MTK_DMA_RING_WRAP; > > + > > + if ((wpt & (len - 1U)) + send < len) > > + mtk_dma_chan_write(c, VFF_WPT, wpt + send); > > + else > > + mtk_dma_chan_write(c, VFF_WPT, > > + ((wpt + send) & (len - 1U)) > > + | wrap); > > + > > + c->remain_size -= send; > > I'm curious why you don't need to set up the hardware from the > descriptor information > mtk_dma_chan_write is update the hardware. remain_size is length of TX data. > > + } > > + > > + if (txcount != c->remain_size) { > > + mtk_dma_chan_write(c, VFF_INT_EN, VFF_TX_INT_EN_B); > > + mtk_dma_tx_flush(chan); > > + } > > +} > > + > > +static void mtk_dma_start_tx(struct mtk_chan *c) > > +{ > > + if (mtk_dma_chan_read(c, VFF_LEFT_SIZE) == 0U) > > + mtk_dma_chan_write(c, VFF_INT_EN, VFF_TX_INT_EN_B); > > + else > > + mtk_dma_tx_write(&c->vc.chan); > > + > > + c->stop = false; > > +} > > + > > +static void mtk_dma_get_rx_size(struct mtk_chan *c) > > +{ > > + unsigned int rx_size = mtk_dma_chan_read(c, VFF_LEN); > > + unsigned int rdptr, wrptr, wrreg, rdreg, count; > > + > > + rdreg = mtk_dma_chan_read(c, VFF_RPT); > > + wrreg = mtk_dma_chan_read(c, VFF_WPT); > > + rdptr = rdreg & MTK_DMA_RING_SIZE; > > + wrptr = wrreg & MTK_DMA_RING_SIZE; > > + count = ((rdreg ^ wrreg) & MTK_DMA_RING_WRAP) ? > > + (wrptr + rx_size - rdptr) : (wrptr - rdptr); > > + > > + c->remain_size = count; > > + c->rx_ptr = rdptr; > > + > > + mtk_dma_chan_write(c, VFF_RPT, wrreg); > > +} > > + > > +static void mtk_dma_start_rx(struct mtk_chan *c) > > +{ > > + struct dma_chan *chan = &c->vc.chan; > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(chan->device); > > + struct mtk_dma_desc *d = c->desc; > > + > > + if (mtk_dma_chan_read(c, VFF_VALID_SIZE) == 0U) > > + return; > > + > > + if (d && d->vd.tx.cookie != 0) { > > the driver benefits from virtual_channel so you can manage the life > cycle of each descriptor by the virtual channel related functions > without handling details about the cookie. > ok, i will modify it at next patch > > + mtk_dma_get_rx_size(c); > > + mtk_dma_remove_virt_list(d->vd.tx.cookie, &c->vc); > > + vchan_cookie_complete(&d->vd); > > + } else { > > + spin_lock(&mtkd->lock); > > + if (list_empty(&mtkd->pending)) > > + list_add_tail(&c->node, &mtkd->pending); > > + spin_unlock(&mtkd->lock); > > + tasklet_schedule(&mtkd->task); > > + } > > +} > > + > > +static void mtk_dma_reset(struct mtk_chan *c) > > +{ > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(c->vc.chan.device); > > + u32 status; > > + int ret; > > + > > + mtk_dma_chan_write(c, VFF_ADDR, 0); > > + mtk_dma_chan_write(c, VFF_THRE, 0); > > + mtk_dma_chan_write(c, VFF_LEN, 0); > > + mtk_dma_chan_write(c, VFF_RST, VFF_WARM_RST_B); > > + > > + ret = readx_poll_timeout(readl, > > + c->base + VFF_EN, > > + status, status == 0, 10, 100); > > + if (ret) { > > + dev_err(c->vc.chan.device->dev, > > + "dma reset: fail, timeout\n"); > > + return; > > + } > > + > > + if (c->cfg.direction == DMA_DEV_TO_MEM) > > + mtk_dma_chan_write(c, VFF_RPT, 0); > > + else if (c->cfg.direction == DMA_MEM_TO_DEV) > > + mtk_dma_chan_write(c, VFF_WPT, 0); > > + > > + if (mtkd->support_33bits) > > + mtk_dma_chan_write(c, VFF_4G_SUPPORT, VFF_4G_SUPPORT_CLR_B); > > +} > > + > > +static void mtk_dma_stop(struct mtk_chan *c) > > +{ > > + u32 status; > > + int ret; > > + > > + mtk_dma_chan_write(c, VFF_FLUSH, VFF_FLUSH_CLR_B); > > + /* Wait for flush */ > > + ret = readx_poll_timeout(readl, > > + c->base + VFF_FLUSH, > > + status, > > + (status & VFF_FLUSH_B) != VFF_FLUSH_B, > > + 10, 100); > > + if (ret) > > + dev_err(c->vc.chan.device->dev, > > + "dma stop: polling FLUSH fail, DEBUG=0x%x\n", > > + mtk_dma_chan_read(c, VFF_DEBUG_STATUS)); > > + > > + /*set stop as 1 -> wait until en is 0 -> set stop as 0*/ > > + mtk_dma_chan_write(c, VFF_STOP, VFF_STOP_B); > > + ret = readx_poll_timeout(readl, > > + c->base + VFF_EN, > > + status, status == 0, 10, 100); > > + if (ret) > > + dev_err(c->vc.chan.device->dev, > > + "dma stop: polling VFF_EN fail, DEBUG=0x%x\n", > > + mtk_dma_chan_read(c, VFF_DEBUG_STATUS)); > > + > > + mtk_dma_chan_write(c, VFF_STOP, VFF_STOP_CLR_B); > > + mtk_dma_chan_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B); > > + > > + if (c->cfg.direction == DMA_DEV_TO_MEM) > > + mtk_dma_chan_write(c, VFF_INT_FLAG, VFF_RX_INT_FLAG_CLR_B); > > + else > > + mtk_dma_chan_write(c, VFF_INT_FLAG, VFF_TX_INT_FLAG_CLR_B); > > + > > + c->stop = true; > > +} > > + > > +/* > > + * This callback schedules all pending channels. We could be more > > + * clever here by postponing allocation of the real DMA channels to > > + * this point, and freeing them when our virtual channel becomes idle. > > + * > > + * We would then need to deal with 'all channels in-use' > > + */ > > +static void mtk_dma_sched(unsigned long data) > > +{ > > + struct mtk_dmadev *mtkd = (struct mtk_dmadev *)data; > > + struct virt_dma_desc *vd; > > + struct mtk_chan *c; > > + dma_cookie_t cookie; > > + unsigned long flags; > > + LIST_HEAD(head); > > + > > + spin_lock_irq(&mtkd->lock); > > + list_splice_tail_init(&mtkd->pending, &head); > > + spin_unlock_irq(&mtkd->lock); > > + > > + if (!list_empty(&head)) { > > + c = list_first_entry(&head, struct mtk_chan, node); > > + cookie = c->vc.chan.cookie; > > + > > + spin_lock_irqsave(&c->vc.lock, flags); > > + if (c->cfg.direction == DMA_DEV_TO_MEM) { > > + list_del_init(&c->node); > > + mtk_dma_start_rx(c); > > + } else if (c->cfg.direction == DMA_MEM_TO_DEV) { > > + vd = vchan_find_desc(&c->vc, cookie); > > + c->desc = to_mtk_dma_desc(&vd->tx); > > + list_del_init(&c->node); > > + mtk_dma_start_tx(c); > > + } > > + spin_unlock_irqrestore(&c->vc.lock, flags); > > + } > > +} > > + > > +static int mtk_dma_alloc_chan_resources(struct dma_chan *chan) > > +{ > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(chan->device); > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + int ret = -EBUSY; > > + > > + pm_runtime_get_sync(mtkd->ddev.dev); > > + > > + if (!mtkd->ch[c->dma_ch]) { > > + c->base = mtkd->mem_base[c->dma_ch]; > > + mtkd->ch[c->dma_ch] = c; > > + ret = 1; > > + } > > + c->requested = false; > > + mtk_dma_reset(c); > > + > > + return ret; > > +} > > + > > +static void mtk_dma_free_chan_resources(struct dma_chan *chan) > > +{ > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(chan->device); > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + > > + if (c->requested) { > > + c->requested = false; > > + free_irq(mtkd->dma_irq[c->dma_ch], chan); > > + } > > + > > + tasklet_kill(&mtkd->task); > > + tasklet_kill(&c->vc.task); > > + > > + c->base = NULL; > > + mtkd->ch[c->dma_ch] = NULL; > > + vchan_free_chan_resources(&c->vc); > > + > > + dev_dbg(mtkd->ddev.dev, "freeing channel for %u\n", c->dma_sig); > > + c->dma_sig = 0; > > + > > + pm_runtime_put_sync(mtkd->ddev.dev); > > +} > > + > > +static enum dma_status mtk_dma_tx_status(struct dma_chan *chan, > > + dma_cookie_t cookie, > > + struct dma_tx_state *txstate) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + enum dma_status ret; > > + unsigned long flags; > > + > > + if (!txstate) > > + return DMA_ERROR; > > + > > + ret = dma_cookie_status(chan, cookie, txstate); > > + spin_lock_irqsave(&c->vc.lock, flags); > > + if (ret == DMA_IN_PROGRESS) { > > + c->rx_ptr = mtk_dma_chan_read(c, VFF_RPT) & MTK_DMA_RING_SIZE; > > + dma_set_residue(txstate, c->rx_ptr); > > + } else if (ret == DMA_COMPLETE && c->cfg.direction == DMA_DEV_TO_MEM) { > > + dma_set_residue(txstate, c->remain_size); > > + } else { > > + dma_set_residue(txstate, 0); > > + } > > + spin_unlock_irqrestore(&c->vc.lock, flags); > > + > > + return ret; > > +} > > + > > +static struct dma_async_tx_descriptor *mtk_dma_prep_slave_sg > > + (struct dma_chan *chan, struct scatterlist *sgl, > > + unsigned int sglen, enum dma_transfer_direction dir, > > + unsigned long tx_flags, void *context) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + struct scatterlist *sgent; > > + struct mtk_dma_desc *d; > > + struct mtk_dma_sg *sg; > > + unsigned int size, i, j, en; > > + > > + en = 1; > > + > > + if ((dir != DMA_DEV_TO_MEM) && > > + (dir != DMA_MEM_TO_DEV)) { > > + dev_err(chan->device->dev, "bad direction\n"); > > + return NULL; > > + } > > + > > + /* Now allocate and setup the descriptor. */ > > + d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC); > > + if (!d) > > + return NULL; > > + > > + d->dir = dir; > > + > > + j = 0; > > + for_each_sg(sgl, sgent, sglen, i) { > > + d->sg[j].addr = sg_dma_address(sgent); > > + d->sg[j].en = en; > > + d->sg[j].fn = sg_dma_len(sgent) / en; > > + j++; > > + } > > + > > + d->sglen = j; > > + > > + if (dir == DMA_MEM_TO_DEV) { > > + for (size = i = 0; i < d->sglen; i++) { > > + sg = &d->sg[i]; > > + size += sg->en * sg->fn; > > + } > > + c->remain_size = size; > > + } > > + > > + return vchan_tx_prep(&c->vc, &d->vd, tx_flags); > > +} > > + > > +static void mtk_dma_issue_pending(struct dma_chan *chan) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + struct virt_dma_desc *vd; > > + struct mtk_dmadev *mtkd; > > + dma_cookie_t cookie; > > + unsigned long flags; > > + > > + spin_lock_irqsave(&c->vc.lock, flags); > > + if (c->cfg.direction == DMA_DEV_TO_MEM) { > > + cookie = c->vc.chan.cookie; > > + mtkd = to_mtk_dma_dev(chan->device); > > + if (vchan_issue_pending(&c->vc) && !c->desc) { > > vchan_issue_pending means putting all the descriptors to list > desc_issued, I'm supposed somewhere would iterate the list by > vchan_next_desc and program each desc. into hardware. but I don't see > the similar code. ok, i will modify it at next patch > > > + vd = vchan_find_desc(&c->vc, cookie); > > + c->desc = to_mtk_dma_desc(&vd->tx); > > + } > > + } else if (c->cfg.direction == DMA_MEM_TO_DEV) { > > + cookie = c->vc.chan.cookie; > > + if (vchan_issue_pending(&c->vc) && !c->desc) { > > ditto as the above > ok, i will modify it at next patch > > + vd = vchan_find_desc(&c->vc, cookie); > > + c->desc = to_mtk_dma_desc(&vd->tx); > > + mtk_dma_start_tx(c); > > + } > > + } > > + spin_unlock_irqrestore(&c->vc.lock, flags); > > +} > > + > > +static irqreturn_t mtk_dma_rx_interrupt(int irq, void *dev_id) > > +{ > > + struct dma_chan *chan = (struct dma_chan *)dev_id; > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + unsigned long flags; > > + > > + spin_lock_irqsave(&c->vc.lock, flags); > > + mtk_dma_chan_write(c, VFF_INT_FLAG, VFF_RX_INT_FLAG_CLR_B); > > + > > + mtk_dma_start_rx(c); > > + > > + spin_unlock_irqrestore(&c->vc.lock, flags); > > + > > + return IRQ_HANDLED; > > +} > > + > > +static irqreturn_t mtk_dma_tx_interrupt(int irq, void *dev_id) > > +{ > > + struct dma_chan *chan = (struct dma_chan *)dev_id; > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(chan->device); > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + struct mtk_dma_desc *d = c->desc; > > + unsigned long flags; > > + > > + spin_lock_irqsave(&c->vc.lock, flags); > > + if (c->remain_size != 0U) { > > + list_add_tail(&c->node, &mtkd->pending); > > + tasklet_schedule(&mtkd->task); > > + } else { > > + mtk_dma_remove_virt_list(d->vd.tx.cookie, &c->vc); > > + vchan_cookie_complete(&d->vd); > > + } > > + spin_unlock_irqrestore(&c->vc.lock, flags); > > + > > + mtk_dma_chan_write(c, VFF_INT_FLAG, VFF_TX_INT_FLAG_CLR_B); > > + > > + return IRQ_HANDLED; > > +} > > + > > +static int mtk_dma_slave_config(struct dma_chan *chan, > > + struct dma_slave_config *cfg) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(c->vc.chan.device); > > + int ret; > > + > > + c->cfg = *cfg; > > + > > + if (cfg->direction == DMA_DEV_TO_MEM) { > > + unsigned int rx_len = cfg->src_addr_width * 1024; > > + > > + mtk_dma_chan_write(c, VFF_ADDR, cfg->src_addr); > > + mtk_dma_chan_write(c, VFF_LEN, rx_len); > > + mtk_dma_chan_write(c, VFF_THRE, VFF_RX_THRE(rx_len)); > > + mtk_dma_chan_write(c, > > + VFF_INT_EN, VFF_RX_INT_EN0_B > > + | VFF_RX_INT_EN1_B); > > + mtk_dma_chan_write(c, VFF_INT_FLAG, VFF_RX_INT_FLAG_CLR_B); > > + mtk_dma_chan_write(c, VFF_EN, VFF_EN_B); > > + > > + if (!c->requested) { > > + c->requested = true; > > + ret = request_irq(mtkd->dma_irq[c->dma_ch], > > + mtk_dma_rx_interrupt, > > + IRQF_TRIGGER_NONE, > > + KBUILD_MODNAME, chan); > > + if (ret < 0) { > > + dev_err(chan->device->dev, "Can't request rx dma IRQ\n"); > > + return -EINVAL; > > + } > > + } > > + } else if (cfg->direction == DMA_MEM_TO_DEV) { > > + unsigned int tx_len = cfg->dst_addr_width * 1024; > > + > > + mtk_dma_chan_write(c, VFF_ADDR, cfg->dst_addr); > > + mtk_dma_chan_write(c, VFF_LEN, tx_len); > > + mtk_dma_chan_write(c, VFF_THRE, VFF_TX_THRE(tx_len)); > > + mtk_dma_chan_write(c, VFF_INT_FLAG, VFF_TX_INT_FLAG_CLR_B); > > + mtk_dma_chan_write(c, VFF_EN, VFF_EN_B); > > + > > + if (!c->requested) { > > + c->requested = true; > > + ret = request_irq(mtkd->dma_irq[c->dma_ch], > > + mtk_dma_tx_interrupt, > > + IRQF_TRIGGER_NONE, > > + KBUILD_MODNAME, chan); > > + if (ret < 0) { > > + dev_err(chan->device->dev, "Can't request tx dma IRQ\n"); > > + return -EINVAL; > > + } > > + } > > + } > > + > > + if (mtkd->support_33bits) > > + mtk_dma_chan_write(c, VFF_4G_SUPPORT, VFF_4G_SUPPORT_B); > > + > > + if (mtk_dma_chan_read(c, VFF_EN) != VFF_EN_B) { > > + dev_err(chan->device->dev, > > + "config dma dir[%d] fail\n", cfg->direction); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +static int mtk_dma_terminate_all(struct dma_chan *chan) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + unsigned long flags; > > + > > + spin_lock_irqsave(&c->vc.lock, flags); > > + list_del_init(&c->node); > > + mtk_dma_stop(c); > > + spin_unlock_irqrestore(&c->vc.lock, flags); > > + > > + return 0; > > +} > > + > > +static int mtk_dma_device_pause(struct dma_chan *chan) > > +{ > > + /* just for check caps pass */ > > + return -EINVAL; > > +} > > it it possible not to register the function to the core if the > hardware doesn't support it? > can't support. the function will set to cmd_pause. in 8250 serial code, will check cmd_pause. if no the function, will can't get DMA channel. So the function just for this. > > + > > +static int mtk_dma_device_resume(struct dma_chan *chan) > > +{ > > + /* just for check caps pass */ > > + return -EINVAL; > > +} > > ditto as the above > > > + > > +static void mtk_dma_free(struct mtk_dmadev *mtkd) > > +{ > > + tasklet_kill(&mtkd->task); > > + while (list_empty(&mtkd->ddev.channels) == 0) { > > + struct mtk_chan *c = list_first_entry(&mtkd->ddev.channels, > > + struct mtk_chan, vc.chan.device_node); > > + > > + list_del(&c->vc.chan.device_node); > > + tasklet_kill(&c->vc.task); > > + devm_kfree(mtkd->ddev.dev, c); > > + } > > +} > > + > > +static const struct of_device_id mtk_uart_dma_match[] = { > > + { .compatible = "mediatek,mt6577-uart-dma", }, > > + { /* sentinel */ }, > > +}; > > +MODULE_DEVICE_TABLE(of, mtk_uart_dma_match); > > + > > +static int mtk_apdma_probe(struct platform_device *pdev) > > +{ > > + struct mtk_dmadev *mtkd; > > + struct resource *res; > > + struct mtk_chan *c; > > + unsigned int i; > > + int rc; > > + > > + mtkd = devm_kzalloc(&pdev->dev, sizeof(*mtkd), GFP_KERNEL); > > + if (!mtkd) > > + return -ENOMEM; > > + > > + for (i = 0; i < MTK_APDMA_CHANNELS; i++) { > > + res = platform_get_resource(pdev, IORESOURCE_MEM, i); > > + if (!res) > > + return -ENODEV; > > + mtkd->mem_base[i] = devm_ioremap_resource(&pdev->dev, res); > > + if (IS_ERR(mtkd->mem_base[i])) > > + return PTR_ERR(mtkd->mem_base[i]); > > + } > > + > > + for (i = 0; i < MTK_APDMA_CHANNELS; i++) { > > + mtkd->dma_irq[i] = platform_get_irq(pdev, i); > > + if ((int)mtkd->dma_irq[i] < 0) { > > + dev_err(&pdev->dev, "failed to get IRQ[%d]\n", i); > > + return -EINVAL; > > + } > > + } > > + > > + mtkd->clk = devm_clk_get(&pdev->dev, NULL); > > + if (IS_ERR(mtkd->clk)) { > > + dev_err(&pdev->dev, "No clock specified\n"); > > + return PTR_ERR(mtkd->clk); > > + } > > + > > + if (of_property_read_bool(pdev->dev.of_node, "dma-33bits")) { > > + dev_info(&pdev->dev, "Support dma 33bits\n"); > > + mtkd->support_33bits = true; > > + } > > + > > + if (mtkd->support_33bits) > > + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33)); > > + else > > + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); > > + if (rc) > > + return rc; > > + > > + dma_cap_set(DMA_SLAVE, mtkd->ddev.cap_mask); > > + mtkd->ddev.device_alloc_chan_resources = mtk_dma_alloc_chan_resources; > > + mtkd->ddev.device_free_chan_resources = mtk_dma_free_chan_resources; > > + mtkd->ddev.device_tx_status = mtk_dma_tx_status; > > + mtkd->ddev.device_issue_pending = mtk_dma_issue_pending; > > + mtkd->ddev.device_prep_slave_sg = mtk_dma_prep_slave_sg; > > + mtkd->ddev.device_config = mtk_dma_slave_config; > > + mtkd->ddev.device_pause = mtk_dma_device_pause; > > + mtkd->ddev.device_resume = mtk_dma_device_resume; > > + mtkd->ddev.device_terminate_all = mtk_dma_terminate_all; > > + mtkd->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE); > > + mtkd->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE); > > + mtkd->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); > > + mtkd->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; > > + mtkd->ddev.dev = &pdev->dev; > > + INIT_LIST_HEAD(&mtkd->ddev.channels); > > + INIT_LIST_HEAD(&mtkd->pending); > > + > > + spin_lock_init(&mtkd->lock); > > + tasklet_init(&mtkd->task, mtk_dma_sched, (unsigned long)mtkd); > > + > > + mtkd->dma_requests = MTK_APDMA_DEFAULT_REQUESTS; > > + if (of_property_read_u32(pdev->dev.of_node, > > + "dma-requests", &mtkd->dma_requests)) { > > + dev_info(&pdev->dev, > > + "Missing dma-requests property, using %u.\n", > > + MTK_APDMA_DEFAULT_REQUESTS); > > + } > > + > > + for (i = 0; i < MTK_APDMA_CHANNELS; i++) { > > + c = devm_kzalloc(mtkd->ddev.dev, sizeof(*c), GFP_KERNEL); > > + if (!c) > > + goto err_no_dma; > > + > > + c->vc.desc_free = mtk_dma_desc_free; > > + vchan_init(&c->vc, &mtkd->ddev); > > + INIT_LIST_HEAD(&c->node); > > + } > > + > > + pm_runtime_enable(&pdev->dev); > > + pm_runtime_set_active(&pdev->dev); > > + > > + rc = dma_async_device_register(&mtkd->ddev); > > + if (rc) > > + goto rpm_disable; > > + > > + platform_set_drvdata(pdev, mtkd); > > + > > + if (pdev->dev.of_node) { > > + mtk_dma_info.dma_cap = mtkd->ddev.cap_mask; > > + > > + /* Device-tree DMA controller registration */ > > + rc = of_dma_controller_register(pdev->dev.of_node, > > + of_dma_simple_xlate, > > + &mtk_dma_info); > > reusing of_dma_xlate_by_chan_id seem that also work for you. in filter_fn function, neeg get number of dma. > > > + if (rc) > > + goto dma_remove; > > + } > > + > > + return rc; > > + > > +dma_remove: > > + dma_async_device_unregister(&mtkd->ddev); > > +rpm_disable: > > + pm_runtime_disable(&pdev->dev); > > +err_no_dma: > > + mtk_dma_free(mtkd); > > + return rc; > > +} > > + > > +static int mtk_apdma_remove(struct platform_device *pdev) > > +{ > > + struct mtk_dmadev *mtkd = platform_get_drvdata(pdev); > > + > > + if (pdev->dev.of_node) > > + of_dma_controller_free(pdev->dev.of_node); > > + > > + pm_runtime_disable(&pdev->dev); > > + pm_runtime_put_noidle(&pdev->dev); > > + > > + dma_async_device_unregister(&mtkd->ddev); > > + > > + mtk_dma_free(mtkd); > > + > > + return 0; > > +} > > + > > +#ifdef CONFIG_PM_SLEEP > > +static int mtk_dma_suspend(struct device *dev) > > +{ > > + struct mtk_dmadev *mtkd = dev_get_drvdata(dev); > > + > > + if (!pm_runtime_suspended(dev)) > > + mtk_dma_clk_disable(mtkd); > > + > > + return 0; > > +} > > + > > +static int mtk_dma_resume(struct device *dev) > > +{ > > + int ret; > > + struct mtk_dmadev *mtkd = dev_get_drvdata(dev); > > + > > + if (!pm_runtime_suspended(dev)) { > > + ret = mtk_dma_clk_enable(mtkd); > > + if (ret) > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > +static int mtk_dma_runtime_suspend(struct device *dev) > > +{ > > + struct mtk_dmadev *mtkd = dev_get_drvdata(dev); > > + > > + mtk_dma_clk_disable(mtkd); > > + > > + return 0; > > +} > > + > > +static int mtk_dma_runtime_resume(struct device *dev) > > +{ > > + int ret; > > + struct mtk_dmadev *mtkd = dev_get_drvdata(dev); > > + > > + ret = mtk_dma_clk_enable(mtkd); > > + if (ret) > > + return ret; > > + > > + return 0; > > +} > > + > > +#endif /* CONFIG_PM_SLEEP */ > > + > > +static const struct dev_pm_ops mtk_dma_pm_ops = { > > + SET_SYSTEM_SLEEP_PM_OPS(mtk_dma_suspend, mtk_dma_resume) > > + SET_RUNTIME_PM_OPS(mtk_dma_runtime_suspend, > > + mtk_dma_runtime_resume, NULL) > > +}; > > + > > +static struct platform_driver mtk_dma_driver = { > > + .probe = mtk_apdma_probe, > > + .remove = mtk_apdma_remove, > > + .driver = { > > + .name = KBUILD_MODNAME, > > + .pm = &mtk_dma_pm_ops, > > + .of_match_table = of_match_ptr(mtk_uart_dma_match), > > + }, > > +}; > > + > > +static bool mtk_dma_filter_fn(struct dma_chan *chan, void *param) > > +{ > > + if (chan->device->dev->driver == &mtk_dma_driver.driver) { > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(chan->device); > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + unsigned int req = *(unsigned int *)param; > > + > > + if (req <= mtkd->dma_requests) { > > + c->dma_sig = req; > > + c->dma_ch = req; > > + return true; > > + } > > + } > > + return false; > > +} > > + > > +module_platform_driver(mtk_dma_driver); > > + > > +MODULE_DESCRIPTION("MediaTek UART APDMA Controller Driver"); > > +MODULE_AUTHOR("Long Cheng "); > > +MODULE_LICENSE("GPL v2"); > > + > > diff --git a/drivers/dma/mediatek/Kconfig b/drivers/dma/mediatek/Kconfig > > index 27bac0b..bef436e 100644 > > --- a/drivers/dma/mediatek/Kconfig > > +++ b/drivers/dma/mediatek/Kconfig > > @@ -1,4 +1,15 @@ > > > > +config DMA_MTK_UART > > + tristate "MediaTek SoCs APDMA support for UART" > > + depends on OF > > + select DMA_ENGINE > > + select DMA_VIRTUAL_CHANNELS > > + help > > + Support for the UART DMA engine found on MediaTek MTK SoCs. > > + when 8250 mtk uart is enabled, and if you want to using DMA, > > + you can enable the config. the DMA engine just only be used > > + with MediaTek Socs. > > + > > config MTK_HSDMA > > tristate "MediaTek High-Speed DMA controller support" > > depends on ARCH_MEDIATEK || COMPILE_TEST > > diff --git a/drivers/dma/mediatek/Makefile b/drivers/dma/mediatek/Makefile > > index 6e778f8..2f2efd9 100644 > > --- a/drivers/dma/mediatek/Makefile > > +++ b/drivers/dma/mediatek/Makefile > > @@ -1 +1,2 @@ > > +obj-$(CONFIG_DMA_MTK_UART) += 8250_mtk_dma.o > > obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o > > -- > > 1.7.9.5 > > > > > > _______________________________________________ > > Linux-mediatek mailing list > > Linux-mediatek@lists.infradead.org > > http://lists.infradead.org/mailman/listinfo/linux-mediatek 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=-8.7 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS,UNPARSEABLE_RELAY 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 BB52EC04EB8 for ; Thu, 6 Dec 2018 09:56:30 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 850A420850 for ; Thu, 6 Dec 2018 09:56:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="EsOR1avh" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 850A420850 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=mediatek.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Date:To:From:Subject:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=oCCY6FxUUNT5iTr5iLBMPv0Dreb6wX2HioBsbCaNXsk=; b=EsOR1avhlOzekb h/qtb26ii2s2ohGh8oMpq6Ss4s2Z/Jl4u1GxcLixrqiG5DwAjvSPY476L8UCO4TP1vnqxzjJlegUa kd89c1Vs+ZMr/KtvuUiN1MCtr4WZ6SBq31fxY+6rxx6wYDGNTalkrmzGdOf662O+9C2NPu3520ibO XX1H6L/jGZrLBx0LLJs6JWdXtlhqfR6NKH3+TS3PENJDREab9hyapZBwhgsJa91DSc9AKavVv2cZv N/4Qlp+uQqTaDTAVGgzphiWhycXDs7e7dhK2L2AgxhE0EgbBgHBsNqnQCDKeCQdC3s+HaH2QvNyvC kyYYltxapgIkybowdXFg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gUqOL-0004O5-BP; Thu, 06 Dec 2018 09:56:21 +0000 Received: from [210.61.82.184] (helo=mailgw02.mediatek.com) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gUqOF-0004Mc-HO; Thu, 06 Dec 2018 09:56:18 +0000 X-UUID: 9d9dcad1dd2f44b0baa22ca76618ea6c-20181206 X-UUID: 9d9dcad1dd2f44b0baa22ca76618ea6c-20181206 Received: from mtkcas07.mediatek.inc [(172.21.101.84)] by mailgw02.mediatek.com (envelope-from ) (mhqrelay.mediatek.com ESMTP with TLS) with ESMTP id 515875639; Thu, 06 Dec 2018 17:55:43 +0800 Received: from MTKCAS36.mediatek.inc (172.27.4.186) by mtkmbs03n1.mediatek.inc (172.21.101.181) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Thu, 6 Dec 2018 17:55:42 +0800 Received: from [10.17.3.153] (10.17.3.153) by MTKCAS36.mediatek.inc (172.27.4.170) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Thu, 6 Dec 2018 17:55:40 +0800 Message-ID: <1544090140.28871.11.camel@mhfsdcap03> Subject: Re: [PATCH v2 2/4] dmaengine: mtk_uart_dma: add Mediatek uart DMA support From: Long Cheng To: Sean Wang Date: Thu, 6 Dec 2018 17:55:40 +0800 In-Reply-To: References: <1543999380-7946-1-git-send-email-long.cheng@mediatek.com> <1543999380-7946-3-git-send-email-long.cheng@mediatek.com> X-Mailer: Evolution 3.2.3-0ubuntu6 MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181206_015616_093022_484D03A9 X-CRM114-Status: GOOD ( 30.15 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, yt.shen@mediatek.com, srv_heupstream@mediatek.com, gregkh@linuxfoundation.org, Sean Wang =?UTF-8?Q?=28=E7=8E=8B=E5=BF=97=E4=BA=98=29?= , linux-kernel@vger.kernel.org, Matthias Brugger , vkoul@kernel.org, robh+dt@kernel.org, linux-mediatek@lists.infradead.org, linux-serial@vger.kernel.org, jslaby@suse.com, dmaengine@vger.kernel.org, yingjoe.chen@mediatek.com, dan.j.williams@intel.com, linux-arm-kernel@lists.infradead.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org On Wed, 2018-12-05 at 13:07 -0800, Sean Wang wrote: > . > On Wed, Dec 5, 2018 at 1:31 AM Long Cheng wrote: > > > > In DMA engine framework, add 8250 mtk dma to support it. > > > > Signed-off-by: Long Cheng > > --- > > drivers/dma/mediatek/8250_mtk_dma.c | 894 +++++++++++++++++++++++++++++++++++ > > drivers/dma/mediatek/Kconfig | 11 + > > drivers/dma/mediatek/Makefile | 1 + > > 3 files changed, 906 insertions(+) > > create mode 100644 drivers/dma/mediatek/8250_mtk_dma.c > > > > diff --git a/drivers/dma/mediatek/8250_mtk_dma.c b/drivers/dma/mediatek/8250_mtk_dma.c > > new file mode 100644 > > index 0000000..3454679 > > --- /dev/null > > +++ b/drivers/dma/mediatek/8250_mtk_dma.c > > @@ -0,0 +1,894 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Mediatek 8250 DMA driver. > > + * > > + * Copyright (c) 2018 MediaTek Inc. > > + * Author: Long Cheng > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "../virt-dma.h" > > + > > +#define MTK_APDMA_DEFAULT_REQUESTS 127 > > +#define MTK_APDMA_CHANNELS (CONFIG_SERIAL_8250_NR_UARTS * 2) > > + > > +#define VFF_EN_B BIT(0) > > +#define VFF_STOP_B BIT(0) > > +#define VFF_FLUSH_B BIT(0) > > +#define VFF_4G_SUPPORT_B BIT(0) > > +#define VFF_RX_INT_EN0_B BIT(0) /*rx valid size >= vff thre*/ > > +#define VFF_RX_INT_EN1_B BIT(1) > > +#define VFF_TX_INT_EN_B BIT(0) /*tx left size >= vff thre*/ > > +#define VFF_WARM_RST_B BIT(0) > > +#define VFF_RX_INT_FLAG_CLR_B (BIT(0) | BIT(1)) > > +#define VFF_TX_INT_FLAG_CLR_B 0 > > +#define VFF_STOP_CLR_B 0 > > +#define VFF_FLUSH_CLR_B 0 > > +#define VFF_INT_EN_CLR_B 0 > > +#define VFF_4G_SUPPORT_CLR_B 0 > > + > > +/* interrupt trigger level for tx */ > > +#define VFF_TX_THRE(n) ((n) * 7 / 8) > > +/* interrupt trigger level for rx */ > > +#define VFF_RX_THRE(n) ((n) * 3 / 4) > > + > > +#define MTK_DMA_RING_SIZE 0xffffU > > +/* invert this bit when wrap ring head again*/ > > +#define MTK_DMA_RING_WRAP 0x10000U > > + > > +#define VFF_INT_FLAG 0x00 > > +#define VFF_INT_EN 0x04 > > +#define VFF_EN 0x08 > > +#define VFF_RST 0x0c > > +#define VFF_STOP 0x10 > > +#define VFF_FLUSH 0x14 > > +#define VFF_ADDR 0x1c > > +#define VFF_LEN 0x24 > > +#define VFF_THRE 0x28 > > +#define VFF_WPT 0x2c > > +#define VFF_RPT 0x30 > > +/*TX: the buffer size HW can read. RX: the buffer size SW can read.*/ > > +#define VFF_VALID_SIZE 0x3c > > +/*TX: the buffer size SW can write. RX: the buffer size HW can write.*/ > > +#define VFF_LEFT_SIZE 0x40 > > +#define VFF_DEBUG_STATUS 0x50 > > +#define VFF_4G_SUPPORT 0x54 > > + > > +struct mtk_dmadev { > > + struct dma_device ddev; > > + void __iomem *mem_base[MTK_APDMA_CHANNELS]; > > + spinlock_t lock; /* dma dev lock */ > > + struct tasklet_struct task; > > + struct list_head pending; > > + struct clk *clk; > > + unsigned int dma_requests; > > + bool support_33bits; > > + unsigned int dma_irq[MTK_APDMA_CHANNELS]; > > + struct mtk_chan *ch[MTK_APDMA_CHANNELS]; > > +}; > > + > > +struct mtk_chan { > > + struct virt_dma_chan vc; > > + struct list_head node; > > + struct dma_slave_config cfg; > > + void __iomem *base; > > + struct mtk_dma_desc *desc; > > + > > + bool stop; > > + bool requested; > > + > > + unsigned int dma_sig; > > the member can be removed as no real user would refer to it > Ok, i will remove it at next patch > > + unsigned int dma_ch; > > a chan_id is already included in struct dma_chan, we can reuse it > chan_id is start from 0. but in this driver, dma info is stored to list. if use port1, in filter_fn function, will set dma_ch to 2, 3(tx, rx). So can't using chan_id > > + unsigned int sgidx; > > the member also can be removed as no real user would refer to it > Ok, i will remove it at next patch > > + unsigned int remain_size; > > The member remain_size seems unnecessary data to maintain a channel. > The virtual channel struct virt_dma_chan already provide the way to > manage all descriptors you're operating on, you should reuse related > functions to virt_dma_chan first. > > Or if you mean remain_size is about the remaining size of current > descriptor, and then putting into struct mtk_dma_desc would be better. > i will move it to mtk_dma_desc > > + unsigned int rx_ptr; > > +}; > > + > > +struct mtk_dma_sg { > > + dma_addr_t addr; > > + unsigned int en; /* number of elements (24-bit) */ > > + unsigned int fn; /* number of frames (16-bit) */ > > +}; > > + > > +struct mtk_dma_desc { > > + struct virt_dma_desc vd; > > + enum dma_transfer_direction dir; > > + > > + unsigned int sglen; > > + struct mtk_dma_sg sg[0]; > > +}; > > + > > +static bool mtk_dma_filter_fn(struct dma_chan *chan, void *param); > > +static struct of_dma_filter_info mtk_dma_info = { > > + .filter_fn = mtk_dma_filter_fn, > > +}; > > + > > +static inline struct mtk_dmadev *to_mtk_dma_dev(struct dma_device *d) > > +{ > > + return container_of(d, struct mtk_dmadev, ddev); > > +} > > + > > +static inline struct mtk_chan *to_mtk_dma_chan(struct dma_chan *c) > > +{ > > + return container_of(c, struct mtk_chan, vc.chan); > > +} > > + > > +static inline struct mtk_dma_desc *to_mtk_dma_desc > > + (struct dma_async_tx_descriptor *t) > > +{ > > + return container_of(t, struct mtk_dma_desc, vd.tx); > > +} > > + > > +static void mtk_dma_chan_write(struct mtk_chan *c, > > + unsigned int reg, unsigned int val) > > +{ > > + writel(val, c->base + reg); > > +} > > + > > +static unsigned int mtk_dma_chan_read(struct mtk_chan *c, unsigned int reg) > > +{ > > + return readl(c->base + reg); > > +} > > + > > +static void mtk_dma_desc_free(struct virt_dma_desc *vd) > > +{ > > + struct dma_chan *chan = vd->tx.chan; > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + > > + kfree(c->desc); > > + c->desc = NULL; > > +} > > + > > +static int mtk_dma_clk_enable(struct mtk_dmadev *mtkd) > > +{ > > + int ret; > > + > > + ret = clk_prepare_enable(mtkd->clk); > > + if (ret) { > > + dev_err(mtkd->ddev.dev, "Couldn't enable the clock\n"); > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > +static void mtk_dma_clk_disable(struct mtk_dmadev *mtkd) > > +{ > > + clk_disable_unprepare(mtkd->clk); > > +} > > + > > +static void mtk_dma_remove_virt_list(dma_cookie_t cookie, > > + struct virt_dma_chan *vc) > > +{ > > + struct virt_dma_desc *vd; > > + > > + if (list_empty(&vc->desc_issued) == 0) { > > + list_for_each_entry(vd, &vc->desc_issued, node) { > > + if (cookie == vd->tx.cookie) { > > + INIT_LIST_HEAD(&vc->desc_issued); > > generally, we don't force initialze the list desc_issued. Instead, > when each descriptor is completed, we need to move each descriptor > from the list desc_issued to the list desc_completed. > ok, i will modify it at next patch > > + break; > > + } > > + } > > + } > > +} > > + > > +static void mtk_dma_tx_flush(struct dma_chan *chan) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + > > + if (mtk_dma_chan_read(c, VFF_FLUSH) == 0U) > > + mtk_dma_chan_write(c, VFF_FLUSH, VFF_FLUSH_B); > > +} > > + > > +static void mtk_dma_tx_write(struct dma_chan *chan) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + unsigned int txcount = c->remain_size; > > + unsigned int len, send, left, wpt, wrap; > > + > > + len = mtk_dma_chan_read(c, VFF_LEN); > > + > > + while ((left = mtk_dma_chan_read(c, VFF_LEFT_SIZE)) > 0U) { > > + if (c->remain_size == 0U) > > + break; > > + send = min(left, c->remain_size); > > min_t > ok, i will modify it at next patch > > + wpt = mtk_dma_chan_read(c, VFF_WPT); > > + wrap = wpt & MTK_DMA_RING_WRAP ? 0U : MTK_DMA_RING_WRAP; > > + > > + if ((wpt & (len - 1U)) + send < len) > > + mtk_dma_chan_write(c, VFF_WPT, wpt + send); > > + else > > + mtk_dma_chan_write(c, VFF_WPT, > > + ((wpt + send) & (len - 1U)) > > + | wrap); > > + > > + c->remain_size -= send; > > I'm curious why you don't need to set up the hardware from the > descriptor information > mtk_dma_chan_write is update the hardware. remain_size is length of TX data. > > + } > > + > > + if (txcount != c->remain_size) { > > + mtk_dma_chan_write(c, VFF_INT_EN, VFF_TX_INT_EN_B); > > + mtk_dma_tx_flush(chan); > > + } > > +} > > + > > +static void mtk_dma_start_tx(struct mtk_chan *c) > > +{ > > + if (mtk_dma_chan_read(c, VFF_LEFT_SIZE) == 0U) > > + mtk_dma_chan_write(c, VFF_INT_EN, VFF_TX_INT_EN_B); > > + else > > + mtk_dma_tx_write(&c->vc.chan); > > + > > + c->stop = false; > > +} > > + > > +static void mtk_dma_get_rx_size(struct mtk_chan *c) > > +{ > > + unsigned int rx_size = mtk_dma_chan_read(c, VFF_LEN); > > + unsigned int rdptr, wrptr, wrreg, rdreg, count; > > + > > + rdreg = mtk_dma_chan_read(c, VFF_RPT); > > + wrreg = mtk_dma_chan_read(c, VFF_WPT); > > + rdptr = rdreg & MTK_DMA_RING_SIZE; > > + wrptr = wrreg & MTK_DMA_RING_SIZE; > > + count = ((rdreg ^ wrreg) & MTK_DMA_RING_WRAP) ? > > + (wrptr + rx_size - rdptr) : (wrptr - rdptr); > > + > > + c->remain_size = count; > > + c->rx_ptr = rdptr; > > + > > + mtk_dma_chan_write(c, VFF_RPT, wrreg); > > +} > > + > > +static void mtk_dma_start_rx(struct mtk_chan *c) > > +{ > > + struct dma_chan *chan = &c->vc.chan; > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(chan->device); > > + struct mtk_dma_desc *d = c->desc; > > + > > + if (mtk_dma_chan_read(c, VFF_VALID_SIZE) == 0U) > > + return; > > + > > + if (d && d->vd.tx.cookie != 0) { > > the driver benefits from virtual_channel so you can manage the life > cycle of each descriptor by the virtual channel related functions > without handling details about the cookie. > ok, i will modify it at next patch > > + mtk_dma_get_rx_size(c); > > + mtk_dma_remove_virt_list(d->vd.tx.cookie, &c->vc); > > + vchan_cookie_complete(&d->vd); > > + } else { > > + spin_lock(&mtkd->lock); > > + if (list_empty(&mtkd->pending)) > > + list_add_tail(&c->node, &mtkd->pending); > > + spin_unlock(&mtkd->lock); > > + tasklet_schedule(&mtkd->task); > > + } > > +} > > + > > +static void mtk_dma_reset(struct mtk_chan *c) > > +{ > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(c->vc.chan.device); > > + u32 status; > > + int ret; > > + > > + mtk_dma_chan_write(c, VFF_ADDR, 0); > > + mtk_dma_chan_write(c, VFF_THRE, 0); > > + mtk_dma_chan_write(c, VFF_LEN, 0); > > + mtk_dma_chan_write(c, VFF_RST, VFF_WARM_RST_B); > > + > > + ret = readx_poll_timeout(readl, > > + c->base + VFF_EN, > > + status, status == 0, 10, 100); > > + if (ret) { > > + dev_err(c->vc.chan.device->dev, > > + "dma reset: fail, timeout\n"); > > + return; > > + } > > + > > + if (c->cfg.direction == DMA_DEV_TO_MEM) > > + mtk_dma_chan_write(c, VFF_RPT, 0); > > + else if (c->cfg.direction == DMA_MEM_TO_DEV) > > + mtk_dma_chan_write(c, VFF_WPT, 0); > > + > > + if (mtkd->support_33bits) > > + mtk_dma_chan_write(c, VFF_4G_SUPPORT, VFF_4G_SUPPORT_CLR_B); > > +} > > + > > +static void mtk_dma_stop(struct mtk_chan *c) > > +{ > > + u32 status; > > + int ret; > > + > > + mtk_dma_chan_write(c, VFF_FLUSH, VFF_FLUSH_CLR_B); > > + /* Wait for flush */ > > + ret = readx_poll_timeout(readl, > > + c->base + VFF_FLUSH, > > + status, > > + (status & VFF_FLUSH_B) != VFF_FLUSH_B, > > + 10, 100); > > + if (ret) > > + dev_err(c->vc.chan.device->dev, > > + "dma stop: polling FLUSH fail, DEBUG=0x%x\n", > > + mtk_dma_chan_read(c, VFF_DEBUG_STATUS)); > > + > > + /*set stop as 1 -> wait until en is 0 -> set stop as 0*/ > > + mtk_dma_chan_write(c, VFF_STOP, VFF_STOP_B); > > + ret = readx_poll_timeout(readl, > > + c->base + VFF_EN, > > + status, status == 0, 10, 100); > > + if (ret) > > + dev_err(c->vc.chan.device->dev, > > + "dma stop: polling VFF_EN fail, DEBUG=0x%x\n", > > + mtk_dma_chan_read(c, VFF_DEBUG_STATUS)); > > + > > + mtk_dma_chan_write(c, VFF_STOP, VFF_STOP_CLR_B); > > + mtk_dma_chan_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B); > > + > > + if (c->cfg.direction == DMA_DEV_TO_MEM) > > + mtk_dma_chan_write(c, VFF_INT_FLAG, VFF_RX_INT_FLAG_CLR_B); > > + else > > + mtk_dma_chan_write(c, VFF_INT_FLAG, VFF_TX_INT_FLAG_CLR_B); > > + > > + c->stop = true; > > +} > > + > > +/* > > + * This callback schedules all pending channels. We could be more > > + * clever here by postponing allocation of the real DMA channels to > > + * this point, and freeing them when our virtual channel becomes idle. > > + * > > + * We would then need to deal with 'all channels in-use' > > + */ > > +static void mtk_dma_sched(unsigned long data) > > +{ > > + struct mtk_dmadev *mtkd = (struct mtk_dmadev *)data; > > + struct virt_dma_desc *vd; > > + struct mtk_chan *c; > > + dma_cookie_t cookie; > > + unsigned long flags; > > + LIST_HEAD(head); > > + > > + spin_lock_irq(&mtkd->lock); > > + list_splice_tail_init(&mtkd->pending, &head); > > + spin_unlock_irq(&mtkd->lock); > > + > > + if (!list_empty(&head)) { > > + c = list_first_entry(&head, struct mtk_chan, node); > > + cookie = c->vc.chan.cookie; > > + > > + spin_lock_irqsave(&c->vc.lock, flags); > > + if (c->cfg.direction == DMA_DEV_TO_MEM) { > > + list_del_init(&c->node); > > + mtk_dma_start_rx(c); > > + } else if (c->cfg.direction == DMA_MEM_TO_DEV) { > > + vd = vchan_find_desc(&c->vc, cookie); > > + c->desc = to_mtk_dma_desc(&vd->tx); > > + list_del_init(&c->node); > > + mtk_dma_start_tx(c); > > + } > > + spin_unlock_irqrestore(&c->vc.lock, flags); > > + } > > +} > > + > > +static int mtk_dma_alloc_chan_resources(struct dma_chan *chan) > > +{ > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(chan->device); > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + int ret = -EBUSY; > > + > > + pm_runtime_get_sync(mtkd->ddev.dev); > > + > > + if (!mtkd->ch[c->dma_ch]) { > > + c->base = mtkd->mem_base[c->dma_ch]; > > + mtkd->ch[c->dma_ch] = c; > > + ret = 1; > > + } > > + c->requested = false; > > + mtk_dma_reset(c); > > + > > + return ret; > > +} > > + > > +static void mtk_dma_free_chan_resources(struct dma_chan *chan) > > +{ > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(chan->device); > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + > > + if (c->requested) { > > + c->requested = false; > > + free_irq(mtkd->dma_irq[c->dma_ch], chan); > > + } > > + > > + tasklet_kill(&mtkd->task); > > + tasklet_kill(&c->vc.task); > > + > > + c->base = NULL; > > + mtkd->ch[c->dma_ch] = NULL; > > + vchan_free_chan_resources(&c->vc); > > + > > + dev_dbg(mtkd->ddev.dev, "freeing channel for %u\n", c->dma_sig); > > + c->dma_sig = 0; > > + > > + pm_runtime_put_sync(mtkd->ddev.dev); > > +} > > + > > +static enum dma_status mtk_dma_tx_status(struct dma_chan *chan, > > + dma_cookie_t cookie, > > + struct dma_tx_state *txstate) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + enum dma_status ret; > > + unsigned long flags; > > + > > + if (!txstate) > > + return DMA_ERROR; > > + > > + ret = dma_cookie_status(chan, cookie, txstate); > > + spin_lock_irqsave(&c->vc.lock, flags); > > + if (ret == DMA_IN_PROGRESS) { > > + c->rx_ptr = mtk_dma_chan_read(c, VFF_RPT) & MTK_DMA_RING_SIZE; > > + dma_set_residue(txstate, c->rx_ptr); > > + } else if (ret == DMA_COMPLETE && c->cfg.direction == DMA_DEV_TO_MEM) { > > + dma_set_residue(txstate, c->remain_size); > > + } else { > > + dma_set_residue(txstate, 0); > > + } > > + spin_unlock_irqrestore(&c->vc.lock, flags); > > + > > + return ret; > > +} > > + > > +static struct dma_async_tx_descriptor *mtk_dma_prep_slave_sg > > + (struct dma_chan *chan, struct scatterlist *sgl, > > + unsigned int sglen, enum dma_transfer_direction dir, > > + unsigned long tx_flags, void *context) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + struct scatterlist *sgent; > > + struct mtk_dma_desc *d; > > + struct mtk_dma_sg *sg; > > + unsigned int size, i, j, en; > > + > > + en = 1; > > + > > + if ((dir != DMA_DEV_TO_MEM) && > > + (dir != DMA_MEM_TO_DEV)) { > > + dev_err(chan->device->dev, "bad direction\n"); > > + return NULL; > > + } > > + > > + /* Now allocate and setup the descriptor. */ > > + d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC); > > + if (!d) > > + return NULL; > > + > > + d->dir = dir; > > + > > + j = 0; > > + for_each_sg(sgl, sgent, sglen, i) { > > + d->sg[j].addr = sg_dma_address(sgent); > > + d->sg[j].en = en; > > + d->sg[j].fn = sg_dma_len(sgent) / en; > > + j++; > > + } > > + > > + d->sglen = j; > > + > > + if (dir == DMA_MEM_TO_DEV) { > > + for (size = i = 0; i < d->sglen; i++) { > > + sg = &d->sg[i]; > > + size += sg->en * sg->fn; > > + } > > + c->remain_size = size; > > + } > > + > > + return vchan_tx_prep(&c->vc, &d->vd, tx_flags); > > +} > > + > > +static void mtk_dma_issue_pending(struct dma_chan *chan) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + struct virt_dma_desc *vd; > > + struct mtk_dmadev *mtkd; > > + dma_cookie_t cookie; > > + unsigned long flags; > > + > > + spin_lock_irqsave(&c->vc.lock, flags); > > + if (c->cfg.direction == DMA_DEV_TO_MEM) { > > + cookie = c->vc.chan.cookie; > > + mtkd = to_mtk_dma_dev(chan->device); > > + if (vchan_issue_pending(&c->vc) && !c->desc) { > > vchan_issue_pending means putting all the descriptors to list > desc_issued, I'm supposed somewhere would iterate the list by > vchan_next_desc and program each desc. into hardware. but I don't see > the similar code. ok, i will modify it at next patch > > > + vd = vchan_find_desc(&c->vc, cookie); > > + c->desc = to_mtk_dma_desc(&vd->tx); > > + } > > + } else if (c->cfg.direction == DMA_MEM_TO_DEV) { > > + cookie = c->vc.chan.cookie; > > + if (vchan_issue_pending(&c->vc) && !c->desc) { > > ditto as the above > ok, i will modify it at next patch > > + vd = vchan_find_desc(&c->vc, cookie); > > + c->desc = to_mtk_dma_desc(&vd->tx); > > + mtk_dma_start_tx(c); > > + } > > + } > > + spin_unlock_irqrestore(&c->vc.lock, flags); > > +} > > + > > +static irqreturn_t mtk_dma_rx_interrupt(int irq, void *dev_id) > > +{ > > + struct dma_chan *chan = (struct dma_chan *)dev_id; > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + unsigned long flags; > > + > > + spin_lock_irqsave(&c->vc.lock, flags); > > + mtk_dma_chan_write(c, VFF_INT_FLAG, VFF_RX_INT_FLAG_CLR_B); > > + > > + mtk_dma_start_rx(c); > > + > > + spin_unlock_irqrestore(&c->vc.lock, flags); > > + > > + return IRQ_HANDLED; > > +} > > + > > +static irqreturn_t mtk_dma_tx_interrupt(int irq, void *dev_id) > > +{ > > + struct dma_chan *chan = (struct dma_chan *)dev_id; > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(chan->device); > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + struct mtk_dma_desc *d = c->desc; > > + unsigned long flags; > > + > > + spin_lock_irqsave(&c->vc.lock, flags); > > + if (c->remain_size != 0U) { > > + list_add_tail(&c->node, &mtkd->pending); > > + tasklet_schedule(&mtkd->task); > > + } else { > > + mtk_dma_remove_virt_list(d->vd.tx.cookie, &c->vc); > > + vchan_cookie_complete(&d->vd); > > + } > > + spin_unlock_irqrestore(&c->vc.lock, flags); > > + > > + mtk_dma_chan_write(c, VFF_INT_FLAG, VFF_TX_INT_FLAG_CLR_B); > > + > > + return IRQ_HANDLED; > > +} > > + > > +static int mtk_dma_slave_config(struct dma_chan *chan, > > + struct dma_slave_config *cfg) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(c->vc.chan.device); > > + int ret; > > + > > + c->cfg = *cfg; > > + > > + if (cfg->direction == DMA_DEV_TO_MEM) { > > + unsigned int rx_len = cfg->src_addr_width * 1024; > > + > > + mtk_dma_chan_write(c, VFF_ADDR, cfg->src_addr); > > + mtk_dma_chan_write(c, VFF_LEN, rx_len); > > + mtk_dma_chan_write(c, VFF_THRE, VFF_RX_THRE(rx_len)); > > + mtk_dma_chan_write(c, > > + VFF_INT_EN, VFF_RX_INT_EN0_B > > + | VFF_RX_INT_EN1_B); > > + mtk_dma_chan_write(c, VFF_INT_FLAG, VFF_RX_INT_FLAG_CLR_B); > > + mtk_dma_chan_write(c, VFF_EN, VFF_EN_B); > > + > > + if (!c->requested) { > > + c->requested = true; > > + ret = request_irq(mtkd->dma_irq[c->dma_ch], > > + mtk_dma_rx_interrupt, > > + IRQF_TRIGGER_NONE, > > + KBUILD_MODNAME, chan); > > + if (ret < 0) { > > + dev_err(chan->device->dev, "Can't request rx dma IRQ\n"); > > + return -EINVAL; > > + } > > + } > > + } else if (cfg->direction == DMA_MEM_TO_DEV) { > > + unsigned int tx_len = cfg->dst_addr_width * 1024; > > + > > + mtk_dma_chan_write(c, VFF_ADDR, cfg->dst_addr); > > + mtk_dma_chan_write(c, VFF_LEN, tx_len); > > + mtk_dma_chan_write(c, VFF_THRE, VFF_TX_THRE(tx_len)); > > + mtk_dma_chan_write(c, VFF_INT_FLAG, VFF_TX_INT_FLAG_CLR_B); > > + mtk_dma_chan_write(c, VFF_EN, VFF_EN_B); > > + > > + if (!c->requested) { > > + c->requested = true; > > + ret = request_irq(mtkd->dma_irq[c->dma_ch], > > + mtk_dma_tx_interrupt, > > + IRQF_TRIGGER_NONE, > > + KBUILD_MODNAME, chan); > > + if (ret < 0) { > > + dev_err(chan->device->dev, "Can't request tx dma IRQ\n"); > > + return -EINVAL; > > + } > > + } > > + } > > + > > + if (mtkd->support_33bits) > > + mtk_dma_chan_write(c, VFF_4G_SUPPORT, VFF_4G_SUPPORT_B); > > + > > + if (mtk_dma_chan_read(c, VFF_EN) != VFF_EN_B) { > > + dev_err(chan->device->dev, > > + "config dma dir[%d] fail\n", cfg->direction); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > + > > +static int mtk_dma_terminate_all(struct dma_chan *chan) > > +{ > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + unsigned long flags; > > + > > + spin_lock_irqsave(&c->vc.lock, flags); > > + list_del_init(&c->node); > > + mtk_dma_stop(c); > > + spin_unlock_irqrestore(&c->vc.lock, flags); > > + > > + return 0; > > +} > > + > > +static int mtk_dma_device_pause(struct dma_chan *chan) > > +{ > > + /* just for check caps pass */ > > + return -EINVAL; > > +} > > it it possible not to register the function to the core if the > hardware doesn't support it? > can't support. the function will set to cmd_pause. in 8250 serial code, will check cmd_pause. if no the function, will can't get DMA channel. So the function just for this. > > + > > +static int mtk_dma_device_resume(struct dma_chan *chan) > > +{ > > + /* just for check caps pass */ > > + return -EINVAL; > > +} > > ditto as the above > > > + > > +static void mtk_dma_free(struct mtk_dmadev *mtkd) > > +{ > > + tasklet_kill(&mtkd->task); > > + while (list_empty(&mtkd->ddev.channels) == 0) { > > + struct mtk_chan *c = list_first_entry(&mtkd->ddev.channels, > > + struct mtk_chan, vc.chan.device_node); > > + > > + list_del(&c->vc.chan.device_node); > > + tasklet_kill(&c->vc.task); > > + devm_kfree(mtkd->ddev.dev, c); > > + } > > +} > > + > > +static const struct of_device_id mtk_uart_dma_match[] = { > > + { .compatible = "mediatek,mt6577-uart-dma", }, > > + { /* sentinel */ }, > > +}; > > +MODULE_DEVICE_TABLE(of, mtk_uart_dma_match); > > + > > +static int mtk_apdma_probe(struct platform_device *pdev) > > +{ > > + struct mtk_dmadev *mtkd; > > + struct resource *res; > > + struct mtk_chan *c; > > + unsigned int i; > > + int rc; > > + > > + mtkd = devm_kzalloc(&pdev->dev, sizeof(*mtkd), GFP_KERNEL); > > + if (!mtkd) > > + return -ENOMEM; > > + > > + for (i = 0; i < MTK_APDMA_CHANNELS; i++) { > > + res = platform_get_resource(pdev, IORESOURCE_MEM, i); > > + if (!res) > > + return -ENODEV; > > + mtkd->mem_base[i] = devm_ioremap_resource(&pdev->dev, res); > > + if (IS_ERR(mtkd->mem_base[i])) > > + return PTR_ERR(mtkd->mem_base[i]); > > + } > > + > > + for (i = 0; i < MTK_APDMA_CHANNELS; i++) { > > + mtkd->dma_irq[i] = platform_get_irq(pdev, i); > > + if ((int)mtkd->dma_irq[i] < 0) { > > + dev_err(&pdev->dev, "failed to get IRQ[%d]\n", i); > > + return -EINVAL; > > + } > > + } > > + > > + mtkd->clk = devm_clk_get(&pdev->dev, NULL); > > + if (IS_ERR(mtkd->clk)) { > > + dev_err(&pdev->dev, "No clock specified\n"); > > + return PTR_ERR(mtkd->clk); > > + } > > + > > + if (of_property_read_bool(pdev->dev.of_node, "dma-33bits")) { > > + dev_info(&pdev->dev, "Support dma 33bits\n"); > > + mtkd->support_33bits = true; > > + } > > + > > + if (mtkd->support_33bits) > > + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33)); > > + else > > + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); > > + if (rc) > > + return rc; > > + > > + dma_cap_set(DMA_SLAVE, mtkd->ddev.cap_mask); > > + mtkd->ddev.device_alloc_chan_resources = mtk_dma_alloc_chan_resources; > > + mtkd->ddev.device_free_chan_resources = mtk_dma_free_chan_resources; > > + mtkd->ddev.device_tx_status = mtk_dma_tx_status; > > + mtkd->ddev.device_issue_pending = mtk_dma_issue_pending; > > + mtkd->ddev.device_prep_slave_sg = mtk_dma_prep_slave_sg; > > + mtkd->ddev.device_config = mtk_dma_slave_config; > > + mtkd->ddev.device_pause = mtk_dma_device_pause; > > + mtkd->ddev.device_resume = mtk_dma_device_resume; > > + mtkd->ddev.device_terminate_all = mtk_dma_terminate_all; > > + mtkd->ddev.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE); > > + mtkd->ddev.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE); > > + mtkd->ddev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); > > + mtkd->ddev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; > > + mtkd->ddev.dev = &pdev->dev; > > + INIT_LIST_HEAD(&mtkd->ddev.channels); > > + INIT_LIST_HEAD(&mtkd->pending); > > + > > + spin_lock_init(&mtkd->lock); > > + tasklet_init(&mtkd->task, mtk_dma_sched, (unsigned long)mtkd); > > + > > + mtkd->dma_requests = MTK_APDMA_DEFAULT_REQUESTS; > > + if (of_property_read_u32(pdev->dev.of_node, > > + "dma-requests", &mtkd->dma_requests)) { > > + dev_info(&pdev->dev, > > + "Missing dma-requests property, using %u.\n", > > + MTK_APDMA_DEFAULT_REQUESTS); > > + } > > + > > + for (i = 0; i < MTK_APDMA_CHANNELS; i++) { > > + c = devm_kzalloc(mtkd->ddev.dev, sizeof(*c), GFP_KERNEL); > > + if (!c) > > + goto err_no_dma; > > + > > + c->vc.desc_free = mtk_dma_desc_free; > > + vchan_init(&c->vc, &mtkd->ddev); > > + INIT_LIST_HEAD(&c->node); > > + } > > + > > + pm_runtime_enable(&pdev->dev); > > + pm_runtime_set_active(&pdev->dev); > > + > > + rc = dma_async_device_register(&mtkd->ddev); > > + if (rc) > > + goto rpm_disable; > > + > > + platform_set_drvdata(pdev, mtkd); > > + > > + if (pdev->dev.of_node) { > > + mtk_dma_info.dma_cap = mtkd->ddev.cap_mask; > > + > > + /* Device-tree DMA controller registration */ > > + rc = of_dma_controller_register(pdev->dev.of_node, > > + of_dma_simple_xlate, > > + &mtk_dma_info); > > reusing of_dma_xlate_by_chan_id seem that also work for you. in filter_fn function, neeg get number of dma. > > > + if (rc) > > + goto dma_remove; > > + } > > + > > + return rc; > > + > > +dma_remove: > > + dma_async_device_unregister(&mtkd->ddev); > > +rpm_disable: > > + pm_runtime_disable(&pdev->dev); > > +err_no_dma: > > + mtk_dma_free(mtkd); > > + return rc; > > +} > > + > > +static int mtk_apdma_remove(struct platform_device *pdev) > > +{ > > + struct mtk_dmadev *mtkd = platform_get_drvdata(pdev); > > + > > + if (pdev->dev.of_node) > > + of_dma_controller_free(pdev->dev.of_node); > > + > > + pm_runtime_disable(&pdev->dev); > > + pm_runtime_put_noidle(&pdev->dev); > > + > > + dma_async_device_unregister(&mtkd->ddev); > > + > > + mtk_dma_free(mtkd); > > + > > + return 0; > > +} > > + > > +#ifdef CONFIG_PM_SLEEP > > +static int mtk_dma_suspend(struct device *dev) > > +{ > > + struct mtk_dmadev *mtkd = dev_get_drvdata(dev); > > + > > + if (!pm_runtime_suspended(dev)) > > + mtk_dma_clk_disable(mtkd); > > + > > + return 0; > > +} > > + > > +static int mtk_dma_resume(struct device *dev) > > +{ > > + int ret; > > + struct mtk_dmadev *mtkd = dev_get_drvdata(dev); > > + > > + if (!pm_runtime_suspended(dev)) { > > + ret = mtk_dma_clk_enable(mtkd); > > + if (ret) > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > +static int mtk_dma_runtime_suspend(struct device *dev) > > +{ > > + struct mtk_dmadev *mtkd = dev_get_drvdata(dev); > > + > > + mtk_dma_clk_disable(mtkd); > > + > > + return 0; > > +} > > + > > +static int mtk_dma_runtime_resume(struct device *dev) > > +{ > > + int ret; > > + struct mtk_dmadev *mtkd = dev_get_drvdata(dev); > > + > > + ret = mtk_dma_clk_enable(mtkd); > > + if (ret) > > + return ret; > > + > > + return 0; > > +} > > + > > +#endif /* CONFIG_PM_SLEEP */ > > + > > +static const struct dev_pm_ops mtk_dma_pm_ops = { > > + SET_SYSTEM_SLEEP_PM_OPS(mtk_dma_suspend, mtk_dma_resume) > > + SET_RUNTIME_PM_OPS(mtk_dma_runtime_suspend, > > + mtk_dma_runtime_resume, NULL) > > +}; > > + > > +static struct platform_driver mtk_dma_driver = { > > + .probe = mtk_apdma_probe, > > + .remove = mtk_apdma_remove, > > + .driver = { > > + .name = KBUILD_MODNAME, > > + .pm = &mtk_dma_pm_ops, > > + .of_match_table = of_match_ptr(mtk_uart_dma_match), > > + }, > > +}; > > + > > +static bool mtk_dma_filter_fn(struct dma_chan *chan, void *param) > > +{ > > + if (chan->device->dev->driver == &mtk_dma_driver.driver) { > > + struct mtk_dmadev *mtkd = to_mtk_dma_dev(chan->device); > > + struct mtk_chan *c = to_mtk_dma_chan(chan); > > + unsigned int req = *(unsigned int *)param; > > + > > + if (req <= mtkd->dma_requests) { > > + c->dma_sig = req; > > + c->dma_ch = req; > > + return true; > > + } > > + } > > + return false; > > +} > > + > > +module_platform_driver(mtk_dma_driver); > > + > > +MODULE_DESCRIPTION("MediaTek UART APDMA Controller Driver"); > > +MODULE_AUTHOR("Long Cheng "); > > +MODULE_LICENSE("GPL v2"); > > + > > diff --git a/drivers/dma/mediatek/Kconfig b/drivers/dma/mediatek/Kconfig > > index 27bac0b..bef436e 100644 > > --- a/drivers/dma/mediatek/Kconfig > > +++ b/drivers/dma/mediatek/Kconfig > > @@ -1,4 +1,15 @@ > > > > +config DMA_MTK_UART > > + tristate "MediaTek SoCs APDMA support for UART" > > + depends on OF > > + select DMA_ENGINE > > + select DMA_VIRTUAL_CHANNELS > > + help > > + Support for the UART DMA engine found on MediaTek MTK SoCs. > > + when 8250 mtk uart is enabled, and if you want to using DMA, > > + you can enable the config. the DMA engine just only be used > > + with MediaTek Socs. > > + > > config MTK_HSDMA > > tristate "MediaTek High-Speed DMA controller support" > > depends on ARCH_MEDIATEK || COMPILE_TEST > > diff --git a/drivers/dma/mediatek/Makefile b/drivers/dma/mediatek/Makefile > > index 6e778f8..2f2efd9 100644 > > --- a/drivers/dma/mediatek/Makefile > > +++ b/drivers/dma/mediatek/Makefile > > @@ -1 +1,2 @@ > > +obj-$(CONFIG_DMA_MTK_UART) += 8250_mtk_dma.o > > obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o > > -- > > 1.7.9.5 > > > > > > _______________________________________________ > > Linux-mediatek mailing list > > Linux-mediatek@lists.infradead.org > > http://lists.infradead.org/mailman/listinfo/linux-mediatek _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel