From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.2 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_2 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EAF9CC38A2A for ; Thu, 7 May 2020 15:46:32 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id B454F2082E for ; Thu, 7 May 2020 15:46:32 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="DRhpAcS+" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B454F2082E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=bootlin.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-mtd-bounces+linux-mtd=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Subject:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=mTh14PYbSjJyBpYdxnkC/d5MgrOf3bHTkEEyAJFnikA=; b=DRhpAcS+tcGwcc 1XOnjRkmMWAH6EK1d8iPD1GTk4J3HiPoDutf+Jz3R5EmUCGxz9+0FmXLwmxIuSOkYkIH1zdG7Z8kg qA+eg3XABybKLFlDFjveMQNTf0M4OTPirNWq6ovXIPBHr2e8rIgmAwM1Mstg/j5WAp6R8/9XUOXPh qjTnZRijclfeTWyN7ye2/06ThIJ8DSsTlcCgs9N4LKo/mRDZljZa1FNQTCwBG5OqJfj9wg4RjVxeh wIjSums3LyofyBYLSNQYUtcRwHsxOx9XZ6lq3eyeeDZjMcbTJtzxFY3Ux6ISSXwUaUHYNmP6sumOQ YnijLdWNVD8p43/3EuJQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jWiiz-0002bV-9d; Thu, 07 May 2020 15:46:13 +0000 Received: from relay1-d.mail.gandi.net ([217.70.183.193]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jWiis-0002Re-HE for linux-mtd@lists.infradead.org; Thu, 07 May 2020 15:46:10 +0000 X-Originating-IP: 91.224.148.103 Received: from xps13 (unknown [91.224.148.103]) (Authenticated sender: miquel.raynal@bootlin.com) by relay1-d.mail.gandi.net (Postfix) with ESMTPSA id 9A00E24000D; Thu, 7 May 2020 15:46:00 +0000 (UTC) Date: Thu, 7 May 2020 17:45:59 +0200 From: Miquel Raynal To: Boris Brezillon Subject: Re: [PATCH v3 7/8] mtd: rawnand: arasan: Add new Arasan NAND controller Message-ID: <20200507174559.58b57452@xps13> In-Reply-To: <20200507145127.71615ed8@collabora.com> References: <20200507110034.14736-1-miquel.raynal@bootlin.com> <20200507110034.14736-8-miquel.raynal@bootlin.com> <20200507145127.71615ed8@collabora.com> Organization: Bootlin X-Mailer: Claws Mail 3.17.4 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200507_084606_851970_DBAC1453 X-CRM114-Status: GOOD ( 25.87 ) X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , devicetree@vger.kernel.org, Michal Simek , Vignesh Raghavendra , Tudor Ambarus , Richard Weinberger , Rob Herring , linux-mtd@lists.infradead.org, Thomas Petazzoni , Naga Sureshkumar Relli Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-mtd" Errors-To: linux-mtd-bounces+linux-mtd=archiver.kernel.org@lists.infradead.org SGkgQm9yaXMsCgpCb3JpcyBCcmV6aWxsb24gPGJvcmlzLmJyZXppbGxvbkBjb2xsYWJvcmEuY29t PiB3cm90ZSBvbiBUaHUsIDcgTWF5CjIwMjAgMTQ6NTE6MjcgKzAyMDA6Cgo+IE9uIFRodSwgIDcg TWF5IDIwMjAgMTM6MDA6MzMgKzAyMDAKPiBNaXF1ZWwgUmF5bmFsIDxtaXF1ZWwucmF5bmFsQGJv b3RsaW4uY29tPiB3cm90ZToKPiAKPiAKPiA+ICsvKioKPiA+ICsgKiBzdHJ1Y3QgYXJhc2FuX25m YyAtIERlZmluZXMgdGhlIEFyYXNhbiBOQU5EIGZsYXNoIGNvbnRyb2xsZXIgZHJpdmVyIGluc3Rh bmNlCj4gPiArICogQGRldjoJCVBvaW50ZXIgdG8gdGhlIGRldmljZSBzdHJ1Y3R1cmUKPiA+ICsg KiBAYmFzZToJCVJlbWFwcGVkIHJlZ2lzdGVyIGFyZWEKPiA+ICsgKiBAY29udHJvbGxlcl9jbGs6 CQlQb2ludGVyIHRvIHRoZSBzeXN0ZW0gY2xvY2sKPiA+ICsgKiBAYnVzX2NsazoJCVBvaW50ZXIg dG8gdGhlIGZsYXNoIGNsb2NrCj4gPiArICogQGNvbnRyb2xsZXI6CQlCYXNlIGNvbnRyb2xsZXIg c3RydWN0dXJlCj4gPiArICogQGNoaXBzOgkJTGlzdCBvZiBhbGwgTkFORCBjaGlwcyBhdHRhY2hl ZCB0byB0aGUgY29udHJvbGxlcgo+ID4gKyAqIEBhc3NpZ25lZF9jczoJQml0bWFzayBkZXNjcmli aW5nIGFscmVhZHkgYXNzaWduZWQgQ1MgbGluZXMKPiA+ICsgKiBAY3VyX2NsazoJCUN1cnJlbnQg Y2xvY2sgcmF0ZQo+ID4gKyAqIEBiZjoJCQlBcnJheSBvZiBiaXRmbGlwcyByZWFkIGluIGVhY2gg RUNDIHN0ZXAKPiA+ICsgKi8KPiA+ICtzdHJ1Y3QgYXJhc2FuX25mYyB7Cj4gPiArCXN0cnVjdCBk ZXZpY2UgKmRldjsKPiA+ICsJdm9pZCBfX2lvbWVtICpiYXNlOwo+ID4gKwlzdHJ1Y3QgY2xrICpj b250cm9sbGVyX2NsazsKPiA+ICsJc3RydWN0IGNsayAqYnVzX2NsazsKPiA+ICsJc3RydWN0IG5h bmRfY29udHJvbGxlciBjb250cm9sbGVyOwo+ID4gKwlzdHJ1Y3QgbGlzdF9oZWFkIGNoaXBzOwo+ ID4gKwl1bnNpZ25lZCBsb25nIGFzc2lnbmVkX2NzOwo+ID4gKwl1bnNpZ25lZCBpbnQgY3VyX2Ns azsKPiA+ICsJdTggKmJmOyAgCj4gCj4gTG9va3MgbGlrZSB0aGlzIGZpZWxkIGlzIG5ldmVyIHVz ZWQuCgpZZXMsIGl0IGlzIGEgbGVmdCBvdmVyIG9mIGEgcHJldmlvdXMgaW1wbGVtZW50YXRpb24s IEknbGwgZHJvcCBpdC4KCj4gCj4gPiArfTsKPiA+ICsKPiA+ICtzdGF0aWMgc3RydWN0IGFuYW5k ICp0b19hbmFuZChzdHJ1Y3QgbmFuZF9jaGlwICpuYW5kKQo+ID4gK3sKPiA+ICsJcmV0dXJuIGNv bnRhaW5lcl9vZihuYW5kLCBzdHJ1Y3QgYW5hbmQsIGNoaXApOwo+ID4gK30KPiA+ICsKPiA+ICtz dGF0aWMgc3RydWN0IGFyYXNhbl9uZmMgKnRvX2FuZmMoc3RydWN0IG5hbmRfY29udHJvbGxlciAq Y3RybCkKPiA+ICt7Cj4gPiArCXJldHVybiBjb250YWluZXJfb2YoY3RybCwgc3RydWN0IGFyYXNh bl9uZmMsIGNvbnRyb2xsZXIpOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgdm9pZCBhbmZjX2Rp c2FibGVfaW50KHN0cnVjdCBhcmFzYW5fbmZjICpuZmMsIHUzMiBtYXNrKQo+ID4gK3sKPiA+ICsJ bWFzayAmPSB+RVZFTlRfTUFTSzsKPiA+ICsJbWFzayAmPSBFVkVOVF9NQVNLOwo+ID4gKwl3cml0 ZWxfcmVsYXhlZChtYXNrLCBuZmMtPmJhc2UgKyBJTlRSX1NJR19FTl9SRUcpOwo+ID4gK30KPiA+ ICsKPiA+ICtzdGF0aWMgaW50IGFuZmNfd2FpdF9mb3JfZXZlbnQoc3RydWN0IGFyYXNhbl9uZmMg Km5mYywgdW5zaWduZWQgaW50IGV2ZW50KQo+ID4gK3sKPiA+ICsJdTMyIHZhbDsKPiA+ICsJaW50 IHJldDsKPiA+ICsKPiA+ICsJcmV0ID0gcmVhZGxfcmVsYXhlZF9wb2xsX3RpbWVvdXQobmZjLT5i YXNlICsgSU5UUl9TVFNfUkVHLCB2YWwsCj4gPiArCQkJCQkgdmFsICYgZXZlbnQsIDAsCj4gPiAr CQkJCQkgQU5GQ19ERkxUX1RJTUVPVVRfVVMpOwo+ID4gKwlpZiAocmV0KSB7Cj4gPiArCQlkZXZf ZXJyKG5mYy0+ZGV2LCAiVGltZW91dCB3YWl0aW5nIGZvciBldmVudCAweCV4XG4iLCBldmVudCk7 Cj4gPiArCQlyZXR1cm4gLUVUSU1FRE9VVDsKPiA+ICsJfQo+ID4gKwo+ID4gKwl3cml0ZWxfcmVs YXhlZChldmVudCwgbmZjLT5iYXNlICsgSU5UUl9TVFNfUkVHKTsKPiA+ICsKPiA+ICsJcmV0dXJu IDA7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgYW5mY193YWl0X2Zvcl9yYihzdHJ1Y3Qg YXJhc2FuX25mYyAqbmZjLCBzdHJ1Y3QgbmFuZF9jaGlwICpjaGlwLAo+ID4gKwkJCSAgICB1bnNp Z25lZCBpbnQgdGltZW91dF9tcykKPiA+ICt7Cj4gPiArCXN0cnVjdCBhbmFuZCAqYW5hbmQgPSB0 b19hbmFuZChjaGlwKTsKPiA+ICsJdTMyIHZhbDsKPiA+ICsJaW50IHJldDsKPiA+ICsKPiA+ICsJ cmV0ID0gcmVhZGxfcmVsYXhlZF9wb2xsX3RpbWVvdXQobmZjLT5iYXNlICsgUkVBRFlfU1RTX1JF RywgdmFsLAo+ID4gKwkJCQkJIHZhbCAmIEJJVChhbmFuZC0+cmIpLAo+ID4gKwkJCQkJIDAsIHRp bWVvdXRfbXMgKiAxMDAwKTsgIAo+IAo+IFlvdSBkb24ndCBoYXZlIGFuIGludGVycnVwdCBvbiBS L0IgdHJhbnNpdGlvbj8gSWYgY2FuLCB0aGF0IHdvdWxkCj4gcHJvYmFibHkgYmUgYmV0dGVyIHRv IHVzZSBpbnRlcnJ1cHRzIHRoYW4gcG9sbGluZyB0aGUgc3RhdHVzIHJlZy4KCk5vLCB0aGVyZSBh cmUgaW50ZXJydXB0cyBmb3IgdGhlIG90aGVyIHNpZ25hbHMsIGJ1dCBub25lIGZvciBSQi4KCkhl cmUgaXMgdGhlIGV4aGF1c3RpdmUgbGlzdCBvZiBhdmFpbGFibGUgaW50ZXJydXB0czoKaHR0cHM6 Ly93d3cueGlsaW54LmNvbS9odG1sX2RvY3MvcmVnaXN0ZXJzL3VnMTA4Ny91ZzEwODctenlucS11 bHRyYXNjYWxlLXJlZ2lzdGVycy5odG1sCgo+IAo+ID4gKwlpZiAocmV0KSB7Cj4gPiArCQlkZXZf ZXJyKG5mYy0+ZGV2LCAiVGltZW91dCB3YWl0aW5nIGZvciBSL0IgMHgleFxuIiwKPiA+ICsJCQly ZWFkbF9yZWxheGVkKG5mYy0+YmFzZSArIFJFQURZX1NUU19SRUcpKTsKPiA+ICsJCXJldHVybiAt RVRJTUVET1VUOwo+ID4gKwl9Cj4gPiArCj4gPiArCXJldHVybiAwOwo+ID4gK30KPiA+ICsKPiA+ ICtzdGF0aWMgdm9pZCBhbmZjX3RyaWdnZXJfb3Aoc3RydWN0IGFyYXNhbl9uZmMgKm5mYywgc3Ry dWN0IGFuZmNfb3AgKm5mY19vcCkKPiA+ICt7Cj4gPiArCXdyaXRlbF9yZWxheGVkKG5mY19vcC0+ cGt0X3JlZywgbmZjLT5iYXNlICsgUEtUX1JFRyk7Cj4gPiArCXdyaXRlbF9yZWxheGVkKG5mY19v cC0+YWRkcjFfcmVnLCBuZmMtPmJhc2UgKyBNRU1fQUREUjFfUkVHKTsKPiA+ICsJd3JpdGVsX3Jl bGF4ZWQobmZjX29wLT5hZGRyMl9yZWcsIG5mYy0+YmFzZSArIE1FTV9BRERSMl9SRUcpOwo+ID4g Kwl3cml0ZWxfcmVsYXhlZChuZmNfb3AtPmNtZF9yZWcsIG5mYy0+YmFzZSArIENNRF9SRUcpOwo+ ID4gKwl3cml0ZWxfcmVsYXhlZChuZmNfb3AtPnByb2dfcmVnLCBuZmMtPmJhc2UgKyBQUk9HX1JF Ryk7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgYW5mY19sZW5fdG9fc3RlcHMoc3RydWN0 IG5hbmRfY2hpcCAqY2hpcCwgdW5zaWduZWQgaW50IGxlbikKPiA+ICt7Cj4gPiArCXVuc2lnbmVk IGludCBzdGVwcyA9IDEsIHBrdHNpemUgPSBsZW47Cj4gPiArCj4gPiArCXdoaWxlIChwa3RzaXpl ID4gQU5GQ19NQVhfUEtUX1NJWkUpIHsKPiA+ICsJCXN0ZXBzICo9IDI7Cj4gPiArCQlwa3RzaXpl ID0gRElWX1JPVU5EX1VQKGxlbiwgc3RlcHMpOyAgCj4gCj4gSG0sIEknbSBub3Qgc3VyZSB0aGF0 J3MgcmlnaHQuIFdoYXQgaGFwcGVucyBpZiBzdGVwcyAqIHBrc2l6ZSBpcyBiaWdnZXIKPiB0aGFu IHRoZSByZXF1ZXN0ZWQgbnVtYmVyIG9mIERBVEEgY3ljbGVzPyBOb3QgYWxsIG9wZXJhdGlvbnMg YWNjZXB0IHRvCj4gaGF2ZSBtb3JlIGRhdGEgcmVhZC93cml0dGVuIHRoYW4gcmVxdWVzdGVkLgo+ IAo+IEknZCByYXRoZXIgaGF2ZSBzb21ldGhpbmcgdGhhdCBkb2VzOgo+IAo+IHN0YXRpYyB2b2lk IGFuZmNfbGVuX3RvX3N0ZXBzKHN0cnVjdCBuYW5kX2NoaXAgKmNoaXAsIHVuc2lnbmVkIGludCBs ZW4sCj4gCQkJICAgICAgdW5zaWduZWQgaW50ICpwa3RzaXplLAo+IAkJCSAgICAgIHVuc2lnbmVk IGludCAqbnBrdHMpCj4gewo+IAlpZiAobGVuIDw9IEFORkNfTUFYX1BLVF9TSVpFKSB7Cj4gCQkq cGt0c2l6ZSA9IGxlbjsKPiAJCSpucGt0cyA9IDE7Cj4gCQlyZXR1cm47Cj4gCX0KPiAKPiAJZm9y ICgqbnBrdHMgPSAyOyAqbnBrdHMgPCBBTkZDX01BWF9OVU1fUEtUUzsgKm5wa3RzICo9IDIpIHsK PiAJCSpwa3RzaXplID0gbGVuIC8gKm5wa3RzOwo+IAkJaWYgKCpwa3RzaXplIDw9IEFORkNfTUFY X1BLVF9TSVpFKQo+IAkJCWJyZWFrOwo+IAl9Cj4gfQo+IAo+IEFuZCB0aGVuLCBmcm9tIHRoZSBj YWxsIHNpemUsIHlvdSB0cmlnZ2VyIG5ldyBEQVRBX09VVC9JTiBvcGVyYXRpb24gaWYKPiBsZW4g PiBwa3RzaXplICogbnBrdHMuCgpUaGF0J3Mgc29tZXRoaW5nIEkgY2Fubm90IGRvIHdpdGggdGhp cyBjb250cm9sbGVyLCB1bmZvcnR1bmF0ZWx5Li4uIEl0CmRvZXMgbm90IHN1cHBvcnQgcmVhZC93 cml0ZSBvbmx5IHBhdHRlcm5zLiBTZWUgYmVsb3cuCgo+IAo+ID4gKwl9Cj4gPiArCj4gPiArCXJl dHVybiBzdGVwczsgIAo+IAo+IEkgZ3Vlc3MgeW91IGhhdmUgYSBsaW1pdCBvbiBzdGVwcy4gSXQn cyBwcm9iYWJseSB3b3J0aCBjaGVja2luZwo+IHRoYXQgc3RlcHMgaXMgaW4gYm91bmRzLgoKVGhl IHVwcGVyIGxpbWl0IGlzIDIwNDgsIEknbSBub3Qgc3VyZSBpdCBpcyByZWxldmFudCB0byBhZGQg YSBjaGVjawpoZXJlPwo+IAo+ID4gK30KPiA+ICsKPiA+ICsvKiBOQU5EIGZyYW1ld29yayAtPmV4 ZWNfb3AoKSBob29rcyBhbmQgcmVsYXRlZCBoZWxwZXJzICovCj4gPiArc3RhdGljIHZvaWQgYW5m Y19wYXJzZV9pbnN0cnVjdGlvbnMoc3RydWN0IG5hbmRfY2hpcCAqY2hpcCwKPiA+ICsJCQkJICAg IGNvbnN0IHN0cnVjdCBuYW5kX3N1Ym9wICpzdWJvcCwKPiA+ICsJCQkJICAgIHN0cnVjdCBhbmZj X29wICpuZmNfb3ApCj4gPiArewo+ID4gKwlzdHJ1Y3QgYW5hbmQgKmFuYW5kID0gdG9fYW5hbmQo Y2hpcCk7Cj4gPiArCWNvbnN0IHN0cnVjdCBuYW5kX29wX2luc3RyICppbnN0ciA9IE5VTEw7Cj4g PiArCWJvb2wgZmlyc3RfY21kID0gdHJ1ZTsKPiA+ICsJdW5zaWduZWQgaW50IG9wX2lkOwo+ID4g KwlpbnQgaTsKPiA+ICsKPiA+ICsJbWVtc2V0KG5mY19vcCwgMCwgc2l6ZW9mKCpuZmNfb3ApKTsK PiA+ICsJbmZjX29wLT5hZGRyMl9yZWcgPSBBRERSMl9DUyhhbmFuZC0+Y3MpOwo+ID4gKwluZmNf b3AtPmNtZF9yZWcgPSBDTURfUEFHRV9TSVpFKGFuYW5kLT5wYWdlX3N6KTsKPiA+ICsKPiA+ICsJ Zm9yIChvcF9pZCA9IDA7IG9wX2lkIDwgc3Vib3AtPm5pbnN0cnM7IG9wX2lkKyspIHsKPiA+ICsJ CXVuc2lnbmVkIGludCBvZmZzZXQsIG5hZGRycywgcGt0c2l6ZTsKPiA+ICsJCWNvbnN0IHU4ICph ZGRyczsKPiA+ICsJCXU4ICpidWY7Cj4gPiArCj4gPiArCQlpbnN0ciA9ICZzdWJvcC0+aW5zdHJz W29wX2lkXTsKPiA+ICsKPiA+ICsJCXN3aXRjaCAoaW5zdHItPnR5cGUpIHsKPiA+ICsJCWNhc2Ug TkFORF9PUF9DTURfSU5TVFI6Cj4gPiArCQkJaWYgKGZpcnN0X2NtZCkKPiA+ICsJCQkJbmZjX29w LT5jbWRfcmVnIHw9IENNRF8xKGluc3RyLT5jdHguY21kLm9wY29kZSk7Cj4gPiArCQkJZWxzZQo+ ID4gKwkJCQluZmNfb3AtPmNtZF9yZWcgfD0gQ01EXzIoaW5zdHItPmN0eC5jbWQub3Bjb2RlKTsK PiA+ICsKPiA+ICsJCQlmaXJzdF9jbWQgPSBmYWxzZTsKPiA+ICsJCQlicmVhazsKPiA+ICsKPiA+ ICsJCWNhc2UgTkFORF9PUF9BRERSX0lOU1RSOgo+ID4gKwkJCW9mZnNldCA9IG5hbmRfc3Vib3Bf Z2V0X2FkZHJfc3RhcnRfb2ZmKHN1Ym9wLCBvcF9pZCk7Cj4gPiArCQkJbmFkZHJzID0gbmFuZF9z dWJvcF9nZXRfbnVtX2FkZHJfY3ljKHN1Ym9wLCBvcF9pZCk7Cj4gPiArCQkJYWRkcnMgPSAmaW5z dHItPmN0eC5hZGRyLmFkZHJzW29mZnNldF07Cj4gPiArCQkJbmZjX29wLT5jbWRfcmVnIHw9IENN RF9OQUREUlMobmFkZHJzKTsKPiA+ICsKPiA+ICsJCQlmb3IgKGkgPSAwOyBpIDwgbWluKEFORkNf TUFYX0FERFJfQ1lDLCBuYWRkcnMpOyBpKyspIHsKPiA+ICsJCQkJaWYgKGkgPCA0KQo+ID4gKwkJ CQkJbmZjX29wLT5hZGRyMV9yZWcgfD0gKHUzMilhZGRyc1tpXSA8PCBpICogODsKPiA+ICsJCQkJ ZWxzZQo+ID4gKwkJCQkJbmZjX29wLT5hZGRyMl9yZWcgfD0gYWRkcnNbaV07Cj4gPiArCQkJfQo+ ID4gKwo+ID4gKwkJCWJyZWFrOwo+ID4gKwkJY2FzZSBOQU5EX09QX0RBVEFfSU5fSU5TVFI6Cj4g PiArCQkJbmZjX29wLT5yZWFkID0gdHJ1ZTsKPiA+ICsJCQlmYWxsdGhyb3VnaDsKPiA+ICsJCWNh c2UgTkFORF9PUF9EQVRBX09VVF9JTlNUUjoKPiA+ICsJCQlvZmZzZXQgPSBuYW5kX3N1Ym9wX2dl dF9kYXRhX3N0YXJ0X29mZihzdWJvcCwgb3BfaWQpOwo+ID4gKwkJCWJ1ZiA9IGluc3RyLT5jdHgu ZGF0YS5idWYuaW47Cj4gPiArCQkJbmZjX29wLT5idWYgPSAmYnVmW29mZnNldF07Cj4gPiArCQkJ bmZjX29wLT5sZW4gPSBuYW5kX3N1Ym9wX2dldF9kYXRhX2xlbihzdWJvcCwgb3BfaWQpOwo+ID4g KwkJCW5mY19vcC0+c3RlcHMgPSBhbmZjX2xlbl90b19zdGVwcyhjaGlwLCBuZmNfb3AtPmxlbik7 Cj4gPiArCQkJcGt0c2l6ZSA9IERJVl9ST1VORF9VUChuZmNfb3AtPmxlbiwgbmZjX29wLT5zdGVw cyk7Cj4gPiArCQkJbmZjX29wLT5wa3RfcmVnIHw9IFBLVF9TSVpFKHJvdW5kX3VwKHBrdHNpemUs IDQpKSB8ICAKPiAKPiBIbSwgcGt0c2l6ZSBoYXMgdG8gYmUgYWxpZ25lZCBvbiA0PyBBZ2Fpbiwg dGhhdCdzIG5vdCBncmVhdCBzaW5jZSB5b3UKPiBhZGp1c3QgdGhlIHNpemUgd2l0aG91dCBsZXR0 aW5nIHRoZSBjb3JlIGtub3cgeW91IGRpZCB0aGF0LgoKTW1taCBwcm9iYWJseSBub3QsIEkgd2ls bCB0ZXN0IHRoYXQuCgpCdXQgYSBGSUZPIHJlYWQgaXMgNCBieXRlcyBsb25nIHNvIGFueXdheSwg aXQgd2lsbCBwcm9iYWJseSByZWFkL3dyaXRlCm1vcmUgbm8gbWF0dGVyIHdoYXQgSSByZXF1ZXN0 IChhbmQgbW92ZSB0aGUgU1JBTSBwb2ludGVyKS4KCj4gCj4gPiArCQkJCQkgICBQS1RfU1RFUFMo bmZjX29wLT5zdGVwcyk7Cj4gPiArCQkJYnJlYWs7Cj4gPiArCQljYXNlIE5BTkRfT1BfV0FJVFJE WV9JTlNUUjoKPiA+ICsJCQluZmNfb3AtPnJkeV90aW1lb3V0X21zID0gaW5zdHItPmN0eC53YWl0 cmR5LnRpbWVvdXRfbXM7Cj4gPiArCQkJYnJlYWs7Cj4gPiArCQl9Cj4gPiArCX0KPiA+ICt9Cj4g PiArCj4gPiArc3RhdGljIGludCBhbmZjX3J3X3Bpb19vcChzdHJ1Y3QgYXJhc2FuX25mYyAqbmZj LCBzdHJ1Y3QgYW5mY19vcCAqbmZjX29wKQo+ID4gK3sKPiA+ICsJdW5zaWduZWQgaW50IGR3b3Jk cyA9IChuZmNfb3AtPmxlbiAvIDQpIC8gbmZjX29wLT5zdGVwczsKPiA+ICsJdW5zaWduZWQgaW50 IGxhc3RfbGVuID0gbmZjX29wLT5sZW4gJSA0Owo+ID4gKwl1bnNpZ25lZCBpbnQgb2Zmc2V0LCBk aXI7Cj4gPiArCXU4ICpidWYgPSBuZmNfb3AtPmJ1ZjsKPiA+ICsJaW50IHJldCwgaTsKPiA+ICsK PiA+ICsJZm9yIChpID0gMDsgaSA8IG5mY19vcC0+c3RlcHM7IGkrKykgewo+ID4gKwkJZGlyID0g bmZjX29wLT5yZWFkID8gUkVBRF9SRUFEWSA6IFdSSVRFX1JFQURZOwo+ID4gKwkJcmV0ID0gYW5m Y193YWl0X2Zvcl9ldmVudChuZmMsIGRpcik7Cj4gPiArCQlpZiAocmV0KSB7Cj4gPiArCQkJZGV2 X2VycihuZmMtPmRldiwgIlBJTyAlcyByZWFkeSBzaWduYWwgbm90IHJlY2VpdmVkXG4iLAo+ID4g KwkJCQluZmNfb3AtPnJlYWQgPyAiUmVhZCIgOiAiV3JpdGUiKTsKPiA+ICsJCQlyZXR1cm4gcmV0 Owo+ID4gKwkJfQo+ID4gKwo+ID4gKwkJb2Zmc2V0ID0gaSAqIChkd29yZHMgKiA0KTsKPiA+ICsJ CWlmIChuZmNfb3AtPnJlYWQpCj4gPiArCQkJaW9yZWFkMzJfcmVwKG5mYy0+YmFzZSArIERBVEFf UE9SVF9SRUcsICZidWZbb2Zmc2V0XSwKPiA+ICsJCQkJICAgICBkd29yZHMpOwo+ID4gKwkJZWxz ZQo+ID4gKwkJCWlvd3JpdGUzMl9yZXAobmZjLT5iYXNlICsgREFUQV9QT1JUX1JFRywgJmJ1Zltv ZmZzZXRdLAo+ID4gKwkJCQkgICAgICBkd29yZHMpOwo+ID4gKwl9Cj4gPiArCj4gPiArCWlmIChs YXN0X2xlbikgewo+ID4gKwkJdTMyIHJlbWFpbmRlcjsKPiA+ICsKPiA+ICsJCW9mZnNldCA9IG5m Y19vcC0+bGVuIC0gbGFzdF9sZW47Cj4gPiArCj4gPiArCQlpZiAobmZjX29wLT5yZWFkKSB7Cj4g PiArCQkJcmVtYWluZGVyID0gcmVhZGxfcmVsYXhlZChuZmMtPmJhc2UgKyBEQVRBX1BPUlRfUkVH KTsKPiA+ICsJCQltZW1jcHkoJmJ1ZltvZmZzZXRdLCAmcmVtYWluZGVyLCBsYXN0X2xlbik7Cj4g PiArCQl9IGVsc2Ugewo+ID4gKwkJCW1lbWNweSgmcmVtYWluZGVyLCAmYnVmW29mZnNldF0sIGxh c3RfbGVuKTsKPiA+ICsJCQl3cml0ZWxfcmVsYXhlZChyZW1haW5kZXIsIG5mYy0+YmFzZSArIERB VEFfUE9SVF9SRUcpOwo+ID4gKwkJfQo+ID4gKwl9Cj4gPiArCj4gPiArCXJldHVybiBhbmZjX3dh aXRfZm9yX2V2ZW50KG5mYywgWEZFUl9DT01QTEVURSk7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRp YyBpbnQgYW5mY19taXNjX2RhdGFfdHlwZV9leGVjKHN0cnVjdCBuYW5kX2NoaXAgKmNoaXAsCj4g PiArCQkJCSAgICBjb25zdCBzdHJ1Y3QgbmFuZF9zdWJvcCAqc3Vib3AsCj4gPiArCQkJCSAgICB1 MzIgcHJvZ19yZWcpCj4gPiArewo+ID4gKwlzdHJ1Y3QgYXJhc2FuX25mYyAqbmZjID0gdG9fYW5m YyhjaGlwLT5jb250cm9sbGVyKTsKPiA+ICsJc3RydWN0IGFuZmNfb3AgbmZjX29wID0ge307Cj4g PiArCWludCByZXQ7Cj4gPiArCj4gPiArCWFuZmNfcGFyc2VfaW5zdHJ1Y3Rpb25zKGNoaXAsIHN1 Ym9wLCAmbmZjX29wKTsKPiA+ICsJbmZjX29wLnByb2dfcmVnID0gcHJvZ19yZWc7Cj4gPiArCWFu ZmNfdHJpZ2dlcl9vcChuZmMsICZuZmNfb3ApOwo+ID4gKwo+ID4gKwlpZiAobmZjX29wLnJkeV90 aW1lb3V0X21zKSB7Cj4gPiArCQlyZXQgPSBhbmZjX3dhaXRfZm9yX3JiKG5mYywgY2hpcCwgbmZj X29wLnJkeV90aW1lb3V0X21zKTsKPiA+ICsJCWlmIChyZXQpCj4gPiArCQkJcmV0dXJuIHJldDsK PiA+ICsJfQo+ID4gKwo+ID4gKwlyZXR1cm4gYW5mY19yd19waW9fb3AobmZjLCAmbmZjX29wKTsK PiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGludCBhbmZjX3BhcmFtX3JlYWRfdHlwZV9leGVjKHN0 cnVjdCBuYW5kX2NoaXAgKmNoaXAsCj4gPiArCQkJCSAgICAgY29uc3Qgc3RydWN0IG5hbmRfc3Vi b3AgKnN1Ym9wKQo+ID4gK3sKPiA+ICsJcmV0dXJuIGFuZmNfbWlzY19kYXRhX3R5cGVfZXhlYyhj aGlwLCBzdWJvcCwgUFJPR19SRFBBUkFNKTsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGludCBh bmZjX2RhdGFfcmVhZF90eXBlX2V4ZWMoc3RydWN0IG5hbmRfY2hpcCAqY2hpcCwKPiA+ICsJCQkJ ICAgIGNvbnN0IHN0cnVjdCBuYW5kX3N1Ym9wICpzdWJvcCkKPiA+ICt7Cj4gPiArCXJldHVybiBh bmZjX21pc2NfZGF0YV90eXBlX2V4ZWMoY2hpcCwgc3Vib3AsIFBST0dfUEdSRCk7Cj4gPiArfQo+ ID4gKwo+ID4gK3N0YXRpYyBpbnQgYW5mY19wYXJhbV93cml0ZV90eXBlX2V4ZWMoc3RydWN0IG5h bmRfY2hpcCAqY2hpcCwKPiA+ICsJCQkJICAgICAgY29uc3Qgc3RydWN0IG5hbmRfc3Vib3AgKnN1 Ym9wKQo+ID4gK3sKPiA+ICsJcmV0dXJuIGFuZmNfbWlzY19kYXRhX3R5cGVfZXhlYyhjaGlwLCBz dWJvcCwgUFJPR19TRVRfRkVBVFVSRSk7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgYW5m Y19kYXRhX3dyaXRlX3R5cGVfZXhlYyhzdHJ1Y3QgbmFuZF9jaGlwICpjaGlwLAo+ID4gKwkJCQkg ICAgIGNvbnN0IHN0cnVjdCBuYW5kX3N1Ym9wICpzdWJvcCkKPiA+ICt7Cj4gPiArCXJldHVybiBh bmZjX21pc2NfZGF0YV90eXBlX2V4ZWMoY2hpcCwgc3Vib3AsIFBST0dfUEdQUk9HKTsKPiA+ICt9 Cj4gPiArCj4gPiArc3RhdGljIGludCBhbmZjX21pc2NfemVyb2xlbl90eXBlX2V4ZWMoc3RydWN0 IG5hbmRfY2hpcCAqY2hpcCwKPiA+ICsJCQkJICAgICAgIGNvbnN0IHN0cnVjdCBuYW5kX3N1Ym9w ICpzdWJvcCwKPiA+ICsJCQkJICAgICAgIHUzMiBwcm9nX3JlZykKPiA+ICt7Cj4gPiArCXN0cnVj dCBhcmFzYW5fbmZjICpuZmMgPSB0b19hbmZjKGNoaXAtPmNvbnRyb2xsZXIpOwo+ID4gKwlzdHJ1 Y3QgYW5mY19vcCBuZmNfb3AgPSB7fTsKPiA+ICsJaW50IHJldDsKPiA+ICsKPiA+ICsJYW5mY19w YXJzZV9pbnN0cnVjdGlvbnMoY2hpcCwgc3Vib3AsICZuZmNfb3ApOwo+ID4gKwluZmNfb3AucHJv Z19yZWcgPSBwcm9nX3JlZzsKPiA+ICsJYW5mY190cmlnZ2VyX29wKG5mYywgJm5mY19vcCk7Cj4g PiArCj4gPiArCXJldCA9IGFuZmNfd2FpdF9mb3JfZXZlbnQobmZjLCBYRkVSX0NPTVBMRVRFKTsK PiA+ICsJaWYgKHJldCkKPiA+ICsJCXJldHVybiByZXQ7Cj4gPiArCj4gPiArCWlmIChuZmNfb3Au cmR5X3RpbWVvdXRfbXMpCj4gPiArCQlyZXQgPSBhbmZjX3dhaXRfZm9yX3JiKG5mYywgY2hpcCwg bmZjX29wLnJkeV90aW1lb3V0X21zKTsKPiA+ICsKPiA+ICsJcmV0dXJuIHJldDsKPiA+ICt9Cj4g PiArCj4gPiArc3RhdGljIGludCBhbmZjX3N0YXR1c190eXBlX2V4ZWMoc3RydWN0IG5hbmRfY2hp cCAqY2hpcCwKPiA+ICsJCQkJIGNvbnN0IHN0cnVjdCBuYW5kX3N1Ym9wICpzdWJvcCkKPiA+ICt7 Cj4gPiArCXN0cnVjdCBhcmFzYW5fbmZjICpuZmMgPSB0b19hbmZjKGNoaXAtPmNvbnRyb2xsZXIp Owo+ID4gKwl1MzIgdG1wOwo+ID4gKwlpbnQgcmV0Owo+ID4gKwo+ID4gKwkvKgo+ID4gKwkgKiBU aGlzIGNvbnRyb2xsZXIgZG9lcyBub3QgYWxsb3cgdG8gcHJvY2VlZCB3aXRoIGEgQ01EK0RBVEFf SU4gY3ljbGUKPiA+ICsJICogbWFudWFsbHkgb24gdGhlIGJ1cyBieSByZWFkaW5nIGRhdGEgZnJv bSB0aGUgZGF0YSByZWdpc3Rlci4gSW5zdGVhZCwKPiA+ICsJICogdGhlIGNvbnRyb2xsZXIgYWJz dHJhY3QgdGhlIHN0YXR1cyByZWFkIG9wZXJhdGlvbiB3aXRoIGl0cyBvd24gc3RhdHVzCj4gPiAr CSAqIHJlZ2lzdGVyIGFmdGVyIG9yZGVyaW5nIGEgcmVhZCBzdGF0dXMgb3BlcmF0aW9uLiBIZW5j ZSwgdGhlIGZvbGxvd2luZwo+ID4gKwkgKiBoYWNrLgo+ID4gKwkgKi8KPiA+ICsJaWYgKHN1Ym9w LT5pbnN0cnNbMF0uY3R4LmNtZC5vcGNvZGUgIT0gTkFORF9DTURfU1RBVFVTKQo+ID4gKwkJcmV0 dXJuIC1FTk9UU1VQUDsKPiA+ICsKPiA+ICsJcmV0ID0gYW5mY19taXNjX3plcm9sZW5fdHlwZV9l eGVjKGNoaXAsIHN1Ym9wLCBQUk9HX1NUQVRVUyk7Cj4gPiArCWlmIChyZXQpCj4gPiArCQlyZXR1 cm4gcmV0Owo+ID4gKwo+ID4gKwl0bXAgPSByZWFkbF9yZWxheGVkKG5mYy0+YmFzZSArIEZMQVNI X1NUU19SRUcpOwo+ID4gKwltZW1jcHkoc3Vib3AtPmluc3Ryc1sxXS5jdHguZGF0YS5idWYuaW4s ICZ0bXAsIDEpOwo+ID4gKwo+ID4gKwlyZXR1cm4gMDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGlj IGludCBhbmZjX3Jlc2V0X3R5cGVfZXhlYyhzdHJ1Y3QgbmFuZF9jaGlwICpjaGlwLAo+ID4gKwkJ CQljb25zdCBzdHJ1Y3QgbmFuZF9zdWJvcCAqc3Vib3ApCj4gPiArewo+ID4gKwlyZXR1cm4gYW5m Y19taXNjX3plcm9sZW5fdHlwZV9leGVjKGNoaXAsIHN1Ym9wLCBQUk9HX1JTVCk7Cj4gPiArfQo+ ID4gKwo+ID4gK3N0YXRpYyBpbnQgYW5mY19lcmFzZV90eXBlX2V4ZWMoc3RydWN0IG5hbmRfY2hp cCAqY2hpcCwKPiA+ICsJCQkJY29uc3Qgc3RydWN0IG5hbmRfc3Vib3AgKnN1Ym9wKQo+ID4gK3sK PiA+ICsJcmV0dXJuIGFuZmNfbWlzY196ZXJvbGVuX3R5cGVfZXhlYyhjaGlwLCBzdWJvcCwgUFJP R19FUkFTRSk7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgYW5mY193YWl0X3R5cGVfZXhl YyhzdHJ1Y3QgbmFuZF9jaGlwICpjaGlwLAo+ID4gKwkJCSAgICAgICBjb25zdCBzdHJ1Y3QgbmFu ZF9zdWJvcCAqc3Vib3ApCj4gPiArewo+ID4gKwlzdHJ1Y3QgYXJhc2FuX25mYyAqbmZjID0gdG9f YW5mYyhjaGlwLT5jb250cm9sbGVyKTsKPiA+ICsJc3RydWN0IGFuZmNfb3AgbmZjX29wID0ge307 Cj4gPiArCj4gPiArCWFuZmNfcGFyc2VfaW5zdHJ1Y3Rpb25zKGNoaXAsIHN1Ym9wLCAmbmZjX29w KTsKPiA+ICsKPiA+ICsJcmV0dXJuIGFuZmNfd2FpdF9mb3JfcmIobmZjLCBjaGlwLCBuZmNfb3Au cmR5X3RpbWVvdXRfbXMpOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IG5h bmRfb3BfcGFyc2VyIGFuZmNfb3BfcGFyc2VyID0gTkFORF9PUF9QQVJTRVIoCj4gPiArCU5BTkRf T1BfUEFSU0VSX1BBVFRFUk4oCj4gPiArCQlhbmZjX3BhcmFtX3JlYWRfdHlwZV9leGVjLAo+ID4g KwkJTkFORF9PUF9QQVJTRVJfUEFUX0NNRF9FTEVNKGZhbHNlKSwKPiA+ICsJCU5BTkRfT1BfUEFS U0VSX1BBVF9BRERSX0VMRU0oZmFsc2UsIEFORkNfTUFYX0FERFJfQ1lDKSwKPiA+ICsJCU5BTkRf T1BfUEFSU0VSX1BBVF9XQUlUUkRZX0VMRU0odHJ1ZSksCj4gPiArCQlOQU5EX09QX1BBUlNFUl9Q QVRfREFUQV9JTl9FTEVNKGZhbHNlLCBBTkZDX01BWF9DSFVOS19TSVpFKSksCj4gPiArCU5BTkRf T1BfUEFSU0VSX1BBVFRFUk4oCj4gPiArCQlhbmZjX3BhcmFtX3dyaXRlX3R5cGVfZXhlYywKPiA+ ICsJCU5BTkRfT1BfUEFSU0VSX1BBVF9DTURfRUxFTShmYWxzZSksCj4gPiArCQlOQU5EX09QX1BB UlNFUl9QQVRfQUREUl9FTEVNKGZhbHNlLCBBTkZDX01BWF9BRERSX0NZQyksCj4gPiArCQlOQU5E X09QX1BBUlNFUl9QQVRfREFUQV9PVVRfRUxFTShmYWxzZSwgQU5GQ19NQVhfUEFSQU1fU0laRSkp LAo+ID4gKwlOQU5EX09QX1BBUlNFUl9QQVRURVJOKAo+ID4gKwkJYW5mY19kYXRhX3JlYWRfdHlw ZV9leGVjLAo+ID4gKwkJTkFORF9PUF9QQVJTRVJfUEFUX0NNRF9FTEVNKGZhbHNlKSwKPiA+ICsJ CU5BTkRfT1BfUEFSU0VSX1BBVF9BRERSX0VMRU0oZmFsc2UsIEFORkNfTUFYX0FERFJfQ1lDKSwK PiA+ICsJCU5BTkRfT1BfUEFSU0VSX1BBVF9DTURfRUxFTShmYWxzZSksCj4gPiArCQlOQU5EX09Q X1BBUlNFUl9QQVRfV0FJVFJEWV9FTEVNKHRydWUpLAo+ID4gKwkJTkFORF9PUF9QQVJTRVJfUEFU X0RBVEFfSU5fRUxFTShmYWxzZSwgQU5GQ19NQVhfQ0hVTktfU0laRSkpLAo+ID4gKwlOQU5EX09Q X1BBUlNFUl9QQVRURVJOKAo+ID4gKwkJYW5mY19kYXRhX3dyaXRlX3R5cGVfZXhlYywKPiA+ICsJ CU5BTkRfT1BfUEFSU0VSX1BBVF9DTURfRUxFTShmYWxzZSksCj4gPiArCQlOQU5EX09QX1BBUlNF Ul9QQVRfQUREUl9FTEVNKGZhbHNlLCBBTkZDX01BWF9BRERSX0NZQyksCj4gPiArCQlOQU5EX09Q X1BBUlNFUl9QQVRfREFUQV9PVVRfRUxFTShmYWxzZSwgQU5GQ19NQVhfQ0hVTktfU0laRSksCj4g PiArCQlOQU5EX09QX1BBUlNFUl9QQVRfQ01EX0VMRU0oZmFsc2UpKSwKPiA+ICsJTkFORF9PUF9Q QVJTRVJfUEFUVEVSTigKPiA+ICsJCWFuZmNfcmVzZXRfdHlwZV9leGVjLAo+ID4gKwkJTkFORF9P UF9QQVJTRVJfUEFUX0NNRF9FTEVNKGZhbHNlKSwKPiA+ICsJCU5BTkRfT1BfUEFSU0VSX1BBVF9X QUlUUkRZX0VMRU0oZmFsc2UpKSwKPiA+ICsJTkFORF9PUF9QQVJTRVJfUEFUVEVSTigKPiA+ICsJ CWFuZmNfZXJhc2VfdHlwZV9leGVjLAo+ID4gKwkJTkFORF9PUF9QQVJTRVJfUEFUX0NNRF9FTEVN KGZhbHNlKSwKPiA+ICsJCU5BTkRfT1BfUEFSU0VSX1BBVF9BRERSX0VMRU0oZmFsc2UsIEFORkNf TUFYX0FERFJfQ1lDKSwKPiA+ICsJCU5BTkRfT1BfUEFSU0VSX1BBVF9DTURfRUxFTShmYWxzZSks Cj4gPiArCQlOQU5EX09QX1BBUlNFUl9QQVRfV0FJVFJEWV9FTEVNKGZhbHNlKSksCj4gPiArCU5B TkRfT1BfUEFSU0VSX1BBVFRFUk4oCj4gPiArCQlhbmZjX3N0YXR1c190eXBlX2V4ZWMsCj4gPiAr CQlOQU5EX09QX1BBUlNFUl9QQVRfQ01EX0VMRU0oZmFsc2UpLAo+ID4gKwkJTkFORF9PUF9QQVJT RVJfUEFUX0RBVEFfSU5fRUxFTShmYWxzZSwgQU5GQ19NQVhfQ0hVTktfU0laRSkpLAo+ID4gKwlO QU5EX09QX1BBUlNFUl9QQVRURVJOKAo+ID4gKwkJYW5mY193YWl0X3R5cGVfZXhlYywKPiA+ICsJ CU5BTkRfT1BfUEFSU0VSX1BBVF9XQUlUUkRZX0VMRU0oZmFsc2UpKSwKPiA+ICsJKTsKPiA+ICsg IAo+IAo+IE9rYXksIG5vIERBVEEtb25seSBwYXR0ZXJucywgc28gbXkgc3VnZ2VzdGlvbiB0byBz cGxpdCBub24tYWxpZ25lZCBkYXRhCj4gcmVhZHMgZG9lc24ndCB3b3JrLiBJJ2Qgc3VnZ2VzdCB0 byBkZXNjcmliZSBkYXRhLWxlbmd0aHMKPiBjb25zdHJhaW50cyByYXRoZXIgdGhhbiBhdXRvbWF0 aWNhbGx5IGFkanVzdGluZyB0aGUgZGF0YSBsZW5ndGggdG8KPiBzb21ldGhpbmcgYmlnZ2VyIHdo ZW4gd2UgY2FuJ3QgZG8gZXhhY3RseSB0aGUgbnVtYmVyIG9mIHJlcXVlc3RlZCBEQVRBCj4gY3lj bGVzLgoKV2VsbCwgd2UgKm11c3QqIGFkanVzdCB0aGUgZGF0YSBsZW5ndGggYXV0b21hdGljYWxs eS4gQnV0IHRoZSBiZWxvdwpjaGFuZ2UgaXMgaW50ZXJlc3RpbmcgYW5kIHNob3VsZCBiZSBleHRl bmRlZCBhbmQgdGhlbiB0aGlzIGNvbnRyb2xsZXIKdXBkYXRlZCAoc2VlIHRoZSBuZXh0IHNlbnRl bmNlKS4KCj4gSSBzdGFydGVkIGRvaW5nIHNvbWV0aGluZyBzaW1pbGFyIGhlcmUgWzFdLCBleGNl cHQgeW91J2QgbmVlZAo+IG11Y2ggbW9yZSBmaW5lZC1ncmFpbmVkIGNvbnN0cmFpbnRzLCBzbyBt YXliZSB3ZSBzaG91bGQgYWRkIGFuIG9wdGlvbmFsCj4gY2hlY2sgaG9vayB0byBkYXRhIHBhdHRl cm5zLgoKV2UgY291bGQgZGVzY3JpYmUgYSAicm91bmRfdXAiIGxpbWl0YXRpb24gdG9vLiBUaGF0 J3MgZGVmaW5pdGVseQpzb21ldGhpbmcgdGhhdCB3ZSBjYW4gYWRkIGluIHRoaXMgZHJpdmVyIG9u IHRvcCBvZiBbMV0uCgpXb3VsZCBhcHBseSB0byBNYXJ2ZWxsIE5GQyBhcyB3ZWxsIGZvciBpbnN0 YW5jZS4KCj4gPiArc3RhdGljIGludCBhbmZjX3NlbGVjdF90YXJnZXQoc3RydWN0IG5hbmRfY2hp cCAqY2hpcCwgaW50IHRhcmdldCkKPiA+ICt7Cj4gPiArCXN0cnVjdCBhbmFuZCAqYW5hbmQgPSB0 b19hbmFuZChjaGlwKTsKPiA+ICsJc3RydWN0IGFyYXNhbl9uZmMgKm5mYyA9IHRvX2FuZmMoY2hp cC0+Y29udHJvbGxlcik7Cj4gPiArCWludCByZXQ7Cj4gPiArCj4gPiArCS8qIFVwZGF0ZSB0aGUg Y29udHJvbGxlciB0aW1pbmdzIGFuZCB0aGUgcG90ZW50aWFsIEVDQyBjb25maWd1cmF0aW9uICov Cj4gPiArCXdyaXRlbF9yZWxheGVkKGFuYW5kLT50aW1pbmdzLCBuZmMtPmJhc2UgKyBEQVRBX0lO VEVSRkFDRV9SRUcpOwo+ID4gKwo+ID4gKwkvKiBVcGRhdGUgY2xvY2sgZnJlcXVlbmN5ICovCj4g PiArCWlmIChuZmMtPmN1cl9jbGsgIT0gYW5hbmQtPmNsaykgewo+ID4gKwkJY2xrX2Rpc2FibGVf dW5wcmVwYXJlKG5mYy0+Y29udHJvbGxlcl9jbGspOwo+ID4gKwkJcmV0ID0gY2xrX3NldF9yYXRl KG5mYy0+Y29udHJvbGxlcl9jbGssIGFuYW5kLT5jbGspOwo+ID4gKwkJaWYgKHJldCkgewo+ID4g KwkJCWRldl9lcnIobmZjLT5kZXYsICJGYWlsZWQgdG8gY2hhbmdlIGNsb2NrIHJhdGVcbiIpOwo+ ID4gKwkJCXJldHVybiByZXQ7Cj4gPiArCQl9Cj4gPiArCj4gPiArCQlyZXQgPSBjbGtfcHJlcGFy ZV9lbmFibGUobmZjLT5jb250cm9sbGVyX2Nsayk7Cj4gPiArCQlpZiAocmV0KSB7Cj4gPiArCQkJ ZGV2X2VycihuZmMtPmRldiwKPiA+ICsJCQkJIkZhaWxlZCB0byByZS1lbmFibGUgdGhlIGNvbnRy b2xsZXIgY2xvY2tcbiIpOwo+ID4gKwkJCXJldHVybiByZXQ7Cj4gPiArCQl9Cj4gPiArCj4gPiAr CQluZmMtPmN1cl9jbGsgPSBhbmFuZC0+Y2xrOwo+ID4gKwl9Cj4gPiArCj4gPiArCXJldHVybiAw Owo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50IGFuZmNfZXhlY19vcChzdHJ1Y3QgbmFuZF9j aGlwICpjaGlwLAo+ID4gKwkJCWNvbnN0IHN0cnVjdCBuYW5kX29wZXJhdGlvbiAqb3AsCj4gPiAr CQkJYm9vbCBjaGVja19vbmx5KQo+ID4gK3sKPiA+ICsJaW50IHJldDsKPiA+ICsKPiA+ICsJaWYg KCFjaGVja19vbmx5KSB7Cj4gPiArCQlyZXQgPSBhbmZjX3NlbGVjdF90YXJnZXQoY2hpcCwgb3At PmNzKTsKPiA+ICsJCWlmIChyZXQpCj4gPiArCQkJcmV0dXJuIHJldDsKPiA+ICsJfSAgCj4gCj4g R2l2ZW4geW91IGRvIG9ubHkgb25lIHRoaW5nIGluIHRoZSBjaGVja19vbmx5IGNhc2UsIEknZCBk bzoKPiAKPiAJaWYgKGNoZWNrX29ubHkpCj4gCQluYW5kX29wX3BhcnNlcl9leGVjX29wKGNoaXAs ICZhbmZjX29wX3BhcnNlciwgb3AsIHRydWUpOwo+IAo+IAlyZXQgPSBhbmZjX3NlbGVjdF90YXJn ZXQoY2hpcCwgb3AtPmNzKTsKPiAJaWYgKHJldCkKPiAJCXJldHVybiByZXQ7Cj4gCj4gCS4uLgoK b2sKCj4gPiArCj4gPiArCXJldHVybiBuYW5kX29wX3BhcnNlcl9leGVjX29wKGNoaXAsICZhbmZj X29wX3BhcnNlciwgb3AsIGNoZWNrX29ubHkpOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50 IGFuZmNfc2V0dXBfZGF0YV9pbnRlcmZhY2Uoc3RydWN0IG5hbmRfY2hpcCAqY2hpcCwgaW50IHRh cmdldCwKPiA+ICsJCQkJICAgICBjb25zdCBzdHJ1Y3QgbmFuZF9kYXRhX2ludGVyZmFjZSAqY29u ZikKPiA+ICt7Cj4gPiArCXN0cnVjdCBhbmFuZCAqYW5hbmQgPSB0b19hbmFuZChjaGlwKTsKPiA+ ICsJc3RydWN0IGFyYXNhbl9uZmMgKm5mYyA9IHRvX2FuZmMoY2hpcC0+Y29udHJvbGxlcik7Cj4g PiArCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbnAgPSBuZmMtPmRldi0+b2Zfbm9kZTsKPiA+ICsKPiA+ ICsJaWYgKHRhcmdldCA8IDApCj4gPiArCQlyZXR1cm4gMDsKPiA+ICsKPiA+ICsJYW5hbmQtPnRp bWluZ3MgPSBESUZBQ0VfU0RSIHwgRElGQUNFX1NEUl9NT0RFKGNvbmYtPnRpbWluZ3MubW9kZSk7 Cj4gPiArCWFuYW5kLT5jbGsgPSBBTkZDX1hMTlhfU0RSX0RGTFRfQ09SRV9DTEs7Cj4gPiArCj4g PiArCS8qCj4gPiArCSAqIER1ZSB0byBhIGhhcmR3YXJlIGJ1ZyBpbiB0aGUgWnlucU1QIFNvQywg U0RSIHRpbWluZyBtb2RlcyAwLTEgd29yawo+ID4gKwkgKiB3aXRoIGYgPiA5ME1IeiAoZGVmYXVs dCBjbG9jayBpcyAxMDBNSHopIGJ1dCBzaWduYWxzIGFyZSB1bnN0YWJsZQo+ID4gKwkgKiB3aXRo IGhpZ2hlciBtb2Rlcy4gSGVuY2Ugd2UgZGVjcmVhc2UgYSBsaXR0bGUgYml0IHRoZSBjbG9jayBy YXRlIHRvCj4gPiArCSAqIDgwTUh6IHdoZW4gdXNpbmcgbW9kZXMgMi01IHdpdGggdGhpcyBTb0Mu Cj4gPiArCSAqLwo+ID4gKwlpZiAob2ZfZGV2aWNlX2lzX2NvbXBhdGlibGUobnAsICJ4bG54LHp5 bnFtcC1uYW5kLWNvbnRyb2xsZXIiKSAmJgo+ID4gKwkgICAgY29uZi0+dGltaW5ncy5tb2RlID49 IDIpCj4gPiArCQlhbmFuZC0+Y2xrID0gQU5GQ19YTE5YX1NEUl9IU19DT1JFX0NMSzsKPiA+ICsK PiA+ICsJcmV0dXJuIDA7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgYW5mY19hdHRhY2hf Y2hpcChzdHJ1Y3QgbmFuZF9jaGlwICpjaGlwKQo+ID4gK3sKPiA+ICsJc3RydWN0IGFuYW5kICph bmFuZCA9IHRvX2FuYW5kKGNoaXApOwo+ID4gKwlzdHJ1Y3QgYXJhc2FuX25mYyAqbmZjID0gdG9f YW5mYyhjaGlwLT5jb250cm9sbGVyKTsKPiA+ICsJc3RydWN0IG10ZF9pbmZvICptdGQgPSBuYW5k X3RvX210ZChjaGlwKTsKPiA+ICsJaW50IHJldCA9IDA7Cj4gPiArCj4gPiArCWlmIChtdGQtPndy aXRlc2l6ZSA8PSBTWl81MTIpCj4gPiArCQlhbmFuZC0+Y2FkZHJfY3ljbGVzID0gMTsKPiA+ICsJ ZWxzZQo+ID4gKwkJYW5hbmQtPmNhZGRyX2N5Y2xlcyA9IDI7Cj4gPiArCj4gPiArCWlmIChjaGlw LT5vcHRpb25zICYgTkFORF9ST1dfQUREUl8zKQo+ID4gKwkJYW5hbmQtPnJhZGRyX2N5Y2xlcyA9 IDM7Cj4gPiArCWVsc2UKPiA+ICsJCWFuYW5kLT5yYWRkcl9jeWNsZXMgPSAyOwo+ID4gKwo+ID4g Kwlzd2l0Y2ggKG10ZC0+d3JpdGVzaXplKSB7Cj4gPiArCWNhc2UgNTEyOgo+ID4gKwkJYW5hbmQt PnBhZ2Vfc3ogPSAwOwo+ID4gKwkJYnJlYWs7Cj4gPiArCWNhc2UgMTAyNDoKPiA+ICsJCWFuYW5k LT5wYWdlX3N6ID0gNTsKPiA+ICsJCWJyZWFrOwo+ID4gKwljYXNlIDIwNDg6Cj4gPiArCQlhbmFu ZC0+cGFnZV9zeiA9IDE7Cj4gPiArCQlicmVhazsKPiA+ICsJY2FzZSA0MDk2Ogo+ID4gKwkJYW5h bmQtPnBhZ2Vfc3ogPSAyOwo+ID4gKwkJYnJlYWs7Cj4gPiArCWNhc2UgODE5MjoKPiA+ICsJCWFu YW5kLT5wYWdlX3N6ID0gMzsKPiA+ICsJCWJyZWFrOwo+ID4gKwljYXNlIDE2Mzg0Ogo+ID4gKwkJ YW5hbmQtPnBhZ2Vfc3ogPSA0Owo+ID4gKwkJYnJlYWs7Cj4gPiArCWRlZmF1bHQ6Cj4gPiArCQly ZXR1cm4gLUVJTlZBTDsKPiA+ICsJfQo+ID4gKwo+ID4gKwkvKiBUaGVzZSBob29rcyBhcmUgdmFs aWQgZm9yIGFsbCBFQ0MgcHJvdmlkZXJzICovCj4gPiArCWNoaXAtPmVjYy5yZWFkX3BhZ2VfcmF3 ID0gbmFuZF9tb25vbGl0aGljX3JlYWRfcGFnZV9yYXc7Cj4gPiArCWNoaXAtPmVjYy53cml0ZV9w YWdlX3JhdyA9IG5hbmRfbW9ub2xpdGhpY193cml0ZV9wYWdlX3JhdzsKPiA+ICsKPiA+ICsJc3dp dGNoIChjaGlwLT5lY2MubW9kZSkgewo+ID4gKwljYXNlIE5BTkRfRUNDX05PTkU6Cj4gPiArCWNh c2UgTkFORF9FQ0NfU09GVDoKPiA+ICsJY2FzZSBOQU5EX0VDQ19PTl9ESUU6Cj4gPiArCQlicmVh azsKPiA+ICsJY2FzZSBOQU5EX0VDQ19IVzoKPiA+ICsJZGVmYXVsdDoKPiA+ICsJCWRldl9lcnIo bmZjLT5kZXYsICJVbnN1cHBvcnRlZCBFQ0MgbW9kZTogJWRcbiIsCj4gPiArCQkJY2hpcC0+ZWNj Lm1vZGUpOwo+ID4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gPiArCX0KPiA+ICsKPiA+ICsJcmV0dXJu IHJldDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBuYW5kX2NvbnRyb2xs ZXJfb3BzIGFuZmNfb3BzID0gewo+ID4gKwkuZXhlY19vcCA9IGFuZmNfZXhlY19vcCwKPiA+ICsJ LnNldHVwX2RhdGFfaW50ZXJmYWNlID0gYW5mY19zZXR1cF9kYXRhX2ludGVyZmFjZSwKPiA+ICsJ LmF0dGFjaF9jaGlwID0gYW5mY19hdHRhY2hfY2hpcCwKPiA+ICt9Owo+ID4gKwo+ID4gK3N0YXRp YyBpbnQgYW5mY19jaGlwX2luaXQoc3RydWN0IGFyYXNhbl9uZmMgKm5mYywgc3RydWN0IGRldmlj ZV9ub2RlICpucCkKPiA+ICt7Cj4gPiArCXN0cnVjdCBhbmFuZCAqYW5hbmQ7Cj4gPiArCXN0cnVj dCBuYW5kX2NoaXAgKmNoaXA7Cj4gPiArCXN0cnVjdCBtdGRfaW5mbyAqbXRkOwo+ID4gKwlpbnQg Y3MsIHJiLCByZXQ7Cj4gPiArCj4gPiArCWFuYW5kID0gZGV2bV9remFsbG9jKG5mYy0+ZGV2LCBz aXplb2YoKmFuYW5kKSwgR0ZQX0tFUk5FTCk7Cj4gPiArCWlmICghYW5hbmQpCj4gPiArCQlyZXR1 cm4gLUVOT01FTTsKPiA+ICsKPiA+ICsJLyogT25seSBvbmUgQ1MgY2FuIGJlIGFzc2VydGVkIGF0 IGEgdGltZSAqLyAgCj4gCj4gWW91IG1lYW4gdGhlIGNvbnRyb2xsZXIgb25seSBoYXMgb25lIENT PyBDYXVzZSB0aGF0IGNvbW1lbnQgZG9lc24ndAo+IG1ha2UgbXVjaCBzZW5zZS4KCkkgZG9uJ3Qg cmVtZW1iZXIgd2h5IEkgd3JvdGUgdGhhdC4gVGhlIGNvbnRyb2xsZXIgaGFzIDIgQ1MgKGJvdGgK dGVzdGVkKSwgSSdsbCBkcm9wIHRoZSBjb21tZW50IGFuZCB0aGUgbGltaXRhdGlvbi4KCj4gCj4g PiArCWlmIChvZl9wcm9wZXJ0eV9jb3VudF9lbGVtc19vZl9zaXplKG5wLCAicmVnIiwgc2l6ZW9m KHUzMikpICE9IDEpIHsKPiA+ICsJCWRldl9lcnIobmZjLT5kZXYsICJJbnZhbGlkIHJlZyBwcm9w ZXJ0eVxuIik7Cj4gPiArCQlyZXR1cm4gLUVJTlZBTDsKPiA+ICsJfSAgCj4gCj4gSXQncyBvbmx5 IGEgU1cgbGltaXRhdGlvbi4gSWYgeW91ciBjb250cm9sbGVyIGhhcyBzZXZlcmFsIENTIHBpbnMK PiAod2hpY2ggc2VlbXMgdG8gYmUgdGhlIGNhc2Ugc2luY2UgeW91IGhhdmUgYSBsaXN0IG9mIGNo aXBzKSwgaXQgY2FuCj4gaGFuZGxlIG11bHRpLUNTIGNoaXBzIHRvby4gSSdtIHBlcmZlY3RseSBm aW5lIHdpdGggdGhlIGxpbWl0YXRpb24KPiBpdHNlbGYsIGJ1dCB0aGUgY29tbWVudCBzaG91bGQg cmVmbGVjdCB0aGUgcmVhbGl0eS4gQW5kIGlmIHlvdSB3YW50IHRvCj4gc3VwcG9ydCBtdWx0aS1D UyBjaGlwcywgeW91IGp1c3QgaGF2ZSB0byBkZWZpbmUgYW4gYXJyYXkgb2YgQ1MvUkIgaW4KPiBh bmFuZC4KPiAKPiA+ICsKPiA+ICsJcmV0ID0gb2ZfcHJvcGVydHlfcmVhZF91MzIobnAsICJyZWci LCAmY3MpOwo+ID4gKwlpZiAocmV0KQo+ID4gKwkJcmV0dXJuIHJldDsKPiA+ICsKPiA+ICsJcmV0 ID0gb2ZfcHJvcGVydHlfcmVhZF91MzIobnAsICJuYW5kLXJiIiwgJnJiKTsKPiA+ICsJaWYgKHJl dCkKPiA+ICsJCXJldHVybiByZXQ7Cj4gPiArCj4gPiArCWlmIChjcyA+PSBBTkZDX01BWF9DUyB8 fCByYiA+PSBBTkZDX01BWF9DUykgewo+ID4gKwkJZGV2X2VycihuZmMtPmRldiwgIldyb25nIENT ICVkIG9yIFJCICVkXG4iLCBjcywgcmIpOwo+ID4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gPiArCX0K PiA+ICsKPiA+ICsJaWYgKHRlc3RfYW5kX3NldF9iaXQoY3MsICZuZmMtPmFzc2lnbmVkX2NzKSkg ewo+ID4gKwkJZGV2X2VycihuZmMtPmRldiwgIkFscmVhZHkgYXNzaWduZWQgQ1MgJWRcbiIsIGNz KTsKPiA+ICsJCXJldHVybiAtRUlOVkFMOwo+ID4gKwl9Cj4gPiArCj4gPiArCWFuYW5kLT5jcyA9 IGNzOwo+ID4gKwlhbmFuZC0+cmIgPSByYjsKPiA+ICsKPiA+ICsJY2hpcCA9ICZhbmFuZC0+Y2hp cDsKPiA+ICsJbXRkID0gbmFuZF90b19tdGQoY2hpcCk7Cj4gPiArCW10ZC0+ZGV2LnBhcmVudCA9 IG5mYy0+ZGV2Owo+ID4gKwljaGlwLT5jb250cm9sbGVyID0gJm5mYy0+Y29udHJvbGxlcjsKPiA+ ICsJY2hpcC0+b3B0aW9ucyA9IE5BTkRfQlVTV0lEVEhfQVVUTyB8IE5BTkRfTk9fU1VCUEFHRV9X UklURSB8Cj4gPiArCQkJTkFORF9VU0VTX0RNQTsKPiA+ICsKPiA+ICsJbmFuZF9zZXRfZmxhc2hf bm9kZShjaGlwLCBucCk7Cj4gPiArCWlmICghbXRkLT5uYW1lKSB7Cj4gPiArCQlkZXZfZXJyKG5m Yy0+ZGV2LCAiTkFORCBsYWJlbCBwcm9wZXJ0eSBpcyBtYW5kYXRvcnlcbiIpOwo+ID4gKwkJcmV0 dXJuIC1FSU5WQUw7Cj4gPiArCX0KPiA+ICsKPiA+ICsJcmV0ID0gbmFuZF9zY2FuKGNoaXAsIDEp Owo+ID4gKwlpZiAocmV0KSB7Cj4gPiArCQlkZXZfZXJyKG5mYy0+ZGV2LCAiU2NhbiBvcGVyYXRp b24gZmFpbGVkXG4iKTsKPiA+ICsJCXJldHVybiByZXQ7Cj4gPiArCX0KPiA+ICsKPiA+ICsJcmV0 ID0gbXRkX2RldmljZV9yZWdpc3RlcihtdGQsIE5VTEwsIDApOwo+ID4gKwlpZiAocmV0KSB7Cj4g PiArCQluYW5kX3JlbGVhc2UoY2hpcCk7ICAKPiAKPiAJCW5hbmRfY2xlYW51cChjaGlwKTsKCkNy YXAKCj4gCj4gPiArCQlyZXR1cm4gcmV0Owo+ID4gKwl9Cj4gPiArCj4gPiArCWxpc3RfYWRkX3Rh aWwoJmFuYW5kLT5ub2RlLCAmbmZjLT5jaGlwcyk7Cj4gPiArCj4gPiArCXJldHVybiAwOwo+ID4g K30KPiA+ICsKPiA+ICtzdGF0aWMgdm9pZCBhbmZjX2NoaXBzX2NsZWFudXAoc3RydWN0IGFyYXNh bl9uZmMgKm5mYykKPiA+ICt7Cj4gPiArCXN0cnVjdCBhbmFuZCAqYW5hbmQsICp0bXA7Cj4gPiAr Cj4gPiArCWxpc3RfZm9yX2VhY2hfZW50cnlfc2FmZShhbmFuZCwgdG1wLCAmbmZjLT5jaGlwcywg bm9kZSkgewo+ID4gKwkJbmFuZF9yZWxlYXNlKCZhbmFuZC0+Y2hpcCk7Cj4gPiArCQlsaXN0X2Rl bCgmYW5hbmQtPm5vZGUpOwo+ID4gKwl9Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgYW5m Y19jaGlwc19pbml0KHN0cnVjdCBhcmFzYW5fbmZjICpuZmMpCj4gPiArewo+ID4gKwlzdHJ1Y3Qg ZGV2aWNlX25vZGUgKm5wID0gbmZjLT5kZXYtPm9mX25vZGUsICpuYW5kX25wOwo+ID4gKwlpbnQg bmNoaXBzID0gb2ZfZ2V0X2NoaWxkX2NvdW50KG5wKTsKPiA+ICsJaW50IHJldDsKPiA+ICsKPiA+ ICsJaWYgKCFuY2hpcHMgfHwgbmNoaXBzID4gQU5GQ19NQVhfQ1MpIHsKPiA+ICsJCWRldl9lcnIo bmZjLT5kZXYsICJJbmNvcnJlY3QgbnVtYmVyIG9mIE5BTkQgY2hpcHMgKCVkKVxuIiwKPiA+ICsJ CQluY2hpcHMpOwo+ID4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gPiArCX0KPiA+ICsKPiA+ICsJZm9y X2VhY2hfY2hpbGRfb2Zfbm9kZShucCwgbmFuZF9ucCkgewo+ID4gKwkJcmV0ID0gYW5mY19jaGlw X2luaXQobmZjLCBuYW5kX25wKTsKPiA+ICsJCWlmIChyZXQpIHsKPiA+ICsJCQlvZl9ub2RlX3B1 dChuYW5kX25wKTsKPiA+ICsJCQlhbmZjX2NoaXBzX2NsZWFudXAobmZjKTsKPiA+ICsJCQlicmVh azsKPiA+ICsJCX0KPiA+ICsJfQo+ID4gKwo+ID4gKwlyZXR1cm4gcmV0Owo+ID4gK30KPiA+ICsK PiA+ICtzdGF0aWMgdm9pZCBhbmZjX3Jlc2V0KHN0cnVjdCBhcmFzYW5fbmZjICpuZmMpCj4gPiAr ewo+ID4gKwlhbmZjX2Rpc2FibGVfaW50KG5mYywgRVZFTlRfTUFTSyk7Cj4gPiArCj4gPiArCS8q IEVuYWJsZSBhbGwgaW50ZXJydXB0IHN0YXR1cyAqLwo+ID4gKwl3cml0ZWxfcmVsYXhlZChFVkVO VF9NQVNLLCBuZmMtPmJhc2UgKyBJTlRSX1NUU19FTl9SRUcpOyAgCj4gCj4gVGhhdCBkb2Vzbid0 IHNvdW5kcyBsaWtlIGEgZ29vZCBpZGVhLiBJbnRlcnJ1cHRzIHNob3VsZCBiZSBlbmFibGVkIG9u bHkKPiB3aGVuIHlvdSBuZWVkIHRvIHdhaXQgb24gc3BlY2lmaWMgZXZlbnRzLgoKSSBhbSBub3Qg ZW5hYmxpbmcgdGhlIGludGVycnVwdCAic2lnbmFscyIgYnV0IGp1c3QgdGhlIGludGVycnVwdAoi c3RhdHVzIi4gSSdsbCBtYWtlIGl0IG1vcmUgY2xlYXIgYnkgZGlzYWJsaW5nIGFsbCBpbnRlcnJ1 cHQgc2lnbmFscwpmaXJzdC4KCj4gWzFdaHR0cHM6Ly9naXRodWIuY29tL2JicmV6aWxsb24vbGlu dXgvY29tbWl0LzAyYzBjZTYzYmUyZDQzZjIwN2JkZWNhZmQ1NTVjNDJlZmRhY2VjZTIKCgoKClRo YW5rcywKTWlxdcOobAoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fCkxpbnV4IE1URCBkaXNjdXNzaW9uIG1haWxpbmcgbGlzdApodHRwOi8vbGlz dHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LW10ZC8K From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.2 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,MENTIONS_GIT_HOSTING,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_SANE_2 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BDEF4C47247 for ; Thu, 7 May 2020 15:46:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 90D2A20838 for ; Thu, 7 May 2020 15:46:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726218AbgEGPqJ convert rfc822-to-8bit (ORCPT ); Thu, 7 May 2020 11:46:09 -0400 Received: from relay1-d.mail.gandi.net ([217.70.183.193]:14641 "EHLO relay1-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725914AbgEGPqH (ORCPT ); Thu, 7 May 2020 11:46:07 -0400 X-Originating-IP: 91.224.148.103 Received: from xps13 (unknown [91.224.148.103]) (Authenticated sender: miquel.raynal@bootlin.com) by relay1-d.mail.gandi.net (Postfix) with ESMTPSA id 9A00E24000D; Thu, 7 May 2020 15:46:00 +0000 (UTC) Date: Thu, 7 May 2020 17:45:59 +0200 From: Miquel Raynal To: Boris Brezillon Cc: , Rob Herring , Mark Rutland , Richard Weinberger , Vignesh Raghavendra , Tudor Ambarus , , Thomas Petazzoni , Michal Simek , Naga Sureshkumar Relli Subject: Re: [PATCH v3 7/8] mtd: rawnand: arasan: Add new Arasan NAND controller Message-ID: <20200507174559.58b57452@xps13> In-Reply-To: <20200507145127.71615ed8@collabora.com> References: <20200507110034.14736-1-miquel.raynal@bootlin.com> <20200507110034.14736-8-miquel.raynal@bootlin.com> <20200507145127.71615ed8@collabora.com> Organization: Bootlin X-Mailer: Claws Mail 3.17.4 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8BIT Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Hi Boris, Boris Brezillon wrote on Thu, 7 May 2020 14:51:27 +0200: > On Thu, 7 May 2020 13:00:33 +0200 > Miquel Raynal wrote: > > > > +/** > > + * struct arasan_nfc - Defines the Arasan NAND flash controller driver instance > > + * @dev: Pointer to the device structure > > + * @base: Remapped register area > > + * @controller_clk: Pointer to the system clock > > + * @bus_clk: Pointer to the flash clock > > + * @controller: Base controller structure > > + * @chips: List of all NAND chips attached to the controller > > + * @assigned_cs: Bitmask describing already assigned CS lines > > + * @cur_clk: Current clock rate > > + * @bf: Array of bitflips read in each ECC step > > + */ > > +struct arasan_nfc { > > + struct device *dev; > > + void __iomem *base; > > + struct clk *controller_clk; > > + struct clk *bus_clk; > > + struct nand_controller controller; > > + struct list_head chips; > > + unsigned long assigned_cs; > > + unsigned int cur_clk; > > + u8 *bf; > > Looks like this field is never used. Yes, it is a left over of a previous implementation, I'll drop it. > > > +}; > > + > > +static struct anand *to_anand(struct nand_chip *nand) > > +{ > > + return container_of(nand, struct anand, chip); > > +} > > + > > +static struct arasan_nfc *to_anfc(struct nand_controller *ctrl) > > +{ > > + return container_of(ctrl, struct arasan_nfc, controller); > > +} > > + > > +static void anfc_disable_int(struct arasan_nfc *nfc, u32 mask) > > +{ > > + mask &= ~EVENT_MASK; > > + mask &= EVENT_MASK; > > + writel_relaxed(mask, nfc->base + INTR_SIG_EN_REG); > > +} > > + > > +static int anfc_wait_for_event(struct arasan_nfc *nfc, unsigned int event) > > +{ > > + u32 val; > > + int ret; > > + > > + ret = readl_relaxed_poll_timeout(nfc->base + INTR_STS_REG, val, > > + val & event, 0, > > + ANFC_DFLT_TIMEOUT_US); > > + if (ret) { > > + dev_err(nfc->dev, "Timeout waiting for event 0x%x\n", event); > > + return -ETIMEDOUT; > > + } > > + > > + writel_relaxed(event, nfc->base + INTR_STS_REG); > > + > > + return 0; > > +} > > + > > +static int anfc_wait_for_rb(struct arasan_nfc *nfc, struct nand_chip *chip, > > + unsigned int timeout_ms) > > +{ > > + struct anand *anand = to_anand(chip); > > + u32 val; > > + int ret; > > + > > + ret = readl_relaxed_poll_timeout(nfc->base + READY_STS_REG, val, > > + val & BIT(anand->rb), > > + 0, timeout_ms * 1000); > > You don't have an interrupt on R/B transition? If can, that would > probably be better to use interrupts than polling the status reg. No, there are interrupts for the other signals, but none for RB. Here is the exhaustive list of available interrupts: https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html > > > + if (ret) { > > + dev_err(nfc->dev, "Timeout waiting for R/B 0x%x\n", > > + readl_relaxed(nfc->base + READY_STS_REG)); > > + return -ETIMEDOUT; > > + } > > + > > + return 0; > > +} > > + > > +static void anfc_trigger_op(struct arasan_nfc *nfc, struct anfc_op *nfc_op) > > +{ > > + writel_relaxed(nfc_op->pkt_reg, nfc->base + PKT_REG); > > + writel_relaxed(nfc_op->addr1_reg, nfc->base + MEM_ADDR1_REG); > > + writel_relaxed(nfc_op->addr2_reg, nfc->base + MEM_ADDR2_REG); > > + writel_relaxed(nfc_op->cmd_reg, nfc->base + CMD_REG); > > + writel_relaxed(nfc_op->prog_reg, nfc->base + PROG_REG); > > +} > > + > > +static int anfc_len_to_steps(struct nand_chip *chip, unsigned int len) > > +{ > > + unsigned int steps = 1, pktsize = len; > > + > > + while (pktsize > ANFC_MAX_PKT_SIZE) { > > + steps *= 2; > > + pktsize = DIV_ROUND_UP(len, steps); > > Hm, I'm not sure that's right. What happens if steps * pksize is bigger > than the requested number of DATA cycles? Not all operations accept to > have more data read/written than requested. > > I'd rather have something that does: > > static void anfc_len_to_steps(struct nand_chip *chip, unsigned int len, > unsigned int *pktsize, > unsigned int *npkts) > { > if (len <= ANFC_MAX_PKT_SIZE) { > *pktsize = len; > *npkts = 1; > return; > } > > for (*npkts = 2; *npkts < ANFC_MAX_NUM_PKTS; *npkts *= 2) { > *pktsize = len / *npkts; > if (*pktsize <= ANFC_MAX_PKT_SIZE) > break; > } > } > > And then, from the call size, you trigger new DATA_OUT/IN operation if > len > pktsize * npkts. That's something I cannot do with this controller, unfortunately... It does not support read/write only patterns. See below. > > > + } > > + > > + return steps; > > I guess you have a limit on steps. It's probably worth checking > that steps is in bounds. The upper limit is 2048, I'm not sure it is relevant to add a check here? > > > +} > > + > > +/* NAND framework ->exec_op() hooks and related helpers */ > > +static void anfc_parse_instructions(struct nand_chip *chip, > > + const struct nand_subop *subop, > > + struct anfc_op *nfc_op) > > +{ > > + struct anand *anand = to_anand(chip); > > + const struct nand_op_instr *instr = NULL; > > + bool first_cmd = true; > > + unsigned int op_id; > > + int i; > > + > > + memset(nfc_op, 0, sizeof(*nfc_op)); > > + nfc_op->addr2_reg = ADDR2_CS(anand->cs); > > + nfc_op->cmd_reg = CMD_PAGE_SIZE(anand->page_sz); > > + > > + for (op_id = 0; op_id < subop->ninstrs; op_id++) { > > + unsigned int offset, naddrs, pktsize; > > + const u8 *addrs; > > + u8 *buf; > > + > > + instr = &subop->instrs[op_id]; > > + > > + switch (instr->type) { > > + case NAND_OP_CMD_INSTR: > > + if (first_cmd) > > + nfc_op->cmd_reg |= CMD_1(instr->ctx.cmd.opcode); > > + else > > + nfc_op->cmd_reg |= CMD_2(instr->ctx.cmd.opcode); > > + > > + first_cmd = false; > > + break; > > + > > + case NAND_OP_ADDR_INSTR: > > + offset = nand_subop_get_addr_start_off(subop, op_id); > > + naddrs = nand_subop_get_num_addr_cyc(subop, op_id); > > + addrs = &instr->ctx.addr.addrs[offset]; > > + nfc_op->cmd_reg |= CMD_NADDRS(naddrs); > > + > > + for (i = 0; i < min(ANFC_MAX_ADDR_CYC, naddrs); i++) { > > + if (i < 4) > > + nfc_op->addr1_reg |= (u32)addrs[i] << i * 8; > > + else > > + nfc_op->addr2_reg |= addrs[i]; > > + } > > + > > + break; > > + case NAND_OP_DATA_IN_INSTR: > > + nfc_op->read = true; > > + fallthrough; > > + case NAND_OP_DATA_OUT_INSTR: > > + offset = nand_subop_get_data_start_off(subop, op_id); > > + buf = instr->ctx.data.buf.in; > > + nfc_op->buf = &buf[offset]; > > + nfc_op->len = nand_subop_get_data_len(subop, op_id); > > + nfc_op->steps = anfc_len_to_steps(chip, nfc_op->len); > > + pktsize = DIV_ROUND_UP(nfc_op->len, nfc_op->steps); > > + nfc_op->pkt_reg |= PKT_SIZE(round_up(pktsize, 4)) | > > Hm, pktsize has to be aligned on 4? Again, that's not great since you > adjust the size without letting the core know you did that. Mmmh probably not, I will test that. But a FIFO read is 4 bytes long so anyway, it will probably read/write more no matter what I request (and move the SRAM pointer). > > > + PKT_STEPS(nfc_op->steps); > > + break; > > + case NAND_OP_WAITRDY_INSTR: > > + nfc_op->rdy_timeout_ms = instr->ctx.waitrdy.timeout_ms; > > + break; > > + } > > + } > > +} > > + > > +static int anfc_rw_pio_op(struct arasan_nfc *nfc, struct anfc_op *nfc_op) > > +{ > > + unsigned int dwords = (nfc_op->len / 4) / nfc_op->steps; > > + unsigned int last_len = nfc_op->len % 4; > > + unsigned int offset, dir; > > + u8 *buf = nfc_op->buf; > > + int ret, i; > > + > > + for (i = 0; i < nfc_op->steps; i++) { > > + dir = nfc_op->read ? READ_READY : WRITE_READY; > > + ret = anfc_wait_for_event(nfc, dir); > > + if (ret) { > > + dev_err(nfc->dev, "PIO %s ready signal not received\n", > > + nfc_op->read ? "Read" : "Write"); > > + return ret; > > + } > > + > > + offset = i * (dwords * 4); > > + if (nfc_op->read) > > + ioread32_rep(nfc->base + DATA_PORT_REG, &buf[offset], > > + dwords); > > + else > > + iowrite32_rep(nfc->base + DATA_PORT_REG, &buf[offset], > > + dwords); > > + } > > + > > + if (last_len) { > > + u32 remainder; > > + > > + offset = nfc_op->len - last_len; > > + > > + if (nfc_op->read) { > > + remainder = readl_relaxed(nfc->base + DATA_PORT_REG); > > + memcpy(&buf[offset], &remainder, last_len); > > + } else { > > + memcpy(&remainder, &buf[offset], last_len); > > + writel_relaxed(remainder, nfc->base + DATA_PORT_REG); > > + } > > + } > > + > > + return anfc_wait_for_event(nfc, XFER_COMPLETE); > > +} > > + > > +static int anfc_misc_data_type_exec(struct nand_chip *chip, > > + const struct nand_subop *subop, > > + u32 prog_reg) > > +{ > > + struct arasan_nfc *nfc = to_anfc(chip->controller); > > + struct anfc_op nfc_op = {}; > > + int ret; > > + > > + anfc_parse_instructions(chip, subop, &nfc_op); > > + nfc_op.prog_reg = prog_reg; > > + anfc_trigger_op(nfc, &nfc_op); > > + > > + if (nfc_op.rdy_timeout_ms) { > > + ret = anfc_wait_for_rb(nfc, chip, nfc_op.rdy_timeout_ms); > > + if (ret) > > + return ret; > > + } > > + > > + return anfc_rw_pio_op(nfc, &nfc_op); > > +} > > + > > +static int anfc_param_read_type_exec(struct nand_chip *chip, > > + const struct nand_subop *subop) > > +{ > > + return anfc_misc_data_type_exec(chip, subop, PROG_RDPARAM); > > +} > > + > > +static int anfc_data_read_type_exec(struct nand_chip *chip, > > + const struct nand_subop *subop) > > +{ > > + return anfc_misc_data_type_exec(chip, subop, PROG_PGRD); > > +} > > + > > +static int anfc_param_write_type_exec(struct nand_chip *chip, > > + const struct nand_subop *subop) > > +{ > > + return anfc_misc_data_type_exec(chip, subop, PROG_SET_FEATURE); > > +} > > + > > +static int anfc_data_write_type_exec(struct nand_chip *chip, > > + const struct nand_subop *subop) > > +{ > > + return anfc_misc_data_type_exec(chip, subop, PROG_PGPROG); > > +} > > + > > +static int anfc_misc_zerolen_type_exec(struct nand_chip *chip, > > + const struct nand_subop *subop, > > + u32 prog_reg) > > +{ > > + struct arasan_nfc *nfc = to_anfc(chip->controller); > > + struct anfc_op nfc_op = {}; > > + int ret; > > + > > + anfc_parse_instructions(chip, subop, &nfc_op); > > + nfc_op.prog_reg = prog_reg; > > + anfc_trigger_op(nfc, &nfc_op); > > + > > + ret = anfc_wait_for_event(nfc, XFER_COMPLETE); > > + if (ret) > > + return ret; > > + > > + if (nfc_op.rdy_timeout_ms) > > + ret = anfc_wait_for_rb(nfc, chip, nfc_op.rdy_timeout_ms); > > + > > + return ret; > > +} > > + > > +static int anfc_status_type_exec(struct nand_chip *chip, > > + const struct nand_subop *subop) > > +{ > > + struct arasan_nfc *nfc = to_anfc(chip->controller); > > + u32 tmp; > > + int ret; > > + > > + /* > > + * This controller does not allow to proceed with a CMD+DATA_IN cycle > > + * manually on the bus by reading data from the data register. Instead, > > + * the controller abstract the status read operation with its own status > > + * register after ordering a read status operation. Hence, the following > > + * hack. > > + */ > > + if (subop->instrs[0].ctx.cmd.opcode != NAND_CMD_STATUS) > > + return -ENOTSUPP; > > + > > + ret = anfc_misc_zerolen_type_exec(chip, subop, PROG_STATUS); > > + if (ret) > > + return ret; > > + > > + tmp = readl_relaxed(nfc->base + FLASH_STS_REG); > > + memcpy(subop->instrs[1].ctx.data.buf.in, &tmp, 1); > > + > > + return 0; > > +} > > + > > +static int anfc_reset_type_exec(struct nand_chip *chip, > > + const struct nand_subop *subop) > > +{ > > + return anfc_misc_zerolen_type_exec(chip, subop, PROG_RST); > > +} > > + > > +static int anfc_erase_type_exec(struct nand_chip *chip, > > + const struct nand_subop *subop) > > +{ > > + return anfc_misc_zerolen_type_exec(chip, subop, PROG_ERASE); > > +} > > + > > +static int anfc_wait_type_exec(struct nand_chip *chip, > > + const struct nand_subop *subop) > > +{ > > + struct arasan_nfc *nfc = to_anfc(chip->controller); > > + struct anfc_op nfc_op = {}; > > + > > + anfc_parse_instructions(chip, subop, &nfc_op); > > + > > + return anfc_wait_for_rb(nfc, chip, nfc_op.rdy_timeout_ms); > > +} > > + > > +static const struct nand_op_parser anfc_op_parser = NAND_OP_PARSER( > > + NAND_OP_PARSER_PATTERN( > > + anfc_param_read_type_exec, > > + NAND_OP_PARSER_PAT_CMD_ELEM(false), > > + NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYC), > > + NAND_OP_PARSER_PAT_WAITRDY_ELEM(true), > > + NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, ANFC_MAX_CHUNK_SIZE)), > > + NAND_OP_PARSER_PATTERN( > > + anfc_param_write_type_exec, > > + NAND_OP_PARSER_PAT_CMD_ELEM(false), > > + NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYC), > > + NAND_OP_PARSER_PAT_DATA_OUT_ELEM(false, ANFC_MAX_PARAM_SIZE)), > > + NAND_OP_PARSER_PATTERN( > > + anfc_data_read_type_exec, > > + NAND_OP_PARSER_PAT_CMD_ELEM(false), > > + NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYC), > > + NAND_OP_PARSER_PAT_CMD_ELEM(false), > > + NAND_OP_PARSER_PAT_WAITRDY_ELEM(true), > > + NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, ANFC_MAX_CHUNK_SIZE)), > > + NAND_OP_PARSER_PATTERN( > > + anfc_data_write_type_exec, > > + NAND_OP_PARSER_PAT_CMD_ELEM(false), > > + NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYC), > > + NAND_OP_PARSER_PAT_DATA_OUT_ELEM(false, ANFC_MAX_CHUNK_SIZE), > > + NAND_OP_PARSER_PAT_CMD_ELEM(false)), > > + NAND_OP_PARSER_PATTERN( > > + anfc_reset_type_exec, > > + NAND_OP_PARSER_PAT_CMD_ELEM(false), > > + NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)), > > + NAND_OP_PARSER_PATTERN( > > + anfc_erase_type_exec, > > + NAND_OP_PARSER_PAT_CMD_ELEM(false), > > + NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYC), > > + NAND_OP_PARSER_PAT_CMD_ELEM(false), > > + NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)), > > + NAND_OP_PARSER_PATTERN( > > + anfc_status_type_exec, > > + NAND_OP_PARSER_PAT_CMD_ELEM(false), > > + NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, ANFC_MAX_CHUNK_SIZE)), > > + NAND_OP_PARSER_PATTERN( > > + anfc_wait_type_exec, > > + NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)), > > + ); > > + > > Okay, no DATA-only patterns, so my suggestion to split non-aligned data > reads doesn't work. I'd suggest to describe data-lengths > constraints rather than automatically adjusting the data length to > something bigger when we can't do exactly the number of requested DATA > cycles. Well, we *must* adjust the data length automatically. But the below change is interesting and should be extended and then this controller updated (see the next sentence). > I started doing something similar here [1], except you'd need > much more fined-grained constraints, so maybe we should add an optional > check hook to data patterns. We could describe a "round_up" limitation too. That's definitely something that we can add in this driver on top of [1]. Would apply to Marvell NFC as well for instance. > > +static int anfc_select_target(struct nand_chip *chip, int target) > > +{ > > + struct anand *anand = to_anand(chip); > > + struct arasan_nfc *nfc = to_anfc(chip->controller); > > + int ret; > > + > > + /* Update the controller timings and the potential ECC configuration */ > > + writel_relaxed(anand->timings, nfc->base + DATA_INTERFACE_REG); > > + > > + /* Update clock frequency */ > > + if (nfc->cur_clk != anand->clk) { > > + clk_disable_unprepare(nfc->controller_clk); > > + ret = clk_set_rate(nfc->controller_clk, anand->clk); > > + if (ret) { > > + dev_err(nfc->dev, "Failed to change clock rate\n"); > > + return ret; > > + } > > + > > + ret = clk_prepare_enable(nfc->controller_clk); > > + if (ret) { > > + dev_err(nfc->dev, > > + "Failed to re-enable the controller clock\n"); > > + return ret; > > + } > > + > > + nfc->cur_clk = anand->clk; > > + } > > + > > + return 0; > > +} > > + > > +static int anfc_exec_op(struct nand_chip *chip, > > + const struct nand_operation *op, > > + bool check_only) > > +{ > > + int ret; > > + > > + if (!check_only) { > > + ret = anfc_select_target(chip, op->cs); > > + if (ret) > > + return ret; > > + } > > Given you do only one thing in the check_only case, I'd do: > > if (check_only) > nand_op_parser_exec_op(chip, &anfc_op_parser, op, true); > > ret = anfc_select_target(chip, op->cs); > if (ret) > return ret; > > ... ok > > + > > + return nand_op_parser_exec_op(chip, &anfc_op_parser, op, check_only); > > +} > > + > > +static int anfc_setup_data_interface(struct nand_chip *chip, int target, > > + const struct nand_data_interface *conf) > > +{ > > + struct anand *anand = to_anand(chip); > > + struct arasan_nfc *nfc = to_anfc(chip->controller); > > + struct device_node *np = nfc->dev->of_node; > > + > > + if (target < 0) > > + return 0; > > + > > + anand->timings = DIFACE_SDR | DIFACE_SDR_MODE(conf->timings.mode); > > + anand->clk = ANFC_XLNX_SDR_DFLT_CORE_CLK; > > + > > + /* > > + * Due to a hardware bug in the ZynqMP SoC, SDR timing modes 0-1 work > > + * with f > 90MHz (default clock is 100MHz) but signals are unstable > > + * with higher modes. Hence we decrease a little bit the clock rate to > > + * 80MHz when using modes 2-5 with this SoC. > > + */ > > + if (of_device_is_compatible(np, "xlnx,zynqmp-nand-controller") && > > + conf->timings.mode >= 2) > > + anand->clk = ANFC_XLNX_SDR_HS_CORE_CLK; > > + > > + return 0; > > +} > > + > > +static int anfc_attach_chip(struct nand_chip *chip) > > +{ > > + struct anand *anand = to_anand(chip); > > + struct arasan_nfc *nfc = to_anfc(chip->controller); > > + struct mtd_info *mtd = nand_to_mtd(chip); > > + int ret = 0; > > + > > + if (mtd->writesize <= SZ_512) > > + anand->caddr_cycles = 1; > > + else > > + anand->caddr_cycles = 2; > > + > > + if (chip->options & NAND_ROW_ADDR_3) > > + anand->raddr_cycles = 3; > > + else > > + anand->raddr_cycles = 2; > > + > > + switch (mtd->writesize) { > > + case 512: > > + anand->page_sz = 0; > > + break; > > + case 1024: > > + anand->page_sz = 5; > > + break; > > + case 2048: > > + anand->page_sz = 1; > > + break; > > + case 4096: > > + anand->page_sz = 2; > > + break; > > + case 8192: > > + anand->page_sz = 3; > > + break; > > + case 16384: > > + anand->page_sz = 4; > > + break; > > + default: > > + return -EINVAL; > > + } > > + > > + /* These hooks are valid for all ECC providers */ > > + chip->ecc.read_page_raw = nand_monolithic_read_page_raw; > > + chip->ecc.write_page_raw = nand_monolithic_write_page_raw; > > + > > + switch (chip->ecc.mode) { > > + case NAND_ECC_NONE: > > + case NAND_ECC_SOFT: > > + case NAND_ECC_ON_DIE: > > + break; > > + case NAND_ECC_HW: > > + default: > > + dev_err(nfc->dev, "Unsupported ECC mode: %d\n", > > + chip->ecc.mode); > > + return -EINVAL; > > + } > > + > > + return ret; > > +} > > + > > +static const struct nand_controller_ops anfc_ops = { > > + .exec_op = anfc_exec_op, > > + .setup_data_interface = anfc_setup_data_interface, > > + .attach_chip = anfc_attach_chip, > > +}; > > + > > +static int anfc_chip_init(struct arasan_nfc *nfc, struct device_node *np) > > +{ > > + struct anand *anand; > > + struct nand_chip *chip; > > + struct mtd_info *mtd; > > + int cs, rb, ret; > > + > > + anand = devm_kzalloc(nfc->dev, sizeof(*anand), GFP_KERNEL); > > + if (!anand) > > + return -ENOMEM; > > + > > + /* Only one CS can be asserted at a time */ > > You mean the controller only has one CS? Cause that comment doesn't > make much sense. I don't remember why I wrote that. The controller has 2 CS (both tested), I'll drop the comment and the limitation. > > > + if (of_property_count_elems_of_size(np, "reg", sizeof(u32)) != 1) { > > + dev_err(nfc->dev, "Invalid reg property\n"); > > + return -EINVAL; > > + } > > It's only a SW limitation. If your controller has several CS pins > (which seems to be the case since you have a list of chips), it can > handle multi-CS chips too. I'm perfectly fine with the limitation > itself, but the comment should reflect the reality. And if you want to > support multi-CS chips, you just have to define an array of CS/RB in > anand. > > > + > > + ret = of_property_read_u32(np, "reg", &cs); > > + if (ret) > > + return ret; > > + > > + ret = of_property_read_u32(np, "nand-rb", &rb); > > + if (ret) > > + return ret; > > + > > + if (cs >= ANFC_MAX_CS || rb >= ANFC_MAX_CS) { > > + dev_err(nfc->dev, "Wrong CS %d or RB %d\n", cs, rb); > > + return -EINVAL; > > + } > > + > > + if (test_and_set_bit(cs, &nfc->assigned_cs)) { > > + dev_err(nfc->dev, "Already assigned CS %d\n", cs); > > + return -EINVAL; > > + } > > + > > + anand->cs = cs; > > + anand->rb = rb; > > + > > + chip = &anand->chip; > > + mtd = nand_to_mtd(chip); > > + mtd->dev.parent = nfc->dev; > > + chip->controller = &nfc->controller; > > + chip->options = NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE | > > + NAND_USES_DMA; > > + > > + nand_set_flash_node(chip, np); > > + if (!mtd->name) { > > + dev_err(nfc->dev, "NAND label property is mandatory\n"); > > + return -EINVAL; > > + } > > + > > + ret = nand_scan(chip, 1); > > + if (ret) { > > + dev_err(nfc->dev, "Scan operation failed\n"); > > + return ret; > > + } > > + > > + ret = mtd_device_register(mtd, NULL, 0); > > + if (ret) { > > + nand_release(chip); > > nand_cleanup(chip); Crap > > > + return ret; > > + } > > + > > + list_add_tail(&anand->node, &nfc->chips); > > + > > + return 0; > > +} > > + > > +static void anfc_chips_cleanup(struct arasan_nfc *nfc) > > +{ > > + struct anand *anand, *tmp; > > + > > + list_for_each_entry_safe(anand, tmp, &nfc->chips, node) { > > + nand_release(&anand->chip); > > + list_del(&anand->node); > > + } > > +} > > + > > +static int anfc_chips_init(struct arasan_nfc *nfc) > > +{ > > + struct device_node *np = nfc->dev->of_node, *nand_np; > > + int nchips = of_get_child_count(np); > > + int ret; > > + > > + if (!nchips || nchips > ANFC_MAX_CS) { > > + dev_err(nfc->dev, "Incorrect number of NAND chips (%d)\n", > > + nchips); > > + return -EINVAL; > > + } > > + > > + for_each_child_of_node(np, nand_np) { > > + ret = anfc_chip_init(nfc, nand_np); > > + if (ret) { > > + of_node_put(nand_np); > > + anfc_chips_cleanup(nfc); > > + break; > > + } > > + } > > + > > + return ret; > > +} > > + > > +static void anfc_reset(struct arasan_nfc *nfc) > > +{ > > + anfc_disable_int(nfc, EVENT_MASK); > > + > > + /* Enable all interrupt status */ > > + writel_relaxed(EVENT_MASK, nfc->base + INTR_STS_EN_REG); > > That doesn't sounds like a good idea. Interrupts should be enabled only > when you need to wait on specific events. I am not enabling the interrupt "signals" but just the interrupt "status". I'll make it more clear by disabling all interrupt signals first. > [1]https://github.com/bbrezillon/linux/commit/02c0ce63be2d43f207bdecafd555c42efdacece2 Thanks, Miquèl