From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jilai Wang Subject: [PATCH 2/3] drm:msm: Initial Add Writeback Support Date: Wed, 1 Apr 2015 17:12:50 -0400 Message-ID: <1427922770-13721-1-git-send-email-jilaiw@codeaurora.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: dri-devel@lists.freedesktop.org Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org List-Id: linux-arm-msm@vger.kernel.org QWRkIHdyaXRlYmFjayBzdXBwb3J0IGluIG1zbSBrbXMgZnJhbWV3b3JrLgoKU2lnbmVkLW9mZi1i eTogSmlsYWkgV2FuZyA8amlsYWl3QGNvZGVhdXJvcmEub3JnPgotLS0KIGRyaXZlcnMvZ3B1L2Ry bS9tc20vS2NvbmZpZyAgICAgICAgICAgICAgICAgICAgICAgfCAgMTAgKwogZHJpdmVycy9ncHUv ZHJtL21zbS9NYWtlZmlsZSAgICAgICAgICAgICAgICAgICAgICB8ICAgOSArLQogZHJpdmVycy9n cHUvZHJtL21zbS9tZHAvbWRwNS9tZHA1X2NmZy5jICAgICAgICAgICB8ICAxMCArCiBkcml2ZXJz L2dwdS9kcm0vbXNtL21kcC9tZHA1L21kcDVfY2ZnLmggICAgICAgICAgIHwgICAxICsKIGRyaXZl cnMvZ3B1L2RybS9tc20vbWRwL21kcDUvbWRwNV9rbXMuYyAgICAgICAgICAgfCAgMTkgKy0KIGRy aXZlcnMvZ3B1L2RybS9tc20vbWRwL21kcDUvbWRwNV9rbXMuaCAgICAgICAgICAgfCAgIDcgKwog ZHJpdmVycy9ncHUvZHJtL21zbS9tZHAvbWRwNS9tZHA1X3diX2VuY29kZXIuYyAgICB8IDQ2MCAr KysrKysrKysrKysrKysrKysrCiBkcml2ZXJzL2dwdS9kcm0vbXNtL21kcC9tZHBfa21zLmggICAg ICAgICAgICAgICAgIHwgICAyICstCiBkcml2ZXJzL2dwdS9kcm0vbXNtL21kcC9tZHBfd2IvbWRw X3diLmMgICAgICAgICAgIHwgMzE5ICsrKysrKysrKysrKysKIGRyaXZlcnMvZ3B1L2RybS9tc20v bWRwL21kcF93Yi9tZHBfd2IuaCAgICAgICAgICAgfCAgOTggKysrKwogZHJpdmVycy9ncHUvZHJt L21zbS9tZHAvbWRwX3diL21kcF93Yl9jb25uZWN0b3IuYyB8IDE1NyArKysrKysrCiBkcml2ZXJz L2dwdS9kcm0vbXNtL21kcC9tZHBfd2IvbWRwX3diX3Y0bDIuYyAgICAgIHwgNTIyICsrKysrKysr KysrKysrKysrKysrKysKIGRyaXZlcnMvZ3B1L2RybS9tc20vbXNtX2Rydi5jICAgICAgICAgICAg ICAgICAgICAgfCAgIDIgKwogZHJpdmVycy9ncHUvZHJtL21zbS9tc21fZHJ2LmggICAgICAgICAg ICAgICAgICAgICB8ICAxOSArLQogZHJpdmVycy9ncHUvZHJtL21zbS9tc21fZmJkZXYuYyAgICAg ICAgICAgICAgICAgICB8ICAzNCArLQogZHJpdmVycy9ncHUvZHJtL21zbS9tc21fZ2VtLmMgICAg ICAgICAgICAgICAgICAgICB8ICAgMSArCiAxNiBmaWxlcyBjaGFuZ2VkLCAxNjY0IGluc2VydGlv bnMoKyksIDYgZGVsZXRpb25zKC0pCiBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9ncHUvZHJt L21zbS9tZHAvbWRwNS9tZHA1X3diX2VuY29kZXIuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZl cnMvZ3B1L2RybS9tc20vbWRwL21kcF93Yi9tZHBfd2IuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRy aXZlcnMvZ3B1L2RybS9tc20vbWRwL21kcF93Yi9tZHBfd2IuaAogY3JlYXRlIG1vZGUgMTAwNjQ0 IGRyaXZlcnMvZ3B1L2RybS9tc20vbWRwL21kcF93Yi9tZHBfd2JfY29ubmVjdG9yLmMKIGNyZWF0 ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2dwdS9kcm0vbXNtL21kcC9tZHBfd2IvbWRwX3diX3Y0bDIu YwoKZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9tc20vS2NvbmZpZyBiL2RyaXZlcnMvZ3B1 L2RybS9tc20vS2NvbmZpZwppbmRleCAxZTZhOTA3Li5mNmM3OTE0IDEwMDY0NAotLS0gYS9kcml2 ZXJzL2dwdS9kcm0vbXNtL0tjb25maWcKKysrIGIvZHJpdmVycy9ncHUvZHJtL21zbS9LY29uZmln CkBAIC0yNyw2ICsyNywxNiBAQCBjb25maWcgRFJNX01TTV9GQkRFVgogCSAgc3VwcG9ydC4gTm90 ZSB0aGF0IHRoaXMgc3VwcG9ydCBhbHNvIHByb3ZpZGUgdGhlIGxpbnV4IGNvbnNvbGUKIAkgIHN1 cHBvcnQgb24gdG9wIG9mIHRoZSBNU00gbW9kZXNldHRpbmcgZHJpdmVyLgogCitjb25maWcgRFJN X01TTV9XQgorCWJvb2wgIkVuYWJsZSB3cml0ZWJhY2sgc3VwcG9ydCBmb3IgTVNNIG1vZGVzZXR0 aW5nIGRyaXZlciIKKwlkZXBlbmRzIG9uIERSTV9NU00KKwlkZXBlbmRzIG9uIFZJREVPX1Y0TDIK KwlzZWxlY3QgVklERU9CVUYyX0NPUkUKKwlkZWZhdWx0IHkKKwloZWxwCisJICBDaG9vc2UgdGhp cyBvcHRpb24gaWYgeW91IGhhdmUgYSBuZWVkIHRvIHN1cHBvcnQgd3JpdGViYWNrCisJICBjb25u ZWN0b3IuCisKIGNvbmZpZyBEUk1fTVNNX1JFR0lTVEVSX0xPR0dJTkcKIAlib29sICJNU00gRFJN IHJlZ2lzdGVyIGxvZ2dpbmciCiAJZGVwZW5kcyBvbiBEUk1fTVNNCmRpZmYgLS1naXQgYS9kcml2 ZXJzL2dwdS9kcm0vbXNtL01ha2VmaWxlIGIvZHJpdmVycy9ncHUvZHJtL21zbS9NYWtlZmlsZQpp bmRleCA2NzRhMTMyLi5lNWJmMzM0IDEwMDY0NAotLS0gYS9kcml2ZXJzL2dwdS9kcm0vbXNtL01h a2VmaWxlCisrKyBiL2RyaXZlcnMvZ3B1L2RybS9tc20vTWFrZWZpbGUKQEAgLTEsNCArMSw1IEBA Ci1jY2ZsYWdzLXkgOj0gLUlpbmNsdWRlL2RybSAtSWRyaXZlcnMvZ3B1L2RybS9tc20KK2NjZmxh Z3MteSA6PSAtSWluY2x1ZGUvZHJtIC1JZHJpdmVycy9ncHUvZHJtL21zbSAtSWRyaXZlcnMvZ3B1 L2RybS9tc20vbWRwX3diCitjY2ZsYWdzLSQoQ09ORklHX0RSTV9NU01fV0IpICs9IC1JZHJpdmVy cy9ncHUvZHJtL21zbS9tZHAvbWRwX3diCiAKIG1zbS15IDo9IFwKIAlhZHJlbm8vYWRyZW5vX2Rl dmljZS5vIFwKQEAgLTUxLDQgKzUyLDEwIEBAIG1zbS15IDo9IFwKIG1zbS0kKENPTkZJR19EUk1f TVNNX0ZCREVWKSArPSBtc21fZmJkZXYubwogbXNtLSQoQ09ORklHX0NPTU1PTl9DTEspICs9IG1k cC9tZHA0L21kcDRfbHZkc19wbGwubwogCittc20tJChDT05GSUdfRFJNX01TTV9XQikgKz0gXAor CW1kcC9tZHA1L21kcDVfd2JfZW5jb2Rlci5vIFwKKwltZHAvbWRwX3diL21kcF93Yi5vIFwKKwlt ZHAvbWRwX3diL21kcF93Yl9jb25uZWN0b3IubyBcCisJbWRwL21kcF93Yi9tZHBfd2JfdjRsMi5v CisKIG9iai0kKENPTkZJR19EUk1fTVNNKQkrPSBtc20ubwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9n cHUvZHJtL21zbS9tZHAvbWRwNS9tZHA1X2NmZy5jIGIvZHJpdmVycy9ncHUvZHJtL21zbS9tZHAv bWRwNS9tZHA1X2NmZy5jCmluZGV4IDFmZTczMTUuLmU4N2NmNzQgMTAwNjQ0Ci0tLSBhL2RyaXZl cnMvZ3B1L2RybS9tc20vbWRwL21kcDUvbWRwNV9jZmcuYworKysgYi9kcml2ZXJzL2dwdS9kcm0v bXNtL21kcC9tZHA1L21kcDVfY2ZnLmMKQEAgLTcxLDkgKzcxLDE0IEBAIGNvbnN0IHN0cnVjdCBt ZHA1X2NmZ19odyBtc204eDc0X2NvbmZpZyA9IHsKIAkJLmNvdW50ID0gNCwKIAkJLmJhc2UgPSB7 IDB4MTI1MDAsIDB4MTI3MDAsIDB4MTI5MDAsIDB4MTJiMDAgfSwKIAl9LAorCS53YiA9IHsKKwkJ LmNvdW50ID0gNSwKKwkJLmJhc2UgPSB7IDB4MTExMDAsIDB4MTMxMDAsIDB4MTUxMDAsIDB4MTcx MDAsIDB4MTkxMDAgfSwKKwl9LAogCS5pbnRmcyA9IHsKIAkJWzBdID0gSU5URl9lRFAsCiAJCVsz XSA9IElOVEZfSERNSSwKKwkJWzRdID0gSU5URl9XQiwKIAl9LAogCS5tYXhfY2xrID0gMjAwMDAw MDAwLAogfTsKQEAgLTEzNSw5ICsxNDAsMTQgQEAgY29uc3Qgc3RydWN0IG1kcDVfY2ZnX2h3IGFw cTgwODRfY29uZmlnID0gewogCQkuY291bnQgPSA1LAogCQkuYmFzZSA9IHsgMHgxMjUwMCwgMHgx MjcwMCwgMHgxMjkwMCwgMHgxMmIwMCwgMHgxMmQwMCB9LAogCX0sCisJLndiID0geworCQkuY291 bnQgPSA1LAorCQkuYmFzZSA9IHsgMHgxMTEwMCwgMHgxMTUwMCwgMHgxMTkwMCwgMHgxMWQwMCwg MHgxMjEwMCB9LAorCX0sCiAJLmludGZzID0gewogCQlbMF0gPSBJTlRGX2VEUCwKIAkJWzNdID0g SU5URl9IRE1JLAorCQlbNF0gPSBJTlRGX1dCLAogCX0sCiAJLm1heF9jbGsgPSAzMjAwMDAwMDAs CiB9OwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL21zbS9tZHAvbWRwNS9tZHA1X2NmZy5o IGIvZHJpdmVycy9ncHUvZHJtL21zbS9tZHAvbWRwNS9tZHA1X2NmZy5oCmluZGV4IGY0NzMyOGQu LmNjYjYwNDhjIDEwMDY0NAotLS0gYS9kcml2ZXJzL2dwdS9kcm0vbXNtL21kcC9tZHA1L21kcDVf Y2ZnLmgKKysrIGIvZHJpdmVycy9ncHUvZHJtL21zbS9tZHAvbWRwNS9tZHA1X2NmZy5oCkBAIC03 NCw2ICs3NCw3IEBAIHN0cnVjdCBtZHA1X2NmZ19odyB7CiAJc3RydWN0IG1kcDVfc3ViX2Jsb2Nr IGRzcHA7CiAJc3RydWN0IG1kcDVfc3ViX2Jsb2NrIGFkOwogCXN0cnVjdCBtZHA1X3N1Yl9ibG9j ayBpbnRmOworCXN0cnVjdCBtZHA1X3N1Yl9ibG9jayB3YjsKIAogCXUzMiBpbnRmc1tNRFA1X0lO VEZfTlVNX01BWF07IC8qIGFycmF5IG9mIGVudW0gbWRwNV9pbnRmX3R5cGUgKi8KIApkaWZmIC0t Z2l0IGEvZHJpdmVycy9ncHUvZHJtL21zbS9tZHAvbWRwNS9tZHA1X2ttcy5jIGIvZHJpdmVycy9n cHUvZHJtL21zbS9tZHAvbWRwNS9tZHA1X2ttcy5jCmluZGV4IGZmOTIwMWIuLjFiMTU2OWQgMTAw NjQ0Ci0tLSBhL2RyaXZlcnMvZ3B1L2RybS9tc20vbWRwL21kcDUvbWRwNV9rbXMuYworKysgYi9k cml2ZXJzL2dwdS9kcm0vbXNtL21kcC9tZHA1L21kcDVfa21zLmMKQEAgLTE3OSw3ICsxNzksMTEg QEAgc3RhdGljIHN0cnVjdCBkcm1fZW5jb2RlciAqY29uc3RydWN0X2VuY29kZXIoc3RydWN0IG1k cDVfa21zICptZHA1X2ttcywKIAkJCS5tb2RlCT0gaW50Zl9tb2RlLAogCX07CiAKLQllbmNvZGVy ID0gbWRwNV9lbmNvZGVyX2luaXQoZGV2LCAmaW50Zik7CisJaWYgKGludGZfdHlwZSA9PSBJTlRG X1dCKQorCQllbmNvZGVyID0gbWRwNV93Yl9lbmNvZGVyX2luaXQoZGV2LCAmaW50Zik7CisJZWxz ZQorCQllbmNvZGVyID0gbWRwNV9lbmNvZGVyX2luaXQoZGV2LCAmaW50Zik7CisKIAlpZiAoSVNf RVJSKGVuY29kZXIpKSB7CiAJCWRldl9lcnIoZGV2LT5kZXYsICJmYWlsZWQgdG8gY29uc3RydWN0 IGVuY29kZXJcbiIpOwogCQlyZXR1cm4gZW5jb2RlcjsKQEAgLTIzMCw2ICsyMzQsMTkgQEAgc3Rh dGljIGludCBtb2Rlc2V0X2luaXRfaW50ZihzdHJ1Y3QgbWRwNV9rbXMgKm1kcDVfa21zLCBpbnQg aW50Zl9udW0pCiAKIAkJcmV0ID0gaGRtaV9tb2Rlc2V0X2luaXQocHJpdi0+aGRtaSwgZGV2LCBl bmNvZGVyKTsKIAkJYnJlYWs7CisJY2FzZSBJTlRGX1dCOgorCQlpZiAoIXByaXYtPndiKQorCQkJ YnJlYWs7CisKKwkJZW5jb2RlciA9IGNvbnN0cnVjdF9lbmNvZGVyKG1kcDVfa21zLCBJTlRGX1dC LCBpbnRmX251bSwKKwkJCQkJTURQNV9JTlRGX1dCX01PREVfTElORSk7CisJCWlmIChJU19FUlIo ZW5jb2RlcikpIHsKKwkJCXJldCA9IFBUUl9FUlIoZW5jb2Rlcik7CisJCQlicmVhazsKKwkJfQor CisJCXJldCA9IG1zbV93Yl9tb2Rlc2V0X2luaXQocHJpdi0+d2IsIGRldiwgZW5jb2Rlcik7CisJ CWJyZWFrOwogCWRlZmF1bHQ6CiAJCWRldl9lcnIoZGV2LT5kZXYsICJ1bmtub3duIGludGY6ICVk XG4iLCBpbnRmX3R5cGUpOwogCQlyZXQgPSAtRUlOVkFMOwpkaWZmIC0tZ2l0IGEvZHJpdmVycy9n cHUvZHJtL21zbS9tZHAvbWRwNS9tZHA1X2ttcy5oIGIvZHJpdmVycy9ncHUvZHJtL21zbS9tZHAv bWRwNS9tZHA1X2ttcy5oCmluZGV4IDZlZmE1YzYuLmY2ZDIzY2MgMTAwNjQ0Ci0tLSBhL2RyaXZl cnMvZ3B1L2RybS9tc20vbWRwL21kcDUvbWRwNV9rbXMuaAorKysgYi9kcml2ZXJzL2dwdS9kcm0v bXNtL21kcC9tZHA1L21kcDVfa21zLmgKQEAgLTIzOCw1ICsyMzgsMTIgQEAgc3RydWN0IGRybV9j cnRjICptZHA1X2NydGNfaW5pdChzdHJ1Y3QgZHJtX2RldmljZSAqZGV2LAogCiBzdHJ1Y3QgZHJt X2VuY29kZXIgKm1kcDVfZW5jb2Rlcl9pbml0KHN0cnVjdCBkcm1fZGV2aWNlICpkZXYsCiAJCXN0 cnVjdCBtZHA1X2ludGVyZmFjZSAqaW50Zik7CisjaWZkZWYgQ09ORklHX0RSTV9NU01fV0IKK3N0 cnVjdCBkcm1fZW5jb2RlciAqbWRwNV93Yl9lbmNvZGVyX2luaXQoc3RydWN0IGRybV9kZXZpY2Ug KmRldiwKKwkJc3RydWN0IG1kcDVfaW50ZXJmYWNlICppbnRmKTsKKyNlbHNlCitzdGF0aWMgaW5s aW5lIHN0cnVjdCBkcm1fZW5jb2RlciAqbWRwNV93Yl9lbmNvZGVyX2luaXQoc3RydWN0IGRybV9k ZXZpY2UgKmRldiwKKwkJc3RydWN0IG1kcDVfaW50ZXJmYWNlICppbnRmKSB7IHJldHVybiBOVUxM OyB9CisjZW5kaWYKIAogI2VuZGlmIC8qIF9fTURQNV9LTVNfSF9fICovCmRpZmYgLS1naXQgYS9k cml2ZXJzL2dwdS9kcm0vbXNtL21kcC9tZHA1L21kcDVfd2JfZW5jb2Rlci5jIGIvZHJpdmVycy9n cHUvZHJtL21zbS9tZHAvbWRwNS9tZHA1X3diX2VuY29kZXIuYwpuZXcgZmlsZSBtb2RlIDEwMDY0 NAppbmRleCAwMDAwMDAwLi44Y2UzNDQ5Ci0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9ncHUv ZHJtL21zbS9tZHAvbWRwNS9tZHA1X3diX2VuY29kZXIuYwpAQCAtMCwwICsxLDQ2MCBAQAorLyog Q29weXJpZ2h0IChjKSAyMDE1LCBUaGUgTGludXggRm91bmRhdGlvbi4gQWxsIHJpZ2h0cyByZXNl cnZlZC4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRp c3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeQorICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBH TlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSB2ZXJzaW9uIDIgYW5kCisgKiBvbmx5IHZlcnNpb24g MiBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4KKyAqCisgKiBU aGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVz ZWZ1bCwKKyAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBs aWVkIHdhcnJhbnR5IG9mCisgKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJU SUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCisgKiBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBm b3IgbW9yZSBkZXRhaWxzLgorICovCisKKyNpbmNsdWRlICJtZHA1X2ttcy5oIgorI2luY2x1ZGUg Im1kcF93Yi5oIgorCisjaW5jbHVkZSAiZHJtX2NydGMuaCIKKyNpbmNsdWRlICJkcm1fY3J0Y19o ZWxwZXIuaCIKKworc3RydWN0IG1kcDVfd2JfZW5jb2RlciB7CisJc3RydWN0IGRybV9lbmNvZGVy IGJhc2U7CisJc3RydWN0IG1kcDVfaW50ZXJmYWNlIGludGY7CisJYm9vbCBlbmFibGVkOworCXVp bnQzMl90IGJzYzsKKwlzdHJ1Y3QgbWRwNV9jdGwgKmN0bDsKKworCS8qIGlycSBoYW5kbGVyIGZv ciB3YiBlbmNvZGVyICovCisJc3RydWN0IG1kcF9pcnEgd2JfdmJsYW5rOworCS8qIHdiIGlkIHNh bWUgYXMgY3RsIGlkICovCisJdTMyIHdiX2lkOworfTsKKyNkZWZpbmUgdG9fbWRwNV93Yl9lbmNv ZGVyKHgpIGNvbnRhaW5lcl9vZih4LCBzdHJ1Y3QgbWRwNV93Yl9lbmNvZGVyLCBiYXNlKQorCitz dGF0aWMgc3RydWN0IG1kcDVfa21zICpnZXRfa21zKHN0cnVjdCBkcm1fZW5jb2RlciAqZW5jb2Rl cikKK3sKKwlzdHJ1Y3QgbXNtX2RybV9wcml2YXRlICpwcml2ID0gZW5jb2Rlci0+ZGV2LT5kZXZf cHJpdmF0ZTsKKwlyZXR1cm4gdG9fbWRwNV9rbXModG9fbWRwX2ttcyhwcml2LT5rbXMpKTsKK30K Kworc3RhdGljIHN0cnVjdCBtc21fd2IgKmdldF93YihzdHJ1Y3QgZHJtX2VuY29kZXIgKmVuY29k ZXIpCit7CisJc3RydWN0IG1zbV9kcm1fcHJpdmF0ZSAqcHJpdiA9IGVuY29kZXItPmRldi0+ZGV2 X3ByaXZhdGU7CisJcmV0dXJuIHByaXYtPndiOworfQorCisjaWZkZWYgQ09ORklHX01TTV9CVVNf U0NBTElORworI2luY2x1ZGUgPG1hY2gvYm9hcmQuaD4KKyNpbmNsdWRlIDxsaW51eC9tc20tYnVz Lmg+CisjaW5jbHVkZSA8bGludXgvbXNtLWJ1cy1ib2FyZC5oPgorI2RlZmluZSBNRFBfQlVTX1ZF Q1RPUl9FTlRSWShhYl92YWwsIGliX3ZhbCkJCVwKKwl7CQkJCQkJXAorCQkuc3JjID0gTVNNX0JV U19NQVNURVJfTURQX1BPUlQwLAlcCisJCS5kc3QgPSBNU01fQlVTX1NMQVZFX0VCSV9DSDAsCQlc CisJCS5hYiA9IChhYl92YWwpLAkJCQlcCisJCS5pYiA9IChpYl92YWwpLAkJCQlcCisJfQorCitz dGF0aWMgc3RydWN0IG1zbV9idXNfdmVjdG9ycyBtZHBfYnVzX3ZlY3RvcnNbXSA9IHsKKwlNRFBf QlVTX1ZFQ1RPUl9FTlRSWSgwLCAwKSwKKwlNRFBfQlVTX1ZFQ1RPUl9FTlRSWSgyMDAwMDAwMDAw LCAyMDAwMDAwMDAwKSwKK307CitzdGF0aWMgc3RydWN0IG1zbV9idXNfcGF0aHMgbWRwX2J1c191 c2VjYXNlc1tdID0geyB7CisJCS5udW1fcGF0aHMgPSAxLAorCQkudmVjdG9ycyA9ICZtZHBfYnVz X3ZlY3RvcnNbMF0sCit9LCB7CisJCS5udW1fcGF0aHMgPSAxLAorCQkudmVjdG9ycyA9ICZtZHBf YnVzX3ZlY3RvcnNbMV0sCit9IH07CitzdGF0aWMgc3RydWN0IG1zbV9idXNfc2NhbGVfcGRhdGEg bWRwX2J1c19zY2FsZV90YWJsZSA9IHsKKwkudXNlY2FzZSA9IG1kcF9idXNfdXNlY2FzZXMsCisJ Lm51bV91c2VjYXNlcyA9IEFSUkFZX1NJWkUobWRwX2J1c191c2VjYXNlcyksCisJLm5hbWUgPSAi bWRzc19tZHAiLAorfTsKKworc3RhdGljIHZvaWQgYnNfaW5pdChzdHJ1Y3QgbWRwNV93Yl9lbmNv ZGVyICptZHA1X3diX2VuY29kZXIpCit7CisJbWRwNV93Yl9lbmNvZGVyLT5ic2MgPSBtc21fYnVz X3NjYWxlX3JlZ2lzdGVyX2NsaWVudCgKKwkJCSZtZHBfYnVzX3NjYWxlX3RhYmxlKTsKKwlEQkco ImJ1cyBzY2FsZSBjbGllbnQ6ICUwOHgiLCBtZHA1X3diX2VuY29kZXItPmJzYyk7Cit9CisKK3N0 YXRpYyB2b2lkIGJzX2Zpbmkoc3RydWN0IG1kcDVfd2JfZW5jb2RlciAqbWRwNV93Yl9lbmNvZGVy KQoreworCWlmIChtZHA1X3diX2VuY29kZXItPmJzYykgeworCQltc21fYnVzX3NjYWxlX3VucmVn aXN0ZXJfY2xpZW50KG1kcDVfd2JfZW5jb2Rlci0+YnNjKTsKKwkJbWRwNV93Yl9lbmNvZGVyLT5i c2MgPSAwOworCX0KK30KKworc3RhdGljIHZvaWQgYnNfc2V0KHN0cnVjdCBtZHA1X3diX2VuY29k ZXIgKm1kcDVfd2JfZW5jb2RlciwgaW50IGlkeCkKK3sKKwlpZiAobWRwNV93Yl9lbmNvZGVyLT5i c2MpIHsKKwkJREJHKCJzZXQgYnVzIHNjYWxpbmc6ICVkIiwgaWR4KTsKKwkJLyogSEFDSzogc2Nh bGluZyBkb3duLCBhbmQgdGhlbiBpbW1lZGlhdGVseSBiYWNrIHVwCisJCSAqIHNlZW1zIHRvIGxl YXZlIHRoaW5ncyBicm9rZW4gKHVuZGVyZmxvdykuLiBzbworCQkgKiBuZXZlciBkaXNhYmxlOgor CQkgKi8KKwkJaWR4ID0gMTsKKwkJbXNtX2J1c19zY2FsZV9jbGllbnRfdXBkYXRlX3JlcXVlc3Qo bWRwNV93Yl9lbmNvZGVyLT5ic2MsIGlkeCk7CisJfQorfQorI2Vsc2UKK3N0YXRpYyB2b2lkIGJz X2luaXQoc3RydWN0IG1kcDVfd2JfZW5jb2RlciAqbWRwNV93Yl9lbmNvZGVyKSB7fQorc3RhdGlj IHZvaWQgYnNfZmluaShzdHJ1Y3QgbWRwNV93Yl9lbmNvZGVyICptZHA1X3diX2VuY29kZXIpIHt9 CitzdGF0aWMgdm9pZCBic19zZXQoc3RydWN0IG1kcDVfd2JfZW5jb2RlciAqbWRwNV93Yl9lbmNv ZGVyLCBpbnQgaWR4KSB7fQorI2VuZGlmCisKK3N0YXRpYyB2b2lkIG1kcDVfd2JfZW5jb2Rlcl9k ZXN0cm95KHN0cnVjdCBkcm1fZW5jb2RlciAqZW5jb2RlcikKK3sKKwlzdHJ1Y3QgbWRwNV93Yl9l bmNvZGVyICptZHA1X3diX2VuY29kZXIgPSB0b19tZHA1X3diX2VuY29kZXIoZW5jb2Rlcik7CisJ YnNfZmluaShtZHA1X3diX2VuY29kZXIpOworCWRybV9lbmNvZGVyX2NsZWFudXAoZW5jb2Rlcik7 CisJa2ZyZWUobWRwNV93Yl9lbmNvZGVyKTsKK30KKworc3RhdGljIGNvbnN0IHN0cnVjdCBkcm1f ZW5jb2Rlcl9mdW5jcyBtZHA1X3diX2VuY29kZXJfZnVuY3MgPSB7CisJLmRlc3Ryb3kgPSBtZHA1 X3diX2VuY29kZXJfZGVzdHJveSwKK307CisKK3N0YXRpYyBib29sIG1kcDVfd2JfZW5jb2Rlcl9t b2RlX2ZpeHVwKHN0cnVjdCBkcm1fZW5jb2RlciAqZW5jb2RlciwKKwkJY29uc3Qgc3RydWN0IGRy bV9kaXNwbGF5X21vZGUgKm1vZGUsCisJCXN0cnVjdCBkcm1fZGlzcGxheV9tb2RlICphZGp1c3Rl ZF9tb2RlKQoreworCXJldHVybiB0cnVlOworfQorCit2b2lkIG1kcDVfd2JfZW5jb2Rlcl9idWZf cHJlcGFyZShzdHJ1Y3QgbXNtX3diICp3Yiwgc3RydWN0IG1zbV93Yl9idWZmZXIgKmJ1ZikKK3sK KwlzdHJ1Y3QgZHJtX2VuY29kZXIgKmVuY29kZXIgPSB3Yi0+ZW5jb2RlcjsKKwlzdHJ1Y3QgbWRw NV9rbXMgKm1kcDVfa21zID0gZ2V0X2ttcyhlbmNvZGVyKTsKKwl1aW50MzJfdCBucGxhbmVzID0g ZHJtX2Zvcm1hdF9udW1fcGxhbmVzKGJ1Zi0+cGl4ZWxfZm9ybWF0KTsKKwlpbnQgaTsKKworCURC RygicGxhbmUgbm8gJWQiLCBucGxhbmVzKTsKKwltZHA1X2VuYWJsZShtZHA1X2ttcyk7CisJZm9y IChpID0gMDsgaSA8IG5wbGFuZXM7IGkrKykgeworCQlEQkcoImJ1ZiAlZDogcGxhbmUgJXgiLCBp LCAoaW50KWJ1Zi0+cGxhbmVzW2ldKTsKKwkJbXNtX2dlbV9nZXRfaW92YShidWYtPnBsYW5lc1tp XSwgbWRwNV9rbXMtPmlkLCAmYnVmLT5pb3ZhW2ldKTsKKwkJYnVmLT5pb3ZhW2ldICs9IGJ1Zi0+ b2Zmc2V0c1tpXTsKKwl9CisJZm9yICg7IGkgPCBNQVhfUExBTkU7IGkrKykKKwkJYnVmLT5pb3Zh W2ldID0gMDsKKwltZHA1X2Rpc2FibGUobWRwNV9rbXMpOworfQorCitzdGF0aWMgdm9pZCBtZHA1 X3diX2VuY29kZXJfYWRkcl9zZXR1cChzdHJ1Y3QgZHJtX2VuY29kZXIgKmVuY29kZXIsCisJc3Ry dWN0IG1zbV93Yl9idWZmZXIgKmJ1ZikKK3sKKwlzdHJ1Y3QgbWRwNV93Yl9lbmNvZGVyICptZHA1 X3diX2VuY29kZXIgPSB0b19tZHA1X3diX2VuY29kZXIoZW5jb2Rlcik7CisJc3RydWN0IG1kcDVf a21zICptZHA1X2ttcyA9IGdldF9rbXMoZW5jb2Rlcik7CisJdTMyIHdiX2lkID0gbWRwNV93Yl9l bmNvZGVyLT53Yl9pZDsKKworCW1kcDVfd3JpdGUobWRwNV9rbXMsIFJFR19NRFA1X1dCX0RTVDBf QUREUih3Yl9pZCksIGJ1Zi0+aW92YVswXSk7CisJbWRwNV93cml0ZShtZHA1X2ttcywgUkVHX01E UDVfV0JfRFNUMV9BRERSKHdiX2lkKSwgYnVmLT5pb3ZhWzFdKTsKKwltZHA1X3dyaXRlKG1kcDVf a21zLCBSRUdfTURQNV9XQl9EU1QyX0FERFIod2JfaWQpLCBidWYtPmlvdmFbMl0pOworCW1kcDVf d3JpdGUobWRwNV9rbXMsIFJFR19NRFA1X1dCX0RTVDNfQUREUih3Yl9pZCksIGJ1Zi0+aW92YVsz XSk7CisJREJHKCJQcm9ncmFtIFdCIERTVCBhZGRyZXNzICV4ICV4ICV4ICV4IiwgYnVmLT5pb3Zh WzBdLAorCQlidWYtPmlvdmFbMV0sIGJ1Zi0+aW92YVsyXSwgYnVmLT5pb3ZhWzNdKTsKKwkvKiBO b3RpZnkgY3RsIHRoYXQgd2IgYnVmZmVyIGlzIHJlYWR5IHRvIHRyaWdnZXIgc3RhcnQgKi8KKwlt ZHA1X2N0bF9jb21taXQobWRwNV93Yl9lbmNvZGVyLT5jdGwsCisJCW1kcF9jdGxfZmx1c2hfbWFz a19lbmNvZGVyKCZtZHA1X3diX2VuY29kZXItPmludGYpKTsKK30KKworc3RhdGljIHZvaWQgd2Jf Y3NjX3NldHVwKHN0cnVjdCBtZHA1X2ttcyAqbWRwNV9rbXMsIHUzMiB3Yl9pZCwKKwkJc3RydWN0 IGNzY19jZmcgKmNzYykKK3sKKwl1aW50MzJfdCAgaTsKKwl1aW50MzJfdCAqbWF0cml4OworCisJ aWYgKHVubGlrZWx5KCFjc2MpKQorCQlyZXR1cm47CisKKwltYXRyaXggPSBjc2MtPm1hdHJpeDsK KwltZHA1X3dyaXRlKG1kcDVfa21zLCBSRUdfTURQNV9XQl9DU0NfTUFUUklYX0NPRUZGXzAod2Jf aWQpLAorCQkJTURQNV9XQl9DU0NfTUFUUklYX0NPRUZGXzBfQ09FRkZfMTEobWF0cml4WzBdKSB8 CisJCQlNRFA1X1dCX0NTQ19NQVRSSVhfQ09FRkZfMF9DT0VGRl8xMihtYXRyaXhbMV0pKTsKKwlt ZHA1X3dyaXRlKG1kcDVfa21zLCBSRUdfTURQNV9XQl9DU0NfTUFUUklYX0NPRUZGXzEod2JfaWQp LAorCQkJTURQNV9XQl9DU0NfTUFUUklYX0NPRUZGXzFfQ09FRkZfMTMobWF0cml4WzJdKSB8CisJ CQlNRFA1X1dCX0NTQ19NQVRSSVhfQ09FRkZfMV9DT0VGRl8yMShtYXRyaXhbM10pKTsKKwltZHA1 X3dyaXRlKG1kcDVfa21zLCBSRUdfTURQNV9XQl9DU0NfTUFUUklYX0NPRUZGXzIod2JfaWQpLAor CQkJTURQNV9XQl9DU0NfTUFUUklYX0NPRUZGXzJfQ09FRkZfMjIobWF0cml4WzRdKSB8CisJCQlN RFA1X1dCX0NTQ19NQVRSSVhfQ09FRkZfMl9DT0VGRl8yMyhtYXRyaXhbNV0pKTsKKwltZHA1X3dy aXRlKG1kcDVfa21zLCBSRUdfTURQNV9XQl9DU0NfTUFUUklYX0NPRUZGXzMod2JfaWQpLAorCQkJ TURQNV9XQl9DU0NfTUFUUklYX0NPRUZGXzNfQ09FRkZfMzEobWF0cml4WzZdKSB8CisJCQlNRFA1 X1dCX0NTQ19NQVRSSVhfQ09FRkZfM19DT0VGRl8zMihtYXRyaXhbN10pKTsKKwltZHA1X3dyaXRl KG1kcDVfa21zLCBSRUdfTURQNV9XQl9DU0NfTUFUUklYX0NPRUZGXzQod2JfaWQpLAorCQkJTURQ NV9XQl9DU0NfTUFUUklYX0NPRUZGXzRfQ09FRkZfMzMobWF0cml4WzhdKSk7CisKKwlmb3IgKGkg PSAwOyBpIDwgQVJSQVlfU0laRShjc2MtPnByZV9iaWFzKTsgaSsrKSB7CisJCXVpbnQzMl90ICpw cmVfY2xhbXAgPSBjc2MtPnByZV9jbGFtcDsKKwkJdWludDMyX3QgKnBvc3RfY2xhbXAgPSBjc2Mt PnBvc3RfY2xhbXA7CisKKwkJbWRwNV93cml0ZShtZHA1X2ttcywgUkVHX01EUDVfV0JfQ1NDX0NP TVBfUFJFQ0xBTVAod2JfaWQsIGkpLAorCQkJTURQNV9XQl9DU0NfQ09NUF9QUkVDTEFNUF9SRUdf SElHSChwcmVfY2xhbXBbMippKzFdKSB8CisJCQlNRFA1X1dCX0NTQ19DT01QX1BSRUNMQU1QX1JF R19MT1cocHJlX2NsYW1wWzIqaV0pKTsKKworCQltZHA1X3dyaXRlKG1kcDVfa21zLCBSRUdfTURQ NV9XQl9DU0NfQ09NUF9QT1NUQ0xBTVAod2JfaWQsIGkpLAorCQkJTURQNV9XQl9DU0NfQ09NUF9Q T1NUQ0xBTVBfUkVHX0hJR0gocG9zdF9jbGFtcFsyKmkrMV0pIHwKKwkJCU1EUDVfV0JfQ1NDX0NP TVBfUE9TVENMQU1QX1JFR19MT1cocG9zdF9jbGFtcFsyKmldKSk7CisKKwkJbWRwNV93cml0ZSht ZHA1X2ttcywgUkVHX01EUDVfV0JfQ1NDX0NPTVBfUFJFQklBUyh3Yl9pZCwgaSksCisJCQlNRFA1 X1dCX0NTQ19DT01QX1BSRUJJQVNfUkVHX1ZBTFVFKGNzYy0+cHJlX2JpYXNbaV0pKTsKKworCQlt ZHA1X3dyaXRlKG1kcDVfa21zLCBSRUdfTURQNV9XQl9DU0NfQ09NUF9QT1NUQklBUyh3Yl9pZCwg aSksCisJCQlNRFA1X1dCX0NTQ19DT01QX1BPU1RCSUFTX1JFR19WQUxVRShjc2MtPnBvc3RfYmlh c1tpXSkpOworCX0KK30KKworc3RhdGljIHZvaWQgbWRwNV93Yl9lbmNvZGVyX21vZGVfc2V0KHN0 cnVjdCBkcm1fZW5jb2RlciAqZW5jb2RlciwKKwkJc3RydWN0IGRybV9kaXNwbGF5X21vZGUgKm1v ZGUsCisJCXN0cnVjdCBkcm1fZGlzcGxheV9tb2RlICphZGp1c3RlZF9tb2RlKQoreworCXN0cnVj dCBtZHA1X3diX2VuY29kZXIgKm1kcDVfd2JfZW5jb2RlciA9IHRvX21kcDVfd2JfZW5jb2Rlcihl bmNvZGVyKTsKKwlzdHJ1Y3QgbWRwNV9rbXMgKm1kcDVfa21zID0gZ2V0X2ttcyhlbmNvZGVyKTsK KwlzdHJ1Y3QgbXNtX2ttcyAqa21zID0gJm1kcDVfa21zLT5iYXNlLmJhc2U7CisJY29uc3Qgc3Ry dWN0IG1zbV9mb3JtYXQgKm1zbV9mbXQ7CisJY29uc3Qgc3RydWN0IG1kcF9mb3JtYXQgKmZtdDsK KwlzdHJ1Y3QgbXNtX3diICp3YiA9IGdldF93YihlbmNvZGVyKTsKKwlzdHJ1Y3QgbXNtX3diX2J1 Zl9mb3JtYXQgKndiX2J1Zl9mbXQ7CisJc3RydWN0IG1zbV93Yl9idWZmZXIgKmJ1ZjsKKwl1MzIg d2JfaWQ7CisJdTMyIGRzdF9mb3JtYXQsIHBhdHRlcm4sIHlzdHJpZGUwLCB5c3RyaWRlMSwgb3V0 c2l6ZSwgY2hyb21hX3NhbXA7CisJdTMyIG9wbW9kZSA9IDA7CisKKwlEQkcoIldiMiBlbmNvZGVy IG1vZGVzZXQiKTsKKworCS8qIG5vdyB3ZSBjYW4gZ2V0IHRoZSBjdGwgZnJvbSBjcnRjIGFuZCBl eHRyYWN0IHRoZSB3Yl9pZCBmcm9tIGN0bCAqLworCWlmICghbWRwNV93Yl9lbmNvZGVyLT5jdGwp CisJCW1kcDVfd2JfZW5jb2Rlci0+Y3RsID0gbWRwNV9jcnRjX2dldF9jdGwoZW5jb2Rlci0+Y3J0 Yyk7CisKKwl3Yl9pZCA9IG1kcDVfY3RsX2dldF9jdGxfaWQobWRwNV93Yl9lbmNvZGVyLT5jdGwp OworCW1kcDVfd2JfZW5jb2Rlci0+d2JfaWQgPSB3Yl9pZDsKKworCS8qIGdldCBjb2xvcl9mb3Jt YXQgZnJvbSB3YiBkZXZpY2UgKi8KKwl3Yl9idWZfZm10ID0gbXNtX3diX2dldF9idWZfZm9ybWF0 KHdiKTsKKwltc21fZm10ID0ga21zLT5mdW5jcy0+Z2V0X2Zvcm1hdChrbXMsIHdiX2J1Zl9mbXQt PnBpeGVsX2Zvcm1hdCk7CisJaWYgKCFtc21fZm10KSB7CisJCXByX2VycigiJXM6IFVuc3VwcG9y dGVkIENvbG9yIEZvcm1hdCAlZFxuIiwgX19mdW5jX18sCisJCQl3Yl9idWZfZm10LT5waXhlbF9m b3JtYXQpOworCQlyZXR1cm47CisJfQorCisJZm10ID0gdG9fbWRwX2Zvcm1hdChtc21fZm10KTsK KwljaHJvbWFfc2FtcCA9IGZtdC0+Y2hyb21hX3NhbXBsZTsKKworCWlmIChNRFBfRk9STUFUX0lT X1lVVihmbXQpKSB7CisJCS8qICBjb25maWcgY3NjICovCisJCURCRygiWVVWIG91dHB1dCAlZCwg Y29uZmlndXJlIENTQyIsCisJCQlmbXQtPmJhc2UucGl4ZWxfZm9ybWF0KTsKKwkJd2JfY3NjX3Nl dHVwKG1kcDVfa21zLCBtZHA1X3diX2VuY29kZXItPndiX2lkLAorCQkJbWRwX2dldF9kZWZhdWx0 X2NzY19jZmcoQ1NDX1JHQjJZVVYpKTsKKwkJb3Btb2RlIHw9IE1EUDVfV0JfRFNUX09QX01PREVf Q1NDX0VOIHwKKwkJCU1EUDVfV0JfRFNUX09QX01PREVfQ1NDX1NSQ19EQVRBX0ZPUk1BVCgKKwkJ CQlEQVRBX0ZPUk1BVF9SR0IpIHwKKwkJCU1EUDVfV0JfRFNUX09QX01PREVfQ1NDX0RTVF9EQVRB X0ZPUk1BVCgKKwkJCQlEQVRBX0ZPUk1BVF9ZVVYpOworCisJCXN3aXRjaCAoY2hyb21hX3NhbXAp IHsKKwkJY2FzZSBDSFJPTUFfNDIwOgorCQljYXNlIENIUk9NQV9IMlYxOgorCQkJb3Btb2RlIHw9 IE1EUDVfV0JfRFNUX09QX01PREVfQ0hST01BX0RXTl9TQU1QTEVfRU47CisJCQlicmVhazsKKwkJ Y2FzZSBDSFJPTUFfSDFWMjoKKwkJZGVmYXVsdDoKKwkJCXByX2VycigidW5zdXBwb3J0ZWQgd2Ig Y2hyb21hIHNhbXA9JWRcbiIsIGNocm9tYV9zYW1wKTsKKwkJCXJldHVybjsKKwkJfQorCX0KKwor CWRzdF9mb3JtYXQgPSBNRFA1X1dCX0RTVF9GT1JNQVRfRFNUX0NIUk9NQV9TQU1QKGNocm9tYV9z YW1wKSB8CisJCU1EUDVfV0JfRFNUX0ZPUk1BVF9XUklURV9QTEFORVMoZm10LT5mZXRjaF90eXBl KSB8CisJCU1EUDVfV0JfRFNUX0ZPUk1BVF9EU1RDM19PVVQoZm10LT5icGNfYSkgfAorCQlNRFA1 X1dCX0RTVF9GT1JNQVRfRFNUQzJfT1VUKGZtdC0+YnBjX3IpIHwKKwkJTURQNV9XQl9EU1RfRk9S TUFUX0RTVEMxX09VVChmbXQtPmJwY19iKSB8CisJCU1EUDVfV0JfRFNUX0ZPUk1BVF9EU1RDMF9P VVQoZm10LT5icGNfZykgfAorCQlDT05EKGZtdC0+dW5wYWNrX3RpZ2h0LCBNRFA1X1dCX0RTVF9G T1JNQVRfUEFDS19USUdIVCkgfAorCQlNRFA1X1dCX0RTVF9GT1JNQVRfUEFDS19DT1VOVChmbXQt PnVucGFja19jb3VudCAtIDEpIHwKKwkJTURQNV9XQl9EU1RfRk9STUFUX0RTVF9CUFAoZm10LT5j cHAgLSAxKTsKKworCWlmIChmbXQtPmJwY19hIHx8IGZtdC0+YWxwaGFfZW5hYmxlKSB7CisJCWRz dF9mb3JtYXQgfD0gTURQNV9XQl9EU1RfRk9STUFUX0RTVEMzX0VOOworCQlpZiAoIWZtdC0+YWxw aGFfZW5hYmxlKQorCQkJZHN0X2Zvcm1hdCB8PSBNRFA1X1dCX0RTVF9GT1JNQVRfRFNUX0FMUEhB X1g7CisJfQorCisJcGF0dGVybiA9IE1EUDVfV0JfRFNUX1BBQ0tfUEFUVEVSTl9FTEVNRU5UMyhm bXQtPnVucGFja1szXSkgfAorCQlNRFA1X1dCX0RTVF9QQUNLX1BBVFRFUk5fRUxFTUVOVDIoZm10 LT51bnBhY2tbMl0pIHwKKwkJTURQNV9XQl9EU1RfUEFDS19QQVRURVJOX0VMRU1FTlQxKGZtdC0+ dW5wYWNrWzFdKSB8CisJCU1EUDVfV0JfRFNUX1BBQ0tfUEFUVEVSTl9FTEVNRU5UMChmbXQtPnVu cGFja1swXSk7CisKKwkvKiBnZXQgdGhlIHN0cmlkZSBpbmZvIGZyb20gV0IgZGV2aWNlICovCisJ eXN0cmlkZTAgPSBNRFA1X1dCX0RTVF9ZU1RSSURFMF9EU1QwX1lTVFJJREUod2JfYnVmX2ZtdC0+ cGl0Y2hlc1swXSkgfAorCQlNRFA1X1dCX0RTVF9ZU1RSSURFMF9EU1QxX1lTVFJJREUod2JfYnVm X2ZtdC0+cGl0Y2hlc1sxXSk7CisJeXN0cmlkZTEgPSBNRFA1X1dCX0RTVF9ZU1RSSURFMV9EU1Qy X1lTVFJJREUod2JfYnVmX2ZtdC0+cGl0Y2hlc1syXSkgfAorCQlNRFA1X1dCX0RTVF9ZU1RSSURF MV9EU1QzX1lTVFJJREUod2JfYnVmX2ZtdC0+cGl0Y2hlc1szXSk7CisKKwkvKiBnZXQgdGhlIG91 dHB1dCByZXNvbHV0aW9uIGZyb20gV0IgZGV2aWNlICovCisJb3V0c2l6ZSA9IE1EUDVfV0JfT1VU X1NJWkVfRFNUX0god2JfYnVmX2ZtdC0+aGVpZ2h0KSB8CisJCU1EUDVfV0JfT1VUX1NJWkVfRFNU X1cod2JfYnVmX2ZtdC0+d2lkdGgpOworCisJbWRwNV93cml0ZShtZHA1X2ttcywgUkVHX01EUDVf V0JfQUxQSEFfWF9WQUxVRSh3Yl9pZCksIDB4RkYpOworCW1kcDVfd3JpdGUobWRwNV9rbXMsIFJF R19NRFA1X1dCX0RTVF9GT1JNQVQod2JfaWQpLCBkc3RfZm9ybWF0KTsKKwltZHA1X3dyaXRlKG1k cDVfa21zLCBSRUdfTURQNV9XQl9EU1RfT1BfTU9ERSh3Yl9pZCksIG9wbW9kZSk7CisJbWRwNV93 cml0ZShtZHA1X2ttcywgUkVHX01EUDVfV0JfRFNUX1BBQ0tfUEFUVEVSTih3Yl9pZCksIHBhdHRl cm4pOworCW1kcDVfd3JpdGUobWRwNV9rbXMsIFJFR19NRFA1X1dCX0RTVF9ZU1RSSURFMCh3Yl9p ZCksIHlzdHJpZGUwKTsKKwltZHA1X3dyaXRlKG1kcDVfa21zLCBSRUdfTURQNV9XQl9EU1RfWVNU UklERTEod2JfaWQpLCB5c3RyaWRlMSk7CisJbWRwNV93cml0ZShtZHA1X2ttcywgUkVHX01EUDVf V0JfT1VUX1NJWkUod2JfaWQpLCBvdXRzaXplKTsKKworCW1kcDVfY3J0Y19zZXRfaW50ZihlbmNv ZGVyLT5jcnRjLCAmbWRwNV93Yl9lbmNvZGVyLT5pbnRmKTsKKworCS8qIHByb2dyYW0gdGhlIGRz dCBhZGRyZXNzICovCisJYnVmID0gbXNtX3diX2RlcXVldWVfYnVmKHdiLCBNU01fV0JfQlVGX1Ff RlJFRSk7CisJLyoKKwkgKiBpZiBubyBmcmVlIGJ1ZmZlciBpcyBhdmFpbGFibGUsIHRoZSBvbmx5 IHBvc3NpYmlsaXR5IGlzCisJICogV0IgY29ubmVjdG9yIGJlY29tZXMgb2ZmbGluZS4gVXNlciBh cHAgc2hvdWxkIGJlIG5vdGlmaWVkCisJICogYnkgdWRldiBldmVudCBhbmQgc3RvcCB0aGUgcmVu ZGVyaW5nIHNvb24uCisJICogc28gZG9uJ3QgZG8gYW55dGhpbmcgaGVyZS4KKwkgKi8KKwlpZiAo IWJ1ZikgeworCQlwcl93YXJuKCIlczogTm8gYnVmZmVyIGF2YWlsYWJsZVxuIiwgX19mdW5jX18p OworCQlyZXR1cm47CisJfQorCisJLyogTGFzdCBzdGVwIG9mIG1vZGUgc2V0OiBzZXQgdXAgZHN0 IGFkZHJlc3MgKi8KKwltc21fd2JfcXVldWVfYnVmKHdiLCBidWYsIE1TTV9XQl9CVUZfUV9BQ1RJ VkUpOworCW1kcDVfd2JfZW5jb2Rlcl9hZGRyX3NldHVwKGVuY29kZXIsIGJ1Zik7Cit9CisKK3N0 YXRpYyB2b2lkIG1kcDVfd2JfZW5jb2Rlcl9kaXNhYmxlKHN0cnVjdCBkcm1fZW5jb2RlciAqZW5j b2RlcikKK3sKKwlzdHJ1Y3QgbWRwNV93Yl9lbmNvZGVyICptZHA1X3diX2VuY29kZXIgPSB0b19t ZHA1X3diX2VuY29kZXIoZW5jb2Rlcik7CisJc3RydWN0IG1kcDVfa21zICptZHA1X2ttcyA9IGdl dF9rbXMoZW5jb2Rlcik7CisJc3RydWN0IG1kcDVfY3RsICpjdGwgPSBtZHA1X2NydGNfZ2V0X2N0 bChlbmNvZGVyLT5jcnRjKTsKKwlzdHJ1Y3QgbXNtX3diICp3YiA9IGdldF93YihlbmNvZGVyKTsK KwlzdHJ1Y3QgbXNtX3diX2J1ZmZlciAqYnVmOworCisJREJHKCJEaXNhYmxlIHdiIGVuY29kZXIi KTsKKworCWlmIChXQVJOX09OKCFtZHA1X3diX2VuY29kZXItPmVuYWJsZWQpKQorCQlyZXR1cm47 CisKKwltZHA1X2N0bF9zZXRfZW5jb2Rlcl9zdGF0ZShjdGwsIGZhbHNlKTsKKworCW1kcF9pcnFf dW5yZWdpc3RlcigmbWRwNV9rbXMtPmJhc2UsCisJCSZtZHA1X3diX2VuY29kZXItPndiX3ZibGFu ayk7CisKKwkvKiBtb3ZlIHRoZSBhY3RpdmUgYnVmIHRvIGZyZWUgYnVmIHF1ZXVlKi8KKwl3aGls ZSAoKGJ1ZiA9IG1zbV93Yl9kZXF1ZXVlX2J1Zih3YiwgTVNNX1dCX0JVRl9RX0FDVElWRSkpCisJ CSE9IE5VTEwpCisJCW1zbV93Yl9xdWV1ZV9idWYod2IsIGJ1ZiwgTVNNX1dCX0JVRl9RX0ZSRUUp OworCisJbXNtX3diX3VwZGF0ZV9lbmNvZGVyX3N0YXRlKHdiLCBmYWxzZSk7CisJYnNfc2V0KG1k cDVfd2JfZW5jb2RlciwgMCk7CisKKwltZHA1X3diX2VuY29kZXItPmVuYWJsZWQgPSBmYWxzZTsK K30KKworc3RhdGljIHZvaWQgbWRwNV93Yl9lbmNvZGVyX2VuYWJsZShzdHJ1Y3QgZHJtX2VuY29k ZXIgKmVuY29kZXIpCit7CisJc3RydWN0IG1kcDVfd2JfZW5jb2RlciAqbWRwNV93Yl9lbmNvZGVy ID0gdG9fbWRwNV93Yl9lbmNvZGVyKGVuY29kZXIpOworCXN0cnVjdCBtZHA1X2ttcyAqbWRwNV9r bXMgPSBnZXRfa21zKGVuY29kZXIpOworCXN0cnVjdCBtZHA1X2N0bCAqY3RsID0gbWRwNV9jcnRj X2dldF9jdGwoZW5jb2Rlci0+Y3J0Yyk7CisJc3RydWN0IG1zbV93YiAqd2IgPSBnZXRfd2IoZW5j b2Rlcik7CisKKwlEQkcoIkVuYWJsZSB3YiBlbmNvZGVyIik7CisKKwlpZiAoV0FSTl9PTihtZHA1 X3diX2VuY29kZXItPmVuYWJsZWQpKQorCQlyZXR1cm47CisKKwlic19zZXQobWRwNV93Yl9lbmNv ZGVyLCAxKTsKKwltZHBfaXJxX3JlZ2lzdGVyKCZtZHA1X2ttcy0+YmFzZSwKKwkJJm1kcDVfd2Jf ZW5jb2Rlci0+d2JfdmJsYW5rKTsKKworCisJbWRwNV9jdGxfc2V0X2VuY29kZXJfc3RhdGUoY3Rs LCB0cnVlKTsKKwltc21fd2JfdXBkYXRlX2VuY29kZXJfc3RhdGUod2IsIHRydWUpOworCisJbWRw NV93Yl9lbmNvZGVyLT5lbmFibGVkID0gdHJ1ZTsKK30KKworc3RhdGljIGNvbnN0IHN0cnVjdCBk cm1fZW5jb2Rlcl9oZWxwZXJfZnVuY3MgbWRwNV93Yl9lbmNvZGVyX2hlbHBlcl9mdW5jcyA9IHsK KwkubW9kZV9maXh1cCA9IG1kcDVfd2JfZW5jb2Rlcl9tb2RlX2ZpeHVwLAorCS5tb2RlX3NldCA9 IG1kcDVfd2JfZW5jb2Rlcl9tb2RlX3NldCwKKwkuZGlzYWJsZSA9IG1kcDVfd2JfZW5jb2Rlcl9k aXNhYmxlLAorCS5lbmFibGUgPSBtZHA1X3diX2VuY29kZXJfZW5hYmxlLAorfTsKKworc3RhdGlj IHZvaWQgbWRwNV93Yl9lbmNvZGVyX3ZibGFua19pcnEoc3RydWN0IG1kcF9pcnEgKmlycSwgdWlu dDMyX3QgaXJxc3RhdHVzKQoreworCXN0cnVjdCBtZHA1X3diX2VuY29kZXIgKm1kcDVfd2JfZW5j b2RlciA9CisJCWNvbnRhaW5lcl9vZihpcnEsIHN0cnVjdCBtZHA1X3diX2VuY29kZXIsIHdiX3Zi bGFuayk7CisJc3RydWN0IG1kcDVfa21zICptZHA1X2ttcyA9IGdldF9rbXMoJm1kcDVfd2JfZW5j b2Rlci0+YmFzZSk7CisJc3RydWN0IG1zbV93YiAqd2IgPSBnZXRfd2IoJm1kcDVfd2JfZW5jb2Rl ci0+YmFzZSk7CisJdTMyIHdiX2lkID0gbWRwNV93Yl9lbmNvZGVyLT53Yl9pZDsKKwlzdHJ1Y3Qg bXNtX3diX2J1ZmZlciAqbmV3X2J1ZiwgKmJ1ZjsKKwl1MzIgcmVnX3ZhbDsKKworCURCRygid2Ig aWQgJWQiLCB3Yl9pZCk7CisKKwlyZWdfdmFsID0gbWRwNV9yZWFkKG1kcDVfa21zLCBSRUdfTURQ NV9XQl9EU1QwX0FERFIod2JfaWQpKTsKKwlidWYgPSBtc21fd2JfZGVxdWV1ZV9idWYod2IsIE1T TV9XQl9CVUZfUV9BQ1RJVkUpOworCWlmIChXQVJOX09OKCFidWYgfHwgKHJlZ192YWwgIT0gYnVm LT5pb3ZhWzBdKSkpIHsKKwkJaWYgKCFidWYpCisJCQlwcl9lcnIoIiVzOiBubyBhY3RpdmUgYnVm ZmVyXG4iLCBfX2Z1bmNfXyk7CisJCWVsc2UKKwkJCXByX2VycigiJXM6IGN1cnJlbnQgYWRkciAl eCBleHBlY3QgJXhcbiIsCisJCQkJX19mdW5jX18sIHJlZ192YWwsIGJ1Zi0+aW92YVswXSk7CisJ CXJldHVybjsKKwl9CisKKwkvKiByZXRyaWV2ZSB0aGUgZnJlZSBidWZmZXIgKi8KKwluZXdfYnVm ID0gbXNtX3diX2RlcXVldWVfYnVmKHdiLCBNU01fV0JfQlVGX1FfRlJFRSk7CisJaWYgKCFuZXdf YnVmKSB7CisJCXByX2luZm8oIiVzOiBObyBidWZmZXIgaXMgYXZhaWxhYmxlXG4iLCBfX2Z1bmNf Xyk7CisJCS8qIHJldXNlIGN1cnJlbnQgYWN0aXZlIGJ1ZmZlciAqLworCQluZXdfYnVmID0gYnVm OworCX0gZWxzZSB7CisJCW1zbV93Yl9idWZfY2FwdHVyZWQod2IsIGJ1ZiwgZmFsc2UpOworCX0K KworCS8qIFVwZGF0ZSB0aGUgYWRkcmVzcyBhbnl3YXkgdG8gdHJpZ2dlciB0aGUgV0IgZmx1c2gg Ki8KKwltc21fd2JfcXVldWVfYnVmKHdiLCBuZXdfYnVmLCBNU01fV0JfQlVGX1FfQUNUSVZFKTsK KwltZHA1X3diX2VuY29kZXJfYWRkcl9zZXR1cCgmbWRwNV93Yl9lbmNvZGVyLT5iYXNlLCBuZXdf YnVmKTsKK30KKworLyogaW5pdGlhbGl6ZSBlbmNvZGVyICovCitzdHJ1Y3QgZHJtX2VuY29kZXIg Km1kcDVfd2JfZW5jb2Rlcl9pbml0KHN0cnVjdCBkcm1fZGV2aWNlICpkZXYsCisJCQkJc3RydWN0 IG1kcDVfaW50ZXJmYWNlICppbnRmKQoreworCXN0cnVjdCBkcm1fZW5jb2RlciAqZW5jb2RlciA9 IE5VTEw7CisJc3RydWN0IG1kcDVfd2JfZW5jb2RlciAqbWRwNV93Yl9lbmNvZGVyOworCWludCBy ZXQ7CisKKwlEQkcoIkluaXQgd3JpdGViYWNrIGVuY29kZXIiKTsKKworCW1kcDVfd2JfZW5jb2Rl ciA9IGt6YWxsb2Moc2l6ZW9mKCptZHA1X3diX2VuY29kZXIpLCBHRlBfS0VSTkVMKTsKKwlpZiAo IW1kcDVfd2JfZW5jb2RlcikgeworCQlyZXQgPSAtRU5PTUVNOworCQlnb3RvIGZhaWw7CisJfQor CisJbWVtY3B5KCZtZHA1X3diX2VuY29kZXItPmludGYsIGludGYsIHNpemVvZihtZHA1X3diX2Vu Y29kZXItPmludGYpKTsKKwllbmNvZGVyID0gJm1kcDVfd2JfZW5jb2Rlci0+YmFzZTsKKworCWRy bV9lbmNvZGVyX2luaXQoZGV2LCBlbmNvZGVyLCAmbWRwNV93Yl9lbmNvZGVyX2Z1bmNzLAorCQkg RFJNX01PREVfRU5DT0RFUl9WSVJUVUFMKTsKKwlkcm1fZW5jb2Rlcl9oZWxwZXJfYWRkKGVuY29k ZXIsICZtZHA1X3diX2VuY29kZXJfaGVscGVyX2Z1bmNzKTsKKworCW1kcDVfd2JfZW5jb2Rlci0+ d2JfdmJsYW5rLmlycSA9IG1kcDVfd2JfZW5jb2Rlcl92YmxhbmtfaXJxOworCW1kcDVfd2JfZW5j b2Rlci0+d2JfdmJsYW5rLmlycW1hc2sgPSBpbnRmMnZibGFuaygwLCBpbnRmKTsKKworCWJzX2lu aXQobWRwNV93Yl9lbmNvZGVyKTsKKworCXJldHVybiBlbmNvZGVyOworCitmYWlsOgorCWlmIChl bmNvZGVyKQorCQltZHA1X3diX2VuY29kZXJfZGVzdHJveShlbmNvZGVyKTsKKworCXJldHVybiBF UlJfUFRSKHJldCk7Cit9CmRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vbXNtL21kcC9tZHBf a21zLmggYi9kcml2ZXJzL2dwdS9kcm0vbXNtL21kcC9tZHBfa21zLmgKaW5kZXggNWFlNDAzOS4u MmQzNDI4YyAxMDA2NDQKLS0tIGEvZHJpdmVycy9ncHUvZHJtL21zbS9tZHAvbWRwX2ttcy5oCisr KyBiL2RyaXZlcnMvZ3B1L2RybS9tc20vbWRwL21kcF9rbXMuaApAQCAtODgsNyArODgsNyBAQCBz dHJ1Y3QgbWRwX2Zvcm1hdCB7CiAJdWludDhfdCB1bnBhY2tbNF07CiAJYm9vbCBhbHBoYV9lbmFi bGUsIHVucGFja190aWdodDsKIAl1aW50OF90IGNwcCwgdW5wYWNrX2NvdW50OwotCWVudW0gbWRw X3NzcHBfZmV0Y2hfdHlwZSBmZXRjaF90eXBlOworCWVudW0gbWRwX2ZldGNoX3R5cGUgZmV0Y2hf dHlwZTsKIAllbnVtIG1kcF9jaHJvbWFfc2FtcF90eXBlIGNocm9tYV9zYW1wbGU7CiB9OwogI2Rl ZmluZSB0b19tZHBfZm9ybWF0KHgpIGNvbnRhaW5lcl9vZih4LCBzdHJ1Y3QgbWRwX2Zvcm1hdCwg YmFzZSkKZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9tc20vbWRwL21kcF93Yi9tZHBfd2Iu YyBiL2RyaXZlcnMvZ3B1L2RybS9tc20vbWRwL21kcF93Yi9tZHBfd2IuYwpuZXcgZmlsZSBtb2Rl IDEwMDY0NAppbmRleCAwMDAwMDAwLi41YzQwZWM5Ci0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVy cy9ncHUvZHJtL21zbS9tZHAvbWRwX3diL21kcF93Yi5jCkBAIC0wLDAgKzEsMzE5IEBACisvKiBD b3B5cmlnaHQgKGMpIDIwMTUsIFRoZSBMaW51eCBGb3VuZGF0aW9uLiBBbGwgcmlnaHRzIHJlc2Vy dmVkLgorICoKKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlz dHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5CisgKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdO VSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb24gMiBhbmQKKyAqIG9ubHkgdmVyc2lvbiAy IGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLgorICoKKyAqIFRo aXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNl ZnVsLAorICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxp ZWQgd2FycmFudHkgb2YKKyAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJ Q1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUKKyAqIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZv ciBtb3JlIGRldGFpbHMuCisgKi8KKworI2luY2x1ZGUgIm1kcF93Yi5oIgorI2luY2x1ZGUgIm1z bV9rbXMuaCIKKyNpbmNsdWRlICIuLi9tZHBfa21zLmgiCisKK3N0cnVjdCBtc21fd2JfcHJpdl9k YXRhIHsKKwlib29sIHN0cmVhbWluZzsKKworCXN0cnVjdCBtc21fd2JfYnVmX2Zvcm1hdCBmbXQ7 CisJLyogYnVmIHF1ZXVlICovCisJc3RydWN0IG1zbV93Yl9idWZfcXVldWUgdmlkcTsKKwlzcGlu bG9ja190IHZpZHFfbG9jazsKKworCS8qIHdhaXQgcXVldWUgdG8gc3luYyBiZXR3ZWVuIHY0bDIg YW5kIGRybSBkdXJpbmcgc3RyZWFtIG9mZiAqLworCWJvb2wgZW5jb2Rlcl9vbjsKKwl3YWl0X3F1 ZXVlX2hlYWRfdCBlbmNvZGVyX3N0YXRlX3dxOworfTsKKwordm9pZCBtc21fd2JfdXBkYXRlX2Vu Y29kZXJfc3RhdGUoc3RydWN0IG1zbV93YiAqd2IsIGJvb2wgZW5hYmxlKQoreworCXdiLT5wcml2 X2RhdGEtPmVuY29kZXJfb24gPSBlbmFibGU7CisJd2FrZV91cF9hbGwoJndiLT5wcml2X2RhdGEt PmVuY29kZXJfc3RhdGVfd3EpOworfQorCitzdHJ1Y3QgbXNtX3diX2J1Zl9mb3JtYXQgKm1zbV93 Yl9nZXRfYnVmX2Zvcm1hdChzdHJ1Y3QgbXNtX3diICp3YikKK3sKKwlyZXR1cm4gJndiLT5wcml2 X2RhdGEtPmZtdDsKK30KKworaW50IG1zbV93Yl9zZXRfYnVmX2Zvcm1hdChzdHJ1Y3QgbXNtX3di ICp3YiwgdTMyIHBpeGVsX2ZtdCwKKwkJdTMyIHdpZHRoLCB1MzIgaGVpZ2h0KQoreworCXN0cnVj dCBtc21fZHJtX3ByaXZhdGUgKnByaXYgPSB3Yi0+ZGV2LT5kZXZfcHJpdmF0ZTsKKwlzdHJ1Y3Qg bXNtX2ttcyAqa21zID0gcHJpdi0+a21zOworCWNvbnN0IHN0cnVjdCBtc21fZm9ybWF0ICptc21f Zm10OworCWNvbnN0IHN0cnVjdCBtZHBfZm9ybWF0ICptZHBfZm10OworCXN0cnVjdCBtc21fd2Jf YnVmX2Zvcm1hdCAqZm10ID0gJndiLT5wcml2X2RhdGEtPmZtdDsKKworCW1zbV9mbXQgPSBrbXMt PmZ1bmNzLT5nZXRfZm9ybWF0KGttcywgcGl4ZWxfZm10KTsKKwlpZiAoIW1zbV9mbXQpIHsKKwkJ cHJfZXJyKCIlczogVW5zdXBwb3J0ZWQgQ29sb3IgRm9ybWF0ICVkXG4iLCBfX2Z1bmNfXywKKwkJ CXBpeGVsX2ZtdCk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCW1kcF9mbXQgPSB0b19tZHBf Zm9ybWF0KG1zbV9mbXQpOworCisJZm10LT5waXhlbF9mb3JtYXQgPSBwaXhlbF9mbXQ7CisJZm10 LT53aWR0aCA9IHdpZHRoOworCWZtdC0+aGVpZ2h0ID0gaGVpZ2h0OworCURCRygiU2V0IGZvcm1h dCAleCB3aWR0aCAlZCBoZWlnaHQgJWQiLCBwaXhlbF9mbXQsIHdpZHRoLCBoZWlnaHQpOworCisJ c3dpdGNoIChtZHBfZm10LT5mZXRjaF90eXBlKSB7CisJY2FzZSBNRFBfUExBTkVfSU5URVJMRUFW RUQ6CisJCWZtdC0+cGxhbmVfbnVtID0gMTsKKwkJZm10LT5waXRjaGVzWzBdID0gd2lkdGggKiBt ZHBfZm10LT5jcHA7CisJCWJyZWFrOworCWNhc2UgTURQX1BMQU5FX1BMQU5BUjoKKwkJZm10LT5w bGFuZV9udW0gPSAzOworCQlmbXQtPnBpdGNoZXNbMF0gPSB3aWR0aDsKKwkJZm10LT5waXRjaGVz WzFdID0gd2lkdGg7CisJCWZtdC0+cGl0Y2hlc1syXSA9IHdpZHRoOworCQlpZiAobWRwX2ZtdC0+ YWxwaGFfZW5hYmxlKSB7CisJCQlmbXQtPnBsYW5lX251bSA9IDQ7CisJCQlmbXQtPnBpdGNoZXNb M10gPSB3aWR0aDsKKwkJfQorCQlicmVhazsKKwljYXNlIE1EUF9QTEFORV9QU0VVRE9fUExBTkFS OgorCQlmbXQtPnBsYW5lX251bSA9IDI7CisJCWZtdC0+cGl0Y2hlc1swXSA9IHdpZHRoOworCQlz d2l0Y2ggKG1kcF9mbXQtPmNocm9tYV9zYW1wbGUpIHsKKwkJY2FzZSBDSFJPTUFfSDJWMToKKwkJ Y2FzZSBDSFJPTUFfNDIwOgorCQkJZm10LT5waXRjaGVzWzFdID0gd2lkdGgvMjsKKwkJCWJyZWFr OworCQljYXNlIENIUk9NQV9IMVYyOgorCQkJZm10LT5waXRjaGVzWzFdID0gd2lkdGg7CisJCQli cmVhazsKKwkJZGVmYXVsdDoKKwkJCXByX2VycigiJXM6IE5vdCBzdXBwb3J0ZWQgZm10XG4iLCBf X2Z1bmNfXyk7CisJCQlyZXR1cm4gLUVJTlZBTDsKKwkJfQorCQlicmVhazsKKwl9CisKKwlyZXR1 cm4gMDsKK30KKwordm9pZCBtc21fd2JfcXVldWVfYnVmKHN0cnVjdCBtc21fd2IgKndiLCBzdHJ1 Y3QgbXNtX3diX2J1ZmZlciAqd2JfYnVmLAorCWVudW0gbXNtX3diX2J1Zl9xdWV1ZV90eXBlIHR5 cGUpCit7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKwlzdHJ1Y3QgbGlzdF9oZWFkICpxOworCisJ aWYgKHR5cGUgPT0gTVNNX1dCX0JVRl9RX0ZSRUUpCisJCXEgPSAmd2ItPnByaXZfZGF0YS0+dmlk cS5mcmVlOworCWVsc2UKKwkJcSA9ICZ3Yi0+cHJpdl9kYXRhLT52aWRxLmFjdGl2ZTsKKworCWlm ICh0eXBlID09IE1TTV9XQl9CVUZfUV9GUkVFKQorCQltZHA1X3diX2VuY29kZXJfYnVmX3ByZXBh cmUod2IsIHdiX2J1Zik7CisKKwlzcGluX2xvY2tfaXJxc2F2ZSgmd2ItPnByaXZfZGF0YS0+dmlk cV9sb2NrLCBmbGFncyk7CisJbGlzdF9hZGRfdGFpbCgmd2JfYnVmLT5saXN0LCBxKTsKKwlzcGlu X3VubG9ja19pcnFyZXN0b3JlKCZ3Yi0+cHJpdl9kYXRhLT52aWRxX2xvY2ssIGZsYWdzKTsKK30K Kworc3RydWN0IG1zbV93Yl9idWZmZXIgKm1zbV93Yl9kZXF1ZXVlX2J1ZihzdHJ1Y3QgbXNtX3di ICp3YiwKKwllbnVtIG1zbV93Yl9idWZfcXVldWVfdHlwZSB0eXBlKQoreworCXN0cnVjdCBtc21f d2JfYnVmZmVyICpidWYgPSBOVUxMOworCXVuc2lnbmVkIGxvbmcgZmxhZ3M7CisJc3RydWN0IGxp c3RfaGVhZCAqcTsKKworCWlmICh0eXBlID09IE1TTV9XQl9CVUZfUV9GUkVFKQorCQlxID0gJndi LT5wcml2X2RhdGEtPnZpZHEuZnJlZTsKKwllbHNlCisJCXEgPSAmd2ItPnByaXZfZGF0YS0+dmlk cS5hY3RpdmU7CisKKwlzcGluX2xvY2tfaXJxc2F2ZSgmd2ItPnByaXZfZGF0YS0+dmlkcV9sb2Nr LCBmbGFncyk7CisJaWYgKCFsaXN0X2VtcHR5KHEpKSB7CisJCWJ1ZiA9IGxpc3RfZW50cnkocS0+ bmV4dCwKKwkJCQlzdHJ1Y3QgbXNtX3diX2J1ZmZlciwgbGlzdCk7CisJCWxpc3RfZGVsKCZidWYt Pmxpc3QpOworCX0KKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZ3Yi0+cHJpdl9kYXRhLT52aWRx X2xvY2ssIGZsYWdzKTsKKworCXJldHVybiBidWY7Cit9CisKK2ludCBtc21fd2Jfc3RhcnRfc3Ry ZWFtaW5nKHN0cnVjdCBtc21fd2IgKndiKQoreworCWlmICh3Yi0+cHJpdl9kYXRhLT5zdHJlYW1p bmcpIHsKKwkJcHJfZXJyKCIlczogd2IgaXMgc3RyZWFtaW5nXG4iLCBfX2Z1bmNfXyk7CisJCXJl dHVybiAtRUJVU1k7CisJfQorCisJREJHKCJTdHJlYW0gT04iKTsKKwl3Yi0+cHJpdl9kYXRhLT5z dHJlYW1pbmcgPSB0cnVlOworCW1zbV93Yl9jb25uZWN0b3JfaG90cGx1Zyh3Yiwgd2ItPnByaXZf ZGF0YS0+c3RyZWFtaW5nKTsKKworCXJldHVybiAwOworfQorCitpbnQgbXNtX3diX3N0b3Bfc3Ry ZWFtaW5nKHN0cnVjdCBtc21fd2IgKndiKQoreworCWludCByYzsKKwlzdHJ1Y3QgbXNtX3diX2J1 ZmZlciAqYnVmOworCisJaWYgKCF3Yi0+cHJpdl9kYXRhLT5zdHJlYW1pbmcpIHsKKwkJcHJfaW5m bygiJXM6IHdiIGlzIG5vdCBzdHJlYW1pbmdcbiIsIF9fZnVuY19fKTsKKwkJcmV0dXJuIC1FSU5W QUw7CisJfQorCisJREJHKCJTdHJlYW0gb2ZmIik7CisJd2ItPnByaXZfZGF0YS0+c3RyZWFtaW5n ID0gZmFsc2U7CisJbXNtX3diX2Nvbm5lY3Rvcl9ob3RwbHVnKHdiLCB3Yi0+cHJpdl9kYXRhLT5z dHJlYW1pbmcpOworCisJLyogd2FpdCB1bnRpbCBkcm0gZW5jb2RlciBvZmYgKi8KKwlyYyA9IHdh aXRfZXZlbnRfdGltZW91dCh3Yi0+cHJpdl9kYXRhLT5lbmNvZGVyX3N0YXRlX3dxLAorCQkhd2It PnByaXZfZGF0YS0+ZW5jb2Rlcl9vbiwgMTAgKiBIWik7CisJaWYgKCFyYykgeworCQlwcl9lcnIo IiVzOiB3YWl0IGVuY29kZXIgb2ZmIHRpbWVvdXRcbiIsIF9fZnVuY19fKTsKKwkJcmV0dXJuIC1F VElNRURPVVQ7CisJfQorCisJLyogZmx1c2ggYWxsIGFjdGl2ZSBhbmQgZnJlZSBidWZmZXJzICov CisJd2hpbGUgKChidWYgPSBtc21fd2JfZGVxdWV1ZV9idWYod2IsIE1TTV9XQl9CVUZfUV9BQ1RJ VkUpKSAhPSBOVUxMKQorCQltc21fd2JfYnVmX2NhcHR1cmVkKHdiLCBidWYsIHRydWUpOworCisJ d2hpbGUgKChidWYgPSBtc21fd2JfZGVxdWV1ZV9idWYod2IsIE1TTV9XQl9CVUZfUV9GUkVFKSkg IT0gTlVMTCkKKwkJbXNtX3diX2J1Zl9jYXB0dXJlZCh3YiwgYnVmLCB0cnVlKTsKKworCURCRygi U3RyZWFtIHR1cm5lZCBvZmYiKTsKKworCXJldHVybiAwOworfQorCitpbnQgbXNtX3diX21vZGVz ZXRfaW5pdChzdHJ1Y3QgbXNtX3diICp3YiwKKwlzdHJ1Y3QgZHJtX2RldmljZSAqZGV2LCBzdHJ1 Y3QgZHJtX2VuY29kZXIgKmVuY29kZXIpCit7CisJc3RydWN0IG1zbV9kcm1fcHJpdmF0ZSAqcHJp diA9IGRldi0+ZGV2X3ByaXZhdGU7CisJaW50IHJldDsKKworCXdiLT5kZXYgPSBkZXY7CisJd2It PmVuY29kZXIgPSBlbmNvZGVyOworCisJd2ItPmNvbm5lY3RvciA9IG1zbV93Yl9jb25uZWN0b3Jf aW5pdCh3Yik7CisJaWYgKElTX0VSUih3Yi0+Y29ubmVjdG9yKSkgeworCQlyZXQgPSBQVFJfRVJS KHdiLT5jb25uZWN0b3IpOworCQlkZXZfZXJyKGRldi0+ZGV2LCAiZmFpbGVkIHRvIGNyZWF0ZSBX QiBjb25uZWN0b3I6ICVkXG4iLCByZXQpOworCQl3Yi0+Y29ubmVjdG9yID0gTlVMTDsKKwkJZ290 byBmYWlsOworCX0KKworCXByaXYtPmNvbm5lY3RvcnNbcHJpdi0+bnVtX2Nvbm5lY3RvcnMrK10g PSB3Yi0+Y29ubmVjdG9yOworCisJcmV0dXJuIDA7CisKK2ZhaWw6CisJaWYgKHdiLT5jb25uZWN0 b3IpIHsKKwkJd2ItPmNvbm5lY3Rvci0+ZnVuY3MtPmRlc3Ryb3kod2ItPmNvbm5lY3Rvcik7CisJ CXdiLT5jb25uZWN0b3IgPSBOVUxMOworCX0KKworCXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyB2 b2lkIG1zbV93Yl9kZXN0cm95KHN0cnVjdCBtc21fd2IgKndiKQoreworCXBsYXRmb3JtX3NldF9k cnZkYXRhKHdiLT5wZGV2LCBOVUxMKTsKK30KKworc3RhdGljIHN0cnVjdCBtc21fd2IgKm1zbV93 Yl9pbml0KHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCit7CisJc3RydWN0IG1zbV93YiAq d2IgPSBOVUxMOworCisJd2IgPSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRldiwgc2l6ZW9mKCp3Yiks IEdGUF9LRVJORUwpOworCWlmICghd2IpCisJCXJldHVybiBFUlJfUFRSKC1FTk9NRU0pOworCisJ d2ItPnBkZXYgPSBwZGV2OworCXdiLT5wcml2X2RhdGEgPSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRl diwgc2l6ZW9mKCp3Yi0+cHJpdl9kYXRhKSwKKwkJR0ZQX0tFUk5FTCk7CisJaWYgKCF3Yi0+cHJp dl9kYXRhKQorCQlyZXR1cm4gRVJSX1BUUigtRU5PTUVNKTsKKworCWlmIChtc21fd2JfdjRsMl9p bml0KHdiKSkgeworCQlwcl9lcnIoIiVzOiB3YiB2NGwyIGluaXQgZmFpbGVkXG4iLCBfX2Z1bmNf Xyk7CisJCXJldHVybiBFUlJfUFRSKC1FTk9ERVYpOworCX0KKworCXNwaW5fbG9ja19pbml0KCZ3 Yi0+cHJpdl9kYXRhLT52aWRxX2xvY2spOworCUlOSVRfTElTVF9IRUFEKCZ3Yi0+cHJpdl9kYXRh LT52aWRxLmFjdGl2ZSk7CisJSU5JVF9MSVNUX0hFQUQoJndiLT5wcml2X2RhdGEtPnZpZHEuZnJl ZSk7CisJaW5pdF93YWl0cXVldWVfaGVhZCgmd2ItPnByaXZfZGF0YS0+ZW5jb2Rlcl9zdGF0ZV93 cSk7CisKKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2LCB3Yik7CisKKwlyZXR1cm4gd2I7Cit9 CisKK3N0YXRpYyBpbnQgbXNtX3diX2JpbmQoc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgZGV2 aWNlICptYXN0ZXIsIHZvaWQgKmRhdGEpCit7CisJc3RydWN0IGRybV9kZXZpY2UgKmRybSA9IGRl dl9nZXRfZHJ2ZGF0YShtYXN0ZXIpOworCXN0cnVjdCBtc21fZHJtX3ByaXZhdGUgKnByaXYgPSBk cm0tPmRldl9wcml2YXRlOworCXN0cnVjdCBtc21fd2IgKndiOworCisJd2IgPSBtc21fd2JfaW5p dCh0b19wbGF0Zm9ybV9kZXZpY2UoZGV2KSk7CisJaWYgKElTX0VSUih3YikpCisJCXJldHVybiBQ VFJfRVJSKHdiKTsKKworCXByaXYtPndiID0gd2I7CisKKwlyZXR1cm4gMDsKK30KKworc3RhdGlj IHZvaWQgbXNtX3diX3VuYmluZChzdHJ1Y3QgZGV2aWNlICpkZXYsIHN0cnVjdCBkZXZpY2UgKm1h c3RlciwKKwkJdm9pZCAqZGF0YSkKK3sKKwlzdHJ1Y3QgZHJtX2RldmljZSAqZHJtID0gZGV2X2dl dF9kcnZkYXRhKG1hc3Rlcik7CisJc3RydWN0IG1zbV9kcm1fcHJpdmF0ZSAqcHJpdiA9IGRybS0+ ZGV2X3ByaXZhdGU7CisKKwlpZiAocHJpdi0+d2IpIHsKKwkJbXNtX3diX2Rlc3Ryb3kocHJpdi0+ d2IpOworCQlwcml2LT53YiA9IE5VTEw7CisJfQorfQorCitzdGF0aWMgY29uc3Qgc3RydWN0IGNv bXBvbmVudF9vcHMgbXNtX3diX29wcyA9IHsKKwkJLmJpbmQgICA9IG1zbV93Yl9iaW5kLAorCQku dW5iaW5kID0gbXNtX3diX3VuYmluZCwKK307CisKK3N0YXRpYyBpbnQgbXNtX3diX2Rldl9wcm9i ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQoreworCXJldHVybiBjb21wb25lbnRfYWRk KCZwZGV2LT5kZXYsICZtc21fd2Jfb3BzKTsKK30KKworc3RhdGljIGludCBtc21fd2JfZGV2X3Jl bW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQoreworCWNvbXBvbmVudF9kZWwoJnBk ZXYtPmRldiwgJm1zbV93Yl9vcHMpOworCXJldHVybiAwOworfQorCitzdGF0aWMgY29uc3Qgc3Ry dWN0IG9mX2RldmljZV9pZCBkdF9tYXRjaFtdID0geworCXsgLmNvbXBhdGlibGUgPSAicWNvbSxt ZHNzX3diIn0sCisJe30KK307CisKK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIG1zbV93 Yl9kcml2ZXIgPSB7CisJLnByb2JlID0gbXNtX3diX2Rldl9wcm9iZSwKKwkucmVtb3ZlID0gbXNt X3diX2Rldl9yZW1vdmUsCisJLmRyaXZlciA9IHsKKwkJLm5hbWUgPSAid2JfbXNtIiwKKwkJLm9m X21hdGNoX3RhYmxlID0gZHRfbWF0Y2gsCisJfSwKK307CisKK3ZvaWQgX19pbml0IG1zbV93Yl9y ZWdpc3Rlcih2b2lkKQoreworCXBsYXRmb3JtX2RyaXZlcl9yZWdpc3RlcigmbXNtX3diX2RyaXZl cik7Cit9CisKK3ZvaWQgX19leGl0IG1zbV93Yl91bnJlZ2lzdGVyKHZvaWQpCit7CisJcGxhdGZv cm1fZHJpdmVyX3VucmVnaXN0ZXIoJm1zbV93Yl9kcml2ZXIpOworfQpkaWZmIC0tZ2l0IGEvZHJp dmVycy9ncHUvZHJtL21zbS9tZHAvbWRwX3diL21kcF93Yi5oIGIvZHJpdmVycy9ncHUvZHJtL21z bS9tZHAvbWRwX3diL21kcF93Yi5oCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAu LjRjNzU0MTkKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2dwdS9kcm0vbXNtL21kcC9tZHBf d2IvbWRwX3diLmgKQEAgLTAsMCArMSw5OCBAQAorLyogQ29weXJpZ2h0IChjKSAyMDE1LCBUaGUg TGludXggRm91bmRhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KKyAqCisgKiBUaGlzIHByb2dy YW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlm eQorICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5z ZSB2ZXJzaW9uIDIgYW5kCisgKiBvbmx5IHZlcnNpb24gMiBhcyBwdWJsaXNoZWQgYnkgdGhlIEZy ZWUgU29mdHdhcmUgRm91bmRhdGlvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0 ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKKyAqIGJ1dCBXSVRIT1VUIEFO WSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCisgKiBNRVJD SEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhl CisgKiBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgorICovCisK KyNpZm5kZWYgX19XQl9DT05ORUNUT1JfSF9fCisjZGVmaW5lIF9fV0JfQ09OTkVDVE9SX0hfXwor CisjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+CisjaW5jbHVkZSAibXNtX2ttcy5o IgorCitzdHJ1Y3QgdmIyX2J1ZmZlcjsKKworc3RydWN0IG1zbV93Yl9idWZmZXIgeworCXN0cnVj dCBsaXN0X2hlYWQgbGlzdDsKKwlzdHJ1Y3QgZHJtX2dlbV9vYmplY3QgKnBsYW5lc1tNQVhfUExB TkVdOworCXUzMiBwaXhlbF9mb3JtYXQ7CisJdTMyIG9mZnNldHNbTUFYX1BMQU5FXTsKKwl1MzIg aW92YVtNQVhfUExBTkVdOworCXN0cnVjdCB2YjJfYnVmZmVyICp2YjsgLyogdjRsMiBidWZmZXIg Ki8KK307CisKK3N0cnVjdCBtc21fd2JfYnVmX2Zvcm1hdCB7CisJdTMyIHBpeGVsX2Zvcm1hdDsK Kwl1MzIgd2lkdGg7CisJdTMyIGhlaWdodDsKKwl1MzIgcGxhbmVfbnVtOworCXUzMiBwaXRjaGVz W01BWF9QTEFORV07Cit9OworCitlbnVtIG1zbV93Yl9idWZfcXVldWVfdHlwZSB7CisJTVNNX1dC X0JVRl9RX0ZSRUUgPSAwLAorCU1TTV9XQl9CVUZfUV9BQ1RJVkUsCisJTVNNX1dCX0JVRl9RX05V TQorfTsKKworc3RydWN0IG1zbV93Yl9idWZfcXVldWUgeworCXN0cnVjdCBsaXN0X2hlYWQgZnJl ZTsKKwlzdHJ1Y3QgbGlzdF9oZWFkIGFjdGl2ZTsKK307CisKK3N0cnVjdCBtc21fd2JfcHJpdl9k YXRhOworc3RydWN0IG1zbV93YiB7CisJc3RydWN0IGRybV9kZXZpY2UgKmRldjsKKwlzdHJ1Y3Qg cGxhdGZvcm1fZGV2aWNlICpwZGV2OworCisJc3RydWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3Rv cjsKKwlzdHJ1Y3QgZHJtX2VuY29kZXIgKmVuY29kZXI7CisKKwl2b2lkICp3Yl92NGwyOworCisJ c3RydWN0IG1zbV93Yl9wcml2X2RhdGEgKnByaXZfZGF0YTsKK307CisKK2ludCBtc21fd2Jfc3Rh cnRfc3RyZWFtaW5nKHN0cnVjdCBtc21fd2IgKndiKTsKK2ludCBtc21fd2Jfc3RvcF9zdHJlYW1p bmcoc3RydWN0IG1zbV93YiAqd2IpOwordm9pZCBtZHA1X3diX2VuY29kZXJfYnVmX3ByZXBhcmUo c3RydWN0IG1zbV93YiAqd2IsIHN0cnVjdCBtc21fd2JfYnVmZmVyICpidWYpOwordm9pZCBtc21f d2JfY29ubmVjdG9yX2hvdHBsdWcoc3RydWN0IG1zbV93YiAqd2IsIGJvb2wgY29ubmVjdGVkKTsK K2ludCBtc21fd2Jfc2V0X2J1Zl9mb3JtYXQoc3RydWN0IG1zbV93YiAqd2IsIHUzMiBwaXhlbF9m bXQsCisJdTMyIHdpZHRoLCB1MzIgaGVpZ2h0KTsKKworI2lmZGVmIENPTkZJR19EUk1fTVNNX1dC CitzdHJ1Y3QgbXNtX3diX2J1Zl9mb3JtYXQgKm1zbV93Yl9nZXRfYnVmX2Zvcm1hdChzdHJ1Y3Qg bXNtX3diICp3Yik7Cit2b2lkIG1zbV93Yl9xdWV1ZV9idWYoc3RydWN0IG1zbV93YiAqd2IsIHN0 cnVjdCBtc21fd2JfYnVmZmVyICpidWYsCisJZW51bSBtc21fd2JfYnVmX3F1ZXVlX3R5cGUgdHlw ZSk7CitzdHJ1Y3QgbXNtX3diX2J1ZmZlciAqbXNtX3diX2RlcXVldWVfYnVmKHN0cnVjdCBtc21f d2IgKndiLAorCWVudW0gbXNtX3diX2J1Zl9xdWV1ZV90eXBlIHR5cGUpOwordm9pZCBtc21fd2Jf dXBkYXRlX2VuY29kZXJfc3RhdGUoc3RydWN0IG1zbV93YiAqd2IsIGJvb2wgZW5hYmxlKTsKK3Zv aWQgbXNtX3diX2J1Zl9jYXB0dXJlZChzdHJ1Y3QgbXNtX3diICp3Yiwgc3RydWN0IG1zbV93Yl9i dWZmZXIgKmJ1ZiwKKwlib29sIGRpc2NhcmQpOworI2Vsc2UKK3N0YXRpYyBpbmxpbmUgc3RydWN0 IG1zbV93Yl9idWZfZm9ybWF0ICptc21fd2JfZ2V0X2J1Zl9mb3JtYXQoCisJc3RydWN0IG1zbV93 YiAqd2IpIHsgcmV0dXJuIE5VTEw7IH0KK3N0YXRpYyBpbmxpbmUgdm9pZCBtc21fd2JfcXVldWVf YnVmKHN0cnVjdCBtc21fd2IgKndiLAorCXN0cnVjdCBtc21fd2JfYnVmZmVyICpidWYsIGVudW0g bXNtX3diX2J1Zl9xdWV1ZV90eXBlIHR5cGUpIHt9CitzdGF0aWMgaW5saW5lIHN0cnVjdCBtc21f d2JfYnVmZmVyICptc21fd2JfZGVxdWV1ZV9idWYoc3RydWN0IG1zbV93YiAqd2IsCisJZW51bSBt c21fd2JfYnVmX3F1ZXVlX3R5cGUgdHlwZSkgeyByZXR1cm4gTlVMTDsgfQorc3RhdGljIGlubGlu ZSB2b2lkIG1zbV93Yl91cGRhdGVfZW5jb2Rlcl9zdGF0ZShzdHJ1Y3QgbXNtX3diICp3YiwKKwli b29sIGVuYWJsZSkge30KK3N0YXRpYyBpbmxpbmUgdm9pZCBtc21fd2JfYnVmX2NhcHR1cmVkKHN0 cnVjdCBtc21fd2IgKndiLAorCXN0cnVjdCBtc21fd2JfYnVmZmVyICpidWYsIGJvb2wgZGlzY2Fy ZCkge30KKyNlbmRpZgorCitpbnQgbXNtX3diX3Y0bDJfaW5pdChzdHJ1Y3QgbXNtX3diICp3Yik7 CisKKy8qCisgKiB3YiBjb25uZWN0b3I6CisgKi8KK3N0cnVjdCBkcm1fY29ubmVjdG9yICptc21f d2JfY29ubmVjdG9yX2luaXQoc3RydWN0IG1zbV93YiAqd2IpOworCisjZW5kaWYgLyogX19XQl9D T05ORUNUT1JfSF9fICovCmRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vbXNtL21kcC9tZHBf d2IvbWRwX3diX2Nvbm5lY3Rvci5jIGIvZHJpdmVycy9ncHUvZHJtL21zbS9tZHAvbWRwX3diL21k cF93Yl9jb25uZWN0b3IuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi44MTRk ZWM5Ci0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9ncHUvZHJtL21zbS9tZHAvbWRwX3diL21k cF93Yl9jb25uZWN0b3IuYwpAQCAtMCwwICsxLDE1NyBAQAorLyogQ29weXJpZ2h0IChjKSAyMDE1 LCBUaGUgTGludXggRm91bmRhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KKyAqCisgKiBUaGlz IHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29y IG1vZGlmeQorICogaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMg TGljZW5zZSB2ZXJzaW9uIDIgYW5kCisgKiBvbmx5IHZlcnNpb24gMiBhcyBwdWJsaXNoZWQgYnkg dGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4KKyAqCisgKiBUaGlzIHByb2dyYW0gaXMgZGlz dHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKKyAqIGJ1dCBXSVRI T1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCisg KiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBT ZWUgdGhlCisgKiBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgor ICovCisKKyNpbmNsdWRlICJtZHBfd2IuaCIKKworc3RydWN0IG1zbV93Yl9jb25uZWN0b3Igewor CXN0cnVjdCBkcm1fY29ubmVjdG9yIGJhc2U7CisJc3RydWN0IG1zbV93YiAqd2I7CisJc3RydWN0 IHdvcmtfc3RydWN0IGhwZF93b3JrOworCWJvb2wgY29ubmVjdGVkOworfTsKKyNkZWZpbmUgdG9f d2JfY29ubmVjdG9yKHgpIGNvbnRhaW5lcl9vZih4LCBzdHJ1Y3QgbXNtX3diX2Nvbm5lY3Rvciwg YmFzZSkKKworc3RhdGljIGVudW0gZHJtX2Nvbm5lY3Rvcl9zdGF0dXMgbXNtX3diX2Nvbm5lY3Rv cl9kZXRlY3QoCisJCXN0cnVjdCBkcm1fY29ubmVjdG9yICpjb25uZWN0b3IsIGJvb2wgZm9yY2Up Cit7CisJc3RydWN0IG1zbV93Yl9jb25uZWN0b3IgKndiX2Nvbm5lY3RvciA9IHRvX3diX2Nvbm5l Y3Rvcihjb25uZWN0b3IpOworCisJREJHKCIlcyIsIHdiX2Nvbm5lY3Rvci0+Y29ubmVjdGVkID8g ImNvbm5lY3RlZCIgOiAiZGlzY29ubmVjdGVkIik7CisJcmV0dXJuIHdiX2Nvbm5lY3Rvci0+Y29u bmVjdGVkID8KKwkJY29ubmVjdG9yX3N0YXR1c19jb25uZWN0ZWQgOiBjb25uZWN0b3Jfc3RhdHVz X2Rpc2Nvbm5lY3RlZDsKK30KKworc3RhdGljIHZvaWQgbXNtX3diX2hvdHBsdWdfd29yayhzdHJ1 Y3Qgd29ya19zdHJ1Y3QgKndvcmspCit7CisJc3RydWN0IG1zbV93Yl9jb25uZWN0b3IgKndiX2Nv bm5lY3RvciA9CisJCWNvbnRhaW5lcl9vZih3b3JrLCBzdHJ1Y3QgbXNtX3diX2Nvbm5lY3Rvciwg aHBkX3dvcmspOworCXN0cnVjdCBkcm1fY29ubmVjdG9yICpjb25uZWN0b3IgPSAmd2JfY29ubmVj dG9yLT5iYXNlOworCisJZHJtX2ttc19oZWxwZXJfaG90cGx1Z19ldmVudChjb25uZWN0b3ItPmRl dik7Cit9CisKK3ZvaWQgbXNtX3diX2Nvbm5lY3Rvcl9ob3RwbHVnKHN0cnVjdCBtc21fd2IgKndi LCBib29sIGNvbm5lY3RlZCkKK3sKKwlzdHJ1Y3QgZHJtX2Nvbm5lY3RvciAqY29ubmVjdG9yID0g d2ItPmNvbm5lY3RvcjsKKwlzdHJ1Y3QgbXNtX3diX2Nvbm5lY3RvciAqd2JfY29ubmVjdG9yID0g dG9fd2JfY29ubmVjdG9yKGNvbm5lY3Rvcik7CisJc3RydWN0IG1zbV9kcm1fcHJpdmF0ZSAqcHJp diA9IGNvbm5lY3Rvci0+ZGV2LT5kZXZfcHJpdmF0ZTsKKworCXdiX2Nvbm5lY3Rvci0+Y29ubmVj dGVkID0gY29ubmVjdGVkOworCXF1ZXVlX3dvcmsocHJpdi0+d3EsICZ3Yl9jb25uZWN0b3ItPmhw ZF93b3JrKTsKK30KKworc3RhdGljIHZvaWQgbXNtX3diX2Nvbm5lY3Rvcl9kZXN0cm95KHN0cnVj dCBkcm1fY29ubmVjdG9yICpjb25uZWN0b3IpCit7CisJc3RydWN0IG1zbV93Yl9jb25uZWN0b3Ig KndiX2Nvbm5lY3RvciA9IHRvX3diX2Nvbm5lY3Rvcihjb25uZWN0b3IpOworCisJZHJtX2Nvbm5l Y3Rvcl91bnJlZ2lzdGVyKGNvbm5lY3Rvcik7CisJZHJtX2Nvbm5lY3Rvcl9jbGVhbnVwKGNvbm5l Y3Rvcik7CisKKwlrZnJlZSh3Yl9jb25uZWN0b3IpOworfQorCitzdGF0aWMgaW50IG1zbV93Yl9j b25uZWN0b3JfZ2V0X21vZGVzKHN0cnVjdCBkcm1fY29ubmVjdG9yICpjb25uZWN0b3IpCit7CisJ c3RydWN0IG1zbV93Yl9jb25uZWN0b3IgKndiX2Nvbm5lY3RvciA9IHRvX3diX2Nvbm5lY3Rvcihj b25uZWN0b3IpOworCXN0cnVjdCBtc21fd2IgKndiID0gd2JfY29ubmVjdG9yLT53YjsKKwlzdHJ1 Y3QgbXNtX3diX2J1Zl9mb3JtYXQgKndiX2J1Zl9mbXQ7CisJc3RydWN0IGRybV9kaXNwbGF5X21v ZGUgKm1vZGUgPSBOVUxMOworCisJd2JfYnVmX2ZtdCA9IG1zbV93Yl9nZXRfYnVmX2Zvcm1hdCh3 Yik7CisJbW9kZSA9IGRybV9jdnRfbW9kZShjb25uZWN0b3ItPmRldiwgd2JfYnVmX2ZtdC0+d2lk dGgsCisJCXdiX2J1Zl9mbXQtPmhlaWdodCwgNjAsIGZhbHNlLCBmYWxzZSwgZmFsc2UpOworCisJ aWYgKCFtb2RlKSB7CisJCXByX2VycigiJXM6IGZhaWxlZCB0byBjcmVhdGUgbW9kZVxuIiwgX19m dW5jX18pOworCQlyZXR1cm4gLUVOT1RTVVBQOworCX0KKworCWRybV9tb2RlX3Byb2JlZF9hZGQo Y29ubmVjdG9yLCBtb2RlKTsKKworCXJldHVybiAxOworfQorCitzdGF0aWMgaW50IG1zbV93Yl9j b25uZWN0b3JfbW9kZV92YWxpZChzdHJ1Y3QgZHJtX2Nvbm5lY3RvciAqY29ubmVjdG9yLAorCQkJ CSBzdHJ1Y3QgZHJtX2Rpc3BsYXlfbW9kZSAqbW9kZSkKK3sKKwlyZXR1cm4gMDsKK30KKworc3Rh dGljIHN0cnVjdCBkcm1fZW5jb2RlciAqCittc21fd2JfY29ubmVjdG9yX2Jlc3RfZW5jb2Rlcihz dHJ1Y3QgZHJtX2Nvbm5lY3RvciAqY29ubmVjdG9yKQoreworCXN0cnVjdCBtc21fd2JfY29ubmVj dG9yICp3Yl9jb25uZWN0b3IgPSB0b193Yl9jb25uZWN0b3IoY29ubmVjdG9yKTsKKworCXJldHVy biB3Yl9jb25uZWN0b3ItPndiLT5lbmNvZGVyOworfQorCitzdGF0aWMgY29uc3Qgc3RydWN0IGRy bV9jb25uZWN0b3JfZnVuY3MgbXNtX3diX2Nvbm5lY3Rvcl9mdW5jcyA9IHsKKwkuZHBtcyA9IGRy bV9oZWxwZXJfY29ubmVjdG9yX2RwbXMsCisJLmRldGVjdCA9IG1zbV93Yl9jb25uZWN0b3JfZGV0 ZWN0LAorCS5maWxsX21vZGVzID0gZHJtX2hlbHBlcl9wcm9iZV9zaW5nbGVfY29ubmVjdG9yX21v ZGVzLAorCS5kZXN0cm95ID0gbXNtX3diX2Nvbm5lY3Rvcl9kZXN0cm95LAorCS5yZXNldCA9IGRy bV9hdG9taWNfaGVscGVyX2Nvbm5lY3Rvcl9yZXNldCwKKwkuYXRvbWljX2R1cGxpY2F0ZV9zdGF0 ZSA9IGRybV9hdG9taWNfaGVscGVyX2Nvbm5lY3Rvcl9kdXBsaWNhdGVfc3RhdGUsCisJLmF0b21p Y19kZXN0cm95X3N0YXRlID0gZHJtX2F0b21pY19oZWxwZXJfY29ubmVjdG9yX2Rlc3Ryb3lfc3Rh dGUsCisKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgZHJtX2Nvbm5lY3Rvcl9oZWxwZXJfZnVu Y3MgbXNtX3diX2Nvbm5lY3Rvcl9oZWxwZXJfZnVuY3MgPSB7CisJLmdldF9tb2RlcyA9IG1zbV93 Yl9jb25uZWN0b3JfZ2V0X21vZGVzLAorCS5tb2RlX3ZhbGlkID0gbXNtX3diX2Nvbm5lY3Rvcl9t b2RlX3ZhbGlkLAorCS5iZXN0X2VuY29kZXIgPSBtc21fd2JfY29ubmVjdG9yX2Jlc3RfZW5jb2Rl ciwKK307CisKKy8qIGluaXRpYWxpemUgY29ubmVjdG9yICovCitzdHJ1Y3QgZHJtX2Nvbm5lY3Rv ciAqbXNtX3diX2Nvbm5lY3Rvcl9pbml0KHN0cnVjdCBtc21fd2IgKndiKQoreworCXN0cnVjdCBk cm1fY29ubmVjdG9yICpjb25uZWN0b3IgPSBOVUxMOworCXN0cnVjdCBtc21fd2JfY29ubmVjdG9y ICp3Yl9jb25uZWN0b3I7CisJaW50IHJldDsKKworCXdiX2Nvbm5lY3RvciA9IGt6YWxsb2Moc2l6 ZW9mKCp3Yl9jb25uZWN0b3IpLCBHRlBfS0VSTkVMKTsKKwlpZiAoIXdiX2Nvbm5lY3Rvcikgewor CQlyZXQgPSAtRU5PTUVNOworCQlnb3RvIGZhaWw7CisJfQorCisJd2JfY29ubmVjdG9yLT53YiA9 IHdiOworCWNvbm5lY3RvciA9ICZ3Yl9jb25uZWN0b3ItPmJhc2U7CisKKwlyZXQgPSBkcm1fY29u bmVjdG9yX2luaXQod2ItPmRldiwgY29ubmVjdG9yLCAmbXNtX3diX2Nvbm5lY3Rvcl9mdW5jcywK KwkJCURSTV9NT0RFX0NPTk5FQ1RPUl9WSVJUVUFMKTsKKwlpZiAocmV0KQorCQlnb3RvIGZhaWw7 CisKKwlkcm1fY29ubmVjdG9yX2hlbHBlcl9hZGQoY29ubmVjdG9yLCAmbXNtX3diX2Nvbm5lY3Rv cl9oZWxwZXJfZnVuY3MpOworCisJY29ubmVjdG9yLT5wb2xsZWQgPSBEUk1fQ09OTkVDVE9SX1BP TExfSFBEOworCisJY29ubmVjdG9yLT5pbnRlcmxhY2VfYWxsb3dlZCA9IDA7CisJY29ubmVjdG9y LT5kb3VibGVzY2FuX2FsbG93ZWQgPSAwOworCisJZHJtX2Nvbm5lY3Rvcl9yZWdpc3Rlcihjb25u ZWN0b3IpOworCisJcmV0ID0gZHJtX21vZGVfY29ubmVjdG9yX2F0dGFjaF9lbmNvZGVyKGNvbm5l Y3Rvciwgd2ItPmVuY29kZXIpOworCWlmIChyZXQpCisJCWdvdG8gZmFpbDsKKworCUlOSVRfV09S Sygmd2JfY29ubmVjdG9yLT5ocGRfd29yaywgbXNtX3diX2hvdHBsdWdfd29yayk7CisKKwlyZXR1 cm4gY29ubmVjdG9yOworCitmYWlsOgorCWlmIChjb25uZWN0b3IpCisJCW1zbV93Yl9jb25uZWN0 b3JfZGVzdHJveShjb25uZWN0b3IpOworCisJcmV0dXJuIEVSUl9QVFIocmV0KTsKK30KZGlmZiAt LWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9tc20vbWRwL21kcF93Yi9tZHBfd2JfdjRsMi5jIGIvZHJp dmVycy9ncHUvZHJtL21zbS9tZHAvbWRwX3diL21kcF93Yl92NGwyLmMKbmV3IGZpbGUgbW9kZSAx MDA2NDQKaW5kZXggMDAwMDAwMC4uZjZkZjRkNAotLS0gL2Rldi9udWxsCisrKyBiL2RyaXZlcnMv Z3B1L2RybS9tc20vbWRwL21kcF93Yi9tZHBfd2JfdjRsMi5jCkBAIC0wLDAgKzEsNTIyIEBACisv KiBDb3B5cmlnaHQgKGMpIDIwMTUsIFRoZSBMaW51eCBGb3VuZGF0aW9uLiBBbGwgcmlnaHRzIHJl c2VydmVkLgorICoKKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJl ZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5CisgKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhl IEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb24gMiBhbmQKKyAqIG9ubHkgdmVyc2lv biAyIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLgorICoKKyAq IFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUg dXNlZnVsLAorICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGlt cGxpZWQgd2FycmFudHkgb2YKKyAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBB UlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUKKyAqIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNl IGZvciBtb3JlIGRldGFpbHMuCisgKi8KKworI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgorI2lu Y2x1ZGUgPGxpbnV4L3ZpZGVvZGV2Mi5oPgorI2luY2x1ZGUgPG1lZGlhL3Y0bDItZGV2aWNlLmg+ CisjaW5jbHVkZSA8bWVkaWEvdjRsMi1pb2N0bC5oPgorI2luY2x1ZGUgPG1lZGlhL3Y0bDItY3Ry bHMuaD4KKyNpbmNsdWRlIDxtZWRpYS92NGwyLWZoLmg+CisjaW5jbHVkZSA8bWVkaWEvdjRsMi1l dmVudC5oPgorI2luY2x1ZGUgPG1lZGlhL3Y0bDItY29tbW9uLmg+CisjaW5jbHVkZSA8bWVkaWEv dmlkZW9idWYyLWNvcmUuaD4KKworI2luY2x1ZGUgIm1kcF93Yi5oIgorCisjZGVmaW5lIE1TTV9X Ql9NT0RVTEVfTkFNRSAibXNtX3diIgorI2RlZmluZSBNQVhfV0lEVEggMjA0OAorI2RlZmluZSBN QVhfSEVJR0hUIDIwNDgKKworc3RhdGljIHVuc2lnbmVkIGRlYnVnOworbW9kdWxlX3BhcmFtKGRl YnVnLCB1aW50LCAwNjQ0KTsKK01PRFVMRV9QQVJNX0RFU0MoZGVidWcsICJhY3RpdmF0ZXMgZGVi dWcgaW5mbyIpOworCisjZGVmaW5lIGRwcmludGsoZGV2LCBsZXZlbCwgZm10LCBhcmcuLi4pIFwK Kwl2NGwyX2RiZyhsZXZlbCwgZGVidWcsICZkZXYtPnY0bDJfZGV2LCBmbXQsICMjIGFyZykKKwor c3RydWN0IG1zbV93Yl9mbXQgeworCWNvbnN0IGNoYXIgKm5hbWU7CisJdTMyIGZvdXJjYzsgICAg ICAgICAgLyogdjRsMiBmb3JtYXQgaWQgKi8KKwl1MzIgZHJtX2ZvdXJjYzsgICAgICAvKiBkcm0g Zm9ybWF0IGlkICovCisJdTggZGVwdGg7CisJdTggcGxhbmVfY250OworCXUzMiBwbGFuZV9icHBb TUFYX1BMQU5FXTsgLyogYml0IHBlciBwaXhlbCBwZXIgcGxhbG5lICovCisJYm9vbCAgaXNfeXV2 OworfTsKKworc3RhdGljIGNvbnN0IHN0cnVjdCBtc21fd2JfZm10IGZvcm1hdHNbXSA9IHsKKwl7 CisJCS5uYW1lICAgICA9ICJZL0NiQ3IgNDoyOjAiLAorCQkuZm91cmNjICAgPSBWNEwyX1BJWF9G TVRfTlYxMiwKKwkJLmRybV9mb3VyY2MgPSBEUk1fRk9STUFUX05WMTIsCisJCS5kZXB0aCAgICA9 IDEyLAorCQkucGxhbmVfY250ID0gMiwKKwkJLnBsYW5lX2JwcCA9IHs4LCA0LCAwLCAwfSwKKwkJ LmlzX3l1diAgID0gdHJ1ZSwKKwl9LAorCXsKKwkJLm5hbWUgICAgID0gIlkvQ3JDYiA0OjI6MCIs CisJCS5mb3VyY2MgICA9IFY0TDJfUElYX0ZNVF9OVjIxLAorCQkuZHJtX2ZvdXJjYyA9IERSTV9G T1JNQVRfTlYyMSwKKwkJLmRlcHRoICAgID0gMTIsCisJCS5wbGFuZV9jbnQgPSAyLAorCQkucGxh bmVfYnBwID0gezgsIDQsIDAsIDB9LAorCQkuaXNfeXV2ICAgPSB0cnVlLAorCX0sCisJeworCQku bmFtZSAgICAgPSAiUkdCMjQiLAorCQkuZm91cmNjICAgPSBWNEwyX1BJWF9GTVRfUkdCMjQsCisJ CS5kcm1fZm91cmNjID0gRFJNX0ZPUk1BVF9SR0I4ODgsCisJCS5kZXB0aCAgICA9IDI0LAorCQku cGxhbmVfY250ID0gMiwKKwkJLnBsYW5lX2JwcCA9IHsyNCwgMCwgMCwgMH0sCisJfSwKKwl7CisJ CS5uYW1lICAgICA9ICJBUkdCMzIiLAorCQkuZm91cmNjICAgPSBWNEwyX1BJWF9GTVRfUkdCMzIs CisJCS5kcm1fZm91cmNjID0gRFJNX0ZPUk1BVF9BUkdCODg4OCwKKwkJLmRlcHRoICAgID0gMzIs CisJCS5wbGFuZV9jbnQgPSAxLAorCQkucGxhbmVfYnBwID0gezI0LCAwLCAwLCAwfSwKKwl9LAor fTsKKworLyogYnVmZmVyIGZvciBvbmUgdmlkZW8gZnJhbWUgKi8KK3N0cnVjdCBtc21fd2JfdjRs Ml9idWZmZXIgeworCS8qIGNvbW1vbiB2NGwgYnVmZmVyIHN0dWZmIC0tIG11c3QgYmUgZmlyc3Qg Ki8KKwlzdHJ1Y3QgdmIyX2J1ZmZlciB2YjsKKwlzdHJ1Y3QgbXNtX3diX2J1ZmZlciB3Yl9idWY7 Cit9OworCitzdHJ1Y3QgbXNtX3diX3Y0bDJfZGV2IHsKKwlzdHJ1Y3QgdjRsMl9kZXZpY2UgdjRs Ml9kZXY7CisJc3RydWN0IHZpZGVvX2RldmljZSB2ZGV2OworCisJc3RydWN0IG11dGV4IG11dGV4 OworCisJLyogdmlkZW8gY2FwdHVyZSAqLworCWNvbnN0IHN0cnVjdCBtc21fd2JfZm10ICpmbXQ7 CisJdW5zaWduZWQgaW50IHdpZHRoLCBoZWlnaHQ7CisKKwlzdHJ1Y3QgdmIyX3F1ZXVlIHZiX3Zp ZHE7CisKKwlzdHJ1Y3QgbXNtX3diICp3YjsKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgbXNt X3diX2ZtdCAqZ2V0X2Zvcm1hdCh1MzIgZm91cmNjKQoreworCWNvbnN0IHN0cnVjdCBtc21fd2Jf Zm10ICpmbXQ7CisJdW5zaWduZWQgaW50IGs7CisKKwlmb3IgKGsgPSAwOyBrIDwgQVJSQVlfU0la RShmb3JtYXRzKTsgaysrKSB7CisJCWZtdCA9ICZmb3JtYXRzW2tdOworCQlpZiAoZm10LT5mb3Vy Y2MgPT0gZm91cmNjKQorCQkJYnJlYWs7CisJfQorCisJaWYgKGsgPT0gQVJSQVlfU0laRShmb3Jt YXRzKSkKKwkJcmV0dXJuIE5VTEw7CisKKwlyZXR1cm4gJmZvcm1hdHNba107Cit9CisKK3ZvaWQg bXNtX3diX2J1Zl9jYXB0dXJlZChzdHJ1Y3QgbXNtX3diICp3YiwKKwlzdHJ1Y3QgbXNtX3diX2J1 ZmZlciAqYnVmLCBib29sIGRpc2NhcmQpCit7CisJc3RydWN0IG1zbV93Yl92NGwyX2J1ZmZlciAq djRsMl9idWYgPQorCQljb250YWluZXJfb2YoYnVmLCBzdHJ1Y3QgbXNtX3diX3Y0bDJfYnVmZmVy LCB3Yl9idWYpOworCWVudW0gdmIyX2J1ZmZlcl9zdGF0ZSBidWZfc3RhdGUgPSBkaXNjYXJkID8g VkIyX0JVRl9TVEFURV9FUlJPUiA6CisJCQlWQjJfQlVGX1NUQVRFX0RPTkU7CisKKwl2NGwyX2dl dF90aW1lc3RhbXAoJnY0bDJfYnVmLT52Yi52NGwyX2J1Zi50aW1lc3RhbXApOworCXZiMl9idWZm ZXJfZG9uZSgmdjRsMl9idWYtPnZiLCBidWZfc3RhdGUpOworfQorCisvKiAtLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KKwlE TUEgYnVmZmVyIG9wZXJhdGlvbnMKKyAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCisKK3N0YXRpYyBpbnQgbXNtX3di X3ZiMl9tYXBfZG1hYnVmKHZvaWQgKm1lbV9wcml2KQoreworCXJldHVybiAwOworfQorCitzdGF0 aWMgdm9pZCBtc21fd2JfdmIyX3VubWFwX2RtYWJ1Zih2b2lkICptZW1fcHJpdikKK3sKK30KKwor c3RhdGljIHZvaWQgKm1zbV93Yl92YjJfYXR0YWNoX2RtYWJ1Zih2b2lkICphbGxvY19jdHgsIHN0 cnVjdCBkbWFfYnVmICpkYnVmLAorCXVuc2lnbmVkIGxvbmcgc2l6ZSwgaW50IHdyaXRlKQorewor CXN0cnVjdCBtc21fd2JfdjRsMl9kZXYgKmRldiA9IGFsbG9jX2N0eDsKKwlzdHJ1Y3QgZHJtX2Rl dmljZSAqZHJtX2RldiA9IGRldi0+d2ItPmRldjsKKwlzdHJ1Y3QgZHJtX2dlbV9vYmplY3QgKm9i ajsKKworCW11dGV4X2xvY2soJmRybV9kZXYtPm9iamVjdF9uYW1lX2xvY2spOworCW9iaiA9IGRy bV9kZXYtPmRyaXZlci0+Z2VtX3ByaW1lX2ltcG9ydChkcm1fZGV2LCBkYnVmKTsKKwlpZiAoV0FS Tl9PTighb2JqKSkgeworCQltdXRleF91bmxvY2soJmRybV9kZXYtPm9iamVjdF9uYW1lX2xvY2sp OworCQl2NGwyX2VycigmZGV2LT52NGwyX2RldiwgIkNhbid0IGNvbnZlcnQgZG1hYnVmIHRvIGdl bSBvYmouXG4iKTsKKwkJcmV0dXJuIE5VTEw7CisJfQorCisJaWYgKG9iai0+ZG1hX2J1Zikgewor CQlpZiAoV0FSTl9PTihvYmotPmRtYV9idWYgIT0gZGJ1ZikpIHsKKwkJCXY0bDJfZXJyKCZkZXYt PnY0bDJfZGV2LAorCQkJCSJkbWEgYnVmIGRvZXNuJ3QgbWF0Y2guXG4iKTsKKwkJCWRybV9nZW1f b2JqZWN0X3VucmVmZXJlbmNlX3VubG9ja2VkKG9iaik7CisKKwkJCW9iaiA9IEVSUl9QVFIoLUVJ TlZBTCk7CisJCX0KKwl9IGVsc2UgeworCQlvYmotPmRtYV9idWYgPSBkYnVmOworCX0KKworCW11 dGV4X3VubG9jaygmZHJtX2Rldi0+b2JqZWN0X25hbWVfbG9jayk7CisKKwlyZXR1cm4gb2JqOwor fQorCitzdGF0aWMgdm9pZCBtc21fd2JfdmIyX2RldGFjaF9kbWFidWYodm9pZCAqbWVtX3ByaXYp Cit7CisJc3RydWN0IGRybV9nZW1fb2JqZWN0ICpvYmogPSBtZW1fcHJpdjsKKworCWRybV9nZW1f b2JqZWN0X3VucmVmZXJlbmNlX3VubG9ja2VkKG9iaik7Cit9CisKK3ZvaWQgKm1zbV93Yl92YjJf Y29va2llKHZvaWQgKmJ1Zl9wcml2KQoreworCXJldHVybiBidWZfcHJpdjsKK30KKworY29uc3Qg c3RydWN0IHZiMl9tZW1fb3BzIG1zbV93Yl92YjJfbWVtX29wcyA9IHsKKwkubWFwX2RtYWJ1ZiA9 IG1zbV93Yl92YjJfbWFwX2RtYWJ1ZiwKKwkudW5tYXBfZG1hYnVmID0gbXNtX3diX3ZiMl91bm1h cF9kbWFidWYsCisJLmF0dGFjaF9kbWFidWYgPSBtc21fd2JfdmIyX2F0dGFjaF9kbWFidWYsCisJ LmRldGFjaF9kbWFidWYgPSBtc21fd2JfdmIyX2RldGFjaF9kbWFidWYsCisJLmNvb2tpZSA9IG1z bV93Yl92YjJfY29va2llLAorfTsKKworLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCisJVmlkZW9idWYgb3BlcmF0aW9u cworICAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tKi8KKyNkZWZpbmUgTVNNX1dCX0JVRl9OVU1fTUlOIDQKKworc3RhdGlj IGludCBtc21fd2JfdmIyX3F1ZXVlX3NldHVwKHN0cnVjdCB2YjJfcXVldWUgKnZxLAorCQljb25z dCBzdHJ1Y3QgdjRsMl9mb3JtYXQgKmZtdCwKKwkJdW5zaWduZWQgaW50ICpuYnVmZmVycywgdW5z aWduZWQgaW50ICpucGxhbmVzLAorCQl1bnNpZ25lZCBpbnQgc2l6ZXNbXSwgdm9pZCAqYWxsb2Nf Y3R4c1tdKQoreworCXN0cnVjdCBtc21fd2JfdjRsMl9kZXYgKmRldiA9IHZiMl9nZXRfZHJ2X3By aXYodnEpOworCWNvbnN0IHN0cnVjdCBtc21fd2JfZm10ICp3Yl9mbXQgPSBkZXYtPmZtdDsKKwlp bnQgaTsKKworCSpuYnVmZmVycyA9IE1TTV9XQl9CVUZfTlVNX01JTjsKKwkqbnBsYW5lcyA9IHdi X2ZtdC0+cGxhbmVfY250OworCisJZm9yIChpID0gMDsgaSA8ICpucGxhbmVzOyBpKyspIHsKKwkJ c2l6ZXNbaV0gPSAod2JfZm10LT5wbGFuZV9icHBbaV0gKiBkZXYtPndpZHRoICoKKwkJCWRldi0+ aGVpZ2h0KSA+PiAzOworCQlhbGxvY19jdHhzW2ldID0gZGV2OworCX0KKworCWRwcmludGsoZGV2 LCAxLCAiJXMsIGNvdW50PSVkLCBwbGFuZSBjb3VudD0lZFxuIiwgX19mdW5jX18sCisJCSpuYnVm ZmVycywgKm5wbGFuZXMpOworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgbXNtX3diX3Zi Ml9idWZfcHJlcGFyZShzdHJ1Y3QgdmIyX2J1ZmZlciAqdmIpCit7CisJcmV0dXJuIDA7Cit9CisK K3N0YXRpYyB2b2lkIG1zbV93Yl92YjJfYnVmX3F1ZXVlKHN0cnVjdCB2YjJfYnVmZmVyICp2YikK K3sKKwlzdHJ1Y3QgbXNtX3diX3Y0bDJfZGV2ICpkZXYgPSB2YjJfZ2V0X2Rydl9wcml2KHZiLT52 YjJfcXVldWUpOworCXN0cnVjdCBtc21fd2JfdjRsMl9idWZmZXIgKmJ1ZiA9CisJCWNvbnRhaW5l cl9vZih2Yiwgc3RydWN0IG1zbV93Yl92NGwyX2J1ZmZlciwgdmIpOworCXN0cnVjdCBtc21fd2Jf YnVmZmVyICp3Yl9idWYgPSAmYnVmLT53Yl9idWY7CisJaW50IGk7CisKKwlkcHJpbnRrKGRldiwg MSwgIiVzXG4iLCBfX2Z1bmNfXyk7CisKKwkvKiBwYXNzIHRoZSBidWZmZXIgdG8gd2IgKi8KKwl3 Yl9idWYtPnZiID0gdmI7CisJd2JfYnVmLT5waXhlbF9mb3JtYXQgPSBkZXYtPmZtdC0+ZHJtX2Zv dXJjYzsKKwlmb3IgKGkgPSAwOyBpIDwgdmItPm51bV9wbGFuZXM7IGkrKykgeworCQl3Yl9idWYt Pm9mZnNldHNbaV0gPSB2Yi0+djRsMl9wbGFuZXNbaV0uZGF0YV9vZmZzZXQ7CisJCXdiX2J1Zi0+ cGxhbmVzW2ldID0gdmIyX3BsYW5lX2Nvb2tpZSh2YiwgaSk7CisJCVdBUk5fT04oIXdiX2J1Zi0+ cGxhbmVzW2ldKTsKKwl9CisKKwltc21fd2JfcXVldWVfYnVmKGRldi0+d2IsIHdiX2J1ZiwgTVNN X1dCX0JVRl9RX0ZSRUUpOworfQorCitzdGF0aWMgaW50IG1zbV93Yl92YjJfc3RhcnRfc3RyZWFt aW5nKHN0cnVjdCB2YjJfcXVldWUgKnZxLCB1bnNpZ25lZCBpbnQgY291bnQpCit7CisJc3RydWN0 IG1zbV93Yl92NGwyX2RldiAqZGV2ID0gdmIyX2dldF9kcnZfcHJpdih2cSk7CisKKwlkcHJpbnRr KGRldiwgMSwgIiVzXG4iLCBfX2Z1bmNfXyk7CisKKwlyZXR1cm4gbXNtX3diX3N0YXJ0X3N0cmVh bWluZyhkZXYtPndiKTsKK30KKworLyogYWJvcnQgc3RyZWFtaW5nIGFuZCB3YWl0IGZvciBsYXN0 IGJ1ZmZlciAqLworc3RhdGljIGludCBtc21fd2JfdmIyX3N0b3Bfc3RyZWFtaW5nKHN0cnVjdCB2 YjJfcXVldWUgKnZxKQoreworCXN0cnVjdCBtc21fd2JfdjRsMl9kZXYgKmRldiA9IHZiMl9nZXRf ZHJ2X3ByaXYodnEpOworCisJZHByaW50ayhkZXYsIDEsICIlc1xuIiwgX19mdW5jX18pOworCisJ cmV0dXJuIG1zbV93Yl9zdG9wX3N0cmVhbWluZyhkZXYtPndiKTsKK30KKworc3RhdGljIGNvbnN0 IHN0cnVjdCB2YjJfb3BzIG1zbV93Yl92YjJfb3BzID0geworCS5xdWV1ZV9zZXR1cCA9IG1zbV93 Yl92YjJfcXVldWVfc2V0dXAsCisJLmJ1Zl9wcmVwYXJlID0gbXNtX3diX3ZiMl9idWZfcHJlcGFy ZSwKKwkuYnVmX3F1ZXVlID0gbXNtX3diX3ZiMl9idWZfcXVldWUsCisJLnN0YXJ0X3N0cmVhbWlu ZyA9IG1zbV93Yl92YjJfc3RhcnRfc3RyZWFtaW5nLAorCS5zdG9wX3N0cmVhbWluZyA9IG1zbV93 Yl92YjJfc3RvcF9zdHJlYW1pbmcsCit9OworCisvKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KKwlJT0NUTCB2aWRpb2Mg aGFuZGxpbmcKKyAgIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovCitzdGF0aWMgaW50IG1zbV93Yl92aWRpb2NfcXVlcnlj YXAoc3RydWN0IGZpbGUgKmZpbGUsIHZvaWQgICpwcml2LAorCQkJCQlzdHJ1Y3QgdjRsMl9jYXBh YmlsaXR5ICpjYXApCit7CisJc3RydWN0IG1zbV93Yl92NGwyX2RldiAqZGV2ID0gdmlkZW9fZHJ2 ZGF0YShmaWxlKTsKKworCXN0cmNweShjYXAtPmRyaXZlciwgIm1zbV93YiIpOworCXN0cmNweShj YXAtPmNhcmQsICJtc21fd2IiKTsKKwlzbnByaW50ZihjYXAtPmJ1c19pbmZvLCBzaXplb2YoY2Fw LT5idXNfaW5mbyksCisJCQkicGxhdGZvcm06JXMiLCBkZXYtPnY0bDJfZGV2Lm5hbWUpOworCWNh cC0+ZGV2aWNlX2NhcHMgPSBWNEwyX0NBUF9WSURFT19DQVBUVVJFX01QTEFORSB8IFY0TDJfQ0FQ X1NUUkVBTUlORzsKKwljYXAtPmNhcGFiaWxpdGllcyA9IGNhcC0+ZGV2aWNlX2NhcHMgfCBWNEwy X0NBUF9ERVZJQ0VfQ0FQUzsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IG1zbV93Yl92 aWRpb2NfZW51bV9mbXRfdmlkX2NhcChzdHJ1Y3QgZmlsZSAqZmlsZSwgdm9pZCAgKnByaXYsCisJ CQkJCXN0cnVjdCB2NGwyX2ZtdGRlc2MgKmYpCit7CisJc3RydWN0IG1zbV93Yl92NGwyX2RldiAq ZGV2ID0gdmlkZW9fZHJ2ZGF0YShmaWxlKTsKKwljb25zdCBzdHJ1Y3QgbXNtX3diX2ZtdCAqZm10 OworCisJaWYgKGYtPnR5cGUgIT0gVjRMMl9CVUZfVFlQRV9WSURFT19DQVBUVVJFX01QTEFORSkg eworCQl2NGwyX2VycigmZGV2LT52NGwyX2RldiwgIkludmFsaWQgYnVmIHR5cGUgJWQuXG4iLAor CQkJZi0+dHlwZSk7CisJCXJldHVybiAtRUlOVkFMOworCX0KKworCWlmIChmLT5pbmRleCA+PSBB UlJBWV9TSVpFKGZvcm1hdHMpKQorCQlyZXR1cm4gLUVSQU5HRTsKKworCWZtdCA9ICZmb3JtYXRz W2YtPmluZGV4XTsKKworCXN0cmxjcHkoZi0+ZGVzY3JpcHRpb24sIGZtdC0+bmFtZSwgc2l6ZW9m KGYtPmRlc2NyaXB0aW9uKSk7CisJZi0+cGl4ZWxmb3JtYXQgPSBmbXQtPmZvdXJjYzsKKworCXJl dHVybiAwOworfQorCitzdGF0aWMgaW50IG1zbV93Yl92aWRpb2NfZ19mbXRfdmlkX2NhcChzdHJ1 Y3QgZmlsZSAqZmlsZSwgdm9pZCAqcHJpdiwKKwkJCQkJc3RydWN0IHY0bDJfZm9ybWF0ICpmKQor eworCXN0cnVjdCBtc21fd2JfdjRsMl9kZXYgKmRldiA9IHZpZGVvX2RydmRhdGEoZmlsZSk7CisJ aW50IGk7CisKKwlmLT50eXBlID0gVjRMMl9CVUZfVFlQRV9WSURFT19DQVBUVVJFX01QTEFORTsK KwlmLT5mbXQucGl4X21wLndpZHRoICAgICAgICA9IGRldi0+d2lkdGg7CisJZi0+Zm10LnBpeF9t cC5oZWlnaHQgICAgICAgPSBkZXYtPmhlaWdodDsKKwlmLT5mbXQucGl4X21wLmZpZWxkICAgICAg ICA9IFY0TDJfRklFTERfTk9ORTsKKwlmLT5mbXQucGl4X21wLnBpeGVsZm9ybWF0ICA9IGRldi0+ Zm10LT5mb3VyY2M7CisJZi0+Zm10LnBpeF9tcC5udW1fcGxhbmVzID0gZGV2LT5mbXQtPnBsYW5l X2NudDsKKworCWZvciAoaSA9IDA7IGkgPCBkZXYtPmZtdC0+cGxhbmVfY250OyBpKyspIHsKKwkJ Zi0+Zm10LnBpeF9tcC5wbGFuZV9mbXRbaV0uYnl0ZXNwZXJsaW5lID0KKwkJCShkZXYtPmZtdC0+ cGxhbmVfYnBwW2ldICogZGV2LT53aWR0aCkgPj4gMzsKKwkJZi0+Zm10LnBpeF9tcC5wbGFuZV9m bXRbaV0uc2l6ZWltYWdlID0KKwkJCWYtPmZtdC5waXhfbXAucGxhbmVfZm10W2ldLmJ5dGVzcGVy bGluZSAqIGRldi0+aGVpZ2h0OworCX0KKworCWlmIChkZXYtPmZtdC0+aXNfeXV2KQorCQlmLT5m bXQucGl4X21wLmNvbG9yc3BhY2UgPSBWNEwyX0NPTE9SU1BBQ0VfU01QVEUxNzBNOworCWVsc2UK KwkJZi0+Zm10LnBpeF9tcC5jb2xvcnNwYWNlID0gVjRMMl9DT0xPUlNQQUNFX1NSR0I7CisKKwly ZXR1cm4gMDsKK30KKworc3RhdGljIGludCBtc21fd2JfdmlkaW9jX3RyeV9mbXRfdmlkX2NhcChz dHJ1Y3QgZmlsZSAqZmlsZSwgdm9pZCAqcHJpdiwKKwkJCXN0cnVjdCB2NGwyX2Zvcm1hdCAqZikK K3sKKwlzdHJ1Y3QgbXNtX3diX3Y0bDJfZGV2ICpkZXYgPSB2aWRlb19kcnZkYXRhKGZpbGUpOwor CWNvbnN0IHN0cnVjdCBtc21fd2JfZm10ICpmbXQ7CisJaW50IGk7CisKKwlpZiAoZi0+dHlwZSAh PSBWNEwyX0JVRl9UWVBFX1ZJREVPX0NBUFRVUkVfTVBMQU5FKSB7CisJCXY0bDJfZXJyKCZkZXYt PnY0bDJfZGV2LCAiSW52YWxpZCBidWYgdHlwZSAlZC5cbiIsCisJCQlmLT50eXBlKTsKKwkJcmV0 dXJuIC1FSU5WQUw7CisJfQorCisJZm10ID0gZ2V0X2Zvcm1hdChmLT5mbXQucGl4X21wLnBpeGVs Zm9ybWF0KTsKKwlpZiAoIWZtdCkgeworCQl2NGwyX2VycigmZGV2LT52NGwyX2RldiwgIkZvdXJj YyBmb3JtYXQgKDB4JTA4eCkgdW5rbm93bi5cbiIsCisJCQlmLT5mbXQucGl4X21wLnBpeGVsZm9y bWF0KTsKKwkJcmV0dXJuIC1FTk9UU1VQUDsKKwl9CisKKwlmLT5mbXQucGl4X21wLmZpZWxkID0g VjRMMl9GSUVMRF9OT05FOworCXY0bF9ib3VuZF9hbGlnbl9pbWFnZSgmZi0+Zm10LnBpeF9tcC53 aWR0aCwgNDgsIE1BWF9XSURUSCwgNCwKKwkJCSAgICAgICZmLT5mbXQucGl4X21wLmhlaWdodCwg MzIsIE1BWF9IRUlHSFQsIDQsIDApOworCWYtPmZtdC5waXhfbXAubnVtX3BsYW5lcyA9IGZtdC0+ cGxhbmVfY250OworCisJZm9yIChpID0gMDsgaSA8IGRldi0+Zm10LT5wbGFuZV9jbnQ7IGkrKykg eworCQlmLT5mbXQucGl4X21wLnBsYW5lX2ZtdFtpXS5ieXRlc3BlcmxpbmUgPQorCQkJKGRldi0+ Zm10LT5wbGFuZV9icHBbaV0gKiBmLT5mbXQucGl4X21wLndpZHRoKSA+PiAzOworCQlmLT5mbXQu cGl4X21wLnBsYW5lX2ZtdFtpXS5zaXplaW1hZ2UgPQorCQkJZi0+Zm10LnBpeF9tcC5wbGFuZV9m bXRbaV0uYnl0ZXNwZXJsaW5lICoKKwkJCWYtPmZtdC5waXhfbXAuaGVpZ2h0OworCX0KKworCWlm IChmbXQtPmlzX3l1dikKKwkJZi0+Zm10LnBpeF9tcC5jb2xvcnNwYWNlID0gVjRMMl9DT0xPUlNQ QUNFX1NNUFRFMTcwTTsKKwllbHNlCisJCWYtPmZtdC5waXhfbXAuY29sb3JzcGFjZSA9IFY0TDJf Q09MT1JTUEFDRV9TUkdCOworCisJcmV0dXJuIDA7Cit9CisKK3N0YXRpYyBpbnQgbXNtX3diX3Zp ZGlvY19zX2ZtdF92aWRfY2FwKHN0cnVjdCBmaWxlICpmaWxlLCB2b2lkICpwcml2LAorCQkJCQlz dHJ1Y3QgdjRsMl9mb3JtYXQgKmYpCit7CisJc3RydWN0IG1zbV93Yl92NGwyX2RldiAqZGV2ID0g dmlkZW9fZHJ2ZGF0YShmaWxlKTsKKwlzdHJ1Y3QgbXNtX3diICp3YiA9IGRldi0+d2I7CisJc3Ry dWN0IHZiMl9xdWV1ZSAqcSA9ICZkZXYtPnZiX3ZpZHE7CisJaW50IHJjOworCisJcmMgPSBtc21f d2JfdmlkaW9jX3RyeV9mbXRfdmlkX2NhcChmaWxlLCBwcml2LCBmKTsKKwlpZiAocmMgPCAwKQor CQlyZXR1cm4gcmM7CisKKwlpZiAodmIyX2lzX2J1c3kocSkpIHsKKwkJdjRsMl9lcnIoJmRldi0+ djRsMl9kZXYsICIlcyBkZXZpY2UgYnVzeVxuIiwgX19mdW5jX18pOworCQlyZXR1cm4gLUVCVVNZ OworCX0KKworCWRldi0+Zm10ID0gZ2V0X2Zvcm1hdChmLT5mbXQucGl4X21wLnBpeGVsZm9ybWF0 KTsKKwlkZXYtPndpZHRoID0gZi0+Zm10LnBpeF9tcC53aWR0aDsKKwlkZXYtPmhlaWdodCA9IGYt PmZtdC5waXhfbXAuaGVpZ2h0OworCisJcmMgPSBtc21fd2Jfc2V0X2J1Zl9mb3JtYXQod2IsIGRl di0+Zm10LT5kcm1fZm91cmNjLAorCQlkZXYtPndpZHRoLCBkZXYtPmhlaWdodCk7CisJaWYgKHJj KQorCQl2NGwyX2VycigmZGV2LT52NGwyX2RldiwKKwkJCSJTZXQgZm9ybWF0ICgweCUwOHggdzol eCBoOiV4KSBmYWlsZWQuXG4iLAorCQkJZGV2LT5mbXQtPmRybV9mb3VyY2MsIGRldi0+d2lkdGgs IGRldi0+aGVpZ2h0KTsKKworCXJldHVybiByYzsKK30KKworc3RhdGljIGNvbnN0IHN0cnVjdCB2 NGwyX2ZpbGVfb3BlcmF0aW9ucyBtc21fd2JfdjRsMl9mb3BzID0geworCS5vd25lciA9IFRISVNf TU9EVUxFLAorCS5vcGVuID0gdjRsMl9maF9vcGVuLAorCS5yZWxlYXNlID0gdmIyX2ZvcF9yZWxl YXNlLAorCS5wb2xsID0gdmIyX2ZvcF9wb2xsLAorCS51bmxvY2tlZF9pb2N0bCA9IHZpZGVvX2lv Y3RsMiwKK307CisKK3N0YXRpYyBjb25zdCBzdHJ1Y3QgdjRsMl9pb2N0bF9vcHMgbXNtX3diX3Y0 bDJfaW9jdGxfb3BzID0geworCS52aWRpb2NfcXVlcnljYXAgICAgICA9IG1zbV93Yl92aWRpb2Nf cXVlcnljYXAsCisJLnZpZGlvY19lbnVtX2ZtdF92aWRfY2FwX21wbGFuZSA9IG1zbV93Yl92aWRp b2NfZW51bV9mbXRfdmlkX2NhcCwKKwkudmlkaW9jX2dfZm10X3ZpZF9jYXBfbXBsYW5lID0gbXNt X3diX3ZpZGlvY19nX2ZtdF92aWRfY2FwLAorCS52aWRpb2NfdHJ5X2ZtdF92aWRfY2FwX21wbGFu ZSA9IG1zbV93Yl92aWRpb2NfdHJ5X2ZtdF92aWRfY2FwLAorCS52aWRpb2Nfc19mbXRfdmlkX2Nh cF9tcGxhbmUgPSBtc21fd2JfdmlkaW9jX3NfZm10X3ZpZF9jYXAsCisJLnZpZGlvY19yZXFidWZz ICAgICAgID0gdmIyX2lvY3RsX3JlcWJ1ZnMsCisJLnZpZGlvY19xdWVyeWJ1ZiAgICAgID0gdmIy X2lvY3RsX3F1ZXJ5YnVmLAorCS52aWRpb2NfcWJ1ZiAgICAgICAgICA9IHZiMl9pb2N0bF9xYnVm LAorCS52aWRpb2NfZHFidWYgICAgICAgICA9IHZiMl9pb2N0bF9kcWJ1ZiwKKwkudmlkaW9jX3N0 cmVhbW9uICAgICAgPSB2YjJfaW9jdGxfc3RyZWFtb24sCisJLnZpZGlvY19zdHJlYW1vZmYgICAg ID0gdmIyX2lvY3RsX3N0cmVhbW9mZiwKKwkudmlkaW9jX2xvZ19zdGF0dXMgICAgPSB2NGwyX2N0 cmxfbG9nX3N0YXR1cywKKwkudmlkaW9jX3N1YnNjcmliZV9ldmVudCA9IHY0bDJfY3RybF9zdWJz Y3JpYmVfZXZlbnQsCisJLnZpZGlvY191bnN1YnNjcmliZV9ldmVudCA9IHY0bDJfZXZlbnRfdW5z dWJzY3JpYmUsCit9OworCitzdGF0aWMgY29uc3Qgc3RydWN0IHZpZGVvX2RldmljZSBtc21fd2Jf djRsMl90ZW1wbGF0ZSA9IHsKKwkubmFtZSA9ICJtc21fd2IiLAorCS5mb3BzID0gJm1zbV93Yl92 NGwyX2ZvcHMsCisJLmlvY3RsX29wcyA9ICZtc21fd2JfdjRsMl9pb2N0bF9vcHMsCisJLnJlbGVh c2UgPSB2aWRlb19kZXZpY2VfcmVsZWFzZV9lbXB0eSwKK307CisKK2ludCBtc21fd2JfdjRsMl9p bml0KHN0cnVjdCBtc21fd2IgKndiKQoreworCXN0cnVjdCBtc21fd2JfdjRsMl9kZXYgKmRldjsK KwlzdHJ1Y3QgdmlkZW9fZGV2aWNlICp2ZmQ7CisJc3RydWN0IHZiMl9xdWV1ZSAqcTsKKwlpbnQg cmV0OworCisJZGV2ID0ga3phbGxvYyhzaXplb2YoKmRldiksIEdGUF9LRVJORUwpOworCWlmICgh ZGV2KQorCQlyZXR1cm4gLUVOT01FTTsKKworCXNucHJpbnRmKGRldi0+djRsMl9kZXYubmFtZSwg c2l6ZW9mKGRldi0+djRsMl9kZXYubmFtZSksCisJCQkiJXMiLCBNU01fV0JfTU9EVUxFX05BTUUp OworCXJldCA9IHY0bDJfZGV2aWNlX3JlZ2lzdGVyKE5VTEwsICZkZXYtPnY0bDJfZGV2KTsKKwlp ZiAocmV0KQorCQlnb3RvIGZyZWVfZGV2OworCisJLyogZGVmYXVsdCBBUkdCODg4OCA2NDB4NDgw ICovCisJZGV2LT5mbXQgPSBnZXRfZm9ybWF0KFY0TDJfUElYX0ZNVF9SR0IzMik7CisJZGV2LT53 aWR0aCA9IDY0MDsKKwlkZXYtPmhlaWdodCA9IDQ4MDsKKworCS8qIGluaXRpYWxpemUgcXVldWUg Ki8KKwlxID0gJmRldi0+dmJfdmlkcTsKKwlxLT50eXBlID0gVjRMMl9CVUZfVFlQRV9WSURFT19D QVBUVVJFX01QTEFORTsKKwlxLT5pb19tb2RlcyA9IFZCMl9ETUFCVUY7CisJcS0+ZHJ2X3ByaXYg PSBkZXY7CisJcS0+YnVmX3N0cnVjdF9zaXplID0gc2l6ZW9mKHN0cnVjdCBtc21fd2JfdjRsMl9i dWZmZXIpOworCXEtPm9wcyA9ICZtc21fd2JfdmIyX29wczsKKwlxLT5tZW1fb3BzID0gJm1zbV93 Yl92YjJfbWVtX29wczsKKwlxLT50aW1lc3RhbXBfdHlwZSA9IFY0TDJfQlVGX0ZMQUdfVElNRVNU QU1QX01PTk9UT05JQzsKKworCXJldCA9IHZiMl9xdWV1ZV9pbml0KHEpOworCWlmIChyZXQpCisJ CWdvdG8gdW5yZWdfZGV2OworCisJbXV0ZXhfaW5pdCgmZGV2LT5tdXRleCk7CisKKwl2ZmQgPSAm ZGV2LT52ZGV2OworCSp2ZmQgPSBtc21fd2JfdjRsMl90ZW1wbGF0ZTsKKwl2ZmQtPmRlYnVnID0g ZGVidWc7CisJdmZkLT52NGwyX2RldiA9ICZkZXYtPnY0bDJfZGV2OworCXZmZC0+cXVldWUgPSBx OworCisJLyoKKwkgKiBQcm92aWRlIGEgbXV0ZXggdG8gdjRsMiBjb3JlLiBJdCB3aWxsIGJlIHVz ZWQgdG8gcHJvdGVjdAorCSAqIGFsbCBmb3BzIGFuZCB2NGwyIGlvY3Rscy4KKwkgKi8KKwl2ZmQt PmxvY2sgPSAmZGV2LT5tdXRleDsKKwl2aWRlb19zZXRfZHJ2ZGF0YSh2ZmQsIGRldik7CisKKwly ZXQgPSB2aWRlb19yZWdpc3Rlcl9kZXZpY2UodmZkLCBWRkxfVFlQRV9HUkFCQkVSLCAtMSk7CisJ aWYgKHJldCA8IDApCisJCWdvdG8gdW5yZWdfZGV2OworCisJZGV2LT53YiA9IHdiOworCXdiLT53 Yl92NGwyID0gZGV2OworCXY0bDJfaW5mbygmZGV2LT52NGwyX2RldiwgIlY0TDIgZGV2aWNlIHJl Z2lzdGVyZWQgYXMgJXNcbiIsCisJCSAgdmlkZW9fZGV2aWNlX25vZGVfbmFtZSh2ZmQpKTsKKwor CXJldHVybiAwOworCit1bnJlZ19kZXY6CisJdjRsMl9kZXZpY2VfdW5yZWdpc3RlcigmZGV2LT52 NGwyX2Rldik7CitmcmVlX2RldjoKKwlrZnJlZShkZXYpOworCXJldHVybiByZXQ7Cit9CmRpZmYg LS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vbXNtL21zbV9kcnYuYyBiL2RyaXZlcnMvZ3B1L2RybS9t c20vbXNtX2Rydi5jCmluZGV4IGE3MmVkMGEuLjYxZTc2ZDAgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMv Z3B1L2RybS9tc20vbXNtX2Rydi5jCisrKyBiL2RyaXZlcnMvZ3B1L2RybS9tc20vbXNtX2Rydi5j CkBAIC0xMDMyLDYgKzEwMzIsNyBAQCBzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBtc21f cGxhdGZvcm1fZHJpdmVyID0gewogc3RhdGljIGludCBfX2luaXQgbXNtX2RybV9yZWdpc3Rlcih2 b2lkKQogewogCURCRygiaW5pdCIpOworCW1zbV93Yl9yZWdpc3RlcigpOwogCW1zbV9lZHBfcmVn aXN0ZXIoKTsKIAloZG1pX3JlZ2lzdGVyKCk7CiAJYWRyZW5vX3JlZ2lzdGVyKCk7CkBAIC0xMDQ1 LDYgKzEwNDYsNyBAQCBzdGF0aWMgdm9pZCBfX2V4aXQgbXNtX2RybV91bnJlZ2lzdGVyKHZvaWQp CiAJaGRtaV91bnJlZ2lzdGVyKCk7CiAJYWRyZW5vX3VucmVnaXN0ZXIoKTsKIAltc21fZWRwX3Vu cmVnaXN0ZXIoKTsKKwltc21fd2JfdW5yZWdpc3RlcigpOwogfQogCiBtb2R1bGVfaW5pdChtc21f ZHJtX3JlZ2lzdGVyKTsKZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9tc20vbXNtX2Rydi5o IGIvZHJpdmVycy9ncHUvZHJtL21zbS9tc21fZHJ2LmgKaW5kZXggOWU4ZDQ0MS4uY2ViNTUxYSAx MDA2NDQKLS0tIGEvZHJpdmVycy9ncHUvZHJtL21zbS9tc21fZHJ2LmgKKysrIGIvZHJpdmVycy9n cHUvZHJtL21zbS9tc21fZHJ2LmgKQEAgLTUzLDYgKzUzLDkgQEAgc3RydWN0IG1zbV9tbXU7CiBz dHJ1Y3QgbXNtX3JkX3N0YXRlOwogc3RydWN0IG1zbV9wZXJmX3N0YXRlOwogc3RydWN0IG1zbV9n ZW1fc3VibWl0Oworc3RydWN0IGhkbWk7CitzdHJ1Y3QgbXNtX2VkcDsKK3N0cnVjdCBtc21fd2I7 CiAKICNkZWZpbmUgTlVNX0RPTUFJTlMgMiAgICAvKiBvbmUgZm9yIEtNUywgdGhlbiBvbmUgcGVy IGdwdSBjb3JlICg/KSAqLwogCkBAIC04Miw2ICs4NSw4IEBAIHN0cnVjdCBtc21fZHJtX3ByaXZh dGUgewogCSAqLwogCXN0cnVjdCBtc21fZWRwICplZHA7CiAKKwlzdHJ1Y3QgbXNtX3diICp3YjsK KwogCS8qIHdoZW4gd2UgaGF2ZSBtb3JlIHRoYW4gb25lICdtc21fZ3B1JyB0aGVzZSBuZWVkIHRv IGJlIGFuIGFycmF5OiAqLwogCXN0cnVjdCBtc21fZ3B1ICpncHU7CiAJc3RydWN0IG1zbV9maWxl X3ByaXZhdGUgKmxhc3RjdHg7CkBAIC0yMjQsMTggKzIyOSwyOCBAQCBzdHJ1Y3QgZHJtX2ZyYW1l YnVmZmVyICptc21fZnJhbWVidWZmZXJfY3JlYXRlKHN0cnVjdCBkcm1fZGV2aWNlICpkZXYsCiAK IHN0cnVjdCBkcm1fZmJfaGVscGVyICptc21fZmJkZXZfaW5pdChzdHJ1Y3QgZHJtX2RldmljZSAq ZGV2KTsKIAotc3RydWN0IGhkbWk7CiBpbnQgaGRtaV9tb2Rlc2V0X2luaXQoc3RydWN0IGhkbWkg KmhkbWksIHN0cnVjdCBkcm1fZGV2aWNlICpkZXYsCiAJCXN0cnVjdCBkcm1fZW5jb2RlciAqZW5j b2Rlcik7CiB2b2lkIF9faW5pdCBoZG1pX3JlZ2lzdGVyKHZvaWQpOwogdm9pZCBfX2V4aXQgaGRt aV91bnJlZ2lzdGVyKHZvaWQpOwogCi1zdHJ1Y3QgbXNtX2VkcDsKIHZvaWQgX19pbml0IG1zbV9l ZHBfcmVnaXN0ZXIodm9pZCk7CiB2b2lkIF9fZXhpdCBtc21fZWRwX3VucmVnaXN0ZXIodm9pZCk7 CiBpbnQgbXNtX2VkcF9tb2Rlc2V0X2luaXQoc3RydWN0IG1zbV9lZHAgKmVkcCwgc3RydWN0IGRy bV9kZXZpY2UgKmRldiwKIAkJc3RydWN0IGRybV9lbmNvZGVyICplbmNvZGVyKTsKIAorI2lmZGVm IENPTkZJR19EUk1fTVNNX1dCCit2b2lkIF9faW5pdCBtc21fd2JfcmVnaXN0ZXIodm9pZCk7Cit2 b2lkIF9fZXhpdCBtc21fd2JfdW5yZWdpc3Rlcih2b2lkKTsKK2ludCBtc21fd2JfbW9kZXNldF9p bml0KHN0cnVjdCBtc21fd2IgKndiLCBzdHJ1Y3QgZHJtX2RldmljZSAqZGV2LAorCQlzdHJ1Y3Qg ZHJtX2VuY29kZXIgKmVuY29kZXIpOworI2Vsc2UKK3N0YXRpYyBpbmxpbmUgdm9pZCBfX2luaXQg bXNtX3diX3JlZ2lzdGVyKHZvaWQpIHt9CitzdGF0aWMgaW5saW5lIHZvaWQgX19leGl0IG1zbV93 Yl91bnJlZ2lzdGVyKHZvaWQpIHt9CitzdGF0aWMgaW5saW5lIGludCBtc21fd2JfbW9kZXNldF9p bml0KHN0cnVjdCBtc21fd2IgKndiLCBzdHJ1Y3QgZHJtX2RldmljZSAqZGV2LAorCQlzdHJ1Y3Qg ZHJtX2VuY29kZXIgKmVuY29kZXIpIHsgcmV0dXJuIC1FSU5WQUw7IH0KKyNlbmRpZgorCiAjaWZk ZWYgQ09ORklHX0RFQlVHX0ZTCiB2b2lkIG1zbV9nZW1fZGVzY3JpYmUoc3RydWN0IGRybV9nZW1f b2JqZWN0ICpvYmosIHN0cnVjdCBzZXFfZmlsZSAqbSk7CiB2b2lkIG1zbV9nZW1fZGVzY3JpYmVf b2JqZWN0cyhzdHJ1Y3QgbGlzdF9oZWFkICpsaXN0LCBzdHJ1Y3Qgc2VxX2ZpbGUgKm0pOwpkaWZm IC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL21zbS9tc21fZmJkZXYuYyBiL2RyaXZlcnMvZ3B1L2Ry bS9tc20vbXNtX2ZiZGV2LmMKaW5kZXggZGY2MGY2NS4uOWQ1NTNmMiAxMDA2NDQKLS0tIGEvZHJp dmVycy9ncHUvZHJtL21zbS9tc21fZmJkZXYuYworKysgYi9kcml2ZXJzL2dwdS9kcm0vbXNtL21z bV9mYmRldi5jCkBAIC0yMTIsNiArMjEyLDM4IEBAIHN0YXRpYyB2b2lkIG1zbV9jcnRjX2ZiX2dh bW1hX2dldChzdHJ1Y3QgZHJtX2NydGMgKmNydGMsCiAJREJHKCJmYmRldjogZ2V0IGdhbW1hIik7 CiB9CiAKKy8qIGFkZCBhbGwgY29ubmVjdG9ycyB0byBmYiBleGNlcHQgd2IgY29ubmVjdG9yICov CitzdGF0aWMgaW50IG1zbV9kcm1fZmJfYWRkX2Nvbm5lY3RvcnMoc3RydWN0IGRybV9mYl9oZWxw ZXIgKmZiX2hlbHBlcikKK3sKKwlzdHJ1Y3QgZHJtX2RldmljZSAqZGV2ID0gZmJfaGVscGVyLT5k ZXY7CisJc3RydWN0IGRybV9jb25uZWN0b3IgKmNvbm5lY3RvcjsKKwlpbnQgaTsKKworCWxpc3Rf Zm9yX2VhY2hfZW50cnkoY29ubmVjdG9yLCAmZGV2LT5tb2RlX2NvbmZpZy5jb25uZWN0b3JfbGlz dCwgaGVhZCkgeworCQlzdHJ1Y3QgZHJtX2ZiX2hlbHBlcl9jb25uZWN0b3IgKmZiX2hlbHBlcl9j b25uZWN0b3I7CisKKwkJaWYgKGNvbm5lY3Rvci0+Y29ubmVjdG9yX3R5cGUgPT0gRFJNX01PREVf Q09OTkVDVE9SX1ZJUlRVQUwpCisJCQljb250aW51ZTsKKworCQlmYl9oZWxwZXJfY29ubmVjdG9y ID0KKwkJCWt6YWxsb2Moc2l6ZW9mKCpmYl9oZWxwZXJfY29ubmVjdG9yKSwgR0ZQX0tFUk5FTCk7 CisJCWlmICghZmJfaGVscGVyX2Nvbm5lY3RvcikKKwkJCWdvdG8gZmFpbDsKKworCQlmYl9oZWxw ZXJfY29ubmVjdG9yLT5jb25uZWN0b3IgPSBjb25uZWN0b3I7CisJCWZiX2hlbHBlci0+Y29ubmVj dG9yX2luZm9bZmJfaGVscGVyLT5jb25uZWN0b3JfY291bnQrK10gPQorCQkJZmJfaGVscGVyX2Nv bm5lY3RvcjsKKwl9CisJcmV0dXJuIDA7CitmYWlsOgorCWZvciAoaSA9IDA7IGkgPCBmYl9oZWxw ZXItPmNvbm5lY3Rvcl9jb3VudDsgaSsrKSB7CisJCWtmcmVlKGZiX2hlbHBlci0+Y29ubmVjdG9y X2luZm9baV0pOworCQlmYl9oZWxwZXItPmNvbm5lY3Rvcl9pbmZvW2ldID0gTlVMTDsKKwl9CisJ ZmJfaGVscGVyLT5jb25uZWN0b3JfY291bnQgPSAwOworCXJldHVybiAtRU5PTUVNOworfQorCiBz dGF0aWMgY29uc3Qgc3RydWN0IGRybV9mYl9oZWxwZXJfZnVuY3MgbXNtX2ZiX2hlbHBlcl9mdW5j cyA9IHsKIAkuZ2FtbWFfc2V0ID0gbXNtX2NydGNfZmJfZ2FtbWFfc2V0LAogCS5nYW1tYV9nZXQg PSBtc21fY3J0Y19mYl9nYW1tYV9nZXQsCkBAIC0yNDEsNyArMjczLDcgQEAgc3RydWN0IGRybV9m Yl9oZWxwZXIgKm1zbV9mYmRldl9pbml0KHN0cnVjdCBkcm1fZGV2aWNlICpkZXYpCiAJCWdvdG8g ZmFpbDsKIAl9CiAKLQlyZXQgPSBkcm1fZmJfaGVscGVyX3NpbmdsZV9hZGRfYWxsX2Nvbm5lY3Rv cnMoaGVscGVyKTsKKwlyZXQgPSBtc21fZHJtX2ZiX2FkZF9jb25uZWN0b3JzKGhlbHBlcik7CiAJ aWYgKHJldCkKIAkJZ290byBmaW5pOwogCmRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vbXNt L21zbV9nZW0uYyBiL2RyaXZlcnMvZ3B1L2RybS9tc20vbXNtX2dlbS5jCmluZGV4IDQ5ZGVhNGYu LjExYTE5MjQgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMvZ3B1L2RybS9tc20vbXNtX2dlbS5jCisrKyBi L2RyaXZlcnMvZ3B1L2RybS9tc20vbXNtX2dlbS5jCkBAIC01MzQsNiArNTM0LDcgQEAgdm9pZCBt c21fZ2VtX2ZyZWVfb2JqZWN0KHN0cnVjdCBkcm1fZ2VtX29iamVjdCAqb2JqKQogCQlpZiAobXNt X29iai0+cGFnZXMpCiAJCQlkcm1fZnJlZV9sYXJnZShtc21fb2JqLT5wYWdlcyk7CiAKKwkJZHJt X3ByaW1lX2dlbV9kZXN0cm95KG9iaiwgbXNtX29iai0+c2d0KTsKIAl9IGVsc2UgewogCQl2dW5t YXAobXNtX29iai0+dmFkZHIpOwogCQlwdXRfcGFnZXMob2JqKTsKLS0gClRoZSBRdWFsY29tbSBJ bm5vdmF0aW9uIENlbnRlciwgSW5jLiBpcyBhIG1lbWJlciBvZiB0aGUgQ29kZSBBdXJvcmEgRm9y dW0sCmEgTGludXggRm91bmRhdGlvbiBDb2xsYWJvcmF0aXZlIFByb2plY3QKCl9fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmRyaS1kZXZlbCBtYWlsaW5nIGxp c3QKZHJpLWRldmVsQGxpc3RzLmZyZWVkZXNrdG9wLm9yZwpodHRwOi8vbGlzdHMuZnJlZWRlc2t0 b3Aub3JnL21haWxtYW4vbGlzdGluZm8vZHJpLWRldmVsCg== From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752819AbbDAVNE (ORCPT ); Wed, 1 Apr 2015 17:13:04 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:55556 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752276AbbDAVNA (ORCPT ); Wed, 1 Apr 2015 17:13:00 -0400 From: Jilai Wang To: dri-devel@lists.freedesktop.org Cc: linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, robdclark@gmail.com, Jilai Wang Subject: [PATCH 2/3] drm:msm: Initial Add Writeback Support Date: Wed, 1 Apr 2015 17:12:50 -0400 Message-Id: <1427922770-13721-1-git-send-email-jilaiw@codeaurora.org> X-Mailer: git-send-email 1.8.2.1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add writeback support in msm kms framework. Signed-off-by: Jilai Wang --- drivers/gpu/drm/msm/Kconfig | 10 + drivers/gpu/drm/msm/Makefile | 9 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c | 10 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 1 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 19 +- drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h | 7 + drivers/gpu/drm/msm/mdp/mdp5/mdp5_wb_encoder.c | 460 +++++++++++++++++++ drivers/gpu/drm/msm/mdp/mdp_kms.h | 2 +- drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.c | 319 +++++++++++++ drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.h | 98 ++++ drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_connector.c | 157 +++++++ drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_v4l2.c | 522 ++++++++++++++++++++++ drivers/gpu/drm/msm/msm_drv.c | 2 + drivers/gpu/drm/msm/msm_drv.h | 19 +- drivers/gpu/drm/msm/msm_fbdev.c | 34 +- drivers/gpu/drm/msm/msm_gem.c | 1 + 16 files changed, 1664 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/msm/mdp/mdp5/mdp5_wb_encoder.c create mode 100644 drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.c create mode 100644 drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.h create mode 100644 drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_connector.c create mode 100644 drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_v4l2.c diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 1e6a907..f6c7914 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -27,6 +27,16 @@ config DRM_MSM_FBDEV support. Note that this support also provide the linux console support on top of the MSM modesetting driver. +config DRM_MSM_WB + bool "Enable writeback support for MSM modesetting driver" + depends on DRM_MSM + depends on VIDEO_V4L2 + select VIDEOBUF2_CORE + default y + help + Choose this option if you have a need to support writeback + connector. + config DRM_MSM_REGISTER_LOGGING bool "MSM DRM register logging" depends on DRM_MSM diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 674a132..e5bf334 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -1,4 +1,5 @@ -ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/msm +ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/msm -Idrivers/gpu/drm/msm/mdp_wb +ccflags-$(CONFIG_DRM_MSM_WB) += -Idrivers/gpu/drm/msm/mdp/mdp_wb msm-y := \ adreno/adreno_device.o \ @@ -51,4 +52,10 @@ msm-y := \ msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o +msm-$(CONFIG_DRM_MSM_WB) += \ + mdp/mdp5/mdp5_wb_encoder.o \ + mdp/mdp_wb/mdp_wb.o \ + mdp/mdp_wb/mdp_wb_connector.o \ + mdp/mdp_wb/mdp_wb_v4l2.o + obj-$(CONFIG_DRM_MSM) += msm.o diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c index 1fe7315..e87cf74 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c @@ -71,9 +71,14 @@ const struct mdp5_cfg_hw msm8x74_config = { .count = 4, .base = { 0x12500, 0x12700, 0x12900, 0x12b00 }, }, + .wb = { + .count = 5, + .base = { 0x11100, 0x13100, 0x15100, 0x17100, 0x19100 }, + }, .intfs = { [0] = INTF_eDP, [3] = INTF_HDMI, + [4] = INTF_WB, }, .max_clk = 200000000, }; @@ -135,9 +140,14 @@ const struct mdp5_cfg_hw apq8084_config = { .count = 5, .base = { 0x12500, 0x12700, 0x12900, 0x12b00, 0x12d00 }, }, + .wb = { + .count = 5, + .base = { 0x11100, 0x11500, 0x11900, 0x11d00, 0x12100 }, + }, .intfs = { [0] = INTF_eDP, [3] = INTF_HDMI, + [4] = INTF_WB, }, .max_clk = 320000000, }; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h index f47328d..ccb6048c 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h @@ -74,6 +74,7 @@ struct mdp5_cfg_hw { struct mdp5_sub_block dspp; struct mdp5_sub_block ad; struct mdp5_sub_block intf; + struct mdp5_sub_block wb; u32 intfs[MDP5_INTF_NUM_MAX]; /* array of enum mdp5_intf_type */ diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index ff9201b..1b1569d 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -179,7 +179,11 @@ static struct drm_encoder *construct_encoder(struct mdp5_kms *mdp5_kms, .mode = intf_mode, }; - encoder = mdp5_encoder_init(dev, &intf); + if (intf_type == INTF_WB) + encoder = mdp5_wb_encoder_init(dev, &intf); + else + encoder = mdp5_encoder_init(dev, &intf); + if (IS_ERR(encoder)) { dev_err(dev->dev, "failed to construct encoder\n"); return encoder; @@ -230,6 +234,19 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, int intf_num) ret = hdmi_modeset_init(priv->hdmi, dev, encoder); break; + case INTF_WB: + if (!priv->wb) + break; + + encoder = construct_encoder(mdp5_kms, INTF_WB, intf_num, + MDP5_INTF_WB_MODE_LINE); + if (IS_ERR(encoder)) { + ret = PTR_ERR(encoder); + break; + } + + ret = msm_wb_modeset_init(priv->wb, dev, encoder); + break; default: dev_err(dev->dev, "unknown intf: %d\n", intf_type); ret = -EINVAL; diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h index 6efa5c6..f6d23cc 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h @@ -238,5 +238,12 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, struct drm_encoder *mdp5_encoder_init(struct drm_device *dev, struct mdp5_interface *intf); +#ifdef CONFIG_DRM_MSM_WB +struct drm_encoder *mdp5_wb_encoder_init(struct drm_device *dev, + struct mdp5_interface *intf); +#else +static inline struct drm_encoder *mdp5_wb_encoder_init(struct drm_device *dev, + struct mdp5_interface *intf) { return NULL; } +#endif #endif /* __MDP5_KMS_H__ */ diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_wb_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_wb_encoder.c new file mode 100644 index 0000000..8ce3449 --- /dev/null +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_wb_encoder.c @@ -0,0 +1,460 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "mdp5_kms.h" +#include "mdp_wb.h" + +#include "drm_crtc.h" +#include "drm_crtc_helper.h" + +struct mdp5_wb_encoder { + struct drm_encoder base; + struct mdp5_interface intf; + bool enabled; + uint32_t bsc; + struct mdp5_ctl *ctl; + + /* irq handler for wb encoder */ + struct mdp_irq wb_vblank; + /* wb id same as ctl id */ + u32 wb_id; +}; +#define to_mdp5_wb_encoder(x) container_of(x, struct mdp5_wb_encoder, base) + +static struct mdp5_kms *get_kms(struct drm_encoder *encoder) +{ + struct msm_drm_private *priv = encoder->dev->dev_private; + return to_mdp5_kms(to_mdp_kms(priv->kms)); +} + +static struct msm_wb *get_wb(struct drm_encoder *encoder) +{ + struct msm_drm_private *priv = encoder->dev->dev_private; + return priv->wb; +} + +#ifdef CONFIG_MSM_BUS_SCALING +#include +#include +#include +#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val) \ + { \ + .src = MSM_BUS_MASTER_MDP_PORT0, \ + .dst = MSM_BUS_SLAVE_EBI_CH0, \ + .ab = (ab_val), \ + .ib = (ib_val), \ + } + +static struct msm_bus_vectors mdp_bus_vectors[] = { + MDP_BUS_VECTOR_ENTRY(0, 0), + MDP_BUS_VECTOR_ENTRY(2000000000, 2000000000), +}; +static struct msm_bus_paths mdp_bus_usecases[] = { { + .num_paths = 1, + .vectors = &mdp_bus_vectors[0], +}, { + .num_paths = 1, + .vectors = &mdp_bus_vectors[1], +} }; +static struct msm_bus_scale_pdata mdp_bus_scale_table = { + .usecase = mdp_bus_usecases, + .num_usecases = ARRAY_SIZE(mdp_bus_usecases), + .name = "mdss_mdp", +}; + +static void bs_init(struct mdp5_wb_encoder *mdp5_wb_encoder) +{ + mdp5_wb_encoder->bsc = msm_bus_scale_register_client( + &mdp_bus_scale_table); + DBG("bus scale client: %08x", mdp5_wb_encoder->bsc); +} + +static void bs_fini(struct mdp5_wb_encoder *mdp5_wb_encoder) +{ + if (mdp5_wb_encoder->bsc) { + msm_bus_scale_unregister_client(mdp5_wb_encoder->bsc); + mdp5_wb_encoder->bsc = 0; + } +} + +static void bs_set(struct mdp5_wb_encoder *mdp5_wb_encoder, int idx) +{ + if (mdp5_wb_encoder->bsc) { + DBG("set bus scaling: %d", idx); + /* HACK: scaling down, and then immediately back up + * seems to leave things broken (underflow).. so + * never disable: + */ + idx = 1; + msm_bus_scale_client_update_request(mdp5_wb_encoder->bsc, idx); + } +} +#else +static void bs_init(struct mdp5_wb_encoder *mdp5_wb_encoder) {} +static void bs_fini(struct mdp5_wb_encoder *mdp5_wb_encoder) {} +static void bs_set(struct mdp5_wb_encoder *mdp5_wb_encoder, int idx) {} +#endif + +static void mdp5_wb_encoder_destroy(struct drm_encoder *encoder) +{ + struct mdp5_wb_encoder *mdp5_wb_encoder = to_mdp5_wb_encoder(encoder); + bs_fini(mdp5_wb_encoder); + drm_encoder_cleanup(encoder); + kfree(mdp5_wb_encoder); +} + +static const struct drm_encoder_funcs mdp5_wb_encoder_funcs = { + .destroy = mdp5_wb_encoder_destroy, +}; + +static bool mdp5_wb_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +void mdp5_wb_encoder_buf_prepare(struct msm_wb *wb, struct msm_wb_buffer *buf) +{ + struct drm_encoder *encoder = wb->encoder; + struct mdp5_kms *mdp5_kms = get_kms(encoder); + uint32_t nplanes = drm_format_num_planes(buf->pixel_format); + int i; + + DBG("plane no %d", nplanes); + mdp5_enable(mdp5_kms); + for (i = 0; i < nplanes; i++) { + DBG("buf %d: plane %x", i, (int)buf->planes[i]); + msm_gem_get_iova(buf->planes[i], mdp5_kms->id, &buf->iova[i]); + buf->iova[i] += buf->offsets[i]; + } + for (; i < MAX_PLANE; i++) + buf->iova[i] = 0; + mdp5_disable(mdp5_kms); +} + +static void mdp5_wb_encoder_addr_setup(struct drm_encoder *encoder, + struct msm_wb_buffer *buf) +{ + struct mdp5_wb_encoder *mdp5_wb_encoder = to_mdp5_wb_encoder(encoder); + struct mdp5_kms *mdp5_kms = get_kms(encoder); + u32 wb_id = mdp5_wb_encoder->wb_id; + + mdp5_write(mdp5_kms, REG_MDP5_WB_DST0_ADDR(wb_id), buf->iova[0]); + mdp5_write(mdp5_kms, REG_MDP5_WB_DST1_ADDR(wb_id), buf->iova[1]); + mdp5_write(mdp5_kms, REG_MDP5_WB_DST2_ADDR(wb_id), buf->iova[2]); + mdp5_write(mdp5_kms, REG_MDP5_WB_DST3_ADDR(wb_id), buf->iova[3]); + DBG("Program WB DST address %x %x %x %x", buf->iova[0], + buf->iova[1], buf->iova[2], buf->iova[3]); + /* Notify ctl that wb buffer is ready to trigger start */ + mdp5_ctl_commit(mdp5_wb_encoder->ctl, + mdp_ctl_flush_mask_encoder(&mdp5_wb_encoder->intf)); +} + +static void wb_csc_setup(struct mdp5_kms *mdp5_kms, u32 wb_id, + struct csc_cfg *csc) +{ + uint32_t i; + uint32_t *matrix; + + if (unlikely(!csc)) + return; + + matrix = csc->matrix; + mdp5_write(mdp5_kms, REG_MDP5_WB_CSC_MATRIX_COEFF_0(wb_id), + MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11(matrix[0]) | + MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12(matrix[1])); + mdp5_write(mdp5_kms, REG_MDP5_WB_CSC_MATRIX_COEFF_1(wb_id), + MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13(matrix[2]) | + MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21(matrix[3])); + mdp5_write(mdp5_kms, REG_MDP5_WB_CSC_MATRIX_COEFF_2(wb_id), + MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22(matrix[4]) | + MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23(matrix[5])); + mdp5_write(mdp5_kms, REG_MDP5_WB_CSC_MATRIX_COEFF_3(wb_id), + MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31(matrix[6]) | + MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32(matrix[7])); + mdp5_write(mdp5_kms, REG_MDP5_WB_CSC_MATRIX_COEFF_4(wb_id), + MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33(matrix[8])); + + for (i = 0; i < ARRAY_SIZE(csc->pre_bias); i++) { + uint32_t *pre_clamp = csc->pre_clamp; + uint32_t *post_clamp = csc->post_clamp; + + mdp5_write(mdp5_kms, REG_MDP5_WB_CSC_COMP_PRECLAMP(wb_id, i), + MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH(pre_clamp[2*i+1]) | + MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW(pre_clamp[2*i])); + + mdp5_write(mdp5_kms, REG_MDP5_WB_CSC_COMP_POSTCLAMP(wb_id, i), + MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH(post_clamp[2*i+1]) | + MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW(post_clamp[2*i])); + + mdp5_write(mdp5_kms, REG_MDP5_WB_CSC_COMP_PREBIAS(wb_id, i), + MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE(csc->pre_bias[i])); + + mdp5_write(mdp5_kms, REG_MDP5_WB_CSC_COMP_POSTBIAS(wb_id, i), + MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE(csc->post_bias[i])); + } +} + +static void mdp5_wb_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct mdp5_wb_encoder *mdp5_wb_encoder = to_mdp5_wb_encoder(encoder); + struct mdp5_kms *mdp5_kms = get_kms(encoder); + struct msm_kms *kms = &mdp5_kms->base.base; + const struct msm_format *msm_fmt; + const struct mdp_format *fmt; + struct msm_wb *wb = get_wb(encoder); + struct msm_wb_buf_format *wb_buf_fmt; + struct msm_wb_buffer *buf; + u32 wb_id; + u32 dst_format, pattern, ystride0, ystride1, outsize, chroma_samp; + u32 opmode = 0; + + DBG("Wb2 encoder modeset"); + + /* now we can get the ctl from crtc and extract the wb_id from ctl */ + if (!mdp5_wb_encoder->ctl) + mdp5_wb_encoder->ctl = mdp5_crtc_get_ctl(encoder->crtc); + + wb_id = mdp5_ctl_get_ctl_id(mdp5_wb_encoder->ctl); + mdp5_wb_encoder->wb_id = wb_id; + + /* get color_format from wb device */ + wb_buf_fmt = msm_wb_get_buf_format(wb); + msm_fmt = kms->funcs->get_format(kms, wb_buf_fmt->pixel_format); + if (!msm_fmt) { + pr_err("%s: Unsupported Color Format %d\n", __func__, + wb_buf_fmt->pixel_format); + return; + } + + fmt = to_mdp_format(msm_fmt); + chroma_samp = fmt->chroma_sample; + + if (MDP_FORMAT_IS_YUV(fmt)) { + /* config csc */ + DBG("YUV output %d, configure CSC", + fmt->base.pixel_format); + wb_csc_setup(mdp5_kms, mdp5_wb_encoder->wb_id, + mdp_get_default_csc_cfg(CSC_RGB2YUV)); + opmode |= MDP5_WB_DST_OP_MODE_CSC_EN | + MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT( + DATA_FORMAT_RGB) | + MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT( + DATA_FORMAT_YUV); + + switch (chroma_samp) { + case CHROMA_420: + case CHROMA_H2V1: + opmode |= MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_EN; + break; + case CHROMA_H1V2: + default: + pr_err("unsupported wb chroma samp=%d\n", chroma_samp); + return; + } + } + + dst_format = MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP(chroma_samp) | + MDP5_WB_DST_FORMAT_WRITE_PLANES(fmt->fetch_type) | + MDP5_WB_DST_FORMAT_DSTC3_OUT(fmt->bpc_a) | + MDP5_WB_DST_FORMAT_DSTC2_OUT(fmt->bpc_r) | + MDP5_WB_DST_FORMAT_DSTC1_OUT(fmt->bpc_b) | + MDP5_WB_DST_FORMAT_DSTC0_OUT(fmt->bpc_g) | + COND(fmt->unpack_tight, MDP5_WB_DST_FORMAT_PACK_TIGHT) | + MDP5_WB_DST_FORMAT_PACK_COUNT(fmt->unpack_count - 1) | + MDP5_WB_DST_FORMAT_DST_BPP(fmt->cpp - 1); + + if (fmt->bpc_a || fmt->alpha_enable) { + dst_format |= MDP5_WB_DST_FORMAT_DSTC3_EN; + if (!fmt->alpha_enable) + dst_format |= MDP5_WB_DST_FORMAT_DST_ALPHA_X; + } + + pattern = MDP5_WB_DST_PACK_PATTERN_ELEMENT3(fmt->unpack[3]) | + MDP5_WB_DST_PACK_PATTERN_ELEMENT2(fmt->unpack[2]) | + MDP5_WB_DST_PACK_PATTERN_ELEMENT1(fmt->unpack[1]) | + MDP5_WB_DST_PACK_PATTERN_ELEMENT0(fmt->unpack[0]); + + /* get the stride info from WB device */ + ystride0 = MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE(wb_buf_fmt->pitches[0]) | + MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE(wb_buf_fmt->pitches[1]); + ystride1 = MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE(wb_buf_fmt->pitches[2]) | + MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE(wb_buf_fmt->pitches[3]); + + /* get the output resolution from WB device */ + outsize = MDP5_WB_OUT_SIZE_DST_H(wb_buf_fmt->height) | + MDP5_WB_OUT_SIZE_DST_W(wb_buf_fmt->width); + + mdp5_write(mdp5_kms, REG_MDP5_WB_ALPHA_X_VALUE(wb_id), 0xFF); + mdp5_write(mdp5_kms, REG_MDP5_WB_DST_FORMAT(wb_id), dst_format); + mdp5_write(mdp5_kms, REG_MDP5_WB_DST_OP_MODE(wb_id), opmode); + mdp5_write(mdp5_kms, REG_MDP5_WB_DST_PACK_PATTERN(wb_id), pattern); + mdp5_write(mdp5_kms, REG_MDP5_WB_DST_YSTRIDE0(wb_id), ystride0); + mdp5_write(mdp5_kms, REG_MDP5_WB_DST_YSTRIDE1(wb_id), ystride1); + mdp5_write(mdp5_kms, REG_MDP5_WB_OUT_SIZE(wb_id), outsize); + + mdp5_crtc_set_intf(encoder->crtc, &mdp5_wb_encoder->intf); + + /* program the dst address */ + buf = msm_wb_dequeue_buf(wb, MSM_WB_BUF_Q_FREE); + /* + * if no free buffer is available, the only possibility is + * WB connector becomes offline. User app should be notified + * by udev event and stop the rendering soon. + * so don't do anything here. + */ + if (!buf) { + pr_warn("%s: No buffer available\n", __func__); + return; + } + + /* Last step of mode set: set up dst address */ + msm_wb_queue_buf(wb, buf, MSM_WB_BUF_Q_ACTIVE); + mdp5_wb_encoder_addr_setup(encoder, buf); +} + +static void mdp5_wb_encoder_disable(struct drm_encoder *encoder) +{ + struct mdp5_wb_encoder *mdp5_wb_encoder = to_mdp5_wb_encoder(encoder); + struct mdp5_kms *mdp5_kms = get_kms(encoder); + struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc); + struct msm_wb *wb = get_wb(encoder); + struct msm_wb_buffer *buf; + + DBG("Disable wb encoder"); + + if (WARN_ON(!mdp5_wb_encoder->enabled)) + return; + + mdp5_ctl_set_encoder_state(ctl, false); + + mdp_irq_unregister(&mdp5_kms->base, + &mdp5_wb_encoder->wb_vblank); + + /* move the active buf to free buf queue*/ + while ((buf = msm_wb_dequeue_buf(wb, MSM_WB_BUF_Q_ACTIVE)) + != NULL) + msm_wb_queue_buf(wb, buf, MSM_WB_BUF_Q_FREE); + + msm_wb_update_encoder_state(wb, false); + bs_set(mdp5_wb_encoder, 0); + + mdp5_wb_encoder->enabled = false; +} + +static void mdp5_wb_encoder_enable(struct drm_encoder *encoder) +{ + struct mdp5_wb_encoder *mdp5_wb_encoder = to_mdp5_wb_encoder(encoder); + struct mdp5_kms *mdp5_kms = get_kms(encoder); + struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc); + struct msm_wb *wb = get_wb(encoder); + + DBG("Enable wb encoder"); + + if (WARN_ON(mdp5_wb_encoder->enabled)) + return; + + bs_set(mdp5_wb_encoder, 1); + mdp_irq_register(&mdp5_kms->base, + &mdp5_wb_encoder->wb_vblank); + + + mdp5_ctl_set_encoder_state(ctl, true); + msm_wb_update_encoder_state(wb, true); + + mdp5_wb_encoder->enabled = true; +} + +static const struct drm_encoder_helper_funcs mdp5_wb_encoder_helper_funcs = { + .mode_fixup = mdp5_wb_encoder_mode_fixup, + .mode_set = mdp5_wb_encoder_mode_set, + .disable = mdp5_wb_encoder_disable, + .enable = mdp5_wb_encoder_enable, +}; + +static void mdp5_wb_encoder_vblank_irq(struct mdp_irq *irq, uint32_t irqstatus) +{ + struct mdp5_wb_encoder *mdp5_wb_encoder = + container_of(irq, struct mdp5_wb_encoder, wb_vblank); + struct mdp5_kms *mdp5_kms = get_kms(&mdp5_wb_encoder->base); + struct msm_wb *wb = get_wb(&mdp5_wb_encoder->base); + u32 wb_id = mdp5_wb_encoder->wb_id; + struct msm_wb_buffer *new_buf, *buf; + u32 reg_val; + + DBG("wb id %d", wb_id); + + reg_val = mdp5_read(mdp5_kms, REG_MDP5_WB_DST0_ADDR(wb_id)); + buf = msm_wb_dequeue_buf(wb, MSM_WB_BUF_Q_ACTIVE); + if (WARN_ON(!buf || (reg_val != buf->iova[0]))) { + if (!buf) + pr_err("%s: no active buffer\n", __func__); + else + pr_err("%s: current addr %x expect %x\n", + __func__, reg_val, buf->iova[0]); + return; + } + + /* retrieve the free buffer */ + new_buf = msm_wb_dequeue_buf(wb, MSM_WB_BUF_Q_FREE); + if (!new_buf) { + pr_info("%s: No buffer is available\n", __func__); + /* reuse current active buffer */ + new_buf = buf; + } else { + msm_wb_buf_captured(wb, buf, false); + } + + /* Update the address anyway to trigger the WB flush */ + msm_wb_queue_buf(wb, new_buf, MSM_WB_BUF_Q_ACTIVE); + mdp5_wb_encoder_addr_setup(&mdp5_wb_encoder->base, new_buf); +} + +/* initialize encoder */ +struct drm_encoder *mdp5_wb_encoder_init(struct drm_device *dev, + struct mdp5_interface *intf) +{ + struct drm_encoder *encoder = NULL; + struct mdp5_wb_encoder *mdp5_wb_encoder; + int ret; + + DBG("Init writeback encoder"); + + mdp5_wb_encoder = kzalloc(sizeof(*mdp5_wb_encoder), GFP_KERNEL); + if (!mdp5_wb_encoder) { + ret = -ENOMEM; + goto fail; + } + + memcpy(&mdp5_wb_encoder->intf, intf, sizeof(mdp5_wb_encoder->intf)); + encoder = &mdp5_wb_encoder->base; + + drm_encoder_init(dev, encoder, &mdp5_wb_encoder_funcs, + DRM_MODE_ENCODER_VIRTUAL); + drm_encoder_helper_add(encoder, &mdp5_wb_encoder_helper_funcs); + + mdp5_wb_encoder->wb_vblank.irq = mdp5_wb_encoder_vblank_irq; + mdp5_wb_encoder->wb_vblank.irqmask = intf2vblank(0, intf); + + bs_init(mdp5_wb_encoder); + + return encoder; + +fail: + if (encoder) + mdp5_wb_encoder_destroy(encoder); + + return ERR_PTR(ret); +} diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h index 5ae4039..2d3428c 100644 --- a/drivers/gpu/drm/msm/mdp/mdp_kms.h +++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h @@ -88,7 +88,7 @@ struct mdp_format { uint8_t unpack[4]; bool alpha_enable, unpack_tight; uint8_t cpp, unpack_count; - enum mdp_sspp_fetch_type fetch_type; + enum mdp_fetch_type fetch_type; enum mdp_chroma_samp_type chroma_sample; }; #define to_mdp_format(x) container_of(x, struct mdp_format, base) diff --git a/drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.c b/drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.c new file mode 100644 index 0000000..5c40ec9 --- /dev/null +++ b/drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.c @@ -0,0 +1,319 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "mdp_wb.h" +#include "msm_kms.h" +#include "../mdp_kms.h" + +struct msm_wb_priv_data { + bool streaming; + + struct msm_wb_buf_format fmt; + /* buf queue */ + struct msm_wb_buf_queue vidq; + spinlock_t vidq_lock; + + /* wait queue to sync between v4l2 and drm during stream off */ + bool encoder_on; + wait_queue_head_t encoder_state_wq; +}; + +void msm_wb_update_encoder_state(struct msm_wb *wb, bool enable) +{ + wb->priv_data->encoder_on = enable; + wake_up_all(&wb->priv_data->encoder_state_wq); +} + +struct msm_wb_buf_format *msm_wb_get_buf_format(struct msm_wb *wb) +{ + return &wb->priv_data->fmt; +} + +int msm_wb_set_buf_format(struct msm_wb *wb, u32 pixel_fmt, + u32 width, u32 height) +{ + struct msm_drm_private *priv = wb->dev->dev_private; + struct msm_kms *kms = priv->kms; + const struct msm_format *msm_fmt; + const struct mdp_format *mdp_fmt; + struct msm_wb_buf_format *fmt = &wb->priv_data->fmt; + + msm_fmt = kms->funcs->get_format(kms, pixel_fmt); + if (!msm_fmt) { + pr_err("%s: Unsupported Color Format %d\n", __func__, + pixel_fmt); + return -EINVAL; + } + + mdp_fmt = to_mdp_format(msm_fmt); + + fmt->pixel_format = pixel_fmt; + fmt->width = width; + fmt->height = height; + DBG("Set format %x width %d height %d", pixel_fmt, width, height); + + switch (mdp_fmt->fetch_type) { + case MDP_PLANE_INTERLEAVED: + fmt->plane_num = 1; + fmt->pitches[0] = width * mdp_fmt->cpp; + break; + case MDP_PLANE_PLANAR: + fmt->plane_num = 3; + fmt->pitches[0] = width; + fmt->pitches[1] = width; + fmt->pitches[2] = width; + if (mdp_fmt->alpha_enable) { + fmt->plane_num = 4; + fmt->pitches[3] = width; + } + break; + case MDP_PLANE_PSEUDO_PLANAR: + fmt->plane_num = 2; + fmt->pitches[0] = width; + switch (mdp_fmt->chroma_sample) { + case CHROMA_H2V1: + case CHROMA_420: + fmt->pitches[1] = width/2; + break; + case CHROMA_H1V2: + fmt->pitches[1] = width; + break; + default: + pr_err("%s: Not supported fmt\n", __func__); + return -EINVAL; + } + break; + } + + return 0; +} + +void msm_wb_queue_buf(struct msm_wb *wb, struct msm_wb_buffer *wb_buf, + enum msm_wb_buf_queue_type type) +{ + unsigned long flags; + struct list_head *q; + + if (type == MSM_WB_BUF_Q_FREE) + q = &wb->priv_data->vidq.free; + else + q = &wb->priv_data->vidq.active; + + if (type == MSM_WB_BUF_Q_FREE) + mdp5_wb_encoder_buf_prepare(wb, wb_buf); + + spin_lock_irqsave(&wb->priv_data->vidq_lock, flags); + list_add_tail(&wb_buf->list, q); + spin_unlock_irqrestore(&wb->priv_data->vidq_lock, flags); +} + +struct msm_wb_buffer *msm_wb_dequeue_buf(struct msm_wb *wb, + enum msm_wb_buf_queue_type type) +{ + struct msm_wb_buffer *buf = NULL; + unsigned long flags; + struct list_head *q; + + if (type == MSM_WB_BUF_Q_FREE) + q = &wb->priv_data->vidq.free; + else + q = &wb->priv_data->vidq.active; + + spin_lock_irqsave(&wb->priv_data->vidq_lock, flags); + if (!list_empty(q)) { + buf = list_entry(q->next, + struct msm_wb_buffer, list); + list_del(&buf->list); + } + spin_unlock_irqrestore(&wb->priv_data->vidq_lock, flags); + + return buf; +} + +int msm_wb_start_streaming(struct msm_wb *wb) +{ + if (wb->priv_data->streaming) { + pr_err("%s: wb is streaming\n", __func__); + return -EBUSY; + } + + DBG("Stream ON"); + wb->priv_data->streaming = true; + msm_wb_connector_hotplug(wb, wb->priv_data->streaming); + + return 0; +} + +int msm_wb_stop_streaming(struct msm_wb *wb) +{ + int rc; + struct msm_wb_buffer *buf; + + if (!wb->priv_data->streaming) { + pr_info("%s: wb is not streaming\n", __func__); + return -EINVAL; + } + + DBG("Stream off"); + wb->priv_data->streaming = false; + msm_wb_connector_hotplug(wb, wb->priv_data->streaming); + + /* wait until drm encoder off */ + rc = wait_event_timeout(wb->priv_data->encoder_state_wq, + !wb->priv_data->encoder_on, 10 * HZ); + if (!rc) { + pr_err("%s: wait encoder off timeout\n", __func__); + return -ETIMEDOUT; + } + + /* flush all active and free buffers */ + while ((buf = msm_wb_dequeue_buf(wb, MSM_WB_BUF_Q_ACTIVE)) != NULL) + msm_wb_buf_captured(wb, buf, true); + + while ((buf = msm_wb_dequeue_buf(wb, MSM_WB_BUF_Q_FREE)) != NULL) + msm_wb_buf_captured(wb, buf, true); + + DBG("Stream turned off"); + + return 0; +} + +int msm_wb_modeset_init(struct msm_wb *wb, + struct drm_device *dev, struct drm_encoder *encoder) +{ + struct msm_drm_private *priv = dev->dev_private; + int ret; + + wb->dev = dev; + wb->encoder = encoder; + + wb->connector = msm_wb_connector_init(wb); + if (IS_ERR(wb->connector)) { + ret = PTR_ERR(wb->connector); + dev_err(dev->dev, "failed to create WB connector: %d\n", ret); + wb->connector = NULL; + goto fail; + } + + priv->connectors[priv->num_connectors++] = wb->connector; + + return 0; + +fail: + if (wb->connector) { + wb->connector->funcs->destroy(wb->connector); + wb->connector = NULL; + } + + return ret; +} + +static void msm_wb_destroy(struct msm_wb *wb) +{ + platform_set_drvdata(wb->pdev, NULL); +} + +static struct msm_wb *msm_wb_init(struct platform_device *pdev) +{ + struct msm_wb *wb = NULL; + + wb = devm_kzalloc(&pdev->dev, sizeof(*wb), GFP_KERNEL); + if (!wb) + return ERR_PTR(-ENOMEM); + + wb->pdev = pdev; + wb->priv_data = devm_kzalloc(&pdev->dev, sizeof(*wb->priv_data), + GFP_KERNEL); + if (!wb->priv_data) + return ERR_PTR(-ENOMEM); + + if (msm_wb_v4l2_init(wb)) { + pr_err("%s: wb v4l2 init failed\n", __func__); + return ERR_PTR(-ENODEV); + } + + spin_lock_init(&wb->priv_data->vidq_lock); + INIT_LIST_HEAD(&wb->priv_data->vidq.active); + INIT_LIST_HEAD(&wb->priv_data->vidq.free); + init_waitqueue_head(&wb->priv_data->encoder_state_wq); + + platform_set_drvdata(pdev, wb); + + return wb; +} + +static int msm_wb_bind(struct device *dev, struct device *master, void *data) +{ + struct drm_device *drm = dev_get_drvdata(master); + struct msm_drm_private *priv = drm->dev_private; + struct msm_wb *wb; + + wb = msm_wb_init(to_platform_device(dev)); + if (IS_ERR(wb)) + return PTR_ERR(wb); + + priv->wb = wb; + + return 0; +} + +static void msm_wb_unbind(struct device *dev, struct device *master, + void *data) +{ + struct drm_device *drm = dev_get_drvdata(master); + struct msm_drm_private *priv = drm->dev_private; + + if (priv->wb) { + msm_wb_destroy(priv->wb); + priv->wb = NULL; + } +} + +static const struct component_ops msm_wb_ops = { + .bind = msm_wb_bind, + .unbind = msm_wb_unbind, +}; + +static int msm_wb_dev_probe(struct platform_device *pdev) +{ + return component_add(&pdev->dev, &msm_wb_ops); +} + +static int msm_wb_dev_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &msm_wb_ops); + return 0; +} + +static const struct of_device_id dt_match[] = { + { .compatible = "qcom,mdss_wb"}, + {} +}; + +static struct platform_driver msm_wb_driver = { + .probe = msm_wb_dev_probe, + .remove = msm_wb_dev_remove, + .driver = { + .name = "wb_msm", + .of_match_table = dt_match, + }, +}; + +void __init msm_wb_register(void) +{ + platform_driver_register(&msm_wb_driver); +} + +void __exit msm_wb_unregister(void) +{ + platform_driver_unregister(&msm_wb_driver); +} diff --git a/drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.h b/drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.h new file mode 100644 index 0000000..4c75419 --- /dev/null +++ b/drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb.h @@ -0,0 +1,98 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __WB_CONNECTOR_H__ +#define __WB_CONNECTOR_H__ + +#include +#include "msm_kms.h" + +struct vb2_buffer; + +struct msm_wb_buffer { + struct list_head list; + struct drm_gem_object *planes[MAX_PLANE]; + u32 pixel_format; + u32 offsets[MAX_PLANE]; + u32 iova[MAX_PLANE]; + struct vb2_buffer *vb; /* v4l2 buffer */ +}; + +struct msm_wb_buf_format { + u32 pixel_format; + u32 width; + u32 height; + u32 plane_num; + u32 pitches[MAX_PLANE]; +}; + +enum msm_wb_buf_queue_type { + MSM_WB_BUF_Q_FREE = 0, + MSM_WB_BUF_Q_ACTIVE, + MSM_WB_BUF_Q_NUM +}; + +struct msm_wb_buf_queue { + struct list_head free; + struct list_head active; +}; + +struct msm_wb_priv_data; +struct msm_wb { + struct drm_device *dev; + struct platform_device *pdev; + + struct drm_connector *connector; + struct drm_encoder *encoder; + + void *wb_v4l2; + + struct msm_wb_priv_data *priv_data; +}; + +int msm_wb_start_streaming(struct msm_wb *wb); +int msm_wb_stop_streaming(struct msm_wb *wb); +void mdp5_wb_encoder_buf_prepare(struct msm_wb *wb, struct msm_wb_buffer *buf); +void msm_wb_connector_hotplug(struct msm_wb *wb, bool connected); +int msm_wb_set_buf_format(struct msm_wb *wb, u32 pixel_fmt, + u32 width, u32 height); + +#ifdef CONFIG_DRM_MSM_WB +struct msm_wb_buf_format *msm_wb_get_buf_format(struct msm_wb *wb); +void msm_wb_queue_buf(struct msm_wb *wb, struct msm_wb_buffer *buf, + enum msm_wb_buf_queue_type type); +struct msm_wb_buffer *msm_wb_dequeue_buf(struct msm_wb *wb, + enum msm_wb_buf_queue_type type); +void msm_wb_update_encoder_state(struct msm_wb *wb, bool enable); +void msm_wb_buf_captured(struct msm_wb *wb, struct msm_wb_buffer *buf, + bool discard); +#else +static inline struct msm_wb_buf_format *msm_wb_get_buf_format( + struct msm_wb *wb) { return NULL; } +static inline void msm_wb_queue_buf(struct msm_wb *wb, + struct msm_wb_buffer *buf, enum msm_wb_buf_queue_type type) {} +static inline struct msm_wb_buffer *msm_wb_dequeue_buf(struct msm_wb *wb, + enum msm_wb_buf_queue_type type) { return NULL; } +static inline void msm_wb_update_encoder_state(struct msm_wb *wb, + bool enable) {} +static inline void msm_wb_buf_captured(struct msm_wb *wb, + struct msm_wb_buffer *buf, bool discard) {} +#endif + +int msm_wb_v4l2_init(struct msm_wb *wb); + +/* + * wb connector: + */ +struct drm_connector *msm_wb_connector_init(struct msm_wb *wb); + +#endif /* __WB_CONNECTOR_H__ */ diff --git a/drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_connector.c b/drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_connector.c new file mode 100644 index 0000000..814dec9 --- /dev/null +++ b/drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_connector.c @@ -0,0 +1,157 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "mdp_wb.h" + +struct msm_wb_connector { + struct drm_connector base; + struct msm_wb *wb; + struct work_struct hpd_work; + bool connected; +}; +#define to_wb_connector(x) container_of(x, struct msm_wb_connector, base) + +static enum drm_connector_status msm_wb_connector_detect( + struct drm_connector *connector, bool force) +{ + struct msm_wb_connector *wb_connector = to_wb_connector(connector); + + DBG("%s", wb_connector->connected ? "connected" : "disconnected"); + return wb_connector->connected ? + connector_status_connected : connector_status_disconnected; +} + +static void msm_wb_hotplug_work(struct work_struct *work) +{ + struct msm_wb_connector *wb_connector = + container_of(work, struct msm_wb_connector, hpd_work); + struct drm_connector *connector = &wb_connector->base; + + drm_kms_helper_hotplug_event(connector->dev); +} + +void msm_wb_connector_hotplug(struct msm_wb *wb, bool connected) +{ + struct drm_connector *connector = wb->connector; + struct msm_wb_connector *wb_connector = to_wb_connector(connector); + struct msm_drm_private *priv = connector->dev->dev_private; + + wb_connector->connected = connected; + queue_work(priv->wq, &wb_connector->hpd_work); +} + +static void msm_wb_connector_destroy(struct drm_connector *connector) +{ + struct msm_wb_connector *wb_connector = to_wb_connector(connector); + + drm_connector_unregister(connector); + drm_connector_cleanup(connector); + + kfree(wb_connector); +} + +static int msm_wb_connector_get_modes(struct drm_connector *connector) +{ + struct msm_wb_connector *wb_connector = to_wb_connector(connector); + struct msm_wb *wb = wb_connector->wb; + struct msm_wb_buf_format *wb_buf_fmt; + struct drm_display_mode *mode = NULL; + + wb_buf_fmt = msm_wb_get_buf_format(wb); + mode = drm_cvt_mode(connector->dev, wb_buf_fmt->width, + wb_buf_fmt->height, 60, false, false, false); + + if (!mode) { + pr_err("%s: failed to create mode\n", __func__); + return -ENOTSUPP; + } + + drm_mode_probed_add(connector, mode); + + return 1; +} + +static int msm_wb_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + return 0; +} + +static struct drm_encoder * +msm_wb_connector_best_encoder(struct drm_connector *connector) +{ + struct msm_wb_connector *wb_connector = to_wb_connector(connector); + + return wb_connector->wb->encoder; +} + +static const struct drm_connector_funcs msm_wb_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .detect = msm_wb_connector_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = msm_wb_connector_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + +}; + +static const struct drm_connector_helper_funcs msm_wb_connector_helper_funcs = { + .get_modes = msm_wb_connector_get_modes, + .mode_valid = msm_wb_connector_mode_valid, + .best_encoder = msm_wb_connector_best_encoder, +}; + +/* initialize connector */ +struct drm_connector *msm_wb_connector_init(struct msm_wb *wb) +{ + struct drm_connector *connector = NULL; + struct msm_wb_connector *wb_connector; + int ret; + + wb_connector = kzalloc(sizeof(*wb_connector), GFP_KERNEL); + if (!wb_connector) { + ret = -ENOMEM; + goto fail; + } + + wb_connector->wb = wb; + connector = &wb_connector->base; + + ret = drm_connector_init(wb->dev, connector, &msm_wb_connector_funcs, + DRM_MODE_CONNECTOR_VIRTUAL); + if (ret) + goto fail; + + drm_connector_helper_add(connector, &msm_wb_connector_helper_funcs); + + connector->polled = DRM_CONNECTOR_POLL_HPD; + + connector->interlace_allowed = 0; + connector->doublescan_allowed = 0; + + drm_connector_register(connector); + + ret = drm_mode_connector_attach_encoder(connector, wb->encoder); + if (ret) + goto fail; + + INIT_WORK(&wb_connector->hpd_work, msm_wb_hotplug_work); + + return connector; + +fail: + if (connector) + msm_wb_connector_destroy(connector); + + return ERR_PTR(ret); +} diff --git a/drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_v4l2.c b/drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_v4l2.c new file mode 100644 index 0000000..f6df4d4 --- /dev/null +++ b/drivers/gpu/drm/msm/mdp/mdp_wb/mdp_wb_v4l2.c @@ -0,0 +1,522 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mdp_wb.h" + +#define MSM_WB_MODULE_NAME "msm_wb" +#define MAX_WIDTH 2048 +#define MAX_HEIGHT 2048 + +static unsigned debug; +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "activates debug info"); + +#define dprintk(dev, level, fmt, arg...) \ + v4l2_dbg(level, debug, &dev->v4l2_dev, fmt, ## arg) + +struct msm_wb_fmt { + const char *name; + u32 fourcc; /* v4l2 format id */ + u32 drm_fourcc; /* drm format id */ + u8 depth; + u8 plane_cnt; + u32 plane_bpp[MAX_PLANE]; /* bit per pixel per plalne */ + bool is_yuv; +}; + +static const struct msm_wb_fmt formats[] = { + { + .name = "Y/CbCr 4:2:0", + .fourcc = V4L2_PIX_FMT_NV12, + .drm_fourcc = DRM_FORMAT_NV12, + .depth = 12, + .plane_cnt = 2, + .plane_bpp = {8, 4, 0, 0}, + .is_yuv = true, + }, + { + .name = "Y/CrCb 4:2:0", + .fourcc = V4L2_PIX_FMT_NV21, + .drm_fourcc = DRM_FORMAT_NV21, + .depth = 12, + .plane_cnt = 2, + .plane_bpp = {8, 4, 0, 0}, + .is_yuv = true, + }, + { + .name = "RGB24", + .fourcc = V4L2_PIX_FMT_RGB24, + .drm_fourcc = DRM_FORMAT_RGB888, + .depth = 24, + .plane_cnt = 2, + .plane_bpp = {24, 0, 0, 0}, + }, + { + .name = "ARGB32", + .fourcc = V4L2_PIX_FMT_RGB32, + .drm_fourcc = DRM_FORMAT_ARGB8888, + .depth = 32, + .plane_cnt = 1, + .plane_bpp = {24, 0, 0, 0}, + }, +}; + +/* buffer for one video frame */ +struct msm_wb_v4l2_buffer { + /* common v4l buffer stuff -- must be first */ + struct vb2_buffer vb; + struct msm_wb_buffer wb_buf; +}; + +struct msm_wb_v4l2_dev { + struct v4l2_device v4l2_dev; + struct video_device vdev; + + struct mutex mutex; + + /* video capture */ + const struct msm_wb_fmt *fmt; + unsigned int width, height; + + struct vb2_queue vb_vidq; + + struct msm_wb *wb; +}; + +static const struct msm_wb_fmt *get_format(u32 fourcc) +{ + const struct msm_wb_fmt *fmt; + unsigned int k; + + for (k = 0; k < ARRAY_SIZE(formats); k++) { + fmt = &formats[k]; + if (fmt->fourcc == fourcc) + break; + } + + if (k == ARRAY_SIZE(formats)) + return NULL; + + return &formats[k]; +} + +void msm_wb_buf_captured(struct msm_wb *wb, + struct msm_wb_buffer *buf, bool discard) +{ + struct msm_wb_v4l2_buffer *v4l2_buf = + container_of(buf, struct msm_wb_v4l2_buffer, wb_buf); + enum vb2_buffer_state buf_state = discard ? VB2_BUF_STATE_ERROR : + VB2_BUF_STATE_DONE; + + v4l2_get_timestamp(&v4l2_buf->vb.v4l2_buf.timestamp); + vb2_buffer_done(&v4l2_buf->vb, buf_state); +} + +/* ------------------------------------------------------------------ + DMA buffer operations + ------------------------------------------------------------------*/ + +static int msm_wb_vb2_map_dmabuf(void *mem_priv) +{ + return 0; +} + +static void msm_wb_vb2_unmap_dmabuf(void *mem_priv) +{ +} + +static void *msm_wb_vb2_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf, + unsigned long size, int write) +{ + struct msm_wb_v4l2_dev *dev = alloc_ctx; + struct drm_device *drm_dev = dev->wb->dev; + struct drm_gem_object *obj; + + mutex_lock(&drm_dev->object_name_lock); + obj = drm_dev->driver->gem_prime_import(drm_dev, dbuf); + if (WARN_ON(!obj)) { + mutex_unlock(&drm_dev->object_name_lock); + v4l2_err(&dev->v4l2_dev, "Can't convert dmabuf to gem obj.\n"); + return NULL; + } + + if (obj->dma_buf) { + if (WARN_ON(obj->dma_buf != dbuf)) { + v4l2_err(&dev->v4l2_dev, + "dma buf doesn't match.\n"); + drm_gem_object_unreference_unlocked(obj); + + obj = ERR_PTR(-EINVAL); + } + } else { + obj->dma_buf = dbuf; + } + + mutex_unlock(&drm_dev->object_name_lock); + + return obj; +} + +static void msm_wb_vb2_detach_dmabuf(void *mem_priv) +{ + struct drm_gem_object *obj = mem_priv; + + drm_gem_object_unreference_unlocked(obj); +} + +void *msm_wb_vb2_cookie(void *buf_priv) +{ + return buf_priv; +} + +const struct vb2_mem_ops msm_wb_vb2_mem_ops = { + .map_dmabuf = msm_wb_vb2_map_dmabuf, + .unmap_dmabuf = msm_wb_vb2_unmap_dmabuf, + .attach_dmabuf = msm_wb_vb2_attach_dmabuf, + .detach_dmabuf = msm_wb_vb2_detach_dmabuf, + .cookie = msm_wb_vb2_cookie, +}; + +/* ------------------------------------------------------------------ + Videobuf operations + ------------------------------------------------------------------*/ +#define MSM_WB_BUF_NUM_MIN 4 + +static int msm_wb_vb2_queue_setup(struct vb2_queue *vq, + const struct v4l2_format *fmt, + unsigned int *nbuffers, unsigned int *nplanes, + unsigned int sizes[], void *alloc_ctxs[]) +{ + struct msm_wb_v4l2_dev *dev = vb2_get_drv_priv(vq); + const struct msm_wb_fmt *wb_fmt = dev->fmt; + int i; + + *nbuffers = MSM_WB_BUF_NUM_MIN; + *nplanes = wb_fmt->plane_cnt; + + for (i = 0; i < *nplanes; i++) { + sizes[i] = (wb_fmt->plane_bpp[i] * dev->width * + dev->height) >> 3; + alloc_ctxs[i] = dev; + } + + dprintk(dev, 1, "%s, count=%d, plane count=%d\n", __func__, + *nbuffers, *nplanes); + + return 0; +} + +static int msm_wb_vb2_buf_prepare(struct vb2_buffer *vb) +{ + return 0; +} + +static void msm_wb_vb2_buf_queue(struct vb2_buffer *vb) +{ + struct msm_wb_v4l2_dev *dev = vb2_get_drv_priv(vb->vb2_queue); + struct msm_wb_v4l2_buffer *buf = + container_of(vb, struct msm_wb_v4l2_buffer, vb); + struct msm_wb_buffer *wb_buf = &buf->wb_buf; + int i; + + dprintk(dev, 1, "%s\n", __func__); + + /* pass the buffer to wb */ + wb_buf->vb = vb; + wb_buf->pixel_format = dev->fmt->drm_fourcc; + for (i = 0; i < vb->num_planes; i++) { + wb_buf->offsets[i] = vb->v4l2_planes[i].data_offset; + wb_buf->planes[i] = vb2_plane_cookie(vb, i); + WARN_ON(!wb_buf->planes[i]); + } + + msm_wb_queue_buf(dev->wb, wb_buf, MSM_WB_BUF_Q_FREE); +} + +static int msm_wb_vb2_start_streaming(struct vb2_queue *vq, unsigned int count) +{ + struct msm_wb_v4l2_dev *dev = vb2_get_drv_priv(vq); + + dprintk(dev, 1, "%s\n", __func__); + + return msm_wb_start_streaming(dev->wb); +} + +/* abort streaming and wait for last buffer */ +static int msm_wb_vb2_stop_streaming(struct vb2_queue *vq) +{ + struct msm_wb_v4l2_dev *dev = vb2_get_drv_priv(vq); + + dprintk(dev, 1, "%s\n", __func__); + + return msm_wb_stop_streaming(dev->wb); +} + +static const struct vb2_ops msm_wb_vb2_ops = { + .queue_setup = msm_wb_vb2_queue_setup, + .buf_prepare = msm_wb_vb2_buf_prepare, + .buf_queue = msm_wb_vb2_buf_queue, + .start_streaming = msm_wb_vb2_start_streaming, + .stop_streaming = msm_wb_vb2_stop_streaming, +}; + +/* ------------------------------------------------------------------ + IOCTL vidioc handling + ------------------------------------------------------------------*/ +static int msm_wb_vidioc_querycap(struct file *file, void *priv, + struct v4l2_capability *cap) +{ + struct msm_wb_v4l2_dev *dev = video_drvdata(file); + + strcpy(cap->driver, "msm_wb"); + strcpy(cap->card, "msm_wb"); + snprintf(cap->bus_info, sizeof(cap->bus_info), + "platform:%s", dev->v4l2_dev.name); + cap->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; + + return 0; +} + +static int msm_wb_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_fmtdesc *f) +{ + struct msm_wb_v4l2_dev *dev = video_drvdata(file); + const struct msm_wb_fmt *fmt; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + v4l2_err(&dev->v4l2_dev, "Invalid buf type %d.\n", + f->type); + return -EINVAL; + } + + if (f->index >= ARRAY_SIZE(formats)) + return -ERANGE; + + fmt = &formats[f->index]; + + strlcpy(f->description, fmt->name, sizeof(f->description)); + f->pixelformat = fmt->fourcc; + + return 0; +} + +static int msm_wb_vidioc_g_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct msm_wb_v4l2_dev *dev = video_drvdata(file); + int i; + + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + f->fmt.pix_mp.width = dev->width; + f->fmt.pix_mp.height = dev->height; + f->fmt.pix_mp.field = V4L2_FIELD_NONE; + f->fmt.pix_mp.pixelformat = dev->fmt->fourcc; + f->fmt.pix_mp.num_planes = dev->fmt->plane_cnt; + + for (i = 0; i < dev->fmt->plane_cnt; i++) { + f->fmt.pix_mp.plane_fmt[i].bytesperline = + (dev->fmt->plane_bpp[i] * dev->width) >> 3; + f->fmt.pix_mp.plane_fmt[i].sizeimage = + f->fmt.pix_mp.plane_fmt[i].bytesperline * dev->height; + } + + if (dev->fmt->is_yuv) + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_SMPTE170M; + else + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_SRGB; + + return 0; +} + +static int msm_wb_vidioc_try_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct msm_wb_v4l2_dev *dev = video_drvdata(file); + const struct msm_wb_fmt *fmt; + int i; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { + v4l2_err(&dev->v4l2_dev, "Invalid buf type %d.\n", + f->type); + return -EINVAL; + } + + fmt = get_format(f->fmt.pix_mp.pixelformat); + if (!fmt) { + v4l2_err(&dev->v4l2_dev, "Fourcc format (0x%08x) unknown.\n", + f->fmt.pix_mp.pixelformat); + return -ENOTSUPP; + } + + f->fmt.pix_mp.field = V4L2_FIELD_NONE; + v4l_bound_align_image(&f->fmt.pix_mp.width, 48, MAX_WIDTH, 4, + &f->fmt.pix_mp.height, 32, MAX_HEIGHT, 4, 0); + f->fmt.pix_mp.num_planes = fmt->plane_cnt; + + for (i = 0; i < dev->fmt->plane_cnt; i++) { + f->fmt.pix_mp.plane_fmt[i].bytesperline = + (dev->fmt->plane_bpp[i] * f->fmt.pix_mp.width) >> 3; + f->fmt.pix_mp.plane_fmt[i].sizeimage = + f->fmt.pix_mp.plane_fmt[i].bytesperline * + f->fmt.pix_mp.height; + } + + if (fmt->is_yuv) + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_SMPTE170M; + else + f->fmt.pix_mp.colorspace = V4L2_COLORSPACE_SRGB; + + return 0; +} + +static int msm_wb_vidioc_s_fmt_vid_cap(struct file *file, void *priv, + struct v4l2_format *f) +{ + struct msm_wb_v4l2_dev *dev = video_drvdata(file); + struct msm_wb *wb = dev->wb; + struct vb2_queue *q = &dev->vb_vidq; + int rc; + + rc = msm_wb_vidioc_try_fmt_vid_cap(file, priv, f); + if (rc < 0) + return rc; + + if (vb2_is_busy(q)) { + v4l2_err(&dev->v4l2_dev, "%s device busy\n", __func__); + return -EBUSY; + } + + dev->fmt = get_format(f->fmt.pix_mp.pixelformat); + dev->width = f->fmt.pix_mp.width; + dev->height = f->fmt.pix_mp.height; + + rc = msm_wb_set_buf_format(wb, dev->fmt->drm_fourcc, + dev->width, dev->height); + if (rc) + v4l2_err(&dev->v4l2_dev, + "Set format (0x%08x w:%x h:%x) failed.\n", + dev->fmt->drm_fourcc, dev->width, dev->height); + + return rc; +} + +static const struct v4l2_file_operations msm_wb_v4l2_fops = { + .owner = THIS_MODULE, + .open = v4l2_fh_open, + .release = vb2_fop_release, + .poll = vb2_fop_poll, + .unlocked_ioctl = video_ioctl2, +}; + +static const struct v4l2_ioctl_ops msm_wb_v4l2_ioctl_ops = { + .vidioc_querycap = msm_wb_vidioc_querycap, + .vidioc_enum_fmt_vid_cap_mplane = msm_wb_vidioc_enum_fmt_vid_cap, + .vidioc_g_fmt_vid_cap_mplane = msm_wb_vidioc_g_fmt_vid_cap, + .vidioc_try_fmt_vid_cap_mplane = msm_wb_vidioc_try_fmt_vid_cap, + .vidioc_s_fmt_vid_cap_mplane = msm_wb_vidioc_s_fmt_vid_cap, + .vidioc_reqbufs = vb2_ioctl_reqbufs, + .vidioc_querybuf = vb2_ioctl_querybuf, + .vidioc_qbuf = vb2_ioctl_qbuf, + .vidioc_dqbuf = vb2_ioctl_dqbuf, + .vidioc_streamon = vb2_ioctl_streamon, + .vidioc_streamoff = vb2_ioctl_streamoff, + .vidioc_log_status = v4l2_ctrl_log_status, + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, +}; + +static const struct video_device msm_wb_v4l2_template = { + .name = "msm_wb", + .fops = &msm_wb_v4l2_fops, + .ioctl_ops = &msm_wb_v4l2_ioctl_ops, + .release = video_device_release_empty, +}; + +int msm_wb_v4l2_init(struct msm_wb *wb) +{ + struct msm_wb_v4l2_dev *dev; + struct video_device *vfd; + struct vb2_queue *q; + int ret; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return -ENOMEM; + + snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), + "%s", MSM_WB_MODULE_NAME); + ret = v4l2_device_register(NULL, &dev->v4l2_dev); + if (ret) + goto free_dev; + + /* default ARGB8888 640x480 */ + dev->fmt = get_format(V4L2_PIX_FMT_RGB32); + dev->width = 640; + dev->height = 480; + + /* initialize queue */ + q = &dev->vb_vidq; + q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + q->io_modes = VB2_DMABUF; + q->drv_priv = dev; + q->buf_struct_size = sizeof(struct msm_wb_v4l2_buffer); + q->ops = &msm_wb_vb2_ops; + q->mem_ops = &msm_wb_vb2_mem_ops; + q->timestamp_type = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; + + ret = vb2_queue_init(q); + if (ret) + goto unreg_dev; + + mutex_init(&dev->mutex); + + vfd = &dev->vdev; + *vfd = msm_wb_v4l2_template; + vfd->debug = debug; + vfd->v4l2_dev = &dev->v4l2_dev; + vfd->queue = q; + + /* + * Provide a mutex to v4l2 core. It will be used to protect + * all fops and v4l2 ioctls. + */ + vfd->lock = &dev->mutex; + video_set_drvdata(vfd, dev); + + ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1); + if (ret < 0) + goto unreg_dev; + + dev->wb = wb; + wb->wb_v4l2 = dev; + v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n", + video_device_node_name(vfd)); + + return 0; + +unreg_dev: + v4l2_device_unregister(&dev->v4l2_dev); +free_dev: + kfree(dev); + return ret; +} diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index a72ed0a..61e76d0 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1032,6 +1032,7 @@ static struct platform_driver msm_platform_driver = { static int __init msm_drm_register(void) { DBG("init"); + msm_wb_register(); msm_edp_register(); hdmi_register(); adreno_register(); @@ -1045,6 +1046,7 @@ static void __exit msm_drm_unregister(void) hdmi_unregister(); adreno_unregister(); msm_edp_unregister(); + msm_wb_unregister(); } module_init(msm_drm_register); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 9e8d441..ceb551a 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -53,6 +53,9 @@ struct msm_mmu; struct msm_rd_state; struct msm_perf_state; struct msm_gem_submit; +struct hdmi; +struct msm_edp; +struct msm_wb; #define NUM_DOMAINS 2 /* one for KMS, then one per gpu core (?) */ @@ -82,6 +85,8 @@ struct msm_drm_private { */ struct msm_edp *edp; + struct msm_wb *wb; + /* when we have more than one 'msm_gpu' these need to be an array: */ struct msm_gpu *gpu; struct msm_file_private *lastctx; @@ -224,18 +229,28 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev, struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev); -struct hdmi; int hdmi_modeset_init(struct hdmi *hdmi, struct drm_device *dev, struct drm_encoder *encoder); void __init hdmi_register(void); void __exit hdmi_unregister(void); -struct msm_edp; void __init msm_edp_register(void); void __exit msm_edp_unregister(void); int msm_edp_modeset_init(struct msm_edp *edp, struct drm_device *dev, struct drm_encoder *encoder); +#ifdef CONFIG_DRM_MSM_WB +void __init msm_wb_register(void); +void __exit msm_wb_unregister(void); +int msm_wb_modeset_init(struct msm_wb *wb, struct drm_device *dev, + struct drm_encoder *encoder); +#else +static inline void __init msm_wb_register(void) {} +static inline void __exit msm_wb_unregister(void) {} +static inline int msm_wb_modeset_init(struct msm_wb *wb, struct drm_device *dev, + struct drm_encoder *encoder) { return -EINVAL; } +#endif + #ifdef CONFIG_DEBUG_FS void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m); void msm_gem_describe_objects(struct list_head *list, struct seq_file *m); diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index df60f65..9d553f2 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -212,6 +212,38 @@ static void msm_crtc_fb_gamma_get(struct drm_crtc *crtc, DBG("fbdev: get gamma"); } +/* add all connectors to fb except wb connector */ +static int msm_drm_fb_add_connectors(struct drm_fb_helper *fb_helper) +{ + struct drm_device *dev = fb_helper->dev; + struct drm_connector *connector; + int i; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct drm_fb_helper_connector *fb_helper_connector; + + if (connector->connector_type == DRM_MODE_CONNECTOR_VIRTUAL) + continue; + + fb_helper_connector = + kzalloc(sizeof(*fb_helper_connector), GFP_KERNEL); + if (!fb_helper_connector) + goto fail; + + fb_helper_connector->connector = connector; + fb_helper->connector_info[fb_helper->connector_count++] = + fb_helper_connector; + } + return 0; +fail: + for (i = 0; i < fb_helper->connector_count; i++) { + kfree(fb_helper->connector_info[i]); + fb_helper->connector_info[i] = NULL; + } + fb_helper->connector_count = 0; + return -ENOMEM; +} + static const struct drm_fb_helper_funcs msm_fb_helper_funcs = { .gamma_set = msm_crtc_fb_gamma_set, .gamma_get = msm_crtc_fb_gamma_get, @@ -241,7 +273,7 @@ struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev) goto fail; } - ret = drm_fb_helper_single_add_all_connectors(helper); + ret = msm_drm_fb_add_connectors(helper); if (ret) goto fini; diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 49dea4f..11a1924 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -534,6 +534,7 @@ void msm_gem_free_object(struct drm_gem_object *obj) if (msm_obj->pages) drm_free_large(msm_obj->pages); + drm_prime_gem_destroy(obj, msm_obj->sgt); } else { vunmap(msm_obj->vaddr); put_pages(obj); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project