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: [v7,3/7] dmaengine: fsl-qdma: Add qDMA controller driver for Layerscape SoCs From: Wen He Message-Id: <20180725112919.31340-3-wen.he_1@nxp.com> Date: Wed, 25 Jul 2018 19:29:15 +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 ZXVlZCBpbnRvIGRpZmZlcmVudApjb21tYW5kIHF1ZXVlcy4KClNpZ25lZC1vZmYtYnk6IFdlbiBI ZSA8d2VuLmhlXzFAbnhwLmNvbT4KU2lnbmVkLW9mZi1ieTogSmlhaGVuZyBGYW4gPGppYWhlbmcu ZmFuQG54cC5jb20+Ci0tLQogZHJpdmVycy9kbWEvS2NvbmZpZyAgICB8ICAgMTMgKwogZHJpdmVy cy9kbWEvTWFrZWZpbGUgICB8ICAgIDEgKwogZHJpdmVycy9kbWEvZnNsLXFkbWEuYyB8IDExMDUg KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCiAzIGZpbGVz IGNoYW5nZWQsIDExMTkgaW5zZXJ0aW9ucygrKSwgMCBkZWxldGlvbnMoLSkKIGNyZWF0ZSBtb2Rl IDEwMDY0NCBkcml2ZXJzL2RtYS9mc2wtcWRtYS5jCgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9kbWEv S2NvbmZpZyBiL2RyaXZlcnMvZG1hL0tjb25maWcKaW5kZXggY2ExNjgwYS4uMjkxNGNhZiAxMDA2 NDQKLS0tIGEvZHJpdmVycy9kbWEvS2NvbmZpZworKysgYi9kcml2ZXJzL2RtYS9LY29uZmlnCkBA IC0yMTgsNiArMjE4LDE5IEBAIGNvbmZpZyBGU0xfRURNQQogCSAgbXVsdGlwbGV4aW5nIGNhcGFi aWxpdHkgZm9yIERNQSByZXF1ZXN0IHNvdXJjZXMoc2xvdCkuCiAJICBUaGlzIG1vZHVsZSBjYW4g YmUgZm91bmQgb24gRnJlZXNjYWxlIFZ5YnJpZCBhbmQgTFMtMSBTb0NzLgogCitjb25maWcgRlNM X1FETUEKKyAgICAgICB0cmlzdGF0ZSAiTlhQIExheWVyc2NhcGUgcURNQSBlbmdpbmUgc3VwcG9y dCIKKyAgICAgICBkZXBlbmRzIG9uIEFSTSB8fCBBUk02NAorICAgICAgIHNlbGVjdCBETUFfRU5H SU5FCisgICAgICAgc2VsZWN0IERNQV9WSVJUVUFMX0NIQU5ORUxTCisgICAgICAgc2VsZWN0IERN QV9FTkdJTkVfUkFJRAorICAgICAgIHNlbGVjdCBBU1lOQ19UWF9FTkFCTEVfQ0hBTk5FTF9TV0lU Q0gKKyAgICAgICBoZWxwCisgICAgICAgICBTdXBwb3J0IHRoZSBOWFAgTGF5ZXJzY2FwZSBxRE1B IGVuZ2luZSB3aXRoIGNvbW1hbmQgcXVldWUgYW5kIGxlZ2FjeSBtb2RlLgorICAgICAgICAgQ2hh bm5lbCB2aXJ0dWFsaXphdGlvbiBpcyBzdXBwb3J0ZWQgdGhyb3VnaCBlbnF1ZXVpbmcgb2YgRE1B IGpvYnMgdG8sCisgICAgICAgICBvciBkZXF1ZXVpbmcgRE1BIGpvYnMgZnJvbSwgZGlmZmVyZW50 IHdvcmsgcXVldWVzLgorICAgICAgICAgVGhpcyBtb2R1bGUgY2FuIGJlIGZvdW5kIG9uIE5YUCBM YXllcnNjYXBlIFNvQ3MuCisKIGNvbmZpZyBGU0xfUkFJRAogICAgICAgICB0cmlzdGF0ZSAiRnJl ZXNjYWxlIFJBSUQgZW5naW5lIFN1cHBvcnQiCiAgICAgICAgIGRlcGVuZHMgb24gRlNMX1NPQyAm JiAhQVNZTkNfVFhfRU5BQkxFX0NIQU5ORUxfU1dJVENICmRpZmYgLS1naXQgYS9kcml2ZXJzL2Rt YS9NYWtlZmlsZSBiL2RyaXZlcnMvZG1hL01ha2VmaWxlCmluZGV4IDIwM2E5OWQuLjA1NTZmOWQg MTAwNjQ0Ci0tLSBhL2RyaXZlcnMvZG1hL01ha2VmaWxlCisrKyBiL2RyaXZlcnMvZG1hL01ha2Vm aWxlCkBAIC0zMiw2ICszMiw3IEBAIG9iai0kKENPTkZJR19EV19ETUFDX0NPUkUpICs9IGR3Lwog b2JqLSQoQ09ORklHX0VQOTNYWF9ETUEpICs9IGVwOTN4eF9kbWEubwogb2JqLSQoQ09ORklHX0ZT TF9ETUEpICs9IGZzbGRtYS5vCiBvYmotJChDT05GSUdfRlNMX0VETUEpICs9IGZzbC1lZG1hLm8K K29iai0kKENPTkZJR19GU0xfUURNQSkgKz0gZnNsLXFkbWEubwogb2JqLSQoQ09ORklHX0ZTTF9S QUlEKSArPSBmc2xfcmFpZC5vCiBvYmotJChDT05GSUdfSFNVX0RNQSkgKz0gaHN1Lwogb2JqLSQo Q09ORklHX0lNR19NRENfRE1BKSArPSBpbWctbWRjLWRtYS5vCmRpZmYgLS1naXQgYS9kcml2ZXJz L2RtYS9mc2wtcWRtYS5jIGIvZHJpdmVycy9kbWEvZnNsLXFkbWEuYwpuZXcgZmlsZSBtb2RlIDEw MDY0NAppbmRleCAwMDAwMDAwLi4xY2VjZjliCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9k bWEvZnNsLXFkbWEuYwpAQCAtMCwwICsxLDExMDUgQEAKKy8vIFNQRFgtTGljZW5zZS1JZGVudGlm aWVyOiBHUEwtMi4wCisvLyBDb3B5cmlnaHQgMjAxOCBOWFAKKworLyoKKyAqIERyaXZlciBmb3Ig TlhQIExheWVyc2NhcGUgUXVldWUgRGlyZWN0IE1lbW9yeSBBY2Nlc3MgQ29udHJvbGxlcgorICoK KyAqIEF1dGhvcjoKKyAqICBXZW4gSGUgPHdlbi5oZV8xQG54cC5jb20+CisgKiAgSmlhaGVuZyBG YW4gPGppYWhlbmcuZmFuQG54cC5jb20+CisgKgorICovCisKKyNpbmNsdWRlIDxsaW51eC9pbnRl cnJ1cHQuaD4KKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KKyNpbmNsdWRlIDxsaW51eC9kZWxh eS5oPgorI2luY2x1ZGUgPGxpbnV4L29mX2lycS5oPgorI2luY2x1ZGUgPGxpbnV4L29mX2FkZHJl c3MuaD4KKyNpbmNsdWRlIDxsaW51eC9vZl9wbGF0Zm9ybS5oPgorI2luY2x1ZGUgPGxpbnV4L29m X2RtYS5oPgorI2luY2x1ZGUgPGxpbnV4L2RtYS1tYXBwaW5nLmg+CisjaW5jbHVkZSA8bGludXgv ZG1hcG9vbC5oPgorI2luY2x1ZGUgPGxpbnV4L2RtYWVuZ2luZS5oPgorI2luY2x1ZGUgPGxpbnV4 L3NsYWIuaD4KKyNpbmNsdWRlIDxsaW51eC9zcGlubG9jay5oPgorCisjaW5jbHVkZSAidmlydC1k bWEuaCIKKyNpbmNsdWRlICJmc2xkbWEuaCIKKworLyogUmVnaXN0ZXIgcmVsYXRlZCBkZWZpbml0 aW9uICovCisjZGVmaW5lIEZTTF9RRE1BX0RNUgkJCTB4MAorI2RlZmluZSBGU0xfUURNQV9EU1IJ CQkweDQKKyNkZWZpbmUgRlNMX1FETUFfREVJRVIJCQkweGUwMAorI2RlZmluZSBGU0xfUURNQV9E RURSCQkJMHhlMDQKKyNkZWZpbmUgRlNMX1FETUFfREVDRkRXMFIJCTB4ZTEwCisjZGVmaW5lIEZT TF9RRE1BX0RFQ0ZEVzFSCQkweGUxNAorI2RlZmluZSBGU0xfUURNQV9ERUNGRFcyUgkJMHhlMTgK KyNkZWZpbmUgRlNMX1FETUFfREVDRkRXM1IJCTB4ZTFjCisjZGVmaW5lIEZTTF9RRE1BX0RFQ0ZR SURSCQkweGUzMAorI2RlZmluZSBGU0xfUURNQV9ERUNCUgkJCTB4ZTM0CisKKyNkZWZpbmUgRlNM X1FETUFfQkNRTVIoeCkJCSgweGMwICsgMHgxMDAgKiAoeCkpCisjZGVmaW5lIEZTTF9RRE1BX0JD UVNSKHgpCQkoMHhjNCArIDB4MTAwICogKHgpKQorI2RlZmluZSBGU0xfUURNQV9CQ1FFRFBBX1NB RERSKHgpCSgweGM4ICsgMHgxMDAgKiAoeCkpCisjZGVmaW5lIEZTTF9RRE1BX0JDUURQQV9TQURE Uih4KQkoMHhjYyArIDB4MTAwICogKHgpKQorI2RlZmluZSBGU0xfUURNQV9CQ1FFRVBBX1NBRERS KHgpCSgweGQwICsgMHgxMDAgKiAoeCkpCisjZGVmaW5lIEZTTF9RRE1BX0JDUUVQQV9TQUREUih4 KQkoMHhkNCArIDB4MTAwICogKHgpKQorI2RlZmluZSBGU0xfUURNQV9CQ1FJRVIoeCkJCSgweGUw ICsgMHgxMDAgKiAoeCkpCisjZGVmaW5lIEZTTF9RRE1BX0JDUUlEUih4KQkJKDB4ZTQgKyAweDEw MCAqICh4KSkKKworI2RlZmluZSBGU0xfUURNQV9TUURQQVIJCQkweDgwYworI2RlZmluZSBGU0xf UURNQV9TUUVQQVIJCQkweDgxNAorI2RlZmluZSBGU0xfUURNQV9CU1FNUgkJCTB4ODAwCisjZGVm aW5lIEZTTF9RRE1BX0JTUVNSCQkJMHg4MDQKKyNkZWZpbmUgRlNMX1FETUFfQlNRSUNSCQkJMHg4 MjgKKyNkZWZpbmUgRlNMX1FETUFfQ1FNUgkJCTB4YTAwCisjZGVmaW5lIEZTTF9RRE1BX0NRRFND UjEJCTB4YTA4CisjZGVmaW5lIEZTTF9RRE1BX0NRRFNDUjIgICAgICAgICAgICAgICAgMHhhMGMK KyNkZWZpbmUgRlNMX1FETUFfQ1FJRVIJCQkweGExMAorI2RlZmluZSBGU0xfUURNQV9DUUVEUgkJ CTB4YTE0CisjZGVmaW5lIEZTTF9RRE1BX1NRQ0NNUgkJCTB4YTIwCisKKy8qIFJlZ2lzdGVycyBm b3IgYml0IGFuZCBnZW5tYXNrICovCisjZGVmaW5lIEZTTF9RRE1BX0NRSURSX1NRVAkJQklUKDE1 KQorI2RlZmluZSBRRE1BX0NDREZfRk9UTUFUCQlCSVQoMjkpCisjZGVmaW5lIFFETUFfQ0NERl9T RVIJCQlCSVQoMzApCisjZGVmaW5lIFFETUFfU0dfRklOCQkJQklUKDMwKQorI2RlZmluZSBRRE1B X1NHX0VYVAkJCUJJVCgzMSkKKyNkZWZpbmUgUURNQV9TR19MRU5fTUFTSwkJR0VOTUFTSygyOSwg MCkKKyNkZWZpbmUgUURNQV9DQ0RGX01BU0sJCQlHRU5NQVNLKDI4LCAyMCkKKworI2RlZmluZSBG U0xfUURNQV9ERURSX0NMRUFSCQlHRU5NQVNLKDMxLCAwKQorI2RlZmluZSBGU0xfUURNQV9CQ1FJ RFJfQ0xFQVIJCUdFTk1BU0soMzEsIDApCisjZGVmaW5lIEZTTF9RRE1BX0RFSUVSX0NMRUFSCQlH RU5NQVNLKDMxLCAwKQorCisjZGVmaW5lIEZTTF9RRE1BX0JDUUlFUl9DUVRJRQkJQklUKDE1KQor I2RlZmluZSBGU0xfUURNQV9CQ1FJRVJfQ1FQRUlFCQlCSVQoMjMpCisjZGVmaW5lIEZTTF9RRE1B X0JTUUlDUl9JQ0VOCQlCSVQoMzEpCisKKyNkZWZpbmUgRlNMX1FETUFfQlNRSUNSX0lDU1QoeCkJ CSgoeCkgPDwgMTYpCisjZGVmaW5lIEZTTF9RRE1BX0NRSUVSX01FSUUJCUJJVCgzMSkKKyNkZWZp bmUgRlNMX1FETUFfQ1FJRVJfVEVJRQkJQklUKDApCisjZGVmaW5lIEZTTF9RRE1BX1NRQ0NNUl9F TlRFUl9XTQlCSVQoMjEpCisKKyNkZWZpbmUgRlNMX1FETUFfQkNRTVJfRU4JCUJJVCgzMSkKKyNk ZWZpbmUgRlNMX1FETUFfQkNRTVJfRUkJCUJJVCgzMCkKKyNkZWZpbmUgRlNMX1FETUFfQkNRTVJf Q0RfVEhMRCh4KQkoKHgpIDw8IDIwKQorI2RlZmluZSBGU0xfUURNQV9CQ1FNUl9DUV9TSVpFKHgp CSgoeCkgPDwgMTYpCisKKyNkZWZpbmUgRlNMX1FETUFfQkNRU1JfUUYJCUJJVCgxNikKKyNkZWZp bmUgRlNMX1FETUFfQkNRU1JfWE9GRgkJQklUKDApCisKKyNkZWZpbmUgRlNMX1FETUFfQlNRTVJf RU4JCUJJVCgzMSkKKyNkZWZpbmUgRlNMX1FETUFfQlNRTVJfREkJCUJJVCgzMCkKKyNkZWZpbmUg RlNMX1FETUFfQlNRTVJfQ1FfU0laRSh4KQkoKHgpIDw8IDE2KQorCisjZGVmaW5lIEZTTF9RRE1B X0JTUVNSX1FFCQlCSVQoMTcpCisKKyNkZWZpbmUgRlNMX1FETUFfRE1SX0RRRAkJQklUKDMwKQor I2RlZmluZSBGU0xfUURNQV9EU1JfREIJCUJJVCgzMSkKKworLyogU2l6ZSByZWxhdGVkIGRlZmlu aXRpb24gKi8KKyNkZWZpbmUgRlNMX1FETUFfUVVFVUVfTUFYCQk4CisjZGVmaW5lIEZTTF9RRE1B X0JBU0VfQlVGRkVSX1NJWkUJOTYKKyNkZWZpbmUgRlNMX1FETUFfQ0lSQ1VMQVJfREVTQ19TSVpF X01JTgk2NAorI2RlZmluZSBGU0xfUURNQV9DSVJDVUxBUl9ERVNDX1NJWkVfTUFYCTE2Mzg0Cisj ZGVmaW5lIEZTTF9RRE1BX1FVRVVFX05VTV9NQVgJCTgKKworLyogRmllbGQgZGVmaW5pdGlvbiBm b3IgQ01EICovCisjZGVmaW5lIEZTTF9RRE1BX0NNRF9SV1RUWVBFCQkweDQKKyNkZWZpbmUgRlNM X1FETUFfQ01EX0xXQyAgICAgICAgICAgICAgICAweDIKKyNkZWZpbmUgRlNMX1FETUFfQ01EX1JX VFRZUEVfT0ZGU0VUCTI4CisjZGVmaW5lIEZTTF9RRE1BX0NNRF9OU19PRkZTRVQJCTI3CisjZGVm aW5lIEZTTF9RRE1BX0NNRF9EUU9TX09GRlNFVAkyNAorI2RlZmluZSBGU0xfUURNQV9DTURfV1RI Uk9UTF9PRkZTRVQJMjAKKyNkZWZpbmUgRlNMX1FETUFfQ01EX0RTRU5fT0ZGU0VUCTE5CisjZGVm aW5lIEZTTF9RRE1BX0NNRF9MV0NfT0ZGU0VUCQkxNgorCisjZGVmaW5lIEZTTF9RRE1BX0VfU0df VEFCTEUJCTEKKyNkZWZpbmUgRlNMX1FETUFfRV9EQVRBX0JVRkZFUgkJMAorI2RlZmluZSBGU0xf UURNQV9GX0xBU1RfRU5UUlkJCTEKKworLyogRmllbGQgZGVmaW5pdGlvbiBmb3Igc2FmZSBsb29w IGNvdW50Ki8KKyNkZWZpbmUgRlNMX1FETUFfSEFMVF9DT1VOVAkJMTUwMAorI2RlZmluZSBGU0xf UURNQV9NQVhfU0laRQkJMTYzODUKKworLyogRmllbGQgZGVmaW5pdGlvbiBmb3IgRGVzY3JpcHRv ciBvZmZzZXQgKi8KKyNkZWZpbmUgUURNQV9DQ0RGX1NUQVRVUwkJMjAKKyNkZWZpbmUgUURNQV9D Q0RGX09GRlNFVAkJMjAKKworLyoqCisgKiBzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0IC0gVGhpcyBp cyB0aGUgc3RydWN0IGhvbGRpbmcgZGVzY3JpYmluZyBjb21wb3VuZAorICoJCQkgICAgZGVzY3Jp cHRvciBmb3JtYXQgd2l0aCBxRE1BLgorICogQHN0YXR1czoJCSAgICBDb21tYW5kIHN0YXR1cyBh bmQgZW5xdWV1ZSBzdGF0dXMgbm90aWZpY2F0aW9uLgorICogQGNmZzoJCSAgICBGcmFtZSBvZmZz ZXQgYW5kIGZyYW1lIGZvcm1hdC4KKyAqIEBhZGRyX2xvOgkJICAgIEhvbGRpbmcgdGhlIGNvbXBv dW5kIGRlc2NyaXB0b3Igb2YgdGhlIGxvd2VyCisgKgkJCSAgICAzMi1iaXRzIGFkZHJlc3MgaW4g bWVtb3J5IDQwLWJpdCBhZGRyZXNzLgorICogQGFkZHJfaGk6CQkgICAgU2FtZSBhcyBhYm92ZSBt ZW1iZXIsIGJ1dCBwb2ludCBoaWdoIDgtYml0cyBpbgorICoJCQkgICAgbWVtb3J5IDQwLWJpdCBh ZGRyZXNzLgorICogQF9fcmVzZXJ2ZWQxOgkgICAgUmVzZXJ2ZWQgZmllbGQuCisgKiBAY2ZnOGJf dzE6CQkgICAgQ29tcG91bmQgZGVzY3JpcHRvciBjb21tYW5kIHF1ZXVlIG9yaWdpbiBwcm9kdWNl ZAorICoJCQkgICAgYnkgcURNQSBhbmQgZHluYW1pYyBkZWJ1ZyBmaWVsZC4KKyAqIEBkYXRhCQkg ICAgUG9pbnRlciB0byB0aGUgbWVtb3J5IDQwLWJpdCBhZGRyZXNzLCBkZXNjcmliZXMgRE1BCisg KgkJCSAgICBzb3VyY2UgaW5mb3JtYXRpb24gYW5kIERNQSBkZXN0aW5hdGlvbiBpbmZvcm1hdGlv bi4KKyAqLworc3RydWN0IGZzbF9xZG1hX2Zvcm1hdCB7CisJX19sZTMyIHN0YXR1czsKKwlfX2xl MzIgY2ZnOworCXVuaW9uIHsKKwkJc3RydWN0IHsKKwkJCV9fbGUzMiBhZGRyX2xvOworCQkJdTgg YWRkcl9oaTsKKwkJCXU4IF9fcmVzZXJ2ZWQxWzJdOworCQkJdTggY2ZnOGJfdzE7CisJCX0gX19w YWNrZWQ7CisJCV9fbGU2NCBkYXRhOworCX07Cit9IF9fcGFja2VkOworCisvKiBxRE1BIHN0YXR1 cyBub3RpZmljYXRpb24gcHJlIGluZm9ybWF0aW9uICovCitzdHJ1Y3QgZnNsX3ByZV9zdGF0dXMg eworCXU2NCBxdWV1ZTsKKwl1NjQgYWRkcjsKK307CisKK3N0cnVjdCBmc2xfcWRtYV9jaGFuIHsK KwlzdHJ1Y3QgdmlydF9kbWFfY2hhbgkJdmNoYW47CisJc3RydWN0IHZpcnRfZG1hX2Rlc2MJCXZk ZXNjOworCWVudW0gZG1hX3N0YXR1cwkJCXN0YXR1czsKKwl1MzIJCQkJc2xhdmVfaWQ7CisJc3Ry dWN0IGZzbF9xZG1hX2VuZ2luZQkJKnFkbWE7CisJc3RydWN0IGZzbF9xZG1hX3F1ZXVlCQkqcXVl dWU7CisJc3RydWN0IGxpc3RfaGVhZAkJcWNvbXA7Cit9OworCitzdHJ1Y3QgZnNsX3FkbWFfcXVl dWUgeworCXN0cnVjdCBmc2xfcWRtYV9mb3JtYXQJKnZpcnRfaGVhZDsKKwlzdHJ1Y3QgZnNsX3Fk bWFfZm9ybWF0CSp2aXJ0X3RhaWw7CisJc3RydWN0IGxpc3RfaGVhZAljb21wX3VzZWQ7CisJc3Ry dWN0IGxpc3RfaGVhZAljb21wX2ZyZWU7CisJc3RydWN0IGRtYV9wb29sCQkqY29tcF9wb29sOwor CXNwaW5sb2NrX3QJCXF1ZXVlX2xvY2s7CisJZG1hX2FkZHJfdAkJYnVzX2FkZHI7CisJdTMyICAg ICAgICAgICAgICAgICAgICAgbl9jcTsKKwl1MzIJCQlpZDsKKwlzdHJ1Y3QgZnNsX3FkbWFfZm9y bWF0CSpjcTsKK307CisKK3N0cnVjdCBmc2xfcWRtYV9jb21wIHsKKwlkbWFfYWRkcl90ICAgICAg ICAgICAgICBidXNfYWRkcjsKKwlzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0CSp2aXJ0X2FkZHI7CisJ c3RydWN0IGZzbF9xZG1hX2NoYW4JKnFjaGFuOworCXN0cnVjdCB2aXJ0X2RtYV9kZXNjICAgIHZk ZXNjOworCXN0cnVjdCBsaXN0X2hlYWQJbGlzdDsKK307CisKK3N0cnVjdCBmc2xfcWRtYV9lbmdp bmUgeworCXN0cnVjdCBkbWFfZGV2aWNlCWRtYV9kZXY7CisJdm9pZCBfX2lvbWVtCQkqY3RybF9i YXNlOworCXZvaWQgX19pb21lbSAgICAgICAgICAgICpzdGF0dXNfYmFzZTsKKwl2b2lkIF9faW9t ZW0JCSpibG9ja19iYXNlOworCXUzMgkJCW5fY2hhbnM7CisJdTMyCQkJbl9xdWV1ZXM7CisJc3Ry dWN0IG11dGV4ICAgICAgICAgICAgZnNsX3FkbWFfbXV0ZXg7CisJaW50CQkJZXJyb3JfaXJxOwor CWludAkJCXF1ZXVlX2lycTsKKwlib29sCQkJZmVhdHVyZTsKKwlzdHJ1Y3QgZnNsX3FkbWFfcXVl dWUJKnF1ZXVlOworCXN0cnVjdCBmc2xfcWRtYV9xdWV1ZQkqc3RhdHVzOworCXN0cnVjdCBmc2xf cWRtYV9jaGFuCWNoYW5zW107CisKK307CisKK3N0YXRpYyBpbmxpbmUgdTY0CitxZG1hX2NjZGZf YWRkcl9nZXQ2NChjb25zdCBzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0ICpjY2RmKQoreworCXJldHVy biBsZTY0X3RvX2NwdShjY2RmLT5kYXRhKSAmIChVNjRfTUFYID4+IDI0KTsKK30KKworc3RhdGlj IGlubGluZSB2b2lkCitxZG1hX2Rlc2NfYWRkcl9zZXQ2NChzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0 ICpjY2RmLCB1NjQgYWRkcikKK3sKKwljY2RmLT5hZGRyX2hpID0gdXBwZXJfMzJfYml0cyhhZGRy KTsKKwljY2RmLT5hZGRyX2xvID0gY3B1X3RvX2xlMzIobG93ZXJfMzJfYml0cyhhZGRyKSk7Cit9 CisKK3N0YXRpYyBpbmxpbmUgdTY0CitxZG1hX2NjZGZfZ2V0X3F1ZXVlKGNvbnN0IHN0cnVjdCBm c2xfcWRtYV9mb3JtYXQgKmNjZGYpCit7CisJcmV0dXJuIGNjZGYtPmNmZzhiX3cxICYgVThfTUFY OworfQorCitzdGF0aWMgaW5saW5lIGludAorcWRtYV9jY2RmX2dldF9vZmZzZXQoY29uc3Qgc3Ry dWN0IGZzbF9xZG1hX2Zvcm1hdCAqY2NkZikKK3sKKwlyZXR1cm4gKGxlMzJfdG9fY3B1KGNjZGYt PmNmZykgJiBRRE1BX0NDREZfTUFTSykgPj4gUURNQV9DQ0RGX09GRlNFVDsKK30KKworc3RhdGlj IGlubGluZSB2b2lkCitxZG1hX2NjZGZfc2V0X2Zvcm1hdChzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0 ICpjY2RmLCBpbnQgb2Zmc2V0KQoreworCWNjZGYtPmNmZyA9IGNwdV90b19sZTMyKFFETUFfQ0NE Rl9GT1RNQVQgfCBvZmZzZXQpOworfQorCitzdGF0aWMgaW5saW5lIGludAorcWRtYV9jY2RmX2dl dF9zdGF0dXMoY29uc3Qgc3RydWN0IGZzbF9xZG1hX2Zvcm1hdCAqY2NkZikKK3sKKwlyZXR1cm4g KGxlMzJfdG9fY3B1KGNjZGYtPnN0YXR1cykgJiBRRE1BX0NDREZfTUFTSykgPj4gUURNQV9DQ0RG X1NUQVRVUzsKK30KKworc3RhdGljIGlubGluZSB2b2lkCitxZG1hX2NjZGZfc2V0X3NlcihzdHJ1 Y3QgZnNsX3FkbWFfZm9ybWF0ICpjY2RmLCBpbnQgc3RhdHVzKQoreworCWNjZGYtPnN0YXR1cyA9 IGNwdV90b19sZTMyKFFETUFfQ0NERl9TRVIgfCBzdGF0dXMpOworfQorCitzdGF0aWMgaW5saW5l IHZvaWQgcWRtYV9jc2dmX3NldF9sZW4oc3RydWN0IGZzbF9xZG1hX2Zvcm1hdCAqY3NnZiwgaW50 IGxlbikKK3sKKwljc2dmLT5jZmcgPSBjcHVfdG9fbGUzMihsZW4gJiBRRE1BX1NHX0xFTl9NQVNL KTsKK30KKworc3RhdGljIGlubGluZSB2b2lkIHFkbWFfY3NnZl9zZXRfZihzdHJ1Y3QgZnNsX3Fk bWFfZm9ybWF0ICpjc2dmLCBpbnQgbGVuKQoreworCWNzZ2YtPmNmZyA9IGNwdV90b19sZTMyKFFE TUFfU0dfRklOIHwgKGxlbiAmIFFETUFfU0dfTEVOX01BU0spKTsKK30KKworc3RhdGljIGlubGlu ZSB2b2lkIHFkbWFfY3NnZl9zZXRfZShzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0ICpjc2dmLCBpbnQg bGVuKQoreworCWNzZ2YtPmNmZyA9IGNwdV90b19sZTMyKFFETUFfU0dfRVhUIHwgKGxlbiAmIFFE TUFfU0dfTEVOX01BU0spKTsKK30KKworc3RhdGljIHUzMiBxZG1hX3JlYWRsKHN0cnVjdCBmc2xf cWRtYV9lbmdpbmUgKnFkbWEsIHZvaWQgX19pb21lbSAqYWRkcikKK3sKKwlyZXR1cm4gRlNMX0RN QV9JTihxZG1hLCBhZGRyLCAzMik7Cit9CisKK3N0YXRpYyB2b2lkIHFkbWFfd3JpdGVsKHN0cnVj dCBmc2xfcWRtYV9lbmdpbmUgKnFkbWEsIHUzMiB2YWwsCisJCQkJCQl2b2lkIF9faW9tZW0gKmFk ZHIpCit7CisJRlNMX0RNQV9PVVQocWRtYSwgYWRkciwgdmFsLCAzMik7Cit9CisKK3N0YXRpYyBz dHJ1Y3QgZnNsX3FkbWFfY2hhbiAqdG9fZnNsX3FkbWFfY2hhbihzdHJ1Y3QgZG1hX2NoYW4gKmNo YW4pCit7CisJcmV0dXJuIGNvbnRhaW5lcl9vZihjaGFuLCBzdHJ1Y3QgZnNsX3FkbWFfY2hhbiwg dmNoYW4uY2hhbik7Cit9CisKK3N0YXRpYyBzdHJ1Y3QgZnNsX3FkbWFfY29tcCAqdG9fZnNsX3Fk bWFfY29tcChzdHJ1Y3QgdmlydF9kbWFfZGVzYyAqdmQpCit7CisJcmV0dXJuIGNvbnRhaW5lcl9v Zih2ZCwgc3RydWN0IGZzbF9xZG1hX2NvbXAsIHZkZXNjKTsKK30KKworc3RhdGljIHZvaWQgZnNs X3FkbWFfZnJlZV9jaGFuX3Jlc291cmNlcyhzdHJ1Y3QgZG1hX2NoYW4gKmNoYW4pCit7CisJc3Ry dWN0IGZzbF9xZG1hX2NoYW4gKmZzbF9jaGFuID0gdG9fZnNsX3FkbWFfY2hhbihjaGFuKTsKKwl1 bnNpZ25lZCBsb25nIGZsYWdzOworCUxJU1RfSEVBRChoZWFkKTsKKworCXNwaW5fbG9ja19pcnFz YXZlKCZmc2xfY2hhbi0+dmNoYW4ubG9jaywgZmxhZ3MpOworCXZjaGFuX2dldF9hbGxfZGVzY3Jp cHRvcnMoJmZzbF9jaGFuLT52Y2hhbiwgJmhlYWQpOworCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUo JmZzbF9jaGFuLT52Y2hhbi5sb2NrLCBmbGFncyk7CisKKwl2Y2hhbl9kbWFfZGVzY19mcmVlX2xp c3QoJmZzbF9jaGFuLT52Y2hhbiwgJmhlYWQpOworfQorCitzdGF0aWMgdm9pZCBmc2xfcWRtYV9j b21wX2ZpbGxfbWVtY3B5KHN0cnVjdCBmc2xfcWRtYV9jb21wICpmc2xfY29tcCwKKwkJCQkJZG1h X2FkZHJfdCBkc3QsIGRtYV9hZGRyX3Qgc3JjLCB1MzIgbGVuKQoreworCXN0cnVjdCBmc2xfcWRt YV9mb3JtYXQgKmNjZGYsICpjc2dmX2Rlc2MsICpjc2dmX3NyYywgKmNzZ2ZfZGVzdDsKKwlzdHJ1 Y3QgZnNsX3FkbWFfZm9ybWF0ICpzZGYsICpkZGY7CisKKwljY2RmID0gZnNsX2NvbXAtPnZpcnRf YWRkcjsKKwljc2dmX2Rlc2MgPSBmc2xfY29tcC0+dmlydF9hZGRyICsgMTsKKwljc2dmX3NyYyA9 IGZzbF9jb21wLT52aXJ0X2FkZHIgKyAyOworCWNzZ2ZfZGVzdCA9IGZzbF9jb21wLT52aXJ0X2Fk ZHIgKyAzOworCXNkZiA9IGZzbF9jb21wLT52aXJ0X2FkZHIgKyA0OworCWRkZiA9IGZzbF9jb21w LT52aXJ0X2FkZHIgKyA1OworCisJbWVtc2V0KGZzbF9jb21wLT52aXJ0X2FkZHIsIDAsIEZTTF9R RE1BX0JBU0VfQlVGRkVSX1NJWkUpOworCS8qIEhlYWQgQ29tbWFuZCBEZXNjcmlwdG9yKEZyYW1l IERlc2NyaXB0b3IpICovCisJcWRtYV9kZXNjX2FkZHJfc2V0NjQoY2NkZiwgZnNsX2NvbXAtPmJ1 c19hZGRyICsgMTYpOworCXFkbWFfY2NkZl9zZXRfZm9ybWF0KGNjZGYsIHFkbWFfY2NkZl9nZXRf b2Zmc2V0KGNjZGYpKTsKKwlxZG1hX2NjZGZfc2V0X3NlcihjY2RmLCBxZG1hX2NjZGZfZ2V0X3N0 YXR1cyhjY2RmKSk7CisKKwkvKiBTdGF0dXMgbm90aWZpY2F0aW9uIGlzIGVucXVldWVkIHRvIHN0 YXR1cyBxdWV1ZS4gKi8KKwkvKiBDb21wb3VuZCBDb21tYW5kIERlc2NyaXB0b3IoRnJhbWUgTGlz dCBUYWJsZSkgKi8KKwlxZG1hX2Rlc2NfYWRkcl9zZXQ2NChjc2dmX2Rlc2MsIGZzbF9jb21wLT5i dXNfYWRkciArIDY0KTsKKwkvKiBJdCBtdXN0IGJlIDMyIGFzIENvbXBvdW5kIFMvRyBEZXNjcmlw dG9yICovCisJcWRtYV9jc2dmX3NldF9sZW4oY3NnZl9kZXNjLCAzMik7CisJcWRtYV9kZXNjX2Fk ZHJfc2V0NjQoY3NnZl9zcmMsIHNyYyk7CisJcWRtYV9jc2dmX3NldF9sZW4oY3NnZl9zcmMsIGxl bik7CisJcWRtYV9kZXNjX2FkZHJfc2V0NjQoY3NnZl9kZXN0LCBkc3QpOworCXFkbWFfY3NnZl9z ZXRfbGVuKGNzZ2ZfZGVzdCwgbGVuKTsKKwkvKiBUaGlzIGVudHJ5IGlzIHRoZSBsYXN0IGVudHJ5 LiAqLworCXFkbWFfY3NnZl9zZXRfZihjc2dmX2Rlc3QsIGxlbik7CisJLyogRGVzY3JpcHRvciBC dWZmZXIgKi8KKwlzZGYtPmRhdGEgPSBjcHVfdG9fbGU2NCgKKwkJCUZTTF9RRE1BX0NNRF9SV1RU WVBFIDw8IEZTTF9RRE1BX0NNRF9SV1RUWVBFX09GRlNFVCk7CisJZGRmLT5kYXRhID0gY3B1X3Rv X2xlNjQoCisJCQlGU0xfUURNQV9DTURfUldUVFlQRSA8PCBGU0xfUURNQV9DTURfUldUVFlQRV9P RkZTRVQpOworCWRkZi0+ZGF0YSB8PSBjcHVfdG9fbGU2NCgKKwkJCUZTTF9RRE1BX0NNRF9MV0Mg PDwgRlNMX1FETUFfQ01EX0xXQ19PRkZTRVQpOworfQorCisvKgorICogUHJlLXJlcXVlc3QgZnVs bCBjb21tYW5kIGRlc2NyaXB0b3IgZm9yIGVucXVldWUuCisgKi8KK3N0YXRpYyBpbnQgZnNsX3Fk bWFfcHJlX3JlcXVlc3RfZW5xdWV1ZV9kZXNjKHN0cnVjdCBmc2xfcWRtYV9xdWV1ZSAqcXVldWUp Cit7CisJc3RydWN0IGZzbF9xZG1hX2NvbXAgKmNvbXBfdGVtcCwgKl9jb21wX3RlbXA7CisJaW50 IGk7CisKKwlmb3IgKGkgPSAwOyBpIDwgcXVldWUtPm5fY3E7IGkrKykgeworCQljb21wX3RlbXAg PSBremFsbG9jKHNpemVvZigqY29tcF90ZW1wKSwgR0ZQX05PV0FJVCk7CisJCWlmICghY29tcF90 ZW1wKQorCQkJZ290byBlcnI7CisKKwkJY29tcF90ZW1wLT52aXJ0X2FkZHIgPSBkbWFfcG9vbF9h bGxvYyhxdWV1ZS0+Y29tcF9wb29sLAorCQkJCQkJICAgICAgR0ZQX05PV0FJVCwKKwkJCQkJCSAg ICAgICZjb21wX3RlbXAtPmJ1c19hZGRyKTsKKwkJaWYgKCFjb21wX3RlbXAtPnZpcnRfYWRkcikK KwkJCWdvdG8gZXJyOworCisJCWxpc3RfYWRkX3RhaWwoJmNvbXBfdGVtcC0+bGlzdCwgJnF1ZXVl LT5jb21wX2ZyZWUpOworCX0KKwlyZXR1cm4gMDsKKworZXJyOgorCWlmIChpID09IDAgJiYgY29t cF90ZW1wKSB7CisJCWtmcmVlKGNvbXBfdGVtcCk7CisJCXJldHVybiAtRU5PTUVNOworCX0KKwor CXdoaWxlICgtLWkgPj0gMSkgeworCQlsaXN0X2Zvcl9lYWNoX2VudHJ5X3NhZmUoY29tcF90ZW1w LCBfY29tcF90ZW1wLAorCQkJCSZxdWV1ZS0+Y29tcF9mcmVlLCBsaXN0KSB7CisJCQlkbWFfcG9v bF9mcmVlKHF1ZXVlLT5jb21wX3Bvb2wsCisJCQkJCWNvbXBfdGVtcC0+dmlydF9hZGRyLAorCQkJ CQljb21wX3RlbXAtPmJ1c19hZGRyKTsKKwkJCWxpc3RfZGVsKCZjb21wX3RlbXAtPmxpc3QpOwor CQkJa2ZyZWUoY29tcF90ZW1wKTsKKwkJfQorCX0KKwlyZXR1cm4gLUVOT01FTTsKK30KKworLyoK KyAqIFJlcXVlc3QgYSBjb21tYW5kIGRlc2NyaXB0b3IgZm9yIGVucXVldWUuCisgKi8KK3N0YXRp YyBzdHJ1Y3QgZnNsX3FkbWFfY29tcCAqZnNsX3FkbWFfcmVxdWVzdF9lbnF1ZXVlX2Rlc2MoCisJ CQkJCXN0cnVjdCBmc2xfcWRtYV9jaGFuICpmc2xfY2hhbiwKKwkJCQkJdW5zaWduZWQgaW50IGRz dF9uZW50cywKKwkJCQkJdW5zaWduZWQgaW50IHNyY19uZW50cykKK3sKKwlzdHJ1Y3QgZnNsX3Fk bWFfY29tcCAqY29tcF90ZW1wOworCXN0cnVjdCBmc2xfcWRtYV9xdWV1ZSAqcXVldWUgPSBmc2xf Y2hhbi0+cXVldWU7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKworCXNwaW5fbG9ja19pcnFzYXZl KCZxdWV1ZS0+cXVldWVfbG9jaywgZmxhZ3MpOworCWlmIChsaXN0X2VtcHR5KCZxdWV1ZS0+Y29t cF9mcmVlKSkgeworCQlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZxdWV1ZS0+cXVldWVfbG9jaywg ZmxhZ3MpOworCQljb21wX3RlbXAgPSBremFsbG9jKHNpemVvZigqY29tcF90ZW1wKSwgR0ZQX0tF Uk5FTCk7CisJCWlmICghY29tcF90ZW1wKQorCQkJcmV0dXJuIE5VTEw7CisKKwkJY29tcF90ZW1w LT52aXJ0X2FkZHIgPSBkbWFfcG9vbF9hbGxvYyhxdWV1ZS0+Y29tcF9wb29sLAorCQkJCQkJICAg ICAgR0ZQX0tFUk5FTCwKKwkJCQkJCSAgICAgICZjb21wX3RlbXAtPmJ1c19hZGRyKTsKKwkJaWYg KCFjb21wX3RlbXAtPnZpcnRfYWRkcikgeworCQkJa2ZyZWUoY29tcF90ZW1wKTsKKwkJCXJldHVy biBOVUxMOworCQl9CisKKwl9IGVsc2UgeworCQljb21wX3RlbXAgPSBsaXN0X2ZpcnN0X2VudHJ5 KCZxdWV1ZS0+Y29tcF9mcmVlLAorCQkJCQkgICAgIHN0cnVjdCBmc2xfcWRtYV9jb21wLAorCQkJ CQkgICAgIGxpc3QpOworCQlsaXN0X2RlbCgmY29tcF90ZW1wLT5saXN0KTsKKwkJc3Bpbl91bmxv Y2tfaXJxcmVzdG9yZSgmcXVldWUtPnF1ZXVlX2xvY2ssIGZsYWdzKTsKKwl9CisKKwljb21wX3Rl bXAtPnFjaGFuID0gZnNsX2NoYW47CisKKwlyZXR1cm4gY29tcF90ZW1wOworfQorCitzdGF0aWMg c3RydWN0IGZzbF9xZG1hX3F1ZXVlICpmc2xfcWRtYV9hbGxvY19xdWV1ZV9yZXNvdXJjZXMoCisJ CQkJCXN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYsCisJCQkJCXVuc2lnbmVkIGludCBxdWV1 ZV9udW0pCit7CisJc3RydWN0IGZzbF9xZG1hX3F1ZXVlICpxdWV1ZV9oZWFkLCAqcXVldWVfdGVt cDsKKwlpbnQgcmV0LCBpOworCXVuc2lnbmVkIGludCBxdWV1ZV9zaXplW0ZTTF9RRE1BX1FVRVVF X01BWF07CisKKwlpZiAocXVldWVfbnVtID4gRlNMX1FETUFfUVVFVUVfTUFYKQorCQlxdWV1ZV9u dW0gPSBGU0xfUURNQV9RVUVVRV9NQVg7CisJcXVldWVfaGVhZCA9IGRldm1fa2NhbGxvYygmcGRl di0+ZGV2LCBxdWV1ZV9udW0sCisJCQkJc2l6ZW9mKCpxdWV1ZV9oZWFkKSwgR0ZQX0tFUk5FTCk7 CisJaWYgKCFxdWV1ZV9oZWFkKQorCQlyZXR1cm4gTlVMTDsKKworCXJldCA9IGRldmljZV9wcm9w ZXJ0eV9yZWFkX3UzMl9hcnJheSgmcGRldi0+ZGV2LCAicXVldWUtc2l6ZXMiLAorCQkJCQlxdWV1 ZV9zaXplLCBxdWV1ZV9udW0pOworCWlmIChyZXQpIHsKKwkJZGV2X2VycigmcGRldi0+ZGV2LCAi Q2FuJ3QgZ2V0IHF1ZXVlLXNpemVzLlxuIik7CisJCXJldHVybiBOVUxMOworCX0KKworCWZvciAo aSA9IDA7IGkgPCBxdWV1ZV9udW07IGkrKykgeworCQlpZiAocXVldWVfc2l6ZVtpXSA+IEZTTF9R RE1BX0NJUkNVTEFSX0RFU0NfU0laRV9NQVggfHwKKwkJCSAgICBxdWV1ZV9zaXplW2ldIDwgRlNM X1FETUFfQ0lSQ1VMQVJfREVTQ19TSVpFX01JTikgeworCQkJZGV2X2VycigmcGRldi0+ZGV2LCAi R2V0IHdyb25nIHF1ZXVlLXNpemVzLlxuIik7CisJCQlyZXR1cm4gTlVMTDsKKwkJfQorCQlxdWV1 ZV90ZW1wID0gcXVldWVfaGVhZCArIGk7CisJCXF1ZXVlX3RlbXAtPmNxID0gZG1hX2FsbG9jX2Nv aGVyZW50KCZwZGV2LT5kZXYsCisJCQkJCQlzaXplb2Yoc3RydWN0IGZzbF9xZG1hX2Zvcm1hdCkg KgorCQkJCQkJcXVldWVfc2l6ZVtpXSwKKwkJCQkJCSZxdWV1ZV90ZW1wLT5idXNfYWRkciwKKwkJ CQkJCUdGUF9LRVJORUwpOworCQlpZiAoIXF1ZXVlX3RlbXAtPmNxKSB7CisJCQlkZXZtX2tmcmVl KCZwZGV2LT5kZXYsIHF1ZXVlX2hlYWQpOworCQkJcmV0dXJuIE5VTEw7CisJCX0KKwkJcXVldWVf dGVtcC0+bl9jcSA9IHF1ZXVlX3NpemVbaV07CisJCXF1ZXVlX3RlbXAtPmlkID0gaTsKKwkJcXVl dWVfdGVtcC0+dmlydF9oZWFkID0gcXVldWVfdGVtcC0+Y3E7CisJCXF1ZXVlX3RlbXAtPnZpcnRf dGFpbCA9IHF1ZXVlX3RlbXAtPmNxOworCisJCS8qCisJCSAqIENyZWF0ZSBhIGNvbXAgZG1hIHBv b2wgdGhhdCBzaXplCisJCSAqIGlzICdGU0xfUURNQV9CQVNFX0JVRkZFUl9TSVpFJy4KKwkJICog VGhlIGRtYSBwb29sIGZvciBxdWV1ZSBjb21tYW5kIGJ1ZmZlci4KKwkJICovCisJCXF1ZXVlX3Rl bXAtPmNvbXBfcG9vbCA9IGRtYV9wb29sX2NyZWF0ZSgiY29tcF9wb29sIiwKKwkJCQkJCSZwZGV2 LT5kZXYsCisJCQkJCQlGU0xfUURNQV9CQVNFX0JVRkZFUl9TSVpFLAorCQkJCQkJMTYsIDApOwor CQlpZiAoIXF1ZXVlX3RlbXAtPmNvbXBfcG9vbCkKKwkJCWdvdG8gZXJyOworCisJCS8qCisJCSAq IExpc3QgZm9yIHF1ZXVlIGNvbW1hbmQgYnVmZmVyCisJCSAqLworCQlJTklUX0xJU1RfSEVBRCgm cXVldWVfdGVtcC0+Y29tcF91c2VkKTsKKwkJSU5JVF9MSVNUX0hFQUQoJnF1ZXVlX3RlbXAtPmNv bXBfZnJlZSk7CisJCXNwaW5fbG9ja19pbml0KCZxdWV1ZV90ZW1wLT5xdWV1ZV9sb2NrKTsKKwl9 CisKKwlyZXR1cm4gcXVldWVfaGVhZDsKKworZXJyOgorCWlmIChpID09IDAgJiYgcXVldWVfdGVt cC0+Y29tcF9wb29sKQorCQlkbWFfcG9vbF9kZXN0cm95KHF1ZXVlX3RlbXAtPmNvbXBfcG9vbCk7 CisJd2hpbGUgKC0taSA+PSAxKSB7CisJCXF1ZXVlX3RlbXAgPSBxdWV1ZV9oZWFkICsgaTsKKwkJ aWYgKGkgPT0gMSAmJiB1bmxpa2VseShxdWV1ZV90ZW1wLT5jb21wX3Bvb2wpKQorCQkJZG1hX3Bv b2xfZGVzdHJveShxdWV1ZV90ZW1wLT5jb21wX3Bvb2wpOworCX0KKworCWRldl9lcnIoJnBkZXYt PmRldiwKKwkJInVuYWJsZSB0byBhbGxvY2F0ZSBjaGFubmVsICVkIGRlc2NyaXB0b3IgcG9vbFxu IiwKKwkJcXVldWVfdGVtcC0+aWQpOworCisJd2hpbGUgKC0taSA+PSAwKSB7CisJCXF1ZXVlX3Rl bXAgPSBxdWV1ZV9oZWFkICsgaTsKKwkJZG1hX2ZyZWVfY29oZXJlbnQoJnBkZXYtPmRldiwKKwkJ CQlzaXplb2Yoc3RydWN0IGZzbF9xZG1hX2Zvcm1hdCkgKgorCQkJCXF1ZXVlX3NpemVbaV0sCisJ CQkJcXVldWVfdGVtcC0+Y3EsCisJCQkJcXVldWVfdGVtcC0+YnVzX2FkZHIpOworCX0KKwlkZXZt X2tmcmVlKCZwZGV2LT5kZXYsIHF1ZXVlX2hlYWQpOworCXJldHVybiBOVUxMOworfQorCitzdGF0 aWMgc3RydWN0IGZzbF9xZG1hX3F1ZXVlICpmc2xfcWRtYV9wcmVwX3N0YXR1c19xdWV1ZSgKKwkJ CQkJCXN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCit7CisJc3RydWN0IGRldmljZV9ub2Rl ICpucCA9IHBkZXYtPmRldi5vZl9ub2RlOworCXN0cnVjdCBmc2xfcWRtYV9xdWV1ZSAqc3RhdHVz X2hlYWQ7CisJdW5zaWduZWQgaW50IHN0YXR1c19zaXplOworCWludCByZXQ7CisKKwlyZXQgPSBv Zl9wcm9wZXJ0eV9yZWFkX3UzMihucCwgInN0YXR1cy1zaXplcyIsICZzdGF0dXNfc2l6ZSk7CisJ aWYgKHJldCkgeworCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJDYW4ndCBnZXQgc3RhdHVzLXNpemVz LlxuIik7CisJCXJldHVybiBOVUxMOworCX0KKwlpZiAoc3RhdHVzX3NpemUgPiBGU0xfUURNQV9D SVJDVUxBUl9ERVNDX1NJWkVfTUFYCisJCQl8fCBzdGF0dXNfc2l6ZSA8IEZTTF9RRE1BX0NJUkNV TEFSX0RFU0NfU0laRV9NSU4pIHsKKwkJZGV2X2VycigmcGRldi0+ZGV2LCAiR2V0IHdyb25nIHN0 YXR1c19zaXplLlxuIik7CisJCXJldHVybiBOVUxMOworCX0KKwlzdGF0dXNfaGVhZCA9IGRldm1f a3phbGxvYygmcGRldi0+ZGV2LCBzaXplb2YoKnN0YXR1c19oZWFkKSwKKwkJCQkJCQkJR0ZQX0tF Uk5FTCk7CisJaWYgKCFzdGF0dXNfaGVhZCkKKwkJcmV0dXJuIE5VTEw7CisKKwkvKgorCSAqIEJ1 ZmZlciBmb3IgcXVldWUgY29tbWFuZAorCSAqLworCXN0YXR1c19oZWFkLT5jcSA9IGRtYV9hbGxv Y19jb2hlcmVudCgmcGRldi0+ZGV2LAorCQkJCQkJc2l6ZW9mKHN0cnVjdCBmc2xfcWRtYV9mb3Jt YXQpICoKKwkJCQkJCXN0YXR1c19zaXplLAorCQkJCQkJJnN0YXR1c19oZWFkLT5idXNfYWRkciwK KwkJCQkJCUdGUF9LRVJORUwpOworCWlmICghc3RhdHVzX2hlYWQtPmNxKSB7CisJCWRldm1fa2Zy ZWUoJnBkZXYtPmRldiwgc3RhdHVzX2hlYWQpOworCQlyZXR1cm4gTlVMTDsKKwl9CisKKwlzdGF0 dXNfaGVhZC0+bl9jcSA9IHN0YXR1c19zaXplOworCXN0YXR1c19oZWFkLT52aXJ0X2hlYWQgPSBz dGF0dXNfaGVhZC0+Y3E7CisJc3RhdHVzX2hlYWQtPnZpcnRfdGFpbCA9IHN0YXR1c19oZWFkLT5j cTsKKwlzdGF0dXNfaGVhZC0+Y29tcF9wb29sID0gTlVMTDsKKworCXJldHVybiBzdGF0dXNfaGVh ZDsKK30KKworc3RhdGljIGludCBmc2xfcWRtYV9oYWx0KHN0cnVjdCBmc2xfcWRtYV9lbmdpbmUg KmZzbF9xZG1hKQoreworCXZvaWQgX19pb21lbSAqY3RybCA9IGZzbF9xZG1hLT5jdHJsX2Jhc2U7 CisJdm9pZCBfX2lvbWVtICpibG9jayA9IGZzbF9xZG1hLT5ibG9ja19iYXNlOworCWludCBpLCBj b3VudCA9IEZTTF9RRE1BX0hBTFRfQ09VTlQ7CisJdTMyIHJlZzsKKworCS8qIERpc2FibGUgdGhl IGNvbW1hbmQgcXVldWUgYW5kIHdhaXQgZm9yIGlkbGUgc3RhdGUuICovCisJcmVnID0gcWRtYV9y ZWFkbChmc2xfcWRtYSwgY3RybCArIEZTTF9RRE1BX0RNUik7CisJcmVnIHw9IEZTTF9RRE1BX0RN Ul9EUUQ7CisJcWRtYV93cml0ZWwoZnNsX3FkbWEsIHJlZywgY3RybCArIEZTTF9RRE1BX0RNUik7 CisJZm9yIChpID0gMDsgaSA8IEZTTF9RRE1BX1FVRVVFX05VTV9NQVg7IGkrKykKKwkJcWRtYV93 cml0ZWwoZnNsX3FkbWEsIDAsIGJsb2NrICsgRlNMX1FETUFfQkNRTVIoaSkpOworCisJd2hpbGUg KDEpIHsKKwkJcmVnID0gcWRtYV9yZWFkbChmc2xfcWRtYSwgY3RybCArIEZTTF9RRE1BX0RTUik7 CisJCWlmICghKHJlZyAmIEZTTF9RRE1BX0RTUl9EQikpCisJCQlicmVhazsKKwkJaWYgKGNvdW50 LS0gPCAwKQorCQkJcmV0dXJuIC1FQlVTWTsKKwkJdWRlbGF5KDEwMCk7CisJfQorCisJLyogRGlz YWJsZSBzdGF0dXMgcXVldWUuICovCisJcWRtYV93cml0ZWwoZnNsX3FkbWEsIDAsIGJsb2NrICsg RlNMX1FETUFfQlNRTVIpOworCisJLyogQ2xlYXIgYWxsIGRldGVjdGVkIGV2ZW50cyBhbmQgaW50 ZXJydXB0cyBmb3IgYWxsIHF1ZXVlcy4gKi8KKwlxZG1hX3dyaXRlbChmc2xfcWRtYSwgRlNMX1FE TUFfQkNRSURSX0NMRUFSLAorCQkJCWJsb2NrICsgRlNMX1FETUFfQkNRSURSKDApKTsKKworCXJl dHVybiAwOworfQorCitzdGF0aWMgaW50IGZzbF9xZG1hX3F1ZXVlX3RyYW5zZmVyX2NvbXBsZXRl KHN0cnVjdCBmc2xfcWRtYV9lbmdpbmUgKmZzbF9xZG1hKQoreworCXN0cnVjdCBmc2xfcWRtYV9x dWV1ZSAqZnNsX3F1ZXVlID0gZnNsX3FkbWEtPnF1ZXVlOworCXN0cnVjdCBmc2xfcWRtYV9xdWV1 ZSAqZnNsX3N0YXR1cyA9IGZzbF9xZG1hLT5zdGF0dXM7CisJc3RydWN0IGZzbF9xZG1hX3F1ZXVl ICp0ZW1wX3F1ZXVlOworCXN0cnVjdCBmc2xfcWRtYV9jb21wICpmc2xfY29tcDsKKwlzdHJ1Y3Qg ZnNsX3FkbWFfZm9ybWF0ICpzdGF0dXNfYWRkcjsKKwlzdHJ1Y3QgZnNsX3FkbWFfZm9ybWF0ICpj c2dmX3NyYzsKKwlzdHJ1Y3QgZnNsX3ByZV9zdGF0dXMgcHJlOworCXZvaWQgX19pb21lbSAqYmxv Y2sgPSBmc2xfcWRtYS0+YmxvY2tfYmFzZTsKKwl1MzIgcmVnLCBpLCBjb3VudDsKKwlib29sIGR1 cGxpY2F0ZSwgZHVwbGljYXRlX2hhbmRsZTsKKworCW1lbXNldCgmcHJlLCAwLCBzaXplb2Yoc3Ry dWN0IGZzbF9wcmVfc3RhdHVzKSk7CisJY291bnQgPSBGU0xfUURNQV9NQVhfU0laRTsKKworCXdo aWxlIChjb3VudC0tKSB7CisJCWR1cGxpY2F0ZSA9IDA7CisKKwkJcmVnID0gcWRtYV9yZWFkbChm c2xfcWRtYSwgYmxvY2sgKyBGU0xfUURNQV9CU1FTUik7CisJCWlmIChyZWcgJiBGU0xfUURNQV9C U1FTUl9RRSkKKwkJCXJldHVybiAwOworCisJCXN0YXR1c19hZGRyID0gZnNsX3N0YXR1cy0+dmly dF9oZWFkOworCQlpZiAocWRtYV9jY2RmX2dldF9xdWV1ZShzdGF0dXNfYWRkcikgPT0gcHJlLnF1 ZXVlICYmCisJCQlxZG1hX2NjZGZfYWRkcl9nZXQ2NChzdGF0dXNfYWRkcikgPT0gcHJlLmFkZHIp CisJCQlkdXBsaWNhdGUgPSAxOworCisJCWkgPSBxZG1hX2NjZGZfZ2V0X3F1ZXVlKHN0YXR1c19h ZGRyKTsKKwkJcHJlLnF1ZXVlID0gcWRtYV9jY2RmX2dldF9xdWV1ZShzdGF0dXNfYWRkcik7CisJ CXByZS5hZGRyID0gcWRtYV9jY2RmX2FkZHJfZ2V0NjQoc3RhdHVzX2FkZHIpOworCQl0ZW1wX3F1 ZXVlID0gZnNsX3F1ZXVlICsgaTsKKwkJc3Bpbl9sb2NrKCZ0ZW1wX3F1ZXVlLT5xdWV1ZV9sb2Nr KTsKKwkJaWYgKGxpc3RfZW1wdHkoJnRlbXBfcXVldWUtPmNvbXBfdXNlZCkpIHsKKwkJCWlmICgh ZHVwbGljYXRlKSB7CisJCQkJc3Bpbl91bmxvY2soJnRlbXBfcXVldWUtPnF1ZXVlX2xvY2spOwor CQkJCXJldHVybiAtRUFHQUlOOworCQkJfQorCQl9IGVsc2UgeworCQkJZnNsX2NvbXAgPSBsaXN0 X2ZpcnN0X2VudHJ5KCZ0ZW1wX3F1ZXVlLT5jb21wX3VzZWQsCisJCQkJCQkJc3RydWN0IGZzbF9x ZG1hX2NvbXAsCisJCQkJCQkJbGlzdCk7CisJCQljc2dmX3NyYyA9IGZzbF9jb21wLT52aXJ0X2Fk ZHIgKyAyOworCQkJaWYgKGZzbF9jb21wLT5idXNfYWRkciArIDE2ICE9IHByZS5hZGRyKSB7CisJ CQkJaWYgKGR1cGxpY2F0ZSkgeworCQkJCQlzcGluX3VubG9jaygmdGVtcF9xdWV1ZS0+cXVldWVf bG9jayk7CisJCQkJCXJldHVybiAtRUFHQUlOOworCQkJCX0KKwkJCX0KKwkJfQorCisJCQlpZiAo ZHVwbGljYXRlKSB7CisJCQkJcmVnID0gcWRtYV9yZWFkbChmc2xfcWRtYSwgYmxvY2sgKworCQkJ CQkJRlNMX1FETUFfQlNRTVIpOworCQkJcmVnIHw9IEZTTF9RRE1BX0JTUU1SX0RJOworCQkJcWRt YV9kZXNjX2FkZHJfc2V0NjQoc3RhdHVzX2FkZHIsIDB4MCk7CisJCQlmc2xfc3RhdHVzLT52aXJ0 X2hlYWQrKzsKKwkJCWlmIChmc2xfc3RhdHVzLT52aXJ0X2hlYWQgPT0gZnNsX3N0YXR1cy0+Y3EK KwkJCQkJCSAgICsgZnNsX3N0YXR1cy0+bl9jcSkKKwkJCQlmc2xfc3RhdHVzLT52aXJ0X2hlYWQg PSBmc2xfc3RhdHVzLT5jcTsKKwkJCXFkbWFfd3JpdGVsKGZzbF9xZG1hLCByZWcsIGJsb2NrICsg RlNMX1FETUFfQlNRTVIpOworCQkJc3Bpbl91bmxvY2soJnRlbXBfcXVldWUtPnF1ZXVlX2xvY2sp OworCQkJY29udGludWU7CisJCX0KKwkJbGlzdF9kZWwoJmZzbF9jb21wLT5saXN0KTsKKworCQly ZWcgPSBxZG1hX3JlYWRsKGZzbF9xZG1hLCBibG9jayArIEZTTF9RRE1BX0JTUU1SKTsKKwkJcmVn IHw9IEZTTF9RRE1BX0JTUU1SX0RJOworCQlxZG1hX2Rlc2NfYWRkcl9zZXQ2NChzdGF0dXNfYWRk ciwgMHgwKTsKKwkJZnNsX3N0YXR1cy0+dmlydF9oZWFkKys7CisJCWlmIChmc2xfc3RhdHVzLT52 aXJ0X2hlYWQgPT0gZnNsX3N0YXR1cy0+Y3EgKyBmc2xfc3RhdHVzLT5uX2NxKQorCQkJZnNsX3N0 YXR1cy0+dmlydF9oZWFkID0gZnNsX3N0YXR1cy0+Y3E7CisJCXFkbWFfd3JpdGVsKGZzbF9xZG1h LCByZWcsIGJsb2NrICsgRlNMX1FETUFfQlNRTVIpOworCQlzcGluX3VubG9jaygmdGVtcF9xdWV1 ZS0+cXVldWVfbG9jayk7CisKKwkJc3Bpbl9sb2NrKCZmc2xfY29tcC0+cWNoYW4tPnZjaGFuLmxv Y2spOworCQl2Y2hhbl9jb29raWVfY29tcGxldGUoJmZzbF9jb21wLT52ZGVzYyk7CisJCWZzbF9j b21wLT5xY2hhbi0+c3RhdHVzID0gRE1BX0NPTVBMRVRFOworCQlzcGluX3VubG9jaygmZnNsX2Nv bXAtPnFjaGFuLT52Y2hhbi5sb2NrKTsKKwl9CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGljIGly cXJldHVybl90IGZzbF9xZG1hX2Vycm9yX2hhbmRsZXIoaW50IGlycSwgdm9pZCAqZGV2X2lkKQor eworCXN0cnVjdCBmc2xfcWRtYV9lbmdpbmUgKmZzbF9xZG1hID0gZGV2X2lkOworCXVuc2lnbmVk IGludCBpbnRyOworCXZvaWQgX19pb21lbSAqc3RhdHVzID0gZnNsX3FkbWEtPnN0YXR1c19iYXNl OworCisJaW50ciA9IHFkbWFfcmVhZGwoZnNsX3FkbWEsIHN0YXR1cyArIEZTTF9RRE1BX0RFRFIp OworCisJaWYgKGludHIpCisJCWRldl9lcnIoZnNsX3FkbWEtPmRtYV9kZXYuZGV2LCAiRE1BIHRy YW5zYWN0aW9uIGVycm9yIVxuIik7CisKKwkvKiBDbGVhciBhbGwgZXJyb3IgY29uZGl0aW9ucyBh bmQgaW50ZXJydXB0cy4gKi8KKwlxZG1hX3dyaXRlbChmc2xfcWRtYSwgRlNMX1FETUFfREVEUl9D TEVBUiwgc3RhdHVzICsgRlNMX1FETUFfREVEUik7CisKKwlyZXR1cm4gSVJRX0hBTkRMRUQ7Cit9 CisKK3N0YXRpYyBpcnFyZXR1cm5fdCBmc2xfcWRtYV9xdWV1ZV9oYW5kbGVyKGludCBpcnEsIHZv aWQgKmRldl9pZCkKK3sKKwlzdHJ1Y3QgZnNsX3FkbWFfZW5naW5lICpmc2xfcWRtYSA9IGRldl9p ZDsKKwl1bnNpZ25lZCBpbnQgaW50ciwgcmVnOworCXZvaWQgX19pb21lbSAqYmxvY2sgPSBmc2xf cWRtYS0+YmxvY2tfYmFzZTsKKwl2b2lkIF9faW9tZW0gKmN0cmwgPSBmc2xfcWRtYS0+Y3RybF9i YXNlOworCisJaW50ciA9IHFkbWFfcmVhZGwoZnNsX3FkbWEsIGJsb2NrICsgRlNMX1FETUFfQkNR SURSKDApKTsKKworCWlmICgoaW50ciAmIEZTTF9RRE1BX0NRSURSX1NRVCkgIT0gMCkKKwkJaW50 ciA9IGZzbF9xZG1hX3F1ZXVlX3RyYW5zZmVyX2NvbXBsZXRlKGZzbF9xZG1hKTsKKworCWlmIChp bnRyICE9IDApIHsKKwkJcmVnID0gcWRtYV9yZWFkbChmc2xfcWRtYSwgY3RybCArIEZTTF9RRE1B X0RNUik7CisJCXJlZyB8PSBGU0xfUURNQV9ETVJfRFFEOworCQlxZG1hX3dyaXRlbChmc2xfcWRt YSwgcmVnLCBjdHJsICsgRlNMX1FETUFfRE1SKTsKKwkJcWRtYV93cml0ZWwoZnNsX3FkbWEsIDAs IGJsb2NrICsgRlNMX1FETUFfQkNRSUVSKDApKTsKKwkJZGV2X2Vycihmc2xfcWRtYS0+ZG1hX2Rl di5kZXYsICJRRE1BOiBzdGF0dXMgZXJyIVxuIik7CisJfQorCisJLyogQ2xlYXIgYWxsIGRldGVj dGVkIGV2ZW50cyBhbmQgaW50ZXJydXB0cy4gKi8KKwlxZG1hX3dyaXRlbChmc2xfcWRtYSwgRlNM X1FETUFfQkNRSURSX0NMRUFSLAorCQkJCWJsb2NrICsgRlNMX1FETUFfQkNRSURSKDApKTsKKwor CXJldHVybiBJUlFfSEFORExFRDsKK30KKworc3RhdGljIGludAorZnNsX3FkbWFfaXJxX2luaXQo c3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldiwKKwkJICBzdHJ1Y3QgZnNsX3FkbWFfZW5naW5l ICpmc2xfcWRtYSkKK3sKKwlpbnQgcmV0OworCisJZnNsX3FkbWEtPmVycm9yX2lycSA9IHBsYXRm b3JtX2dldF9pcnFfYnluYW1lKHBkZXYsCisJCQkJCQkJInFkbWEtZXJyb3IiKTsKKwlpZiAoZnNs X3FkbWEtPmVycm9yX2lycSA8IDApIHsKKwkJZGV2X2VycigmcGRldi0+ZGV2LCAiQ2FuJ3QgZ2V0 IHFkbWEgY29udHJvbGxlciBpcnEuXG4iKTsKKwkJcmV0dXJuIGZzbF9xZG1hLT5lcnJvcl9pcnE7 CisJfQorCisJZnNsX3FkbWEtPnF1ZXVlX2lycSA9IHBsYXRmb3JtX2dldF9pcnFfYnluYW1lKHBk ZXYsICJxZG1hLXF1ZXVlIik7CisJaWYgKGZzbF9xZG1hLT5xdWV1ZV9pcnEgPCAwKSB7CisJCWRl dl9lcnIoJnBkZXYtPmRldiwgIkNhbid0IGdldCBxZG1hIHF1ZXVlIGlycS5cbiIpOworCQlyZXR1 cm4gZnNsX3FkbWEtPnF1ZXVlX2lycTsKKwl9CisKKwlyZXQgPSBkZXZtX3JlcXVlc3RfaXJxKCZw ZGV2LT5kZXYsIGZzbF9xZG1hLT5lcnJvcl9pcnEsCisJCQlmc2xfcWRtYV9lcnJvcl9oYW5kbGVy LCAwLCAicURNQSBlcnJvciIsIGZzbF9xZG1hKTsKKwlpZiAocmV0KSB7CisJCWRldl9lcnIoJnBk ZXYtPmRldiwgIkNhbid0IHJlZ2lzdGVyIHFETUEgY29udHJvbGxlciBJUlEuXG4iKTsKKwkJcmV0 dXJuICByZXQ7CisJfQorCXJldCA9IGRldm1fcmVxdWVzdF9pcnEoJnBkZXYtPmRldiwgZnNsX3Fk bWEtPnF1ZXVlX2lycSwKKwkJCWZzbF9xZG1hX3F1ZXVlX2hhbmRsZXIsIDAsICJxRE1BIHF1ZXVl IiwgZnNsX3FkbWEpOworCWlmIChyZXQpIHsKKwkJZGV2X2VycigmcGRldi0+ZGV2LCAiQ2FuJ3Qg cmVnaXN0ZXIgcURNQSBxdWV1ZSBJUlEuXG4iKTsKKwkJcmV0dXJuICByZXQ7CisJfQorCisJcmV0 dXJuIDA7Cit9CisKK3N0YXRpYyB2b2lkIGZzbF9xZG1hX2lycV9leGl0KAorCQlzdHJ1Y3QgcGxh dGZvcm1fZGV2aWNlICpwZGV2LCBzdHJ1Y3QgZnNsX3FkbWFfZW5naW5lICpmc2xfcWRtYSkKK3sK KwlpZiAoZnNsX3FkbWEtPnF1ZXVlX2lycSA9PSBmc2xfcWRtYS0+ZXJyb3JfaXJxKSB7CisJCWRl dm1fZnJlZV9pcnEoJnBkZXYtPmRldiwgZnNsX3FkbWEtPnF1ZXVlX2lycSwgZnNsX3FkbWEpOwor CX0gZWxzZSB7CisJCWRldm1fZnJlZV9pcnEoJnBkZXYtPmRldiwgZnNsX3FkbWEtPnF1ZXVlX2ly cSwgZnNsX3FkbWEpOworCQlkZXZtX2ZyZWVfaXJxKCZwZGV2LT5kZXYsIGZzbF9xZG1hLT5lcnJv cl9pcnEsIGZzbF9xZG1hKTsKKwl9Cit9CisKK3N0YXRpYyBpbnQgZnNsX3FkbWFfcmVnX2luaXQo c3RydWN0IGZzbF9xZG1hX2VuZ2luZSAqZnNsX3FkbWEpCit7CisJc3RydWN0IGZzbF9xZG1hX3F1 ZXVlICpmc2xfcXVldWUgPSBmc2xfcWRtYS0+cXVldWU7CisJc3RydWN0IGZzbF9xZG1hX3F1ZXVl ICp0ZW1wOworCXZvaWQgX19pb21lbSAqY3RybCA9IGZzbF9xZG1hLT5jdHJsX2Jhc2U7CisJdm9p ZCBfX2lvbWVtICpzdGF0dXMgPSBmc2xfcWRtYS0+c3RhdHVzX2Jhc2U7CisJdm9pZCBfX2lvbWVt ICpibG9jayA9IGZzbF9xZG1hLT5ibG9ja19iYXNlOworCWludCBpLCByZXQ7CisJdTMyIHJlZzsK KworCS8qIFRyeSB0byBoYWx0IHRoZSBxRE1BIGVuZ2luZSBmaXJzdC4gKi8KKwlyZXQgPSBmc2xf cWRtYV9oYWx0KGZzbF9xZG1hKTsKKwlpZiAocmV0KSB7CisJCWRldl9lcnIoZnNsX3FkbWEtPmRt YV9kZXYuZGV2LCAiRE1BIGhhbHQgZmFpbGVkISIpOworCQlyZXR1cm4gcmV0OworCX0KKworCS8q IENsZWFyIGFsbCBkZXRlY3RlZCBldmVudHMgYW5kIGludGVycnVwdHMgZm9yIGFsbCBxdWV1ZXMu ICovCisJcWRtYV93cml0ZWwoZnNsX3FkbWEsIEZTTF9RRE1BX0JDUUlEUl9DTEVBUiwKKwkJCQli bG9jayArIEZTTF9RRE1BX0JDUUlEUigwKSk7CisKKwlmb3IgKGkgPSAwOyBpIDwgZnNsX3FkbWEt Pm5fcXVldWVzOyBpKyspIHsKKwkJdGVtcCA9IGZzbF9xdWV1ZSArIGk7CisJCS8qCisJCSAqIElu aXRpYWxpemUgQ29tbWFuZCBRdWV1ZSByZWdpc3RlcnMgdG8gcG9pbnQgdG8gdGhlIGZpcnN0CisJ CSAqIGNvbW1hbmQgZGVzY3JpcHRvciBpbiBtZW1vcnkuCisJCSAqIERlcXVldWUgUG9pbnRlciBB ZGRyZXNzIFJlZ2lzdGVycworCQkgKiBFbnF1ZXVlIFBvaW50ZXIgQWRkcmVzcyBSZWdpc3RlcnMK KwkJICovCisJCXFkbWFfd3JpdGVsKGZzbF9xZG1hLCB0ZW1wLT5idXNfYWRkciwKKwkJCQlibG9j ayArIEZTTF9RRE1BX0JDUURQQV9TQUREUihpKSk7CisJCXFkbWFfd3JpdGVsKGZzbF9xZG1hLCB0 ZW1wLT5idXNfYWRkciwKKwkJCQlibG9jayArIEZTTF9RRE1BX0JDUUVQQV9TQUREUihpKSk7CisK KwkJLyogSW5pdGlhbGl6ZSB0aGUgcXVldWUgbW9kZS4gKi8KKwkJcmVnID0gRlNMX1FETUFfQkNR TVJfRU47CisJCXJlZyB8PSBGU0xfUURNQV9CQ1FNUl9DRF9USExEKGlsb2cyKHRlbXAtPm5fY3Ep IC0gNCk7CisJCXJlZyB8PSBGU0xfUURNQV9CQ1FNUl9DUV9TSVpFKGlsb2cyKHRlbXAtPm5fY3Ep IC0gNik7CisJCXFkbWFfd3JpdGVsKGZzbF9xZG1hLCByZWcsIGJsb2NrICsgRlNMX1FETUFfQkNR TVIoaSkpOworCX0KKworCS8qCisJICogV29ya2Fyb3VuZCBmb3IgZXJyYXR1bTogRVJSMDEwODEy LgorCSAqIFdlIG11c3QgZW5hYmxlIFhPRkYgdG8gYXZvaWQgdGhlIGVucXVldWUgcmVqZWN0aW9u IG9jY3Vycy4KKwkgKiBTZXR0aW5nIFNRQ0NNUiBFTlRFUl9XTSB0byAweDIwLgorCSAqLworCXFk bWFfd3JpdGVsKGZzbF9xZG1hLCBGU0xfUURNQV9TUUNDTVJfRU5URVJfV00sCisJCQkgICAgICBi bG9jayArIEZTTF9RRE1BX1NRQ0NNUik7CisJLyoKKwkgKiBJbml0aWFsaXplIHN0YXR1cyBxdWV1 ZSByZWdpc3RlcnMgdG8gcG9pbnQgdG8gdGhlIGZpcnN0CisJICogY29tbWFuZCBkZXNjcmlwdG9y IGluIG1lbW9yeS4KKwkgKiBEZXF1ZXVlIFBvaW50ZXIgQWRkcmVzcyBSZWdpc3RlcnMKKwkgKiBF bnF1ZXVlIFBvaW50ZXIgQWRkcmVzcyBSZWdpc3RlcnMKKwkgKi8KKwlxZG1hX3dyaXRlbChmc2xf cWRtYSwgZnNsX3FkbWEtPnN0YXR1cy0+YnVzX2FkZHIsCisJCQkJCWJsb2NrICsgRlNMX1FETUFf U1FFUEFSKTsKKwlxZG1hX3dyaXRlbChmc2xfcWRtYSwgZnNsX3FkbWEtPnN0YXR1cy0+YnVzX2Fk ZHIsCisJCQkJCWJsb2NrICsgRlNMX1FETUFfU1FEUEFSKTsKKwkvKiBJbml0aWFsaXplIHN0YXR1 cyBxdWV1ZSBpbnRlcnJ1cHQuICovCisJcWRtYV93cml0ZWwoZnNsX3FkbWEsIEZTTF9RRE1BX0JD UUlFUl9DUVRJRSwKKwkJCSAgICAgIGJsb2NrICsgRlNMX1FETUFfQkNRSUVSKDApKTsKKwlxZG1h X3dyaXRlbChmc2xfcWRtYSwgRlNMX1FETUFfQlNRSUNSX0lDRU4gfCBGU0xfUURNQV9CU1FJQ1Jf SUNTVCg1KQorCQkJCQkJICAgfCAweDgwMDAsCisJCQkgICAgICBibG9jayArIEZTTF9RRE1BX0JT UUlDUik7CisJcWRtYV93cml0ZWwoZnNsX3FkbWEsIEZTTF9RRE1BX0NRSUVSX01FSUUgfCBGU0xf UURNQV9DUUlFUl9URUlFLAorCQkJICAgICAgYmxvY2sgKyBGU0xfUURNQV9DUUlFUik7CisJLyog SW5pdGlhbGl6ZSBjb250cm9sbGVyIGludGVycnVwdCByZWdpc3Rlci4gKi8KKwlxZG1hX3dyaXRl bChmc2xfcWRtYSwgRlNMX1FETUFfREVEUl9DTEVBUiwgc3RhdHVzICsgRlNMX1FETUFfREVEUik7 CisJcWRtYV93cml0ZWwoZnNsX3FkbWEsIEZTTF9RRE1BX0RFSUVSX0NMRUFSLCBzdGF0dXMgKyBG U0xfUURNQV9ERUlFUik7CisKKwkvKiBJbml0aWFsaXplIHRoZSBzdGF0dXMgcXVldWUgbW9kZS4g Ki8KKwlyZWcgPSBGU0xfUURNQV9CU1FNUl9FTjsKKwlyZWcgfD0gRlNMX1FETUFfQlNRTVJfQ1Ff U0laRShpbG9nMihmc2xfcWRtYS0+c3RhdHVzLT5uX2NxKS02KTsKKwlxZG1hX3dyaXRlbChmc2xf cWRtYSwgcmVnLCBibG9jayArIEZTTF9RRE1BX0JTUU1SKTsKKworCXJlZyA9IHFkbWFfcmVhZGwo ZnNsX3FkbWEsIGN0cmwgKyBGU0xfUURNQV9ETVIpOworCXJlZyAmPSB+RlNMX1FETUFfRE1SX0RR RDsKKwlxZG1hX3dyaXRlbChmc2xfcWRtYSwgcmVnLCBjdHJsICsgRlNMX1FETUFfRE1SKTsKKwor CXJldHVybiAwOworfQorCitzdGF0aWMgc3RydWN0IGRtYV9hc3luY190eF9kZXNjcmlwdG9yICoK K2ZzbF9xZG1hX3ByZXBfbWVtY3B5KHN0cnVjdCBkbWFfY2hhbiAqY2hhbiwgZG1hX2FkZHJfdCBk c3QsCisJCWRtYV9hZGRyX3Qgc3JjLCBzaXplX3QgbGVuLCB1bnNpZ25lZCBsb25nIGZsYWdzKQor eworCXN0cnVjdCBmc2xfcWRtYV9jaGFuICpmc2xfY2hhbiA9IHRvX2ZzbF9xZG1hX2NoYW4oY2hh bik7CisJc3RydWN0IGZzbF9xZG1hX2NvbXAgKmZzbF9jb21wOworCisJZnNsX2NvbXAgPSBmc2xf cWRtYV9yZXF1ZXN0X2VucXVldWVfZGVzYyhmc2xfY2hhbiwgMCwgMCk7CisJZnNsX3FkbWFfY29t cF9maWxsX21lbWNweShmc2xfY29tcCwgZHN0LCBzcmMsIGxlbik7CisKKwlyZXR1cm4gdmNoYW5f dHhfcHJlcCgmZnNsX2NoYW4tPnZjaGFuLCAmZnNsX2NvbXAtPnZkZXNjLCBmbGFncyk7Cit9CisK K3N0YXRpYyB2b2lkIGZzbF9xZG1hX2VucXVldWVfZGVzYyhzdHJ1Y3QgZnNsX3FkbWFfY2hhbiAq ZnNsX2NoYW4pCit7CisJdm9pZCBfX2lvbWVtICpibG9jayA9IGZzbF9jaGFuLT5xZG1hLT5ibG9j a19iYXNlOworCXN0cnVjdCBmc2xfcWRtYV9xdWV1ZSAqZnNsX3F1ZXVlID0gZnNsX2NoYW4tPnF1 ZXVlOworCXN0cnVjdCBmc2xfcWRtYV9jb21wICpmc2xfY29tcDsKKwlzdHJ1Y3QgdmlydF9kbWFf ZGVzYyAqdmRlc2M7CisJdTMyIHJlZzsKKworCXJlZyA9IHFkbWFfcmVhZGwoZnNsX2NoYW4tPnFk bWEsIGJsb2NrICsgRlNMX1FETUFfQkNRU1IoZnNsX3F1ZXVlLT5pZCkpOworCWlmIChyZWcgJiAo RlNMX1FETUFfQkNRU1JfUUYgfCBGU0xfUURNQV9CQ1FTUl9YT0ZGKSkKKwkJcmV0dXJuOworCXZk ZXNjID0gdmNoYW5fbmV4dF9kZXNjKCZmc2xfY2hhbi0+dmNoYW4pOworCWlmICghdmRlc2MpCisJ CXJldHVybjsKKwlsaXN0X2RlbCgmdmRlc2MtPm5vZGUpOworCWZzbF9jb21wID0gdG9fZnNsX3Fk bWFfY29tcCh2ZGVzYyk7CisKKwltZW1jcHkoZnNsX3F1ZXVlLT52aXJ0X2hlYWQrKywgZnNsX2Nv bXAtPnZpcnRfYWRkciwKKwkJCQkJc2l6ZW9mKHN0cnVjdCBmc2xfcWRtYV9mb3JtYXQpKTsKKwlp ZiAoZnNsX3F1ZXVlLT52aXJ0X2hlYWQgPT0gZnNsX3F1ZXVlLT5jcSArIGZzbF9xdWV1ZS0+bl9j cSkKKwkJZnNsX3F1ZXVlLT52aXJ0X2hlYWQgPSBmc2xfcXVldWUtPmNxOworCisJbGlzdF9hZGRf dGFpbCgmZnNsX2NvbXAtPmxpc3QsICZmc2xfcXVldWUtPmNvbXBfdXNlZCk7CisJYmFycmllcigp OworCXJlZyA9IHFkbWFfcmVhZGwoZnNsX2NoYW4tPnFkbWEsIGJsb2NrICsgRlNMX1FETUFfQkNR TVIoZnNsX3F1ZXVlLT5pZCkpOworCXJlZyB8PSBGU0xfUURNQV9CQ1FNUl9FSTsKKwlxZG1hX3dy aXRlbChmc2xfY2hhbi0+cWRtYSwgcmVnLCBibG9jayArIEZTTF9RRE1BX0JDUU1SKGZzbF9xdWV1 ZS0+aWQpKTsKKwlmc2xfY2hhbi0+c3RhdHVzID0gRE1BX0lOX1BST0dSRVNTOworfQorCitzdGF0 aWMgZW51bSBkbWFfc3RhdHVzIGZzbF9xZG1hX3R4X3N0YXR1cyhzdHJ1Y3QgZG1hX2NoYW4gKmNo YW4sCisJCWRtYV9jb29raWVfdCBjb29raWUsIHN0cnVjdCBkbWFfdHhfc3RhdGUgKnR4c3RhdGUp Cit7CisJZW51bSBkbWFfc3RhdHVzIHJldDsKKworCXJldCA9IGRtYV9jb29raWVfc3RhdHVzKGNo YW4sIGNvb2tpZSwgdHhzdGF0ZSk7CisJaWYgKHJldCA9PSBETUFfQ09NUExFVEUgfHwgIXR4c3Rh dGUpCisJCXJldHVybiByZXQ7CisKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgdm9pZCBmc2xf cWRtYV9mcmVlX2Rlc2Moc3RydWN0IHZpcnRfZG1hX2Rlc2MgKnZkZXNjKQoreworCXN0cnVjdCBm c2xfcWRtYV9jb21wICpmc2xfY29tcDsKKwlzdHJ1Y3QgZnNsX3FkbWFfcXVldWUgKmZzbF9xdWV1 ZTsKKwl1bnNpZ25lZCBsb25nIGZsYWdzOworCisJZnNsX2NvbXAgPSB0b19mc2xfcWRtYV9jb21w KHZkZXNjKTsKKwlmc2xfcXVldWUgPSBmc2xfY29tcC0+cWNoYW4tPnF1ZXVlOworCisJc3Bpbl9s b2NrX2lycXNhdmUoJmZzbF9xdWV1ZS0+cXVldWVfbG9jaywgZmxhZ3MpOworCWxpc3RfYWRkX3Rh aWwoJmZzbF9jb21wLT5saXN0LCAmZnNsX3F1ZXVlLT5jb21wX2ZyZWUpOworCXNwaW5fdW5sb2Nr X2lycXJlc3RvcmUoJmZzbF9xdWV1ZS0+cXVldWVfbG9jaywgZmxhZ3MpOworfQorCitzdGF0aWMg dm9pZCBmc2xfcWRtYV9pc3N1ZV9wZW5kaW5nKHN0cnVjdCBkbWFfY2hhbiAqY2hhbikKK3sKKwlz dHJ1Y3QgZnNsX3FkbWFfY2hhbiAqZnNsX2NoYW4gPSB0b19mc2xfcWRtYV9jaGFuKGNoYW4pOwor CXN0cnVjdCBmc2xfcWRtYV9xdWV1ZSAqZnNsX3F1ZXVlID0gZnNsX2NoYW4tPnF1ZXVlOworCXVu c2lnbmVkIGxvbmcgZmxhZ3M7CisKKwlzcGluX2xvY2tfaXJxc2F2ZSgmZnNsX3F1ZXVlLT5xdWV1 ZV9sb2NrLCBmbGFncyk7CisJc3Bpbl9sb2NrKCZmc2xfY2hhbi0+dmNoYW4ubG9jayk7CisJaWYg KHZjaGFuX2lzc3VlX3BlbmRpbmcoJmZzbF9jaGFuLT52Y2hhbikpCisJCWZzbF9xZG1hX2VucXVl dWVfZGVzYyhmc2xfY2hhbik7CisJc3Bpbl91bmxvY2soJmZzbF9jaGFuLT52Y2hhbi5sb2NrKTsK KwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZmc2xfcXVldWUtPnF1ZXVlX2xvY2ssIGZsYWdzKTsK K30KKworc3RhdGljIGludCBmc2xfcWRtYV9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpw ZGV2KQoreworCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbnAgPSBwZGV2LT5kZXYub2Zfbm9kZTsKKwlz dHJ1Y3QgZnNsX3FkbWFfZW5naW5lICpmc2xfcWRtYTsKKwlzdHJ1Y3QgZnNsX3FkbWFfY2hhbiAq ZnNsX2NoYW47CisJc3RydWN0IHJlc291cmNlICpyZXM7CisJdW5zaWduZWQgaW50IGxlbiwgY2hh bnMsIHF1ZXVlczsKKwlpbnQgcmV0LCBpOworCisJcmV0ID0gb2ZfcHJvcGVydHlfcmVhZF91MzIo bnAsICJkbWEtY2hhbm5lbHMiLCAmY2hhbnMpOworCWlmIChyZXQpIHsKKwkJZGV2X2VycigmcGRl di0+ZGV2LCAiQ2FuJ3QgZ2V0IGRtYS1jaGFubmVscy5cbiIpOworCQlyZXR1cm4gcmV0OworCX0K KworCWxlbiA9IHNpemVvZigqZnNsX3FkbWEpICsgc2l6ZW9mKCpmc2xfY2hhbikgKiBjaGFuczsK Kwlmc2xfcWRtYSA9IGRldm1fa3phbGxvYygmcGRldi0+ZGV2LCBsZW4sIEdGUF9LRVJORUwpOwor CWlmICghZnNsX3FkbWEpCisJCXJldHVybiAtRU5PTUVNOworCisJcmV0ID0gb2ZfcHJvcGVydHlf cmVhZF91MzIobnAsICJmc2wscXVldWVzIiwgJnF1ZXVlcyk7CisJaWYgKHJldCkgeworCQlkZXZf ZXJyKCZwZGV2LT5kZXYsICJDYW4ndCBnZXQgcXVldWVzLlxuIik7CisJCXJldHVybiByZXQ7CisJ fQorCisJZnNsX3FkbWEtPnF1ZXVlID0gZnNsX3FkbWFfYWxsb2NfcXVldWVfcmVzb3VyY2VzKHBk ZXYsIHF1ZXVlcyk7CisJaWYgKCFmc2xfcWRtYS0+cXVldWUpCisJCXJldHVybiAtRU5PTUVNOwor CisJZnNsX3FkbWEtPnN0YXR1cyA9IGZzbF9xZG1hX3ByZXBfc3RhdHVzX3F1ZXVlKHBkZXYpOwor CWlmICghZnNsX3FkbWEtPnN0YXR1cykKKwkJcmV0dXJuIC1FTk9NRU07CisKKwlmc2xfcWRtYS0+ bl9jaGFucyA9IGNoYW5zOworCWZzbF9xZG1hLT5uX3F1ZXVlcyA9IHF1ZXVlczsKKwltdXRleF9p bml0KCZmc2xfcWRtYS0+ZnNsX3FkbWFfbXV0ZXgpOworCisJcmVzID0gcGxhdGZvcm1fZ2V0X3Jl c291cmNlKHBkZXYsIElPUkVTT1VSQ0VfTUVNLCAwKTsKKwlmc2xfcWRtYS0+Y3RybF9iYXNlID0g ZGV2bV9pb3JlbWFwX3Jlc291cmNlKCZwZGV2LT5kZXYsIHJlcyk7CisJaWYgKElTX0VSUihmc2xf cWRtYS0+Y3RybF9iYXNlKSkKKwkJcmV0dXJuIFBUUl9FUlIoZnNsX3FkbWEtPmN0cmxfYmFzZSk7 CisKKwlyZXMgPSBwbGF0Zm9ybV9nZXRfcmVzb3VyY2UocGRldiwgSU9SRVNPVVJDRV9NRU0sIDEp OworCWZzbF9xZG1hLT5zdGF0dXNfYmFzZSA9IGRldm1faW9yZW1hcF9yZXNvdXJjZSgmcGRldi0+ ZGV2LCByZXMpOworCWlmIChJU19FUlIoZnNsX3FkbWEtPnN0YXR1c19iYXNlKSkKKwkJcmV0dXJu IFBUUl9FUlIoZnNsX3FkbWEtPnN0YXR1c19iYXNlKTsKKworCXJlcyA9IHBsYXRmb3JtX2dldF9y ZXNvdXJjZShwZGV2LCBJT1JFU09VUkNFX01FTSwgMik7CisJZnNsX3FkbWEtPmJsb2NrX2Jhc2Ug PSBkZXZtX2lvcmVtYXBfcmVzb3VyY2UoJnBkZXYtPmRldiwgcmVzKTsKKwlpZiAoSVNfRVJSKGZz bF9xZG1hLT5ibG9ja19iYXNlKSkKKwkJcmV0dXJuIFBUUl9FUlIoZnNsX3FkbWEtPmJsb2NrX2Jh c2UpOworCisJcmV0ID0gZnNsX3FkbWFfaXJxX2luaXQocGRldiwgZnNsX3FkbWEpOworCWlmIChy ZXQpCisJCXJldHVybiByZXQ7CisKKwlmc2xfcWRtYS0+ZmVhdHVyZSA9IG9mX3Byb3BlcnR5X3Jl YWRfYm9vbChucCwgImJpZy1lbmRpYW4iKTsKKwlJTklUX0xJU1RfSEVBRCgmZnNsX3FkbWEtPmRt YV9kZXYuY2hhbm5lbHMpOworCWZvciAoaSA9IDA7IGkgPCBmc2xfcWRtYS0+bl9jaGFuczsgaSsr KSB7CisJCXN0cnVjdCBmc2xfcWRtYV9jaGFuICpmc2xfY2hhbiA9ICZmc2xfcWRtYS0+Y2hhbnNb aV07CisKKwkJZnNsX2NoYW4tPnFkbWEgPSBmc2xfcWRtYTsKKwkJZnNsX2NoYW4tPnF1ZXVlID0g ZnNsX3FkbWEtPnF1ZXVlICsgaSAlIGZzbF9xZG1hLT5uX3F1ZXVlczsKKwkJZnNsX2NoYW4tPnZj aGFuLmRlc2NfZnJlZSA9IGZzbF9xZG1hX2ZyZWVfZGVzYzsKKwkJSU5JVF9MSVNUX0hFQUQoJmZz bF9jaGFuLT5xY29tcCk7CisJCXZjaGFuX2luaXQoJmZzbF9jaGFuLT52Y2hhbiwgJmZzbF9xZG1h LT5kbWFfZGV2KTsKKwl9CisJZm9yIChpID0gMDsgaSA8IGZzbF9xZG1hLT5uX3F1ZXVlczsgaSsr KQorCQlmc2xfcWRtYV9wcmVfcmVxdWVzdF9lbnF1ZXVlX2Rlc2MoZnNsX3FkbWEtPnF1ZXVlICsg aSk7CisKKwlkbWFfY2FwX3NldChETUFfTUVNQ1BZLCBmc2xfcWRtYS0+ZG1hX2Rldi5jYXBfbWFz ayk7CisKKwlmc2xfcWRtYS0+ZG1hX2Rldi5kZXYgPSAmcGRldi0+ZGV2OworCWZzbF9xZG1hLT5k bWFfZGV2LmRldmljZV9mcmVlX2NoYW5fcmVzb3VyY2VzCisJCT0gZnNsX3FkbWFfZnJlZV9jaGFu X3Jlc291cmNlczsKKwlmc2xfcWRtYS0+ZG1hX2Rldi5kZXZpY2VfdHhfc3RhdHVzID0gZnNsX3Fk bWFfdHhfc3RhdHVzOworCWZzbF9xZG1hLT5kbWFfZGV2LmRldmljZV9wcmVwX2RtYV9tZW1jcHkg PSBmc2xfcWRtYV9wcmVwX21lbWNweTsKKwlmc2xfcWRtYS0+ZG1hX2Rldi5kZXZpY2VfaXNzdWVf cGVuZGluZyA9IGZzbF9xZG1hX2lzc3VlX3BlbmRpbmc7CisKKwlkbWFfc2V0X21hc2soJnBkZXYt PmRldiwgRE1BX0JJVF9NQVNLKDQwKSk7CisKKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2LCBm c2xfcWRtYSk7CisKKwlyZXQgPSBkbWFfYXN5bmNfZGV2aWNlX3JlZ2lzdGVyKCZmc2xfcWRtYS0+ ZG1hX2Rldik7CisJaWYgKHJldCkgeworCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJDYW4ndCByZWdp c3RlciBOWFAgTGF5ZXJzY2FwZSBxRE1BIGVuZ2luZS5cbiIpOworCQlyZXR1cm4gcmV0OworCX0K KworCXJldCA9IGZzbF9xZG1hX3JlZ19pbml0KGZzbF9xZG1hKTsKKwlpZiAocmV0KSB7CisJCWRl dl9lcnIoJnBkZXYtPmRldiwgIkNhbid0IEluaXRpYWxpemUgdGhlIHFETUEgZW5naW5lLlxuIik7 CisJCXJldHVybiByZXQ7CisJfQorCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyB2b2lkIGZzbF9x ZG1hX2NsZWFudXBfdmNoYW4oc3RydWN0IGRtYV9kZXZpY2UgKmRtYWRldikKK3sKKwlzdHJ1Y3Qg ZnNsX3FkbWFfY2hhbiAqY2hhbiwgKl9jaGFuOworCisJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZl KGNoYW4sIF9jaGFuLAorCQkJCSZkbWFkZXYtPmNoYW5uZWxzLCB2Y2hhbi5jaGFuLmRldmljZV9u b2RlKSB7CisJCWxpc3RfZGVsKCZjaGFuLT52Y2hhbi5jaGFuLmRldmljZV9ub2RlKTsKKwkJdGFz a2xldF9raWxsKCZjaGFuLT52Y2hhbi50YXNrKTsKKwl9Cit9CisKK3N0YXRpYyBpbnQgZnNsX3Fk bWFfcmVtb3ZlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCit7CisJc3RydWN0IGRldmlj ZV9ub2RlICpucCA9IHBkZXYtPmRldi5vZl9ub2RlOworCXN0cnVjdCBmc2xfcWRtYV9lbmdpbmUg KmZzbF9xZG1hID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7CisJc3RydWN0IGZzbF9xZG1h X3F1ZXVlICpxdWV1ZV90ZW1wOworCXN0cnVjdCBmc2xfcWRtYV9xdWV1ZSAqc3RhdHVzID0gZnNs X3FkbWEtPnN0YXR1czsKKwlzdHJ1Y3QgZnNsX3FkbWFfY29tcCAqY29tcF90ZW1wLCAqX2NvbXBf dGVtcDsKKwlpbnQgaTsKKworCWZzbF9xZG1hX2lycV9leGl0KHBkZXYsIGZzbF9xZG1hKTsKKwlm c2xfcWRtYV9jbGVhbnVwX3ZjaGFuKCZmc2xfcWRtYS0+ZG1hX2Rldik7CisJb2ZfZG1hX2NvbnRy b2xsZXJfZnJlZShucCk7CisJZG1hX2FzeW5jX2RldmljZV91bnJlZ2lzdGVyKCZmc2xfcWRtYS0+ ZG1hX2Rldik7CisKKwkvKiBGcmVlIGRlc2NyaXB0b3IgYXJlYXMgKi8KKwlmb3IgKGkgPSAwOyBp IDwgZnNsX3FkbWEtPm5fcXVldWVzOyBpKyspIHsKKwkJcXVldWVfdGVtcCA9IGZzbF9xZG1hLT5x dWV1ZSArIGk7CisJCWxpc3RfZm9yX2VhY2hfZW50cnlfc2FmZShjb21wX3RlbXAsIF9jb21wX3Rl bXAsCisJCQkJCSZxdWV1ZV90ZW1wLT5jb21wX3VzZWQsCWxpc3QpIHsKKwkJCWRtYV9wb29sX2Zy ZWUocXVldWVfdGVtcC0+Y29tcF9wb29sLAorCQkJCQljb21wX3RlbXAtPnZpcnRfYWRkciwKKwkJ CQkJY29tcF90ZW1wLT5idXNfYWRkcik7CisJCQlsaXN0X2RlbCgmY29tcF90ZW1wLT5saXN0KTsK KwkJCWtmcmVlKGNvbXBfdGVtcCk7CisJCX0KKwkJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKGNv bXBfdGVtcCwgX2NvbXBfdGVtcCwKKwkJCQkJJnF1ZXVlX3RlbXAtPmNvbXBfZnJlZSwgbGlzdCkg eworCQkJZG1hX3Bvb2xfZnJlZShxdWV1ZV90ZW1wLT5jb21wX3Bvb2wsCisJCQkJCWNvbXBfdGVt cC0+dmlydF9hZGRyLAorCQkJCQljb21wX3RlbXAtPmJ1c19hZGRyKTsKKwkJCWxpc3RfZGVsKCZj b21wX3RlbXAtPmxpc3QpOworCQkJa2ZyZWUoY29tcF90ZW1wKTsKKwkJfQorCQlkbWFfZnJlZV9j b2hlcmVudCgmcGRldi0+ZGV2LCBzaXplb2Yoc3RydWN0IGZzbF9xZG1hX2Zvcm1hdCkgKgorCQkJ CQlxdWV1ZV90ZW1wLT5uX2NxLCBxdWV1ZV90ZW1wLT5jcSwKKwkJCQkJcXVldWVfdGVtcC0+YnVz X2FkZHIpOworCQlkbWFfcG9vbF9kZXN0cm95KHF1ZXVlX3RlbXAtPmNvbXBfcG9vbCk7CisJfQor CisJZG1hX2ZyZWVfY29oZXJlbnQoJnBkZXYtPmRldiwgc2l6ZW9mKHN0cnVjdCBmc2xfcWRtYV9m b3JtYXQpICoKKwkJCQlzdGF0dXMtPm5fY3EsIHN0YXR1cy0+Y3EsIHN0YXR1cy0+YnVzX2FkZHIp OworCXJldHVybiAwOworfQorCitzdGF0aWMgY29uc3Qgc3RydWN0IG9mX2RldmljZV9pZCBmc2xf cWRtYV9kdF9pZHNbXSA9IHsKKwl7IC5jb21wYXRpYmxlID0gImZzbCxsczEwMjFhLXFkbWEiLCB9 LAorCXsgLyogc2VudGluZWwgKi8gfQorfTsKK01PRFVMRV9ERVZJQ0VfVEFCTEUob2YsIGZzbF9x ZG1hX2R0X2lkcyk7CisKK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIGZzbF9xZG1hX2Ry aXZlciA9IHsKKwkuZHJpdmVyCQk9IHsKKwkJLm5hbWUJPSAiZnNsLXFkbWEiLAorCQkub2ZfbWF0 Y2hfdGFibGUgPSBmc2xfcWRtYV9kdF9pZHMsCisJfSwKKwkucHJvYmUgICAgICAgICAgPSBmc2xf cWRtYV9wcm9iZSwKKwkucmVtb3ZlCQk9IGZzbF9xZG1hX3JlbW92ZSwKK307CisKK21vZHVsZV9w bGF0Zm9ybV9kcml2ZXIoZnNsX3FkbWFfZHJpdmVyKTsKKworTU9EVUxFX0FMSUFTKCJwbGF0Zm9y bTpmc2wtcWRtYSIpOworTU9EVUxFX0RFU0NSSVBUSU9OKCJOWFAgTGF5ZXJzY2FwZSBxRE1BIGVu Z2luZSBkcml2ZXIiKTsKK01PRFVMRV9MSUNFTlNFKCJHUEwgdjIiKTsK From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Wen He Subject: [v7 3/7] dmaengine: fsl-qdma: Add qDMA controller driver for Layerscape SoCs Date: Wed, 25 Jul 2018 19:29:15 +0800 Message-Id: <20180725112919.31340-3-wen.he_1@nxp.com> In-Reply-To: <20180725112919.31340-1-wen.he_1@nxp.com> References: <20180725112919.31340-1-wen.he_1@nxp.com> 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. Signed-off-by: Wen He Signed-off-by: Jiaheng Fan --- drivers/dma/Kconfig | 13 + drivers/dma/Makefile | 1 + drivers/dma/fsl-qdma.c | 1105 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1119 insertions(+), 0 deletions(-) create mode 100644 drivers/dma/fsl-qdma.c diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index ca1680a..2914caf 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -218,6 +218,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 203a99d..0556f9d 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -32,6 +32,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..1cecf9b --- /dev/null +++ b/drivers/dma/fsl-qdma.c @@ -0,0 +1,1105 @@ +// 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_DEDR_CLEAR GENMASK(31, 0) +#define FSL_QDMA_BCQIDR_CLEAR GENMASK(31, 0) +#define FSL_QDMA_DEIER_CLEAR GENMASK(31, 0) + +#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 safe loop count*/ +#define FSL_QDMA_HALT_COUNT 1500 +#define FSL_QDMA_MAX_SIZE 16385 + +/* 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: Command status and enqueue status notification. + * @cfg: Frame offset and frame format. + * @addr_lo: Holding the compound descriptor of the lower + * 32-bits address in memory 40-bit address. + * @addr_hi: Same as above member, but point high 8-bits in + * memory 40-bit address. + * @__reserved1: Reserved field. + * @cfg8b_w1: Compound descriptor command queue origin produced + * by qDMA and dynamic debug field. + * @data Pointer to the memory 40-bit address, describes DMA + * source information 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_NOWAIT); + if (!comp_temp) + goto err; + + comp_temp->virt_addr = dma_pool_alloc(queue->comp_pool, + GFP_NOWAIT, + &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, i; + unsigned int queue_size[FSL_QDMA_QUEUE_MAX]; + + if (queue_num > FSL_QDMA_QUEUE_MAX) + queue_num = FSL_QDMA_QUEUE_MAX; + queue_head = devm_kcalloc(&pdev->dev, queue_num, + sizeof(*queue_head), 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 = FSL_QDMA_HALT_COUNT; + 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 all detected events and interrupts for all queues. */ + qdma_writel(fsl_qdma, FSL_QDMA_BCQIDR_CLEAR, + 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, count; + bool duplicate, duplicate_handle; + + memset(&pre, 0, sizeof(struct fsl_pre_status)); + count = FSL_QDMA_MAX_SIZE; + + while (count--) { + duplicate = 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) { + 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) { + spin_unlock(&temp_queue->queue_lock); + return -EAGAIN; + } + } + } + + if (duplicate) { + 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"); + + /* Clear all error conditions and interrupts. */ + qdma_writel(fsl_qdma, FSL_QDMA_DEDR_CLEAR, 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"); + } + + /* Clear all detected events and interrupts. */ + qdma_writel(fsl_qdma, FSL_QDMA_BCQIDR_CLEAR, + 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 all detected events and interrupts for all queues. */ + qdma_writel(fsl_qdma, FSL_QDMA_BCQIDR_CLEAR, + 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, FSL_QDMA_DEDR_CLEAR, status + FSL_QDMA_DEDR); + qdma_writel(fsl_qdma, FSL_QDMA_DEIER_CLEAR, 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