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=-8.3 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,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 DC47CC3A5A4 for ; Fri, 30 Aug 2019 09:47:30 +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 942C121670 for ; Fri, 30 Aug 2019 09:47:30 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="kaXNYIk/" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 942C121670 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=GpJ0AELkQcKf3xVtBtG3PulkEXbItKqT2GMGDnYlfgM=; b=kaXNYIk/ZaSSH7 Z2IA7CA7mv4p2QTQXdOMRaG7d3hq13KNnkyOerzuAda6hrbX/6HZ1PY7zFsl9EUDdkCEQIWAR4+mJ 6PQfqbviVXWgKQo16Bh3nFKwClezAV3pm4xvLqhA+f8ZLzfS0at8K/8io/h0/57ZbGUwm466K7K/C eM6Mck+6BsHSnrwMK/KYrOZzevNkqzB7sEdnnz3H4uM7l5hzOMRqoXRBr3J0U9G2Vw1oh7aDshlG/ JxXaAyFKk9ViSHNrrTEt3Hq8hQGrIOCbNpcHITMz4uGhBzp/ZjM6g3RvQ3Ybc45dBIz4bx8R3/7lE uajoiwOetW9wxEsHtoqw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92 #3 (Red Hat Linux)) id 1i3dUp-000742-DD; Fri, 30 Aug 2019 09:47:07 +0000 Received: from relay1-d.mail.gandi.net ([217.70.183.193]) by bombadil.infradead.org with esmtps (Exim 4.92 #3 (Red Hat Linux)) id 1i3dUc-0006uk-F8 for linux-mtd@lists.infradead.org; Fri, 30 Aug 2019 09:47:01 +0000 X-Originating-IP: 86.250.200.211 Received: from xps13 (lfbn-1-17395-211.w86-250.abo.wanadoo.fr [86.250.200.211]) (Authenticated sender: miquel.raynal@bootlin.com) by relay1-d.mail.gandi.net (Postfix) with ESMTPSA id 8AE39240006; Fri, 30 Aug 2019 09:46:46 +0000 (UTC) Date: Fri, 30 Aug 2019 11:46:45 +0200 From: Miquel Raynal To: Piotr Sroka Subject: Re: [v5 1/2] mtd: nand: Add new Cadence NAND driver to MTD subsystem Message-ID: <20190830114645.59898cfe@xps13> In-Reply-To: <20190725150012.14416-1-piotrs@cadence.com> References: <20190725145804.8886-1-piotrs@cadence.com> <20190725150012.14416-1-piotrs@cadence.com> Organization: Bootlin X-Mailer: Claws Mail 3.17.3 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 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: Arnd Bergmann , Boris Brezillon , Marcel Ziswiler , Richard Weinberger , linux-kernel@vger.kernel.org, Stefan Agner , Marek Vasut , Paul Burton , Geert Uytterhoeven , linux-mtd@lists.infradead.org, Dmitry Osipenko , Brian Norris , David Woodhouse , Kazuhiro Kasai 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 SGkgUGlvdHIsCgpQaW90ciBTcm9rYSA8cGlvdHJzQGNhZGVuY2UuY29tPiB3cm90ZSBvbiBUaHUs IDI1IEp1bCAyMDE5IDE2OjAwOjEyCiswMTAwOgoKU3ViamVjdCBzaG91bGQgYmU6IG10ZDogcmF3 bmFuZDoKCkxhc3QgZmV3IG5pdHMgaW4geW91ciBkcml2ZXIgd2hpY2ggb3ZlcmFsbCBsb29rcyBn b29kIChzZWUgYmVsb3cpLgoKTm93IEknbSB3YWl0aW5nIGZvciBSb2IncyBhY2sgb24gdGhlIGJp bmRpbmdzLiBUaGlzIGRyaXZlciBzaG91bGQgYmUgYQpnb29kIGNhbmRpZGF0ZSBmb3IgNS41LgoK PiBBZGQgbmV3IENhZGVuY2UgTkFORCBkcml2ZXIgdG8gTVREIHN1YnN5c3RlbQo+IAo+IFNpZ25l ZC1vZmYtYnk6IFBpb3RyIFNyb2thIDxwaW90cnNAY2FkZW5jZS5jb20+Cj4gLS0tCj4gQ2hhbmdl cyBmb3IgdjU6Cj4gLSBmaXggImVjYyBjb25maWcgc3RyZW5ndGgiIGZpZWxkIHNpemUKPiAtIHJl bW92ZSB1bnVzZWQgbWFjcm9zCj4gLSBmaXggYWRkcmVzcyBvZiB0aW1pbmcyIHJlZ2lzdGVyCj4g LSBhZGQgZ3VhcmQgZm9yIGFjY2Vzc2luZyBkYXRhX2NvbnRyb2xfc2l6ZSByZWdpc3Rlcgo+IC0g c2ltcGxpZnkgdGhlIGRyaXZlciBieSB1c2UgdGhlIHNhbWUgZnVuY3Rpb24gCj4gICBmb3IgYWNj ZXNzaW5nIG1haW4gYXJlYSBhbmQgb29iIGFyZWEKPiAtIGFkZCBjb21tZW50IHRvIHRoZSBkcml2 ZXIgZGVzY3JpYmluZyBtYWluIGNvbnRyb2xsZXIgbW9kZXMKPiAtIGNoYW5nZSBjb21wYXRpYmxl IG5hbWUgZnJvbSBjZG5zLGhwbmZjIHRvIGNkbnMsaHAtbmZjCj4gQ2hhbmdlcyBmb3IgdjQ6Cj4g LSBmaXggY29tbWVudHMgaXNzdWVzIGxpa2UgdHlwb3MsIG1pc3NpbmcgY2FwaXRhbHMsIG1pc3Np bmcgZG90cyBldGMuCj4gLSByZW1vdmUgdW5uZWNlc3NhcnkgUEhZIG9wdGlvbnMgcGh5X2RsbF9h Z2luZyBhbmQgcGh5X3Blcl9iaXRfZGVza2V3Cj4gLSByZXBsYWNlIGFsbCByZWdpc3RlciBhY2Nl c3MgZnVuY3Rpb25zIHRvICJyZWxheGVkIiB2ZXJzaW9uCj4gLSByZW1vdmUgYWxsIHVubmVjZXNz YXJ5IHZhcmlhYmxlcyBpbml0aWFsaXphdGlvbnMKPiAtIGhhbmRsZSBlcnJvciBpbnNpZGUgY2Fk ZW5jZV9uYW5kX2dldF9lY2Nfc3RyZW5ndGhfaWR4IGZ1bmN0aW9uIGluIGNhc2UgCj4gICBjb3Jy ZW5jdGlvbiBzdHJlbmd0aCBpcyBub3QgZm91bmQKPiAtIGFkZCBjb21taXQgbWVzc2FnZQo+IENo YW5nZXMgZm9yIHYzOgo+IC0gcmVtb3ZlIGRlZmluaXRpb25zIG9mIHVudXNlZCByZWdpc3RlcnMK PiAtIHJlbW92ZSBjb25maWd1cmluZyByZWdpc3RlcnMgd2hpY2ggYXJlIG5vdCBleHBlY3RlZCB0 byBiZSBjb25maWd1cmVkIGluCj4gICBhc3luY2hyb25vdXMgbW9kZQo+IC0gcmVtb3ZlIG5vdCBu ZWVkZWQgZnVuY3Rpb24gcmVhZGluZyB0aW1pbmcgcmVnaXN0ZXJzCj4gLSByZW1vdmUgaW5mb3Jt YXRpb24gYWJvdXQgb29iIHNpemUgYW5kIHdyaXRlIHNpemUgZnJvbSBjZG5zX25hbmRfY2hpcCB0 eXBlCj4gICBhbmQgdXNlIHZhbGVzIGZyb20gbXRkX2luZm8gZGlyZWN0bHkKPiAtIHVzZSBuYW5k X2NsZWFudXAgaW5zdGVhZCBvZiBuYW5kX3JlbGVhc2UgaWYgbXRkIGRldmljZSBpcyBub3QgcmVn aXN0ZXJlZCB5ZXQKPiAtIGZpeCBjYWRlbmNlX25hbmRfY2hpcHNfaW5pdCBmdW5jdGlvbiBhZGQg Z2FyYmFnZSBjb2xsZWN0aW9uIAo+ICAgaWYgYSBjaGlwIGluaXQgZmFpbHMKPiAtIHNpbXBsaWZ5 IFBIWSBjYWxjdWxhdGlvbnMKPiBDaGFuZ2VzIGZvciB2MjoKPiAtIGNyZWF0ZSBvbmUgdW5pdmVy c2FsIHdhaXQgZnVuY3Rpb24gZm9yIGFsbCBldmVudHMgaW5zdGVhZCBvZiBvbmUKPiAgIGZ1bmN0 aW9uIHBlciBldmVudC4KPiAtIHNwbGl0IG9uZSBiaWcgZnVuY3Rpb24gZXhlY3V0aW5nIG5hbmQg b3BlcmF0aW9ucyB0byBzZXBhcmF0ZQo+ICAgZnVuY3Rpb25zIG9uZSBwZXIgZWFjaCB0eXBlIG9m IG9wZXJhdGlvbi4KPiAtIGFkZCBlcmFzZSBhdG9taWMgb3BlcmF0aW9uIHRvIG5hbmQgb3BlcmF0 aW9uIHBhcnNlcgo+IC0gcmVtb3ZlIHVubmVjZXNzYXJ5IGluY2x1ZGVzLgo+IC0gcmVtb3ZlIHVu dXNlZCByZWdpc3RlciBkZWZpbmVzIAo+IC0gYWRkIHN1cHBvcnQgZm9yIG11bHRpcGxlIG5hbmQg Y2hpcHMKPiAtIHJlbW92ZSBhbGwgY29kZSB1c2luZyBsZWdhY3kgZnVuY3Rpb25zCj4gLSByZW1v dmUgY2hpcCBkZXBlbmRlbnRzIHBhcmFtZXRlcnMgZnJvbSBkdHMgYmluZGluZ3MsIHRoZXkgd2Vy ZQo+ICAgYXR0YWNoZWQgdG8gdGhlIFNvQyBzcGVjaWZpYyBjb21wYXRpYmxlIGF0IHRoZSBkcml2 ZXIgbGV2ZWwKPiAtIHNpbXBsaWZ5IGludGVycnVwdCBoYW5kbGluZwo+IC0gc2ltcGxpZnkgdGlt aW5nIGNhbGN1bGF0aW9ucwo+IC0gZml4IGNhbGN1bGF0aW9uIG9mIG1heGltdW0gc3VwcG9ydGVk IGNzIHNpZ25hbHMKPiAtIHNpbXBsaWZ5IGVjYyBzaXplIGNhbGN1bGF0aW9uCj4gLSByZW1vdmUg aGVhZGVyIGZpbGUgYW5kIHB1dCB3aG9sZSBjb2RlIHRvIG9uZSBjIGZpbGUKPiAtLS0KPiAgZHJp dmVycy9tdGQvbmFuZC9yYXcvS2NvbmZpZyAgICAgICAgICAgICAgICAgICB8ICAgIDcgKwo+ICBk cml2ZXJzL210ZC9uYW5kL3Jhdy9NYWtlZmlsZSAgICAgICAgICAgICAgICAgIHwgICAgMSArCj4g IGRyaXZlcnMvbXRkL25hbmQvcmF3L2NhZGVuY2UtbmFuZC1jb250cm9sbGVyLmMgfCAzMDIxICsr KysrKysrKysrKysrKysrKysrKysrKwo+ICAzIGZpbGVzIGNoYW5nZWQsIDMwMjkgaW5zZXJ0aW9u cygrKQo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9tdGQvbmFuZC9yYXcvY2FkZW5jZS1u YW5kLWNvbnRyb2xsZXIuYwo+IAo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL210ZC9uYW5kL3Jhdy9L Y29uZmlnIGIvZHJpdmVycy9tdGQvbmFuZC9yYXcvS2NvbmZpZwo+IGluZGV4IGU2MDQ2MjVlMmRm YS4uNGQyY2UzYjViMmFlIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvbXRkL25hbmQvcmF3L0tjb25m aWcKPiArKysgYi9kcml2ZXJzL210ZC9uYW5kL3Jhdy9LY29uZmlnCj4gQEAgLTU1Nyw1ICs1NTcs MTIgQEAgY29uZmlnIE1URF9OQU5EX01FU09OCj4gIAloZWxwCj4gIAkgIEVuYWJsZXMgc3VwcG9y dCBmb3IgTkFORCBjb250cm9sbGVyIG9uIEFtbG9naWMncyBNZXNvbiBTb0NzLgo+ICAJICBUaGlz IGNvbnRyb2xsZXIgaXMgZm91bmQgb24gTWVzb24gU29Dcy4KCk1pc3Npbmcgc3BhY2U/Cgo+ICtj b25maWcgTVREX05BTkRfQ0FERU5DRQo+ICsJdHJpc3RhdGUgIlN1cHBvcnQgQ2FkZW5jZSBOQU5E IChIUE5GQykgY29udHJvbGxlciIKPiArCWRlcGVuZHMgb24gT0YKCiB8fCBDT01QSUxFX1RFU1QK Cj4gKwloZWxwCj4gKwkgIEVuYWJsZSB0aGUgZHJpdmVyIGZvciBOQU5EIGZsYXNoIG9uIHBsYXRm b3JtcyB1c2luZyBhIENhZGVuY2UgTkFORAo+ICsJICBjb250cm9sbGVyLgo+ICsKPiAgCj4gIGVu ZGlmICMgTVREX05BTkQKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9tdGQvbmFuZC9yYXcvTWFrZWZp bGUgYi9kcml2ZXJzL210ZC9uYW5kL3Jhdy9NYWtlZmlsZQo+IGluZGV4IDVhNWE3MmYwNzkzZS4u ZjRiMDk5ZjI3NmY3IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvbXRkL25hbmQvcmF3L01ha2VmaWxl Cj4gKysrIGIvZHJpdmVycy9tdGQvbmFuZC9yYXcvTWFrZWZpbGUKPiBAQCAtNTgsNiArNTgsNyBA QCBvYmotJChDT05GSUdfTVREX05BTkRfTVRLKQkJKz0gbXRrX2VjYy5vIG10a19uYW5kLm8KPiAg b2JqLSQoQ09ORklHX01URF9OQU5EX1RFR1JBKQkJKz0gdGVncmFfbmFuZC5vCj4gIG9iai0kKENP TkZJR19NVERfTkFORF9TVE0zMl9GTUMyKQkrPSBzdG0zMl9mbWMyX25hbmQubwo+ICBvYmotJChD T05GSUdfTVREX05BTkRfTUVTT04pCQkrPSBtZXNvbl9uYW5kLm8KPiArb2JqLSQoQ09ORklHX01U RF9OQU5EX0NBREVOQ0UpCQkrPSBjYWRlbmNlLW5hbmQtY29udHJvbGxlci5vCj4gIAo+ICBuYW5k LW9ianMgOj0gbmFuZF9iYXNlLm8gbmFuZF9sZWdhY3kubyBuYW5kX2JidC5vIG5hbmRfdGltaW5n cy5vIG5hbmRfaWRzLm8KPiAgbmFuZC1vYmpzICs9IG5hbmRfb25maS5vCj4gZGlmZiAtLWdpdCBh L2RyaXZlcnMvbXRkL25hbmQvcmF3L2NhZGVuY2UtbmFuZC1jb250cm9sbGVyLmMgYi9kcml2ZXJz L210ZC9uYW5kL3Jhdy9jYWRlbmNlLW5hbmQtY29udHJvbGxlci5jCj4gbmV3IGZpbGUgbW9kZSAx MDA2NDQKPiBpbmRleCAwMDAwMDAwMDAwMDAuLmE3ZmY0ZTQ1ODVkMwo+IC0tLSAvZGV2L251bGwK PiArKysgYi9kcml2ZXJzL210ZC9uYW5kL3Jhdy9jYWRlbmNlLW5hbmQtY29udHJvbGxlci5jCj4g QEAgLTAsMCArMSwzMDIxIEBACj4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4w Kwo+ICsvKgo+ICsgKiBDYWRlbmNlIE5BTkQgZmxhc2ggY29udHJvbGxlciBkcml2ZXIKPiArICoK PiArICogQ29weXJpZ2h0IChDKSAyMDE5IENhZGVuY2UKCkkgZ3Vlc3MgeW91IGRlc2VydmUgdGhl IEF1dGhvcjogZW50cnkgaGVyZSA6KQoKPiArICovCj4gKwo+ICsjaW5jbHVkZSA8bGludXgvYml0 ZmllbGQuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2Nsay5oPgo+ICsjaW5jbHVkZSA8bGludXgvZG1h LW1hcHBpbmcuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2RtYWVuZ2luZS5oPgo+ICsjaW5jbHVkZSA8 bGludXgvaW50ZXJydXB0Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KPiArI2luY2x1 ZGUgPGxpbnV4L210ZC9tdGQuaD4KPiArI2luY2x1ZGUgPGxpbnV4L210ZC9yYXduYW5kLmg+Cj4g KyNpbmNsdWRlIDxsaW51eC9vZl9kZXZpY2UuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2lvcG9sbC5o Pgo+ICsKPiArLyoKPiArICogSFBORkMgY2FuIHdvcmsgaW4gMyBtb2RlczoKPiArICogLSAgUElP IC0gY2FuIHdvcmsgaW4gbWFzdGVyIG9yIHNsYXZlIERNQS4KPiArICogLSAgQ0RNQSAtIG5lZWRz IE1hc3RlciBETUEgZm9yIGFjY2Vzc2luZyBjb21tYW5kIGRlc2NyaXB0b3JzLgo+ICsgKiAtICBH ZW5lcmljIG1vZGUgLSBjYW4gdXNlIG9ubHkgc2xhdmUgRE1BLgo+ICsgKiBDRE1BIGFuZCBQSU8g bW9kZXMgY2FuIGJlIHVzZWQgdG8gZXhlY3V0ZSBvbmx5IGJhc2UgY29tbWFuZHMuCj4gKyAqIEdl bmVyaWMgbW9kZSBjYW4gYmUgdXNlZCB0byBleGVjdXRlIGFueSBjb21tYW5kCj4gKyAqIG9uIE5B TkQgZmxhc2ggbWVtb3J5LiBEcml2ZXIgdXNlcyBDRE1BIG1vZGUgZm9yCj4gKyAqIGJsb2NrIGVy YXNpbmcsIHBhZ2UgcmVhZGluZywgcGFnZSBwcm9ncmFtaW5nLgo+ICsgKiBHZW5lcmljIG1vZGUg aXMgdXNlZCBmb3IgZXhlY3V0aW5nIHJlc3Qgb2YgY29tbWFuZHMuCj4gKyAqLwo+ICsKPiArI2Rl ZmluZSBNQVhfT09CX1NJWkVfUEVSX1NFQ1RPUgkzMgo+ICsjZGVmaW5lIE1BWF9BRERSRVNTX0NZ QwkJNgo+ICsjZGVmaW5lIE1BWF9FUkFTRV9BRERSRVNTX0NZQwkzCj4gKyNkZWZpbmUgTUFYX0RB VEFfU0laRQkJMHhGRkZDCj4gKwo+ICsvKiBSZWdpc3RlciBkZWZpbml0aW9uLiAqLwo+ICsvKgo+ ICsgKiBDb21tYW5kIHJlZ2lzdGVyIDAuCj4gKyAqIFdyaXRpbmcgZGF0YSB0byB0aGlzIHJlZ2lz dGVyIHdpbGwgaW5pdGlhdGUgYSBuZXcgdHJhbnNhY3Rpb24KPiArICogb2YgdGhlIE5GIGNvbnRy b2xsZXIuCj4gKyAqLwo+ICsjZGVmaW5lIENNRF9SRUcwCQkJMHgwMDAwCj4gKy8qIENvbW1hbmQg dHlwZSBmaWVsZCBtYXNrLiAqLwo+ICsjZGVmaW5lCQlDTURfUkVHMF9DVAkJR0VOTUFTSygzMSwg MzApCj4gKy8qIENvbW1hbmQgdHlwZSBDRE1BLiAqLwo+ICsjZGVmaW5lCQlDTURfUkVHMF9DVF9D RE1BCTB1TAo+ICsvKiBDb21tYW5kIHR5cGUgZ2VuZXJpYy4gKi8KPiArI2RlZmluZQkJQ01EX1JF RzBfQ1RfR0VOCQkzdUwKPiArLyogQ29tbWFuZCB0aHJlYWQgbnVtYmVyIGZpZWxkIG1hc2suICov Cj4gKyNkZWZpbmUJCUNNRF9SRUcwX1ROCQlHRU5NQVNLKDI3LCAyNCkKPiArCj4gKy8qIENvbW1h bmQgcmVnaXN0ZXIgMi4gKi8KPiArI2RlZmluZSBDTURfUkVHMgkJCTB4MDAwOAo+ICsvKiBDb21t YW5kIHJlZ2lzdGVyIDMuICovCj4gKyNkZWZpbmUgQ01EX1JFRzMJCQkweDAwMEMKPiArLyogUG9p bnRlciByZWdpc3RlciB0byBzZWxlY3Qgd2hpY2ggdGhyZWFkIHN0YXR1cyB3aWxsIGJlIHNlbGVj dGVkLiAqLwo+ICsjZGVmaW5lIENNRF9TVEFUVVNfUFRSCQkJMHgwMDEwCj4gKy8qIENvbW1hbmQg c3RhdHVzIHJlZ2lzdGVyIGZvciBzZWxlY3RlZCB0aHJlYWQuICovCj4gKyNkZWZpbmUgQ01EX1NU QVRVUwkJCTB4MDAxNAo+ICsKPiArLyogSW50ZXJydXB0IHN0YXR1cyByZWdpc3Rlci4gKi8KPiAr I2RlZmluZSBJTlRSX1NUQVRVUwkJCTB4MDExMAo+ICsjZGVmaW5lCQlJTlRSX1NUQVRVU19TRE1B X0VSUglCSVQoMjIpCj4gKyNkZWZpbmUJCUlOVFJfU1RBVFVTX1NETUFfVFJJR0cJQklUKDIxKQo+ ICsjZGVmaW5lCQlJTlRSX1NUQVRVU19VTlNVUFBfQ01ECUJJVCgxOSkKPiArI2RlZmluZQkJSU5U Ul9TVEFUVVNfRERNQV9URVJSCUJJVCgxOCkKPiArI2RlZmluZQkJSU5UUl9TVEFUVVNfQ0RNQV9U RVJSCUJJVCgxNykKPiArI2RlZmluZQkJSU5UUl9TVEFUVVNfQ0RNQV9JREwJQklUKDE2KQo+ICsK PiArLyogSW50ZXJydXB0IGVuYWJsZSByZWdpc3Rlci4gKi8KPiArI2RlZmluZSBJTlRSX0VOQUJM RQkJCQkweDAxMTQKPiArI2RlZmluZQkJSU5UUl9FTkFCTEVfSU5UUl9FTgkJQklUKDMxKQo+ICsj ZGVmaW5lCQlJTlRSX0VOQUJMRV9TRE1BX0VSUl9FTgkJQklUKDIyKQo+ICsjZGVmaW5lCQlJTlRS X0VOQUJMRV9TRE1BX1RSSUdHX0VOCUJJVCgyMSkKPiArI2RlZmluZQkJSU5UUl9FTkFCTEVfVU5T VVBQX0NNRF9FTglCSVQoMTkpCj4gKyNkZWZpbmUJCUlOVFJfRU5BQkxFX0RETUFfVEVSUl9FTglC SVQoMTgpCj4gKyNkZWZpbmUJCUlOVFJfRU5BQkxFX0NETUFfVEVSUl9FTglCSVQoMTcpCj4gKyNk ZWZpbmUJCUlOVFJfRU5BQkxFX0NETUFfSURMRV9FTglCSVQoMTYpCj4gKwo+ICsvKiBDb250cm9s bGVyIGludGVybmFsIHN0YXRlLiAqLwo+ICsjZGVmaW5lIENUUkxfU1RBVFVTCQkJCTB4MDExOAo+ ICsjZGVmaW5lCQlDVFJMX1NUQVRVU19JTklUX0NPTVAJCUJJVCg5KQo+ICsjZGVmaW5lCQlDVFJM X1NUQVRVU19DVFJMX0JVU1kJCUJJVCg4KQo+ICsKPiArLyogQ29tbWFuZCBFbmdpbmUgdGhyZWFk cyBzdGF0ZS4gKi8KPiArI2RlZmluZSBUUkRfU1RBVFVTCQkJCTB4MDEyMAo+ICsKPiArLyogQ29t bWFuZCBFbmdpbmUgaW50ZXJydXB0IHRocmVhZCBlcnJvciBzdGF0dXMuICovCj4gKyNkZWZpbmUg VFJEX0VSUl9JTlRfU1RBVFVTCQkJMHgwMTI4Cj4gKy8qIENvbW1hbmQgRW5naW5lIGludGVycnVw dCB0aHJlYWQgZXJyb3IgZW5hYmxlLiAqLwo+ICsjZGVmaW5lIFRSRF9FUlJfSU5UX1NUQVRVU19F TgkJCTB4MDEzMAo+ICsvKiBDb21tYW5kIEVuZ2luZSBpbnRlcnJ1cHQgdGhyZWFkIGNvbXBsZXRl IHN0YXR1cy4gKi8KPiArI2RlZmluZSBUUkRfQ09NUF9JTlRfU1RBVFVTCQkJMHgwMTM4Cj4gKwo+ ICsvKgo+ICsgKiBUcmFuc2ZlciBjb25maWcgMCByZWdpc3Rlci4KPiArICogQ29uZmlndXJlcyBk YXRhIHRyYW5zZmVyIHBhcmFtZXRlcnMuCj4gKyAqLwo+ICsjZGVmaW5lIFRSQU5fQ0ZHXzAJCQkJ MHgwNDAwCj4gKy8qIE9mZnNldCB2YWx1ZSBmcm9tIHRoZSBiZWdpbm5pbmcgb2YgdGhlIHBhZ2Uu ICovCj4gKyNkZWZpbmUJCVRSQU5fQ0ZHXzBfT0ZGU0VUCQlHRU5NQVNLKDMxLCAxNikKPiArLyog TnVtYmVycyBvZiBzZWN0b3JzIHRvIHRyYW5zZmVyIHdpdGhpbiBzaW5nbE5GIGRldmljZSdzIHBh Z2UuICovCj4gKyNkZWZpbmUJCVRSQU5fQ0ZHXzBfU0VDX0NOVAkJR0VOTUFTSyg3LCAwKQo+ICsK PiArLyoKPiArICogVHJhbnNmZXIgY29uZmlnIDEgcmVnaXN0ZXIuCj4gKyAqIENvbmZpZ3VyZXMg ZGF0YSB0cmFuc2ZlciBwYXJhbWV0ZXJzLgo+ICsgKi8KPiArI2RlZmluZSBUUkFOX0NGR18xCQkJ CTB4MDQwNAo+ICsvKiBTaXplIG9mIGxhc3QgZGF0YSBzZWN0b3IuICovCj4gKyNkZWZpbmUJCVRS QU5fQ0ZHXzFfTEFTVF9TRUNfU0laRQlHRU5NQVNLKDMxLCAxNikKPiArLyogU2l6ZSBvZiBub3Qt bGFzdCBkYXRhIHNlY3Rvci4gKi8KPiArI2RlZmluZQkJVFJBTl9DRkdfMV9TRUNUT1JfU0laRQkJ R0VOTUFTSygxNSwgMCkKPiArCj4gKy8qIEVDQyBlbmdpbmUgY29uZmlndXJhdGlvbiByZWdpc3Rl ciAwLiAqLwo+ICsjZGVmaW5lIEVDQ19DT05GSUdfMAkJCQkweDA0MjgKPiArLyogQ29ycmVjdGlv biBzdHJlbmd0aC4gKi8KPiArI2RlZmluZQkJRUNDX0NPTkZJR18wX0NPUlJfU1RSCQlHRU5NQVNL KDEwLCA4KQo+ICsvKiBFbmFibGUgZXJhc2VkIHBhZ2VzIGRldGVjdGlvbiBtZWNoYW5pc20uICov Cj4gKyNkZWZpbmUJCUVDQ19DT05GSUdfMF9FUkFTRV9ERVRfRU4JQklUKDEpCj4gKy8qIEVuYWJs ZSBjb250cm9sbGVyIEVDQyBjaGVjayBiaXRzIGdlbmVyYXRpb24gYW5kIGNvcnJlY3Rpb24uICov Cj4gKyNkZWZpbmUJCUVDQ19DT05GSUdfMF9FQ0NfRU4JCUJJVCgwKQo+ICsKPiArLyogRUNDIGVu Z2luZSBjb25maWd1cmF0aW9uIHJlZ2lzdGVyIDEuICovCj4gKyNkZWZpbmUgRUNDX0NPTkZJR18x CQkJCTB4MDQyQwo+ICsKPiArLyogTXVsdGlwbGFuZSBzZXR0aW5ncyByZWdpc3Rlci4gKi8KPiAr I2RlZmluZSBNVUxUSVBMQU5FX0NGRwkJCQkweDA0MzQKPiArLyogQ2FjaGUgb3BlcmF0aW9uIHNl dHRpbmdzLiAqLwo+ICsjZGVmaW5lIENBQ0hFX0NGRwkJCQkweDA0MzgKPiArCj4gKy8qIERNQSBz ZXR0aW5ncyByZWdpc3Rlci4gKi8KPiArI2RlZmluZSBETUFfU0VUSU5HUwkJCQkweDA0M0MKPiAr LyogRW5hYmxlIFNETUEgZXJyb3IgcmVwb3J0IG9uIGFjY2VzcyB1bnByZXBhcmVkIHNsYXZlIERN QSBpbnRlcmZhY2UuICovCj4gKyNkZWZpbmUJCURNQV9TRVRJTkdTX1NETUFfRVJSX1JTUAlCSVQo MTcpCj4gKwo+ICsvKiBUcmFuc2ZlcnJlZCBkYXRhIGJsb2NrIHNpemUgZm9yIHRoZSBzbGF2ZSBE TUEgbW9kdWxlLiAqLwo+ICsjZGVmaW5lIFNETUFfU0laRQkJCQkweDA0NDAKPiArCj4gKy8qIFRo cmVhZCBudW1iZXIgYXNzb2NpYXRlZCB3aXRoIHRyYW5zZmVycmVkIGRhdGEgYmxvY2sKPiArICog Zm9yIHRoZSBzbGF2ZSBETUEgbW9kdWxlLgo+ICsgKi8KPiArI2RlZmluZSBTRE1BX1RSRF9OVU0J CQkJMHgwNDQ0Cj4gKy8qIFRocmVhZCBudW1iZXIgbWFzay4gKi8KPiArI2RlZmluZQkJU0RNQV9U UkRfTlVNX1NETUFfVFJECQlHRU5NQVNLKDIsIDApCj4gKwo+ICsjZGVmaW5lIENPTlRST0xfREFU QV9DVFJMCQkJMHgwNDk0Cj4gKy8qIFRocmVhZCBudW1iZXIgbWFzay4gKi8KPiArI2RlZmluZQkJ Q09OVFJPTF9EQVRBX0NUUkxfU0laRQkJR0VOTUFTSygxNSwgMCkKPiArCj4gKyNkZWZpbmUgQ1RS TF9WRVJTSU9OCQkJCTB4ODAwCj4gKwo+ICsvKiBBdmFpbGFibGUgaGFyZHdhcmUgZmVhdHVyZXMg b2YgdGhlIGNvbnRyb2xsZXIuICovCj4gKyNkZWZpbmUgQ1RSTF9GRUFUVVJFUwkJCQkweDgwNAo+ ICsvKiBTdXBwb3J0IGZvciBOVi1ERFIyLzMgd29yayBtb2RlLiAqLwo+ICsjZGVmaW5lCQlDVFJM X0ZFQVRVUkVTX05WRERSXzJfMwkJQklUKDI4KQo+ICsvKiBTdXBwb3J0IGZvciBOVi1ERFIgd29y ayBtb2RlLiAqLwo+ICsjZGVmaW5lCQlDVFJMX0ZFQVRVUkVTX05WRERSCQlCSVQoMjcpCj4gKy8q IFN1cHBvcnQgZm9yIGFzeW5jaHJvbm91cyB3b3JrIG1vZGUuICovCj4gKyNkZWZpbmUJCUNUUkxf RkVBVFVSRVNfQVNZTkMJCUJJVCgyNikKPiArLyogU3VwcG9ydCBmb3IgYXN5bmNocm9ub3VzIHdv cmsgbW9kZS4gKi8KPiArI2RlZmluZQkJQ1RSTF9GRUFUVVJFU19OX0JBTktTCQlHRU5NQVNLKDI1 LCAyNCkKPiArLyogU2xhdmUgYW5kIE1hc3RlciBETUEgZGF0YSB3aWR0aC4gKi8KPiArI2RlZmlu ZQkJQ1RSTF9GRUFUVVJFU19ETUFfRFdJVEg2NAlCSVQoMjEpCj4gKy8qIEF2YWlsYWJpbGl0eSBv ZiBDb250cm9sIERhdGEgZmVhdHVyZS4qLwo+ICsjZGVmaW5lCQlDVFJMX0ZFQVRVUkVTX0NPTlRS T0xfREFUQQlCSVQoMTApCj4gKwo+ICsvKiBCQ0ggRW5naW5lIGlkZW50aWZpY2F0aW9uIHJlZ2lz dGVyIDAgLSBjb3JyZWN0aW9uIHN0cmVuZ3Rocy4gKi8KPiArI2RlZmluZSBCQ0hfQ0ZHXzAJCQkJ MHg4MzgKPiArI2RlZmluZQkJQkNIX0NGR18wX0NPUlJfQ0FQXzAJCUdFTk1BU0soNywgMCkKPiAr I2RlZmluZQkJQkNIX0NGR18wX0NPUlJfQ0FQXzEJCUdFTk1BU0soMTUsIDgpCj4gKyNkZWZpbmUJ CUJDSF9DRkdfMF9DT1JSX0NBUF8yCQlHRU5NQVNLKDIzLCAxNikKPiArI2RlZmluZQkJQkNIX0NG R18wX0NPUlJfQ0FQXzMJCUdFTk1BU0soMzEsIDI0KQo+ICsKPiArLyogQkNIIEVuZ2luZSBpZGVu dGlmaWNhdGlvbiByZWdpc3RlciAxIC0gY29ycmVjdGlvbiBzdHJlbmd0aHMuICovCj4gKyNkZWZp bmUgQkNIX0NGR18xCQkJCTB4ODNDCj4gKyNkZWZpbmUJCUJDSF9DRkdfMV9DT1JSX0NBUF80CQlH RU5NQVNLKDcsIDApCj4gKyNkZWZpbmUJCUJDSF9DRkdfMV9DT1JSX0NBUF81CQlHRU5NQVNLKDE1 LCA4KQo+ICsjZGVmaW5lCQlCQ0hfQ0ZHXzFfQ09SUl9DQVBfNgkJR0VOTUFTSygyMywgMTYpCj4g KyNkZWZpbmUJCUJDSF9DRkdfMV9DT1JSX0NBUF83CQlHRU5NQVNLKDMxLCAyNCkKPiArCj4gKy8q IEJDSCBFbmdpbmUgaWRlbnRpZmljYXRpb24gcmVnaXN0ZXIgMiAtIHNlY3RvciBzaXplcy4gKi8K PiArI2RlZmluZSBCQ0hfQ0ZHXzIJCQkJMHg4NDAKPiArI2RlZmluZQkJQkNIX0NGR18yX1NFQ1Rf MAkJR0VOTUFTSygxNSwgMCkKPiArI2RlZmluZQkJQkNIX0NGR18yX1NFQ1RfMQkJR0VOTUFTSygz MSwgMTYpCj4gKwo+ICsvKiBCQ0ggRW5naW5lIGlkZW50aWZpY2F0aW9uIHJlZ2lzdGVyIDMuICov Cj4gKyNkZWZpbmUgQkNIX0NGR18zCQkJCTB4ODQ0Cj4gKwo+ICsvKiBSZWFkeS9CdXN5IyBsaW5l IHN0YXR1cy4gKi8KPiArI2RlZmluZSBSQk5fU0VUSU5HUwkJCQkweDEwMDQKPiArCj4gKy8qIENv bW1vbiBzZXR0aW5ncy4gKi8KPiArI2RlZmluZSBDT01NT05fU0VUCQkJCTB4MTAwOAo+ICsvKiAx NiBiaXQgZGV2aWNlIGNvbm5lY3RlZCB0byB0aGUgTkFORCBGbGFzaCBpbnRlcmZhY2UuICovCj4g KyNkZWZpbmUJCUNPTU1PTl9TRVRfREVWSUNFXzE2QklUCQlCSVQoOCkKPiArCj4gKy8qIFNraXBf Ynl0ZXMgcmVnaXN0ZXJzLiAqLwo+ICsjZGVmaW5lIFNLSVBfQllURVNfQ09ORgkJCQkweDEwMEMK PiArI2RlZmluZQkJU0tJUF9CWVRFU19NQVJLRVJfVkFMVUUJCUdFTk1BU0soMzEsIDE2KQo+ICsj ZGVmaW5lCQlTS0lQX0JZVEVTX05VTV9PRl9CWVRFUwkJR0VOTUFTSyg3LCAwKQo+ICsKPiArI2Rl ZmluZSBTS0lQX0JZVEVTX09GRlNFVAkJCTB4MTAxMAo+ICsjZGVmaW5lCQkgU0tJUF9CWVRFU19P RkZTRVRfVkFMVUUJR0VOTUFTSygyMywgMCkKPiArCj4gKy8qIFRpbWluZ3MgY29uZmlndXJhdGlv bi4gKi8KPiArI2RlZmluZSBBU1lOQ19UT0dHTEVfVElNSU5HUwkJCTB4MTAxYwo+ICsjZGVmaW5l CQlBU1lOQ19UT0dHTEVfVElNSU5HU19UUkgJR0VOTUFTSygyOCwgMjQpCj4gKyNkZWZpbmUJCUFT WU5DX1RPR0dMRV9USU1JTkdTX1RSUAlHRU5NQVNLKDIwLCAxNikKPiArI2RlZmluZQkJQVNZTkNf VE9HR0xFX1RJTUlOR1NfVFdICUdFTk1BU0soMTIsIDgpCj4gKyNkZWZpbmUJCUFTWU5DX1RPR0dM RV9USU1JTkdTX1RXUAlHRU5NQVNLKDQsIDApCj4gKwo+ICsjZGVmaW5lCVRJTUlOR1MwCQkJCTB4 MTAyNAo+ICsjZGVmaW5lCQlUSU1JTkdTMF9UQURMCQkJR0VOTUFTSygzMSwgMjQpCj4gKyNkZWZp bmUJCVRJTUlOR1MwX1RDQ1MJCQlHRU5NQVNLKDIzLCAxNikKPiArI2RlZmluZQkJVElNSU5HUzBf VFdIUgkJCUdFTk1BU0soMTUsIDgpCj4gKyNkZWZpbmUJCVRJTUlOR1MwX1RSSFcJCQlHRU5NQVNL KDcsIDApCj4gKwo+ICsjZGVmaW5lCVRJTUlOR1MxCQkJCTB4MTAyOAo+ICsjZGVmaW5lCQlUSU1J TkdTMV9UUkhaCQkJR0VOTUFTSygzMSwgMjQpCj4gKyNkZWZpbmUJCVRJTUlOR1MxX1RXQgkJCUdF Tk1BU0soMjMsIDE2KQo+ICsjZGVmaW5lCQlUSU1JTkdTMV9UVkRMWQkJCUdFTk1BU0soNywgMCkK PiArCj4gKyNkZWZpbmUJVElNSU5HUzIJCQkJMHgxMDJjCj4gKyNkZWZpbmUJCVRJTUlOR1MyX1RG RUFUCQkJR0VOTUFTSygyNSwgMTYpCj4gKyNkZWZpbmUJCVRJTUlOR1MyX0NTX0hPTERfVElNRQkJ R0VOTUFTSygxMywgOCkKPiArI2RlZmluZQkJVElNSU5HUzJfQ1NfU0VUVVBfVElNRQkJR0VOTUFT Syg1LCAwKQo+ICsKPiArLyogQ29uZmlndXJhdGlvbiBvZiB0aGUgcmVzeW5jaHJvbml6YXRpb24g b2Ygc2xhdmUgRExMIG9mIFBIWS4gKi8KPiArI2RlZmluZSBETExfUEhZX0NUUkwJCQkJMHgxMDM0 Cj4gKyNkZWZpbmUJCURMTF9QSFlfQ1RSTF9ETExfUlNUX04JCUJJVCgyNCkKPiArI2RlZmluZQkJ RExMX1BIWV9DVFJMX0VYVEVOREVEX1dSX01PREUJQklUKDE3KQo+ICsjZGVmaW5lCQlETExfUEhZ X0NUUkxfRVhURU5ERURfUkRfTU9ERQlCSVQoMTYpCj4gKyNkZWZpbmUJCURMTF9QSFlfQ1RSTF9S U19ISUdIX1dBSVRfQ05UCUdFTk1BU0soMTEsIDgpCj4gKyNkZWZpbmUJCURMTF9QSFlfQ1RSTF9S U19JRExFX0NOVAlHRU5NQVNLKDcsIDApCj4gKwo+ICsvKiBSZWdpc3RlciBjb250cm9sbGluZyBE USByZWxhdGVkIHRpbWluZy4gKi8KPiArI2RlZmluZSBQSFlfRFFfVElNSU5HCQkJCTB4MjAwMAo+ ICsvKiBSZWdpc3RlciBjb250cm9sbGluZyBEU1EgcmVsYXRlZCB0aW1pbmcuICAqLwo+ICsjZGVm aW5lIFBIWV9EUVNfVElNSU5HCQkJCTB4MjAwNAo+ICsjZGVmaW5lCQlQSFlfRFFTX1RJTUlOR19E UVNfU0VMX09FX0VORAlHRU5NQVNLKDMsIDApCj4gKyNkZWZpbmUJCVBIWV9EUVNfVElNSU5HX1BI T05ZX0RRU19TRUwJQklUKDE2KQo+ICsjZGVmaW5lCQlQSFlfRFFTX1RJTUlOR19VU0VfUEhPTllf RFFTCUJJVCgyMCkKPiArCj4gKy8qIFJlZ2lzdGVyIGNvbnRyb2xsaW5nIHRoZSBnYXRlIGFuZCBs b29wYmFjayBjb250cm9sIHJlbGF0ZWQgdGltaW5nLiAqLwo+ICsjZGVmaW5lIFBIWV9HQVRFX0xQ QktfQ1RSTAkJCTB4MjAwOAo+ICsjZGVmaW5lCQlQSFlfR0FURV9MUEJLX0NUUkxfUkRTCQlHRU5N QVNLKDI0LCAxOSkKPiArCj4gKy8qIFJlZ2lzdGVyIGhvbGRzIHRoZSBjb250cm9sIGZvciB0aGUg bWFzdGVyIERMTCBsb2dpYy4gKi8KPiArI2RlZmluZSBQSFlfRExMX01BU1RFUl9DVFJMCQkJMHgy MDBDCj4gKyNkZWZpbmUJCVBIWV9ETExfTUFTVEVSX0NUUkxfQllQQVNTX01PREUJQklUKDIzKQo+ ICsKPiArLyogUmVnaXN0ZXIgaG9sZHMgdGhlIGNvbnRyb2wgZm9yIHRoZSBzbGF2ZSBETEwgbG9n aWMuICovCj4gKyNkZWZpbmUgUEhZX0RMTF9TTEFWRV9DVFJMCQkJMHgyMDEwCj4gKwo+ICsvKiBU aGlzIHJlZ2lzdGVyIGhhbmRsZXMgdGhlIGdsb2JhbCBjb250cm9sIHNldHRpbmdzIGZvciB0aGUg UEhZLiAqLwo+ICsjZGVmaW5lIFBIWV9DVFJMCQkJCTB4MjA4MAo+ICsjZGVmaW5lCQlQSFlfQ1RS TF9TRFJfRFFTCQlCSVQoMTQpCj4gKyNkZWZpbmUJCVBIWV9DVFJMX1BIT05ZX0RRUwkJR0VOTUFT Syg5LCA0KQo+ICsKPiArLyoKPiArICogVGhpcyByZWdpc3RlciBoYW5kbGVzIHRoZSBnbG9iYWwg Y29udHJvbCBzZXR0aW5ncwo+ICsgKiBmb3IgdGhlIHRlcm1pbmF0aW9uIHNlbGVjdHMgZm9yIHJl YWRzLgo+ICsgKi8KPiArI2RlZmluZSBQSFlfVFNFTAkJCQkweDIwODQKPiArCj4gKy8qIEdlbmVy aWMgY29tbWFuZCBsYXlvdXQuICovCj4gKyNkZWZpbmUgR0NNRF9MQVlfQ1MJCQlHRU5NQVNLX1VM TCgxMSwgOCkKPiArLyoKPiArICogVGhpcyBiaXQgaW5mb3JtcyB0aGUgbWluaWNvdHJvbGxlciBp ZiBpdCBoYXMgdG8gd2FpdCBmb3IgdFdCCj4gKyAqIGFmdGVyIHNlbmRpbmcgdGhlIGxhc3QgQ01E L0FERFIvREFUQSBpbiB0aGUgc2VxdWVuY2UuCj4gKyAqLwo+ICsjZGVmaW5lIEdDTURfTEFZX1RX QgkJCUJJVF9VTEwoNikKPiArLyogVHlwZSBvZiBnZW5lcmljIGluc3RydWN0aW9uLiAqLwo+ICsj ZGVmaW5lIEdDTURfTEFZX0lOU1RSCQkJR0VOTUFTS19VTEwoNSwgMCkKPiArCj4gKy8qIEdlbmVy aWMgQ01EIHNlcXVlbmNlIHR5cGUuICovCj4gKyNkZWZpbmUJCUdDTURfTEFZX0lOU1RSX0NNRAkw Cj4gKy8qIEdlbmVyaWMgQUREUiBzZXF1ZW5jZSB0eXBlLiAqLwo+ICsjZGVmaW5lCQlHQ01EX0xB WV9JTlNUUl9BRERSCTEKPiArLyogR2VuZXJpYyBkYXRhIHRyYW5zZmVyIHNlcXVlbmNlIHR5cGUu ICovCj4gKyNkZWZpbmUJCUdDTURfTEFZX0lOU1RSX0RBVEEJMgo+ICsKPiArLyogSW5wdXQgcGFy dCBvZiBnZW5lcmljIGNvbW1hbmQgdHlwZSBvZiBpbnB1dCBpcyBjb21tYW5kLiAqLwo+ICsjZGVm aW5lIEdDTURfTEFZX0lOUFVUX0NNRAkJR0VOTUFTS19VTEwoMjMsIDE2KQo+ICsKPiArLyogR2Vu ZXJpYyBjb21tYW5kIGFkZHJlc3Mgc2VxdWVuY2UgLSBhZGRyZXNzIGZpZWxkcy4gKi8KPiArI2Rl ZmluZSBHQ01EX0xBWV9JTlBVVF9BRERSCQlHRU5NQVNLX1VMTCg2MywgMTYpCj4gKy8qIEdlbmVy aWMgY29tbWFuZCBhZGRyZXNzIHNlcXVlbmNlIC0gYWRkcmVzcyBzaXplLiAqLwo+ICsjZGVmaW5l IEdDTURfTEFZX0lOUFVUX0FERFJfU0laRQlHRU5NQVNLX1VMTCgxMywgMTEpCj4gKwo+ICsvKiBU cmFuc2ZlciBkaXJlY3Rpb24gZmllbGQgb2YgZ2VuZXJpYyBjb21tYW5kIGRhdGEgc2VxdWVuY2Uu ICovCj4gKyNkZWZpbmUgR0NNRF9ESVIJCQlCSVRfVUxMKDExKQo+ICsvKiBSZWFkIHRyYW5zZmVy IGRpcmVjdGlvbiBvZiBnZW5lcmljIGNvbW1hbmQgZGF0YSBzZXF1ZW5jZS4gKi8KPiArI2RlZmlu ZQkJR0NNRF9ESVJfUkVBRAkJMAo+ICsvKiBXcml0ZSB0cmFuc2ZlciBkaXJlY3Rpb24gb2YgZ2Vu ZXJpYyBjb21tYW5kIGRhdGEgc2VxdWVuY2UuICovCj4gKyNkZWZpbmUJCUdDTURfRElSX1dSSVRF CQkxCj4gKwo+ICsvKiBFQ0MgZW5hYmxlZCBmbGFnIG9mIGdlbmVyaWMgY29tbWFuZCBkYXRhIHNl cXVlbmNlIC0gRUNDIGVuYWJsZWQuICovCj4gKyNkZWZpbmUgR0NNRF9FQ0NfRU4JCQlCSVRfVUxM KDEyKQo+ICsvKiBHZW5lcmljIGNvbW1hbmQgZGF0YSBzZXF1ZW5jZSAtIHNlY3RvciBzaXplLiAq Lwo+ICsjZGVmaW5lIEdDTURfU0VDVF9TSVpFCQkJR0VOTUFTS19VTEwoMzEsIDE2KQo+ICsvKiBH ZW5lcmljIGNvbW1hbmQgZGF0YSBzZXF1ZW5jZSAtIHNlY3RvciBjb3VudC4gKi8KPiArI2RlZmlu ZSBHQ01EX1NFQ1RfQ05UCQkJR0VOTUFTS19VTEwoMzksIDMyKQo+ICsvKiBHZW5lcmljIGNvbW1h bmQgZGF0YSBzZXF1ZW5jZSAtIGxhc3Qgc2VjdG9yIHNpemUuICovCj4gKyNkZWZpbmUgR0NNRF9M QVNUX1NJWkUJCQlHRU5NQVNLX1VMTCg1NSwgNDApCj4gKwo+ICsvKiBDRE1BIGRlc2NyaXB0b3Ig ZmllbGRzLiAqLwo+ICsvKiBFcmFzZSBjb21tYW5kIHR5cGUgb2YgQ0RNQSBkZXNjcmlwdG9yLiAq Lwo+ICsjZGVmaW5lIENETUFfQ1RfRVJBU0UJCTB4MTAwMAo+ICsvKiBQcm9ncmFtIHBhZ2UgY29t bWFuZCB0eXBlIG9mIENETUEgZGVzY3JpcHRvci4gKi8KPiArI2RlZmluZSBDRE1BX0NUX1dSCQkw eDIxMDAKPiArLyogUmVhZCBwYWdlIGNvbW1hbmQgdHlwZSBvZiBDRE1BIGRlc2NyaXB0b3IuICov Cj4gKyNkZWZpbmUgQ0RNQV9DVF9SRAkJMHgyMjAwCj4gKwo+ICsvKiBGbGFzaCBwb2ludGVyIG1l bW9yeSBzaGlmdC4gKi8KPiArI2RlZmluZSBDRE1BX0NGUFRSX01FTV9TSElGVAkyNAo+ICsvKiBG bGFzaCBwb2ludGVyIG1lbW9yeSBtYXNrLiAqLwo+ICsjZGVmaW5lIENETUFfQ0ZQVFJfTUVNCQlH RU5NQVNLKDI2LCAyNCkKPiArCj4gKy8qCj4gKyAqIENvbW1hbmQgRE1BIGRlc2NyaXB0b3IgZmxh Z3MuIElmIHNldCBjYXVzZXMgaXNzdWUgaW50ZXJydXB0IGFmdGVyCj4gKyAqIHRoZSBjb21wbGV0 aW9uIG9mIGRlc2NyaXB0b3IgcHJvY2Vzc2luZy4KPiArICovCj4gKyNkZWZpbmUgQ0RNQV9DRl9J TlQJCUJJVCg4KQo+ICsvKgo+ICsgKiBDb21tYW5kIERNQSBkZXNjcmlwdG9yIGZsYWdzIC0gdGhl IG5leHQgZGVzY3JpcHRvcgo+ICsgKiBhZGRyZXNzIGZpZWxkIGlzIHZhbGlkIGFuZCBkZXNjcmlw dG9yIHByb2Nlc3Npbmcgc2hvdWxkIGNvbnRpbnVlLgo+ICsgKi8KPiArI2RlZmluZSBDRE1BX0NG X0NPTlQJCUJJVCg5KQo+ICsvKiBETUEgbWFzdGVyIGZsYWcgb2YgY29tbWFuZCBETUEgZGVzY3Jp cHRvci4gKi8KPiArI2RlZmluZSBDRE1BX0NGX0RNQV9NQVNURVIJQklUKDEwKQo+ICsKPiArLyog T3BlcmF0aW9uIGNvbXBsZXRlIHN0YXR1cyBvZiBjb21tYW5kIGRlc2NyaXB0b3IuICovCj4gKyNk ZWZpbmUgQ0RNQV9DU19DT01QCQlCSVQoMTUpCj4gKy8qIE9wZXJhdGlvbiBjb21wbGV0ZSBzdGF0 dXMgb2YgY29tbWFuZCBkZXNjcmlwdG9yLiAqLwo+ICsvKiBDb21tYW5kIGRlc2NyaXB0b3Igc3Rh dHVzIC0gb3BlcmF0aW9uIGZhaWwuICovCj4gKyNkZWZpbmUgQ0RNQV9DU19GQUlMCQlCSVQoMTQp Cj4gKy8qIENvbW1hbmQgZGVzY3JpcHRvciBzdGF0dXMgLSBwYWdlIGVyYXNlZC4gKi8KPiArI2Rl ZmluZSBDRE1BX0NTX0VSUAkJQklUKDExKQo+ICsvKiBDb21tYW5kIGRlc2NyaXB0b3Igc3RhdHVz IC0gdGltZW91dCBvY2N1cnJlZC4gKi8KPiArI2RlZmluZSBDRE1BX0NTX1RPVVQJCUJJVCgxMCkK PiArLyoKPiArICogTWF4aW11bSBhbW91bnQgb2YgY29ycmVjdGlvbiBhcHBsaWVkIHRvIG9uZSBF Q0Mgc2VjdG9yLgo+ICsgKiBJdCBpcyBwYXJ0IG9mIGNvbW1hbmQgZGVzY3JpcHRvciBzdGF0dXMu Cj4gKyAqLwo+ICsjZGVmaW5lIENETUFfQ1NfTUFYRVJSCQlHRU5NQVNLKDksIDIpCj4gKy8qIENv bW1hbmQgZGVzY3JpcHRvciBzdGF0dXMgLSB1bmNvcnJlY3RhYmxlIEVDQyBlcnJvci4gKi8KPiAr I2RlZmluZSBDRE1BX0NTX1VOQ0UJCUJJVCgxKQo+ICsvKiBDb21tYW5kIGRlc2NyaXB0b3Igc3Rh dHVzIC0gZGVzY3JpcHRvciBlcnJvci4gKi8KPiArI2RlZmluZSBDRE1BX0NTX0VSUgkJQklUKDAp Cj4gKwo+ICsvKiBTdGF0dXMgb2Ygb3BlcmF0aW9uIC0gT0suICovCj4gKyNkZWZpbmUgU1RBVF9P SwkJCTAKPiArLyogU3RhdHVzIG9mIG9wZXJhdGlvbiAtIEZBSUwuICovCj4gKyNkZWZpbmUgU1RB VF9GQUlMCQkyCj4gKy8qIFN0YXR1cyBvZiBvcGVyYXRpb24gLSB1bmNvcnJlY3RhYmxlIEVDQyBl cnJvci4gKi8KPiArI2RlZmluZSBTVEFUX0VDQ19VTkNPUlIJCTMKPiArLyogU3RhdHVzIG9mIG9w ZXJhdGlvbiAtIHBhZ2UgZXJhc2VkLiAqLwo+ICsjZGVmaW5lIFNUQVRfRVJBU0VECQk1Cj4gKy8q IFN0YXR1cyBvZiBvcGVyYXRpb24gLSBjb3JyZWN0YWJsZSBFQ0MgZXJyb3IuICovCj4gKyNkZWZp bmUgU1RBVF9FQ0NfQ09SUgkJNgo+ICsvKiBTdGF0dXMgb2Ygb3BlcmF0aW9uIC0gdW5zdXNwZWN0 ZWQgc3RhdGUuICovCj4gKyNkZWZpbmUgU1RBVF9VTktOT1dOCQk3Cj4gKy8qIFN0YXR1cyBvZiBv cGVyYXRpb24gLSBvcGVyYXRpb24gaXMgbm90IGNvbXBsZXRlZCB5ZXQuICovCj4gKyNkZWZpbmUg U1RBVF9CVVNZCQkweEZGCj4gKwo+ICsjZGVmaW5lIEJDSF9NQVhfTlVNX0NPUlJfQ0FQUwkJOAo+ ICsjZGVmaW5lIEJDSF9NQVhfTlVNX1NFQ1RPUl9TSVpFUwkyCj4gKwo+ICtzdHJ1Y3QgY2FkZW5j ZV9uYW5kX3RpbWluZ3Mgewo+ICsJdTMyIGFzeW5jX3RvZ2dsZV90aW1pbmdzOwo+ICsJdTMyIHRp bWluZ3MwOwo+ICsJdTMyIHRpbWluZ3MxOwo+ICsJdTMyIHRpbWluZ3MyOwo+ICsJdTMyIGRsbF9w aHlfY3RybDsKPiArCXUzMiBwaHlfY3RybDsKPiArCXUzMiBwaHlfZHFzX3RpbWluZzsKPiArCXUz MiBwaHlfZ2F0ZV9scGJrX2N0cmw7Cj4gK307Cj4gKwo+ICsvKiBDb21tYW5kIERNQSBkZXNjcmlw dG9yLiAqLwo+ICtzdHJ1Y3QgY2FkZW5jZV9uYW5kX2NkbWFfZGVzYyB7Cj4gKwkvKiBOZXh0IGRl c2NyaXB0b3IgYWRkcmVzcy4gKi8KPiArCXU2NCBuZXh0X3BvaW50ZXI7Cj4gKwo+ICsJLyogRmxh c2ggYWRkcmVzcyBpcyBhIDMyLWJpdCBhZGRyZXNzIGNvbXByaXNpbmcgb2YgQkFOSyBhbmQgUk9X IEFERFIuICovCj4gKwl1MzIgZmxhc2hfcG9pbnRlcjsKPiArCXUzMiByc3ZkMDsKPiArCj4gKwkv KiBPcGVyYXRpb24gdGhlIGNvbnRyb2xsZXIgbmVlZHMgdG8gcGVyZm9ybS4gKi8KPiArCXUxNiBj b21tYW5kX3R5cGU7Cj4gKwl1MTYgcnN2ZDE7Cj4gKwkvKiBGbGFncyBmb3Igb3BlcmF0aW9uIG9m IHRoaXMgY29tbWFuZC4gKi8KPiArCXUxNiBjb21tYW5kX2ZsYWdzOwo+ICsJdTE2IHJzdmQyOwo+ ICsKPiArCS8qIFN5c3RlbS9ob3N0IG1lbW9yeSBhZGRyZXNzIHJlcXVpcmVkIGZvciBkYXRhIERN QSBjb21tYW5kcy4gKi8KPiArCXU2NCBtZW1vcnlfcG9pbnRlcjsKPiArCj4gKwkvKiBTdGF0dXMg b2Ygb3BlcmF0aW9uLiAqLwo+ICsJdTMyIHN0YXR1czsKPiArCXUzMiByc3ZkMzsKPiArCj4gKwkv KiBBZGRyZXNzIHBvaW50ZXIgdG8gc3luYyBidWZmZXIgbG9jYXRpb24uICovCj4gKwl1NjQgc3lu Y19mbGFnX3BvaW50ZXI7Cj4gKwo+ICsJLyogQ29udHJvbHMgdGhlIGJ1ZmZlciBzeW5jIG1lY2hh bmlzbS4gKi8KPiArCXUzMiBzeW5jX2FyZ3VtZW50czsKPiArCXUzMiByc3ZkNDsKPiArCj4gKwkv KiBDb250cm9sIGRhdGEgcG9pbnRlci4gKi8KPiArCXU2NCBjdHJsX2RhdGFfcHRyOwo+ICt9Owo+ ICsKPiArLyogSW50ZXJydXB0IHN0YXR1cy4gKi8KPiArc3RydWN0IGNhZGVuY2VfbmFuZF9pcnFf c3RhdHVzIHsKPiArCS8qIFRocmVhZCBvcGVyYXRpb24gY29tcGxldGUgc3RhdHVzLiAqLwo+ICsJ dTMyIHRyZF9zdGF0dXM7Cj4gKwkvKiBUaHJlYWQgb3BlcmF0aW9uIGVycm9yLiAqLwo+ICsJdTMy IHRyZF9lcnJvcjsKPiArCS8qIENvbnRyb2xsZXIgc3RhdHVzLiAqLwo+ICsJdTMyIHN0YXR1czsK PiArfTsKPiArCj4gKy8qIENhZGVuY2UgTkFORCBmbGFzaCBjb250cm9sbGVyIGNhcGFiaWxpdGll cyBnZXQgZnJvbSBkcml2ZXIgZGF0YS4gKi8KPiArc3RydWN0IGNhZGVuY2VfbmFuZF9kdF9kZXZk YXRhIHsKPiArCS8qIFNrZXcgdmFsdWUgb2YgdGhlIG91dHB1dCBzaWduYWxzIG9mIHRoZSBOQU5E IEZsYXNoIGludGVyZmFjZS4gKi8KPiArCXUzMiBpZl9za2V3Owo+ICsJLyogSXQgaW5mb3JtcyBp ZiBzbGF2ZSBETUEgaW50ZXJmYWNlIGlzIGNvbm5lY3RlZCB0byBETUEgZW5naW5lLiAqLwo+ICsJ dW5zaWduZWQgaW50IGhhc19kbWE6MTsKPiArfTsKPiArCj4gKy8qIENhZGVuY2UgTkFORCBmbGFz aCBjb250cm9sbGVyIGNhcGFiaWxpdGllcyByZWFkIGZyb20gcmVnaXN0ZXJzLiAqLwo+ICtzdHJ1 Y3QgY2Ruc19uYW5kX2NhcHMgewo+ICsJLyogTWF4aW11bSBudW1iZXIgb2YgYmFua3Mgc3VwcG9y dGVkIGJ5IGhhcmR3YXJlLiAqLwo+ICsJdTggbWF4X2JhbmtzOwo+ICsJLyogU2xhdmUgYW5kIE1h c3RlciBETUEgZGF0YSB3aWR0aCBpbiBieXRlcyAoNCBvciA4KS4gKi8KPiArCXU4IGRhdGFfZG1h X3dpZHRoOwo+ICsJLyogQ29udHJvbCBEYXRhIGZlYXR1cmUgc3VwcG9ydGVkLiAqLwo+ICsJdTgg ZGF0YV9jb250cm9sX3N1cHA7Cj4gKwkvKiBJcyBQSFkgdHlwZSBETEwuICovCj4gKwl1OCBpc19w aHlfdHlwZV9kbGw7Cj4gK307Cj4gKwo+ICtzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgewo+ICsJc3Ry dWN0IGRldmljZSAqZGV2Owo+ICsJc3RydWN0IG5hbmRfY29udHJvbGxlciBjb250cm9sbGVyOwo+ ICsJc3RydWN0IGNhZGVuY2VfbmFuZF9jZG1hX2Rlc2MgKmNkbWFfZGVzYzsKPiArCS8qIElQIGNh cGFiaWxpdHkuICovCj4gKwljb25zdCBzdHJ1Y3QgY2FkZW5jZV9uYW5kX2R0X2RldmRhdGEgKmNh cHMxOwo+ICsJc3RydWN0IGNkbnNfbmFuZF9jYXBzIGNhcHMyOwo+ICsJZG1hX2FkZHJfdCBkbWFf Y2RtYV9kZXNjOwo+ICsJdTggKmJ1ZjsKPiArCXUzMiBidWZfc2l6ZTsKPiArCXU4IGN1cnJfY29y cl9zdHJfaWR4Owo+ICsKPiArCS8qIFJlZ2lzdGVyIGludGVyZmFjZS4gKi8KPiArCXZvaWQgX19p b21lbSAqcmVnOwo+ICsKPiArCXN0cnVjdCB7Cj4gKwkJdm9pZCBfX2lvbWVtICp2aXJ0Owo+ICsJ CWRtYV9hZGRyX3QgZG1hOwo+ICsJfSBpbzsKPiArCj4gKwlpbnQgaXJxOwo+ICsJLyogSW50ZXJy dXB0cyB0aGF0IGhhdmUgaGFwcGVuZWQuICovCj4gKwlzdHJ1Y3QgY2FkZW5jZV9uYW5kX2lycV9z dGF0dXMgaXJxX3N0YXR1czsKPiArCS8qIEludGVycnVwdHMgd2UgYXJlIHdhaXRpbmcgZm9yLiAq Lwo+ICsJc3RydWN0IGNhZGVuY2VfbmFuZF9pcnFfc3RhdHVzIGlycV9tYXNrOwo+ICsJc3RydWN0 IGNvbXBsZXRpb24gY29tcGxldGU7Cj4gKwkvKiBQcm90ZWN0IGlycV9tYXNrIGFuZCBpcnFfc3Rh dHVzLiAqLwo+ICsJc3BpbmxvY2tfdCBpcnFfbG9jazsKPiArCj4gKwlpbnQgZWNjX3N0cmVuZ3Ro c1tCQ0hfTUFYX05VTV9DT1JSX0NBUFNdOwo+ICsJc3RydWN0IG5hbmRfZWNjX3N0ZXBfaW5mbyBl Y2Nfc3RlcGluZm9zW0JDSF9NQVhfTlVNX1NFQ1RPUl9TSVpFU107Cj4gKwlzdHJ1Y3QgbmFuZF9l Y2NfY2FwcyBlY2NfY2FwczsKPiArCj4gKwlpbnQgY3Vycl90cmFuc190eXBlOwo+ICsKPiArCXN0 cnVjdCBkbWFfY2hhbiAqZG1hYzsKPiArCj4gKwl1MzIgbmZfY2xrX3JhdGU7Cj4gKwkvKgo+ICsJ ICogRXN0aW1hdGVkIEJvYXJkIGRlbGF5LiBUaGUgdmFsdWUgaW5jbHVkZXMgdGhlIHRvdGFsCj4g KwkgKiByb3VuZCB0cmlwIGRlbGF5IGZvciB0aGUgc2lnbmFscyBhbmQgaXMgdXNlZCBmb3IgZGVj aWRpbmcgb24gdmFsdWVzCj4gKwkgKiBhc3NvY2lhdGVkIHdpdGggZGF0YSByZWFkIGNhcHR1cmUu Cj4gKwkgKi8KPiArCXUzMiBib2FyZF9kZWxheTsKPiArCj4gKwlzdHJ1Y3QgbmFuZF9jaGlwICpz ZWxlY3RlZF9jaGlwOwo+ICsKPiArCXVuc2lnbmVkIGxvbmcgYXNzaWduZWRfY3M7Cj4gKwlzdHJ1 Y3QgbGlzdF9oZWFkIGNoaXBzOwo+ICt9Owo+ICsKPiArc3RydWN0IGNkbnNfbmFuZF9jaGlwIHsK PiArCXN0cnVjdCBjYWRlbmNlX25hbmRfdGltaW5ncyB0aW1pbmdzOwo+ICsJc3RydWN0IG5hbmRf Y2hpcCBjaGlwOwo+ICsJdTggbnNlbHM7Cj4gKwlzdHJ1Y3QgbGlzdF9oZWFkIG5vZGU7Cj4gKwo+ ICsJLyoKPiArCSAqIHBhcnQgb2Ygb29iIGFyZWEgb2YgTkFORCBmbGFzaCBtZW1vcnkgcGFnZS4K PiArCSAqIFRoaXMgcGFydCBpcyBhdmFpbGFibGUgZm9yIHVzZXIgdG8gcmVhZCBvciB3cml0ZS4K PiArCSAqLwo+ICsJdTMyIGF2YWlsX29vYl9zaXplOwo+ICsKPiArCS8qIFNlY3RvciBzaXplLiBU aGVyZSBhcmUgZmV3IHNlY3RvcnMgcGVyIG10ZC0+d3JpdGVzaXplICovCj4gKwl1MzIgc2VjdG9y X3NpemU7Cj4gKwl1MzIgc2VjdG9yX2NvdW50Owo+ICsKPiArCS8qIE9mZnNldCBvZiBCQk0uICov Cj4gKwl1OCBiYm1fb2ZmczsKPiArCS8qIE51bWJlciBvZiBieXRlcyByZXNlcnZlZCBmb3IgQkJN LiAqLwo+ICsJdTggYmJtX2xlbjsKPiArCS8qIEVDQyBzdHJlbmd0aCBpbmRleC4gKi8KPiArCXU4 IGNvcnJfc3RyX2lkeDsKPiArCj4gKwl1OCBjc1tdOwo+ICt9Owo+ICsKPiArc3RydWN0IGVjY19p bmZvIHsKPiArCWludCAoKmNhbGNfZWNjX2J5dGVzKShpbnQgc3RlcF9zaXplLCBpbnQgc3RyZW5n dGgpOwo+ICsJaW50IG1heF9zdGVwX3NpemU7Cj4gK307Cj4gKwo+ICtzdGF0aWMgaW5saW5lIHN0 cnVjdAo+ICtjZG5zX25hbmRfY2hpcCAqdG9fY2Ruc19uYW5kX2NoaXAoc3RydWN0IG5hbmRfY2hp cCAqY2hpcCkKPiArewo+ICsJcmV0dXJuIGNvbnRhaW5lcl9vZihjaGlwLCBzdHJ1Y3QgY2Ruc19u YW5kX2NoaXAsIGNoaXApOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIHN0cnVjdAo+ICtjZG5z X25hbmRfY3RybCAqdG9fY2Ruc19uYW5kX2N0cmwoc3RydWN0IG5hbmRfY29udHJvbGxlciAqY29u dHJvbGxlcikKPiArewo+ICsJcmV0dXJuIGNvbnRhaW5lcl9vZihjb250cm9sbGVyLCBzdHJ1Y3Qg Y2Ruc19uYW5kX2N0cmwsIGNvbnRyb2xsZXIpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgYm9vbAo+ICtj YWRlbmNlX25hbmRfZG1hX2J1Zl9vayhzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3RybCwg Y29uc3Qgdm9pZCAqYnVmLAo+ICsJCQl1MzIgYnVmX2xlbikKPiArewo+ICsJdTggZGF0YV9kbWFf d2lkdGggPSBjZG5zX2N0cmwtPmNhcHMyLmRhdGFfZG1hX3dpZHRoOwo+ICsKPiArCXJldHVybiBi dWYgJiYgdmlydF9hZGRyX3ZhbGlkKGJ1ZikgJiYKPiArCQlsaWtlbHkoSVNfQUxJR05FRCgodWlu dHB0cl90KWJ1ZiwgZGF0YV9kbWFfd2lkdGgpKSAmJgo+ICsJCWxpa2VseShJU19BTElHTkVEKGJ1 Zl9sZW4sIGRhdGFfZG1hX3dpZHRoKSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgY2FkZW5jZV9u YW5kX3dhaXRfZm9yX3ZhbHVlKHN0cnVjdCBjZG5zX25hbmRfY3RybCAqY2Ruc19jdHJsLAo+ICsJ CQkJICAgICAgIHUzMiByZWdfb2Zmc2V0LCB1MzIgdGltZW91dF91cywKPiArCQkJCSAgICAgICB1 MzIgbWFzaywgYm9vbCBpc19jbGVhcikKPiArewo+ICsJdTMyIHZhbDsKPiArCWludCByZXQ7Cj4g Kwo+ICsJcmV0ID0gcmVhZGxfcmVsYXhlZF9wb2xsX3RpbWVvdXQoY2Ruc19jdHJsLT5yZWcgKyBy ZWdfb2Zmc2V0LAo+ICsJCQkJCSB2YWwsICEodmFsICYgbWFzaykgPT0gaXNfY2xlYXIsCj4gKwkJ CQkJIDEwLCB0aW1lb3V0X3VzKTsKPiArCj4gKwlpZiAocmV0IDwgMCkgewo+ICsJCWRldl9lcnIo Y2Ruc19jdHJsLT5kZXYsCj4gKwkJCSJUaW1lb3V0IHdoaWxlIHdhaXRpbmcgZm9yIHJlZyAleCB3 aXRoIG1hc2sgJXggaXMgY2xlYXIgJWRcbiIsCj4gKwkJCXJlZ19vZmZzZXQsIG1hc2ssIGlzX2Ns ZWFyKTsKPiArCX0KPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGNh ZGVuY2VfbmFuZF9zZXRfZWNjX2VuYWJsZShzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3Ry bCwKPiArCQkJCSAgICAgICBib29sIGVuYWJsZSkKPiArewo+ICsJdTMyIHJlZzsKPiArCj4gKwlp ZiAoY2FkZW5jZV9uYW5kX3dhaXRfZm9yX3ZhbHVlKGNkbnNfY3RybCwgQ1RSTF9TVEFUVVMsCj4g KwkJCQkJMTAwMDAwMCwKPiArCQkJCQlDVFJMX1NUQVRVU19DVFJMX0JVU1ksIHRydWUpKQo+ICsJ CXJldHVybiAtRVRJTUVET1VUOwo+ICsKPiArCXJlZyA9IHJlYWRsX3JlbGF4ZWQoY2Ruc19jdHJs LT5yZWcgKyBFQ0NfQ09ORklHXzApOwo+ICsKPiArCWlmIChlbmFibGUpCj4gKwkJcmVnIHw9IEVD Q19DT05GSUdfMF9FQ0NfRU47Cj4gKwllbHNlCj4gKwkJcmVnICY9IH5FQ0NfQ09ORklHXzBfRUND X0VOOwo+ICsKPiArCXdyaXRlbF9yZWxheGVkKHJlZywgY2Ruc19jdHJsLT5yZWcgKyBFQ0NfQ09O RklHXzApOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBjYWRlbmNl X25hbmRfc2V0X2VjY19zdHJlbmd0aChzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3RybCwK PiArCQkJCQkgIHU4IGNvcnJfc3RyX2lkeCkKPiArewo+ICsJdTMyIHJlZzsKPiArCj4gKwlpZiAo Y2Ruc19jdHJsLT5jdXJyX2NvcnJfc3RyX2lkeCA9PSBjb3JyX3N0cl9pZHgpCj4gKwkJcmV0dXJu Owo+ICsKPiArCXJlZyA9IHJlYWRsX3JlbGF4ZWQoY2Ruc19jdHJsLT5yZWcgKyBFQ0NfQ09ORklH XzApOwo+ICsJcmVnICY9IH5FQ0NfQ09ORklHXzBfQ09SUl9TVFI7Cj4gKwlyZWcgfD0gRklFTERf UFJFUChFQ0NfQ09ORklHXzBfQ09SUl9TVFIsIGNvcnJfc3RyX2lkeCk7Cj4gKwl3cml0ZWxfcmVs YXhlZChyZWcsIGNkbnNfY3RybC0+cmVnICsgRUNDX0NPTkZJR18wKTsKPiArCj4gKwljZG5zX2N0 cmwtPmN1cnJfY29ycl9zdHJfaWR4ID0gY29ycl9zdHJfaWR4Owo+ICt9Cj4gKwo+ICtzdGF0aWMg aW50IGNhZGVuY2VfbmFuZF9nZXRfZWNjX3N0cmVuZ3RoX2lkeChzdHJ1Y3QgY2Ruc19uYW5kX2N0 cmwgKmNkbnNfY3RybCwKPiArCQkJCQkgICAgIHU4IHN0cmVuZ3RoKQo+ICt7Cj4gKwlpbnQgaSwg Y29ycl9zdHJfaWR4ID0gLTE7Cj4gKwo+ICsJZm9yIChpID0gMDsgaSA8IEJDSF9NQVhfTlVNX0NP UlJfQ0FQUzsgaSsrKSB7Cj4gKwkJaWYgKGNkbnNfY3RybC0+ZWNjX3N0cmVuZ3Roc1tpXSA9PSBz dHJlbmd0aCkgewo+ICsJCQljb3JyX3N0cl9pZHggPSBpOwo+ICsJCQlicmVhazsKPiArCQl9Cj4g Kwl9Cj4gKwo+ICsJcmV0dXJuIGNvcnJfc3RyX2lkeDsKPiArfQo+ICsKPiArc3RhdGljIGludCBj YWRlbmNlX25hbmRfc2V0X3NraXBfbWFya2VyX3ZhbChzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgKmNk bnNfY3RybCwKPiArCQkJCQkgICAgdTE2IG1hcmtlcl92YWx1ZSkKPiArewo+ICsJdTMyIHJlZzsK PiArCj4gKwlpZiAoY2FkZW5jZV9uYW5kX3dhaXRfZm9yX3ZhbHVlKGNkbnNfY3RybCwgQ1RSTF9T VEFUVVMsCj4gKwkJCQkJMTAwMDAwMCwKPiArCQkJCQlDVFJMX1NUQVRVU19DVFJMX0JVU1ksIHRy dWUpKQo+ICsJCXJldHVybiAtRVRJTUVET1VUOwo+ICsKPiArCXJlZyA9IHJlYWRsX3JlbGF4ZWQo Y2Ruc19jdHJsLT5yZWcgKyBTS0lQX0JZVEVTX0NPTkYpOwo+ICsJcmVnICY9IH5TS0lQX0JZVEVT X01BUktFUl9WQUxVRTsKPiArCXJlZyB8PSBGSUVMRF9QUkVQKFNLSVBfQllURVNfTUFSS0VSX1ZB TFVFLAo+ICsJCQkgIG1hcmtlcl92YWx1ZSk7Cj4gKwo+ICsJd3JpdGVsX3JlbGF4ZWQocmVnLCBj ZG5zX2N0cmwtPnJlZyArIFNLSVBfQllURVNfQ09ORik7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30K PiArCj4gK3N0YXRpYyBpbnQgY2FkZW5jZV9uYW5kX3NldF9za2lwX2J5dGVzX2NvbmYoc3RydWN0 IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwsCj4gKwkJCQkJICAgIHU4IG51bV9vZl9ieXRlcywK PiArCQkJCQkgICAgdTMyIG9mZnNldF92YWx1ZSwKPiArCQkJCQkgICAgaW50IGVuYWJsZSkKPiAr ewo+ICsJdTMyIHJlZywgc2tpcF9ieXRlc19vZmZzZXQ7Cj4gKwo+ICsJaWYgKGNhZGVuY2VfbmFu ZF93YWl0X2Zvcl92YWx1ZShjZG5zX2N0cmwsIENUUkxfU1RBVFVTLAo+ICsJCQkJCTEwMDAwMDAs Cj4gKwkJCQkJQ1RSTF9TVEFUVVNfQ1RSTF9CVVNZLCB0cnVlKSkKPiArCQlyZXR1cm4gLUVUSU1F RE9VVDsKPiArCj4gKwlpZiAoIWVuYWJsZSkgewo+ICsJCW51bV9vZl9ieXRlcyA9IDA7Cj4gKwkJ b2Zmc2V0X3ZhbHVlID0gMDsKPiArCX0KPiArCj4gKwlyZWcgPSByZWFkbF9yZWxheGVkKGNkbnNf Y3RybC0+cmVnICsgU0tJUF9CWVRFU19DT05GKTsKPiArCXJlZyAmPSB+U0tJUF9CWVRFU19OVU1f T0ZfQllURVM7Cj4gKwlyZWcgfD0gRklFTERfUFJFUChTS0lQX0JZVEVTX05VTV9PRl9CWVRFUywK PiArCQkJICBudW1fb2ZfYnl0ZXMpOwo+ICsJc2tpcF9ieXRlc19vZmZzZXQgPSBGSUVMRF9QUkVQ KFNLSVBfQllURVNfT0ZGU0VUX1ZBTFVFLAo+ICsJCQkJICAgICAgIG9mZnNldF92YWx1ZSk7Cj4g Kwo+ICsJd3JpdGVsX3JlbGF4ZWQocmVnLCBjZG5zX2N0cmwtPnJlZyArIFNLSVBfQllURVNfQ09O Rik7Cj4gKwl3cml0ZWxfcmVsYXhlZChza2lwX2J5dGVzX29mZnNldCwgY2Ruc19jdHJsLT5yZWcg KyBTS0lQX0JZVEVTX09GRlNFVCk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gKy8qIEZ1 bmN0aW9ucyBlbmFibGVzL2Rpc2FibGVzIGhhcmR3YXJlIGRldGVjdGlvbiBvZiBlcmFzZWQgZGF0 YSAqLwo+ICtzdGF0aWMgdm9pZCBjYWRlbmNlX25hbmRfc2V0X2VyYXNlX2RldGVjdGlvbihzdHJ1 Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3RybCwKPiArCQkJCQkgICAgIGJvb2wgZW5hYmxlLAo+ ICsJCQkJCSAgICAgdTggYml0ZmxpcHNfdGhyZXNob2xkKQo+ICt7Cj4gKwl1MzIgcmVnOwo+ICsK PiArCXJlZyA9IHJlYWRsX3JlbGF4ZWQoY2Ruc19jdHJsLT5yZWcgKyBFQ0NfQ09ORklHXzApOwo+ ICsKPiArCWlmIChlbmFibGUpCj4gKwkJcmVnIHw9IEVDQ19DT05GSUdfMF9FUkFTRV9ERVRfRU47 Cj4gKwllbHNlCj4gKwkJcmVnICY9IH5FQ0NfQ09ORklHXzBfRVJBU0VfREVUX0VOOwo+ICsKPiAr CXdyaXRlbF9yZWxheGVkKHJlZywgY2Ruc19jdHJsLT5yZWcgKyBFQ0NfQ09ORklHXzApOwo+ICsJ d3JpdGVsX3JlbGF4ZWQoYml0ZmxpcHNfdGhyZXNob2xkLCBjZG5zX2N0cmwtPnJlZyArIEVDQ19D T05GSUdfMSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgY2FkZW5jZV9uYW5kX3NldF9hY2Nlc3Nf d2lkdGgxNihzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3RybCwKPiArCQkJCQkgICBib29s IGJpdF9idXMxNikKPiArewo+ICsJdTMyIHJlZzsKPiArCj4gKwlpZiAoY2FkZW5jZV9uYW5kX3dh aXRfZm9yX3ZhbHVlKGNkbnNfY3RybCwgQ1RSTF9TVEFUVVMsCj4gKwkJCQkJMTAwMDAwMCwKPiAr CQkJCQlDVFJMX1NUQVRVU19DVFJMX0JVU1ksIHRydWUpKQo+ICsJCXJldHVybiAtRVRJTUVET1VU Owo+ICsKPiArCXJlZyA9IHJlYWRsX3JlbGF4ZWQoY2Ruc19jdHJsLT5yZWcgKyBDT01NT05fU0VU KTsKPiArCj4gKwlpZiAoIWJpdF9idXMxNikKPiArCQlyZWcgJj0gfkNPTU1PTl9TRVRfREVWSUNF XzE2QklUOwo+ICsJZWxzZQo+ICsJCXJlZyB8PSBDT01NT05fU0VUX0RFVklDRV8xNkJJVDsKPiAr CXdyaXRlbF9yZWxheGVkKHJlZywgY2Ruc19jdHJsLT5yZWcgKyBDT01NT05fU0VUKTsKPiArCj4g KwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQKPiArY2FkZW5jZV9uYW5kX2NsZWFy X2ludGVycnVwdChzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3RybCwKPiArCQkJICAgICBz dHJ1Y3QgY2FkZW5jZV9uYW5kX2lycV9zdGF0dXMgKmlycV9zdGF0dXMpCj4gK3sKPiArCXdyaXRl bF9yZWxheGVkKGlycV9zdGF0dXMtPnN0YXR1cywgY2Ruc19jdHJsLT5yZWcgKyBJTlRSX1NUQVRV Uyk7Cj4gKwl3cml0ZWxfcmVsYXhlZChpcnFfc3RhdHVzLT50cmRfc3RhdHVzLAo+ICsJCSAgICAg ICBjZG5zX2N0cmwtPnJlZyArIFRSRF9DT01QX0lOVF9TVEFUVVMpOwo+ICsJd3JpdGVsX3JlbGF4 ZWQoaXJxX3N0YXR1cy0+dHJkX2Vycm9yLAo+ICsJCSAgICAgICBjZG5zX2N0cmwtPnJlZyArIFRS RF9FUlJfSU5UX1NUQVRVUyk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkCj4gK2NhZGVuY2VfbmFu ZF9yZWFkX2ludF9zdGF0dXMoc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwsCj4gKwkJ CSAgICAgc3RydWN0IGNhZGVuY2VfbmFuZF9pcnFfc3RhdHVzICppcnFfc3RhdHVzKQo+ICt7Cj4g KwlpcnFfc3RhdHVzLT5zdGF0dXMgPSByZWFkbF9yZWxheGVkKGNkbnNfY3RybC0+cmVnICsgSU5U Ul9TVEFUVVMpOwo+ICsJaXJxX3N0YXR1cy0+dHJkX3N0YXR1cyA9IHJlYWRsX3JlbGF4ZWQoY2Ru c19jdHJsLT5yZWcKPiArCQkJCQkgICAgICAgKyBUUkRfQ09NUF9JTlRfU1RBVFVTKTsKPiArCWly cV9zdGF0dXMtPnRyZF9lcnJvciA9IHJlYWRsX3JlbGF4ZWQoY2Ruc19jdHJsLT5yZWcKPiArCQkJ CQkgICAgICArIFRSRF9FUlJfSU5UX1NUQVRVUyk7Cj4gK30KPiArCj4gK3N0YXRpYyB1MzIgaXJx X2RldGVjdGVkKHN0cnVjdCBjZG5zX25hbmRfY3RybCAqY2Ruc19jdHJsLAo+ICsJCQlzdHJ1Y3Qg Y2FkZW5jZV9uYW5kX2lycV9zdGF0dXMgKmlycV9zdGF0dXMpCj4gK3sKPiArCWNhZGVuY2VfbmFu ZF9yZWFkX2ludF9zdGF0dXMoY2Ruc19jdHJsLCBpcnFfc3RhdHVzKTsKPiArCj4gKwlyZXR1cm4g aXJxX3N0YXR1cy0+c3RhdHVzIHx8IGlycV9zdGF0dXMtPnRyZF9zdGF0dXMgfHwKPiArCQlpcnFf c3RhdHVzLT50cmRfZXJyb3I7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIGNhZGVuY2VfbmFuZF9y ZXNldF9pcnEoc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwpCj4gK3sKPiArCXNwaW5f bG9jaygmY2Ruc19jdHJsLT5pcnFfbG9jayk7Cj4gKwltZW1zZXQoJmNkbnNfY3RybC0+aXJxX3N0 YXR1cywgMCwgc2l6ZW9mKGNkbnNfY3RybC0+aXJxX3N0YXR1cykpOwo+ICsJbWVtc2V0KCZjZG5z X2N0cmwtPmlycV9tYXNrLCAwLCBzaXplb2YoY2Ruc19jdHJsLT5pcnFfbWFzaykpOwo+ICsJc3Bp bl91bmxvY2soJmNkbnNfY3RybC0+aXJxX2xvY2spOwo+ICt9Cj4gKwo+ICsvKgo+ICsgKiBUaGlz IGlzIHRoZSBpbnRlcnJ1cHQgc2VydmljZSByb3V0aW5lLiBJdCBoYW5kbGVzIGFsbCBpbnRlcnJ1 cHRzCj4gKyAqIHNlbnQgdG8gdGhpcyBkZXZpY2UuCj4gKyAqLwo+ICtzdGF0aWMgaXJxcmV0dXJu X3QgY2FkZW5jZV9uYW5kX2lzcihpbnQgaXJxLCB2b2lkICpkZXZfaWQpCj4gK3sKPiArCXN0cnVj dCBjZG5zX25hbmRfY3RybCAqY2Ruc19jdHJsID0gZGV2X2lkOwo+ICsJc3RydWN0IGNhZGVuY2Vf bmFuZF9pcnFfc3RhdHVzIGlycV9zdGF0dXM7Cj4gKwlpcnFyZXR1cm5fdCByZXN1bHQgPSBJUlFf Tk9ORTsKPiArCj4gKwlzcGluX2xvY2soJmNkbnNfY3RybC0+aXJxX2xvY2spOwo+ICsKPiArCWlm IChpcnFfZGV0ZWN0ZWQoY2Ruc19jdHJsLCAmaXJxX3N0YXR1cykpIHsKPiArCQkvKiBIYW5kbGUg aW50ZXJydXB0LiAqLwo+ICsJCS8qIEZpcnN0IGFja25vd2xlZGdlIGl0LiAqLwo+ICsJCWNhZGVu Y2VfbmFuZF9jbGVhcl9pbnRlcnJ1cHQoY2Ruc19jdHJsLCAmaXJxX3N0YXR1cyk7Cj4gKwkJLyog U3RhdHVzIGluIHRoZSBkZXZpY2UgY29udGV4dCBmb3Igc29tZW9uZSB0byByZWFkLiAqLwo+ICsJ CWNkbnNfY3RybC0+aXJxX3N0YXR1cy5zdGF0dXMgfD0gaXJxX3N0YXR1cy5zdGF0dXM7Cj4gKwkJ Y2Ruc19jdHJsLT5pcnFfc3RhdHVzLnRyZF9zdGF0dXMgfD0gaXJxX3N0YXR1cy50cmRfc3RhdHVz Owo+ICsJCWNkbnNfY3RybC0+aXJxX3N0YXR1cy50cmRfZXJyb3IgfD0gaXJxX3N0YXR1cy50cmRf ZXJyb3I7Cj4gKwkJLyogTm90aWZ5IGFueW9uZSB3aG8gY2FyZXMgdGhhdCBpdCBoYXBwZW5lZC4g Ki8KPiArCQljb21wbGV0ZSgmY2Ruc19jdHJsLT5jb21wbGV0ZSk7Cj4gKwkJLyogVGVsbCB0aGUg T1MgdGhhdCB3ZSd2ZSBoYW5kbGVkIHRoaXMuICovCj4gKwkJcmVzdWx0ID0gSVJRX0hBTkRMRUQ7 Cj4gKwl9Cj4gKwlzcGluX3VubG9jaygmY2Ruc19jdHJsLT5pcnFfbG9jayk7CgpZb3VyIGxvY2tp bmcgc2NoZW1lIHNlZW1zIHdyb25nIChtYXliZSBJJ20gbm90IGdvaW5nIGRlZXAgZW5vdWdoIGlu IHRoZQpjb2RlKSwgY2FuIHlvdSBwbGVhc2UgdHJ5IHdpdGggTE9DS0RFUCBlbmFibGVkPwoKPiAr Cj4gKwlyZXR1cm4gcmVzdWx0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBjYWRlbmNlX25hbmRf c2V0X2lycV9tYXNrKHN0cnVjdCBjZG5zX25hbmRfY3RybCAqY2Ruc19jdHJsLAo+ICsJCQkJICAg ICAgc3RydWN0IGNhZGVuY2VfbmFuZF9pcnFfc3RhdHVzICppcnFfbWFzaykKPiArewo+ICsJd3Jp dGVsX3JlbGF4ZWQoSU5UUl9FTkFCTEVfSU5UUl9FTiB8IGlycV9tYXNrLT5zdGF0dXMsCj4gKwkJ ICAgICAgIGNkbnNfY3RybC0+cmVnICsgSU5UUl9FTkFCTEUpOwo+ICsKPiArCXdyaXRlbF9yZWxh eGVkKGlycV9tYXNrLT50cmRfZXJyb3IsCj4gKwkJICAgICAgIGNkbnNfY3RybC0+cmVnICsgVFJE X0VSUl9JTlRfU1RBVFVTX0VOKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQKPiArY2FkZW5jZV9u YW5kX3dhaXRfZm9yX2lycShzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3RybCwKPiArCQkJ ICBzdHJ1Y3QgY2FkZW5jZV9uYW5kX2lycV9zdGF0dXMgKmlycV9tYXNrLAo+ICsJCQkgIHN0cnVj dCBjYWRlbmNlX25hbmRfaXJxX3N0YXR1cyAqaXJxX3N0YXR1cykKPiArewo+ICsJdW5zaWduZWQg bG9uZyB0aW1lb3V0ID0gbXNlY3NfdG9famlmZmllcygxMDAwMCk7Cj4gKwl1bnNpZ25lZCBsb25n IHRpbWVfbGVmdDsKPiArCj4gKwl0aW1lX2xlZnQgPSB3YWl0X2Zvcl9jb21wbGV0aW9uX3RpbWVv dXQoJmNkbnNfY3RybC0+Y29tcGxldGUsCj4gKwkJCQkJCXRpbWVvdXQpOwo+ICsKPiArCSppcnFf c3RhdHVzID0gY2Ruc19jdHJsLT5pcnFfc3RhdHVzOwo+ICsJaWYgKHRpbWVfbGVmdCA9PSAwKSB7 Cj4gKwkJLyogVGltZW91dCBlcnJvci4gKi8KPiArCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LCAi dGltZW91dCBvY2N1cnJlZDpcbiIpOwo+ICsJCWRldl9lcnIoY2Ruc19jdHJsLT5kZXYsICJcdHN0 YXR1cyA9IDB4JXgsIG1hc2sgPSAweCV4XG4iLAo+ICsJCQlpcnFfc3RhdHVzLT5zdGF0dXMsIGly cV9tYXNrLT5zdGF0dXMpOwo+ICsJCWRldl9lcnIoY2Ruc19jdHJsLT5kZXYsCj4gKwkJCSJcdHRy ZF9zdGF0dXMgPSAweCV4LCB0cmRfc3RhdHVzIG1hc2sgPSAweCV4XG4iLAo+ICsJCQlpcnFfc3Rh dHVzLT50cmRfc3RhdHVzLCBpcnFfbWFzay0+dHJkX3N0YXR1cyk7Cj4gKwkJZGV2X2VycihjZG5z X2N0cmwtPmRldiwKPiArCQkJIlx0IHRyZF9lcnJvciA9IDB4JXgsIHRyZF9lcnJvciBtYXNrID0g MHgleFxuIiwKPiArCQkJaXJxX3N0YXR1cy0+dHJkX2Vycm9yLCBpcnFfbWFzay0+dHJkX2Vycm9y KTsKPiArCX0KPiArfQo+ICsKPiArc3RhdGljIHZvaWQKPiArY2FkZW5jZV9uYW5kX2lycV9jbGVh bnVwKGludCBpcnFudW0sIHN0cnVjdCBjZG5zX25hbmRfY3RybCAqY2Ruc19jdHJsKQo+ICt7Cj4g KwkvKiBEaXNhYmxlIGludGVycnVwdHMuICovCj4gKwl3cml0ZWxfcmVsYXhlZChJTlRSX0VOQUJM RV9JTlRSX0VOLCBjZG5zX2N0cmwtPnJlZyArIElOVFJfRU5BQkxFKTsKPiArfQoKV291bGQgeW91 IG1pbmQgbW92aW5nIHRoaXMgaGVscGVyIHRvIHRoZSBib3R0b20sIHdoZXJlIGl0IGlzIHVzZWQK KGNsb3NlciB0byB0aGUgcmVtb3ZlL2NsZWFudXAgZnVuY3Rpb25zKS4KCj4gKwo+ICsvKiBFeGVj dXRlIGdlbmVyaWMgY29tbWFuZCBvbiBOQU5EIGNvbnRyb2xsZXIuICovCj4gK3N0YXRpYyBpbnQg Y2FkZW5jZV9uYW5kX2dlbmVyaWNfY21kX3NlbmQoc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5z X2N0cmwsCj4gKwkJCQkJIHU4IGNoaXBfbnIsCj4gKwkJCQkJIHU2NCBtaW5pX2N0cmxfY21kKQo+ ICt7Cj4gKwl1MzIgbWluaV9jdHJsX2NtZF9sLCBtaW5pX2N0cmxfY21kX2gsIHJlZzsKPiArCj4g KwltaW5pX2N0cmxfY21kIHw9IEZJRUxEX1BSRVAoR0NNRF9MQVlfQ1MsIGNoaXBfbnIpOwo+ICsJ bWluaV9jdHJsX2NtZF9sID0gbWluaV9jdHJsX2NtZCAmIDB4RkZGRkZGRkY7Cj4gKwltaW5pX2N0 cmxfY21kX2ggPSBtaW5pX2N0cmxfY21kID4+IDMyOwo+ICsKPiArCWlmIChjYWRlbmNlX25hbmRf d2FpdF9mb3JfdmFsdWUoY2Ruc19jdHJsLCBDVFJMX1NUQVRVUywKPiArCQkJCQkxMDAwMDAwLAo+ ICsJCQkJCUNUUkxfU1RBVFVTX0NUUkxfQlVTWSwgdHJ1ZSkpCj4gKwkJcmV0dXJuIC1FVElNRURP VVQ7Cj4gKwo+ICsJY2FkZW5jZV9uYW5kX3Jlc2V0X2lycShjZG5zX2N0cmwpOwo+ICsKPiArCXdy aXRlbF9yZWxheGVkKG1pbmlfY3RybF9jbWRfbCwgY2Ruc19jdHJsLT5yZWcgKyBDTURfUkVHMik7 Cj4gKwl3cml0ZWxfcmVsYXhlZChtaW5pX2N0cmxfY21kX2gsIGNkbnNfY3RybC0+cmVnICsgQ01E X1JFRzMpOwo+ICsKPiArCS8qIFNlbGVjdCBnZW5lcmljIGNvbW1hbmQuICovCj4gKwlyZWcgPSBG SUVMRF9QUkVQKENNRF9SRUcwX0NULCBDTURfUkVHMF9DVF9HRU4pOwo+ICsJLyogVGhyZWFkIG51 bWJlci4gKi8KPiArCXJlZyB8PSBGSUVMRF9QUkVQKENNRF9SRUcwX1ROLCAwKTsKPiArCj4gKwkv KiBJc3N1ZSBjb21tYW5kLiAqLwo+ICsJd3JpdGVsX3JlbGF4ZWQocmVnLCBjZG5zX2N0cmwtPnJl ZyArIENNRF9SRUcwKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArLyogV2FpdCBmb3Ig ZGF0YSBvbiBzbGF2ZSBETUEgaW50ZXJmYWNlLiAqLwo+ICtzdGF0aWMgaW50IGNhZGVuY2VfbmFu ZF93YWl0X29uX3NkbWEoc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwsCj4gKwkJCQkg ICAgIHU4ICpvdXRfc2RtYV90cmQsCj4gKwkJCQkgICAgIHUzMiAqb3V0X3NkbWFfc2l6ZSkKPiAr ewo+ICsJc3RydWN0IGNhZGVuY2VfbmFuZF9pcnFfc3RhdHVzIGlycV9tYXNrLCBpcnFfc3RhdHVz Owo+ICsKPiArCWlycV9tYXNrLnRyZF9zdGF0dXMgPSAwOwo+ICsJaXJxX21hc2sudHJkX2Vycm9y ID0gMDsKPiArCWlycV9tYXNrLnN0YXR1cyA9IElOVFJfU1RBVFVTX1NETUFfVFJJR0cKPiArCQl8 IElOVFJfU1RBVFVTX1NETUFfRVJSCj4gKwkJfCBJTlRSX1NUQVRVU19VTlNVUFBfQ01EOwo+ICsK PiArCWNhZGVuY2VfbmFuZF9zZXRfaXJxX21hc2soY2Ruc19jdHJsLCAmaXJxX21hc2spOwo+ICsJ Y2FkZW5jZV9uYW5kX3dhaXRfZm9yX2lycShjZG5zX2N0cmwsICZpcnFfbWFzaywgJmlycV9zdGF0 dXMpOwo+ICsJaWYgKGlycV9zdGF0dXMuc3RhdHVzID09IDApIHsKPiArCQlkZXZfZXJyKGNkbnNf Y3RybC0+ZGV2LCAiVGltZW91dCB3aGlsZSB3YWl0aW5nIGZvciBTRE1BXG4iKTsKPiArCQlyZXR1 cm4gLUVUSU1FRE9VVDsKPiArCX0KPiArCj4gKwlpZiAoaXJxX3N0YXR1cy5zdGF0dXMgJiBJTlRS X1NUQVRVU19TRE1BX1RSSUdHKSB7Cj4gKwkJKm91dF9zZG1hX3NpemUgPSByZWFkbF9yZWxheGVk KGNkbnNfY3RybC0+cmVnICsgU0RNQV9TSVpFKTsKPiArCQkqb3V0X3NkbWFfdHJkICA9IHJlYWRs X3JlbGF4ZWQoY2Ruc19jdHJsLT5yZWcgKyBTRE1BX1RSRF9OVU0pOwo+ICsJCSpvdXRfc2RtYV90 cmQgPQo+ICsJCQlGSUVMRF9HRVQoU0RNQV9UUkRfTlVNX1NETUFfVFJELCAqb3V0X3NkbWFfdHJk KTsKPiArCX0gZWxzZSB7Cj4gKwkJZGV2X2VycihjZG5zX2N0cmwtPmRldiwgIlNETUEgZXJyb3Ig LSBpcnFfc3RhdHVzICV4XG4iLAo+ICsJCQlpcnFfc3RhdHVzLnN0YXR1cyk7Cj4gKwkJcmV0dXJu IC1FSU87Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIGNh ZGVuY2VfbmFuZF9nZXRfY2FwcyhzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3RybCkKPiAr ewo+ICsJdTMyICByZWc7Cj4gKwo+ICsJcmVnID0gcmVhZGxfcmVsYXhlZChjZG5zX2N0cmwtPnJl ZyArIENUUkxfRkVBVFVSRVMpOwo+ICsKPiArCWNkbnNfY3RybC0+Y2FwczIubWF4X2JhbmtzID0g MSA8PCBGSUVMRF9HRVQoQ1RSTF9GRUFUVVJFU19OX0JBTktTLCByZWcpOwo+ICsKPiArCWlmIChG SUVMRF9HRVQoQ1RSTF9GRUFUVVJFU19ETUFfRFdJVEg2NCwgcmVnKSkKPiArCQljZG5zX2N0cmwt PmNhcHMyLmRhdGFfZG1hX3dpZHRoID0gODsKPiArCWVsc2UKPiArCQljZG5zX2N0cmwtPmNhcHMy LmRhdGFfZG1hX3dpZHRoID0gNDsKPiArCj4gKwlpZiAocmVnICYgQ1RSTF9GRUFUVVJFU19DT05U Uk9MX0RBVEEpCj4gKwkJY2Ruc19jdHJsLT5jYXBzMi5kYXRhX2NvbnRyb2xfc3VwcCA9IDE7Cj4g Kwo+ICsJaWYgKHJlZyAmIChDVFJMX0ZFQVRVUkVTX05WRERSXzJfMwo+ICsJCSAgIHwgQ1RSTF9G RUFUVVJFU19OVkREUikpCj4gKwkJY2Ruc19jdHJsLT5jYXBzMi5pc19waHlfdHlwZV9kbGwgPSAx Owo+ICt9Cj4gKwo+ICsvKiBQcmVwYXJlIENETUEgZGVzY3JpcHRvci4gKi8KPiArc3RhdGljIHZv aWQKPiArY2FkZW5jZV9uYW5kX2NkbWFfZGVzY19wcmVwYXJlKHN0cnVjdCBjYWRlbmNlX25hbmRf Y2RtYV9kZXNjICpjZG1hX2Rlc2MsCj4gKwkJCSAgICAgICBjaGFyIG5mX21lbSwgdTMyIGZsYXNo X3B0ciwgY2hhciAqbWVtX3B0ciwKPiArCQkJICAgICAgIGNoYXIgKmN0cmxfZGF0YV9wdHIsIHUx NiBjdHlwZSkKPiArewo+ICsJbWVtc2V0KGNkbWFfZGVzYywgMCwgc2l6ZW9mKHN0cnVjdCBjYWRl bmNlX25hbmRfY2RtYV9kZXNjKSk7Cj4gKwo+ICsJLyogU2V0IGZpZWxkcyBmb3Igb25lIGRlc2Ny aXB0b3IuICovCj4gKwljZG1hX2Rlc2MtPmZsYXNoX3BvaW50ZXIgPSAobmZfbWVtIDw8IENETUFf Q0ZQVFJfTUVNX1NISUZUKQo+ICsJCSsgZmxhc2hfcHRyOwo+ICsJY2RtYV9kZXNjLT5jb21tYW5k X2ZsYWdzIHw9IENETUFfQ0ZfRE1BX01BU1RFUjsKPiArCWNkbWFfZGVzYy0+Y29tbWFuZF9mbGFn cyAgfD0gQ0RNQV9DRl9JTlQ7Cj4gKwo+ICsJY2RtYV9kZXNjLT5tZW1vcnlfcG9pbnRlciA9ICh1 aW50cHRyX3QpbWVtX3B0cjsKPiArCWNkbWFfZGVzYy0+c3RhdHVzID0gMDsKPiArCWNkbWFfZGVz Yy0+c3luY19mbGFnX3BvaW50ZXIgPSAwOwo+ICsJY2RtYV9kZXNjLT5zeW5jX2FyZ3VtZW50cyA9 IDA7Cj4gKwo+ICsJY2RtYV9kZXNjLT5jb21tYW5kX3R5cGUgPSBjdHlwZTsKPiArCWNkbWFfZGVz Yy0+Y3RybF9kYXRhX3B0ciA9ICh1aW50cHRyX3QpY3RybF9kYXRhX3B0cjsKPiArfQo+ICsKPiAr c3RhdGljIHU4IGNhZGVuY2VfbmFuZF9jaGVja19kZXNjX2Vycm9yKHN0cnVjdCBjZG5zX25hbmRf Y3RybCAqY2Ruc19jdHJsLAo+ICsJCQkJCXUzMiBkZXNjX3N0YXR1cykKPiArewo+ICsJaWYgKGRl c2Nfc3RhdHVzICYgQ0RNQV9DU19FUlApCj4gKwkJcmV0dXJuIFNUQVRfRVJBU0VEOwo+ICsKPiAr CWlmIChkZXNjX3N0YXR1cyAmIENETUFfQ1NfVU5DRSkKPiArCQlyZXR1cm4gU1RBVF9FQ0NfVU5D T1JSOwo+ICsKPiArCWlmIChkZXNjX3N0YXR1cyAmIENETUFfQ1NfRVJSKSB7Cj4gKwkJZGV2X2Vy cihjZG5zX2N0cmwtPmRldiwgIjpDRE1BIGRlc2MgZXJyb3IgZmxhZyBkZXRlY3RlZC5cbiIpOwo+ ICsJCXJldHVybiBTVEFUX0ZBSUw7Cj4gKwl9Cj4gKwo+ICsJaWYgKEZJRUxEX0dFVChDRE1BX0NT X01BWEVSUiwgZGVzY19zdGF0dXMpKQo+ICsJCXJldHVybiBTVEFUX0VDQ19DT1JSOwo+ICsKPiAr CXJldHVybiBTVEFUX0ZBSUw7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgY2FkZW5jZV9uYW5kX2Nk bWFfZmluaXNoKHN0cnVjdCBjZG5zX25hbmRfY3RybCAqY2Ruc19jdHJsLAo+ICsJCQkJICAgIHN0 cnVjdCBjYWRlbmNlX25hbmRfY2RtYV9kZXNjICpjZG1hX2Rlc2MpCj4gK3sKPiArCXN0cnVjdCBj YWRlbmNlX25hbmRfY2RtYV9kZXNjICpkZXNjX3B0ciA9IGNkbWFfZGVzYzsKPiArCXU4IHN0YXR1 cyA9IFNUQVRfQlVTWTsKPiArCj4gKwlpZiAoZGVzY19wdHItPnN0YXR1cyAmIENETUFfQ1NfRkFJ TCkgewo+ICsJCXN0YXR1cyA9IGNhZGVuY2VfbmFuZF9jaGVja19kZXNjX2Vycm9yKGNkbnNfY3Ry bCwKPiArCQkJCQkJICAgICAgIGRlc2NfcHRyLT5zdGF0dXMpOwo+ICsJCWRldl9lcnIoY2Ruc19j dHJsLT5kZXYsICI6Q0RNQSBlcnJvciAleFxuIiwgZGVzY19wdHItPnN0YXR1cyk7Cj4gKwl9IGVs c2UgaWYgKGRlc2NfcHRyLT5zdGF0dXMgJiBDRE1BX0NTX0NPTVApIHsKPiArCQkvKiBEZXNjcmlw dG9yIGZpbmlzaGVkIHdpdGggbm8gZXJyb3JzLiAqLwo+ICsJCWlmIChkZXNjX3B0ci0+Y29tbWFu ZF9mbGFncyAmIENETUFfQ0ZfQ09OVCkgewo+ICsJCQlkZXZfaW5mbyhjZG5zX2N0cmwtPmRldiwg IkRNQSB1bnN1cHBvcnRlZCBmbGFnIGlzIHNldCIpOwo+ICsJCQlzdGF0dXMgPSBTVEFUX1VOS05P V047Cj4gKwkJfSBlbHNlIHsKPiArCQkJLyogTGFzdCBkZXNjcmlwdG9yLiAgKi8KPiArCQkJc3Rh dHVzID0gU1RBVF9PSzsKPiArCQl9Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIHN0YXR1czsKPiArfQo+ ICsKPiArc3RhdGljIGludCBjYWRlbmNlX25hbmRfY2RtYV9zZW5kKHN0cnVjdCBjZG5zX25hbmRf Y3RybCAqY2Ruc19jdHJsLAo+ICsJCQkJICB1OCB0aHJlYWQpCj4gK3sKPiArCXUzMiByZWc7Cj4g KwlpbnQgc3RhdHVzOwo+ICsKPiArCS8qIFdhaXQgZm9yIHRocmVhZCByZWFkeS4gKi8KPiArCXN0 YXR1cyA9IGNhZGVuY2VfbmFuZF93YWl0X2Zvcl92YWx1ZShjZG5zX2N0cmwsIFRSRF9TVEFUVVMs Cj4gKwkJCQkJICAgICAxMDAwMDAwLAo+ICsJCQkJCSAgICAgMVUgPDwgdGhyZWFkLCB0cnVlKTsK PiArCWlmIChzdGF0dXMpCj4gKwkJcmV0dXJuIHN0YXR1czsKPiArCj4gKwljYWRlbmNlX25hbmRf cmVzZXRfaXJxKGNkbnNfY3RybCk7Cj4gKwo+ICsJd3JpdGVsX3JlbGF4ZWQoKHUzMiljZG5zX2N0 cmwtPmRtYV9jZG1hX2Rlc2MsCj4gKwkJICAgICAgIGNkbnNfY3RybC0+cmVnICsgQ01EX1JFRzIp Owo+ICsJd3JpdGVsX3JlbGF4ZWQoMCwgY2Ruc19jdHJsLT5yZWcgKyBDTURfUkVHMyk7Cj4gKwo+ ICsJLyogU2VsZWN0IENETUEgbW9kZS4gKi8KPiArCXJlZyA9IEZJRUxEX1BSRVAoQ01EX1JFRzBf Q1QsIENNRF9SRUcwX0NUX0NETUEpOwo+ICsJLyogVGhyZWFkIG51bWJlci4gKi8KPiArCXJlZyB8 PSBGSUVMRF9QUkVQKENNRF9SRUcwX1ROLCB0aHJlYWQpOwo+ICsJLyogSXNzdWUgY29tbWFuZC4g Ki8KPiArCXdyaXRlbF9yZWxheGVkKHJlZywgY2Ruc19jdHJsLT5yZWcgKyBDTURfUkVHMCk7Cj4g Kwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gKy8qIFNlbmQgU0RNQSBjb21tYW5kIGFuZCB3YWl0 IGZvciBmaW5pc2guICovCj4gK3N0YXRpYyB1MzIKPiArY2FkZW5jZV9uYW5kX2NkbWFfc2VuZF9h bmRfd2FpdChzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3RybCwKPiArCQkJCXU4IHRocmVh ZCkKPiArewo+ICsJc3RydWN0IGNhZGVuY2VfbmFuZF9pcnFfc3RhdHVzIGlycV9tYXNrLCBpcnFf c3RhdHVzID0gezB9Owo+ICsJaW50IHN0YXR1czsKPiArCj4gKwlpcnFfbWFzay50cmRfc3RhdHVz ID0gMSA8PCB0aHJlYWQ7Cj4gKwlpcnFfbWFzay50cmRfZXJyb3IgPSAxIDw8IHRocmVhZDsKPiAr CWlycV9tYXNrLnN0YXR1cyA9IElOVFJfU1RBVFVTX0NETUFfVEVSUjsKPiArCj4gKwljYWRlbmNl X25hbmRfc2V0X2lycV9tYXNrKGNkbnNfY3RybCwgJmlycV9tYXNrKTsKPiArCj4gKwlzdGF0dXMg PSBjYWRlbmNlX25hbmRfY2RtYV9zZW5kKGNkbnNfY3RybCwgdGhyZWFkKTsKPiArCWlmIChzdGF0 dXMpCj4gKwkJcmV0dXJuIHN0YXR1czsKPiArCj4gKwljYWRlbmNlX25hbmRfd2FpdF9mb3JfaXJx KGNkbnNfY3RybCwgJmlycV9tYXNrLCAmaXJxX3N0YXR1cyk7Cj4gKwo+ICsJaWYgKGlycV9zdGF0 dXMuc3RhdHVzID09IDAgJiYgaXJxX3N0YXR1cy50cmRfc3RhdHVzID09IDAgJiYKPiArCSAgICBp cnFfc3RhdHVzLnRyZF9lcnJvciA9PSAwKSB7Cj4gKwkJZGV2X2VycihjZG5zX2N0cmwtPmRldiwg IkNETUEgY29tbWFuZCB0aW1lb3V0XG4iKTsKPiArCQlyZXR1cm4gLUVUSU1FRE9VVDsKPiArCX0K PiArCWlmIChpcnFfc3RhdHVzLnN0YXR1cyAmIGlycV9tYXNrLnN0YXR1cykgewo+ICsJCWRldl9l cnIoY2Ruc19jdHJsLT5kZXYsICJDRE1BIGNvbW1hbmQgZmFpbGVkXG4iKTsKPiArCQlyZXR1cm4g LUVJTzsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArLyoKPiArICogRUNDIHNp emUgZGVwZW5kcyBvbiBjb25maWd1cmVkIEVDQyBzdHJlbmd0aCBhbmQgb24gbWF4aW11bSBzdXBw b3J0ZWQKPiArICogRUNDIHN0ZXAgc2l6ZS4KPiArICovCj4gK3N0YXRpYyBpbnQgY2FkZW5jZV9u YW5kX2NhbGNfZWNjX2J5dGVzKGludCBtYXhfc3RlcF9zaXplLCBpbnQgc3RyZW5ndGgpCj4gK3sK PiArCWludCBuYnl0ZXMgPSBESVZfUk9VTkRfVVAoZmxzKDggKiBtYXhfc3RlcF9zaXplKSAqIHN0 cmVuZ3RoLCA4KTsKPiArCj4gKwlyZXR1cm4gQUxJR04obmJ5dGVzLCAyKTsKPiArfQo+ICsKPiAr I2RlZmluZSBDQURFTkNFX05BTkRfQ0FMQ19FQ0NfQllURVMobWF4X3N0ZXBfc2l6ZSkgXAo+ICsJ c3RhdGljIGludCBcCj4gKwljYWRlbmNlX25hbmRfY2FsY19lY2NfYnl0ZXNfIyNtYXhfc3RlcF9z aXplKGludCBzdGVwX3NpemUsIFwKPiArCQkJCQkJICAgIGludCBzdHJlbmd0aClcCj4gKwl7XAo+ ICsJCXJldHVybiBjYWRlbmNlX25hbmRfY2FsY19lY2NfYnl0ZXMobWF4X3N0ZXBfc2l6ZSwgc3Ry ZW5ndGgpO1wKPiArCX0KPiArCj4gK0NBREVOQ0VfTkFORF9DQUxDX0VDQ19CWVRFUygyNTYpCj4g K0NBREVOQ0VfTkFORF9DQUxDX0VDQ19CWVRFUyg1MTIpCj4gK0NBREVOQ0VfTkFORF9DQUxDX0VD Q19CWVRFUygxMDI0KQo+ICtDQURFTkNFX05BTkRfQ0FMQ19FQ0NfQllURVMoMjA0OCkKPiArQ0FE RU5DRV9OQU5EX0NBTENfRUNDX0JZVEVTKDQwOTYpCj4gKwo+ICsvKiBGdW5jdGlvbiByZWFkcyBC Q0ggY2FwYWJpbGl0aWVzLiAqLwo+ICtzdGF0aWMgaW50IGNhZGVuY2VfbmFuZF9yZWFkX2JjaF9j YXBzKHN0cnVjdCBjZG5zX25hbmRfY3RybCAqY2Ruc19jdHJsKQo+ICt7Cj4gKwlzdHJ1Y3QgbmFu ZF9lY2NfY2FwcyAqZWNjX2NhcHMgPSAmY2Ruc19jdHJsLT5lY2NfY2FwczsKPiArCWludCBtYXhf c3RlcF9zaXplID0gMCwgbnN0cmVuZ3RocywgaTsKPiArCXUzMiByZWc7Cj4gKwo+ICsJcmVnID0g cmVhZGxfcmVsYXhlZChjZG5zX2N0cmwtPnJlZyArIEJDSF9DRkdfMCk7Cj4gKwljZG5zX2N0cmwt PmVjY19zdHJlbmd0aHNbMF0gPSBGSUVMRF9HRVQoQkNIX0NGR18wX0NPUlJfQ0FQXzAsIHJlZyk7 Cj4gKwljZG5zX2N0cmwtPmVjY19zdHJlbmd0aHNbMV0gPSBGSUVMRF9HRVQoQkNIX0NGR18wX0NP UlJfQ0FQXzEsIHJlZyk7Cj4gKwljZG5zX2N0cmwtPmVjY19zdHJlbmd0aHNbMl0gPSBGSUVMRF9H RVQoQkNIX0NGR18wX0NPUlJfQ0FQXzIsIHJlZyk7Cj4gKwljZG5zX2N0cmwtPmVjY19zdHJlbmd0 aHNbM10gPSBGSUVMRF9HRVQoQkNIX0NGR18wX0NPUlJfQ0FQXzMsIHJlZyk7Cj4gKwo+ICsJcmVn ID0gcmVhZGxfcmVsYXhlZChjZG5zX2N0cmwtPnJlZyArIEJDSF9DRkdfMSk7Cj4gKwljZG5zX2N0 cmwtPmVjY19zdHJlbmd0aHNbNF0gPSBGSUVMRF9HRVQoQkNIX0NGR18xX0NPUlJfQ0FQXzQsIHJl Zyk7Cj4gKwljZG5zX2N0cmwtPmVjY19zdHJlbmd0aHNbNV0gPSBGSUVMRF9HRVQoQkNIX0NGR18x X0NPUlJfQ0FQXzUsIHJlZyk7Cj4gKwljZG5zX2N0cmwtPmVjY19zdHJlbmd0aHNbNl0gPSBGSUVM RF9HRVQoQkNIX0NGR18xX0NPUlJfQ0FQXzYsIHJlZyk7Cj4gKwljZG5zX2N0cmwtPmVjY19zdHJl bmd0aHNbN10gPSBGSUVMRF9HRVQoQkNIX0NGR18xX0NPUlJfQ0FQXzcsIHJlZyk7Cj4gKwo+ICsJ cmVnID0gcmVhZGxfcmVsYXhlZChjZG5zX2N0cmwtPnJlZyArIEJDSF9DRkdfMik7Cj4gKwljZG5z X2N0cmwtPmVjY19zdGVwaW5mb3NbMF0uc3RlcHNpemUgPQo+ICsJCUZJRUxEX0dFVChCQ0hfQ0ZH XzJfU0VDVF8wLCByZWcpOwo+ICsKPiArCWNkbnNfY3RybC0+ZWNjX3N0ZXBpbmZvc1sxXS5zdGVw c2l6ZSA9Cj4gKwkJRklFTERfR0VUKEJDSF9DRkdfMl9TRUNUXzEsIHJlZyk7Cj4gKwo+ICsJbnN0 cmVuZ3RocyA9IDA7Cj4gKwlmb3IgKGkgPSAwOyBpIDwgQkNIX01BWF9OVU1fQ09SUl9DQVBTOyBp KyspIHsKPiArCQlpZiAoY2Ruc19jdHJsLT5lY2Nfc3RyZW5ndGhzW2ldICE9IDApCj4gKwkJCW5z dHJlbmd0aHMrKzsKPiArCX0KPiArCj4gKwllY2NfY2Fwcy0+bnN0ZXBpbmZvcyA9IDA7Cj4gKwlm b3IgKGkgPSAwOyBpIDwgQkNIX01BWF9OVU1fU0VDVE9SX1NJWkVTOyBpKyspIHsKPiArCQkvKiBF Q0Mgc3RyZW5ndGhzIGFyZSBjb21tb24gZm9yIGFsbCBzdGVwIGluZm9zLiAqLwo+ICsJCWNkbnNf Y3RybC0+ZWNjX3N0ZXBpbmZvc1tpXS5uc3RyZW5ndGhzID0gbnN0cmVuZ3RoczsKPiArCQljZG5z X2N0cmwtPmVjY19zdGVwaW5mb3NbaV0uc3RyZW5ndGhzID0KPiArCQkJY2Ruc19jdHJsLT5lY2Nf c3RyZW5ndGhzOwo+ICsKPiArCQlpZiAoY2Ruc19jdHJsLT5lY2Nfc3RlcGluZm9zW2ldLnN0ZXBz aXplICE9IDApCj4gKwkJCWVjY19jYXBzLT5uc3RlcGluZm9zKys7Cj4gKwo+ICsJCWlmIChjZG5z X2N0cmwtPmVjY19zdGVwaW5mb3NbaV0uc3RlcHNpemUgPiBtYXhfc3RlcF9zaXplKQo+ICsJCQlt YXhfc3RlcF9zaXplID0gY2Ruc19jdHJsLT5lY2Nfc3RlcGluZm9zW2ldLnN0ZXBzaXplOwo+ICsJ fQo+ICsJZWNjX2NhcHMtPnN0ZXBpbmZvcyA9ICZjZG5zX2N0cmwtPmVjY19zdGVwaW5mb3NbMF07 Cj4gKwo+ICsJc3dpdGNoIChtYXhfc3RlcF9zaXplKSB7Cj4gKwljYXNlIDI1NjoKPiArCQllY2Nf Y2Fwcy0+Y2FsY19lY2NfYnl0ZXMgPSAmY2FkZW5jZV9uYW5kX2NhbGNfZWNjX2J5dGVzXzI1NjsK PiArCQlicmVhazsKPiArCWNhc2UgNTEyOgo+ICsJCWVjY19jYXBzLT5jYWxjX2VjY19ieXRlcyA9 ICZjYWRlbmNlX25hbmRfY2FsY19lY2NfYnl0ZXNfNTEyOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSAx MDI0Ogo+ICsJCWVjY19jYXBzLT5jYWxjX2VjY19ieXRlcyA9ICZjYWRlbmNlX25hbmRfY2FsY19l Y2NfYnl0ZXNfMTAyNDsKPiArCQlicmVhazsKPiArCWNhc2UgMjA0ODoKPiArCQllY2NfY2Fwcy0+ Y2FsY19lY2NfYnl0ZXMgPSAmY2FkZW5jZV9uYW5kX2NhbGNfZWNjX2J5dGVzXzIwNDg7Cj4gKwkJ YnJlYWs7Cj4gKwljYXNlIDQwOTY6Cj4gKwkJZWNjX2NhcHMtPmNhbGNfZWNjX2J5dGVzID0gJmNh ZGVuY2VfbmFuZF9jYWxjX2VjY19ieXRlc180MDk2Owo+ICsJCWJyZWFrOwo+ICsJZGVmYXVsdDoK PiArCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LAo+ICsJCQkiVW5zdXBwb3J0ZWQgc2VjdG9yIHNp emUoZWNjIHN0ZXAgc2l6ZSkgJWRcbiIsCj4gKwkJCW1heF9zdGVwX3NpemUpOwo+ICsJCXJldHVy biAtRUlPOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICsvKiBIYXJkd2FyZSBp bml0aWFsaXphdGlvbi4gKi8KPiArc3RhdGljIGludCBjYWRlbmNlX25hbmRfaHdfaW5pdChzdHJ1 Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3RybCkKPiArewo+ICsJaW50IHN0YXR1czsKPiArCXUz MiByZWc7Cj4gKwo+ICsJc3RhdHVzID0gY2FkZW5jZV9uYW5kX3dhaXRfZm9yX3ZhbHVlKGNkbnNf Y3RybCwgQ1RSTF9TVEFUVVMsCj4gKwkJCQkJICAgICAxMDAwMDAwLAo+ICsJCQkJCSAgICAgQ1RS TF9TVEFUVVNfSU5JVF9DT01QLCBmYWxzZSk7Cj4gKwlpZiAoc3RhdHVzKQo+ICsJCXJldHVybiBz dGF0dXM7Cj4gKwo+ICsJcmVnID0gcmVhZGxfcmVsYXhlZChjZG5zX2N0cmwtPnJlZyArIENUUkxf VkVSU0lPTik7Cj4gKwo+ICsJZGV2X2luZm8oY2Ruc19jdHJsLT5kZXYsCj4gKwkJICIlczogY2Fk ZW5jZSBuYW5kIGNvbnRyb2xsZXIgdmVyc2lvbiByZWcgJXhcbiIsCj4gKwkJIF9fZnVuY19fLCBy ZWcpOwo+ICsKPiArCS8qIERpc2FibGUgY2FjaGUgYW5kIG11bHRpcGxhbmUuICovCj4gKwl3cml0 ZWxfcmVsYXhlZCgwLCBjZG5zX2N0cmwtPnJlZyArIE1VTFRJUExBTkVfQ0ZHKTsKPiArCXdyaXRl bF9yZWxheGVkKDAsIGNkbnNfY3RybC0+cmVnICsgQ0FDSEVfQ0ZHKTsKCkNhY2hlPwoKPiArCj4g KwkvKiBDbGVhciBhbGwgaW50ZXJydXB0cy4gKi8KPiArCXdyaXRlbF9yZWxheGVkKDB4RkZGRkZG RkYsIGNkbnNfY3RybC0+cmVnICsgSU5UUl9TVEFUVVMpOwo+ICsKPiArCWNhZGVuY2VfbmFuZF9n ZXRfY2FwcyhjZG5zX2N0cmwpOwo+ICsJY2FkZW5jZV9uYW5kX3JlYWRfYmNoX2NhcHMoY2Ruc19j dHJsKTsKPiArCj4gKwkvKgo+ICsJICogU2V0IElPIHdpZHRoIGFjY2VzcyB0byA4Lgo+ICsJICog SXQgaXMgYmVjYXVzZSBkdXJpbmcgU1cgZGV2aWNlIGRpc2NvdmVyaW5nIHdpZHRoIGFjY2Vzcwo+ ICsJICogaXMgZXhwZWN0ZWQgdG8gYmUgOC4KPiArCSAqLwo+ICsJc3RhdHVzID0gY2FkZW5jZV9u YW5kX3NldF9hY2Nlc3Nfd2lkdGgxNihjZG5zX2N0cmwsIGZhbHNlKTsKPiArCj4gKwlyZXR1cm4g c3RhdHVzOwo+ICt9Cj4gKwo+ICsjZGVmaW5lIFRUX01BSU5fT09CX0FSRUFTCTIKPiArI2RlZmlu ZSBUVF9SQVdfUEFHRQkJMwo+ICsjZGVmaW5lIFRUX0JCTQkJCTQKPiArI2RlZmluZSBUVF9NQUlO X09PQl9BUkVBX0VYVAk1Cj4gKwo+ICsvKiBQcmVwYXJlIHNpemUgb2YgZGF0YSB0byB0cmFuc2Zl ci4gKi8KPiArc3RhdGljIHZvaWQKPiArY2FkZW5jZV9uYW5kX3ByZXBhcmVfZGF0YV9zaXplKHN0 cnVjdCBuYW5kX2NoaXAgKmNoaXAsCj4gKwkJCSAgICAgICBpbnQgdHJhbnNmZXJfdHlwZSkKPiAr ewo+ICsJc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwgPSB0b19jZG5zX25hbmRfY3Ry bChjaGlwLT5jb250cm9sbGVyKTsKPiArCXN0cnVjdCBjZG5zX25hbmRfY2hpcCAqY2Ruc19jaGlw ID0gdG9fY2Ruc19uYW5kX2NoaXAoY2hpcCk7Cj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IG5h bmRfdG9fbXRkKGNoaXApOwo+ICsJdTMyIHNlY19zaXplID0gMCwgb2Zmc2V0ID0gMCwgc2VjX2Nu dCA9IDE7Cj4gKwl1MzIgbGFzdF9zZWNfc2l6ZSA9IGNkbnNfY2hpcC0+c2VjdG9yX3NpemU7Cj4g Kwl1MzIgZWNjX3NpemUgPSBjaGlwLT5lY2MuYnl0ZXM7Cj4gKwl1MzIgZGF0YV9jdHJsX3NpemUg PSAwOwo+ICsJdTMyIHJlZyA9IDA7Cj4gKwo+ICsJaWYgKGNkbnNfY3RybC0+Y3Vycl90cmFuc190 eXBlID09IHRyYW5zZmVyX3R5cGUpCj4gKwkJcmV0dXJuOwo+ICsKPiArCXN3aXRjaCAodHJhbnNm ZXJfdHlwZSkgewo+ICsJY2FzZSBUVF9NQUlOX09PQl9BUkVBX0VYVDoKPiArCQlzZWNfY250ID0g Y2Ruc19jaGlwLT5zZWN0b3JfY291bnQ7Cj4gKwkJc2VjX3NpemUgPSBjZG5zX2NoaXAtPnNlY3Rv cl9zaXplOwo+ICsJCWRhdGFfY3RybF9zaXplID0gY2Ruc19jaGlwLT5hdmFpbF9vb2Jfc2l6ZTsK PiArCQlicmVhazsKPiArCWNhc2UgVFRfTUFJTl9PT0JfQVJFQVM6Cj4gKwkJc2VjX2NudCA9IGNk bnNfY2hpcC0+c2VjdG9yX2NvdW50Owo+ICsJCWxhc3Rfc2VjX3NpemUgPSBjZG5zX2NoaXAtPnNl Y3Rvcl9zaXplCj4gKwkJCSsgY2Ruc19jaGlwLT5hdmFpbF9vb2Jfc2l6ZTsKPiArCQlzZWNfc2l6 ZSA9IGNkbnNfY2hpcC0+c2VjdG9yX3NpemU7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFRUX1JBV19Q QUdFOgo+ICsJCWxhc3Rfc2VjX3NpemUgPSBtdGQtPndyaXRlc2l6ZSArIG10ZC0+b29ic2l6ZTsK PiArCQlicmVhazsKPiArCWNhc2UgVFRfQkJNOgo+ICsJCW9mZnNldCA9IG10ZC0+d3JpdGVzaXpl ICsgY2Ruc19jaGlwLT5iYm1fb2ZmczsKPiArCQlsYXN0X3NlY19zaXplID0gODsKPiArCQlicmVh azsKPiArCX0KPiArCj4gKwlyZWcgPSAwOwo+ICsJcmVnIHw9IEZJRUxEX1BSRVAoVFJBTl9DRkdf MF9PRkZTRVQsIG9mZnNldCk7Cj4gKwlyZWcgfD0gRklFTERfUFJFUChUUkFOX0NGR18wX1NFQ19D TlQsIHNlY19jbnQpOwo+ICsJd3JpdGVsX3JlbGF4ZWQocmVnLCBjZG5zX2N0cmwtPnJlZyArIFRS QU5fQ0ZHXzApOwo+ICsKPiArCXJlZyA9IDA7Cj4gKwlyZWcgfD0gRklFTERfUFJFUChUUkFOX0NG R18xX0xBU1RfU0VDX1NJWkUsIGxhc3Rfc2VjX3NpemUpOwo+ICsJcmVnIHw9IEZJRUxEX1BSRVAo VFJBTl9DRkdfMV9TRUNUT1JfU0laRSwgc2VjX3NpemUpOwo+ICsJd3JpdGVsX3JlbGF4ZWQocmVn LCBjZG5zX2N0cmwtPnJlZyArIFRSQU5fQ0ZHXzEpOwo+ICsKPiArCWlmIChjZG5zX2N0cmwtPmNh cHMyLmRhdGFfY29udHJvbF9zdXBwID09IDEpIHsKPiArCQlyZWcgPSByZWFkbF9yZWxheGVkKGNk bnNfY3RybC0+cmVnICsgQ09OVFJPTF9EQVRBX0NUUkwpOwo+ICsJCXJlZyAmPSB+Q09OVFJPTF9E QVRBX0NUUkxfU0laRTsKPiArCQlyZWcgfD0gRklFTERfUFJFUChDT05UUk9MX0RBVEFfQ1RSTF9T SVpFLCBkYXRhX2N0cmxfc2l6ZSk7Cj4gKwkJd3JpdGVsX3JlbGF4ZWQocmVnLCBjZG5zX2N0cmwt PnJlZyArIENPTlRST0xfREFUQV9DVFJMKTsKPiArCX0KPiArCj4gKwljZG5zX2N0cmwtPmN1cnJf dHJhbnNfdHlwZSA9IHRyYW5zZmVyX3R5cGU7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQKPiArY2Fk ZW5jZV9uYW5kX2NkbWFfdHJhbnNmZXIoc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmws IHU4IGNoaXBfbnIsCj4gKwkJCSAgIGludCBwYWdlLCB2b2lkICpidWYsIHZvaWQgKmN0cmxfZGF0 LCB1MzIgYnVmX3NpemUsCj4gKwkJCSAgIHUzMiBjdHJsX2RhdF9zaXplLCBlbnVtIGRtYV9kYXRh X2RpcmVjdGlvbiBkaXIsCj4gKwkJCSAgIGJvb2wgd2l0aF9lY2MpCj4gK3sKPiArCXN0cnVjdCBj YWRlbmNlX25hbmRfY2RtYV9kZXNjICpjZG1hX2Rlc2MgPSBjZG5zX2N0cmwtPmNkbWFfZGVzYzsK PiArCWRtYV9hZGRyX3QgZG1hX2J1ZiwgZG1hX2N0cmxfZGF0ID0gMDsKPiArCXU4IHRocmVhZF9u ciA9IGNoaXBfbnI7Cj4gKwlpbnQgc3RhdHVzOwo+ICsJdTE2IGN0eXBlOwo+ICsKPiArCWlmIChk aXIgPT0gRE1BX0ZST01fREVWSUNFKQo+ICsJCWN0eXBlID0gQ0RNQV9DVF9SRDsKPiArCWVsc2UK PiArCQljdHlwZSA9IENETUFfQ1RfV1I7Cj4gKwo+ICsJY2FkZW5jZV9uYW5kX3NldF9lY2NfZW5h YmxlKGNkbnNfY3RybCwgd2l0aF9lY2MpOwo+ICsKPiArCWRtYV9idWYgPSBkbWFfbWFwX3Npbmds ZShjZG5zX2N0cmwtPmRldiwgYnVmLCBidWZfc2l6ZSwgZGlyKTsKPiArCWlmIChkbWFfbWFwcGlu Z19lcnJvcihjZG5zX2N0cmwtPmRldiwgZG1hX2J1ZikpIHsKPiArCQlkZXZfZXJyKGNkbnNfY3Ry bC0+ZGV2LCAiRmFpbGVkIHRvIG1hcCBETUEgYnVmZmVyXG4iKTsKPiArCQlyZXR1cm4gLUVJTzsK PiArCX0KPiArCj4gKwlpZiAoY3RybF9kYXQgJiYgY3RybF9kYXRfc2l6ZSkgewo+ICsJCWRtYV9j dHJsX2RhdCA9IGRtYV9tYXBfc2luZ2xlKGNkbnNfY3RybC0+ZGV2LCBjdHJsX2RhdCwKPiArCQkJ CQkgICAgICBjdHJsX2RhdF9zaXplLCBkaXIpOwo+ICsJCWlmIChkbWFfbWFwcGluZ19lcnJvcihj ZG5zX2N0cmwtPmRldiwgZG1hX2N0cmxfZGF0KSkgewo+ICsJCQlkbWFfdW5tYXBfc2luZ2xlKGNk bnNfY3RybC0+ZGV2LCBkbWFfYnVmLAo+ICsJCQkJCSBidWZfc2l6ZSwgZGlyKTsKPiArCQkJZGV2 X2VycihjZG5zX2N0cmwtPmRldiwgIkZhaWxlZCB0byBtYXAgRE1BIGJ1ZmZlclxuIik7Cj4gKwkJ CXJldHVybiAtRUlPOwo+ICsJCX0KPiArCX0KPiArCj4gKwljYWRlbmNlX25hbmRfY2RtYV9kZXNj X3ByZXBhcmUoY2RtYV9kZXNjLCBjaGlwX25yLCBwYWdlLAo+ICsJCQkJICAgICAgICh2b2lkICop ZG1hX2J1ZiwgKHZvaWQgKilkbWFfY3RybF9kYXQsCj4gKwkJCQkgICAgICAgY3R5cGUpOwo+ICsK PiArCXN0YXR1cyA9IGNhZGVuY2VfbmFuZF9jZG1hX3NlbmRfYW5kX3dhaXQoY2Ruc19jdHJsLCB0 aHJlYWRfbnIpOwo+ICsKPiArCWRtYV91bm1hcF9zaW5nbGUoY2Ruc19jdHJsLT5kZXYsIGRtYV9i dWYsCj4gKwkJCSBidWZfc2l6ZSwgZGlyKTsKPiArCj4gKwlpZiAoY3RybF9kYXQgJiYgY3RybF9k YXRfc2l6ZSkKPiArCQlkbWFfdW5tYXBfc2luZ2xlKGNkbnNfY3RybC0+ZGV2LCBkbWFfY3RybF9k YXQsCj4gKwkJCQkgY3RybF9kYXRfc2l6ZSwgZGlyKTsKPiArCWlmIChzdGF0dXMpCj4gKwkJcmV0 dXJuIHN0YXR1czsKPiArCj4gKwlyZXR1cm4gY2FkZW5jZV9uYW5kX2NkbWFfZmluaXNoKGNkbnNf Y3RybCwgY2Ruc19jdHJsLT5jZG1hX2Rlc2MpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBjYWRl bmNlX25hbmRfc2V0X3RpbWluZ3Moc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwsCj4g KwkJCQkgICAgIHN0cnVjdCBjYWRlbmNlX25hbmRfdGltaW5ncyAqdCkKPiArewo+ICsJd3JpdGVs X3JlbGF4ZWQodC0+YXN5bmNfdG9nZ2xlX3RpbWluZ3MsCj4gKwkJICAgICAgIGNkbnNfY3RybC0+ cmVnICsgQVNZTkNfVE9HR0xFX1RJTUlOR1MpOwo+ICsJd3JpdGVsX3JlbGF4ZWQodC0+dGltaW5n czAsIGNkbnNfY3RybC0+cmVnICsgVElNSU5HUzApOwo+ICsJd3JpdGVsX3JlbGF4ZWQodC0+dGlt aW5nczEsIGNkbnNfY3RybC0+cmVnICsgVElNSU5HUzEpOwo+ICsJd3JpdGVsX3JlbGF4ZWQodC0+ dGltaW5nczIsIGNkbnNfY3RybC0+cmVnICsgVElNSU5HUzIpOwo+ICsKPiArCWlmIChjZG5zX2N0 cmwtPmNhcHMyLmlzX3BoeV90eXBlX2RsbCkKPiArCQl3cml0ZWxfcmVsYXhlZCh0LT5kbGxfcGh5 X2N0cmwsIGNkbnNfY3RybC0+cmVnICsgRExMX1BIWV9DVFJMKTsKPiArCj4gKwl3cml0ZWxfcmVs YXhlZCh0LT5waHlfY3RybCwgY2Ruc19jdHJsLT5yZWcgKyBQSFlfQ1RSTCk7Cj4gKwo+ICsJaWYg KGNkbnNfY3RybC0+Y2FwczIuaXNfcGh5X3R5cGVfZGxsKSB7Cj4gKwkJd3JpdGVsX3JlbGF4ZWQo MCwgY2Ruc19jdHJsLT5yZWcgKyBQSFlfVFNFTCk7Cj4gKwkJd3JpdGVsX3JlbGF4ZWQoMiwgY2Ru c19jdHJsLT5yZWcgKyBQSFlfRFFfVElNSU5HKTsKPiArCQl3cml0ZWxfcmVsYXhlZCh0LT5waHlf ZHFzX3RpbWluZywKPiArCQkJICAgICAgIGNkbnNfY3RybC0+cmVnICsgUEhZX0RRU19USU1JTkcp Owo+ICsJCXdyaXRlbF9yZWxheGVkKHQtPnBoeV9nYXRlX2xwYmtfY3RybCwKPiArCQkJICAgICAg IGNkbnNfY3RybC0+cmVnICsgUEhZX0dBVEVfTFBCS19DVFJMKTsKPiArCQl3cml0ZWxfcmVsYXhl ZChQSFlfRExMX01BU1RFUl9DVFJMX0JZUEFTU19NT0RFLAo+ICsJCQkgICAgICAgY2Ruc19jdHJs LT5yZWcgKyBQSFlfRExMX01BU1RFUl9DVFJMKTsKPiArCQl3cml0ZWxfcmVsYXhlZCgwLCBjZG5z X2N0cmwtPnJlZyArIFBIWV9ETExfU0xBVkVfQ1RSTCk7Cj4gKwl9Cj4gK30KPiArCj4gK3N0YXRp YyBpbnQgY2FkZW5jZV9uYW5kX3NlbGVjdF90YXJnZXQoc3RydWN0IG5hbmRfY2hpcCAqY2hpcCkK PiArewo+ICsJc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwgPSB0b19jZG5zX25hbmRf Y3RybChjaGlwLT5jb250cm9sbGVyKTsKPiArCXN0cnVjdCBjZG5zX25hbmRfY2hpcCAqY2Ruc19j aGlwID0gdG9fY2Ruc19uYW5kX2NoaXAoY2hpcCk7Cj4gKwo+ICsJaWYgKGNoaXAgPT0gY2Ruc19j dHJsLT5zZWxlY3RlZF9jaGlwKQo+ICsJCXJldHVybiAwOwo+ICsKPiArCWlmIChjYWRlbmNlX25h bmRfd2FpdF9mb3JfdmFsdWUoY2Ruc19jdHJsLCBDVFJMX1NUQVRVUywKPiArCQkJCQkxMDAwMDAw LAo+ICsJCQkJCUNUUkxfU1RBVFVTX0NUUkxfQlVTWSwgdHJ1ZSkpCj4gKwkJcmV0dXJuIC1FVElN RURPVVQ7Cj4gKwo+ICsJY2FkZW5jZV9uYW5kX3NldF90aW1pbmdzKGNkbnNfY3RybCwgJmNkbnNf Y2hpcC0+dGltaW5ncyk7Cj4gKwo+ICsJY2FkZW5jZV9uYW5kX3NldF9lY2Nfc3RyZW5ndGgoY2Ru c19jdHJsLAo+ICsJCQkJICAgICAgY2Ruc19jaGlwLT5jb3JyX3N0cl9pZHgpOwo+ICsKPiArCWNh ZGVuY2VfbmFuZF9zZXRfZXJhc2VfZGV0ZWN0aW9uKGNkbnNfY3RybCwgdHJ1ZSwKPiArCQkJCQkg Y2hpcC0+ZWNjLnN0cmVuZ3RoKTsKPiArCj4gKwljZG5zX2N0cmwtPmN1cnJfdHJhbnNfdHlwZSA9 IC0xOwo+ICsJY2Ruc19jdHJsLT5zZWxlY3RlZF9jaGlwID0gY2hpcDsKPiArCj4gKwlyZXR1cm4g MDsKPiArfQo+ICsKPiArc3RhdGljIGludCBjYWRlbmNlX25hbmRfZXJhc2Uoc3RydWN0IG5hbmRf Y2hpcCAqY2hpcCwgdTMyIHBhZ2UpCj4gK3sKPiArCXN0cnVjdCBjZG5zX25hbmRfY3RybCAqY2Ru c19jdHJsID0gdG9fY2Ruc19uYW5kX2N0cmwoY2hpcC0+Y29udHJvbGxlcik7Cj4gKwlzdHJ1Y3Qg Y2Ruc19uYW5kX2NoaXAgKmNkbnNfY2hpcCA9IHRvX2NkbnNfbmFuZF9jaGlwKGNoaXApOwo+ICsJ aW50IHN0YXR1czsKPiArCXU4IHRocmVhZF9uciA9IGNkbnNfY2hpcC0+Y3NbY2hpcC0+Y3VyX2Nz XTsKPiArCj4gKwljYWRlbmNlX25hbmRfY2RtYV9kZXNjX3ByZXBhcmUoY2Ruc19jdHJsLT5jZG1h X2Rlc2MsCj4gKwkJCQkgICAgICAgY2Ruc19jaGlwLT5jc1tjaGlwLT5jdXJfY3NdLAo+ICsJCQkJ ICAgICAgIHBhZ2UsIE5VTEwsIE5VTEwsCj4gKwkJCQkgICAgICAgQ0RNQV9DVF9FUkFTRSk7Cj4g KwlzdGF0dXMgPSBjYWRlbmNlX25hbmRfY2RtYV9zZW5kX2FuZF93YWl0KGNkbnNfY3RybCwgdGhy ZWFkX25yKTsKPiArCWlmIChzdGF0dXMpIHsKPiArCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LCAi ZXJhc2Ugb3BlcmF0aW9uIGZhaWxlZFxuIik7Cj4gKwkJcmV0dXJuIC1FSU87Cj4gKwl9Cj4gKwo+ ICsJc3RhdHVzID0gY2FkZW5jZV9uYW5kX2NkbWFfZmluaXNoKGNkbnNfY3RybCwgY2Ruc19jdHJs LT5jZG1hX2Rlc2MpOwo+ICsJaWYgKHN0YXR1cykKPiArCQlyZXR1cm4gc3RhdHVzOwo+ICsKPiAr CXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGNhZGVuY2VfbmFuZF9yZWFkX2JibShz dHJ1Y3QgbmFuZF9jaGlwICpjaGlwLCBpbnQgcGFnZSwgdTggKmJ1ZikKPiArewo+ICsJaW50IHN0 YXR1czsKPiArCXN0cnVjdCBjZG5zX25hbmRfY3RybCAqY2Ruc19jdHJsID0gdG9fY2Ruc19uYW5k X2N0cmwoY2hpcC0+Y29udHJvbGxlcik7Cj4gKwlzdHJ1Y3QgY2Ruc19uYW5kX2NoaXAgKmNkbnNf Y2hpcCA9IHRvX2NkbnNfbmFuZF9jaGlwKGNoaXApOwo+ICsJc3RydWN0IG10ZF9pbmZvICptdGQg PSBuYW5kX3RvX210ZChjaGlwKTsKPiArCj4gKwljYWRlbmNlX25hbmRfcHJlcGFyZV9kYXRhX3Np emUoY2hpcCwgVFRfQkJNKTsKPiArCj4gKwljYWRlbmNlX25hbmRfc2V0X3NraXBfYnl0ZXNfY29u ZihjZG5zX2N0cmwsIDAsIDAsIDApOwo+ICsKPiArCS8qCj4gKwkgKiBSZWFkIG9ubHkgYmFkIGJs b2NrIG1hcmtlciBmcm9tIG9mZnNldAo+ICsJICogZGVmaW5lZCBieSBhIG1lbW9yeSBtYW51ZmFj dHVyZXIuCj4gKwkgKi8KPiArCXN0YXR1cyA9IGNhZGVuY2VfbmFuZF9jZG1hX3RyYW5zZmVyKGNk bnNfY3RybCwKPiArCQkJCQkgICAgY2Ruc19jaGlwLT5jc1tjaGlwLT5jdXJfY3NdLAo+ICsJCQkJ CSAgICBwYWdlLCBjZG5zX2N0cmwtPmJ1ZiwgTlVMTCwKPiArCQkJCQkgICAgbXRkLT5vb2JzaXpl LAo+ICsJCQkJCSAgICAwLCBETUFfRlJPTV9ERVZJQ0UsIGZhbHNlKTsKPiArCWlmIChzdGF0dXMp IHsKPiArCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LCAicmVhZCBCQk0gZmFpbGVkXG4iKTsKPiAr CQlyZXR1cm4gLUVJTzsKPiArCX0KPiArCj4gKwltZW1jcHkoYnVmICsgY2Ruc19jaGlwLT5iYm1f b2ZmcywgY2Ruc19jdHJsLT5idWYsIGNkbnNfY2hpcC0+YmJtX2xlbik7Cj4gKwo+ICsJcmV0dXJu IDA7Cj4gK30KCk5vdCBzdXJlIHRoaXMgZnVuY3Rpb24gaXMgcmVsZXZhbnQsIHNlZSBiZWxvdy4K Cj4gKwo+ICtzdGF0aWMgaW50IGNhZGVuY2VfbmFuZF93cml0ZV9wYWdlKHN0cnVjdCBuYW5kX2No aXAgKmNoaXAsCj4gKwkJCQkgICBjb25zdCB1OCAqYnVmLCBpbnQgb29iX3JlcXVpcmVkLAo+ICsJ CQkJICAgaW50IHBhZ2UpCj4gK3sKPiArCXN0cnVjdCBjZG5zX25hbmRfY3RybCAqY2Ruc19jdHJs ID0gdG9fY2Ruc19uYW5kX2N0cmwoY2hpcC0+Y29udHJvbGxlcik7Cj4gKwlzdHJ1Y3QgY2Ruc19u YW5kX2NoaXAgKmNkbnNfY2hpcCA9IHRvX2NkbnNfbmFuZF9jaGlwKGNoaXApOwo+ICsJc3RydWN0 IG10ZF9pbmZvICptdGQgPSBuYW5kX3RvX210ZChjaGlwKTsKPiArCWludCBzdGF0dXM7Cj4gKwl1 MTYgbWFya2VyX3ZhbCA9IDB4RkZGRjsKPiArCj4gKwlzdGF0dXMgPSBjYWRlbmNlX25hbmRfc2Vs ZWN0X3RhcmdldChjaGlwKTsKPiArCWlmIChzdGF0dXMpCj4gKwkJcmV0dXJuIHN0YXR1czsKPiAr Cj4gKwljYWRlbmNlX25hbmRfc2V0X3NraXBfYnl0ZXNfY29uZihjZG5zX2N0cmwsIGNkbnNfY2hp cC0+YmJtX2xlbiwKPiArCQkJCQkgbXRkLT53cml0ZXNpemUKPiArCQkJCQkgKyBjZG5zX2NoaXAt PmJibV9vZmZzLAo+ICsJCQkJCSAxKTsKPiArCj4gKwlpZiAob29iX3JlcXVpcmVkKSB7Cj4gKwkJ bWFya2VyX3ZhbCA9ICoodTE2ICopKGNoaXAtPm9vYl9wb2kKPiArCQkJCSAgICAgICsgY2Ruc19j aGlwLT5iYm1fb2Zmcyk7Cj4gKwl9IGVsc2Ugewo+ICsJCS8qIFNldCBvb2IgZGF0YSB0byAweEZG LiAqLwo+ICsJCW1lbXNldChjZG5zX2N0cmwtPmJ1ZiArIG10ZC0+d3JpdGVzaXplLCAweEZGLAo+ ICsJCSAgICAgICBjZG5zX2NoaXAtPmF2YWlsX29vYl9zaXplKTsKPiArCX0KPiArCj4gKwljYWRl bmNlX25hbmRfc2V0X3NraXBfbWFya2VyX3ZhbChjZG5zX2N0cmwsIG1hcmtlcl92YWwpOwo+ICsK PiArCWNhZGVuY2VfbmFuZF9wcmVwYXJlX2RhdGFfc2l6ZShjaGlwLCBUVF9NQUlOX09PQl9BUkVB X0VYVCk7Cj4gKwo+ICsJaWYgKGNhZGVuY2VfbmFuZF9kbWFfYnVmX29rKGNkbnNfY3RybCwgYnVm LCBtdGQtPndyaXRlc2l6ZSkgJiYKPiArCSAgICBjZG5zX2N0cmwtPmNhcHMyLmRhdGFfY29udHJv bF9zdXBwKSB7Cj4gKwkJdTggKm9vYjsKPiArCj4gKwkJaWYgKG9vYl9yZXF1aXJlZCkKPiArCQkJ b29iID0gY2hpcC0+b29iX3BvaTsKPiArCQllbHNlCj4gKwkJCW9vYiA9IGNkbnNfY3RybC0+YnVm ICsgbXRkLT53cml0ZXNpemU7Cj4gKwo+ICsJCXN0YXR1cyA9IGNhZGVuY2VfbmFuZF9jZG1hX3Ry YW5zZmVyKGNkbnNfY3RybCwKPiArCQkJCQkJICAgIGNkbnNfY2hpcC0+Y3NbY2hpcC0+Y3VyX2Nz XSwKPiArCQkJCQkJICAgIHBhZ2UsICh2b2lkICopYnVmLCBvb2IsCj4gKwkJCQkJCSAgICBtdGQt PndyaXRlc2l6ZSwKPiArCQkJCQkJICAgIGNkbnNfY2hpcC0+YXZhaWxfb29iX3NpemUsCj4gKwkJ CQkJCSAgICBETUFfVE9fREVWSUNFLCB0cnVlKTsKPiArCQlpZiAoc3RhdHVzKSB7Cj4gKwkJCWRl dl9lcnIoY2Ruc19jdHJsLT5kZXYsICJ3cml0ZSBwYWdlIGZhaWxlZFxuIik7Cj4gKwkJCXJldHVy biAtRUlPOwo+ICsJCX0KPiArCj4gKwkJcmV0dXJuIDA7Cj4gKwl9Cj4gKwo+ICsJaWYgKG9vYl9y ZXF1aXJlZCkgewo+ICsJCS8qIFRyYW5zZmVyIHRoZSBkYXRhIHRvIHRoZSBvb2IgYXJlYS4gKi8K PiArCQltZW1jcHkoY2Ruc19jdHJsLT5idWYgKyBtdGQtPndyaXRlc2l6ZSwgY2hpcC0+b29iX3Bv aSwKPiArCQkgICAgICAgY2Ruc19jaGlwLT5hdmFpbF9vb2Jfc2l6ZSk7Cj4gKwl9Cj4gKwo+ICsJ bWVtY3B5KGNkbnNfY3RybC0+YnVmLCBidWYsIG10ZC0+d3JpdGVzaXplKTsKPiArCj4gKwljYWRl bmNlX25hbmRfcHJlcGFyZV9kYXRhX3NpemUoY2hpcCwgVFRfTUFJTl9PT0JfQVJFQVMpOwo+ICsK PiArCXJldHVybiBjYWRlbmNlX25hbmRfY2RtYV90cmFuc2ZlcihjZG5zX2N0cmwsCj4gKwkJCQkJ ICBjZG5zX2NoaXAtPmNzW2NoaXAtPmN1cl9jc10sCj4gKwkJCQkJICBwYWdlLCBjZG5zX2N0cmwt PmJ1ZiwgTlVMTCwKPiArCQkJCQkgIG10ZC0+d3JpdGVzaXplCj4gKwkJCQkJICArIGNkbnNfY2hp cC0+YXZhaWxfb29iX3NpemUsCj4gKwkJCQkJICAwLCBETUFfVE9fREVWSUNFLCB0cnVlKTsKPiAr fQo+ICsKPiArc3RhdGljIGludCBjYWRlbmNlX25hbmRfd3JpdGVfb29iKHN0cnVjdCBuYW5kX2No aXAgKmNoaXAsIGludCBwYWdlKQo+ICt7Cj4gKwlzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNf Y3RybCA9IHRvX2NkbnNfbmFuZF9jdHJsKGNoaXAtPmNvbnRyb2xsZXIpOwo+ICsJc3RydWN0IG10 ZF9pbmZvICptdGQgPSBuYW5kX3RvX210ZChjaGlwKTsKPiArCj4gKwltZW1zZXQoY2Ruc19jdHJs LT5idWYsIDB4RkYsIG10ZC0+d3JpdGVzaXplKTsKPiArCj4gKwlyZXR1cm4gY2FkZW5jZV9uYW5k X3dyaXRlX3BhZ2UoY2hpcCwgY2Ruc19jdHJsLT5idWYsIDEsIHBhZ2UpOwo+ICt9Cj4gKwo+ICtz dGF0aWMgaW50IGNhZGVuY2VfbmFuZF93cml0ZV9wYWdlX3JhdyhzdHJ1Y3QgbmFuZF9jaGlwICpj aGlwLAo+ICsJCQkJICAgICAgIGNvbnN0IHU4ICpidWYsIGludCBvb2JfcmVxdWlyZWQsCj4gKwkJ CQkgICAgICAgaW50IHBhZ2UpCj4gK3sKPiArCXN0cnVjdCBjZG5zX25hbmRfY3RybCAqY2Ruc19j dHJsID0gdG9fY2Ruc19uYW5kX2N0cmwoY2hpcC0+Y29udHJvbGxlcik7Cj4gKwlzdHJ1Y3QgY2Ru c19uYW5kX2NoaXAgKmNkbnNfY2hpcCA9IHRvX2NkbnNfbmFuZF9jaGlwKGNoaXApOwo+ICsJc3Ry dWN0IG10ZF9pbmZvICptdGQgPSBuYW5kX3RvX210ZChjaGlwKTsKPiArCWludCB3cml0ZXNpemUg PSBtdGQtPndyaXRlc2l6ZTsKPiArCWludCBvb2JzaXplID0gbXRkLT5vb2JzaXplOwo+ICsJaW50 IGVjY19zdGVwcyA9IGNoaXAtPmVjYy5zdGVwczsKPiArCWludCBlY2Nfc2l6ZSA9IGNoaXAtPmVj Yy5zaXplOwo+ICsJaW50IGVjY19ieXRlcyA9IGNoaXAtPmVjYy5ieXRlczsKPiArCXZvaWQgKnRt cF9idWYgPSBjZG5zX2N0cmwtPmJ1ZjsKPiArCWludCBvb2Jfc2tpcCA9IGNkbnNfY2hpcC0+YmJt X2xlbjsKPiArCXNpemVfdCBzaXplID0gd3JpdGVzaXplICsgb29ic2l6ZTsKPiArCWludCBpLCBw b3MsIGxlbjsKPiArCWludCBzdGF0dXMgPSAwOwo+ICsKPiArCXN0YXR1cyA9IGNhZGVuY2VfbmFu ZF9zZWxlY3RfdGFyZ2V0KGNoaXApOwo+ICsJaWYgKHN0YXR1cykKPiArCQlyZXR1cm4gc3RhdHVz Owo+ICsKPiArCS8qCj4gKwkgKiBGaWxsIHRoZSBidWZmZXIgd2l0aCAweGZmIGZpcnN0IGV4Y2Vw dCB0aGUgZnVsbCBwYWdlIHRyYW5zZmVyLgo+ICsJICogVGhpcyBzaW1wbGlmaWVzIHRoZSBsb2dp Yy4KPiArCSAqLwo+ICsJaWYgKCFidWYgfHwgIW9vYl9yZXF1aXJlZCkKPiArCQltZW1zZXQodG1w X2J1ZiwgMHhmZiwgc2l6ZSk7Cj4gKwo+ICsJY2FkZW5jZV9uYW5kX3NldF9za2lwX2J5dGVzX2Nv bmYoY2Ruc19jdHJsLCAwLCAwLCAwKTsKPiArCj4gKwkvKiBBcnJhbmdlIHRoZSBidWZmZXIgZm9y IHN5bmRyb21lIHBheWxvYWQvZWNjIGxheW91dC4gKi8KPiArCWlmIChidWYpIHsKPiArCQlmb3Ig KGkgPSAwOyBpIDwgZWNjX3N0ZXBzOyBpKyspIHsKPiArCQkJcG9zID0gaSAqIChlY2Nfc2l6ZSAr IGVjY19ieXRlcyk7Cj4gKwkJCWxlbiA9IGVjY19zaXplOwo+ICsKPiArCQkJaWYgKHBvcyA+PSB3 cml0ZXNpemUpCj4gKwkJCQlwb3MgKz0gb29iX3NraXA7Cj4gKwkJCWVsc2UgaWYgKHBvcyArIGxl biA+IHdyaXRlc2l6ZSkKPiArCQkJCWxlbiA9IHdyaXRlc2l6ZSAtIHBvczsKPiArCj4gKwkJCW1l bWNweSh0bXBfYnVmICsgcG9zLCBidWYsIGxlbik7Cj4gKwkJCWJ1ZiArPSBsZW47Cj4gKwkJCWlm IChsZW4gPCBlY2Nfc2l6ZSkgewo+ICsJCQkJbGVuID0gZWNjX3NpemUgLSBsZW47Cj4gKwkJCQlt ZW1jcHkodG1wX2J1ZiArIHdyaXRlc2l6ZSArIG9vYl9za2lwLCBidWYsCj4gKwkJCQkgICAgICAg bGVuKTsKPiArCQkJCWJ1ZiArPSBsZW47Cj4gKwkJCX0KPiArCQl9Cj4gKwl9Cj4gKwo+ICsJaWYg KG9vYl9yZXF1aXJlZCkgewo+ICsJCWNvbnN0IHU4ICpvb2IgPSBjaGlwLT5vb2JfcG9pOwo+ICsJ CXUzMiBvb2JfZGF0YV9vZmZzZXQgPSAoY2Ruc19jaGlwLT5zZWN0b3JfY291bnQgLSAxKSAqCj4g KwkJCShjZG5zX2NoaXAtPnNlY3Rvcl9zaXplICsgY2hpcC0+ZWNjLmJ5dGVzKQo+ICsJCQkrIGNk bnNfY2hpcC0+c2VjdG9yX3NpemUgKyBvb2Jfc2tpcDsKPiArCj4gKwkJLyogQkJNIGF0IHRoZSBi ZWdpbm5pbmcgb2YgdGhlIE9PQiBhcmVhLiAqLwo+ICsJCW1lbWNweSh0bXBfYnVmICsgd3JpdGVz aXplLCBvb2IsIG9vYl9za2lwKTsKPiArCj4gKwkJLyogT09CIGZyZWUuICovCj4gKwkJbWVtY3B5 KHRtcF9idWYgKyBvb2JfZGF0YV9vZmZzZXQsIG9vYiwKPiArCQkgICAgICAgY2Ruc19jaGlwLT5h dmFpbF9vb2Jfc2l6ZSk7Cj4gKwkJb29iICs9IGNkbnNfY2hpcC0+YXZhaWxfb29iX3NpemU7Cj4g Kwo+ICsJCS8qIE9PQiBFQ0MuICovCj4gKwkJZm9yIChpID0gMDsgaSA8IGVjY19zdGVwczsgaSsr KSB7Cj4gKwkJCXBvcyA9IGVjY19zaXplICsgaSAqIChlY2Nfc2l6ZSArIGVjY19ieXRlcyk7Cj4g KwkJCWlmIChpID09IChlY2Nfc3RlcHMgLSAxKSkKPiArCQkJCXBvcyArPSBjZG5zX2NoaXAtPmF2 YWlsX29vYl9zaXplOwo+ICsKPiArCQkJbGVuID0gZWNjX2J5dGVzOwo+ICsKPiArCQkJaWYgKHBv cyA+PSB3cml0ZXNpemUpCj4gKwkJCQlwb3MgKz0gb29iX3NraXA7Cj4gKwkJCWVsc2UgaWYgKHBv cyArIGxlbiA+IHdyaXRlc2l6ZSkKPiArCQkJCWxlbiA9IHdyaXRlc2l6ZSAtIHBvczsKPiArCj4g KwkJCW1lbWNweSh0bXBfYnVmICsgcG9zLCBvb2IsIGxlbik7Cj4gKwkJCW9vYiArPSBsZW47Cj4g KwkJCWlmIChsZW4gPCBlY2NfYnl0ZXMpIHsKPiArCQkJCWxlbiA9IGVjY19ieXRlcyAtIGxlbjsK PiArCQkJCW1lbWNweSh0bXBfYnVmICsgd3JpdGVzaXplICsgb29iX3NraXAsIG9vYiwKPiArCQkJ CSAgICAgICBsZW4pOwo+ICsJCQkJb29iICs9IGxlbjsKPiArCQkJfQo+ICsJCX0KPiArCX0KPiAr Cj4gKwljYWRlbmNlX25hbmRfcHJlcGFyZV9kYXRhX3NpemUoY2hpcCwgVFRfUkFXX1BBR0UpOwo+ ICsKPiArCXJldHVybiBjYWRlbmNlX25hbmRfY2RtYV90cmFuc2ZlcihjZG5zX2N0cmwsCj4gKwkJ CQkJICBjZG5zX2NoaXAtPmNzW2NoaXAtPmN1cl9jc10sCj4gKwkJCQkJICBwYWdlLCBjZG5zX2N0 cmwtPmJ1ZiwgTlVMTCwKPiArCQkJCQkgIG10ZC0+d3JpdGVzaXplICsKPiArCQkJCQkgIG10ZC0+ b29ic2l6ZSwKPiArCQkJCQkgIDAsIERNQV9UT19ERVZJQ0UsIGZhbHNlKTsKPiArfQo+ICsKPiAr c3RhdGljIGludCBjYWRlbmNlX25hbmRfd3JpdGVfb29iX3JhdyhzdHJ1Y3QgbmFuZF9jaGlwICpj aGlwLAo+ICsJCQkJICAgICAgaW50IHBhZ2UpCj4gK3sKPiArCXJldHVybiBjYWRlbmNlX25hbmRf d3JpdGVfcGFnZV9yYXcoY2hpcCwgTlVMTCwgdHJ1ZSwgcGFnZSk7Cj4gK30KPiArCj4gK3N0YXRp YyBpbnQgY2FkZW5jZV9uYW5kX3JlYWRfcGFnZShzdHJ1Y3QgbmFuZF9jaGlwICpjaGlwLAo+ICsJ CQkJICB1OCAqYnVmLCBpbnQgb29iX3JlcXVpcmVkLCBpbnQgcGFnZSkKPiArewo+ICsJc3RydWN0 IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwgPSB0b19jZG5zX25hbmRfY3RybChjaGlwLT5jb250 cm9sbGVyKTsKPiArCXN0cnVjdCBjZG5zX25hbmRfY2hpcCAqY2Ruc19jaGlwID0gdG9fY2Ruc19u YW5kX2NoaXAoY2hpcCk7Cj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IG5hbmRfdG9fbXRkKGNo aXApOwo+ICsJaW50IHN0YXR1cyA9IDA7Cj4gKwlpbnQgZWNjX2Vycl9jb3VudCA9IDA7Cj4gKwo+ ICsJc3RhdHVzID0gY2FkZW5jZV9uYW5kX3NlbGVjdF90YXJnZXQoY2hpcCk7Cj4gKwlpZiAoc3Rh dHVzKQo+ICsJCXJldHVybiBzdGF0dXM7Cj4gKwo+ICsJY2FkZW5jZV9uYW5kX3NldF9za2lwX2J5 dGVzX2NvbmYoY2Ruc19jdHJsLCBjZG5zX2NoaXAtPmJibV9sZW4sCj4gKwkJCQkJIG10ZC0+d3Jp dGVzaXplCj4gKwkJCQkJICsgY2Ruc19jaGlwLT5iYm1fb2ZmcywgMSk7Cj4gKwo+ICsJLyoKPiAr CSAqIElmIGRhdGEgYnVmZmVyIGNhbiBiZSBhY2Nlc3NlZCBieSBETUEgYW5kIGRhdGFfY29udHJv bCBmZWF0dXJlCj4gKwkgKiBpcyBzdXBwb3J0ZWQgdGhlbiB0cmFuc2ZlciBkYXRhIGFuZCBvb2Ig ZGlyZWN0bHkuCj4gKwkgKi8KPiArCWlmIChjYWRlbmNlX25hbmRfZG1hX2J1Zl9vayhjZG5zX2N0 cmwsIGJ1ZiwgbXRkLT53cml0ZXNpemUpICYmCj4gKwkgICAgY2Ruc19jdHJsLT5jYXBzMi5kYXRh X2NvbnRyb2xfc3VwcCkgewo+ICsJCXU4ICpvb2I7Cj4gKwo+ICsJCWlmIChvb2JfcmVxdWlyZWQp Cj4gKwkJCW9vYiA9IGNoaXAtPm9vYl9wb2k7Cj4gKwkJZWxzZQo+ICsJCQlvb2IgPSBjZG5zX2N0 cmwtPmJ1ZiArIG10ZC0+d3JpdGVzaXplOwo+ICsKPiArCQljYWRlbmNlX25hbmRfcHJlcGFyZV9k YXRhX3NpemUoY2hpcCwgVFRfTUFJTl9PT0JfQVJFQV9FWFQpOwo+ICsJCXN0YXR1cyA9IGNhZGVu Y2VfbmFuZF9jZG1hX3RyYW5zZmVyKGNkbnNfY3RybCwKPiArCQkJCQkJICAgIGNkbnNfY2hpcC0+ Y3NbY2hpcC0+Y3VyX2NzXSwKPiArCQkJCQkJICAgIHBhZ2UsIGJ1Ziwgb29iLAo+ICsJCQkJCQkg ICAgbXRkLT53cml0ZXNpemUsCj4gKwkJCQkJCSAgICBjZG5zX2NoaXAtPmF2YWlsX29vYl9zaXpl LAo+ICsJCQkJCQkgICAgRE1BX0ZST01fREVWSUNFLCB0cnVlKTsKPiArCS8qIE90aGVyd2lzZSB1 c2UgYm91bmNlIGJ1ZmZlci4gKi8KPiArCX0gZWxzZSB7Cj4gKwkJY2FkZW5jZV9uYW5kX3ByZXBh cmVfZGF0YV9zaXplKGNoaXAsIFRUX01BSU5fT09CX0FSRUFTKTsKPiArCQlzdGF0dXMgPSBjYWRl bmNlX25hbmRfY2RtYV90cmFuc2ZlcihjZG5zX2N0cmwsCj4gKwkJCQkJCSAgICBjZG5zX2NoaXAt PmNzW2NoaXAtPmN1cl9jc10sCj4gKwkJCQkJCSAgICBwYWdlLCBjZG5zX2N0cmwtPmJ1ZiwKPiAr CQkJCQkJICAgIE5VTEwsIG10ZC0+d3JpdGVzaXplCj4gKwkJCQkJCSAgICArIGNkbnNfY2hpcC0+ YXZhaWxfb29iX3NpemUsCj4gKwkJCQkJCSAgICAwLCBETUFfRlJPTV9ERVZJQ0UsIHRydWUpOwo+ ICsKPiArCQltZW1jcHkoYnVmLCBjZG5zX2N0cmwtPmJ1ZiwgbXRkLT53cml0ZXNpemUpOwo+ICsJ CWlmIChvb2JfcmVxdWlyZWQpCj4gKwkJCW1lbWNweShjaGlwLT5vb2JfcG9pLAo+ICsJCQkgICAg ICAgY2Ruc19jdHJsLT5idWYgKyBtdGQtPndyaXRlc2l6ZSwKPiArCQkJICAgICAgIG10ZC0+b29i c2l6ZSk7Cj4gKwl9Cj4gKwo+ICsJc3dpdGNoIChzdGF0dXMpIHsKPiArCWNhc2UgU1RBVF9FQ0Nf VU5DT1JSOgo+ICsJCW10ZC0+ZWNjX3N0YXRzLmZhaWxlZCsrOwo+ICsJCWVjY19lcnJfY291bnQr KzsKPiArCQlicmVhazsKPiArCWNhc2UgU1RBVF9FQ0NfQ09SUjoKPiArCQllY2NfZXJyX2NvdW50 ID0gRklFTERfR0VUKENETUFfQ1NfTUFYRVJSLAo+ICsJCQkJCSAgY2Ruc19jdHJsLT5jZG1hX2Rl c2MtPnN0YXR1cyk7Cj4gKwkJbXRkLT5lY2Nfc3RhdHMuY29ycmVjdGVkICs9IGVjY19lcnJfY291 bnQ7CgpJcyB0aGlzIHZhbHVlIHRoZSBtYXhpbXVtIG51bWJlciBvZiBiaXRmbGlwcyBpbiBlYWNo IGNodW5rIG9mIHRoZSBwYWdlPwpJZiBpdCByZXR1cm5zIHRoZSB0b3RhbCBudW1iZXIgb2YgYml0 ZmxpcHMgY29ycmVjdGVkIGluIHRoZSBlbnRpcmUgcGFnZQp3ZSBoYXZlIGEgcHJvYmxlbS4KCj4g KwkJYnJlYWs7Cj4gKwljYXNlIFNUQVRfRVJBU0VEOgo+ICsJY2FzZSBTVEFUX09LOgo+ICsJCWJy ZWFrOwo+ICsJZGVmYXVsdDoKPiArCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LCAicmVhZCBwYWdl IGZhaWxlZFxuIik7Cj4gKwkJcmV0dXJuIC1FSU87Cj4gKwl9Cj4gKwo+ICsJaWYgKG9vYl9yZXF1 aXJlZCkKPiArCQlpZiAoY2FkZW5jZV9uYW5kX3JlYWRfYmJtKGNoaXAsIHBhZ2UsIGNoaXAtPm9v Yl9wb2kpKQo+ICsJCQlyZXR1cm4gLUVJTzsKCkRvIHdlIHJlYWxseSBjYXJlIGFib3V0IHRoZSBC Qk0gYXQgdGhpcyBsZXZlbD8gSWYgd2UgYXJlIHJlcXVlc3RlZCB0bwpyZWFkIHRoZSBwYWdlLCBJ IHN1cHBvc2Ugd2UgbXVzdCBkbyB3aGF0IGlzIGluIG91ciBoYW5kcyB0byByZXR1cm4gdGhlCmRh dGE/IE5vcm1hbGx5IHRoaXMgaXMgaGFuZGxlZCBpbiB1c2Vyc3BhY2UgZGlyZWN0bHkuCgo+ICsK PiArCXJldHVybiBlY2NfZXJyX2NvdW50Owo+ICt9Cj4gKwo+ICsvKiBSZWFkcyBPT0IgZGF0YSBm cm9tIHRoZSBkZXZpY2UuICovCj4gK3N0YXRpYyBpbnQgY2FkZW5jZV9uYW5kX3JlYWRfb29iKHN0 cnVjdCBuYW5kX2NoaXAgKmNoaXAsIGludCBwYWdlKQo+ICt7Cj4gKwlzdHJ1Y3QgY2Ruc19uYW5k X2N0cmwgKmNkbnNfY3RybCA9IHRvX2NkbnNfbmFuZF9jdHJsKGNoaXAtPmNvbnRyb2xsZXIpOwo+ ICsKPiArCXJldHVybiBjYWRlbmNlX25hbmRfcmVhZF9wYWdlKGNoaXAsIGNkbnNfY3RybC0+YnVm LCAxLCBwYWdlKTsKPiArfQo+ICsKPiArc3RhdGljIGludCBjYWRlbmNlX25hbmRfcmVhZF9wYWdl X3JhdyhzdHJ1Y3QgbmFuZF9jaGlwICpjaGlwLAo+ICsJCQkJICAgICAgdTggKmJ1ZiwgaW50IG9v Yl9yZXF1aXJlZCwgaW50IHBhZ2UpCj4gK3sKPiArCXN0cnVjdCBjZG5zX25hbmRfY3RybCAqY2Ru c19jdHJsID0gdG9fY2Ruc19uYW5kX2N0cmwoY2hpcC0+Y29udHJvbGxlcik7Cj4gKwlzdHJ1Y3Qg Y2Ruc19uYW5kX2NoaXAgKmNkbnNfY2hpcCA9IHRvX2NkbnNfbmFuZF9jaGlwKGNoaXApOwo+ICsJ c3RydWN0IG10ZF9pbmZvICptdGQgPSBuYW5kX3RvX210ZChjaGlwKTsKPiArCWludCBvb2Jfc2tp cCA9IGNkbnNfY2hpcC0+YmJtX2xlbjsKPiArCWludCB3cml0ZXNpemUgPSBtdGQtPndyaXRlc2l6 ZTsKPiArCWludCBlY2Nfc3RlcHMgPSBjaGlwLT5lY2Muc3RlcHM7Cj4gKwlpbnQgZWNjX3NpemUg PSBjaGlwLT5lY2Muc2l6ZTsKPiArCWludCBlY2NfYnl0ZXMgPSBjaGlwLT5lY2MuYnl0ZXM7Cj4g Kwl2b2lkICp0bXBfYnVmID0gY2Ruc19jdHJsLT5idWY7Cj4gKwlpbnQgaSwgcG9zLCBsZW47Cj4g KwlpbnQgc3RhdHVzID0gMDsKPiArCj4gKwlzdGF0dXMgPSBjYWRlbmNlX25hbmRfc2VsZWN0X3Rh cmdldChjaGlwKTsKPiArCWlmIChzdGF0dXMpCj4gKwkJcmV0dXJuIHN0YXR1czsKPiArCj4gKwlj YWRlbmNlX25hbmRfc2V0X3NraXBfYnl0ZXNfY29uZihjZG5zX2N0cmwsIDAsIDAsIDApOwo+ICsK PiArCWNhZGVuY2VfbmFuZF9wcmVwYXJlX2RhdGFfc2l6ZShjaGlwLCBUVF9SQVdfUEFHRSk7Cj4g KwlzdGF0dXMgPSBjYWRlbmNlX25hbmRfY2RtYV90cmFuc2ZlcihjZG5zX2N0cmwsCj4gKwkJCQkJ ICAgIGNkbnNfY2hpcC0+Y3NbY2hpcC0+Y3VyX2NzXSwKPiArCQkJCQkgICAgcGFnZSwgY2Ruc19j dHJsLT5idWYsIE5VTEwsCj4gKwkJCQkJICAgIG10ZC0+d3JpdGVzaXplCj4gKwkJCQkJICAgICsg bXRkLT5vb2JzaXplLAo+ICsJCQkJCSAgICAwLCBETUFfRlJPTV9ERVZJQ0UsIGZhbHNlKTsKPiAr Cj4gKwlzd2l0Y2ggKHN0YXR1cykgewo+ICsJY2FzZSBTVEFUX0VSQVNFRDoKPiArCWNhc2UgU1RB VF9PSzoKPiArCQlicmVhazsKPiArCWRlZmF1bHQ6Cj4gKwkJZGV2X2VycihjZG5zX2N0cmwtPmRl diwgInJlYWQgcmF3IHBhZ2UgZmFpbGVkXG4iKTsKPiArCQlyZXR1cm4gLUVJTzsKPiArCX0KPiAr Cj4gKwkvKiBBcnJhbmdlIHRoZSBidWZmZXIgZm9yIHN5bmRyb21lIHBheWxvYWQvZWNjIGxheW91 dC4gKi8KPiArCWlmIChidWYpIHsKPiArCQlmb3IgKGkgPSAwOyBpIDwgZWNjX3N0ZXBzOyBpKysp IHsKPiArCQkJcG9zID0gaSAqIChlY2Nfc2l6ZSArIGVjY19ieXRlcyk7Cj4gKwkJCWxlbiA9IGVj Y19zaXplOwo+ICsKPiArCQkJaWYgKHBvcyA+PSB3cml0ZXNpemUpCj4gKwkJCQlwb3MgKz0gb29i X3NraXA7Cj4gKwkJCWVsc2UgaWYgKHBvcyArIGxlbiA+IHdyaXRlc2l6ZSkKPiArCQkJCWxlbiA9 IHdyaXRlc2l6ZSAtIHBvczsKPiArCj4gKwkJCW1lbWNweShidWYsIHRtcF9idWYgKyBwb3MsIGxl bik7Cj4gKwkJCWJ1ZiArPSBsZW47Cj4gKwkJCWlmIChsZW4gPCBlY2Nfc2l6ZSkgewo+ICsJCQkJ bGVuID0gZWNjX3NpemUgLSBsZW47Cj4gKwkJCQltZW1jcHkoYnVmLCB0bXBfYnVmICsgd3JpdGVz aXplICsgb29iX3NraXAsCj4gKwkJCQkgICAgICAgbGVuKTsKPiArCQkJCWJ1ZiArPSBsZW47Cj4g KwkJCX0KPiArCQl9Cj4gKwl9Cj4gKwo+ICsJaWYgKG9vYl9yZXF1aXJlZCkgewo+ICsJCXU4ICpv b2IgPSBjaGlwLT5vb2JfcG9pOwo+ICsJCXUzMiBvb2JfZGF0YV9vZmZzZXQgPSAoY2Ruc19jaGlw LT5zZWN0b3JfY291bnQgLSAxKSAqCj4gKwkJCShjZG5zX2NoaXAtPnNlY3Rvcl9zaXplICsgY2hp cC0+ZWNjLmJ5dGVzKQo+ICsJCQkrIGNkbnNfY2hpcC0+c2VjdG9yX3NpemUgKyBvb2Jfc2tpcDsK PiArCj4gKwkJLyogT09CIGZyZWUuICovCj4gKwkJbWVtY3B5KG9vYiwgdG1wX2J1ZiArIG9vYl9k YXRhX29mZnNldCwKPiArCQkgICAgICAgY2Ruc19jaGlwLT5hdmFpbF9vb2Jfc2l6ZSk7Cj4gKwo+ ICsJCS8qIEJCTSBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBPT0IgYXJlYS4gKi8KPiArCQltZW1j cHkob29iLCB0bXBfYnVmICsgd3JpdGVzaXplLCBvb2Jfc2tpcCk7Cj4gKwo+ICsJCW9vYiArPSBj ZG5zX2NoaXAtPmF2YWlsX29vYl9zaXplOwo+ICsKPiArCQkvKiBPT0IgRUNDICovCj4gKwkJZm9y IChpID0gMDsgaSA8IGVjY19zdGVwczsgaSsrKSB7Cj4gKwkJCXBvcyA9IGVjY19zaXplICsgaSAq IChlY2Nfc2l6ZSArIGVjY19ieXRlcyk7Cj4gKwkJCWxlbiA9IGVjY19ieXRlczsKPiArCj4gKwkJ CWlmIChpID09IChlY2Nfc3RlcHMgLSAxKSkKPiArCQkJCXBvcyArPSBjZG5zX2NoaXAtPmF2YWls X29vYl9zaXplOwo+ICsKPiArCQkJaWYgKHBvcyA+PSB3cml0ZXNpemUpCj4gKwkJCQlwb3MgKz0g b29iX3NraXA7Cj4gKwkJCWVsc2UgaWYgKHBvcyArIGxlbiA+IHdyaXRlc2l6ZSkKPiArCQkJCWxl biA9IHdyaXRlc2l6ZSAtIHBvczsKPiArCj4gKwkJCW1lbWNweShvb2IsIHRtcF9idWYgKyBwb3Ms IGxlbik7Cj4gKwkJCW9vYiArPSBsZW47Cj4gKwkJCWlmIChsZW4gPCBlY2NfYnl0ZXMpIHsKPiAr CQkJCWxlbiA9IGVjY19ieXRlcyAtIGxlbjsKPiArCQkJCW1lbWNweShvb2IsIHRtcF9idWYgKyB3 cml0ZXNpemUgKyBvb2Jfc2tpcCwKPiArCQkJCSAgICAgICBsZW4pOwo+ICsJCQkJb29iICs9IGxl bjsKPiArCQkJfQo+ICsJCX0KPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3Rh dGljIGludCBjYWRlbmNlX25hbmRfcmVhZF9vb2JfcmF3KHN0cnVjdCBuYW5kX2NoaXAgKmNoaXAs Cj4gKwkJCQkgICAgIGludCBwYWdlKQo+ICt7Cj4gKwlyZXR1cm4gY2FkZW5jZV9uYW5kX3JlYWRf cGFnZV9yYXcoY2hpcCwgTlVMTCwgdHJ1ZSwgcGFnZSk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lk IGNhZGVuY2VfbmFuZF9zbGF2ZV9kbWFfdHJhbnNmZXJfZmluaXNoZWQodm9pZCAqZGF0YSkKPiAr ewo+ICsJc3RydWN0IGNvbXBsZXRpb24gKmZpbmlzaGVkID0gZGF0YTsKPiArCj4gKwljb21wbGV0 ZShmaW5pc2hlZCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgY2FkZW5jZV9uYW5kX3NsYXZlX2Rt YV90cmFuc2ZlcihzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3RybCwKPiArCQkJCQkgICB2 b2lkICpidWYsCj4gKwkJCQkJICAgZG1hX2FkZHJfdCBkZXZfZG1hLCBzaXplX3QgbGVuLAo+ICsJ CQkJCSAgIGVudW0gZG1hX2RhdGFfZGlyZWN0aW9uIGRpcikKPiArewo+ICsJREVDTEFSRV9DT01Q TEVUSU9OX09OU1RBQ0soZmluaXNoZWQpOwo+ICsJc3RydWN0IGRtYV9jaGFuICpjaGFuOwo+ICsJ c3RydWN0IGRtYV9kZXZpY2UgKmRtYV9kZXY7Cj4gKwlkbWFfYWRkcl90IHNyY19kbWEsIGRzdF9k bWEsIGJ1Zl9kbWE7Cj4gKwlzdHJ1Y3QgZG1hX2FzeW5jX3R4X2Rlc2NyaXB0b3IgKnR4Owo+ICsJ ZG1hX2Nvb2tpZV90IGNvb2tpZTsKPiArCj4gKwljaGFuID0gY2Ruc19jdHJsLT5kbWFjOwo+ICsJ ZG1hX2RldiA9IGNoYW4tPmRldmljZTsKPiArCj4gKwlidWZfZG1hID0gZG1hX21hcF9zaW5nbGUo ZG1hX2Rldi0+ZGV2LCBidWYsIGxlbiwgZGlyKTsKPiArCWlmIChkbWFfbWFwcGluZ19lcnJvcihk bWFfZGV2LT5kZXYsIGJ1Zl9kbWEpKSB7Cj4gKwkJZGV2X2VycihjZG5zX2N0cmwtPmRldiwgIkZh aWxlZCB0byBtYXAgRE1BIGJ1ZmZlclxuIik7Cj4gKwkJZ290byBlcnI7Cj4gKwl9Cj4gKwo+ICsJ aWYgKGRpciA9PSBETUFfRlJPTV9ERVZJQ0UpIHsKPiArCQlzcmNfZG1hID0gY2Ruc19jdHJsLT5p by5kbWE7Cj4gKwkJZHN0X2RtYSA9IGJ1Zl9kbWE7Cj4gKwl9IGVsc2Ugewo+ICsJCXNyY19kbWEg PSBidWZfZG1hOwo+ICsJCWRzdF9kbWEgPSBjZG5zX2N0cmwtPmlvLmRtYTsKPiArCX0KPiArCj4g Kwl0eCA9IGRtYWVuZ2luZV9wcmVwX2RtYV9tZW1jcHkoY2Ruc19jdHJsLT5kbWFjLCBkc3RfZG1h LCBzcmNfZG1hLCBsZW4sCj4gKwkJCQkgICAgICAgRE1BX0NUUkxfQUNLIHwgRE1BX1BSRVBfSU5U RVJSVVBUKTsKPiArCWlmICghdHgpIHsKPiArCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LCAiRmFp bGVkIHRvIHByZXBhcmUgRE1BIG1lbWNweVxuIik7Cj4gKwkJZ290byBlcnJfdW5tYXA7Cj4gKwl9 Cj4gKwo+ICsJdHgtPmNhbGxiYWNrID0gY2FkZW5jZV9uYW5kX3NsYXZlX2RtYV90cmFuc2Zlcl9m aW5pc2hlZDsKPiArCXR4LT5jYWxsYmFja19wYXJhbSA9ICZmaW5pc2hlZDsKPiArCj4gKwljb29r aWUgPSBkbWFlbmdpbmVfc3VibWl0KHR4KTsKPiArCWlmIChkbWFfc3VibWl0X2Vycm9yKGNvb2tp ZSkpIHsKPiArCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LCAiRmFpbGVkIHRvIGRvIERNQSB0eF9z dWJtaXRcbiIpOwo+ICsJCWdvdG8gZXJyX3VubWFwOwo+ICsJfQo+ICsKPiArCWRtYV9hc3luY19p c3N1ZV9wZW5kaW5nKGNkbnNfY3RybC0+ZG1hYyk7Cj4gKwl3YWl0X2Zvcl9jb21wbGV0aW9uKCZm aW5pc2hlZCk7Cj4gKwo+ICsJZG1hX3VubWFwX3NpbmdsZShjZG5zX2N0cmwtPmRldiwgYnVmX2Rt YSwgbGVuLCBkaXIpOwo+ICsKPiArCXJldHVybiAwOwo+ICsKPiArZXJyX3VubWFwOgo+ICsJZG1h X3VubWFwX3NpbmdsZShjZG5zX2N0cmwtPmRldiwgYnVmX2RtYSwgbGVuLCBkaXIpOwo+ICsKPiAr ZXJyOgo+ICsJZGV2X2RiZyhjZG5zX2N0cmwtPmRldiwgIkZhbGwgYmFjayB0byBDUFUgSS9PXG4i KTsKPiArCj4gKwlyZXR1cm4gLUVJTzsKPiArfQo+ICsKPiArc3RhdGljIGludCBjYWRlbmNlX25h bmRfcmVhZF9idWYoc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwsCj4gKwkJCQkgdTgg KmJ1ZiwgaW50IGxlbikKPiArewo+ICsJaW50IGxlbl9hbGlnbmVkID0gQUxJR04obGVuLCBjZG5z X2N0cmwtPmNhcHMyLmRhdGFfZG1hX3dpZHRoKTsKPiArCXU4IHRocmVhZF9uciA9IDA7Cj4gKwl1 MzIgc2RtYV9zaXplOwo+ICsJaW50IHN0YXR1czsKPiArCj4gKwlpZiAoIWNkbnNfY3RybC0+Y2Fw czEtPmhhc19kbWEpIHsKPiArCQlpZiAobGVuICYgMykgewo+ICsJCQlkZXZfZXJyKGNkbnNfY3Ry bC0+ZGV2LCAidW5hbGlnbmVkIGRhdGFcbiIpOwo+ICsJCQlyZXR1cm4gLUVJTzsKPiArCQl9Cj4g KwkJcmVhZHNsKGNkbnNfY3RybC0+aW8udmlydCwgYnVmLCBsZW4gLyA0KTsKPiArCQlyZXR1cm4g MDsKPiArCX0KPiArCj4gKwkvKiBXYWl0IHVudGlsIHNsYXZlIERNQSBpbnRlcmZhY2UgaXMgcmVh ZHkgdG8gZGF0YSB0cmFuc2Zlci4gKi8KPiArCXN0YXR1cyA9IGNhZGVuY2VfbmFuZF93YWl0X29u X3NkbWEoY2Ruc19jdHJsLCAmdGhyZWFkX25yLCAmc2RtYV9zaXplKTsKPiArCWlmIChzdGF0dXMp Cj4gKwkJcmV0dXJuIHN0YXR1czsKPiArCj4gKwlpZiAoc2RtYV9zaXplICE9IGxlbl9hbGlnbmVk KSB7Cj4gKwkJZGV2X2VycihjZG5zX2N0cmwtPmRldiwgInVuZXhwZWN0ZWQgc2NlbmFyaW9cbiIp Owo+ICsJCXJldHVybiAtRUlPOwo+ICsJfQo+ICsKPiArCWlmIChjZG5zX2N0cmwtPmRtYWMgJiYg Y2FkZW5jZV9uYW5kX2RtYV9idWZfb2soY2Ruc19jdHJsLCBidWYsIGxlbikpIHsKPiArCQlzdGF0 dXMgPSBjYWRlbmNlX25hbmRfc2xhdmVfZG1hX3RyYW5zZmVyKGNkbnNfY3RybCwgYnVmLAo+ICsJ CQkJCQkJIGNkbnNfY3RybC0+aW8uZG1hLAo+ICsJCQkJCQkJIGxlbiwgRE1BX0ZST01fREVWSUNF KTsKPiArCQlpZiAoc3RhdHVzID09IDApCj4gKwkJCXJldHVybiAwOwo+ICsKPiArCQlkZXZfd2Fy bihjZG5zX2N0cmwtPmRldiwKPiArCQkJICJTbGF2ZSBETUEgdHJhbnNmZXIgZmFpbGVkLiBUcnkg YWdhaW4gdXNpbmcgYm91bmNlIGJ1ZmZlci4iKTsKPiArCX0KPiArCj4gKwkvKiBJZiBETUEgdHJh bnNmZXIgaXMgbm90IHBvc3NpYmxlIG9yIGZhaWxlZCB0aGVuIHVzZSBib3VuY2UgYnVmZmVyLiAq Lwo+ICsJc3RhdHVzID0gY2FkZW5jZV9uYW5kX3NsYXZlX2RtYV90cmFuc2ZlcihjZG5zX2N0cmws IGNkbnNfY3RybC0+YnVmLAo+ICsJCQkJCQkgY2Ruc19jdHJsLT5pby5kbWEsCj4gKwkJCQkJCSBs ZW5fYWxpZ25lZCwgRE1BX0ZST01fREVWSUNFKTsKPiArCj4gKwlpZiAoc3RhdHVzKSB7Cj4gKwkJ ZGV2X2VycihjZG5zX2N0cmwtPmRldiwgIlNsYXZlIERNQSB0cmFuc2ZlciBmYWlsZWQiKTsKPiAr CQlyZXR1cm4gc3RhdHVzOwo+ICsJfQo+ICsKPiArCW1lbWNweShidWYsIGNkbnNfY3RybC0+YnVm LCBsZW4pOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGNhZGVuY2Vf bmFuZF93cml0ZV9idWYoc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwsCj4gKwkJCQkg IGNvbnN0IHU4ICpidWYsIGludCBsZW4pCj4gK3sKPiArCXU4IHRocmVhZF9uciA9IDA7Cj4gKwl1 MzIgc2RtYV9zaXplOwo+ICsJaW50IHN0YXR1czsKPiArCWludCBsZW5fYWxpZ25lZCA9IEFMSUdO KGxlbiwgY2Ruc19jdHJsLT5jYXBzMi5kYXRhX2RtYV93aWR0aCk7Cj4gKwo+ICsJaWYgKCFjZG5z X2N0cmwtPmNhcHMxLT5oYXNfZG1hKSB7Cj4gKwkJaWYgKGxlbiAmIDMpIHsKPiArCQkJZGV2X2Vy cihjZG5zX2N0cmwtPmRldiwgInVuYWxpZ25lZCBkYXRhXG4iKTsKPiArCQkJcmV0dXJuIC1FSU87 Cj4gKwkJfQo+ICsJCXdyaXRlc2woY2Ruc19jdHJsLT5pby52aXJ0LCBidWYsIGxlbiAvIDQpOwo+ ICsJCXJldHVybiAwOwo+ICsJfQo+ICsKPiArCS8qIFdhaXQgdW50aWwgc2xhdmUgRE1BIGludGVy ZmFjZSBpcyByZWFkeSB0byBkYXRhIHRyYW5zZmVyLiAqLwo+ICsJc3RhdHVzID0gY2FkZW5jZV9u YW5kX3dhaXRfb25fc2RtYShjZG5zX2N0cmwsICZ0aHJlYWRfbnIsICZzZG1hX3NpemUpOwo+ICsJ aWYgKHN0YXR1cykKPiArCQlyZXR1cm4gc3RhdHVzOwo+ICsKPiArCWlmIChzZG1hX3NpemUgIT0g bGVuX2FsaWduZWQpIHsKPiArCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LCAiRXJyb3IgdW5leHBl Y3RlZCBzY2VuYXJpb1xuIik7Cj4gKwkJcmV0dXJuIC1FSU87Cj4gKwl9Cj4gKwo+ICsJaWYgKGNk bnNfY3RybC0+ZG1hYyAmJiBjYWRlbmNlX25hbmRfZG1hX2J1Zl9vayhjZG5zX2N0cmwsIGJ1Ziwg bGVuKSkgewo+ICsJCXN0YXR1cyA9IGNhZGVuY2VfbmFuZF9zbGF2ZV9kbWFfdHJhbnNmZXIoY2Ru c19jdHJsLCAodm9pZCAqKWJ1ZiwKPiArCQkJCQkJCSBjZG5zX2N0cmwtPmlvLmRtYSwKPiArCQkJ CQkJCSBsZW4sIERNQV9UT19ERVZJQ0UpOwo+ICsJCWlmIChzdGF0dXMgPT0gMCkKPiArCQkJcmV0 dXJuIDA7Cj4gKwo+ICsJCWRldl93YXJuKGNkbnNfY3RybC0+ZGV2LAo+ICsJCQkgIlNsYXZlIERN QSB0cmFuc2ZlciBmYWlsZWQuIFRyeSBhZ2FpbiB1c2luZyBib3VuY2UgYnVmZmVyLiIpOwo+ICsJ fQo+ICsKPiArCS8qIElmIERNQSB0cmFuc2ZlciBpcyBub3QgcG9zc2libGUgb3IgZmFpbGVkIHRo ZW4gdXNlIGJvdW5jZSBidWZmZXIuICovCj4gKwltZW1jcHkoY2Ruc19jdHJsLT5idWYsIGJ1Ziwg bGVuKTsKPiArCj4gKwlzdGF0dXMgPSBjYWRlbmNlX25hbmRfc2xhdmVfZG1hX3RyYW5zZmVyKGNk bnNfY3RybCwgY2Ruc19jdHJsLT5idWYsCj4gKwkJCQkJCSBjZG5zX2N0cmwtPmlvLmRtYSwKPiAr CQkJCQkJIGxlbl9hbGlnbmVkLCBETUFfVE9fREVWSUNFKTsKPiArCj4gKwlpZiAoc3RhdHVzKQo+ ICsJCWRldl9lcnIoY2Ruc19jdHJsLT5kZXYsICJTbGF2ZSBETUEgdHJhbnNmZXIgZmFpbGVkIik7 Cj4gKwo+ICsJcmV0dXJuIHN0YXR1czsKPiArfQo+ICsKPiArc3RhdGljIGludCBjYWRlbmNlX25h bmRfZm9yY2VfYnl0ZV9hY2Nlc3Moc3RydWN0IG5hbmRfY2hpcCAqY2hpcCwKPiArCQkJCQkgIGJv b2wgZm9yY2VfOGJpdCkKPiArewo+ICsJc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwg PSB0b19jZG5zX25hbmRfY3RybChjaGlwLT5jb250cm9sbGVyKTsKPiArCWludCBzdGF0dXM7Cj4g Kwo+ICsJLyoKPiArCSAqIENhbGxlcnMgb2YgdGhpcyBmdW5jdGlvbiBkbyBub3QgdmVyaWZ5IGlm IHRoZSBOQU5EIGlzIHVzaW5nIGEgMTYtYml0Cj4gKwkgKiBhbiA4LWJpdCBidXMgZm9yIG5vcm1h bCBvcGVyYXRpb25zLCBzbyB3ZSBuZWVkIHRvIHRha2UgY2FyZSBvZiB0aGF0Cj4gKwkgKiBoZXJl IGJ5IGxlYXZpbmcgdGhlIGNvbmZpZ3VyYXRpb24gdW5jaGFuZ2VkIGlmIHRoZSBOQU5EIGRvZXMg bm90IGhhdmUKPiArCSAqIHRoZSBOQU5EX0JVU1dJRFRIXzE2IGZsYWcgc2V0Lgo+ICsJICovCj4g KwlpZiAoIShjaGlwLT5vcHRpb25zICYgTkFORF9CVVNXSURUSF8xNikpCj4gKwkJcmV0dXJuIDA7 Cj4gKwo+ICsJc3RhdHVzID0gY2FkZW5jZV9uYW5kX3NldF9hY2Nlc3Nfd2lkdGgxNihjZG5zX2N0 cmwsICFmb3JjZV84Yml0KTsKPiArCj4gKwlyZXR1cm4gc3RhdHVzOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgaW50IGNhZGVuY2VfbmFuZF9jbWRfb3Bjb2RlKHN0cnVjdCBuYW5kX2NoaXAgKmNoaXAsCj4g KwkJCQkgICBjb25zdCBzdHJ1Y3QgbmFuZF9zdWJvcCAqc3Vib3ApCj4gK3sKPiArCXN0cnVjdCBj ZG5zX25hbmRfY3RybCAqY2Ruc19jdHJsID0gdG9fY2Ruc19uYW5kX2N0cmwoY2hpcC0+Y29udHJv bGxlcik7Cj4gKwlzdHJ1Y3QgY2Ruc19uYW5kX2NoaXAgKmNkbnNfY2hpcCA9IHRvX2NkbnNfbmFu ZF9jaGlwKGNoaXApOwo+ICsJY29uc3Qgc3RydWN0IG5hbmRfb3BfaW5zdHIgKmluc3RyOwo+ICsJ dW5zaWduZWQgaW50IG9wX2lkID0gMDsKPiArCXU2NCBtaW5pX2N0cmxfY21kID0gMDsKPiArCWlu dCByZXQ7Cj4gKwo+ICsJaW5zdHIgPSAmc3Vib3AtPmluc3Ryc1tvcF9pZF07Cj4gKwo+ICsJaWYg KGluc3RyLT5kZWxheV9ucyA+IDApCj4gKwkJbWluaV9jdHJsX2NtZCB8PSBHQ01EX0xBWV9UV0I7 Cj4gKwo+ICsJbWluaV9jdHJsX2NtZCB8PSBGSUVMRF9QUkVQKEdDTURfTEFZX0lOU1RSLAo+ICsJ CQkJICAgIEdDTURfTEFZX0lOU1RSX0NNRCk7Cj4gKwltaW5pX2N0cmxfY21kIHw9IEZJRUxEX1BS RVAoR0NNRF9MQVlfSU5QVVRfQ01ELAo+ICsJCQkJICAgIGluc3RyLT5jdHguY21kLm9wY29kZSk7 Cj4gKwo+ICsJcmV0ID0gY2FkZW5jZV9uYW5kX2dlbmVyaWNfY21kX3NlbmQoY2Ruc19jdHJsLAo+ ICsJCQkJCSAgICBjZG5zX2NoaXAtPmNzW2NoaXAtPmN1cl9jc10sCj4gKwkJCQkJICAgIG1pbmlf Y3RybF9jbWQpOwo+ICsJaWYgKHJldCkKPiArCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LCAic2Vu ZCBjbWQgJXggZmFpbGVkXG4iLAo+ICsJCQlpbnN0ci0+Y3R4LmNtZC5vcGNvZGUpOwo+ICsKPiAr CXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgY2FkZW5jZV9uYW5kX2NtZF9hZGRy ZXNzKHN0cnVjdCBuYW5kX2NoaXAgKmNoaXAsCj4gKwkJCQkgICAgY29uc3Qgc3RydWN0IG5hbmRf c3Vib3AgKnN1Ym9wKQo+ICt7Cj4gKwlzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3RybCA9 IHRvX2NkbnNfbmFuZF9jdHJsKGNoaXAtPmNvbnRyb2xsZXIpOwo+ICsJc3RydWN0IGNkbnNfbmFu ZF9jaGlwICpjZG5zX2NoaXAgPSB0b19jZG5zX25hbmRfY2hpcChjaGlwKTsKPiArCWNvbnN0IHN0 cnVjdCBuYW5kX29wX2luc3RyICppbnN0cjsKPiArCXVuc2lnbmVkIGludCBvcF9pZCA9IDA7Cj4g Kwl1NjQgbWluaV9jdHJsX2NtZCA9IDA7Cj4gKwl1bnNpZ25lZCBpbnQgb2Zmc2V0LCBuYWRkcnM7 Cj4gKwl1NjQgYWRkcmVzcyA9IDA7Cj4gKwljb25zdCB1OCAqYWRkcnM7Cj4gKwlpbnQgcmV0Owo+ ICsJaW50IGk7Cj4gKwo+ICsJaW5zdHIgPSAmc3Vib3AtPmluc3Ryc1tvcF9pZF07Cj4gKwo+ICsJ aWYgKGluc3RyLT5kZWxheV9ucyA+IDApCj4gKwkJbWluaV9jdHJsX2NtZCB8PSBHQ01EX0xBWV9U V0I7Cj4gKwo+ICsJbWluaV9jdHJsX2NtZCB8PSBGSUVMRF9QUkVQKEdDTURfTEFZX0lOU1RSLAo+ ICsJCQkJICAgIEdDTURfTEFZX0lOU1RSX0FERFIpOwo+ICsKPiArCW9mZnNldCA9IG5hbmRfc3Vi b3BfZ2V0X2FkZHJfc3RhcnRfb2ZmKHN1Ym9wLCBvcF9pZCk7Cj4gKwluYWRkcnMgPSBuYW5kX3N1 Ym9wX2dldF9udW1fYWRkcl9jeWMoc3Vib3AsIG9wX2lkKTsKPiArCWFkZHJzID0gJmluc3RyLT5j dHguYWRkci5hZGRyc1tvZmZzZXRdOwo+ICsKPiArCWZvciAoaSA9IDA7IGkgPCBuYWRkcnM7IGkr KykKPiArCQlhZGRyZXNzIHw9ICh1NjQpYWRkcnNbaV0gPDwgKDggKiBpKTsKPiArCj4gKwltaW5p X2N0cmxfY21kIHw9IEZJRUxEX1BSRVAoR0NNRF9MQVlfSU5QVVRfQUREUiwKPiArCQkJCSAgICBh ZGRyZXNzKTsKPiArCW1pbmlfY3RybF9jbWQgfD0gRklFTERfUFJFUChHQ01EX0xBWV9JTlBVVF9B RERSX1NJWkUsCj4gKwkJCQkgICAgbmFkZHJzIC0gMSk7Cj4gKwo+ICsJcmV0ID0gY2FkZW5jZV9u YW5kX2dlbmVyaWNfY21kX3NlbmQoY2Ruc19jdHJsLAo+ICsJCQkJCSAgICBjZG5zX2NoaXAtPmNz W2NoaXAtPmN1cl9jc10sCj4gKwkJCQkJICAgIG1pbmlfY3RybF9jbWQpOwo+ICsJaWYgKHJldCkK PiArCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LCAic2VuZCBhZGRyZXNzICVsbHggZmFpbGVkXG4i LCBhZGRyZXNzKTsKPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGNh ZGVuY2VfbmFuZF9jbWRfZXJhc2Uoc3RydWN0IG5hbmRfY2hpcCAqY2hpcCwKPiArCQkJCSAgY29u c3Qgc3RydWN0IG5hbmRfc3Vib3AgKnN1Ym9wKQo+ICt7Cj4gKwl1bnNpZ25lZCBpbnQgb3BfaWQ7 Cj4gKwo+ICsJaWYgKHN1Ym9wLT5pbnN0cnNbMF0uY3R4LmNtZC5vcGNvZGUgPT0gTkFORF9DTURf RVJBU0UxKSB7Cj4gKwkJaW50IGk7Cj4gKwkJY29uc3Qgc3RydWN0IG5hbmRfb3BfaW5zdHIgKmlu c3RyID0gTlVMTDsKPiArCQl1bnNpZ25lZCBpbnQgb2Zmc2V0LCBuYWRkcnM7Cj4gKwkJY29uc3Qg dTggKmFkZHJzOwo+ICsJCXUzMiBwYWdlID0gMDsKPiArCj4gKwkJaW5zdHIgPSAmc3Vib3AtPmlu c3Ryc1sxXTsKPiArCQlvZmZzZXQgPSBuYW5kX3N1Ym9wX2dldF9hZGRyX3N0YXJ0X29mZihzdWJv cCwgMSk7Cj4gKwkJbmFkZHJzID0gbmFuZF9zdWJvcF9nZXRfbnVtX2FkZHJfY3ljKHN1Ym9wLCAx KTsKPiArCQlhZGRycyA9ICZpbnN0ci0+Y3R4LmFkZHIuYWRkcnNbb2Zmc2V0XTsKPiArCj4gKwkJ Zm9yIChpID0gMDsgaSA8IG5hZGRyczsgaSsrKQo+ICsJCQlwYWdlIHw9ICh1MzIpYWRkcnNbaV0g PDwgKDggKiBpKTsKPiArCj4gKwkJcmV0dXJuIGNhZGVuY2VfbmFuZF9lcmFzZShjaGlwLCBwYWdl KTsKPiArCX0KPiArCj4gKwkvKgo+ICsJICogSWYgaXQgaXMgbm90IGFuIGVyYXNlIG9wZXJhdGlv biB0aGVuIGhhbmRsZSBvcGVyYXRpb24KPiArCSAqIGJ5IGNhbGxpbmcgZXhlY19vcCBmdW5jdGlv bi4KPiArCSAqLwo+ICsJZm9yIChvcF9pZCA9IDA7IG9wX2lkIDwgc3Vib3AtPm5pbnN0cnM7IG9w X2lkKyspIHsKPiArCQlpbnQgcmV0Owo+ICsJCWNvbnN0IHN0cnVjdCBuYW5kX29wZXJhdGlvbiBu YW5kX29wID0gewo+ICsJCQkuY3MgPSBjaGlwLT5jdXJfY3MsCj4gKwkJCS5pbnN0cnMgPSAgJnN1 Ym9wLT5pbnN0cnNbb3BfaWRdLAo+ICsJCQkubmluc3RycyA9IDF9Owo+ICsJCXJldCA9IGNoaXAt PmNvbnRyb2xsZXItPm9wcy0+ZXhlY19vcChjaGlwLCAmbmFuZF9vcCwgZmFsc2UpOwo+ICsJCWlm IChyZXQpCj4gKwkJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiAr Cj4gK3N0YXRpYyBpbnQgY2FkZW5jZV9uYW5kX2NtZF9kYXRhKHN0cnVjdCBuYW5kX2NoaXAgKmNo aXAsCj4gKwkJCQkgY29uc3Qgc3RydWN0IG5hbmRfc3Vib3AgKnN1Ym9wKQo+ICt7Cj4gKwlzdHJ1 Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3RybCA9IHRvX2NkbnNfbmFuZF9jdHJsKGNoaXAtPmNv bnRyb2xsZXIpOwo+ICsJc3RydWN0IGNkbnNfbmFuZF9jaGlwICpjZG5zX2NoaXAgPSB0b19jZG5z X25hbmRfY2hpcChjaGlwKTsKPiArCWNvbnN0IHN0cnVjdCBuYW5kX29wX2luc3RyICppbnN0cjsK PiArCXVuc2lnbmVkIGludCBvZmZzZXQsIG9wX2lkID0gMDsKPiArCXU2NCBtaW5pX2N0cmxfY21k ID0gMDsKPiArCWludCBsZW4gPSAwOwo+ICsJaW50IHJldDsKPiArCj4gKwlpbnN0ciA9ICZzdWJv cC0+aW5zdHJzW29wX2lkXTsKPiArCj4gKwlpZiAoaW5zdHItPmRlbGF5X25zID4gMCkKPiArCQlt aW5pX2N0cmxfY21kIHw9IEdDTURfTEFZX1RXQjsKPiArCj4gKwltaW5pX2N0cmxfY21kIHw9IEZJ RUxEX1BSRVAoR0NNRF9MQVlfSU5TVFIsCj4gKwkJCQkgICAgR0NNRF9MQVlfSU5TVFJfREFUQSk7 Cj4gKwo+ICsJaWYgKGluc3RyLT50eXBlID09IE5BTkRfT1BfREFUQV9PVVRfSU5TVFIpCj4gKwkJ bWluaV9jdHJsX2NtZCB8PSBGSUVMRF9QUkVQKEdDTURfRElSLAo+ICsJCQkJCSAgICBHQ01EX0RJ Ul9XUklURSk7Cj4gKwo+ICsJbGVuID0gbmFuZF9zdWJvcF9nZXRfZGF0YV9sZW4oc3Vib3AsIG9w X2lkKTsKPiArCW9mZnNldCA9IG5hbmRfc3Vib3BfZ2V0X2RhdGFfc3RhcnRfb2ZmKHN1Ym9wLCBv cF9pZCk7Cj4gKwltaW5pX2N0cmxfY21kIHw9IEZJRUxEX1BSRVAoR0NNRF9TRUNUX0NOVCwgMSk7 Cj4gKwltaW5pX2N0cmxfY21kIHw9IEZJRUxEX1BSRVAoR0NNRF9MQVNUX1NJWkUsIGxlbik7Cj4g KwlpZiAoaW5zdHItPmN0eC5kYXRhLmZvcmNlXzhiaXQpIHsKPiArCQlyZXQgPSBjYWRlbmNlX25h bmRfZm9yY2VfYnl0ZV9hY2Nlc3MoY2hpcCwgdHJ1ZSk7Cj4gKwkJaWYgKHJldCkgewo+ICsJCQlk ZXZfZXJyKGNkbnNfY3RybC0+ZGV2LAo+ICsJCQkJImNhbm5vdCBjaGFuZ2UgYnl0ZSBhY2Nlc3Mg Z2VuZXJpYyBkYXRhIGNtZCBmYWlsZWRcbiIpOwo+ICsJCQlyZXR1cm4gcmV0Owo+ICsJCX0KPiAr CX0KPiArCj4gKwlyZXQgPSBjYWRlbmNlX25hbmRfZ2VuZXJpY19jbWRfc2VuZChjZG5zX2N0cmws Cj4gKwkJCQkJICAgIGNkbnNfY2hpcC0+Y3NbY2hpcC0+Y3VyX2NzXSwKPiArCQkJCQkgICAgbWlu aV9jdHJsX2NtZCk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZGV2X2VycihjZG5zX2N0cmwtPmRldiwg InNlbmQgZ2VuZXJpYyBkYXRhIGNtZCBmYWlsZWRcbiIpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9 Cj4gKwo+ICsJaWYgKGluc3RyLT50eXBlID09IE5BTkRfT1BfREFUQV9JTl9JTlNUUikgewo+ICsJ CXZvaWQgKmJ1ZiA9IGluc3RyLT5jdHguZGF0YS5idWYuaW4gKyBvZmZzZXQ7Cj4gKwo+ICsJCXJl dCA9IGNhZGVuY2VfbmFuZF9yZWFkX2J1ZihjZG5zX2N0cmwsIGJ1ZiwgbGVuKTsKPiArCX0gZWxz ZSB7Cj4gKwkJY29uc3Qgdm9pZCAqYnVmID0gaW5zdHItPmN0eC5kYXRhLmJ1Zi5vdXQgKyBvZmZz ZXQ7Cj4gKwo+ICsJCXJldCA9IGNhZGVuY2VfbmFuZF93cml0ZV9idWYoY2Ruc19jdHJsLCBidWYs IGxlbik7Cj4gKwl9Cj4gKwo+ICsJaWYgKHJldCkgewo+ICsJCWRldl9lcnIoY2Ruc19jdHJsLT5k ZXYsICJkYXRhIHRyYW5zZmVyIGZhaWxlZCBmb3IgZ2VuZXJpYyBjb21tYW5kXG4iKTsKPiArCQly ZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCWlmIChpbnN0ci0+Y3R4LmRhdGEuZm9yY2VfOGJpdCkg ewo+ICsJCXJldCA9IGNhZGVuY2VfbmFuZF9mb3JjZV9ieXRlX2FjY2VzcyhjaGlwLCBmYWxzZSk7 Cj4gKwkJaWYgKHJldCkgewo+ICsJCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LAo+ICsJCQkJImNh bm5vdCBjaGFuZ2UgYnl0ZSBhY2Nlc3MgZ2VuZXJpYyBkYXRhIGNtZCBmYWlsZWRcbiIpOwo+ICsJ CX0KPiArCX0KPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGNhZGVu Y2VfbmFuZF9jbWRfd2FpdHJkeShzdHJ1Y3QgbmFuZF9jaGlwICpjaGlwLAo+ICsJCQkJICAgIGNv bnN0IHN0cnVjdCBuYW5kX3N1Ym9wICpzdWJvcCkKPiArewo+ICsJaW50IHN0YXR1czsKPiArCXVu c2lnbmVkIGludCBvcF9pZCA9IDA7Cj4gKwlzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgKmNkbnNfY3Ry bCA9IHRvX2NkbnNfbmFuZF9jdHJsKGNoaXAtPmNvbnRyb2xsZXIpOwo+ICsJc3RydWN0IGNkbnNf bmFuZF9jaGlwICpjZG5zX2NoaXAgPSB0b19jZG5zX25hbmRfY2hpcChjaGlwKTsKPiArCWNvbnN0 IHN0cnVjdCBuYW5kX29wX2luc3RyICppbnN0ciA9ICZzdWJvcC0+aW5zdHJzW29wX2lkXTsKPiAr CXUzMiB0aW1lb3V0X3VzID0gaW5zdHItPmN0eC53YWl0cmR5LnRpbWVvdXRfbXMgKiAxMDAwOwo+ ICsKPiArCXN0YXR1cyA9IGNhZGVuY2VfbmFuZF93YWl0X2Zvcl92YWx1ZShjZG5zX2N0cmwsIFJC Tl9TRVRJTkdTLAo+ICsJCQkJCSAgICAgdGltZW91dF91cywKPiArCQkJCQkgICAgIDFVIDw8IGNk bnNfY2hpcC0+Y3NbY2hpcC0+Y3VyX2NzXSwKCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIEJJVCgpID8KCj4gKwkJCQkJICAgICBmYWxzZSk7Cj4gKwlyZXR1cm4g c3RhdHVzOwo+ICt9Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IG5hbmRfb3BfcGFyc2VyIGNh ZGVuY2VfbmFuZF9vcF9wYXJzZXIgPSBOQU5EX09QX1BBUlNFUigKPiArCU5BTkRfT1BfUEFSU0VS X1BBVFRFUk4oCj4gKwkJY2FkZW5jZV9uYW5kX2NtZF9lcmFzZSwKPiArCQlOQU5EX09QX1BBUlNF Ul9QQVRfQ01EX0VMRU0oZmFsc2UpLAo+ICsJCU5BTkRfT1BfUEFSU0VSX1BBVF9BRERSX0VMRU0o ZmFsc2UsIE1BWF9FUkFTRV9BRERSRVNTX0NZQyksCj4gKwkJTkFORF9PUF9QQVJTRVJfUEFUX0NN RF9FTEVNKGZhbHNlKSwKPiArCQlOQU5EX09QX1BBUlNFUl9QQVRfV0FJVFJEWV9FTEVNKGZhbHNl KSksCj4gKwlOQU5EX09QX1BBUlNFUl9QQVRURVJOKAo+ICsJCWNhZGVuY2VfbmFuZF9jbWRfb3Bj b2RlLAo+ICsJCU5BTkRfT1BfUEFSU0VSX1BBVF9DTURfRUxFTShmYWxzZSkpLAo+ICsJTkFORF9P UF9QQVJTRVJfUEFUVEVSTigKPiArCQljYWRlbmNlX25hbmRfY21kX2FkZHJlc3MsCj4gKwkJTkFO RF9PUF9QQVJTRVJfUEFUX0FERFJfRUxFTShmYWxzZSwgTUFYX0FERFJFU1NfQ1lDKSksCj4gKwlO QU5EX09QX1BBUlNFUl9QQVRURVJOKAo+ICsJCWNhZGVuY2VfbmFuZF9jbWRfZGF0YSwKPiArCQlO QU5EX09QX1BBUlNFUl9QQVRfREFUQV9JTl9FTEVNKGZhbHNlLCBNQVhfREFUQV9TSVpFKSksCj4g KwlOQU5EX09QX1BBUlNFUl9QQVRURVJOKAo+ICsJCWNhZGVuY2VfbmFuZF9jbWRfZGF0YSwKPiAr CQlOQU5EX09QX1BBUlNFUl9QQVRfREFUQV9PVVRfRUxFTShmYWxzZSwgTUFYX0RBVEFfU0laRSkp LAo+ICsJTkFORF9PUF9QQVJTRVJfUEFUVEVSTigKPiArCQljYWRlbmNlX25hbmRfY21kX3dhaXRy ZHksCj4gKwkJTkFORF9PUF9QQVJTRVJfUEFUX1dBSVRSRFlfRUxFTShmYWxzZSkpCj4gKwkpOwo+ ICsKPiArc3RhdGljIGludCBjYWRlbmNlX25hbmRfZXhlY19vcChzdHJ1Y3QgbmFuZF9jaGlwICpj aGlwLAo+ICsJCQkJY29uc3Qgc3RydWN0IG5hbmRfb3BlcmF0aW9uICpvcCwKPiArCQkJCWJvb2wg Y2hlY2tfb25seSkKPiArewo+ICsJaW50IHN0YXR1cyA9IGNhZGVuY2VfbmFuZF9zZWxlY3RfdGFy Z2V0KGNoaXApOwo+ICsKPiArCWlmIChzdGF0dXMpCj4gKwkJcmV0dXJuIHN0YXR1czsKPiArCj4g KwlyZXR1cm4gbmFuZF9vcF9wYXJzZXJfZXhlY19vcChjaGlwLCAmY2FkZW5jZV9uYW5kX29wX3Bh cnNlciwgb3AsCj4gKwkJCQkgICAgICBjaGVja19vbmx5KTsKPiArfQo+ICsKPiArc3RhdGljIGlu dCBjYWRlbmNlX25hbmRfb29ibGF5b3V0X2ZyZWUoc3RydWN0IG10ZF9pbmZvICptdGQsIGludCBz ZWN0aW9uLAo+ICsJCQkJICAgICAgIHN0cnVjdCBtdGRfb29iX3JlZ2lvbiAqb29icmVnaW9uKQo+ ICt7Cj4gKwlzdHJ1Y3QgbmFuZF9jaGlwICpjaGlwID0gbXRkX3RvX25hbmQobXRkKTsKPiArCXN0 cnVjdCBjZG5zX25hbmRfY2hpcCAqY2Ruc19jaGlwID0gdG9fY2Ruc19uYW5kX2NoaXAoY2hpcCk7 Cj4gKwo+ICsJaWYgKHNlY3Rpb24pCj4gKwkJcmV0dXJuIC1FUkFOR0U7Cj4gKwo+ICsJb29icmVn aW9uLT5vZmZzZXQgPSBjZG5zX2NoaXAtPmJibV9sZW47Cj4gKwlvb2JyZWdpb24tPmxlbmd0aCA9 IGNkbnNfY2hpcC0+YXZhaWxfb29iX3NpemUKPiArCQktIGNkbnNfY2hpcC0+YmJtX2xlbjsKPiAr Cj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBjYWRlbmNlX25hbmRfb29ibGF5 b3V0X2VjYyhzdHJ1Y3QgbXRkX2luZm8gKm10ZCwgaW50IHNlY3Rpb24sCj4gKwkJCQkgICAgICBz dHJ1Y3QgbXRkX29vYl9yZWdpb24gKm9vYnJlZ2lvbikKPiArewo+ICsJc3RydWN0IG5hbmRfY2hp cCAqY2hpcCA9IG10ZF90b19uYW5kKG10ZCk7Cj4gKwlzdHJ1Y3QgY2Ruc19uYW5kX2NoaXAgKmNk bnNfY2hpcCA9IHRvX2NkbnNfbmFuZF9jaGlwKGNoaXApOwo+ICsKPiArCWlmIChzZWN0aW9uKQo+ ICsJCXJldHVybiAtRVJBTkdFOwo+ICsKPiArCW9vYnJlZ2lvbi0+b2Zmc2V0ID0gY2Ruc19jaGlw LT5hdmFpbF9vb2Jfc2l6ZTsKPiArCW9vYnJlZ2lvbi0+bGVuZ3RoID0gY2hpcC0+ZWNjLnRvdGFs Owo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IG10ZF9v b2JsYXlvdXRfb3BzIGNhZGVuY2VfbmFuZF9vb2JsYXlvdXRfb3BzID0gewo+ICsJLmZyZWUgPSBj YWRlbmNlX25hbmRfb29ibGF5b3V0X2ZyZWUsCj4gKwkuZWNjID0gY2FkZW5jZV9uYW5kX29vYmxh eW91dF9lY2MsCj4gK307Cj4gKwo+ICtzdGF0aWMgaW50IGNhbGNfY3ljbCh1MzIgdGltaW5nLCB1 MzIgY2xvY2spCj4gK3sKPiArCWlmICh0aW1pbmcgPT0gMCB8fCBjbG9jayA9PSAwKQo+ICsJCXJl dHVybiAwOwo+ICsKPiArCWlmICgodGltaW5nICUgY2xvY2spID4gMCkKPiArCQlyZXR1cm4gdGlt aW5nIC8gY2xvY2s7Cj4gKwllbHNlCj4gKwkJcmV0dXJuIHRpbWluZyAvIGNsb2NrIC0gMTsKPiAr fQo+ICsKPiArLyogQ2FsY3VsYXRlIG1heCBkYXRhIHZhbGlkIHdpbmRvdy4gKi8KPiArc3RhdGlj IGlubGluZSB1MzIgY2FsY190ZHZ3X21heCh1MzIgdHJwX2NudCwgdTMyIGNsa19wZXJpb2QsIHUz MiB0cmhvaF9taW4sCj4gKwkJCQl1MzIgYm9hcmRfZGVsYXlfc2tld19taW4sIHUzMiBleHRfbW9k ZSkKPiArewo+ICsJaWYgKGV4dF9tb2RlID09IDApCj4gKwkJY2xrX3BlcmlvZCAvPSAyOwo+ICsK PiArCXJldHVybiAodHJwX2NudCArIDEpICogY2xrX3BlcmlvZCArIHRyaG9oX21pbiArCj4gKwkJ Ym9hcmRfZGVsYXlfc2tld19taW47Cj4gK30KPiArCj4gKy8qIENhbGN1bGF0ZSBkYXRhIHZhbGlk IHdpbmRvdy4gKi8KPiArc3RhdGljIGlubGluZSB1MzIgY2FsY190ZHZ3KHUzMiB0cnBfY250LCB1 MzIgY2xrX3BlcmlvZCwgdTMyIHRyaG9oX21pbiwKPiArCQkJICAgIHUzMiB0cmVhX21heCwgdTMy IGV4dF9tb2RlKQo+ICt7Cj4gKwlpZiAoZXh0X21vZGUgPT0gMCkKPiArCQljbGtfcGVyaW9kIC89 IDI7Cj4gKwo+ICsJcmV0dXJuICh0cnBfY250ICsgMSkgKiBjbGtfcGVyaW9kICsgdHJob2hfbWlu IC0gdHJlYV9tYXg7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQKPiArY2FkZW5jZV9uYW5kX3NldHVw X2RhdGFfaW50ZXJmYWNlKHN0cnVjdCBuYW5kX2NoaXAgKmNoaXAsIGludCBjaGlwbnIsCj4gKwkJ CQkgIGNvbnN0IHN0cnVjdCBuYW5kX2RhdGFfaW50ZXJmYWNlICpjb25mKQo+ICt7Cj4gKwljb25z dCBzdHJ1Y3QgbmFuZF9zZHJfdGltaW5ncyAqc2RyOwo+ICsJc3RydWN0IGNkbnNfbmFuZF9jdHJs ICpjZG5zX2N0cmwgPSB0b19jZG5zX25hbmRfY3RybChjaGlwLT5jb250cm9sbGVyKTsKPiArCXN0 cnVjdCBjZG5zX25hbmRfY2hpcCAqY2Ruc19jaGlwID0gdG9fY2Ruc19uYW5kX2NoaXAoY2hpcCk7 Cj4gKwlzdHJ1Y3QgY2FkZW5jZV9uYW5kX3RpbWluZ3MgKnQgPSAmY2Ruc19jaGlwLT50aW1pbmdz Owo+ICsJdTMyIHJlZzsKPiArCXUzMiBib2FyZF9kZWxheSA9IGNkbnNfY3RybC0+Ym9hcmRfZGVs YXk7Cj4gKwl1MzIgY2xrX3BlcmlvZCA9IERJVl9ST1VORF9ET1dOX1VMTCgxMDAwMDAwMDAwMDAw VUxMLAo+ICsJCQkJCSAgICBjZG5zX2N0cmwtPm5mX2Nsa19yYXRlKTsKPiArCXUzMiB0Y2VoX2Nu dCwgdGNzX2NudCwgdGFkbF9jbnQsIHRjY3NfY250Owo+ICsJdTMyIHRmZWF0X2NudCwgdHJoel9j bnQsIHR2ZGx5X2NudDsKPiArCXUzMiB0cmh3X2NudCwgdHdiX2NudCwgdHdoX2NudCA9IDAsIHR3 aHJfY250Owo+ICsJdTMyIHR3cF9jbnQgPSAwLCB0cnBfY250ID0gMCwgdHJoX2NudCA9IDA7Cj4g Kwl1MzIgaWZfc2tldyA9IGNkbnNfY3RybC0+Y2FwczEtPmlmX3NrZXc7Cj4gKwl1MzIgYm9hcmRf ZGVsYXlfc2tld19taW4gPSBib2FyZF9kZWxheSAtIGlmX3NrZXc7Cj4gKwl1MzIgYm9hcmRfZGVs YXlfc2tld19tYXggPSBib2FyZF9kZWxheSArIGlmX3NrZXc7Cj4gKwl1MzIgZHFzX3NhbXBsX3Jl cywgcGhvbnlfZHFzX21vZDsKPiArCXUzMiB0ZHZ3LCB0ZHZ3X21pbiwgdGR2d19tYXg7Cj4gKwl1 MzIgZXh0X3JkX21vZGUsIGV4dF93cl9tb2RlOwo+ICsJdTMyIGRsbF9waHlfZHFzX3RpbWluZyA9 IDAsIHBob255X2Rxc190aW1pbmcgPSAwLCByZF9kZWxfc2VsID0gMDsKPiArCXUzMiBzYW1wbGlu Z19wb2ludDsKPiArCj4gKwlzZHIgPSBuYW5kX2dldF9zZHJfdGltaW5ncyhjb25mKTsKPiArCWlm IChJU19FUlIoc2RyKSkKPiArCQlyZXR1cm4gUFRSX0VSUihzZHIpOwo+ICsKPiArCW1lbXNldCh0 LCAwLCBzaXplb2YoKnQpKTsKPiArCS8qIFNhbXBsaW5nIHBvaW50IGNhbGN1bGF0aW9uLiAqLwo+ ICsKPiArCWlmIChjZG5zX2N0cmwtPmNhcHMyLmlzX3BoeV90eXBlX2RsbCkKPiArCQlwaG9ueV9k cXNfbW9kID0gMjsKPiArCWVsc2UKPiArCQlwaG9ueV9kcXNfbW9kID0gMTsKPiArCj4gKwlkcXNf c2FtcGxfcmVzID0gY2xrX3BlcmlvZCAvIHBob255X2Rxc19tb2Q7Cj4gKwo+ICsJdGR2d19taW4g PSBzZHItPnRSRUFfbWF4ICsgYm9hcmRfZGVsYXlfc2tld19tYXg7Cj4gKwkvKgo+ICsJICogVGhl IGlkZWEgb2YgdGhvc2UgY2FsY3VsYXRpb24gaXMgdG8gZ2V0IHRoZSBvcHRpbXVtIHZhbHVlCj4g KwkgKiBmb3IgdFJQIGFuZCB0UkggdGltaW5ncy4gSWYgaXQgaXMgTk9UIHBvc3NpYmxlIHRvIHNh bXBsZSBkYXRhCj4gKwkgKiB3aXRoIG9wdGltYWwgdFJQL3RSSCBzZXR0aW5ncywgdGhlIHBhcmFt ZXRlcnMgd2lsbCBiZSBleHRlbmRlZC4KPiArCSAqIElmIGNsa19wZXJpb2QgaXMgNTBucyAodGhl IGxvd2VzdCB2YWx1ZSkgdGhpcyBjb25kaXRpb24gaXMgbWV0Cj4gKwkgKiBmb3IgYXN5bmNocm9u b3VzIHRpbWluZyBtb2RlcyAxLCAyLCAzLCA0IGFuZCA1Lgo+ICsJICogSWYgY2xrX3BlcmlvZCBp cyAyMG5zIHRoZSBjb25kaXRpb24gaXMgbWV0IG9ubHkKPiArCSAqIGZvciBhc3luY2hyb25vdXMg dGltaW5nIG1vZGUgNS4KPiArCSAqLwo+ICsJaWYgKHNkci0+dFJDX21pbiA8PSBjbGtfcGVyaW9k ICYmCj4gKwkgICAgc2RyLT50UlBfbWluIDw9IChjbGtfcGVyaW9kIC8gMikgJiYKPiArCSAgICBz ZHItPnRSRUhfbWluIDw9IChjbGtfcGVyaW9kIC8gMikpIHsKPiArCQkvKiBQZXJmb3JtYW5jZSBt b2RlLiAqLwo+ICsJCWV4dF9yZF9tb2RlID0gMDsKPiArCQl0ZHZ3ID0gY2FsY190ZHZ3KHRycF9j bnQsIGNsa19wZXJpb2QsIHNkci0+dFJIT0hfbWluLAo+ICsJCQkJIHNkci0+dFJFQV9tYXgsIGV4 dF9yZF9tb2RlKTsKPiArCQl0ZHZ3X21heCA9IGNhbGNfdGR2d19tYXgodHJwX2NudCwgY2xrX3Bl cmlvZCwgc2RyLT50UkhPSF9taW4sCj4gKwkJCQkJIGJvYXJkX2RlbGF5X3NrZXdfbWluLAo+ICsJ CQkJCSBleHRfcmRfbW9kZSk7Cj4gKwkJLyoKPiArCQkgKiBDaGVjayBpZiBkYXRhIHZhbGlkIHdp bmRvdyBhbmQgc2FtcGxpbmcgcG9pbnQgY2FuIGJlIGZvdW5kCj4gKwkJICogYW5kIGlzIG5vdCBv biB0aGUgZWRnZSAoaWUuIHdlIGhhdmUgaG9sZCBtYXJnaW4pLgo+ICsJCSAqIElmIG5vdCBleHRl bmQgdGhlIHRSUCB0aW1pbmdzLgo+ICsJCSAqLwo+ICsJCWlmICh0ZHZ3ID4gMCkgewo+ICsJCQlp ZiAodGR2d19tYXggPD0gdGR2d19taW4gfHwKPiArCQkJICAgICh0ZHZ3X21heCAlIGRxc19zYW1w bF9yZXMpID09IDApIHsKPiArCQkJCS8qCj4gKwkJCQkgKiBObyB2YWxpZCBzYW1wbGluZyBwb2lu dCBzbyB0aGUgUkUgcHVsc2UgbmVlZAo+ICsJCQkJICogdG8gYmUgd2lkZW4gd2lkZW5pbmcgYnkg aGFsZiBjbG9jayBjeWNsZS4KPiArCQkJCSAqLwo+ICsJCQkJZXh0X3JkX21vZGUgPSAxOwo+ICsJ CQl9Cj4gKwkJfSBlbHNlIHsKPiArCQkJLyoKPiArCQkJICogVGhlcmUgaXMgbm8gdmFsaWQgd2lu ZG93Cj4gKwkJCSAqIHRvIGJlIGFibGUgdG8gc2FtcGxlIGRhdGEgdGhlIHRSUCBuZWVkIHRvIGJl IHdpZGVuLgo+ICsJCQkgKiBWZXJ5IHNhZmUgY2FsY3VsYXRpb25zIGFyZSBwZXJmb3JtZWQgaGVy ZS4KPiArCQkJICovCj4gKwkJCXRycF9jbnQgPSAoc2RyLT50UkVBX21heCArIGJvYXJkX2RlbGF5 X3NrZXdfbWF4Cj4gKwkJCQkgICArIGRxc19zYW1wbF9yZXMpIC8gY2xrX3BlcmlvZDsKPiArCQkJ ZXh0X3JkX21vZGUgPSAxOwo+ICsJCX0KPiArCj4gKwl9IGVsc2Ugewo+ICsJCS8qIEV4dGVuZGVk IHJlYWQgbW9kZS4gKi8KPiArCQl1MzIgdHJoOwo+ICsKPiArCQlleHRfcmRfbW9kZSA9IDE7Cj4g KwkJdHJwX2NudCA9IGNhbGNfY3ljbChzZHItPnRSUF9taW4sIGNsa19wZXJpb2QpOwo+ICsJCXRy aCA9IHNkci0+dFJDX21pbiAtICgodHJwX2NudCArIDEpICogY2xrX3BlcmlvZCk7Cj4gKwkJaWYg KHNkci0+dFJFSF9taW4gPj0gdHJoKQo+ICsJCQl0cmhfY250ID0gY2FsY19jeWNsKHNkci0+dFJF SF9taW4sIGNsa19wZXJpb2QpOwo+ICsJCWVsc2UKPiArCQkJdHJoX2NudCA9IGNhbGNfY3ljbCh0 cmgsIGNsa19wZXJpb2QpOwo+ICsKPiArCQl0ZHZ3ID0gY2FsY190ZHZ3KHRycF9jbnQsIGNsa19w ZXJpb2QsIHNkci0+dFJIT0hfbWluLAo+ICsJCQkJIHNkci0+dFJFQV9tYXgsIGV4dF9yZF9tb2Rl KTsKPiArCQkvKgo+ICsJCSAqIENoZWNrIGlmIGRhdGEgdmFsaWQgd2luZG93IGFuZCBzYW1wbGlu ZyBwb2ludCBjYW4gYmUgZm91bmQKPiArCQkgKiBvciBpZiBpdCBpcyBhdCB0aGUgZWRnZSBjaGVj ayBpZiBwcmV2aW91cyBpcyB2YWxpZAo+ICsJCSAqIC0gaWYgbm90IGV4dGVuZCB0aGUgdFJQIHRp bWluZ3MuCj4gKwkJICovCj4gKwkJaWYgKHRkdncgPiAwKSB7Cj4gKwkJCXRkdndfbWF4ID0gY2Fs Y190ZHZ3X21heCh0cnBfY250LCBjbGtfcGVyaW9kLAo+ICsJCQkJCQkgc2RyLT50UkhPSF9taW4s Cj4gKwkJCQkJCSBib2FyZF9kZWxheV9za2V3X21pbiwKPiArCQkJCQkJIGV4dF9yZF9tb2RlKTsK PiArCj4gKwkJCWlmICgoKCh0ZHZ3X21heCAvIGRxc19zYW1wbF9yZXMpCj4gKwkJCSAgICAgICog ZHFzX3NhbXBsX3JlcykgPD0gdGR2d19taW4pIHx8Cj4gKwkJCSAgICAoKCh0ZHZ3X21heCAlIGRx c19zYW1wbF9yZXMpID09IDApICYmCj4gKwkJCSAgICAgKCgodGR2d19tYXggLyBkcXNfc2FtcGxf cmVzIC0gMSkKPiArCQkJICAgICAgICogZHFzX3NhbXBsX3JlcykgPD0gdGR2d19taW4pKSkgewo+ ICsJCQkJLyoKPiArCQkJCSAqIERhdGEgdmFsaWQgd2luZG93IHdpZHRoIGlzIGxvd2VyIHRoYW4K PiArCQkJCSAqIHNhbXBsaW5nIHJlc29sdXRpb24gYW5kIGRvIG5vdCBoaXQgYW55Cj4gKwkJCQkg KiBzYW1wbGluZyBwb2ludCB0byBiZSBzdXJlIHRoZSBzYW1wbGluZyBwb2ludAo+ICsJCQkJICog d2lsbCBiZSBmb3VuZCB0aGUgUkUgbG93IHB1bHNlIHdpZHRoIHdpbGwgYmUKPiArCQkJCSAqICBl eHRlbmRlZCBieSBvbmUgY2xvY2sgY3ljbGUuCj4gKwkJCQkgKi8KPiArCQkJCXRycF9jbnQgPSB0 cnBfY250ICsgMTsKPiArCQkJfQo+ICsJCX0gZWxzZSB7Cj4gKwkJCS8qCj4gKwkJCSAqIFRoZXJl IGlzIG5vIHZhbGlkIHdpbmRvdyB0byBiZSBhYmxlIHRvIHNhbXBsZSBkYXRhLgo+ICsJCQkgKiBU aGUgdFJQIG5lZWQgdG8gYmUgd2lkZW4uCj4gKwkJCSAqIFZlcnkgc2FmZSBjYWxjdWxhdGlvbnMg YXJlIHBlcmZvcm1lZCBoZXJlLgo+ICsJCQkgKi8KPiArCQkJdHJwX2NudCA9IChzZHItPnRSRUFf bWF4ICsgYm9hcmRfZGVsYXlfc2tld19tYXgKPiArCQkJCSAgICsgZHFzX3NhbXBsX3JlcykgLyBj bGtfcGVyaW9kOwo+ICsJCX0KPiArCX0KPiArCj4gKwl0ZHZ3X21heCA9IGNhbGNfdGR2d19tYXgo dHJwX2NudCwgY2xrX3BlcmlvZCwKPiArCQkJCSBzZHItPnRSSE9IX21pbiwKPiArCQkJCSBib2Fy ZF9kZWxheV9za2V3X21pbiwgZXh0X3JkX21vZGUpOwo+ICsKPiArCWlmIChzZHItPnRXQ19taW4g PD0gY2xrX3BlcmlvZCAmJgo+ICsJICAgIChzZHItPnRXUF9taW4gKyBpZl9za2V3KSA8PSAoY2xr X3BlcmlvZCAvIDIpICYmCj4gKwkgICAgKHNkci0+dFdIX21pbiArIGlmX3NrZXcpIDw9IChjbGtf cGVyaW9kIC8gMikpIHsKPiArCQlleHRfd3JfbW9kZSA9IDA7Cj4gKwl9IGVsc2Ugewo+ICsJCXUz MiB0d2g7Cj4gKwo+ICsJCWV4dF93cl9tb2RlID0gMTsKPiArCQl0d3BfY250ID0gY2FsY19jeWNs KHNkci0+dFdQX21pbiArIGlmX3NrZXcsIGNsa19wZXJpb2QpOwo+ICsJCWlmICgodHdwX2NudCAr IDEpICogY2xrX3BlcmlvZCA8IChzZHItPnRBTFNfbWluICsgaWZfc2tldykpCj4gKwkJCXR3cF9j bnQgPSBjYWxjX2N5Y2woc2RyLT50QUxTX21pbiArIGlmX3NrZXcsCj4gKwkJCQkJICAgIGNsa19w ZXJpb2QpOwo+ICsKPiArCQl0d2ggPSAoc2RyLT50V0NfbWluIC0gKHR3cF9jbnQgKyAxKSAqIGNs a19wZXJpb2QpOwo+ICsJCWlmIChzZHItPnRXSF9taW4gPj0gdHdoKQo+ICsJCQl0d2ggPSBzZHIt PnRXSF9taW47Cj4gKwo+ICsJCXR3aF9jbnQgPSBjYWxjX2N5Y2wodHdoICsgaWZfc2tldywgY2xr X3BlcmlvZCk7Cj4gKwl9Cj4gKwo+ICsJcmVnID0gRklFTERfUFJFUChBU1lOQ19UT0dHTEVfVElN SU5HU19UUkgsIHRyaF9jbnQpOwo+ICsJcmVnIHw9IEZJRUxEX1BSRVAoQVNZTkNfVE9HR0xFX1RJ TUlOR1NfVFJQLCB0cnBfY250KTsKPiArCXJlZyB8PSBGSUVMRF9QUkVQKEFTWU5DX1RPR0dMRV9U SU1JTkdTX1RXSCwgdHdoX2NudCk7Cj4gKwlyZWcgfD0gRklFTERfUFJFUChBU1lOQ19UT0dHTEVf VElNSU5HU19UV1AsIHR3cF9jbnQpOwo+ICsJdC0+YXN5bmNfdG9nZ2xlX3RpbWluZ3MgPSByZWc7 Cj4gKwlkZXZfZGJnKGNkbnNfY3RybC0+ZGV2LCAiQVNZTkNfVE9HR0xFX1RJTUlOR1NfU0RSXHQl eFxuIiwgcmVnKTsKPiArCj4gKwl0YWRsX2NudCA9IGNhbGNfY3ljbCgoc2RyLT50QURMX21pbiAr IGlmX3NrZXcpLCBjbGtfcGVyaW9kKTsKPiArCXRjY3NfY250ID0gY2FsY19jeWNsKChzZHItPnRD Q1NfbWluICsgaWZfc2tldyksIGNsa19wZXJpb2QpOwo+ICsJdHdocl9jbnQgPSBjYWxjX2N5Y2wo KHNkci0+dFdIUl9taW4gKyBpZl9za2V3KSwgY2xrX3BlcmlvZCk7Cj4gKwl0cmh3X2NudCA9IGNh bGNfY3ljbCgoc2RyLT50UkhXX21pbiArIGlmX3NrZXcpLCBjbGtfcGVyaW9kKTsKPiArCXJlZyA9 IEZJRUxEX1BSRVAoVElNSU5HUzBfVEFETCwgdGFkbF9jbnQpOwo+ICsKPiArCS8qCj4gKwkgKiBJ ZiB0aW1pbmcgZXhjZWVkcyBkZWxheSBmaWVsZCBpbiB0aW1pbmcgcmVnaXN0ZXIKPiArCSAqIHRo ZW4gdXNlIG1heGltdW0gdmFsdWUuCj4gKwkgKi8KPiArCWlmIChGSUVMRF9GSVQoVElNSU5HUzBf VENDUywgdGNjc19jbnQpKQo+ICsJCXJlZyB8PSBGSUVMRF9QUkVQKFRJTUlOR1MwX1RDQ1MsIHRj Y3NfY250KTsKPiArCWVsc2UKPiArCQlyZWcgfD0gVElNSU5HUzBfVENDUzsKPiArCj4gKwlyZWcg fD0gRklFTERfUFJFUChUSU1JTkdTMF9UV0hSLCB0d2hyX2NudCk7Cj4gKwlyZWcgfD0gRklFTERf UFJFUChUSU1JTkdTMF9UUkhXLCB0cmh3X2NudCk7Cj4gKwl0LT50aW1pbmdzMCA9IHJlZzsKPiAr CWRldl9kYmcoY2Ruc19jdHJsLT5kZXYsICJUSU1JTkdTMF9TRFJcdCV4XG4iLCByZWcpOwo+ICsK PiArCS8qIFRoZSBmb2xsb3dpbmcgaXMgcmVsYXRlZCB0byBzaW5nbGUgc2lnbmFsIHNvIHNrZXcg aXMgbm90IG5lZWRlZC4gKi8KPiArCXRyaHpfY250ID0gY2FsY19jeWNsKHNkci0+dFJIWl9tYXgs IGNsa19wZXJpb2QpOwo+ICsJdHJoel9jbnQgPSB0cmh6X2NudCArIDE7Cj4gKwl0d2JfY250ID0g Y2FsY19jeWNsKChzZHItPnRXQl9tYXggKyBib2FyZF9kZWxheSksIGNsa19wZXJpb2QpOwo+ICsJ LyoKPiArCSAqIEJlY2F1c2Ugb2YgdGhlIHR3byBzdGFnZSBzeW5jZmxvcCB0aGUgdmFsdWUgbXVz dCBiZSBpbmNyZWFzZWQgYnkgMwo+ICsJICogZmlyc3QgdmFsdWUgaXMgcmVsYXRlZCB3aXRoIHN5 bmMsIHNlY29uZCB2YWx1ZSBpcyByZWxhdGVkCj4gKwkgKiB3aXRoIG91dHB1dCBpZiBkZWxheS4K PiArCSAqLwo+ICsJdHdiX2NudCA9IHR3Yl9jbnQgKyAzICsgNTsKPiArCS8qCj4gKwkgKiBUaGUg Zm9sbG93aW5nIGlzIHJlbGF0ZWQgdG8gdGhlIHdlIGVkZ2Ugb2YgdGhlIHJhbmRvbSBkYXRhIGlu cHV0Cj4gKwkgKiBzZXF1ZW5jZSBzbyBza2V3IGlzIG5vdCBuZWVkZWQuCj4gKwkgKi8KPiArCXR2 ZGx5X2NudCA9IGNhbGNfY3ljbCg1MDAwMDAgKyBpZl9za2V3LCBjbGtfcGVyaW9kKTsKPiArCXJl ZyA9IEZJRUxEX1BSRVAoVElNSU5HUzFfVFJIWiwgdHJoel9jbnQpOwo+ICsJcmVnIHw9IEZJRUxE X1BSRVAoVElNSU5HUzFfVFdCLCB0d2JfY250KTsKPiArCXJlZyB8PSBGSUVMRF9QUkVQKFRJTUlO R1MxX1RWRExZLCB0dmRseV9jbnQpOwo+ICsJdC0+dGltaW5nczEgPSByZWc7Cj4gKwlkZXZfZGJn KGNkbnNfY3RybC0+ZGV2LCAiVElNSU5HUzFfU0RSXHQleFxuIiwgcmVnKTsKPiArCj4gKwl0ZmVh dF9jbnQgPSBjYWxjX2N5Y2woc2RyLT50RkVBVF9tYXgsIGNsa19wZXJpb2QpOwo+ICsJaWYgKHRm ZWF0X2NudCA8IHR3Yl9jbnQpCj4gKwkJdGZlYXRfY250ID0gdHdiX2NudDsKPiArCj4gKwl0Y2Vo X2NudCA9IGNhbGNfY3ljbChzZHItPnRDRUhfbWluLCBjbGtfcGVyaW9kKTsKPiArCXRjc19jbnQg PSBjYWxjX2N5Y2woKHNkci0+dENTX21pbiArIGlmX3NrZXcpLCBjbGtfcGVyaW9kKTsKPiArCj4g KwlyZWcgPSBGSUVMRF9QUkVQKFRJTUlOR1MyX1RGRUFULCB0ZmVhdF9jbnQpOwo+ICsJcmVnIHw9 IEZJRUxEX1BSRVAoVElNSU5HUzJfQ1NfSE9MRF9USU1FLCB0Y2VoX2NudCk7Cj4gKwlyZWcgfD0g RklFTERfUFJFUChUSU1JTkdTMl9DU19TRVRVUF9USU1FLCB0Y3NfY250KTsKPiArCXQtPnRpbWlu Z3MyID0gcmVnOwo+ICsJZGV2X2RiZyhjZG5zX2N0cmwtPmRldiwgIlRJTUlOR1MyX1NEUlx0JXhc biIsIHJlZyk7Cj4gKwo+ICsJaWYgKGNkbnNfY3RybC0+Y2FwczIuaXNfcGh5X3R5cGVfZGxsKSB7 Cj4gKwkJcmVnID0gRExMX1BIWV9DVFJMX0RMTF9SU1RfTjsKPiArCQlpZiAoZXh0X3dyX21vZGUp Cj4gKwkJCXJlZyB8PSBETExfUEhZX0NUUkxfRVhURU5ERURfV1JfTU9ERTsKPiArCQlpZiAoZXh0 X3JkX21vZGUpCj4gKwkJCXJlZyB8PSBETExfUEhZX0NUUkxfRVhURU5ERURfUkRfTU9ERTsKPiAr Cj4gKwkJcmVnIHw9IEZJRUxEX1BSRVAoRExMX1BIWV9DVFJMX1JTX0hJR0hfV0FJVF9DTlQsIDcp Owo+ICsJCXJlZyB8PSBGSUVMRF9QUkVQKERMTF9QSFlfQ1RSTF9SU19JRExFX0NOVCwgNyk7Cj4g KwkJdC0+ZGxsX3BoeV9jdHJsID0gcmVnOwo+ICsJCWRldl9kYmcoY2Ruc19jdHJsLT5kZXYsICJE TExfUEhZX0NUUkxfU0RSXHQleFxuIiwgcmVnKTsKPiArCX0KPiArCj4gKwkvKiBTYW1wbGluZyBw b2ludCBjYWxjdWxhdGlvbi4gKi8KPiArCWlmICgodGR2d19tYXggJSBkcXNfc2FtcGxfcmVzKSA+ IDApCj4gKwkJc2FtcGxpbmdfcG9pbnQgPSB0ZHZ3X21heCAvIGRxc19zYW1wbF9yZXM7Cj4gKwll bHNlCj4gKwkJc2FtcGxpbmdfcG9pbnQgPSAodGR2d19tYXggLyBkcXNfc2FtcGxfcmVzIC0gMSk7 Cj4gKwo+ICsJaWYgKHNhbXBsaW5nX3BvaW50ICogZHFzX3NhbXBsX3JlcyA+IHRkdndfbWluKSB7 Cj4gKwkJZGxsX3BoeV9kcXNfdGltaW5nID0KPiArCQkJRklFTERfUFJFUChQSFlfRFFTX1RJTUlO R19EUVNfU0VMX09FX0VORCwgNCk7Cj4gKwkJZGxsX3BoeV9kcXNfdGltaW5nIHw9IFBIWV9EUVNf VElNSU5HX1VTRV9QSE9OWV9EUVM7Cj4gKwkJcGhvbnlfZHFzX3RpbWluZyA9IHNhbXBsaW5nX3Bv aW50IC8gcGhvbnlfZHFzX21vZDsKPiArCj4gKwkJaWYgKChzYW1wbGluZ19wb2ludCAlIDIpID4g MCkgewo+ICsJCQlkbGxfcGh5X2Rxc190aW1pbmcgfD0gUEhZX0RRU19USU1JTkdfUEhPTllfRFFT X1NFTDsKPiArCQkJaWYgKCh0ZHZ3X21heCAlIGRxc19zYW1wbF9yZXMpID09IDApCj4gKwkJCQkv Kgo+ICsJCQkJICogQ2FsY3VsYXRpb24gZm9yIHNhbXBsaW5nIHBvaW50IGF0IHRoZSBlZGdlCj4g KwkJCQkgKiBvZiBkYXRhIGFuZCBiZWluZyBvZGQgbnVtYmVyLgo+ICsJCQkJICovCj4gKwkJCQlw aG9ueV9kcXNfdGltaW5nID0gKHRkdndfbWF4IC8gZHFzX3NhbXBsX3JlcykKPiArCQkJCQkvIHBo b255X2Rxc19tb2QgLSAxOwo+ICsKPiArCQkJaWYgKCFjZG5zX2N0cmwtPmNhcHMyLmlzX3BoeV90 eXBlX2RsbCkKPiArCQkJCXBob255X2Rxc190aW1pbmctLTsKPiArCj4gKwkJfSBlbHNlIHsKPiAr CQkJcGhvbnlfZHFzX3RpbWluZy0tOwo+ICsJCX0KPiArCQlyZF9kZWxfc2VsID0gcGhvbnlfZHFz X3RpbWluZyArIDM7Cj4gKwl9IGVsc2Ugewo+ICsJCWRldl93YXJuKGNkbnNfY3RybC0+ZGV2LAo+ ICsJCQkgIkVSUk9SIDogY2Fubm90IGZpbmQgdmFsaWQgc2FtcGxpbmcgcG9pbnRcbiIpOwo+ICsJ fQo+ICsKPiArCXJlZyA9IEZJRUxEX1BSRVAoUEhZX0NUUkxfUEhPTllfRFFTLCBwaG9ueV9kcXNf dGltaW5nKTsKPiArCWlmIChjZG5zX2N0cmwtPmNhcHMyLmlzX3BoeV90eXBlX2RsbCkKPiArCQly ZWcgIHw9IFBIWV9DVFJMX1NEUl9EUVM7Cj4gKwl0LT5waHlfY3RybCA9IHJlZzsKPiArCWRldl9k YmcoY2Ruc19jdHJsLT5kZXYsICJQSFlfQ1RSTF9SRUdfU0RSXHQleFxuIiwgcmVnKTsKPiArCj4g KwlpZiAoY2Ruc19jdHJsLT5jYXBzMi5pc19waHlfdHlwZV9kbGwpIHsKPiArCQlkZXZfZGJnKGNk bnNfY3RybC0+ZGV2LCAiUEhZX1RTRUxfUkVHX1NEUlx0JXhcbiIsIDApOwo+ICsJCWRldl9kYmco Y2Ruc19jdHJsLT5kZXYsICJQSFlfRFFfVElNSU5HX1JFR19TRFJcdCV4XG4iLCAyKTsKPiArCQlk ZXZfZGJnKGNkbnNfY3RybC0+ZGV2LCAiUEhZX0RRU19USU1JTkdfUkVHX1NEUlx0JXhcbiIsCj4g KwkJCWRsbF9waHlfZHFzX3RpbWluZyk7Cj4gKwkJdC0+cGh5X2Rxc190aW1pbmcgPSBkbGxfcGh5 X2Rxc190aW1pbmc7Cj4gKwo+ICsJCXJlZyA9IEZJRUxEX1BSRVAoUEhZX0dBVEVfTFBCS19DVFJM X1JEUywgcmRfZGVsX3NlbCk7Cj4gKwkJZGV2X2RiZyhjZG5zX2N0cmwtPmRldiwgIlBIWV9HQVRF X0xQQktfQ1RSTF9SRUdfU0RSXHQleFxuIiwKPiArCQkJcmVnKTsKPiArCQl0LT5waHlfZ2F0ZV9s cGJrX2N0cmwgPSByZWc7Cj4gKwo+ICsJCWRldl9kYmcoY2Ruc19jdHJsLT5kZXYsICJQSFlfRExM X01BU1RFUl9DVFJMX1JFR19TRFJcdCVseFxuIiwKPiArCQkJUEhZX0RMTF9NQVNURVJfQ1RSTF9C WVBBU1NfTU9ERSk7Cj4gKwkJZGV2X2RiZyhjZG5zX2N0cmwtPmRldiwgIlBIWV9ETExfU0xBVkVf Q1RSTF9SRUdfU0RSXHQleFxuIiwgMCk7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiAr Cj4gK2ludCBjYWRlbmNlX25hbmRfYXR0YWNoX2NoaXAoc3RydWN0IG5hbmRfY2hpcCAqY2hpcCkK PiArewo+ICsJc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwgPSB0b19jZG5zX25hbmRf Y3RybChjaGlwLT5jb250cm9sbGVyKTsKPiArCXN0cnVjdCBjZG5zX25hbmRfY2hpcCAqY2Ruc19j aGlwID0gdG9fY2Ruc19uYW5kX2NoaXAoY2hpcCk7Cj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9 IG5hbmRfdG9fbXRkKGNoaXApOwo+ICsJdTMyIG1heF9vb2JfZGF0YV9zaXplOwo+ICsJaW50IHJl dDsKPiArCj4gKwlpZiAoY2hpcC0+b3B0aW9ucyAmIE5BTkRfQlVTV0lEVEhfMTYpIHsKPiArCQly ZXQgPSBjYWRlbmNlX25hbmRfc2V0X2FjY2Vzc193aWR0aDE2KGNkbnNfY3RybCwgdHJ1ZSk7Cj4g KwkJaWYgKHJldCkKPiArCQkJZ290byBmcmVlX2J1ZjsKPiArCX0KPiArCj4gKwljaGlwLT5iYnRf b3B0aW9ucyB8PSBOQU5EX0JCVF9VU0VfRkxBU0g7Cj4gKwljaGlwLT5iYnRfb3B0aW9ucyB8PSBO QU5EX0JCVF9OT19PT0I7Cj4gKwljaGlwLT5lY2MubW9kZSA9IE5BTkRfRUNDX0hXOwo+ICsKPiAr CWNoaXAtPm9wdGlvbnMgfD0gTkFORF9OT19TVUJQQUdFX1dSSVRFOwo+ICsKPiArCWNkbnNfY2hp cC0+YmJtX29mZnMgPSBjaGlwLT5iYWRibG9ja3BvczsKPiArCWlmIChjaGlwLT5vcHRpb25zICYg TkFORF9CVVNXSURUSF8xNikgewo+ICsJCWNkbnNfY2hpcC0+YmJtX29mZnMgJj0gfjB4MDE7Cj4g KwkJY2Ruc19jaGlwLT5iYm1fbGVuID0gMjsKPiArCX0gZWxzZSB7Cj4gKwkJY2Ruc19jaGlwLT5i Ym1fbGVuID0gMTsKPiArCX0KPiArCj4gKwlyZXQgPSBuYW5kX2VjY19jaG9vc2VfY29uZihjaGlw LAo+ICsJCQkJICAgJmNkbnNfY3RybC0+ZWNjX2NhcHMsCj4gKwkJCQkgICBtdGQtPm9vYnNpemUg LSBjZG5zX2NoaXAtPmJibV9sZW4pOwo+ICsJaWYgKHJldCkgewo+ICsJCWRldl9lcnIoY2Ruc19j dHJsLT5kZXYsICJFQ0MgY29uZmlndXJhdGlvbiBmYWlsZWRcbiIpOwo+ICsJCWdvdG8gZnJlZV9i dWY7Cj4gKwl9Cj4gKwo+ICsJZGV2X2RiZyhjZG5zX2N0cmwtPmRldiwKPiArCQkiY2hvc2VuIEVD QyBzZXR0aW5nczogc3RlcD0lZCwgc3RyZW5ndGg9JWQsIGJ5dGVzPSVkXG4iLAo+ICsJCWNoaXAt PmVjYy5zaXplLCBjaGlwLT5lY2Muc3RyZW5ndGgsIGNoaXAtPmVjYy5ieXRlcyk7Cj4gKwo+ICsJ LyogRXJyb3IgY29ycmVjdGlvbiBjb25maWd1cmF0aW9uLiAqLwo+ICsJY2Ruc19jaGlwLT5zZWN0 b3Jfc2l6ZSA9IGNoaXAtPmVjYy5zaXplOwo+ICsJY2Ruc19jaGlwLT5zZWN0b3JfY291bnQgPSBt dGQtPndyaXRlc2l6ZSAvIGNkbnNfY2hpcC0+c2VjdG9yX3NpemU7Cj4gKwo+ICsJY2Ruc19jaGlw LT5hdmFpbF9vb2Jfc2l6ZSA9IG10ZC0+b29ic2l6ZQo+ICsJCS0gY2Ruc19jaGlwLT5zZWN0b3Jf Y291bnQgKiBjaGlwLT5lY2MuYnl0ZXM7Cj4gKwo+ICsJbWF4X29vYl9kYXRhX3NpemUgPSBNQVhf T09CX1NJWkVfUEVSX1NFQ1RPUjsKPiArCj4gKwlpZiAoY2Ruc19jaGlwLT5hdmFpbF9vb2Jfc2l6 ZSA+IG1heF9vb2JfZGF0YV9zaXplKQo+ICsJCWNkbnNfY2hpcC0+YXZhaWxfb29iX3NpemUgPSBt YXhfb29iX2RhdGFfc2l6ZTsKPiArCj4gKwlpZiAoKGNkbnNfY2hpcC0+YXZhaWxfb29iX3NpemUg KyBjZG5zX2NoaXAtPmJibV9sZW4KPiArCSAgICAgKyBjZG5zX2NoaXAtPnNlY3Rvcl9jb3VudAo+ ICsJICAgICAqIGNoaXAtPmVjYy5ieXRlcykgPiBtdGQtPm9vYnNpemUpCgpJZiB0aGUgbGluZSBp cyBub3QgcmVhZGFibGUgZW5vdWdoIHlvdSBjYW4gdXNlIGludGVybWVkaWF0ZSB2YXJpYWJsZXMu CkFsc28gdGhlIHByaW9yaXR5IG9mIHRoZSAnKicgb3BlcmF0b3IgY291bGQgYmUgZW5mb3JjZWQg d2l0aApwYXJlbnRoZXNpcy4gUmVhbGx5IHRoaXMgaXMganVzdCBhIG5pdCBwaWNrIDopCgo+ICsJ CWNkbnNfY2hpcC0+YXZhaWxfb29iX3NpemUgLT0gNDsKPiArCj4gKwljZG5zX2NoaXAtPmNvcnJf c3RyX2lkeCA9Cj4gKwkJY2FkZW5jZV9uYW5kX2dldF9lY2Nfc3RyZW5ndGhfaWR4KGNkbnNfY3Ry bCwKPiArCQkJCQkJICBjaGlwLT5lY2Muc3RyZW5ndGgpOwo+ICsJaWYgKGNkbnNfY2hpcC0+Y29y cl9zdHJfaWR4IDwgMCkKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwlpZiAoY2FkZW5jZV9u YW5kX3dhaXRfZm9yX3ZhbHVlKGNkbnNfY3RybCwgQ1RSTF9TVEFUVVMsCj4gKwkJCQkJMTAwMDAw MCwKPiArCQkJCQlDVFJMX1NUQVRVU19DVFJMX0JVU1ksIHRydWUpKQo+ICsJCXJldHVybiAtRVRJ TUVET1VUOwo+ICsKPiArCWNhZGVuY2VfbmFuZF9zZXRfZWNjX3N0cmVuZ3RoKGNkbnNfY3RybCwK PiArCQkJCSAgICAgIGNkbnNfY2hpcC0+Y29ycl9zdHJfaWR4KTsKPiArCj4gKwljYWRlbmNlX25h bmRfc2V0X2VyYXNlX2RldGVjdGlvbihjZG5zX2N0cmwsIHRydWUsCj4gKwkJCQkJIGNoaXAtPmVj Yy5zdHJlbmd0aCk7Cj4gKwo+ICsJLyogT3ZlcnJpZGUgdGhlIGRlZmF1bHQgcmVhZCBvcGVyYXRp b25zLiAqLwo+ICsJY2hpcC0+ZWNjLnJlYWRfcGFnZSA9IGNhZGVuY2VfbmFuZF9yZWFkX3BhZ2U7 Cj4gKwljaGlwLT5lY2MucmVhZF9wYWdlX3JhdyA9IGNhZGVuY2VfbmFuZF9yZWFkX3BhZ2VfcmF3 Owo+ICsJY2hpcC0+ZWNjLndyaXRlX3BhZ2UgPSBjYWRlbmNlX25hbmRfd3JpdGVfcGFnZTsKPiAr CWNoaXAtPmVjYy53cml0ZV9wYWdlX3JhdyA9IGNhZGVuY2VfbmFuZF93cml0ZV9wYWdlX3JhdzsK PiArCWNoaXAtPmVjYy5yZWFkX29vYiA9IGNhZGVuY2VfbmFuZF9yZWFkX29vYjsKPiArCWNoaXAt PmVjYy53cml0ZV9vb2IgPSBjYWRlbmNlX25hbmRfd3JpdGVfb29iOwo+ICsJY2hpcC0+ZWNjLnJl YWRfb29iX3JhdyA9IGNhZGVuY2VfbmFuZF9yZWFkX29vYl9yYXc7Cj4gKwljaGlwLT5lY2Mud3Jp dGVfb29iX3JhdyA9IGNhZGVuY2VfbmFuZF93cml0ZV9vb2JfcmF3Owo+ICsKPiArCWlmICgobXRk LT53cml0ZXNpemUgKyBtdGQtPm9vYnNpemUpID4gY2Ruc19jdHJsLT5idWZfc2l6ZSkgewo+ICsJ CWNkbnNfY3RybC0+YnVmX3NpemUgPSBtdGQtPndyaXRlc2l6ZSArIG10ZC0+b29ic2l6ZTsKPiAr CQlrZnJlZShjZG5zX2N0cmwtPmJ1Zik7Cj4gKwkJY2Ruc19jdHJsLT5idWYgPSBremFsbG9jKGNk bnNfY3RybC0+YnVmX3NpemUsIEdGUF9LRVJORUwpOwo+ICsJCWlmICghY2Ruc19jdHJsLT5idWYp IHsKPiArCQkJcmV0ID0gLUVOT01FTTsKPiArCQkJZ290byBmcmVlX2J1ZjsKPiArCQl9Cj4gKwl9 Cj4gKwo+ICsJLyogSXMgMzItYml0IERNQSBzdXBwb3J0ZWQ/ICovCj4gKwlyZXQgPSBkbWFfc2V0 X21hc2soY2Ruc19jdHJsLT5kZXYsIERNQV9CSVRfTUFTSygzMikpOwo+ICsJaWYgKHJldCkgewo+ ICsJCWRldl9lcnIoY2Ruc19jdHJsLT5kZXYsICJubyB1c2FibGUgRE1BIGNvbmZpZ3VyYXRpb25c biIpOwo+ICsJCWdvdG8gZnJlZV9idWY7Cj4gKwl9Cj4gKwo+ICsJbXRkX3NldF9vb2JsYXlvdXQo bXRkLCAmY2FkZW5jZV9uYW5kX29vYmxheW91dF9vcHMpOwo+ICsKPiArCXJldHVybiAwOwo+ICsK PiArZnJlZV9idWY6Cj4gKwlrZnJlZShjZG5zX2N0cmwtPmJ1Zik7Cj4gKwo+ICsJcmV0dXJuIHJl dDsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBuYW5kX2NvbnRyb2xsZXJfb3BzIGNh ZGVuY2VfbmFuZF9jb250cm9sbGVyX29wcyA9IHsKPiArCS5hdHRhY2hfY2hpcCA9IGNhZGVuY2Vf bmFuZF9hdHRhY2hfY2hpcCwKPiArCS5leGVjX29wID0gY2FkZW5jZV9uYW5kX2V4ZWNfb3AsCj4g Kwkuc2V0dXBfZGF0YV9pbnRlcmZhY2UgPSBjYWRlbmNlX25hbmRfc2V0dXBfZGF0YV9pbnRlcmZh Y2UsCj4gK307Cj4gKwo+ICtzdGF0aWMgaW50IGNhZGVuY2VfbmFuZF9jaGlwX2luaXQoc3RydWN0 IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwsCj4gKwkJCQkgIHN0cnVjdCBkZXZpY2Vfbm9kZSAq bnApCj4gK3sKPiArCXN0cnVjdCBjZG5zX25hbmRfY2hpcCAqY2Ruc19jaGlwOwo+ICsJc3RydWN0 IG10ZF9pbmZvICptdGQ7Cj4gKwlzdHJ1Y3QgbmFuZF9jaGlwICpjaGlwOwo+ICsJaW50IG5zZWxz LCByZXQsIGk7Cj4gKwl1MzIgY3M7Cj4gKwo+ICsJbnNlbHMgPSBvZl9wcm9wZXJ0eV9jb3VudF9l bGVtc19vZl9zaXplKG5wLCAicmVnIiwgc2l6ZW9mKHUzMikpOwo+ICsJaWYgKG5zZWxzIDw9IDAp IHsKPiArCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LCAibWlzc2luZy9pbnZhbGlkIHJlZyBwcm9w ZXJ0eVxuIik7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJLyogQWxsb2NhdGUg dGhlIG5hbmQgY2hpcCBzdHJ1Y3R1cmUuICovCj4gKwljZG5zX2NoaXAgPSBkZXZtX2t6YWxsb2Mo Y2Ruc19jdHJsLT5kZXYsIHNpemVvZigqY2Ruc19jaGlwKSArCj4gKwkJCQkgKG5zZWxzICogc2l6 ZW9mKHU4KSksCj4gKwkJCQkgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIWNkbnNfY2hpcCkgewo+ICsJ CWRldl9lcnIoY2Ruc19jdHJsLT5kZXYsICJjb3VsZCBub3QgYWxsb2NhdGUgY2hpcCBzdHJ1Y3R1 cmVcbiIpOwo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsJfQo+ICsKPiArCWNkbnNfY2hpcC0+bnNl bHMgPSBuc2VsczsKPiArCj4gKwlmb3IgKGkgPSAwOyBpIDwgbnNlbHM7IGkrKykgewo+ICsJCS8q IFJldHJpZXZlIENTIGlkLiAqLwo+ICsJCXJldCA9IG9mX3Byb3BlcnR5X3JlYWRfdTMyX2luZGV4 KG5wLCAicmVnIiwgaSwgJmNzKTsKPiArCQlpZiAocmV0KSB7Cj4gKwkJCWRldl9lcnIoY2Ruc19j dHJsLT5kZXYsCj4gKwkJCQkiY291bGQgbm90IHJldHJpZXZlIHJlZyBwcm9wZXJ0eTogJWRcbiIs Cj4gKwkJCQlyZXQpOwo+ICsJCQlyZXR1cm4gcmV0Owo+ICsJCX0KPiArCj4gKwkJaWYgKGNzID49 IGNkbnNfY3RybC0+Y2FwczIubWF4X2JhbmtzKSB7Cj4gKwkJCWRldl9lcnIoY2Ruc19jdHJsLT5k ZXYsCj4gKwkJCQkiaW52YWxpZCByZWcgdmFsdWU6ICV1IChtYXggQ1MgPSAlZClcbiIsCj4gKwkJ CQljcywgY2Ruc19jdHJsLT5jYXBzMi5tYXhfYmFua3MpOwo+ICsJCQlyZXR1cm4gLUVJTlZBTDsK PiArCQl9Cj4gKwo+ICsJCWlmICh0ZXN0X2FuZF9zZXRfYml0KGNzLCAmY2Ruc19jdHJsLT5hc3Np Z25lZF9jcykpIHsKPiArCQkJZGV2X2VycihjZG5zX2N0cmwtPmRldiwKPiArCQkJCSJDUyAlZCBh bHJlYWR5IGFzc2lnbmVkXG4iLCBjcyk7Cj4gKwkJCXJldHVybiAtRUlOVkFMOwo+ICsJCX0KPiAr Cj4gKwkJY2Ruc19jaGlwLT5jc1tpXSA9IGNzOwo+ICsJfQo+ICsKPiArCWNoaXAgPSAmY2Ruc19j aGlwLT5jaGlwOwo+ICsJY2hpcC0+Y29udHJvbGxlciA9ICZjZG5zX2N0cmwtPmNvbnRyb2xsZXI7 Cj4gKwluYW5kX3NldF9mbGFzaF9ub2RlKGNoaXAsIG5wKTsKPiArCj4gKwltdGQgPSBuYW5kX3Rv X210ZChjaGlwKTsKPiArCW10ZC0+ZGV2LnBhcmVudCA9IGNkbnNfY3RybC0+ZGV2Owo+ICsKPiAr CS8qCj4gKwkgKiBEZWZhdWx0IHRvIEhXIEVDQyBlbmdpbmUgbW9kZS4gSWYgdGhlIG5hbmQtZWNj LW1vZGUgcHJvcGVydHkgaXMgZ2l2ZW4KPiArCSAqIGluIHRoZSBEVCBub2RlLCB0aGlzIGVudHJ5 IHdpbGwgYmUgb3ZlcndyaXR0ZW4gaW4gbmFuZF9zY2FuX2lkZW50KCkuCj4gKwkgKi8KPiArCWNo aXAtPmVjYy5tb2RlID0gTkFORF9FQ0NfSFc7Cj4gKwo+ICsJcmV0ID0gbmFuZF9zY2FuKGNoaXAs IGNkbnNfY2hpcC0+bnNlbHMpOwo+ICsJaWYgKHJldCkgewo+ICsJCWRldl9lcnIoY2Ruc19jdHJs LT5kZXYsICJjb3VsZCBub3Qgc2NhbiB0aGUgbmFuZCBjaGlwXG4iKTsKPiArCQlyZXR1cm4gcmV0 Owo+ICsJfQo+ICsKPiArCXJldCA9IG10ZF9kZXZpY2VfcmVnaXN0ZXIobXRkLCBOVUxMLCAwKTsK PiArCWlmIChyZXQpIHsKPiArCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LAo+ICsJCQkiZmFpbGVk IHRvIHJlZ2lzdGVyIG10ZCBkZXZpY2U6ICVkXG4iLCByZXQpOwo+ICsJCW5hbmRfY2xlYW51cChj aGlwKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCWxpc3RfYWRkX3RhaWwoJmNkbnNf Y2hpcC0+bm9kZSwgJmNkbnNfY3RybC0+Y2hpcHMpOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4g Kwo+ICtzdGF0aWMgdm9pZCBjYWRlbmNlX25hbmRfY2hpcHNfY2xlYW51cChzdHJ1Y3QgY2Ruc19u YW5kX2N0cmwgKmNkbnNfY3RybCkKPiArewo+ICsJc3RydWN0IGNkbnNfbmFuZF9jaGlwICplbnRy eSwgKnRlbXA7Cj4gKwo+ICsJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKGVudHJ5LCB0ZW1wLCAm Y2Ruc19jdHJsLT5jaGlwcywgbm9kZSkgewo+ICsJCW5hbmRfcmVsZWFzZSgmZW50cnktPmNoaXAp Owo+ICsJCWxpc3RfZGVsKCZlbnRyeS0+bm9kZSk7Cj4gKwl9Cj4gK30KPiArCj4gK3N0YXRpYyBp bnQgY2FkZW5jZV9uYW5kX2NoaXBzX2luaXQoc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0 cmwpCj4gK3sKPiArCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbnAgPSBjZG5zX2N0cmwtPmRldi0+b2Zf bm9kZTsKPiArCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbmFuZF9ucDsKPiArCWludCBtYXhfY3MgPSBj ZG5zX2N0cmwtPmNhcHMyLm1heF9iYW5rczsKPiArCWludCBuY2hpcHMsIHJldDsKPiArCj4gKwlu Y2hpcHMgPSBvZl9nZXRfY2hpbGRfY291bnQobnApOwo+ICsKPiArCWlmIChuY2hpcHMgPiBtYXhf Y3MpIHsKPiArCQlkZXZfZXJyKGNkbnNfY3RybC0+ZGV2LAo+ICsJCQkidG9vIG1hbnkgTkFORCBj aGlwczogJWQgKG1heCA9ICVkIENTKVxuIiwKPiArCQkJbmNoaXBzLCBtYXhfY3MpOwo+ICsJCXJl dHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCWZvcl9lYWNoX2NoaWxkX29mX25vZGUobnAsIG5h bmRfbnApIHsKPiArCQlyZXQgPSBjYWRlbmNlX25hbmRfY2hpcF9pbml0KGNkbnNfY3RybCwgbmFu ZF9ucCk7Cj4gKwkJaWYgKHJldCkgewo+ICsJCQlvZl9ub2RlX3B1dChuYW5kX25wKTsKPiArCQkJ Y2FkZW5jZV9uYW5kX2NoaXBzX2NsZWFudXAoY2Ruc19jdHJsKTsKPiArCQkJcmV0dXJuIHJldDsK PiArCQl9Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgY2Fk ZW5jZV9uYW5kX2luaXQoc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwpCj4gK3sKPiAr CWRtYV9jYXBfbWFza190IG1hc2s7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCWNkbnNfY3RybC0+Y2Rt YV9kZXNjID0gZG1hX2FsbG9jX2NvaGVyZW50KGNkbnNfY3RybC0+ZGV2LAo+ICsJCQkJCQkgIHNp emVvZigqY2Ruc19jdHJsLT5jZG1hX2Rlc2MpLAo+ICsJCQkJCQkgICZjZG5zX2N0cmwtPmRtYV9j ZG1hX2Rlc2MsCj4gKwkJCQkJCSAgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIWNkbnNfY3RybC0+ZG1h X2NkbWFfZGVzYykKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwljZG5zX2N0cmwtPmJ1Zl9z aXplID0gU1pfMTZLOwo+ICsJY2Ruc19jdHJsLT5idWYgPSBrbWFsbG9jKGNkbnNfY3RybC0+YnVm X3NpemUsIEdGUF9LRVJORUwpOwo+ICsJaWYgKCFjZG5zX2N0cmwtPmJ1Zikgewo+ICsJCWdvdG8g ZnJlZV9idWZfZGVzYzsKPiArCQlyZXQgPSAtRU5PTUVNOwo+ICsJfQo+ICsKPiArCWlmIChkZXZt X3JlcXVlc3RfaXJxKGNkbnNfY3RybC0+ZGV2LCBjZG5zX2N0cmwtPmlycSwgY2FkZW5jZV9uYW5k X2lzciwKPiArCQkJICAgICBJUlFGX1NIQVJFRCwgImNhZGVuY2UtbmFuZC1jb250cm9sbGVyIiwK PiArCQkJICAgICBjZG5zX2N0cmwpKSB7Cj4gKwkJZGV2X2VycihjZG5zX2N0cmwtPmRldiwgIlVu YWJsZSB0byBhbGxvY2F0ZSBJUlFcbiIpOwo+ICsJCXJldCA9IC1FTk9ERVY7Cj4gKwkJZ290byBm cmVlX2J1ZjsKPiArCX0KPiArCj4gKwlzcGluX2xvY2tfaW5pdCgmY2Ruc19jdHJsLT5pcnFfbG9j ayk7Cj4gKwlpbml0X2NvbXBsZXRpb24oJmNkbnNfY3RybC0+Y29tcGxldGUpOwo+ICsKPiArCXJl dCA9IGNhZGVuY2VfbmFuZF9od19pbml0KGNkbnNfY3RybCk7Cj4gKwlpZiAocmV0KQo+ICsJCWdv dG8gZGlzYWJsZV9pcnE7Cj4gKwo+ICsJZG1hX2NhcF96ZXJvKG1hc2spOwo+ICsJZG1hX2NhcF9z ZXQoRE1BX01FTUNQWSwgbWFzayk7Cj4gKwo+ICsJaWYgKGNkbnNfY3RybC0+Y2FwczEtPmhhc19k bWEpIHsKPiArCQljZG5zX2N0cmwtPmRtYWMgPSBkbWFfcmVxdWVzdF9jaGFubmVsKG1hc2ssIE5V TEwsIE5VTEwpOwo+ICsJCWlmICghY2Ruc19jdHJsLT5kbWFjKSB7Cj4gKwkJCWRldl9lcnIoY2Ru c19jdHJsLT5kZXYsCj4gKwkJCQkiVW5hYmxlIHRvIGdldCBhIERNQSBjaGFubmVsXG4iKTsKPiAr CQkJcmV0ID0gLUVCVVNZOwo+ICsJCQlnb3RvIGRpc2FibGVfaXJxOwo+ICsJCX0KPiArCX0KPiAr Cj4gKwluYW5kX2NvbnRyb2xsZXJfaW5pdCgmY2Ruc19jdHJsLT5jb250cm9sbGVyKTsKPiArCUlO SVRfTElTVF9IRUFEKCZjZG5zX2N0cmwtPmNoaXBzKTsKPiArCj4gKwljZG5zX2N0cmwtPmNvbnRy b2xsZXIub3BzID0gJmNhZGVuY2VfbmFuZF9jb250cm9sbGVyX29wczsKPiArCWNkbnNfY3RybC0+ Y3Vycl9jb3JyX3N0cl9pZHggPSAweEZGOwo+ICsKPiArCXJldCA9IGNhZGVuY2VfbmFuZF9jaGlw c19pbml0KGNkbnNfY3RybCk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZGV2X2VycihjZG5zX2N0cmwt PmRldiwgIkZhaWxlZCB0byByZWdpc3RlciBNVEQ6ICVkXG4iLAo+ICsJCQlyZXQpOwo+ICsJCWdv dG8gZG1hX3JlbGVhc2VfY2hubDsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArCj4gK2RtYV9y ZWxlYXNlX2Nobmw6Cj4gKwlpZiAoY2Ruc19jdHJsLT5kbWFjKQo+ICsJCWRtYV9yZWxlYXNlX2No YW5uZWwoY2Ruc19jdHJsLT5kbWFjKTsKPiArCj4gK2Rpc2FibGVfaXJxOgo+ICsJY2FkZW5jZV9u YW5kX2lycV9jbGVhbnVwKGNkbnNfY3RybC0+aXJxLCBjZG5zX2N0cmwpOwo+ICsKPiArZnJlZV9i dWY6Cj4gKwlrZnJlZShjZG5zX2N0cmwtPmJ1Zik7Cj4gKwo+ICtmcmVlX2J1Zl9kZXNjOgo+ICsJ ZG1hX2ZyZWVfY29oZXJlbnQoY2Ruc19jdHJsLT5kZXYsIHNpemVvZihzdHJ1Y3QgY2FkZW5jZV9u YW5kX2NkbWFfZGVzYyksCj4gKwkJCSAgY2Ruc19jdHJsLT5jZG1hX2Rlc2MsIGNkbnNfY3RybC0+ ZG1hX2NkbWFfZGVzYyk7Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArLyogRHJpdmVy IGV4aXQgcG9pbnQuICovCj4gK3N0YXRpYyB2b2lkIGNhZGVuY2VfbmFuZF9yZW1vdmUoc3RydWN0 IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmwpCj4gK3sKPiArCWNhZGVuY2VfbmFuZF9jaGlwc19j bGVhbnVwKGNkbnNfY3RybCk7Cj4gKwljYWRlbmNlX25hbmRfaXJxX2NsZWFudXAoY2Ruc19jdHJs LT5pcnEsIGNkbnNfY3RybCk7Cj4gKwlrZnJlZShjZG5zX2N0cmwtPmJ1Zik7Cj4gKwlkbWFfZnJl ZV9jb2hlcmVudChjZG5zX2N0cmwtPmRldiwgc2l6ZW9mKHN0cnVjdCBjYWRlbmNlX25hbmRfY2Rt YV9kZXNjKSwKPiArCQkJICBjZG5zX2N0cmwtPmNkbWFfZGVzYywgY2Ruc19jdHJsLT5kbWFfY2Rt YV9kZXNjKTsKPiArCj4gKwlpZiAoY2Ruc19jdHJsLT5kbWFjKQo+ICsJCWRtYV9yZWxlYXNlX2No YW5uZWwoY2Ruc19jdHJsLT5kbWFjKTsKPiArfQo+ICsKPiArc3RydWN0IGNhZGVuY2VfbmFuZF9k dCB7Cj4gKwlzdHJ1Y3QgY2Ruc19uYW5kX2N0cmwgY2Ruc19jdHJsOwo+ICsJc3RydWN0IGNsayAq Y2xrOwo+ICt9Owo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBjYWRlbmNlX25hbmRfZHRfZGV2 ZGF0YSBjYWRlbmNlX25hbmRfZGVmYXVsdCA9IHsKPiArCS5pZl9za2V3ID0gMCwKPiArCS5oYXNf ZG1hID0gMSwKPiArfTsKPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lkIGNh ZGVuY2VfbmFuZF9kdF9pZHNbXSA9IHsKPiArCXsKPiArCQkuY29tcGF0aWJsZSA9ICJjZG5zLGhw LW5mYyIsCj4gKwkJLmRhdGEgPSAmY2FkZW5jZV9uYW5kX2RlZmF1bHQKPiArCX0sIHt9Cj4gK307 Cj4gKwo+ICtNT0RVTEVfREVWSUNFX1RBQkxFKG9mLCBjYWRlbmNlX25hbmRfZHRfaWRzKTsKPiAr Cj4gK3N0YXRpYyBpbnQgY2FkZW5jZV9uYW5kX2R0X3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZp Y2UgKm9mZGV2KQo+ICt7Cj4gKwlzdHJ1Y3QgcmVzb3VyY2UgKnJlczsKPiArCXN0cnVjdCBjYWRl bmNlX25hbmRfZHQgKmR0Owo+ICsJc3RydWN0IGNkbnNfbmFuZF9jdHJsICpjZG5zX2N0cmw7Cj4g KwlpbnQgcmV0Owo+ICsJY29uc3Qgc3RydWN0IG9mX2RldmljZV9pZCAqb2ZfaWQ7Cj4gKwljb25z dCBzdHJ1Y3QgY2FkZW5jZV9uYW5kX2R0X2RldmRhdGEgKmRldmRhdGE7Cj4gKwl1MzIgdmFsOwo+ ICsKPiArCW9mX2lkID0gb2ZfbWF0Y2hfZGV2aWNlKGNhZGVuY2VfbmFuZF9kdF9pZHMsICZvZmRl di0+ZGV2KTsKPiArCWlmIChvZl9pZCkgewo+ICsJCW9mZGV2LT5pZF9lbnRyeSA9IG9mX2lkLT5k YXRhOwo+ICsJCWRldmRhdGEgPSBvZl9pZC0+ZGF0YTsKPiArCX0gZWxzZSB7Cj4gKwkJcHJfZXJy KCJGYWlsZWQgdG8gZmluZCB0aGUgcmlnaHQgZGV2aWNlIGlkLlxuIik7Cj4gKwkJcmV0dXJuIC1F Tk9NRU07Cj4gKwl9Cj4gKwo+ICsJZHQgPSBkZXZtX2t6YWxsb2MoJm9mZGV2LT5kZXYsIHNpemVv ZigqZHQpLCBHRlBfS0VSTkVMKTsKPiArCWlmICghZHQpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4g Kwo+ICsJY2Ruc19jdHJsID0gJmR0LT5jZG5zX2N0cmw7Cj4gKwljZG5zX2N0cmwtPmNhcHMxID0g ZGV2ZGF0YTsKPiArCj4gKwljZG5zX2N0cmwtPmRldiA9ICZvZmRldi0+ZGV2Owo+ICsJY2Ruc19j dHJsLT5pcnEgPSBwbGF0Zm9ybV9nZXRfaXJxKG9mZGV2LCAwKTsKPiArCWlmIChjZG5zX2N0cmwt PmlycSA8IDApIHsKPiArCQlkZXZfZXJyKCZvZmRldi0+ZGV2LCAibm8gaXJxIGRlZmluZWRcbiIp Owo+ICsJCXJldHVybiBjZG5zX2N0cmwtPmlycTsKPiArCX0KPiArCWRldl9pbmZvKGNkbnNfY3Ry bC0+ZGV2LCAiSVJROiBuciAlZFxuIiwgY2Ruc19jdHJsLT5pcnEpOwo+ICsKPiArCXJlcyA9IHBs YXRmb3JtX2dldF9yZXNvdXJjZShvZmRldiwgSU9SRVNPVVJDRV9NRU0sIDApOwo+ICsJY2Ruc19j dHJsLT5yZWcgPSBkZXZtX2lvcmVtYXBfcmVzb3VyY2UoY2Ruc19jdHJsLT5kZXYsIHJlcyk7CgpJ IHRoaW5rIHRoaXMgd2lsbCBiZSByZWZ1c2VkIGJ5IHJvYm90cywgeW91IGhhdmUgdG8gc3F1YXNo IHRoZSB0d28KbGluZXMgaW50bwoKICAgICAgICBjZG5zX2N0cmwtPnJlZyA9IGRldm1fcGxhdGZv cm1faW9yZW1hcF9yZXNvdXJjZShvZmRldiwgMCk7Cgo+ICsJaWYgKElTX0VSUihjZG5zX2N0cmwt PnJlZykpIHsKPiArCQlkZXZfZXJyKCZvZmRldi0+ZGV2LCAiZGV2bV9pb3JlbWFwX3Jlc291cmNl IHJlcyAwIGZhaWxlZFxuIik7Cj4gKwkJcmV0dXJuIFBUUl9FUlIoY2Ruc19jdHJsLT5yZWcpOwo+ ICsJfQo+ICsKPiArCXJlcyA9IHBsYXRmb3JtX2dldF9yZXNvdXJjZShvZmRldiwgSU9SRVNPVVJD RV9NRU0sIDEpOwo+ICsJY2Ruc19jdHJsLT5pby5kbWEgPSByZXMtPnN0YXJ0Owo+ICsJY2Ruc19j dHJsLT5pby52aXJ0ID0gZGV2bV9pb3JlbWFwX3Jlc291cmNlKCZvZmRldi0+ZGV2LCByZXMpOwo+ ICsJaWYgKElTX0VSUihjZG5zX2N0cmwtPmlvLnZpcnQpKSB7Cj4gKwkJZGV2X2VycihjZG5zX2N0 cmwtPmRldiwgImRldm1faW9yZW1hcF9yZXNvdXJjZSByZXMgMSBmYWlsZWRcbiIpOwo+ICsJCXJl dHVybiBQVFJfRVJSKGNkbnNfY3RybC0+aW8udmlydCk7Cj4gKwl9Cj4gKwo+ICsJZHQtPmNsayA9 IGRldm1fY2xrX2dldChjZG5zX2N0cmwtPmRldiwgIm5mX2NsayIpOwo+ICsJaWYgKElTX0VSUihk dC0+Y2xrKSkKPiArCQlyZXR1cm4gUFRSX0VSUihkdC0+Y2xrKTsKPiArCj4gKwljZG5zX2N0cmwt Pm5mX2Nsa19yYXRlID0gY2xrX2dldF9yYXRlKGR0LT5jbGspOwo+ICsKPiArCXJldCA9IG9mX3By b3BlcnR5X3JlYWRfdTMyKG9mZGV2LT5kZXYub2Zfbm9kZSwKPiArCQkJCSAgICJjZG5zLGJvYXJk LWRlbGF5LXBzIiwgJnZhbCk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZGV2X3dhcm4oY2Ruc19jdHJs LT5kZXYsICJtaXNzaW5nIGNkbnMsYm9hcmQtZGVsYXktcHMgcHJvcGVydHlcbiIpOwoKTWF5YmUg eW91IGNvdWxkIHR1cm4gdGhpcyBwcm9wZXJ0eSBpbnRvIGFuIG9wdGlvbmFsIG9uZSwgd2l0aCBh IGRlZmF1bHQKdmFsdWU/Cgo+ICsJCXZhbCA9IDA7Cj4gKwl9Cj4gKwljZG5zX2N0cmwtPmJvYXJk X2RlbGF5ID0gdmFsOwo+ICsKPiArCXJldCA9IGNhZGVuY2VfbmFuZF9pbml0KGNkbnNfY3RybCk7 Cj4gKwlpZiAocmV0KQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJcGxhdGZvcm1fc2V0X2RydmRh dGEob2ZkZXYsIGR0KTsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGNhZGVu Y2VfbmFuZF9kdF9yZW1vdmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqb2ZkZXYpCj4gK3sKPiAr CXN0cnVjdCBjYWRlbmNlX25hbmRfZHQgKmR0ID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEob2ZkZXYp Owo+ICsKPiArCWNhZGVuY2VfbmFuZF9yZW1vdmUoJmR0LT5jZG5zX2N0cmwpOwo+ICsKPiArCXJl dHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBjYWRlbmNl X25hbmRfZHRfZHJpdmVyID0gewo+ICsJLnByb2JlCQk9IGNhZGVuY2VfbmFuZF9kdF9wcm9iZSwK PiArCS5yZW1vdmUJCT0gY2FkZW5jZV9uYW5kX2R0X3JlbW92ZSwKPiArCS5kcml2ZXIJCT0gewo+ ICsJCS5uYW1lCT0gImNhZGVuY2UtbmFuZC1jb250cm9sbGVyIiwKPiArCQkub2ZfbWF0Y2hfdGFi bGUgPSBjYWRlbmNlX25hbmRfZHRfaWRzLAo+ICsJfSwKPiArfTsKPiArCj4gK21vZHVsZV9wbGF0 Zm9ybV9kcml2ZXIoY2FkZW5jZV9uYW5kX2R0X2RyaXZlcik7Cj4gKwo+ICtNT0RVTEVfQVVUSE9S KCJQaW90ciBTcm9rYSA8cGlvdHJzQGNhZGVuY2UuY29tPiIpOwo+ICtNT0RVTEVfTElDRU5TRSgi R1BMIHYyIik7Cj4gK01PRFVMRV9ERVNDUklQVElPTigiRHJpdmVyIGZvciBDYWRlbmNlIE5BTkQg Zmxhc2ggY29udHJvbGxlciIpOwo+ICsKCldvdWxkIHlvdSBtaW5kIGFkZGluZyB5b3Vyc2VsZiBp biBNQUlOVEFJTkVSUyBmb3IgdGhpcyBkcml2ZXIgKCsKYmluZGluZ3MpPwoKVGhhbmtzLApNaXF1 w6hsCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X18KTGludXggTVREIGRpc2N1c3Npb24gbWFpbGluZyBsaXN0Cmh0dHA6Ly9saXN0cy5pbmZyYWRl YWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtbXRkLwo= 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=-8.2 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,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 152B5C3A5A7 for ; Fri, 30 Aug 2019 09:47:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A460423427 for ; Fri, 30 Aug 2019 09:47:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727900AbfH3JrA convert rfc822-to-8bit (ORCPT ); Fri, 30 Aug 2019 05:47:00 -0400 Received: from relay1-d.mail.gandi.net ([217.70.183.193]:34825 "EHLO relay1-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725780AbfH3JrA (ORCPT ); Fri, 30 Aug 2019 05:47:00 -0400 X-Originating-IP: 86.250.200.211 Received: from xps13 (lfbn-1-17395-211.w86-250.abo.wanadoo.fr [86.250.200.211]) (Authenticated sender: miquel.raynal@bootlin.com) by relay1-d.mail.gandi.net (Postfix) with ESMTPSA id 8AE39240006; Fri, 30 Aug 2019 09:46:46 +0000 (UTC) Date: Fri, 30 Aug 2019 11:46:45 +0200 From: Miquel Raynal To: Piotr Sroka Cc: , Boris Brezillon , Richard Weinberger , David Woodhouse , Brian Norris , Marek Vasut , Paul Burton , Geert Uytterhoeven , Arnd Bergmann , Marcel Ziswiler , Dmitry Osipenko , Stefan Agner , , Kazuhiro Kasai Subject: Re: [v5 1/2] mtd: nand: Add new Cadence NAND driver to MTD subsystem Message-ID: <20190830114645.59898cfe@xps13> In-Reply-To: <20190725150012.14416-1-piotrs@cadence.com> References: <20190725145804.8886-1-piotrs@cadence.com> <20190725150012.14416-1-piotrs@cadence.com> Organization: Bootlin X-Mailer: Claws Mail 3.17.3 (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: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Piotr, Piotr Sroka wrote on Thu, 25 Jul 2019 16:00:12 +0100: Subject should be: mtd: rawnand: Last few nits in your driver which overall looks good (see below). Now I'm waiting for Rob's ack on the bindings. This driver should be a good candidate for 5.5. > Add new Cadence NAND driver to MTD subsystem > > Signed-off-by: Piotr Sroka > --- > Changes for v5: > - fix "ecc config strength" field size > - remove unused macros > - fix address of timing2 register > - add guard for accessing data_control_size register > - simplify the driver by use the same function > for accessing main area and oob area > - add comment to the driver describing main controller modes > - change compatible name from cdns,hpnfc to cdns,hp-nfc > Changes for v4: > - fix comments issues like typos, missing capitals, missing dots etc. > - remove unnecessary PHY options phy_dll_aging and phy_per_bit_deskew > - replace all register access functions to "relaxed" version > - remove all unnecessary variables initializations > - handle error inside cadence_nand_get_ecc_strength_idx function in case > correnction strength is not found > - add commit message > Changes for v3: > - remove definitions of unused registers > - remove configuring registers which are not expected to be configured in > asynchronous mode > - remove not needed function reading timing registers > - remove information about oob size and write size from cdns_nand_chip type > and use vales from mtd_info directly > - use nand_cleanup instead of nand_release if mtd device is not registered yet > - fix cadence_nand_chips_init function add garbage collection > if a chip init fails > - simplify PHY calculations > Changes for v2: > - create one universal wait function for all events instead of one > function per event. > - split one big function executing nand operations to separate > functions one per each type of operation. > - add erase atomic operation to nand operation parser > - remove unnecessary includes. > - remove unused register defines > - add support for multiple nand chips > - remove all code using legacy functions > - remove chip dependents parameters from dts bindings, they were > attached to the SoC specific compatible at the driver level > - simplify interrupt handling > - simplify timing calculations > - fix calculation of maximum supported cs signals > - simplify ecc size calculation > - remove header file and put whole code to one c file > --- > drivers/mtd/nand/raw/Kconfig | 7 + > drivers/mtd/nand/raw/Makefile | 1 + > drivers/mtd/nand/raw/cadence-nand-controller.c | 3021 ++++++++++++++++++++++++ > 3 files changed, 3029 insertions(+) > create mode 100644 drivers/mtd/nand/raw/cadence-nand-controller.c > > diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig > index e604625e2dfa..4d2ce3b5b2ae 100644 > --- a/drivers/mtd/nand/raw/Kconfig > +++ b/drivers/mtd/nand/raw/Kconfig > @@ -557,5 +557,12 @@ config MTD_NAND_MESON > help > Enables support for NAND controller on Amlogic's Meson SoCs. > This controller is found on Meson SoCs. Missing space? > +config MTD_NAND_CADENCE > + tristate "Support Cadence NAND (HPNFC) controller" > + depends on OF || COMPILE_TEST > + help > + Enable the driver for NAND flash on platforms using a Cadence NAND > + controller. > + > > endif # MTD_NAND > diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile > index 5a5a72f0793e..f4b099f276f7 100644 > --- a/drivers/mtd/nand/raw/Makefile > +++ b/drivers/mtd/nand/raw/Makefile > @@ -58,6 +58,7 @@ obj-$(CONFIG_MTD_NAND_MTK) += mtk_ecc.o mtk_nand.o > obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o > obj-$(CONFIG_MTD_NAND_STM32_FMC2) += stm32_fmc2_nand.o > obj-$(CONFIG_MTD_NAND_MESON) += meson_nand.o > +obj-$(CONFIG_MTD_NAND_CADENCE) += cadence-nand-controller.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/cadence-nand-controller.c b/drivers/mtd/nand/raw/cadence-nand-controller.c > new file mode 100644 > index 000000000000..a7ff4e4585d3 > --- /dev/null > +++ b/drivers/mtd/nand/raw/cadence-nand-controller.c > @@ -0,0 +1,3021 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Cadence NAND flash controller driver > + * > + * Copyright (C) 2019 Cadence I guess you deserve the Author: entry here :) > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* > + * HPNFC can work in 3 modes: > + * - PIO - can work in master or slave DMA. > + * - CDMA - needs Master DMA for accessing command descriptors. > + * - Generic mode - can use only slave DMA. > + * CDMA and PIO modes can be used to execute only base commands. > + * Generic mode can be used to execute any command > + * on NAND flash memory. Driver uses CDMA mode for > + * block erasing, page reading, page programing. > + * Generic mode is used for executing rest of commands. > + */ > + > +#define MAX_OOB_SIZE_PER_SECTOR 32 > +#define MAX_ADDRESS_CYC 6 > +#define MAX_ERASE_ADDRESS_CYC 3 > +#define MAX_DATA_SIZE 0xFFFC > + > +/* Register definition. */ > +/* > + * Command register 0. > + * Writing data to this register will initiate a new transaction > + * of the NF controller. > + */ > +#define CMD_REG0 0x0000 > +/* Command type field mask. */ > +#define CMD_REG0_CT GENMASK(31, 30) > +/* Command type CDMA. */ > +#define CMD_REG0_CT_CDMA 0uL > +/* Command type generic. */ > +#define CMD_REG0_CT_GEN 3uL > +/* Command thread number field mask. */ > +#define CMD_REG0_TN GENMASK(27, 24) > + > +/* Command register 2. */ > +#define CMD_REG2 0x0008 > +/* Command register 3. */ > +#define CMD_REG3 0x000C > +/* Pointer register to select which thread status will be selected. */ > +#define CMD_STATUS_PTR 0x0010 > +/* Command status register for selected thread. */ > +#define CMD_STATUS 0x0014 > + > +/* Interrupt status register. */ > +#define INTR_STATUS 0x0110 > +#define INTR_STATUS_SDMA_ERR BIT(22) > +#define INTR_STATUS_SDMA_TRIGG BIT(21) > +#define INTR_STATUS_UNSUPP_CMD BIT(19) > +#define INTR_STATUS_DDMA_TERR BIT(18) > +#define INTR_STATUS_CDMA_TERR BIT(17) > +#define INTR_STATUS_CDMA_IDL BIT(16) > + > +/* Interrupt enable register. */ > +#define INTR_ENABLE 0x0114 > +#define INTR_ENABLE_INTR_EN BIT(31) > +#define INTR_ENABLE_SDMA_ERR_EN BIT(22) > +#define INTR_ENABLE_SDMA_TRIGG_EN BIT(21) > +#define INTR_ENABLE_UNSUPP_CMD_EN BIT(19) > +#define INTR_ENABLE_DDMA_TERR_EN BIT(18) > +#define INTR_ENABLE_CDMA_TERR_EN BIT(17) > +#define INTR_ENABLE_CDMA_IDLE_EN BIT(16) > + > +/* Controller internal state. */ > +#define CTRL_STATUS 0x0118 > +#define CTRL_STATUS_INIT_COMP BIT(9) > +#define CTRL_STATUS_CTRL_BUSY BIT(8) > + > +/* Command Engine threads state. */ > +#define TRD_STATUS 0x0120 > + > +/* Command Engine interrupt thread error status. */ > +#define TRD_ERR_INT_STATUS 0x0128 > +/* Command Engine interrupt thread error enable. */ > +#define TRD_ERR_INT_STATUS_EN 0x0130 > +/* Command Engine interrupt thread complete status. */ > +#define TRD_COMP_INT_STATUS 0x0138 > + > +/* > + * Transfer config 0 register. > + * Configures data transfer parameters. > + */ > +#define TRAN_CFG_0 0x0400 > +/* Offset value from the beginning of the page. */ > +#define TRAN_CFG_0_OFFSET GENMASK(31, 16) > +/* Numbers of sectors to transfer within singlNF device's page. */ > +#define TRAN_CFG_0_SEC_CNT GENMASK(7, 0) > + > +/* > + * Transfer config 1 register. > + * Configures data transfer parameters. > + */ > +#define TRAN_CFG_1 0x0404 > +/* Size of last data sector. */ > +#define TRAN_CFG_1_LAST_SEC_SIZE GENMASK(31, 16) > +/* Size of not-last data sector. */ > +#define TRAN_CFG_1_SECTOR_SIZE GENMASK(15, 0) > + > +/* ECC engine configuration register 0. */ > +#define ECC_CONFIG_0 0x0428 > +/* Correction strength. */ > +#define ECC_CONFIG_0_CORR_STR GENMASK(10, 8) > +/* Enable erased pages detection mechanism. */ > +#define ECC_CONFIG_0_ERASE_DET_EN BIT(1) > +/* Enable controller ECC check bits generation and correction. */ > +#define ECC_CONFIG_0_ECC_EN BIT(0) > + > +/* ECC engine configuration register 1. */ > +#define ECC_CONFIG_1 0x042C > + > +/* Multiplane settings register. */ > +#define MULTIPLANE_CFG 0x0434 > +/* Cache operation settings. */ > +#define CACHE_CFG 0x0438 > + > +/* DMA settings register. */ > +#define DMA_SETINGS 0x043C > +/* Enable SDMA error report on access unprepared slave DMA interface. */ > +#define DMA_SETINGS_SDMA_ERR_RSP BIT(17) > + > +/* Transferred data block size for the slave DMA module. */ > +#define SDMA_SIZE 0x0440 > + > +/* Thread number associated with transferred data block > + * for the slave DMA module. > + */ > +#define SDMA_TRD_NUM 0x0444 > +/* Thread number mask. */ > +#define SDMA_TRD_NUM_SDMA_TRD GENMASK(2, 0) > + > +#define CONTROL_DATA_CTRL 0x0494 > +/* Thread number mask. */ > +#define CONTROL_DATA_CTRL_SIZE GENMASK(15, 0) > + > +#define CTRL_VERSION 0x800 > + > +/* Available hardware features of the controller. */ > +#define CTRL_FEATURES 0x804 > +/* Support for NV-DDR2/3 work mode. */ > +#define CTRL_FEATURES_NVDDR_2_3 BIT(28) > +/* Support for NV-DDR work mode. */ > +#define CTRL_FEATURES_NVDDR BIT(27) > +/* Support for asynchronous work mode. */ > +#define CTRL_FEATURES_ASYNC BIT(26) > +/* Support for asynchronous work mode. */ > +#define CTRL_FEATURES_N_BANKS GENMASK(25, 24) > +/* Slave and Master DMA data width. */ > +#define CTRL_FEATURES_DMA_DWITH64 BIT(21) > +/* Availability of Control Data feature.*/ > +#define CTRL_FEATURES_CONTROL_DATA BIT(10) > + > +/* BCH Engine identification register 0 - correction strengths. */ > +#define BCH_CFG_0 0x838 > +#define BCH_CFG_0_CORR_CAP_0 GENMASK(7, 0) > +#define BCH_CFG_0_CORR_CAP_1 GENMASK(15, 8) > +#define BCH_CFG_0_CORR_CAP_2 GENMASK(23, 16) > +#define BCH_CFG_0_CORR_CAP_3 GENMASK(31, 24) > + > +/* BCH Engine identification register 1 - correction strengths. */ > +#define BCH_CFG_1 0x83C > +#define BCH_CFG_1_CORR_CAP_4 GENMASK(7, 0) > +#define BCH_CFG_1_CORR_CAP_5 GENMASK(15, 8) > +#define BCH_CFG_1_CORR_CAP_6 GENMASK(23, 16) > +#define BCH_CFG_1_CORR_CAP_7 GENMASK(31, 24) > + > +/* BCH Engine identification register 2 - sector sizes. */ > +#define BCH_CFG_2 0x840 > +#define BCH_CFG_2_SECT_0 GENMASK(15, 0) > +#define BCH_CFG_2_SECT_1 GENMASK(31, 16) > + > +/* BCH Engine identification register 3. */ > +#define BCH_CFG_3 0x844 > + > +/* Ready/Busy# line status. */ > +#define RBN_SETINGS 0x1004 > + > +/* Common settings. */ > +#define COMMON_SET 0x1008 > +/* 16 bit device connected to the NAND Flash interface. */ > +#define COMMON_SET_DEVICE_16BIT BIT(8) > + > +/* Skip_bytes registers. */ > +#define SKIP_BYTES_CONF 0x100C > +#define SKIP_BYTES_MARKER_VALUE GENMASK(31, 16) > +#define SKIP_BYTES_NUM_OF_BYTES GENMASK(7, 0) > + > +#define SKIP_BYTES_OFFSET 0x1010 > +#define SKIP_BYTES_OFFSET_VALUE GENMASK(23, 0) > + > +/* Timings configuration. */ > +#define ASYNC_TOGGLE_TIMINGS 0x101c > +#define ASYNC_TOGGLE_TIMINGS_TRH GENMASK(28, 24) > +#define ASYNC_TOGGLE_TIMINGS_TRP GENMASK(20, 16) > +#define ASYNC_TOGGLE_TIMINGS_TWH GENMASK(12, 8) > +#define ASYNC_TOGGLE_TIMINGS_TWP GENMASK(4, 0) > + > +#define TIMINGS0 0x1024 > +#define TIMINGS0_TADL GENMASK(31, 24) > +#define TIMINGS0_TCCS GENMASK(23, 16) > +#define TIMINGS0_TWHR GENMASK(15, 8) > +#define TIMINGS0_TRHW GENMASK(7, 0) > + > +#define TIMINGS1 0x1028 > +#define TIMINGS1_TRHZ GENMASK(31, 24) > +#define TIMINGS1_TWB GENMASK(23, 16) > +#define TIMINGS1_TVDLY GENMASK(7, 0) > + > +#define TIMINGS2 0x102c > +#define TIMINGS2_TFEAT GENMASK(25, 16) > +#define TIMINGS2_CS_HOLD_TIME GENMASK(13, 8) > +#define TIMINGS2_CS_SETUP_TIME GENMASK(5, 0) > + > +/* Configuration of the resynchronization of slave DLL of PHY. */ > +#define DLL_PHY_CTRL 0x1034 > +#define DLL_PHY_CTRL_DLL_RST_N BIT(24) > +#define DLL_PHY_CTRL_EXTENDED_WR_MODE BIT(17) > +#define DLL_PHY_CTRL_EXTENDED_RD_MODE BIT(16) > +#define DLL_PHY_CTRL_RS_HIGH_WAIT_CNT GENMASK(11, 8) > +#define DLL_PHY_CTRL_RS_IDLE_CNT GENMASK(7, 0) > + > +/* Register controlling DQ related timing. */ > +#define PHY_DQ_TIMING 0x2000 > +/* Register controlling DSQ related timing. */ > +#define PHY_DQS_TIMING 0x2004 > +#define PHY_DQS_TIMING_DQS_SEL_OE_END GENMASK(3, 0) > +#define PHY_DQS_TIMING_PHONY_DQS_SEL BIT(16) > +#define PHY_DQS_TIMING_USE_PHONY_DQS BIT(20) > + > +/* Register controlling the gate and loopback control related timing. */ > +#define PHY_GATE_LPBK_CTRL 0x2008 > +#define PHY_GATE_LPBK_CTRL_RDS GENMASK(24, 19) > + > +/* Register holds the control for the master DLL logic. */ > +#define PHY_DLL_MASTER_CTRL 0x200C > +#define PHY_DLL_MASTER_CTRL_BYPASS_MODE BIT(23) > + > +/* Register holds the control for the slave DLL logic. */ > +#define PHY_DLL_SLAVE_CTRL 0x2010 > + > +/* This register handles the global control settings for the PHY. */ > +#define PHY_CTRL 0x2080 > +#define PHY_CTRL_SDR_DQS BIT(14) > +#define PHY_CTRL_PHONY_DQS GENMASK(9, 4) > + > +/* > + * This register handles the global control settings > + * for the termination selects for reads. > + */ > +#define PHY_TSEL 0x2084 > + > +/* Generic command layout. */ > +#define GCMD_LAY_CS GENMASK_ULL(11, 8) > +/* > + * This bit informs the minicotroller if it has to wait for tWB > + * after sending the last CMD/ADDR/DATA in the sequence. > + */ > +#define GCMD_LAY_TWB BIT_ULL(6) > +/* Type of generic instruction. */ > +#define GCMD_LAY_INSTR GENMASK_ULL(5, 0) > + > +/* Generic CMD sequence type. */ > +#define GCMD_LAY_INSTR_CMD 0 > +/* Generic ADDR sequence type. */ > +#define GCMD_LAY_INSTR_ADDR 1 > +/* Generic data transfer sequence type. */ > +#define GCMD_LAY_INSTR_DATA 2 > + > +/* Input part of generic command type of input is command. */ > +#define GCMD_LAY_INPUT_CMD GENMASK_ULL(23, 16) > + > +/* Generic command address sequence - address fields. */ > +#define GCMD_LAY_INPUT_ADDR GENMASK_ULL(63, 16) > +/* Generic command address sequence - address size. */ > +#define GCMD_LAY_INPUT_ADDR_SIZE GENMASK_ULL(13, 11) > + > +/* Transfer direction field of generic command data sequence. */ > +#define GCMD_DIR BIT_ULL(11) > +/* Read transfer direction of generic command data sequence. */ > +#define GCMD_DIR_READ 0 > +/* Write transfer direction of generic command data sequence. */ > +#define GCMD_DIR_WRITE 1 > + > +/* ECC enabled flag of generic command data sequence - ECC enabled. */ > +#define GCMD_ECC_EN BIT_ULL(12) > +/* Generic command data sequence - sector size. */ > +#define GCMD_SECT_SIZE GENMASK_ULL(31, 16) > +/* Generic command data sequence - sector count. */ > +#define GCMD_SECT_CNT GENMASK_ULL(39, 32) > +/* Generic command data sequence - last sector size. */ > +#define GCMD_LAST_SIZE GENMASK_ULL(55, 40) > + > +/* CDMA descriptor fields. */ > +/* Erase command type of CDMA descriptor. */ > +#define CDMA_CT_ERASE 0x1000 > +/* Program page command type of CDMA descriptor. */ > +#define CDMA_CT_WR 0x2100 > +/* Read page command type of CDMA descriptor. */ > +#define CDMA_CT_RD 0x2200 > + > +/* Flash pointer memory shift. */ > +#define CDMA_CFPTR_MEM_SHIFT 24 > +/* Flash pointer memory mask. */ > +#define CDMA_CFPTR_MEM GENMASK(26, 24) > + > +/* > + * Command DMA descriptor flags. If set causes issue interrupt after > + * the completion of descriptor processing. > + */ > +#define CDMA_CF_INT BIT(8) > +/* > + * Command DMA descriptor flags - the next descriptor > + * address field is valid and descriptor processing should continue. > + */ > +#define CDMA_CF_CONT BIT(9) > +/* DMA master flag of command DMA descriptor. */ > +#define CDMA_CF_DMA_MASTER BIT(10) > + > +/* Operation complete status of command descriptor. */ > +#define CDMA_CS_COMP BIT(15) > +/* Operation complete status of command descriptor. */ > +/* Command descriptor status - operation fail. */ > +#define CDMA_CS_FAIL BIT(14) > +/* Command descriptor status - page erased. */ > +#define CDMA_CS_ERP BIT(11) > +/* Command descriptor status - timeout occurred. */ > +#define CDMA_CS_TOUT BIT(10) > +/* > + * Maximum amount of correction applied to one ECC sector. > + * It is part of command descriptor status. > + */ > +#define CDMA_CS_MAXERR GENMASK(9, 2) > +/* Command descriptor status - uncorrectable ECC error. */ > +#define CDMA_CS_UNCE BIT(1) > +/* Command descriptor status - descriptor error. */ > +#define CDMA_CS_ERR BIT(0) > + > +/* Status of operation - OK. */ > +#define STAT_OK 0 > +/* Status of operation - FAIL. */ > +#define STAT_FAIL 2 > +/* Status of operation - uncorrectable ECC error. */ > +#define STAT_ECC_UNCORR 3 > +/* Status of operation - page erased. */ > +#define STAT_ERASED 5 > +/* Status of operation - correctable ECC error. */ > +#define STAT_ECC_CORR 6 > +/* Status of operation - unsuspected state. */ > +#define STAT_UNKNOWN 7 > +/* Status of operation - operation is not completed yet. */ > +#define STAT_BUSY 0xFF > + > +#define BCH_MAX_NUM_CORR_CAPS 8 > +#define BCH_MAX_NUM_SECTOR_SIZES 2 > + > +struct cadence_nand_timings { > + u32 async_toggle_timings; > + u32 timings0; > + u32 timings1; > + u32 timings2; > + u32 dll_phy_ctrl; > + u32 phy_ctrl; > + u32 phy_dqs_timing; > + u32 phy_gate_lpbk_ctrl; > +}; > + > +/* Command DMA descriptor. */ > +struct cadence_nand_cdma_desc { > + /* Next descriptor address. */ > + u64 next_pointer; > + > + /* Flash address is a 32-bit address comprising of BANK and ROW ADDR. */ > + u32 flash_pointer; > + u32 rsvd0; > + > + /* Operation the controller needs to perform. */ > + u16 command_type; > + u16 rsvd1; > + /* Flags for operation of this command. */ > + u16 command_flags; > + u16 rsvd2; > + > + /* System/host memory address required for data DMA commands. */ > + u64 memory_pointer; > + > + /* Status of operation. */ > + u32 status; > + u32 rsvd3; > + > + /* Address pointer to sync buffer location. */ > + u64 sync_flag_pointer; > + > + /* Controls the buffer sync mechanism. */ > + u32 sync_arguments; > + u32 rsvd4; > + > + /* Control data pointer. */ > + u64 ctrl_data_ptr; > +}; > + > +/* Interrupt status. */ > +struct cadence_nand_irq_status { > + /* Thread operation complete status. */ > + u32 trd_status; > + /* Thread operation error. */ > + u32 trd_error; > + /* Controller status. */ > + u32 status; > +}; > + > +/* Cadence NAND flash controller capabilities get from driver data. */ > +struct cadence_nand_dt_devdata { > + /* Skew value of the output signals of the NAND Flash interface. */ > + u32 if_skew; > + /* It informs if slave DMA interface is connected to DMA engine. */ > + unsigned int has_dma:1; > +}; > + > +/* Cadence NAND flash controller capabilities read from registers. */ > +struct cdns_nand_caps { > + /* Maximum number of banks supported by hardware. */ > + u8 max_banks; > + /* Slave and Master DMA data width in bytes (4 or 8). */ > + u8 data_dma_width; > + /* Control Data feature supported. */ > + u8 data_control_supp; > + /* Is PHY type DLL. */ > + u8 is_phy_type_dll; > +}; > + > +struct cdns_nand_ctrl { > + struct device *dev; > + struct nand_controller controller; > + struct cadence_nand_cdma_desc *cdma_desc; > + /* IP capability. */ > + const struct cadence_nand_dt_devdata *caps1; > + struct cdns_nand_caps caps2; > + dma_addr_t dma_cdma_desc; > + u8 *buf; > + u32 buf_size; > + u8 curr_corr_str_idx; > + > + /* Register interface. */ > + void __iomem *reg; > + > + struct { > + void __iomem *virt; > + dma_addr_t dma; > + } io; > + > + int irq; > + /* Interrupts that have happened. */ > + struct cadence_nand_irq_status irq_status; > + /* Interrupts we are waiting for. */ > + struct cadence_nand_irq_status irq_mask; > + struct completion complete; > + /* Protect irq_mask and irq_status. */ > + spinlock_t irq_lock; > + > + int ecc_strengths[BCH_MAX_NUM_CORR_CAPS]; > + struct nand_ecc_step_info ecc_stepinfos[BCH_MAX_NUM_SECTOR_SIZES]; > + struct nand_ecc_caps ecc_caps; > + > + int curr_trans_type; > + > + struct dma_chan *dmac; > + > + u32 nf_clk_rate; > + /* > + * Estimated Board delay. The value includes the total > + * round trip delay for the signals and is used for deciding on values > + * associated with data read capture. > + */ > + u32 board_delay; > + > + struct nand_chip *selected_chip; > + > + unsigned long assigned_cs; > + struct list_head chips; > +}; > + > +struct cdns_nand_chip { > + struct cadence_nand_timings timings; > + struct nand_chip chip; > + u8 nsels; > + struct list_head node; > + > + /* > + * part of oob area of NAND flash memory page. > + * This part is available for user to read or write. > + */ > + u32 avail_oob_size; > + > + /* Sector size. There are few sectors per mtd->writesize */ > + u32 sector_size; > + u32 sector_count; > + > + /* Offset of BBM. */ > + u8 bbm_offs; > + /* Number of bytes reserved for BBM. */ > + u8 bbm_len; > + /* ECC strength index. */ > + u8 corr_str_idx; > + > + u8 cs[]; > +}; > + > +struct ecc_info { > + int (*calc_ecc_bytes)(int step_size, int strength); > + int max_step_size; > +}; > + > +static inline struct > +cdns_nand_chip *to_cdns_nand_chip(struct nand_chip *chip) > +{ > + return container_of(chip, struct cdns_nand_chip, chip); > +} > + > +static inline struct > +cdns_nand_ctrl *to_cdns_nand_ctrl(struct nand_controller *controller) > +{ > + return container_of(controller, struct cdns_nand_ctrl, controller); > +} > + > +static bool > +cadence_nand_dma_buf_ok(struct cdns_nand_ctrl *cdns_ctrl, const void *buf, > + u32 buf_len) > +{ > + u8 data_dma_width = cdns_ctrl->caps2.data_dma_width; > + > + return buf && virt_addr_valid(buf) && > + likely(IS_ALIGNED((uintptr_t)buf, data_dma_width)) && > + likely(IS_ALIGNED(buf_len, data_dma_width)); > +} > + > +static int cadence_nand_wait_for_value(struct cdns_nand_ctrl *cdns_ctrl, > + u32 reg_offset, u32 timeout_us, > + u32 mask, bool is_clear) > +{ > + u32 val; > + int ret; > + > + ret = readl_relaxed_poll_timeout(cdns_ctrl->reg + reg_offset, > + val, !(val & mask) == is_clear, > + 10, timeout_us); > + > + if (ret < 0) { > + dev_err(cdns_ctrl->dev, > + "Timeout while waiting for reg %x with mask %x is clear %d\n", > + reg_offset, mask, is_clear); > + } > + > + return ret; > +} > + > +static int cadence_nand_set_ecc_enable(struct cdns_nand_ctrl *cdns_ctrl, > + bool enable) > +{ > + u32 reg; > + > + if (cadence_nand_wait_for_value(cdns_ctrl, CTRL_STATUS, > + 1000000, > + CTRL_STATUS_CTRL_BUSY, true)) > + return -ETIMEDOUT; > + > + reg = readl_relaxed(cdns_ctrl->reg + ECC_CONFIG_0); > + > + if (enable) > + reg |= ECC_CONFIG_0_ECC_EN; > + else > + reg &= ~ECC_CONFIG_0_ECC_EN; > + > + writel_relaxed(reg, cdns_ctrl->reg + ECC_CONFIG_0); > + > + return 0; > +} > + > +static void cadence_nand_set_ecc_strength(struct cdns_nand_ctrl *cdns_ctrl, > + u8 corr_str_idx) > +{ > + u32 reg; > + > + if (cdns_ctrl->curr_corr_str_idx == corr_str_idx) > + return; > + > + reg = readl_relaxed(cdns_ctrl->reg + ECC_CONFIG_0); > + reg &= ~ECC_CONFIG_0_CORR_STR; > + reg |= FIELD_PREP(ECC_CONFIG_0_CORR_STR, corr_str_idx); > + writel_relaxed(reg, cdns_ctrl->reg + ECC_CONFIG_0); > + > + cdns_ctrl->curr_corr_str_idx = corr_str_idx; > +} > + > +static int cadence_nand_get_ecc_strength_idx(struct cdns_nand_ctrl *cdns_ctrl, > + u8 strength) > +{ > + int i, corr_str_idx = -1; > + > + for (i = 0; i < BCH_MAX_NUM_CORR_CAPS; i++) { > + if (cdns_ctrl->ecc_strengths[i] == strength) { > + corr_str_idx = i; > + break; > + } > + } > + > + return corr_str_idx; > +} > + > +static int cadence_nand_set_skip_marker_val(struct cdns_nand_ctrl *cdns_ctrl, > + u16 marker_value) > +{ > + u32 reg; > + > + if (cadence_nand_wait_for_value(cdns_ctrl, CTRL_STATUS, > + 1000000, > + CTRL_STATUS_CTRL_BUSY, true)) > + return -ETIMEDOUT; > + > + reg = readl_relaxed(cdns_ctrl->reg + SKIP_BYTES_CONF); > + reg &= ~SKIP_BYTES_MARKER_VALUE; > + reg |= FIELD_PREP(SKIP_BYTES_MARKER_VALUE, > + marker_value); > + > + writel_relaxed(reg, cdns_ctrl->reg + SKIP_BYTES_CONF); > + > + return 0; > +} > + > +static int cadence_nand_set_skip_bytes_conf(struct cdns_nand_ctrl *cdns_ctrl, > + u8 num_of_bytes, > + u32 offset_value, > + int enable) > +{ > + u32 reg, skip_bytes_offset; > + > + if (cadence_nand_wait_for_value(cdns_ctrl, CTRL_STATUS, > + 1000000, > + CTRL_STATUS_CTRL_BUSY, true)) > + return -ETIMEDOUT; > + > + if (!enable) { > + num_of_bytes = 0; > + offset_value = 0; > + } > + > + reg = readl_relaxed(cdns_ctrl->reg + SKIP_BYTES_CONF); > + reg &= ~SKIP_BYTES_NUM_OF_BYTES; > + reg |= FIELD_PREP(SKIP_BYTES_NUM_OF_BYTES, > + num_of_bytes); > + skip_bytes_offset = FIELD_PREP(SKIP_BYTES_OFFSET_VALUE, > + offset_value); > + > + writel_relaxed(reg, cdns_ctrl->reg + SKIP_BYTES_CONF); > + writel_relaxed(skip_bytes_offset, cdns_ctrl->reg + SKIP_BYTES_OFFSET); > + > + return 0; > +} > + > +/* Functions enables/disables hardware detection of erased data */ > +static void cadence_nand_set_erase_detection(struct cdns_nand_ctrl *cdns_ctrl, > + bool enable, > + u8 bitflips_threshold) > +{ > + u32 reg; > + > + reg = readl_relaxed(cdns_ctrl->reg + ECC_CONFIG_0); > + > + if (enable) > + reg |= ECC_CONFIG_0_ERASE_DET_EN; > + else > + reg &= ~ECC_CONFIG_0_ERASE_DET_EN; > + > + writel_relaxed(reg, cdns_ctrl->reg + ECC_CONFIG_0); > + writel_relaxed(bitflips_threshold, cdns_ctrl->reg + ECC_CONFIG_1); > +} > + > +static int cadence_nand_set_access_width16(struct cdns_nand_ctrl *cdns_ctrl, > + bool bit_bus16) > +{ > + u32 reg; > + > + if (cadence_nand_wait_for_value(cdns_ctrl, CTRL_STATUS, > + 1000000, > + CTRL_STATUS_CTRL_BUSY, true)) > + return -ETIMEDOUT; > + > + reg = readl_relaxed(cdns_ctrl->reg + COMMON_SET); > + > + if (!bit_bus16) > + reg &= ~COMMON_SET_DEVICE_16BIT; > + else > + reg |= COMMON_SET_DEVICE_16BIT; > + writel_relaxed(reg, cdns_ctrl->reg + COMMON_SET); > + > + return 0; > +} > + > +static void > +cadence_nand_clear_interrupt(struct cdns_nand_ctrl *cdns_ctrl, > + struct cadence_nand_irq_status *irq_status) > +{ > + writel_relaxed(irq_status->status, cdns_ctrl->reg + INTR_STATUS); > + writel_relaxed(irq_status->trd_status, > + cdns_ctrl->reg + TRD_COMP_INT_STATUS); > + writel_relaxed(irq_status->trd_error, > + cdns_ctrl->reg + TRD_ERR_INT_STATUS); > +} > + > +static void > +cadence_nand_read_int_status(struct cdns_nand_ctrl *cdns_ctrl, > + struct cadence_nand_irq_status *irq_status) > +{ > + irq_status->status = readl_relaxed(cdns_ctrl->reg + INTR_STATUS); > + irq_status->trd_status = readl_relaxed(cdns_ctrl->reg > + + TRD_COMP_INT_STATUS); > + irq_status->trd_error = readl_relaxed(cdns_ctrl->reg > + + TRD_ERR_INT_STATUS); > +} > + > +static u32 irq_detected(struct cdns_nand_ctrl *cdns_ctrl, > + struct cadence_nand_irq_status *irq_status) > +{ > + cadence_nand_read_int_status(cdns_ctrl, irq_status); > + > + return irq_status->status || irq_status->trd_status || > + irq_status->trd_error; > +} > + > +static void cadence_nand_reset_irq(struct cdns_nand_ctrl *cdns_ctrl) > +{ > + spin_lock(&cdns_ctrl->irq_lock); > + memset(&cdns_ctrl->irq_status, 0, sizeof(cdns_ctrl->irq_status)); > + memset(&cdns_ctrl->irq_mask, 0, sizeof(cdns_ctrl->irq_mask)); > + spin_unlock(&cdns_ctrl->irq_lock); > +} > + > +/* > + * This is the interrupt service routine. It handles all interrupts > + * sent to this device. > + */ > +static irqreturn_t cadence_nand_isr(int irq, void *dev_id) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = dev_id; > + struct cadence_nand_irq_status irq_status; > + irqreturn_t result = IRQ_NONE; > + > + spin_lock(&cdns_ctrl->irq_lock); > + > + if (irq_detected(cdns_ctrl, &irq_status)) { > + /* Handle interrupt. */ > + /* First acknowledge it. */ > + cadence_nand_clear_interrupt(cdns_ctrl, &irq_status); > + /* Status in the device context for someone to read. */ > + cdns_ctrl->irq_status.status |= irq_status.status; > + cdns_ctrl->irq_status.trd_status |= irq_status.trd_status; > + cdns_ctrl->irq_status.trd_error |= irq_status.trd_error; > + /* Notify anyone who cares that it happened. */ > + complete(&cdns_ctrl->complete); > + /* Tell the OS that we've handled this. */ > + result = IRQ_HANDLED; > + } > + spin_unlock(&cdns_ctrl->irq_lock); Your locking scheme seems wrong (maybe I'm not going deep enough in the code), can you please try with LOCKDEP enabled? > + > + return result; > +} > + > +static void cadence_nand_set_irq_mask(struct cdns_nand_ctrl *cdns_ctrl, > + struct cadence_nand_irq_status *irq_mask) > +{ > + writel_relaxed(INTR_ENABLE_INTR_EN | irq_mask->status, > + cdns_ctrl->reg + INTR_ENABLE); > + > + writel_relaxed(irq_mask->trd_error, > + cdns_ctrl->reg + TRD_ERR_INT_STATUS_EN); > +} > + > +static void > +cadence_nand_wait_for_irq(struct cdns_nand_ctrl *cdns_ctrl, > + struct cadence_nand_irq_status *irq_mask, > + struct cadence_nand_irq_status *irq_status) > +{ > + unsigned long timeout = msecs_to_jiffies(10000); > + unsigned long time_left; > + > + time_left = wait_for_completion_timeout(&cdns_ctrl->complete, > + timeout); > + > + *irq_status = cdns_ctrl->irq_status; > + if (time_left == 0) { > + /* Timeout error. */ > + dev_err(cdns_ctrl->dev, "timeout occurred:\n"); > + dev_err(cdns_ctrl->dev, "\tstatus = 0x%x, mask = 0x%x\n", > + irq_status->status, irq_mask->status); > + dev_err(cdns_ctrl->dev, > + "\ttrd_status = 0x%x, trd_status mask = 0x%x\n", > + irq_status->trd_status, irq_mask->trd_status); > + dev_err(cdns_ctrl->dev, > + "\t trd_error = 0x%x, trd_error mask = 0x%x\n", > + irq_status->trd_error, irq_mask->trd_error); > + } > +} > + > +static void > +cadence_nand_irq_cleanup(int irqnum, struct cdns_nand_ctrl *cdns_ctrl) > +{ > + /* Disable interrupts. */ > + writel_relaxed(INTR_ENABLE_INTR_EN, cdns_ctrl->reg + INTR_ENABLE); > +} Would you mind moving this helper to the bottom, where it is used (closer to the remove/cleanup functions). > + > +/* Execute generic command on NAND controller. */ > +static int cadence_nand_generic_cmd_send(struct cdns_nand_ctrl *cdns_ctrl, > + u8 chip_nr, > + u64 mini_ctrl_cmd) > +{ > + u32 mini_ctrl_cmd_l, mini_ctrl_cmd_h, reg; > + > + mini_ctrl_cmd |= FIELD_PREP(GCMD_LAY_CS, chip_nr); > + mini_ctrl_cmd_l = mini_ctrl_cmd & 0xFFFFFFFF; > + mini_ctrl_cmd_h = mini_ctrl_cmd >> 32; > + > + if (cadence_nand_wait_for_value(cdns_ctrl, CTRL_STATUS, > + 1000000, > + CTRL_STATUS_CTRL_BUSY, true)) > + return -ETIMEDOUT; > + > + cadence_nand_reset_irq(cdns_ctrl); > + > + writel_relaxed(mini_ctrl_cmd_l, cdns_ctrl->reg + CMD_REG2); > + writel_relaxed(mini_ctrl_cmd_h, cdns_ctrl->reg + CMD_REG3); > + > + /* Select generic command. */ > + reg = FIELD_PREP(CMD_REG0_CT, CMD_REG0_CT_GEN); > + /* Thread number. */ > + reg |= FIELD_PREP(CMD_REG0_TN, 0); > + > + /* Issue command. */ > + writel_relaxed(reg, cdns_ctrl->reg + CMD_REG0); > + > + return 0; > +} > + > +/* Wait for data on slave DMA interface. */ > +static int cadence_nand_wait_on_sdma(struct cdns_nand_ctrl *cdns_ctrl, > + u8 *out_sdma_trd, > + u32 *out_sdma_size) > +{ > + struct cadence_nand_irq_status irq_mask, irq_status; > + > + irq_mask.trd_status = 0; > + irq_mask.trd_error = 0; > + irq_mask.status = INTR_STATUS_SDMA_TRIGG > + | INTR_STATUS_SDMA_ERR > + | INTR_STATUS_UNSUPP_CMD; > + > + cadence_nand_set_irq_mask(cdns_ctrl, &irq_mask); > + cadence_nand_wait_for_irq(cdns_ctrl, &irq_mask, &irq_status); > + if (irq_status.status == 0) { > + dev_err(cdns_ctrl->dev, "Timeout while waiting for SDMA\n"); > + return -ETIMEDOUT; > + } > + > + if (irq_status.status & INTR_STATUS_SDMA_TRIGG) { > + *out_sdma_size = readl_relaxed(cdns_ctrl->reg + SDMA_SIZE); > + *out_sdma_trd = readl_relaxed(cdns_ctrl->reg + SDMA_TRD_NUM); > + *out_sdma_trd = > + FIELD_GET(SDMA_TRD_NUM_SDMA_TRD, *out_sdma_trd); > + } else { > + dev_err(cdns_ctrl->dev, "SDMA error - irq_status %x\n", > + irq_status.status); > + return -EIO; > + } > + > + return 0; > +} > + > +static void cadence_nand_get_caps(struct cdns_nand_ctrl *cdns_ctrl) > +{ > + u32 reg; > + > + reg = readl_relaxed(cdns_ctrl->reg + CTRL_FEATURES); > + > + cdns_ctrl->caps2.max_banks = 1 << FIELD_GET(CTRL_FEATURES_N_BANKS, reg); > + > + if (FIELD_GET(CTRL_FEATURES_DMA_DWITH64, reg)) > + cdns_ctrl->caps2.data_dma_width = 8; > + else > + cdns_ctrl->caps2.data_dma_width = 4; > + > + if (reg & CTRL_FEATURES_CONTROL_DATA) > + cdns_ctrl->caps2.data_control_supp = 1; > + > + if (reg & (CTRL_FEATURES_NVDDR_2_3 > + | CTRL_FEATURES_NVDDR)) > + cdns_ctrl->caps2.is_phy_type_dll = 1; > +} > + > +/* Prepare CDMA descriptor. */ > +static void > +cadence_nand_cdma_desc_prepare(struct cadence_nand_cdma_desc *cdma_desc, > + char nf_mem, u32 flash_ptr, char *mem_ptr, > + char *ctrl_data_ptr, u16 ctype) > +{ > + memset(cdma_desc, 0, sizeof(struct cadence_nand_cdma_desc)); > + > + /* Set fields for one descriptor. */ > + cdma_desc->flash_pointer = (nf_mem << CDMA_CFPTR_MEM_SHIFT) > + + flash_ptr; > + cdma_desc->command_flags |= CDMA_CF_DMA_MASTER; > + cdma_desc->command_flags |= CDMA_CF_INT; > + > + cdma_desc->memory_pointer = (uintptr_t)mem_ptr; > + cdma_desc->status = 0; > + cdma_desc->sync_flag_pointer = 0; > + cdma_desc->sync_arguments = 0; > + > + cdma_desc->command_type = ctype; > + cdma_desc->ctrl_data_ptr = (uintptr_t)ctrl_data_ptr; > +} > + > +static u8 cadence_nand_check_desc_error(struct cdns_nand_ctrl *cdns_ctrl, > + u32 desc_status) > +{ > + if (desc_status & CDMA_CS_ERP) > + return STAT_ERASED; > + > + if (desc_status & CDMA_CS_UNCE) > + return STAT_ECC_UNCORR; > + > + if (desc_status & CDMA_CS_ERR) { > + dev_err(cdns_ctrl->dev, ":CDMA desc error flag detected.\n"); > + return STAT_FAIL; > + } > + > + if (FIELD_GET(CDMA_CS_MAXERR, desc_status)) > + return STAT_ECC_CORR; > + > + return STAT_FAIL; > +} > + > +static int cadence_nand_cdma_finish(struct cdns_nand_ctrl *cdns_ctrl, > + struct cadence_nand_cdma_desc *cdma_desc) > +{ > + struct cadence_nand_cdma_desc *desc_ptr = cdma_desc; > + u8 status = STAT_BUSY; > + > + if (desc_ptr->status & CDMA_CS_FAIL) { > + status = cadence_nand_check_desc_error(cdns_ctrl, > + desc_ptr->status); > + dev_err(cdns_ctrl->dev, ":CDMA error %x\n", desc_ptr->status); > + } else if (desc_ptr->status & CDMA_CS_COMP) { > + /* Descriptor finished with no errors. */ > + if (desc_ptr->command_flags & CDMA_CF_CONT) { > + dev_info(cdns_ctrl->dev, "DMA unsupported flag is set"); > + status = STAT_UNKNOWN; > + } else { > + /* Last descriptor. */ > + status = STAT_OK; > + } > + } > + > + return status; > +} > + > +static int cadence_nand_cdma_send(struct cdns_nand_ctrl *cdns_ctrl, > + u8 thread) > +{ > + u32 reg; > + int status; > + > + /* Wait for thread ready. */ > + status = cadence_nand_wait_for_value(cdns_ctrl, TRD_STATUS, > + 1000000, > + 1U << thread, true); > + if (status) > + return status; > + > + cadence_nand_reset_irq(cdns_ctrl); > + > + writel_relaxed((u32)cdns_ctrl->dma_cdma_desc, > + cdns_ctrl->reg + CMD_REG2); > + writel_relaxed(0, cdns_ctrl->reg + CMD_REG3); > + > + /* Select CDMA mode. */ > + reg = FIELD_PREP(CMD_REG0_CT, CMD_REG0_CT_CDMA); > + /* Thread number. */ > + reg |= FIELD_PREP(CMD_REG0_TN, thread); > + /* Issue command. */ > + writel_relaxed(reg, cdns_ctrl->reg + CMD_REG0); > + > + return 0; > +} > + > +/* Send SDMA command and wait for finish. */ > +static u32 > +cadence_nand_cdma_send_and_wait(struct cdns_nand_ctrl *cdns_ctrl, > + u8 thread) > +{ > + struct cadence_nand_irq_status irq_mask, irq_status = {0}; > + int status; > + > + irq_mask.trd_status = 1 << thread; > + irq_mask.trd_error = 1 << thread; > + irq_mask.status = INTR_STATUS_CDMA_TERR; > + > + cadence_nand_set_irq_mask(cdns_ctrl, &irq_mask); > + > + status = cadence_nand_cdma_send(cdns_ctrl, thread); > + if (status) > + return status; > + > + cadence_nand_wait_for_irq(cdns_ctrl, &irq_mask, &irq_status); > + > + if (irq_status.status == 0 && irq_status.trd_status == 0 && > + irq_status.trd_error == 0) { > + dev_err(cdns_ctrl->dev, "CDMA command timeout\n"); > + return -ETIMEDOUT; > + } > + if (irq_status.status & irq_mask.status) { > + dev_err(cdns_ctrl->dev, "CDMA command failed\n"); > + return -EIO; > + } > + > + return 0; > +} > + > +/* > + * ECC size depends on configured ECC strength and on maximum supported > + * ECC step size. > + */ > +static int cadence_nand_calc_ecc_bytes(int max_step_size, int strength) > +{ > + int nbytes = DIV_ROUND_UP(fls(8 * max_step_size) * strength, 8); > + > + return ALIGN(nbytes, 2); > +} > + > +#define CADENCE_NAND_CALC_ECC_BYTES(max_step_size) \ > + static int \ > + cadence_nand_calc_ecc_bytes_##max_step_size(int step_size, \ > + int strength)\ > + {\ > + return cadence_nand_calc_ecc_bytes(max_step_size, strength);\ > + } > + > +CADENCE_NAND_CALC_ECC_BYTES(256) > +CADENCE_NAND_CALC_ECC_BYTES(512) > +CADENCE_NAND_CALC_ECC_BYTES(1024) > +CADENCE_NAND_CALC_ECC_BYTES(2048) > +CADENCE_NAND_CALC_ECC_BYTES(4096) > + > +/* Function reads BCH capabilities. */ > +static int cadence_nand_read_bch_caps(struct cdns_nand_ctrl *cdns_ctrl) > +{ > + struct nand_ecc_caps *ecc_caps = &cdns_ctrl->ecc_caps; > + int max_step_size = 0, nstrengths, i; > + u32 reg; > + > + reg = readl_relaxed(cdns_ctrl->reg + BCH_CFG_0); > + cdns_ctrl->ecc_strengths[0] = FIELD_GET(BCH_CFG_0_CORR_CAP_0, reg); > + cdns_ctrl->ecc_strengths[1] = FIELD_GET(BCH_CFG_0_CORR_CAP_1, reg); > + cdns_ctrl->ecc_strengths[2] = FIELD_GET(BCH_CFG_0_CORR_CAP_2, reg); > + cdns_ctrl->ecc_strengths[3] = FIELD_GET(BCH_CFG_0_CORR_CAP_3, reg); > + > + reg = readl_relaxed(cdns_ctrl->reg + BCH_CFG_1); > + cdns_ctrl->ecc_strengths[4] = FIELD_GET(BCH_CFG_1_CORR_CAP_4, reg); > + cdns_ctrl->ecc_strengths[5] = FIELD_GET(BCH_CFG_1_CORR_CAP_5, reg); > + cdns_ctrl->ecc_strengths[6] = FIELD_GET(BCH_CFG_1_CORR_CAP_6, reg); > + cdns_ctrl->ecc_strengths[7] = FIELD_GET(BCH_CFG_1_CORR_CAP_7, reg); > + > + reg = readl_relaxed(cdns_ctrl->reg + BCH_CFG_2); > + cdns_ctrl->ecc_stepinfos[0].stepsize = > + FIELD_GET(BCH_CFG_2_SECT_0, reg); > + > + cdns_ctrl->ecc_stepinfos[1].stepsize = > + FIELD_GET(BCH_CFG_2_SECT_1, reg); > + > + nstrengths = 0; > + for (i = 0; i < BCH_MAX_NUM_CORR_CAPS; i++) { > + if (cdns_ctrl->ecc_strengths[i] != 0) > + nstrengths++; > + } > + > + ecc_caps->nstepinfos = 0; > + for (i = 0; i < BCH_MAX_NUM_SECTOR_SIZES; i++) { > + /* ECC strengths are common for all step infos. */ > + cdns_ctrl->ecc_stepinfos[i].nstrengths = nstrengths; > + cdns_ctrl->ecc_stepinfos[i].strengths = > + cdns_ctrl->ecc_strengths; > + > + if (cdns_ctrl->ecc_stepinfos[i].stepsize != 0) > + ecc_caps->nstepinfos++; > + > + if (cdns_ctrl->ecc_stepinfos[i].stepsize > max_step_size) > + max_step_size = cdns_ctrl->ecc_stepinfos[i].stepsize; > + } > + ecc_caps->stepinfos = &cdns_ctrl->ecc_stepinfos[0]; > + > + switch (max_step_size) { > + case 256: > + ecc_caps->calc_ecc_bytes = &cadence_nand_calc_ecc_bytes_256; > + break; > + case 512: > + ecc_caps->calc_ecc_bytes = &cadence_nand_calc_ecc_bytes_512; > + break; > + case 1024: > + ecc_caps->calc_ecc_bytes = &cadence_nand_calc_ecc_bytes_1024; > + break; > + case 2048: > + ecc_caps->calc_ecc_bytes = &cadence_nand_calc_ecc_bytes_2048; > + break; > + case 4096: > + ecc_caps->calc_ecc_bytes = &cadence_nand_calc_ecc_bytes_4096; > + break; > + default: > + dev_err(cdns_ctrl->dev, > + "Unsupported sector size(ecc step size) %d\n", > + max_step_size); > + return -EIO; > + } > + > + return 0; > +} > + > +/* Hardware initialization. */ > +static int cadence_nand_hw_init(struct cdns_nand_ctrl *cdns_ctrl) > +{ > + int status; > + u32 reg; > + > + status = cadence_nand_wait_for_value(cdns_ctrl, CTRL_STATUS, > + 1000000, > + CTRL_STATUS_INIT_COMP, false); > + if (status) > + return status; > + > + reg = readl_relaxed(cdns_ctrl->reg + CTRL_VERSION); > + > + dev_info(cdns_ctrl->dev, > + "%s: cadence nand controller version reg %x\n", > + __func__, reg); > + > + /* Disable cache and multiplane. */ > + writel_relaxed(0, cdns_ctrl->reg + MULTIPLANE_CFG); > + writel_relaxed(0, cdns_ctrl->reg + CACHE_CFG); Cache? > + > + /* Clear all interrupts. */ > + writel_relaxed(0xFFFFFFFF, cdns_ctrl->reg + INTR_STATUS); > + > + cadence_nand_get_caps(cdns_ctrl); > + cadence_nand_read_bch_caps(cdns_ctrl); > + > + /* > + * Set IO width access to 8. > + * It is because during SW device discovering width access > + * is expected to be 8. > + */ > + status = cadence_nand_set_access_width16(cdns_ctrl, false); > + > + return status; > +} > + > +#define TT_MAIN_OOB_AREAS 2 > +#define TT_RAW_PAGE 3 > +#define TT_BBM 4 > +#define TT_MAIN_OOB_AREA_EXT 5 > + > +/* Prepare size of data to transfer. */ > +static void > +cadence_nand_prepare_data_size(struct nand_chip *chip, > + int transfer_type) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + struct mtd_info *mtd = nand_to_mtd(chip); > + u32 sec_size = 0, offset = 0, sec_cnt = 1; > + u32 last_sec_size = cdns_chip->sector_size; > + u32 ecc_size = chip->ecc.bytes; > + u32 data_ctrl_size = 0; > + u32 reg = 0; > + > + if (cdns_ctrl->curr_trans_type == transfer_type) > + return; > + > + switch (transfer_type) { > + case TT_MAIN_OOB_AREA_EXT: > + sec_cnt = cdns_chip->sector_count; > + sec_size = cdns_chip->sector_size; > + data_ctrl_size = cdns_chip->avail_oob_size; > + break; > + case TT_MAIN_OOB_AREAS: > + sec_cnt = cdns_chip->sector_count; > + last_sec_size = cdns_chip->sector_size > + + cdns_chip->avail_oob_size; > + sec_size = cdns_chip->sector_size; > + break; > + case TT_RAW_PAGE: > + last_sec_size = mtd->writesize + mtd->oobsize; > + break; > + case TT_BBM: > + offset = mtd->writesize + cdns_chip->bbm_offs; > + last_sec_size = 8; > + break; > + } > + > + reg = 0; > + reg |= FIELD_PREP(TRAN_CFG_0_OFFSET, offset); > + reg |= FIELD_PREP(TRAN_CFG_0_SEC_CNT, sec_cnt); > + writel_relaxed(reg, cdns_ctrl->reg + TRAN_CFG_0); > + > + reg = 0; > + reg |= FIELD_PREP(TRAN_CFG_1_LAST_SEC_SIZE, last_sec_size); > + reg |= FIELD_PREP(TRAN_CFG_1_SECTOR_SIZE, sec_size); > + writel_relaxed(reg, cdns_ctrl->reg + TRAN_CFG_1); > + > + if (cdns_ctrl->caps2.data_control_supp == 1) { > + reg = readl_relaxed(cdns_ctrl->reg + CONTROL_DATA_CTRL); > + reg &= ~CONTROL_DATA_CTRL_SIZE; > + reg |= FIELD_PREP(CONTROL_DATA_CTRL_SIZE, data_ctrl_size); > + writel_relaxed(reg, cdns_ctrl->reg + CONTROL_DATA_CTRL); > + } > + > + cdns_ctrl->curr_trans_type = transfer_type; > +} > + > +static int > +cadence_nand_cdma_transfer(struct cdns_nand_ctrl *cdns_ctrl, u8 chip_nr, > + int page, void *buf, void *ctrl_dat, u32 buf_size, > + u32 ctrl_dat_size, enum dma_data_direction dir, > + bool with_ecc) > +{ > + struct cadence_nand_cdma_desc *cdma_desc = cdns_ctrl->cdma_desc; > + dma_addr_t dma_buf, dma_ctrl_dat = 0; > + u8 thread_nr = chip_nr; > + int status; > + u16 ctype; > + > + if (dir == DMA_FROM_DEVICE) > + ctype = CDMA_CT_RD; > + else > + ctype = CDMA_CT_WR; > + > + cadence_nand_set_ecc_enable(cdns_ctrl, with_ecc); > + > + dma_buf = dma_map_single(cdns_ctrl->dev, buf, buf_size, dir); > + if (dma_mapping_error(cdns_ctrl->dev, dma_buf)) { > + dev_err(cdns_ctrl->dev, "Failed to map DMA buffer\n"); > + return -EIO; > + } > + > + if (ctrl_dat && ctrl_dat_size) { > + dma_ctrl_dat = dma_map_single(cdns_ctrl->dev, ctrl_dat, > + ctrl_dat_size, dir); > + if (dma_mapping_error(cdns_ctrl->dev, dma_ctrl_dat)) { > + dma_unmap_single(cdns_ctrl->dev, dma_buf, > + buf_size, dir); > + dev_err(cdns_ctrl->dev, "Failed to map DMA buffer\n"); > + return -EIO; > + } > + } > + > + cadence_nand_cdma_desc_prepare(cdma_desc, chip_nr, page, > + (void *)dma_buf, (void *)dma_ctrl_dat, > + ctype); > + > + status = cadence_nand_cdma_send_and_wait(cdns_ctrl, thread_nr); > + > + dma_unmap_single(cdns_ctrl->dev, dma_buf, > + buf_size, dir); > + > + if (ctrl_dat && ctrl_dat_size) > + dma_unmap_single(cdns_ctrl->dev, dma_ctrl_dat, > + ctrl_dat_size, dir); > + if (status) > + return status; > + > + return cadence_nand_cdma_finish(cdns_ctrl, cdns_ctrl->cdma_desc); > +} > + > +static void cadence_nand_set_timings(struct cdns_nand_ctrl *cdns_ctrl, > + struct cadence_nand_timings *t) > +{ > + writel_relaxed(t->async_toggle_timings, > + cdns_ctrl->reg + ASYNC_TOGGLE_TIMINGS); > + writel_relaxed(t->timings0, cdns_ctrl->reg + TIMINGS0); > + writel_relaxed(t->timings1, cdns_ctrl->reg + TIMINGS1); > + writel_relaxed(t->timings2, cdns_ctrl->reg + TIMINGS2); > + > + if (cdns_ctrl->caps2.is_phy_type_dll) > + writel_relaxed(t->dll_phy_ctrl, cdns_ctrl->reg + DLL_PHY_CTRL); > + > + writel_relaxed(t->phy_ctrl, cdns_ctrl->reg + PHY_CTRL); > + > + if (cdns_ctrl->caps2.is_phy_type_dll) { > + writel_relaxed(0, cdns_ctrl->reg + PHY_TSEL); > + writel_relaxed(2, cdns_ctrl->reg + PHY_DQ_TIMING); > + writel_relaxed(t->phy_dqs_timing, > + cdns_ctrl->reg + PHY_DQS_TIMING); > + writel_relaxed(t->phy_gate_lpbk_ctrl, > + cdns_ctrl->reg + PHY_GATE_LPBK_CTRL); > + writel_relaxed(PHY_DLL_MASTER_CTRL_BYPASS_MODE, > + cdns_ctrl->reg + PHY_DLL_MASTER_CTRL); > + writel_relaxed(0, cdns_ctrl->reg + PHY_DLL_SLAVE_CTRL); > + } > +} > + > +static int cadence_nand_select_target(struct nand_chip *chip) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + > + if (chip == cdns_ctrl->selected_chip) > + return 0; > + > + if (cadence_nand_wait_for_value(cdns_ctrl, CTRL_STATUS, > + 1000000, > + CTRL_STATUS_CTRL_BUSY, true)) > + return -ETIMEDOUT; > + > + cadence_nand_set_timings(cdns_ctrl, &cdns_chip->timings); > + > + cadence_nand_set_ecc_strength(cdns_ctrl, > + cdns_chip->corr_str_idx); > + > + cadence_nand_set_erase_detection(cdns_ctrl, true, > + chip->ecc.strength); > + > + cdns_ctrl->curr_trans_type = -1; > + cdns_ctrl->selected_chip = chip; > + > + return 0; > +} > + > +static int cadence_nand_erase(struct nand_chip *chip, u32 page) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + int status; > + u8 thread_nr = cdns_chip->cs[chip->cur_cs]; > + > + cadence_nand_cdma_desc_prepare(cdns_ctrl->cdma_desc, > + cdns_chip->cs[chip->cur_cs], > + page, NULL, NULL, > + CDMA_CT_ERASE); > + status = cadence_nand_cdma_send_and_wait(cdns_ctrl, thread_nr); > + if (status) { > + dev_err(cdns_ctrl->dev, "erase operation failed\n"); > + return -EIO; > + } > + > + status = cadence_nand_cdma_finish(cdns_ctrl, cdns_ctrl->cdma_desc); > + if (status) > + return status; > + > + return 0; > +} > + > +static int cadence_nand_read_bbm(struct nand_chip *chip, int page, u8 *buf) > +{ > + int status; > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + struct mtd_info *mtd = nand_to_mtd(chip); > + > + cadence_nand_prepare_data_size(chip, TT_BBM); > + > + cadence_nand_set_skip_bytes_conf(cdns_ctrl, 0, 0, 0); > + > + /* > + * Read only bad block marker from offset > + * defined by a memory manufacturer. > + */ > + status = cadence_nand_cdma_transfer(cdns_ctrl, > + cdns_chip->cs[chip->cur_cs], > + page, cdns_ctrl->buf, NULL, > + mtd->oobsize, > + 0, DMA_FROM_DEVICE, false); > + if (status) { > + dev_err(cdns_ctrl->dev, "read BBM failed\n"); > + return -EIO; > + } > + > + memcpy(buf + cdns_chip->bbm_offs, cdns_ctrl->buf, cdns_chip->bbm_len); > + > + return 0; > +} Not sure this function is relevant, see below. > + > +static int cadence_nand_write_page(struct nand_chip *chip, > + const u8 *buf, int oob_required, > + int page) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + struct mtd_info *mtd = nand_to_mtd(chip); > + int status; > + u16 marker_val = 0xFFFF; > + > + status = cadence_nand_select_target(chip); > + if (status) > + return status; > + > + cadence_nand_set_skip_bytes_conf(cdns_ctrl, cdns_chip->bbm_len, > + mtd->writesize > + + cdns_chip->bbm_offs, > + 1); > + > + if (oob_required) { > + marker_val = *(u16 *)(chip->oob_poi > + + cdns_chip->bbm_offs); > + } else { > + /* Set oob data to 0xFF. */ > + memset(cdns_ctrl->buf + mtd->writesize, 0xFF, > + cdns_chip->avail_oob_size); > + } > + > + cadence_nand_set_skip_marker_val(cdns_ctrl, marker_val); > + > + cadence_nand_prepare_data_size(chip, TT_MAIN_OOB_AREA_EXT); > + > + if (cadence_nand_dma_buf_ok(cdns_ctrl, buf, mtd->writesize) && > + cdns_ctrl->caps2.data_control_supp) { > + u8 *oob; > + > + if (oob_required) > + oob = chip->oob_poi; > + else > + oob = cdns_ctrl->buf + mtd->writesize; > + > + status = cadence_nand_cdma_transfer(cdns_ctrl, > + cdns_chip->cs[chip->cur_cs], > + page, (void *)buf, oob, > + mtd->writesize, > + cdns_chip->avail_oob_size, > + DMA_TO_DEVICE, true); > + if (status) { > + dev_err(cdns_ctrl->dev, "write page failed\n"); > + return -EIO; > + } > + > + return 0; > + } > + > + if (oob_required) { > + /* Transfer the data to the oob area. */ > + memcpy(cdns_ctrl->buf + mtd->writesize, chip->oob_poi, > + cdns_chip->avail_oob_size); > + } > + > + memcpy(cdns_ctrl->buf, buf, mtd->writesize); > + > + cadence_nand_prepare_data_size(chip, TT_MAIN_OOB_AREAS); > + > + return cadence_nand_cdma_transfer(cdns_ctrl, > + cdns_chip->cs[chip->cur_cs], > + page, cdns_ctrl->buf, NULL, > + mtd->writesize > + + cdns_chip->avail_oob_size, > + 0, DMA_TO_DEVICE, true); > +} > + > +static int cadence_nand_write_oob(struct nand_chip *chip, int page) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct mtd_info *mtd = nand_to_mtd(chip); > + > + memset(cdns_ctrl->buf, 0xFF, mtd->writesize); > + > + return cadence_nand_write_page(chip, cdns_ctrl->buf, 1, page); > +} > + > +static int cadence_nand_write_page_raw(struct nand_chip *chip, > + const u8 *buf, int oob_required, > + int page) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + struct mtd_info *mtd = nand_to_mtd(chip); > + int writesize = mtd->writesize; > + int oobsize = mtd->oobsize; > + int ecc_steps = chip->ecc.steps; > + int ecc_size = chip->ecc.size; > + int ecc_bytes = chip->ecc.bytes; > + void *tmp_buf = cdns_ctrl->buf; > + int oob_skip = cdns_chip->bbm_len; > + size_t size = writesize + oobsize; > + int i, pos, len; > + int status = 0; > + > + status = cadence_nand_select_target(chip); > + if (status) > + return status; > + > + /* > + * Fill the buffer with 0xff first except the full page transfer. > + * This simplifies the logic. > + */ > + if (!buf || !oob_required) > + memset(tmp_buf, 0xff, size); > + > + cadence_nand_set_skip_bytes_conf(cdns_ctrl, 0, 0, 0); > + > + /* Arrange the buffer for syndrome payload/ecc layout. */ > + if (buf) { > + for (i = 0; i < ecc_steps; i++) { > + pos = i * (ecc_size + ecc_bytes); > + len = ecc_size; > + > + if (pos >= writesize) > + pos += oob_skip; > + else if (pos + len > writesize) > + len = writesize - pos; > + > + memcpy(tmp_buf + pos, buf, len); > + buf += len; > + if (len < ecc_size) { > + len = ecc_size - len; > + memcpy(tmp_buf + writesize + oob_skip, buf, > + len); > + buf += len; > + } > + } > + } > + > + if (oob_required) { > + const u8 *oob = chip->oob_poi; > + u32 oob_data_offset = (cdns_chip->sector_count - 1) * > + (cdns_chip->sector_size + chip->ecc.bytes) > + + cdns_chip->sector_size + oob_skip; > + > + /* BBM at the beginning of the OOB area. */ > + memcpy(tmp_buf + writesize, oob, oob_skip); > + > + /* OOB free. */ > + memcpy(tmp_buf + oob_data_offset, oob, > + cdns_chip->avail_oob_size); > + oob += cdns_chip->avail_oob_size; > + > + /* OOB ECC. */ > + for (i = 0; i < ecc_steps; i++) { > + pos = ecc_size + i * (ecc_size + ecc_bytes); > + if (i == (ecc_steps - 1)) > + pos += cdns_chip->avail_oob_size; > + > + len = ecc_bytes; > + > + if (pos >= writesize) > + pos += oob_skip; > + else if (pos + len > writesize) > + len = writesize - pos; > + > + memcpy(tmp_buf + pos, oob, len); > + oob += len; > + if (len < ecc_bytes) { > + len = ecc_bytes - len; > + memcpy(tmp_buf + writesize + oob_skip, oob, > + len); > + oob += len; > + } > + } > + } > + > + cadence_nand_prepare_data_size(chip, TT_RAW_PAGE); > + > + return cadence_nand_cdma_transfer(cdns_ctrl, > + cdns_chip->cs[chip->cur_cs], > + page, cdns_ctrl->buf, NULL, > + mtd->writesize + > + mtd->oobsize, > + 0, DMA_TO_DEVICE, false); > +} > + > +static int cadence_nand_write_oob_raw(struct nand_chip *chip, > + int page) > +{ > + return cadence_nand_write_page_raw(chip, NULL, true, page); > +} > + > +static int cadence_nand_read_page(struct nand_chip *chip, > + u8 *buf, int oob_required, int page) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + struct mtd_info *mtd = nand_to_mtd(chip); > + int status = 0; > + int ecc_err_count = 0; > + > + status = cadence_nand_select_target(chip); > + if (status) > + return status; > + > + cadence_nand_set_skip_bytes_conf(cdns_ctrl, cdns_chip->bbm_len, > + mtd->writesize > + + cdns_chip->bbm_offs, 1); > + > + /* > + * If data buffer can be accessed by DMA and data_control feature > + * is supported then transfer data and oob directly. > + */ > + if (cadence_nand_dma_buf_ok(cdns_ctrl, buf, mtd->writesize) && > + cdns_ctrl->caps2.data_control_supp) { > + u8 *oob; > + > + if (oob_required) > + oob = chip->oob_poi; > + else > + oob = cdns_ctrl->buf + mtd->writesize; > + > + cadence_nand_prepare_data_size(chip, TT_MAIN_OOB_AREA_EXT); > + status = cadence_nand_cdma_transfer(cdns_ctrl, > + cdns_chip->cs[chip->cur_cs], > + page, buf, oob, > + mtd->writesize, > + cdns_chip->avail_oob_size, > + DMA_FROM_DEVICE, true); > + /* Otherwise use bounce buffer. */ > + } else { > + cadence_nand_prepare_data_size(chip, TT_MAIN_OOB_AREAS); > + status = cadence_nand_cdma_transfer(cdns_ctrl, > + cdns_chip->cs[chip->cur_cs], > + page, cdns_ctrl->buf, > + NULL, mtd->writesize > + + cdns_chip->avail_oob_size, > + 0, DMA_FROM_DEVICE, true); > + > + memcpy(buf, cdns_ctrl->buf, mtd->writesize); > + if (oob_required) > + memcpy(chip->oob_poi, > + cdns_ctrl->buf + mtd->writesize, > + mtd->oobsize); > + } > + > + switch (status) { > + case STAT_ECC_UNCORR: > + mtd->ecc_stats.failed++; > + ecc_err_count++; > + break; > + case STAT_ECC_CORR: > + ecc_err_count = FIELD_GET(CDMA_CS_MAXERR, > + cdns_ctrl->cdma_desc->status); > + mtd->ecc_stats.corrected += ecc_err_count; Is this value the maximum number of bitflips in each chunk of the page? If it returns the total number of bitflips corrected in the entire page we have a problem. > + break; > + case STAT_ERASED: > + case STAT_OK: > + break; > + default: > + dev_err(cdns_ctrl->dev, "read page failed\n"); > + return -EIO; > + } > + > + if (oob_required) > + if (cadence_nand_read_bbm(chip, page, chip->oob_poi)) > + return -EIO; Do we really care about the BBM at this level? If we are requested to read the page, I suppose we must do what is in our hands to return the data? Normally this is handled in userspace directly. > + > + return ecc_err_count; > +} > + > +/* Reads OOB data from the device. */ > +static int cadence_nand_read_oob(struct nand_chip *chip, int page) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + > + return cadence_nand_read_page(chip, cdns_ctrl->buf, 1, page); > +} > + > +static int cadence_nand_read_page_raw(struct nand_chip *chip, > + u8 *buf, int oob_required, int page) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + struct mtd_info *mtd = nand_to_mtd(chip); > + int oob_skip = cdns_chip->bbm_len; > + int writesize = mtd->writesize; > + int ecc_steps = chip->ecc.steps; > + int ecc_size = chip->ecc.size; > + int ecc_bytes = chip->ecc.bytes; > + void *tmp_buf = cdns_ctrl->buf; > + int i, pos, len; > + int status = 0; > + > + status = cadence_nand_select_target(chip); > + if (status) > + return status; > + > + cadence_nand_set_skip_bytes_conf(cdns_ctrl, 0, 0, 0); > + > + cadence_nand_prepare_data_size(chip, TT_RAW_PAGE); > + status = cadence_nand_cdma_transfer(cdns_ctrl, > + cdns_chip->cs[chip->cur_cs], > + page, cdns_ctrl->buf, NULL, > + mtd->writesize > + + mtd->oobsize, > + 0, DMA_FROM_DEVICE, false); > + > + switch (status) { > + case STAT_ERASED: > + case STAT_OK: > + break; > + default: > + dev_err(cdns_ctrl->dev, "read raw page failed\n"); > + return -EIO; > + } > + > + /* Arrange the buffer for syndrome payload/ecc layout. */ > + if (buf) { > + for (i = 0; i < ecc_steps; i++) { > + pos = i * (ecc_size + ecc_bytes); > + len = ecc_size; > + > + if (pos >= writesize) > + pos += oob_skip; > + else if (pos + len > writesize) > + len = writesize - pos; > + > + memcpy(buf, tmp_buf + pos, len); > + buf += len; > + if (len < ecc_size) { > + len = ecc_size - len; > + memcpy(buf, tmp_buf + writesize + oob_skip, > + len); > + buf += len; > + } > + } > + } > + > + if (oob_required) { > + u8 *oob = chip->oob_poi; > + u32 oob_data_offset = (cdns_chip->sector_count - 1) * > + (cdns_chip->sector_size + chip->ecc.bytes) > + + cdns_chip->sector_size + oob_skip; > + > + /* OOB free. */ > + memcpy(oob, tmp_buf + oob_data_offset, > + cdns_chip->avail_oob_size); > + > + /* BBM at the beginning of the OOB area. */ > + memcpy(oob, tmp_buf + writesize, oob_skip); > + > + oob += cdns_chip->avail_oob_size; > + > + /* OOB ECC */ > + for (i = 0; i < ecc_steps; i++) { > + pos = ecc_size + i * (ecc_size + ecc_bytes); > + len = ecc_bytes; > + > + if (i == (ecc_steps - 1)) > + pos += cdns_chip->avail_oob_size; > + > + if (pos >= writesize) > + pos += oob_skip; > + else if (pos + len > writesize) > + len = writesize - pos; > + > + memcpy(oob, tmp_buf + pos, len); > + oob += len; > + if (len < ecc_bytes) { > + len = ecc_bytes - len; > + memcpy(oob, tmp_buf + writesize + oob_skip, > + len); > + oob += len; > + } > + } > + } > + > + return 0; > +} > + > +static int cadence_nand_read_oob_raw(struct nand_chip *chip, > + int page) > +{ > + return cadence_nand_read_page_raw(chip, NULL, true, page); > +} > + > +static void cadence_nand_slave_dma_transfer_finished(void *data) > +{ > + struct completion *finished = data; > + > + complete(finished); > +} > + > +static int cadence_nand_slave_dma_transfer(struct cdns_nand_ctrl *cdns_ctrl, > + void *buf, > + dma_addr_t dev_dma, size_t len, > + enum dma_data_direction dir) > +{ > + DECLARE_COMPLETION_ONSTACK(finished); > + struct dma_chan *chan; > + struct dma_device *dma_dev; > + dma_addr_t src_dma, dst_dma, buf_dma; > + struct dma_async_tx_descriptor *tx; > + dma_cookie_t cookie; > + > + chan = cdns_ctrl->dmac; > + dma_dev = chan->device; > + > + buf_dma = dma_map_single(dma_dev->dev, buf, len, dir); > + if (dma_mapping_error(dma_dev->dev, buf_dma)) { > + dev_err(cdns_ctrl->dev, "Failed to map DMA buffer\n"); > + goto err; > + } > + > + if (dir == DMA_FROM_DEVICE) { > + src_dma = cdns_ctrl->io.dma; > + dst_dma = buf_dma; > + } else { > + src_dma = buf_dma; > + dst_dma = cdns_ctrl->io.dma; > + } > + > + tx = dmaengine_prep_dma_memcpy(cdns_ctrl->dmac, dst_dma, src_dma, len, > + DMA_CTRL_ACK | DMA_PREP_INTERRUPT); > + if (!tx) { > + dev_err(cdns_ctrl->dev, "Failed to prepare DMA memcpy\n"); > + goto err_unmap; > + } > + > + tx->callback = cadence_nand_slave_dma_transfer_finished; > + tx->callback_param = &finished; > + > + cookie = dmaengine_submit(tx); > + if (dma_submit_error(cookie)) { > + dev_err(cdns_ctrl->dev, "Failed to do DMA tx_submit\n"); > + goto err_unmap; > + } > + > + dma_async_issue_pending(cdns_ctrl->dmac); > + wait_for_completion(&finished); > + > + dma_unmap_single(cdns_ctrl->dev, buf_dma, len, dir); > + > + return 0; > + > +err_unmap: > + dma_unmap_single(cdns_ctrl->dev, buf_dma, len, dir); > + > +err: > + dev_dbg(cdns_ctrl->dev, "Fall back to CPU I/O\n"); > + > + return -EIO; > +} > + > +static int cadence_nand_read_buf(struct cdns_nand_ctrl *cdns_ctrl, > + u8 *buf, int len) > +{ > + int len_aligned = ALIGN(len, cdns_ctrl->caps2.data_dma_width); > + u8 thread_nr = 0; > + u32 sdma_size; > + int status; > + > + if (!cdns_ctrl->caps1->has_dma) { > + if (len & 3) { > + dev_err(cdns_ctrl->dev, "unaligned data\n"); > + return -EIO; > + } > + readsl(cdns_ctrl->io.virt, buf, len / 4); > + return 0; > + } > + > + /* Wait until slave DMA interface is ready to data transfer. */ > + status = cadence_nand_wait_on_sdma(cdns_ctrl, &thread_nr, &sdma_size); > + if (status) > + return status; > + > + if (sdma_size != len_aligned) { > + dev_err(cdns_ctrl->dev, "unexpected scenario\n"); > + return -EIO; > + } > + > + if (cdns_ctrl->dmac && cadence_nand_dma_buf_ok(cdns_ctrl, buf, len)) { > + status = cadence_nand_slave_dma_transfer(cdns_ctrl, buf, > + cdns_ctrl->io.dma, > + len, DMA_FROM_DEVICE); > + if (status == 0) > + return 0; > + > + dev_warn(cdns_ctrl->dev, > + "Slave DMA transfer failed. Try again using bounce buffer."); > + } > + > + /* If DMA transfer is not possible or failed then use bounce buffer. */ > + status = cadence_nand_slave_dma_transfer(cdns_ctrl, cdns_ctrl->buf, > + cdns_ctrl->io.dma, > + len_aligned, DMA_FROM_DEVICE); > + > + if (status) { > + dev_err(cdns_ctrl->dev, "Slave DMA transfer failed"); > + return status; > + } > + > + memcpy(buf, cdns_ctrl->buf, len); > + > + return 0; > +} > + > +static int cadence_nand_write_buf(struct cdns_nand_ctrl *cdns_ctrl, > + const u8 *buf, int len) > +{ > + u8 thread_nr = 0; > + u32 sdma_size; > + int status; > + int len_aligned = ALIGN(len, cdns_ctrl->caps2.data_dma_width); > + > + if (!cdns_ctrl->caps1->has_dma) { > + if (len & 3) { > + dev_err(cdns_ctrl->dev, "unaligned data\n"); > + return -EIO; > + } > + writesl(cdns_ctrl->io.virt, buf, len / 4); > + return 0; > + } > + > + /* Wait until slave DMA interface is ready to data transfer. */ > + status = cadence_nand_wait_on_sdma(cdns_ctrl, &thread_nr, &sdma_size); > + if (status) > + return status; > + > + if (sdma_size != len_aligned) { > + dev_err(cdns_ctrl->dev, "Error unexpected scenario\n"); > + return -EIO; > + } > + > + if (cdns_ctrl->dmac && cadence_nand_dma_buf_ok(cdns_ctrl, buf, len)) { > + status = cadence_nand_slave_dma_transfer(cdns_ctrl, (void *)buf, > + cdns_ctrl->io.dma, > + len, DMA_TO_DEVICE); > + if (status == 0) > + return 0; > + > + dev_warn(cdns_ctrl->dev, > + "Slave DMA transfer failed. Try again using bounce buffer."); > + } > + > + /* If DMA transfer is not possible or failed then use bounce buffer. */ > + memcpy(cdns_ctrl->buf, buf, len); > + > + status = cadence_nand_slave_dma_transfer(cdns_ctrl, cdns_ctrl->buf, > + cdns_ctrl->io.dma, > + len_aligned, DMA_TO_DEVICE); > + > + if (status) > + dev_err(cdns_ctrl->dev, "Slave DMA transfer failed"); > + > + return status; > +} > + > +static int cadence_nand_force_byte_access(struct nand_chip *chip, > + bool force_8bit) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + int status; > + > + /* > + * Callers of this function do not verify if the NAND is using a 16-bit > + * an 8-bit bus for normal operations, so we need to take care of that > + * here by leaving the configuration unchanged if the NAND does not have > + * the NAND_BUSWIDTH_16 flag set. > + */ > + if (!(chip->options & NAND_BUSWIDTH_16)) > + return 0; > + > + status = cadence_nand_set_access_width16(cdns_ctrl, !force_8bit); > + > + return status; > +} > + > +static int cadence_nand_cmd_opcode(struct nand_chip *chip, > + const struct nand_subop *subop) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + const struct nand_op_instr *instr; > + unsigned int op_id = 0; > + u64 mini_ctrl_cmd = 0; > + int ret; > + > + instr = &subop->instrs[op_id]; > + > + if (instr->delay_ns > 0) > + mini_ctrl_cmd |= GCMD_LAY_TWB; > + > + mini_ctrl_cmd |= FIELD_PREP(GCMD_LAY_INSTR, > + GCMD_LAY_INSTR_CMD); > + mini_ctrl_cmd |= FIELD_PREP(GCMD_LAY_INPUT_CMD, > + instr->ctx.cmd.opcode); > + > + ret = cadence_nand_generic_cmd_send(cdns_ctrl, > + cdns_chip->cs[chip->cur_cs], > + mini_ctrl_cmd); > + if (ret) > + dev_err(cdns_ctrl->dev, "send cmd %x failed\n", > + instr->ctx.cmd.opcode); > + > + return ret; > +} > + > +static int cadence_nand_cmd_address(struct nand_chip *chip, > + const struct nand_subop *subop) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + const struct nand_op_instr *instr; > + unsigned int op_id = 0; > + u64 mini_ctrl_cmd = 0; > + unsigned int offset, naddrs; > + u64 address = 0; > + const u8 *addrs; > + int ret; > + int i; > + > + instr = &subop->instrs[op_id]; > + > + if (instr->delay_ns > 0) > + mini_ctrl_cmd |= GCMD_LAY_TWB; > + > + mini_ctrl_cmd |= FIELD_PREP(GCMD_LAY_INSTR, > + GCMD_LAY_INSTR_ADDR); > + > + 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]; > + > + for (i = 0; i < naddrs; i++) > + address |= (u64)addrs[i] << (8 * i); > + > + mini_ctrl_cmd |= FIELD_PREP(GCMD_LAY_INPUT_ADDR, > + address); > + mini_ctrl_cmd |= FIELD_PREP(GCMD_LAY_INPUT_ADDR_SIZE, > + naddrs - 1); > + > + ret = cadence_nand_generic_cmd_send(cdns_ctrl, > + cdns_chip->cs[chip->cur_cs], > + mini_ctrl_cmd); > + if (ret) > + dev_err(cdns_ctrl->dev, "send address %llx failed\n", address); > + > + return ret; > +} > + > +static int cadence_nand_cmd_erase(struct nand_chip *chip, > + const struct nand_subop *subop) > +{ > + unsigned int op_id; > + > + if (subop->instrs[0].ctx.cmd.opcode == NAND_CMD_ERASE1) { > + int i; > + const struct nand_op_instr *instr = NULL; > + unsigned int offset, naddrs; > + const u8 *addrs; > + u32 page = 0; > + > + instr = &subop->instrs[1]; > + offset = nand_subop_get_addr_start_off(subop, 1); > + naddrs = nand_subop_get_num_addr_cyc(subop, 1); > + addrs = &instr->ctx.addr.addrs[offset]; > + > + for (i = 0; i < naddrs; i++) > + page |= (u32)addrs[i] << (8 * i); > + > + return cadence_nand_erase(chip, page); > + } > + > + /* > + * If it is not an erase operation then handle operation > + * by calling exec_op function. > + */ > + for (op_id = 0; op_id < subop->ninstrs; op_id++) { > + int ret; > + const struct nand_operation nand_op = { > + .cs = chip->cur_cs, > + .instrs = &subop->instrs[op_id], > + .ninstrs = 1}; > + ret = chip->controller->ops->exec_op(chip, &nand_op, false); > + if (ret) > + return ret; > + } > + > + return 0; > +} > + > +static int cadence_nand_cmd_data(struct nand_chip *chip, > + const struct nand_subop *subop) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + const struct nand_op_instr *instr; > + unsigned int offset, op_id = 0; > + u64 mini_ctrl_cmd = 0; > + int len = 0; > + int ret; > + > + instr = &subop->instrs[op_id]; > + > + if (instr->delay_ns > 0) > + mini_ctrl_cmd |= GCMD_LAY_TWB; > + > + mini_ctrl_cmd |= FIELD_PREP(GCMD_LAY_INSTR, > + GCMD_LAY_INSTR_DATA); > + > + if (instr->type == NAND_OP_DATA_OUT_INSTR) > + mini_ctrl_cmd |= FIELD_PREP(GCMD_DIR, > + GCMD_DIR_WRITE); > + > + len = nand_subop_get_data_len(subop, op_id); > + offset = nand_subop_get_data_start_off(subop, op_id); > + mini_ctrl_cmd |= FIELD_PREP(GCMD_SECT_CNT, 1); > + mini_ctrl_cmd |= FIELD_PREP(GCMD_LAST_SIZE, len); > + if (instr->ctx.data.force_8bit) { > + ret = cadence_nand_force_byte_access(chip, true); > + if (ret) { > + dev_err(cdns_ctrl->dev, > + "cannot change byte access generic data cmd failed\n"); > + return ret; > + } > + } > + > + ret = cadence_nand_generic_cmd_send(cdns_ctrl, > + cdns_chip->cs[chip->cur_cs], > + mini_ctrl_cmd); > + if (ret) { > + dev_err(cdns_ctrl->dev, "send generic data cmd failed\n"); > + return ret; > + } > + > + if (instr->type == NAND_OP_DATA_IN_INSTR) { > + void *buf = instr->ctx.data.buf.in + offset; > + > + ret = cadence_nand_read_buf(cdns_ctrl, buf, len); > + } else { > + const void *buf = instr->ctx.data.buf.out + offset; > + > + ret = cadence_nand_write_buf(cdns_ctrl, buf, len); > + } > + > + if (ret) { > + dev_err(cdns_ctrl->dev, "data transfer failed for generic command\n"); > + return ret; > + } > + > + if (instr->ctx.data.force_8bit) { > + ret = cadence_nand_force_byte_access(chip, false); > + if (ret) { > + dev_err(cdns_ctrl->dev, > + "cannot change byte access generic data cmd failed\n"); > + } > + } > + > + return ret; > +} > + > +static int cadence_nand_cmd_waitrdy(struct nand_chip *chip, > + const struct nand_subop *subop) > +{ > + int status; > + unsigned int op_id = 0; > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + const struct nand_op_instr *instr = &subop->instrs[op_id]; > + u32 timeout_us = instr->ctx.waitrdy.timeout_ms * 1000; > + > + status = cadence_nand_wait_for_value(cdns_ctrl, RBN_SETINGS, > + timeout_us, > + 1U << cdns_chip->cs[chip->cur_cs], BIT() ? > + false); > + return status; > +} > + > +static const struct nand_op_parser cadence_nand_op_parser = NAND_OP_PARSER( > + NAND_OP_PARSER_PATTERN( > + cadence_nand_cmd_erase, > + NAND_OP_PARSER_PAT_CMD_ELEM(false), > + NAND_OP_PARSER_PAT_ADDR_ELEM(false, MAX_ERASE_ADDRESS_CYC), > + NAND_OP_PARSER_PAT_CMD_ELEM(false), > + NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)), > + NAND_OP_PARSER_PATTERN( > + cadence_nand_cmd_opcode, > + NAND_OP_PARSER_PAT_CMD_ELEM(false)), > + NAND_OP_PARSER_PATTERN( > + cadence_nand_cmd_address, > + NAND_OP_PARSER_PAT_ADDR_ELEM(false, MAX_ADDRESS_CYC)), > + NAND_OP_PARSER_PATTERN( > + cadence_nand_cmd_data, > + NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, MAX_DATA_SIZE)), > + NAND_OP_PARSER_PATTERN( > + cadence_nand_cmd_data, > + NAND_OP_PARSER_PAT_DATA_OUT_ELEM(false, MAX_DATA_SIZE)), > + NAND_OP_PARSER_PATTERN( > + cadence_nand_cmd_waitrdy, > + NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)) > + ); > + > +static int cadence_nand_exec_op(struct nand_chip *chip, > + const struct nand_operation *op, > + bool check_only) > +{ > + int status = cadence_nand_select_target(chip); > + > + if (status) > + return status; > + > + return nand_op_parser_exec_op(chip, &cadence_nand_op_parser, op, > + check_only); > +} > + > +static int cadence_nand_ooblayout_free(struct mtd_info *mtd, int section, > + struct mtd_oob_region *oobregion) > +{ > + struct nand_chip *chip = mtd_to_nand(mtd); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + > + if (section) > + return -ERANGE; > + > + oobregion->offset = cdns_chip->bbm_len; > + oobregion->length = cdns_chip->avail_oob_size > + - cdns_chip->bbm_len; > + > + return 0; > +} > + > +static int cadence_nand_ooblayout_ecc(struct mtd_info *mtd, int section, > + struct mtd_oob_region *oobregion) > +{ > + struct nand_chip *chip = mtd_to_nand(mtd); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + > + if (section) > + return -ERANGE; > + > + oobregion->offset = cdns_chip->avail_oob_size; > + oobregion->length = chip->ecc.total; > + > + return 0; > +} > + > +static const struct mtd_ooblayout_ops cadence_nand_ooblayout_ops = { > + .free = cadence_nand_ooblayout_free, > + .ecc = cadence_nand_ooblayout_ecc, > +}; > + > +static int calc_cycl(u32 timing, u32 clock) > +{ > + if (timing == 0 || clock == 0) > + return 0; > + > + if ((timing % clock) > 0) > + return timing / clock; > + else > + return timing / clock - 1; > +} > + > +/* Calculate max data valid window. */ > +static inline u32 calc_tdvw_max(u32 trp_cnt, u32 clk_period, u32 trhoh_min, > + u32 board_delay_skew_min, u32 ext_mode) > +{ > + if (ext_mode == 0) > + clk_period /= 2; > + > + return (trp_cnt + 1) * clk_period + trhoh_min + > + board_delay_skew_min; > +} > + > +/* Calculate data valid window. */ > +static inline u32 calc_tdvw(u32 trp_cnt, u32 clk_period, u32 trhoh_min, > + u32 trea_max, u32 ext_mode) > +{ > + if (ext_mode == 0) > + clk_period /= 2; > + > + return (trp_cnt + 1) * clk_period + trhoh_min - trea_max; > +} > + > +static int > +cadence_nand_setup_data_interface(struct nand_chip *chip, int chipnr, > + const struct nand_data_interface *conf) > +{ > + const struct nand_sdr_timings *sdr; > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + struct cadence_nand_timings *t = &cdns_chip->timings; > + u32 reg; > + u32 board_delay = cdns_ctrl->board_delay; > + u32 clk_period = DIV_ROUND_DOWN_ULL(1000000000000ULL, > + cdns_ctrl->nf_clk_rate); > + u32 tceh_cnt, tcs_cnt, tadl_cnt, tccs_cnt; > + u32 tfeat_cnt, trhz_cnt, tvdly_cnt; > + u32 trhw_cnt, twb_cnt, twh_cnt = 0, twhr_cnt; > + u32 twp_cnt = 0, trp_cnt = 0, trh_cnt = 0; > + u32 if_skew = cdns_ctrl->caps1->if_skew; > + u32 board_delay_skew_min = board_delay - if_skew; > + u32 board_delay_skew_max = board_delay + if_skew; > + u32 dqs_sampl_res, phony_dqs_mod; > + u32 tdvw, tdvw_min, tdvw_max; > + u32 ext_rd_mode, ext_wr_mode; > + u32 dll_phy_dqs_timing = 0, phony_dqs_timing = 0, rd_del_sel = 0; > + u32 sampling_point; > + > + sdr = nand_get_sdr_timings(conf); > + if (IS_ERR(sdr)) > + return PTR_ERR(sdr); > + > + memset(t, 0, sizeof(*t)); > + /* Sampling point calculation. */ > + > + if (cdns_ctrl->caps2.is_phy_type_dll) > + phony_dqs_mod = 2; > + else > + phony_dqs_mod = 1; > + > + dqs_sampl_res = clk_period / phony_dqs_mod; > + > + tdvw_min = sdr->tREA_max + board_delay_skew_max; > + /* > + * The idea of those calculation is to get the optimum value > + * for tRP and tRH timings. If it is NOT possible to sample data > + * with optimal tRP/tRH settings, the parameters will be extended. > + * If clk_period is 50ns (the lowest value) this condition is met > + * for asynchronous timing modes 1, 2, 3, 4 and 5. > + * If clk_period is 20ns the condition is met only > + * for asynchronous timing mode 5. > + */ > + if (sdr->tRC_min <= clk_period && > + sdr->tRP_min <= (clk_period / 2) && > + sdr->tREH_min <= (clk_period / 2)) { > + /* Performance mode. */ > + ext_rd_mode = 0; > + tdvw = calc_tdvw(trp_cnt, clk_period, sdr->tRHOH_min, > + sdr->tREA_max, ext_rd_mode); > + tdvw_max = calc_tdvw_max(trp_cnt, clk_period, sdr->tRHOH_min, > + board_delay_skew_min, > + ext_rd_mode); > + /* > + * Check if data valid window and sampling point can be found > + * and is not on the edge (ie. we have hold margin). > + * If not extend the tRP timings. > + */ > + if (tdvw > 0) { > + if (tdvw_max <= tdvw_min || > + (tdvw_max % dqs_sampl_res) == 0) { > + /* > + * No valid sampling point so the RE pulse need > + * to be widen widening by half clock cycle. > + */ > + ext_rd_mode = 1; > + } > + } else { > + /* > + * There is no valid window > + * to be able to sample data the tRP need to be widen. > + * Very safe calculations are performed here. > + */ > + trp_cnt = (sdr->tREA_max + board_delay_skew_max > + + dqs_sampl_res) / clk_period; > + ext_rd_mode = 1; > + } > + > + } else { > + /* Extended read mode. */ > + u32 trh; > + > + ext_rd_mode = 1; > + trp_cnt = calc_cycl(sdr->tRP_min, clk_period); > + trh = sdr->tRC_min - ((trp_cnt + 1) * clk_period); > + if (sdr->tREH_min >= trh) > + trh_cnt = calc_cycl(sdr->tREH_min, clk_period); > + else > + trh_cnt = calc_cycl(trh, clk_period); > + > + tdvw = calc_tdvw(trp_cnt, clk_period, sdr->tRHOH_min, > + sdr->tREA_max, ext_rd_mode); > + /* > + * Check if data valid window and sampling point can be found > + * or if it is at the edge check if previous is valid > + * - if not extend the tRP timings. > + */ > + if (tdvw > 0) { > + tdvw_max = calc_tdvw_max(trp_cnt, clk_period, > + sdr->tRHOH_min, > + board_delay_skew_min, > + ext_rd_mode); > + > + if ((((tdvw_max / dqs_sampl_res) > + * dqs_sampl_res) <= tdvw_min) || > + (((tdvw_max % dqs_sampl_res) == 0) && > + (((tdvw_max / dqs_sampl_res - 1) > + * dqs_sampl_res) <= tdvw_min))) { > + /* > + * Data valid window width is lower than > + * sampling resolution and do not hit any > + * sampling point to be sure the sampling point > + * will be found the RE low pulse width will be > + * extended by one clock cycle. > + */ > + trp_cnt = trp_cnt + 1; > + } > + } else { > + /* > + * There is no valid window to be able to sample data. > + * The tRP need to be widen. > + * Very safe calculations are performed here. > + */ > + trp_cnt = (sdr->tREA_max + board_delay_skew_max > + + dqs_sampl_res) / clk_period; > + } > + } > + > + tdvw_max = calc_tdvw_max(trp_cnt, clk_period, > + sdr->tRHOH_min, > + board_delay_skew_min, ext_rd_mode); > + > + if (sdr->tWC_min <= clk_period && > + (sdr->tWP_min + if_skew) <= (clk_period / 2) && > + (sdr->tWH_min + if_skew) <= (clk_period / 2)) { > + ext_wr_mode = 0; > + } else { > + u32 twh; > + > + ext_wr_mode = 1; > + twp_cnt = calc_cycl(sdr->tWP_min + if_skew, clk_period); > + if ((twp_cnt + 1) * clk_period < (sdr->tALS_min + if_skew)) > + twp_cnt = calc_cycl(sdr->tALS_min + if_skew, > + clk_period); > + > + twh = (sdr->tWC_min - (twp_cnt + 1) * clk_period); > + if (sdr->tWH_min >= twh) > + twh = sdr->tWH_min; > + > + twh_cnt = calc_cycl(twh + if_skew, clk_period); > + } > + > + reg = FIELD_PREP(ASYNC_TOGGLE_TIMINGS_TRH, trh_cnt); > + reg |= FIELD_PREP(ASYNC_TOGGLE_TIMINGS_TRP, trp_cnt); > + reg |= FIELD_PREP(ASYNC_TOGGLE_TIMINGS_TWH, twh_cnt); > + reg |= FIELD_PREP(ASYNC_TOGGLE_TIMINGS_TWP, twp_cnt); > + t->async_toggle_timings = reg; > + dev_dbg(cdns_ctrl->dev, "ASYNC_TOGGLE_TIMINGS_SDR\t%x\n", reg); > + > + tadl_cnt = calc_cycl((sdr->tADL_min + if_skew), clk_period); > + tccs_cnt = calc_cycl((sdr->tCCS_min + if_skew), clk_period); > + twhr_cnt = calc_cycl((sdr->tWHR_min + if_skew), clk_period); > + trhw_cnt = calc_cycl((sdr->tRHW_min + if_skew), clk_period); > + reg = FIELD_PREP(TIMINGS0_TADL, tadl_cnt); > + > + /* > + * If timing exceeds delay field in timing register > + * then use maximum value. > + */ > + if (FIELD_FIT(TIMINGS0_TCCS, tccs_cnt)) > + reg |= FIELD_PREP(TIMINGS0_TCCS, tccs_cnt); > + else > + reg |= TIMINGS0_TCCS; > + > + reg |= FIELD_PREP(TIMINGS0_TWHR, twhr_cnt); > + reg |= FIELD_PREP(TIMINGS0_TRHW, trhw_cnt); > + t->timings0 = reg; > + dev_dbg(cdns_ctrl->dev, "TIMINGS0_SDR\t%x\n", reg); > + > + /* The following is related to single signal so skew is not needed. */ > + trhz_cnt = calc_cycl(sdr->tRHZ_max, clk_period); > + trhz_cnt = trhz_cnt + 1; > + twb_cnt = calc_cycl((sdr->tWB_max + board_delay), clk_period); > + /* > + * Because of the two stage syncflop the value must be increased by 3 > + * first value is related with sync, second value is related > + * with output if delay. > + */ > + twb_cnt = twb_cnt + 3 + 5; > + /* > + * The following is related to the we edge of the random data input > + * sequence so skew is not needed. > + */ > + tvdly_cnt = calc_cycl(500000 + if_skew, clk_period); > + reg = FIELD_PREP(TIMINGS1_TRHZ, trhz_cnt); > + reg |= FIELD_PREP(TIMINGS1_TWB, twb_cnt); > + reg |= FIELD_PREP(TIMINGS1_TVDLY, tvdly_cnt); > + t->timings1 = reg; > + dev_dbg(cdns_ctrl->dev, "TIMINGS1_SDR\t%x\n", reg); > + > + tfeat_cnt = calc_cycl(sdr->tFEAT_max, clk_period); > + if (tfeat_cnt < twb_cnt) > + tfeat_cnt = twb_cnt; > + > + tceh_cnt = calc_cycl(sdr->tCEH_min, clk_period); > + tcs_cnt = calc_cycl((sdr->tCS_min + if_skew), clk_period); > + > + reg = FIELD_PREP(TIMINGS2_TFEAT, tfeat_cnt); > + reg |= FIELD_PREP(TIMINGS2_CS_HOLD_TIME, tceh_cnt); > + reg |= FIELD_PREP(TIMINGS2_CS_SETUP_TIME, tcs_cnt); > + t->timings2 = reg; > + dev_dbg(cdns_ctrl->dev, "TIMINGS2_SDR\t%x\n", reg); > + > + if (cdns_ctrl->caps2.is_phy_type_dll) { > + reg = DLL_PHY_CTRL_DLL_RST_N; > + if (ext_wr_mode) > + reg |= DLL_PHY_CTRL_EXTENDED_WR_MODE; > + if (ext_rd_mode) > + reg |= DLL_PHY_CTRL_EXTENDED_RD_MODE; > + > + reg |= FIELD_PREP(DLL_PHY_CTRL_RS_HIGH_WAIT_CNT, 7); > + reg |= FIELD_PREP(DLL_PHY_CTRL_RS_IDLE_CNT, 7); > + t->dll_phy_ctrl = reg; > + dev_dbg(cdns_ctrl->dev, "DLL_PHY_CTRL_SDR\t%x\n", reg); > + } > + > + /* Sampling point calculation. */ > + if ((tdvw_max % dqs_sampl_res) > 0) > + sampling_point = tdvw_max / dqs_sampl_res; > + else > + sampling_point = (tdvw_max / dqs_sampl_res - 1); > + > + if (sampling_point * dqs_sampl_res > tdvw_min) { > + dll_phy_dqs_timing = > + FIELD_PREP(PHY_DQS_TIMING_DQS_SEL_OE_END, 4); > + dll_phy_dqs_timing |= PHY_DQS_TIMING_USE_PHONY_DQS; > + phony_dqs_timing = sampling_point / phony_dqs_mod; > + > + if ((sampling_point % 2) > 0) { > + dll_phy_dqs_timing |= PHY_DQS_TIMING_PHONY_DQS_SEL; > + if ((tdvw_max % dqs_sampl_res) == 0) > + /* > + * Calculation for sampling point at the edge > + * of data and being odd number. > + */ > + phony_dqs_timing = (tdvw_max / dqs_sampl_res) > + / phony_dqs_mod - 1; > + > + if (!cdns_ctrl->caps2.is_phy_type_dll) > + phony_dqs_timing--; > + > + } else { > + phony_dqs_timing--; > + } > + rd_del_sel = phony_dqs_timing + 3; > + } else { > + dev_warn(cdns_ctrl->dev, > + "ERROR : cannot find valid sampling point\n"); > + } > + > + reg = FIELD_PREP(PHY_CTRL_PHONY_DQS, phony_dqs_timing); > + if (cdns_ctrl->caps2.is_phy_type_dll) > + reg |= PHY_CTRL_SDR_DQS; > + t->phy_ctrl = reg; > + dev_dbg(cdns_ctrl->dev, "PHY_CTRL_REG_SDR\t%x\n", reg); > + > + if (cdns_ctrl->caps2.is_phy_type_dll) { > + dev_dbg(cdns_ctrl->dev, "PHY_TSEL_REG_SDR\t%x\n", 0); > + dev_dbg(cdns_ctrl->dev, "PHY_DQ_TIMING_REG_SDR\t%x\n", 2); > + dev_dbg(cdns_ctrl->dev, "PHY_DQS_TIMING_REG_SDR\t%x\n", > + dll_phy_dqs_timing); > + t->phy_dqs_timing = dll_phy_dqs_timing; > + > + reg = FIELD_PREP(PHY_GATE_LPBK_CTRL_RDS, rd_del_sel); > + dev_dbg(cdns_ctrl->dev, "PHY_GATE_LPBK_CTRL_REG_SDR\t%x\n", > + reg); > + t->phy_gate_lpbk_ctrl = reg; > + > + dev_dbg(cdns_ctrl->dev, "PHY_DLL_MASTER_CTRL_REG_SDR\t%lx\n", > + PHY_DLL_MASTER_CTRL_BYPASS_MODE); > + dev_dbg(cdns_ctrl->dev, "PHY_DLL_SLAVE_CTRL_REG_SDR\t%x\n", 0); > + } > + > + return 0; > +} > + > +int cadence_nand_attach_chip(struct nand_chip *chip) > +{ > + struct cdns_nand_ctrl *cdns_ctrl = to_cdns_nand_ctrl(chip->controller); > + struct cdns_nand_chip *cdns_chip = to_cdns_nand_chip(chip); > + struct mtd_info *mtd = nand_to_mtd(chip); > + u32 max_oob_data_size; > + int ret; > + > + if (chip->options & NAND_BUSWIDTH_16) { > + ret = cadence_nand_set_access_width16(cdns_ctrl, true); > + if (ret) > + goto free_buf; > + } > + > + chip->bbt_options |= NAND_BBT_USE_FLASH; > + chip->bbt_options |= NAND_BBT_NO_OOB; > + chip->ecc.mode = NAND_ECC_HW; > + > + chip->options |= NAND_NO_SUBPAGE_WRITE; > + > + cdns_chip->bbm_offs = chip->badblockpos; > + if (chip->options & NAND_BUSWIDTH_16) { > + cdns_chip->bbm_offs &= ~0x01; > + cdns_chip->bbm_len = 2; > + } else { > + cdns_chip->bbm_len = 1; > + } > + > + ret = nand_ecc_choose_conf(chip, > + &cdns_ctrl->ecc_caps, > + mtd->oobsize - cdns_chip->bbm_len); > + if (ret) { > + dev_err(cdns_ctrl->dev, "ECC configuration failed\n"); > + goto free_buf; > + } > + > + dev_dbg(cdns_ctrl->dev, > + "chosen ECC settings: step=%d, strength=%d, bytes=%d\n", > + chip->ecc.size, chip->ecc.strength, chip->ecc.bytes); > + > + /* Error correction configuration. */ > + cdns_chip->sector_size = chip->ecc.size; > + cdns_chip->sector_count = mtd->writesize / cdns_chip->sector_size; > + > + cdns_chip->avail_oob_size = mtd->oobsize > + - cdns_chip->sector_count * chip->ecc.bytes; > + > + max_oob_data_size = MAX_OOB_SIZE_PER_SECTOR; > + > + if (cdns_chip->avail_oob_size > max_oob_data_size) > + cdns_chip->avail_oob_size = max_oob_data_size; > + > + if ((cdns_chip->avail_oob_size + cdns_chip->bbm_len > + + cdns_chip->sector_count > + * chip->ecc.bytes) > mtd->oobsize) If the line is not readable enough you can use intermediate variables. Also the priority of the '*' operator could be enforced with parenthesis. Really this is just a nit pick :) > + cdns_chip->avail_oob_size -= 4; > + > + cdns_chip->corr_str_idx = > + cadence_nand_get_ecc_strength_idx(cdns_ctrl, > + chip->ecc.strength); > + if (cdns_chip->corr_str_idx < 0) > + return -EINVAL; > + > + if (cadence_nand_wait_for_value(cdns_ctrl, CTRL_STATUS, > + 1000000, > + CTRL_STATUS_CTRL_BUSY, true)) > + return -ETIMEDOUT; > + > + cadence_nand_set_ecc_strength(cdns_ctrl, > + cdns_chip->corr_str_idx); > + > + cadence_nand_set_erase_detection(cdns_ctrl, true, > + chip->ecc.strength); > + > + /* Override the default read operations. */ > + chip->ecc.read_page = cadence_nand_read_page; > + chip->ecc.read_page_raw = cadence_nand_read_page_raw; > + chip->ecc.write_page = cadence_nand_write_page; > + chip->ecc.write_page_raw = cadence_nand_write_page_raw; > + chip->ecc.read_oob = cadence_nand_read_oob; > + chip->ecc.write_oob = cadence_nand_write_oob; > + chip->ecc.read_oob_raw = cadence_nand_read_oob_raw; > + chip->ecc.write_oob_raw = cadence_nand_write_oob_raw; > + > + if ((mtd->writesize + mtd->oobsize) > cdns_ctrl->buf_size) { > + cdns_ctrl->buf_size = mtd->writesize + mtd->oobsize; > + kfree(cdns_ctrl->buf); > + cdns_ctrl->buf = kzalloc(cdns_ctrl->buf_size, GFP_KERNEL); > + if (!cdns_ctrl->buf) { > + ret = -ENOMEM; > + goto free_buf; > + } > + } > + > + /* Is 32-bit DMA supported? */ > + ret = dma_set_mask(cdns_ctrl->dev, DMA_BIT_MASK(32)); > + if (ret) { > + dev_err(cdns_ctrl->dev, "no usable DMA configuration\n"); > + goto free_buf; > + } > + > + mtd_set_ooblayout(mtd, &cadence_nand_ooblayout_ops); > + > + return 0; > + > +free_buf: > + kfree(cdns_ctrl->buf); > + > + return ret; > +} > + > +static const struct nand_controller_ops cadence_nand_controller_ops = { > + .attach_chip = cadence_nand_attach_chip, > + .exec_op = cadence_nand_exec_op, > + .setup_data_interface = cadence_nand_setup_data_interface, > +}; > + > +static int cadence_nand_chip_init(struct cdns_nand_ctrl *cdns_ctrl, > + struct device_node *np) > +{ > + struct cdns_nand_chip *cdns_chip; > + struct mtd_info *mtd; > + struct nand_chip *chip; > + int nsels, ret, i; > + u32 cs; > + > + nsels = of_property_count_elems_of_size(np, "reg", sizeof(u32)); > + if (nsels <= 0) { > + dev_err(cdns_ctrl->dev, "missing/invalid reg property\n"); > + return -EINVAL; > + } > + > + /* Allocate the nand chip structure. */ > + cdns_chip = devm_kzalloc(cdns_ctrl->dev, sizeof(*cdns_chip) + > + (nsels * sizeof(u8)), > + GFP_KERNEL); > + if (!cdns_chip) { > + dev_err(cdns_ctrl->dev, "could not allocate chip structure\n"); > + return -ENOMEM; > + } > + > + cdns_chip->nsels = nsels; > + > + for (i = 0; i < nsels; i++) { > + /* Retrieve CS id. */ > + ret = of_property_read_u32_index(np, "reg", i, &cs); > + if (ret) { > + dev_err(cdns_ctrl->dev, > + "could not retrieve reg property: %d\n", > + ret); > + return ret; > + } > + > + if (cs >= cdns_ctrl->caps2.max_banks) { > + dev_err(cdns_ctrl->dev, > + "invalid reg value: %u (max CS = %d)\n", > + cs, cdns_ctrl->caps2.max_banks); > + return -EINVAL; > + } > + > + if (test_and_set_bit(cs, &cdns_ctrl->assigned_cs)) { > + dev_err(cdns_ctrl->dev, > + "CS %d already assigned\n", cs); > + return -EINVAL; > + } > + > + cdns_chip->cs[i] = cs; > + } > + > + chip = &cdns_chip->chip; > + chip->controller = &cdns_ctrl->controller; > + nand_set_flash_node(chip, np); > + > + mtd = nand_to_mtd(chip); > + mtd->dev.parent = cdns_ctrl->dev; > + > + /* > + * Default to HW ECC engine mode. If the nand-ecc-mode property is given > + * in the DT node, this entry will be overwritten in nand_scan_ident(). > + */ > + chip->ecc.mode = NAND_ECC_HW; > + > + ret = nand_scan(chip, cdns_chip->nsels); > + if (ret) { > + dev_err(cdns_ctrl->dev, "could not scan the nand chip\n"); > + return ret; > + } > + > + ret = mtd_device_register(mtd, NULL, 0); > + if (ret) { > + dev_err(cdns_ctrl->dev, > + "failed to register mtd device: %d\n", ret); > + nand_cleanup(chip); > + return ret; > + } > + > + list_add_tail(&cdns_chip->node, &cdns_ctrl->chips); > + > + return 0; > +} > + > +static void cadence_nand_chips_cleanup(struct cdns_nand_ctrl *cdns_ctrl) > +{ > + struct cdns_nand_chip *entry, *temp; > + > + list_for_each_entry_safe(entry, temp, &cdns_ctrl->chips, node) { > + nand_release(&entry->chip); > + list_del(&entry->node); > + } > +} > + > +static int cadence_nand_chips_init(struct cdns_nand_ctrl *cdns_ctrl) > +{ > + struct device_node *np = cdns_ctrl->dev->of_node; > + struct device_node *nand_np; > + int max_cs = cdns_ctrl->caps2.max_banks; > + int nchips, ret; > + > + nchips = of_get_child_count(np); > + > + if (nchips > max_cs) { > + dev_err(cdns_ctrl->dev, > + "too many NAND chips: %d (max = %d CS)\n", > + nchips, max_cs); > + return -EINVAL; > + } > + > + for_each_child_of_node(np, nand_np) { > + ret = cadence_nand_chip_init(cdns_ctrl, nand_np); > + if (ret) { > + of_node_put(nand_np); > + cadence_nand_chips_cleanup(cdns_ctrl); > + return ret; > + } > + } > + > + return 0; > +} > + > +static int cadence_nand_init(struct cdns_nand_ctrl *cdns_ctrl) > +{ > + dma_cap_mask_t mask; > + int ret; > + > + cdns_ctrl->cdma_desc = dma_alloc_coherent(cdns_ctrl->dev, > + sizeof(*cdns_ctrl->cdma_desc), > + &cdns_ctrl->dma_cdma_desc, > + GFP_KERNEL); > + if (!cdns_ctrl->dma_cdma_desc) > + return -ENOMEM; > + > + cdns_ctrl->buf_size = SZ_16K; > + cdns_ctrl->buf = kmalloc(cdns_ctrl->buf_size, GFP_KERNEL); > + if (!cdns_ctrl->buf) { > + goto free_buf_desc; > + ret = -ENOMEM; > + } > + > + if (devm_request_irq(cdns_ctrl->dev, cdns_ctrl->irq, cadence_nand_isr, > + IRQF_SHARED, "cadence-nand-controller", > + cdns_ctrl)) { > + dev_err(cdns_ctrl->dev, "Unable to allocate IRQ\n"); > + ret = -ENODEV; > + goto free_buf; > + } > + > + spin_lock_init(&cdns_ctrl->irq_lock); > + init_completion(&cdns_ctrl->complete); > + > + ret = cadence_nand_hw_init(cdns_ctrl); > + if (ret) > + goto disable_irq; > + > + dma_cap_zero(mask); > + dma_cap_set(DMA_MEMCPY, mask); > + > + if (cdns_ctrl->caps1->has_dma) { > + cdns_ctrl->dmac = dma_request_channel(mask, NULL, NULL); > + if (!cdns_ctrl->dmac) { > + dev_err(cdns_ctrl->dev, > + "Unable to get a DMA channel\n"); > + ret = -EBUSY; > + goto disable_irq; > + } > + } > + > + nand_controller_init(&cdns_ctrl->controller); > + INIT_LIST_HEAD(&cdns_ctrl->chips); > + > + cdns_ctrl->controller.ops = &cadence_nand_controller_ops; > + cdns_ctrl->curr_corr_str_idx = 0xFF; > + > + ret = cadence_nand_chips_init(cdns_ctrl); > + if (ret) { > + dev_err(cdns_ctrl->dev, "Failed to register MTD: %d\n", > + ret); > + goto dma_release_chnl; > + } > + > + return 0; > + > +dma_release_chnl: > + if (cdns_ctrl->dmac) > + dma_release_channel(cdns_ctrl->dmac); > + > +disable_irq: > + cadence_nand_irq_cleanup(cdns_ctrl->irq, cdns_ctrl); > + > +free_buf: > + kfree(cdns_ctrl->buf); > + > +free_buf_desc: > + dma_free_coherent(cdns_ctrl->dev, sizeof(struct cadence_nand_cdma_desc), > + cdns_ctrl->cdma_desc, cdns_ctrl->dma_cdma_desc); > + > + return ret; > +} > + > +/* Driver exit point. */ > +static void cadence_nand_remove(struct cdns_nand_ctrl *cdns_ctrl) > +{ > + cadence_nand_chips_cleanup(cdns_ctrl); > + cadence_nand_irq_cleanup(cdns_ctrl->irq, cdns_ctrl); > + kfree(cdns_ctrl->buf); > + dma_free_coherent(cdns_ctrl->dev, sizeof(struct cadence_nand_cdma_desc), > + cdns_ctrl->cdma_desc, cdns_ctrl->dma_cdma_desc); > + > + if (cdns_ctrl->dmac) > + dma_release_channel(cdns_ctrl->dmac); > +} > + > +struct cadence_nand_dt { > + struct cdns_nand_ctrl cdns_ctrl; > + struct clk *clk; > +}; > + > +static const struct cadence_nand_dt_devdata cadence_nand_default = { > + .if_skew = 0, > + .has_dma = 1, > +}; > + > +static const struct of_device_id cadence_nand_dt_ids[] = { > + { > + .compatible = "cdns,hp-nfc", > + .data = &cadence_nand_default > + }, {} > +}; > + > +MODULE_DEVICE_TABLE(of, cadence_nand_dt_ids); > + > +static int cadence_nand_dt_probe(struct platform_device *ofdev) > +{ > + struct resource *res; > + struct cadence_nand_dt *dt; > + struct cdns_nand_ctrl *cdns_ctrl; > + int ret; > + const struct of_device_id *of_id; > + const struct cadence_nand_dt_devdata *devdata; > + u32 val; > + > + of_id = of_match_device(cadence_nand_dt_ids, &ofdev->dev); > + if (of_id) { > + ofdev->id_entry = of_id->data; > + devdata = of_id->data; > + } else { > + pr_err("Failed to find the right device id.\n"); > + return -ENOMEM; > + } > + > + dt = devm_kzalloc(&ofdev->dev, sizeof(*dt), GFP_KERNEL); > + if (!dt) > + return -ENOMEM; > + > + cdns_ctrl = &dt->cdns_ctrl; > + cdns_ctrl->caps1 = devdata; > + > + cdns_ctrl->dev = &ofdev->dev; > + cdns_ctrl->irq = platform_get_irq(ofdev, 0); > + if (cdns_ctrl->irq < 0) { > + dev_err(&ofdev->dev, "no irq defined\n"); > + return cdns_ctrl->irq; > + } > + dev_info(cdns_ctrl->dev, "IRQ: nr %d\n", cdns_ctrl->irq); > + > + res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); > + cdns_ctrl->reg = devm_ioremap_resource(cdns_ctrl->dev, res); I think this will be refused by robots, you have to squash the two lines into cdns_ctrl->reg = devm_platform_ioremap_resource(ofdev, 0); > + if (IS_ERR(cdns_ctrl->reg)) { > + dev_err(&ofdev->dev, "devm_ioremap_resource res 0 failed\n"); > + return PTR_ERR(cdns_ctrl->reg); > + } > + > + res = platform_get_resource(ofdev, IORESOURCE_MEM, 1); > + cdns_ctrl->io.dma = res->start; > + cdns_ctrl->io.virt = devm_ioremap_resource(&ofdev->dev, res); > + if (IS_ERR(cdns_ctrl->io.virt)) { > + dev_err(cdns_ctrl->dev, "devm_ioremap_resource res 1 failed\n"); > + return PTR_ERR(cdns_ctrl->io.virt); > + } > + > + dt->clk = devm_clk_get(cdns_ctrl->dev, "nf_clk"); > + if (IS_ERR(dt->clk)) > + return PTR_ERR(dt->clk); > + > + cdns_ctrl->nf_clk_rate = clk_get_rate(dt->clk); > + > + ret = of_property_read_u32(ofdev->dev.of_node, > + "cdns,board-delay-ps", &val); > + if (ret) { > + dev_warn(cdns_ctrl->dev, "missing cdns,board-delay-ps property\n"); Maybe you could turn this property into an optional one, with a default value? > + val = 0; > + } > + cdns_ctrl->board_delay = val; > + > + ret = cadence_nand_init(cdns_ctrl); > + if (ret) > + return ret; > + > + platform_set_drvdata(ofdev, dt); > + return 0; > +} > + > +static int cadence_nand_dt_remove(struct platform_device *ofdev) > +{ > + struct cadence_nand_dt *dt = platform_get_drvdata(ofdev); > + > + cadence_nand_remove(&dt->cdns_ctrl); > + > + return 0; > +} > + > +static struct platform_driver cadence_nand_dt_driver = { > + .probe = cadence_nand_dt_probe, > + .remove = cadence_nand_dt_remove, > + .driver = { > + .name = "cadence-nand-controller", > + .of_match_table = cadence_nand_dt_ids, > + }, > +}; > + > +module_platform_driver(cadence_nand_dt_driver); > + > +MODULE_AUTHOR("Piotr Sroka "); > +MODULE_LICENSE("GPL v2"); > +MODULE_DESCRIPTION("Driver for Cadence NAND flash controller"); > + Would you mind adding yourself in MAINTAINERS for this driver (+ bindings)? Thanks, Miquèl