From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5F5BACED25D for ; Tue, 8 Oct 2024 03:21:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:Content-Type: Content-Transfer-Encoding:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:From:References:Cc:To:Subject: MIME-Version:Date:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=7+T9HUIUj3X8gjSzVmPVynP3Ulog6SbdU0fqdbxaNKI=; b=bPXEwUjZa+8Rv8 5tuHRWAoq9+wDmE+iJF5S0f+26buUSQ67LoN+oTy9ztx3ecjr2NhCTXzcF+lKw88LETUGDYuM4S5x QD8SkYAyWN43CIAn8qPmy8CXu23J9giaO1lCH3A60ace9/v2uykcvLju/gQ08icltJ72KGZy220mV IOQH+accNO8z29Ddy9bOCXVkBTbwQPZDwo9+JzMNwwxfOOIbqFH/UZfeFS+oqZM+6483+FZCdARjf dst1ZVI6urPwzpImTQwFq8Clf2ngo0FXci8jckDkp+yz7C7Hk5jflfend87BsINuLyw26eFrP/p6X JbqSOm/Sav3DSM/V4K1A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1sy0mu-00000004OH5-0A2N; Tue, 08 Oct 2024 03:21:28 +0000 Received: from mail-pj1-x1033.google.com ([2607:f8b0:4864:20::1033]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1sy0lW-00000004O7x-39wZ; Tue, 08 Oct 2024 03:20:06 +0000 Received: by mail-pj1-x1033.google.com with SMTP id 98e67ed59e1d1-2e18aa9f06dso3649588a91.0; Mon, 07 Oct 2024 20:20:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728357602; x=1728962402; darn=lists.infradead.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=vFntR5p2J86VuDGwgkOeGjdKlfKqRgMieCplvZuIyzg=; b=EVQFwOjJ+dJ+DXUqM9JAJUEjAzpLd+4f1xF5tu/yVS1E82NNCObsr5nbyC1PDQh8MR XAIn2np6rx1g5SoOrC1ApyS/zPNRXOGAKlYlDIfqo6AFG/uHsHZYCtxlYjJxk8mZ8QZM mPE8ME/SJzVPjUgKz3rhZQYImC4Ged03p+peAagCDba3ivBH6JqhSdfrwolAfGX+AYre e6bjCa76kJS+Dbcpu17c7oW8+UkfEwh4xZOtjPoDj9+o+KkB6IMF+MbTxbPfk4UnF87V q2vqpC3mUWnJrZJIukQ1kQR2hOq4aVIizZMJYg8yCzAqWfx/pc2ByeKRYAoZ3EMWyxO4 reYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728357602; x=1728962402; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=vFntR5p2J86VuDGwgkOeGjdKlfKqRgMieCplvZuIyzg=; b=NAHshyYmMFV6ckgsRwcXoE6TnH6BRPVcKsc+PinfNx/A/Yrwta+TOP6FieVx6FrtS1 X1UcKAwmmc4oBfJN+WbulfvrNsrNHDlo18/KR12XwBLBXbMUbj7iP/AbACN5n9eSQcsp uIIKa7q597pAMHM3zrF+pTPRhRVhPa/Hf1v1opQyYAWajl0GE/yXKetx26SD0YJRPuLp 04dLPqXhBDMhgEWqaCLtYtG1RM7G6JcrRLD2PHUC18EilAd4ZlP2EWLS234uR4WQUtYX 4LZ7fifsx9l3P3GlELirqpDCmPs0R1xhd8yp1IJqMUSU9ZHQOTGIfVXjg5H1s7H24cM7 JZtQ== X-Forwarded-Encrypted: i=1; AJvYcCV4UekY7zTXBGPPz6fWbVzFHASibU+EqsdwyQkN89ww994dj0xd/TTReh1TU9Zt4VJH1QdpYvzy2qMl@lists.infradead.org, AJvYcCWIVYoDmjkO3d1METglUTo2AwsAb/d+pNFYaAejQVgHdZII/k6M267+MGJMCd49ghEnKIRVtUteF/eW2tMsgvuk@lists.infradead.org X-Gm-Message-State: AOJu0Yw+SDnd0yBejTRrU7qIDVIT8SpS4yI/Qwd5w7Uj20PQL5A6CwEv YLvrDOHwbwxoHZ61+ohMMZ5Ipq6f2+Zb/YXS50I96iRgMneGOl/z X-Google-Smtp-Source: AGHT+IGruia56J8OL3/MX7UQ1hDdtBG35QP76rfwJ6CEuU6FQcQq/RFSak5t59vmXzj8dhRXoqzLOw== X-Received: by 2002:a17:90a:6884:b0:2e2:18ac:afad with SMTP id 98e67ed59e1d1-2e27ded0213mr2873514a91.15.1728357601406; Mon, 07 Oct 2024 20:20:01 -0700 (PDT) Received: from [172.19.1.53] (60-250-196-139.hinet-ip.hinet.net. [60.250.196.139]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2e2848d28f4sm333855a91.24.2024.10.07.20.19.58 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 07 Oct 2024 20:20:01 -0700 (PDT) Message-ID: <8d5e7755-17fd-4860-bcb0-8c1de04bf0c5@gmail.com> Date: Tue, 8 Oct 2024 11:19:57 +0800 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v6 2/2] mtd: rawnand: nuvoton: add new driver for the Nuvoton MA35 SoC To: Miquel Raynal Cc: richard@nod.at, vigneshr@ti.com, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, nikita.shubin@maquefel.me, arnd@arndb.de, vkoul@kernel.org, esben@geanix.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org References: <20240927020749.46791-1-hpchen0nvt@gmail.com> <20240927020749.46791-3-hpchen0nvt@gmail.com> <20241001215755.5c2f8465@xps-13> Content-Language: en-US From: Hui-Ping Chen In-Reply-To: <20241001215755.5c2f8465@xps-13> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241007_202002_880308_AA3BE59C X-CRM114-Status: GOOD ( 35.03 ) X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Sender: "linux-mtd" Errors-To: linux-mtd-bounces+linux-mtd=archiver.kernel.org@lists.infradead.org RGVhciBNaXF1ZWwsCgoKVGhhbmsgeW91IGZvciB5b3VyIHJlcGx5LgoKCgpPbiAyMDI0LzEwLzIg 5LiK5Y2IIDAzOjU3LCBNaXF1ZWwgUmF5bmFsIHdyb3RlOgo+IEhpIEh1aS1QaW5nLAo+Cj4gaHBj aGVuMG52dEBnbWFpbC5jb20gd3JvdGUgb24gRnJpLCAyNyBTZXAgMjAyNCAwMjowNzo0OSArMDAw MDoKPgo+PiBOdXZvdG9uIE1BMzUgU29DcyBOQU5EIEZsYXNoIEludGVyZmFjZSBDb250cm9sbGVy Cj4+IHN1cHBvcnRzIDJraUIsIDRraUIgYW5kIDhraUIgcGFnZSBzaXplLCBhbmQgdXAgdG8KPj4g OC1iaXQsIDEyLWJpdCwgYW5kIDI0LWJpdCBoYXJkd2FyZSBFQ0MgY2FsY3VsYXRpb24KPj4gY2ly Y3VpdCB0byBwcm90ZWN0IGRhdGEuCj4+Cj4+IFNpZ25lZC1vZmYtYnk6IEh1aS1QaW5nIENoZW4g PGhwY2hlbjBudnRAZ21haWwuY29tPgo+PiAtLS0KPj4gICBkcml2ZXJzL210ZC9uYW5kL3Jhdy9L Y29uZmlnICAgICAgICAgICAgICAgfCAgIDggKwo+PiAgIGRyaXZlcnMvbXRkL25hbmQvcmF3L01h a2VmaWxlICAgICAgICAgICAgICB8ICAgMSArCj4+ICAgZHJpdmVycy9tdGQvbmFuZC9yYXcvbnV2 b3Rvbl9tYTM1ZDFfbmFuZC5jIHwgODYyICsrKysrKysrKysrKysrKysrKysrKwo+PiAgIDMgZmls ZXMgY2hhbmdlZCwgODcxIGluc2VydGlvbnMoKykKPj4gICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJp dmVycy9tdGQvbmFuZC9yYXcvbnV2b3Rvbl9tYTM1ZDFfbmFuZC5jCj4+Cj4+IGRpZmYgLS1naXQg YS9kcml2ZXJzL210ZC9uYW5kL3Jhdy9LY29uZmlnIGIvZHJpdmVycy9tdGQvbmFuZC9yYXcvS2Nv bmZpZwo+PiBpbmRleCBkMGFhY2NmNzJkNzguLmUzNjc3YmNhZjAzNSAxMDA2NDQKPj4gLS0tIGEv ZHJpdmVycy9tdGQvbmFuZC9yYXcvS2NvbmZpZwo+PiArKysgYi9kcml2ZXJzL210ZC9uYW5kL3Jh dy9LY29uZmlnCj4+IEBAIC00NTQsNiArNDU0LDE0IEBAIGNvbmZpZyBNVERfTkFORF9UUzcyWFgK Pj4gICAJaGVscAo+PiAgIAkgIEVuYWJsZXMgc3VwcG9ydCBmb3IgTkFORCBjb250cm9sbGVyIG9u IHRzNzJ4eCBTQkNzLgo+PiAgIAo+PiArY29uZmlnIE1URF9OQU5EX05VVk9UT05fTUEzNQo+PiAr CXRyaXN0YXRlICJOdXZvdG9uIE1BMzUgU29DIE5BTkQgY29udHJvbGxlciIKPj4gKwlkZXBlbmRz IG9uIEFSQ0hfTUEzNSB8fCBDT01QSUxFX1RFU1QKPj4gKwlkZXBlbmRzIG9uIE9GCj4+ICsJaGVs cAo+PiArCSAgRW5hYmxlcyBzdXBwb3J0IGZvciB0aGUgTkFORCBjb250cm9sbGVyIGZvdW5kIG9u Cj4+ICsJICB0aGUgTnV2b3RvbiBNQTM1IHNlcmllcyBTb0NzLgo+PiArCj4+ICAgY29tbWVudCAi TWlzYyIKPj4gICAKPj4gICBjb25maWcgTVREX1NNX0NPTU1PTgo+PiBkaWZmIC0tZ2l0IGEvZHJp dmVycy9tdGQvbmFuZC9yYXcvTWFrZWZpbGUgYi9kcml2ZXJzL210ZC9uYW5kL3Jhdy9NYWtlZmls ZQo+PiBpbmRleCBkMGIwZTZiODM1NjguLmNjMjQ5NTU2MjdmOCAxMDA2NDQKPj4gLS0tIGEvZHJp dmVycy9tdGQvbmFuZC9yYXcvTWFrZWZpbGUKPj4gKysrIGIvZHJpdmVycy9tdGQvbmFuZC9yYXcv TWFrZWZpbGUKPj4gQEAgLTU4LDYgKzU4LDcgQEAgb2JqLSQoQ09ORklHX01URF9OQU5EX0lOVEVM X0xHTSkJKz0gaW50ZWwtbmFuZC1jb250cm9sbGVyLm8KPj4gICBvYmotJChDT05GSUdfTVREX05B TkRfUk9DS0NISVApCQkrPSByb2NrY2hpcC1uYW5kLWNvbnRyb2xsZXIubwo+PiAgIG9iai0kKENP TkZJR19NVERfTkFORF9QTDM1WCkJCSs9IHBsMzV4LW5hbmQtY29udHJvbGxlci5vCj4+ICAgb2Jq LSQoQ09ORklHX01URF9OQU5EX1JFTkVTQVMpCQkrPSByZW5lc2FzLW5hbmQtY29udHJvbGxlci5v Cj4+ICtvYmotJChDT05GSUdfTVREX05BTkRfTlVWT1RPTl9NQTM1KQkrPSBudXZvdG9uX21hMzVk MV9uYW5kLm8KPj4gICAKPj4gICBuYW5kLW9ianMgOj0gbmFuZF9iYXNlLm8gbmFuZF9sZWdhY3ku byBuYW5kX2JidC5vIG5hbmRfdGltaW5ncy5vIG5hbmRfaWRzLm8KPj4gICBuYW5kLW9ianMgKz0g bmFuZF9vbmZpLm8KPj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbXRkL25hbmQvcmF3L251dm90b25f bWEzNWQxX25hbmQuYyBiL2RyaXZlcnMvbXRkL25hbmQvcmF3L251dm90b25fbWEzNWQxX25hbmQu Ywo+PiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+PiBpbmRleCAwMDAwMDAwMDAwMDAuLmVmZDYwNDkz ZjIyYQo+PiAtLS0gL2Rldi9udWxsCj4+ICsrKyBiL2RyaXZlcnMvbXRkL25hbmQvcmF3L251dm90 b25fbWEzNWQxX25hbmQuYwo+PiBAQCAtMCwwICsxLDg2MiBAQAo+PiArLy8gU1BEWC1MaWNlbnNl LUlkZW50aWZpZXI6IEdQTC0yLjAKPj4gKy8qCj4+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMjQgTnV2 b3RvbiBUZWNobm9sb2d5IENvcnAuCj4+ICsgKi8KPj4gKyNpbmNsdWRlIDxsaW51eC9jbGsuaD4K Pj4gKyNpbmNsdWRlIDxsaW51eC9kbWEtbWFwcGluZy5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2Vy ci5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9pbnRl cnJ1cHQuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9pby5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L2lv cG9sbC5oPgo+PiArI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+PiArI2luY2x1ZGUgPGxpbnV4 L210ZC9tdGQuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9tdGQvcGFydGl0aW9ucy5oPgo+PiArI2lu Y2x1ZGUgPGxpbnV4L210ZC9yYXduYW5kLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvb2YuaD4KPj4g KyNpbmNsdWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZpY2UuaD4KPj4gKyNpbmNsdWRlIDxsaW51eC9z bGFiLmg+Cj4+ICsKPj4gKy8qIE5GSSBSZWdpc3RlcnMgKi8KPj4gKyNkZWZpbmUgTUEzNV9ORklf UkVHX0RNQUNUTAkJMHg0MDAKPj4gKyNkZWZpbmUgICBETUFfRU4JCQkJQklUKDApCj4+ICsjZGVm aW5lICAgRE1BX1JTVAkJCQlCSVQoMSkKPj4gKyNkZWZpbmUgICBETUFfQlVTWQkJCQlCSVQoOSkK Pj4gKwo+PiArI2RlZmluZSBNQTM1X05GSV9SRUdfRE1BU0EJCTB4NDA4Cj4+ICsjZGVmaW5lIE1B MzVfTkZJX1JFR19HQ1RMCQkweDgwMAo+PiArI2RlZmluZSAgIE5BTkRfRU4JCQkJQklUKDMpCj4+ ICsKPj4gKyNkZWZpbmUgTUEzNV9ORklfUkVHX05BTkRDVEwJCTB4OEEwCj4+ICsjZGVmaW5lICAg U1dSU1QJCQkJQklUKDApCj4+ICsjZGVmaW5lICAgRE1BX1JfRU4JCQkJQklUKDEpCj4+ICsjZGVm aW5lICAgRE1BX1dfRU4JCQkJQklUKDIpCj4+ICsjZGVmaW5lICAgRUNDX0NISwkJCQlCSVQoNykK Pj4gKyNkZWZpbmUgICBQUk9UM0JFTgkJCQlCSVQoOCkKPj4gKyNkZWZpbmUgICBQU0laRV8ySwkJ CQlCSVQoMTYpCj4+ICsjZGVmaW5lICAgUFNJWkVfNEsJCQkJQklUKDE3KQo+PiArI2RlZmluZSAg IFBTSVpFXzhLCQkJCUdFTk1BU0soMTcsIDE2KQo+PiArI2RlZmluZSAgIFBTSVpFX01BU0sJCQkJ R0VOTUFTSygxNywgMTYpCj4+ICsjZGVmaW5lICAgQkNIX1QyNAkJCQlCSVQoMTgpCj4+ICsjZGVm aW5lICAgQkNIX1Q4CQkJCUJJVCgyMCkKPj4gKyNkZWZpbmUgICBCQ0hfVDEyCQkJCUJJVCgyMSkK Pj4gKyNkZWZpbmUgICBCQ0hfTk9ORQkJCQkoMHgwKQo+PiArI2RlZmluZSAgIEJDSF9NQVNLCQkJ CUdFTk1BU0soMjIsIDE4KQo+PiArI2RlZmluZSAgIEVDQ19FTgkJCQlCSVQoMjMpCj4+ICsjZGVm aW5lICAgRElTQUJMRV9DUzAJCQkJQklUKDI1KQo+PiArCj4+ICsjZGVmaW5lIE1BMzVfTkZJX1JF R19OQU5ESU5URU4JMHg4QTgKPj4gKyNkZWZpbmUgTUEzNV9ORklfUkVHX05BTkRJTlRTVFMJMHg4 QUMKPj4gKyNkZWZpbmUgICBJTlRfRE1BCQkJCUJJVCgwKQo+PiArI2RlZmluZSAgIElOVF9FQ0MJ CQkJQklUKDIpCj4+ICsjZGVmaW5lICAgSU5UX1JCMAkJCQlCSVQoMTApCj4+ICsjZGVmaW5lICAg SU5UX1JCMF9TVFMJCQkJQklUKDE4KQo+PiArCj4+ICsjZGVmaW5lIE1BMzVfTkZJX1JFR19OQU5E Q01ECQkweDhCMAo+PiArI2RlZmluZSBNQTM1X05GSV9SRUdfTkFOREFERFIJCTB4OEI0Cj4+ICsj ZGVmaW5lICAgRU5EQUREUgkJCQlCSVQoMzEpCj4+ICsKPj4gKyNkZWZpbmUgTUEzNV9ORklfUkVH X05BTkREQVRBCQkweDhCOAo+PiArI2RlZmluZSBNQTM1X05GSV9SRUdfTkFORFJBQ1RMCTB4OEJD Cj4+ICsjZGVmaW5lIE1BMzVfTkZJX1JFR19OQU5ERUNUTAkJMHg4QzAKPj4gKyNkZWZpbmUgICBF TkFCTEVfV1AJCQkJMHgwCj4+ICsjZGVmaW5lICAgRElTQUJMRV9XUAkJCQlCSVQoMCkKPj4gKwo+ PiArI2RlZmluZSBNQTM1X05GSV9SRUdfTkFOREVDQ0VTMAkweDhEMAo+PiArI2RlZmluZSAgIEVD Q19TVEFUVVNfTUFTSwkJCUdFTk1BU0soMSwgMCkKPj4gKyNkZWZpbmUgICBFQ0NfRVJSX0NOVF9N QVNLCQkJR0VOTUFTSyg0LCAwKQo+PiArCj4+ICsjZGVmaW5lIE1BMzVfTkZJX1JFR19OQU5ERUND RUEwCTB4OTAwCj4+ICsjZGVmaW5lIE1BMzVfTkZJX1JFR19OQU5ERUNDRUQwCTB4OTYwCj4+ICsj ZGVmaW5lIE1BMzVfTkZJX1JFR19OQU5EUkEwCQkweEEwMAo+PiArCj4+ICsvKiBEZWZpbmUgZm9y IHRoZSBCQ0ggaGFyZHdhcmUgRUNDIGVuZ2luZSAqLwo+PiArLyogZGVmaW5lIHRoZSB0b3RhbCBw YWRkaW5nIGJ5dGVzIGZvciA1MTIvMTAyNCBkYXRhIHNlZ21lbnQgKi8KPj4gKyNkZWZpbmUgTUEz NV9CQ0hfUEFERElOR181MTIJMzIKPj4gKyNkZWZpbmUgTUEzNV9CQ0hfUEFERElOR18xMDI0CTY0 Cj4+ICsvKiBkZWZpbmUgdGhlIEJDSCBwYXJpdHkgY29kZSBsZW5ndGggZm9yIDUxMiBieXRlcyBk YXRhIHBhdHRlcm4gKi8KPj4gKyNkZWZpbmUgTUEzNV9QQVJJVFlfQkNIOAkxNQo+PiArI2RlZmlu ZSBNQTM1X1BBUklUWV9CQ0gxMgkyMwo+PiArLyogZGVmaW5lIHRoZSBCQ0ggcGFyaXR5IGNvZGUg bGVuZ3RoIGZvciAxMDI0IGJ5dGVzIGRhdGEgcGF0dGVybiAqLwo+PiArI2RlZmluZSBNQTM1X1BB UklUWV9CQ0gyNAk0NQo+PiArCj4+ICtzdHJ1Y3QgbWEzNV9uYW5kX2luZm8gewo+PiArCXN0cnVj dCBuYW5kX2NvbnRyb2xsZXIgY29udHJvbGxlcjsKPj4gKwlzdHJ1Y3QgbmFuZF9jaGlwIGNoaXA7 Cj4+ICsJc3RydWN0IGRldmljZSAqZGV2Owo+PiArCXZvaWQgX19pb21lbSAqcmVnczsKPj4gKwlp bnQgaXJxOwo+PiArCXN0cnVjdCBjbGsgKmNsazsKPj4gKwlzdHJ1Y3QgY29tcGxldGlvbiBjb21w bGV0ZTsKPj4gKwl1MzIgYmNoOwo+PiArCXUzMiBiaXRmbGlwczsKPj4gKwl1OCAqZWNjX2J1ZjsK Pj4gK307Cj4+ICsKPj4gK3N0YXRpYyBpbnQgbWEzNV9vb2JsYXlvdXRfZWNjKHN0cnVjdCBtdGRf aW5mbyAqbXRkLCBpbnQgc2VjdGlvbiwKPj4gKwkJCSAgICAgIHN0cnVjdCBtdGRfb29iX3JlZ2lv biAqb29icmVnaW9uKQo+PiArewo+PiArCXN0cnVjdCBuYW5kX2NoaXAgKmNoaXAgPSBtdGRfdG9f bmFuZChtdGQpOwo+PiArCj4+ICsJaWYgKHNlY3Rpb24pCj4+ICsJCXJldHVybiAtRVJBTkdFOwo+ PiArCj4+ICsJb29icmVnaW9uLT5sZW5ndGggPSBjaGlwLT5lY2MudG90YWw7Cj4+ICsJb29icmVn aW9uLT5vZmZzZXQgPSBtdGQtPm9vYnNpemUgLSBvb2JyZWdpb24tPmxlbmd0aDsKPj4gKwo+PiAr CXJldHVybiAwOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW50IG1hMzVfb29ibGF5b3V0X2ZyZWUo c3RydWN0IG10ZF9pbmZvICptdGQsIGludCBzZWN0aW9uLAo+PiArCQkJICAgICAgIHN0cnVjdCBt dGRfb29iX3JlZ2lvbiAqb29icmVnaW9uKQo+PiArewo+PiArCXN0cnVjdCBuYW5kX2NoaXAgKmNo aXAgPSBtdGRfdG9fbmFuZChtdGQpOwo+PiArCj4+ICsJaWYgKHNlY3Rpb24pCj4+ICsJCXJldHVy biAtRVJBTkdFOwo+PiArCj4+ICsJb29icmVnaW9uLT5sZW5ndGggPSBtdGQtPm9vYnNpemUgLSBj aGlwLT5lY2MudG90YWwgLSAyOwo+PiArCW9vYnJlZ2lvbi0+b2Zmc2V0ID0gMjsKPj4gKwo+PiAr CXJldHVybiAwOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgY29uc3Qgc3RydWN0IG10ZF9vb2JsYXlv dXRfb3BzIG1hMzVfb29ibGF5b3V0X29wcyA9IHsKPj4gKwkuZnJlZSA9IG1hMzVfb29ibGF5b3V0 X2ZyZWUsCj4+ICsJLmVjYyA9IG1hMzVfb29ibGF5b3V0X2VjYywKPj4gK307Cj4+ICsKPj4gK3N0 YXRpYyBpbmxpbmUgdm9pZCBtYTM1X2NsZWFyX3NwYXJlKHN0cnVjdCBuYW5kX2NoaXAgKmNoaXAs IGludCBzaXplKQo+PiArewo+PiArCXN0cnVjdCBtYTM1X25hbmRfaW5mbyAqbmFuZCA9IG5hbmRf Z2V0X2NvbnRyb2xsZXJfZGF0YShjaGlwKTsKPj4gKwlpbnQgaTsKPj4gKwo+PiArCWZvciAoaSA9 IDA7IGkgPCBzaXplLzQ7IGkrKykKPiBTcGFjaW5nICAgICAgICAgICAgICAgICAgICBeCgpJIHdp bGwgY2hlY2sgYW5kIGZpeCBpdC4KCgo+PiArCQl3cml0ZWwoMHhmZiwgbmFuZC0+cmVncyArIE1B MzVfTkZJX1JFR19OQU5EUkEwKTsKPj4gK30KPj4gKwo+PiArc3RhdGljIGlubGluZSB2b2lkIHJl YWRfcmVtYWluaW5nX2J5dGVzKHN0cnVjdCBtYTM1X25hbmRfaW5mbyAqbmFuZCwgdTMyICpidWYs Cj4+ICsJCQkJCXUzMiBvZmZzZXQsIGludCBzaXplKQo+PiArewo+PiArCXUzMiB2YWx1ZSA9IHJl YWRsKG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORFJBMCArIG9mZnNldCk7Cj4+ICsJdTgg KnB0ciA9ICh1OCAqKWJ1ZjsKPj4gKwlpbnQgaTsKPj4gKwo+PiArCWZvciAoaSA9IDA7IGkgPCBz aXplOyBpKyspCj4+ICsJCXB0cltpXSA9ICh2YWx1ZSA+PiAoaSAqIDgpKSAmIDB4ZmY7Cj4+ICt9 Cj4+ICsKPj4gK3N0YXRpYyBpbmxpbmUgdm9pZCBtYTM1X3JlYWRfc3BhcmUoc3RydWN0IG5hbmRf Y2hpcCAqY2hpcCwgaW50IHNpemUsIHUzMiAqYnVmLCB1MzIgb2Zmc2V0KQo+PiArewo+PiArCXN0 cnVjdCBtYTM1X25hbmRfaW5mbyAqbmFuZCA9IG5hbmRfZ2V0X2NvbnRyb2xsZXJfZGF0YShjaGlw KTsKPj4gKwlpbnQgaSwgajsKPj4gKwo+PiArCWlmICgob2Zmc2V0ICUgNCkgPT0gMCkgewo+PiAr CQlmb3IgKGkgPSAwLCBqID0gMDsgaSA8IHNpemUgLyA0OyBpKyssIGogKz0gNCkKPj4gKwkJCSpi dWYrKyA9IHJlYWRsKG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORFJBMCArIG9mZnNldCAr IGopOwo+PiArCj4+ICsJCXJlYWRfcmVtYWluaW5nX2J5dGVzKG5hbmQsIGJ1Ziwgb2Zmc2V0ICsg aiwgc2l6ZSAlIDQpOwo+PiArCX0gZWxzZSB7Cj4+ICsJCXJlYWRfcmVtYWluaW5nX2J5dGVzKG5h bmQsIGJ1Ziwgb2Zmc2V0LCA0IC0gKG9mZnNldCAlIDQpKTsKPj4gKwkJb2Zmc2V0ICs9IDQ7Cj4+ ICsJCXNpemUgLT0gKDQgLSAob2Zmc2V0ICUgNCkpOwo+PiArCj4+ICsJCWZvciAoaSA9IDAsIGog PSAwOyBpIDwgc2l6ZSAvIDQ7IGkrKywgaiArPSA0KQo+PiArCQkJKmJ1ZisrID0gcmVhZGwobmFu ZC0+cmVncyArIE1BMzVfTkZJX1JFR19OQU5EUkEwICsgb2Zmc2V0ICsgaik7Cj4+ICsKPj4gKwkJ cmVhZF9yZW1haW5pbmdfYnl0ZXMobmFuZCwgYnVmLCBvZmZzZXQgKyBqLCBzaXplICUgNCk7Cj4+ ICsJfQo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW5saW5lIHZvaWQgbWEzNV93cml0ZV9zcGFyZShz dHJ1Y3QgbmFuZF9jaGlwICpjaGlwLCBpbnQgc2l6ZSwgdTMyICpidWYpCj4+ICt7Cj4+ICsJc3Ry dWN0IG1hMzVfbmFuZF9pbmZvICpuYW5kID0gbmFuZF9nZXRfY29udHJvbGxlcl9kYXRhKGNoaXAp Owo+PiArCXUzMiB2YWx1ZTsKPj4gKwlpbnQgaSwgajsKPj4gKwl1OCAqcHRyOwo+PiArCj4+ICsJ Zm9yIChpID0gMCwgaiA9IDA7IGkgPCBzaXplIC8gNDsgaSsrLCBqICs9IDQpCj4+ICsJCXdyaXRl bCgqYnVmKyssIG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORFJBMCArIGopOwo+PiArCj4+ ICsJcHRyID0gKHU4ICopYnVmOwo+PiArCXN3aXRjaCAoc2l6ZSAlIDQpIHsKPj4gKwljYXNlIDE6 Cj4+ICsJCXdyaXRlbCgqcHRyLCBuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRSQTAgKyBq KTsKPj4gKwkJYnJlYWs7Cj4+ICsJY2FzZSAyOgo+PiArCQl2YWx1ZSA9ICpwdHIgfCAoKihwdHIr MSkgPDwgOCk7Cj4+ICsJCXdyaXRlbCh2YWx1ZSwgbmFuZC0+cmVncyArIE1BMzVfTkZJX1JFR19O QU5EUkEwICsgaik7Cj4+ICsJCWJyZWFrOwo+PiArCWNhc2UgMzoKPj4gKwkJdmFsdWUgPSAqcHRy IHwgKCoocHRyKzEpIDw8IDgpIHwgKCoocHRyKzIpIDw8IDE2KTsKPj4gKwkJd3JpdGVsKHZhbHVl LCBuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRSQTAgKyBqKTsKPj4gKwkJYnJlYWs7Cj4+ ICsJZGVmYXVsdDoKPj4gKwkJYnJlYWs7Cj4+ICsJfQo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW5s aW5lIHZvaWQgbWEzNV9uYW5kX3RhcmdldF9lbmFibGUoc3RydWN0IG1hMzVfbmFuZF9pbmZvICpu YW5kKQo+PiArewo+PiArCXdyaXRlbChyZWFkbChuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05B TkRDVEwpICYgKH5ESVNBQkxFX0NTMCksCj4+ICsJCW5hbmQtPnJlZ3MrTUEzNV9ORklfUkVHX05B TkRDVEwpOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW5saW5lIHZvaWQgbWEzNV9uYW5kX3Rhcmdl dF9kaXNhYmxlKHN0cnVjdCBtYTM1X25hbmRfaW5mbyAqbmFuZCkKPj4gK3sKPj4gKwl3cml0ZWwo cmVhZGwobmFuZC0+cmVncyArIE1BMzVfTkZJX1JFR19OQU5EQ1RMKSB8IERJU0FCTEVfQ1MwLAo+ PiArCQluYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRDVEwpOwo+PiArfQo+PiArCj4+ICtz dGF0aWMgdm9pZCBtYTM1X25hbmRfaHdlY2NfaW5pdChzdHJ1Y3QgbWEzNV9uYW5kX2luZm8gKm5h bmQpCj4+ICt7Cj4+ICsJc3RydWN0IG10ZF9pbmZvICptdGQgPSBuYW5kX3RvX210ZCgmbmFuZC0+ Y2hpcCk7Cj4+ICsJdTMyIHJlZzsKPj4gKwo+PiArCS8qIHJlc2V0cyB0aGUgaW50ZXJuYWwgc3Rh dGUgbWFjaGluZSBhbmQgY291bnRlcnMKPiBQbGVhc2UgY2hlY2sgdGhlIHN0eWxlIGluIGFsbCB5 b3UgY29tbWVudHMuCj4KPiAJLyoKPiAJICogUmVzZXQgdGhlCgpJIHdpbGwgY2hlY2sgYW5kIGZp eCBhbGwuCgoKPj4gKwkgKiBUaGlzIGJpdCB3aWxsIGJlIGF1dG8gY2xlYXJlZCBhZnRlciBhIGZl dyBjbG9jayBjeWNsZXMuCj4+ICsJICovCj4+ICsJcmVnID0gcmVhZGwobmFuZC0+cmVncyArIE1B MzVfTkZJX1JFR19OQU5EQ1RMKTsKPj4gKwlyZWcgfD0gU1dSU1Q7Cj4+ICsJd3JpdGVsKHJlZywg bmFuZC0+cmVncyArIE1BMzVfTkZJX1JFR19OQU5EQ1RMKTsKPiBUaGlzIGhhcyBhIHdheSB3aWRl ciBpbXBhY3QgdGhhbiBqdXN0IGNvbmZpZ3VyaW5nIHRoZSBodyBFQ0MgZW5naW5lLAo+IG5vPyBB cmUgeW91IHN1cmUgeW91IHdhbnQgdG8gZG8gdGhpcyBub3c/IEkgYmVsaWV2ZSBpdCBzaG91bGQg YmUgaW4gaXRzCj4gb3duIGhlbHBlciwgYW5kIHlvdSB3YW50IHRvIGRvIGl0IGVhcmxpZXIgdGhh biB0aGF0LCBsaWtlIGJlZm9yZSB0aGUKPiBkaXNjb3Zlcnkgc3RlcCAoYW5kIGFsc28gaW4gdGhl IHJlc3VtZSBwYXRoKS4KCkkgY2FyZWZ1bGx5IGV4YW1pbmVkIG91ciBOQU5EIGNvbnRyb2xsZXIg YW5kIGZvdW5kIHRoYXQgdGhpcyBhY3Rpb24gaXMgCnVubmVjZXNzYXJ5LgoKSSB3aWxsIHJlbW92 ZSBpdC4KCgo+PiArCXdoaWxlIChyZWFkbChuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRD VEwpICYgU1dSU1QpCj4+ICsJCTsKPiBjcHVfcmVsYXgoKQoKSSB3aWxsIHJlbW92ZSB0aGlzIHdo aWxlLWxvb3AsIHNvIHRoaXMgQVBJIHdpbGwgbm90IGJlIGFkZGVkLgoKCj4+ICsKPj4gKwkvKiBS ZWR1bmRhbnQgYXJlYSBzaXplICovCj4+ICsJd3JpdGVsKG10ZC0+b29ic2l6ZSwgbmFuZC0+cmVn cyArIE1BMzVfTkZJX1JFR19OQU5EUkFDVEwpOwo+PiArCj4+ICsJLyogUHJvdGVjdCByZWR1bmRh bnQgMyBieXRlcyAqLwo+PiArCXJlZyA9IHJlYWRsKG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdf TkFORENUTCk7Cj4+ICsJcmVnIHw9IChQUk9UM0JFTiB8IEVDQ19DSEspOwo+PiArCXdyaXRlbChy ZWcsIG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORENUTCk7Cj4+ICsKPj4gKwlpZiAobmFu ZC0+YmNoID09IEJDSF9OT05FKSB7Cj4gUGxlYXNlIHVzZSB0aGUgZGVmaW5pdGlvbnMvY29uc3Rh bnRzIGZyb20gdGhlIGNvcmUuCgpXaWxsIHVzZSBlY2Muc3RyZW5ndGggaW5zdGVhZC4KCgo+PiAr CQkvKiBEaXNhYmxlIEgvVyBFQ0MsIEVDQyBwYXJpdHkgY2hlY2sgZW5hYmxlIGJpdCBkdXJpbmcg cmVhZCBwYWdlICovCj4+ICsJCXdyaXRlbChyZWFkbChuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVH X05BTkRDVEwpICYgKH5FQ0NfRU4pLAo+PiArCQkJbmFuZC0+cmVncyArIE1BMzVfTkZJX1JFR19O QU5EQ1RMKTsKPiBNb3ZlIHRoZSByZWFkbCBiZWZvcmUgdGhlIGlmIGFuZCBzYXZlIGl0IGluIHRo ZSByZWcgdmFyaWFibGUuCj4KPiBJbiBnZW5lcmFsIHBsZWFzZSBkbyBub3Qgb3ZlcmxvYWQgdGhl IGxpbmVzIGxpa2UgdGhhdCB3aGVuIGl0J3Mgbm90Cj4gbmVlZGVkLgoKSXQgd2lsbCBiZSBjaGFu Z2VkIHRvOgoKcmVnID0gcmVhZGwoKTsKCndyaXRlbCguLi4pOwoKCj4+ICsJfSBlbHNlIHsKPj4g KwkJLyogU2V0IEJDSCBhbGdvcml0aG0gKi8KPj4gKwkJd3JpdGVsKChyZWFkbChuYW5kLT5yZWdz ICsgTUEzNV9ORklfUkVHX05BTkRDVEwpICYgKH5CQ0hfTUFTSykpIHwKPiBQYXJlbnRoZXNpcyBh cmUgbm90IG5lZWRlZCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXgoK SSB3aWxsIHJlbW92ZSB0aGUgcGFyZW50aGVzZXMuCgoKPj4gKwkJCW5hbmQtPmJjaCwgbmFuZC0+ cmVncyArIE1BMzVfTkZJX1JFR19OQU5EQ1RMKTsKPj4gKwo+PiArCQkvKiBFbmFibGUgSC9XIEVD QywgRUNDIHBhcml0eSBjaGVjayBlbmFibGUgYml0IGR1cmluZyByZWFkIHBhZ2UgKi8KPj4gKwkJ d3JpdGVsKHJlYWRsKG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORENUTCkgfCBFQ0NfRU4s Cj4+ICsJCQluYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRDVEwpOwo+PiArCX0KPj4gK30K Pj4gKwo+PiArLyogQ29ycmVjdCBkYXRhIGJ5IEJDSCBhbHJvZ2l0aG0gKi8KPj4gK3N0YXRpYyB2 b2lkIG1hMzVfbmZpX2NvcnJlY3Qoc3RydWN0IG1hMzVfbmFuZF9pbmZvICpuYW5kLCB1OCBpbmRl eCwKPj4gKwkJCQkgdTggZXJyX2NudCwgdTggKmFkZHIpCj4+ICt7Cj4+ICsJdTMyIHRlbXBfZGF0 YVsyNF0sIHRlbXBfYWRkclsyNF07Cj4+ICsJdTMyIHBhZGRpbmdfbGVuLCBwYXJpdHlfbGVuOwo+ PiArCXUzMiB2YWx1ZSwgb2Zmc2V0LCByZW1haW47Cj4+ICsJdTMyIGVycl9kYXRhWzZdOwo+PiAr CXU4ICBpLCBqOwo+PiArCj4+ICsJLyogY29uZmlndXJhdGlvbnMgKi8KPj4gKwlzd2l0Y2ggKG5h bmQtPmJjaCkgewo+PiArCWNhc2UgQkNIX1QyNDoKPj4gKwkJcGFyaXR5X2xlbiA9IE1BMzVfUEFS SVRZX0JDSDI0Owo+PiArCQlwYWRkaW5nX2xlbiA9IE1BMzVfQkNIX1BBRERJTkdfMTAyNDsKPj4g KwkJYnJlYWs7Cj4+ICsJY2FzZSBCQ0hfVDEyOgo+PiArCQlwYXJpdHlfbGVuID0gTUEzNV9QQVJJ VFlfQkNIMTI7Cj4+ICsJCXBhZGRpbmdfbGVuID0gTUEzNV9CQ0hfUEFERElOR181MTI7Cj4+ICsJ CWJyZWFrOwo+PiArCWNhc2UgQkNIX1Q4Ogo+PiArCQlwYXJpdHlfbGVuID0gTUEzNV9QQVJJVFlf QkNIODsKPj4gKwkJcGFkZGluZ19sZW4gPSBNQTM1X0JDSF9QQURESU5HXzUxMjsKPj4gKwkJYnJl YWs7Cj4+ICsJZGVmYXVsdDoKPj4gKwkJZGV2X3dhcm4obmFuZC0+ZGV2LCAiTkFORCBFUlJPUjog aW52YWxpZCBTTUNSX0JDSF9UU0VMID0gMHglMDhYXG4iLAo+PiArCQkJKHUzMikocmVhZGwobmFu ZC0+cmVncyArIE1BMzVfTkZJX1JFR19OQU5EQ1RMKSAmIEJDSF9NQVNLKSk7Cj4+ICsJCXJldHVy bjsKPj4gKwl9Cj4+ICsKPj4gKwkvKiBnb3QgdmFsaWQgQkNIX0VDQ19EQVRBeCBhbmQgcGFyc2Ug dGhlbSB0byB0ZW1wX2RhdGFbXQo+PiArCSAqIGdvdCB0aGUgdmFsaWQgcmVnaXN0ZXIgbnVtYmVy IG9mIEJDSF9FQ0NfREFUQXggc2luY2UKPj4gKwkgKiBvbmUgcmVnaXN0ZXIgaW5jbHVkZSA0IGVy cm9yIGJ5dGVzCj4+ICsJICovCj4+ICsJaiA9IChlcnJfY250ICsgMykgLyA0Owo+PiArCWogPSAo aiA+IDYpID8gNiA6IGo7Cj4+ICsJZm9yIChpID0gMDsgaSA8IGo7IGkrKykKPj4gKwkJZXJyX2Rh dGFbaV0gPSByZWFkbChuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRFQ0NFRDAgKyBpICog NCk7Cj4+ICsKPj4gKwlmb3IgKGkgPSAwOyBpIDwgajsgaSsrKSB7Cj4+ICsJCXRlbXBfZGF0YVtp KjQrMF0gPSBlcnJfZGF0YVtpXSAmIDB4ZmY7Cj4+ICsJCXRlbXBfZGF0YVtpKjQrMV0gPSAoZXJy X2RhdGFbaV0gPj4gOCkgJiAweGZmOwo+PiArCQl0ZW1wX2RhdGFbaSo0KzJdID0gKGVycl9kYXRh W2ldID4+IDE2KSAmIDB4ZmY7Cj4+ICsJCXRlbXBfZGF0YVtpKjQrM10gPSAoZXJyX2RhdGFbaV0g Pj4gMjQpICYgMHhmZjsKPj4gKwl9Cj4+ICsKPj4gKwkvKiBnb3QgdmFsaWQgUkVHX0JDSF9FQ0Nf QUREUnggYW5kIHBhcnNlIHRoZW0gdG8gdGVtcF9hZGRyW10KPj4gKwkgKiBnb3QgdGhlIHZhbGlk IHJlZ2lzdGVyIG51bWJlciBvZiBSRUdfQkNIX0VDQ19BRERSeCBzaW5jZQo+PiArCSAqIG9uZSBy ZWdpc3RlciBpbmNsdWRlIDIgZXJyb3IgYWRkcmVzc2VzCj4+ICsJICovCj4+ICsJaiA9IChlcnJf Y250ICsgMSkgLyAyOwo+PiArCWogPSAoaiA+IDEyKSA/IDEyIDogajsKPj4gKwlmb3IgKGkgPSAw OyBpIDwgajsgaSsrKSB7Cj4+ICsJCXRlbXBfYWRkcltpKjIrMF0gPSByZWFkbChuYW5kLT5yZWdz ICsgTUEzNV9ORklfUkVHX05BTkRFQ0NFQTAgKyBpICogNCkKPj4gKwkJCQkJJiAweDA3ZmY7Cj4+ ICsJCXRlbXBfYWRkcltpKjIrMV0gPSAocmVhZGwobmFuZC0+cmVncyArIE1BMzVfTkZJX1JFR19O QU5ERUNDRUEwICsgaSAqIDQpCj4+ICsJCQkJCT4+IDE2KSAmIDB4MDdmZjsKPj4gKwl9Cj4+ICsK Pj4gKwkvKiBwb2ludGVyIHRvIGJlZ2luIGFkZHJlc3Mgb2YgZmllbGQgdGhhdCB3aXRoIGRhdGEg ZXJyb3IgKi8KPj4gKwlhZGRyICs9IGluZGV4ICogbmFuZC0+Y2hpcC5lY2Muc3RlcHM7Cj4+ICsK Pj4gKwkvKiBjb3JyZWN0IGVhY2ggZXJyb3IgYnl0ZXMgKi8KPj4gKwlmb3IgKGkgPSAwOyBpIDwg ZXJyX2NudDsgaSsrKSB7Cj4+ICsJCXUzMiBjb3JyZWN0ZWRfaW5kZXggPSB0ZW1wX2FkZHJbaV07 Cj4+ICsKPj4gKwkJLyogZm9yIHdyb25nIGRhdGEgaW4gZmllbGQgKi8KPj4gKwkJaWYgKGNvcnJl Y3RlZF9pbmRleCA8IG5hbmQtPmNoaXAuZWNjLnN0ZXBzKQo+PiArCQkJKihhZGRyICsgY29ycmVj dGVkX2luZGV4KSBePSB0ZW1wX2RhdGFbaV07Cj4+ICsKPj4gKwkJLyogZm9yIHdyb25nIGZpcnN0 LTMtYnl0ZXMgaW4gcmVkdW5kYW5jeSBhcmVhICovCj4+ICsJCWVsc2UgaWYgKGNvcnJlY3RlZF9p bmRleCA8IChuYW5kLT5jaGlwLmVjYy5zdGVwcyArIDMpKSB7Cj4+ICsJCQljb3JyZWN0ZWRfaW5k ZXggLT0gbmFuZC0+Y2hpcC5lY2Muc3RlcHM7Cj4+ICsJCQl0ZW1wX2FkZHJbaV0gKz0gKHBhcml0 eV9sZW4gKiBpbmRleCk7CS8qIGZpZWxkIG9mZnNldCAqLwo+PiArCj4+ICsJCQl2YWx1ZSA9IHJl YWRsKG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORFJBMCk7Cj4+ICsJCQl2YWx1ZSBePSB0 ZW1wX2RhdGFbaV0gPDwgKDggKiBjb3JyZWN0ZWRfaW5kZXgpOwo+PiArCQkJd3JpdGVsKHZhbHVl LCBuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRSQTApOwo+PiArCQl9Cj4+ICsJCS8qIGZv ciB3cm9uZyBwYXJpdHkgY29kZSBpbiByZWR1bmRhbmN5IGFyZWEKPj4gKwkJICogQkNIX0VSUl9B RERSeCA9IFtkYXRhIGluIGZpZWxkXSArIFszIGJ5dGVzXSArIFt4eF0gKyBbcGFyaXR5IGNvZGVd Cj4+ICsJCSAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8PC0tICAgICBwYWRk aW5nIGJ5dGVzICAgICAgLS0+fAo+PiArCQkgKiBUaGUgQkNIX0VSUl9BRERSeCBmb3IgbGFzdCBw YXJpdHkgY29kZSBhbHdheXMgPSBmaWVsZCBzaXplICsgcGFkZGluZyBzaXplLgo+PiArCQkgKiBT bywgdGhlIGZpcnN0IHBhcml0eSBjb2RlID0gZmllbGQgc2l6ZSArIHBhZGRpbmcgc2l6ZSAtIHBh cml0eSBjb2RlIGxlbmd0aC4KPj4gKwkJICogRm9yIGV4YW1wbGUsIGZvciBCQ0ggVDEyLCB0aGUg Zmlyc3QgcGFyaXR5IGNvZGUgPSA1MTIgKyAzMiAtIDIzID0gNTIxLgo+PiArCQkgKiBUaGF0IGlz LCBlcnJvciBieXRlIGFkZHJlc3Mgb2Zmc2V0IHdpdGhpbiBmaWVsZCBpcwo+PiArCQkgKi8KPj4g KwkJZWxzZSB7Cj4+ICsJCQljb3JyZWN0ZWRfaW5kZXggLT0gKG5hbmQtPmNoaXAuZWNjLnN0ZXBz ICsgcGFkZGluZ19sZW4gLSBwYXJpdHlfbGVuKTsKPj4gKwo+PiArCQkJLyogZmluYWwgYWRkcmVz cyA9IGZpcnN0IHBhcml0eSBjb2RlIG9mIGZpcnN0IGZpZWxkICsKPj4gKwkJCSAqICAgICAgICAg ICAgICAgICBvZmZzZXQgb2YgZmllbGRzICsKPj4gKwkJCSAqICAgICAgICAgICAgICAgICBvZmZz ZXQgd2l0aGluIGZpZWxkCj4+ICsJCQkgKi8KPj4gKwkJCW9mZnNldCA9IChyZWFkbChuYW5kLT5y ZWdzICsgTUEzNV9ORklfUkVHX05BTkRSQUNUTCkgJiAweDFmZikgLQo+PiArCQkJCShwYXJpdHlf bGVuICogbmFuZC0+Y2hpcC5lY2Muc3RlcHMpICsKPj4gKwkJCQkocGFyaXR5X2xlbiAqIGluZGV4 KSArIGNvcnJlY3RlZF9pbmRleDsKPj4gKwo+PiArCQkJcmVtYWluID0gb2Zmc2V0ICUgNDsKPj4g KwkJCXZhbHVlID0gcmVhZGwobmFuZC0+cmVncyArIE1BMzVfTkZJX1JFR19OQU5EUkEwICsgb2Zm c2V0IC0gcmVtYWluKTsKPj4gKwkJCXZhbHVlIF49IHRlbXBfZGF0YVtpXSA8PCAoOCAqIHJlbWFp bik7Cj4+ICsJCQl3cml0ZWwodmFsdWUsIG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORFJB MCArIG9mZnNldCAtIHJlbWFpbik7Cj4+ICsJCX0KPj4gKwl9Cj4+ICt9Cj4+ICsKPj4gK3N0YXRp YyBpbnQgbWEzNV9uZmlfZWNjX2NoZWNrKHN0cnVjdCBuYW5kX2NoaXAgKmNoaXAsIHU4ICphZGRy KQo+PiArewo+PiArCXN0cnVjdCBtYTM1X25hbmRfaW5mbyAqbmFuZCA9IG5hbmRfZ2V0X2NvbnRy b2xsZXJfZGF0YShjaGlwKTsKPj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IG5hbmRfdG9fbXRk KGNoaXApOwo+PiArCWludCBpLCBqLCBuY2h1bmtzID0gMDsKPj4gKwlpbnQgcmVwb3J0X2VyciA9 IDA7Cj4+ICsJaW50IGVycl9jbnQgPSAwOwo+PiArCXUzMiBzdGF0dXM7Cj4+ICsKPj4gKwluY2h1 bmtzID0gbXRkLT53cml0ZXNpemUgLyBjaGlwLT5lY2Muc3RlcHM7Cj4+ICsJaWYgKG5jaHVua3Mg PCA0KQo+PiArCQluY2h1bmtzID0gMTsKPj4gKwllbHNlCj4+ICsJCW5jaHVua3MgLz0gNDsKPj4g Kwo+PiArCWZvciAoaiA9IDA7IGogPCBuY2h1bmtzOyBqKyspIHsKPj4gKwkJc3RhdHVzID0gcmVh ZGwobmFuZC0+cmVncyArIE1BMzVfTkZJX1JFR19OQU5ERUNDRVMwICsgaiAqIDQpOwo+PiArCQlp ZiAoIXN0YXR1cykKPj4gKwkJCWNvbnRpbnVlOwo+PiArCj4+ICsJCWZvciAoaSA9IDA7IGkgPCA0 OyBpKyspIHsKPj4gKwkJCWlmICghKHN0YXR1cyAmIEVDQ19TVEFUVVNfTUFTSykpIHsKPj4gKwkJ CQkvKiBObyBlcnJvciAqLwo+PiArCQkJCXN0YXR1cyA+Pj0gODsKPj4gKwkJCQljb250aW51ZTsK PiBSZW1vdmUgdGhpcyBibG9jaywgaXQgd2lsbCBkbyB0aGUgc2FtZSBhbmQgYmUgbW9yZSBjbGVh ci4KCkluZGVlZCwgdGhpcyBpcyB1bm5lY2Vzc2FyeS4gSSB3aWxsIHJlbW92ZSBpdC4KCgo+PiAr CQkJfSBlbHNlIGlmICgoc3RhdHVzICYgRUNDX1NUQVRVU19NQVNLKSA9PSAweDAxKSB7Cj4+ICsJ CQkJLyogQ29ycmVjdGFibGUgZXJyb3IgKi8KPj4gKwkJCQllcnJfY250ID0gKHN0YXR1cyA+PiAy KSAmIEVDQ19FUlJfQ05UX01BU0s7Cj4+ICsJCQkJbWEzNV9uZmlfY29ycmVjdChuYW5kLCBqKjQr aSwgZXJyX2NudCwgYWRkcik7Cj4gU3BhY2luZyAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgXl5eXl5eCgpJIHdpbGwgY2hlY2sgYW5kIGZpeCBpdC4KCgo+PiAr CQkJCXJlcG9ydF9lcnIgKz0gZXJyX2NudDsKPj4gKwkJCX0gZWxzZSB7Cj4+ICsJCQkJLyogdW5j b3JyZWN0YWJsZSBlcnJvciAqLwo+PiArCQkJCWRldl93YXJuKG5hbmQtPmRldiwgInVuY29ycmVj dGFibGUgZXJyb3IhIDB4JTR4XG4iLCBzdGF0dXMpOwo+PiArCQkJCXJldHVybiAtMTsKPiBOb3Qg YSB2YWxpZCBlcnJvciBjb2RlCgpJIHdpbGwgY2hhbmdlIGl0IHRvIHJldHVybiAtRUJBRE1TRzsK Cgo+PiArCQkJfQo+PiArCQkJc3RhdHVzID4+PSA4Owo+PiArCQl9Cj4+ICsJfQo+PiArCXJldHVy biByZXBvcnRfZXJyOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgdm9pZCBtYTM1X25hbmRfZG1hY19p bml0KHN0cnVjdCBtYTM1X25hbmRfaW5mbyAqbmFuZCkKPj4gK3sKPj4gKwkvKiBETUFDIHJlc2V0 IGFuZCBlbmFibGUgKi8KPj4gKwl3cml0ZWwoRE1BX1JTVCB8IERNQV9FTiwgbmFuZC0+cmVncyAr IE1BMzVfTkZJX1JFR19ETUFDVEwpOwo+PiArCXdyaXRlbChETUFfRU4sIG5hbmQtPnJlZ3MgKyBN QTM1X05GSV9SRUdfRE1BQ1RMKTsKPj4gKwo+PiArCS8qIENsZWFyIERNQSBmaW5pc2hlZCBmbGFn ICovCj4+ICsJd3JpdGVsKElOVF9ETUEgfCBJTlRfRUNDLCBuYW5kLT5yZWdzICsgTUEzNV9ORklf UkVHX05BTkRJTlRTVFMpOwo+PiArCj4+ICsJaW5pdF9jb21wbGV0aW9uKCZuYW5kLT5jb21wbGV0 ZSk7Cj4gWW91J3JlIGdvbm5hIGNhbGwgaW5pdF9jb21wbGV0aW9uIG1vcmUgdGhhbiBvbmNlIGR1 cmluZyBzdXNwZW5kL3Jlc3VtZQo+IGN5Y2xlcywgdGhpcyBpcyB1bnNhZmUuCgpJIHdpbGwgbW92 ZSBpbml0X2NvbXBsZXRpb24gdG8gcHJvYmUsIGFuZCB0aGVuIGFkZCByZWluaXRfY29tcGxldGlv biBpbiAKdGhlIHJlYWQvd3JpdGUgcGFnZS4KCgo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW50IG1h MzVfbmFuZF9kb193cml0ZShzdHJ1Y3QgbmFuZF9jaGlwICpjaGlwLCBjb25zdCB1OCAqYWRkciwg dTMyIGxlbikKPj4gK3sKPj4gKwlzdHJ1Y3QgbWEzNV9uYW5kX2luZm8gKm5hbmQgPSBuYW5kX2dl dF9jb250cm9sbGVyX2RhdGEoY2hpcCk7Cj4+ICsJc3RydWN0IG10ZF9pbmZvICptdGQgPSBuYW5k X3RvX210ZChjaGlwKTsKPj4gKwlkbWFfYWRkcl90IGRtYV9hZGRyOwo+PiArCWludCByZXQgPSAw LCBpOwo+PiArCXUzMiByZWc7Cj4+ICsKPj4gKwlpZiAobGVuICE9IG10ZC0+d3JpdGVzaXplKSB7 Cj4+ICsJCWZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykKPj4gKwkJCXdyaXRlbChhZGRyW2ldLCBu YW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkREQVRBKTsKPj4gKwkJcmV0dXJuIDA7Cj4+ICsJ fQo+PiArCj4+ICsJbWEzNV9uYW5kX2RtYWNfaW5pdChuYW5kKTsKPj4gKwo+PiArCXdyaXRlbCht dGQtPm9vYnNpemUsIG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORFJBQ1RMKTsKPj4gKwo+ PiArCXdyaXRlbChJTlRfRE1BLCBuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRJTlRFTik7 Cj4+ICsJLyogVG8gbWFyayB0aGlzIHBhZ2UgYXMgZGlydHkuICovCj4+ICsJcmVnID0gcmVhZGwo bmFuZC0+cmVncyArIE1BMzVfTkZJX1JFR19OQU5EUkEwKTsKPj4gKwlpZiAocmVnICYgMHhmZmZm MDAwMCkKPj4gKwkJd3JpdGVsKHJlZyAmIDB4ZmZmZiwgbmFuZC0+cmVncyArIE1BMzVfTkZJX1JF R19OQU5EUkEwKTsKPj4gKwo+PiArCWRtYV9hZGRyID0gZG1hX21hcF9zaW5nbGUobmFuZC0+ZGV2 LCAodm9pZCAqKWFkZHIsIGxlbiwgRE1BX1RPX0RFVklDRSk7Cj4+ICsJcmV0ID0gZG1hX21hcHBp bmdfZXJyb3IobmFuZC0+ZGV2LCBkbWFfYWRkcik7Cj4+ICsJaWYgKHJldCkgewo+PiArCQlkZXZf ZXJyKG5hbmQtPmRldiwgImRtYSBtYXBwaW5nIGVycm9yXG4iKTsKPj4gKwkJcmV0dXJuIC1FSU5W QUw7Cj4+ICsJfQo+PiArCWRtYV9zeW5jX3NpbmdsZV9mb3JfZGV2aWNlKG5hbmQtPmRldiwgZG1h X2FkZHIsIGxlbiwgRE1BX1RPX0RFVklDRSk7Cj4+ICsKPj4gKwl3cml0ZWwoKHVuc2lnbmVkIGxv bmcpZG1hX2FkZHIsIG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfRE1BU0EpOwo+PiArCXdyaXRl bChyZWFkbChuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRDVEwpIHwgRE1BX1dfRU4sCj4+ ICsJCW5hbmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORENUTCk7Cj4+ICsJcmV0ID0gd2FpdF9m b3JfY29tcGxldGlvbl90aW1lb3V0KCZuYW5kLT5jb21wbGV0ZSwgbXNlY3NfdG9famlmZmllcygx MDAwKSk7Cj4+ICsJaWYgKCFyZXQpIHsKPj4gKwkJZGV2X2VycihuYW5kLT5kZXYsICJ3cml0ZSB0 aW1lb3V0XG4iKTsKPj4gKwkJcmV0ID0gLUVUSU1FRE9VVDsKPj4gKwl9Cj4+ICsKPj4gKwlkbWFf dW5tYXBfc2luZ2xlKG5hbmQtPmRldiwgZG1hX2FkZHIsIGxlbiwgRE1BX1RPX0RFVklDRSk7Cj4+ ICsKPj4gKwlyZXR1cm4gcmV0Owo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW50IG1hMzVfbmFuZF9k b19yZWFkKHN0cnVjdCBuYW5kX2NoaXAgKmNoaXAsIHU4ICphZGRyLCB1MzIgbGVuKQo+PiArewo+ PiArCXN0cnVjdCBtYTM1X25hbmRfaW5mbyAqbmFuZCA9IG5hbmRfZ2V0X2NvbnRyb2xsZXJfZGF0 YShjaGlwKTsKPj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IG5hbmRfdG9fbXRkKGNoaXApOwo+ PiArCWludCByZXQgPSAwLCBjbnQgPSAwLCBpOwo+PiArCWRtYV9hZGRyX3QgZG1hX2FkZHI7Cj4+ ICsJdTMyIHJlZzsKPj4gKwo+PiArCWlmIChsZW4gIT0gbXRkLT53cml0ZXNpemUpIHsKPj4gKwkJ Zm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKQo+PiArCQkJKihhZGRyK2kpID0gKHU4KXJlYWRsKG5h bmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORERBVEEpOwo+IE1taCwgdGhhdCBsaW5lIGlzIHN0 cmFuZ2UuIFBsZWFzZSBkb24ndCBkbyB0aGF0Lgo+Cj4gCQkJYWRkcltpXSA9IHJlYWRiKCkgPwoK SXQgd2lsbCBiZSBmaXhlZCB0byByZWFkYigpLgoKCj4+ICsJCXJldHVybiAwOwo+PiArCX0KPj4g Kwo+PiArCW1hMzVfbmFuZF9kbWFjX2luaXQobmFuZCk7Cj4+ICsKPj4gKwl3cml0ZWwobXRkLT5v b2JzaXplLCBuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRSQUNUTCk7Cj4+ICsKPj4gKwkv KiBzZXR1cCBhbmQgc3RhcnQgRE1BIHVzaW5nIGRtYV9hZGRyICovCj4+ICsJZG1hX2FkZHIgPSBk bWFfbWFwX3NpbmdsZShuYW5kLT5kZXYsICh2b2lkICopYWRkciwgbGVuLCBETUFfRlJPTV9ERVZJ Q0UpOwo+PiArCXJldCA9IGRtYV9tYXBwaW5nX2Vycm9yKG5hbmQtPmRldiwgZG1hX2FkZHIpOwo+ PiArCWlmIChyZXQpIHsKPj4gKwkJZGV2X2VycihuYW5kLT5kZXYsICJkbWEgbWFwcGluZyBlcnJv clxuIik7Cj4+ICsJCXJldHVybiAtRUlOVkFMOwo+PiArCX0KPj4gKwo+PiArCXdyaXRlbCgodW5z aWduZWQgbG9uZylkbWFfYWRkciwgbmFuZC0+cmVncyArIE1BMzVfTkZJX1JFR19ETUFTQSk7Cj4g UGxlYXNlIGVuZm9yY2UgYSBkbWEgbWFzayBvZiAzMiAoZXZlbiB0aG91Z2ggaXQgbWlnaHQgYmUg dGhlIGZhdWx0KS4KCkkgd2lsbCBjaGFuZ2UgaXQgdG8gZG1hX2FkZHIgJiAweGZmZmZmZmZmLgoK Cj4+ICsJd3JpdGVsKHJlYWRsKG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORENUTCkgfCBE TUFfUl9FTiwKPj4gKwkJbmFuZC0+cmVncyArIE1BMzVfTkZJX1JFR19OQU5EQ1RMKTsKPj4gKwly ZXQgPSB3YWl0X2Zvcl9jb21wbGV0aW9uX3RpbWVvdXQoJm5hbmQtPmNvbXBsZXRlLCBtc2Vjc190 b19qaWZmaWVzKDEwMDApKTsKPj4gKwlpZiAoIXJldCkgewo+PiArCQlkZXZfZXJyKG5hbmQtPmRl diwgInJlYWQgdGltZW91dFxuIik7Cj4+ICsJCXJldCA9IC1FVElNRURPVVQ7Cj4+ICsJfQo+PiAr Cj4+ICsJZG1hX3VubWFwX3NpbmdsZShuYW5kLT5kZXYsIGRtYV9hZGRyLCBsZW4sIERNQV9GUk9N X0RFVklDRSk7Cj4+ICsKPj4gKwlyZWcgPSByZWFkbChuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVH X05BTkRJTlRTVFMpOwo+PiArCWlmIChyZWcgJiBJTlRfRUNDKSB7Cj4+ICsJCWNudCA9IG1hMzVf bmZpX2VjY19jaGVjaygmbmFuZC0+Y2hpcCwgYWRkcik7Cj4+ICsJCWlmIChjbnQgPCAwKSB7Cj4+ ICsJCQltdGQtPmVjY19zdGF0cy5mYWlsZWQrKzsKPj4gKwkJCXdyaXRlbChETUFfUlNUIHwgRE1B X0VOLCBuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX0RNQUNUTCk7Cj4+ICsJCQl3cml0ZWwocmVh ZGwobmFuZC0+cmVncyArIE1BMzVfTkZJX1JFR19OQU5EQ1RMKSB8IFNXUlNULAo+PiArCQkJCW5h bmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORENUTCk7Cj4+ICsJCX0gZWxzZSB7Cj4+ICsJCQlt dGQtPmVjY19zdGF0cy5jb3JyZWN0ZWQgKz0gY250Owo+PiArCQkJbmFuZC0+Yml0ZmxpcHMgPSBj bnQ7Cj4+ICsJCX0KPj4gKwkJd3JpdGVsKElOVF9FQ0MsIG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9S RUdfTkFORElOVFNUUyk7Cj4+ICsJfQo+PiArCj4+ICsJcmV0dXJuIHJldDsKPj4gK30KPj4gKwo+ PiArc3RhdGljIGludCBtYTM1X25hbmRfd3JpdGVfcGFnZV9od2VjYyhzdHJ1Y3QgbmFuZF9jaGlw ICpjaGlwLCBjb25zdCB1OCAqYnVmLAo+PiArCQkJCSAgICAgIGludCBvb2JfcmVxdWlyZWQsIGlu dCBwYWdlKQo+PiArewo+PiArCXN0cnVjdCBtdGRfaW5mbyAqbXRkID0gbmFuZF90b19tdGQoY2hp cCk7Cj4+ICsJdm9pZCAqZWNjX2NhbGMgPSBjaGlwLT5lY2MuY2FsY19idWY7Cj4+ICsKPj4gKwlt YTM1X2NsZWFyX3NwYXJlKGNoaXAsIG10ZC0+b29ic2l6ZSk7Cj4+ICsJbWEzNV93cml0ZV9zcGFy ZShjaGlwLCBtdGQtPm9vYnNpemUgLSBjaGlwLT5lY2MudG90YWwsCj4+ICsJCQkodTMyICopY2hp cC0+b29iX3BvaSk7Cj4+ICsKPj4gKwluYW5kX3Byb2dfcGFnZV9iZWdpbl9vcChjaGlwLCBwYWdl LCAwLCBidWYsIG10ZC0+d3JpdGVzaXplKTsKPj4gKwluYW5kX3Byb2dfcGFnZV9lbmRfb3AoY2hp cCk7Cj4+ICsKPj4gKwkvKiBDb3B5IHBhcml0eSBjb2RlIGluIE5BTkRSQSB0byBjYWxjICovCj4+ ICsJbWEzNV9yZWFkX3NwYXJlKGNoaXAsIGNoaXAtPmVjYy50b3RhbCwgKHUzMiAqKWVjY19jYWxj LAo+PiArCQkJbXRkLT5vb2JzaXplIC0gY2hpcC0+ZWNjLnRvdGFsKTsKPj4gKwo+PiArCS8qIENv cHkgcGFyaXR5IGNvZGUgaW4gY2FsYyB0byBvb2JfcG9pICovCj4+ICsJbWVtY3B5KGNoaXAtPm9v Yl9wb2kgKyAobXRkLT5vb2JzaXplIC0gY2hpcC0+ZWNjLnRvdGFsKSwKPj4gKwkJZWNjX2NhbGMs IGNoaXAtPmVjYy50b3RhbCk7Cj4+ICsKPj4gKwlyZXR1cm4gMDsKPj4gK30KPj4gKwo+PiArc3Rh dGljIGludCBtYTM1X25hbmRfcmVhZF9wYWdlX2h3ZWNjKHN0cnVjdCBuYW5kX2NoaXAgKmNoaXAs IHU4ICpidWYsCj4+ICsJCQkJCWludCBvb2JfcmVxdWlyZWQsIGludCBwYWdlKQo+PiArewo+PiAr CXN0cnVjdCBtYTM1X25hbmRfaW5mbyAqbmFuZCA9IG5hbmRfZ2V0X2NvbnRyb2xsZXJfZGF0YShj aGlwKTsKPj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IG5hbmRfdG9fbXRkKGNoaXApOwo+PiAr CXUzMiByZWc7Cj4+ICsKPj4gKwkvKiByZWFkIHRoZSBPT0IgYXJlYSAgKi8KPj4gKwluYW5kX3Jl YWRfb29iX29wKGNoaXAsIHBhZ2UsIDAsIGNoaXAtPm9vYl9wb2ksIG10ZC0+b29ic2l6ZSk7Cj4+ ICsJbmFuZC0+Yml0ZmxpcHMgPSAwOwo+IFdoeSBzdG9yaW5nIHRoaXMgdmFsdWUgaW4geW91ciBz dHJ1Y3R1cmU/CgpCZWNhdXNlIGVjYy5yZWFkX3BhZ2UgbmVlZHMgdG8gcmV0dXJuIGJpdCBmbGlw cywgaXQgaXMgbmVjZXNzYXJ5IHRvIGxvZyAKdGhlbS4KCgo+PiArCj4+ICsJLyogY29weSBPT0Ig ZGF0YSB0byBOQU5EUkEgZm9yIHBhZ2UgcmVhZCAqLwo+PiArCW1hMzVfd3JpdGVfc3BhcmUoY2hp cCwgbXRkLT5vb2JzaXplLCAodTMyICopY2hpcC0+b29iX3BvaSk7Cj4+ICsKPj4gKwlyZWcgPSBy ZWFkbChuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRSQTApOwo+PiArCWlmIChyZWcgJiAw eGZmZmYwMDAwKSB7Cj4+ICsJCW1lbXNldCgodm9pZCAqKWJ1ZiwgMHhmZiwgbXRkLT53cml0ZXNp emUpOwo+PiArCX0gZWxzZSB7Cj4+ICsJCS8qIHJlYWQgZGF0YSBmcm9tIG5hbmQgKi8KPj4gKwkJ bmFuZF9yZWFkX3BhZ2Vfb3AoY2hpcCwgcGFnZSwgMCwgYnVmLCBtdGQtPndyaXRlc2l6ZSk7Cj4g cmV0ID0KPiBpZiAocmV0KQo+IAkuLi4KCkkgd2lsbCBhZGQgYSByZXR1cm4gdmFsdWUgaGVyZS4K Cgo+PiArCj4+ICsJCS8qIHJlc3RvcmUgT09CIGRhdGEgZnJvbSBTTVJBICovCj4+ICsJCW1hMzVf cmVhZF9zcGFyZShjaGlwLCBtdGQtPm9vYnNpemUsICh1MzIgKiljaGlwLT5vb2JfcG9pLCAwKTsK Pgo+IHNhbWUKCm1hMzVfcmVhZF9zcGFyZSgpIGlzIGRlY2xhcmVkIGFzIHZvaWQsIHdpdGggbm8g cmV0dXJuIHZhbHVlLgoKU01SQSB3aWxsIGJlIGNoYW5nZWQgdG8gTkFORFJBIHJlZ2lzdGVycy4K Cgo+PiArCX0KPj4gKwo+PiArCXJldHVybiBuYW5kLT5iaXRmbGlwczsKPj4gK30KPj4gKwo+PiAr c3RhdGljIGludCBtYTM1X25hbmRfcmVhZF9vb2JfaHdlY2Moc3RydWN0IG5hbmRfY2hpcCAqY2hp cCwgaW50IHBhZ2UpCj4+ICt7Cj4+ICsJc3RydWN0IG1hMzVfbmFuZF9pbmZvICpuYW5kID0gbmFu ZF9nZXRfY29udHJvbGxlcl9kYXRhKGNoaXApOwo+PiArCXN0cnVjdCBtdGRfaW5mbyAqbXRkID0g bmFuZF90b19tdGQoY2hpcCk7Cj4+ICsJdTMyIHJlZzsKPj4gKwo+PiArCW5hbmRfcmVhZF9vb2Jf b3AoY2hpcCwgcGFnZSwgMCwgY2hpcC0+b29iX3BvaSwgbXRkLT5vb2JzaXplKTsKPj4gKwo+PiAr CS8qIGNvcHkgT09CIGRhdGEgdG8gTkFORFJBIGZvciBwYWdlIHJlYWQgKi8KPiBXaGF0IGlzIE5B TkRSQT8gZG9lcyBub3QgbWVhbiBhbnl0aGluZyB0byBtZS4KCk5BTkRSQSBpcyB0aGUgUmVkdW5k YW50IEFyZWEgV29yZCBvZiB0aGUgTUEzNSBOQU5EIGNvbnRyb2xsZXIuCgpUaGUgY29udHJvbGxl ciByZWFkcyBFQ0MgcGFyaXR5IGZyb20gdGhpcyBhcmVhIGZvciBjYWxjdWxhdGlvbnMgb3IgdXNl cyAKdGhlIGluZm9ybWF0aW9uIGZvciBjaGVjay4KCkkgd2lsbCBjaGFuZ2UgTkFORFJBIHRvIE5B TkRSQSByZWdpc3RlcnMuCgoKPj4gKwltYTM1X3dyaXRlX3NwYXJlKGNoaXAsIG10ZC0+b29ic2l6 ZSwgKHUzMiAqKWNoaXAtPm9vYl9wb2kpOwo+PiArCj4+ICsJcmVnID0gcmVhZGwobmFuZC0+cmVn cyArIE1BMzVfTkZJX1JFR19OQU5EUkEwKTsKPj4gKwlpZiAocmVnICYgMHhmZmZmMDAwMCkKPj4g KwkJbWVtc2V0KCh2b2lkICopY2hpcC0+b29iX3BvaSwgMHhmZiwgbXRkLT5vb2JzaXplKTsKPiBX aGF0IGRvZXMgdGhpcyBtZWFuPwoKTUEzNSBOQU5EIGNvbnRyb2xsZXIgY2hlY2tzIG9vYiBieXRl cyAyIGFuZCAzLgoKSWYgdGhpcyBwYWdlIGhhcyBiZWVuIHdyaXR0ZW4sIG9vYiBieXRlcyAyIGFu ZCAzIHdpbGwgYmUgc2V0IHRvIDAuCgpUaGVyZWZvcmUsIGlmIGJ5dGVzIDIgYW5kIDMgYXJlIG5v dCAwLCBpdCBpbmRpY2F0ZXMgYW4gZW1wdHkgcGFnZSwgYW5kIAppdCB3aWxsIHJldHVybiAweGZm LgoKCj4+ICsKPj4gKwlyZXR1cm4gMDsKPj4gK30KPj4gKwo+PiArc3RhdGljIGlycXJldHVybl90 IG1hMzVfbmFuZF9pcnEoaW50IGlycSwgdm9pZCAqaWQpCj4+ICt7Cj4+ICsJc3RydWN0IG1hMzVf bmFuZF9pbmZvICpuYW5kID0gKHN0cnVjdCBtYTM1X25hbmRfaW5mbyAqKWlkOwo+PiArCXUzMiBp c3I7Cj4+ICsKPj4gKwlpc3IgPSByZWFkbChuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRJ TlRTVFMpOwo+PiArCWlmIChpc3IgJiBJTlRfRE1BKSB7Cj4+ICsJCXdyaXRlbChJTlRfRE1BLCBu YW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRJTlRTVFMpOwo+PiArCQljb21wbGV0ZSgmbmFu ZC0+Y29tcGxldGUpOwo+PiArCX0KPiBJIGd1ZXNzIGEgbW9yZSBmdXR1cmUgcHJvb2YgaW1wbGVt ZW50YXRpb24gd291bGQgYWx3YXlzIHdyaXRlbChpc3IpOyB0bwo+IHNpbGVuY2UgdGhlIGludGVy cnVwdC4gT3RoZXJ3aXNlIG9mIGNvdXJzZSB5b3UgbXVzdCBjYWxsIGNvbXBsZXRlKCkKPiBvbmx5 IHVwb24gaXNyICYgSU5UX0RNQS4KClRoaXMgcGFydCBjYW4gcmVtb3ZlIHRoZSBpZigpLCBidXQg d3JpdGVsKGlzcikgaXMgbm90IGZlYXNpYmxlLgoKVGhlIGlzciBtYXkgY29udGFpbiB0aGUgRUND IGZsYWcsIGFuZCBjbGVhcmluZyBpdCBjb3VsZCBjYXVzZSBhIG1pc3MgaW4gCkVDQyBoYW5kbGlu Zy4KCkkgd2lsbCBjaGFuZ2UgaXQgdG86CgogwqDCoMKgIHdyaXRlbChJTlRfRE1BLCBuYW5kLT5y ZWdzICsgTUEzNV9ORklfUkVHX05BTkRJTlRTVFMpOwogwqDCoMKgIGNvbXBsZXRlKCZuYW5kLT5j b21wbGV0ZSk7CgoKPj4gKwo+PiArCXJldHVybiBJUlFfSEFORExFRDsKPj4gK30KPj4gKwo+PiAr c3RhdGljIGludCBtYTM1X25hbmRfYXR0YWNoX2NoaXAoc3RydWN0IG5hbmRfY2hpcCAqY2hpcCkK Pj4gK3sKPj4gKwlzdHJ1Y3QgbWEzNV9uYW5kX2luZm8gKm5hbmQgPSBuYW5kX2dldF9jb250cm9s bGVyX2RhdGEoY2hpcCk7Cj4+ICsJc3RydWN0IG10ZF9pbmZvICptdGQgPSBuYW5kX3RvX210ZChj aGlwKTsKPj4gKwl1bnNpZ25lZCBpbnQgcmVnOwo+PiArCj4+ICsJaWYgKGNoaXAtPm9wdGlvbnMg JiBOQU5EX0JVU1dJRFRIXzE2KSB7Cj4+ICsJCWRldl9lcnIobmFuZC0+ZGV2LCAiMTYgYml0cyBi dXMgd2lkdGggbm90IHN1cHBvcnRlZCIpOwo+PiArCQlyZXR1cm4gLUVJTlZBTDsKPj4gKwl9Cj4+ ICsKPj4gKwkvKiBzdXBwb3J0IG9ubHkgZWNjIGh3IG1vZGUgKi8KPiBXaHkgPyBQbGVhc2UgZG9u J3QuCgpJIHdpbGwgYWRkIGhhbmRsaW5nIGZvciBvdGhlciBjYXNlcy4KCgo+PiArCWlmIChjaGlw LT5lY2MuZW5naW5lX3R5cGUgIT0gTkFORF9FQ0NfRU5HSU5FX1RZUEVfT05fSE9TVCkgewo+PiAr CQlkZXZfZXJyKG5hbmQtPmRldiwgImVjYy5lbmdpbmVfdHlwZSBub3Qgc3VwcG9ydGVkXG4iKTsK Pj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4+ICsJfQo+PiArCj4+ICsJbmFuZC0+ZWNjX2J1ZiA9IGRl dm1fa3phbGxvYyhuYW5kLT5kZXYsIG10ZC0+d3JpdGVzaXplICsgbXRkLT5vb2JzaXplLAo+PiAr CQkJCQlHRlBfS0VSTkVMKTsKPj4gKwlpZiAoIW5hbmQtPmVjY19idWYpCj4+ICsJCXJldHVybiAg LUVOT01FTTsKPj4gKwljaGlwLT5lY2MuY2FsY19idWYgPSBuYW5kLT5lY2NfYnVmOwo+IEFyZSB5 b3Ugc3VyZSB5b3UgbmVlZCB0aGlzPyBJIGRvbid0IHNlZSB0aGUgcG9pbnQuCgpUaGlzIGlzIHVu bmVjZXNzYXJ5OyBJIHdpbGwgcmVtb3ZlIGl0LgoKCj4+ICsKPj4gKwkvKiBTZXQgUFNpemUgKi8K Pj4gKwlyZWcgPSByZWFkbChuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRDVEwpICYgKH5Q U0laRV9NQVNLKTsKPj4gKwlpZiAobXRkLT53cml0ZXNpemUgPT0gMjA0OCkKPj4gKwkJd3JpdGVs KHJlZyB8IFBTSVpFXzJLLCBuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRDVEwpOwo+PiAr CWVsc2UgaWYgKG10ZC0+d3JpdGVzaXplID09IDQwOTYpCj4+ICsJCXdyaXRlbChyZWcgfCBQU0la RV80SywgbmFuZC0+cmVncyArIE1BMzVfTkZJX1JFR19OQU5EQ1RMKTsKPj4gKwllbHNlIGlmICht dGQtPndyaXRlc2l6ZSA9PSA4MTkyKQo+PiArCQl3cml0ZWwocmVnIHwgUFNJWkVfOEssIG5hbmQt PnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORENUTCk7Cj4+ICsKPj4gKwljaGlwLT5lY2Muc3RlcHMg PSBtdGQtPndyaXRlc2l6ZSAvIGNoaXAtPmVjYy5zaXplOwo+PiArCWlmIChjaGlwLT5lY2Muc3Ry ZW5ndGggPT0gMCkgewo+PiArCQluYW5kLT5iY2ggPSBCQ0hfTk9ORTsgLyogTm8gRUNDICovCj4+ ICsJCWNoaXAtPmVjYy50b3RhbCA9IDA7Cj4+ICsJfSBlbHNlIGlmIChjaGlwLT5lY2Muc3RyZW5n dGggPD0gOCkgewo+PiArCQluYW5kLT5iY2ggPSBCQ0hfVDg7IC8qIFQ4ICovCj4gYmNoIGlzIHBy b2JhYmx5IGEgYmFkIG5hbWUsIGFuZCBpbiBnZW5lcmFsIEkgZG9uJ3Qgc2VlIHRoZSBwb2ludCBv Zgo+IHNhdmluZyB0aGlzIHZhbHVlLiBKdXN0IGNoZWNrIHRoZSBFQ0Mgc3RyZW5ndGggaW4gdGhl IGFib3ZlIHN3aXRjaAo+IGNhc2VzIGFuZCBkb24ndCB1c2UgdGhpcyBpbnRlcm1lZGlhdGUgdmFy aWFibGUuCgpJIHdpbGwgY2hhbmdlIGl0IHRvIGRpcmVjdGx5IHVzZSBlY2Muc3RyZW5ndGggZm9y IHRoZSBjaGVjay4KCgo+PiArCQljaGlwLT5lY2MudG90YWwgPSBjaGlwLT5lY2Muc3RlcHMgKiBN QTM1X1BBUklUWV9CQ0g4Owo+PiArCX0gZWxzZSBpZiAoY2hpcC0+ZWNjLnN0cmVuZ3RoIDw9IDEy KSB7Cj4+ICsJCW5hbmQtPmJjaCA9IEJDSF9UMTI7IC8qIFQxMiAqLwo+PiArCQljaGlwLT5lY2Mu dG90YWwgPSBjaGlwLT5lY2Muc3RlcHMgKiBNQTM1X1BBUklUWV9CQ0gxMjsKPj4gKwl9IGVsc2Ug aWYgKGNoaXAtPmVjYy5zdHJlbmd0aCA8PSAyNCkgewo+PiArCQluYW5kLT5iY2ggPSBCQ0hfVDI0 OyAvKiBUMjQgKi8KPj4gKwkJY2hpcC0+ZWNjLnRvdGFsID0gY2hpcC0+ZWNjLnN0ZXBzICogTUEz NV9QQVJJVFlfQkNIMjQ7Cj4+ICsJfSBlbHNlIHsKPj4gKwkJZGV2X3dhcm4obmFuZC0+ZGV2LCAi TkFORCBDb250cm9sbGVyIGlzIG5vdCBzdXBwb3J0IHRoaXMgZmxhc2guICglZCwgJWQpXG4iLAo+ PiArCQkJbXRkLT53cml0ZXNpemUsIG10ZC0+b29ic2l6ZSk7Cj4gVGhpcyBtdXN0IGJlIGEgZGV2 X2VycigpIGFuZCByZXR1cm4gYW4gZXJyb3IgaW1tZWRpYXRlbHkuCj4KPiBBbHNvIHRoZSBzdHJp bmcgaXMgbm90IGNvcnJlY3QuCgpJIHdpbGwgY2hhbmdlIGl0IHRvOgoKIMKgwqDCoMKgwqDCoMKg IGRldl9lcnIobmFuZC0+ZGV2LCAiRUNDIHN0cmVuZ3RoIGVycm9yXG4iKTsKIMKgwqDCoMKgwqDC oMKgIHJldHVybiAtRUlOVkFMOwoKCj4+ICsJfQo+PiArCj4+ICsJY2hpcC0+ZWNjLmJ5dGVzID0g Y2hpcC0+ZWNjLnRvdGFsIC8gY2hpcC0+ZWNjLnN0ZXBzOwo+PiArCW10ZF9zZXRfb29ibGF5b3V0 KG10ZCwgJm1hMzVfb29ibGF5b3V0X29wcyk7Cj4+ICsKPj4gKwkvKiBhZGQgbXRkLWlkLiBUaGUg c3RyaW5nIHNob3VsZCBzYW1lIGFzIHVib290IGRlZmluaXRpb24gKi8KPj4gKwltdGQtPm5hbWUg PSAibmFuZDAiOwo+IE5vISBUaGVyZSBhcmUgRFQgbGFiZWxzIGZvciB0aGF0IGFuZCBtdGQtPm5h bWUgd2lsbCBhdXRvbWF0aWNhbGx5IGJlCj4gc2V0IHdoZW4gY2FsbGluZyBuYW5kX3NldF9mbGFz aF9ub2RlKCkuCgpJIHdpbGwgcmVtb3ZlIGl0LgoKCj4+ICsKPj4gKwltYTM1X25hbmRfaHdlY2Nf aW5pdChuYW5kKTsKPj4gKwo+PiArCXdyaXRlbChESVNBQkxFX1dQLCBuYW5kLT5yZWdzICsgTUEz NV9ORklfUkVHX05BTkRFQ1RMKTsKPj4gKwo+PiArCXJldHVybiAwOwo+PiArfQo+PiArCj4+ICtz dGF0aWMgaW50IG1hMzVfbmZjX2V4ZWNfaW5zdHIoc3RydWN0IG5hbmRfY2hpcCAqY2hpcCwKPj4g KwkJCSAgICAgIGNvbnN0IHN0cnVjdCBuYW5kX29wX2luc3RyICppbnN0cikKPj4gK3sKPj4gKwlz dHJ1Y3QgbWEzNV9uYW5kX2luZm8gKm5hbmQgPSBuYW5kX2dldF9jb250cm9sbGVyX2RhdGEoY2hp cCk7Cj4+ICsJdW5zaWduZWQgaW50IGk7Cj4+ICsJdTMyIHN0YXR1czsKPj4gKwo+PiArCXN3aXRj aCAoaW5zdHItPnR5cGUpIHsKPj4gKwljYXNlIE5BTkRfT1BfQ01EX0lOU1RSOgo+PiArCQl3cml0 ZWwoaW5zdHItPmN0eC5jbWQub3Bjb2RlLCBuYW5kLT5yZWdzICsgTUEzNV9ORklfUkVHX05BTkRD TUQpOwo+PiArCQlyZXR1cm4gMDsKPj4gKwljYXNlIE5BTkRfT1BfQUREUl9JTlNUUjoKPj4gKwkJ Zm9yIChpID0gMDsgaSA8IGluc3RyLT5jdHguYWRkci5uYWRkcnM7IGkrKykgewo+PiArCQkJaWYg KGkgPT0gKGluc3RyLT5jdHguYWRkci5uYWRkcnMgLSAxKSkKPj4gKwkJCQl3cml0ZWwoaW5zdHIt PmN0eC5hZGRyLmFkZHJzW2ldIHwgRU5EQUREUiwKPj4gKwkJCQkJbmFuZC0+cmVncyArIE1BMzVf TkZJX1JFR19OQU5EQUREUik7Cj4+ICsJCQllbHNlCj4+ICsJCQkJd3JpdGVsKGluc3RyLT5jdHgu YWRkci5hZGRyc1tpXSwKPj4gKwkJCQkJbmFuZC0+cmVncyArIE1BMzVfTkZJX1JFR19OQU5EQURE Uik7Cj4+ICsJCX0KPj4gKwkJcmV0dXJuIDA7Cj4+ICsJY2FzZSBOQU5EX09QX0RBVEFfSU5fSU5T VFI6Cj4+ICsJCW1hMzVfbmFuZF9kb19yZWFkKGNoaXAsIGluc3RyLT5jdHguZGF0YS5idWYuaW4s IGluc3RyLT5jdHguZGF0YS5sZW4pOwo+PiArCQlyZXR1cm4gMDsKPj4gKwljYXNlIE5BTkRfT1Bf REFUQV9PVVRfSU5TVFI6Cj4+ICsJCW1hMzVfbmFuZF9kb193cml0ZShjaGlwLCBpbnN0ci0+Y3R4 LmRhdGEuYnVmLm91dCwgaW5zdHItPmN0eC5kYXRhLmxlbik7Cj4+ICsJCXJldHVybiAwOwo+PiAr CWNhc2UgTkFORF9PUF9XQUlUUkRZX0lOU1RSOgo+PiArCQlyZXR1cm4gcmVhZGxfcG9sbF90aW1l b3V0KG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9SRUdfTkFORElOVFNUUywgc3RhdHVzLAo+PiArCQkJ CQkgIHN0YXR1cyAmIElOVF9SQjAsIDIwLAo+PiArCQkJCQkgIGluc3RyLT5jdHgud2FpdHJkeS50 aW1lb3V0X21zICogMTAwMCk7Cj4gTVNFQ19QRVJfU0VDCgpJIHdpbGwgY2hhbmdlIGl0IHRvIGlu c3RyLT5jdHgud2FpdHJkeS50aW1lb3V0X21zICogTVNFQ19QRVJfU0VDLgoKCj4+ICsJZGVmYXVs dDoKPj4gKwkJYnJlYWs7Cj4+ICsJfQo+PiArCj4+ICsJcmV0dXJuIC1FSU5WQUw7Cj4+ICt9Cj4g VGhpcyBpcyBtdWNoIGJldHRlciB0aGFuIHRoZSBsZWdhY3kgaG9va3MhCgpUaGFua3MuCgoKPj4g Kwo+PiArc3RhdGljIGludCBtYTM1X25mY19leGVjX29wKHN0cnVjdCBuYW5kX2NoaXAgKmNoaXAs Cj4+ICsJCQkgIGNvbnN0IHN0cnVjdCBuYW5kX29wZXJhdGlvbiAqb3AsCj4+ICsJCQkgIGJvb2wg Y2hlY2tfb25seSkKPj4gK3sKPj4gKwlzdHJ1Y3QgbWEzNV9uYW5kX2luZm8gKm5hbmQgPSBuYW5k X2dldF9jb250cm9sbGVyX2RhdGEoY2hpcCk7Cj4+ICsJaW50IHJldCA9IDA7Cj4+ICsJdTMyIGks IHJlZzsKPj4gKwo+PiArCWlmIChjaGVja19vbmx5KQo+PiArCQlyZXR1cm4gMDsKPj4gKwo+PiAr CW1hMzVfbmFuZF90YXJnZXRfZW5hYmxlKG5hbmQpOwo+PiArCj4+ICsJcmVnID0gcmVhZGwobmFu ZC0+cmVncyArIE1BMzVfTkZJX1JFR19OQU5ESU5UU1RTKTsKPj4gKwlyZWcgfD0gSU5UX1JCMDsK PiBUaGlzIFJCIHBpbiBsb29rcyBsaWtlIHNvbWV0aGluZyBoYXJkY29kZWQsIHdoZXJlYXMgaXQg c2hvdWxkIG5vdCA6LSkKPgo+IElmIHlvdSBoYXZlIHNldmVyYWwgUkIsIGl0IG1lYW5zIHlvdSBo YXZlIHNldmVyYWwgQ1MgYXMgd2VsbCEKClRoZSBNQTM1IE5BTkQgY29udHJvbGxlciBpcyBpbmRl ZWQgZXhwZWN0ZWQgdG8gc3VwcG9ydCB0d28gc2V0cyBvZiBDUyAKYW5kIFJCLgoKSG93ZXZlciwg Y3VycmVudGx5LCB0aGUgTUEzNSBzZXJpZXMgb25seSBzdXBwb3J0cyBvbmUgc2V0LCBzbyB0aGlz IG5hbWUgCndpbGwgYmUgY2hhbmdlZCB0byBSQi4KCgo+PiArCXdyaXRlbChyZWcsIG5hbmQtPnJl Z3MgKyBNQTM1X05GSV9SRUdfTkFORElOVFNUUyk7Cj4+ICsKPj4gKwlmb3IgKGkgPSAwOyBpIDwg b3AtPm5pbnN0cnM7IGkrKykgewo+PiArCQlyZXQgPSBtYTM1X25mY19leGVjX2luc3RyKGNoaXAs ICZvcC0+aW5zdHJzW2ldKTsKPj4gKwkJaWYgKHJldCkKPj4gKwkJCWJyZWFrOwo+PiArCX0KPj4g Kwo+PiArCW1hMzVfbmFuZF90YXJnZXRfZGlzYWJsZShuYW5kKTsKPj4gKwo+PiArCXJldHVybiBy ZXQ7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgbmFuZF9jb250cm9sbGVyX29w cyBtYTM1X25mY19vcHMgPSB7Cj4+ICsJLmF0dGFjaF9jaGlwID0gbWEzNV9uYW5kX2F0dGFjaF9j aGlwLAo+PiArCS5leGVjX29wID0gbWEzNV9uZmNfZXhlY19vcCwKPj4gK307Cj4+ICsKPj4gK3N0 YXRpYyBpbnQgbWEzNV9uYW5kX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4+ ICt7Cj4+ICsJc3RydWN0IG1hMzVfbmFuZF9pbmZvICpuYW5kOwo+PiArCXN0cnVjdCBuYW5kX2No aXAgKmNoaXA7Cj4+ICsJc3RydWN0IG10ZF9pbmZvICptdGQ7Cj4+ICsJaW50IHJldCA9IDA7Cj4+ ICsKPj4gKwluYW5kID0gZGV2bV9remFsbG9jKCZwZGV2LT5kZXYsIHNpemVvZigqbmFuZCksIEdG UF9LRVJORUwpOwo+PiArCWlmICghbmFuZCkKPj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4+ICsKPj4g KwluYW5kX2NvbnRyb2xsZXJfaW5pdCgmbmFuZC0+Y29udHJvbGxlcik7Cj4+ICsJbmFuZC0+Y29u dHJvbGxlci5vcHMgPSAmbWEzNV9uZmNfb3BzOwo+PiArCj4+ICsJbmFuZC0+cmVncyA9IGRldm1f cGxhdGZvcm1faW9yZW1hcF9yZXNvdXJjZShwZGV2LCAwKTsKPj4gKwlpZiAoSVNfRVJSKG5hbmQt PnJlZ3MpKQo+PiArCQlyZXR1cm4gUFRSX0VSUihuYW5kLT5yZWdzKTsKPj4gKwo+PiArCW5hbmQt PmRldiA9ICZwZGV2LT5kZXY7Cj4+ICsJY2hpcCA9ICZuYW5kLT5jaGlwOwo+PiArCW5hbmRfc2V0 X2NvbnRyb2xsZXJfZGF0YShjaGlwLCBuYW5kKTsKPj4gKwluYW5kX3NldF9mbGFzaF9ub2RlKGNo aXAsIHBkZXYtPmRldi5vZl9ub2RlKTsKPj4gKwo+PiArCW5hbmQtPmNsayA9IGRldm1fY2xrX2dl dF9lbmFibGVkKCZwZGV2LT5kZXYsICJuYW5kX2dhdGUiKTsKPj4gKwlpZiAoSVNfRVJSKG5hbmQt PmNsaykpCj4+ICsJCXJldHVybiBkZXZfZXJyX3Byb2JlKCZwZGV2LT5kZXYsIFBUUl9FUlIobmFu ZC0+Y2xrKSwKPj4gKwkJCQkgICAgICJmYWlsZWQgdG8gZmluZCBuYW5kIGNsb2NrXG4iKTsKPiBO QU5ECgpJIHdpbGwgZml4IGl0LgoKCj4+ICsKPj4gKwluYW5kLT5pcnEgPSBwbGF0Zm9ybV9nZXRf aXJxKHBkZXYsIDApOwo+PiArCWlmIChuYW5kLT5pcnEgPCAwKQo+PiArCQlyZXR1cm4gZGV2X2Vy cl9wcm9iZSgmcGRldi0+ZGV2LCBuYW5kLT5pcnEsCj4+ICsJCQkJICAgICAiZmFpbGVkIHRvIGdl dCBwbGF0Zm9ybSBpcnFcbiIpOwo+PiArCj4+ICsJcmV0ID0gZGV2bV9yZXF1ZXN0X2lycSgmcGRl di0+ZGV2LCBuYW5kLT5pcnEsIG1hMzVfbmFuZF9pcnEsCj4+ICsJCQkJICBJUlFGX1RSSUdHRVJf SElHSCwgIm1hMzVkMS1uYW5kIiwgbmFuZCk7Cj4+ICsJaWYgKHJldCkgewo+PiArCQlkZXZfZXJy KCZwZGV2LT5kZXYsICJmYWlsZWQgdG8gcmVxdWVzdCBOQU5EIGlycVxuIik7Cj4+ICsJCXJldHVy biAtRU5YSU87Cj4+ICsJfQo+PiArCj4+ICsJbmFuZC0+Y2hpcC5jb250cm9sbGVyID0gJm5hbmQt PmNvbnRyb2xsZXI7Cj4+ICsJcGxhdGZvcm1fc2V0X2RydmRhdGEocGRldiwgbmFuZCk7Cj4+ICsK Pj4gKwljaGlwLT5vcHRpb25zIHw9IE5BTkRfTk9fU1VCUEFHRV9XUklURSB8IE5BTkRfVVNFU19E TUE7Cj4+ICsKPj4gKwljaGlwLT5lY2MuZW5naW5lX3R5cGUgPSBOQU5EX0VDQ19FTkdJTkVfVFlQ RV9PTl9IT1NUOwo+PiArCWNoaXAtPmVjYy53cml0ZV9wYWdlID0gbWEzNV9uYW5kX3dyaXRlX3Bh Z2VfaHdlY2M7Cj4+ICsJY2hpcC0+ZWNjLnJlYWRfcGFnZSAgPSBtYTM1X25hbmRfcmVhZF9wYWdl X2h3ZWNjOwo+PiArCWNoaXAtPmVjYy5yZWFkX29vYiAgID0gbWEzNV9uYW5kX3JlYWRfb29iX2h3 ZWNjOwo+IFlvdSBzdXBwb3J0IHRvIGRpc2FibGUgdGhlIEVDQyBlbmdpbmUsIHNvIHlvdSBtdXN0 IHN1cHBvcnQgc29mdHdhcmUKPiBjb3JyZWN0aW9ucyBhcyB3ZWxsLiBQbGVhc2UgZG9uJ3QgZm9y Y2UgaHcgRUNDIHVzZS4gUGxlYXNlIGxvb2sgYXQKPiBvdGhlciBpbXBsZW1lbnRhdGlvbnMsIHRo ZXJlIGlzIHVzdWFsbHkgYSBoZWxwZXIgd2l0aCBhIHN3aXRjaCBjYXNlCj4gd2hpY2ggc3VwcG9y dHMgdmFyaW91cyBFQ0MgY29uZmlndXJhdGlvbnMuCgpJIHdpbGwgcmVmZXIgdG8gb3RoZXIgaW1w bGVtZW50YXRpb25zIGFuZCB3aWxsIGFkZCBoYW5kbGluZyBmb3Igb3RoZXIgY2FzZXMuCgoKPj4g Kwo+PiArCW10ZCA9IG5hbmRfdG9fbXRkKGNoaXApOwo+PiArCW10ZC0+cHJpdiA9IGNoaXA7Cj4+ ICsJbXRkLT5vd25lciA9IFRISVNfTU9EVUxFOwo+PiArCW10ZC0+ZGV2LnBhcmVudCA9ICZwZGV2 LT5kZXY7Cj4+ICsKPj4gKwl3cml0ZWwoTkFORF9FTiwgbmFuZC0+cmVncyArIE1BMzVfTkZJX1JF R19HQ1RMKTsKPiBJIHdvdWxkIGV4cGVjdCB5b3VyIHJlc2V0IGJpdCB0byBiZSBzZXQgYmVmb3Jl IHRoaXMgd3JpdGVsLgoKQXJlIHlvdSByZWZlcnJpbmcgdG8gU1dSU1Q/IEkgd2lsbCBjYWxsIHRo ZSByZXNldCBlbmdpbmUgYmVmb3JlIGVuYWJsaW5nIGl0LgoKCj4+ICsKPj4gKwlyZXQgPSBuYW5k X3NjYW4oY2hpcCwgMSk7Cj4+ICsJaWYgKHJldCkKPj4gKwkJcmV0dXJuIHJldDsKPj4gKwo+PiAr CXJldCA9IG10ZF9kZXZpY2VfcmVnaXN0ZXIobXRkLCBOVUxMLCAwKTsKPj4gKwlpZiAocmV0KSB7 Cj4+ICsJCW5hbmRfY2xlYW51cChjaGlwKTsKPj4gKwkJcmV0dXJuIHJldDsKPj4gKwl9Cj4+ICsK Pj4gKwlyZXR1cm4gcmV0Owo+IHJldHVybiAwOyB0aGVuCgpJIHdpbGwgY2hhbmdlIGl0IHRvIHJl dHVybiAwOwoKCj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyB2b2lkIG1hMzVfbmFuZF9yZW1vdmUoc3Ry dWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKPj4gK3sKPj4gKwlzdHJ1Y3QgbWEzNV9uYW5kX2lu Zm8gKm5hbmQgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKPj4gKwlpbnQgcmV0Owo+PiAr Cj4+ICsJcmV0ID0gbXRkX2RldmljZV91bnJlZ2lzdGVyKG5hbmRfdG9fbXRkKCZuYW5kLT5jaGlw KSk7Cj4+ICsJV0FSTl9PTihyZXQpOwo+PiArCW5hbmRfY2xlYW51cCgmbmFuZC0+Y2hpcCk7Cj4+ ICt9Cj4+ICsKPj4gKy8qIFBNIFN1cHBvcnQgKi8KPj4gKyNpZmRlZiBDT05GSUdfUE0KPj4gK3N0 YXRpYyBpbnQgbWEzNV9uYW5kX3N1c3BlbmQoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldiwg cG1fbWVzc2FnZV90IHBtKQo+PiArewo+PiArCXN0cnVjdCBtYTM1X25hbmRfaW5mbyAqbmFuZCA9 IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+PiArCWludCByZXQgPSAwOwo+PiArCXUzMiB2 YWw7Cj4+ICsKPj4gKwkvKiB3YWl0IERNQUMgdG8gcmVhZHkgKi8KPiAJCQliZQoKSSB3aWxsIGZp eCBpdC4KCgo+PiArCXJldCA9IHJlYWRsX3BvbGxfdGltZW91dChuYW5kLT5yZWdzICsgTUEzNV9O RklfUkVHX0RNQUNUTCwgdmFsLAo+PiArCQkJCSAhKHZhbCAmIERNQV9CVVNZKSwgNTAsIEhaLzIp Owo+PiArCWlmIChyZXQpCj4+ICsJCWRldl93YXJuKCZwZGV2LT5kZXYsICJkbWEgYnVzeVxuIik7 Cj4gCQkJCQlETUEKPgo+IEFuZCBwbGVhc2UgbWFrZSBhIHNlbnRlbmNlLgoKSSB3aWxsIGZpeCBp dC4KCgo+PiArCj4+ICsJY2xrX2Rpc2FibGUobmFuZC0+Y2xrKTsKPiBJZiB5b3UgZGVjaWRlIHRv IHJldHVybiByZXQgIT0gMCwgc2hhbGwgeW91IHJlYWxseSBkaXNhYmxlIHRoaXMgY2xvY2sgPwoK SSB3aWxsIGNoYW5nZSBpdCB0bzoKCiDCoMKgwqAgLyogd2FpdCBETUFDIHRvIGJlIHJlYWR5ICov CiDCoMKgwqAgcmV0ID0gcmVhZGxfcG9sbF90aW1lb3V0KG5hbmQtPnJlZ3MgKyBNQTM1X05GSV9S RUdfRE1BQ1RMLCB2YWwsCiDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoCAhKHZhbCAm IERNQV9CVVNZKSwgNTAsIEhaLzIpOwogwqDCoMKgIGlmIChyZXQpIHsKIMKgwqDCoMKgwqDCoMKg IGRldl93YXJuKCZwZGV2LT5kZXYsICJ3YWl0IERNQSBkb25lIHRpbWVvdXQuXG4iKTsKIMKgwqDC oMKgwqDCoMKgIHJldHVybiByZXQ7CiDCoMKgwqAgfQoKIMKgwqDCoCBjbGtfZGlzYWJsZShuYW5k LT5jbGspOwoKIMKgwqDCoCByZXR1cm4gMDsKCgo+PiArCj4+ICsJcmV0dXJuIHJldDsKPj4gK30K Pj4gKwo+PiArc3RhdGljIGludCBtYTM1X25hbmRfcmVzdW1lKHN0cnVjdCBwbGF0Zm9ybV9kZXZp Y2UgKnBkZXYpCj4+ICt7Cj4+ICsJc3RydWN0IG1hMzVfbmFuZF9pbmZvICpuYW5kID0gcGxhdGZv cm1fZ2V0X2RydmRhdGEocGRldik7Cj4+ICsKPj4gKwljbGtfZW5hYmxlKG5hbmQtPmNsayk7Cj4+ ICsJbWEzNV9uYW5kX2h3ZWNjX2luaXQobmFuZCk7Cj4gVGhlIG5hbWluZyBpcyB3cm9uZy4gVGhp cyBpbml0IGlzIG5vdCBqdXN0IHRoZSBodyBFQ0MgY29udHJvbGxlci4KClRoaXMgd2lsbCBiZSBj aGFuZ2VkIHRvIGhhbmRsZSB0aGUgaW5pdGlhbGl6YXRpb24gb2YgdGhlIE5BTkQgY29udHJvbGxl ciAKYW5kIEVDQyBjb250cm9sbGVyLgoKSXQgd2lsbCBhbHNvIGNhbGwgbmFuZF9yZXNldCgpLgoK Cj4+ICsJbWEzNV9uYW5kX2RtYWNfaW5pdChuYW5kKTsKPj4gKwo+PiArCXJldHVybiAwOwo+PiAr fQo+PiArCj4+ICsjZWxzZQo+PiArI2RlZmluZSBtYTM1X25hbmRfc3VzcGVuZCBOVUxMCj4+ICsj ZGVmaW5lIG1hMzVfbmFuZF9yZXN1bWUgTlVMTAo+PiArI2VuZGlmCj4+ICsKPj4gK3N0YXRpYyBj b25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lkIG1hMzVfbmZpX29mX21hdGNoW10gPSB7Cj4gbWEzNV9u Zmkgb3IgbWEzNV9uYW5kLCB0YWtlIG9uZSBhbmQgcGxlYXNlIHN0aWNrIHRvIGl0LgoKV2lsbCBi ZSB1bmlmaWVkIGludG8gbWEzNV9uYW5kLgoKCj4+ICsJeyAuY29tcGF0aWJsZSA9ICJudXZvdG9u LG1hMzVkMS1uYW5kIiB9LAo+PiArCXt9LAo+PiArfTsKPj4gK01PRFVMRV9ERVZJQ0VfVEFCTEUo b2YsIG1hMzVfbmZpX29mX21hdGNoKTsKPj4gKwo+PiArc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9k cml2ZXIgbWEzNV9uYW5kX2RyaXZlciA9IHsKPj4gKwkuZHJpdmVyID0gewo+PiArCQkubmFtZSA9 ICJtYTM1ZDEtbmFuZCIsCj4+ICsJCS5vZl9tYXRjaF90YWJsZSA9IG1hMzVfbmZpX29mX21hdGNo LAo+PiArCX0sCj4+ICsJLnByb2JlID0gbWEzNV9uYW5kX3Byb2JlLAo+PiArCS5yZW1vdmUgPSBt YTM1X25hbmRfcmVtb3ZlLAo+PiArCS5zdXNwZW5kID0gbWEzNV9uYW5kX3N1c3BlbmQsCj4+ICsJ LnJlc3VtZSA9IG1hMzVfbmFuZF9yZXN1bWUsCj4+ICt9Owo+PiArCj4+ICttb2R1bGVfcGxhdGZv cm1fZHJpdmVyKG1hMzVfbmFuZF9kcml2ZXIpOwo+PiArCj4+ICtNT0RVTEVfREVTQ1JJUFRJT04o Ik51dm90b24gbWEzNSBOQU5EIGRyaXZlciIpOwo+PiArTU9EVUxFX0FVVEhPUigiSHVpLVBpbmcg Q2hlbiA8aHBjaGVuMG52dEBnbWFpbC5jb20+Iik7Cj4+ICtNT0RVTEVfTElDRU5TRSgiR1BMIik7 Cj4KPiBUaGFua3MsCj4gTWlxdcOobAoKCkJlc3QgcmVnYXJkcywKCkh1aS1QaW5nIENoZW4KCgoK X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCkxp bnV4IE1URCBkaXNjdXNzaW9uIG1haWxpbmcgbGlzdApodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9y Zy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LW10ZC8K From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 381A4CED25F for ; Tue, 8 Oct 2024 03:21:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: Content-Type:In-Reply-To:From:References:Cc:To:Subject:MIME-Version:Date: Message-ID:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=vFntR5p2J86VuDGwgkOeGjdKlfKqRgMieCplvZuIyzg=; b=hLO/GAVK8SUev4lT3cvjmYQiRg sh2uYSrkZaulNuExBQrVPwQKmf7g+nFt3YdxpH5ehl6fYS2OwZ6LmL2U9rtP3QE8RJLZtEsU7CklZ cxwodCbL+yrp12KEhb7w4bvHKHJuc0wYaGa3jtUY6eQMneQehO8nonSDjyj6b9K3wqMriwRUJKx4y S5lIVcxpd2VSjqAVttsTN+Qx/qBRHmENzHQL+VTCBcgNMIpOP8TAPSIxWWNnIK2l+kQryC0wMGNt0 v3YFzmNDCoNdeEOszOiSK59acpJgTUwtJirXs49lLsPNdDm04TyQ0UK2KphCBJf1JXn2Bn2xWdaRl fcPWJZLg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1sy0mt-00000004OGz-17In; Tue, 08 Oct 2024 03:21:27 +0000 Received: from mail-pj1-x1033.google.com ([2607:f8b0:4864:20::1033]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1sy0lW-00000004O7x-39wZ; Tue, 08 Oct 2024 03:20:06 +0000 Received: by mail-pj1-x1033.google.com with SMTP id 98e67ed59e1d1-2e18aa9f06dso3649588a91.0; Mon, 07 Oct 2024 20:20:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728357602; x=1728962402; darn=lists.infradead.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=vFntR5p2J86VuDGwgkOeGjdKlfKqRgMieCplvZuIyzg=; b=EVQFwOjJ+dJ+DXUqM9JAJUEjAzpLd+4f1xF5tu/yVS1E82NNCObsr5nbyC1PDQh8MR XAIn2np6rx1g5SoOrC1ApyS/zPNRXOGAKlYlDIfqo6AFG/uHsHZYCtxlYjJxk8mZ8QZM mPE8ME/SJzVPjUgKz3rhZQYImC4Ged03p+peAagCDba3ivBH6JqhSdfrwolAfGX+AYre e6bjCa76kJS+Dbcpu17c7oW8+UkfEwh4xZOtjPoDj9+o+KkB6IMF+MbTxbPfk4UnF87V q2vqpC3mUWnJrZJIukQ1kQR2hOq4aVIizZMJYg8yCzAqWfx/pc2ByeKRYAoZ3EMWyxO4 reYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728357602; x=1728962402; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=vFntR5p2J86VuDGwgkOeGjdKlfKqRgMieCplvZuIyzg=; b=NAHshyYmMFV6ckgsRwcXoE6TnH6BRPVcKsc+PinfNx/A/Yrwta+TOP6FieVx6FrtS1 X1UcKAwmmc4oBfJN+WbulfvrNsrNHDlo18/KR12XwBLBXbMUbj7iP/AbACN5n9eSQcsp uIIKa7q597pAMHM3zrF+pTPRhRVhPa/Hf1v1opQyYAWajl0GE/yXKetx26SD0YJRPuLp 04dLPqXhBDMhgEWqaCLtYtG1RM7G6JcrRLD2PHUC18EilAd4ZlP2EWLS234uR4WQUtYX 4LZ7fifsx9l3P3GlELirqpDCmPs0R1xhd8yp1IJqMUSU9ZHQOTGIfVXjg5H1s7H24cM7 JZtQ== X-Forwarded-Encrypted: i=1; AJvYcCV4UekY7zTXBGPPz6fWbVzFHASibU+EqsdwyQkN89ww994dj0xd/TTReh1TU9Zt4VJH1QdpYvzy2qMl@lists.infradead.org, AJvYcCWIVYoDmjkO3d1METglUTo2AwsAb/d+pNFYaAejQVgHdZII/k6M267+MGJMCd49ghEnKIRVtUteF/eW2tMsgvuk@lists.infradead.org X-Gm-Message-State: AOJu0Yw+SDnd0yBejTRrU7qIDVIT8SpS4yI/Qwd5w7Uj20PQL5A6CwEv YLvrDOHwbwxoHZ61+ohMMZ5Ipq6f2+Zb/YXS50I96iRgMneGOl/z X-Google-Smtp-Source: AGHT+IGruia56J8OL3/MX7UQ1hDdtBG35QP76rfwJ6CEuU6FQcQq/RFSak5t59vmXzj8dhRXoqzLOw== X-Received: by 2002:a17:90a:6884:b0:2e2:18ac:afad with SMTP id 98e67ed59e1d1-2e27ded0213mr2873514a91.15.1728357601406; Mon, 07 Oct 2024 20:20:01 -0700 (PDT) Received: from [172.19.1.53] (60-250-196-139.hinet-ip.hinet.net. [60.250.196.139]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2e2848d28f4sm333855a91.24.2024.10.07.20.19.58 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 07 Oct 2024 20:20:01 -0700 (PDT) Message-ID: <8d5e7755-17fd-4860-bcb0-8c1de04bf0c5@gmail.com> Date: Tue, 8 Oct 2024 11:19:57 +0800 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v6 2/2] mtd: rawnand: nuvoton: add new driver for the Nuvoton MA35 SoC To: Miquel Raynal Cc: richard@nod.at, vigneshr@ti.com, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, nikita.shubin@maquefel.me, arnd@arndb.de, vkoul@kernel.org, esben@geanix.com, linux-arm-kernel@lists.infradead.org, linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org References: <20240927020749.46791-1-hpchen0nvt@gmail.com> <20240927020749.46791-3-hpchen0nvt@gmail.com> <20241001215755.5c2f8465@xps-13> Content-Language: en-US From: Hui-Ping Chen In-Reply-To: <20241001215755.5c2f8465@xps-13> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20241007_202002_880308_AA3BE59C X-CRM114-Status: GOOD ( 35.03 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Dear Miquel, Thank you for your reply. On 2024/10/2 上午 03:57, Miquel Raynal wrote: > Hi Hui-Ping, > > hpchen0nvt@gmail.com wrote on Fri, 27 Sep 2024 02:07:49 +0000: > >> Nuvoton MA35 SoCs NAND Flash Interface Controller >> supports 2kiB, 4kiB and 8kiB page size, and up to >> 8-bit, 12-bit, and 24-bit hardware ECC calculation >> circuit to protect data. >> >> Signed-off-by: Hui-Ping Chen >> --- >> drivers/mtd/nand/raw/Kconfig | 8 + >> drivers/mtd/nand/raw/Makefile | 1 + >> drivers/mtd/nand/raw/nuvoton_ma35d1_nand.c | 862 +++++++++++++++++++++ >> 3 files changed, 871 insertions(+) >> create mode 100644 drivers/mtd/nand/raw/nuvoton_ma35d1_nand.c >> >> diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig >> index d0aaccf72d78..e3677bcaf035 100644 >> --- a/drivers/mtd/nand/raw/Kconfig >> +++ b/drivers/mtd/nand/raw/Kconfig >> @@ -454,6 +454,14 @@ config MTD_NAND_TS72XX >> help >> Enables support for NAND controller on ts72xx SBCs. >> >> +config MTD_NAND_NUVOTON_MA35 >> + tristate "Nuvoton MA35 SoC NAND controller" >> + depends on ARCH_MA35 || COMPILE_TEST >> + depends on OF >> + help >> + Enables support for the NAND controller found on >> + the Nuvoton MA35 series SoCs. >> + >> comment "Misc" >> >> config MTD_SM_COMMON >> diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile >> index d0b0e6b83568..cc24955627f8 100644 >> --- a/drivers/mtd/nand/raw/Makefile >> +++ b/drivers/mtd/nand/raw/Makefile >> @@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_INTEL_LGM) += intel-nand-controller.o >> obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip-nand-controller.o >> obj-$(CONFIG_MTD_NAND_PL35X) += pl35x-nand-controller.o >> obj-$(CONFIG_MTD_NAND_RENESAS) += renesas-nand-controller.o >> +obj-$(CONFIG_MTD_NAND_NUVOTON_MA35) += nuvoton_ma35d1_nand.o >> >> nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o >> nand-objs += nand_onfi.o >> diff --git a/drivers/mtd/nand/raw/nuvoton_ma35d1_nand.c b/drivers/mtd/nand/raw/nuvoton_ma35d1_nand.c >> new file mode 100644 >> index 000000000000..efd60493f22a >> --- /dev/null >> +++ b/drivers/mtd/nand/raw/nuvoton_ma35d1_nand.c >> @@ -0,0 +1,862 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> +/* >> + * Copyright (C) 2024 Nuvoton Technology Corp. >> + */ >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +/* NFI Registers */ >> +#define MA35_NFI_REG_DMACTL 0x400 >> +#define DMA_EN BIT(0) >> +#define DMA_RST BIT(1) >> +#define DMA_BUSY BIT(9) >> + >> +#define MA35_NFI_REG_DMASA 0x408 >> +#define MA35_NFI_REG_GCTL 0x800 >> +#define NAND_EN BIT(3) >> + >> +#define MA35_NFI_REG_NANDCTL 0x8A0 >> +#define SWRST BIT(0) >> +#define DMA_R_EN BIT(1) >> +#define DMA_W_EN BIT(2) >> +#define ECC_CHK BIT(7) >> +#define PROT3BEN BIT(8) >> +#define PSIZE_2K BIT(16) >> +#define PSIZE_4K BIT(17) >> +#define PSIZE_8K GENMASK(17, 16) >> +#define PSIZE_MASK GENMASK(17, 16) >> +#define BCH_T24 BIT(18) >> +#define BCH_T8 BIT(20) >> +#define BCH_T12 BIT(21) >> +#define BCH_NONE (0x0) >> +#define BCH_MASK GENMASK(22, 18) >> +#define ECC_EN BIT(23) >> +#define DISABLE_CS0 BIT(25) >> + >> +#define MA35_NFI_REG_NANDINTEN 0x8A8 >> +#define MA35_NFI_REG_NANDINTSTS 0x8AC >> +#define INT_DMA BIT(0) >> +#define INT_ECC BIT(2) >> +#define INT_RB0 BIT(10) >> +#define INT_RB0_STS BIT(18) >> + >> +#define MA35_NFI_REG_NANDCMD 0x8B0 >> +#define MA35_NFI_REG_NANDADDR 0x8B4 >> +#define ENDADDR BIT(31) >> + >> +#define MA35_NFI_REG_NANDDATA 0x8B8 >> +#define MA35_NFI_REG_NANDRACTL 0x8BC >> +#define MA35_NFI_REG_NANDECTL 0x8C0 >> +#define ENABLE_WP 0x0 >> +#define DISABLE_WP BIT(0) >> + >> +#define MA35_NFI_REG_NANDECCES0 0x8D0 >> +#define ECC_STATUS_MASK GENMASK(1, 0) >> +#define ECC_ERR_CNT_MASK GENMASK(4, 0) >> + >> +#define MA35_NFI_REG_NANDECCEA0 0x900 >> +#define MA35_NFI_REG_NANDECCED0 0x960 >> +#define MA35_NFI_REG_NANDRA0 0xA00 >> + >> +/* Define for the BCH hardware ECC engine */ >> +/* define the total padding bytes for 512/1024 data segment */ >> +#define MA35_BCH_PADDING_512 32 >> +#define MA35_BCH_PADDING_1024 64 >> +/* define the BCH parity code length for 512 bytes data pattern */ >> +#define MA35_PARITY_BCH8 15 >> +#define MA35_PARITY_BCH12 23 >> +/* define the BCH parity code length for 1024 bytes data pattern */ >> +#define MA35_PARITY_BCH24 45 >> + >> +struct ma35_nand_info { >> + struct nand_controller controller; >> + struct nand_chip chip; >> + struct device *dev; >> + void __iomem *regs; >> + int irq; >> + struct clk *clk; >> + struct completion complete; >> + u32 bch; >> + u32 bitflips; >> + u8 *ecc_buf; >> +}; >> + >> +static int ma35_ooblayout_ecc(struct mtd_info *mtd, int section, >> + struct mtd_oob_region *oobregion) >> +{ >> + struct nand_chip *chip = mtd_to_nand(mtd); >> + >> + if (section) >> + return -ERANGE; >> + >> + oobregion->length = chip->ecc.total; >> + oobregion->offset = mtd->oobsize - oobregion->length; >> + >> + return 0; >> +} >> + >> +static int ma35_ooblayout_free(struct mtd_info *mtd, int section, >> + struct mtd_oob_region *oobregion) >> +{ >> + struct nand_chip *chip = mtd_to_nand(mtd); >> + >> + if (section) >> + return -ERANGE; >> + >> + oobregion->length = mtd->oobsize - chip->ecc.total - 2; >> + oobregion->offset = 2; >> + >> + return 0; >> +} >> + >> +static const struct mtd_ooblayout_ops ma35_ooblayout_ops = { >> + .free = ma35_ooblayout_free, >> + .ecc = ma35_ooblayout_ecc, >> +}; >> + >> +static inline void ma35_clear_spare(struct nand_chip *chip, int size) >> +{ >> + struct ma35_nand_info *nand = nand_get_controller_data(chip); >> + int i; >> + >> + for (i = 0; i < size/4; i++) > Spacing ^ I will check and fix it. >> + writel(0xff, nand->regs + MA35_NFI_REG_NANDRA0); >> +} >> + >> +static inline void read_remaining_bytes(struct ma35_nand_info *nand, u32 *buf, >> + u32 offset, int size) >> +{ >> + u32 value = readl(nand->regs + MA35_NFI_REG_NANDRA0 + offset); >> + u8 *ptr = (u8 *)buf; >> + int i; >> + >> + for (i = 0; i < size; i++) >> + ptr[i] = (value >> (i * 8)) & 0xff; >> +} >> + >> +static inline void ma35_read_spare(struct nand_chip *chip, int size, u32 *buf, u32 offset) >> +{ >> + struct ma35_nand_info *nand = nand_get_controller_data(chip); >> + int i, j; >> + >> + if ((offset % 4) == 0) { >> + for (i = 0, j = 0; i < size / 4; i++, j += 4) >> + *buf++ = readl(nand->regs + MA35_NFI_REG_NANDRA0 + offset + j); >> + >> + read_remaining_bytes(nand, buf, offset + j, size % 4); >> + } else { >> + read_remaining_bytes(nand, buf, offset, 4 - (offset % 4)); >> + offset += 4; >> + size -= (4 - (offset % 4)); >> + >> + for (i = 0, j = 0; i < size / 4; i++, j += 4) >> + *buf++ = readl(nand->regs + MA35_NFI_REG_NANDRA0 + offset + j); >> + >> + read_remaining_bytes(nand, buf, offset + j, size % 4); >> + } >> +} >> + >> +static inline void ma35_write_spare(struct nand_chip *chip, int size, u32 *buf) >> +{ >> + struct ma35_nand_info *nand = nand_get_controller_data(chip); >> + u32 value; >> + int i, j; >> + u8 *ptr; >> + >> + for (i = 0, j = 0; i < size / 4; i++, j += 4) >> + writel(*buf++, nand->regs + MA35_NFI_REG_NANDRA0 + j); >> + >> + ptr = (u8 *)buf; >> + switch (size % 4) { >> + case 1: >> + writel(*ptr, nand->regs + MA35_NFI_REG_NANDRA0 + j); >> + break; >> + case 2: >> + value = *ptr | (*(ptr+1) << 8); >> + writel(value, nand->regs + MA35_NFI_REG_NANDRA0 + j); >> + break; >> + case 3: >> + value = *ptr | (*(ptr+1) << 8) | (*(ptr+2) << 16); >> + writel(value, nand->regs + MA35_NFI_REG_NANDRA0 + j); >> + break; >> + default: >> + break; >> + } >> +} >> + >> +static inline void ma35_nand_target_enable(struct ma35_nand_info *nand) >> +{ >> + writel(readl(nand->regs + MA35_NFI_REG_NANDCTL) & (~DISABLE_CS0), >> + nand->regs+MA35_NFI_REG_NANDCTL); >> +} >> + >> +static inline void ma35_nand_target_disable(struct ma35_nand_info *nand) >> +{ >> + writel(readl(nand->regs + MA35_NFI_REG_NANDCTL) | DISABLE_CS0, >> + nand->regs + MA35_NFI_REG_NANDCTL); >> +} >> + >> +static void ma35_nand_hwecc_init(struct ma35_nand_info *nand) >> +{ >> + struct mtd_info *mtd = nand_to_mtd(&nand->chip); >> + u32 reg; >> + >> + /* resets the internal state machine and counters > Please check the style in all you comments. > > /* > * Reset the I will check and fix all. >> + * This bit will be auto cleared after a few clock cycles. >> + */ >> + reg = readl(nand->regs + MA35_NFI_REG_NANDCTL); >> + reg |= SWRST; >> + writel(reg, nand->regs + MA35_NFI_REG_NANDCTL); > This has a way wider impact than just configuring the hw ECC engine, > no? Are you sure you want to do this now? I believe it should be in its > own helper, and you want to do it earlier than that, like before the > discovery step (and also in the resume path). I carefully examined our NAND controller and found that this action is unnecessary. I will remove it. >> + while (readl(nand->regs + MA35_NFI_REG_NANDCTL) & SWRST) >> + ; > cpu_relax() I will remove this while-loop, so this API will not be added. >> + >> + /* Redundant area size */ >> + writel(mtd->oobsize, nand->regs + MA35_NFI_REG_NANDRACTL); >> + >> + /* Protect redundant 3 bytes */ >> + reg = readl(nand->regs + MA35_NFI_REG_NANDCTL); >> + reg |= (PROT3BEN | ECC_CHK); >> + writel(reg, nand->regs + MA35_NFI_REG_NANDCTL); >> + >> + if (nand->bch == BCH_NONE) { > Please use the definitions/constants from the core. Will use ecc.strength instead. >> + /* Disable H/W ECC, ECC parity check enable bit during read page */ >> + writel(readl(nand->regs + MA35_NFI_REG_NANDCTL) & (~ECC_EN), >> + nand->regs + MA35_NFI_REG_NANDCTL); > Move the readl before the if and save it in the reg variable. > > In general please do not overload the lines like that when it's not > needed. It will be changed to: reg = readl(); writel(...); >> + } else { >> + /* Set BCH algorithm */ >> + writel((readl(nand->regs + MA35_NFI_REG_NANDCTL) & (~BCH_MASK)) | > Parenthesis are not needed ^ I will remove the parentheses. >> + nand->bch, nand->regs + MA35_NFI_REG_NANDCTL); >> + >> + /* Enable H/W ECC, ECC parity check enable bit during read page */ >> + writel(readl(nand->regs + MA35_NFI_REG_NANDCTL) | ECC_EN, >> + nand->regs + MA35_NFI_REG_NANDCTL); >> + } >> +} >> + >> +/* Correct data by BCH alrogithm */ >> +static void ma35_nfi_correct(struct ma35_nand_info *nand, u8 index, >> + u8 err_cnt, u8 *addr) >> +{ >> + u32 temp_data[24], temp_addr[24]; >> + u32 padding_len, parity_len; >> + u32 value, offset, remain; >> + u32 err_data[6]; >> + u8 i, j; >> + >> + /* configurations */ >> + switch (nand->bch) { >> + case BCH_T24: >> + parity_len = MA35_PARITY_BCH24; >> + padding_len = MA35_BCH_PADDING_1024; >> + break; >> + case BCH_T12: >> + parity_len = MA35_PARITY_BCH12; >> + padding_len = MA35_BCH_PADDING_512; >> + break; >> + case BCH_T8: >> + parity_len = MA35_PARITY_BCH8; >> + padding_len = MA35_BCH_PADDING_512; >> + break; >> + default: >> + dev_warn(nand->dev, "NAND ERROR: invalid SMCR_BCH_TSEL = 0x%08X\n", >> + (u32)(readl(nand->regs + MA35_NFI_REG_NANDCTL) & BCH_MASK)); >> + return; >> + } >> + >> + /* got valid BCH_ECC_DATAx and parse them to temp_data[] >> + * got the valid register number of BCH_ECC_DATAx since >> + * one register include 4 error bytes >> + */ >> + j = (err_cnt + 3) / 4; >> + j = (j > 6) ? 6 : j; >> + for (i = 0; i < j; i++) >> + err_data[i] = readl(nand->regs + MA35_NFI_REG_NANDECCED0 + i * 4); >> + >> + for (i = 0; i < j; i++) { >> + temp_data[i*4+0] = err_data[i] & 0xff; >> + temp_data[i*4+1] = (err_data[i] >> 8) & 0xff; >> + temp_data[i*4+2] = (err_data[i] >> 16) & 0xff; >> + temp_data[i*4+3] = (err_data[i] >> 24) & 0xff; >> + } >> + >> + /* got valid REG_BCH_ECC_ADDRx and parse them to temp_addr[] >> + * got the valid register number of REG_BCH_ECC_ADDRx since >> + * one register include 2 error addresses >> + */ >> + j = (err_cnt + 1) / 2; >> + j = (j > 12) ? 12 : j; >> + for (i = 0; i < j; i++) { >> + temp_addr[i*2+0] = readl(nand->regs + MA35_NFI_REG_NANDECCEA0 + i * 4) >> + & 0x07ff; >> + temp_addr[i*2+1] = (readl(nand->regs + MA35_NFI_REG_NANDECCEA0 + i * 4) >> + >> 16) & 0x07ff; >> + } >> + >> + /* pointer to begin address of field that with data error */ >> + addr += index * nand->chip.ecc.steps; >> + >> + /* correct each error bytes */ >> + for (i = 0; i < err_cnt; i++) { >> + u32 corrected_index = temp_addr[i]; >> + >> + /* for wrong data in field */ >> + if (corrected_index < nand->chip.ecc.steps) >> + *(addr + corrected_index) ^= temp_data[i]; >> + >> + /* for wrong first-3-bytes in redundancy area */ >> + else if (corrected_index < (nand->chip.ecc.steps + 3)) { >> + corrected_index -= nand->chip.ecc.steps; >> + temp_addr[i] += (parity_len * index); /* field offset */ >> + >> + value = readl(nand->regs + MA35_NFI_REG_NANDRA0); >> + value ^= temp_data[i] << (8 * corrected_index); >> + writel(value, nand->regs + MA35_NFI_REG_NANDRA0); >> + } >> + /* for wrong parity code in redundancy area >> + * BCH_ERR_ADDRx = [data in field] + [3 bytes] + [xx] + [parity code] >> + * |<-- padding bytes -->| >> + * The BCH_ERR_ADDRx for last parity code always = field size + padding size. >> + * So, the first parity code = field size + padding size - parity code length. >> + * For example, for BCH T12, the first parity code = 512 + 32 - 23 = 521. >> + * That is, error byte address offset within field is >> + */ >> + else { >> + corrected_index -= (nand->chip.ecc.steps + padding_len - parity_len); >> + >> + /* final address = first parity code of first field + >> + * offset of fields + >> + * offset within field >> + */ >> + offset = (readl(nand->regs + MA35_NFI_REG_NANDRACTL) & 0x1ff) - >> + (parity_len * nand->chip.ecc.steps) + >> + (parity_len * index) + corrected_index; >> + >> + remain = offset % 4; >> + value = readl(nand->regs + MA35_NFI_REG_NANDRA0 + offset - remain); >> + value ^= temp_data[i] << (8 * remain); >> + writel(value, nand->regs + MA35_NFI_REG_NANDRA0 + offset - remain); >> + } >> + } >> +} >> + >> +static int ma35_nfi_ecc_check(struct nand_chip *chip, u8 *addr) >> +{ >> + struct ma35_nand_info *nand = nand_get_controller_data(chip); >> + struct mtd_info *mtd = nand_to_mtd(chip); >> + int i, j, nchunks = 0; >> + int report_err = 0; >> + int err_cnt = 0; >> + u32 status; >> + >> + nchunks = mtd->writesize / chip->ecc.steps; >> + if (nchunks < 4) >> + nchunks = 1; >> + else >> + nchunks /= 4; >> + >> + for (j = 0; j < nchunks; j++) { >> + status = readl(nand->regs + MA35_NFI_REG_NANDECCES0 + j * 4); >> + if (!status) >> + continue; >> + >> + for (i = 0; i < 4; i++) { >> + if (!(status & ECC_STATUS_MASK)) { >> + /* No error */ >> + status >>= 8; >> + continue; > Remove this block, it will do the same and be more clear. Indeed, this is unnecessary. I will remove it. >> + } else if ((status & ECC_STATUS_MASK) == 0x01) { >> + /* Correctable error */ >> + err_cnt = (status >> 2) & ECC_ERR_CNT_MASK; >> + ma35_nfi_correct(nand, j*4+i, err_cnt, addr); > Spacing ^^^^^^ I will check and fix it. >> + report_err += err_cnt; >> + } else { >> + /* uncorrectable error */ >> + dev_warn(nand->dev, "uncorrectable error! 0x%4x\n", status); >> + return -1; > Not a valid error code I will change it to return -EBADMSG; >> + } >> + status >>= 8; >> + } >> + } >> + return report_err; >> +} >> + >> +static void ma35_nand_dmac_init(struct ma35_nand_info *nand) >> +{ >> + /* DMAC reset and enable */ >> + writel(DMA_RST | DMA_EN, nand->regs + MA35_NFI_REG_DMACTL); >> + writel(DMA_EN, nand->regs + MA35_NFI_REG_DMACTL); >> + >> + /* Clear DMA finished flag */ >> + writel(INT_DMA | INT_ECC, nand->regs + MA35_NFI_REG_NANDINTSTS); >> + >> + init_completion(&nand->complete); > You're gonna call init_completion more than once during suspend/resume > cycles, this is unsafe. I will move init_completion to probe, and then add reinit_completion in the read/write page. >> +} >> + >> +static int ma35_nand_do_write(struct nand_chip *chip, const u8 *addr, u32 len) >> +{ >> + struct ma35_nand_info *nand = nand_get_controller_data(chip); >> + struct mtd_info *mtd = nand_to_mtd(chip); >> + dma_addr_t dma_addr; >> + int ret = 0, i; >> + u32 reg; >> + >> + if (len != mtd->writesize) { >> + for (i = 0; i < len; i++) >> + writel(addr[i], nand->regs + MA35_NFI_REG_NANDDATA); >> + return 0; >> + } >> + >> + ma35_nand_dmac_init(nand); >> + >> + writel(mtd->oobsize, nand->regs + MA35_NFI_REG_NANDRACTL); >> + >> + writel(INT_DMA, nand->regs + MA35_NFI_REG_NANDINTEN); >> + /* To mark this page as dirty. */ >> + reg = readl(nand->regs + MA35_NFI_REG_NANDRA0); >> + if (reg & 0xffff0000) >> + writel(reg & 0xffff, nand->regs + MA35_NFI_REG_NANDRA0); >> + >> + dma_addr = dma_map_single(nand->dev, (void *)addr, len, DMA_TO_DEVICE); >> + ret = dma_mapping_error(nand->dev, dma_addr); >> + if (ret) { >> + dev_err(nand->dev, "dma mapping error\n"); >> + return -EINVAL; >> + } >> + dma_sync_single_for_device(nand->dev, dma_addr, len, DMA_TO_DEVICE); >> + >> + writel((unsigned long)dma_addr, nand->regs + MA35_NFI_REG_DMASA); >> + writel(readl(nand->regs + MA35_NFI_REG_NANDCTL) | DMA_W_EN, >> + nand->regs + MA35_NFI_REG_NANDCTL); >> + ret = wait_for_completion_timeout(&nand->complete, msecs_to_jiffies(1000)); >> + if (!ret) { >> + dev_err(nand->dev, "write timeout\n"); >> + ret = -ETIMEDOUT; >> + } >> + >> + dma_unmap_single(nand->dev, dma_addr, len, DMA_TO_DEVICE); >> + >> + return ret; >> +} >> + >> +static int ma35_nand_do_read(struct nand_chip *chip, u8 *addr, u32 len) >> +{ >> + struct ma35_nand_info *nand = nand_get_controller_data(chip); >> + struct mtd_info *mtd = nand_to_mtd(chip); >> + int ret = 0, cnt = 0, i; >> + dma_addr_t dma_addr; >> + u32 reg; >> + >> + if (len != mtd->writesize) { >> + for (i = 0; i < len; i++) >> + *(addr+i) = (u8)readl(nand->regs + MA35_NFI_REG_NANDDATA); > Mmh, that line is strange. Please don't do that. > > addr[i] = readb() ? It will be fixed to readb(). >> + return 0; >> + } >> + >> + ma35_nand_dmac_init(nand); >> + >> + writel(mtd->oobsize, nand->regs + MA35_NFI_REG_NANDRACTL); >> + >> + /* setup and start DMA using dma_addr */ >> + dma_addr = dma_map_single(nand->dev, (void *)addr, len, DMA_FROM_DEVICE); >> + ret = dma_mapping_error(nand->dev, dma_addr); >> + if (ret) { >> + dev_err(nand->dev, "dma mapping error\n"); >> + return -EINVAL; >> + } >> + >> + writel((unsigned long)dma_addr, nand->regs + MA35_NFI_REG_DMASA); > Please enforce a dma mask of 32 (even though it might be the fault). I will change it to dma_addr & 0xffffffff. >> + writel(readl(nand->regs + MA35_NFI_REG_NANDCTL) | DMA_R_EN, >> + nand->regs + MA35_NFI_REG_NANDCTL); >> + ret = wait_for_completion_timeout(&nand->complete, msecs_to_jiffies(1000)); >> + if (!ret) { >> + dev_err(nand->dev, "read timeout\n"); >> + ret = -ETIMEDOUT; >> + } >> + >> + dma_unmap_single(nand->dev, dma_addr, len, DMA_FROM_DEVICE); >> + >> + reg = readl(nand->regs + MA35_NFI_REG_NANDINTSTS); >> + if (reg & INT_ECC) { >> + cnt = ma35_nfi_ecc_check(&nand->chip, addr); >> + if (cnt < 0) { >> + mtd->ecc_stats.failed++; >> + writel(DMA_RST | DMA_EN, nand->regs + MA35_NFI_REG_DMACTL); >> + writel(readl(nand->regs + MA35_NFI_REG_NANDCTL) | SWRST, >> + nand->regs + MA35_NFI_REG_NANDCTL); >> + } else { >> + mtd->ecc_stats.corrected += cnt; >> + nand->bitflips = cnt; >> + } >> + writel(INT_ECC, nand->regs + MA35_NFI_REG_NANDINTSTS); >> + } >> + >> + return ret; >> +} >> + >> +static int ma35_nand_write_page_hwecc(struct nand_chip *chip, const u8 *buf, >> + int oob_required, int page) >> +{ >> + struct mtd_info *mtd = nand_to_mtd(chip); >> + void *ecc_calc = chip->ecc.calc_buf; >> + >> + ma35_clear_spare(chip, mtd->oobsize); >> + ma35_write_spare(chip, mtd->oobsize - chip->ecc.total, >> + (u32 *)chip->oob_poi); >> + >> + nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); >> + nand_prog_page_end_op(chip); >> + >> + /* Copy parity code in NANDRA to calc */ >> + ma35_read_spare(chip, chip->ecc.total, (u32 *)ecc_calc, >> + mtd->oobsize - chip->ecc.total); >> + >> + /* Copy parity code in calc to oob_poi */ >> + memcpy(chip->oob_poi + (mtd->oobsize - chip->ecc.total), >> + ecc_calc, chip->ecc.total); >> + >> + return 0; >> +} >> + >> +static int ma35_nand_read_page_hwecc(struct nand_chip *chip, u8 *buf, >> + int oob_required, int page) >> +{ >> + struct ma35_nand_info *nand = nand_get_controller_data(chip); >> + struct mtd_info *mtd = nand_to_mtd(chip); >> + u32 reg; >> + >> + /* read the OOB area */ >> + nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); >> + nand->bitflips = 0; > Why storing this value in your structure? Because ecc.read_page needs to return bit flips, it is necessary to log them. >> + >> + /* copy OOB data to NANDRA for page read */ >> + ma35_write_spare(chip, mtd->oobsize, (u32 *)chip->oob_poi); >> + >> + reg = readl(nand->regs + MA35_NFI_REG_NANDRA0); >> + if (reg & 0xffff0000) { >> + memset((void *)buf, 0xff, mtd->writesize); >> + } else { >> + /* read data from nand */ >> + nand_read_page_op(chip, page, 0, buf, mtd->writesize); > ret = > if (ret) > ... I will add a return value here. >> + >> + /* restore OOB data from SMRA */ >> + ma35_read_spare(chip, mtd->oobsize, (u32 *)chip->oob_poi, 0); > > same ma35_read_spare() is declared as void, with no return value. SMRA will be changed to NANDRA registers. >> + } >> + >> + return nand->bitflips; >> +} >> + >> +static int ma35_nand_read_oob_hwecc(struct nand_chip *chip, int page) >> +{ >> + struct ma35_nand_info *nand = nand_get_controller_data(chip); >> + struct mtd_info *mtd = nand_to_mtd(chip); >> + u32 reg; >> + >> + nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); >> + >> + /* copy OOB data to NANDRA for page read */ > What is NANDRA? does not mean anything to me. NANDRA is the Redundant Area Word of the MA35 NAND controller. The controller reads ECC parity from this area for calculations or uses the information for check. I will change NANDRA to NANDRA registers. >> + ma35_write_spare(chip, mtd->oobsize, (u32 *)chip->oob_poi); >> + >> + reg = readl(nand->regs + MA35_NFI_REG_NANDRA0); >> + if (reg & 0xffff0000) >> + memset((void *)chip->oob_poi, 0xff, mtd->oobsize); > What does this mean? MA35 NAND controller checks oob bytes 2 and 3. If this page has been written, oob bytes 2 and 3 will be set to 0. Therefore, if bytes 2 and 3 are not 0, it indicates an empty page, and it will return 0xff. >> + >> + return 0; >> +} >> + >> +static irqreturn_t ma35_nand_irq(int irq, void *id) >> +{ >> + struct ma35_nand_info *nand = (struct ma35_nand_info *)id; >> + u32 isr; >> + >> + isr = readl(nand->regs + MA35_NFI_REG_NANDINTSTS); >> + if (isr & INT_DMA) { >> + writel(INT_DMA, nand->regs + MA35_NFI_REG_NANDINTSTS); >> + complete(&nand->complete); >> + } > I guess a more future proof implementation would always writel(isr); to > silence the interrupt. Otherwise of course you must call complete() > only upon isr & INT_DMA. This part can remove the if(), but writel(isr) is not feasible. The isr may contain the ECC flag, and clearing it could cause a miss in ECC handling. I will change it to:     writel(INT_DMA, nand->regs + MA35_NFI_REG_NANDINTSTS);     complete(&nand->complete); >> + >> + return IRQ_HANDLED; >> +} >> + >> +static int ma35_nand_attach_chip(struct nand_chip *chip) >> +{ >> + struct ma35_nand_info *nand = nand_get_controller_data(chip); >> + struct mtd_info *mtd = nand_to_mtd(chip); >> + unsigned int reg; >> + >> + if (chip->options & NAND_BUSWIDTH_16) { >> + dev_err(nand->dev, "16 bits bus width not supported"); >> + return -EINVAL; >> + } >> + >> + /* support only ecc hw mode */ > Why ? Please don't. I will add handling for other cases. >> + if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) { >> + dev_err(nand->dev, "ecc.engine_type not supported\n"); >> + return -EINVAL; >> + } >> + >> + nand->ecc_buf = devm_kzalloc(nand->dev, mtd->writesize + mtd->oobsize, >> + GFP_KERNEL); >> + if (!nand->ecc_buf) >> + return -ENOMEM; >> + chip->ecc.calc_buf = nand->ecc_buf; > Are you sure you need this? I don't see the point. This is unnecessary; I will remove it. >> + >> + /* Set PSize */ >> + reg = readl(nand->regs + MA35_NFI_REG_NANDCTL) & (~PSIZE_MASK); >> + if (mtd->writesize == 2048) >> + writel(reg | PSIZE_2K, nand->regs + MA35_NFI_REG_NANDCTL); >> + else if (mtd->writesize == 4096) >> + writel(reg | PSIZE_4K, nand->regs + MA35_NFI_REG_NANDCTL); >> + else if (mtd->writesize == 8192) >> + writel(reg | PSIZE_8K, nand->regs + MA35_NFI_REG_NANDCTL); >> + >> + chip->ecc.steps = mtd->writesize / chip->ecc.size; >> + if (chip->ecc.strength == 0) { >> + nand->bch = BCH_NONE; /* No ECC */ >> + chip->ecc.total = 0; >> + } else if (chip->ecc.strength <= 8) { >> + nand->bch = BCH_T8; /* T8 */ > bch is probably a bad name, and in general I don't see the point of > saving this value. Just check the ECC strength in the above switch > cases and don't use this intermediate variable. I will change it to directly use ecc.strength for the check. >> + chip->ecc.total = chip->ecc.steps * MA35_PARITY_BCH8; >> + } else if (chip->ecc.strength <= 12) { >> + nand->bch = BCH_T12; /* T12 */ >> + chip->ecc.total = chip->ecc.steps * MA35_PARITY_BCH12; >> + } else if (chip->ecc.strength <= 24) { >> + nand->bch = BCH_T24; /* T24 */ >> + chip->ecc.total = chip->ecc.steps * MA35_PARITY_BCH24; >> + } else { >> + dev_warn(nand->dev, "NAND Controller is not support this flash. (%d, %d)\n", >> + mtd->writesize, mtd->oobsize); > This must be a dev_err() and return an error immediately. > > Also the string is not correct. I will change it to:         dev_err(nand->dev, "ECC strength error\n");         return -EINVAL; >> + } >> + >> + chip->ecc.bytes = chip->ecc.total / chip->ecc.steps; >> + mtd_set_ooblayout(mtd, &ma35_ooblayout_ops); >> + >> + /* add mtd-id. The string should same as uboot definition */ >> + mtd->name = "nand0"; > No! There are DT labels for that and mtd->name will automatically be > set when calling nand_set_flash_node(). I will remove it. >> + >> + ma35_nand_hwecc_init(nand); >> + >> + writel(DISABLE_WP, nand->regs + MA35_NFI_REG_NANDECTL); >> + >> + return 0; >> +} >> + >> +static int ma35_nfc_exec_instr(struct nand_chip *chip, >> + const struct nand_op_instr *instr) >> +{ >> + struct ma35_nand_info *nand = nand_get_controller_data(chip); >> + unsigned int i; >> + u32 status; >> + >> + switch (instr->type) { >> + case NAND_OP_CMD_INSTR: >> + writel(instr->ctx.cmd.opcode, nand->regs + MA35_NFI_REG_NANDCMD); >> + return 0; >> + case NAND_OP_ADDR_INSTR: >> + for (i = 0; i < instr->ctx.addr.naddrs; i++) { >> + if (i == (instr->ctx.addr.naddrs - 1)) >> + writel(instr->ctx.addr.addrs[i] | ENDADDR, >> + nand->regs + MA35_NFI_REG_NANDADDR); >> + else >> + writel(instr->ctx.addr.addrs[i], >> + nand->regs + MA35_NFI_REG_NANDADDR); >> + } >> + return 0; >> + case NAND_OP_DATA_IN_INSTR: >> + ma35_nand_do_read(chip, instr->ctx.data.buf.in, instr->ctx.data.len); >> + return 0; >> + case NAND_OP_DATA_OUT_INSTR: >> + ma35_nand_do_write(chip, instr->ctx.data.buf.out, instr->ctx.data.len); >> + return 0; >> + case NAND_OP_WAITRDY_INSTR: >> + return readl_poll_timeout(nand->regs + MA35_NFI_REG_NANDINTSTS, status, >> + status & INT_RB0, 20, >> + instr->ctx.waitrdy.timeout_ms * 1000); > MSEC_PER_SEC I will change it to instr->ctx.waitrdy.timeout_ms * MSEC_PER_SEC. >> + default: >> + break; >> + } >> + >> + return -EINVAL; >> +} > This is much better than the legacy hooks! Thanks. >> + >> +static int ma35_nfc_exec_op(struct nand_chip *chip, >> + const struct nand_operation *op, >> + bool check_only) >> +{ >> + struct ma35_nand_info *nand = nand_get_controller_data(chip); >> + int ret = 0; >> + u32 i, reg; >> + >> + if (check_only) >> + return 0; >> + >> + ma35_nand_target_enable(nand); >> + >> + reg = readl(nand->regs + MA35_NFI_REG_NANDINTSTS); >> + reg |= INT_RB0; > This RB pin looks like something hardcoded, whereas it should not :-) > > If you have several RB, it means you have several CS as well! The MA35 NAND controller is indeed expected to support two sets of CS and RB. However, currently, the MA35 series only supports one set, so this name will be changed to RB. >> + writel(reg, nand->regs + MA35_NFI_REG_NANDINTSTS); >> + >> + for (i = 0; i < op->ninstrs; i++) { >> + ret = ma35_nfc_exec_instr(chip, &op->instrs[i]); >> + if (ret) >> + break; >> + } >> + >> + ma35_nand_target_disable(nand); >> + >> + return ret; >> +} >> + >> +static const struct nand_controller_ops ma35_nfc_ops = { >> + .attach_chip = ma35_nand_attach_chip, >> + .exec_op = ma35_nfc_exec_op, >> +}; >> + >> +static int ma35_nand_probe(struct platform_device *pdev) >> +{ >> + struct ma35_nand_info *nand; >> + struct nand_chip *chip; >> + struct mtd_info *mtd; >> + int ret = 0; >> + >> + nand = devm_kzalloc(&pdev->dev, sizeof(*nand), GFP_KERNEL); >> + if (!nand) >> + return -ENOMEM; >> + >> + nand_controller_init(&nand->controller); >> + nand->controller.ops = &ma35_nfc_ops; >> + >> + nand->regs = devm_platform_ioremap_resource(pdev, 0); >> + if (IS_ERR(nand->regs)) >> + return PTR_ERR(nand->regs); >> + >> + nand->dev = &pdev->dev; >> + chip = &nand->chip; >> + nand_set_controller_data(chip, nand); >> + nand_set_flash_node(chip, pdev->dev.of_node); >> + >> + nand->clk = devm_clk_get_enabled(&pdev->dev, "nand_gate"); >> + if (IS_ERR(nand->clk)) >> + return dev_err_probe(&pdev->dev, PTR_ERR(nand->clk), >> + "failed to find nand clock\n"); > NAND I will fix it. >> + >> + nand->irq = platform_get_irq(pdev, 0); >> + if (nand->irq < 0) >> + return dev_err_probe(&pdev->dev, nand->irq, >> + "failed to get platform irq\n"); >> + >> + ret = devm_request_irq(&pdev->dev, nand->irq, ma35_nand_irq, >> + IRQF_TRIGGER_HIGH, "ma35d1-nand", nand); >> + if (ret) { >> + dev_err(&pdev->dev, "failed to request NAND irq\n"); >> + return -ENXIO; >> + } >> + >> + nand->chip.controller = &nand->controller; >> + platform_set_drvdata(pdev, nand); >> + >> + chip->options |= NAND_NO_SUBPAGE_WRITE | NAND_USES_DMA; >> + >> + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; >> + chip->ecc.write_page = ma35_nand_write_page_hwecc; >> + chip->ecc.read_page = ma35_nand_read_page_hwecc; >> + chip->ecc.read_oob = ma35_nand_read_oob_hwecc; > You support to disable the ECC engine, so you must support software > corrections as well. Please don't force hw ECC use. Please look at > other implementations, there is usually a helper with a switch case > which supports various ECC configurations. I will refer to other implementations and will add handling for other cases. >> + >> + mtd = nand_to_mtd(chip); >> + mtd->priv = chip; >> + mtd->owner = THIS_MODULE; >> + mtd->dev.parent = &pdev->dev; >> + >> + writel(NAND_EN, nand->regs + MA35_NFI_REG_GCTL); > I would expect your reset bit to be set before this writel. Are you referring to SWRST? I will call the reset engine before enabling it. >> + >> + ret = nand_scan(chip, 1); >> + if (ret) >> + return ret; >> + >> + ret = mtd_device_register(mtd, NULL, 0); >> + if (ret) { >> + nand_cleanup(chip); >> + return ret; >> + } >> + >> + return ret; > return 0; then I will change it to return 0; >> +} >> + >> +static void ma35_nand_remove(struct platform_device *pdev) >> +{ >> + struct ma35_nand_info *nand = platform_get_drvdata(pdev); >> + int ret; >> + >> + ret = mtd_device_unregister(nand_to_mtd(&nand->chip)); >> + WARN_ON(ret); >> + nand_cleanup(&nand->chip); >> +} >> + >> +/* PM Support */ >> +#ifdef CONFIG_PM >> +static int ma35_nand_suspend(struct platform_device *pdev, pm_message_t pm) >> +{ >> + struct ma35_nand_info *nand = platform_get_drvdata(pdev); >> + int ret = 0; >> + u32 val; >> + >> + /* wait DMAC to ready */ > be I will fix it. >> + ret = readl_poll_timeout(nand->regs + MA35_NFI_REG_DMACTL, val, >> + !(val & DMA_BUSY), 50, HZ/2); >> + if (ret) >> + dev_warn(&pdev->dev, "dma busy\n"); > DMA > > And please make a sentence. I will fix it. >> + >> + clk_disable(nand->clk); > If you decide to return ret != 0, shall you really disable this clock ? I will change it to:     /* wait DMAC to be ready */     ret = readl_poll_timeout(nand->regs + MA35_NFI_REG_DMACTL, val,                  !(val & DMA_BUSY), 50, HZ/2);     if (ret) {         dev_warn(&pdev->dev, "wait DMA done timeout.\n");         return ret;     }     clk_disable(nand->clk);     return 0; >> + >> + return ret; >> +} >> + >> +static int ma35_nand_resume(struct platform_device *pdev) >> +{ >> + struct ma35_nand_info *nand = platform_get_drvdata(pdev); >> + >> + clk_enable(nand->clk); >> + ma35_nand_hwecc_init(nand); > The naming is wrong. This init is not just the hw ECC controller. This will be changed to handle the initialization of the NAND controller and ECC controller. It will also call nand_reset(). >> + ma35_nand_dmac_init(nand); >> + >> + return 0; >> +} >> + >> +#else >> +#define ma35_nand_suspend NULL >> +#define ma35_nand_resume NULL >> +#endif >> + >> +static const struct of_device_id ma35_nfi_of_match[] = { > ma35_nfi or ma35_nand, take one and please stick to it. Will be unified into ma35_nand. >> + { .compatible = "nuvoton,ma35d1-nand" }, >> + {}, >> +}; >> +MODULE_DEVICE_TABLE(of, ma35_nfi_of_match); >> + >> +static struct platform_driver ma35_nand_driver = { >> + .driver = { >> + .name = "ma35d1-nand", >> + .of_match_table = ma35_nfi_of_match, >> + }, >> + .probe = ma35_nand_probe, >> + .remove = ma35_nand_remove, >> + .suspend = ma35_nand_suspend, >> + .resume = ma35_nand_resume, >> +}; >> + >> +module_platform_driver(ma35_nand_driver); >> + >> +MODULE_DESCRIPTION("Nuvoton ma35 NAND driver"); >> +MODULE_AUTHOR("Hui-Ping Chen "); >> +MODULE_LICENSE("GPL"); > > Thanks, > Miquèl Best regards, Hui-Ping Chen