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: [v5,2/6] dmaengine: fsl-qdma: Add qDMA controller driver for Layerscape SoCs From: Wen He Message-Id: <20180525111920.24498-2-wen.he_1@nxp.com> Date: Fri, 25 May 2018 19:19:16 +0800 To: vkoul@kernel.org, dmaengine@vger.kernel.org Cc: robh+dt@kernel.org, devicetree@vger.kernel.org, leoyang.li@nxp.com, jiafei.pan@nxp.com, jiaheng.fan@nxp.com, wen.he_1@nxp.com List-ID: TlhQIFF1ZXVlIERNQSBjb250cm9sbGVyKHFETUEpIG9uIExheWVyc2NhcGUgU29DcyBzdXBwb3J0 cyBjaGFubmVsCnZpcnR1YWxsaXphdGlvbiBieSBhbGxvd2luZyBETUEgam9icyB0byBiZSBlbnF1 ZXVlZCBpbnRvIGRpZmZlcmVudApjb21tYW5kIHF1ZXVlcy4KCk5vdGUgdGhhdCB0aGlzIG1vZHVs ZSBkZXBlbmRzIG9uIE5YUCBEUEFBLgoKU2lnbmVkLW9mZi1ieTogV2VuIEhlIDx3ZW4uaGVfMUBu eHAuY29tPgpTaWduZWQtb2ZmLWJ5OiBKaWFoZW5nIEZhbiA8amlhaGVuZy5mYW5AbnhwLmNvbT4K LS0tCmNoYW5nZSBpbiB2NToKCS0gRml4ZWQgdGhlIGlzc3VlcyBpbmNsdWRlczoKCQkqIGFkZCBl cnJvciBoYW5kbGVyIHdoaWNoIGV2ZXJ5IGZ1bmN0aW9uCgkJKiByZXBsYWNlIHdvcmQgdG8gYml0 IGRlZmluaXRpb24KCQkqIG1vdmUgZ2xvYmFsIHZhcmlhYmxlIHRvIHN0cnVjdCBkZWZpbml0aW9u CgkJKiBhZGQgc29tZSBjb21tZW50cyB0byBjb250ZXh0CgpjaGFuZ2UgaW4gdjQ6CgktIEZpeGVk IHRoZSBpc3N1ZXMgdGhhdCBWaW5vZCBwb2ludCBvdXQgaW4gdGhlIG1haWwgbGlzdC4KCmNoYW5n ZSBpbiB2MzoKCS0gQWRkICdkZXBlbmRzIG9uIEFSTSB8fCBBUk02NCcgaW4gZmlsZSAnZHJpdmVy cy9kbWEvS2NvbmZpZycKCmNoYW5nZSBpbiB2MjoKCS0gUmVwbGFjZSBHUEwgVjIgTGljZW5zZSBk ZXRhaWxzIGJ5IFNQRFggdGFncwoJLSBSZXBsYWNlIEZyZWVzY2FsZSBieSBOWFAKCS0gUmVkdWNl IGFuZCBvcHRpbWl6ZSBoZWFkZXIgZmlsZSByZWZlcmVuY2VzCgktIFJlcGxhY2UgYmlnX2VuZGlh biBieSBmZWF0dXJlIGluIHN0cnVjdCBmc2xfcWRtYV9lbmdpbmUKCS0gUmVwbGFjZSBzdHJ1Y3Qg ZnNsX3FkbWFfZm9ybWF0IGJ5IHN0cnVjdCBmc2xfcWRtYV9jY2RmCgkgIGFuZCBzdHJ1Y3QgZnNs X3FkbWFfY3NnZgoJLSBSZW1vdmUgZW1wdHkgbGluZQoJLSBSZXBsYWNlICdpZi4uZWxzZScgYnkg bWFjcm8gJ0ZTTF9RRE1BX0lOL09VVCcgaW4gZnVuY3Rpb24KCSAgcWRtYV9yZWFkbCgpIGFuZCBx ZG1hX3dyaXRlbCgpCgktIFJlbW92ZSBmdW5jdGlvbiBmc2xfcWRtYV9hbGxvY19jaGFuX3Jlc291 cmNlcygpCgktIFJlcGxhY2UgJ3ByZWknIGJ5ICdwcmUnCgktIFJlcGxhY2UgJy0xJyBieSAnLUVO T01FTScgaW4gZnVuY3Rpb24gZnNsX3FkbWFfcHJlX3JlcXVlc3RfZW5xdWV1ZV9kZXNjKCkKCS0g Rml4IGRtYSBwb29sIGFsbG9jYXRpb24gbmVlZCB0byByb2xsZWQgYmFjayBpbiBmdW5jdGlvbgoJ ICBmc2xfcWRtYV9yZXF1ZXN0X2VucXVldWVfZGVzYygpCgktIFJlcGxhY2UgZnVuY3Rpb24gb2Zf cHJvcGVydHlfcmVhZF91MzJfYXJyYXkoKSBieSBkZXZpY2VfcHJvcGVydHlfcmVhZF91MzJfYXJy YXkoKQoJLSBBZGQgZnVuY3Rpb25zIGZzbF9xZG1hX2NsZWFudXBfdmNoYW4oKSBhbmQgZnNsX3Fk bWFfaXJxX2V4aXQoKSB0byBlbnN1cmUKCSAgaXJxIGFuZCB0YXNrbGV0cyBzdG9wcGVkCgktIFJl cGxhY2UgZHRzIG5vZGUgZWxlbWVudCAnY2hhbm5lbHMnIGJ5ICdkbWEtY2hhbm5lbHMnCgktIFJl cGxhY2UgZnVuY3Rpb24gcGxhdGZvcm1fZHJpdmVyX3JlZ2lzdGVyKCkgYnkgbW9kdWxlX3BsYXRm b3JtX2RyaXZlcigpCgogZHJpdmVycy9kbWEvS2NvbmZpZyAgICB8ICAgMTMgKwogZHJpdmVycy9k bWEvTWFrZWZpbGUgICB8ICAgIDEgKwogZHJpdmVycy9kbWEvZnNsLXFkbWEuYyB8IDExMDEgKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCiAzIGZpbGVzIGNo YW5nZWQsIDExMTUgaW5zZXJ0aW9ucygrKSwgMCBkZWxldGlvbnMoLSkKIGNyZWF0ZSBtb2RlIDEw MDY0NCBkcml2ZXJzL2RtYS9mc2wtcWRtYS5jCgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9kbWEvS2Nv bmZpZyBiL2RyaXZlcnMvZG1hL0tjb25maWcKaW5kZXggNmQ2MWNkMC4uOTlhZmYzMyAxMDA2NDQK LS0tIGEvZHJpdmVycy9kbWEvS2NvbmZpZworKysgYi9kcml2ZXJzL2RtYS9LY29uZmlnCkBAIC0y MjUsNiArMjI1LDE5IEBAIGNvbmZpZyBGU0xfRURNQQogCSAgbXVsdGlwbGV4aW5nIGNhcGFiaWxp dHkgZm9yIERNQSByZXF1ZXN0IHNvdXJjZXMoc2xvdCkuCiAJICBUaGlzIG1vZHVsZSBjYW4gYmUg Zm91bmQgb24gRnJlZXNjYWxlIFZ5YnJpZCBhbmQgTFMtMSBTb0NzLgogCitjb25maWcgRlNMX1FE TUEKKyAgICAgICB0cmlzdGF0ZSAiTlhQIExheWVyc2NhcGUgcURNQSBlbmdpbmUgc3VwcG9ydCIK KyAgICAgICBkZXBlbmRzIG9uIEFSTSB8fCBBUk02NAorICAgICAgIHNlbGVjdCBETUFfRU5HSU5F CisgICAgICAgc2VsZWN0IERNQV9WSVJUVUFMX0NIQU5ORUxTCisgICAgICAgc2VsZWN0IERNQV9F TkdJTkVfUkFJRAorICAgICAgIHNlbGVjdCBBU1lOQ19UWF9FTkFCTEVfQ0hBTk5FTF9TV0lUQ0gK KyAgICAgICBoZWxwCisgICAgICAgICBTdXBwb3J0IHRoZSBOWFAgTGF5ZXJzY2FwZSBxRE1BIGVu Z2luZSB3aXRoIGNvbW1hbmQgcXVldWUgYW5kIGxlZ2FjeSBtb2RlLgorICAgICAgICAgQ2hhbm5l bCB2aXJ0dWFsaXphdGlvbiBpcyBzdXBwb3J0ZWQgdGhyb3VnaCBlbnF1ZXVpbmcgb2YgRE1BIGpv YnMgdG8sCisgICAgICAgICBvciBkZXF1ZXVpbmcgRE1BIGpvYnMgZnJvbSwgZGlmZmVyZW50IHdv cmsgcXVldWVzLgorICAgICAgICAgVGhpcyBtb2R1bGUgY2FuIGJlIGZvdW5kIG9uIE5YUCBMYXll cnNjYXBlIFNvQ3MuCisKIGNvbmZpZyBGU0xfUkFJRAogICAgICAgICB0cmlzdGF0ZSAiRnJlZXNj YWxlIFJBSUQgZW5naW5lIFN1cHBvcnQiCiAgICAgICAgIGRlcGVuZHMgb24gRlNMX1NPQyAmJiAh QVNZTkNfVFhfRU5BQkxFX0NIQU5ORUxfU1dJVENICmRpZmYgLS1naXQgYS9kcml2ZXJzL2RtYS9N YWtlZmlsZSBiL2RyaXZlcnMvZG1hL01ha2VmaWxlCmluZGV4IDBmNjJhNGQuLjkzZGIwZmMgMTAw NjQ0Ci0tLSBhL2RyaXZlcnMvZG1hL01ha2VmaWxlCisrKyBiL2RyaXZlcnMvZG1hL01ha2VmaWxl CkBAIC0zMyw2ICszMyw3IEBAIG9iai0kKENPTkZJR19EV19ETUFDX0NPUkUpICs9IGR3Lwogb2Jq LSQoQ09ORklHX0VQOTNYWF9ETUEpICs9IGVwOTN4eF9kbWEubwogb2JqLSQoQ09ORklHX0ZTTF9E TUEpICs9IGZzbGRtYS5vCiBvYmotJChDT05GSUdfRlNMX0VETUEpICs9IGZzbC1lZG1hLm8KK29i ai0kKENPTkZJR19GU0xfUURNQSkgKz0gZnNsLXFkbWEubwogb2JqLSQoQ09ORklHX0ZTTF9SQUlE KSArPSBmc2xfcmFpZC5vCiBvYmotJChDT05GSUdfSFNVX0RNQSkgKz0gaHN1Lwogb2JqLSQoQ09O RklHX0lNR19NRENfRE1BKSArPSBpbWctbWRjLWRtYS5vCmRpZmYgLS1naXQgYS9kcml2ZXJzL2Rt YS9mc2wtcWRtYS5jIGIvZHJpdmVycy9kbWEvZnNsLXFkbWEuYwpuZXcgZmlsZSBtb2RlIDEwMDY0 NAppbmRleCAwMDAwMDAwLi44MWRmODEyCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9kbWEv ZnNsLXFkbWEuYwpAQCAtMCwwICsxLDExMDEgQEAKKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVy OiBHUEwtMi4wCisvLyBDb3B5cmlnaHQgMjAxOCBOWFAKKworLyoKKyAqIERyaXZlciBmb3IgTlhQ IExheWVyc2NhcGUgUXVldWUgRGlyZWN0IE1lbW9yeSBBY2Nlc3MgQ29udHJvbGxlcgorICoKKyAq IEF1dGhvcjoKKyAqICBXZW4gSGUgPHdlbi5oZV8xQG54cC5jb20+CisgKiAgSmlhaGVuZyBGYW4g PGppYWhlbmcuZmFuQG54cC5jb20+CisgKgorICovCisKKyNpbmNsdWRlIDxsaW51eC9pbnRlcnJ1 cHQuaD4KKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9kZWxheS5o PgorI2luY2x1ZGUgPGxpbnV4L29mX2lycS5oPgorI2luY2x1ZGUgPGxpbnV4L29mX2FkZHJlc3Mu aD4KKyNpbmNsdWRlIDxsaW51eC9vZl9wbGF0Zm9ybS5oPgorI2luY2x1ZGUgPGxpbnV4L29mX2Rt YS5oPgorI2luY2x1ZGUgPGxpbnV4L2RtYS1tYXBwaW5nLmg+CisjaW5jbHVkZSA8bGludXgvZG1h cG9vbC5oPgorI2luY2x1ZGUgPGxpbnV4L2RtYWVuZ2luZS5oPgorI2luY2x1ZGUgPGxpbnV4L3Ns YWIuaD4KKyNpbmNsdWRlIDxsaW51eC9zcGlubG9jay5oPgorCisjaW5jbHVkZSAidmlydC1kbWEu aCIKKyNpbmNsdWRlICJmc2xkbWEuaCIKKworLyogUmVnaXN0ZXIgcmVsYXRlZCBkZWZpbml0aW9u ICovCisjZGVmaW5lIEZTTF9RRE1BX0RNUgkJCTB4MAorI2RlZmluZSBGU0xfUURNQV9EU1IJCQkw eDQKKyNkZWZpbmUgRlNMX1FETUFfREVJRVIJCQkweGUwMAorI2RlZmluZSBGU0xfUURNQV9ERURS CQkJMHhlMDQKKyNkZWZpbmUgRlNMX1FETUFfREVDRkRXMFIJCTB4ZTEwCisjZGVmaW5lIEZTTF9R RE1BX0RFQ0ZEVzFSCQkweGUxNAorI2RlZmluZSBGU0xfUURNQV9ERUNGRFcyUgkJMHhlMTgKKyNk ZWZpbmUgRlNMX1FETUFfREVDRkRXM1IJCTB4ZTFjCisjZGVmaW5lIEZTTF9RRE1BX0RFQ0ZRSURS CQkweGUzMAorI2RlZmluZSBGU0xfUURNQV9ERUNCUgkJCTB4ZTM0CisKKyNkZWZpbmUgRlNMX1FE TUFfQkNRTVIoeCkJCSgweGMwICsgMHgxMDAgKiAoeCkpCisjZGVmaW5lIEZTTF9RRE1BX0JDUVNS KHgpCQkoMHhjNCArIDB4MTAwICogKHgpKQorI2RlZmluZSBGU0xfUURNQV9CQ1FFRFBBX1NBRERS KHgpCSgweGM4ICsgMHgxMDAgKiAoeCkpCisjZGVmaW5lIEZTTF9RRE1BX0JDUURQQV9TQUREUih4 KQkoMHhjYyArIDB4MTAwICogKHgpKQorI2RlZmluZSBGU0xfUURNQV9CQ1FFRVBBX1NBRERSKHgp CSgweGQwICsgMHgxMDAgKiAoeCkpCisjZGVmaW5lIEZTTF9RRE1BX0JDUUVQQV9TQUREUih4KQko MHhkNCArIDB4MTAwICogKHgpKQorI2RlZmluZSBGU0xfUURNQV9CQ1FJRVIoeCkJCSgweGUwICsg MHgxMDAgKiAoeCkpCisjZGVmaW5lIEZTTF9RRE1BX0JDUUlEUih4KQkJKDB4ZTQgKyAweDEwMCAq ICh4KSkKKworI2RlZmluZSBGU0xfUURNQV9TUURQQVIJCQkweDgwYworI2RlZmluZSBGU0xfUURN QV9TUUVQQVIJCQkweDgxNAorI2RlZmluZSBGU0xfUURNQV9CU1FNUgkJCTB4ODAwCisjZGVmaW5l IEZTTF9RRE1BX0JTUVNSCQkJMHg4MDQKKyNkZWZpbmUgRlNMX1FETUFfQlNRSUNSCQkJMHg4MjgK KyNkZWZpbmUgRlNMX1FETUFfQ1FNUgkJCTB4YTAwCisjZGVmaW5lIEZTTF9RRE1BX0NRRFNDUjEJ CTB4YTA4CisjZGVmaW5lIEZTTF9RRE1BX0NRRFNDUjIgICAgICAgICAgICAgICAgMHhhMGMKKyNk ZWZpbmUgRlNMX1FETUFfQ1FJRVIJCQkweGExMAorI2RlZmluZSBGU0xfUURNQV9DUUVEUgkJCTB4 YTE0CisjZGVmaW5lIEZTTF9RRE1BX1NRQ0NNUgkJCTB4YTIwCisKKy8qIFJlZ2lzdGVycyBmb3Ig Yml0IGFuZCBnZW5tYXNrICovCisjZGVmaW5lIEZTTF9RRE1BX0NRSURSX1NRVAkJQklUKDE1KQor I2RlZmluZSBRRE1BX0NDREZfRk9UTUFUCQlCSVQoMjkpCisjZGVmaW5lIFFETUFfQ0NERl9TRVIJ CQlCSVQoMzApCisjZGVmaW5lIFFETUFfU0dfRklOCQkJQklUKDMwKQorI2RlZmluZSBRRE1BX1NH X0VYVAkJCUJJVCgzMSkKKyNkZWZpbmUgUURNQV9TR19MRU5fTUFTSwkJR0VOTUFTSygyOSwgMCkK KyNkZWZpbmUgUURNQV9DQ0RGX01BU0sJCQlHRU5NQVNLKDI4LCAyMCkKKworI2RlZmluZSBGU0xf UURNQV9CQ1FJRVJfQ1FUSUUJCUJJVCgxNSkKKyNkZWZpbmUgRlNMX1FETUFfQkNRSUVSX0NRUEVJ RQkJQklUKDIzKQorI2RlZmluZSBGU0xfUURNQV9CU1FJQ1JfSUNFTgkJQklUKDMxKQorCisjZGVm aW5lIEZTTF9RRE1BX0JTUUlDUl9JQ1NUKHgpCQkoKHgpIDw8IDE2KQorI2RlZmluZSBGU0xfUURN QV9DUUlFUl9NRUlFCQlCSVQoMzEpCisjZGVmaW5lIEZTTF9RRE1BX0NRSUVSX1RFSUUJCUJJVCgw KQorI2RlZmluZSBGU0xfUURNQV9TUUNDTVJfRU5URVJfV00JQklUKDIxKQorCisjZGVmaW5lIEZT TF9RRE1BX0JDUU1SX0VOCQlCSVQoMzEpCisjZGVmaW5lIEZTTF9RRE1BX0JDUU1SX0VJCQlCSVQo MzApCisjZGVmaW5lIEZTTF9RRE1BX0JDUU1SX0NEX1RITEQoeCkJKCh4KSA8PCAyMCkKKyNkZWZp bmUgRlNMX1FETUFfQkNRTVJfQ1FfU0laRSh4KQkoKHgpIDw8IDE2KQorCisjZGVmaW5lIEZTTF9R RE1BX0JDUVNSX1FGCQlCSVQoMTYpCisjZGVmaW5lIEZTTF9RRE1BX0JDUVNSX1hPRkYJCUJJVCgw KQorCisjZGVmaW5lIEZTTF9RRE1BX0JTUU1SX0VOCQlCSVQoMzEpCisjZGVmaW5lIEZTTF9RRE1B X0JTUU1SX0RJCQlCSVQoMzApCisjZGVmaW5lIEZTTF9RRE1BX0JTUU1SX0NRX1NJWkUoeCkJKCh4 KSA8PCAxNikKKworI2RlZmluZSBGU0xfUURNQV9CU1FTUl9RRQkJQklUKDE3KQorCisjZGVmaW5l IEZTTF9RRE1BX0RNUl9EUUQJCUJJVCgzMCkKKyNkZWZpbmUgRlNMX1FETUFfRFNSX0RCCQlCSVQo MzEpCisKKy8qIFNpemUgcmVsYXRlZCBkZWZpbml0aW9uICovCisjZGVmaW5lIEZTTF9RRE1BX1FV RVVFX01BWAkJOAorI2RlZmluZSBGU0xfUURNQV9CQVNFX0JVRkZFUl9TSVpFCTk2CisjZGVmaW5l IEZTTF9RRE1BX0NJUkNVTEFSX0RFU0NfU0laRV9NSU4JNjQKKyNkZWZpbmUgRlNMX1FETUFfQ0lS Q1VMQVJfREVTQ19TSVpFX01BWAkxNjM4NAorI2RlZmluZSBGU0xfUURNQV9RVUVVRV9OVU1fTUFY CQk4CisKKy8qIEZpZWxkIGRlZmluaXRpb24gZm9yIENNRCAqLworI2RlZmluZSBGU0xfUURNQV9D TURfUldUVFlQRQkJMHg0CisjZGVmaW5lIEZTTF9RRE1BX0NNRF9MV0MgICAgICAgICAgICAgICAg MHgyCisjZGVmaW5lIEZTTF9RRE1BX0NNRF9SV1RUWVBFX09GRlNFVAkyOAorI2RlZmluZSBGU0xf UURNQV9DTURfTlNfT0ZGU0VUCQkyNworI2RlZmluZSBGU0xfUURNQV9DTURfRFFPU19PRkZTRVQJ MjQKKyNkZWZpbmUgRlNMX1FETUFfQ01EX1dUSFJPVExfT0ZGU0VUCTIwCisjZGVmaW5lIEZTTF9R RE1BX0NNRF9EU0VOX09GRlNFVAkxOQorI2RlZmluZSBGU0xfUURNQV9DTURfTFdDX09GRlNFVAkJ MTYKKworI2RlZmluZSBGU0xfUURNQV9FX1NHX1RBQkxFCQkxCisjZGVmaW5lIEZTTF9RRE1BX0Vf REFUQV9CVUZGRVIJCTAKKyNkZWZpbmUgRlNMX1FETUFfRl9MQVNUX0VOVFJZCQkxCisKKy8qIEZp ZWxkIGRlZmluaXRpb24gZm9yIERlc2NyaXB0b3Igb2Zmc2V0ICovCisjZGVmaW5lIFFETUFfQ0NE Rl9TVEFUVVMJCTIwCisjZGVmaW5lIFFETUFfQ0NERl9PRkZTRVQJCTIwCisKKy8qKgorICogc3Ry dWN0IGZzbF9xZG1hX2Zvcm1hdCAtIFRoaXMgaXMgdGhlIHN0cnVjdCBob2xkaW5nIGRlc2NyaWJp bmcgY29tcG91bmQKKyAqCQkJICAgIGRlc2NyaXB0b3IgZm9ybWF0IHdpdGggcURNQS4KKyAqIEBz dGF0dXM6CQkgICAgVGhpcyBmaWVsZCB3aGljaCBkZXNjcmliZXMgY29tbWFuZCBzdGF0dXMgYW5k CisgKgkJCSAgICBlbnF1ZXVlIHN0YXR1cyBub3RpZmljYXRpb24uCisgKiBAY2ZnOgkJICAgIFRo aXMgZmllbGQgd2hpY2ggZGVzY3JpYmVzIGZyYW1lIG9mZnNldCBhbmQgZnJhbWUKKyAqCQkJICAg IGZvcm1hdC4KKyAqIEBhZGRyX2xvOgkJICAgIFRoaXMgZmllbGQgd2hpY2ggaW5kaWNhdGluZyB0 aGUgc3RhcnQgb2YgdGhlIGJ1ZmZlcgorICoJCQkgICAgaG9sZGluZyB0aGUgY29tcG91bmQgZGVz Y3JpcHRvciBvZiB0aGUgbG93ZXIgMzItYml0cworICoJCQkgICAgYWRkcmVzcyBpbiBtZW1vcnkg NDAtYml0IGFkZHJlc3MuCisgKiBAYWRkcl9oaToJCSAgICBUaGlzIGZpZWxkJ3MgdGhlIHNhbWUg YXMgYWJvdmUgZmllbGQsIGJ1dCBwb2ludCBoaWdoCisgKgkJCSAgICA4LWJpdHMgaW4gbWVtb3J5 IDQwLWJpdCBhZGRyZXNzLgorICogQF9fcmVzZXJ2ZWQxOgkgICAgUmVzZXJ2ZWQgZmllbGQuCisg KiBAY2ZnOGJfdzE6CQkgICAgVGhpcyBmaWVsZCB3aGljaCBkZXNjcmliZXMgY29tcG91bmQgZGVz Y3JpcHRvcgorICoJCQkgICAgY29tbWFuZCBxdWV1ZSBvcmlnaW4gcHJvZHVjZWQgYnkgcURNQSBh bmQgZHluYW1pYworICoJCQkgICAgZGVidWcgZmllbGQuCisgKiBAZGF0YQkJICAgIFBvaW50ZXIg dG8gdGhlIG1lbW9yeSA0MC1iaXQgYWRkcmVzcywgZGVzY3JpYmVzIERNQQorICoJCQkgICAgc291 cmNlIGluZm9ybWFpb24gYW5kIERNQSBkZXN0aW5hdGlvbiBpbmZvcm1hdGlvbi4KKyAqLworc3Ry dWN0IGZzbF9xZG1hX2Zvcm1hdCB7CisJX19sZTMyIHN0YXR1czsKKwlfX2xlMzIgY2ZnOworCXVu aW9uIHsKKwkJc3RydWN0IHsKKwkJCV9fbGUzMiBhZGRyX2xvOworCQkJdTggYWRkcl9oaTsKKwkJ CXU4IF9fcmVzZXJ2ZWQxWzJdOworCQkJdTggY2ZnOGJfdzE7CisJCX0gX19wYWNrZWQ7CisJCV9f bGU2NCBkYXRhOworCX07Cit9IF9fcGFja2VkOworCisvKiBxRE1BIHN0YXR1cyBub3RpZmljYXRp b24gcHJlIGluZm9ybWF0aW9uICovCitzdHJ1Y3QgZnNsX3ByZV9zdGF0dXMgeworCXU2NCBxdWV1 ZTsKKwl1NjQgYWRkcjsKK307CisKK3N0cnVjdCBmc2xfcWRtYV9jaGFuIHsKKwlzdHJ1Y3Qgdmly dF9kbWFfY2hhbgkJdmNoYW47CisJc3RydWN0IHZpcnRfZG1hX2Rlc2MJCXZkZXNjOworCWVudW0g ZG1hX3N0YXR1cwkJCXN0YXR1czsKKwl1MzIJCQkJc2xhdmVfaWQ7CisJc3RydWN0IGZzbF9xZG1h X2VuZ2luZQkJKnFkbWE7CisJc3RydWN0IGZzbF9xZG1hX3F1ZXVlCQkqcXVldWU7CisJc3RydWN0 IGxpc3RfaGVhZAkJcWNvbXA7Cit9OworCitzdHJ1Y3QgZnNsX3FkbWFfcXVldWUgeworCXN0cnVj dCBmc2xfcWRtYV9mb3JtYXQJKnZpcnRfaGVhZDsKKwlzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0CSp2 aXJ0X3RhaWw7CisJc3RydWN0IGxpc3RfaGVhZAljb21wX3VzZWQ7CisJc3RydWN0IGxpc3RfaGVh ZAljb21wX2ZyZWU7CisJc3RydWN0IGRtYV9wb29sCQkqY29tcF9wb29sOworCXNwaW5sb2NrX3QJ CXF1ZXVlX2xvY2s7CisJZG1hX2FkZHJfdAkJYnVzX2FkZHI7CisJdTMyICAgICAgICAgICAgICAg ICAgICAgbl9jcTsKKwl1MzIJCQlpZDsKKwlzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0CSpjcTsKK307 CisKK3N0cnVjdCBmc2xfcWRtYV9jb21wIHsKKwlkbWFfYWRkcl90ICAgICAgICAgICAgICBidXNf YWRkcjsKKwlzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0CSp2aXJ0X2FkZHI7CisJc3RydWN0IGZzbF9x ZG1hX2NoYW4JKnFjaGFuOworCXN0cnVjdCB2aXJ0X2RtYV9kZXNjICAgIHZkZXNjOworCXN0cnVj dCBsaXN0X2hlYWQJbGlzdDsKK307CisKK3N0cnVjdCBmc2xfcWRtYV9lbmdpbmUgeworCXN0cnVj dCBkbWFfZGV2aWNlCWRtYV9kZXY7CisJdm9pZCBfX2lvbWVtCQkqY3RybF9iYXNlOworCXZvaWQg X19pb21lbSAgICAgICAgICAgICpzdGF0dXNfYmFzZTsKKwl2b2lkIF9faW9tZW0JCSpibG9ja19i YXNlOworCXUzMgkJCW5fY2hhbnM7CisJdTMyCQkJbl9xdWV1ZXM7CisJc3RydWN0IG11dGV4ICAg ICAgICAgICAgZnNsX3FkbWFfbXV0ZXg7CisJaW50CQkJZXJyb3JfaXJxOworCWludAkJCXF1ZXVl X2lycTsKKwlib29sCQkJZmVhdHVyZTsKKwlzdHJ1Y3QgZnNsX3FkbWFfcXVldWUJKnF1ZXVlOwor CXN0cnVjdCBmc2xfcWRtYV9xdWV1ZQkqc3RhdHVzOworCXN0cnVjdCBmc2xfcWRtYV9jaGFuCWNo YW5zW107CisKK307CisKK3N0YXRpYyBpbmxpbmUgdTY0CitxZG1hX2NjZGZfYWRkcl9nZXQ2NChj b25zdCBzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0ICpjY2RmKQoreworCXJldHVybiBsZTY0X3RvX2Nw dShjY2RmLT5kYXRhKSAmIChVNjRfTUFYID4+IDI0KTsKK30KKworc3RhdGljIGlubGluZSB2b2lk CitxZG1hX2Rlc2NfYWRkcl9zZXQ2NChzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0ICpjY2RmLCB1NjQg YWRkcikKK3sKKwljY2RmLT5hZGRyX2hpID0gdXBwZXJfMzJfYml0cyhhZGRyKTsKKwljY2RmLT5h ZGRyX2xvID0gY3B1X3RvX2xlMzIobG93ZXJfMzJfYml0cyhhZGRyKSk7Cit9CisKK3N0YXRpYyBp bmxpbmUgdTY0CitxZG1hX2NjZGZfZ2V0X3F1ZXVlKGNvbnN0IHN0cnVjdCBmc2xfcWRtYV9mb3Jt YXQgKmNjZGYpCit7CisJcmV0dXJuIGNjZGYtPmNmZzhiX3cxICYgVThfTUFYOworfQorCitzdGF0 aWMgaW5saW5lIGludAorcWRtYV9jY2RmX2dldF9vZmZzZXQoY29uc3Qgc3RydWN0IGZzbF9xZG1h X2Zvcm1hdCAqY2NkZikKK3sKKwlyZXR1cm4gKGxlMzJfdG9fY3B1KGNjZGYtPmNmZykgJiBRRE1B X0NDREZfTUFTSykgPj4gUURNQV9DQ0RGX09GRlNFVDsKK30KKworc3RhdGljIGlubGluZSB2b2lk CitxZG1hX2NjZGZfc2V0X2Zvcm1hdChzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0ICpjY2RmLCBpbnQg b2Zmc2V0KQoreworCWNjZGYtPmNmZyA9IGNwdV90b19sZTMyKFFETUFfQ0NERl9GT1RNQVQgfCBv ZmZzZXQpOworfQorCitzdGF0aWMgaW5saW5lIGludAorcWRtYV9jY2RmX2dldF9zdGF0dXMoY29u c3Qgc3RydWN0IGZzbF9xZG1hX2Zvcm1hdCAqY2NkZikKK3sKKwlyZXR1cm4gKGxlMzJfdG9fY3B1 KGNjZGYtPnN0YXR1cykgJiBRRE1BX0NDREZfTUFTSykgPj4gUURNQV9DQ0RGX1NUQVRVUzsKK30K Kworc3RhdGljIGlubGluZSB2b2lkCitxZG1hX2NjZGZfc2V0X3NlcihzdHJ1Y3QgZnNsX3FkbWFf Zm9ybWF0ICpjY2RmLCBpbnQgc3RhdHVzKQoreworCWNjZGYtPnN0YXR1cyA9IGNwdV90b19sZTMy KFFETUFfQ0NERl9TRVIgfCBzdGF0dXMpOworfQorCitzdGF0aWMgaW5saW5lIHZvaWQgcWRtYV9j c2dmX3NldF9sZW4oc3RydWN0IGZzbF9xZG1hX2Zvcm1hdCAqY3NnZiwgaW50IGxlbikKK3sKKwlj c2dmLT5jZmcgPSBjcHVfdG9fbGUzMihsZW4gJiBRRE1BX1NHX0xFTl9NQVNLKTsKK30KKworc3Rh dGljIGlubGluZSB2b2lkIHFkbWFfY3NnZl9zZXRfZihzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0ICpj c2dmLCBpbnQgbGVuKQoreworCWNzZ2YtPmNmZyA9IGNwdV90b19sZTMyKFFETUFfU0dfRklOIHwg KGxlbiAmIFFETUFfU0dfTEVOX01BU0spKTsKK30KKworc3RhdGljIGlubGluZSB2b2lkIHFkbWFf Y3NnZl9zZXRfZShzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0ICpjc2dmLCBpbnQgbGVuKQoreworCWNz Z2YtPmNmZyA9IGNwdV90b19sZTMyKFFETUFfU0dfRVhUIHwgKGxlbiAmIFFETUFfU0dfTEVOX01B U0spKTsKK30KKworc3RhdGljIHUzMiBxZG1hX3JlYWRsKHN0cnVjdCBmc2xfcWRtYV9lbmdpbmUg KnFkbWEsIHZvaWQgX19pb21lbSAqYWRkcikKK3sKKwlyZXR1cm4gRlNMX0RNQV9JTihxZG1hLCBh ZGRyLCAzMik7Cit9CisKK3N0YXRpYyB2b2lkIHFkbWFfd3JpdGVsKHN0cnVjdCBmc2xfcWRtYV9l bmdpbmUgKnFkbWEsIHUzMiB2YWwsCisJCQkJCQl2b2lkIF9faW9tZW0gKmFkZHIpCit7CisJRlNM X0RNQV9PVVQocWRtYSwgYWRkciwgdmFsLCAzMik7Cit9CisKK3N0YXRpYyBzdHJ1Y3QgZnNsX3Fk bWFfY2hhbiAqdG9fZnNsX3FkbWFfY2hhbihzdHJ1Y3QgZG1hX2NoYW4gKmNoYW4pCit7CisJcmV0 dXJuIGNvbnRhaW5lcl9vZihjaGFuLCBzdHJ1Y3QgZnNsX3FkbWFfY2hhbiwgdmNoYW4uY2hhbik7 Cit9CisKK3N0YXRpYyBzdHJ1Y3QgZnNsX3FkbWFfY29tcCAqdG9fZnNsX3FkbWFfY29tcChzdHJ1 Y3QgdmlydF9kbWFfZGVzYyAqdmQpCit7CisJcmV0dXJuIGNvbnRhaW5lcl9vZih2ZCwgc3RydWN0 IGZzbF9xZG1hX2NvbXAsIHZkZXNjKTsKK30KKworc3RhdGljIHZvaWQgZnNsX3FkbWFfZnJlZV9j aGFuX3Jlc291cmNlcyhzdHJ1Y3QgZG1hX2NoYW4gKmNoYW4pCit7CisJc3RydWN0IGZzbF9xZG1h X2NoYW4gKmZzbF9jaGFuID0gdG9fZnNsX3FkbWFfY2hhbihjaGFuKTsKKwl1bnNpZ25lZCBsb25n IGZsYWdzOworCUxJU1RfSEVBRChoZWFkKTsKKworCXNwaW5fbG9ja19pcnFzYXZlKCZmc2xfY2hh bi0+dmNoYW4ubG9jaywgZmxhZ3MpOworCXZjaGFuX2dldF9hbGxfZGVzY3JpcHRvcnMoJmZzbF9j aGFuLT52Y2hhbiwgJmhlYWQpOworCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmZzbF9jaGFuLT52 Y2hhbi5sb2NrLCBmbGFncyk7CisKKwl2Y2hhbl9kbWFfZGVzY19mcmVlX2xpc3QoJmZzbF9jaGFu LT52Y2hhbiwgJmhlYWQpOworfQorCitzdGF0aWMgdm9pZCBmc2xfcWRtYV9jb21wX2ZpbGxfbWVt Y3B5KHN0cnVjdCBmc2xfcWRtYV9jb21wICpmc2xfY29tcCwKKwkJCQkJZG1hX2FkZHJfdCBkc3Qs IGRtYV9hZGRyX3Qgc3JjLCB1MzIgbGVuKQoreworCXN0cnVjdCBmc2xfcWRtYV9mb3JtYXQgKmNj ZGYsICpjc2dmX2Rlc2MsICpjc2dmX3NyYywgKmNzZ2ZfZGVzdDsKKwlzdHJ1Y3QgZnNsX3FkbWFf Zm9ybWF0ICpzZGYsICpkZGY7CisKKwljY2RmID0gZnNsX2NvbXAtPnZpcnRfYWRkcjsKKwljc2dm X2Rlc2MgPSBmc2xfY29tcC0+dmlydF9hZGRyICsgMTsKKwljc2dmX3NyYyA9IGZzbF9jb21wLT52 aXJ0X2FkZHIgKyAyOworCWNzZ2ZfZGVzdCA9IGZzbF9jb21wLT52aXJ0X2FkZHIgKyAzOworCXNk ZiA9IGZzbF9jb21wLT52aXJ0X2FkZHIgKyA0OworCWRkZiA9IGZzbF9jb21wLT52aXJ0X2FkZHIg KyA1OworCisJbWVtc2V0KGZzbF9jb21wLT52aXJ0X2FkZHIsIDAsIEZTTF9RRE1BX0JBU0VfQlVG RkVSX1NJWkUpOworCS8qIEhlYWQgQ29tbWFuZCBEZXNjcmlwdG9yKEZyYW1lIERlc2NyaXB0b3Ip ICovCisJcWRtYV9kZXNjX2FkZHJfc2V0NjQoY2NkZiwgZnNsX2NvbXAtPmJ1c19hZGRyICsgMTYp OworCXFkbWFfY2NkZl9zZXRfZm9ybWF0KGNjZGYsIHFkbWFfY2NkZl9nZXRfb2Zmc2V0KGNjZGYp KTsKKwlxZG1hX2NjZGZfc2V0X3NlcihjY2RmLCBxZG1hX2NjZGZfZ2V0X3N0YXR1cyhjY2RmKSk7 CisKKwkvKiBTdGF0dXMgbm90aWZpY2F0aW9uIGlzIGVucXVldWVkIHRvIHN0YXR1cyBxdWV1ZS4g Ki8KKwkvKiBDb21wb3VuZCBDb21tYW5kIERlc2NyaXB0b3IoRnJhbWUgTGlzdCBUYWJsZSkgKi8K KwlxZG1hX2Rlc2NfYWRkcl9zZXQ2NChjc2dmX2Rlc2MsIGZzbF9jb21wLT5idXNfYWRkciArIDY0 KTsKKwkvKiBJdCBtdXN0IGJlIDMyIGFzIENvbXBvdW5kIFMvRyBEZXNjcmlwdG9yICovCisJcWRt YV9jc2dmX3NldF9sZW4oY3NnZl9kZXNjLCAzMik7CisJcWRtYV9kZXNjX2FkZHJfc2V0NjQoY3Nn Zl9zcmMsIHNyYyk7CisJcWRtYV9jc2dmX3NldF9sZW4oY3NnZl9zcmMsIGxlbik7CisJcWRtYV9k ZXNjX2FkZHJfc2V0NjQoY3NnZl9kZXN0LCBkc3QpOworCXFkbWFfY3NnZl9zZXRfbGVuKGNzZ2Zf ZGVzdCwgbGVuKTsKKwkvKiBUaGlzIGVudHJ5IGlzIHRoZSBsYXN0IGVudHJ5LiAqLworCXFkbWFf Y3NnZl9zZXRfZihjc2dmX2Rlc3QsIGxlbik7CisJLyogRGVzY3JpcHRvciBCdWZmZXIgKi8KKwlz ZGYtPmRhdGEgPSBjcHVfdG9fbGU2NCgKKwkJCUZTTF9RRE1BX0NNRF9SV1RUWVBFIDw8IEZTTF9R RE1BX0NNRF9SV1RUWVBFX09GRlNFVCk7CisJZGRmLT5kYXRhID0gY3B1X3RvX2xlNjQoCisJCQlG U0xfUURNQV9DTURfUldUVFlQRSA8PCBGU0xfUURNQV9DTURfUldUVFlQRV9PRkZTRVQpOworCWRk Zi0+ZGF0YSB8PSBjcHVfdG9fbGU2NCgKKwkJCUZTTF9RRE1BX0NNRF9MV0MgPDwgRlNMX1FETUFf Q01EX0xXQ19PRkZTRVQpOworfQorCisvKgorICogUHJlLXJlcXVlc3QgZnVsbCBjb21tYW5kIGRl c2NyaXB0b3IgZm9yIGVucXVldWUuCisgKi8KK3N0YXRpYyBpbnQgZnNsX3FkbWFfcHJlX3JlcXVl c3RfZW5xdWV1ZV9kZXNjKHN0cnVjdCBmc2xfcWRtYV9xdWV1ZSAqcXVldWUpCit7CisJc3RydWN0 IGZzbF9xZG1hX2NvbXAgKmNvbXBfdGVtcCwgKl9jb21wX3RlbXA7CisJaW50IGk7CisKKwlmb3Ig KGkgPSAwOyBpIDwgcXVldWUtPm5fY3E7IGkrKykgeworCQljb21wX3RlbXAgPSBremFsbG9jKHNp emVvZigqY29tcF90ZW1wKSwgR0ZQX0tFUk5FTCk7CisJCWlmICghY29tcF90ZW1wKQorCQkJZ290 byBlcnI7CisKKwkJY29tcF90ZW1wLT52aXJ0X2FkZHIgPSBkbWFfcG9vbF9hbGxvYyhxdWV1ZS0+ Y29tcF9wb29sLAorCQkJCQkJICAgICAgR0ZQX0tFUk5FTCwKKwkJCQkJCSAgICAgICZjb21wX3Rl bXAtPmJ1c19hZGRyKTsKKwkJaWYgKCFjb21wX3RlbXAtPnZpcnRfYWRkcikKKwkJCWdvdG8gZXJy OworCisJCWxpc3RfYWRkX3RhaWwoJmNvbXBfdGVtcC0+bGlzdCwgJnF1ZXVlLT5jb21wX2ZyZWUp OworCX0KKwlyZXR1cm4gMDsKKworZXJyOgorCWlmIChpID09IDAgJiYgY29tcF90ZW1wKSB7CisJ CWtmcmVlKGNvbXBfdGVtcCk7CisJCXJldHVybiAtRU5PTUVNOworCX0KKworCXdoaWxlICgtLWkg Pj0gMSkgeworCQlsaXN0X2Zvcl9lYWNoX2VudHJ5X3NhZmUoY29tcF90ZW1wLCBfY29tcF90ZW1w LAorCQkJCSZxdWV1ZS0+Y29tcF9mcmVlLCBsaXN0KSB7CisJCQlkbWFfcG9vbF9mcmVlKHF1ZXVl LT5jb21wX3Bvb2wsCisJCQkJCWNvbXBfdGVtcC0+dmlydF9hZGRyLAorCQkJCQljb21wX3RlbXAt PmJ1c19hZGRyKTsKKwkJCWxpc3RfZGVsKCZjb21wX3RlbXAtPmxpc3QpOworCQkJa2ZyZWUoY29t cF90ZW1wKTsKKwkJfQorCX0KKwlyZXR1cm4gLUVOT01FTTsKK30KKworLyoKKyAqIFJlcXVlc3Qg YSBjb21tYW5kIGRlc2NyaXB0b3IgZm9yIGVucXVldWUuCisgKi8KK3N0YXRpYyBzdHJ1Y3QgZnNs X3FkbWFfY29tcCAqZnNsX3FkbWFfcmVxdWVzdF9lbnF1ZXVlX2Rlc2MoCisJCQkJCXN0cnVjdCBm c2xfcWRtYV9jaGFuICpmc2xfY2hhbiwKKwkJCQkJdW5zaWduZWQgaW50IGRzdF9uZW50cywKKwkJ CQkJdW5zaWduZWQgaW50IHNyY19uZW50cykKK3sKKwlzdHJ1Y3QgZnNsX3FkbWFfY29tcCAqY29t cF90ZW1wOworCXN0cnVjdCBmc2xfcWRtYV9xdWV1ZSAqcXVldWUgPSBmc2xfY2hhbi0+cXVldWU7 CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKworCXNwaW5fbG9ja19pcnFzYXZlKCZxdWV1ZS0+cXVl dWVfbG9jaywgZmxhZ3MpOworCWlmIChsaXN0X2VtcHR5KCZxdWV1ZS0+Y29tcF9mcmVlKSkgewor CQlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZxdWV1ZS0+cXVldWVfbG9jaywgZmxhZ3MpOworCQlj b21wX3RlbXAgPSBremFsbG9jKHNpemVvZigqY29tcF90ZW1wKSwgR0ZQX0tFUk5FTCk7CisJCWlm ICghY29tcF90ZW1wKQorCQkJcmV0dXJuIE5VTEw7CisKKwkJY29tcF90ZW1wLT52aXJ0X2FkZHIg PSBkbWFfcG9vbF9hbGxvYyhxdWV1ZS0+Y29tcF9wb29sLAorCQkJCQkJICAgICAgR0ZQX0tFUk5F TCwKKwkJCQkJCSAgICAgICZjb21wX3RlbXAtPmJ1c19hZGRyKTsKKwkJaWYgKCFjb21wX3RlbXAt PnZpcnRfYWRkcikgeworCQkJa2ZyZWUoY29tcF90ZW1wKTsKKwkJCXJldHVybiBOVUxMOworCQl9 CisKKwl9IGVsc2UgeworCQljb21wX3RlbXAgPSBsaXN0X2ZpcnN0X2VudHJ5KCZxdWV1ZS0+Y29t cF9mcmVlLAorCQkJCQkgICAgIHN0cnVjdCBmc2xfcWRtYV9jb21wLAorCQkJCQkgICAgIGxpc3Qp OworCQlsaXN0X2RlbCgmY29tcF90ZW1wLT5saXN0KTsKKwkJc3Bpbl91bmxvY2tfaXJxcmVzdG9y ZSgmcXVldWUtPnF1ZXVlX2xvY2ssIGZsYWdzKTsKKwl9CisKKwljb21wX3RlbXAtPnFjaGFuID0g ZnNsX2NoYW47CisKKwlyZXR1cm4gY29tcF90ZW1wOworfQorCitzdGF0aWMgc3RydWN0IGZzbF9x ZG1hX3F1ZXVlICpmc2xfcWRtYV9hbGxvY19xdWV1ZV9yZXNvdXJjZXMoCisJCQkJCXN0cnVjdCBw bGF0Zm9ybV9kZXZpY2UgKnBkZXYsCisJCQkJCXVuc2lnbmVkIGludCBxdWV1ZV9udW0pCit7CisJ c3RydWN0IGZzbF9xZG1hX3F1ZXVlICpxdWV1ZV9oZWFkLCAqcXVldWVfdGVtcDsKKwlpbnQgcmV0 LCBsZW4sIGk7CisJdW5zaWduZWQgaW50IHF1ZXVlX3NpemVbRlNMX1FETUFfUVVFVUVfTUFYXTsK KworCWlmIChxdWV1ZV9udW0gPiBGU0xfUURNQV9RVUVVRV9NQVgpCisJCXF1ZXVlX251bSA9IEZT TF9RRE1BX1FVRVVFX01BWDsKKwlsZW4gPSBzaXplb2YoKnF1ZXVlX2hlYWQpICogcXVldWVfbnVt OworCXF1ZXVlX2hlYWQgPSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRldiwgbGVuLCBHRlBfS0VSTkVM KTsKKwlpZiAoIXF1ZXVlX2hlYWQpCisJCXJldHVybiBOVUxMOworCisJcmV0ID0gZGV2aWNlX3By b3BlcnR5X3JlYWRfdTMyX2FycmF5KCZwZGV2LT5kZXYsICJxdWV1ZS1zaXplcyIsCisJCQkJCXF1 ZXVlX3NpemUsIHF1ZXVlX251bSk7CisJaWYgKHJldCkgeworCQlkZXZfZXJyKCZwZGV2LT5kZXYs ICJDYW4ndCBnZXQgcXVldWUtc2l6ZXMuXG4iKTsKKwkJcmV0dXJuIE5VTEw7CisJfQorCisJZm9y IChpID0gMDsgaSA8IHF1ZXVlX251bTsgaSsrKSB7CisJCWlmIChxdWV1ZV9zaXplW2ldID4gRlNM X1FETUFfQ0lSQ1VMQVJfREVTQ19TSVpFX01BWAorCQkJfHwgcXVldWVfc2l6ZVtpXSA8IEZTTF9R RE1BX0NJUkNVTEFSX0RFU0NfU0laRV9NSU4pIHsKKwkJCWRldl9lcnIoJnBkZXYtPmRldiwgIkdl dCB3cm9uZyBxdWV1ZS1zaXplcy5cbiIpOworCQkJcmV0dXJuIE5VTEw7CisJCX0KKwkJcXVldWVf dGVtcCA9IHF1ZXVlX2hlYWQgKyBpOworCQlxdWV1ZV90ZW1wLT5jcSA9IGRtYV9hbGxvY19jb2hl cmVudCgmcGRldi0+ZGV2LAorCQkJCQkJc2l6ZW9mKHN0cnVjdCBmc2xfcWRtYV9mb3JtYXQpICoK KwkJCQkJCXF1ZXVlX3NpemVbaV0sCisJCQkJCQkmcXVldWVfdGVtcC0+YnVzX2FkZHIsCisJCQkJ CQlHRlBfS0VSTkVMKTsKKwkJaWYgKCFxdWV1ZV90ZW1wLT5jcSkgeworCQkJZGV2bV9rZnJlZSgm cGRldi0+ZGV2LCBxdWV1ZV9oZWFkKTsKKwkJCXJldHVybiBOVUxMOworCQl9CisJCXF1ZXVlX3Rl bXAtPm5fY3EgPSBxdWV1ZV9zaXplW2ldOworCQlxdWV1ZV90ZW1wLT5pZCA9IGk7CisJCXF1ZXVl X3RlbXAtPnZpcnRfaGVhZCA9IHF1ZXVlX3RlbXAtPmNxOworCQlxdWV1ZV90ZW1wLT52aXJ0X3Rh aWwgPSBxdWV1ZV90ZW1wLT5jcTsKKworCQkvKgorCQkgKiBDcmVhdGUgYSBjb21wIGRtYSBwb29s IHRoYXQgc2l6ZQorCQkgKiBpcyAnRlNMX1FETUFfQkFTRV9CVUZGRVJfU0laRScuCisJCSAqIFRo ZSBkbWEgcG9vbCBmb3IgcXVldWUgY29tbWFuZCBidWZmZXIuCisJCSAqLworCQlxdWV1ZV90ZW1w LT5jb21wX3Bvb2wgPSBkbWFfcG9vbF9jcmVhdGUoImNvbXBfcG9vbCIsCisJCQkJCQkmcGRldi0+ ZGV2LAorCQkJCQkJRlNMX1FETUFfQkFTRV9CVUZGRVJfU0laRSwKKwkJCQkJCTE2LCAwKTsKKwkJ aWYgKCFxdWV1ZV90ZW1wLT5jb21wX3Bvb2wpCisJCQlnb3RvIGVycjsKKworCQkvKgorCQkgKiBM aXN0IGZvciBxdWV1ZSBjb21tYW5kIGJ1ZmZlcgorCQkgKi8KKwkJSU5JVF9MSVNUX0hFQUQoJnF1 ZXVlX3RlbXAtPmNvbXBfdXNlZCk7CisJCUlOSVRfTElTVF9IRUFEKCZxdWV1ZV90ZW1wLT5jb21w X2ZyZWUpOworCQlzcGluX2xvY2tfaW5pdCgmcXVldWVfdGVtcC0+cXVldWVfbG9jayk7CisJfQor CisJcmV0dXJuIHF1ZXVlX2hlYWQ7CisKK2VycjoKKwlpZiAoaSA9PSAwICYmIHF1ZXVlX3RlbXAt PmNvbXBfcG9vbCkKKwkJZG1hX3Bvb2xfZGVzdHJveShxdWV1ZV90ZW1wLT5jb21wX3Bvb2wpOwor CXdoaWxlICgtLWkgPj0gMSkgeworCQlxdWV1ZV90ZW1wID0gcXVldWVfaGVhZCArIGk7CisJCWlm IChpID09IDEgJiYgdW5saWtlbHkocXVldWVfdGVtcC0+Y29tcF9wb29sKSkKKwkJCWRtYV9wb29s X2Rlc3Ryb3kocXVldWVfdGVtcC0+Y29tcF9wb29sKTsKKwl9CisKKwlkZXZfZXJyKCZwZGV2LT5k ZXYsCisJCSJ1bmFibGUgdG8gYWxsb2NhdGUgY2hhbm5lbCAlZCBkZXNjcmlwdG9yIHBvb2xcbiIs CisJCXF1ZXVlX3RlbXAtPmlkKTsKKworCXdoaWxlICgtLWkgPj0gMCkgeworCQlxdWV1ZV90ZW1w ID0gcXVldWVfaGVhZCArIGk7CisJCWRtYV9mcmVlX2NvaGVyZW50KCZwZGV2LT5kZXYsCisJCQkJ c2l6ZW9mKHN0cnVjdCBmc2xfcWRtYV9mb3JtYXQpICoKKwkJCQlxdWV1ZV9zaXplW2ldLAorCQkJ CXF1ZXVlX3RlbXAtPmNxLAorCQkJCXF1ZXVlX3RlbXAtPmJ1c19hZGRyKTsKKwl9CisJZGV2bV9r ZnJlZSgmcGRldi0+ZGV2LCBxdWV1ZV9oZWFkKTsKKwlyZXR1cm4gTlVMTDsKK30KKworc3RhdGlj IHN0cnVjdCBmc2xfcWRtYV9xdWV1ZSAqZnNsX3FkbWFfcHJlcF9zdGF0dXNfcXVldWUoCisJCQkJ CQlzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQoreworCXN0cnVjdCBkZXZpY2Vfbm9kZSAq bnAgPSBwZGV2LT5kZXYub2Zfbm9kZTsKKwlzdHJ1Y3QgZnNsX3FkbWFfcXVldWUgKnN0YXR1c19o ZWFkOworCXVuc2lnbmVkIGludCBzdGF0dXNfc2l6ZTsKKwlpbnQgcmV0OworCisJcmV0ID0gb2Zf cHJvcGVydHlfcmVhZF91MzIobnAsICJzdGF0dXMtc2l6ZXMiLCAmc3RhdHVzX3NpemUpOworCWlm IChyZXQpIHsKKwkJZGV2X2VycigmcGRldi0+ZGV2LCAiQ2FuJ3QgZ2V0IHN0YXR1cy1zaXplcy5c biIpOworCQlyZXR1cm4gTlVMTDsKKwl9CisJaWYgKHN0YXR1c19zaXplID4gRlNMX1FETUFfQ0lS Q1VMQVJfREVTQ19TSVpFX01BWAorCQkJfHwgc3RhdHVzX3NpemUgPCBGU0xfUURNQV9DSVJDVUxB Ul9ERVNDX1NJWkVfTUlOKSB7CisJCWRldl9lcnIoJnBkZXYtPmRldiwgIkdldCB3cm9uZyBzdGF0 dXNfc2l6ZS5cbiIpOworCQlyZXR1cm4gTlVMTDsKKwl9CisJc3RhdHVzX2hlYWQgPSBkZXZtX2t6 YWxsb2MoJnBkZXYtPmRldiwgc2l6ZW9mKCpzdGF0dXNfaGVhZCksCisJCQkJCQkJCUdGUF9LRVJO RUwpOworCWlmICghc3RhdHVzX2hlYWQpCisJCXJldHVybiBOVUxMOworCisJLyoKKwkgKiBCdWZm ZXIgZm9yIHF1ZXVlIGNvbW1hbmQKKwkgKi8KKwlzdGF0dXNfaGVhZC0+Y3EgPSBkbWFfYWxsb2Nf Y29oZXJlbnQoJnBkZXYtPmRldiwKKwkJCQkJCXNpemVvZihzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0 KSAqCisJCQkJCQlzdGF0dXNfc2l6ZSwKKwkJCQkJCSZzdGF0dXNfaGVhZC0+YnVzX2FkZHIsCisJ CQkJCQlHRlBfS0VSTkVMKTsKKwlpZiAoIXN0YXR1c19oZWFkLT5jcSkgeworCQlkZXZtX2tmcmVl KCZwZGV2LT5kZXYsIHN0YXR1c19oZWFkKTsKKwkJcmV0dXJuIE5VTEw7CisJfQorCisJc3RhdHVz X2hlYWQtPm5fY3EgPSBzdGF0dXNfc2l6ZTsKKwlzdGF0dXNfaGVhZC0+dmlydF9oZWFkID0gc3Rh dHVzX2hlYWQtPmNxOworCXN0YXR1c19oZWFkLT52aXJ0X3RhaWwgPSBzdGF0dXNfaGVhZC0+Y3E7 CisJc3RhdHVzX2hlYWQtPmNvbXBfcG9vbCA9IE5VTEw7CisKKwlyZXR1cm4gc3RhdHVzX2hlYWQ7 Cit9CisKK3N0YXRpYyBpbnQgZnNsX3FkbWFfaGFsdChzdHJ1Y3QgZnNsX3FkbWFfZW5naW5lICpm c2xfcWRtYSkKK3sKKwl2b2lkIF9faW9tZW0gKmN0cmwgPSBmc2xfcWRtYS0+Y3RybF9iYXNlOwor CXZvaWQgX19pb21lbSAqYmxvY2sgPSBmc2xfcWRtYS0+YmxvY2tfYmFzZTsKKwlpbnQgaSwgY291 bnQgPSA1OworCXUzMiByZWc7CisKKwkvKiBEaXNhYmxlIHRoZSBjb21tYW5kIHF1ZXVlIGFuZCB3 YWl0IGZvciBpZGxlIHN0YXRlLiAqLworCXJlZyA9IHFkbWFfcmVhZGwoZnNsX3FkbWEsIGN0cmwg KyBGU0xfUURNQV9ETVIpOworCXJlZyB8PSBGU0xfUURNQV9ETVJfRFFEOworCXFkbWFfd3JpdGVs KGZzbF9xZG1hLCByZWcsIGN0cmwgKyBGU0xfUURNQV9ETVIpOworCWZvciAoaSA9IDA7IGkgPCBG U0xfUURNQV9RVUVVRV9OVU1fTUFYOyBpKyspCisJCXFkbWFfd3JpdGVsKGZzbF9xZG1hLCAwLCBi bG9jayArIEZTTF9RRE1BX0JDUU1SKGkpKTsKKworCXdoaWxlICgxKSB7CisJCXJlZyA9IHFkbWFf cmVhZGwoZnNsX3FkbWEsIGN0cmwgKyBGU0xfUURNQV9EU1IpOworCQlpZiAoIShyZWcgJiBGU0xf UURNQV9EU1JfREIpKQorCQkJYnJlYWs7CisJCWlmIChjb3VudC0tIDwgMCkKKwkJCXJldHVybiAt RUJVU1k7CisJCXVkZWxheSgxMDApOworCX0KKworCS8qIERpc2FibGUgc3RhdHVzIHF1ZXVlLiAq LworCXFkbWFfd3JpdGVsKGZzbF9xZG1hLCAwLCBibG9jayArIEZTTF9RRE1BX0JTUU1SKTsKKwor CS8qCisJICogQ2xlYXIgdGhlIGNvbW1hbmQgcXVldWUgaW50ZXJydXB0IGRldGVjdCByZWdpc3Rl ciBmb3IgYWxsIHF1ZXVlcy4KKwkgKi8KKwlxZG1hX3dyaXRlbChmc2xfcWRtYSwgMHhmZmZmZmZm ZiwgYmxvY2sgKyBGU0xfUURNQV9CQ1FJRFIoMCkpOworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRp YyBpbnQgZnNsX3FkbWFfcXVldWVfdHJhbnNmZXJfY29tcGxldGUoc3RydWN0IGZzbF9xZG1hX2Vu Z2luZSAqZnNsX3FkbWEpCit7CisJc3RydWN0IGZzbF9xZG1hX3F1ZXVlICpmc2xfcXVldWUgPSBm c2xfcWRtYS0+cXVldWU7CisJc3RydWN0IGZzbF9xZG1hX3F1ZXVlICpmc2xfc3RhdHVzID0gZnNs X3FkbWEtPnN0YXR1czsKKwlzdHJ1Y3QgZnNsX3FkbWFfcXVldWUgKnRlbXBfcXVldWU7CisJc3Ry dWN0IGZzbF9xZG1hX2NvbXAgKmZzbF9jb21wOworCXN0cnVjdCBmc2xfcWRtYV9mb3JtYXQgKnN0 YXR1c19hZGRyOworCXN0cnVjdCBmc2xfcWRtYV9mb3JtYXQgKmNzZ2Zfc3JjOworCXN0cnVjdCBm c2xfcHJlX3N0YXR1cyBwcmU7CisJdm9pZCBfX2lvbWVtICpibG9jayA9IGZzbF9xZG1hLT5ibG9j a19iYXNlOworCXUzMiByZWcsIGk7CisJYm9vbCBkdXBsaWNhdGUsIGR1cGxpY2F0ZV9oYW5kbGU7 CisKKwltZW1zZXQoJnByZSwgMCwgc2l6ZW9mKHN0cnVjdCBmc2xfcHJlX3N0YXR1cykpOworCisJ d2hpbGUgKDEpIHsKKwkJZHVwbGljYXRlID0gMDsKKwkJZHVwbGljYXRlX2hhbmRsZSA9IDA7CisJ CXJlZyA9IHFkbWFfcmVhZGwoZnNsX3FkbWEsIGJsb2NrICsgRlNMX1FETUFfQlNRU1IpOworCQlp ZiAocmVnICYgRlNMX1FETUFfQlNRU1JfUUUpCisJCQlyZXR1cm4gMDsKKwkJc3RhdHVzX2FkZHIg PSBmc2xfc3RhdHVzLT52aXJ0X2hlYWQ7CisJCWlmIChxZG1hX2NjZGZfZ2V0X3F1ZXVlKHN0YXR1 c19hZGRyKSA9PSBwcmUucXVldWUgJiYKKwkJCXFkbWFfY2NkZl9hZGRyX2dldDY0KHN0YXR1c19h ZGRyKSA9PSBwcmUuYWRkcikKKwkJCWR1cGxpY2F0ZSA9IDE7CisJCWkgPSBxZG1hX2NjZGZfZ2V0 X3F1ZXVlKHN0YXR1c19hZGRyKTsKKwkJcHJlLnF1ZXVlID0gcWRtYV9jY2RmX2dldF9xdWV1ZShz dGF0dXNfYWRkcik7CisJCXByZS5hZGRyID0gcWRtYV9jY2RmX2FkZHJfZ2V0NjQoc3RhdHVzX2Fk ZHIpOworCQl0ZW1wX3F1ZXVlID0gZnNsX3F1ZXVlICsgaTsKKwkJc3Bpbl9sb2NrKCZ0ZW1wX3F1 ZXVlLT5xdWV1ZV9sb2NrKTsKKwkJaWYgKGxpc3RfZW1wdHkoJnRlbXBfcXVldWUtPmNvbXBfdXNl ZCkpIHsKKwkJCWlmIChkdXBsaWNhdGUpCisJCQkJZHVwbGljYXRlX2hhbmRsZSA9IDE7CisJCQll bHNlIHsKKwkJCQlzcGluX3VubG9jaygmdGVtcF9xdWV1ZS0+cXVldWVfbG9jayk7CisJCQkJcmV0 dXJuIC1FQUdBSU47CisJCQl9CisJCX0gZWxzZSB7CisJCQlmc2xfY29tcCA9IGxpc3RfZmlyc3Rf ZW50cnkoJnRlbXBfcXVldWUtPmNvbXBfdXNlZCwKKwkJCQkJCQlzdHJ1Y3QgZnNsX3FkbWFfY29t cCwKKwkJCQkJCQlsaXN0KTsKKwkJCWNzZ2Zfc3JjID0gZnNsX2NvbXAtPnZpcnRfYWRkciArIDI7 CisJCQlpZiAoZnNsX2NvbXAtPmJ1c19hZGRyICsgMTYgIT0gcHJlLmFkZHIpIHsKKwkJCQlpZiAo ZHVwbGljYXRlKQorCQkJCQlkdXBsaWNhdGVfaGFuZGxlID0gMTsKKwkJCQllbHNlIHsKKwkJCQkJ c3Bpbl91bmxvY2soJnRlbXBfcXVldWUtPnF1ZXVlX2xvY2spOworCQkJCQlyZXR1cm4gLUVBR0FJ TjsKKwkJCQl9CisJCQl9CisJCX0KKworCQkJaWYgKGR1cGxpY2F0ZV9oYW5kbGUpIHsKKwkJCQly ZWcgPSBxZG1hX3JlYWRsKGZzbF9xZG1hLCBibG9jayArCisJCQkJCQlGU0xfUURNQV9CU1FNUik7 CisJCQlyZWcgfD0gRlNMX1FETUFfQlNRTVJfREk7CisJCQlxZG1hX2Rlc2NfYWRkcl9zZXQ2NChz dGF0dXNfYWRkciwgMHgwKTsKKwkJCWZzbF9zdGF0dXMtPnZpcnRfaGVhZCsrOworCQkJaWYgKGZz bF9zdGF0dXMtPnZpcnRfaGVhZCA9PSBmc2xfc3RhdHVzLT5jcQorCQkJCQkJICAgKyBmc2xfc3Rh dHVzLT5uX2NxKQorCQkJCWZzbF9zdGF0dXMtPnZpcnRfaGVhZCA9IGZzbF9zdGF0dXMtPmNxOwor CQkJcWRtYV93cml0ZWwoZnNsX3FkbWEsIHJlZywgYmxvY2sgKyBGU0xfUURNQV9CU1FNUik7CisJ CQlzcGluX3VubG9jaygmdGVtcF9xdWV1ZS0+cXVldWVfbG9jayk7CisJCQljb250aW51ZTsKKwkJ fQorCQlsaXN0X2RlbCgmZnNsX2NvbXAtPmxpc3QpOworCisJCXJlZyA9IHFkbWFfcmVhZGwoZnNs X3FkbWEsIGJsb2NrICsgRlNMX1FETUFfQlNRTVIpOworCQlyZWcgfD0gRlNMX1FETUFfQlNRTVJf REk7CisJCXFkbWFfZGVzY19hZGRyX3NldDY0KHN0YXR1c19hZGRyLCAweDApOworCQlmc2xfc3Rh dHVzLT52aXJ0X2hlYWQrKzsKKwkJaWYgKGZzbF9zdGF0dXMtPnZpcnRfaGVhZCA9PSBmc2xfc3Rh dHVzLT5jcSArIGZzbF9zdGF0dXMtPm5fY3EpCisJCQlmc2xfc3RhdHVzLT52aXJ0X2hlYWQgPSBm c2xfc3RhdHVzLT5jcTsKKwkJcWRtYV93cml0ZWwoZnNsX3FkbWEsIHJlZywgYmxvY2sgKyBGU0xf UURNQV9CU1FNUik7CisJCXNwaW5fdW5sb2NrKCZ0ZW1wX3F1ZXVlLT5xdWV1ZV9sb2NrKTsKKwor CQlzcGluX2xvY2soJmZzbF9jb21wLT5xY2hhbi0+dmNoYW4ubG9jayk7CisJCXZjaGFuX2Nvb2tp ZV9jb21wbGV0ZSgmZnNsX2NvbXAtPnZkZXNjKTsKKwkJZnNsX2NvbXAtPnFjaGFuLT5zdGF0dXMg PSBETUFfQ09NUExFVEU7CisJCXNwaW5fdW5sb2NrKCZmc2xfY29tcC0+cWNoYW4tPnZjaGFuLmxv Y2spOworCX0KKworCXJldHVybiAwOworfQorCitzdGF0aWMgaXJxcmV0dXJuX3QgZnNsX3FkbWFf ZXJyb3JfaGFuZGxlcihpbnQgaXJxLCB2b2lkICpkZXZfaWQpCit7CisJc3RydWN0IGZzbF9xZG1h X2VuZ2luZSAqZnNsX3FkbWEgPSBkZXZfaWQ7CisJdW5zaWduZWQgaW50IGludHI7CisJdm9pZCBf X2lvbWVtICpzdGF0dXMgPSBmc2xfcWRtYS0+c3RhdHVzX2Jhc2U7CisKKwlpbnRyID0gcWRtYV9y ZWFkbChmc2xfcWRtYSwgc3RhdHVzICsgRlNMX1FETUFfREVEUik7CisKKwlpZiAoaW50cikKKwkJ ZGV2X2Vycihmc2xfcWRtYS0+ZG1hX2Rldi5kZXYsICJETUEgdHJhbnNhY3Rpb24gZXJyb3IhXG4i KTsKKworCXFkbWFfd3JpdGVsKGZzbF9xZG1hLCAweGZmZmZmZmZmLCBzdGF0dXMgKyBGU0xfUURN QV9ERURSKTsKKworCXJldHVybiBJUlFfSEFORExFRDsKK30KKworc3RhdGljIGlycXJldHVybl90 IGZzbF9xZG1hX3F1ZXVlX2hhbmRsZXIoaW50IGlycSwgdm9pZCAqZGV2X2lkKQoreworCXN0cnVj dCBmc2xfcWRtYV9lbmdpbmUgKmZzbF9xZG1hID0gZGV2X2lkOworCXVuc2lnbmVkIGludCBpbnRy LCByZWc7CisJdm9pZCBfX2lvbWVtICpibG9jayA9IGZzbF9xZG1hLT5ibG9ja19iYXNlOworCXZv aWQgX19pb21lbSAqY3RybCA9IGZzbF9xZG1hLT5jdHJsX2Jhc2U7CisKKwlpbnRyID0gcWRtYV9y ZWFkbChmc2xfcWRtYSwgYmxvY2sgKyBGU0xfUURNQV9CQ1FJRFIoMCkpOworCisJaWYgKChpbnRy ICYgRlNMX1FETUFfQ1FJRFJfU1FUKSAhPSAwKQorCQlpbnRyID0gZnNsX3FkbWFfcXVldWVfdHJh bnNmZXJfY29tcGxldGUoZnNsX3FkbWEpOworCisJaWYgKGludHIgIT0gMCkgeworCQlyZWcgPSBx ZG1hX3JlYWRsKGZzbF9xZG1hLCBjdHJsICsgRlNMX1FETUFfRE1SKTsKKwkJcmVnIHw9IEZTTF9R RE1BX0RNUl9EUUQ7CisJCXFkbWFfd3JpdGVsKGZzbF9xZG1hLCByZWcsIGN0cmwgKyBGU0xfUURN QV9ETVIpOworCQlxZG1hX3dyaXRlbChmc2xfcWRtYSwgMCwgYmxvY2sgKyBGU0xfUURNQV9CQ1FJ RVIoMCkpOworCQlkZXZfZXJyKGZzbF9xZG1hLT5kbWFfZGV2LmRldiwgIlFETUE6IHN0YXR1cyBl cnIhXG4iKTsKKwl9CisKKwlxZG1hX3dyaXRlbChmc2xfcWRtYSwgMHhmZmZmZmZmZiwgYmxvY2sg KyBGU0xfUURNQV9CQ1FJRFIoMCkpOworCisJcmV0dXJuIElSUV9IQU5ETEVEOworfQorCitzdGF0 aWMgaW50Citmc2xfcWRtYV9pcnFfaW5pdChzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2LAor CQkgIHN0cnVjdCBmc2xfcWRtYV9lbmdpbmUgKmZzbF9xZG1hKQoreworCWludCByZXQ7CisKKwlm c2xfcWRtYS0+ZXJyb3JfaXJxID0gcGxhdGZvcm1fZ2V0X2lycV9ieW5hbWUocGRldiwKKwkJCQkJ CQkicWRtYS1lcnJvciIpOworCWlmIChmc2xfcWRtYS0+ZXJyb3JfaXJxIDwgMCkgeworCQlkZXZf ZXJyKCZwZGV2LT5kZXYsICJDYW4ndCBnZXQgcWRtYSBjb250cm9sbGVyIGlycS5cbiIpOworCQly ZXR1cm4gZnNsX3FkbWEtPmVycm9yX2lycTsKKwl9CisKKwlmc2xfcWRtYS0+cXVldWVfaXJxID0g cGxhdGZvcm1fZ2V0X2lycV9ieW5hbWUocGRldiwgInFkbWEtcXVldWUiKTsKKwlpZiAoZnNsX3Fk bWEtPnF1ZXVlX2lycSA8IDApIHsKKwkJZGV2X2VycigmcGRldi0+ZGV2LCAiQ2FuJ3QgZ2V0IHFk bWEgcXVldWUgaXJxLlxuIik7CisJCXJldHVybiBmc2xfcWRtYS0+cXVldWVfaXJxOworCX0KKwor CXJldCA9IGRldm1fcmVxdWVzdF9pcnEoJnBkZXYtPmRldiwgZnNsX3FkbWEtPmVycm9yX2lycSwK KwkJCWZzbF9xZG1hX2Vycm9yX2hhbmRsZXIsIDAsICJxRE1BIGVycm9yIiwgZnNsX3FkbWEpOwor CWlmIChyZXQpIHsKKwkJZGV2X2VycigmcGRldi0+ZGV2LCAiQ2FuJ3QgcmVnaXN0ZXIgcURNQSBj b250cm9sbGVyIElSUS5cbiIpOworCQlyZXR1cm4gIHJldDsKKwl9CisJcmV0ID0gZGV2bV9yZXF1 ZXN0X2lycSgmcGRldi0+ZGV2LCBmc2xfcWRtYS0+cXVldWVfaXJxLAorCQkJZnNsX3FkbWFfcXVl dWVfaGFuZGxlciwgMCwgInFETUEgcXVldWUiLCBmc2xfcWRtYSk7CisJaWYgKHJldCkgeworCQlk ZXZfZXJyKCZwZGV2LT5kZXYsICJDYW4ndCByZWdpc3RlciBxRE1BIHF1ZXVlIElSUS5cbiIpOwor CQlyZXR1cm4gIHJldDsKKwl9CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIHZvaWQgZnNsX3Fk bWFfaXJxX2V4aXQoCisJCXN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYsIHN0cnVjdCBmc2xf cWRtYV9lbmdpbmUgKmZzbF9xZG1hKQoreworCWlmIChmc2xfcWRtYS0+cXVldWVfaXJxID09IGZz bF9xZG1hLT5lcnJvcl9pcnEpIHsKKwkJZGV2bV9mcmVlX2lycSgmcGRldi0+ZGV2LCBmc2xfcWRt YS0+cXVldWVfaXJxLCBmc2xfcWRtYSk7CisJfSBlbHNlIHsKKwkJZGV2bV9mcmVlX2lycSgmcGRl di0+ZGV2LCBmc2xfcWRtYS0+cXVldWVfaXJxLCBmc2xfcWRtYSk7CisJCWRldm1fZnJlZV9pcnEo JnBkZXYtPmRldiwgZnNsX3FkbWEtPmVycm9yX2lycSwgZnNsX3FkbWEpOworCX0KK30KKworc3Rh dGljIGludCBmc2xfcWRtYV9yZWdfaW5pdChzdHJ1Y3QgZnNsX3FkbWFfZW5naW5lICpmc2xfcWRt YSkKK3sKKwlzdHJ1Y3QgZnNsX3FkbWFfcXVldWUgKmZzbF9xdWV1ZSA9IGZzbF9xZG1hLT5xdWV1 ZTsKKwlzdHJ1Y3QgZnNsX3FkbWFfcXVldWUgKnRlbXA7CisJdm9pZCBfX2lvbWVtICpjdHJsID0g ZnNsX3FkbWEtPmN0cmxfYmFzZTsKKwl2b2lkIF9faW9tZW0gKnN0YXR1cyA9IGZzbF9xZG1hLT5z dGF0dXNfYmFzZTsKKwl2b2lkIF9faW9tZW0gKmJsb2NrID0gZnNsX3FkbWEtPmJsb2NrX2Jhc2U7 CisJaW50IGksIHJldDsKKwl1MzIgcmVnOworCisJLyogVHJ5IHRvIGhhbHQgdGhlIHFETUEgZW5n aW5lIGZpcnN0LiAqLworCXJldCA9IGZzbF9xZG1hX2hhbHQoZnNsX3FkbWEpOworCWlmIChyZXQp IHsKKwkJZGV2X2Vycihmc2xfcWRtYS0+ZG1hX2Rldi5kZXYsICJETUEgaGFsdCBmYWlsZWQhIik7 CisJCXJldHVybiByZXQ7CisJfQorCisJLyoKKwkgKiBDbGVhciB0aGUgY29tbWFuZCBxdWV1ZSBp bnRlcnJ1cHQgZGV0ZWN0IHJlZ2lzdGVyIGZvciBhbGwgcXVldWVzLgorCSAqLworCXFkbWFfd3Jp dGVsKGZzbF9xZG1hLCAweGZmZmZmZmZmLCBibG9jayArIEZTTF9RRE1BX0JDUUlEUigwKSk7CisK Kwlmb3IgKGkgPSAwOyBpIDwgZnNsX3FkbWEtPm5fcXVldWVzOyBpKyspIHsKKwkJdGVtcCA9IGZz bF9xdWV1ZSArIGk7CisJCS8qCisJCSAqIEluaXRpYWxpemUgQ29tbWFuZCBRdWV1ZSByZWdpc3Rl cnMgdG8gcG9pbnQgdG8gdGhlIGZpcnN0CisJCSAqIGNvbW1hbmQgZGVzY3JpcHRvciBpbiBtZW1v cnkuCisJCSAqIERlcXVldWUgUG9pbnRlciBBZGRyZXNzIFJlZ2lzdGVycworCQkgKiBFbnF1ZXVl IFBvaW50ZXIgQWRkcmVzcyBSZWdpc3RlcnMKKwkJICovCisJCXFkbWFfd3JpdGVsKGZzbF9xZG1h LCB0ZW1wLT5idXNfYWRkciwKKwkJCQlibG9jayArIEZTTF9RRE1BX0JDUURQQV9TQUREUihpKSk7 CisJCXFkbWFfd3JpdGVsKGZzbF9xZG1hLCB0ZW1wLT5idXNfYWRkciwKKwkJCQlibG9jayArIEZT TF9RRE1BX0JDUUVQQV9TQUREUihpKSk7CisKKwkJLyogSW5pdGlhbGl6ZSB0aGUgcXVldWUgbW9k ZS4gKi8KKwkJcmVnID0gRlNMX1FETUFfQkNRTVJfRU47CisJCXJlZyB8PSBGU0xfUURNQV9CQ1FN Ul9DRF9USExEKGlsb2cyKHRlbXAtPm5fY3EpLTQpOworCQlyZWcgfD0gRlNMX1FETUFfQkNRTVJf Q1FfU0laRShpbG9nMih0ZW1wLT5uX2NxKS02KTsKKwkJcWRtYV93cml0ZWwoZnNsX3FkbWEsIHJl ZywgYmxvY2sgKyBGU0xfUURNQV9CQ1FNUihpKSk7CisJfQorCisJLyoKKwkgKiBXb3JrYXJvdW5k IGZvciBlcnJhdHVtOiBFUlIwMTA4MTIuCisJICogV2UgbXVzdCBlbmFibGUgWE9GRiB0byBhdm9p ZCB0aGUgZW5xdWV1ZSByZWplY3Rpb24gb2NjdXJzLgorCSAqIFNldHRpbmcgU1FDQ01SIEVOVEVS X1dNIHRvIDB4MjAuCisJICovCisJcWRtYV93cml0ZWwoZnNsX3FkbWEsIEZTTF9RRE1BX1NRQ0NN Ul9FTlRFUl9XTSwKKwkJCSAgICAgIGJsb2NrICsgRlNMX1FETUFfU1FDQ01SKTsKKwkvKgorCSAq IEluaXRpYWxpemUgc3RhdHVzIHF1ZXVlIHJlZ2lzdGVycyB0byBwb2ludCB0byB0aGUgZmlyc3QK KwkgKiBjb21tYW5kIGRlc2NyaXB0b3IgaW4gbWVtb3J5LgorCSAqIERlcXVldWUgUG9pbnRlciBB ZGRyZXNzIFJlZ2lzdGVycworCSAqIEVucXVldWUgUG9pbnRlciBBZGRyZXNzIFJlZ2lzdGVycwor CSAqLworCXFkbWFfd3JpdGVsKGZzbF9xZG1hLCBmc2xfcWRtYS0+c3RhdHVzLT5idXNfYWRkciwK KwkJCQkJYmxvY2sgKyBGU0xfUURNQV9TUUVQQVIpOworCXFkbWFfd3JpdGVsKGZzbF9xZG1hLCBm c2xfcWRtYS0+c3RhdHVzLT5idXNfYWRkciwKKwkJCQkJYmxvY2sgKyBGU0xfUURNQV9TUURQQVIp OworCS8qIEluaXRpYWxpemUgc3RhdHVzIHF1ZXVlIGludGVycnVwdC4gKi8KKwlxZG1hX3dyaXRl bChmc2xfcWRtYSwgRlNMX1FETUFfQkNRSUVSX0NRVElFLAorCQkJICAgICAgYmxvY2sgKyBGU0xf UURNQV9CQ1FJRVIoMCkpOworCXFkbWFfd3JpdGVsKGZzbF9xZG1hLCBGU0xfUURNQV9CU1FJQ1Jf SUNFTiB8IEZTTF9RRE1BX0JTUUlDUl9JQ1NUKDUpCisJCQkJCQkgICB8IDB4ODAwMCwKKwkJCSAg ICAgIGJsb2NrICsgRlNMX1FETUFfQlNRSUNSKTsKKwlxZG1hX3dyaXRlbChmc2xfcWRtYSwgRlNM X1FETUFfQ1FJRVJfTUVJRSB8IEZTTF9RRE1BX0NRSUVSX1RFSUUsCisJCQkgICAgICBibG9jayAr IEZTTF9RRE1BX0NRSUVSKTsKKwkvKiBJbml0aWFsaXplIGNvbnRyb2xsZXIgaW50ZXJydXB0IHJl Z2lzdGVyLiAqLworCXFkbWFfd3JpdGVsKGZzbF9xZG1hLCAweGZmZmZmZmZmLCBzdGF0dXMgKyBG U0xfUURNQV9ERURSKTsKKwlxZG1hX3dyaXRlbChmc2xfcWRtYSwgMHhmZmZmZmZmZiwgc3RhdHVz ICsgRlNMX1FETUFfREVJRVIpOworCisJLyogSW5pdGlhbGl6ZSB0aGUgc3RhdHVzIHF1ZXVlIG1v ZGUuICovCisJcmVnID0gRlNMX1FETUFfQlNRTVJfRU47CisJcmVnIHw9IEZTTF9RRE1BX0JTUU1S X0NRX1NJWkUoaWxvZzIoZnNsX3FkbWEtPnN0YXR1cy0+bl9jcSktNik7CisJcWRtYV93cml0ZWwo ZnNsX3FkbWEsIHJlZywgYmxvY2sgKyBGU0xfUURNQV9CU1FNUik7CisKKwlyZWcgPSBxZG1hX3Jl YWRsKGZzbF9xZG1hLCBjdHJsICsgRlNMX1FETUFfRE1SKTsKKwlyZWcgJj0gfkZTTF9RRE1BX0RN Ul9EUUQ7CisJcWRtYV93cml0ZWwoZnNsX3FkbWEsIHJlZywgY3RybCArIEZTTF9RRE1BX0RNUik7 CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIHN0cnVjdCBkbWFfYXN5bmNfdHhfZGVzY3JpcHRv ciAqCitmc2xfcWRtYV9wcmVwX21lbWNweShzdHJ1Y3QgZG1hX2NoYW4gKmNoYW4sIGRtYV9hZGRy X3QgZHN0LAorCQlkbWFfYWRkcl90IHNyYywgc2l6ZV90IGxlbiwgdW5zaWduZWQgbG9uZyBmbGFn cykKK3sKKwlzdHJ1Y3QgZnNsX3FkbWFfY2hhbiAqZnNsX2NoYW4gPSB0b19mc2xfcWRtYV9jaGFu KGNoYW4pOworCXN0cnVjdCBmc2xfcWRtYV9jb21wICpmc2xfY29tcDsKKworCWZzbF9jb21wID0g ZnNsX3FkbWFfcmVxdWVzdF9lbnF1ZXVlX2Rlc2MoZnNsX2NoYW4sIDAsIDApOworCWZzbF9xZG1h X2NvbXBfZmlsbF9tZW1jcHkoZnNsX2NvbXAsIGRzdCwgc3JjLCBsZW4pOworCisJcmV0dXJuIHZj aGFuX3R4X3ByZXAoJmZzbF9jaGFuLT52Y2hhbiwgJmZzbF9jb21wLT52ZGVzYywgZmxhZ3MpOwor fQorCitzdGF0aWMgdm9pZCBmc2xfcWRtYV9lbnF1ZXVlX2Rlc2Moc3RydWN0IGZzbF9xZG1hX2No YW4gKmZzbF9jaGFuKQoreworCXZvaWQgX19pb21lbSAqYmxvY2sgPSBmc2xfY2hhbi0+cWRtYS0+ YmxvY2tfYmFzZTsKKwlzdHJ1Y3QgZnNsX3FkbWFfcXVldWUgKmZzbF9xdWV1ZSA9IGZzbF9jaGFu LT5xdWV1ZTsKKwlzdHJ1Y3QgZnNsX3FkbWFfY29tcCAqZnNsX2NvbXA7CisJc3RydWN0IHZpcnRf ZG1hX2Rlc2MgKnZkZXNjOworCXUzMiByZWc7CisKKwlyZWcgPSBxZG1hX3JlYWRsKGZzbF9jaGFu LT5xZG1hLCBibG9jayArIEZTTF9RRE1BX0JDUVNSKGZzbF9xdWV1ZS0+aWQpKTsKKwlpZiAocmVn ICYgKEZTTF9RRE1BX0JDUVNSX1FGIHwgRlNMX1FETUFfQkNRU1JfWE9GRikpCisJCXJldHVybjsK Kwl2ZGVzYyA9IHZjaGFuX25leHRfZGVzYygmZnNsX2NoYW4tPnZjaGFuKTsKKwlpZiAoIXZkZXNj KQorCQlyZXR1cm47CisJbGlzdF9kZWwoJnZkZXNjLT5ub2RlKTsKKwlmc2xfY29tcCA9IHRvX2Zz bF9xZG1hX2NvbXAodmRlc2MpOworCisJbWVtY3B5KGZzbF9xdWV1ZS0+dmlydF9oZWFkKyssIGZz bF9jb21wLT52aXJ0X2FkZHIsCisJCQkJCXNpemVvZihzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0KSk7 CisJaWYgKGZzbF9xdWV1ZS0+dmlydF9oZWFkID09IGZzbF9xdWV1ZS0+Y3EgKyBmc2xfcXVldWUt Pm5fY3EpCisJCWZzbF9xdWV1ZS0+dmlydF9oZWFkID0gZnNsX3F1ZXVlLT5jcTsKKworCWxpc3Rf YWRkX3RhaWwoJmZzbF9jb21wLT5saXN0LCAmZnNsX3F1ZXVlLT5jb21wX3VzZWQpOworCWJhcnJp ZXIoKTsKKwlyZWcgPSBxZG1hX3JlYWRsKGZzbF9jaGFuLT5xZG1hLCBibG9jayArIEZTTF9RRE1B X0JDUU1SKGZzbF9xdWV1ZS0+aWQpKTsKKwlyZWcgfD0gRlNMX1FETUFfQkNRTVJfRUk7CisJcWRt YV93cml0ZWwoZnNsX2NoYW4tPnFkbWEsIHJlZywgYmxvY2sgKyBGU0xfUURNQV9CQ1FNUihmc2xf cXVldWUtPmlkKSk7CisJZnNsX2NoYW4tPnN0YXR1cyA9IERNQV9JTl9QUk9HUkVTUzsKK30KKwor c3RhdGljIGVudW0gZG1hX3N0YXR1cyBmc2xfcWRtYV90eF9zdGF0dXMoc3RydWN0IGRtYV9jaGFu ICpjaGFuLAorCQlkbWFfY29va2llX3QgY29va2llLCBzdHJ1Y3QgZG1hX3R4X3N0YXRlICp0eHN0 YXRlKQoreworCWVudW0gZG1hX3N0YXR1cyByZXQ7CisKKwlyZXQgPSBkbWFfY29va2llX3N0YXR1 cyhjaGFuLCBjb29raWUsIHR4c3RhdGUpOworCWlmIChyZXQgPT0gRE1BX0NPTVBMRVRFIHx8ICF0 eHN0YXRlKQorCQlyZXR1cm4gcmV0OworCisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIHZvaWQg ZnNsX3FkbWFfZnJlZV9kZXNjKHN0cnVjdCB2aXJ0X2RtYV9kZXNjICp2ZGVzYykKK3sKKwlzdHJ1 Y3QgZnNsX3FkbWFfY29tcCAqZnNsX2NvbXA7CisJc3RydWN0IGZzbF9xZG1hX3F1ZXVlICpmc2xf cXVldWU7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKworCWZzbF9jb21wID0gdG9fZnNsX3FkbWFf Y29tcCh2ZGVzYyk7CisJZnNsX3F1ZXVlID0gZnNsX2NvbXAtPnFjaGFuLT5xdWV1ZTsKKworCXNw aW5fbG9ja19pcnFzYXZlKCZmc2xfcXVldWUtPnF1ZXVlX2xvY2ssIGZsYWdzKTsKKwlsaXN0X2Fk ZF90YWlsKCZmc2xfY29tcC0+bGlzdCwgJmZzbF9xdWV1ZS0+Y29tcF9mcmVlKTsKKwlzcGluX3Vu bG9ja19pcnFyZXN0b3JlKCZmc2xfcXVldWUtPnF1ZXVlX2xvY2ssIGZsYWdzKTsKK30KKworc3Rh dGljIHZvaWQgZnNsX3FkbWFfaXNzdWVfcGVuZGluZyhzdHJ1Y3QgZG1hX2NoYW4gKmNoYW4pCit7 CisJc3RydWN0IGZzbF9xZG1hX2NoYW4gKmZzbF9jaGFuID0gdG9fZnNsX3FkbWFfY2hhbihjaGFu KTsKKwlzdHJ1Y3QgZnNsX3FkbWFfcXVldWUgKmZzbF9xdWV1ZSA9IGZzbF9jaGFuLT5xdWV1ZTsK Kwl1bnNpZ25lZCBsb25nIGZsYWdzOworCisJc3Bpbl9sb2NrX2lycXNhdmUoJmZzbF9xdWV1ZS0+ cXVldWVfbG9jaywgZmxhZ3MpOworCXNwaW5fbG9jaygmZnNsX2NoYW4tPnZjaGFuLmxvY2spOwor CWlmICh2Y2hhbl9pc3N1ZV9wZW5kaW5nKCZmc2xfY2hhbi0+dmNoYW4pKQorCQlmc2xfcWRtYV9l bnF1ZXVlX2Rlc2MoZnNsX2NoYW4pOworCXNwaW5fdW5sb2NrKCZmc2xfY2hhbi0+dmNoYW4ubG9j ayk7CisJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmZnNsX3F1ZXVlLT5xdWV1ZV9sb2NrLCBmbGFn cyk7Cit9CisKK3N0YXRpYyBpbnQgZnNsX3FkbWFfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2Rldmlj ZSAqcGRldikKK3sKKwlzdHJ1Y3QgZGV2aWNlX25vZGUgKm5wID0gcGRldi0+ZGV2Lm9mX25vZGU7 CisJc3RydWN0IGZzbF9xZG1hX2VuZ2luZSAqZnNsX3FkbWE7CisJc3RydWN0IGZzbF9xZG1hX2No YW4gKmZzbF9jaGFuOworCXN0cnVjdCByZXNvdXJjZSAqcmVzOworCXVuc2lnbmVkIGludCBsZW4s IGNoYW5zLCBxdWV1ZXM7CisJaW50IHJldCwgaTsKKworCXJldCA9IG9mX3Byb3BlcnR5X3JlYWRf dTMyKG5wLCAiZG1hLWNoYW5uZWxzIiwgJmNoYW5zKTsKKwlpZiAocmV0KSB7CisJCWRldl9lcnIo JnBkZXYtPmRldiwgIkNhbid0IGdldCBkbWEtY2hhbm5lbHMuXG4iKTsKKwkJcmV0dXJuIHJldDsK Kwl9CisKKwlsZW4gPSBzaXplb2YoKmZzbF9xZG1hKSArIHNpemVvZigqZnNsX2NoYW4pICogY2hh bnM7CisJZnNsX3FkbWEgPSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRldiwgbGVuLCBHRlBfS0VSTkVM KTsKKwlpZiAoIWZzbF9xZG1hKQorCQlyZXR1cm4gLUVOT01FTTsKKworCXJldCA9IG9mX3Byb3Bl cnR5X3JlYWRfdTMyKG5wLCAiZnNsLHF1ZXVlcyIsICZxdWV1ZXMpOworCWlmIChyZXQpIHsKKwkJ ZGV2X2VycigmcGRldi0+ZGV2LCAiQ2FuJ3QgZ2V0IHF1ZXVlcy5cbiIpOworCQlyZXR1cm4gcmV0 OworCX0KKworCWZzbF9xZG1hLT5xdWV1ZSA9IGZzbF9xZG1hX2FsbG9jX3F1ZXVlX3Jlc291cmNl cyhwZGV2LCBxdWV1ZXMpOworCWlmICghZnNsX3FkbWEtPnF1ZXVlKQorCQlyZXR1cm4gLUVOT01F TTsKKworCWZzbF9xZG1hLT5zdGF0dXMgPSBmc2xfcWRtYV9wcmVwX3N0YXR1c19xdWV1ZShwZGV2 KTsKKwlpZiAoIWZzbF9xZG1hLT5zdGF0dXMpCisJCXJldHVybiAtRU5PTUVNOworCisJZnNsX3Fk bWEtPm5fY2hhbnMgPSBjaGFuczsKKwlmc2xfcWRtYS0+bl9xdWV1ZXMgPSBxdWV1ZXM7CisJbXV0 ZXhfaW5pdCgmZnNsX3FkbWEtPmZzbF9xZG1hX211dGV4KTsKKworCXJlcyA9IHBsYXRmb3JtX2dl dF9yZXNvdXJjZShwZGV2LCBJT1JFU09VUkNFX01FTSwgMCk7CisJZnNsX3FkbWEtPmN0cmxfYmFz ZSA9IGRldm1faW9yZW1hcF9yZXNvdXJjZSgmcGRldi0+ZGV2LCByZXMpOworCWlmIChJU19FUlIo ZnNsX3FkbWEtPmN0cmxfYmFzZSkpCisJCXJldHVybiBQVFJfRVJSKGZzbF9xZG1hLT5jdHJsX2Jh c2UpOworCisJcmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlKHBkZXYsIElPUkVTT1VSQ0VfTUVN LCAxKTsKKwlmc2xfcWRtYS0+c3RhdHVzX2Jhc2UgPSBkZXZtX2lvcmVtYXBfcmVzb3VyY2UoJnBk ZXYtPmRldiwgcmVzKTsKKwlpZiAoSVNfRVJSKGZzbF9xZG1hLT5zdGF0dXNfYmFzZSkpCisJCXJl dHVybiBQVFJfRVJSKGZzbF9xZG1hLT5zdGF0dXNfYmFzZSk7CisKKwlyZXMgPSBwbGF0Zm9ybV9n ZXRfcmVzb3VyY2UocGRldiwgSU9SRVNPVVJDRV9NRU0sIDIpOworCWZzbF9xZG1hLT5ibG9ja19i YXNlID0gZGV2bV9pb3JlbWFwX3Jlc291cmNlKCZwZGV2LT5kZXYsIHJlcyk7CisJaWYgKElTX0VS Uihmc2xfcWRtYS0+YmxvY2tfYmFzZSkpCisJCXJldHVybiBQVFJfRVJSKGZzbF9xZG1hLT5ibG9j a19iYXNlKTsKKworCXJldCA9IGZzbF9xZG1hX2lycV9pbml0KHBkZXYsIGZzbF9xZG1hKTsKKwlp ZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJZnNsX3FkbWEtPmZlYXR1cmUgPSBvZl9wcm9wZXJ0 eV9yZWFkX2Jvb2wobnAsICJiaWctZW5kaWFuIik7CisJSU5JVF9MSVNUX0hFQUQoJmZzbF9xZG1h LT5kbWFfZGV2LmNoYW5uZWxzKTsKKwlmb3IgKGkgPSAwOyBpIDwgZnNsX3FkbWEtPm5fY2hhbnM7 IGkrKykgeworCQlzdHJ1Y3QgZnNsX3FkbWFfY2hhbiAqZnNsX2NoYW4gPSAmZnNsX3FkbWEtPmNo YW5zW2ldOworCisJCWZzbF9jaGFuLT5xZG1hID0gZnNsX3FkbWE7CisJCWZzbF9jaGFuLT5xdWV1 ZSA9IGZzbF9xZG1hLT5xdWV1ZSArIGkgJSBmc2xfcWRtYS0+bl9xdWV1ZXM7CisJCWZzbF9jaGFu LT52Y2hhbi5kZXNjX2ZyZWUgPSBmc2xfcWRtYV9mcmVlX2Rlc2M7CisJCUlOSVRfTElTVF9IRUFE KCZmc2xfY2hhbi0+cWNvbXApOworCQl2Y2hhbl9pbml0KCZmc2xfY2hhbi0+dmNoYW4sICZmc2xf cWRtYS0+ZG1hX2Rldik7CisJfQorCWZvciAoaSA9IDA7IGkgPCBmc2xfcWRtYS0+bl9xdWV1ZXM7 IGkrKykKKwkJZnNsX3FkbWFfcHJlX3JlcXVlc3RfZW5xdWV1ZV9kZXNjKGZzbF9xZG1hLT5xdWV1 ZSArIGkpOworCisJZG1hX2NhcF9zZXQoRE1BX01FTUNQWSwgZnNsX3FkbWEtPmRtYV9kZXYuY2Fw X21hc2spOworCisJZnNsX3FkbWEtPmRtYV9kZXYuZGV2ID0gJnBkZXYtPmRldjsKKwlmc2xfcWRt YS0+ZG1hX2Rldi5kZXZpY2VfZnJlZV9jaGFuX3Jlc291cmNlcworCQk9IGZzbF9xZG1hX2ZyZWVf Y2hhbl9yZXNvdXJjZXM7CisJZnNsX3FkbWEtPmRtYV9kZXYuZGV2aWNlX3R4X3N0YXR1cyA9IGZz bF9xZG1hX3R4X3N0YXR1czsKKwlmc2xfcWRtYS0+ZG1hX2Rldi5kZXZpY2VfcHJlcF9kbWFfbWVt Y3B5ID0gZnNsX3FkbWFfcHJlcF9tZW1jcHk7CisJZnNsX3FkbWEtPmRtYV9kZXYuZGV2aWNlX2lz c3VlX3BlbmRpbmcgPSBmc2xfcWRtYV9pc3N1ZV9wZW5kaW5nOworCisJZG1hX3NldF9tYXNrKCZw ZGV2LT5kZXYsIERNQV9CSVRfTUFTSyg0MCkpOworCisJcGxhdGZvcm1fc2V0X2RydmRhdGEocGRl diwgZnNsX3FkbWEpOworCisJcmV0ID0gZG1hX2FzeW5jX2RldmljZV9yZWdpc3RlcigmZnNsX3Fk bWEtPmRtYV9kZXYpOworCWlmIChyZXQpIHsKKwkJZGV2X2VycigmcGRldi0+ZGV2LCAiQ2FuJ3Qg cmVnaXN0ZXIgTlhQIExheWVyc2NhcGUgcURNQSBlbmdpbmUuXG4iKTsKKwkJcmV0dXJuIHJldDsK Kwl9CisKKwlyZXQgPSBmc2xfcWRtYV9yZWdfaW5pdChmc2xfcWRtYSk7CisJaWYgKHJldCkgewor CQlkZXZfZXJyKCZwZGV2LT5kZXYsICJDYW4ndCBJbml0aWFsaXplIHRoZSBxRE1BIGVuZ2luZS5c biIpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldHVybiAwOworfQorCitzdGF0aWMgdm9pZCBm c2xfcWRtYV9jbGVhbnVwX3ZjaGFuKHN0cnVjdCBkbWFfZGV2aWNlICpkbWFkZXYpCit7CisJc3Ry dWN0IGZzbF9xZG1hX2NoYW4gKmNoYW4sICpfY2hhbjsKKworCWxpc3RfZm9yX2VhY2hfZW50cnlf c2FmZShjaGFuLCBfY2hhbiwKKwkJCQkmZG1hZGV2LT5jaGFubmVscywgdmNoYW4uY2hhbi5kZXZp Y2Vfbm9kZSkgeworCQlsaXN0X2RlbCgmY2hhbi0+dmNoYW4uY2hhbi5kZXZpY2Vfbm9kZSk7CisJ CXRhc2tsZXRfa2lsbCgmY2hhbi0+dmNoYW4udGFzayk7CisJfQorfQorCitzdGF0aWMgaW50IGZz bF9xZG1hX3JlbW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQoreworCXN0cnVjdCBk ZXZpY2Vfbm9kZSAqbnAgPSBwZGV2LT5kZXYub2Zfbm9kZTsKKwlzdHJ1Y3QgZnNsX3FkbWFfZW5n aW5lICpmc2xfcWRtYSA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOworCXN0cnVjdCBmc2xf cWRtYV9xdWV1ZSAqcXVldWVfdGVtcDsKKwlzdHJ1Y3QgZnNsX3FkbWFfcXVldWUgKnN0YXR1cyA9 IGZzbF9xZG1hLT5zdGF0dXM7CisJc3RydWN0IGZzbF9xZG1hX2NvbXAgKmNvbXBfdGVtcCwgKl9j b21wX3RlbXA7CisJaW50IGk7CisKKwlmc2xfcWRtYV9pcnFfZXhpdChwZGV2LCBmc2xfcWRtYSk7 CisJZnNsX3FkbWFfY2xlYW51cF92Y2hhbigmZnNsX3FkbWEtPmRtYV9kZXYpOworCW9mX2RtYV9j b250cm9sbGVyX2ZyZWUobnApOworCWRtYV9hc3luY19kZXZpY2VfdW5yZWdpc3RlcigmZnNsX3Fk bWEtPmRtYV9kZXYpOworCisJLyogRnJlZSBkZXNjcmlwdG9yIGFyZWFzICovCisJZm9yIChpID0g MDsgaSA8IGZzbF9xZG1hLT5uX3F1ZXVlczsgaSsrKSB7CisJCXF1ZXVlX3RlbXAgPSBmc2xfcWRt YS0+cXVldWUgKyBpOworCQlsaXN0X2Zvcl9lYWNoX2VudHJ5X3NhZmUoY29tcF90ZW1wLCBfY29t cF90ZW1wLAorCQkJCQkmcXVldWVfdGVtcC0+Y29tcF91c2VkLAlsaXN0KSB7CisJCQlkbWFfcG9v bF9mcmVlKHF1ZXVlX3RlbXAtPmNvbXBfcG9vbCwKKwkJCQkJY29tcF90ZW1wLT52aXJ0X2FkZHIs CisJCQkJCWNvbXBfdGVtcC0+YnVzX2FkZHIpOworCQkJbGlzdF9kZWwoJmNvbXBfdGVtcC0+bGlz dCk7CisJCQlrZnJlZShjb21wX3RlbXApOworCQl9CisJCWxpc3RfZm9yX2VhY2hfZW50cnlfc2Fm ZShjb21wX3RlbXAsIF9jb21wX3RlbXAsCisJCQkJCSZxdWV1ZV90ZW1wLT5jb21wX2ZyZWUsIGxp c3QpIHsKKwkJCWRtYV9wb29sX2ZyZWUocXVldWVfdGVtcC0+Y29tcF9wb29sLAorCQkJCQljb21w X3RlbXAtPnZpcnRfYWRkciwKKwkJCQkJY29tcF90ZW1wLT5idXNfYWRkcik7CisJCQlsaXN0X2Rl bCgmY29tcF90ZW1wLT5saXN0KTsKKwkJCWtmcmVlKGNvbXBfdGVtcCk7CisJCX0KKwkJZG1hX2Zy ZWVfY29oZXJlbnQoJnBkZXYtPmRldiwgc2l6ZW9mKHN0cnVjdCBmc2xfcWRtYV9mb3JtYXQpICoK KwkJCQkJcXVldWVfdGVtcC0+bl9jcSwgcXVldWVfdGVtcC0+Y3EsCisJCQkJCXF1ZXVlX3RlbXAt PmJ1c19hZGRyKTsKKwkJZG1hX3Bvb2xfZGVzdHJveShxdWV1ZV90ZW1wLT5jb21wX3Bvb2wpOwor CX0KKworCWRtYV9mcmVlX2NvaGVyZW50KCZwZGV2LT5kZXYsIHNpemVvZihzdHJ1Y3QgZnNsX3Fk bWFfZm9ybWF0KSAqCisJCQkJc3RhdHVzLT5uX2NxLCBzdGF0dXMtPmNxLCBzdGF0dXMtPmJ1c19h ZGRyKTsKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQg ZnNsX3FkbWFfZHRfaWRzW10gPSB7CisJeyAuY29tcGF0aWJsZSA9ICJmc2wsbHMxMDIxYS1xZG1h IiwgfSwKKwl7IC8qIHNlbnRpbmVsICovIH0KK307CitNT0RVTEVfREVWSUNFX1RBQkxFKG9mLCBm c2xfcWRtYV9kdF9pZHMpOworCitzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBmc2xfcWRt YV9kcml2ZXIgPSB7CisJLmRyaXZlcgkJPSB7CisJCS5uYW1lCT0gImZzbC1xZG1hIiwKKwkJLm9m X21hdGNoX3RhYmxlID0gZnNsX3FkbWFfZHRfaWRzLAorCX0sCisJLnByb2JlICAgICAgICAgID0g ZnNsX3FkbWFfcHJvYmUsCisJLnJlbW92ZQkJPSBmc2xfcWRtYV9yZW1vdmUsCit9OworCittb2R1 bGVfcGxhdGZvcm1fZHJpdmVyKGZzbF9xZG1hX2RyaXZlcik7CisKK01PRFVMRV9BTElBUygicGxh dGZvcm06ZnNsLXFkbWEiKTsKK01PRFVMRV9ERVNDUklQVElPTigiTlhQIExheWVyc2NhcGUgcURN QSBlbmdpbmUgZHJpdmVyIik7CitNT0RVTEVfTElDRU5TRSgiR1BMIHYyIik7Cg== From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Wen He Subject: [v5 2/6] dmaengine: fsl-qdma: Add qDMA controller driver for Layerscape SoCs Date: Fri, 25 May 2018 19:19:16 +0800 Message-ID: <20180525111920.24498-2-wen.he_1@nxp.com> In-Reply-To: <20180525111920.24498-1-wen.he_1@nxp.com> References: <20180525111920.24498-1-wen.he_1@nxp.com> MIME-Version: 1.0 Content-Type: text/plain To: vkoul@kernel.org, dmaengine@vger.kernel.org Cc: robh+dt@kernel.org, devicetree@vger.kernel.org, leoyang.li@nxp.com, jiafei.pan@nxp.com, jiaheng.fan@nxp.com, wen.he_1@nxp.com List-ID: NXP Queue DMA controller(qDMA) on Layerscape SoCs supports channel virtuallization by allowing DMA jobs to be enqueued into different command queues. Note that this module depends on NXP DPAA. Signed-off-by: Wen He Signed-off-by: Jiaheng Fan --- change in v5: - Fixed the issues includes: * add error handler which every function * replace word to bit definition * move global variable to struct definition * add some comments to context change in v4: - Fixed the issues that Vinod point out in the mail list. change in v3: - Add 'depends on ARM || ARM64' in file 'drivers/dma/Kconfig' change in v2: - Replace GPL V2 License details by SPDX tags - Replace Freescale by NXP - Reduce and optimize header file references - Replace big_endian by feature in struct fsl_qdma_engine - Replace struct fsl_qdma_format by struct fsl_qdma_ccdf and struct fsl_qdma_csgf - Remove empty line - Replace 'if..else' by macro 'FSL_QDMA_IN/OUT' in function qdma_readl() and qdma_writel() - Remove function fsl_qdma_alloc_chan_resources() - Replace 'prei' by 'pre' - Replace '-1' by '-ENOMEM' in function fsl_qdma_pre_request_enqueue_desc() - Fix dma pool allocation need to rolled back in function fsl_qdma_request_enqueue_desc() - Replace function of_property_read_u32_array() by device_property_read_u32_array() - Add functions fsl_qdma_cleanup_vchan() and fsl_qdma_irq_exit() to ensure irq and tasklets stopped - Replace dts node element 'channels' by 'dma-channels' - Replace function platform_driver_register() by module_platform_driver() drivers/dma/Kconfig | 13 + drivers/dma/Makefile | 1 + drivers/dma/fsl-qdma.c | 1101 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1115 insertions(+), 0 deletions(-) create mode 100644 drivers/dma/fsl-qdma.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 6d61cd0..99aff33 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -225,6 +225,19 @@ config FSL_EDMA multiplexing capability for DMA request sources(slot). This module can be found on Freescale Vybrid and LS-1 SoCs. +config FSL_QDMA + tristate "NXP Layerscape qDMA engine support" + depends on ARM || ARM64 + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + select DMA_ENGINE_RAID + select ASYNC_TX_ENABLE_CHANNEL_SWITCH + help + Support the NXP Layerscape qDMA engine with command queue and legacy mode. + Channel virtualization is supported through enqueuing of DMA jobs to, + or dequeuing DMA jobs from, different work queues. + This module can be found on NXP Layerscape SoCs. + config FSL_RAID tristate "Freescale RAID engine Support" depends on FSL_SOC && !ASYNC_TX_ENABLE_CHANNEL_SWITCH diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 0f62a4d..93db0fc 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_DW_DMAC_CORE) += dw/ obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o obj-$(CONFIG_FSL_DMA) += fsldma.o obj-$(CONFIG_FSL_EDMA) += fsl-edma.o +obj-$(CONFIG_FSL_QDMA) += fsl-qdma.o obj-$(CONFIG_FSL_RAID) += fsl_raid.o obj-$(CONFIG_HSU_DMA) += hsu/ obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o diff --git a/drivers/dma/fsl-qdma.c b/drivers/dma/fsl-qdma.c new file mode 100644 index 0000000..81df812 --- /dev/null +++ b/drivers/dma/fsl-qdma.c @@ -0,0 +1,1101 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright 2018 NXP + +/* + * Driver for NXP Layerscape Queue Direct Memory Access Controller + * + * Author: + * Wen He + * Jiaheng Fan + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "virt-dma.h" +#include "fsldma.h" + +/* Register related definition */ +#define FSL_QDMA_DMR 0x0 +#define FSL_QDMA_DSR 0x4 +#define FSL_QDMA_DEIER 0xe00 +#define FSL_QDMA_DEDR 0xe04 +#define FSL_QDMA_DECFDW0R 0xe10 +#define FSL_QDMA_DECFDW1R 0xe14 +#define FSL_QDMA_DECFDW2R 0xe18 +#define FSL_QDMA_DECFDW3R 0xe1c +#define FSL_QDMA_DECFQIDR 0xe30 +#define FSL_QDMA_DECBR 0xe34 + +#define FSL_QDMA_BCQMR(x) (0xc0 + 0x100 * (x)) +#define FSL_QDMA_BCQSR(x) (0xc4 + 0x100 * (x)) +#define FSL_QDMA_BCQEDPA_SADDR(x) (0xc8 + 0x100 * (x)) +#define FSL_QDMA_BCQDPA_SADDR(x) (0xcc + 0x100 * (x)) +#define FSL_QDMA_BCQEEPA_SADDR(x) (0xd0 + 0x100 * (x)) +#define FSL_QDMA_BCQEPA_SADDR(x) (0xd4 + 0x100 * (x)) +#define FSL_QDMA_BCQIER(x) (0xe0 + 0x100 * (x)) +#define FSL_QDMA_BCQIDR(x) (0xe4 + 0x100 * (x)) + +#define FSL_QDMA_SQDPAR 0x80c +#define FSL_QDMA_SQEPAR 0x814 +#define FSL_QDMA_BSQMR 0x800 +#define FSL_QDMA_BSQSR 0x804 +#define FSL_QDMA_BSQICR 0x828 +#define FSL_QDMA_CQMR 0xa00 +#define FSL_QDMA_CQDSCR1 0xa08 +#define FSL_QDMA_CQDSCR2 0xa0c +#define FSL_QDMA_CQIER 0xa10 +#define FSL_QDMA_CQEDR 0xa14 +#define FSL_QDMA_SQCCMR 0xa20 + +/* Registers for bit and genmask */ +#define FSL_QDMA_CQIDR_SQT BIT(15) +#define QDMA_CCDF_FOTMAT BIT(29) +#define QDMA_CCDF_SER BIT(30) +#define QDMA_SG_FIN BIT(30) +#define QDMA_SG_EXT BIT(31) +#define QDMA_SG_LEN_MASK GENMASK(29, 0) +#define QDMA_CCDF_MASK GENMASK(28, 20) + +#define FSL_QDMA_BCQIER_CQTIE BIT(15) +#define FSL_QDMA_BCQIER_CQPEIE BIT(23) +#define FSL_QDMA_BSQICR_ICEN BIT(31) + +#define FSL_QDMA_BSQICR_ICST(x) ((x) << 16) +#define FSL_QDMA_CQIER_MEIE BIT(31) +#define FSL_QDMA_CQIER_TEIE BIT(0) +#define FSL_QDMA_SQCCMR_ENTER_WM BIT(21) + +#define FSL_QDMA_BCQMR_EN BIT(31) +#define FSL_QDMA_BCQMR_EI BIT(30) +#define FSL_QDMA_BCQMR_CD_THLD(x) ((x) << 20) +#define FSL_QDMA_BCQMR_CQ_SIZE(x) ((x) << 16) + +#define FSL_QDMA_BCQSR_QF BIT(16) +#define FSL_QDMA_BCQSR_XOFF BIT(0) + +#define FSL_QDMA_BSQMR_EN BIT(31) +#define FSL_QDMA_BSQMR_DI BIT(30) +#define FSL_QDMA_BSQMR_CQ_SIZE(x) ((x) << 16) + +#define FSL_QDMA_BSQSR_QE BIT(17) + +#define FSL_QDMA_DMR_DQD BIT(30) +#define FSL_QDMA_DSR_DB BIT(31) + +/* Size related definition */ +#define FSL_QDMA_QUEUE_MAX 8 +#define FSL_QDMA_BASE_BUFFER_SIZE 96 +#define FSL_QDMA_CIRCULAR_DESC_SIZE_MIN 64 +#define FSL_QDMA_CIRCULAR_DESC_SIZE_MAX 16384 +#define FSL_QDMA_QUEUE_NUM_MAX 8 + +/* Field definition for CMD */ +#define FSL_QDMA_CMD_RWTTYPE 0x4 +#define FSL_QDMA_CMD_LWC 0x2 +#define FSL_QDMA_CMD_RWTTYPE_OFFSET 28 +#define FSL_QDMA_CMD_NS_OFFSET 27 +#define FSL_QDMA_CMD_DQOS_OFFSET 24 +#define FSL_QDMA_CMD_WTHROTL_OFFSET 20 +#define FSL_QDMA_CMD_DSEN_OFFSET 19 +#define FSL_QDMA_CMD_LWC_OFFSET 16 + +#define FSL_QDMA_E_SG_TABLE 1 +#define FSL_QDMA_E_DATA_BUFFER 0 +#define FSL_QDMA_F_LAST_ENTRY 1 + +/* Field definition for Descriptor offset */ +#define QDMA_CCDF_STATUS 20 +#define QDMA_CCDF_OFFSET 20 + +/** + * struct fsl_qdma_format - This is the struct holding describing compound + * descriptor format with qDMA. + * @status: This field which describes command status and + * enqueue status notification. + * @cfg: This field which describes frame offset and frame + * format. + * @addr_lo: This field which indicating the start of the buffer + * holding the compound descriptor of the lower 32-bits + * address in memory 40-bit address. + * @addr_hi: This field's the same as above field, but point high + * 8-bits in memory 40-bit address. + * @__reserved1: Reserved field. + * @cfg8b_w1: This field which describes compound descriptor + * command queue origin produced by qDMA and dynamic + * debug field. + * @data Pointer to the memory 40-bit address, describes DMA + * source informaion and DMA destination information. + */ +struct fsl_qdma_format { + __le32 status; + __le32 cfg; + union { + struct { + __le32 addr_lo; + u8 addr_hi; + u8 __reserved1[2]; + u8 cfg8b_w1; + } __packed; + __le64 data; + }; +} __packed; + +/* qDMA status notification pre information */ +struct fsl_pre_status { + u64 queue; + u64 addr; +}; + +struct fsl_qdma_chan { + struct virt_dma_chan vchan; + struct virt_dma_desc vdesc; + enum dma_status status; + u32 slave_id; + struct fsl_qdma_engine *qdma; + struct fsl_qdma_queue *queue; + struct list_head qcomp; +}; + +struct fsl_qdma_queue { + struct fsl_qdma_format *virt_head; + struct fsl_qdma_format *virt_tail; + struct list_head comp_used; + struct list_head comp_free; + struct dma_pool *comp_pool; + spinlock_t queue_lock; + dma_addr_t bus_addr; + u32 n_cq; + u32 id; + struct fsl_qdma_format *cq; +}; + +struct fsl_qdma_comp { + dma_addr_t bus_addr; + struct fsl_qdma_format *virt_addr; + struct fsl_qdma_chan *qchan; + struct virt_dma_desc vdesc; + struct list_head list; +}; + +struct fsl_qdma_engine { + struct dma_device dma_dev; + void __iomem *ctrl_base; + void __iomem *status_base; + void __iomem *block_base; + u32 n_chans; + u32 n_queues; + struct mutex fsl_qdma_mutex; + int error_irq; + int queue_irq; + bool feature; + struct fsl_qdma_queue *queue; + struct fsl_qdma_queue *status; + struct fsl_qdma_chan chans[]; + +}; + +static inline u64 +qdma_ccdf_addr_get64(const struct fsl_qdma_format *ccdf) +{ + return le64_to_cpu(ccdf->data) & (U64_MAX >> 24); +} + +static inline void +qdma_desc_addr_set64(struct fsl_qdma_format *ccdf, u64 addr) +{ + ccdf->addr_hi = upper_32_bits(addr); + ccdf->addr_lo = cpu_to_le32(lower_32_bits(addr)); +} + +static inline u64 +qdma_ccdf_get_queue(const struct fsl_qdma_format *ccdf) +{ + return ccdf->cfg8b_w1 & U8_MAX; +} + +static inline int +qdma_ccdf_get_offset(const struct fsl_qdma_format *ccdf) +{ + return (le32_to_cpu(ccdf->cfg) & QDMA_CCDF_MASK) >> QDMA_CCDF_OFFSET; +} + +static inline void +qdma_ccdf_set_format(struct fsl_qdma_format *ccdf, int offset) +{ + ccdf->cfg = cpu_to_le32(QDMA_CCDF_FOTMAT | offset); +} + +static inline int +qdma_ccdf_get_status(const struct fsl_qdma_format *ccdf) +{ + return (le32_to_cpu(ccdf->status) & QDMA_CCDF_MASK) >> QDMA_CCDF_STATUS; +} + +static inline void +qdma_ccdf_set_ser(struct fsl_qdma_format *ccdf, int status) +{ + ccdf->status = cpu_to_le32(QDMA_CCDF_SER | status); +} + +static inline void qdma_csgf_set_len(struct fsl_qdma_format *csgf, int len) +{ + csgf->cfg = cpu_to_le32(len & QDMA_SG_LEN_MASK); +} + +static inline void qdma_csgf_set_f(struct fsl_qdma_format *csgf, int len) +{ + csgf->cfg = cpu_to_le32(QDMA_SG_FIN | (len & QDMA_SG_LEN_MASK)); +} + +static inline void qdma_csgf_set_e(struct fsl_qdma_format *csgf, int len) +{ + csgf->cfg = cpu_to_le32(QDMA_SG_EXT | (len & QDMA_SG_LEN_MASK)); +} + +static u32 qdma_readl(struct fsl_qdma_engine *qdma, void __iomem *addr) +{ + return FSL_DMA_IN(qdma, addr, 32); +} + +static void qdma_writel(struct fsl_qdma_engine *qdma, u32 val, + void __iomem *addr) +{ + FSL_DMA_OUT(qdma, addr, val, 32); +} + +static struct fsl_qdma_chan *to_fsl_qdma_chan(struct dma_chan *chan) +{ + return container_of(chan, struct fsl_qdma_chan, vchan.chan); +} + +static struct fsl_qdma_comp *to_fsl_qdma_comp(struct virt_dma_desc *vd) +{ + return container_of(vd, struct fsl_qdma_comp, vdesc); +} + +static void fsl_qdma_free_chan_resources(struct dma_chan *chan) +{ + struct fsl_qdma_chan *fsl_chan = to_fsl_qdma_chan(chan); + unsigned long flags; + LIST_HEAD(head); + + spin_lock_irqsave(&fsl_chan->vchan.lock, flags); + vchan_get_all_descriptors(&fsl_chan->vchan, &head); + spin_unlock_irqrestore(&fsl_chan->vchan.lock, flags); + + vchan_dma_desc_free_list(&fsl_chan->vchan, &head); +} + +static void fsl_qdma_comp_fill_memcpy(struct fsl_qdma_comp *fsl_comp, + dma_addr_t dst, dma_addr_t src, u32 len) +{ + struct fsl_qdma_format *ccdf, *csgf_desc, *csgf_src, *csgf_dest; + struct fsl_qdma_format *sdf, *ddf; + + ccdf = fsl_comp->virt_addr; + csgf_desc = fsl_comp->virt_addr + 1; + csgf_src = fsl_comp->virt_addr + 2; + csgf_dest = fsl_comp->virt_addr + 3; + sdf = fsl_comp->virt_addr + 4; + ddf = fsl_comp->virt_addr + 5; + + memset(fsl_comp->virt_addr, 0, FSL_QDMA_BASE_BUFFER_SIZE); + /* Head Command Descriptor(Frame Descriptor) */ + qdma_desc_addr_set64(ccdf, fsl_comp->bus_addr + 16); + qdma_ccdf_set_format(ccdf, qdma_ccdf_get_offset(ccdf)); + qdma_ccdf_set_ser(ccdf, qdma_ccdf_get_status(ccdf)); + + /* Status notification is enqueued to status queue. */ + /* Compound Command Descriptor(Frame List Table) */ + qdma_desc_addr_set64(csgf_desc, fsl_comp->bus_addr + 64); + /* It must be 32 as Compound S/G Descriptor */ + qdma_csgf_set_len(csgf_desc, 32); + qdma_desc_addr_set64(csgf_src, src); + qdma_csgf_set_len(csgf_src, len); + qdma_desc_addr_set64(csgf_dest, dst); + qdma_csgf_set_len(csgf_dest, len); + /* This entry is the last entry. */ + qdma_csgf_set_f(csgf_dest, len); + /* Descriptor Buffer */ + sdf->data = cpu_to_le64( + FSL_QDMA_CMD_RWTTYPE << FSL_QDMA_CMD_RWTTYPE_OFFSET); + ddf->data = cpu_to_le64( + FSL_QDMA_CMD_RWTTYPE << FSL_QDMA_CMD_RWTTYPE_OFFSET); + ddf->data |= cpu_to_le64( + FSL_QDMA_CMD_LWC << FSL_QDMA_CMD_LWC_OFFSET); +} + +/* + * Pre-request full command descriptor for enqueue. + */ +static int fsl_qdma_pre_request_enqueue_desc(struct fsl_qdma_queue *queue) +{ + struct fsl_qdma_comp *comp_temp, *_comp_temp; + int i; + + for (i = 0; i < queue->n_cq; i++) { + comp_temp = kzalloc(sizeof(*comp_temp), GFP_KERNEL); + if (!comp_temp) + goto err; + + comp_temp->virt_addr = dma_pool_alloc(queue->comp_pool, + GFP_KERNEL, + &comp_temp->bus_addr); + if (!comp_temp->virt_addr) + goto err; + + list_add_tail(&comp_temp->list, &queue->comp_free); + } + return 0; + +err: + if (i == 0 && comp_temp) { + kfree(comp_temp); + return -ENOMEM; + } + + while (--i >= 1) { + list_for_each_entry_safe(comp_temp, _comp_temp, + &queue->comp_free, list) { + dma_pool_free(queue->comp_pool, + comp_temp->virt_addr, + comp_temp->bus_addr); + list_del(&comp_temp->list); + kfree(comp_temp); + } + } + return -ENOMEM; +} + +/* + * Request a command descriptor for enqueue. + */ +static struct fsl_qdma_comp *fsl_qdma_request_enqueue_desc( + struct fsl_qdma_chan *fsl_chan, + unsigned int dst_nents, + unsigned int src_nents) +{ + struct fsl_qdma_comp *comp_temp; + struct fsl_qdma_queue *queue = fsl_chan->queue; + unsigned long flags; + + spin_lock_irqsave(&queue->queue_lock, flags); + if (list_empty(&queue->comp_free)) { + spin_unlock_irqrestore(&queue->queue_lock, flags); + comp_temp = kzalloc(sizeof(*comp_temp), GFP_KERNEL); + if (!comp_temp) + return NULL; + + comp_temp->virt_addr = dma_pool_alloc(queue->comp_pool, + GFP_KERNEL, + &comp_temp->bus_addr); + if (!comp_temp->virt_addr) { + kfree(comp_temp); + return NULL; + } + + } else { + comp_temp = list_first_entry(&queue->comp_free, + struct fsl_qdma_comp, + list); + list_del(&comp_temp->list); + spin_unlock_irqrestore(&queue->queue_lock, flags); + } + + comp_temp->qchan = fsl_chan; + + return comp_temp; +} + +static struct fsl_qdma_queue *fsl_qdma_alloc_queue_resources( + struct platform_device *pdev, + unsigned int queue_num) +{ + struct fsl_qdma_queue *queue_head, *queue_temp; + int ret, len, i; + unsigned int queue_size[FSL_QDMA_QUEUE_MAX]; + + if (queue_num > FSL_QDMA_QUEUE_MAX) + queue_num = FSL_QDMA_QUEUE_MAX; + len = sizeof(*queue_head) * queue_num; + queue_head = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); + if (!queue_head) + return NULL; + + ret = device_property_read_u32_array(&pdev->dev, "queue-sizes", + queue_size, queue_num); + if (ret) { + dev_err(&pdev->dev, "Can't get queue-sizes.\n"); + return NULL; + } + + for (i = 0; i < queue_num; i++) { + if (queue_size[i] > FSL_QDMA_CIRCULAR_DESC_SIZE_MAX + || queue_size[i] < FSL_QDMA_CIRCULAR_DESC_SIZE_MIN) { + dev_err(&pdev->dev, "Get wrong queue-sizes.\n"); + return NULL; + } + queue_temp = queue_head + i; + queue_temp->cq = dma_alloc_coherent(&pdev->dev, + sizeof(struct fsl_qdma_format) * + queue_size[i], + &queue_temp->bus_addr, + GFP_KERNEL); + if (!queue_temp->cq) { + devm_kfree(&pdev->dev, queue_head); + return NULL; + } + queue_temp->n_cq = queue_size[i]; + queue_temp->id = i; + queue_temp->virt_head = queue_temp->cq; + queue_temp->virt_tail = queue_temp->cq; + + /* + * Create a comp dma pool that size + * is 'FSL_QDMA_BASE_BUFFER_SIZE'. + * The dma pool for queue command buffer. + */ + queue_temp->comp_pool = dma_pool_create("comp_pool", + &pdev->dev, + FSL_QDMA_BASE_BUFFER_SIZE, + 16, 0); + if (!queue_temp->comp_pool) + goto err; + + /* + * List for queue command buffer + */ + INIT_LIST_HEAD(&queue_temp->comp_used); + INIT_LIST_HEAD(&queue_temp->comp_free); + spin_lock_init(&queue_temp->queue_lock); + } + + return queue_head; + +err: + if (i == 0 && queue_temp->comp_pool) + dma_pool_destroy(queue_temp->comp_pool); + while (--i >= 1) { + queue_temp = queue_head + i; + if (i == 1 && unlikely(queue_temp->comp_pool)) + dma_pool_destroy(queue_temp->comp_pool); + } + + dev_err(&pdev->dev, + "unable to allocate channel %d descriptor pool\n", + queue_temp->id); + + while (--i >= 0) { + queue_temp = queue_head + i; + dma_free_coherent(&pdev->dev, + sizeof(struct fsl_qdma_format) * + queue_size[i], + queue_temp->cq, + queue_temp->bus_addr); + } + devm_kfree(&pdev->dev, queue_head); + return NULL; +} + +static struct fsl_qdma_queue *fsl_qdma_prep_status_queue( + struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct fsl_qdma_queue *status_head; + unsigned int status_size; + int ret; + + ret = of_property_read_u32(np, "status-sizes", &status_size); + if (ret) { + dev_err(&pdev->dev, "Can't get status-sizes.\n"); + return NULL; + } + if (status_size > FSL_QDMA_CIRCULAR_DESC_SIZE_MAX + || status_size < FSL_QDMA_CIRCULAR_DESC_SIZE_MIN) { + dev_err(&pdev->dev, "Get wrong status_size.\n"); + return NULL; + } + status_head = devm_kzalloc(&pdev->dev, sizeof(*status_head), + GFP_KERNEL); + if (!status_head) + return NULL; + + /* + * Buffer for queue command + */ + status_head->cq = dma_alloc_coherent(&pdev->dev, + sizeof(struct fsl_qdma_format) * + status_size, + &status_head->bus_addr, + GFP_KERNEL); + if (!status_head->cq) { + devm_kfree(&pdev->dev, status_head); + return NULL; + } + + status_head->n_cq = status_size; + status_head->virt_head = status_head->cq; + status_head->virt_tail = status_head->cq; + status_head->comp_pool = NULL; + + return status_head; +} + +static int fsl_qdma_halt(struct fsl_qdma_engine *fsl_qdma) +{ + void __iomem *ctrl = fsl_qdma->ctrl_base; + void __iomem *block = fsl_qdma->block_base; + int i, count = 5; + u32 reg; + + /* Disable the command queue and wait for idle state. */ + reg = qdma_readl(fsl_qdma, ctrl + FSL_QDMA_DMR); + reg |= FSL_QDMA_DMR_DQD; + qdma_writel(fsl_qdma, reg, ctrl + FSL_QDMA_DMR); + for (i = 0; i < FSL_QDMA_QUEUE_NUM_MAX; i++) + qdma_writel(fsl_qdma, 0, block + FSL_QDMA_BCQMR(i)); + + while (1) { + reg = qdma_readl(fsl_qdma, ctrl + FSL_QDMA_DSR); + if (!(reg & FSL_QDMA_DSR_DB)) + break; + if (count-- < 0) + return -EBUSY; + udelay(100); + } + + /* Disable status queue. */ + qdma_writel(fsl_qdma, 0, block + FSL_QDMA_BSQMR); + + /* + * Clear the command queue interrupt detect register for all queues. + */ + qdma_writel(fsl_qdma, 0xffffffff, block + FSL_QDMA_BCQIDR(0)); + + return 0; +} + +static int fsl_qdma_queue_transfer_complete(struct fsl_qdma_engine *fsl_qdma) +{ + struct fsl_qdma_queue *fsl_queue = fsl_qdma->queue; + struct fsl_qdma_queue *fsl_status = fsl_qdma->status; + struct fsl_qdma_queue *temp_queue; + struct fsl_qdma_comp *fsl_comp; + struct fsl_qdma_format *status_addr; + struct fsl_qdma_format *csgf_src; + struct fsl_pre_status pre; + void __iomem *block = fsl_qdma->block_base; + u32 reg, i; + bool duplicate, duplicate_handle; + + memset(&pre, 0, sizeof(struct fsl_pre_status)); + + while (1) { + duplicate = 0; + duplicate_handle = 0; + reg = qdma_readl(fsl_qdma, block + FSL_QDMA_BSQSR); + if (reg & FSL_QDMA_BSQSR_QE) + return 0; + status_addr = fsl_status->virt_head; + if (qdma_ccdf_get_queue(status_addr) == pre.queue && + qdma_ccdf_addr_get64(status_addr) == pre.addr) + duplicate = 1; + i = qdma_ccdf_get_queue(status_addr); + pre.queue = qdma_ccdf_get_queue(status_addr); + pre.addr = qdma_ccdf_addr_get64(status_addr); + temp_queue = fsl_queue + i; + spin_lock(&temp_queue->queue_lock); + if (list_empty(&temp_queue->comp_used)) { + if (duplicate) + duplicate_handle = 1; + else { + spin_unlock(&temp_queue->queue_lock); + return -EAGAIN; + } + } else { + fsl_comp = list_first_entry(&temp_queue->comp_used, + struct fsl_qdma_comp, + list); + csgf_src = fsl_comp->virt_addr + 2; + if (fsl_comp->bus_addr + 16 != pre.addr) { + if (duplicate) + duplicate_handle = 1; + else { + spin_unlock(&temp_queue->queue_lock); + return -EAGAIN; + } + } + } + + if (duplicate_handle) { + reg = qdma_readl(fsl_qdma, block + + FSL_QDMA_BSQMR); + reg |= FSL_QDMA_BSQMR_DI; + qdma_desc_addr_set64(status_addr, 0x0); + fsl_status->virt_head++; + if (fsl_status->virt_head == fsl_status->cq + + fsl_status->n_cq) + fsl_status->virt_head = fsl_status->cq; + qdma_writel(fsl_qdma, reg, block + FSL_QDMA_BSQMR); + spin_unlock(&temp_queue->queue_lock); + continue; + } + list_del(&fsl_comp->list); + + reg = qdma_readl(fsl_qdma, block + FSL_QDMA_BSQMR); + reg |= FSL_QDMA_BSQMR_DI; + qdma_desc_addr_set64(status_addr, 0x0); + fsl_status->virt_head++; + if (fsl_status->virt_head == fsl_status->cq + fsl_status->n_cq) + fsl_status->virt_head = fsl_status->cq; + qdma_writel(fsl_qdma, reg, block + FSL_QDMA_BSQMR); + spin_unlock(&temp_queue->queue_lock); + + spin_lock(&fsl_comp->qchan->vchan.lock); + vchan_cookie_complete(&fsl_comp->vdesc); + fsl_comp->qchan->status = DMA_COMPLETE; + spin_unlock(&fsl_comp->qchan->vchan.lock); + } + + return 0; +} + +static irqreturn_t fsl_qdma_error_handler(int irq, void *dev_id) +{ + struct fsl_qdma_engine *fsl_qdma = dev_id; + unsigned int intr; + void __iomem *status = fsl_qdma->status_base; + + intr = qdma_readl(fsl_qdma, status + FSL_QDMA_DEDR); + + if (intr) + dev_err(fsl_qdma->dma_dev.dev, "DMA transaction error!\n"); + + qdma_writel(fsl_qdma, 0xffffffff, status + FSL_QDMA_DEDR); + + return IRQ_HANDLED; +} + +static irqreturn_t fsl_qdma_queue_handler(int irq, void *dev_id) +{ + struct fsl_qdma_engine *fsl_qdma = dev_id; + unsigned int intr, reg; + void __iomem *block = fsl_qdma->block_base; + void __iomem *ctrl = fsl_qdma->ctrl_base; + + intr = qdma_readl(fsl_qdma, block + FSL_QDMA_BCQIDR(0)); + + if ((intr & FSL_QDMA_CQIDR_SQT) != 0) + intr = fsl_qdma_queue_transfer_complete(fsl_qdma); + + if (intr != 0) { + reg = qdma_readl(fsl_qdma, ctrl + FSL_QDMA_DMR); + reg |= FSL_QDMA_DMR_DQD; + qdma_writel(fsl_qdma, reg, ctrl + FSL_QDMA_DMR); + qdma_writel(fsl_qdma, 0, block + FSL_QDMA_BCQIER(0)); + dev_err(fsl_qdma->dma_dev.dev, "QDMA: status err!\n"); + } + + qdma_writel(fsl_qdma, 0xffffffff, block + FSL_QDMA_BCQIDR(0)); + + return IRQ_HANDLED; +} + +static int +fsl_qdma_irq_init(struct platform_device *pdev, + struct fsl_qdma_engine *fsl_qdma) +{ + int ret; + + fsl_qdma->error_irq = platform_get_irq_byname(pdev, + "qdma-error"); + if (fsl_qdma->error_irq < 0) { + dev_err(&pdev->dev, "Can't get qdma controller irq.\n"); + return fsl_qdma->error_irq; + } + + fsl_qdma->queue_irq = platform_get_irq_byname(pdev, "qdma-queue"); + if (fsl_qdma->queue_irq < 0) { + dev_err(&pdev->dev, "Can't get qdma queue irq.\n"); + return fsl_qdma->queue_irq; + } + + ret = devm_request_irq(&pdev->dev, fsl_qdma->error_irq, + fsl_qdma_error_handler, 0, "qDMA error", fsl_qdma); + if (ret) { + dev_err(&pdev->dev, "Can't register qDMA controller IRQ.\n"); + return ret; + } + ret = devm_request_irq(&pdev->dev, fsl_qdma->queue_irq, + fsl_qdma_queue_handler, 0, "qDMA queue", fsl_qdma); + if (ret) { + dev_err(&pdev->dev, "Can't register qDMA queue IRQ.\n"); + return ret; + } + + return 0; +} + +static void fsl_qdma_irq_exit( + struct platform_device *pdev, struct fsl_qdma_engine *fsl_qdma) +{ + if (fsl_qdma->queue_irq == fsl_qdma->error_irq) { + devm_free_irq(&pdev->dev, fsl_qdma->queue_irq, fsl_qdma); + } else { + devm_free_irq(&pdev->dev, fsl_qdma->queue_irq, fsl_qdma); + devm_free_irq(&pdev->dev, fsl_qdma->error_irq, fsl_qdma); + } +} + +static int fsl_qdma_reg_init(struct fsl_qdma_engine *fsl_qdma) +{ + struct fsl_qdma_queue *fsl_queue = fsl_qdma->queue; + struct fsl_qdma_queue *temp; + void __iomem *ctrl = fsl_qdma->ctrl_base; + void __iomem *status = fsl_qdma->status_base; + void __iomem *block = fsl_qdma->block_base; + int i, ret; + u32 reg; + + /* Try to halt the qDMA engine first. */ + ret = fsl_qdma_halt(fsl_qdma); + if (ret) { + dev_err(fsl_qdma->dma_dev.dev, "DMA halt failed!"); + return ret; + } + + /* + * Clear the command queue interrupt detect register for all queues. + */ + qdma_writel(fsl_qdma, 0xffffffff, block + FSL_QDMA_BCQIDR(0)); + + for (i = 0; i < fsl_qdma->n_queues; i++) { + temp = fsl_queue + i; + /* + * Initialize Command Queue registers to point to the first + * command descriptor in memory. + * Dequeue Pointer Address Registers + * Enqueue Pointer Address Registers + */ + qdma_writel(fsl_qdma, temp->bus_addr, + block + FSL_QDMA_BCQDPA_SADDR(i)); + qdma_writel(fsl_qdma, temp->bus_addr, + block + FSL_QDMA_BCQEPA_SADDR(i)); + + /* Initialize the queue mode. */ + reg = FSL_QDMA_BCQMR_EN; + reg |= FSL_QDMA_BCQMR_CD_THLD(ilog2(temp->n_cq)-4); + reg |= FSL_QDMA_BCQMR_CQ_SIZE(ilog2(temp->n_cq)-6); + qdma_writel(fsl_qdma, reg, block + FSL_QDMA_BCQMR(i)); + } + + /* + * Workaround for erratum: ERR010812. + * We must enable XOFF to avoid the enqueue rejection occurs. + * Setting SQCCMR ENTER_WM to 0x20. + */ + qdma_writel(fsl_qdma, FSL_QDMA_SQCCMR_ENTER_WM, + block + FSL_QDMA_SQCCMR); + /* + * Initialize status queue registers to point to the first + * command descriptor in memory. + * Dequeue Pointer Address Registers + * Enqueue Pointer Address Registers + */ + qdma_writel(fsl_qdma, fsl_qdma->status->bus_addr, + block + FSL_QDMA_SQEPAR); + qdma_writel(fsl_qdma, fsl_qdma->status->bus_addr, + block + FSL_QDMA_SQDPAR); + /* Initialize status queue interrupt. */ + qdma_writel(fsl_qdma, FSL_QDMA_BCQIER_CQTIE, + block + FSL_QDMA_BCQIER(0)); + qdma_writel(fsl_qdma, FSL_QDMA_BSQICR_ICEN | FSL_QDMA_BSQICR_ICST(5) + | 0x8000, + block + FSL_QDMA_BSQICR); + qdma_writel(fsl_qdma, FSL_QDMA_CQIER_MEIE | FSL_QDMA_CQIER_TEIE, + block + FSL_QDMA_CQIER); + /* Initialize controller interrupt register. */ + qdma_writel(fsl_qdma, 0xffffffff, status + FSL_QDMA_DEDR); + qdma_writel(fsl_qdma, 0xffffffff, status + FSL_QDMA_DEIER); + + /* Initialize the status queue mode. */ + reg = FSL_QDMA_BSQMR_EN; + reg |= FSL_QDMA_BSQMR_CQ_SIZE(ilog2(fsl_qdma->status->n_cq)-6); + qdma_writel(fsl_qdma, reg, block + FSL_QDMA_BSQMR); + + reg = qdma_readl(fsl_qdma, ctrl + FSL_QDMA_DMR); + reg &= ~FSL_QDMA_DMR_DQD; + qdma_writel(fsl_qdma, reg, ctrl + FSL_QDMA_DMR); + + return 0; +} + +static struct dma_async_tx_descriptor * +fsl_qdma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, + dma_addr_t src, size_t len, unsigned long flags) +{ + struct fsl_qdma_chan *fsl_chan = to_fsl_qdma_chan(chan); + struct fsl_qdma_comp *fsl_comp; + + fsl_comp = fsl_qdma_request_enqueue_desc(fsl_chan, 0, 0); + fsl_qdma_comp_fill_memcpy(fsl_comp, dst, src, len); + + return vchan_tx_prep(&fsl_chan->vchan, &fsl_comp->vdesc, flags); +} + +static void fsl_qdma_enqueue_desc(struct fsl_qdma_chan *fsl_chan) +{ + void __iomem *block = fsl_chan->qdma->block_base; + struct fsl_qdma_queue *fsl_queue = fsl_chan->queue; + struct fsl_qdma_comp *fsl_comp; + struct virt_dma_desc *vdesc; + u32 reg; + + reg = qdma_readl(fsl_chan->qdma, block + FSL_QDMA_BCQSR(fsl_queue->id)); + if (reg & (FSL_QDMA_BCQSR_QF | FSL_QDMA_BCQSR_XOFF)) + return; + vdesc = vchan_next_desc(&fsl_chan->vchan); + if (!vdesc) + return; + list_del(&vdesc->node); + fsl_comp = to_fsl_qdma_comp(vdesc); + + memcpy(fsl_queue->virt_head++, fsl_comp->virt_addr, + sizeof(struct fsl_qdma_format)); + if (fsl_queue->virt_head == fsl_queue->cq + fsl_queue->n_cq) + fsl_queue->virt_head = fsl_queue->cq; + + list_add_tail(&fsl_comp->list, &fsl_queue->comp_used); + barrier(); + reg = qdma_readl(fsl_chan->qdma, block + FSL_QDMA_BCQMR(fsl_queue->id)); + reg |= FSL_QDMA_BCQMR_EI; + qdma_writel(fsl_chan->qdma, reg, block + FSL_QDMA_BCQMR(fsl_queue->id)); + fsl_chan->status = DMA_IN_PROGRESS; +} + +static enum dma_status fsl_qdma_tx_status(struct dma_chan *chan, + dma_cookie_t cookie, struct dma_tx_state *txstate) +{ + enum dma_status ret; + + ret = dma_cookie_status(chan, cookie, txstate); + if (ret == DMA_COMPLETE || !txstate) + return ret; + + return ret; +} + +static void fsl_qdma_free_desc(struct virt_dma_desc *vdesc) +{ + struct fsl_qdma_comp *fsl_comp; + struct fsl_qdma_queue *fsl_queue; + unsigned long flags; + + fsl_comp = to_fsl_qdma_comp(vdesc); + fsl_queue = fsl_comp->qchan->queue; + + spin_lock_irqsave(&fsl_queue->queue_lock, flags); + list_add_tail(&fsl_comp->list, &fsl_queue->comp_free); + spin_unlock_irqrestore(&fsl_queue->queue_lock, flags); +} + +static void fsl_qdma_issue_pending(struct dma_chan *chan) +{ + struct fsl_qdma_chan *fsl_chan = to_fsl_qdma_chan(chan); + struct fsl_qdma_queue *fsl_queue = fsl_chan->queue; + unsigned long flags; + + spin_lock_irqsave(&fsl_queue->queue_lock, flags); + spin_lock(&fsl_chan->vchan.lock); + if (vchan_issue_pending(&fsl_chan->vchan)) + fsl_qdma_enqueue_desc(fsl_chan); + spin_unlock(&fsl_chan->vchan.lock); + spin_unlock_irqrestore(&fsl_queue->queue_lock, flags); +} + +static int fsl_qdma_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct fsl_qdma_engine *fsl_qdma; + struct fsl_qdma_chan *fsl_chan; + struct resource *res; + unsigned int len, chans, queues; + int ret, i; + + ret = of_property_read_u32(np, "dma-channels", &chans); + if (ret) { + dev_err(&pdev->dev, "Can't get dma-channels.\n"); + return ret; + } + + len = sizeof(*fsl_qdma) + sizeof(*fsl_chan) * chans; + fsl_qdma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); + if (!fsl_qdma) + return -ENOMEM; + + ret = of_property_read_u32(np, "fsl,queues", &queues); + if (ret) { + dev_err(&pdev->dev, "Can't get queues.\n"); + return ret; + } + + fsl_qdma->queue = fsl_qdma_alloc_queue_resources(pdev, queues); + if (!fsl_qdma->queue) + return -ENOMEM; + + fsl_qdma->status = fsl_qdma_prep_status_queue(pdev); + if (!fsl_qdma->status) + return -ENOMEM; + + fsl_qdma->n_chans = chans; + fsl_qdma->n_queues = queues; + mutex_init(&fsl_qdma->fsl_qdma_mutex); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + fsl_qdma->ctrl_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(fsl_qdma->ctrl_base)) + return PTR_ERR(fsl_qdma->ctrl_base); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + fsl_qdma->status_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(fsl_qdma->status_base)) + return PTR_ERR(fsl_qdma->status_base); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + fsl_qdma->block_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(fsl_qdma->block_base)) + return PTR_ERR(fsl_qdma->block_base); + + ret = fsl_qdma_irq_init(pdev, fsl_qdma); + if (ret) + return ret; + + fsl_qdma->feature = of_property_read_bool(np, "big-endian"); + INIT_LIST_HEAD(&fsl_qdma->dma_dev.channels); + for (i = 0; i < fsl_qdma->n_chans; i++) { + struct fsl_qdma_chan *fsl_chan = &fsl_qdma->chans[i]; + + fsl_chan->qdma = fsl_qdma; + fsl_chan->queue = fsl_qdma->queue + i % fsl_qdma->n_queues; + fsl_chan->vchan.desc_free = fsl_qdma_free_desc; + INIT_LIST_HEAD(&fsl_chan->qcomp); + vchan_init(&fsl_chan->vchan, &fsl_qdma->dma_dev); + } + for (i = 0; i < fsl_qdma->n_queues; i++) + fsl_qdma_pre_request_enqueue_desc(fsl_qdma->queue + i); + + dma_cap_set(DMA_MEMCPY, fsl_qdma->dma_dev.cap_mask); + + fsl_qdma->dma_dev.dev = &pdev->dev; + fsl_qdma->dma_dev.device_free_chan_resources + = fsl_qdma_free_chan_resources; + fsl_qdma->dma_dev.device_tx_status = fsl_qdma_tx_status; + fsl_qdma->dma_dev.device_prep_dma_memcpy = fsl_qdma_prep_memcpy; + fsl_qdma->dma_dev.device_issue_pending = fsl_qdma_issue_pending; + + dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)); + + platform_set_drvdata(pdev, fsl_qdma); + + ret = dma_async_device_register(&fsl_qdma->dma_dev); + if (ret) { + dev_err(&pdev->dev, "Can't register NXP Layerscape qDMA engine.\n"); + return ret; + } + + ret = fsl_qdma_reg_init(fsl_qdma); + if (ret) { + dev_err(&pdev->dev, "Can't Initialize the qDMA engine.\n"); + return ret; + } + + return 0; +} + +static void fsl_qdma_cleanup_vchan(struct dma_device *dmadev) +{ + struct fsl_qdma_chan *chan, *_chan; + + list_for_each_entry_safe(chan, _chan, + &dmadev->channels, vchan.chan.device_node) { + list_del(&chan->vchan.chan.device_node); + tasklet_kill(&chan->vchan.task); + } +} + +static int fsl_qdma_remove(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct fsl_qdma_engine *fsl_qdma = platform_get_drvdata(pdev); + struct fsl_qdma_queue *queue_temp; + struct fsl_qdma_queue *status = fsl_qdma->status; + struct fsl_qdma_comp *comp_temp, *_comp_temp; + int i; + + fsl_qdma_irq_exit(pdev, fsl_qdma); + fsl_qdma_cleanup_vchan(&fsl_qdma->dma_dev); + of_dma_controller_free(np); + dma_async_device_unregister(&fsl_qdma->dma_dev); + + /* Free descriptor areas */ + for (i = 0; i < fsl_qdma->n_queues; i++) { + queue_temp = fsl_qdma->queue + i; + list_for_each_entry_safe(comp_temp, _comp_temp, + &queue_temp->comp_used, list) { + dma_pool_free(queue_temp->comp_pool, + comp_temp->virt_addr, + comp_temp->bus_addr); + list_del(&comp_temp->list); + kfree(comp_temp); + } + list_for_each_entry_safe(comp_temp, _comp_temp, + &queue_temp->comp_free, list) { + dma_pool_free(queue_temp->comp_pool, + comp_temp->virt_addr, + comp_temp->bus_addr); + list_del(&comp_temp->list); + kfree(comp_temp); + } + dma_free_coherent(&pdev->dev, sizeof(struct fsl_qdma_format) * + queue_temp->n_cq, queue_temp->cq, + queue_temp->bus_addr); + dma_pool_destroy(queue_temp->comp_pool); + } + + dma_free_coherent(&pdev->dev, sizeof(struct fsl_qdma_format) * + status->n_cq, status->cq, status->bus_addr); + return 0; +} + +static const struct of_device_id fsl_qdma_dt_ids[] = { + { .compatible = "fsl,ls1021a-qdma", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, fsl_qdma_dt_ids); + +static struct platform_driver fsl_qdma_driver = { + .driver = { + .name = "fsl-qdma", + .of_match_table = fsl_qdma_dt_ids, + }, + .probe = fsl_qdma_probe, + .remove = fsl_qdma_remove, +}; + +module_platform_driver(fsl_qdma_driver); + +MODULE_ALIAS("platform:fsl-qdma"); +MODULE_DESCRIPTION("NXP Layerscape qDMA engine driver"); +MODULE_LICENSE("GPL v2"); -- 1.7.1