From mboxrd@z Thu Jan 1 00:00:00 1970 Date: Mon, 10 Dec 2018 11:19:09 +0100 From: Boris Brezillon To: Yogesh Narayan Gaur Cc: Schrempf Frieder , "linux-mtd@lists.infradead.org" , "marek.vasut@gmail.com" , "broonie@kernel.org" , "linux-spi@vger.kernel.org" , "devicetree@vger.kernel.org" , "robh@kernel.org" , "mark.rutland@arm.com" , "shawnguo@kernel.org" , "linux-arm-kernel@lists.infradead.org" , "computersforpeace@gmail.com" , "linux-kernel@vger.kernel.org" Subject: Re: [PATCH v5 1/5] spi: spi-mem: Add driver for NXP FlexSPI controller Message-ID: <20181210111909.35384eee@bbrezillon> In-Reply-To: References: <1542366701-16065-1-git-send-email-yogeshnarayan.gaur@nxp.com> <1542366701-16065-2-git-send-email-yogeshnarayan.gaur@nxp.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , On Mon, 10 Dec 2018 09:41:51 +0000 Yogesh Narayan Gaur wrote: > > > +/* Instead of busy looping invoke readl_poll_timeout functionality. > > > +*/ static int fspi_readl_poll_tout(struct nxp_fspi *f, void __iomem = *base, > > > + u32 mask, u32 delay_us, > > > + u32 timeout_us, bool condition) > > > +{ > > > + u32 reg; > > > + > > > + if (!f->devtype_data->little_endian) > > > + mask =3D (u32)cpu_to_be32(mask); > > > + > > > + if (condition) > > > + return readl_poll_timeout(base, reg, (reg & mask), > > > + delay_us, timeout_us); > > > + else > > > + return readl_poll_timeout(base, reg, !(reg & mask), > > > + delay_us, timeout_us); =20 > >=20 > > I would rather use a local variable to store the condition: > >=20 > > bool c =3D condition ? (reg & mask):!(reg & mask); > > =20 > With these type of usage getting below warning messages. > =20 > drivers/spi/spi-nxp-fspi.c: In function =E2=80=98fspi_readl_poll_tout.isr= a.10.constprop=E2=80=99: > drivers/spi/spi-nxp-fspi.c:446:21: warning: =E2=80=98reg=E2=80=99 may be = used uninitialized in this function [-Wmaybe-uninitialized] > bool cn =3D c ? (reg & mask) : !(reg & mask); >=20 > If assign value to reg =3D 0xffffffff then timeout is start getting hit f= or False case and if assign value 0 then start getting timeout hit for true= case. >=20 > I would rather not try to modify this function. I agree. Let's keep this function readable even if this implies duplicating a few lines of code. >=20 > > return readl_poll_timeout(base, reg, c, delay_us, timeout_us); > > =20 > > > +} > > > + > > > +/* > > > + * If the slave device content being changed by Write/Erase, need to > > > + * invalidate the AHB buffer. This can be achieved by doing the reset > > > + * of controller after setting MCR0[SWRESET] bit. > > > + */ > > > +static inline void nxp_fspi_invalid(struct nxp_fspi *f) { > > > + u32 reg; > > > + int ret; > > > + > > > + reg =3D fspi_readl(f, f->iobase + FSPI_MCR0); > > > + fspi_writel(f, reg | FSPI_MCR0_SWRST, f->iobase + FSPI_MCR0); > > > + > > > + /* w1c register, wait unit clear */ > > > + ret =3D fspi_readl_poll_tout(f, f->iobase + FSPI_MCR0, > > > + FSPI_MCR0_SWRST, 0, POLL_TOUT, false); > > > + WARN_ON(ret); > > > +} > > > + > > > +static void nxp_fspi_prepare_lut(struct nxp_fspi *f, > > > + const struct spi_mem_op *op) > > > +{ > > > + void __iomem *base =3D f->iobase; > > > + u32 lutval[4] =3D {}; > > > + int lutidx =3D 1, i; > > > + > > > + /* cmd */ > > > + lutval[0] |=3D LUT_DEF(0, LUT_CMD, LUT_PAD(op->cmd.buswidth), > > > + op->cmd.opcode); > > > + > > > + /* addr bus width */ > > > + if (op->addr.nbytes) { > > > + u32 addrlen =3D 0; > > > + > > > + switch (op->addr.nbytes) { > > > + case 1: > > > + addrlen =3D ADDR8BIT; > > > + break; > > > + case 2: > > > + addrlen =3D ADDR16BIT; > > > + break; > > > + case 3: > > > + addrlen =3D ADDR24BIT; > > > + break; > > > + case 4: > > > + addrlen =3D ADDR32BIT; > > > + break; > > > + default: > > > + dev_err(f->dev, "In-correct address length\n"); > > > + return; > > > + } =20 > >=20 > > You don't need to validate op->addr.nbytes here, this is already done in > > nxp_fspi_supports_op(). =20 >=20 > Yes, I need to validate op->addr.nbytes else LUT would going to be progra= mmed for 0 addrlen. > I have checked this on the target. Also agree there. Some operations have 0 address bytes. We could also test addr.buswidth, but I'm fine with the addr.nbytes test too. > > > +static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device > > > +*spi) { > > > + unsigned long rate =3D spi->max_speed_hz; > > > + int ret; > > > + uint64_t size_kb; > > > + > > > + /* > > > + * Return, if previously selected slave device is same as current > > > + * requested slave device. > > > + */ > > > + if (f->selected =3D=3D spi->chip_select) > > > + return; > > > + > > > + /* Reset FLSHxxCR0 registers */ > > > + fspi_writel(f, 0, f->iobase + FSPI_FLSHA1CR0); > > > + fspi_writel(f, 0, f->iobase + FSPI_FLSHA2CR0); > > > + fspi_writel(f, 0, f->iobase + FSPI_FLSHB1CR0); > > > + fspi_writel(f, 0, f->iobase + FSPI_FLSHB2CR0); > > > + > > > + /* Assign controller memory mapped space as size, KBytes, of flash.= */ > > > + size_kb =3D FSPI_FLSHXCR0_SZ(f->memmap_phy_size); =20 > > =20 > Above description of this function, explains the reason for using memmap_= phy_size. > This is not the arbitrary size, but the memory mapped size being assigned= to the controller. >=20 > > You are still using memory of arbitrary size (memmap_phy_size) for mapp= ing the > > flash. Why not use the same approach as in the QSPI driver and just map > > ahb_buf_size until we implement the dirmap API? =20 > The approach which being used in QSPI driver didn't work here, I have tri= ed with that. > In QSPI driver, while preparing LUT we are assigning read/write address i= n the LUT preparation and have to for some unknown hack have to provide mac= ro for LUT_MODE instead of LUT_ADDR. > But this thing didn't work for FlexSPI. > I discussed with HW IP owner and they suggested only to use LUT_ADDR for = specifying the address length of the command i.e. 3-byte or 4-byte address = command (NOR) or 1-2 byte address command for NAND. Actually, we would have used a LUT_ADDR too if the QSPI IP was support ADDR instructions with a number of bytes < 3, but for some unknown reasons it does not work.=20 >=20 > Thus, in LUT preparation we have assigned only the base address. > Now if I have assigned ahb_buf_size to FSPI_FLSHXXCR0 register then for r= ead/write data beyond limit of ahb_buf_size offset I get data corruption. Why would you do that? We have the ->adjust_op_size() exactly for this reason, so, if someone tries to do a spi_mem_op with data.nbytes > ahb_buf_size you should return an error. >=20 > Thus, for generic approach have assigned FSPI_FLSHXXCR0 equal to the memo= ry mapped size to the controller. This would also not going to depend on th= e number of CS present on the target. I kind of agree with Frieder on that one, I think it's preferable to limit the per-read-op size to ahb_buf_size and let the upper layer split the request in several sub-requests. On the controller side of things, you just have to have a mapping of ahb_buf_size per-CS. If you want to further optimize things, implement the dirmap hooks. >=20 > > You are already aligning the AHB reads for this in nxp_fspi_adjust_op_s= ize(). > > =20 > Yes, max read data size can be ahb_buf_size. Thus we need to check max re= ad size with ahb_buf_size. Well, it's never a bad thing to check it twice, just in case the spi-mem user is misusing the API. > > > +static void nxp_fspi_fill_txfifo(struct nxp_fspi *f, > > > + const struct spi_mem_op *op) > > > +{ > > > + void __iomem *base =3D f->iobase; > > > + int i, j, ret; > > > + int size, tmp_size, wm_size; > > > + u32 data =3D 0; > > > + u32 *txbuf =3D (u32 *) op->data.buf.out; > > > + > > > + /* clear the TX FIFO. */ > > > + fspi_writel(f, FSPI_IPTXFCR_CLR, base + FSPI_IPTXFCR); > > > + > > > + /* Default value of water mark level is 8 bytes. */ > > > + wm_size =3D 8; > > > + size =3D op->data.nbytes / wm_size; > > > + for (i =3D 0; i < size; i++) { > > > + /* Wait for TXFIFO empty */ > > > + ret =3D fspi_readl_poll_tout(f, f->iobase + FSPI_INTR, > > > + FSPI_INTR_IPTXWE, 0, > > > + POLL_TOUT, true); > > > + WARN_ON(ret); > > > + > > > + j =3D 0; > > > + tmp_size =3D wm_size; > > > + while (tmp_size > 0) { > > > + data =3D 0; > > > + memcpy(&data, txbuf, 4); > > > + fspi_writel(f, data, base + FSPI_TFDR + j * 4); > > > + tmp_size -=3D 4; > > > + j++; > > > + txbuf +=3D 1; > > > + } > > > + fspi_writel(f, FSPI_INTR_IPTXWE, base + FSPI_INTR); > > > + } > > > + > > > + size =3D op->data.nbytes % wm_size; > > > + if (size) { > > > + /* Wait for TXFIFO empty */ > > > + ret =3D fspi_readl_poll_tout(f, f->iobase + FSPI_INTR, > > > + FSPI_INTR_IPTXWE, 0, > > > + POLL_TOUT, true); > > > + WARN_ON(ret); > > > + > > > + j =3D 0; > > > + tmp_size =3D 0; > > > + while (size > 0) { > > > + data =3D 0; > > > + tmp_size =3D (size < 4) ? size : 4; > > > + memcpy(&data, txbuf, tmp_size); > > > + fspi_writel(f, data, base + FSPI_TFDR + j * 4); > > > + size -=3D tmp_size; > > > + j++; > > > + txbuf +=3D 1; > > > + } > > > + fspi_writel(f, FSPI_INTR_IPTXWE, base + FSPI_INTR); > > > + } =20 > >=20 > > All these nested loops to fill the TX buffer and also the ones below to= read the > > RX buffer look much more complicated than they should really be. Can yo= u try to > > make this more readable? =20 > Yes > >=20 > > Maybe something like this would work: > >=20 > > for (i =3D 0; i < ALIGN_DOWN(op->data.nbytes, 8); i +=3D 8) { > > /* Wait for TXFIFO empty */ > > ret =3D fspi_readl_poll_tout(f, f->iobase + FSPI_INTR, > > FSPI_INTR_IPTXWE, 0, > > POLL_TOUT, true); > >=20 > > fspi_writel(f, op->data.buf.out + i, base + FSPI_TFDR); > > fspi_writel(f, op->data.buf.out + i + 4, base + FSPI_TFDR + 4); > > fspi_writel(f, FSPI_INTR_IPTXWE, base + FSPI_INTR); } =20 > With this above 2 lines we are hardcoding it for read/write with watermar= k size as 8 bytes. > Watermark size can be variable and depends on the value of IPRXFCR/IPTXFC= R register with default value as 8 bytes > Thus, I would still prefer to use the internal for loop instead of 2 fspi= _writel(...) for FSPI_TFDR and FSPI_TFDR + 4 register write commands. Just like you're hardcoding wm_size to 8, so I don't see a difference here. And I indeed prefer Frieder's version. 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=-1.1 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SPF_PASS, URIBL_BLOCKED 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 879DFC5CFFE for ; Mon, 10 Dec 2018 10:19:29 +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 490F020821 for ; Mon, 10 Dec 2018 10:19:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="bX0rboeo" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 490F020821 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-arm-kernel-bounces+infradead-linux-arm-kernel=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=IMwLN4AIHUBwDZc1/gYx7gM3nFlsHIj5CxR69bvp/Mo=; b=bX0rboeoAXLLfI alVkR0QxYABmiscl7/bGHqu+/kOppLa4Ry4u/bELDSlsLLp6tfwivdExLINdDWblOXo8lsLhqlwlC SX4QS7+p6W9tzBwJKJ8m1a143dYlHSlkeCIxgNCSfXE/sM5KqRJUM9KeQWsxmWRlOiHQ2JCVx/cEl y7+XXzlPvY19NpldsyW+3en61XO6bRgVSNT/1L45PJa54d06i85wD7daetxGOeTuw9NvCwKpNnRyG JfvZEQ+Wjqo2tbZoxzMdhcnWcZDNj15U7w/MQP+JjL6ekkkDTHogQgL6/iLIi9kRU8gfMxkZqxVbT 0RWbq2JF5C/g26zTj85w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gWIet-0000GP-GA; Mon, 10 Dec 2018 10:19:27 +0000 Received: from mail.bootlin.com ([62.4.15.54]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gWIep-0000F7-O0; Mon, 10 Dec 2018 10:19:25 +0000 Received: by mail.bootlin.com (Postfix, from userid 110) id 2CD4320CE3; Mon, 10 Dec 2018 11:19:12 +0100 (CET) Received: from bbrezillon (91-160-177-164.subs.proxad.net [91.160.177.164]) by mail.bootlin.com (Postfix) with ESMTPSA id CB15720711; Mon, 10 Dec 2018 11:19:11 +0100 (CET) Date: Mon, 10 Dec 2018 11:19:09 +0100 From: Boris Brezillon To: Yogesh Narayan Gaur Subject: Re: [PATCH v5 1/5] spi: spi-mem: Add driver for NXP FlexSPI controller Message-ID: <20181210111909.35384eee@bbrezillon> In-Reply-To: References: <1542366701-16065-1-git-send-email-yogeshnarayan.gaur@nxp.com> <1542366701-16065-2-git-send-email-yogeshnarayan.gaur@nxp.com> X-Mailer: Claws Mail 3.16.0 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181210_021924_054970_B999EEC5 X-CRM114-Status: GOOD ( 34.46 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "mark.rutland@arm.com" , "devicetree@vger.kernel.org" , "robh@kernel.org" , "linux-kernel@vger.kernel.org" , Schrempf Frieder , "linux-spi@vger.kernel.org" , "marek.vasut@gmail.com" , "broonie@kernel.org" , "linux-mtd@lists.infradead.org" , "computersforpeace@gmail.com" , "shawnguo@kernel.org" , "linux-arm-kernel@lists.infradead.org" Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org T24gTW9uLCAxMCBEZWMgMjAxOCAwOTo0MTo1MSArMDAwMApZb2dlc2ggTmFyYXlhbiBHYXVyIDx5 b2dlc2huYXJheWFuLmdhdXJAbnhwLmNvbT4gd3JvdGU6Cgo+ID4gPiArLyogSW5zdGVhZCBvZiBi dXN5IGxvb3BpbmcgaW52b2tlIHJlYWRsX3BvbGxfdGltZW91dCBmdW5jdGlvbmFsaXR5Lgo+ID4g PiArKi8gc3RhdGljIGludCBmc3BpX3JlYWRsX3BvbGxfdG91dChzdHJ1Y3QgbnhwX2ZzcGkgKmYs IHZvaWQgX19pb21lbSAqYmFzZSwKPiA+ID4gKwkJCQl1MzIgbWFzaywgdTMyIGRlbGF5X3VzLAo+ ID4gPiArCQkJCXUzMiB0aW1lb3V0X3VzLCBib29sIGNvbmRpdGlvbikKPiA+ID4gK3sKPiA+ID4g Kwl1MzIgcmVnOwo+ID4gPiArCj4gPiA+ICsJaWYgKCFmLT5kZXZ0eXBlX2RhdGEtPmxpdHRsZV9l bmRpYW4pCj4gPiA+ICsJCW1hc2sgPSAodTMyKWNwdV90b19iZTMyKG1hc2spOwo+ID4gPiArCj4g PiA+ICsJaWYgKGNvbmRpdGlvbikKPiA+ID4gKwkJcmV0dXJuIHJlYWRsX3BvbGxfdGltZW91dChi YXNlLCByZWcsIChyZWcgJiBtYXNrKSwKPiA+ID4gKwkJCQkJICBkZWxheV91cywgdGltZW91dF91 cyk7Cj4gPiA+ICsJZWxzZQo+ID4gPiArCQlyZXR1cm4gcmVhZGxfcG9sbF90aW1lb3V0KGJhc2Us IHJlZywgIShyZWcgJiBtYXNrKSwKPiA+ID4gKwkJCQkJICBkZWxheV91cywgdGltZW91dF91cyk7 ICAKPiA+IAo+ID4gSSB3b3VsZCByYXRoZXIgdXNlIGEgbG9jYWwgdmFyaWFibGUgdG8gc3RvcmUg dGhlIGNvbmRpdGlvbjoKPiA+IAo+ID4gYm9vbCBjID0gY29uZGl0aW9uID8gKHJlZyAmIG1hc2sp OiEocmVnICYgbWFzayk7Cj4gPiAgIAo+IFdpdGggdGhlc2UgdHlwZSBvZiB1c2FnZSBnZXR0aW5n IGJlbG93IHdhcm5pbmcgbWVzc2FnZXMuCj4gIAo+IGRyaXZlcnMvc3BpL3NwaS1ueHAtZnNwaS5j OiBJbiBmdW5jdGlvbiDigJhmc3BpX3JlYWRsX3BvbGxfdG91dC5pc3JhLjEwLmNvbnN0cHJvcOKA mToKPiBkcml2ZXJzL3NwaS9zcGktbnhwLWZzcGkuYzo0NDY6MjE6IHdhcm5pbmc6IOKAmHJlZ+KA mSBtYXkgYmUgdXNlZCB1bmluaXRpYWxpemVkIGluIHRoaXMgZnVuY3Rpb24gWy1XbWF5YmUtdW5p bml0aWFsaXplZF0KPiAgIGJvb2wgY24gPSBjID8gKHJlZyAmIG1hc2spIDogIShyZWcgJiBtYXNr KTsKPiAKPiBJZiBhc3NpZ24gdmFsdWUgdG8gcmVnID0gMHhmZmZmZmZmZiB0aGVuIHRpbWVvdXQg aXMgc3RhcnQgZ2V0dGluZyBoaXQgZm9yIEZhbHNlIGNhc2UgYW5kIGlmIGFzc2lnbiB2YWx1ZSAw IHRoZW4gc3RhcnQgZ2V0dGluZyB0aW1lb3V0IGhpdCBmb3IgdHJ1ZSBjYXNlLgo+IAo+IEkgd291 bGQgcmF0aGVyIG5vdCB0cnkgdG8gbW9kaWZ5IHRoaXMgZnVuY3Rpb24uCgpJIGFncmVlLiBMZXQn cyBrZWVwIHRoaXMgZnVuY3Rpb24gcmVhZGFibGUgZXZlbiBpZiB0aGlzIGltcGxpZXMKZHVwbGlj YXRpbmcgYSBmZXcgbGluZXMgb2YgY29kZS4KCj4gCj4gPiByZXR1cm4gcmVhZGxfcG9sbF90aW1l b3V0KGJhc2UsIHJlZywgYywgZGVsYXlfdXMsIHRpbWVvdXRfdXMpOwo+ID4gICAKPiA+ID4gK30K PiA+ID4gKwo+ID4gPiArLyoKPiA+ID4gKyAqIElmIHRoZSBzbGF2ZSBkZXZpY2UgY29udGVudCBi ZWluZyBjaGFuZ2VkIGJ5IFdyaXRlL0VyYXNlLCBuZWVkIHRvCj4gPiA+ICsgKiBpbnZhbGlkYXRl IHRoZSBBSEIgYnVmZmVyLiBUaGlzIGNhbiBiZSBhY2hpZXZlZCBieSBkb2luZyB0aGUgcmVzZXQK PiA+ID4gKyAqIG9mIGNvbnRyb2xsZXIgYWZ0ZXIgc2V0dGluZyBNQ1IwW1NXUkVTRVRdIGJpdC4K PiA+ID4gKyAqLwo+ID4gPiArc3RhdGljIGlubGluZSB2b2lkIG54cF9mc3BpX2ludmFsaWQoc3Ry dWN0IG54cF9mc3BpICpmKSB7Cj4gPiA+ICsJdTMyIHJlZzsKPiA+ID4gKwlpbnQgcmV0Owo+ID4g PiArCj4gPiA+ICsJcmVnID0gZnNwaV9yZWFkbChmLCBmLT5pb2Jhc2UgKyBGU1BJX01DUjApOwo+ ID4gPiArCWZzcGlfd3JpdGVsKGYsIHJlZyB8IEZTUElfTUNSMF9TV1JTVCwgZi0+aW9iYXNlICsg RlNQSV9NQ1IwKTsKPiA+ID4gKwo+ID4gPiArCS8qIHcxYyByZWdpc3Rlciwgd2FpdCB1bml0IGNs ZWFyICovCj4gPiA+ICsJcmV0ID0gZnNwaV9yZWFkbF9wb2xsX3RvdXQoZiwgZi0+aW9iYXNlICsg RlNQSV9NQ1IwLAo+ID4gPiArCQkJCSAgIEZTUElfTUNSMF9TV1JTVCwgMCwgUE9MTF9UT1VULCBm YWxzZSk7Cj4gPiA+ICsJV0FSTl9PTihyZXQpOwo+ID4gPiArfQo+ID4gPiArCj4gPiA+ICtzdGF0 aWMgdm9pZCBueHBfZnNwaV9wcmVwYXJlX2x1dChzdHJ1Y3QgbnhwX2ZzcGkgKmYsCj4gPiA+ICsJ CQkJIGNvbnN0IHN0cnVjdCBzcGlfbWVtX29wICpvcCkKPiA+ID4gK3sKPiA+ID4gKwl2b2lkIF9f aW9tZW0gKmJhc2UgPSBmLT5pb2Jhc2U7Cj4gPiA+ICsJdTMyIGx1dHZhbFs0XSA9IHt9Owo+ID4g PiArCWludCBsdXRpZHggPSAxLCBpOwo+ID4gPiArCj4gPiA+ICsJLyogY21kICovCj4gPiA+ICsJ bHV0dmFsWzBdIHw9IExVVF9ERUYoMCwgTFVUX0NNRCwgTFVUX1BBRChvcC0+Y21kLmJ1c3dpZHRo KSwKPiA+ID4gKwkJCSAgICAgb3AtPmNtZC5vcGNvZGUpOwo+ID4gPiArCj4gPiA+ICsJLyogYWRk ciBidXMgd2lkdGggKi8KPiA+ID4gKwlpZiAob3AtPmFkZHIubmJ5dGVzKSB7Cj4gPiA+ICsJCXUz MiBhZGRybGVuID0gMDsKPiA+ID4gKwo+ID4gPiArCQlzd2l0Y2ggKG9wLT5hZGRyLm5ieXRlcykg ewo+ID4gPiArCQljYXNlIDE6Cj4gPiA+ICsJCQlhZGRybGVuID0gQUREUjhCSVQ7Cj4gPiA+ICsJ CQlicmVhazsKPiA+ID4gKwkJY2FzZSAyOgo+ID4gPiArCQkJYWRkcmxlbiA9IEFERFIxNkJJVDsK PiA+ID4gKwkJCWJyZWFrOwo+ID4gPiArCQljYXNlIDM6Cj4gPiA+ICsJCQlhZGRybGVuID0gQURE UjI0QklUOwo+ID4gPiArCQkJYnJlYWs7Cj4gPiA+ICsJCWNhc2UgNDoKPiA+ID4gKwkJCWFkZHJs ZW4gPSBBRERSMzJCSVQ7Cj4gPiA+ICsJCQlicmVhazsKPiA+ID4gKwkJZGVmYXVsdDoKPiA+ID4g KwkJCWRldl9lcnIoZi0+ZGV2LCAiSW4tY29ycmVjdCBhZGRyZXNzIGxlbmd0aFxuIik7Cj4gPiA+ ICsJCQlyZXR1cm47Cj4gPiA+ICsJCX0gIAo+ID4gCj4gPiBZb3UgZG9uJ3QgbmVlZCB0byB2YWxp ZGF0ZSBvcC0+YWRkci5uYnl0ZXMgaGVyZSwgdGhpcyBpcyBhbHJlYWR5IGRvbmUgaW4KPiA+IG54 cF9mc3BpX3N1cHBvcnRzX29wKCkuICAKPiAKPiBZZXMsIEkgbmVlZCB0byB2YWxpZGF0ZSBvcC0+ YWRkci5uYnl0ZXMgZWxzZSBMVVQgd291bGQgZ29pbmcgdG8gYmUgcHJvZ3JhbW1lZCBmb3IgMCBh ZGRybGVuLgo+IEkgaGF2ZSBjaGVja2VkIHRoaXMgb24gdGhlIHRhcmdldC4KCkFsc28gYWdyZWUg dGhlcmUuIFNvbWUgb3BlcmF0aW9ucyBoYXZlIDAgYWRkcmVzcyBieXRlcy4gV2UgY291bGQgYWxz bwp0ZXN0IGFkZHIuYnVzd2lkdGgsIGJ1dCBJJ20gZmluZSB3aXRoIHRoZSBhZGRyLm5ieXRlcyB0 ZXN0IHRvby4KCgo+ID4gPiArc3RhdGljIHZvaWQgbnhwX2ZzcGlfc2VsZWN0X21lbShzdHJ1Y3Qg bnhwX2ZzcGkgKmYsIHN0cnVjdCBzcGlfZGV2aWNlCj4gPiA+ICsqc3BpKSB7Cj4gPiA+ICsJdW5z aWduZWQgbG9uZyByYXRlID0gc3BpLT5tYXhfc3BlZWRfaHo7Cj4gPiA+ICsJaW50IHJldDsKPiA+ ID4gKwl1aW50NjRfdCBzaXplX2tiOwo+ID4gPiArCj4gPiA+ICsJLyoKPiA+ID4gKwkgKiBSZXR1 cm4sIGlmIHByZXZpb3VzbHkgc2VsZWN0ZWQgc2xhdmUgZGV2aWNlIGlzIHNhbWUgYXMgY3VycmVu dAo+ID4gPiArCSAqIHJlcXVlc3RlZCBzbGF2ZSBkZXZpY2UuCj4gPiA+ICsJICovCj4gPiA+ICsJ aWYgKGYtPnNlbGVjdGVkID09IHNwaS0+Y2hpcF9zZWxlY3QpCj4gPiA+ICsJCXJldHVybjsKPiA+ ID4gKwo+ID4gPiArCS8qIFJlc2V0IEZMU0h4eENSMCByZWdpc3RlcnMgKi8KPiA+ID4gKwlmc3Bp X3dyaXRlbChmLCAwLCBmLT5pb2Jhc2UgKyBGU1BJX0ZMU0hBMUNSMCk7Cj4gPiA+ICsJZnNwaV93 cml0ZWwoZiwgMCwgZi0+aW9iYXNlICsgRlNQSV9GTFNIQTJDUjApOwo+ID4gPiArCWZzcGlfd3Jp dGVsKGYsIDAsIGYtPmlvYmFzZSArIEZTUElfRkxTSEIxQ1IwKTsKPiA+ID4gKwlmc3BpX3dyaXRl bChmLCAwLCBmLT5pb2Jhc2UgKyBGU1BJX0ZMU0hCMkNSMCk7Cj4gPiA+ICsKPiA+ID4gKwkvKiBB c3NpZ24gY29udHJvbGxlciBtZW1vcnkgbWFwcGVkIHNwYWNlIGFzIHNpemUsIEtCeXRlcywgb2Yg Zmxhc2guICovCj4gPiA+ICsJc2l6ZV9rYiA9IEZTUElfRkxTSFhDUjBfU1ooZi0+bWVtbWFwX3Bo eV9zaXplKTsgIAo+ID4gICAKPiBBYm92ZSBkZXNjcmlwdGlvbiBvZiB0aGlzIGZ1bmN0aW9uLCBl eHBsYWlucyB0aGUgcmVhc29uIGZvciB1c2luZyBtZW1tYXBfcGh5X3NpemUuCj4gVGhpcyBpcyBu b3QgdGhlIGFyYml0cmFyeSBzaXplLCBidXQgdGhlIG1lbW9yeSBtYXBwZWQgc2l6ZSBiZWluZyBh c3NpZ25lZCB0byB0aGUgY29udHJvbGxlci4KPiAKPiA+IFlvdSBhcmUgc3RpbGwgdXNpbmcgbWVt b3J5IG9mIGFyYml0cmFyeSBzaXplIChtZW1tYXBfcGh5X3NpemUpIGZvciBtYXBwaW5nIHRoZQo+ ID4gZmxhc2guIFdoeSBub3QgdXNlIHRoZSBzYW1lIGFwcHJvYWNoIGFzIGluIHRoZSBRU1BJIGRy aXZlciBhbmQganVzdCBtYXAKPiA+IGFoYl9idWZfc2l6ZSB1bnRpbCB3ZSBpbXBsZW1lbnQgdGhl IGRpcm1hcCBBUEk/ICAKPiBUaGUgYXBwcm9hY2ggd2hpY2ggYmVpbmcgdXNlZCBpbiBRU1BJIGRy aXZlciBkaWRuJ3Qgd29yayBoZXJlLCBJIGhhdmUgdHJpZWQgd2l0aCB0aGF0Lgo+IEluIFFTUEkg ZHJpdmVyLCB3aGlsZSBwcmVwYXJpbmcgTFVUIHdlIGFyZSBhc3NpZ25pbmcgcmVhZC93cml0ZSBh ZGRyZXNzIGluIHRoZSBMVVQgcHJlcGFyYXRpb24gYW5kIGhhdmUgdG8gZm9yIHNvbWUgdW5rbm93 biBoYWNrIGhhdmUgdG8gcHJvdmlkZSBtYWNybyBmb3IgTFVUX01PREUgaW5zdGVhZCBvZiBMVVRf QUREUi4KPiBCdXQgdGhpcyB0aGluZyBkaWRuJ3Qgd29yayBmb3IgRmxleFNQSS4KPiBJIGRpc2N1 c3NlZCB3aXRoIEhXIElQIG93bmVyIGFuZCB0aGV5IHN1Z2dlc3RlZCBvbmx5IHRvIHVzZSBMVVRf QUREUiBmb3Igc3BlY2lmeWluZyB0aGUgYWRkcmVzcyBsZW5ndGggb2YgdGhlIGNvbW1hbmQgaS5l LiAzLWJ5dGUgb3IgNC1ieXRlIGFkZHJlc3MgY29tbWFuZCAoTk9SKSBvciAxLTIgYnl0ZSBhZGRy ZXNzIGNvbW1hbmQgZm9yIE5BTkQuCgpBY3R1YWxseSwgd2Ugd291bGQgaGF2ZSB1c2VkIGEgTFVU X0FERFIgdG9vIGlmIHRoZSBRU1BJIElQIHdhcyBzdXBwb3J0CkFERFIgaW5zdHJ1Y3Rpb25zIHdp dGggYSBudW1iZXIgb2YgYnl0ZXMgPCAzLCBidXQgZm9yIHNvbWUgdW5rbm93bgpyZWFzb25zIGl0 IGRvZXMgbm90IHdvcmsuIAoKPiAKPiBUaHVzLCBpbiBMVVQgcHJlcGFyYXRpb24gd2UgaGF2ZSBh c3NpZ25lZCBvbmx5IHRoZSBiYXNlIGFkZHJlc3MuCj4gTm93IGlmIEkgaGF2ZSBhc3NpZ25lZCBh aGJfYnVmX3NpemUgdG8gRlNQSV9GTFNIWFhDUjAgcmVnaXN0ZXIgdGhlbiBmb3IgcmVhZC93cml0 ZSBkYXRhIGJleW9uZCBsaW1pdCBvZiBhaGJfYnVmX3NpemUgb2Zmc2V0IEkgZ2V0IGRhdGEgY29y cnVwdGlvbi4KCldoeSB3b3VsZCB5b3UgZG8gdGhhdD8gV2UgaGF2ZSB0aGUgLT5hZGp1c3Rfb3Bf c2l6ZSgpIGV4YWN0bHkgZm9yIHRoaXMKcmVhc29uLCBzbywgaWYgc29tZW9uZSB0cmllcyB0byBk byBhIHNwaV9tZW1fb3Agd2l0aCBkYXRhLm5ieXRlcyA+CmFoYl9idWZfc2l6ZSB5b3Ugc2hvdWxk IHJldHVybiBhbiBlcnJvci4KCj4gCj4gVGh1cywgZm9yIGdlbmVyaWMgYXBwcm9hY2ggaGF2ZSBh c3NpZ25lZCBGU1BJX0ZMU0hYWENSMCBlcXVhbCB0byB0aGUgbWVtb3J5IG1hcHBlZCBzaXplIHRv IHRoZSBjb250cm9sbGVyLiBUaGlzIHdvdWxkIGFsc28gbm90IGdvaW5nIHRvIGRlcGVuZCBvbiB0 aGUgbnVtYmVyIG9mIENTIHByZXNlbnQgb24gdGhlIHRhcmdldC4KCkkga2luZCBvZiBhZ3JlZSB3 aXRoIEZyaWVkZXIgb24gdGhhdCBvbmUsIEkgdGhpbmsgaXQncyBwcmVmZXJhYmxlIHRvCmxpbWl0 IHRoZSBwZXItcmVhZC1vcCBzaXplIHRvIGFoYl9idWZfc2l6ZSBhbmQgbGV0IHRoZSB1cHBlciBs YXllcgpzcGxpdCB0aGUgcmVxdWVzdCBpbiBzZXZlcmFsIHN1Yi1yZXF1ZXN0cy4gT24gdGhlIGNv bnRyb2xsZXIgc2lkZSBvZgp0aGluZ3MsIHlvdSBqdXN0IGhhdmUgdG8gaGF2ZSBhIG1hcHBpbmcg b2YgYWhiX2J1Zl9zaXplIHBlci1DUy4gSWYgeW91CndhbnQgdG8gZnVydGhlciBvcHRpbWl6ZSB0 aGluZ3MsIGltcGxlbWVudCB0aGUgZGlybWFwIGhvb2tzLgoKPiAKPiA+IFlvdSBhcmUgYWxyZWFk eSBhbGlnbmluZyB0aGUgQUhCIHJlYWRzIGZvciB0aGlzIGluIG54cF9mc3BpX2FkanVzdF9vcF9z aXplKCkuCj4gPiAgIAo+IFllcywgbWF4IHJlYWQgZGF0YSBzaXplIGNhbiBiZSBhaGJfYnVmX3Np emUuIFRodXMgd2UgbmVlZCB0byBjaGVjayBtYXggcmVhZCBzaXplIHdpdGggYWhiX2J1Zl9zaXpl LgoKV2VsbCwgaXQncyBuZXZlciBhIGJhZCB0aGluZyB0byBjaGVjayBpdCB0d2ljZSwganVzdCBp biBjYXNlIHRoZQpzcGktbWVtIHVzZXIgaXMgbWlzdXNpbmcgdGhlIEFQSS4KCj4gPiA+ICtzdGF0 aWMgdm9pZCBueHBfZnNwaV9maWxsX3R4ZmlmbyhzdHJ1Y3QgbnhwX2ZzcGkgKmYsCj4gPiA+ICsJ CQkJIGNvbnN0IHN0cnVjdCBzcGlfbWVtX29wICpvcCkKPiA+ID4gK3sKPiA+ID4gKwl2b2lkIF9f aW9tZW0gKmJhc2UgPSBmLT5pb2Jhc2U7Cj4gPiA+ICsJaW50IGksIGosIHJldDsKPiA+ID4gKwlp bnQgc2l6ZSwgdG1wX3NpemUsIHdtX3NpemU7Cj4gPiA+ICsJdTMyIGRhdGEgPSAwOwo+ID4gPiAr CXUzMiAqdHhidWYgPSAodTMyICopIG9wLT5kYXRhLmJ1Zi5vdXQ7Cj4gPiA+ICsKPiA+ID4gKwkv KiBjbGVhciB0aGUgVFggRklGTy4gKi8KPiA+ID4gKwlmc3BpX3dyaXRlbChmLCBGU1BJX0lQVFhG Q1JfQ0xSLCBiYXNlICsgRlNQSV9JUFRYRkNSKTsKPiA+ID4gKwo+ID4gPiArCS8qIERlZmF1bHQg dmFsdWUgb2Ygd2F0ZXIgbWFyayBsZXZlbCBpcyA4IGJ5dGVzLiAqLwo+ID4gPiArCXdtX3NpemUg PSA4Owo+ID4gPiArCXNpemUgPSBvcC0+ZGF0YS5uYnl0ZXMgLyB3bV9zaXplOwo+ID4gPiArCWZv ciAoaSA9IDA7IGkgPCBzaXplOyBpKyspIHsKPiA+ID4gKwkJLyogV2FpdCBmb3IgVFhGSUZPIGVt cHR5ICovCj4gPiA+ICsJCXJldCA9IGZzcGlfcmVhZGxfcG9sbF90b3V0KGYsIGYtPmlvYmFzZSAr IEZTUElfSU5UUiwKPiA+ID4gKwkJCQkJICAgRlNQSV9JTlRSX0lQVFhXRSwgMCwKPiA+ID4gKwkJ CQkJICAgUE9MTF9UT1VULCB0cnVlKTsKPiA+ID4gKwkJV0FSTl9PTihyZXQpOwo+ID4gPiArCj4g PiA+ICsJCWogPSAwOwo+ID4gPiArCQl0bXBfc2l6ZSA9IHdtX3NpemU7Cj4gPiA+ICsJCXdoaWxl ICh0bXBfc2l6ZSA+IDApIHsKPiA+ID4gKwkJCWRhdGEgPSAwOwo+ID4gPiArCQkJbWVtY3B5KCZk YXRhLCB0eGJ1ZiwgNCk7Cj4gPiA+ICsJCQlmc3BpX3dyaXRlbChmLCBkYXRhLCBiYXNlICsgRlNQ SV9URkRSICsgaiAqIDQpOwo+ID4gPiArCQkJdG1wX3NpemUgLT0gNDsKPiA+ID4gKwkJCWorKzsK PiA+ID4gKwkJCXR4YnVmICs9IDE7Cj4gPiA+ICsJCX0KPiA+ID4gKwkJZnNwaV93cml0ZWwoZiwg RlNQSV9JTlRSX0lQVFhXRSwgYmFzZSArIEZTUElfSU5UUik7Cj4gPiA+ICsJfQo+ID4gPiArCj4g PiA+ICsJc2l6ZSA9IG9wLT5kYXRhLm5ieXRlcyAlIHdtX3NpemU7Cj4gPiA+ICsJaWYgKHNpemUp IHsKPiA+ID4gKwkJLyogV2FpdCBmb3IgVFhGSUZPIGVtcHR5ICovCj4gPiA+ICsJCXJldCA9IGZz cGlfcmVhZGxfcG9sbF90b3V0KGYsIGYtPmlvYmFzZSArIEZTUElfSU5UUiwKPiA+ID4gKwkJCQkJ ICAgRlNQSV9JTlRSX0lQVFhXRSwgMCwKPiA+ID4gKwkJCQkJICAgUE9MTF9UT1VULCB0cnVlKTsK PiA+ID4gKwkJV0FSTl9PTihyZXQpOwo+ID4gPiArCj4gPiA+ICsJCWogPSAwOwo+ID4gPiArCQl0 bXBfc2l6ZSA9IDA7Cj4gPiA+ICsJCXdoaWxlIChzaXplID4gMCkgewo+ID4gPiArCQkJZGF0YSA9 IDA7Cj4gPiA+ICsJCQl0bXBfc2l6ZSA9IChzaXplIDwgNCkgPyBzaXplIDogNDsKPiA+ID4gKwkJ CW1lbWNweSgmZGF0YSwgdHhidWYsIHRtcF9zaXplKTsKPiA+ID4gKwkJCWZzcGlfd3JpdGVsKGYs IGRhdGEsIGJhc2UgKyBGU1BJX1RGRFIgKyBqICogNCk7Cj4gPiA+ICsJCQlzaXplIC09IHRtcF9z aXplOwo+ID4gPiArCQkJaisrOwo+ID4gPiArCQkJdHhidWYgKz0gMTsKPiA+ID4gKwkJfQo+ID4g PiArCQlmc3BpX3dyaXRlbChmLCBGU1BJX0lOVFJfSVBUWFdFLCBiYXNlICsgRlNQSV9JTlRSKTsK PiA+ID4gKwl9ICAKPiA+IAo+ID4gQWxsIHRoZXNlIG5lc3RlZCBsb29wcyB0byBmaWxsIHRoZSBU WCBidWZmZXIgYW5kIGFsc28gdGhlIG9uZXMgYmVsb3cgdG8gcmVhZCB0aGUKPiA+IFJYIGJ1ZmZl ciBsb29rIG11Y2ggbW9yZSBjb21wbGljYXRlZCB0aGFuIHRoZXkgc2hvdWxkIHJlYWxseSBiZS4g Q2FuIHlvdSB0cnkgdG8KPiA+IG1ha2UgdGhpcyBtb3JlIHJlYWRhYmxlPyAgCj4gWWVzCj4gPiAK PiA+IE1heWJlIHNvbWV0aGluZyBsaWtlIHRoaXMgd291bGQgd29yazoKPiA+IAo+ID4gZm9yIChp ID0gMDsgaSA8IEFMSUdOX0RPV04ob3AtPmRhdGEubmJ5dGVzLCA4KTsgaSArPSA4KSB7Cj4gPiAJ LyogV2FpdCBmb3IgVFhGSUZPIGVtcHR5ICovCj4gPiAJcmV0ID0gZnNwaV9yZWFkbF9wb2xsX3Rv dXQoZiwgZi0+aW9iYXNlICsgRlNQSV9JTlRSLAo+ID4gCQkJCSAgIEZTUElfSU5UUl9JUFRYV0Us IDAsCj4gPiAJCQkJICAgUE9MTF9UT1VULCB0cnVlKTsKPiA+IAo+ID4gCWZzcGlfd3JpdGVsKGYs IG9wLT5kYXRhLmJ1Zi5vdXQgKyBpLCBiYXNlICsgRlNQSV9URkRSKTsKPiA+IAlmc3BpX3dyaXRl bChmLCBvcC0+ZGF0YS5idWYub3V0ICsgaSArIDQsIGJhc2UgKyBGU1BJX1RGRFIgKyA0KTsKPiA+ IAlmc3BpX3dyaXRlbChmLCBGU1BJX0lOVFJfSVBUWFdFLCBiYXNlICsgRlNQSV9JTlRSKTsgfSAg Cj4gV2l0aCB0aGlzIGFib3ZlIDIgbGluZXMgd2UgYXJlIGhhcmRjb2RpbmcgaXQgZm9yIHJlYWQv d3JpdGUgd2l0aCB3YXRlcm1hcmsgc2l6ZSBhcyA4IGJ5dGVzLgo+IFdhdGVybWFyayBzaXplIGNh biBiZSB2YXJpYWJsZSBhbmQgZGVwZW5kcyBvbiB0aGUgdmFsdWUgb2YgSVBSWEZDUi9JUFRYRkNS IHJlZ2lzdGVyIHdpdGggZGVmYXVsdCB2YWx1ZSBhcyA4IGJ5dGVzCj4gVGh1cywgSSB3b3VsZCBz dGlsbCBwcmVmZXIgdG8gdXNlIHRoZSBpbnRlcm5hbCBmb3IgbG9vcCBpbnN0ZWFkIG9mIDIgZnNw aV93cml0ZWwoLi4uKSBmb3IgRlNQSV9URkRSIGFuZCBGU1BJX1RGRFIgKyA0IHJlZ2lzdGVyIHdy aXRlIGNvbW1hbmRzLgoKSnVzdCBsaWtlIHlvdSdyZSBoYXJkY29kaW5nIHdtX3NpemUgdG8gOCwg c28gSSBkb24ndCBzZWUgYSBkaWZmZXJlbmNlCmhlcmUuIEFuZCBJIGluZGVlZCBwcmVmZXIgRnJp ZWRlcidzIHZlcnNpb24uCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fXwpsaW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdApsaW51eC1hcm0ta2VybmVsQGxp c3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0 aW5mby9saW51eC1hcm0ta2VybmVsCg==