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=-13.2 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_2 autolearn=unavailable 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 51379C33CA4 for ; Fri, 10 Jan 2020 11:05:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 07E9A2077C for ; Fri, 10 Jan 2020 11:05:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727716AbgAJLFn convert rfc822-to-8bit (ORCPT ); Fri, 10 Jan 2020 06:05:43 -0500 Received: from relay7-d.mail.gandi.net ([217.70.183.200]:55249 "EHLO relay7-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727437AbgAJLFm (ORCPT ); Fri, 10 Jan 2020 06:05:42 -0500 X-Originating-IP: 91.224.148.103 Received: from xps13 (unknown [91.224.148.103]) (Authenticated sender: miquel.raynal@bootlin.com) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 006AD20011; Fri, 10 Jan 2020 11:05:35 +0000 (UTC) Date: Fri, 10 Jan 2020 12:05:34 +0100 From: Miquel Raynal To: Johan Jonker Cc: richard@nod.at, vigneshr@ti.com, robh+dt@kernel.org, mark.rutland@arm.com, heiko@sntech.de, linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org Subject: Re: [RFC PATCH v1 02/10] mtd: nand: raw: add rockchip nand controller driver Message-ID: <20200110120534.1b4026b0@xps13> In-Reply-To: <20200108205338.11369-3-jbx6244@gmail.com> References: <20200108205338.11369-1-jbx6244@gmail.com> <20200108205338.11369-3-jbx6244@gmail.com> Organization: Bootlin X-Mailer: Claws Mail 3.17.4 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8BIT Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Johan, Johan Jonker wrote on Wed, 8 Jan 2020 21:53:30 +0100: > From: Yifeng Zhao > Can you change the title to "mtd: rawnand: rockchip: Add NAND controller driver" > Add basic Rockchip nand controller driver. > > Compatible with hardware version 6 and 9. > V6:16, 24, 40, 60 per 1024B BCH/ECC. > V9:16, 40, 60, 70 per 1024B BCH/ECC. > 8 bit asynchronous flash interface support. > Supports up to 2 identical nandc nodes. > Max 4 nand chips per controller. > Able to select a different hardware ecc setup > for the loader blocks. > No bad block support. Thank you very much for this series, as the bad blocks support is absolutely fundamental, I wonder what is the issue here? > > Signed-off-by: Yifeng Zhao > Signed-off-by: Johan Jonker > --- > drivers/mtd/nand/raw/Kconfig | 8 + > drivers/mtd/nand/raw/Makefile | 1 + > drivers/mtd/nand/raw/rockchip_nandc.c | 1224 +++++++++++++++++++++++++++++++++ > 3 files changed, 1233 insertions(+) > create mode 100644 drivers/mtd/nand/raw/rockchip_nandc.c > > diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig > index 74fb91ade..68dc9a36d 100644 > --- a/drivers/mtd/nand/raw/Kconfig > +++ b/drivers/mtd/nand/raw/Kconfig > @@ -457,6 +457,14 @@ config MTD_NAND_CADENCE > Enable the driver for NAND flash on platforms using a Cadence NAND > controller. > > +config MTD_NAND_ROCKCHIP > + tristate "Rockchip raw NAND controller driver" > + depends on ARCH_ROCKCHIP || COMPILE_TEST > + depends on HAS_IOMEM > + help > + Enables support for the Rockchip raw NAND controller driver. > + This controller is found on rk3066, rk3188, rk3288 and more. Can you write an exhaustive list if you know it? Or at least the families? It is quite challenging when you are not in the Rockchip world to know what SoC is similar to another random SoC. > + > comment "Misc" > > config MTD_SM_COMMON > diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile > index 2d136b158..3063fe74a 100644 > --- a/drivers/mtd/nand/raw/Makefile > +++ b/drivers/mtd/nand/raw/Makefile > @@ -58,6 +58,7 @@ 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 > +obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip_nandc.o A driver named rockchip-nand-controller.c would be nice! > > 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/rockchip_nandc.c b/drivers/mtd/nand/raw/rockchip_nandc.c > new file mode 100644 > index 000000000..018308e58 > --- /dev/null > +++ b/drivers/mtd/nand/raw/rockchip_nandc.c > @@ -0,0 +1,1224 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Based on: > + * https://github.com/rockchip-linux/kernel/blob/develop-4.4/drivers/mtd/nand/ > + * rockchip_nand_v6.c > + * https://github.com/rockchip-linux/kernel/blob/develop-4.4/drivers/mtd/nand/ > + * rockchip_nand_v9.c I'm not sure the entire link is relevant, I would simple mention the Rockchip official Github repository and work from Yifeng. > + * Copyright (c) 2016-2019 Yifeng Zhao yifeng.zhao@rock-chips.com > + * > + * Update/restyle for linux-next. > + * Add exec_op function. You can drop these two lines too. This is more a "commit description" thing. > + * Combine driver for nandc version 6 and 9. Support NAND controller versions 6 and 9 found on SoCs ... > + * Copyright (c) 2020 Johan Jonker jbx6244@gmail.com > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#define NANDC_ID_V600 0x56363030 > +#define NANDC_ID_V622 0x56363232 > +#define NANDC_ID_V701 0x701 > +#define NANDC_ID_V800 0x56383030 > +#define NANDC_ID_V801 0x801 > +#define NANDC_ID_V900 0x56393030 I would prefer prefixing everything RK_NANDC_ or RK_ > + > +#define NANDC_IDBResBlkNum 16 > +#define NANDC_IDBEccBits 24 > +#define NANDC_IDBStartAddr 0 > + > +#define NANDC_V6_ECC_16 0x00000000 > +#define NANDC_V6_ECC_24 0x00000010 > +#define NANDC_V6_ECC_40 0x00040000 > +#define NANDC_V6_ECC_60 0x00040010 > + > +#define NANDC_V9_ECC_16 0x02000001 > +#define NANDC_V9_ECC_40 0x04000001 > +#define NANDC_V9_ECC_60 0x06000001 > +#define NANDC_V9_ECC_70 0x00000001 > + > +#define NANDC_NUM_BANKS 4 > +#define NANDC_DEF_TIMEOUT 10000 > + > +#define NANDC_REG_DATA 0x00 > +#define NANDC_REG_ADDR 0x04 > +#define NANDC_REG_CMD 0x08 > + > +/* register offset nandc version 6 */ > +#define NANDC_REG_V6_FMCTL 0x00 > +#define NANDC_REG_V6_FMWAIT 0x04 > +#define NANDC_REG_V6_FLCTL 0x08 > +#define NANDC_REG_V6_BCHCTL 0x0c > +#define NANDC_REG_V6_DMA_CFG 0x10 > +#define NANDC_REG_V6_DMA_BUF0 0x14 > +#define NANDC_REG_V6_DMA_BUF1 0x18 > +#define NANDC_REG_V6_DMA_ST 0x1C > +#define NANDC_REG_V6_BCHST 0x20 > +#define NANDC_REG_V6_RANDMZ 0x150 > +#define NANDC_REG_V6_VER 0x160 > +#define NANDC_REG_V6_INTEN 0x16C > +#define NANDC_REG_V6_INTCLR 0x170 > +#define NANDC_REG_V6_INTST 0x174 > +#define NANDC_REG_V6_SPARE0 0x200 > +#define NANDC_REG_V6_SPARE1 0x230 > + > +/* register offset nandc version 9 */ > +#define NANDC_REG_V9_FMCTL 0x00 > +#define NANDC_REG_V9_FMWAIT 0x04 > +#define NANDC_REG_V9_FLCTL 0x10 > +#define NANDC_REG_V9_BCHCTL 0x20 > +#define NANDC_REG_V9_DMA_CFG 0x30 > +#define NANDC_REG_V9_DMA_BUF0 0x34 > +#define NANDC_REG_V9_DMA_BUF1 0x38 > +#define NANDC_REG_V9_DMA_ST 0x40 > +#define NANDC_REG_V9_VER 0x80 > +#define NANDC_REG_V9_INTEN 0x120 > +#define NANDC_REG_V9_INTCLR 0x124 > +#define NANDC_REG_V9_INTST 0x128 > +#define NANDC_REG_V9_BCHST 0x150 > +#define NANDC_REG_V9_SPARE0 0x200 > +#define NANDC_REG_V9_SPARE1 0x204 > +#define NANDC_REG_V9_RANDMZ 0x208 > + > +/* register offset nandc common */ > +#define NANDC_REG_BANK0 0x800 > +#define NANDC_REG_SRAM0 0x1000 > + > +/* FMCTL */ > +#define NANDC_V6_FM_WP BIT(8) > +#define NANDC_V6_FM_CE_SEL_M 0xFF > +#define NANDC_V6_FM_CE_SEL(x) (1 << (x)) > +#define NANDC_V6_FM_FREADY BIT(9) > + > +#define NANDC_V9_FM_WP BIT(8) > +#define NANDC_V9_FM_CE_SEL_M 0xFF > +#define NANDC_V9_FM_CE_SEL(x) (1 << (x)) > +#define NANDC_V9_RDY BIT(9) > + > +/* FLCTL */ > +#define NANDC_V6_FL_RST BIT(0) > +#define NANDC_V6_FL_DIR(x) ((x) ? BIT(1) : 0) > +#define NANDC_V6_FL_XFER_START BIT(2) > +#define NANDC_V6_FL_XFER_EN BIT(3) > +#define NANDC_V6_FL_ST_BUF_S 0x4 > +#define NANDC_V6_FL_XFER_COUNT BIT(5) > +#define NANDC_V6_FL_ACORRECT BIT(10) > +#define NANDC_V6_FL_XFER_READY BIT(20) > +#define NANDC_V6_FL_PAGE_NUM(x) ((x) << 22) > +#define NANDC_V6_FL_ASYNC_TOG_MIX BIT(29) > + > +#define NANDC_V9_FL_RST BIT(0) > +#define NANDC_V9_FL_DIR(x) ((x) ? BIT(1) : 0) > +#define NANDC_V9_FL_XFER_START BIT(2) > +#define NANDC_V9_FL_XFER_EN BIT(3) > +#define NANDC_V9_FL_ST_BUF_S 0x4 > +#define NANDC_V9_FL_XFER_COUNT BIT(5) > +#define NANDC_V9_FL_ACORRECT BIT(10) > +#define NANDC_V9_FL_XFER_READY BIT(20) > +#define NANDC_V9_FL_PAGE_NUM(x) ((x) << 22) > +#define NANDC_V9_FL_ASYNC_TOG_MIX BIT(29) > + > +/* BCHCTL */ > +#define NAND_V6_BCH_REGION_S 0x5 > +#define NAND_V6_BCH_REGION_M 0x7 > + > +#define NAND_V9_BCH_MODE_S 25 > +#define NAND_V9_BCH_MODE_M 0x7 > + > +/* BCHST */ > +#define NANDC_V6_BCH0_ST_ERR BIT(2) > +#define NANDC_V6_BCH1_ST_ERR BIT(15) > +#define NANDC_V6_ECC_ERR_CNT0(x) ((((x & (0x1F << 3)) >> 3) \ > + | ((x & (1 << 27)) >> 22)) & 0x3F) > +#define NANDC_V6_ECC_ERR_CNT1(x) ((((x & (0x1F << 16)) >> 16) \ > + | ((x & (1 << 29)) >> 24)) & 0x3F) > + > +#define NANDC_V9_BCH0_ST_ERR BIT(2) > +#define NANDC_V9_BCH1_ST_ERR BIT(18) > +#define NANDC_V9_ECC_ERR_CNT0(x) (((x) & (0x7F << 3)) >> 3) > +#define NANDC_V9_ECC_ERR_CNT1(x) (((x) & (0x7F << 19)) >> 19) > + > +/* DMA_CFG */ > +#define NANDC_V6_DMA_CFG_WR_ST BIT(0) > +#define NANDC_V6_DMA_CFG_WR(x) ((!x) ? BIT(1) : 0) > +#define NANDC_V6_DMA_CFG_BUS_MODE BIT(2) > + > +#define NANDC_V6_DMA_CFG_HSIZE_8 0 > +#define NANDC_V6_DMA_CFG_HSIZE_16 (1 << 3) > +#define NANDC_V6_DMA_CFG_HSIZE_32 (2 << 3) > + > +#define NANDC_V6_DMA_CFG_BURST_1 0 > +#define NANDC_V6_DMA_CFG_BURST_4 (3 << 6) > +#define NANDC_V6_DMA_CFG_BURST_8 (5 << 6) > +#define NANDC_V6_DMA_CFG_BURST_16 (7 << 6) > + > +#define NANDC_V6_DMA_CFG_INCR_NUM(x) ((x) << 9) > + > +#define NANDC_V9_DMA_CFG_WR_ST BIT(0) > +#define NANDC_V9_DMA_CFG_WR(x) ((!x) ? BIT(1) : 0) > +#define NANDC_V9_DMA_CFG_BUS_MODE BIT(2) > + > +#define NANDC_V9_DMA_CFG_HSIZE_8 0 > +#define NANDC_V9_DMA_CFG_HSIZE_16 (1 << 3) > +#define NANDC_V9_DMA_CFG_HSIZE_32 (2 << 3) > + > +#define NANDC_V9_DMA_CFG_BURST_1 0 > +#define NANDC_V9_DMA_CFG_BURST_4 (3 << 6) > +#define NANDC_V9_DMA_CFG_BURST_8 (5 << 6) > +#define NANDC_V9_DMA_CFG_BURST_16 (7 << 6) > + > +#define NANDC_V9_DMA_CFG_INCR_NUM(x) ((x) << 9) > + > +/* INTEN */ > +#define NANDC_V6_INT_DMA BIT(0) > + > +#define NANDC_V9_INT_DMA BIT(0) > + > +enum rk_nandc_version { > + VERSION_6 = 6, > + VERSION_9 = 9, > +}; > + > +struct rk_nandc_data { > + enum rk_nandc_version version; If you make a distinction between both version, maybe you can add more parameters here and do foo = data->param instead of if (data->version == 6) foo = this; else foo = that; > +}; > + > +struct rk_nand_controller { > + void __iomem *regs; > + int irq; > + struct clk *hclk; > + struct clk *clk; > + struct list_head chips; > + struct completion complete; > + struct nand_controller controller; > + int banks[NANDC_NUM_BANKS]; > + bool bootromblocks; > + int ecc_mode; > + uint32_t ecc_strength; > + int max_ecc_strength; I have not read yet the entire driver but I believe the above 4 parameters should probably be moved in rk_nand_chip, right? Anything that is NAND chip related should not be in the controller structure. It depends if you can change ECC requirements on the fly or not. > + uint32_t *oob_buf; > + uint32_t *page_buf; > + int selected_bank; > + enum rk_nandc_version version; > +}; > + > +struct rk_nand_chip { > + struct nand_chip nand; > + struct list_head chip_list; > +}; > + > +static struct rk_nand_controller g_nandc_info[2]; I don't like this idea so much. I prefer a dynamic allocation in the probe. > +static int g_id_counter; Don't know what this is yet, but it is probably a bad idea :) > + > +static void rk_nandc_init(struct rk_nand_controller *ctrl) > +{ > + if (ctrl->version == VERSION_9) { > + writel(0, ctrl->regs + NANDC_REG_V9_RANDMZ); > + writel(0, ctrl->regs + NANDC_REG_V9_DMA_CFG); > + writel(NANDC_V9_FM_WP, ctrl->regs + NANDC_REG_V9_FMCTL); > + writel(NANDC_V9_FL_RST, ctrl->regs + NANDC_REG_V9_FLCTL); > + writel(0x1081, ctrl->regs + NANDC_REG_V9_FMWAIT); > + } else { > + writel(0, ctrl->regs + NANDC_REG_V6_RANDMZ); > + writel(0, ctrl->regs + NANDC_REG_V6_DMA_CFG); > + writel(NANDC_V6_FM_WP, ctrl->regs + NANDC_REG_V6_FMCTL); > + writel(NANDC_V6_FL_RST, ctrl->regs + NANDC_REG_V6_FLCTL); > + writel(0x1081, ctrl->regs + NANDC_REG_V6_FMWAIT); > + } My above comment about the platform data would make a lot of sense here! > +} > + > +static irqreturn_t rk_nandc_interrupt(int irq, void *dev_id) > +{ > + struct rk_nand_controller *ctrl = dev_id; > + > + if (ctrl->version == VERSION_9) { > + uint32_t st = readl(ctrl->regs + NANDC_REG_V9_INTST); > + uint32_t ien = readl(ctrl->regs + NANDC_REG_V9_INTEN); > + > + if (!(ien & st)) > + return IRQ_NONE; > + > + if ((ien & st) == ien) > + complete(&ctrl->complete); > + > + writel(st, ctrl->regs + NANDC_REG_V9_INTCLR); > + writel(~st & ien, ctrl->regs + NANDC_REG_V9_INTEN); > + } else { > + uint32_t st = readl(ctrl->regs + NANDC_REG_V6_INTST); > + uint32_t ien = readl(ctrl->regs + NANDC_REG_V6_INTEN); > + > + if (!(ien & st)) > + return IRQ_NONE; > + > + if ((ien & st) == ien) > + complete(&ctrl->complete); > + > + writel(st, ctrl->regs + NANDC_REG_V6_INTCLR); > + writel(~st & ien, ctrl->regs + NANDC_REG_V6_INTEN); > + } Same comment! > + > + return IRQ_HANDLED; > +} > + > +static void rk_nandc_select_chip(struct nand_chip *nand, int chipnr) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + uint32_t reg; > + int banknr; > + > + /* The register offset and bit positions for should be: /* * The register... Please run checkpatch.pl --strict on this file, this kind of mistake would have been detected. > + * NANDC_REG_V6_FMCTL and NANDC_REG_V9_FMCTL > + * are identical. > + */ > + reg = readl(ctrl->regs + NANDC_REG_V6_FMCTL); > + reg &= ~NANDC_V6_FM_CE_SEL_M; > + > + if (chipnr == -1) { > + banknr = -1; > + } else { > + banknr = ctrl->banks[chipnr]; > + > + reg |= NANDC_V6_FM_CE_SEL(banknr); > + } > + writel(reg, ctrl->regs + NANDC_REG_V6_FMCTL); Maybe you can spare this writel by returning early if banknr == ctrl->selected_bank. > + > + ctrl->selected_bank = banknr; > +} > + > +static int rk_nandc_hw_ecc_setup(struct nand_chip *nand, > + uint32_t strength) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + uint32_t reg; > + > + nand->ecc.strength = strength; > + nand->ecc.bytes = DIV_ROUND_UP(nand->ecc.strength * 14, 8); What do 14 and 8 mean? > + /* HW ECC only works with an even number of ECC bytes */ > + nand->ecc.bytes = ALIGN(nand->ecc.bytes, 2); > + > + if (ctrl->version == VERSION_9) { > + switch (nand->ecc.strength) { > + case 70: > + reg = NANDC_V9_ECC_70; > + break; > + case 60: > + reg = NANDC_V9_ECC_60; > + break; > + case 40: > + reg = NANDC_V9_ECC_40; > + break; > + case 16: > + reg = NANDC_V9_ECC_16; > + break; > + default: > + return -EINVAL; > + } > + writel(reg, ctrl->regs + NANDC_REG_V9_BCHCTL); > + } else { > + switch (nand->ecc.strength) { > + case 60: > + reg = NANDC_V6_ECC_60; > + break; > + case 40: > + reg = NANDC_V6_ECC_40; > + break; > + case 24: > + reg = NANDC_V6_ECC_24; > + break; > + case 16: > + reg = NANDC_V6_ECC_16; > + break; > + default: > + return -EINVAL; > + } > + writel(reg, ctrl->regs + NANDC_REG_V6_BCHCTL); > + } > + > + return 0; > +} > + > +static void rk_nandc_xfer_start(struct rk_nand_controller *ctrl, > + uint8_t dir, uint8_t n_KB, > + dma_addr_t dma_data, dma_addr_t dma_oob) > +{ > + uint32_t reg; > + > + if (ctrl->version == VERSION_9) { > + reg = NANDC_V9_DMA_CFG_WR_ST | > + NANDC_V9_DMA_CFG_WR(dir) | > + NANDC_V9_DMA_CFG_BUS_MODE | > + NANDC_V9_DMA_CFG_HSIZE_32 | > + NANDC_V9_DMA_CFG_BURST_16 | > + NANDC_V9_DMA_CFG_INCR_NUM(16); > + writel(reg, ctrl->regs + NANDC_REG_V9_DMA_CFG); > + writel((uint32_t)dma_data, ctrl->regs + NANDC_REG_V9_DMA_BUF0); > + writel((uint32_t)dma_oob, ctrl->regs + NANDC_REG_V9_DMA_BUF1); I'm pretty sure most of these writel could be turned into writel_relaxed. Also I am not a big fan of these casts, maybe you should change dma_data and dma_oob types (be careful: you enabled COMPILE_TEST in Kconfig, you must support 32-bit and 64-bit pointers, please try to compile this driver with different toolchains). > + > + reg = NANDC_V9_FL_DIR(dir) | > + NANDC_V9_FL_XFER_EN | > + NANDC_V9_FL_XFER_COUNT | > + NANDC_V9_FL_ACORRECT | > + NANDC_V9_FL_PAGE_NUM(n_KB) | > + NANDC_V9_FL_ASYNC_TOG_MIX; > + writel(reg, ctrl->regs + NANDC_REG_V9_FLCTL); > + reg |= NANDC_V9_FL_XFER_START; > + writel(reg, ctrl->regs + NANDC_REG_V9_FLCTL); > + } else { > + reg = readl(ctrl->regs + NANDC_REG_V6_BCHCTL); > + reg = (reg & (~(NAND_V6_BCH_REGION_M << > + NAND_V6_BCH_REGION_S))) | > + (ctrl->selected_bank << NAND_V6_BCH_REGION_S); > + writel(reg, ctrl->regs + NANDC_REG_V6_BCHCTL); > + > + reg = NANDC_V6_DMA_CFG_WR_ST | > + NANDC_V6_DMA_CFG_WR(dir) | > + NANDC_V6_DMA_CFG_BUS_MODE | > + NANDC_V6_DMA_CFG_HSIZE_32 | > + NANDC_V6_DMA_CFG_BURST_16 | > + NANDC_V6_DMA_CFG_INCR_NUM(16); > + writel(reg, ctrl->regs + NANDC_REG_V6_DMA_CFG); > + writel(dma_data, ctrl->regs + NANDC_REG_V6_DMA_BUF0); > + writel(dma_oob, ctrl->regs + NANDC_REG_V6_DMA_BUF1); > + > + reg = NANDC_V6_FL_DIR(dir) | > + NANDC_V6_FL_XFER_EN | > + NANDC_V6_FL_XFER_COUNT | > + NANDC_V6_FL_ACORRECT | > + NANDC_V6_FL_PAGE_NUM(n_KB) | > + NANDC_V6_FL_ASYNC_TOG_MIX; > + writel(reg, ctrl->regs + NANDC_REG_V6_FLCTL); > + reg |= NANDC_V6_FL_XFER_START; > + writel(reg, ctrl->regs + NANDC_REG_V6_FLCTL); > + } > +} > + > +static int rk_nandc_wait_for_xfer_done(struct rk_nand_controller *ctrl) > +{ > + uint32_t reg; > + int ret; > + > + if (ctrl->version == VERSION_9) { > + void __iomem *ptr = ctrl->regs + NANDC_REG_V9_FLCTL; > + > + ret = readl_poll_timeout_atomic(ptr, reg, > + reg & NANDC_V9_FL_XFER_READY, > + 1, NANDC_DEF_TIMEOUT); > + } else { > + void __iomem *ptr = ctrl->regs + NANDC_REG_V6_FLCTL; > + > + ret = readl_poll_timeout_atomic(ptr, reg, > + reg & NANDC_V6_FL_XFER_READY, > + 1, NANDC_DEF_TIMEOUT); > + } Space > + if (ret) > + pr_err("timeout reg=%x\n", reg); > + > + return ret; > +} > + > +static unsigned long rk_nandc_dma_map_single(struct device *dev, > + void *ptr, int size, int dir) Unaligned parameters > +{ > +#ifdef CONFIG_ARM64 > + __dma_map_area((void *)ptr, size, dir); > + return ((unsigned long)virt_to_phys((void *)ptr)); > +#else > + return dma_map_single(dev, (void *)ptr, size, dir); > +#endif Please try to remove these #ifdefs, I don't know why would you need the former block? > +} > + > +static void rk_nandc_dma_unmap_single(struct device *dev, > + unsigned long ptr, int size, int dir) > +{ > +#ifdef CONFIG_ARM64 > + __dma_unmap_area(phys_to_virt(ptr), size, dir); > +#else > + dma_unmap_single(dev, (dma_addr_t)ptr, size, dir); > +#endif Same > +} > + > +static int rk_nandc_hw_syndrome_ecc_read_page(struct nand_chip *nand, > + uint8_t *buf, > + int oob_required, int page) Unaligned parameters (please check all of them). > +{ > + struct mtd_info *mtd = nand_to_mtd(nand); > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + struct nand_ecc_ctrl *ecc = &nand->ecc; > + int max_bitflips = 0; > + dma_addr_t dma_data, dma_oob; > + int ret, i; > + int bch_st; > + int dma_oob_size = ecc->steps * 128; > + int pages_per_blk = mtd->erasesize / mtd->writesize; > + > + rk_nandc_select_chip(nand, ctrl->selected_bank); > + > + if ((page < pages_per_blk * NANDC_IDBResBlkNum) && Camel case is usually not welcome > + ctrl->bootromblocks) This would probably deserve a helper > + rk_nandc_hw_ecc_setup(nand, NANDC_IDBEccBits); > + > + nand_read_page_op(nand, page, 0, NULL, 0); > + > + dma_data = rk_nandc_dma_map_single(mtd->dev.parent, > + ctrl->page_buf, mtd->writesize, > + DMA_FROM_DEVICE); > + dma_oob = rk_nandc_dma_map_single(mtd->dev.parent, > + ctrl->oob_buf, dma_oob_size, > + DMA_FROM_DEVICE); > + > + init_completion(&ctrl->complete); One init_completion is needed (in the probe, probably) then please use reinit_completion(). > + if (ctrl->version == VERSION_9) > + writel(NANDC_V9_INT_DMA, ctrl->regs + NANDC_REG_V9_INTEN); > + else > + writel(NANDC_V6_INT_DMA, ctrl->regs + NANDC_REG_V6_INTEN); > + rk_nandc_xfer_start(ctrl, 0, ecc->steps, dma_data, dma_oob); > + wait_for_completion_timeout(&ctrl->complete, msecs_to_jiffies(5)); > + rk_nandc_wait_for_xfer_done(ctrl); Yous should check the return status of almost all the functions here. > + rk_nandc_dma_unmap_single(mtd->dev.parent, dma_data, mtd->writesize, > + DMA_FROM_DEVICE); > + rk_nandc_dma_unmap_single(mtd->dev.parent, dma_oob, dma_oob_size, > + DMA_FROM_DEVICE); > + > + memcpy(buf, ctrl->page_buf, mtd->writesize); > + > + if (oob_required) { > + uint8_t *oob; > + uint32_t tmp; Please use u8, u16 and u32 types. > + > + for (i = 0; i < ecc->steps; i++) { > + oob = nand->oob_poi + > + i * (ecc->bytes + nand->ecc.prepad); > + if (ctrl->version == VERSION_9) { > + tmp = ctrl->oob_buf[i]; > + } else { > + uint8_t oob_step = (ctrl->ecc_mode <= 24) ? > + 64 : 128; > + tmp = ctrl->oob_buf[i * oob_step / 4]; > + } > + *oob++ = (uint8_t)tmp; > + *oob++ = (uint8_t)(tmp >> 8); > + *oob++ = (uint8_t)(tmp >> 16); > + *oob++ = (uint8_t)(tmp >> 24); > + } > + } > + > + if (ctrl->version == VERSION_9) { > + for (i = 0; i < ecc->steps / 2; i++) { > + bch_st = readl(ctrl->regs + NANDC_REG_V9_BCHST + i * 4); > + if (bch_st & NANDC_V9_BCH0_ST_ERR || > + bch_st & NANDC_V9_BCH1_ST_ERR) { > + mtd->ecc_stats.failed++; > + max_bitflips = -1; > + } else { > + ret = NANDC_V9_ECC_ERR_CNT0(bch_st); > + mtd->ecc_stats.corrected += ret; > + max_bitflips = max_t(unsigned int, > + max_bitflips, ret); > + > + ret = NANDC_V9_ECC_ERR_CNT1(bch_st); > + mtd->ecc_stats.corrected += ret; > + max_bitflips = max_t(unsigned int, > + max_bitflips, ret); > + } > + } > + } else { > + for (i = 0; i < ecc->steps / 2; i++) { > + bch_st = readl(ctrl->regs + NANDC_REG_V6_BCHST + i * 4); > + if (bch_st & NANDC_V6_BCH0_ST_ERR || > + bch_st & NANDC_V6_BCH1_ST_ERR) { > + mtd->ecc_stats.failed++; > + max_bitflips = -1; Why not using ret = $(real error) instead of using max_bitflips here? Then: if (ret) { dev_err(); return ret; } return max_bitflips; > + } else { > + ret = NANDC_V6_ECC_ERR_CNT0(bch_st); > + mtd->ecc_stats.corrected += ret; > + max_bitflips = max_t(unsigned int, > + max_bitflips, ret); > + > + ret = NANDC_V6_ECC_ERR_CNT1(bch_st); > + mtd->ecc_stats.corrected += ret; > + max_bitflips = max_t(unsigned int, > + max_bitflips, ret); > + } > + } > + } > + > + if (max_bitflips == -1) { > + dev_err(mtd->dev.parent, > + "read_page %x %x %x %x %x %p %x\n", > + page, > + max_bitflips, > + bch_st, > + ((uint32_t *)buf)[0], > + ((uint32_t *)buf)[1], > + buf, > + (uint32_t)dma_data); This is not very informative, please write a real error message. Avoid putting too much debug information, people will troubleshoot themselves if needed. > + } > + > + if (ctrl->bootromblocks) > + rk_nandc_hw_ecc_setup(nand, ctrl->ecc_mode); > + You don't use the same condition as above. Why ? Maybe the helper would help. > + return max_bitflips; > +} > + > +static int rk_nandc_hw_syndrome_ecc_write_page(struct nand_chip *nand, > + const uint8_t *buf, > + int oob_required, > + int page) > +{ > + struct mtd_info *mtd = nand_to_mtd(nand); > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + struct nand_ecc_ctrl *ecc = &nand->ecc; > + dma_addr_t dma_data, dma_oob; > + int i; > + int dma_oob_size = ecc->steps * 128; > + int pages_per_blk = mtd->erasesize / mtd->writesize; > + > + rk_nandc_select_chip(nand, ctrl->selected_bank); > + > + if ((page < pages_per_blk * NANDC_IDBResBlkNum) && > + ctrl->bootromblocks) > + rk_nandc_hw_ecc_setup(nand, NANDC_IDBEccBits); > + > + nand_prog_page_begin_op(nand, page, 0, NULL, 0); > + > + for (i = 0; i < ecc->steps; i++) { > + uint32_t tmp; > + > + if (oob_required) { > + uint8_t *oob; > + > + oob = nand->oob_poi + > + i * (ecc->bytes + nand->ecc.prepad); > + tmp = oob[0] | > + (oob[1] << 8) | > + (oob[2] << 16) | > + (oob[3] << 24); > + } else { > + /* The first NANDC_IDBResBlkNum blocks are > + * for the stored loader. The first 32 bits > + * of oob must contain a sort of link to > + * the next page address in that same block > + * for the Bootrom. > + * Depending on what FTL from Rockchip is used, > + * the first 2 pages in the NANDC_IDBResBlkNum blocks > + * are reserved for FlashPhyInfo. > + * Raw IDB data then starts at page 2 or higher. I would separate the function to read/write the loader than the usual read/write helpers to avoid any confusion on why you do these tricks. Maybe not the whole function, but at least the data/oob placement? (This is really a suggestion) > + */ > + if (!i && > + page < pages_per_blk * NANDC_IDBResBlkNum && > + page >= NANDC_IDBStartAddr) > + tmp = (page & (pages_per_blk - 1)) * 4; > + else > + tmp = 0xFFFFFFFF; > + } > + if (ctrl->version == VERSION_9) { > + ctrl->oob_buf[i] = tmp; > + } else { > + uint8_t oob_step = (ctrl->ecc_mode <= 24) ? > + 64 : 128; > + ctrl->oob_buf[i * oob_step / 4] = tmp; > + } > + } > + > + memcpy(ctrl->page_buf, buf, mtd->writesize); > + dma_data = rk_nandc_dma_map_single(mtd->dev.parent, > + ctrl->page_buf, mtd->writesize, > + DMA_TO_DEVICE); > + dma_oob = rk_nandc_dma_map_single(mtd->dev.parent, > + ctrl->oob_buf, dma_oob_size, > + DMA_TO_DEVICE); > + init_completion(&ctrl->complete); > + if (ctrl->version == VERSION_9) > + writel(NANDC_V9_INT_DMA, ctrl->regs + NANDC_REG_V9_INTEN); > + else > + writel(NANDC_V6_INT_DMA, ctrl->regs + NANDC_REG_V6_INTEN); > + rk_nandc_xfer_start(ctrl, 1, ecc->steps, dma_data, dma_oob); > + wait_for_completion_timeout(&ctrl->complete, msecs_to_jiffies(10)); > + rk_nandc_wait_for_xfer_done(ctrl); > + rk_nandc_dma_unmap_single(mtd->dev.parent, dma_data, mtd->writesize, > + DMA_TO_DEVICE); > + rk_nandc_dma_unmap_single(mtd->dev.parent, dma_oob, dma_oob_size, > + DMA_TO_DEVICE); > + > + if (ctrl->bootromblocks) > + rk_nandc_hw_ecc_setup(nand, ctrl->ecc_mode); > + > + return nand_prog_page_end_op(nand); > +} > + > +static int rk_nandc_hw_ecc_read_oob(struct nand_chip *nand, int page) > +{ > + uint8_t *buf = nand_get_data_buf(nand); > + > + return nand->ecc.read_page(nand, buf, true, page); > +} > + > +static int rk_nandc_hw_ecc_write_oob(struct nand_chip *nand, int page) > +{ > + struct mtd_info *mtd = nand_to_mtd(nand); > + int ret; > + uint8_t *buf = nand_get_data_buf(nand); > + > + memset(buf, 0xFF, mtd->writesize); > + ret = nand->ecc.write_page(nand, buf, true, page); > + if (ret) > + return ret; > + > + return nand_prog_page_end_op(nand); > +} > + > +static void rk_nandc_read_buf(struct nand_chip *nand, uint8_t *buf, int len) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + int offs = 0; > + void __iomem *bank_base = ctrl->regs + NANDC_REG_BANK0 + > + ctrl->selected_bank * 0x100; 0x100: Maybe a define > + > + for (offs = 0; offs < len; offs++) > + buf[offs] = readb(bank_base); > +} > + > +static void rk_nandc_write_buf(struct nand_chip *nand, > + const uint8_t *buf, int len) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + int offs = 0; > + void __iomem *bank_base = ctrl->regs + NANDC_REG_BANK0 + > + ctrl->selected_bank * 0x100; > + > + for (offs = 0; offs < len; offs++) > + writeb(buf[offs], bank_base); > +} > + > +static void rk_nandc_write_cmd(struct nand_chip *nand, uint8_t cmd) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + > + void __iomem *bank_base = ctrl->regs + NANDC_REG_BANK0 + > + ctrl->selected_bank * 0x100 + > + NANDC_REG_CMD; You might want to write an helper to calculate bank_base, to avoid repeating these lines. > + > + writeb(cmd, bank_base); > +} > + > +static void rk_nandc_write_addr(struct nand_chip *nand, uint8_t addr) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + > + void __iomem *bank_base = ctrl->regs + NANDC_REG_BANK0 + > + ctrl->selected_bank * 0x100 + > + NANDC_REG_ADDR; > + > + writeb(addr, bank_base); > +} > + > +static int rk_nandc_dev_ready(struct nand_chip *nand) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + > + if (readl(ctrl->regs + NANDC_REG_V6_FMCTL) & NANDC_V6_FM_FREADY) > + return 1; > + > + return 0; > +} > + > +static int rk_nandc_ooblayout_ecc(struct mtd_info *mtd, int section, > + struct mtd_oob_region *oobregion) > +{ > + struct nand_chip *nand = mtd_to_nand(mtd); > + > + if (section >= nand->ecc.steps) > + return -ERANGE; > + > + oobregion->offset = (nand->ecc.bytes + nand->ecc.prepad) * section + > + nand->ecc.prepad; > + oobregion->length = nand->ecc.steps * nand->ecc.bytes; > + > + return 0; > +} > + > +static int rk_nandc_ooblayout_free(struct mtd_info *mtd, int section, > + struct mtd_oob_region *oobregion) > +{ > + struct nand_chip *nand = mtd_to_nand(mtd); > + > + if (section >= nand->ecc.steps) > + return -ERANGE; > + > + oobregion->offset = (nand->ecc.bytes + nand->ecc.prepad) * section; > + oobregion->length = nand->ecc.steps * nand->ecc.prepad; > + > + return 0; > +} > + > +static const struct mtd_ooblayout_ops rk_nandc_oob_ops = { > + .ecc = rk_nandc_ooblayout_ecc, > + .free = rk_nandc_ooblayout_free, > +}; > + > +static void rk_nandc_free_buffer(struct nand_chip *nand) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + > + kfree(ctrl->page_buf); > + kfree(ctrl->oob_buf); > +} > + > +static int rk_nandc_buffer_init(struct nand_chip *nand) > +{ > + struct mtd_info *mtd = nand_to_mtd(nand); > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + > + ctrl->page_buf = kmalloc(mtd->writesize, GFP_KERNEL | GFP_DMA); device managed allocations (devm_...) would be nice > + if (!ctrl->page_buf) > + return -ENOMEM; > + > + ctrl->oob_buf = kmalloc(nand->ecc.steps * 128, GFP_KERNEL | GFP_DMA); > + if (!ctrl->oob_buf) { > + kfree(ctrl->page_buf); > + return -ENOMEM; > + } > + > + return 0; > +} > + > +static int rk_nandc_hw_ecc_ctrl_init(struct nand_chip *nand) > +{ > + uint8_t strengths_v6[] = {60, 40, 24, 16}; > + uint8_t strengths_v9[] = {70, 60, 40, 16}; > + struct mtd_info *mtd = nand_to_mtd(nand); > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + int max_strength; > + uint32_t i, ver; > + > + if (nand->options & NAND_IS_BOOT_MEDIUM) > + ctrl->bootromblocks = true; > + else > + ctrl->bootromblocks = false; > + > + nand->ecc.prepad = 4; > + nand->ecc.steps = mtd->writesize / nand->ecc.size; > + > + max_strength = ((mtd->oobsize / nand->ecc.steps) - 4) * 8 / 14; > + if (ctrl->version == VERSION_9) { > + ctrl->max_ecc_strength = 70; > + ver = readl(ctrl->regs + NANDC_REG_V9_VER); > + if (ver != NANDC_ID_V900) > + dev_err(mtd->dev.parent, > + "unsupported nandc version %x\n", ver); > + > + if (max_strength > ctrl->max_ecc_strength) > + max_strength = ctrl->max_ecc_strength; > + > + for (i = 0; i < ARRAY_SIZE(strengths_v9); i++) { > + if (max_strength >= strengths_v9[i]) > + break; > + } > + > + if (i >= ARRAY_SIZE(strengths_v9)) { > + dev_err(mtd->dev.parent, > + "unsupported strength\n"); > + return -ENOTSUPP; > + } > + > + ctrl->ecc_mode = strengths_v9[i]; > + } else { > + ctrl->max_ecc_strength = 60; > + > + ver = readl(ctrl->regs + NANDC_REG_V6_VER); > + if (ver == NANDC_ID_V801) > + ctrl->max_ecc_strength = 16; > + else if (ver == NANDC_ID_V600 || > + ver == NANDC_ID_V622 || > + ver == NANDC_ID_V701 || > + ver == NANDC_ID_V800) > + ctrl->max_ecc_strength = 60; > + else > + dev_err(mtd->dev.parent, > + "unsupported nandc version %x\n", ver); > + > + if (max_strength > ctrl->max_ecc_strength) > + max_strength = ctrl->max_ecc_strength; > + > + for (i = 0; i < ARRAY_SIZE(strengths_v6); i++) { > + if (max_strength >= strengths_v6[i]) > + break; > + } > + > + if (i >= ARRAY_SIZE(strengths_v6)) { > + dev_err(mtd->dev.parent, > + "unsupported strength\n"); > + return -ENOTSUPP; > + } > + > + ctrl->ecc_mode = strengths_v6[i]; > + } > + rk_nandc_hw_ecc_setup(nand, ctrl->ecc_mode); > + > + mtd_set_ooblayout(mtd, &rk_nandc_oob_ops); > + > + if (mtd->oobsize < ((nand->ecc.bytes + nand->ecc.prepad) * > + nand->ecc.steps)) { > + return -EINVAL; > + } > + > + return 0; > +} > + > +static void rk_nandc_detach_chip(struct nand_chip *nand) > +{ > + switch (nand->ecc.mode) { > + case NAND_ECC_HW_SYNDROME: > + rk_nandc_free_buffer(nand); > + break; > + default: > + break; > + } > +} > + > +static int rk_nandc_attach_chip(struct nand_chip *nand) > +{ > + struct mtd_info *mtd = nand_to_mtd(nand); > + int ret; > + > + switch (nand->ecc.mode) { > + case NAND_ECC_HW_SYNDROME: > + ret = rk_nandc_hw_ecc_ctrl_init(nand); > + if (ret) > + return ret; > + ret = rk_nandc_buffer_init(nand); > + if (ret) > + return -ENOMEM; > + nand->ecc.read_page = rk_nandc_hw_syndrome_ecc_read_page; > + nand->ecc.write_page = rk_nandc_hw_syndrome_ecc_write_page; > + nand->ecc.read_oob = rk_nandc_hw_ecc_read_oob; > + nand->ecc.write_oob = rk_nandc_hw_ecc_write_oob; > + break; > + case NAND_ECC_HW: I would either refuse ECC_HW or put it besides HW_SYNDROME. > + case NAND_ECC_NONE: > + case NAND_ECC_SOFT: Have you tested with SW BCH? > + break; > + default: > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int rk_nandc_exec_op(struct nand_chip *nand, > + const struct nand_operation *op, > + bool check_only) > +{ > + int i; > + unsigned int op_id; > + const struct nand_op_instr *instr = NULL; > + > + rk_nandc_select_chip(nand, op->cs); > + > + if (check_only) > + return 0; > + > + for (op_id = 0; op_id < op->ninstrs; op_id++) { > + instr = &op->instrs[op_id]; > + > + switch (instr->type) { > + case NAND_OP_CMD_INSTR: > + rk_nandc_write_cmd(nand, instr->ctx.cmd.opcode); > + break; > + case NAND_OP_ADDR_INSTR: > + for (i = 0; i < instr->ctx.addr.naddrs; i++) > + rk_nandc_write_addr(nand, > + instr->ctx.addr.addrs[i]); > + break; > + case NAND_OP_DATA_IN_INSTR: > + rk_nandc_read_buf(nand, instr->ctx.data.buf.in, > + instr->ctx.data.len); > + break; > + case NAND_OP_DATA_OUT_INSTR: > + rk_nandc_write_buf(nand, instr->ctx.data.buf.out, > + instr->ctx.data.len); > + break; > + case NAND_OP_WAITRDY_INSTR: > + rk_nandc_dev_ready(nand); > + break; > + } > + } > + > + return 0; > +} > + > +static const struct nand_controller_ops rk_nand_controller_ops = { > + .attach_chip = rk_nandc_attach_chip, > + .detach_chip = rk_nandc_detach_chip, > + .exec_op = rk_nandc_exec_op, > +}; > + > +static int rk_nandc_chip_init(struct device *dev, > + struct rk_nand_controller *ctrl, > + struct device_node *np, unsigned int chipnr) > +{ > + struct rk_nand_chip *node; > + struct nand_chip *nand; > + struct mtd_info *mtd; > + const __be32 *reg; > + int ret; > + > + reg = of_get_property(np, "reg", NULL); > + if (!reg) > + return -EINVAL; > + > + ctrl->banks[chipnr] = be32_to_cpu(*reg); > + > + if (ctrl->banks[chipnr] < 0) > + return -EINVAL; > + > + node = devm_kzalloc(dev, sizeof(*node), GFP_KERNEL); > + if (!node) > + return -ENOMEM; > + > + nand = &node->nand; > + > + nand_set_flash_node(nand, np); > + nand_set_controller_data(nand, ctrl); > + > + nand->controller = &ctrl->controller; > + nand->controller->ops = &rk_nand_controller_ops; > + > + nand->ecc.mode = NAND_ECC_HW_SYNDROME; > + nand->ecc.size = 1024; > + nand->ecc.strength = 40; > + > + nand->options = NAND_SKIP_BBTSCAN | NAND_NO_SUBPAGE_WRITE; > + > + mtd = nand_to_mtd(nand); > + mtd->dev.parent = dev; > + mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev), > + ctrl->banks[chipnr]); > + > + ret = nand_scan(nand, 1); Why 1 here? > + if (ret) > + return ret; > + > + ret = mtd_device_register(mtd, NULL, 0); > + if (ret) { > + dev_err(dev, "mtd device register failed: %d\n", ret); > + nand_release(nand); > + return ret; > + } > + > + list_add_tail(&node->chip_list, &ctrl->chips); > + > + return 0; > +} > + > +static int rk_nandc_cleanup_chips(struct rk_nand_controller *ctrl) > +{ > + struct rk_nand_chip *node; > + struct mtd_info *mtd; > + int ret; > + > + while (!list_empty(&ctrl->chips)) { > + node = list_first_entry(&ctrl->chips, struct rk_nand_chip, > + chip_list); > + mtd = nand_to_mtd(&node->nand); > + ret = mtd_device_unregister(mtd); > + if (ret) > + return ret; > + > + rk_nandc_free_buffer(&node->nand); > + nand_cleanup(&node->nand); > + list_del(&node->chip_list); > + } > + > + return 0; > +} > + > +static int rk_nandc_chips_init(struct device *dev, > + struct rk_nand_controller *ctrl) > +{ > + struct device_node *np = dev->of_node; > + struct device_node *nand_np; > + int nchips = of_get_child_count(np); > + int i = 0; > + int ret; > + > + if (nchips > NANDC_NUM_BANKS) { > + dev_err(dev, "too many NAND chips: %d (max = 4)\n", nchips); > + return -EINVAL; > + } > + > + for_each_child_of_node(np, nand_np) { > + ret = rk_nandc_chip_init(dev, ctrl, nand_np, i); > + if (ret) { > + rk_nandc_cleanup_chips(ctrl); > + of_node_put(nand_np); > + return ret; > + } > + i++; > + } > + > + return 0; > +} > + > +static int rk_nandc_probe(struct platform_device *pdev) > +{ > + const struct rk_nandc_data *data; > + struct device *dev = &pdev->dev; > + struct device_node *node; > + int id; > + int ret; > + > + data = of_device_get_match_data(&pdev->dev); > + if (!data) > + return -ENODEV; > + > + node = pdev->dev.of_node; > + > + id = of_alias_get_id(node, "nandc"); > + if (id < 0) > + id = g_id_counter; > + if ((id >= ARRAY_SIZE(g_nandc_info) || g_nandc_info[id].regs)) { > + dev_err( > + &pdev->dev, > + "failed to get id for nandc node '%pOFn'\n", > + node); > + of_node_put(node); > + return -ENODEV; > + } > + ++g_id_counter; > + > + g_nandc_info[id].version = data->version; > + > + g_nandc_info[id].regs = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(g_nandc_info[id].regs)) { > + dev_err(dev, "ioremap failed\n"); > + return PTR_ERR(g_nandc_info[id].regs); > + } > + > + g_nandc_info[id].irq = platform_get_irq(pdev, 0); > + if (g_nandc_info[id].irq < 0) { > + dev_err(dev, "get irq failed\n"); > + return g_nandc_info[id].irq; > + } > + > + g_nandc_info[id].hclk = devm_clk_get(dev, "hclk_nandc"); > + if (IS_ERR(g_nandc_info[id].hclk)) { > + dev_err(dev, "get hclk_nandc failed\n"); > + return PTR_ERR(g_nandc_info[id].hclk); > + } > + > + ret = clk_prepare_enable(g_nandc_info[id].hclk); > + if (ret) > + return ret; > + > + g_nandc_info[id].clk = devm_clk_get(dev, "clk_nandc"); > + if (!(IS_ERR(g_nandc_info[id].clk))) { > + clk_set_rate(g_nandc_info[id].clk, 150 * 1000 * 1000); > + > + ret = clk_prepare_enable(g_nandc_info[id].clk); > + if (ret) > + goto err_disable_hclk; > + } else > + dev_err(dev, "get clk_nandc failed\n"); > + > + if (g_nandc_info[id].version == VERSION_9) > + writel(0, g_nandc_info[id].regs + NANDC_REG_V9_INTEN); > + else > + writel(0, g_nandc_info[id].regs + NANDC_REG_V6_INTEN); > + ret = devm_request_irq(dev, g_nandc_info[id].irq, rk_nandc_interrupt, > + 0, "nandc", &g_nandc_info[id]); > + if (ret) > + goto err_disable_clk; > + > + nand_controller_init(&g_nandc_info[id].controller); > + INIT_LIST_HEAD(&g_nandc_info[id].chips); > + > + rk_nandc_init(&g_nandc_info[id]); > + > + ret = rk_nandc_chips_init(dev, &g_nandc_info[id]); > + if (ret) { > + dev_err(dev, "init nand chips failed\n"); > + goto err_disable_clk; > + } > + > + platform_set_drvdata(pdev, &g_nandc_info[id]); > + > + return 0; > + > +err_disable_clk: > + clk_disable_unprepare(g_nandc_info[id].clk); > +err_disable_hclk: > + clk_disable_unprepare(g_nandc_info[id].hclk); > + > + return ret; > +} > + > +static int rk_nandc_remove(struct platform_device *pdev) > +{ > + struct rk_nand_controller *ctrl = platform_get_drvdata(pdev); > + int ret; > + > + ret = rk_nandc_cleanup_chips(ctrl); > + if (ret) > + return ret; > + > + clk_disable_unprepare(ctrl->clk); > + clk_disable_unprepare(ctrl->hclk); > + platform_set_drvdata(pdev, NULL); > + > + return 0; > +} > + > +static void rk_nandc_shutdown(struct platform_device *pdev) > +{ > + struct rk_nand_controller *ctrl = platform_get_drvdata(pdev); > + int ret; > + > + ret = rk_nandc_cleanup_chips(ctrl); > + if (ret) > + return; > + > + clk_disable_unprepare(ctrl->clk); > + clk_disable_unprepare(ctrl->hclk); > + platform_set_drvdata(pdev, NULL); > +} > + > +static const struct rk_nandc_data rk_nandc_v6_data = { > + .version = VERSION_6, > +}; > + > +static const struct rk_nandc_data rk_nandc_v9_data = { > + .version = VERSION_9, > +}; > + > +static const struct of_device_id of_rk_nandc_match[] = { > + { > + .compatible = "rockchip,nandc-v6", > + .data = &rk_nandc_v6_data, > + }, > + { > + .compatible = "rockchip,nandc-v9", > + .data = &rk_nandc_v9_data, > + }, > + { /* sentinel */ }, > +}; > + > +static struct platform_driver rk_nandc_driver = { > + .probe = rk_nandc_probe, > + .remove = rk_nandc_remove, > + .shutdown = rk_nandc_shutdown, > + .driver = { > + .name = "rockchip-nandc", > + .of_match_table = of_rk_nandc_match, > + }, > +}; > + Move this empty line... > +module_platform_driver(rk_nandc_driver); ...Here > +MODULE_LICENSE("GPL v2"); Thanks, Miquèl 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=-13.3 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_2 autolearn=unavailable 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 0CD24C33CA2 for ; Fri, 10 Jan 2020 11:06:16 +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 C36382077C for ; Fri, 10 Jan 2020 11:06:15 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="nSTld6sv" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C36382077C 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=/kLWN8JQnAJ2fTz47vObr/plh1QWzebjbQ66gjuuuyo=; b=nSTld6sva1x4Ao UGj0tlEY1k42deSEe5OXxhebkjzga83wqBox25qhMS18vqFKorXhBZSJJLiJUXhTv3D6pAVKAilAq Sanmub4/Bfu4RZ60m0drw7zrMZM6DRtHLjbsEYxNndezDqEUFcrh4ysOtZdMMOSt+e2Oo4o4UyPPp 5C/BnxNxkQ9PqtZMjygyAqflKoTajuL2toZCQfABgFTEFfUr3J5jl2r48FHtRcwlAQmYmN2vj4pge Aau6upMWWI/AFAUwZ4+iIKYmOBVk3e6tBIRKylC+ddkmpz05QKGPmxqU3TmDyEhOv8mTOm5oLrsh7 M6qpqTjpmmP7LpyuUR3g==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1ips78-0000fN-Uu; Fri, 10 Jan 2020 11:06:03 +0000 Received: from relay7-d.mail.gandi.net ([217.70.183.200]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1ips6t-0000Up-9G; Fri, 10 Jan 2020 11:05:51 +0000 X-Originating-IP: 91.224.148.103 Received: from xps13 (unknown [91.224.148.103]) (Authenticated sender: miquel.raynal@bootlin.com) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 006AD20011; Fri, 10 Jan 2020 11:05:35 +0000 (UTC) Date: Fri, 10 Jan 2020 12:05:34 +0100 From: Miquel Raynal To: Johan Jonker Subject: Re: [RFC PATCH v1 02/10] mtd: nand: raw: add rockchip nand controller driver Message-ID: <20200110120534.1b4026b0@xps13> In-Reply-To: <20200108205338.11369-3-jbx6244@gmail.com> References: <20200108205338.11369-1-jbx6244@gmail.com> <20200108205338.11369-3-jbx6244@gmail.com> Organization: Bootlin X-Mailer: Claws Mail 3.17.4 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200110_030547_758867_37DFCA52 X-CRM114-Status: GOOD ( 28.28 ) X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, vigneshr@ti.com, richard@nod.at, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, robh+dt@kernel.org, linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, heiko@sntech.de 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 SGkgSm9oYW4sCgpKb2hhbiBKb25rZXIgPGpieDYyNDRAZ21haWwuY29tPiB3cm90ZSBvbiBXZWQs ICA4IEphbiAyMDIwIDIxOjUzOjMwCiswMTAwOgoKPiBGcm9tOiBZaWZlbmcgWmhhbyA8enlmQHJv Y2stY2hpcHMuY29tPgo+IAoKQ2FuIHlvdSBjaGFuZ2UgdGhlIHRpdGxlIHRvICJtdGQ6IHJhd25h bmQ6IHJvY2tjaGlwOiBBZGQgTkFORApjb250cm9sbGVyIGRyaXZlciIKCj4gQWRkIGJhc2ljIFJv Y2tjaGlwIG5hbmQgY29udHJvbGxlciBkcml2ZXIuCj4gCj4gQ29tcGF0aWJsZSB3aXRoIGhhcmR3 YXJlIHZlcnNpb24gNiBhbmQgOS4KPiBWNjoxNiwgMjQsIDQwLCA2MCBwZXIgMTAyNEIgQkNIL0VD Qy4KPiBWOToxNiwgNDAsIDYwLCA3MCBwZXIgMTAyNEIgQkNIL0VDQy4KPiA4IGJpdCBhc3luY2hy b25vdXMgZmxhc2ggaW50ZXJmYWNlIHN1cHBvcnQuCj4gU3VwcG9ydHMgdXAgdG8gMiBpZGVudGlj YWwgbmFuZGMgbm9kZXMuCj4gTWF4IDQgbmFuZCBjaGlwcyBwZXIgY29udHJvbGxlci4KPiBBYmxl IHRvIHNlbGVjdCBhIGRpZmZlcmVudCBoYXJkd2FyZSBlY2Mgc2V0dXAKPiBmb3IgdGhlIGxvYWRl ciBibG9ja3MuCj4gTm8gYmFkIGJsb2NrIHN1cHBvcnQuCgpUaGFuayB5b3UgdmVyeSBtdWNoIGZv ciB0aGlzIHNlcmllcywgYXMgdGhlIGJhZCBibG9ja3Mgc3VwcG9ydCBpcwphYnNvbHV0ZWx5IGZ1 bmRhbWVudGFsLCBJIHdvbmRlciB3aGF0IGlzIHRoZSBpc3N1ZSBoZXJlPwoKPiAKPiBTaWduZWQt b2ZmLWJ5OiBZaWZlbmcgWmhhbyA8enlmQHJvY2stY2hpcHMuY29tPgo+IFNpZ25lZC1vZmYtYnk6 IEpvaGFuIEpvbmtlciA8amJ4NjI0NEBnbWFpbC5jb20+Cj4gLS0tCj4gIGRyaXZlcnMvbXRkL25h bmQvcmF3L0tjb25maWcgICAgICAgICAgfCAgICA4ICsKPiAgZHJpdmVycy9tdGQvbmFuZC9yYXcv TWFrZWZpbGUgICAgICAgICB8ICAgIDEgKwo+ICBkcml2ZXJzL210ZC9uYW5kL3Jhdy9yb2NrY2hp cF9uYW5kYy5jIHwgMTIyNCArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKPiAgMyBm aWxlcyBjaGFuZ2VkLCAxMjMzIGluc2VydGlvbnMoKykKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRy aXZlcnMvbXRkL25hbmQvcmF3L3JvY2tjaGlwX25hbmRjLmMKPiAKPiBkaWZmIC0tZ2l0IGEvZHJp dmVycy9tdGQvbmFuZC9yYXcvS2NvbmZpZyBiL2RyaXZlcnMvbXRkL25hbmQvcmF3L0tjb25maWcK PiBpbmRleCA3NGZiOTFhZGUuLjY4ZGM5YTM2ZCAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL210ZC9u YW5kL3Jhdy9LY29uZmlnCj4gKysrIGIvZHJpdmVycy9tdGQvbmFuZC9yYXcvS2NvbmZpZwo+IEBA IC00NTcsNiArNDU3LDE0IEBAIGNvbmZpZyBNVERfTkFORF9DQURFTkNFCj4gIAkgIEVuYWJsZSB0 aGUgZHJpdmVyIGZvciBOQU5EIGZsYXNoIG9uIHBsYXRmb3JtcyB1c2luZyBhIENhZGVuY2UgTkFO RAo+ICAJICBjb250cm9sbGVyLgo+ICAKPiArY29uZmlnIE1URF9OQU5EX1JPQ0tDSElQCj4gKwl0 cmlzdGF0ZSAiUm9ja2NoaXAgcmF3IE5BTkQgY29udHJvbGxlciBkcml2ZXIiCj4gKwlkZXBlbmRz IG9uIEFSQ0hfUk9DS0NISVAgfHwgQ09NUElMRV9URVNUCj4gKwlkZXBlbmRzIG9uIEhBU19JT01F TQo+ICsJaGVscAo+ICsJICBFbmFibGVzIHN1cHBvcnQgZm9yIHRoZSBSb2NrY2hpcCByYXcgTkFO RCBjb250cm9sbGVyIGRyaXZlci4KPiArCSAgVGhpcyBjb250cm9sbGVyIGlzIGZvdW5kIG9uIHJr MzA2NiwgcmszMTg4LCByazMyODggYW5kIG1vcmUuCgpDYW4geW91IHdyaXRlIGFuIGV4aGF1c3Rp dmUgbGlzdCBpZiB5b3Uga25vdyBpdD8gT3IgYXQgbGVhc3QgdGhlCmZhbWlsaWVzPyBJdCBpcyBx dWl0ZSBjaGFsbGVuZ2luZyB3aGVuIHlvdSBhcmUgbm90IGluIHRoZSBSb2NrY2hpcAp3b3JsZCB0 byBrbm93IHdoYXQgU29DIGlzIHNpbWlsYXIgdG8gYW5vdGhlciByYW5kb20gU29DLgogCj4gKwo+ ICBjb21tZW50ICJNaXNjIgo+ICAKPiAgY29uZmlnIE1URF9TTV9DT01NT04KPiBkaWZmIC0tZ2l0 IGEvZHJpdmVycy9tdGQvbmFuZC9yYXcvTWFrZWZpbGUgYi9kcml2ZXJzL210ZC9uYW5kL3Jhdy9N YWtlZmlsZQo+IGluZGV4IDJkMTM2YjE1OC4uMzA2M2ZlNzRhIDEwMDY0NAo+IC0tLSBhL2RyaXZl cnMvbXRkL25hbmQvcmF3L01ha2VmaWxlCj4gKysrIGIvZHJpdmVycy9tdGQvbmFuZC9yYXcvTWFr ZWZpbGUKPiBAQCAtNTgsNiArNTgsNyBAQCBvYmotJChDT05GSUdfTVREX05BTkRfVEVHUkEpCQkr PSB0ZWdyYV9uYW5kLm8KPiAgb2JqLSQoQ09ORklHX01URF9OQU5EX1NUTTMyX0ZNQzIpCSs9IHN0 bTMyX2ZtYzJfbmFuZC5vCj4gIG9iai0kKENPTkZJR19NVERfTkFORF9NRVNPTikJCSs9IG1lc29u X25hbmQubwo+ICBvYmotJChDT05GSUdfTVREX05BTkRfQ0FERU5DRSkJCSs9IGNhZGVuY2UtbmFu ZC1jb250cm9sbGVyLm8KPiArb2JqLSQoQ09ORklHX01URF9OQU5EX1JPQ0tDSElQKQkJKz0gcm9j a2NoaXBfbmFuZGMubwoKQSBkcml2ZXIgbmFtZWQgcm9ja2NoaXAtbmFuZC1jb250cm9sbGVyLmMg d291bGQgYmUgbmljZSEKCj4gIAo+ICBuYW5kLW9ianMgOj0gbmFuZF9iYXNlLm8gbmFuZF9sZWdh Y3kubyBuYW5kX2JidC5vIG5hbmRfdGltaW5ncy5vIG5hbmRfaWRzLm8KPiAgbmFuZC1vYmpzICs9 IG5hbmRfb25maS5vCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbXRkL25hbmQvcmF3L3JvY2tjaGlw X25hbmRjLmMgYi9kcml2ZXJzL210ZC9uYW5kL3Jhdy9yb2NrY2hpcF9uYW5kYy5jCj4gbmV3IGZp bGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAuLjAxODMwOGU1OAo+IC0tLSAvZGV2L251 bGwKPiArKysgYi9kcml2ZXJzL210ZC9uYW5kL3Jhdy9yb2NrY2hpcF9uYW5kYy5jCj4gQEAgLTAs MCArMSwxMjI0IEBACj4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wCj4gKy8q Cj4gKyAqIEJhc2VkIG9uOgo+ICsgKiBodHRwczovL2dpdGh1Yi5jb20vcm9ja2NoaXAtbGludXgv a2VybmVsL2Jsb2IvZGV2ZWxvcC00LjQvZHJpdmVycy9tdGQvbmFuZC8KPiArICogICAgICAgICBy b2NrY2hpcF9uYW5kX3Y2LmMKPiArICogaHR0cHM6Ly9naXRodWIuY29tL3JvY2tjaGlwLWxpbnV4 L2tlcm5lbC9ibG9iL2RldmVsb3AtNC40L2RyaXZlcnMvbXRkL25hbmQvCj4gKyAqICAgICAgICAg cm9ja2NoaXBfbmFuZF92OS5jCgpJJ20gbm90IHN1cmUgdGhlIGVudGlyZSBsaW5rIGlzIHJlbGV2 YW50LCBJIHdvdWxkIHNpbXBsZSBtZW50aW9uIHRoZQpSb2NrY2hpcCBvZmZpY2lhbCBHaXRodWIg cmVwb3NpdG9yeSBhbmQgd29yayBmcm9tIFlpZmVuZy4KCj4gKyAqIENvcHlyaWdodCAoYykgMjAx Ni0yMDE5IFlpZmVuZyBaaGFvIHlpZmVuZy56aGFvQHJvY2stY2hpcHMuY29tCj4gKyAqCj4gKyAq IFVwZGF0ZS9yZXN0eWxlIGZvciBsaW51eC1uZXh0Lgo+ICsgKiBBZGQgZXhlY19vcCBmdW5jdGlv bi4KCllvdSBjYW4gZHJvcCB0aGVzZSB0d28gbGluZXMgdG9vLiBUaGlzIGlzIG1vcmUgYSAiY29t bWl0IGRlc2NyaXB0aW9uIgp0aGluZy4KCj4gKyAqIENvbWJpbmUgZHJpdmVyIGZvciBuYW5kYyB2 ZXJzaW9uIDYgYW5kIDkuCgogICAgICBTdXBwb3J0IE5BTkQgY29udHJvbGxlciB2ZXJzaW9ucyA2 IGFuZCA5IGZvdW5kIG9uIFNvQ3MgLi4uCgo+ICsgKiBDb3B5cmlnaHQgKGMpIDIwMjAgSm9oYW4g Sm9ua2VyIGpieDYyNDRAZ21haWwuY29tCj4gKyAqLwo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L2Ns ay5oPgo+ICsjaW5jbHVkZSA8bGludXgvZG1hLW1hcHBpbmcuaD4KPiArI2luY2x1ZGUgPGxpbnV4 L2ludGVycnVwdC5oPgo+ICsjaW5jbHVkZSA8bGludXgvaW9wb2xsLmg+Cj4gKyNpbmNsdWRlIDxs aW51eC9tb2R1bGUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L29mX2RldmljZS5oPgo+ICsjaW5jbHVk ZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4gKwo+ICsjaW5jbHVkZSA8bGludXgvbXRkL3Jh d25hbmQuaD4KPiArCj4gKyNkZWZpbmUgTkFORENfSURfVjYwMAkJCTB4NTYzNjMwMzAKPiArI2Rl ZmluZSBOQU5EQ19JRF9WNjIyCQkJMHg1NjM2MzIzMgo+ICsjZGVmaW5lIE5BTkRDX0lEX1Y3MDEJ CQkweDcwMQo+ICsjZGVmaW5lIE5BTkRDX0lEX1Y4MDAJCQkweDU2MzgzMDMwCj4gKyNkZWZpbmUg TkFORENfSURfVjgwMQkJCTB4ODAxCj4gKyNkZWZpbmUgTkFORENfSURfVjkwMAkJCTB4NTYzOTMw MzAKCkkgd291bGQgcHJlZmVyIHByZWZpeGluZyBldmVyeXRoaW5nIFJLX05BTkRDXyBvciBSS18K Cj4gKwo+ICsjZGVmaW5lIE5BTkRDX0lEQlJlc0Jsa051bQkJMTYKPiArI2RlZmluZSBOQU5EQ19J REJFY2NCaXRzCQkyNAo+ICsjZGVmaW5lIE5BTkRDX0lEQlN0YXJ0QWRkcgkJMAo+ICsKPiArI2Rl ZmluZSBOQU5EQ19WNl9FQ0NfMTYJCQkweDAwMDAwMDAwCj4gKyNkZWZpbmUgTkFORENfVjZfRUND XzI0CQkJMHgwMDAwMDAxMAo+ICsjZGVmaW5lIE5BTkRDX1Y2X0VDQ180MAkJCTB4MDAwNDAwMDAK PiArI2RlZmluZSBOQU5EQ19WNl9FQ0NfNjAJCQkweDAwMDQwMDEwCj4gKwo+ICsjZGVmaW5lIE5B TkRDX1Y5X0VDQ18xNgkJCTB4MDIwMDAwMDEKPiArI2RlZmluZSBOQU5EQ19WOV9FQ0NfNDAJCQkw eDA0MDAwMDAxCj4gKyNkZWZpbmUgTkFORENfVjlfRUNDXzYwCQkJMHgwNjAwMDAwMQo+ICsjZGVm aW5lIE5BTkRDX1Y5X0VDQ183MAkJCTB4MDAwMDAwMDEKPiArCj4gKyNkZWZpbmUgTkFORENfTlVN X0JBTktTCQkJNAo+ICsjZGVmaW5lIE5BTkRDX0RFRl9USU1FT1VUCQkxMDAwMAo+ICsKPiArI2Rl ZmluZSBOQU5EQ19SRUdfREFUQQkJCTB4MDAKPiArI2RlZmluZSBOQU5EQ19SRUdfQUREUgkJCTB4 MDQKPiArI2RlZmluZSBOQU5EQ19SRUdfQ01ECQkJMHgwOAo+ICsKPiArLyogcmVnaXN0ZXIgb2Zm c2V0IG5hbmRjIHZlcnNpb24gNiAqLwo+ICsjZGVmaW5lIE5BTkRDX1JFR19WNl9GTUNUTAkJMHgw MAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WNl9GTVdBSVQJCTB4MDQKPiArI2RlZmluZSBOQU5EQ19S RUdfVjZfRkxDVEwJCTB4MDgKPiArI2RlZmluZSBOQU5EQ19SRUdfVjZfQkNIQ1RMCQkweDBjCj4g KyNkZWZpbmUgTkFORENfUkVHX1Y2X0RNQV9DRkcJCTB4MTAKPiArI2RlZmluZSBOQU5EQ19SRUdf VjZfRE1BX0JVRjAJCTB4MTQKPiArI2RlZmluZSBOQU5EQ19SRUdfVjZfRE1BX0JVRjEJCTB4MTgK PiArI2RlZmluZSBOQU5EQ19SRUdfVjZfRE1BX1NUCQkweDFDCj4gKyNkZWZpbmUgTkFORENfUkVH X1Y2X0JDSFNUCQkweDIwCj4gKyNkZWZpbmUgTkFORENfUkVHX1Y2X1JBTkRNWgkJMHgxNTAKPiAr I2RlZmluZSBOQU5EQ19SRUdfVjZfVkVSCQkweDE2MAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WNl9J TlRFTgkJMHgxNkMKPiArI2RlZmluZSBOQU5EQ19SRUdfVjZfSU5UQ0xSCQkweDE3MAo+ICsjZGVm aW5lIE5BTkRDX1JFR19WNl9JTlRTVAkJMHgxNzQKPiArI2RlZmluZSBOQU5EQ19SRUdfVjZfU1BB UkUwCQkweDIwMAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WNl9TUEFSRTEJCTB4MjMwCj4gKwo+ICsv KiByZWdpc3RlciBvZmZzZXQgbmFuZGMgdmVyc2lvbiA5ICovCj4gKyNkZWZpbmUgTkFORENfUkVH X1Y5X0ZNQ1RMCQkweDAwCj4gKyNkZWZpbmUgTkFORENfUkVHX1Y5X0ZNV0FJVAkJMHgwNAo+ICsj ZGVmaW5lIE5BTkRDX1JFR19WOV9GTENUTAkJMHgxMAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WOV9C Q0hDVEwJCTB4MjAKPiArI2RlZmluZSBOQU5EQ19SRUdfVjlfRE1BX0NGRwkJMHgzMAo+ICsjZGVm aW5lIE5BTkRDX1JFR19WOV9ETUFfQlVGMAkJMHgzNAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WOV9E TUFfQlVGMQkJMHgzOAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WOV9ETUFfU1QJCTB4NDAKPiArI2Rl ZmluZSBOQU5EQ19SRUdfVjlfVkVSCQkweDgwCj4gKyNkZWZpbmUgTkFORENfUkVHX1Y5X0lOVEVO CQkweDEyMAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WOV9JTlRDTFIJCTB4MTI0Cj4gKyNkZWZpbmUg TkFORENfUkVHX1Y5X0lOVFNUCQkweDEyOAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WOV9CQ0hTVAkJ MHgxNTAKPiArI2RlZmluZSBOQU5EQ19SRUdfVjlfU1BBUkUwCQkweDIwMAo+ICsjZGVmaW5lIE5B TkRDX1JFR19WOV9TUEFSRTEJCTB4MjA0Cj4gKyNkZWZpbmUgTkFORENfUkVHX1Y5X1JBTkRNWgkJ MHgyMDgKPiArCj4gKy8qIHJlZ2lzdGVyIG9mZnNldCBuYW5kYyBjb21tb24gKi8KPiArI2RlZmlu ZSBOQU5EQ19SRUdfQkFOSzAJCQkweDgwMAo+ICsjZGVmaW5lIE5BTkRDX1JFR19TUkFNMAkJCTB4 MTAwMAo+ICsKPiArLyogRk1DVEwgKi8KPiArI2RlZmluZSBOQU5EQ19WNl9GTV9XUAkJCUJJVCg4 KQo+ICsjZGVmaW5lIE5BTkRDX1Y2X0ZNX0NFX1NFTF9NCQkweEZGCj4gKyNkZWZpbmUgTkFORENf VjZfRk1fQ0VfU0VMKHgpCQkoMSA8PCAoeCkpCj4gKyNkZWZpbmUgTkFORENfVjZfRk1fRlJFQURZ CQlCSVQoOSkKPiArCj4gKyNkZWZpbmUgTkFORENfVjlfRk1fV1AJCQlCSVQoOCkKPiArI2RlZmlu ZSBOQU5EQ19WOV9GTV9DRV9TRUxfTQkJMHhGRgo+ICsjZGVmaW5lIE5BTkRDX1Y5X0ZNX0NFX1NF TCh4KQkJKDEgPDwgKHgpKQo+ICsjZGVmaW5lIE5BTkRDX1Y5X1JEWQkJCUJJVCg5KQo+ICsKPiAr LyogRkxDVEwgKi8KPiArI2RlZmluZSBOQU5EQ19WNl9GTF9SU1QJCQlCSVQoMCkKPiArI2RlZmlu ZSBOQU5EQ19WNl9GTF9ESVIoeCkJCSgoeCkgPyBCSVQoMSkgOiAwKQo+ICsjZGVmaW5lIE5BTkRD X1Y2X0ZMX1hGRVJfU1RBUlQJCUJJVCgyKQo+ICsjZGVmaW5lIE5BTkRDX1Y2X0ZMX1hGRVJfRU4J CUJJVCgzKQo+ICsjZGVmaW5lIE5BTkRDX1Y2X0ZMX1NUX0JVRl9TCQkweDQKPiArI2RlZmluZSBO QU5EQ19WNl9GTF9YRkVSX0NPVU5UCQlCSVQoNSkKPiArI2RlZmluZSBOQU5EQ19WNl9GTF9BQ09S UkVDVAkJQklUKDEwKQo+ICsjZGVmaW5lIE5BTkRDX1Y2X0ZMX1hGRVJfUkVBRFkJCUJJVCgyMCkK PiArI2RlZmluZSBOQU5EQ19WNl9GTF9QQUdFX05VTSh4KQkJKCh4KSA8PCAyMikKPiArI2RlZmlu ZSBOQU5EQ19WNl9GTF9BU1lOQ19UT0dfTUlYCUJJVCgyOSkKPiArCj4gKyNkZWZpbmUgTkFORENf VjlfRkxfUlNUCQkJQklUKDApCj4gKyNkZWZpbmUgTkFORENfVjlfRkxfRElSKHgpCQkoKHgpID8g QklUKDEpIDogMCkKPiArI2RlZmluZSBOQU5EQ19WOV9GTF9YRkVSX1NUQVJUCQlCSVQoMikKPiAr I2RlZmluZSBOQU5EQ19WOV9GTF9YRkVSX0VOCQlCSVQoMykKPiArI2RlZmluZSBOQU5EQ19WOV9G TF9TVF9CVUZfUwkJMHg0Cj4gKyNkZWZpbmUgTkFORENfVjlfRkxfWEZFUl9DT1VOVAkJQklUKDUp Cj4gKyNkZWZpbmUgTkFORENfVjlfRkxfQUNPUlJFQ1QJCUJJVCgxMCkKPiArI2RlZmluZSBOQU5E Q19WOV9GTF9YRkVSX1JFQURZCQlCSVQoMjApCj4gKyNkZWZpbmUgTkFORENfVjlfRkxfUEFHRV9O VU0oeCkJCSgoeCkgPDwgMjIpCj4gKyNkZWZpbmUgTkFORENfVjlfRkxfQVNZTkNfVE9HX01JWAlC SVQoMjkpCj4gKwo+ICsvKiBCQ0hDVEwgKi8KPiArI2RlZmluZSBOQU5EX1Y2X0JDSF9SRUdJT05f UwkJMHg1Cj4gKyNkZWZpbmUgTkFORF9WNl9CQ0hfUkVHSU9OX00JCTB4Nwo+ICsKPiArI2RlZmlu ZSBOQU5EX1Y5X0JDSF9NT0RFX1MJCTI1Cj4gKyNkZWZpbmUgTkFORF9WOV9CQ0hfTU9ERV9NCQkw eDcKPiArCj4gKy8qIEJDSFNUICovCj4gKyNkZWZpbmUgTkFORENfVjZfQkNIMF9TVF9FUlIJCUJJ VCgyKQo+ICsjZGVmaW5lIE5BTkRDX1Y2X0JDSDFfU1RfRVJSCQlCSVQoMTUpCj4gKyNkZWZpbmUg TkFORENfVjZfRUNDX0VSUl9DTlQwKHgpCSgoKCh4ICYgKDB4MUYgPDwgMykpID4+IDMpIFwKPiAr CQkJCQl8ICgoeCAmICgxIDw8IDI3KSkgPj4gMjIpKSAmIDB4M0YpCj4gKyNkZWZpbmUgTkFORENf VjZfRUNDX0VSUl9DTlQxKHgpCSgoKCh4ICYgKDB4MUYgPDwgMTYpKSA+PiAxNikgXAo+ICsJCQkJ CXwgKCh4ICYgKDEgPDwgMjkpKSA+PiAyNCkpICYgMHgzRikKPiArCj4gKyNkZWZpbmUgTkFORENf VjlfQkNIMF9TVF9FUlIJCUJJVCgyKQo+ICsjZGVmaW5lIE5BTkRDX1Y5X0JDSDFfU1RfRVJSCQlC SVQoMTgpCj4gKyNkZWZpbmUgTkFORENfVjlfRUNDX0VSUl9DTlQwKHgpCSgoKHgpICYgKDB4N0Yg PDwgMykpID4+IDMpCj4gKyNkZWZpbmUgTkFORENfVjlfRUNDX0VSUl9DTlQxKHgpCSgoKHgpICYg KDB4N0YgPDwgMTkpKSA+PiAxOSkKPiArCj4gKy8qIERNQV9DRkcgKi8KPiArI2RlZmluZSBOQU5E Q19WNl9ETUFfQ0ZHX1dSX1NUCQlCSVQoMCkKPiArI2RlZmluZSBOQU5EQ19WNl9ETUFfQ0ZHX1dS KHgpCQkoKCF4KSA/IEJJVCgxKSA6IDApCj4gKyNkZWZpbmUgTkFORENfVjZfRE1BX0NGR19CVVNf TU9ERQlCSVQoMikKPiArCj4gKyNkZWZpbmUgTkFORENfVjZfRE1BX0NGR19IU0laRV84CTAKPiAr I2RlZmluZSBOQU5EQ19WNl9ETUFfQ0ZHX0hTSVpFXzE2CSgxIDw8IDMpCj4gKyNkZWZpbmUgTkFO RENfVjZfRE1BX0NGR19IU0laRV8zMgkoMiA8PCAzKQo+ICsKPiArI2RlZmluZSBOQU5EQ19WNl9E TUFfQ0ZHX0JVUlNUXzEJMAo+ICsjZGVmaW5lIE5BTkRDX1Y2X0RNQV9DRkdfQlVSU1RfNAkoMyA8 PCA2KQo+ICsjZGVmaW5lIE5BTkRDX1Y2X0RNQV9DRkdfQlVSU1RfOAkoNSA8PCA2KQo+ICsjZGVm aW5lIE5BTkRDX1Y2X0RNQV9DRkdfQlVSU1RfMTYJKDcgPDwgNikKPiArCj4gKyNkZWZpbmUgTkFO RENfVjZfRE1BX0NGR19JTkNSX05VTSh4KQkoKHgpIDw8IDkpCj4gKwo+ICsjZGVmaW5lIE5BTkRD X1Y5X0RNQV9DRkdfV1JfU1QJCUJJVCgwKQo+ICsjZGVmaW5lIE5BTkRDX1Y5X0RNQV9DRkdfV1Io eCkJCSgoIXgpID8gQklUKDEpIDogMCkKPiArI2RlZmluZSBOQU5EQ19WOV9ETUFfQ0ZHX0JVU19N T0RFCUJJVCgyKQo+ICsKPiArI2RlZmluZSBOQU5EQ19WOV9ETUFfQ0ZHX0hTSVpFXzgJMAo+ICsj ZGVmaW5lIE5BTkRDX1Y5X0RNQV9DRkdfSFNJWkVfMTYJKDEgPDwgMykKPiArI2RlZmluZSBOQU5E Q19WOV9ETUFfQ0ZHX0hTSVpFXzMyCSgyIDw8IDMpCj4gKwo+ICsjZGVmaW5lIE5BTkRDX1Y5X0RN QV9DRkdfQlVSU1RfMQkwCj4gKyNkZWZpbmUgTkFORENfVjlfRE1BX0NGR19CVVJTVF80CSgzIDw8 IDYpCj4gKyNkZWZpbmUgTkFORENfVjlfRE1BX0NGR19CVVJTVF84CSg1IDw8IDYpCj4gKyNkZWZp bmUgTkFORENfVjlfRE1BX0NGR19CVVJTVF8xNgkoNyA8PCA2KQo+ICsKPiArI2RlZmluZSBOQU5E Q19WOV9ETUFfQ0ZHX0lOQ1JfTlVNKHgpCSgoeCkgPDwgOSkKPiArCj4gKy8qIElOVEVOICovCj4g KyNkZWZpbmUgTkFORENfVjZfSU5UX0RNQQkJQklUKDApCj4gKwo+ICsjZGVmaW5lIE5BTkRDX1Y5 X0lOVF9ETUEJCUJJVCgwKQo+ICsKPiArZW51bSBya19uYW5kY192ZXJzaW9uIHsKPiArCVZFUlNJ T05fNiA9IDYsCj4gKwlWRVJTSU9OXzkgPSA5LAo+ICt9Owo+ICsKPiArc3RydWN0IHJrX25hbmRj X2RhdGEgewo+ICsJZW51bSBya19uYW5kY192ZXJzaW9uIHZlcnNpb247CgpJZiB5b3UgbWFrZSBh IGRpc3RpbmN0aW9uIGJldHdlZW4gYm90aCB2ZXJzaW9uLCBtYXliZSB5b3UgY2FuIGFkZCBtb3Jl CnBhcmFtZXRlcnMgaGVyZSBhbmQgZG8KCglmb28gPSBkYXRhLT5wYXJhbQoKaW5zdGVhZCBvZgoK CWlmIChkYXRhLT52ZXJzaW9uID09IDYpCgkJZm9vID0gdGhpczsKCWVsc2UKCQlmb28gPSB0aGF0 OwoKPiArfTsKPiArCj4gK3N0cnVjdCBya19uYW5kX2NvbnRyb2xsZXIgewo+ICsJdm9pZCBfX2lv bWVtICpyZWdzOwo+ICsJaW50IGlycTsKPiArCXN0cnVjdCBjbGsgKmhjbGs7Cj4gKwlzdHJ1Y3Qg Y2xrICpjbGs7Cj4gKwlzdHJ1Y3QgbGlzdF9oZWFkIGNoaXBzOwo+ICsJc3RydWN0IGNvbXBsZXRp b24gY29tcGxldGU7Cj4gKwlzdHJ1Y3QgbmFuZF9jb250cm9sbGVyIGNvbnRyb2xsZXI7Cj4gKwlp bnQgYmFua3NbTkFORENfTlVNX0JBTktTXTsKCj4gKwlib29sIGJvb3Ryb21ibG9ja3M7Cj4gKwlp bnQgZWNjX21vZGU7Cj4gKwl1aW50MzJfdCBlY2Nfc3RyZW5ndGg7Cj4gKwlpbnQgbWF4X2VjY19z dHJlbmd0aDsKCkkgaGF2ZSBub3QgcmVhZCB5ZXQgdGhlIGVudGlyZSBkcml2ZXIgYnV0IEkgYmVs aWV2ZSB0aGUgYWJvdmUgNApwYXJhbWV0ZXJzIHNob3VsZCBwcm9iYWJseSBiZSBtb3ZlZCBpbiBy a19uYW5kX2NoaXAsIHJpZ2h0PyBBbnl0aGluZwp0aGF0IGlzIE5BTkQgY2hpcCByZWxhdGVkIHNo b3VsZCBub3QgYmUgaW4gdGhlIGNvbnRyb2xsZXIgc3RydWN0dXJlLiBJdApkZXBlbmRzIGlmIHlv dSBjYW4gY2hhbmdlIEVDQyByZXF1aXJlbWVudHMgb24gdGhlIGZseSBvciBub3QuCgo+ICsJdWlu dDMyX3QgKm9vYl9idWY7Cj4gKwl1aW50MzJfdCAqcGFnZV9idWY7Cj4gKwlpbnQgc2VsZWN0ZWRf YmFuazsKPiArCWVudW0gcmtfbmFuZGNfdmVyc2lvbiB2ZXJzaW9uOwo+ICt9Owo+ICsKPiArc3Ry dWN0IHJrX25hbmRfY2hpcCB7Cj4gKwlzdHJ1Y3QgbmFuZF9jaGlwIG5hbmQ7Cj4gKwlzdHJ1Y3Qg bGlzdF9oZWFkIGNoaXBfbGlzdDsKPiArfTsKPiArCj4gK3N0YXRpYyBzdHJ1Y3QgcmtfbmFuZF9j b250cm9sbGVyIGdfbmFuZGNfaW5mb1syXTsKCkkgZG9uJ3QgbGlrZSB0aGlzIGlkZWEgc28gbXVj aC4gSSBwcmVmZXIgYSBkeW5hbWljIGFsbG9jYXRpb24gaW4gdGhlCnByb2JlLgoKPiArc3RhdGlj IGludCBnX2lkX2NvdW50ZXI7CgpEb24ndCBrbm93IHdoYXQgdGhpcyBpcyB5ZXQsIGJ1dCBpdCBp cyBwcm9iYWJseSBhIGJhZCBpZGVhIDopCgo+ICsKPiArc3RhdGljIHZvaWQgcmtfbmFuZGNfaW5p dChzdHJ1Y3QgcmtfbmFuZF9jb250cm9sbGVyICpjdHJsKQo+ICt7Cj4gKwlpZiAoY3RybC0+dmVy c2lvbiA9PSBWRVJTSU9OXzkpIHsKPiArCQl3cml0ZWwoMCwgY3RybC0+cmVncyArIE5BTkRDX1JF R19WOV9SQU5ETVopOwo+ICsJCXdyaXRlbCgwLCBjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y5X0RN QV9DRkcpOwo+ICsJCXdyaXRlbChOQU5EQ19WOV9GTV9XUCwgY3RybC0+cmVncyArIE5BTkRDX1JF R19WOV9GTUNUTCk7Cj4gKwkJd3JpdGVsKE5BTkRDX1Y5X0ZMX1JTVCwgY3RybC0+cmVncyArIE5B TkRDX1JFR19WOV9GTENUTCk7Cj4gKwkJd3JpdGVsKDB4MTA4MSwgY3RybC0+cmVncyArIE5BTkRD X1JFR19WOV9GTVdBSVQpOwo+ICsJfSBlbHNlIHsKPiArCQl3cml0ZWwoMCwgY3RybC0+cmVncyAr IE5BTkRDX1JFR19WNl9SQU5ETVopOwo+ICsJCXdyaXRlbCgwLCBjdHJsLT5yZWdzICsgTkFORENf UkVHX1Y2X0RNQV9DRkcpOwo+ICsJCXdyaXRlbChOQU5EQ19WNl9GTV9XUCwgY3RybC0+cmVncyAr IE5BTkRDX1JFR19WNl9GTUNUTCk7Cj4gKwkJd3JpdGVsKE5BTkRDX1Y2X0ZMX1JTVCwgY3RybC0+ cmVncyArIE5BTkRDX1JFR19WNl9GTENUTCk7Cj4gKwkJd3JpdGVsKDB4MTA4MSwgY3RybC0+cmVn cyArIE5BTkRDX1JFR19WNl9GTVdBSVQpOwo+ICsJfQoKTXkgYWJvdmUgY29tbWVudCBhYm91dCB0 aGUgcGxhdGZvcm0gZGF0YSB3b3VsZCBtYWtlIGEgbG90IG9mIHNlbnNlIGhlcmUhCgo+ICt9Cj4g Kwo+ICtzdGF0aWMgaXJxcmV0dXJuX3QgcmtfbmFuZGNfaW50ZXJydXB0KGludCBpcnEsIHZvaWQg KmRldl9pZCkKPiArewo+ICsJc3RydWN0IHJrX25hbmRfY29udHJvbGxlciAqY3RybCA9IGRldl9p ZDsKPiArCj4gKwlpZiAoY3RybC0+dmVyc2lvbiA9PSBWRVJTSU9OXzkpIHsKPiArCQl1aW50MzJf dCBzdCA9IHJlYWRsKGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjlfSU5UU1QpOwo+ICsJCXVpbnQz Ml90IGllbiA9IHJlYWRsKGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjlfSU5URU4pOwo+ICsKPiAr CQlpZiAoIShpZW4gJiBzdCkpCj4gKwkJCXJldHVybiBJUlFfTk9ORTsKPiArCj4gKwkJaWYgKChp ZW4gJiBzdCkgPT0gaWVuKQo+ICsJCQljb21wbGV0ZSgmY3RybC0+Y29tcGxldGUpOwo+ICsKPiAr CQl3cml0ZWwoc3QsIGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjlfSU5UQ0xSKTsKPiArCQl3cml0 ZWwofnN0ICYgaWVuLCBjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y5X0lOVEVOKTsKPiArCX0gZWxz ZSB7Cj4gKwkJdWludDMyX3Qgc3QgPSByZWFkbChjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y2X0lO VFNUKTsKPiArCQl1aW50MzJfdCBpZW4gPSByZWFkbChjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y2 X0lOVEVOKTsKPiArCj4gKwkJaWYgKCEoaWVuICYgc3QpKQo+ICsJCQlyZXR1cm4gSVJRX05PTkU7 Cj4gKwo+ICsJCWlmICgoaWVuICYgc3QpID09IGllbikKPiArCQkJY29tcGxldGUoJmN0cmwtPmNv bXBsZXRlKTsKPiArCj4gKwkJd3JpdGVsKHN0LCBjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y2X0lO VENMUik7Cj4gKwkJd3JpdGVsKH5zdCAmIGllbiwgY3RybC0+cmVncyArIE5BTkRDX1JFR19WNl9J TlRFTik7Cj4gKwl9CgpTYW1lIGNvbW1lbnQhCgo+ICsKPiArCXJldHVybiBJUlFfSEFORExFRDsK PiArfQo+ICsKPiArc3RhdGljIHZvaWQgcmtfbmFuZGNfc2VsZWN0X2NoaXAoc3RydWN0IG5hbmRf Y2hpcCAqbmFuZCwgaW50IGNoaXBucikKPiArewo+ICsJc3RydWN0IHJrX25hbmRfY29udHJvbGxl ciAqY3RybCA9IG5hbmRfZ2V0X2NvbnRyb2xsZXJfZGF0YShuYW5kKTsKPiArCXVpbnQzMl90IHJl ZzsKPiArCWludCBiYW5rbnI7Cj4gKwo+ICsJLyogVGhlIHJlZ2lzdGVyIG9mZnNldCBhbmQgYml0 IHBvc2l0aW9ucyBmb3IKCnNob3VsZCBiZToKCgkvKgoJICogVGhlIHJlZ2lzdGVyLi4uCgpQbGVh c2UgcnVuIGNoZWNrcGF0Y2gucGwgLS1zdHJpY3Qgb24gdGhpcyBmaWxlLCB0aGlzIGtpbmQgb2Yg bWlzdGFrZQp3b3VsZCBoYXZlIGJlZW4gZGV0ZWN0ZWQuCgo+ICsJICogTkFORENfUkVHX1Y2X0ZN Q1RMIGFuZCBOQU5EQ19SRUdfVjlfRk1DVEwKPiArCSAqIGFyZSBpZGVudGljYWwuCj4gKwkgKi8K PiArCXJlZyA9IHJlYWRsKGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjZfRk1DVEwpOwo+ICsJcmVn ICY9IH5OQU5EQ19WNl9GTV9DRV9TRUxfTTsKPiArCj4gKwlpZiAoY2hpcG5yID09IC0xKSB7Cj4g KwkJYmFua25yID0gLTE7Cj4gKwl9IGVsc2Ugewo+ICsJCWJhbmtuciA9IGN0cmwtPmJhbmtzW2No aXBucl07Cj4gKwo+ICsJCXJlZyB8PSBOQU5EQ19WNl9GTV9DRV9TRUwoYmFua25yKTsKPiArCX0K PiArCXdyaXRlbChyZWcsIGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjZfRk1DVEwpOwoKTWF5YmUg eW91IGNhbiBzcGFyZSB0aGlzIHdyaXRlbCBieSByZXR1cm5pbmcgZWFybHkgaWYgYmFua25yID09 CmN0cmwtPnNlbGVjdGVkX2JhbmsuCgo+ICsKPiArCWN0cmwtPnNlbGVjdGVkX2JhbmsgPSBiYW5r bnI7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcmtfbmFuZGNfaHdfZWNjX3NldHVwKHN0cnVjdCBu YW5kX2NoaXAgKm5hbmQsCj4gKwkJCQkgdWludDMyX3Qgc3RyZW5ndGgpCj4gK3sKPiArCXN0cnVj dCBya19uYW5kX2NvbnRyb2xsZXIgKmN0cmwgPSBuYW5kX2dldF9jb250cm9sbGVyX2RhdGEobmFu ZCk7Cj4gKwl1aW50MzJfdCByZWc7Cj4gKwo+ICsJbmFuZC0+ZWNjLnN0cmVuZ3RoID0gc3RyZW5n dGg7Cj4gKwluYW5kLT5lY2MuYnl0ZXMgPSBESVZfUk9VTkRfVVAobmFuZC0+ZWNjLnN0cmVuZ3Ro ICogMTQsIDgpOwoKV2hhdCBkbyAxNCBhbmQgOCBtZWFuPwoKPiArCS8qIEhXIEVDQyBvbmx5IHdv cmtzIHdpdGggYW4gZXZlbiBudW1iZXIgb2YgRUNDIGJ5dGVzICovCj4gKwluYW5kLT5lY2MuYnl0 ZXMgPSBBTElHTihuYW5kLT5lY2MuYnl0ZXMsIDIpOwo+ICsKPiArCWlmIChjdHJsLT52ZXJzaW9u ID09IFZFUlNJT05fOSkgewo+ICsJCXN3aXRjaCAobmFuZC0+ZWNjLnN0cmVuZ3RoKSB7Cj4gKwkJ Y2FzZSA3MDoKPiArCQkJcmVnID0gTkFORENfVjlfRUNDXzcwOwo+ICsJCQlicmVhazsKPiArCQlj YXNlIDYwOgo+ICsJCQlyZWcgPSBOQU5EQ19WOV9FQ0NfNjA7Cj4gKwkJCWJyZWFrOwo+ICsJCWNh c2UgNDA6Cj4gKwkJCXJlZyA9IE5BTkRDX1Y5X0VDQ180MDsKPiArCQkJYnJlYWs7Cj4gKwkJY2Fz ZSAxNjoKPiArCQkJcmVnID0gTkFORENfVjlfRUNDXzE2Owo+ICsJCQlicmVhazsKPiArCQlkZWZh dWx0Ogo+ICsJCQlyZXR1cm4gLUVJTlZBTDsKPiArCQl9Cj4gKwkJd3JpdGVsKHJlZywgY3RybC0+ cmVncyArIE5BTkRDX1JFR19WOV9CQ0hDVEwpOwo+ICsJfSBlbHNlIHsKPiArCQlzd2l0Y2ggKG5h bmQtPmVjYy5zdHJlbmd0aCkgewo+ICsJCWNhc2UgNjA6Cj4gKwkJCXJlZyA9IE5BTkRDX1Y2X0VD Q182MDsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSA0MDoKPiArCQkJcmVnID0gTkFORENfVjZfRUND XzQwOwo+ICsJCQlicmVhazsKPiArCQljYXNlIDI0Ogo+ICsJCQlyZWcgPSBOQU5EQ19WNl9FQ0Nf MjQ7Cj4gKwkJCWJyZWFrOwo+ICsJCWNhc2UgMTY6Cj4gKwkJCXJlZyA9IE5BTkRDX1Y2X0VDQ18x NjsKPiArCQkJYnJlYWs7Cj4gKwkJZGVmYXVsdDoKPiArCQkJcmV0dXJuIC1FSU5WQUw7Cj4gKwkJ fQo+ICsJCXdyaXRlbChyZWcsIGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjZfQkNIQ1RMKTsKPiAr CX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgcmtfbmFuZGNfeGZl cl9zdGFydChzdHJ1Y3QgcmtfbmFuZF9jb250cm9sbGVyICpjdHJsLAo+ICsJCQkJdWludDhfdCBk aXIsIHVpbnQ4X3Qgbl9LQiwKPiArCQkJCWRtYV9hZGRyX3QgZG1hX2RhdGEsIGRtYV9hZGRyX3Qg ZG1hX29vYikKPiArewo+ICsJdWludDMyX3QgcmVnOwo+ICsKPiArCWlmIChjdHJsLT52ZXJzaW9u ID09IFZFUlNJT05fOSkgewo+ICsJCXJlZyA9IE5BTkRDX1Y5X0RNQV9DRkdfV1JfU1QgfAo+ICsJ CSAgICAgIE5BTkRDX1Y5X0RNQV9DRkdfV1IoZGlyKSB8Cj4gKwkJICAgICAgTkFORENfVjlfRE1B X0NGR19CVVNfTU9ERSB8Cj4gKwkJICAgICAgTkFORENfVjlfRE1BX0NGR19IU0laRV8zMiB8Cj4g KwkJICAgICAgTkFORENfVjlfRE1BX0NGR19CVVJTVF8xNiB8Cj4gKwkJICAgICAgTkFORENfVjlf RE1BX0NGR19JTkNSX05VTSgxNik7Cj4gKwkJd3JpdGVsKHJlZywgY3RybC0+cmVncyArIE5BTkRD X1JFR19WOV9ETUFfQ0ZHKTsKPiArCQl3cml0ZWwoKHVpbnQzMl90KWRtYV9kYXRhLCBjdHJsLT5y ZWdzICsgTkFORENfUkVHX1Y5X0RNQV9CVUYwKTsKPiArCQl3cml0ZWwoKHVpbnQzMl90KWRtYV9v b2IsIGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjlfRE1BX0JVRjEpOwoKSSdtIHByZXR0eSBzdXJl IG1vc3Qgb2YgdGhlc2Ugd3JpdGVsIGNvdWxkIGJlIHR1cm5lZCBpbnRvCndyaXRlbF9yZWxheGVk LgoKQWxzbyBJIGFtIG5vdCBhIGJpZyBmYW4gb2YgdGhlc2UgY2FzdHMsIG1heWJlIHlvdSBzaG91 bGQgY2hhbmdlCmRtYV9kYXRhIGFuZCBkbWFfb29iIHR5cGVzIChiZSBjYXJlZnVsOiB5b3UgZW5h YmxlZCBDT01QSUxFX1RFU1QgaW4KS2NvbmZpZywgeW91IG11c3Qgc3VwcG9ydCAzMi1iaXQgYW5k IDY0LWJpdCBwb2ludGVycywgcGxlYXNlIHRyeSB0bwpjb21waWxlIHRoaXMgZHJpdmVyIHdpdGgg ZGlmZmVyZW50IHRvb2xjaGFpbnMpLgogCj4gKwo+ICsJCXJlZyA9IE5BTkRDX1Y5X0ZMX0RJUihk aXIpIHwKPiArCQkgICAgICBOQU5EQ19WOV9GTF9YRkVSX0VOIHwKPiArCQkgICAgICBOQU5EQ19W OV9GTF9YRkVSX0NPVU5UIHwKPiArCQkgICAgICBOQU5EQ19WOV9GTF9BQ09SUkVDVCB8Cj4gKwkJ ICAgICAgTkFORENfVjlfRkxfUEFHRV9OVU0obl9LQikgfAo+ICsJCSAgICAgIE5BTkRDX1Y5X0ZM X0FTWU5DX1RPR19NSVg7Cj4gKwkJd3JpdGVsKHJlZywgY3RybC0+cmVncyArIE5BTkRDX1JFR19W OV9GTENUTCk7Cj4gKwkJcmVnIHw9IE5BTkRDX1Y5X0ZMX1hGRVJfU1RBUlQ7Cj4gKwkJd3JpdGVs KHJlZywgY3RybC0+cmVncyArIE5BTkRDX1JFR19WOV9GTENUTCk7Cj4gKwl9IGVsc2Ugewo+ICsJ CXJlZyA9IHJlYWRsKGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjZfQkNIQ1RMKTsKPiArCQlyZWcg PSAocmVnICYgKH4oTkFORF9WNl9CQ0hfUkVHSU9OX00gPDwKPiArCQkJCU5BTkRfVjZfQkNIX1JF R0lPTl9TKSkpIHwKPiArCQkgICAgICAoY3RybC0+c2VsZWN0ZWRfYmFuayA8PCBOQU5EX1Y2X0JD SF9SRUdJT05fUyk7Cj4gKwkJd3JpdGVsKHJlZywgY3RybC0+cmVncyArIE5BTkRDX1JFR19WNl9C Q0hDVEwpOwo+ICsKPiArCQlyZWcgPSBOQU5EQ19WNl9ETUFfQ0ZHX1dSX1NUIHwKPiArCQkgICAg ICBOQU5EQ19WNl9ETUFfQ0ZHX1dSKGRpcikgfAo+ICsJCSAgICAgIE5BTkRDX1Y2X0RNQV9DRkdf QlVTX01PREUgfAo+ICsJCSAgICAgIE5BTkRDX1Y2X0RNQV9DRkdfSFNJWkVfMzIgfAo+ICsJCSAg ICAgIE5BTkRDX1Y2X0RNQV9DRkdfQlVSU1RfMTYgfAo+ICsJCSAgICAgIE5BTkRDX1Y2X0RNQV9D RkdfSU5DUl9OVU0oMTYpOwo+ICsJCXdyaXRlbChyZWcsIGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdf VjZfRE1BX0NGRyk7Cj4gKwkJd3JpdGVsKGRtYV9kYXRhLCBjdHJsLT5yZWdzICsgTkFORENfUkVH X1Y2X0RNQV9CVUYwKTsKPiArCQl3cml0ZWwoZG1hX29vYiwgY3RybC0+cmVncyArIE5BTkRDX1JF R19WNl9ETUFfQlVGMSk7Cj4gKwo+ICsJCXJlZyA9IE5BTkRDX1Y2X0ZMX0RJUihkaXIpIHwKPiAr CQkgICAgICBOQU5EQ19WNl9GTF9YRkVSX0VOIHwKPiArCQkgICAgICBOQU5EQ19WNl9GTF9YRkVS X0NPVU5UIHwKPiArCQkgICAgICBOQU5EQ19WNl9GTF9BQ09SUkVDVCB8Cj4gKwkJICAgICAgTkFO RENfVjZfRkxfUEFHRV9OVU0obl9LQikgfAo+ICsJCSAgICAgIE5BTkRDX1Y2X0ZMX0FTWU5DX1RP R19NSVg7Cj4gKwkJd3JpdGVsKHJlZywgY3RybC0+cmVncyArIE5BTkRDX1JFR19WNl9GTENUTCk7 Cj4gKwkJcmVnIHw9IE5BTkRDX1Y2X0ZMX1hGRVJfU1RBUlQ7Cj4gKwkJd3JpdGVsKHJlZywgY3Ry bC0+cmVncyArIE5BTkRDX1JFR19WNl9GTENUTCk7Cj4gKwl9Cj4gK30KPiArCj4gK3N0YXRpYyBp bnQgcmtfbmFuZGNfd2FpdF9mb3JfeGZlcl9kb25lKHN0cnVjdCBya19uYW5kX2NvbnRyb2xsZXIg KmN0cmwpCj4gK3sKPiArCXVpbnQzMl90IHJlZzsKPiArCWludCByZXQ7Cj4gKwo+ICsJaWYgKGN0 cmwtPnZlcnNpb24gPT0gVkVSU0lPTl85KSB7Cj4gKwkJdm9pZCBfX2lvbWVtICpwdHIgPSBjdHJs LT5yZWdzICsgTkFORENfUkVHX1Y5X0ZMQ1RMOwo+ICsKPiArCQlyZXQgPSByZWFkbF9wb2xsX3Rp bWVvdXRfYXRvbWljKHB0ciwgcmVnLAo+ICsJCQkJCQlyZWcgJiBOQU5EQ19WOV9GTF9YRkVSX1JF QURZLAo+ICsJCQkJCQkxLCBOQU5EQ19ERUZfVElNRU9VVCk7Cj4gKwl9IGVsc2Ugewo+ICsJCXZv aWQgX19pb21lbSAqcHRyID0gY3RybC0+cmVncyArIE5BTkRDX1JFR19WNl9GTENUTDsKPiArCj4g KwkJcmV0ID0gcmVhZGxfcG9sbF90aW1lb3V0X2F0b21pYyhwdHIsIHJlZywKPiArCQkJCQkJcmVn ICYgTkFORENfVjZfRkxfWEZFUl9SRUFEWSwKPiArCQkJCQkJMSwgTkFORENfREVGX1RJTUVPVVQp Owo+ICsJfQoKU3BhY2UKCj4gKwlpZiAocmV0KQo+ICsJCXByX2VycigidGltZW91dCByZWc9JXhc biIsIHJlZyk7Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIHVuc2lnbmVk IGxvbmcgcmtfbmFuZGNfZG1hX21hcF9zaW5nbGUoc3RydWN0IGRldmljZSAqZGV2LAo+ICsJCXZv aWQgKnB0ciwgaW50IHNpemUsIGludCBkaXIpCgpVbmFsaWduZWQgcGFyYW1ldGVycwoKPiArewo+ ICsjaWZkZWYgQ09ORklHX0FSTTY0Cj4gKwlfX2RtYV9tYXBfYXJlYSgodm9pZCAqKXB0ciwgc2l6 ZSwgZGlyKTsKPiArCXJldHVybiAoKHVuc2lnbmVkIGxvbmcpdmlydF90b19waHlzKCh2b2lkICop cHRyKSk7Cj4gKyNlbHNlCj4gKwlyZXR1cm4gZG1hX21hcF9zaW5nbGUoZGV2LCAodm9pZCAqKXB0 ciwgc2l6ZSwgZGlyKTsKPiArI2VuZGlmCgpQbGVhc2UgdHJ5IHRvIHJlbW92ZSB0aGVzZSAjaWZk ZWZzLCBJIGRvbid0IGtub3cgd2h5IHdvdWxkIHlvdSBuZWVkIHRoZQpmb3JtZXIgYmxvY2s/Cgo+ ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBya19uYW5kY19kbWFfdW5tYXBfc2luZ2xlKHN0cnVjdCBk ZXZpY2UgKmRldiwKPiArCQkJCSAgICAgIHVuc2lnbmVkIGxvbmcgcHRyLCBpbnQgc2l6ZSwgaW50 IGRpcikKPiArewo+ICsjaWZkZWYgQ09ORklHX0FSTTY0Cj4gKwlfX2RtYV91bm1hcF9hcmVhKHBo eXNfdG9fdmlydChwdHIpLCBzaXplLCBkaXIpOwo+ICsjZWxzZQo+ICsJZG1hX3VubWFwX3Npbmds ZShkZXYsIChkbWFfYWRkcl90KXB0ciwgc2l6ZSwgZGlyKTsKPiArI2VuZGlmCgpTYW1lCgo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW50IHJrX25hbmRjX2h3X3N5bmRyb21lX2VjY19yZWFkX3BhZ2Uoc3Ry dWN0IG5hbmRfY2hpcCAqbmFuZCwKPiArCQl1aW50OF90ICpidWYsCj4gKwkJaW50IG9vYl9yZXF1 aXJlZCwgaW50IHBhZ2UpCgpVbmFsaWduZWQgcGFyYW1ldGVycyAocGxlYXNlIGNoZWNrIGFsbCBv ZiB0aGVtKS4KCj4gK3sKPiArCXN0cnVjdCBtdGRfaW5mbyAqbXRkID0gbmFuZF90b19tdGQobmFu ZCk7Cj4gKwlzdHJ1Y3QgcmtfbmFuZF9jb250cm9sbGVyICpjdHJsID0gbmFuZF9nZXRfY29udHJv bGxlcl9kYXRhKG5hbmQpOwo+ICsJc3RydWN0IG5hbmRfZWNjX2N0cmwgKmVjYyA9ICZuYW5kLT5l Y2M7Cj4gKwlpbnQgbWF4X2JpdGZsaXBzID0gMDsKPiArCWRtYV9hZGRyX3QgZG1hX2RhdGEsIGRt YV9vb2I7Cj4gKwlpbnQgcmV0LCBpOwo+ICsJaW50IGJjaF9zdDsKPiArCWludCBkbWFfb29iX3Np emUgPSBlY2MtPnN0ZXBzICogMTI4Owo+ICsJaW50IHBhZ2VzX3Blcl9ibGsgPSBtdGQtPmVyYXNl c2l6ZSAvIG10ZC0+d3JpdGVzaXplOwo+ICsKPiArCXJrX25hbmRjX3NlbGVjdF9jaGlwKG5hbmQs IGN0cmwtPnNlbGVjdGVkX2JhbmspOwo+ICsKPiArCWlmICgocGFnZSA8IHBhZ2VzX3Blcl9ibGsg KiBOQU5EQ19JREJSZXNCbGtOdW0pICYmCgpDYW1lbCBjYXNlIGlzIHVzdWFsbHkgbm90IHdlbGNv bWUKCj4gKwkgICAgY3RybC0+Ym9vdHJvbWJsb2NrcykKClRoaXMgd291bGQgcHJvYmFibHkgZGVz ZXJ2ZSBhIGhlbHBlcgoKPiArCQlya19uYW5kY19od19lY2Nfc2V0dXAobmFuZCwgTkFORENfSURC RWNjQml0cyk7Cj4gKwo+ICsJbmFuZF9yZWFkX3BhZ2Vfb3AobmFuZCwgcGFnZSwgMCwgTlVMTCwg MCk7Cj4gKwo+ICsJZG1hX2RhdGEgPSBya19uYW5kY19kbWFfbWFwX3NpbmdsZShtdGQtPmRldi5w YXJlbnQsCj4gKwkJCQkJICAgY3RybC0+cGFnZV9idWYsIG10ZC0+d3JpdGVzaXplLAo+ICsJCQkJ CSAgIERNQV9GUk9NX0RFVklDRSk7Cj4gKwlkbWFfb29iID0gcmtfbmFuZGNfZG1hX21hcF9zaW5n bGUobXRkLT5kZXYucGFyZW50LAo+ICsJCQkJCSAgY3RybC0+b29iX2J1ZiwgZG1hX29vYl9zaXpl LAo+ICsJCQkJCSAgRE1BX0ZST01fREVWSUNFKTsKPiArCj4gKwlpbml0X2NvbXBsZXRpb24oJmN0 cmwtPmNvbXBsZXRlKTsKCk9uZSBpbml0X2NvbXBsZXRpb24gaXMgbmVlZGVkIChpbiB0aGUgcHJv YmUsIHByb2JhYmx5KSB0aGVuIHBsZWFzZSB1c2UKcmVpbml0X2NvbXBsZXRpb24oKS4KCj4gKwlp ZiAoY3RybC0+dmVyc2lvbiA9PSBWRVJTSU9OXzkpCj4gKwkJd3JpdGVsKE5BTkRDX1Y5X0lOVF9E TUEsIGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjlfSU5URU4pOwo+ICsJZWxzZQo+ICsJCXdyaXRl bChOQU5EQ19WNl9JTlRfRE1BLCBjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y2X0lOVEVOKTsKPiAr CXJrX25hbmRjX3hmZXJfc3RhcnQoY3RybCwgMCwgZWNjLT5zdGVwcywgZG1hX2RhdGEsIGRtYV9v b2IpOwo+ICsJd2FpdF9mb3JfY29tcGxldGlvbl90aW1lb3V0KCZjdHJsLT5jb21wbGV0ZSwgbXNl Y3NfdG9famlmZmllcyg1KSk7Cj4gKwlya19uYW5kY193YWl0X2Zvcl94ZmVyX2RvbmUoY3RybCk7 CgpZb3VzIHNob3VsZCBjaGVjayB0aGUgcmV0dXJuIHN0YXR1cyBvZiBhbG1vc3QgYWxsIHRoZSBm dW5jdGlvbnMgaGVyZS4KCj4gKwlya19uYW5kY19kbWFfdW5tYXBfc2luZ2xlKG10ZC0+ZGV2LnBh cmVudCwgZG1hX2RhdGEsIG10ZC0+d3JpdGVzaXplLAo+ICsJCQkJICBETUFfRlJPTV9ERVZJQ0Up Owo+ICsJcmtfbmFuZGNfZG1hX3VubWFwX3NpbmdsZShtdGQtPmRldi5wYXJlbnQsIGRtYV9vb2Is IGRtYV9vb2Jfc2l6ZSwKPiArCQkJCSAgRE1BX0ZST01fREVWSUNFKTsKPiArCj4gKwltZW1jcHko YnVmLCBjdHJsLT5wYWdlX2J1ZiwgbXRkLT53cml0ZXNpemUpOwo+ICsKPiArCWlmIChvb2JfcmVx dWlyZWQpIHsKPiArCQl1aW50OF90ICpvb2I7Cj4gKwkJdWludDMyX3QgdG1wOwoKUGxlYXNlIHVz ZSB1OCwgdTE2IGFuZCB1MzIgdHlwZXMuCgo+ICsKPiArCQlmb3IgKGkgPSAwOyBpIDwgZWNjLT5z dGVwczsgaSsrKSB7Cj4gKwkJCW9vYiA9IG5hbmQtPm9vYl9wb2kgKwo+ICsJCQkgICAgICBpICog KGVjYy0+Ynl0ZXMgKyBuYW5kLT5lY2MucHJlcGFkKTsKPiArCQkJaWYgKGN0cmwtPnZlcnNpb24g PT0gVkVSU0lPTl85KSB7Cj4gKwkJCQl0bXAgPSBjdHJsLT5vb2JfYnVmW2ldOwo+ICsJCQl9IGVs c2Ugewo+ICsJCQkJdWludDhfdCBvb2Jfc3RlcCA9IChjdHJsLT5lY2NfbW9kZSA8PSAyNCkgPwo+ ICsJCQkJCQkgICA2NCA6IDEyODsKPiArCQkJCXRtcCA9IGN0cmwtPm9vYl9idWZbaSAqIG9vYl9z dGVwIC8gNF07Cj4gKwkJCX0KPiArCQkJKm9vYisrID0gKHVpbnQ4X3QpdG1wOwo+ICsJCQkqb29i KysgPSAodWludDhfdCkodG1wID4+IDgpOwo+ICsJCQkqb29iKysgPSAodWludDhfdCkodG1wID4+ IDE2KTsKPiArCQkJKm9vYisrID0gKHVpbnQ4X3QpKHRtcCA+PiAyNCk7Cj4gKwkJfQo+ICsJfQo+ ICsKPiArCWlmIChjdHJsLT52ZXJzaW9uID09IFZFUlNJT05fOSkgewo+ICsJCWZvciAoaSA9IDA7 IGkgPCBlY2MtPnN0ZXBzIC8gMjsgaSsrKSB7Cj4gKwkJCWJjaF9zdCA9IHJlYWRsKGN0cmwtPnJl Z3MgKyBOQU5EQ19SRUdfVjlfQkNIU1QgKyBpICogNCk7Cj4gKwkJCWlmIChiY2hfc3QgJiBOQU5E Q19WOV9CQ0gwX1NUX0VSUiB8fAo+ICsJCQkgICAgYmNoX3N0ICYgTkFORENfVjlfQkNIMV9TVF9F UlIpIHsKPiArCQkJCW10ZC0+ZWNjX3N0YXRzLmZhaWxlZCsrOwo+ICsJCQkJbWF4X2JpdGZsaXBz ID0gLTE7Cj4gKwkJCX0gZWxzZSB7Cj4gKwkJCQlyZXQgPSBOQU5EQ19WOV9FQ0NfRVJSX0NOVDAo YmNoX3N0KTsKPiArCQkJCW10ZC0+ZWNjX3N0YXRzLmNvcnJlY3RlZCArPSByZXQ7Cj4gKwkJCQlt YXhfYml0ZmxpcHMgPSBtYXhfdCh1bnNpZ25lZCBpbnQsCj4gKwkJCQkJCSAgICAgbWF4X2JpdGZs aXBzLCByZXQpOwo+ICsKPiArCQkJCXJldCA9IE5BTkRDX1Y5X0VDQ19FUlJfQ05UMShiY2hfc3Qp Owo+ICsJCQkJbXRkLT5lY2Nfc3RhdHMuY29ycmVjdGVkICs9IHJldDsKPiArCQkJCW1heF9iaXRm bGlwcyA9IG1heF90KHVuc2lnbmVkIGludCwKPiArCQkJCQkJICAgICBtYXhfYml0ZmxpcHMsIHJl dCk7Cj4gKwkJCX0KPiArCQl9Cj4gKwl9IGVsc2Ugewo+ICsJCWZvciAoaSA9IDA7IGkgPCBlY2Mt PnN0ZXBzIC8gMjsgaSsrKSB7Cj4gKwkJCWJjaF9zdCA9IHJlYWRsKGN0cmwtPnJlZ3MgKyBOQU5E Q19SRUdfVjZfQkNIU1QgKyBpICogNCk7Cj4gKwkJCWlmIChiY2hfc3QgJiBOQU5EQ19WNl9CQ0gw X1NUX0VSUiB8fAo+ICsJCQkgICAgYmNoX3N0ICYgTkFORENfVjZfQkNIMV9TVF9FUlIpIHsKPiAr CQkJCW10ZC0+ZWNjX3N0YXRzLmZhaWxlZCsrOwo+ICsJCQkJbWF4X2JpdGZsaXBzID0gLTE7CgpX aHkgbm90IHVzaW5nIHJldCA9ICQocmVhbCBlcnJvcikgaW5zdGVhZCBvZiB1c2luZyBtYXhfYml0 ZmxpcHMgaGVyZT8KClRoZW46CgoJaWYgKHJldCkgewoJCWRldl9lcnIoKTsKCQlyZXR1cm4gcmV0 OwoJfQoKCXJldHVybiBtYXhfYml0ZmxpcHM7Cgo+ICsJCQl9IGVsc2Ugewo+ICsJCQkJcmV0ID0g TkFORENfVjZfRUNDX0VSUl9DTlQwKGJjaF9zdCk7Cj4gKwkJCQltdGQtPmVjY19zdGF0cy5jb3Jy ZWN0ZWQgKz0gcmV0Owo+ICsJCQkJbWF4X2JpdGZsaXBzID0gbWF4X3QodW5zaWduZWQgaW50LAo+ ICsJCQkJCQkgICAgIG1heF9iaXRmbGlwcywgcmV0KTsKPiArCj4gKwkJCQlyZXQgPSBOQU5EQ19W Nl9FQ0NfRVJSX0NOVDEoYmNoX3N0KTsKPiArCQkJCW10ZC0+ZWNjX3N0YXRzLmNvcnJlY3RlZCAr PSByZXQ7Cj4gKwkJCQltYXhfYml0ZmxpcHMgPSBtYXhfdCh1bnNpZ25lZCBpbnQsCj4gKwkJCQkJ CSAgICAgbWF4X2JpdGZsaXBzLCByZXQpOwo+ICsJCQl9Cj4gKwkJfQo+ICsJfQo+ICsKPiArCWlm IChtYXhfYml0ZmxpcHMgPT0gLTEpIHsKPiArCQlkZXZfZXJyKG10ZC0+ZGV2LnBhcmVudCwKPiAr CQkJInJlYWRfcGFnZSAleCAleCAleCAleCAleCAlcCAleFxuIiwKPiArCQkJcGFnZSwKPiArCQkJ bWF4X2JpdGZsaXBzLAo+ICsJCQliY2hfc3QsCj4gKwkJCSgodWludDMyX3QgKilidWYpWzBdLAo+ ICsJCQkoKHVpbnQzMl90ICopYnVmKVsxXSwKPiArCQkJYnVmLAo+ICsJCQkodWludDMyX3QpZG1h X2RhdGEpOwoKVGhpcyBpcyBub3QgdmVyeSBpbmZvcm1hdGl2ZSwgcGxlYXNlIHdyaXRlIGEgcmVh bCBlcnJvciBtZXNzYWdlLiBBdm9pZApwdXR0aW5nIHRvbyBtdWNoIGRlYnVnIGluZm9ybWF0aW9u LCBwZW9wbGUgd2lsbCB0cm91Ymxlc2hvb3QgdGhlbXNlbHZlcwppZiBuZWVkZWQuCgo+ICsJfQo+ ICsKPiArCWlmIChjdHJsLT5ib290cm9tYmxvY2tzKQo+ICsJCXJrX25hbmRjX2h3X2VjY19zZXR1 cChuYW5kLCBjdHJsLT5lY2NfbW9kZSk7Cj4gKwoKWW91IGRvbid0IHVzZSB0aGUgc2FtZSBjb25k aXRpb24gYXMgYWJvdmUuIFdoeSA/IE1heWJlIHRoZSBoZWxwZXIgd291bGQKaGVscC4KCj4gKwly ZXR1cm4gbWF4X2JpdGZsaXBzOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHJrX25hbmRjX2h3X3N5 bmRyb21lX2VjY193cml0ZV9wYWdlKHN0cnVjdCBuYW5kX2NoaXAgKm5hbmQsCj4gKwkJY29uc3Qg dWludDhfdCAqYnVmLAo+ICsJCWludCBvb2JfcmVxdWlyZWQsCj4gKwkJaW50IHBhZ2UpCj4gK3sK PiArCXN0cnVjdCBtdGRfaW5mbyAqbXRkID0gbmFuZF90b19tdGQobmFuZCk7Cj4gKwlzdHJ1Y3Qg cmtfbmFuZF9jb250cm9sbGVyICpjdHJsID0gbmFuZF9nZXRfY29udHJvbGxlcl9kYXRhKG5hbmQp Owo+ICsJc3RydWN0IG5hbmRfZWNjX2N0cmwgKmVjYyA9ICZuYW5kLT5lY2M7Cj4gKwlkbWFfYWRk cl90IGRtYV9kYXRhLCBkbWFfb29iOwo+ICsJaW50IGk7Cj4gKwlpbnQgZG1hX29vYl9zaXplID0g ZWNjLT5zdGVwcyAqIDEyODsKPiArCWludCBwYWdlc19wZXJfYmxrID0gbXRkLT5lcmFzZXNpemUg LyBtdGQtPndyaXRlc2l6ZTsKPiArCj4gKwlya19uYW5kY19zZWxlY3RfY2hpcChuYW5kLCBjdHJs LT5zZWxlY3RlZF9iYW5rKTsKPiArCj4gKwlpZiAoKHBhZ2UgPCBwYWdlc19wZXJfYmxrICogTkFO RENfSURCUmVzQmxrTnVtKSAmJgo+ICsJICAgIGN0cmwtPmJvb3Ryb21ibG9ja3MpCj4gKwkJcmtf bmFuZGNfaHdfZWNjX3NldHVwKG5hbmQsIE5BTkRDX0lEQkVjY0JpdHMpOwo+ICsKPiArCW5hbmRf cHJvZ19wYWdlX2JlZ2luX29wKG5hbmQsIHBhZ2UsIDAsIE5VTEwsIDApOwo+ICsKPiArCWZvciAo aSA9IDA7IGkgPCBlY2MtPnN0ZXBzOyBpKyspIHsKPiArCQl1aW50MzJfdCB0bXA7Cj4gKwo+ICsJ CWlmIChvb2JfcmVxdWlyZWQpIHsKPiArCQkJdWludDhfdCAqb29iOwo+ICsKPiArCQkJb29iID0g bmFuZC0+b29iX3BvaSArCj4gKwkJCSAgICAgIGkgKiAoZWNjLT5ieXRlcyArIG5hbmQtPmVjYy5w cmVwYWQpOwo+ICsJCQl0bXAgPSBvb2JbMF0gfAo+ICsJCQkgICAgICAob29iWzFdIDw8IDgpIHwK PiArCQkJICAgICAgKG9vYlsyXSA8PCAxNikgfAo+ICsJCQkgICAgICAob29iWzNdIDw8IDI0KTsK PiArCQl9IGVsc2Ugewo+ICsJCQkvKiBUaGUgZmlyc3QgTkFORENfSURCUmVzQmxrTnVtIGJsb2Nr cyBhcmUKPiArCQkJICogZm9yIHRoZSBzdG9yZWQgbG9hZGVyLiBUaGUgZmlyc3QgMzIgYml0cwo+ ICsJCQkgKiBvZiBvb2IgbXVzdCBjb250YWluIGEgc29ydCBvZiBsaW5rIHRvCj4gKwkJCSAqIHRo ZSBuZXh0IHBhZ2UgYWRkcmVzcyBpbiB0aGF0IHNhbWUgYmxvY2sKPiArCQkJICogZm9yIHRoZSBC b290cm9tLgo+ICsJCQkgKiBEZXBlbmRpbmcgb24gd2hhdCBGVEwgZnJvbSBSb2NrY2hpcCBpcyB1 c2VkLAo+ICsJCQkgKiB0aGUgZmlyc3QgMiBwYWdlcyBpbiB0aGUgTkFORENfSURCUmVzQmxrTnVt IGJsb2Nrcwo+ICsJCQkgKiBhcmUgcmVzZXJ2ZWQgZm9yIEZsYXNoUGh5SW5mby4KPiArCQkJICog UmF3IElEQiBkYXRhIHRoZW4gc3RhcnRzIGF0IHBhZ2UgMiBvciBoaWdoZXIuCgpJIHdvdWxkIHNl cGFyYXRlIHRoZSBmdW5jdGlvbiB0byByZWFkL3dyaXRlIHRoZSBsb2FkZXIgdGhhbiB0aGUgdXN1 YWwKcmVhZC93cml0ZSBoZWxwZXJzIHRvIGF2b2lkIGFueSBjb25mdXNpb24gb24gd2h5IHlvdSBk byB0aGVzZSB0cmlja3MuCgpNYXliZSBub3QgdGhlIHdob2xlIGZ1bmN0aW9uLCBidXQgYXQgbGVh c3QgdGhlIGRhdGEvb29iIHBsYWNlbWVudD8KKFRoaXMgaXMgcmVhbGx5IGEgc3VnZ2VzdGlvbikK Cj4gKwkJCSAqLwo+ICsJCQlpZiAoIWkgJiYKPiArCQkJICAgIHBhZ2UgPCBwYWdlc19wZXJfYmxr ICogTkFORENfSURCUmVzQmxrTnVtICYmCj4gKwkJCSAgICBwYWdlID49IE5BTkRDX0lEQlN0YXJ0 QWRkcikKPiArCQkJCXRtcCA9IChwYWdlICYgKHBhZ2VzX3Blcl9ibGsgLSAxKSkgKiA0Owo+ICsJ CQllbHNlCj4gKwkJCQl0bXAgPSAweEZGRkZGRkZGOwo+ICsJCX0KPiArCQlpZiAoY3RybC0+dmVy c2lvbiA9PSBWRVJTSU9OXzkpIHsKPiArCQkJY3RybC0+b29iX2J1ZltpXSA9IHRtcDsKPiArCQl9 IGVsc2Ugewo+ICsJCQl1aW50OF90IG9vYl9zdGVwID0gKGN0cmwtPmVjY19tb2RlIDw9IDI0KSA/ Cj4gKwkJCQkJICAgNjQgOiAxMjg7Cj4gKwkJCWN0cmwtPm9vYl9idWZbaSAqIG9vYl9zdGVwIC8g NF0gPSB0bXA7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCW1lbWNweShjdHJsLT5wYWdlX2J1ZiwgYnVm LCBtdGQtPndyaXRlc2l6ZSk7Cj4gKwlkbWFfZGF0YSA9IHJrX25hbmRjX2RtYV9tYXBfc2luZ2xl KG10ZC0+ZGV2LnBhcmVudCwKPiArCQkJCQkgICBjdHJsLT5wYWdlX2J1ZiwgbXRkLT53cml0ZXNp emUsCj4gKwkJCQkJICAgRE1BX1RPX0RFVklDRSk7Cj4gKwlkbWFfb29iID0gcmtfbmFuZGNfZG1h X21hcF9zaW5nbGUobXRkLT5kZXYucGFyZW50LAo+ICsJCQkJCSAgY3RybC0+b29iX2J1ZiwgZG1h X29vYl9zaXplLAo+ICsJCQkJCSAgRE1BX1RPX0RFVklDRSk7Cj4gKwlpbml0X2NvbXBsZXRpb24o JmN0cmwtPmNvbXBsZXRlKTsKPiArCWlmIChjdHJsLT52ZXJzaW9uID09IFZFUlNJT05fOSkKPiAr CQl3cml0ZWwoTkFORENfVjlfSU5UX0RNQSwgY3RybC0+cmVncyArIE5BTkRDX1JFR19WOV9JTlRF Tik7Cj4gKwllbHNlCj4gKwkJd3JpdGVsKE5BTkRDX1Y2X0lOVF9ETUEsIGN0cmwtPnJlZ3MgKyBO QU5EQ19SRUdfVjZfSU5URU4pOwo+ICsJcmtfbmFuZGNfeGZlcl9zdGFydChjdHJsLCAxLCBlY2Mt PnN0ZXBzLCBkbWFfZGF0YSwgZG1hX29vYik7Cj4gKwl3YWl0X2Zvcl9jb21wbGV0aW9uX3RpbWVv dXQoJmN0cmwtPmNvbXBsZXRlLCBtc2Vjc190b19qaWZmaWVzKDEwKSk7Cj4gKwlya19uYW5kY193 YWl0X2Zvcl94ZmVyX2RvbmUoY3RybCk7Cj4gKwlya19uYW5kY19kbWFfdW5tYXBfc2luZ2xlKG10 ZC0+ZGV2LnBhcmVudCwgZG1hX2RhdGEsIG10ZC0+d3JpdGVzaXplLAo+ICsJCQkJICBETUFfVE9f REVWSUNFKTsKPiArCXJrX25hbmRjX2RtYV91bm1hcF9zaW5nbGUobXRkLT5kZXYucGFyZW50LCBk bWFfb29iLCBkbWFfb29iX3NpemUsCj4gKwkJCQkgIERNQV9UT19ERVZJQ0UpOwo+ICsKPiArCWlm IChjdHJsLT5ib290cm9tYmxvY2tzKQo+ICsJCXJrX25hbmRjX2h3X2VjY19zZXR1cChuYW5kLCBj dHJsLT5lY2NfbW9kZSk7Cj4gKwo+ICsJcmV0dXJuIG5hbmRfcHJvZ19wYWdlX2VuZF9vcChuYW5k KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBya19uYW5kY19od19lY2NfcmVhZF9vb2Ioc3RydWN0 IG5hbmRfY2hpcCAqbmFuZCwgaW50IHBhZ2UpCj4gK3sKPiArCXVpbnQ4X3QgKmJ1ZiA9IG5hbmRf Z2V0X2RhdGFfYnVmKG5hbmQpOwo+ICsKPiArCXJldHVybiBuYW5kLT5lY2MucmVhZF9wYWdlKG5h bmQsIGJ1ZiwgdHJ1ZSwgcGFnZSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcmtfbmFuZGNfaHdf ZWNjX3dyaXRlX29vYihzdHJ1Y3QgbmFuZF9jaGlwICpuYW5kLCBpbnQgcGFnZSkKPiArewo+ICsJ c3RydWN0IG10ZF9pbmZvICptdGQgPSBuYW5kX3RvX210ZChuYW5kKTsKPiArCWludCByZXQ7Cj4g Kwl1aW50OF90ICpidWYgPSBuYW5kX2dldF9kYXRhX2J1ZihuYW5kKTsKPiArCj4gKwltZW1zZXQo YnVmLCAweEZGLCBtdGQtPndyaXRlc2l6ZSk7Cj4gKwlyZXQgPSBuYW5kLT5lY2Mud3JpdGVfcGFn ZShuYW5kLCBidWYsIHRydWUsIHBhZ2UpOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1cm4gcmV0Owo+ ICsKPiArCXJldHVybiBuYW5kX3Byb2dfcGFnZV9lbmRfb3AobmFuZCk7Cj4gK30KPiArCj4gK3N0 YXRpYyB2b2lkIHJrX25hbmRjX3JlYWRfYnVmKHN0cnVjdCBuYW5kX2NoaXAgKm5hbmQsIHVpbnQ4 X3QgKmJ1ZiwgaW50IGxlbikKPiArewo+ICsJc3RydWN0IHJrX25hbmRfY29udHJvbGxlciAqY3Ry bCA9IG5hbmRfZ2V0X2NvbnRyb2xsZXJfZGF0YShuYW5kKTsKPiArCWludCBvZmZzID0gMDsKPiAr CXZvaWQgX19pb21lbSAqYmFua19iYXNlID0gY3RybC0+cmVncyArIE5BTkRDX1JFR19CQU5LMCAr Cj4gKwkJCQkgIGN0cmwtPnNlbGVjdGVkX2JhbmsgKiAweDEwMDsKCjB4MTAwOiBNYXliZSBhIGRl ZmluZQoKPiArCj4gKwlmb3IgKG9mZnMgPSAwOyBvZmZzIDwgbGVuOyBvZmZzKyspCj4gKwkJYnVm W29mZnNdID0gcmVhZGIoYmFua19iYXNlKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgcmtfbmFu ZGNfd3JpdGVfYnVmKHN0cnVjdCBuYW5kX2NoaXAgKm5hbmQsCj4gKwkJCSAgICAgICBjb25zdCB1 aW50OF90ICpidWYsIGludCBsZW4pCj4gK3sKPiArCXN0cnVjdCBya19uYW5kX2NvbnRyb2xsZXIg KmN0cmwgPSBuYW5kX2dldF9jb250cm9sbGVyX2RhdGEobmFuZCk7Cj4gKwlpbnQgb2ZmcyA9IDA7 Cj4gKwl2b2lkIF9faW9tZW0gKmJhbmtfYmFzZSA9IGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfQkFO SzAgKwo+ICsJCQkJICBjdHJsLT5zZWxlY3RlZF9iYW5rICogMHgxMDA7Cj4gKwo+ICsJZm9yIChv ZmZzID0gMDsgb2ZmcyA8IGxlbjsgb2ZmcysrKQo+ICsJCXdyaXRlYihidWZbb2Zmc10sIGJhbmtf YmFzZSk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHJrX25hbmRjX3dyaXRlX2NtZChzdHJ1Y3Qg bmFuZF9jaGlwICpuYW5kLCB1aW50OF90IGNtZCkKPiArewo+ICsJc3RydWN0IHJrX25hbmRfY29u dHJvbGxlciAqY3RybCA9IG5hbmRfZ2V0X2NvbnRyb2xsZXJfZGF0YShuYW5kKTsKPiArCj4gKwl2 b2lkIF9faW9tZW0gKmJhbmtfYmFzZSA9IGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfQkFOSzAgKwo+ ICsJCQkJICBjdHJsLT5zZWxlY3RlZF9iYW5rICogMHgxMDAgKwo+ICsJCQkJICBOQU5EQ19SRUdf Q01EOwoKWW91IG1pZ2h0IHdhbnQgdG8gd3JpdGUgYW4gaGVscGVyIHRvIGNhbGN1bGF0ZSBiYW5r X2Jhc2UsIHRvIGF2b2lkCnJlcGVhdGluZyB0aGVzZSBsaW5lcy4KCj4gKwo+ICsJd3JpdGViKGNt ZCwgYmFua19iYXNlKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgcmtfbmFuZGNfd3JpdGVfYWRk cihzdHJ1Y3QgbmFuZF9jaGlwICpuYW5kLCB1aW50OF90IGFkZHIpCj4gK3sKPiArCXN0cnVjdCBy a19uYW5kX2NvbnRyb2xsZXIgKmN0cmwgPSBuYW5kX2dldF9jb250cm9sbGVyX2RhdGEobmFuZCk7 Cj4gKwo+ICsJdm9pZCBfX2lvbWVtICpiYW5rX2Jhc2UgPSBjdHJsLT5yZWdzICsgTkFORENfUkVH X0JBTkswICsKPiArCQkJCSAgY3RybC0+c2VsZWN0ZWRfYmFuayAqIDB4MTAwICsKPiArCQkJCSAg TkFORENfUkVHX0FERFI7Cj4gKwo+ICsJd3JpdGViKGFkZHIsIGJhbmtfYmFzZSk7Cj4gK30KPiAr Cj4gK3N0YXRpYyBpbnQgcmtfbmFuZGNfZGV2X3JlYWR5KHN0cnVjdCBuYW5kX2NoaXAgKm5hbmQp Cj4gK3sKPiArCXN0cnVjdCBya19uYW5kX2NvbnRyb2xsZXIgKmN0cmwgPSBuYW5kX2dldF9jb250 cm9sbGVyX2RhdGEobmFuZCk7Cj4gKwo+ICsJaWYgKHJlYWRsKGN0cmwtPnJlZ3MgKyBOQU5EQ19S RUdfVjZfRk1DVEwpICYgTkFORENfVjZfRk1fRlJFQURZKQo+ICsJCXJldHVybiAxOwo+ICsKPiAr CXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHJrX25hbmRjX29vYmxheW91dF9lY2Mo c3RydWN0IG10ZF9pbmZvICptdGQsIGludCBzZWN0aW9uLAo+ICsJCQkJICBzdHJ1Y3QgbXRkX29v Yl9yZWdpb24gKm9vYnJlZ2lvbikKPiArewo+ICsJc3RydWN0IG5hbmRfY2hpcCAqbmFuZCA9IG10 ZF90b19uYW5kKG10ZCk7Cj4gKwo+ICsJaWYgKHNlY3Rpb24gPj0gbmFuZC0+ZWNjLnN0ZXBzKQo+ ICsJCXJldHVybiAtRVJBTkdFOwo+ICsKPiArCW9vYnJlZ2lvbi0+b2Zmc2V0ID0gKG5hbmQtPmVj Yy5ieXRlcyArIG5hbmQtPmVjYy5wcmVwYWQpICogc2VjdGlvbiArCj4gKwkJCSAgICBuYW5kLT5l Y2MucHJlcGFkOwo+ICsJb29icmVnaW9uLT5sZW5ndGggPSBuYW5kLT5lY2Muc3RlcHMgKiBuYW5k LT5lY2MuYnl0ZXM7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcmtf bmFuZGNfb29ibGF5b3V0X2ZyZWUoc3RydWN0IG10ZF9pbmZvICptdGQsIGludCBzZWN0aW9uLAo+ ICsJCQkJICAgc3RydWN0IG10ZF9vb2JfcmVnaW9uICpvb2JyZWdpb24pCj4gK3sKPiArCXN0cnVj dCBuYW5kX2NoaXAgKm5hbmQgPSBtdGRfdG9fbmFuZChtdGQpOwo+ICsKPiArCWlmIChzZWN0aW9u ID49IG5hbmQtPmVjYy5zdGVwcykKPiArCQlyZXR1cm4gLUVSQU5HRTsKPiArCj4gKwlvb2JyZWdp b24tPm9mZnNldCA9IChuYW5kLT5lY2MuYnl0ZXMgKyBuYW5kLT5lY2MucHJlcGFkKSAqIHNlY3Rp b247Cj4gKwlvb2JyZWdpb24tPmxlbmd0aCA9IG5hbmQtPmVjYy5zdGVwcyAqIG5hbmQtPmVjYy5w cmVwYWQ7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qg bXRkX29vYmxheW91dF9vcHMgcmtfbmFuZGNfb29iX29wcyA9IHsKPiArCS5lY2MgPSBya19uYW5k Y19vb2JsYXlvdXRfZWNjLAo+ICsJLmZyZWUgPSBya19uYW5kY19vb2JsYXlvdXRfZnJlZSwKPiAr fTsKPiArCj4gK3N0YXRpYyB2b2lkIHJrX25hbmRjX2ZyZWVfYnVmZmVyKHN0cnVjdCBuYW5kX2No aXAgKm5hbmQpCj4gK3sKPiArCXN0cnVjdCBya19uYW5kX2NvbnRyb2xsZXIgKmN0cmwgPSBuYW5k X2dldF9jb250cm9sbGVyX2RhdGEobmFuZCk7Cj4gKwo+ICsJa2ZyZWUoY3RybC0+cGFnZV9idWYp Owo+ICsJa2ZyZWUoY3RybC0+b29iX2J1Zik7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcmtfbmFu ZGNfYnVmZmVyX2luaXQoc3RydWN0IG5hbmRfY2hpcCAqbmFuZCkKPiArewo+ICsJc3RydWN0IG10 ZF9pbmZvICptdGQgPSBuYW5kX3RvX210ZChuYW5kKTsKPiArCXN0cnVjdCBya19uYW5kX2NvbnRy b2xsZXIgKmN0cmwgPSBuYW5kX2dldF9jb250cm9sbGVyX2RhdGEobmFuZCk7Cj4gKwo+ICsJY3Ry bC0+cGFnZV9idWYgPSBrbWFsbG9jKG10ZC0+d3JpdGVzaXplLCBHRlBfS0VSTkVMIHwgR0ZQX0RN QSk7CgpkZXZpY2UgbWFuYWdlZCBhbGxvY2F0aW9ucyAoZGV2bV8uLi4pIHdvdWxkIGJlIG5pY2UK Cj4gKwlpZiAoIWN0cmwtPnBhZ2VfYnVmKQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCWN0 cmwtPm9vYl9idWYgPSBrbWFsbG9jKG5hbmQtPmVjYy5zdGVwcyAqIDEyOCwgR0ZQX0tFUk5FTCB8 IEdGUF9ETUEpOwo+ICsJaWYgKCFjdHJsLT5vb2JfYnVmKSB7Cj4gKwkJa2ZyZWUoY3RybC0+cGFn ZV9idWYpOwo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW50IHJrX25hbmRjX2h3X2VjY19jdHJsX2luaXQoc3RydWN0IG5hbmRf Y2hpcCAqbmFuZCkKPiArewo+ICsJdWludDhfdCBzdHJlbmd0aHNfdjZbXSA9IHs2MCwgNDAsIDI0 LCAxNn07Cj4gKwl1aW50OF90IHN0cmVuZ3Roc192OVtdID0gezcwLCA2MCwgNDAsIDE2fTsKPiAr CXN0cnVjdCBtdGRfaW5mbyAqbXRkID0gbmFuZF90b19tdGQobmFuZCk7Cj4gKwlzdHJ1Y3Qgcmtf bmFuZF9jb250cm9sbGVyICpjdHJsID0gbmFuZF9nZXRfY29udHJvbGxlcl9kYXRhKG5hbmQpOwo+ ICsJaW50IG1heF9zdHJlbmd0aDsKPiArCXVpbnQzMl90IGksIHZlcjsKPiArCj4gKwlpZiAobmFu ZC0+b3B0aW9ucyAmIE5BTkRfSVNfQk9PVF9NRURJVU0pCj4gKwkJY3RybC0+Ym9vdHJvbWJsb2Nr cyA9IHRydWU7Cj4gKwllbHNlCj4gKwkJY3RybC0+Ym9vdHJvbWJsb2NrcyA9IGZhbHNlOwo+ICsK PiArCW5hbmQtPmVjYy5wcmVwYWQgPSA0Owo+ICsJbmFuZC0+ZWNjLnN0ZXBzID0gbXRkLT53cml0 ZXNpemUgLyBuYW5kLT5lY2Muc2l6ZTsKPiArCj4gKwltYXhfc3RyZW5ndGggPSAoKG10ZC0+b29i c2l6ZSAvIG5hbmQtPmVjYy5zdGVwcykgLSA0KSAqIDggLyAxNDsKPiArCWlmIChjdHJsLT52ZXJz aW9uID09IFZFUlNJT05fOSkgewo+ICsJCWN0cmwtPm1heF9lY2Nfc3RyZW5ndGggPSA3MDsKPiAr CQl2ZXIgPSByZWFkbChjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y5X1ZFUik7Cj4gKwkJaWYgKHZl ciAhPSBOQU5EQ19JRF9WOTAwKQo+ICsJCQlkZXZfZXJyKG10ZC0+ZGV2LnBhcmVudCwKPiArCQkJ CSJ1bnN1cHBvcnRlZCBuYW5kYyB2ZXJzaW9uICV4XG4iLCB2ZXIpOwo+ICsKPiArCQlpZiAobWF4 X3N0cmVuZ3RoID4gY3RybC0+bWF4X2VjY19zdHJlbmd0aCkKPiArCQkJbWF4X3N0cmVuZ3RoID0g Y3RybC0+bWF4X2VjY19zdHJlbmd0aDsKPiArCj4gKwkJZm9yIChpID0gMDsgaSA8IEFSUkFZX1NJ WkUoc3RyZW5ndGhzX3Y5KTsgaSsrKSB7Cj4gKwkJCWlmIChtYXhfc3RyZW5ndGggPj0gc3RyZW5n dGhzX3Y5W2ldKQo+ICsJCQkJYnJlYWs7Cj4gKwkJfQo+ICsKPiArCQlpZiAoaSA+PSBBUlJBWV9T SVpFKHN0cmVuZ3Roc192OSkpIHsKPiArCQkJZGV2X2VycihtdGQtPmRldi5wYXJlbnQsCj4gKwkJ CQkidW5zdXBwb3J0ZWQgc3RyZW5ndGhcbiIpOwo+ICsJCQlyZXR1cm4gLUVOT1RTVVBQOwo+ICsJ CX0KPiArCj4gKwkJY3RybC0+ZWNjX21vZGUgPSBzdHJlbmd0aHNfdjlbaV07Cj4gKwl9IGVsc2Ug ewo+ICsJCWN0cmwtPm1heF9lY2Nfc3RyZW5ndGggPSA2MDsKPiArCj4gKwkJdmVyID0gcmVhZGwo Y3RybC0+cmVncyArIE5BTkRDX1JFR19WNl9WRVIpOwo+ICsJCWlmICh2ZXIgPT0gTkFORENfSURf VjgwMSkKPiArCQkJY3RybC0+bWF4X2VjY19zdHJlbmd0aCA9IDE2Owo+ICsJCWVsc2UgaWYgKHZl ciA9PSBOQU5EQ19JRF9WNjAwIHx8Cj4gKwkJCSB2ZXIgPT0gTkFORENfSURfVjYyMiB8fAo+ICsJ CQkgdmVyID09IE5BTkRDX0lEX1Y3MDEgfHwKPiArCQkJIHZlciA9PSBOQU5EQ19JRF9WODAwKQo+ ICsJCQljdHJsLT5tYXhfZWNjX3N0cmVuZ3RoID0gNjA7Cj4gKwkJZWxzZQo+ICsJCQlkZXZfZXJy KG10ZC0+ZGV2LnBhcmVudCwKPiArCQkJCSJ1bnN1cHBvcnRlZCBuYW5kYyB2ZXJzaW9uICV4XG4i LCB2ZXIpOwo+ICsKPiArCQlpZiAobWF4X3N0cmVuZ3RoID4gY3RybC0+bWF4X2VjY19zdHJlbmd0 aCkKPiArCQkJbWF4X3N0cmVuZ3RoID0gY3RybC0+bWF4X2VjY19zdHJlbmd0aDsKPiArCj4gKwkJ Zm9yIChpID0gMDsgaSA8IEFSUkFZX1NJWkUoc3RyZW5ndGhzX3Y2KTsgaSsrKSB7Cj4gKwkJCWlm IChtYXhfc3RyZW5ndGggPj0gc3RyZW5ndGhzX3Y2W2ldKQo+ICsJCQkJYnJlYWs7Cj4gKwkJfQo+ ICsKPiArCQlpZiAoaSA+PSBBUlJBWV9TSVpFKHN0cmVuZ3Roc192NikpIHsKPiArCQkJZGV2X2Vy cihtdGQtPmRldi5wYXJlbnQsCj4gKwkJCQkidW5zdXBwb3J0ZWQgc3RyZW5ndGhcbiIpOwo+ICsJ CQlyZXR1cm4gLUVOT1RTVVBQOwo+ICsJCX0KPiArCj4gKwkJY3RybC0+ZWNjX21vZGUgPSBzdHJl bmd0aHNfdjZbaV07Cj4gKwl9Cj4gKwlya19uYW5kY19od19lY2Nfc2V0dXAobmFuZCwgY3RybC0+ ZWNjX21vZGUpOwo+ICsKPiArCW10ZF9zZXRfb29ibGF5b3V0KG10ZCwgJnJrX25hbmRjX29vYl9v cHMpOwo+ICsKPiArCWlmIChtdGQtPm9vYnNpemUgPCAoKG5hbmQtPmVjYy5ieXRlcyArIG5hbmQt PmVjYy5wcmVwYWQpICoKPiArCQkJICAgIG5hbmQtPmVjYy5zdGVwcykpIHsKPiArCQlyZXR1cm4g LUVJTlZBTDsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQg cmtfbmFuZGNfZGV0YWNoX2NoaXAoc3RydWN0IG5hbmRfY2hpcCAqbmFuZCkKPiArewo+ICsJc3dp dGNoIChuYW5kLT5lY2MubW9kZSkgewo+ICsJY2FzZSBOQU5EX0VDQ19IV19TWU5EUk9NRToKPiAr CQlya19uYW5kY19mcmVlX2J1ZmZlcihuYW5kKTsKPiArCQlicmVhazsKPiArCWRlZmF1bHQ6Cj4g KwkJYnJlYWs7Cj4gKwl9Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcmtfbmFuZGNfYXR0YWNoX2No aXAoc3RydWN0IG5hbmRfY2hpcCAqbmFuZCkKPiArewo+ICsJc3RydWN0IG10ZF9pbmZvICptdGQg PSBuYW5kX3RvX210ZChuYW5kKTsKPiArCWludCByZXQ7Cj4gKwo+ICsJc3dpdGNoIChuYW5kLT5l Y2MubW9kZSkgewo+ICsJY2FzZSBOQU5EX0VDQ19IV19TWU5EUk9NRToKPiArCQlyZXQgPSBya19u YW5kY19od19lY2NfY3RybF9pbml0KG5hbmQpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJldHVybiBy ZXQ7Cj4gKwkJcmV0ID0gcmtfbmFuZGNfYnVmZmVyX2luaXQobmFuZCk7Cj4gKwkJaWYgKHJldCkK PiArCQkJcmV0dXJuIC1FTk9NRU07Cj4gKwkJbmFuZC0+ZWNjLnJlYWRfcGFnZSA9IHJrX25hbmRj X2h3X3N5bmRyb21lX2VjY19yZWFkX3BhZ2U7Cj4gKwkJbmFuZC0+ZWNjLndyaXRlX3BhZ2UgPSBy a19uYW5kY19od19zeW5kcm9tZV9lY2Nfd3JpdGVfcGFnZTsKPiArCQluYW5kLT5lY2MucmVhZF9v b2IgPSBya19uYW5kY19od19lY2NfcmVhZF9vb2I7Cj4gKwkJbmFuZC0+ZWNjLndyaXRlX29vYiA9 IHJrX25hbmRjX2h3X2VjY193cml0ZV9vb2I7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIE5BTkRfRUND X0hXOgoKSSB3b3VsZCBlaXRoZXIgcmVmdXNlIEVDQ19IVyBvciBwdXQgaXQgYmVzaWRlcyBIV19T WU5EUk9NRS4KCj4gKwljYXNlIE5BTkRfRUNDX05PTkU6Cj4gKwljYXNlIE5BTkRfRUNDX1NPRlQ6 CgpIYXZlIHlvdSB0ZXN0ZWQgd2l0aCBTVyBCQ0g/Cgo+ICsJCWJyZWFrOwo+ICsJZGVmYXVsdDoK PiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiAr c3RhdGljIGludCBya19uYW5kY19leGVjX29wKHN0cnVjdCBuYW5kX2NoaXAgKm5hbmQsCj4gKwkJ CSAgICBjb25zdCBzdHJ1Y3QgbmFuZF9vcGVyYXRpb24gKm9wLAo+ICsJCQkgICAgYm9vbCBjaGVj a19vbmx5KQo+ICt7Cj4gKwlpbnQgaTsKPiArCXVuc2lnbmVkIGludCBvcF9pZDsKPiArCWNvbnN0 IHN0cnVjdCBuYW5kX29wX2luc3RyICppbnN0ciA9IE5VTEw7Cj4gKwo+ICsJcmtfbmFuZGNfc2Vs ZWN0X2NoaXAobmFuZCwgb3AtPmNzKTsKPiArCj4gKwlpZiAoY2hlY2tfb25seSkKPiArCQlyZXR1 cm4gMDsKPiArCj4gKwlmb3IgKG9wX2lkID0gMDsgb3BfaWQgPCBvcC0+bmluc3Ryczsgb3BfaWQr Kykgewo+ICsJCWluc3RyID0gJm9wLT5pbnN0cnNbb3BfaWRdOwo+ICsKPiArCQlzd2l0Y2ggKGlu c3RyLT50eXBlKSB7Cj4gKwkJY2FzZSBOQU5EX09QX0NNRF9JTlNUUjoKPiArCQkJcmtfbmFuZGNf d3JpdGVfY21kKG5hbmQsIGluc3RyLT5jdHguY21kLm9wY29kZSk7Cj4gKwkJCWJyZWFrOwo+ICsJ CWNhc2UgTkFORF9PUF9BRERSX0lOU1RSOgo+ICsJCQlmb3IgKGkgPSAwOyBpIDwgaW5zdHItPmN0 eC5hZGRyLm5hZGRyczsgaSsrKQo+ICsJCQkJcmtfbmFuZGNfd3JpdGVfYWRkcihuYW5kLAo+ICsJ CQkJCQkgICAgaW5zdHItPmN0eC5hZGRyLmFkZHJzW2ldKTsKPiArCQkJYnJlYWs7Cj4gKwkJY2Fz ZSBOQU5EX09QX0RBVEFfSU5fSU5TVFI6Cj4gKwkJCXJrX25hbmRjX3JlYWRfYnVmKG5hbmQsIGlu c3RyLT5jdHguZGF0YS5idWYuaW4sCj4gKwkJCQkJICBpbnN0ci0+Y3R4LmRhdGEubGVuKTsKPiAr CQkJYnJlYWs7Cj4gKwkJY2FzZSBOQU5EX09QX0RBVEFfT1VUX0lOU1RSOgo+ICsJCQlya19uYW5k Y193cml0ZV9idWYobmFuZCwgaW5zdHItPmN0eC5kYXRhLmJ1Zi5vdXQsCj4gKwkJCQkJICAgaW5z dHItPmN0eC5kYXRhLmxlbik7Cj4gKwkJCWJyZWFrOwo+ICsJCWNhc2UgTkFORF9PUF9XQUlUUkRZ X0lOU1RSOgo+ICsJCQlya19uYW5kY19kZXZfcmVhZHkobmFuZCk7Cj4gKwkJCWJyZWFrOwo+ICsJ CX0KPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVj dCBuYW5kX2NvbnRyb2xsZXJfb3BzIHJrX25hbmRfY29udHJvbGxlcl9vcHMgPSB7Cj4gKwkuYXR0 YWNoX2NoaXAgPSBya19uYW5kY19hdHRhY2hfY2hpcCwKPiArCS5kZXRhY2hfY2hpcCA9IHJrX25h bmRjX2RldGFjaF9jaGlwLAo+ICsJLmV4ZWNfb3AgPSBya19uYW5kY19leGVjX29wLAo+ICt9Owo+ ICsKPiArc3RhdGljIGludCBya19uYW5kY19jaGlwX2luaXQoc3RydWN0IGRldmljZSAqZGV2LAo+ ICsJCQkgICAgICBzdHJ1Y3QgcmtfbmFuZF9jb250cm9sbGVyICpjdHJsLAo+ICsJCQkgICAgICBz dHJ1Y3QgZGV2aWNlX25vZGUgKm5wLCB1bnNpZ25lZCBpbnQgY2hpcG5yKQo+ICt7Cj4gKwlzdHJ1 Y3QgcmtfbmFuZF9jaGlwICpub2RlOwo+ICsJc3RydWN0IG5hbmRfY2hpcCAqbmFuZDsKPiArCXN0 cnVjdCBtdGRfaW5mbyAqbXRkOwo+ICsJY29uc3QgX19iZTMyICpyZWc7Cj4gKwlpbnQgcmV0Owo+ ICsKPiArCXJlZyA9IG9mX2dldF9wcm9wZXJ0eShucCwgInJlZyIsIE5VTEwpOwo+ICsJaWYgKCFy ZWcpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJY3RybC0+YmFua3NbY2hpcG5yXSA9IGJl MzJfdG9fY3B1KCpyZWcpOwo+ICsKPiArCWlmIChjdHJsLT5iYW5rc1tjaGlwbnJdIDwgMCkKPiAr CQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwlub2RlID0gZGV2bV9remFsbG9jKGRldiwgc2l6ZW9m KCpub2RlKSwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIW5vZGUpCj4gKwkJcmV0dXJuIC1FTk9NRU07 Cj4gKwo+ICsJbmFuZCA9ICZub2RlLT5uYW5kOwo+ICsKPiArCW5hbmRfc2V0X2ZsYXNoX25vZGUo bmFuZCwgbnApOwo+ICsJbmFuZF9zZXRfY29udHJvbGxlcl9kYXRhKG5hbmQsIGN0cmwpOwo+ICsK PiArCW5hbmQtPmNvbnRyb2xsZXIgPSAmY3RybC0+Y29udHJvbGxlcjsKPiArCW5hbmQtPmNvbnRy b2xsZXItPm9wcyA9ICZya19uYW5kX2NvbnRyb2xsZXJfb3BzOwo+ICsKPiArCW5hbmQtPmVjYy5t b2RlID0gTkFORF9FQ0NfSFdfU1lORFJPTUU7Cj4gKwluYW5kLT5lY2Muc2l6ZSA9IDEwMjQ7Cj4g KwluYW5kLT5lY2Muc3RyZW5ndGggPSA0MDsKPiArCj4gKwluYW5kLT5vcHRpb25zID0gTkFORF9T S0lQX0JCVFNDQU4gfCBOQU5EX05PX1NVQlBBR0VfV1JJVEU7Cj4gKwo+ICsJbXRkID0gbmFuZF90 b19tdGQobmFuZCk7Cj4gKwltdGQtPmRldi5wYXJlbnQgPSBkZXY7Cj4gKwltdGQtPm5hbWUgPSBk ZXZtX2thc3ByaW50ZihkZXYsIEdGUF9LRVJORUwsICIlcy4lZCIsIGRldl9uYW1lKGRldiksCj4g KwkJCQkgICBjdHJsLT5iYW5rc1tjaGlwbnJdKTsKPiArCj4gKwlyZXQgPSBuYW5kX3NjYW4obmFu ZCwgMSk7CgpXaHkgMSBoZXJlPwoKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4g KwlyZXQgPSBtdGRfZGV2aWNlX3JlZ2lzdGVyKG10ZCwgTlVMTCwgMCk7Cj4gKwlpZiAocmV0KSB7 Cj4gKwkJZGV2X2VycihkZXYsICJtdGQgZGV2aWNlIHJlZ2lzdGVyIGZhaWxlZDogJWRcbiIsIHJl dCk7Cj4gKwkJbmFuZF9yZWxlYXNlKG5hbmQpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ ICsJbGlzdF9hZGRfdGFpbCgmbm9kZS0+Y2hpcF9saXN0LCAmY3RybC0+Y2hpcHMpOwo+ICsKPiAr CXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHJrX25hbmRjX2NsZWFudXBfY2hpcHMo c3RydWN0IHJrX25hbmRfY29udHJvbGxlciAqY3RybCkKPiArewo+ICsJc3RydWN0IHJrX25hbmRf Y2hpcCAqbm9kZTsKPiArCXN0cnVjdCBtdGRfaW5mbyAqbXRkOwo+ICsJaW50IHJldDsKPiArCj4g Kwl3aGlsZSAoIWxpc3RfZW1wdHkoJmN0cmwtPmNoaXBzKSkgewo+ICsJCW5vZGUgPSBsaXN0X2Zp cnN0X2VudHJ5KCZjdHJsLT5jaGlwcywgc3RydWN0IHJrX25hbmRfY2hpcCwKPiArCQkJCQljaGlw X2xpc3QpOwo+ICsJCW10ZCA9IG5hbmRfdG9fbXRkKCZub2RlLT5uYW5kKTsKPiArCQlyZXQgPSBt dGRfZGV2aWNlX3VucmVnaXN0ZXIobXRkKTsKPiArCQlpZiAocmV0KQo+ICsJCQlyZXR1cm4gcmV0 Owo+ICsKPiArCQlya19uYW5kY19mcmVlX2J1ZmZlcigmbm9kZS0+bmFuZCk7Cj4gKwkJbmFuZF9j bGVhbnVwKCZub2RlLT5uYW5kKTsKPiArCQlsaXN0X2RlbCgmbm9kZS0+Y2hpcF9saXN0KTsKPiAr CX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBya19uYW5kY19jaGlw c19pbml0KHN0cnVjdCBkZXZpY2UgKmRldiwKPiArCQkJICAgICAgIHN0cnVjdCBya19uYW5kX2Nv bnRyb2xsZXIgKmN0cmwpCj4gK3sKPiArCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbnAgPSBkZXYtPm9m X25vZGU7Cj4gKwlzdHJ1Y3QgZGV2aWNlX25vZGUgKm5hbmRfbnA7Cj4gKwlpbnQgbmNoaXBzID0g b2ZfZ2V0X2NoaWxkX2NvdW50KG5wKTsKPiArCWludCBpID0gMDsKPiArCWludCByZXQ7Cj4gKwo+ ICsJaWYgKG5jaGlwcyA+IE5BTkRDX05VTV9CQU5LUykgewo+ICsJCWRldl9lcnIoZGV2LCAidG9v IG1hbnkgTkFORCBjaGlwczogJWQgKG1heCA9IDQpXG4iLCBuY2hpcHMpOwo+ICsJCXJldHVybiAt RUlOVkFMOwo+ICsJfQo+ICsKPiArCWZvcl9lYWNoX2NoaWxkX29mX25vZGUobnAsIG5hbmRfbnAp IHsKPiArCQlyZXQgPSBya19uYW5kY19jaGlwX2luaXQoZGV2LCBjdHJsLCBuYW5kX25wLCBpKTsK PiArCQlpZiAocmV0KSB7Cj4gKwkJCXJrX25hbmRjX2NsZWFudXBfY2hpcHMoY3RybCk7Cj4gKwkJ CW9mX25vZGVfcHV0KG5hbmRfbnApOwo+ICsJCQlyZXR1cm4gcmV0Owo+ICsJCX0KPiArCQlpKys7 Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcmtfbmFuZGNf cHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKPiArewo+ICsJY29uc3Qgc3RydWN0 IHJrX25hbmRjX2RhdGEgKmRhdGE7Cj4gKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSAmcGRldi0+ZGV2 Owo+ICsJc3RydWN0IGRldmljZV9ub2RlICpub2RlOwo+ICsJaW50IGlkOwo+ICsJaW50IHJldDsK PiArCj4gKwlkYXRhID0gb2ZfZGV2aWNlX2dldF9tYXRjaF9kYXRhKCZwZGV2LT5kZXYpOwo+ICsJ aWYgKCFkYXRhKQo+ICsJCXJldHVybiAtRU5PREVWOwo+ICsKPiArCW5vZGUgPSBwZGV2LT5kZXYu b2Zfbm9kZTsKPiArCj4gKwlpZCA9IG9mX2FsaWFzX2dldF9pZChub2RlLCAibmFuZGMiKTsKPiAr CWlmIChpZCA8IDApCj4gKwkJaWQgPSBnX2lkX2NvdW50ZXI7Cj4gKwlpZiAoKGlkID49IEFSUkFZ X1NJWkUoZ19uYW5kY19pbmZvKSB8fCBnX25hbmRjX2luZm9baWRdLnJlZ3MpKSB7Cj4gKwkJZGV2 X2VycigKPiArCQkJJnBkZXYtPmRldiwKPiArCQkJImZhaWxlZCB0byBnZXQgaWQgZm9yIG5hbmRj IG5vZGUgJyVwT0ZuJ1xuIiwKPiArCQkJbm9kZSk7Cj4gKwkJb2Zfbm9kZV9wdXQobm9kZSk7Cj4g KwkJcmV0dXJuIC1FTk9ERVY7Cj4gKwl9Cj4gKwkrK2dfaWRfY291bnRlcjsKPiArCj4gKwlnX25h bmRjX2luZm9baWRdLnZlcnNpb24gPSBkYXRhLT52ZXJzaW9uOwo+ICsKPiArCWdfbmFuZGNfaW5m b1tpZF0ucmVncyA9IGRldm1fcGxhdGZvcm1faW9yZW1hcF9yZXNvdXJjZShwZGV2LCAwKTsKPiAr CWlmIChJU19FUlIoZ19uYW5kY19pbmZvW2lkXS5yZWdzKSkgewo+ICsJCWRldl9lcnIoZGV2LCAi aW9yZW1hcCBmYWlsZWRcbiIpOwo+ICsJCXJldHVybiBQVFJfRVJSKGdfbmFuZGNfaW5mb1tpZF0u cmVncyk7Cj4gKwl9Cj4gKwo+ICsJZ19uYW5kY19pbmZvW2lkXS5pcnEgPSBwbGF0Zm9ybV9nZXRf aXJxKHBkZXYsIDApOwo+ICsJaWYgKGdfbmFuZGNfaW5mb1tpZF0uaXJxIDwgMCkgewo+ICsJCWRl dl9lcnIoZGV2LCAiZ2V0IGlycSBmYWlsZWRcbiIpOwo+ICsJCXJldHVybiBnX25hbmRjX2luZm9b aWRdLmlycTsKPiArCX0KPiArCj4gKwlnX25hbmRjX2luZm9baWRdLmhjbGsgPSBkZXZtX2Nsa19n ZXQoZGV2LCAiaGNsa19uYW5kYyIpOwo+ICsJaWYgKElTX0VSUihnX25hbmRjX2luZm9baWRdLmhj bGspKSB7Cj4gKwkJZGV2X2VycihkZXYsICJnZXQgaGNsa19uYW5kYyBmYWlsZWRcbiIpOwo+ICsJ CXJldHVybiBQVFJfRVJSKGdfbmFuZGNfaW5mb1tpZF0uaGNsayk7Cj4gKwl9Cj4gKwo+ICsJcmV0 ID0gY2xrX3ByZXBhcmVfZW5hYmxlKGdfbmFuZGNfaW5mb1tpZF0uaGNsayk7Cj4gKwlpZiAocmV0 KQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJZ19uYW5kY19pbmZvW2lkXS5jbGsgPSBkZXZtX2Ns a19nZXQoZGV2LCAiY2xrX25hbmRjIik7Cj4gKwlpZiAoIShJU19FUlIoZ19uYW5kY19pbmZvW2lk XS5jbGspKSkgewo+ICsJCWNsa19zZXRfcmF0ZShnX25hbmRjX2luZm9baWRdLmNsaywgMTUwICog MTAwMCAqIDEwMDApOwo+ICsKPiArCQlyZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoZ19uYW5kY19p bmZvW2lkXS5jbGspOwo+ICsJCWlmIChyZXQpCj4gKwkJCWdvdG8gZXJyX2Rpc2FibGVfaGNsazsK PiArCX0gZWxzZQo+ICsJCWRldl9lcnIoZGV2LCAiZ2V0IGNsa19uYW5kYyBmYWlsZWRcbiIpOwo+ ICsKPiArCWlmIChnX25hbmRjX2luZm9baWRdLnZlcnNpb24gPT0gVkVSU0lPTl85KQo+ICsJCXdy aXRlbCgwLCBnX25hbmRjX2luZm9baWRdLnJlZ3MgKyBOQU5EQ19SRUdfVjlfSU5URU4pOwo+ICsJ ZWxzZQo+ICsJCXdyaXRlbCgwLCBnX25hbmRjX2luZm9baWRdLnJlZ3MgKyBOQU5EQ19SRUdfVjZf SU5URU4pOwo+ICsJcmV0ID0gZGV2bV9yZXF1ZXN0X2lycShkZXYsIGdfbmFuZGNfaW5mb1tpZF0u aXJxLCBya19uYW5kY19pbnRlcnJ1cHQsCj4gKwkJCSAgICAgICAwLCAibmFuZGMiLCAmZ19uYW5k Y19pbmZvW2lkXSk7Cj4gKwlpZiAocmV0KQo+ICsJCWdvdG8gZXJyX2Rpc2FibGVfY2xrOwo+ICsK PiArCW5hbmRfY29udHJvbGxlcl9pbml0KCZnX25hbmRjX2luZm9baWRdLmNvbnRyb2xsZXIpOwo+ ICsJSU5JVF9MSVNUX0hFQUQoJmdfbmFuZGNfaW5mb1tpZF0uY2hpcHMpOwo+ICsKPiArCXJrX25h bmRjX2luaXQoJmdfbmFuZGNfaW5mb1tpZF0pOwo+ICsKPiArCXJldCA9IHJrX25hbmRjX2NoaXBz X2luaXQoZGV2LCAmZ19uYW5kY19pbmZvW2lkXSk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZGV2X2Vy cihkZXYsICJpbml0IG5hbmQgY2hpcHMgZmFpbGVkXG4iKTsKPiArCQlnb3RvIGVycl9kaXNhYmxl X2NsazsKPiArCX0KPiArCj4gKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2LCAmZ19uYW5kY19p bmZvW2lkXSk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gKwo+ICtlcnJfZGlzYWJsZV9jbGs6Cj4gKwlj bGtfZGlzYWJsZV91bnByZXBhcmUoZ19uYW5kY19pbmZvW2lkXS5jbGspOwo+ICtlcnJfZGlzYWJs ZV9oY2xrOgo+ICsJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKGdfbmFuZGNfaW5mb1tpZF0uaGNsayk7 Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGludCBya19uYW5kY19yZW1v dmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKPiArewo+ICsJc3RydWN0IHJrX25hbmRf Y29udHJvbGxlciAqY3RybCA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ICsJaW50IHJl dDsKPiArCj4gKwlyZXQgPSBya19uYW5kY19jbGVhbnVwX2NoaXBzKGN0cmwpOwo+ICsJaWYgKHJl dCkKPiArCQlyZXR1cm4gcmV0Owo+ICsKPiArCWNsa19kaXNhYmxlX3VucHJlcGFyZShjdHJsLT5j bGspOwo+ICsJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKGN0cmwtPmhjbGspOwo+ICsJcGxhdGZvcm1f c2V0X2RydmRhdGEocGRldiwgTlVMTCk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0 YXRpYyB2b2lkIHJrX25hbmRjX3NodXRkb3duKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYp Cj4gK3sKPiArCXN0cnVjdCBya19uYW5kX2NvbnRyb2xsZXIgKmN0cmwgPSBwbGF0Zm9ybV9nZXRf ZHJ2ZGF0YShwZGV2KTsKPiArCWludCByZXQ7Cj4gKwo+ICsJcmV0ID0gcmtfbmFuZGNfY2xlYW51 cF9jaGlwcyhjdHJsKTsKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuOwo+ICsKPiArCWNsa19kaXNh YmxlX3VucHJlcGFyZShjdHJsLT5jbGspOwo+ICsJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKGN0cmwt PmhjbGspOwo+ICsJcGxhdGZvcm1fc2V0X2RydmRhdGEocGRldiwgTlVMTCk7Cj4gK30KPiArCj4g K3N0YXRpYyBjb25zdCBzdHJ1Y3QgcmtfbmFuZGNfZGF0YSBya19uYW5kY192Nl9kYXRhID0gewo+ ICsJLnZlcnNpb24gPSBWRVJTSU9OXzYsCj4gK307Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0 IHJrX25hbmRjX2RhdGEgcmtfbmFuZGNfdjlfZGF0YSA9IHsKPiArCS52ZXJzaW9uID0gVkVSU0lP Tl85LAo+ICt9Owo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgb2Zfcmtf bmFuZGNfbWF0Y2hbXSA9IHsKPiArCXsKPiArCQkuY29tcGF0aWJsZSA9ICJyb2NrY2hpcCxuYW5k Yy12NiIsCj4gKwkJLmRhdGEgPSAmcmtfbmFuZGNfdjZfZGF0YSwKPiArCX0sCj4gKwl7Cj4gKwkJ LmNvbXBhdGlibGUgPSAicm9ja2NoaXAsbmFuZGMtdjkiLAo+ICsJCS5kYXRhID0gJnJrX25hbmRj X3Y5X2RhdGEsCj4gKwl9LAo+ICsJeyAvKiBzZW50aW5lbCAqLyB9LAo+ICt9Owo+ICsKPiArc3Rh dGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgcmtfbmFuZGNfZHJpdmVyID0gewo+ICsJLnByb2Jl ICA9IHJrX25hbmRjX3Byb2JlLAo+ICsJLnJlbW92ZSA9IHJrX25hbmRjX3JlbW92ZSwKPiArCS5z aHV0ZG93biA9IHJrX25hbmRjX3NodXRkb3duLAo+ICsJLmRyaXZlciA9IHsKPiArCQkubmFtZSA9 ICJyb2NrY2hpcC1uYW5kYyIsCj4gKwkJLm9mX21hdGNoX3RhYmxlID0gb2ZfcmtfbmFuZGNfbWF0 Y2gsCj4gKwl9LAo+ICt9Owo+ICsKCk1vdmUgdGhpcyBlbXB0eSBsaW5lLi4uCgo+ICttb2R1bGVf cGxhdGZvcm1fZHJpdmVyKHJrX25hbmRjX2RyaXZlcik7CgouLi5IZXJlCgo+ICtNT0RVTEVfTElD RU5TRSgiR1BMIHYyIik7CgpUaGFua3MsCk1pcXXDqGwKCl9fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpMaW51eCBNVEQgZGlzY3Vzc2lvbiBtYWls aW5nIGxpc3QKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51 eC1tdGQvCg== From mboxrd@z Thu Jan 1 00:00:00 1970 From: Miquel Raynal Subject: Re: [RFC PATCH v1 02/10] mtd: nand: raw: add rockchip nand controller driver Date: Fri, 10 Jan 2020 12:05:34 +0100 Message-ID: <20200110120534.1b4026b0@xps13> References: <20200108205338.11369-1-jbx6244@gmail.com> <20200108205338.11369-3-jbx6244@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8BIT Return-path: In-Reply-To: <20200108205338.11369-3-jbx6244-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> Sender: devicetree-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: Johan Jonker Cc: richard-/L3Ra7n9ekc@public.gmane.org, vigneshr-l0cyMroinI0@public.gmane.org, robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, mark.rutland-5wv7dgnIgG8@public.gmane.org, heiko-4mtYJXux2i+zQB+pC5nmwQ@public.gmane.org, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org, linux-rockchip-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org, linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org List-Id: linux-rockchip.vger.kernel.org Hi Johan, Johan Jonker wrote on Wed, 8 Jan 2020 21:53:30 +0100: > From: Yifeng Zhao > Can you change the title to "mtd: rawnand: rockchip: Add NAND controller driver" > Add basic Rockchip nand controller driver. > > Compatible with hardware version 6 and 9. > V6:16, 24, 40, 60 per 1024B BCH/ECC. > V9:16, 40, 60, 70 per 1024B BCH/ECC. > 8 bit asynchronous flash interface support. > Supports up to 2 identical nandc nodes. > Max 4 nand chips per controller. > Able to select a different hardware ecc setup > for the loader blocks. > No bad block support. Thank you very much for this series, as the bad blocks support is absolutely fundamental, I wonder what is the issue here? > > Signed-off-by: Yifeng Zhao > Signed-off-by: Johan Jonker > --- > drivers/mtd/nand/raw/Kconfig | 8 + > drivers/mtd/nand/raw/Makefile | 1 + > drivers/mtd/nand/raw/rockchip_nandc.c | 1224 +++++++++++++++++++++++++++++++++ > 3 files changed, 1233 insertions(+) > create mode 100644 drivers/mtd/nand/raw/rockchip_nandc.c > > diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig > index 74fb91ade..68dc9a36d 100644 > --- a/drivers/mtd/nand/raw/Kconfig > +++ b/drivers/mtd/nand/raw/Kconfig > @@ -457,6 +457,14 @@ config MTD_NAND_CADENCE > Enable the driver for NAND flash on platforms using a Cadence NAND > controller. > > +config MTD_NAND_ROCKCHIP > + tristate "Rockchip raw NAND controller driver" > + depends on ARCH_ROCKCHIP || COMPILE_TEST > + depends on HAS_IOMEM > + help > + Enables support for the Rockchip raw NAND controller driver. > + This controller is found on rk3066, rk3188, rk3288 and more. Can you write an exhaustive list if you know it? Or at least the families? It is quite challenging when you are not in the Rockchip world to know what SoC is similar to another random SoC. > + > comment "Misc" > > config MTD_SM_COMMON > diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile > index 2d136b158..3063fe74a 100644 > --- a/drivers/mtd/nand/raw/Makefile > +++ b/drivers/mtd/nand/raw/Makefile > @@ -58,6 +58,7 @@ 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 > +obj-$(CONFIG_MTD_NAND_ROCKCHIP) += rockchip_nandc.o A driver named rockchip-nand-controller.c would be nice! > > 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/rockchip_nandc.c b/drivers/mtd/nand/raw/rockchip_nandc.c > new file mode 100644 > index 000000000..018308e58 > --- /dev/null > +++ b/drivers/mtd/nand/raw/rockchip_nandc.c > @@ -0,0 +1,1224 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Based on: > + * https://github.com/rockchip-linux/kernel/blob/develop-4.4/drivers/mtd/nand/ > + * rockchip_nand_v6.c > + * https://github.com/rockchip-linux/kernel/blob/develop-4.4/drivers/mtd/nand/ > + * rockchip_nand_v9.c I'm not sure the entire link is relevant, I would simple mention the Rockchip official Github repository and work from Yifeng. > + * Copyright (c) 2016-2019 Yifeng Zhao yifeng.zhao-TNX95d0MmH7DzftRWevZcw@public.gmane.org > + * > + * Update/restyle for linux-next. > + * Add exec_op function. You can drop these two lines too. This is more a "commit description" thing. > + * Combine driver for nandc version 6 and 9. Support NAND controller versions 6 and 9 found on SoCs ... > + * Copyright (c) 2020 Johan Jonker jbx6244-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#define NANDC_ID_V600 0x56363030 > +#define NANDC_ID_V622 0x56363232 > +#define NANDC_ID_V701 0x701 > +#define NANDC_ID_V800 0x56383030 > +#define NANDC_ID_V801 0x801 > +#define NANDC_ID_V900 0x56393030 I would prefer prefixing everything RK_NANDC_ or RK_ > + > +#define NANDC_IDBResBlkNum 16 > +#define NANDC_IDBEccBits 24 > +#define NANDC_IDBStartAddr 0 > + > +#define NANDC_V6_ECC_16 0x00000000 > +#define NANDC_V6_ECC_24 0x00000010 > +#define NANDC_V6_ECC_40 0x00040000 > +#define NANDC_V6_ECC_60 0x00040010 > + > +#define NANDC_V9_ECC_16 0x02000001 > +#define NANDC_V9_ECC_40 0x04000001 > +#define NANDC_V9_ECC_60 0x06000001 > +#define NANDC_V9_ECC_70 0x00000001 > + > +#define NANDC_NUM_BANKS 4 > +#define NANDC_DEF_TIMEOUT 10000 > + > +#define NANDC_REG_DATA 0x00 > +#define NANDC_REG_ADDR 0x04 > +#define NANDC_REG_CMD 0x08 > + > +/* register offset nandc version 6 */ > +#define NANDC_REG_V6_FMCTL 0x00 > +#define NANDC_REG_V6_FMWAIT 0x04 > +#define NANDC_REG_V6_FLCTL 0x08 > +#define NANDC_REG_V6_BCHCTL 0x0c > +#define NANDC_REG_V6_DMA_CFG 0x10 > +#define NANDC_REG_V6_DMA_BUF0 0x14 > +#define NANDC_REG_V6_DMA_BUF1 0x18 > +#define NANDC_REG_V6_DMA_ST 0x1C > +#define NANDC_REG_V6_BCHST 0x20 > +#define NANDC_REG_V6_RANDMZ 0x150 > +#define NANDC_REG_V6_VER 0x160 > +#define NANDC_REG_V6_INTEN 0x16C > +#define NANDC_REG_V6_INTCLR 0x170 > +#define NANDC_REG_V6_INTST 0x174 > +#define NANDC_REG_V6_SPARE0 0x200 > +#define NANDC_REG_V6_SPARE1 0x230 > + > +/* register offset nandc version 9 */ > +#define NANDC_REG_V9_FMCTL 0x00 > +#define NANDC_REG_V9_FMWAIT 0x04 > +#define NANDC_REG_V9_FLCTL 0x10 > +#define NANDC_REG_V9_BCHCTL 0x20 > +#define NANDC_REG_V9_DMA_CFG 0x30 > +#define NANDC_REG_V9_DMA_BUF0 0x34 > +#define NANDC_REG_V9_DMA_BUF1 0x38 > +#define NANDC_REG_V9_DMA_ST 0x40 > +#define NANDC_REG_V9_VER 0x80 > +#define NANDC_REG_V9_INTEN 0x120 > +#define NANDC_REG_V9_INTCLR 0x124 > +#define NANDC_REG_V9_INTST 0x128 > +#define NANDC_REG_V9_BCHST 0x150 > +#define NANDC_REG_V9_SPARE0 0x200 > +#define NANDC_REG_V9_SPARE1 0x204 > +#define NANDC_REG_V9_RANDMZ 0x208 > + > +/* register offset nandc common */ > +#define NANDC_REG_BANK0 0x800 > +#define NANDC_REG_SRAM0 0x1000 > + > +/* FMCTL */ > +#define NANDC_V6_FM_WP BIT(8) > +#define NANDC_V6_FM_CE_SEL_M 0xFF > +#define NANDC_V6_FM_CE_SEL(x) (1 << (x)) > +#define NANDC_V6_FM_FREADY BIT(9) > + > +#define NANDC_V9_FM_WP BIT(8) > +#define NANDC_V9_FM_CE_SEL_M 0xFF > +#define NANDC_V9_FM_CE_SEL(x) (1 << (x)) > +#define NANDC_V9_RDY BIT(9) > + > +/* FLCTL */ > +#define NANDC_V6_FL_RST BIT(0) > +#define NANDC_V6_FL_DIR(x) ((x) ? BIT(1) : 0) > +#define NANDC_V6_FL_XFER_START BIT(2) > +#define NANDC_V6_FL_XFER_EN BIT(3) > +#define NANDC_V6_FL_ST_BUF_S 0x4 > +#define NANDC_V6_FL_XFER_COUNT BIT(5) > +#define NANDC_V6_FL_ACORRECT BIT(10) > +#define NANDC_V6_FL_XFER_READY BIT(20) > +#define NANDC_V6_FL_PAGE_NUM(x) ((x) << 22) > +#define NANDC_V6_FL_ASYNC_TOG_MIX BIT(29) > + > +#define NANDC_V9_FL_RST BIT(0) > +#define NANDC_V9_FL_DIR(x) ((x) ? BIT(1) : 0) > +#define NANDC_V9_FL_XFER_START BIT(2) > +#define NANDC_V9_FL_XFER_EN BIT(3) > +#define NANDC_V9_FL_ST_BUF_S 0x4 > +#define NANDC_V9_FL_XFER_COUNT BIT(5) > +#define NANDC_V9_FL_ACORRECT BIT(10) > +#define NANDC_V9_FL_XFER_READY BIT(20) > +#define NANDC_V9_FL_PAGE_NUM(x) ((x) << 22) > +#define NANDC_V9_FL_ASYNC_TOG_MIX BIT(29) > + > +/* BCHCTL */ > +#define NAND_V6_BCH_REGION_S 0x5 > +#define NAND_V6_BCH_REGION_M 0x7 > + > +#define NAND_V9_BCH_MODE_S 25 > +#define NAND_V9_BCH_MODE_M 0x7 > + > +/* BCHST */ > +#define NANDC_V6_BCH0_ST_ERR BIT(2) > +#define NANDC_V6_BCH1_ST_ERR BIT(15) > +#define NANDC_V6_ECC_ERR_CNT0(x) ((((x & (0x1F << 3)) >> 3) \ > + | ((x & (1 << 27)) >> 22)) & 0x3F) > +#define NANDC_V6_ECC_ERR_CNT1(x) ((((x & (0x1F << 16)) >> 16) \ > + | ((x & (1 << 29)) >> 24)) & 0x3F) > + > +#define NANDC_V9_BCH0_ST_ERR BIT(2) > +#define NANDC_V9_BCH1_ST_ERR BIT(18) > +#define NANDC_V9_ECC_ERR_CNT0(x) (((x) & (0x7F << 3)) >> 3) > +#define NANDC_V9_ECC_ERR_CNT1(x) (((x) & (0x7F << 19)) >> 19) > + > +/* DMA_CFG */ > +#define NANDC_V6_DMA_CFG_WR_ST BIT(0) > +#define NANDC_V6_DMA_CFG_WR(x) ((!x) ? BIT(1) : 0) > +#define NANDC_V6_DMA_CFG_BUS_MODE BIT(2) > + > +#define NANDC_V6_DMA_CFG_HSIZE_8 0 > +#define NANDC_V6_DMA_CFG_HSIZE_16 (1 << 3) > +#define NANDC_V6_DMA_CFG_HSIZE_32 (2 << 3) > + > +#define NANDC_V6_DMA_CFG_BURST_1 0 > +#define NANDC_V6_DMA_CFG_BURST_4 (3 << 6) > +#define NANDC_V6_DMA_CFG_BURST_8 (5 << 6) > +#define NANDC_V6_DMA_CFG_BURST_16 (7 << 6) > + > +#define NANDC_V6_DMA_CFG_INCR_NUM(x) ((x) << 9) > + > +#define NANDC_V9_DMA_CFG_WR_ST BIT(0) > +#define NANDC_V9_DMA_CFG_WR(x) ((!x) ? BIT(1) : 0) > +#define NANDC_V9_DMA_CFG_BUS_MODE BIT(2) > + > +#define NANDC_V9_DMA_CFG_HSIZE_8 0 > +#define NANDC_V9_DMA_CFG_HSIZE_16 (1 << 3) > +#define NANDC_V9_DMA_CFG_HSIZE_32 (2 << 3) > + > +#define NANDC_V9_DMA_CFG_BURST_1 0 > +#define NANDC_V9_DMA_CFG_BURST_4 (3 << 6) > +#define NANDC_V9_DMA_CFG_BURST_8 (5 << 6) > +#define NANDC_V9_DMA_CFG_BURST_16 (7 << 6) > + > +#define NANDC_V9_DMA_CFG_INCR_NUM(x) ((x) << 9) > + > +/* INTEN */ > +#define NANDC_V6_INT_DMA BIT(0) > + > +#define NANDC_V9_INT_DMA BIT(0) > + > +enum rk_nandc_version { > + VERSION_6 = 6, > + VERSION_9 = 9, > +}; > + > +struct rk_nandc_data { > + enum rk_nandc_version version; If you make a distinction between both version, maybe you can add more parameters here and do foo = data->param instead of if (data->version == 6) foo = this; else foo = that; > +}; > + > +struct rk_nand_controller { > + void __iomem *regs; > + int irq; > + struct clk *hclk; > + struct clk *clk; > + struct list_head chips; > + struct completion complete; > + struct nand_controller controller; > + int banks[NANDC_NUM_BANKS]; > + bool bootromblocks; > + int ecc_mode; > + uint32_t ecc_strength; > + int max_ecc_strength; I have not read yet the entire driver but I believe the above 4 parameters should probably be moved in rk_nand_chip, right? Anything that is NAND chip related should not be in the controller structure. It depends if you can change ECC requirements on the fly or not. > + uint32_t *oob_buf; > + uint32_t *page_buf; > + int selected_bank; > + enum rk_nandc_version version; > +}; > + > +struct rk_nand_chip { > + struct nand_chip nand; > + struct list_head chip_list; > +}; > + > +static struct rk_nand_controller g_nandc_info[2]; I don't like this idea so much. I prefer a dynamic allocation in the probe. > +static int g_id_counter; Don't know what this is yet, but it is probably a bad idea :) > + > +static void rk_nandc_init(struct rk_nand_controller *ctrl) > +{ > + if (ctrl->version == VERSION_9) { > + writel(0, ctrl->regs + NANDC_REG_V9_RANDMZ); > + writel(0, ctrl->regs + NANDC_REG_V9_DMA_CFG); > + writel(NANDC_V9_FM_WP, ctrl->regs + NANDC_REG_V9_FMCTL); > + writel(NANDC_V9_FL_RST, ctrl->regs + NANDC_REG_V9_FLCTL); > + writel(0x1081, ctrl->regs + NANDC_REG_V9_FMWAIT); > + } else { > + writel(0, ctrl->regs + NANDC_REG_V6_RANDMZ); > + writel(0, ctrl->regs + NANDC_REG_V6_DMA_CFG); > + writel(NANDC_V6_FM_WP, ctrl->regs + NANDC_REG_V6_FMCTL); > + writel(NANDC_V6_FL_RST, ctrl->regs + NANDC_REG_V6_FLCTL); > + writel(0x1081, ctrl->regs + NANDC_REG_V6_FMWAIT); > + } My above comment about the platform data would make a lot of sense here! > +} > + > +static irqreturn_t rk_nandc_interrupt(int irq, void *dev_id) > +{ > + struct rk_nand_controller *ctrl = dev_id; > + > + if (ctrl->version == VERSION_9) { > + uint32_t st = readl(ctrl->regs + NANDC_REG_V9_INTST); > + uint32_t ien = readl(ctrl->regs + NANDC_REG_V9_INTEN); > + > + if (!(ien & st)) > + return IRQ_NONE; > + > + if ((ien & st) == ien) > + complete(&ctrl->complete); > + > + writel(st, ctrl->regs + NANDC_REG_V9_INTCLR); > + writel(~st & ien, ctrl->regs + NANDC_REG_V9_INTEN); > + } else { > + uint32_t st = readl(ctrl->regs + NANDC_REG_V6_INTST); > + uint32_t ien = readl(ctrl->regs + NANDC_REG_V6_INTEN); > + > + if (!(ien & st)) > + return IRQ_NONE; > + > + if ((ien & st) == ien) > + complete(&ctrl->complete); > + > + writel(st, ctrl->regs + NANDC_REG_V6_INTCLR); > + writel(~st & ien, ctrl->regs + NANDC_REG_V6_INTEN); > + } Same comment! > + > + return IRQ_HANDLED; > +} > + > +static void rk_nandc_select_chip(struct nand_chip *nand, int chipnr) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + uint32_t reg; > + int banknr; > + > + /* The register offset and bit positions for should be: /* * The register... Please run checkpatch.pl --strict on this file, this kind of mistake would have been detected. > + * NANDC_REG_V6_FMCTL and NANDC_REG_V9_FMCTL > + * are identical. > + */ > + reg = readl(ctrl->regs + NANDC_REG_V6_FMCTL); > + reg &= ~NANDC_V6_FM_CE_SEL_M; > + > + if (chipnr == -1) { > + banknr = -1; > + } else { > + banknr = ctrl->banks[chipnr]; > + > + reg |= NANDC_V6_FM_CE_SEL(banknr); > + } > + writel(reg, ctrl->regs + NANDC_REG_V6_FMCTL); Maybe you can spare this writel by returning early if banknr == ctrl->selected_bank. > + > + ctrl->selected_bank = banknr; > +} > + > +static int rk_nandc_hw_ecc_setup(struct nand_chip *nand, > + uint32_t strength) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + uint32_t reg; > + > + nand->ecc.strength = strength; > + nand->ecc.bytes = DIV_ROUND_UP(nand->ecc.strength * 14, 8); What do 14 and 8 mean? > + /* HW ECC only works with an even number of ECC bytes */ > + nand->ecc.bytes = ALIGN(nand->ecc.bytes, 2); > + > + if (ctrl->version == VERSION_9) { > + switch (nand->ecc.strength) { > + case 70: > + reg = NANDC_V9_ECC_70; > + break; > + case 60: > + reg = NANDC_V9_ECC_60; > + break; > + case 40: > + reg = NANDC_V9_ECC_40; > + break; > + case 16: > + reg = NANDC_V9_ECC_16; > + break; > + default: > + return -EINVAL; > + } > + writel(reg, ctrl->regs + NANDC_REG_V9_BCHCTL); > + } else { > + switch (nand->ecc.strength) { > + case 60: > + reg = NANDC_V6_ECC_60; > + break; > + case 40: > + reg = NANDC_V6_ECC_40; > + break; > + case 24: > + reg = NANDC_V6_ECC_24; > + break; > + case 16: > + reg = NANDC_V6_ECC_16; > + break; > + default: > + return -EINVAL; > + } > + writel(reg, ctrl->regs + NANDC_REG_V6_BCHCTL); > + } > + > + return 0; > +} > + > +static void rk_nandc_xfer_start(struct rk_nand_controller *ctrl, > + uint8_t dir, uint8_t n_KB, > + dma_addr_t dma_data, dma_addr_t dma_oob) > +{ > + uint32_t reg; > + > + if (ctrl->version == VERSION_9) { > + reg = NANDC_V9_DMA_CFG_WR_ST | > + NANDC_V9_DMA_CFG_WR(dir) | > + NANDC_V9_DMA_CFG_BUS_MODE | > + NANDC_V9_DMA_CFG_HSIZE_32 | > + NANDC_V9_DMA_CFG_BURST_16 | > + NANDC_V9_DMA_CFG_INCR_NUM(16); > + writel(reg, ctrl->regs + NANDC_REG_V9_DMA_CFG); > + writel((uint32_t)dma_data, ctrl->regs + NANDC_REG_V9_DMA_BUF0); > + writel((uint32_t)dma_oob, ctrl->regs + NANDC_REG_V9_DMA_BUF1); I'm pretty sure most of these writel could be turned into writel_relaxed. Also I am not a big fan of these casts, maybe you should change dma_data and dma_oob types (be careful: you enabled COMPILE_TEST in Kconfig, you must support 32-bit and 64-bit pointers, please try to compile this driver with different toolchains). > + > + reg = NANDC_V9_FL_DIR(dir) | > + NANDC_V9_FL_XFER_EN | > + NANDC_V9_FL_XFER_COUNT | > + NANDC_V9_FL_ACORRECT | > + NANDC_V9_FL_PAGE_NUM(n_KB) | > + NANDC_V9_FL_ASYNC_TOG_MIX; > + writel(reg, ctrl->regs + NANDC_REG_V9_FLCTL); > + reg |= NANDC_V9_FL_XFER_START; > + writel(reg, ctrl->regs + NANDC_REG_V9_FLCTL); > + } else { > + reg = readl(ctrl->regs + NANDC_REG_V6_BCHCTL); > + reg = (reg & (~(NAND_V6_BCH_REGION_M << > + NAND_V6_BCH_REGION_S))) | > + (ctrl->selected_bank << NAND_V6_BCH_REGION_S); > + writel(reg, ctrl->regs + NANDC_REG_V6_BCHCTL); > + > + reg = NANDC_V6_DMA_CFG_WR_ST | > + NANDC_V6_DMA_CFG_WR(dir) | > + NANDC_V6_DMA_CFG_BUS_MODE | > + NANDC_V6_DMA_CFG_HSIZE_32 | > + NANDC_V6_DMA_CFG_BURST_16 | > + NANDC_V6_DMA_CFG_INCR_NUM(16); > + writel(reg, ctrl->regs + NANDC_REG_V6_DMA_CFG); > + writel(dma_data, ctrl->regs + NANDC_REG_V6_DMA_BUF0); > + writel(dma_oob, ctrl->regs + NANDC_REG_V6_DMA_BUF1); > + > + reg = NANDC_V6_FL_DIR(dir) | > + NANDC_V6_FL_XFER_EN | > + NANDC_V6_FL_XFER_COUNT | > + NANDC_V6_FL_ACORRECT | > + NANDC_V6_FL_PAGE_NUM(n_KB) | > + NANDC_V6_FL_ASYNC_TOG_MIX; > + writel(reg, ctrl->regs + NANDC_REG_V6_FLCTL); > + reg |= NANDC_V6_FL_XFER_START; > + writel(reg, ctrl->regs + NANDC_REG_V6_FLCTL); > + } > +} > + > +static int rk_nandc_wait_for_xfer_done(struct rk_nand_controller *ctrl) > +{ > + uint32_t reg; > + int ret; > + > + if (ctrl->version == VERSION_9) { > + void __iomem *ptr = ctrl->regs + NANDC_REG_V9_FLCTL; > + > + ret = readl_poll_timeout_atomic(ptr, reg, > + reg & NANDC_V9_FL_XFER_READY, > + 1, NANDC_DEF_TIMEOUT); > + } else { > + void __iomem *ptr = ctrl->regs + NANDC_REG_V6_FLCTL; > + > + ret = readl_poll_timeout_atomic(ptr, reg, > + reg & NANDC_V6_FL_XFER_READY, > + 1, NANDC_DEF_TIMEOUT); > + } Space > + if (ret) > + pr_err("timeout reg=%x\n", reg); > + > + return ret; > +} > + > +static unsigned long rk_nandc_dma_map_single(struct device *dev, > + void *ptr, int size, int dir) Unaligned parameters > +{ > +#ifdef CONFIG_ARM64 > + __dma_map_area((void *)ptr, size, dir); > + return ((unsigned long)virt_to_phys((void *)ptr)); > +#else > + return dma_map_single(dev, (void *)ptr, size, dir); > +#endif Please try to remove these #ifdefs, I don't know why would you need the former block? > +} > + > +static void rk_nandc_dma_unmap_single(struct device *dev, > + unsigned long ptr, int size, int dir) > +{ > +#ifdef CONFIG_ARM64 > + __dma_unmap_area(phys_to_virt(ptr), size, dir); > +#else > + dma_unmap_single(dev, (dma_addr_t)ptr, size, dir); > +#endif Same > +} > + > +static int rk_nandc_hw_syndrome_ecc_read_page(struct nand_chip *nand, > + uint8_t *buf, > + int oob_required, int page) Unaligned parameters (please check all of them). > +{ > + struct mtd_info *mtd = nand_to_mtd(nand); > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + struct nand_ecc_ctrl *ecc = &nand->ecc; > + int max_bitflips = 0; > + dma_addr_t dma_data, dma_oob; > + int ret, i; > + int bch_st; > + int dma_oob_size = ecc->steps * 128; > + int pages_per_blk = mtd->erasesize / mtd->writesize; > + > + rk_nandc_select_chip(nand, ctrl->selected_bank); > + > + if ((page < pages_per_blk * NANDC_IDBResBlkNum) && Camel case is usually not welcome > + ctrl->bootromblocks) This would probably deserve a helper > + rk_nandc_hw_ecc_setup(nand, NANDC_IDBEccBits); > + > + nand_read_page_op(nand, page, 0, NULL, 0); > + > + dma_data = rk_nandc_dma_map_single(mtd->dev.parent, > + ctrl->page_buf, mtd->writesize, > + DMA_FROM_DEVICE); > + dma_oob = rk_nandc_dma_map_single(mtd->dev.parent, > + ctrl->oob_buf, dma_oob_size, > + DMA_FROM_DEVICE); > + > + init_completion(&ctrl->complete); One init_completion is needed (in the probe, probably) then please use reinit_completion(). > + if (ctrl->version == VERSION_9) > + writel(NANDC_V9_INT_DMA, ctrl->regs + NANDC_REG_V9_INTEN); > + else > + writel(NANDC_V6_INT_DMA, ctrl->regs + NANDC_REG_V6_INTEN); > + rk_nandc_xfer_start(ctrl, 0, ecc->steps, dma_data, dma_oob); > + wait_for_completion_timeout(&ctrl->complete, msecs_to_jiffies(5)); > + rk_nandc_wait_for_xfer_done(ctrl); Yous should check the return status of almost all the functions here. > + rk_nandc_dma_unmap_single(mtd->dev.parent, dma_data, mtd->writesize, > + DMA_FROM_DEVICE); > + rk_nandc_dma_unmap_single(mtd->dev.parent, dma_oob, dma_oob_size, > + DMA_FROM_DEVICE); > + > + memcpy(buf, ctrl->page_buf, mtd->writesize); > + > + if (oob_required) { > + uint8_t *oob; > + uint32_t tmp; Please use u8, u16 and u32 types. > + > + for (i = 0; i < ecc->steps; i++) { > + oob = nand->oob_poi + > + i * (ecc->bytes + nand->ecc.prepad); > + if (ctrl->version == VERSION_9) { > + tmp = ctrl->oob_buf[i]; > + } else { > + uint8_t oob_step = (ctrl->ecc_mode <= 24) ? > + 64 : 128; > + tmp = ctrl->oob_buf[i * oob_step / 4]; > + } > + *oob++ = (uint8_t)tmp; > + *oob++ = (uint8_t)(tmp >> 8); > + *oob++ = (uint8_t)(tmp >> 16); > + *oob++ = (uint8_t)(tmp >> 24); > + } > + } > + > + if (ctrl->version == VERSION_9) { > + for (i = 0; i < ecc->steps / 2; i++) { > + bch_st = readl(ctrl->regs + NANDC_REG_V9_BCHST + i * 4); > + if (bch_st & NANDC_V9_BCH0_ST_ERR || > + bch_st & NANDC_V9_BCH1_ST_ERR) { > + mtd->ecc_stats.failed++; > + max_bitflips = -1; > + } else { > + ret = NANDC_V9_ECC_ERR_CNT0(bch_st); > + mtd->ecc_stats.corrected += ret; > + max_bitflips = max_t(unsigned int, > + max_bitflips, ret); > + > + ret = NANDC_V9_ECC_ERR_CNT1(bch_st); > + mtd->ecc_stats.corrected += ret; > + max_bitflips = max_t(unsigned int, > + max_bitflips, ret); > + } > + } > + } else { > + for (i = 0; i < ecc->steps / 2; i++) { > + bch_st = readl(ctrl->regs + NANDC_REG_V6_BCHST + i * 4); > + if (bch_st & NANDC_V6_BCH0_ST_ERR || > + bch_st & NANDC_V6_BCH1_ST_ERR) { > + mtd->ecc_stats.failed++; > + max_bitflips = -1; Why not using ret = $(real error) instead of using max_bitflips here? Then: if (ret) { dev_err(); return ret; } return max_bitflips; > + } else { > + ret = NANDC_V6_ECC_ERR_CNT0(bch_st); > + mtd->ecc_stats.corrected += ret; > + max_bitflips = max_t(unsigned int, > + max_bitflips, ret); > + > + ret = NANDC_V6_ECC_ERR_CNT1(bch_st); > + mtd->ecc_stats.corrected += ret; > + max_bitflips = max_t(unsigned int, > + max_bitflips, ret); > + } > + } > + } > + > + if (max_bitflips == -1) { > + dev_err(mtd->dev.parent, > + "read_page %x %x %x %x %x %p %x\n", > + page, > + max_bitflips, > + bch_st, > + ((uint32_t *)buf)[0], > + ((uint32_t *)buf)[1], > + buf, > + (uint32_t)dma_data); This is not very informative, please write a real error message. Avoid putting too much debug information, people will troubleshoot themselves if needed. > + } > + > + if (ctrl->bootromblocks) > + rk_nandc_hw_ecc_setup(nand, ctrl->ecc_mode); > + You don't use the same condition as above. Why ? Maybe the helper would help. > + return max_bitflips; > +} > + > +static int rk_nandc_hw_syndrome_ecc_write_page(struct nand_chip *nand, > + const uint8_t *buf, > + int oob_required, > + int page) > +{ > + struct mtd_info *mtd = nand_to_mtd(nand); > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + struct nand_ecc_ctrl *ecc = &nand->ecc; > + dma_addr_t dma_data, dma_oob; > + int i; > + int dma_oob_size = ecc->steps * 128; > + int pages_per_blk = mtd->erasesize / mtd->writesize; > + > + rk_nandc_select_chip(nand, ctrl->selected_bank); > + > + if ((page < pages_per_blk * NANDC_IDBResBlkNum) && > + ctrl->bootromblocks) > + rk_nandc_hw_ecc_setup(nand, NANDC_IDBEccBits); > + > + nand_prog_page_begin_op(nand, page, 0, NULL, 0); > + > + for (i = 0; i < ecc->steps; i++) { > + uint32_t tmp; > + > + if (oob_required) { > + uint8_t *oob; > + > + oob = nand->oob_poi + > + i * (ecc->bytes + nand->ecc.prepad); > + tmp = oob[0] | > + (oob[1] << 8) | > + (oob[2] << 16) | > + (oob[3] << 24); > + } else { > + /* The first NANDC_IDBResBlkNum blocks are > + * for the stored loader. The first 32 bits > + * of oob must contain a sort of link to > + * the next page address in that same block > + * for the Bootrom. > + * Depending on what FTL from Rockchip is used, > + * the first 2 pages in the NANDC_IDBResBlkNum blocks > + * are reserved for FlashPhyInfo. > + * Raw IDB data then starts at page 2 or higher. I would separate the function to read/write the loader than the usual read/write helpers to avoid any confusion on why you do these tricks. Maybe not the whole function, but at least the data/oob placement? (This is really a suggestion) > + */ > + if (!i && > + page < pages_per_blk * NANDC_IDBResBlkNum && > + page >= NANDC_IDBStartAddr) > + tmp = (page & (pages_per_blk - 1)) * 4; > + else > + tmp = 0xFFFFFFFF; > + } > + if (ctrl->version == VERSION_9) { > + ctrl->oob_buf[i] = tmp; > + } else { > + uint8_t oob_step = (ctrl->ecc_mode <= 24) ? > + 64 : 128; > + ctrl->oob_buf[i * oob_step / 4] = tmp; > + } > + } > + > + memcpy(ctrl->page_buf, buf, mtd->writesize); > + dma_data = rk_nandc_dma_map_single(mtd->dev.parent, > + ctrl->page_buf, mtd->writesize, > + DMA_TO_DEVICE); > + dma_oob = rk_nandc_dma_map_single(mtd->dev.parent, > + ctrl->oob_buf, dma_oob_size, > + DMA_TO_DEVICE); > + init_completion(&ctrl->complete); > + if (ctrl->version == VERSION_9) > + writel(NANDC_V9_INT_DMA, ctrl->regs + NANDC_REG_V9_INTEN); > + else > + writel(NANDC_V6_INT_DMA, ctrl->regs + NANDC_REG_V6_INTEN); > + rk_nandc_xfer_start(ctrl, 1, ecc->steps, dma_data, dma_oob); > + wait_for_completion_timeout(&ctrl->complete, msecs_to_jiffies(10)); > + rk_nandc_wait_for_xfer_done(ctrl); > + rk_nandc_dma_unmap_single(mtd->dev.parent, dma_data, mtd->writesize, > + DMA_TO_DEVICE); > + rk_nandc_dma_unmap_single(mtd->dev.parent, dma_oob, dma_oob_size, > + DMA_TO_DEVICE); > + > + if (ctrl->bootromblocks) > + rk_nandc_hw_ecc_setup(nand, ctrl->ecc_mode); > + > + return nand_prog_page_end_op(nand); > +} > + > +static int rk_nandc_hw_ecc_read_oob(struct nand_chip *nand, int page) > +{ > + uint8_t *buf = nand_get_data_buf(nand); > + > + return nand->ecc.read_page(nand, buf, true, page); > +} > + > +static int rk_nandc_hw_ecc_write_oob(struct nand_chip *nand, int page) > +{ > + struct mtd_info *mtd = nand_to_mtd(nand); > + int ret; > + uint8_t *buf = nand_get_data_buf(nand); > + > + memset(buf, 0xFF, mtd->writesize); > + ret = nand->ecc.write_page(nand, buf, true, page); > + if (ret) > + return ret; > + > + return nand_prog_page_end_op(nand); > +} > + > +static void rk_nandc_read_buf(struct nand_chip *nand, uint8_t *buf, int len) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + int offs = 0; > + void __iomem *bank_base = ctrl->regs + NANDC_REG_BANK0 + > + ctrl->selected_bank * 0x100; 0x100: Maybe a define > + > + for (offs = 0; offs < len; offs++) > + buf[offs] = readb(bank_base); > +} > + > +static void rk_nandc_write_buf(struct nand_chip *nand, > + const uint8_t *buf, int len) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + int offs = 0; > + void __iomem *bank_base = ctrl->regs + NANDC_REG_BANK0 + > + ctrl->selected_bank * 0x100; > + > + for (offs = 0; offs < len; offs++) > + writeb(buf[offs], bank_base); > +} > + > +static void rk_nandc_write_cmd(struct nand_chip *nand, uint8_t cmd) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + > + void __iomem *bank_base = ctrl->regs + NANDC_REG_BANK0 + > + ctrl->selected_bank * 0x100 + > + NANDC_REG_CMD; You might want to write an helper to calculate bank_base, to avoid repeating these lines. > + > + writeb(cmd, bank_base); > +} > + > +static void rk_nandc_write_addr(struct nand_chip *nand, uint8_t addr) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + > + void __iomem *bank_base = ctrl->regs + NANDC_REG_BANK0 + > + ctrl->selected_bank * 0x100 + > + NANDC_REG_ADDR; > + > + writeb(addr, bank_base); > +} > + > +static int rk_nandc_dev_ready(struct nand_chip *nand) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + > + if (readl(ctrl->regs + NANDC_REG_V6_FMCTL) & NANDC_V6_FM_FREADY) > + return 1; > + > + return 0; > +} > + > +static int rk_nandc_ooblayout_ecc(struct mtd_info *mtd, int section, > + struct mtd_oob_region *oobregion) > +{ > + struct nand_chip *nand = mtd_to_nand(mtd); > + > + if (section >= nand->ecc.steps) > + return -ERANGE; > + > + oobregion->offset = (nand->ecc.bytes + nand->ecc.prepad) * section + > + nand->ecc.prepad; > + oobregion->length = nand->ecc.steps * nand->ecc.bytes; > + > + return 0; > +} > + > +static int rk_nandc_ooblayout_free(struct mtd_info *mtd, int section, > + struct mtd_oob_region *oobregion) > +{ > + struct nand_chip *nand = mtd_to_nand(mtd); > + > + if (section >= nand->ecc.steps) > + return -ERANGE; > + > + oobregion->offset = (nand->ecc.bytes + nand->ecc.prepad) * section; > + oobregion->length = nand->ecc.steps * nand->ecc.prepad; > + > + return 0; > +} > + > +static const struct mtd_ooblayout_ops rk_nandc_oob_ops = { > + .ecc = rk_nandc_ooblayout_ecc, > + .free = rk_nandc_ooblayout_free, > +}; > + > +static void rk_nandc_free_buffer(struct nand_chip *nand) > +{ > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + > + kfree(ctrl->page_buf); > + kfree(ctrl->oob_buf); > +} > + > +static int rk_nandc_buffer_init(struct nand_chip *nand) > +{ > + struct mtd_info *mtd = nand_to_mtd(nand); > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + > + ctrl->page_buf = kmalloc(mtd->writesize, GFP_KERNEL | GFP_DMA); device managed allocations (devm_...) would be nice > + if (!ctrl->page_buf) > + return -ENOMEM; > + > + ctrl->oob_buf = kmalloc(nand->ecc.steps * 128, GFP_KERNEL | GFP_DMA); > + if (!ctrl->oob_buf) { > + kfree(ctrl->page_buf); > + return -ENOMEM; > + } > + > + return 0; > +} > + > +static int rk_nandc_hw_ecc_ctrl_init(struct nand_chip *nand) > +{ > + uint8_t strengths_v6[] = {60, 40, 24, 16}; > + uint8_t strengths_v9[] = {70, 60, 40, 16}; > + struct mtd_info *mtd = nand_to_mtd(nand); > + struct rk_nand_controller *ctrl = nand_get_controller_data(nand); > + int max_strength; > + uint32_t i, ver; > + > + if (nand->options & NAND_IS_BOOT_MEDIUM) > + ctrl->bootromblocks = true; > + else > + ctrl->bootromblocks = false; > + > + nand->ecc.prepad = 4; > + nand->ecc.steps = mtd->writesize / nand->ecc.size; > + > + max_strength = ((mtd->oobsize / nand->ecc.steps) - 4) * 8 / 14; > + if (ctrl->version == VERSION_9) { > + ctrl->max_ecc_strength = 70; > + ver = readl(ctrl->regs + NANDC_REG_V9_VER); > + if (ver != NANDC_ID_V900) > + dev_err(mtd->dev.parent, > + "unsupported nandc version %x\n", ver); > + > + if (max_strength > ctrl->max_ecc_strength) > + max_strength = ctrl->max_ecc_strength; > + > + for (i = 0; i < ARRAY_SIZE(strengths_v9); i++) { > + if (max_strength >= strengths_v9[i]) > + break; > + } > + > + if (i >= ARRAY_SIZE(strengths_v9)) { > + dev_err(mtd->dev.parent, > + "unsupported strength\n"); > + return -ENOTSUPP; > + } > + > + ctrl->ecc_mode = strengths_v9[i]; > + } else { > + ctrl->max_ecc_strength = 60; > + > + ver = readl(ctrl->regs + NANDC_REG_V6_VER); > + if (ver == NANDC_ID_V801) > + ctrl->max_ecc_strength = 16; > + else if (ver == NANDC_ID_V600 || > + ver == NANDC_ID_V622 || > + ver == NANDC_ID_V701 || > + ver == NANDC_ID_V800) > + ctrl->max_ecc_strength = 60; > + else > + dev_err(mtd->dev.parent, > + "unsupported nandc version %x\n", ver); > + > + if (max_strength > ctrl->max_ecc_strength) > + max_strength = ctrl->max_ecc_strength; > + > + for (i = 0; i < ARRAY_SIZE(strengths_v6); i++) { > + if (max_strength >= strengths_v6[i]) > + break; > + } > + > + if (i >= ARRAY_SIZE(strengths_v6)) { > + dev_err(mtd->dev.parent, > + "unsupported strength\n"); > + return -ENOTSUPP; > + } > + > + ctrl->ecc_mode = strengths_v6[i]; > + } > + rk_nandc_hw_ecc_setup(nand, ctrl->ecc_mode); > + > + mtd_set_ooblayout(mtd, &rk_nandc_oob_ops); > + > + if (mtd->oobsize < ((nand->ecc.bytes + nand->ecc.prepad) * > + nand->ecc.steps)) { > + return -EINVAL; > + } > + > + return 0; > +} > + > +static void rk_nandc_detach_chip(struct nand_chip *nand) > +{ > + switch (nand->ecc.mode) { > + case NAND_ECC_HW_SYNDROME: > + rk_nandc_free_buffer(nand); > + break; > + default: > + break; > + } > +} > + > +static int rk_nandc_attach_chip(struct nand_chip *nand) > +{ > + struct mtd_info *mtd = nand_to_mtd(nand); > + int ret; > + > + switch (nand->ecc.mode) { > + case NAND_ECC_HW_SYNDROME: > + ret = rk_nandc_hw_ecc_ctrl_init(nand); > + if (ret) > + return ret; > + ret = rk_nandc_buffer_init(nand); > + if (ret) > + return -ENOMEM; > + nand->ecc.read_page = rk_nandc_hw_syndrome_ecc_read_page; > + nand->ecc.write_page = rk_nandc_hw_syndrome_ecc_write_page; > + nand->ecc.read_oob = rk_nandc_hw_ecc_read_oob; > + nand->ecc.write_oob = rk_nandc_hw_ecc_write_oob; > + break; > + case NAND_ECC_HW: I would either refuse ECC_HW or put it besides HW_SYNDROME. > + case NAND_ECC_NONE: > + case NAND_ECC_SOFT: Have you tested with SW BCH? > + break; > + default: > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int rk_nandc_exec_op(struct nand_chip *nand, > + const struct nand_operation *op, > + bool check_only) > +{ > + int i; > + unsigned int op_id; > + const struct nand_op_instr *instr = NULL; > + > + rk_nandc_select_chip(nand, op->cs); > + > + if (check_only) > + return 0; > + > + for (op_id = 0; op_id < op->ninstrs; op_id++) { > + instr = &op->instrs[op_id]; > + > + switch (instr->type) { > + case NAND_OP_CMD_INSTR: > + rk_nandc_write_cmd(nand, instr->ctx.cmd.opcode); > + break; > + case NAND_OP_ADDR_INSTR: > + for (i = 0; i < instr->ctx.addr.naddrs; i++) > + rk_nandc_write_addr(nand, > + instr->ctx.addr.addrs[i]); > + break; > + case NAND_OP_DATA_IN_INSTR: > + rk_nandc_read_buf(nand, instr->ctx.data.buf.in, > + instr->ctx.data.len); > + break; > + case NAND_OP_DATA_OUT_INSTR: > + rk_nandc_write_buf(nand, instr->ctx.data.buf.out, > + instr->ctx.data.len); > + break; > + case NAND_OP_WAITRDY_INSTR: > + rk_nandc_dev_ready(nand); > + break; > + } > + } > + > + return 0; > +} > + > +static const struct nand_controller_ops rk_nand_controller_ops = { > + .attach_chip = rk_nandc_attach_chip, > + .detach_chip = rk_nandc_detach_chip, > + .exec_op = rk_nandc_exec_op, > +}; > + > +static int rk_nandc_chip_init(struct device *dev, > + struct rk_nand_controller *ctrl, > + struct device_node *np, unsigned int chipnr) > +{ > + struct rk_nand_chip *node; > + struct nand_chip *nand; > + struct mtd_info *mtd; > + const __be32 *reg; > + int ret; > + > + reg = of_get_property(np, "reg", NULL); > + if (!reg) > + return -EINVAL; > + > + ctrl->banks[chipnr] = be32_to_cpu(*reg); > + > + if (ctrl->banks[chipnr] < 0) > + return -EINVAL; > + > + node = devm_kzalloc(dev, sizeof(*node), GFP_KERNEL); > + if (!node) > + return -ENOMEM; > + > + nand = &node->nand; > + > + nand_set_flash_node(nand, np); > + nand_set_controller_data(nand, ctrl); > + > + nand->controller = &ctrl->controller; > + nand->controller->ops = &rk_nand_controller_ops; > + > + nand->ecc.mode = NAND_ECC_HW_SYNDROME; > + nand->ecc.size = 1024; > + nand->ecc.strength = 40; > + > + nand->options = NAND_SKIP_BBTSCAN | NAND_NO_SUBPAGE_WRITE; > + > + mtd = nand_to_mtd(nand); > + mtd->dev.parent = dev; > + mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev), > + ctrl->banks[chipnr]); > + > + ret = nand_scan(nand, 1); Why 1 here? > + if (ret) > + return ret; > + > + ret = mtd_device_register(mtd, NULL, 0); > + if (ret) { > + dev_err(dev, "mtd device register failed: %d\n", ret); > + nand_release(nand); > + return ret; > + } > + > + list_add_tail(&node->chip_list, &ctrl->chips); > + > + return 0; > +} > + > +static int rk_nandc_cleanup_chips(struct rk_nand_controller *ctrl) > +{ > + struct rk_nand_chip *node; > + struct mtd_info *mtd; > + int ret; > + > + while (!list_empty(&ctrl->chips)) { > + node = list_first_entry(&ctrl->chips, struct rk_nand_chip, > + chip_list); > + mtd = nand_to_mtd(&node->nand); > + ret = mtd_device_unregister(mtd); > + if (ret) > + return ret; > + > + rk_nandc_free_buffer(&node->nand); > + nand_cleanup(&node->nand); > + list_del(&node->chip_list); > + } > + > + return 0; > +} > + > +static int rk_nandc_chips_init(struct device *dev, > + struct rk_nand_controller *ctrl) > +{ > + struct device_node *np = dev->of_node; > + struct device_node *nand_np; > + int nchips = of_get_child_count(np); > + int i = 0; > + int ret; > + > + if (nchips > NANDC_NUM_BANKS) { > + dev_err(dev, "too many NAND chips: %d (max = 4)\n", nchips); > + return -EINVAL; > + } > + > + for_each_child_of_node(np, nand_np) { > + ret = rk_nandc_chip_init(dev, ctrl, nand_np, i); > + if (ret) { > + rk_nandc_cleanup_chips(ctrl); > + of_node_put(nand_np); > + return ret; > + } > + i++; > + } > + > + return 0; > +} > + > +static int rk_nandc_probe(struct platform_device *pdev) > +{ > + const struct rk_nandc_data *data; > + struct device *dev = &pdev->dev; > + struct device_node *node; > + int id; > + int ret; > + > + data = of_device_get_match_data(&pdev->dev); > + if (!data) > + return -ENODEV; > + > + node = pdev->dev.of_node; > + > + id = of_alias_get_id(node, "nandc"); > + if (id < 0) > + id = g_id_counter; > + if ((id >= ARRAY_SIZE(g_nandc_info) || g_nandc_info[id].regs)) { > + dev_err( > + &pdev->dev, > + "failed to get id for nandc node '%pOFn'\n", > + node); > + of_node_put(node); > + return -ENODEV; > + } > + ++g_id_counter; > + > + g_nandc_info[id].version = data->version; > + > + g_nandc_info[id].regs = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(g_nandc_info[id].regs)) { > + dev_err(dev, "ioremap failed\n"); > + return PTR_ERR(g_nandc_info[id].regs); > + } > + > + g_nandc_info[id].irq = platform_get_irq(pdev, 0); > + if (g_nandc_info[id].irq < 0) { > + dev_err(dev, "get irq failed\n"); > + return g_nandc_info[id].irq; > + } > + > + g_nandc_info[id].hclk = devm_clk_get(dev, "hclk_nandc"); > + if (IS_ERR(g_nandc_info[id].hclk)) { > + dev_err(dev, "get hclk_nandc failed\n"); > + return PTR_ERR(g_nandc_info[id].hclk); > + } > + > + ret = clk_prepare_enable(g_nandc_info[id].hclk); > + if (ret) > + return ret; > + > + g_nandc_info[id].clk = devm_clk_get(dev, "clk_nandc"); > + if (!(IS_ERR(g_nandc_info[id].clk))) { > + clk_set_rate(g_nandc_info[id].clk, 150 * 1000 * 1000); > + > + ret = clk_prepare_enable(g_nandc_info[id].clk); > + if (ret) > + goto err_disable_hclk; > + } else > + dev_err(dev, "get clk_nandc failed\n"); > + > + if (g_nandc_info[id].version == VERSION_9) > + writel(0, g_nandc_info[id].regs + NANDC_REG_V9_INTEN); > + else > + writel(0, g_nandc_info[id].regs + NANDC_REG_V6_INTEN); > + ret = devm_request_irq(dev, g_nandc_info[id].irq, rk_nandc_interrupt, > + 0, "nandc", &g_nandc_info[id]); > + if (ret) > + goto err_disable_clk; > + > + nand_controller_init(&g_nandc_info[id].controller); > + INIT_LIST_HEAD(&g_nandc_info[id].chips); > + > + rk_nandc_init(&g_nandc_info[id]); > + > + ret = rk_nandc_chips_init(dev, &g_nandc_info[id]); > + if (ret) { > + dev_err(dev, "init nand chips failed\n"); > + goto err_disable_clk; > + } > + > + platform_set_drvdata(pdev, &g_nandc_info[id]); > + > + return 0; > + > +err_disable_clk: > + clk_disable_unprepare(g_nandc_info[id].clk); > +err_disable_hclk: > + clk_disable_unprepare(g_nandc_info[id].hclk); > + > + return ret; > +} > + > +static int rk_nandc_remove(struct platform_device *pdev) > +{ > + struct rk_nand_controller *ctrl = platform_get_drvdata(pdev); > + int ret; > + > + ret = rk_nandc_cleanup_chips(ctrl); > + if (ret) > + return ret; > + > + clk_disable_unprepare(ctrl->clk); > + clk_disable_unprepare(ctrl->hclk); > + platform_set_drvdata(pdev, NULL); > + > + return 0; > +} > + > +static void rk_nandc_shutdown(struct platform_device *pdev) > +{ > + struct rk_nand_controller *ctrl = platform_get_drvdata(pdev); > + int ret; > + > + ret = rk_nandc_cleanup_chips(ctrl); > + if (ret) > + return; > + > + clk_disable_unprepare(ctrl->clk); > + clk_disable_unprepare(ctrl->hclk); > + platform_set_drvdata(pdev, NULL); > +} > + > +static const struct rk_nandc_data rk_nandc_v6_data = { > + .version = VERSION_6, > +}; > + > +static const struct rk_nandc_data rk_nandc_v9_data = { > + .version = VERSION_9, > +}; > + > +static const struct of_device_id of_rk_nandc_match[] = { > + { > + .compatible = "rockchip,nandc-v6", > + .data = &rk_nandc_v6_data, > + }, > + { > + .compatible = "rockchip,nandc-v9", > + .data = &rk_nandc_v9_data, > + }, > + { /* sentinel */ }, > +}; > + > +static struct platform_driver rk_nandc_driver = { > + .probe = rk_nandc_probe, > + .remove = rk_nandc_remove, > + .shutdown = rk_nandc_shutdown, > + .driver = { > + .name = "rockchip-nandc", > + .of_match_table = of_rk_nandc_match, > + }, > +}; > + Move this empty line... > +module_platform_driver(rk_nandc_driver); ...Here > +MODULE_LICENSE("GPL v2"); Thanks, Miquèl 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=-13.3 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, MENTIONS_GIT_HOSTING,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,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 0D9F8C33CA2 for ; Fri, 10 Jan 2020 11:05:54 +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 CB9132077C for ; Fri, 10 Jan 2020 11:05:53 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="RFQZyDPA" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org CB9132077C 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=c4XbxK4jr3iS0RcXWLFXkugYZ7rszvZfXafUyqVOe1E=; b=RFQZyDPAmjzub0 i8vU1mRY7Ljk6onboVViGAmMehT6LusKhXD93NK18kUjhhI3Zorym0uK1N18Y4k4S6bG/RzrlfJoS fK3kYnWBYnKK1nEDka13Ae/GJ8JNuhvQ+NIg+kPy/lqxHKAT/Byoa5I8ccpe/Tk7QYmmrRYgwJejj r1VLv8JW0WTQ1SvylDmSk8eE0dgREEzOqejx//LL3LjpDz8vsrPALDFKi5gpwL40/cYcYZ3r6dZol oR6JEYjkqzHzmg3LtZwjjARvDXlkczTehHEDjRxvJZQO9gpBP236KmmQK2AM0I5H/uhorP1m7x1J7 xepMn+GACL2D6YJg94lw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1ips6z-0000XN-Ci; Fri, 10 Jan 2020 11:05:53 +0000 Received: from relay7-d.mail.gandi.net ([217.70.183.200]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1ips6t-0000Up-9G; Fri, 10 Jan 2020 11:05:51 +0000 X-Originating-IP: 91.224.148.103 Received: from xps13 (unknown [91.224.148.103]) (Authenticated sender: miquel.raynal@bootlin.com) by relay7-d.mail.gandi.net (Postfix) with ESMTPSA id 006AD20011; Fri, 10 Jan 2020 11:05:35 +0000 (UTC) Date: Fri, 10 Jan 2020 12:05:34 +0100 From: Miquel Raynal To: Johan Jonker Subject: Re: [RFC PATCH v1 02/10] mtd: nand: raw: add rockchip nand controller driver Message-ID: <20200110120534.1b4026b0@xps13> In-Reply-To: <20200108205338.11369-3-jbx6244@gmail.com> References: <20200108205338.11369-1-jbx6244@gmail.com> <20200108205338.11369-3-jbx6244@gmail.com> Organization: Bootlin X-Mailer: Claws Mail 3.17.4 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200110_030547_758867_37DFCA52 X-CRM114-Status: GOOD ( 28.28 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, vigneshr@ti.com, richard@nod.at, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org, robh+dt@kernel.org, linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, heiko@sntech.de 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 SGkgSm9oYW4sCgpKb2hhbiBKb25rZXIgPGpieDYyNDRAZ21haWwuY29tPiB3cm90ZSBvbiBXZWQs ICA4IEphbiAyMDIwIDIxOjUzOjMwCiswMTAwOgoKPiBGcm9tOiBZaWZlbmcgWmhhbyA8enlmQHJv Y2stY2hpcHMuY29tPgo+IAoKQ2FuIHlvdSBjaGFuZ2UgdGhlIHRpdGxlIHRvICJtdGQ6IHJhd25h bmQ6IHJvY2tjaGlwOiBBZGQgTkFORApjb250cm9sbGVyIGRyaXZlciIKCj4gQWRkIGJhc2ljIFJv Y2tjaGlwIG5hbmQgY29udHJvbGxlciBkcml2ZXIuCj4gCj4gQ29tcGF0aWJsZSB3aXRoIGhhcmR3 YXJlIHZlcnNpb24gNiBhbmQgOS4KPiBWNjoxNiwgMjQsIDQwLCA2MCBwZXIgMTAyNEIgQkNIL0VD Qy4KPiBWOToxNiwgNDAsIDYwLCA3MCBwZXIgMTAyNEIgQkNIL0VDQy4KPiA4IGJpdCBhc3luY2hy b25vdXMgZmxhc2ggaW50ZXJmYWNlIHN1cHBvcnQuCj4gU3VwcG9ydHMgdXAgdG8gMiBpZGVudGlj YWwgbmFuZGMgbm9kZXMuCj4gTWF4IDQgbmFuZCBjaGlwcyBwZXIgY29udHJvbGxlci4KPiBBYmxl IHRvIHNlbGVjdCBhIGRpZmZlcmVudCBoYXJkd2FyZSBlY2Mgc2V0dXAKPiBmb3IgdGhlIGxvYWRl ciBibG9ja3MuCj4gTm8gYmFkIGJsb2NrIHN1cHBvcnQuCgpUaGFuayB5b3UgdmVyeSBtdWNoIGZv ciB0aGlzIHNlcmllcywgYXMgdGhlIGJhZCBibG9ja3Mgc3VwcG9ydCBpcwphYnNvbHV0ZWx5IGZ1 bmRhbWVudGFsLCBJIHdvbmRlciB3aGF0IGlzIHRoZSBpc3N1ZSBoZXJlPwoKPiAKPiBTaWduZWQt b2ZmLWJ5OiBZaWZlbmcgWmhhbyA8enlmQHJvY2stY2hpcHMuY29tPgo+IFNpZ25lZC1vZmYtYnk6 IEpvaGFuIEpvbmtlciA8amJ4NjI0NEBnbWFpbC5jb20+Cj4gLS0tCj4gIGRyaXZlcnMvbXRkL25h bmQvcmF3L0tjb25maWcgICAgICAgICAgfCAgICA4ICsKPiAgZHJpdmVycy9tdGQvbmFuZC9yYXcv TWFrZWZpbGUgICAgICAgICB8ICAgIDEgKwo+ICBkcml2ZXJzL210ZC9uYW5kL3Jhdy9yb2NrY2hp cF9uYW5kYy5jIHwgMTIyNCArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKPiAgMyBm aWxlcyBjaGFuZ2VkLCAxMjMzIGluc2VydGlvbnMoKykKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRy aXZlcnMvbXRkL25hbmQvcmF3L3JvY2tjaGlwX25hbmRjLmMKPiAKPiBkaWZmIC0tZ2l0IGEvZHJp dmVycy9tdGQvbmFuZC9yYXcvS2NvbmZpZyBiL2RyaXZlcnMvbXRkL25hbmQvcmF3L0tjb25maWcK PiBpbmRleCA3NGZiOTFhZGUuLjY4ZGM5YTM2ZCAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL210ZC9u YW5kL3Jhdy9LY29uZmlnCj4gKysrIGIvZHJpdmVycy9tdGQvbmFuZC9yYXcvS2NvbmZpZwo+IEBA IC00NTcsNiArNDU3LDE0IEBAIGNvbmZpZyBNVERfTkFORF9DQURFTkNFCj4gIAkgIEVuYWJsZSB0 aGUgZHJpdmVyIGZvciBOQU5EIGZsYXNoIG9uIHBsYXRmb3JtcyB1c2luZyBhIENhZGVuY2UgTkFO RAo+ICAJICBjb250cm9sbGVyLgo+ICAKPiArY29uZmlnIE1URF9OQU5EX1JPQ0tDSElQCj4gKwl0 cmlzdGF0ZSAiUm9ja2NoaXAgcmF3IE5BTkQgY29udHJvbGxlciBkcml2ZXIiCj4gKwlkZXBlbmRz IG9uIEFSQ0hfUk9DS0NISVAgfHwgQ09NUElMRV9URVNUCj4gKwlkZXBlbmRzIG9uIEhBU19JT01F TQo+ICsJaGVscAo+ICsJICBFbmFibGVzIHN1cHBvcnQgZm9yIHRoZSBSb2NrY2hpcCByYXcgTkFO RCBjb250cm9sbGVyIGRyaXZlci4KPiArCSAgVGhpcyBjb250cm9sbGVyIGlzIGZvdW5kIG9uIHJr MzA2NiwgcmszMTg4LCByazMyODggYW5kIG1vcmUuCgpDYW4geW91IHdyaXRlIGFuIGV4aGF1c3Rp dmUgbGlzdCBpZiB5b3Uga25vdyBpdD8gT3IgYXQgbGVhc3QgdGhlCmZhbWlsaWVzPyBJdCBpcyBx dWl0ZSBjaGFsbGVuZ2luZyB3aGVuIHlvdSBhcmUgbm90IGluIHRoZSBSb2NrY2hpcAp3b3JsZCB0 byBrbm93IHdoYXQgU29DIGlzIHNpbWlsYXIgdG8gYW5vdGhlciByYW5kb20gU29DLgogCj4gKwo+ ICBjb21tZW50ICJNaXNjIgo+ICAKPiAgY29uZmlnIE1URF9TTV9DT01NT04KPiBkaWZmIC0tZ2l0 IGEvZHJpdmVycy9tdGQvbmFuZC9yYXcvTWFrZWZpbGUgYi9kcml2ZXJzL210ZC9uYW5kL3Jhdy9N YWtlZmlsZQo+IGluZGV4IDJkMTM2YjE1OC4uMzA2M2ZlNzRhIDEwMDY0NAo+IC0tLSBhL2RyaXZl cnMvbXRkL25hbmQvcmF3L01ha2VmaWxlCj4gKysrIGIvZHJpdmVycy9tdGQvbmFuZC9yYXcvTWFr ZWZpbGUKPiBAQCAtNTgsNiArNTgsNyBAQCBvYmotJChDT05GSUdfTVREX05BTkRfVEVHUkEpCQkr PSB0ZWdyYV9uYW5kLm8KPiAgb2JqLSQoQ09ORklHX01URF9OQU5EX1NUTTMyX0ZNQzIpCSs9IHN0 bTMyX2ZtYzJfbmFuZC5vCj4gIG9iai0kKENPTkZJR19NVERfTkFORF9NRVNPTikJCSs9IG1lc29u X25hbmQubwo+ICBvYmotJChDT05GSUdfTVREX05BTkRfQ0FERU5DRSkJCSs9IGNhZGVuY2UtbmFu ZC1jb250cm9sbGVyLm8KPiArb2JqLSQoQ09ORklHX01URF9OQU5EX1JPQ0tDSElQKQkJKz0gcm9j a2NoaXBfbmFuZGMubwoKQSBkcml2ZXIgbmFtZWQgcm9ja2NoaXAtbmFuZC1jb250cm9sbGVyLmMg d291bGQgYmUgbmljZSEKCj4gIAo+ICBuYW5kLW9ianMgOj0gbmFuZF9iYXNlLm8gbmFuZF9sZWdh Y3kubyBuYW5kX2JidC5vIG5hbmRfdGltaW5ncy5vIG5hbmRfaWRzLm8KPiAgbmFuZC1vYmpzICs9 IG5hbmRfb25maS5vCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbXRkL25hbmQvcmF3L3JvY2tjaGlw X25hbmRjLmMgYi9kcml2ZXJzL210ZC9uYW5kL3Jhdy9yb2NrY2hpcF9uYW5kYy5jCj4gbmV3IGZp bGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAuLjAxODMwOGU1OAo+IC0tLSAvZGV2L251 bGwKPiArKysgYi9kcml2ZXJzL210ZC9uYW5kL3Jhdy9yb2NrY2hpcF9uYW5kYy5jCj4gQEAgLTAs MCArMSwxMjI0IEBACj4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wCj4gKy8q Cj4gKyAqIEJhc2VkIG9uOgo+ICsgKiBodHRwczovL2dpdGh1Yi5jb20vcm9ja2NoaXAtbGludXgv a2VybmVsL2Jsb2IvZGV2ZWxvcC00LjQvZHJpdmVycy9tdGQvbmFuZC8KPiArICogICAgICAgICBy b2NrY2hpcF9uYW5kX3Y2LmMKPiArICogaHR0cHM6Ly9naXRodWIuY29tL3JvY2tjaGlwLWxpbnV4 L2tlcm5lbC9ibG9iL2RldmVsb3AtNC40L2RyaXZlcnMvbXRkL25hbmQvCj4gKyAqICAgICAgICAg cm9ja2NoaXBfbmFuZF92OS5jCgpJJ20gbm90IHN1cmUgdGhlIGVudGlyZSBsaW5rIGlzIHJlbGV2 YW50LCBJIHdvdWxkIHNpbXBsZSBtZW50aW9uIHRoZQpSb2NrY2hpcCBvZmZpY2lhbCBHaXRodWIg cmVwb3NpdG9yeSBhbmQgd29yayBmcm9tIFlpZmVuZy4KCj4gKyAqIENvcHlyaWdodCAoYykgMjAx Ni0yMDE5IFlpZmVuZyBaaGFvIHlpZmVuZy56aGFvQHJvY2stY2hpcHMuY29tCj4gKyAqCj4gKyAq IFVwZGF0ZS9yZXN0eWxlIGZvciBsaW51eC1uZXh0Lgo+ICsgKiBBZGQgZXhlY19vcCBmdW5jdGlv bi4KCllvdSBjYW4gZHJvcCB0aGVzZSB0d28gbGluZXMgdG9vLiBUaGlzIGlzIG1vcmUgYSAiY29t bWl0IGRlc2NyaXB0aW9uIgp0aGluZy4KCj4gKyAqIENvbWJpbmUgZHJpdmVyIGZvciBuYW5kYyB2 ZXJzaW9uIDYgYW5kIDkuCgogICAgICBTdXBwb3J0IE5BTkQgY29udHJvbGxlciB2ZXJzaW9ucyA2 IGFuZCA5IGZvdW5kIG9uIFNvQ3MgLi4uCgo+ICsgKiBDb3B5cmlnaHQgKGMpIDIwMjAgSm9oYW4g Sm9ua2VyIGpieDYyNDRAZ21haWwuY29tCj4gKyAqLwo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L2Ns ay5oPgo+ICsjaW5jbHVkZSA8bGludXgvZG1hLW1hcHBpbmcuaD4KPiArI2luY2x1ZGUgPGxpbnV4 L2ludGVycnVwdC5oPgo+ICsjaW5jbHVkZSA8bGludXgvaW9wb2xsLmg+Cj4gKyNpbmNsdWRlIDxs aW51eC9tb2R1bGUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L29mX2RldmljZS5oPgo+ICsjaW5jbHVk ZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4gKwo+ICsjaW5jbHVkZSA8bGludXgvbXRkL3Jh d25hbmQuaD4KPiArCj4gKyNkZWZpbmUgTkFORENfSURfVjYwMAkJCTB4NTYzNjMwMzAKPiArI2Rl ZmluZSBOQU5EQ19JRF9WNjIyCQkJMHg1NjM2MzIzMgo+ICsjZGVmaW5lIE5BTkRDX0lEX1Y3MDEJ CQkweDcwMQo+ICsjZGVmaW5lIE5BTkRDX0lEX1Y4MDAJCQkweDU2MzgzMDMwCj4gKyNkZWZpbmUg TkFORENfSURfVjgwMQkJCTB4ODAxCj4gKyNkZWZpbmUgTkFORENfSURfVjkwMAkJCTB4NTYzOTMw MzAKCkkgd291bGQgcHJlZmVyIHByZWZpeGluZyBldmVyeXRoaW5nIFJLX05BTkRDXyBvciBSS18K Cj4gKwo+ICsjZGVmaW5lIE5BTkRDX0lEQlJlc0Jsa051bQkJMTYKPiArI2RlZmluZSBOQU5EQ19J REJFY2NCaXRzCQkyNAo+ICsjZGVmaW5lIE5BTkRDX0lEQlN0YXJ0QWRkcgkJMAo+ICsKPiArI2Rl ZmluZSBOQU5EQ19WNl9FQ0NfMTYJCQkweDAwMDAwMDAwCj4gKyNkZWZpbmUgTkFORENfVjZfRUND XzI0CQkJMHgwMDAwMDAxMAo+ICsjZGVmaW5lIE5BTkRDX1Y2X0VDQ180MAkJCTB4MDAwNDAwMDAK PiArI2RlZmluZSBOQU5EQ19WNl9FQ0NfNjAJCQkweDAwMDQwMDEwCj4gKwo+ICsjZGVmaW5lIE5B TkRDX1Y5X0VDQ18xNgkJCTB4MDIwMDAwMDEKPiArI2RlZmluZSBOQU5EQ19WOV9FQ0NfNDAJCQkw eDA0MDAwMDAxCj4gKyNkZWZpbmUgTkFORENfVjlfRUNDXzYwCQkJMHgwNjAwMDAwMQo+ICsjZGVm aW5lIE5BTkRDX1Y5X0VDQ183MAkJCTB4MDAwMDAwMDEKPiArCj4gKyNkZWZpbmUgTkFORENfTlVN X0JBTktTCQkJNAo+ICsjZGVmaW5lIE5BTkRDX0RFRl9USU1FT1VUCQkxMDAwMAo+ICsKPiArI2Rl ZmluZSBOQU5EQ19SRUdfREFUQQkJCTB4MDAKPiArI2RlZmluZSBOQU5EQ19SRUdfQUREUgkJCTB4 MDQKPiArI2RlZmluZSBOQU5EQ19SRUdfQ01ECQkJMHgwOAo+ICsKPiArLyogcmVnaXN0ZXIgb2Zm c2V0IG5hbmRjIHZlcnNpb24gNiAqLwo+ICsjZGVmaW5lIE5BTkRDX1JFR19WNl9GTUNUTAkJMHgw MAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WNl9GTVdBSVQJCTB4MDQKPiArI2RlZmluZSBOQU5EQ19S RUdfVjZfRkxDVEwJCTB4MDgKPiArI2RlZmluZSBOQU5EQ19SRUdfVjZfQkNIQ1RMCQkweDBjCj4g KyNkZWZpbmUgTkFORENfUkVHX1Y2X0RNQV9DRkcJCTB4MTAKPiArI2RlZmluZSBOQU5EQ19SRUdf VjZfRE1BX0JVRjAJCTB4MTQKPiArI2RlZmluZSBOQU5EQ19SRUdfVjZfRE1BX0JVRjEJCTB4MTgK PiArI2RlZmluZSBOQU5EQ19SRUdfVjZfRE1BX1NUCQkweDFDCj4gKyNkZWZpbmUgTkFORENfUkVH X1Y2X0JDSFNUCQkweDIwCj4gKyNkZWZpbmUgTkFORENfUkVHX1Y2X1JBTkRNWgkJMHgxNTAKPiAr I2RlZmluZSBOQU5EQ19SRUdfVjZfVkVSCQkweDE2MAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WNl9J TlRFTgkJMHgxNkMKPiArI2RlZmluZSBOQU5EQ19SRUdfVjZfSU5UQ0xSCQkweDE3MAo+ICsjZGVm aW5lIE5BTkRDX1JFR19WNl9JTlRTVAkJMHgxNzQKPiArI2RlZmluZSBOQU5EQ19SRUdfVjZfU1BB UkUwCQkweDIwMAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WNl9TUEFSRTEJCTB4MjMwCj4gKwo+ICsv KiByZWdpc3RlciBvZmZzZXQgbmFuZGMgdmVyc2lvbiA5ICovCj4gKyNkZWZpbmUgTkFORENfUkVH X1Y5X0ZNQ1RMCQkweDAwCj4gKyNkZWZpbmUgTkFORENfUkVHX1Y5X0ZNV0FJVAkJMHgwNAo+ICsj ZGVmaW5lIE5BTkRDX1JFR19WOV9GTENUTAkJMHgxMAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WOV9C Q0hDVEwJCTB4MjAKPiArI2RlZmluZSBOQU5EQ19SRUdfVjlfRE1BX0NGRwkJMHgzMAo+ICsjZGVm aW5lIE5BTkRDX1JFR19WOV9ETUFfQlVGMAkJMHgzNAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WOV9E TUFfQlVGMQkJMHgzOAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WOV9ETUFfU1QJCTB4NDAKPiArI2Rl ZmluZSBOQU5EQ19SRUdfVjlfVkVSCQkweDgwCj4gKyNkZWZpbmUgTkFORENfUkVHX1Y5X0lOVEVO CQkweDEyMAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WOV9JTlRDTFIJCTB4MTI0Cj4gKyNkZWZpbmUg TkFORENfUkVHX1Y5X0lOVFNUCQkweDEyOAo+ICsjZGVmaW5lIE5BTkRDX1JFR19WOV9CQ0hTVAkJ MHgxNTAKPiArI2RlZmluZSBOQU5EQ19SRUdfVjlfU1BBUkUwCQkweDIwMAo+ICsjZGVmaW5lIE5B TkRDX1JFR19WOV9TUEFSRTEJCTB4MjA0Cj4gKyNkZWZpbmUgTkFORENfUkVHX1Y5X1JBTkRNWgkJ MHgyMDgKPiArCj4gKy8qIHJlZ2lzdGVyIG9mZnNldCBuYW5kYyBjb21tb24gKi8KPiArI2RlZmlu ZSBOQU5EQ19SRUdfQkFOSzAJCQkweDgwMAo+ICsjZGVmaW5lIE5BTkRDX1JFR19TUkFNMAkJCTB4 MTAwMAo+ICsKPiArLyogRk1DVEwgKi8KPiArI2RlZmluZSBOQU5EQ19WNl9GTV9XUAkJCUJJVCg4 KQo+ICsjZGVmaW5lIE5BTkRDX1Y2X0ZNX0NFX1NFTF9NCQkweEZGCj4gKyNkZWZpbmUgTkFORENf VjZfRk1fQ0VfU0VMKHgpCQkoMSA8PCAoeCkpCj4gKyNkZWZpbmUgTkFORENfVjZfRk1fRlJFQURZ CQlCSVQoOSkKPiArCj4gKyNkZWZpbmUgTkFORENfVjlfRk1fV1AJCQlCSVQoOCkKPiArI2RlZmlu ZSBOQU5EQ19WOV9GTV9DRV9TRUxfTQkJMHhGRgo+ICsjZGVmaW5lIE5BTkRDX1Y5X0ZNX0NFX1NF TCh4KQkJKDEgPDwgKHgpKQo+ICsjZGVmaW5lIE5BTkRDX1Y5X1JEWQkJCUJJVCg5KQo+ICsKPiAr LyogRkxDVEwgKi8KPiArI2RlZmluZSBOQU5EQ19WNl9GTF9SU1QJCQlCSVQoMCkKPiArI2RlZmlu ZSBOQU5EQ19WNl9GTF9ESVIoeCkJCSgoeCkgPyBCSVQoMSkgOiAwKQo+ICsjZGVmaW5lIE5BTkRD X1Y2X0ZMX1hGRVJfU1RBUlQJCUJJVCgyKQo+ICsjZGVmaW5lIE5BTkRDX1Y2X0ZMX1hGRVJfRU4J CUJJVCgzKQo+ICsjZGVmaW5lIE5BTkRDX1Y2X0ZMX1NUX0JVRl9TCQkweDQKPiArI2RlZmluZSBO QU5EQ19WNl9GTF9YRkVSX0NPVU5UCQlCSVQoNSkKPiArI2RlZmluZSBOQU5EQ19WNl9GTF9BQ09S UkVDVAkJQklUKDEwKQo+ICsjZGVmaW5lIE5BTkRDX1Y2X0ZMX1hGRVJfUkVBRFkJCUJJVCgyMCkK PiArI2RlZmluZSBOQU5EQ19WNl9GTF9QQUdFX05VTSh4KQkJKCh4KSA8PCAyMikKPiArI2RlZmlu ZSBOQU5EQ19WNl9GTF9BU1lOQ19UT0dfTUlYCUJJVCgyOSkKPiArCj4gKyNkZWZpbmUgTkFORENf VjlfRkxfUlNUCQkJQklUKDApCj4gKyNkZWZpbmUgTkFORENfVjlfRkxfRElSKHgpCQkoKHgpID8g QklUKDEpIDogMCkKPiArI2RlZmluZSBOQU5EQ19WOV9GTF9YRkVSX1NUQVJUCQlCSVQoMikKPiAr I2RlZmluZSBOQU5EQ19WOV9GTF9YRkVSX0VOCQlCSVQoMykKPiArI2RlZmluZSBOQU5EQ19WOV9G TF9TVF9CVUZfUwkJMHg0Cj4gKyNkZWZpbmUgTkFORENfVjlfRkxfWEZFUl9DT1VOVAkJQklUKDUp Cj4gKyNkZWZpbmUgTkFORENfVjlfRkxfQUNPUlJFQ1QJCUJJVCgxMCkKPiArI2RlZmluZSBOQU5E Q19WOV9GTF9YRkVSX1JFQURZCQlCSVQoMjApCj4gKyNkZWZpbmUgTkFORENfVjlfRkxfUEFHRV9O VU0oeCkJCSgoeCkgPDwgMjIpCj4gKyNkZWZpbmUgTkFORENfVjlfRkxfQVNZTkNfVE9HX01JWAlC SVQoMjkpCj4gKwo+ICsvKiBCQ0hDVEwgKi8KPiArI2RlZmluZSBOQU5EX1Y2X0JDSF9SRUdJT05f UwkJMHg1Cj4gKyNkZWZpbmUgTkFORF9WNl9CQ0hfUkVHSU9OX00JCTB4Nwo+ICsKPiArI2RlZmlu ZSBOQU5EX1Y5X0JDSF9NT0RFX1MJCTI1Cj4gKyNkZWZpbmUgTkFORF9WOV9CQ0hfTU9ERV9NCQkw eDcKPiArCj4gKy8qIEJDSFNUICovCj4gKyNkZWZpbmUgTkFORENfVjZfQkNIMF9TVF9FUlIJCUJJ VCgyKQo+ICsjZGVmaW5lIE5BTkRDX1Y2X0JDSDFfU1RfRVJSCQlCSVQoMTUpCj4gKyNkZWZpbmUg TkFORENfVjZfRUNDX0VSUl9DTlQwKHgpCSgoKCh4ICYgKDB4MUYgPDwgMykpID4+IDMpIFwKPiAr CQkJCQl8ICgoeCAmICgxIDw8IDI3KSkgPj4gMjIpKSAmIDB4M0YpCj4gKyNkZWZpbmUgTkFORENf VjZfRUNDX0VSUl9DTlQxKHgpCSgoKCh4ICYgKDB4MUYgPDwgMTYpKSA+PiAxNikgXAo+ICsJCQkJ CXwgKCh4ICYgKDEgPDwgMjkpKSA+PiAyNCkpICYgMHgzRikKPiArCj4gKyNkZWZpbmUgTkFORENf VjlfQkNIMF9TVF9FUlIJCUJJVCgyKQo+ICsjZGVmaW5lIE5BTkRDX1Y5X0JDSDFfU1RfRVJSCQlC SVQoMTgpCj4gKyNkZWZpbmUgTkFORENfVjlfRUNDX0VSUl9DTlQwKHgpCSgoKHgpICYgKDB4N0Yg PDwgMykpID4+IDMpCj4gKyNkZWZpbmUgTkFORENfVjlfRUNDX0VSUl9DTlQxKHgpCSgoKHgpICYg KDB4N0YgPDwgMTkpKSA+PiAxOSkKPiArCj4gKy8qIERNQV9DRkcgKi8KPiArI2RlZmluZSBOQU5E Q19WNl9ETUFfQ0ZHX1dSX1NUCQlCSVQoMCkKPiArI2RlZmluZSBOQU5EQ19WNl9ETUFfQ0ZHX1dS KHgpCQkoKCF4KSA/IEJJVCgxKSA6IDApCj4gKyNkZWZpbmUgTkFORENfVjZfRE1BX0NGR19CVVNf TU9ERQlCSVQoMikKPiArCj4gKyNkZWZpbmUgTkFORENfVjZfRE1BX0NGR19IU0laRV84CTAKPiAr I2RlZmluZSBOQU5EQ19WNl9ETUFfQ0ZHX0hTSVpFXzE2CSgxIDw8IDMpCj4gKyNkZWZpbmUgTkFO RENfVjZfRE1BX0NGR19IU0laRV8zMgkoMiA8PCAzKQo+ICsKPiArI2RlZmluZSBOQU5EQ19WNl9E TUFfQ0ZHX0JVUlNUXzEJMAo+ICsjZGVmaW5lIE5BTkRDX1Y2X0RNQV9DRkdfQlVSU1RfNAkoMyA8 PCA2KQo+ICsjZGVmaW5lIE5BTkRDX1Y2X0RNQV9DRkdfQlVSU1RfOAkoNSA8PCA2KQo+ICsjZGVm aW5lIE5BTkRDX1Y2X0RNQV9DRkdfQlVSU1RfMTYJKDcgPDwgNikKPiArCj4gKyNkZWZpbmUgTkFO RENfVjZfRE1BX0NGR19JTkNSX05VTSh4KQkoKHgpIDw8IDkpCj4gKwo+ICsjZGVmaW5lIE5BTkRD X1Y5X0RNQV9DRkdfV1JfU1QJCUJJVCgwKQo+ICsjZGVmaW5lIE5BTkRDX1Y5X0RNQV9DRkdfV1Io eCkJCSgoIXgpID8gQklUKDEpIDogMCkKPiArI2RlZmluZSBOQU5EQ19WOV9ETUFfQ0ZHX0JVU19N T0RFCUJJVCgyKQo+ICsKPiArI2RlZmluZSBOQU5EQ19WOV9ETUFfQ0ZHX0hTSVpFXzgJMAo+ICsj ZGVmaW5lIE5BTkRDX1Y5X0RNQV9DRkdfSFNJWkVfMTYJKDEgPDwgMykKPiArI2RlZmluZSBOQU5E Q19WOV9ETUFfQ0ZHX0hTSVpFXzMyCSgyIDw8IDMpCj4gKwo+ICsjZGVmaW5lIE5BTkRDX1Y5X0RN QV9DRkdfQlVSU1RfMQkwCj4gKyNkZWZpbmUgTkFORENfVjlfRE1BX0NGR19CVVJTVF80CSgzIDw8 IDYpCj4gKyNkZWZpbmUgTkFORENfVjlfRE1BX0NGR19CVVJTVF84CSg1IDw8IDYpCj4gKyNkZWZp bmUgTkFORENfVjlfRE1BX0NGR19CVVJTVF8xNgkoNyA8PCA2KQo+ICsKPiArI2RlZmluZSBOQU5E Q19WOV9ETUFfQ0ZHX0lOQ1JfTlVNKHgpCSgoeCkgPDwgOSkKPiArCj4gKy8qIElOVEVOICovCj4g KyNkZWZpbmUgTkFORENfVjZfSU5UX0RNQQkJQklUKDApCj4gKwo+ICsjZGVmaW5lIE5BTkRDX1Y5 X0lOVF9ETUEJCUJJVCgwKQo+ICsKPiArZW51bSBya19uYW5kY192ZXJzaW9uIHsKPiArCVZFUlNJ T05fNiA9IDYsCj4gKwlWRVJTSU9OXzkgPSA5LAo+ICt9Owo+ICsKPiArc3RydWN0IHJrX25hbmRj X2RhdGEgewo+ICsJZW51bSBya19uYW5kY192ZXJzaW9uIHZlcnNpb247CgpJZiB5b3UgbWFrZSBh IGRpc3RpbmN0aW9uIGJldHdlZW4gYm90aCB2ZXJzaW9uLCBtYXliZSB5b3UgY2FuIGFkZCBtb3Jl CnBhcmFtZXRlcnMgaGVyZSBhbmQgZG8KCglmb28gPSBkYXRhLT5wYXJhbQoKaW5zdGVhZCBvZgoK CWlmIChkYXRhLT52ZXJzaW9uID09IDYpCgkJZm9vID0gdGhpczsKCWVsc2UKCQlmb28gPSB0aGF0 OwoKPiArfTsKPiArCj4gK3N0cnVjdCBya19uYW5kX2NvbnRyb2xsZXIgewo+ICsJdm9pZCBfX2lv bWVtICpyZWdzOwo+ICsJaW50IGlycTsKPiArCXN0cnVjdCBjbGsgKmhjbGs7Cj4gKwlzdHJ1Y3Qg Y2xrICpjbGs7Cj4gKwlzdHJ1Y3QgbGlzdF9oZWFkIGNoaXBzOwo+ICsJc3RydWN0IGNvbXBsZXRp b24gY29tcGxldGU7Cj4gKwlzdHJ1Y3QgbmFuZF9jb250cm9sbGVyIGNvbnRyb2xsZXI7Cj4gKwlp bnQgYmFua3NbTkFORENfTlVNX0JBTktTXTsKCj4gKwlib29sIGJvb3Ryb21ibG9ja3M7Cj4gKwlp bnQgZWNjX21vZGU7Cj4gKwl1aW50MzJfdCBlY2Nfc3RyZW5ndGg7Cj4gKwlpbnQgbWF4X2VjY19z dHJlbmd0aDsKCkkgaGF2ZSBub3QgcmVhZCB5ZXQgdGhlIGVudGlyZSBkcml2ZXIgYnV0IEkgYmVs aWV2ZSB0aGUgYWJvdmUgNApwYXJhbWV0ZXJzIHNob3VsZCBwcm9iYWJseSBiZSBtb3ZlZCBpbiBy a19uYW5kX2NoaXAsIHJpZ2h0PyBBbnl0aGluZwp0aGF0IGlzIE5BTkQgY2hpcCByZWxhdGVkIHNo b3VsZCBub3QgYmUgaW4gdGhlIGNvbnRyb2xsZXIgc3RydWN0dXJlLiBJdApkZXBlbmRzIGlmIHlv dSBjYW4gY2hhbmdlIEVDQyByZXF1aXJlbWVudHMgb24gdGhlIGZseSBvciBub3QuCgo+ICsJdWlu dDMyX3QgKm9vYl9idWY7Cj4gKwl1aW50MzJfdCAqcGFnZV9idWY7Cj4gKwlpbnQgc2VsZWN0ZWRf YmFuazsKPiArCWVudW0gcmtfbmFuZGNfdmVyc2lvbiB2ZXJzaW9uOwo+ICt9Owo+ICsKPiArc3Ry dWN0IHJrX25hbmRfY2hpcCB7Cj4gKwlzdHJ1Y3QgbmFuZF9jaGlwIG5hbmQ7Cj4gKwlzdHJ1Y3Qg bGlzdF9oZWFkIGNoaXBfbGlzdDsKPiArfTsKPiArCj4gK3N0YXRpYyBzdHJ1Y3QgcmtfbmFuZF9j b250cm9sbGVyIGdfbmFuZGNfaW5mb1syXTsKCkkgZG9uJ3QgbGlrZSB0aGlzIGlkZWEgc28gbXVj aC4gSSBwcmVmZXIgYSBkeW5hbWljIGFsbG9jYXRpb24gaW4gdGhlCnByb2JlLgoKPiArc3RhdGlj IGludCBnX2lkX2NvdW50ZXI7CgpEb24ndCBrbm93IHdoYXQgdGhpcyBpcyB5ZXQsIGJ1dCBpdCBp cyBwcm9iYWJseSBhIGJhZCBpZGVhIDopCgo+ICsKPiArc3RhdGljIHZvaWQgcmtfbmFuZGNfaW5p dChzdHJ1Y3QgcmtfbmFuZF9jb250cm9sbGVyICpjdHJsKQo+ICt7Cj4gKwlpZiAoY3RybC0+dmVy c2lvbiA9PSBWRVJTSU9OXzkpIHsKPiArCQl3cml0ZWwoMCwgY3RybC0+cmVncyArIE5BTkRDX1JF R19WOV9SQU5ETVopOwo+ICsJCXdyaXRlbCgwLCBjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y5X0RN QV9DRkcpOwo+ICsJCXdyaXRlbChOQU5EQ19WOV9GTV9XUCwgY3RybC0+cmVncyArIE5BTkRDX1JF R19WOV9GTUNUTCk7Cj4gKwkJd3JpdGVsKE5BTkRDX1Y5X0ZMX1JTVCwgY3RybC0+cmVncyArIE5B TkRDX1JFR19WOV9GTENUTCk7Cj4gKwkJd3JpdGVsKDB4MTA4MSwgY3RybC0+cmVncyArIE5BTkRD X1JFR19WOV9GTVdBSVQpOwo+ICsJfSBlbHNlIHsKPiArCQl3cml0ZWwoMCwgY3RybC0+cmVncyAr IE5BTkRDX1JFR19WNl9SQU5ETVopOwo+ICsJCXdyaXRlbCgwLCBjdHJsLT5yZWdzICsgTkFORENf UkVHX1Y2X0RNQV9DRkcpOwo+ICsJCXdyaXRlbChOQU5EQ19WNl9GTV9XUCwgY3RybC0+cmVncyAr IE5BTkRDX1JFR19WNl9GTUNUTCk7Cj4gKwkJd3JpdGVsKE5BTkRDX1Y2X0ZMX1JTVCwgY3RybC0+ cmVncyArIE5BTkRDX1JFR19WNl9GTENUTCk7Cj4gKwkJd3JpdGVsKDB4MTA4MSwgY3RybC0+cmVn cyArIE5BTkRDX1JFR19WNl9GTVdBSVQpOwo+ICsJfQoKTXkgYWJvdmUgY29tbWVudCBhYm91dCB0 aGUgcGxhdGZvcm0gZGF0YSB3b3VsZCBtYWtlIGEgbG90IG9mIHNlbnNlIGhlcmUhCgo+ICt9Cj4g Kwo+ICtzdGF0aWMgaXJxcmV0dXJuX3QgcmtfbmFuZGNfaW50ZXJydXB0KGludCBpcnEsIHZvaWQg KmRldl9pZCkKPiArewo+ICsJc3RydWN0IHJrX25hbmRfY29udHJvbGxlciAqY3RybCA9IGRldl9p ZDsKPiArCj4gKwlpZiAoY3RybC0+dmVyc2lvbiA9PSBWRVJTSU9OXzkpIHsKPiArCQl1aW50MzJf dCBzdCA9IHJlYWRsKGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjlfSU5UU1QpOwo+ICsJCXVpbnQz Ml90IGllbiA9IHJlYWRsKGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjlfSU5URU4pOwo+ICsKPiAr CQlpZiAoIShpZW4gJiBzdCkpCj4gKwkJCXJldHVybiBJUlFfTk9ORTsKPiArCj4gKwkJaWYgKChp ZW4gJiBzdCkgPT0gaWVuKQo+ICsJCQljb21wbGV0ZSgmY3RybC0+Y29tcGxldGUpOwo+ICsKPiAr CQl3cml0ZWwoc3QsIGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjlfSU5UQ0xSKTsKPiArCQl3cml0 ZWwofnN0ICYgaWVuLCBjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y5X0lOVEVOKTsKPiArCX0gZWxz ZSB7Cj4gKwkJdWludDMyX3Qgc3QgPSByZWFkbChjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y2X0lO VFNUKTsKPiArCQl1aW50MzJfdCBpZW4gPSByZWFkbChjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y2 X0lOVEVOKTsKPiArCj4gKwkJaWYgKCEoaWVuICYgc3QpKQo+ICsJCQlyZXR1cm4gSVJRX05PTkU7 Cj4gKwo+ICsJCWlmICgoaWVuICYgc3QpID09IGllbikKPiArCQkJY29tcGxldGUoJmN0cmwtPmNv bXBsZXRlKTsKPiArCj4gKwkJd3JpdGVsKHN0LCBjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y2X0lO VENMUik7Cj4gKwkJd3JpdGVsKH5zdCAmIGllbiwgY3RybC0+cmVncyArIE5BTkRDX1JFR19WNl9J TlRFTik7Cj4gKwl9CgpTYW1lIGNvbW1lbnQhCgo+ICsKPiArCXJldHVybiBJUlFfSEFORExFRDsK PiArfQo+ICsKPiArc3RhdGljIHZvaWQgcmtfbmFuZGNfc2VsZWN0X2NoaXAoc3RydWN0IG5hbmRf Y2hpcCAqbmFuZCwgaW50IGNoaXBucikKPiArewo+ICsJc3RydWN0IHJrX25hbmRfY29udHJvbGxl ciAqY3RybCA9IG5hbmRfZ2V0X2NvbnRyb2xsZXJfZGF0YShuYW5kKTsKPiArCXVpbnQzMl90IHJl ZzsKPiArCWludCBiYW5rbnI7Cj4gKwo+ICsJLyogVGhlIHJlZ2lzdGVyIG9mZnNldCBhbmQgYml0 IHBvc2l0aW9ucyBmb3IKCnNob3VsZCBiZToKCgkvKgoJICogVGhlIHJlZ2lzdGVyLi4uCgpQbGVh c2UgcnVuIGNoZWNrcGF0Y2gucGwgLS1zdHJpY3Qgb24gdGhpcyBmaWxlLCB0aGlzIGtpbmQgb2Yg bWlzdGFrZQp3b3VsZCBoYXZlIGJlZW4gZGV0ZWN0ZWQuCgo+ICsJICogTkFORENfUkVHX1Y2X0ZN Q1RMIGFuZCBOQU5EQ19SRUdfVjlfRk1DVEwKPiArCSAqIGFyZSBpZGVudGljYWwuCj4gKwkgKi8K PiArCXJlZyA9IHJlYWRsKGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjZfRk1DVEwpOwo+ICsJcmVn ICY9IH5OQU5EQ19WNl9GTV9DRV9TRUxfTTsKPiArCj4gKwlpZiAoY2hpcG5yID09IC0xKSB7Cj4g KwkJYmFua25yID0gLTE7Cj4gKwl9IGVsc2Ugewo+ICsJCWJhbmtuciA9IGN0cmwtPmJhbmtzW2No aXBucl07Cj4gKwo+ICsJCXJlZyB8PSBOQU5EQ19WNl9GTV9DRV9TRUwoYmFua25yKTsKPiArCX0K PiArCXdyaXRlbChyZWcsIGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjZfRk1DVEwpOwoKTWF5YmUg eW91IGNhbiBzcGFyZSB0aGlzIHdyaXRlbCBieSByZXR1cm5pbmcgZWFybHkgaWYgYmFua25yID09 CmN0cmwtPnNlbGVjdGVkX2JhbmsuCgo+ICsKPiArCWN0cmwtPnNlbGVjdGVkX2JhbmsgPSBiYW5r bnI7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcmtfbmFuZGNfaHdfZWNjX3NldHVwKHN0cnVjdCBu YW5kX2NoaXAgKm5hbmQsCj4gKwkJCQkgdWludDMyX3Qgc3RyZW5ndGgpCj4gK3sKPiArCXN0cnVj dCBya19uYW5kX2NvbnRyb2xsZXIgKmN0cmwgPSBuYW5kX2dldF9jb250cm9sbGVyX2RhdGEobmFu ZCk7Cj4gKwl1aW50MzJfdCByZWc7Cj4gKwo+ICsJbmFuZC0+ZWNjLnN0cmVuZ3RoID0gc3RyZW5n dGg7Cj4gKwluYW5kLT5lY2MuYnl0ZXMgPSBESVZfUk9VTkRfVVAobmFuZC0+ZWNjLnN0cmVuZ3Ro ICogMTQsIDgpOwoKV2hhdCBkbyAxNCBhbmQgOCBtZWFuPwoKPiArCS8qIEhXIEVDQyBvbmx5IHdv cmtzIHdpdGggYW4gZXZlbiBudW1iZXIgb2YgRUNDIGJ5dGVzICovCj4gKwluYW5kLT5lY2MuYnl0 ZXMgPSBBTElHTihuYW5kLT5lY2MuYnl0ZXMsIDIpOwo+ICsKPiArCWlmIChjdHJsLT52ZXJzaW9u ID09IFZFUlNJT05fOSkgewo+ICsJCXN3aXRjaCAobmFuZC0+ZWNjLnN0cmVuZ3RoKSB7Cj4gKwkJ Y2FzZSA3MDoKPiArCQkJcmVnID0gTkFORENfVjlfRUNDXzcwOwo+ICsJCQlicmVhazsKPiArCQlj YXNlIDYwOgo+ICsJCQlyZWcgPSBOQU5EQ19WOV9FQ0NfNjA7Cj4gKwkJCWJyZWFrOwo+ICsJCWNh c2UgNDA6Cj4gKwkJCXJlZyA9IE5BTkRDX1Y5X0VDQ180MDsKPiArCQkJYnJlYWs7Cj4gKwkJY2Fz ZSAxNjoKPiArCQkJcmVnID0gTkFORENfVjlfRUNDXzE2Owo+ICsJCQlicmVhazsKPiArCQlkZWZh dWx0Ogo+ICsJCQlyZXR1cm4gLUVJTlZBTDsKPiArCQl9Cj4gKwkJd3JpdGVsKHJlZywgY3RybC0+ cmVncyArIE5BTkRDX1JFR19WOV9CQ0hDVEwpOwo+ICsJfSBlbHNlIHsKPiArCQlzd2l0Y2ggKG5h bmQtPmVjYy5zdHJlbmd0aCkgewo+ICsJCWNhc2UgNjA6Cj4gKwkJCXJlZyA9IE5BTkRDX1Y2X0VD Q182MDsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSA0MDoKPiArCQkJcmVnID0gTkFORENfVjZfRUND XzQwOwo+ICsJCQlicmVhazsKPiArCQljYXNlIDI0Ogo+ICsJCQlyZWcgPSBOQU5EQ19WNl9FQ0Nf MjQ7Cj4gKwkJCWJyZWFrOwo+ICsJCWNhc2UgMTY6Cj4gKwkJCXJlZyA9IE5BTkRDX1Y2X0VDQ18x NjsKPiArCQkJYnJlYWs7Cj4gKwkJZGVmYXVsdDoKPiArCQkJcmV0dXJuIC1FSU5WQUw7Cj4gKwkJ fQo+ICsJCXdyaXRlbChyZWcsIGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjZfQkNIQ1RMKTsKPiAr CX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgcmtfbmFuZGNfeGZl cl9zdGFydChzdHJ1Y3QgcmtfbmFuZF9jb250cm9sbGVyICpjdHJsLAo+ICsJCQkJdWludDhfdCBk aXIsIHVpbnQ4X3Qgbl9LQiwKPiArCQkJCWRtYV9hZGRyX3QgZG1hX2RhdGEsIGRtYV9hZGRyX3Qg ZG1hX29vYikKPiArewo+ICsJdWludDMyX3QgcmVnOwo+ICsKPiArCWlmIChjdHJsLT52ZXJzaW9u ID09IFZFUlNJT05fOSkgewo+ICsJCXJlZyA9IE5BTkRDX1Y5X0RNQV9DRkdfV1JfU1QgfAo+ICsJ CSAgICAgIE5BTkRDX1Y5X0RNQV9DRkdfV1IoZGlyKSB8Cj4gKwkJICAgICAgTkFORENfVjlfRE1B X0NGR19CVVNfTU9ERSB8Cj4gKwkJICAgICAgTkFORENfVjlfRE1BX0NGR19IU0laRV8zMiB8Cj4g KwkJICAgICAgTkFORENfVjlfRE1BX0NGR19CVVJTVF8xNiB8Cj4gKwkJICAgICAgTkFORENfVjlf RE1BX0NGR19JTkNSX05VTSgxNik7Cj4gKwkJd3JpdGVsKHJlZywgY3RybC0+cmVncyArIE5BTkRD X1JFR19WOV9ETUFfQ0ZHKTsKPiArCQl3cml0ZWwoKHVpbnQzMl90KWRtYV9kYXRhLCBjdHJsLT5y ZWdzICsgTkFORENfUkVHX1Y5X0RNQV9CVUYwKTsKPiArCQl3cml0ZWwoKHVpbnQzMl90KWRtYV9v b2IsIGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjlfRE1BX0JVRjEpOwoKSSdtIHByZXR0eSBzdXJl IG1vc3Qgb2YgdGhlc2Ugd3JpdGVsIGNvdWxkIGJlIHR1cm5lZCBpbnRvCndyaXRlbF9yZWxheGVk LgoKQWxzbyBJIGFtIG5vdCBhIGJpZyBmYW4gb2YgdGhlc2UgY2FzdHMsIG1heWJlIHlvdSBzaG91 bGQgY2hhbmdlCmRtYV9kYXRhIGFuZCBkbWFfb29iIHR5cGVzIChiZSBjYXJlZnVsOiB5b3UgZW5h YmxlZCBDT01QSUxFX1RFU1QgaW4KS2NvbmZpZywgeW91IG11c3Qgc3VwcG9ydCAzMi1iaXQgYW5k IDY0LWJpdCBwb2ludGVycywgcGxlYXNlIHRyeSB0bwpjb21waWxlIHRoaXMgZHJpdmVyIHdpdGgg ZGlmZmVyZW50IHRvb2xjaGFpbnMpLgogCj4gKwo+ICsJCXJlZyA9IE5BTkRDX1Y5X0ZMX0RJUihk aXIpIHwKPiArCQkgICAgICBOQU5EQ19WOV9GTF9YRkVSX0VOIHwKPiArCQkgICAgICBOQU5EQ19W OV9GTF9YRkVSX0NPVU5UIHwKPiArCQkgICAgICBOQU5EQ19WOV9GTF9BQ09SUkVDVCB8Cj4gKwkJ ICAgICAgTkFORENfVjlfRkxfUEFHRV9OVU0obl9LQikgfAo+ICsJCSAgICAgIE5BTkRDX1Y5X0ZM X0FTWU5DX1RPR19NSVg7Cj4gKwkJd3JpdGVsKHJlZywgY3RybC0+cmVncyArIE5BTkRDX1JFR19W OV9GTENUTCk7Cj4gKwkJcmVnIHw9IE5BTkRDX1Y5X0ZMX1hGRVJfU1RBUlQ7Cj4gKwkJd3JpdGVs KHJlZywgY3RybC0+cmVncyArIE5BTkRDX1JFR19WOV9GTENUTCk7Cj4gKwl9IGVsc2Ugewo+ICsJ CXJlZyA9IHJlYWRsKGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjZfQkNIQ1RMKTsKPiArCQlyZWcg PSAocmVnICYgKH4oTkFORF9WNl9CQ0hfUkVHSU9OX00gPDwKPiArCQkJCU5BTkRfVjZfQkNIX1JF R0lPTl9TKSkpIHwKPiArCQkgICAgICAoY3RybC0+c2VsZWN0ZWRfYmFuayA8PCBOQU5EX1Y2X0JD SF9SRUdJT05fUyk7Cj4gKwkJd3JpdGVsKHJlZywgY3RybC0+cmVncyArIE5BTkRDX1JFR19WNl9C Q0hDVEwpOwo+ICsKPiArCQlyZWcgPSBOQU5EQ19WNl9ETUFfQ0ZHX1dSX1NUIHwKPiArCQkgICAg ICBOQU5EQ19WNl9ETUFfQ0ZHX1dSKGRpcikgfAo+ICsJCSAgICAgIE5BTkRDX1Y2X0RNQV9DRkdf QlVTX01PREUgfAo+ICsJCSAgICAgIE5BTkRDX1Y2X0RNQV9DRkdfSFNJWkVfMzIgfAo+ICsJCSAg ICAgIE5BTkRDX1Y2X0RNQV9DRkdfQlVSU1RfMTYgfAo+ICsJCSAgICAgIE5BTkRDX1Y2X0RNQV9D RkdfSU5DUl9OVU0oMTYpOwo+ICsJCXdyaXRlbChyZWcsIGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdf VjZfRE1BX0NGRyk7Cj4gKwkJd3JpdGVsKGRtYV9kYXRhLCBjdHJsLT5yZWdzICsgTkFORENfUkVH X1Y2X0RNQV9CVUYwKTsKPiArCQl3cml0ZWwoZG1hX29vYiwgY3RybC0+cmVncyArIE5BTkRDX1JF R19WNl9ETUFfQlVGMSk7Cj4gKwo+ICsJCXJlZyA9IE5BTkRDX1Y2X0ZMX0RJUihkaXIpIHwKPiAr CQkgICAgICBOQU5EQ19WNl9GTF9YRkVSX0VOIHwKPiArCQkgICAgICBOQU5EQ19WNl9GTF9YRkVS X0NPVU5UIHwKPiArCQkgICAgICBOQU5EQ19WNl9GTF9BQ09SUkVDVCB8Cj4gKwkJICAgICAgTkFO RENfVjZfRkxfUEFHRV9OVU0obl9LQikgfAo+ICsJCSAgICAgIE5BTkRDX1Y2X0ZMX0FTWU5DX1RP R19NSVg7Cj4gKwkJd3JpdGVsKHJlZywgY3RybC0+cmVncyArIE5BTkRDX1JFR19WNl9GTENUTCk7 Cj4gKwkJcmVnIHw9IE5BTkRDX1Y2X0ZMX1hGRVJfU1RBUlQ7Cj4gKwkJd3JpdGVsKHJlZywgY3Ry bC0+cmVncyArIE5BTkRDX1JFR19WNl9GTENUTCk7Cj4gKwl9Cj4gK30KPiArCj4gK3N0YXRpYyBp bnQgcmtfbmFuZGNfd2FpdF9mb3JfeGZlcl9kb25lKHN0cnVjdCBya19uYW5kX2NvbnRyb2xsZXIg KmN0cmwpCj4gK3sKPiArCXVpbnQzMl90IHJlZzsKPiArCWludCByZXQ7Cj4gKwo+ICsJaWYgKGN0 cmwtPnZlcnNpb24gPT0gVkVSU0lPTl85KSB7Cj4gKwkJdm9pZCBfX2lvbWVtICpwdHIgPSBjdHJs LT5yZWdzICsgTkFORENfUkVHX1Y5X0ZMQ1RMOwo+ICsKPiArCQlyZXQgPSByZWFkbF9wb2xsX3Rp bWVvdXRfYXRvbWljKHB0ciwgcmVnLAo+ICsJCQkJCQlyZWcgJiBOQU5EQ19WOV9GTF9YRkVSX1JF QURZLAo+ICsJCQkJCQkxLCBOQU5EQ19ERUZfVElNRU9VVCk7Cj4gKwl9IGVsc2Ugewo+ICsJCXZv aWQgX19pb21lbSAqcHRyID0gY3RybC0+cmVncyArIE5BTkRDX1JFR19WNl9GTENUTDsKPiArCj4g KwkJcmV0ID0gcmVhZGxfcG9sbF90aW1lb3V0X2F0b21pYyhwdHIsIHJlZywKPiArCQkJCQkJcmVn ICYgTkFORENfVjZfRkxfWEZFUl9SRUFEWSwKPiArCQkJCQkJMSwgTkFORENfREVGX1RJTUVPVVQp Owo+ICsJfQoKU3BhY2UKCj4gKwlpZiAocmV0KQo+ICsJCXByX2VycigidGltZW91dCByZWc9JXhc biIsIHJlZyk7Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIHVuc2lnbmVk IGxvbmcgcmtfbmFuZGNfZG1hX21hcF9zaW5nbGUoc3RydWN0IGRldmljZSAqZGV2LAo+ICsJCXZv aWQgKnB0ciwgaW50IHNpemUsIGludCBkaXIpCgpVbmFsaWduZWQgcGFyYW1ldGVycwoKPiArewo+ ICsjaWZkZWYgQ09ORklHX0FSTTY0Cj4gKwlfX2RtYV9tYXBfYXJlYSgodm9pZCAqKXB0ciwgc2l6 ZSwgZGlyKTsKPiArCXJldHVybiAoKHVuc2lnbmVkIGxvbmcpdmlydF90b19waHlzKCh2b2lkICop cHRyKSk7Cj4gKyNlbHNlCj4gKwlyZXR1cm4gZG1hX21hcF9zaW5nbGUoZGV2LCAodm9pZCAqKXB0 ciwgc2l6ZSwgZGlyKTsKPiArI2VuZGlmCgpQbGVhc2UgdHJ5IHRvIHJlbW92ZSB0aGVzZSAjaWZk ZWZzLCBJIGRvbid0IGtub3cgd2h5IHdvdWxkIHlvdSBuZWVkIHRoZQpmb3JtZXIgYmxvY2s/Cgo+ ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBya19uYW5kY19kbWFfdW5tYXBfc2luZ2xlKHN0cnVjdCBk ZXZpY2UgKmRldiwKPiArCQkJCSAgICAgIHVuc2lnbmVkIGxvbmcgcHRyLCBpbnQgc2l6ZSwgaW50 IGRpcikKPiArewo+ICsjaWZkZWYgQ09ORklHX0FSTTY0Cj4gKwlfX2RtYV91bm1hcF9hcmVhKHBo eXNfdG9fdmlydChwdHIpLCBzaXplLCBkaXIpOwo+ICsjZWxzZQo+ICsJZG1hX3VubWFwX3Npbmds ZShkZXYsIChkbWFfYWRkcl90KXB0ciwgc2l6ZSwgZGlyKTsKPiArI2VuZGlmCgpTYW1lCgo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW50IHJrX25hbmRjX2h3X3N5bmRyb21lX2VjY19yZWFkX3BhZ2Uoc3Ry dWN0IG5hbmRfY2hpcCAqbmFuZCwKPiArCQl1aW50OF90ICpidWYsCj4gKwkJaW50IG9vYl9yZXF1 aXJlZCwgaW50IHBhZ2UpCgpVbmFsaWduZWQgcGFyYW1ldGVycyAocGxlYXNlIGNoZWNrIGFsbCBv ZiB0aGVtKS4KCj4gK3sKPiArCXN0cnVjdCBtdGRfaW5mbyAqbXRkID0gbmFuZF90b19tdGQobmFu ZCk7Cj4gKwlzdHJ1Y3QgcmtfbmFuZF9jb250cm9sbGVyICpjdHJsID0gbmFuZF9nZXRfY29udHJv bGxlcl9kYXRhKG5hbmQpOwo+ICsJc3RydWN0IG5hbmRfZWNjX2N0cmwgKmVjYyA9ICZuYW5kLT5l Y2M7Cj4gKwlpbnQgbWF4X2JpdGZsaXBzID0gMDsKPiArCWRtYV9hZGRyX3QgZG1hX2RhdGEsIGRt YV9vb2I7Cj4gKwlpbnQgcmV0LCBpOwo+ICsJaW50IGJjaF9zdDsKPiArCWludCBkbWFfb29iX3Np emUgPSBlY2MtPnN0ZXBzICogMTI4Owo+ICsJaW50IHBhZ2VzX3Blcl9ibGsgPSBtdGQtPmVyYXNl c2l6ZSAvIG10ZC0+d3JpdGVzaXplOwo+ICsKPiArCXJrX25hbmRjX3NlbGVjdF9jaGlwKG5hbmQs IGN0cmwtPnNlbGVjdGVkX2JhbmspOwo+ICsKPiArCWlmICgocGFnZSA8IHBhZ2VzX3Blcl9ibGsg KiBOQU5EQ19JREJSZXNCbGtOdW0pICYmCgpDYW1lbCBjYXNlIGlzIHVzdWFsbHkgbm90IHdlbGNv bWUKCj4gKwkgICAgY3RybC0+Ym9vdHJvbWJsb2NrcykKClRoaXMgd291bGQgcHJvYmFibHkgZGVz ZXJ2ZSBhIGhlbHBlcgoKPiArCQlya19uYW5kY19od19lY2Nfc2V0dXAobmFuZCwgTkFORENfSURC RWNjQml0cyk7Cj4gKwo+ICsJbmFuZF9yZWFkX3BhZ2Vfb3AobmFuZCwgcGFnZSwgMCwgTlVMTCwg MCk7Cj4gKwo+ICsJZG1hX2RhdGEgPSBya19uYW5kY19kbWFfbWFwX3NpbmdsZShtdGQtPmRldi5w YXJlbnQsCj4gKwkJCQkJICAgY3RybC0+cGFnZV9idWYsIG10ZC0+d3JpdGVzaXplLAo+ICsJCQkJ CSAgIERNQV9GUk9NX0RFVklDRSk7Cj4gKwlkbWFfb29iID0gcmtfbmFuZGNfZG1hX21hcF9zaW5n bGUobXRkLT5kZXYucGFyZW50LAo+ICsJCQkJCSAgY3RybC0+b29iX2J1ZiwgZG1hX29vYl9zaXpl LAo+ICsJCQkJCSAgRE1BX0ZST01fREVWSUNFKTsKPiArCj4gKwlpbml0X2NvbXBsZXRpb24oJmN0 cmwtPmNvbXBsZXRlKTsKCk9uZSBpbml0X2NvbXBsZXRpb24gaXMgbmVlZGVkIChpbiB0aGUgcHJv YmUsIHByb2JhYmx5KSB0aGVuIHBsZWFzZSB1c2UKcmVpbml0X2NvbXBsZXRpb24oKS4KCj4gKwlp ZiAoY3RybC0+dmVyc2lvbiA9PSBWRVJTSU9OXzkpCj4gKwkJd3JpdGVsKE5BTkRDX1Y5X0lOVF9E TUEsIGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfVjlfSU5URU4pOwo+ICsJZWxzZQo+ICsJCXdyaXRl bChOQU5EQ19WNl9JTlRfRE1BLCBjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y2X0lOVEVOKTsKPiAr CXJrX25hbmRjX3hmZXJfc3RhcnQoY3RybCwgMCwgZWNjLT5zdGVwcywgZG1hX2RhdGEsIGRtYV9v b2IpOwo+ICsJd2FpdF9mb3JfY29tcGxldGlvbl90aW1lb3V0KCZjdHJsLT5jb21wbGV0ZSwgbXNl Y3NfdG9famlmZmllcyg1KSk7Cj4gKwlya19uYW5kY193YWl0X2Zvcl94ZmVyX2RvbmUoY3RybCk7 CgpZb3VzIHNob3VsZCBjaGVjayB0aGUgcmV0dXJuIHN0YXR1cyBvZiBhbG1vc3QgYWxsIHRoZSBm dW5jdGlvbnMgaGVyZS4KCj4gKwlya19uYW5kY19kbWFfdW5tYXBfc2luZ2xlKG10ZC0+ZGV2LnBh cmVudCwgZG1hX2RhdGEsIG10ZC0+d3JpdGVzaXplLAo+ICsJCQkJICBETUFfRlJPTV9ERVZJQ0Up Owo+ICsJcmtfbmFuZGNfZG1hX3VubWFwX3NpbmdsZShtdGQtPmRldi5wYXJlbnQsIGRtYV9vb2Is IGRtYV9vb2Jfc2l6ZSwKPiArCQkJCSAgRE1BX0ZST01fREVWSUNFKTsKPiArCj4gKwltZW1jcHko YnVmLCBjdHJsLT5wYWdlX2J1ZiwgbXRkLT53cml0ZXNpemUpOwo+ICsKPiArCWlmIChvb2JfcmVx dWlyZWQpIHsKPiArCQl1aW50OF90ICpvb2I7Cj4gKwkJdWludDMyX3QgdG1wOwoKUGxlYXNlIHVz ZSB1OCwgdTE2IGFuZCB1MzIgdHlwZXMuCgo+ICsKPiArCQlmb3IgKGkgPSAwOyBpIDwgZWNjLT5z dGVwczsgaSsrKSB7Cj4gKwkJCW9vYiA9IG5hbmQtPm9vYl9wb2kgKwo+ICsJCQkgICAgICBpICog KGVjYy0+Ynl0ZXMgKyBuYW5kLT5lY2MucHJlcGFkKTsKPiArCQkJaWYgKGN0cmwtPnZlcnNpb24g PT0gVkVSU0lPTl85KSB7Cj4gKwkJCQl0bXAgPSBjdHJsLT5vb2JfYnVmW2ldOwo+ICsJCQl9IGVs c2Ugewo+ICsJCQkJdWludDhfdCBvb2Jfc3RlcCA9IChjdHJsLT5lY2NfbW9kZSA8PSAyNCkgPwo+ ICsJCQkJCQkgICA2NCA6IDEyODsKPiArCQkJCXRtcCA9IGN0cmwtPm9vYl9idWZbaSAqIG9vYl9z dGVwIC8gNF07Cj4gKwkJCX0KPiArCQkJKm9vYisrID0gKHVpbnQ4X3QpdG1wOwo+ICsJCQkqb29i KysgPSAodWludDhfdCkodG1wID4+IDgpOwo+ICsJCQkqb29iKysgPSAodWludDhfdCkodG1wID4+ IDE2KTsKPiArCQkJKm9vYisrID0gKHVpbnQ4X3QpKHRtcCA+PiAyNCk7Cj4gKwkJfQo+ICsJfQo+ ICsKPiArCWlmIChjdHJsLT52ZXJzaW9uID09IFZFUlNJT05fOSkgewo+ICsJCWZvciAoaSA9IDA7 IGkgPCBlY2MtPnN0ZXBzIC8gMjsgaSsrKSB7Cj4gKwkJCWJjaF9zdCA9IHJlYWRsKGN0cmwtPnJl Z3MgKyBOQU5EQ19SRUdfVjlfQkNIU1QgKyBpICogNCk7Cj4gKwkJCWlmIChiY2hfc3QgJiBOQU5E Q19WOV9CQ0gwX1NUX0VSUiB8fAo+ICsJCQkgICAgYmNoX3N0ICYgTkFORENfVjlfQkNIMV9TVF9F UlIpIHsKPiArCQkJCW10ZC0+ZWNjX3N0YXRzLmZhaWxlZCsrOwo+ICsJCQkJbWF4X2JpdGZsaXBz ID0gLTE7Cj4gKwkJCX0gZWxzZSB7Cj4gKwkJCQlyZXQgPSBOQU5EQ19WOV9FQ0NfRVJSX0NOVDAo YmNoX3N0KTsKPiArCQkJCW10ZC0+ZWNjX3N0YXRzLmNvcnJlY3RlZCArPSByZXQ7Cj4gKwkJCQlt YXhfYml0ZmxpcHMgPSBtYXhfdCh1bnNpZ25lZCBpbnQsCj4gKwkJCQkJCSAgICAgbWF4X2JpdGZs aXBzLCByZXQpOwo+ICsKPiArCQkJCXJldCA9IE5BTkRDX1Y5X0VDQ19FUlJfQ05UMShiY2hfc3Qp Owo+ICsJCQkJbXRkLT5lY2Nfc3RhdHMuY29ycmVjdGVkICs9IHJldDsKPiArCQkJCW1heF9iaXRm bGlwcyA9IG1heF90KHVuc2lnbmVkIGludCwKPiArCQkJCQkJICAgICBtYXhfYml0ZmxpcHMsIHJl dCk7Cj4gKwkJCX0KPiArCQl9Cj4gKwl9IGVsc2Ugewo+ICsJCWZvciAoaSA9IDA7IGkgPCBlY2Mt PnN0ZXBzIC8gMjsgaSsrKSB7Cj4gKwkJCWJjaF9zdCA9IHJlYWRsKGN0cmwtPnJlZ3MgKyBOQU5E Q19SRUdfVjZfQkNIU1QgKyBpICogNCk7Cj4gKwkJCWlmIChiY2hfc3QgJiBOQU5EQ19WNl9CQ0gw X1NUX0VSUiB8fAo+ICsJCQkgICAgYmNoX3N0ICYgTkFORENfVjZfQkNIMV9TVF9FUlIpIHsKPiAr CQkJCW10ZC0+ZWNjX3N0YXRzLmZhaWxlZCsrOwo+ICsJCQkJbWF4X2JpdGZsaXBzID0gLTE7CgpX aHkgbm90IHVzaW5nIHJldCA9ICQocmVhbCBlcnJvcikgaW5zdGVhZCBvZiB1c2luZyBtYXhfYml0 ZmxpcHMgaGVyZT8KClRoZW46CgoJaWYgKHJldCkgewoJCWRldl9lcnIoKTsKCQlyZXR1cm4gcmV0 OwoJfQoKCXJldHVybiBtYXhfYml0ZmxpcHM7Cgo+ICsJCQl9IGVsc2Ugewo+ICsJCQkJcmV0ID0g TkFORENfVjZfRUNDX0VSUl9DTlQwKGJjaF9zdCk7Cj4gKwkJCQltdGQtPmVjY19zdGF0cy5jb3Jy ZWN0ZWQgKz0gcmV0Owo+ICsJCQkJbWF4X2JpdGZsaXBzID0gbWF4X3QodW5zaWduZWQgaW50LAo+ ICsJCQkJCQkgICAgIG1heF9iaXRmbGlwcywgcmV0KTsKPiArCj4gKwkJCQlyZXQgPSBOQU5EQ19W Nl9FQ0NfRVJSX0NOVDEoYmNoX3N0KTsKPiArCQkJCW10ZC0+ZWNjX3N0YXRzLmNvcnJlY3RlZCAr PSByZXQ7Cj4gKwkJCQltYXhfYml0ZmxpcHMgPSBtYXhfdCh1bnNpZ25lZCBpbnQsCj4gKwkJCQkJ CSAgICAgbWF4X2JpdGZsaXBzLCByZXQpOwo+ICsJCQl9Cj4gKwkJfQo+ICsJfQo+ICsKPiArCWlm IChtYXhfYml0ZmxpcHMgPT0gLTEpIHsKPiArCQlkZXZfZXJyKG10ZC0+ZGV2LnBhcmVudCwKPiAr CQkJInJlYWRfcGFnZSAleCAleCAleCAleCAleCAlcCAleFxuIiwKPiArCQkJcGFnZSwKPiArCQkJ bWF4X2JpdGZsaXBzLAo+ICsJCQliY2hfc3QsCj4gKwkJCSgodWludDMyX3QgKilidWYpWzBdLAo+ ICsJCQkoKHVpbnQzMl90ICopYnVmKVsxXSwKPiArCQkJYnVmLAo+ICsJCQkodWludDMyX3QpZG1h X2RhdGEpOwoKVGhpcyBpcyBub3QgdmVyeSBpbmZvcm1hdGl2ZSwgcGxlYXNlIHdyaXRlIGEgcmVh bCBlcnJvciBtZXNzYWdlLiBBdm9pZApwdXR0aW5nIHRvbyBtdWNoIGRlYnVnIGluZm9ybWF0aW9u LCBwZW9wbGUgd2lsbCB0cm91Ymxlc2hvb3QgdGhlbXNlbHZlcwppZiBuZWVkZWQuCgo+ICsJfQo+ ICsKPiArCWlmIChjdHJsLT5ib290cm9tYmxvY2tzKQo+ICsJCXJrX25hbmRjX2h3X2VjY19zZXR1 cChuYW5kLCBjdHJsLT5lY2NfbW9kZSk7Cj4gKwoKWW91IGRvbid0IHVzZSB0aGUgc2FtZSBjb25k aXRpb24gYXMgYWJvdmUuIFdoeSA/IE1heWJlIHRoZSBoZWxwZXIgd291bGQKaGVscC4KCj4gKwly ZXR1cm4gbWF4X2JpdGZsaXBzOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHJrX25hbmRjX2h3X3N5 bmRyb21lX2VjY193cml0ZV9wYWdlKHN0cnVjdCBuYW5kX2NoaXAgKm5hbmQsCj4gKwkJY29uc3Qg dWludDhfdCAqYnVmLAo+ICsJCWludCBvb2JfcmVxdWlyZWQsCj4gKwkJaW50IHBhZ2UpCj4gK3sK PiArCXN0cnVjdCBtdGRfaW5mbyAqbXRkID0gbmFuZF90b19tdGQobmFuZCk7Cj4gKwlzdHJ1Y3Qg cmtfbmFuZF9jb250cm9sbGVyICpjdHJsID0gbmFuZF9nZXRfY29udHJvbGxlcl9kYXRhKG5hbmQp Owo+ICsJc3RydWN0IG5hbmRfZWNjX2N0cmwgKmVjYyA9ICZuYW5kLT5lY2M7Cj4gKwlkbWFfYWRk cl90IGRtYV9kYXRhLCBkbWFfb29iOwo+ICsJaW50IGk7Cj4gKwlpbnQgZG1hX29vYl9zaXplID0g ZWNjLT5zdGVwcyAqIDEyODsKPiArCWludCBwYWdlc19wZXJfYmxrID0gbXRkLT5lcmFzZXNpemUg LyBtdGQtPndyaXRlc2l6ZTsKPiArCj4gKwlya19uYW5kY19zZWxlY3RfY2hpcChuYW5kLCBjdHJs LT5zZWxlY3RlZF9iYW5rKTsKPiArCj4gKwlpZiAoKHBhZ2UgPCBwYWdlc19wZXJfYmxrICogTkFO RENfSURCUmVzQmxrTnVtKSAmJgo+ICsJICAgIGN0cmwtPmJvb3Ryb21ibG9ja3MpCj4gKwkJcmtf bmFuZGNfaHdfZWNjX3NldHVwKG5hbmQsIE5BTkRDX0lEQkVjY0JpdHMpOwo+ICsKPiArCW5hbmRf cHJvZ19wYWdlX2JlZ2luX29wKG5hbmQsIHBhZ2UsIDAsIE5VTEwsIDApOwo+ICsKPiArCWZvciAo aSA9IDA7IGkgPCBlY2MtPnN0ZXBzOyBpKyspIHsKPiArCQl1aW50MzJfdCB0bXA7Cj4gKwo+ICsJ CWlmIChvb2JfcmVxdWlyZWQpIHsKPiArCQkJdWludDhfdCAqb29iOwo+ICsKPiArCQkJb29iID0g bmFuZC0+b29iX3BvaSArCj4gKwkJCSAgICAgIGkgKiAoZWNjLT5ieXRlcyArIG5hbmQtPmVjYy5w cmVwYWQpOwo+ICsJCQl0bXAgPSBvb2JbMF0gfAo+ICsJCQkgICAgICAob29iWzFdIDw8IDgpIHwK PiArCQkJICAgICAgKG9vYlsyXSA8PCAxNikgfAo+ICsJCQkgICAgICAob29iWzNdIDw8IDI0KTsK PiArCQl9IGVsc2Ugewo+ICsJCQkvKiBUaGUgZmlyc3QgTkFORENfSURCUmVzQmxrTnVtIGJsb2Nr cyBhcmUKPiArCQkJICogZm9yIHRoZSBzdG9yZWQgbG9hZGVyLiBUaGUgZmlyc3QgMzIgYml0cwo+ ICsJCQkgKiBvZiBvb2IgbXVzdCBjb250YWluIGEgc29ydCBvZiBsaW5rIHRvCj4gKwkJCSAqIHRo ZSBuZXh0IHBhZ2UgYWRkcmVzcyBpbiB0aGF0IHNhbWUgYmxvY2sKPiArCQkJICogZm9yIHRoZSBC b290cm9tLgo+ICsJCQkgKiBEZXBlbmRpbmcgb24gd2hhdCBGVEwgZnJvbSBSb2NrY2hpcCBpcyB1 c2VkLAo+ICsJCQkgKiB0aGUgZmlyc3QgMiBwYWdlcyBpbiB0aGUgTkFORENfSURCUmVzQmxrTnVt IGJsb2Nrcwo+ICsJCQkgKiBhcmUgcmVzZXJ2ZWQgZm9yIEZsYXNoUGh5SW5mby4KPiArCQkJICog UmF3IElEQiBkYXRhIHRoZW4gc3RhcnRzIGF0IHBhZ2UgMiBvciBoaWdoZXIuCgpJIHdvdWxkIHNl cGFyYXRlIHRoZSBmdW5jdGlvbiB0byByZWFkL3dyaXRlIHRoZSBsb2FkZXIgdGhhbiB0aGUgdXN1 YWwKcmVhZC93cml0ZSBoZWxwZXJzIHRvIGF2b2lkIGFueSBjb25mdXNpb24gb24gd2h5IHlvdSBk byB0aGVzZSB0cmlja3MuCgpNYXliZSBub3QgdGhlIHdob2xlIGZ1bmN0aW9uLCBidXQgYXQgbGVh c3QgdGhlIGRhdGEvb29iIHBsYWNlbWVudD8KKFRoaXMgaXMgcmVhbGx5IGEgc3VnZ2VzdGlvbikK Cj4gKwkJCSAqLwo+ICsJCQlpZiAoIWkgJiYKPiArCQkJICAgIHBhZ2UgPCBwYWdlc19wZXJfYmxr ICogTkFORENfSURCUmVzQmxrTnVtICYmCj4gKwkJCSAgICBwYWdlID49IE5BTkRDX0lEQlN0YXJ0 QWRkcikKPiArCQkJCXRtcCA9IChwYWdlICYgKHBhZ2VzX3Blcl9ibGsgLSAxKSkgKiA0Owo+ICsJ CQllbHNlCj4gKwkJCQl0bXAgPSAweEZGRkZGRkZGOwo+ICsJCX0KPiArCQlpZiAoY3RybC0+dmVy c2lvbiA9PSBWRVJTSU9OXzkpIHsKPiArCQkJY3RybC0+b29iX2J1ZltpXSA9IHRtcDsKPiArCQl9 IGVsc2Ugewo+ICsJCQl1aW50OF90IG9vYl9zdGVwID0gKGN0cmwtPmVjY19tb2RlIDw9IDI0KSA/ Cj4gKwkJCQkJICAgNjQgOiAxMjg7Cj4gKwkJCWN0cmwtPm9vYl9idWZbaSAqIG9vYl9zdGVwIC8g NF0gPSB0bXA7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCW1lbWNweShjdHJsLT5wYWdlX2J1ZiwgYnVm LCBtdGQtPndyaXRlc2l6ZSk7Cj4gKwlkbWFfZGF0YSA9IHJrX25hbmRjX2RtYV9tYXBfc2luZ2xl KG10ZC0+ZGV2LnBhcmVudCwKPiArCQkJCQkgICBjdHJsLT5wYWdlX2J1ZiwgbXRkLT53cml0ZXNp emUsCj4gKwkJCQkJICAgRE1BX1RPX0RFVklDRSk7Cj4gKwlkbWFfb29iID0gcmtfbmFuZGNfZG1h X21hcF9zaW5nbGUobXRkLT5kZXYucGFyZW50LAo+ICsJCQkJCSAgY3RybC0+b29iX2J1ZiwgZG1h X29vYl9zaXplLAo+ICsJCQkJCSAgRE1BX1RPX0RFVklDRSk7Cj4gKwlpbml0X2NvbXBsZXRpb24o JmN0cmwtPmNvbXBsZXRlKTsKPiArCWlmIChjdHJsLT52ZXJzaW9uID09IFZFUlNJT05fOSkKPiAr CQl3cml0ZWwoTkFORENfVjlfSU5UX0RNQSwgY3RybC0+cmVncyArIE5BTkRDX1JFR19WOV9JTlRF Tik7Cj4gKwllbHNlCj4gKwkJd3JpdGVsKE5BTkRDX1Y2X0lOVF9ETUEsIGN0cmwtPnJlZ3MgKyBO QU5EQ19SRUdfVjZfSU5URU4pOwo+ICsJcmtfbmFuZGNfeGZlcl9zdGFydChjdHJsLCAxLCBlY2Mt PnN0ZXBzLCBkbWFfZGF0YSwgZG1hX29vYik7Cj4gKwl3YWl0X2Zvcl9jb21wbGV0aW9uX3RpbWVv dXQoJmN0cmwtPmNvbXBsZXRlLCBtc2Vjc190b19qaWZmaWVzKDEwKSk7Cj4gKwlya19uYW5kY193 YWl0X2Zvcl94ZmVyX2RvbmUoY3RybCk7Cj4gKwlya19uYW5kY19kbWFfdW5tYXBfc2luZ2xlKG10 ZC0+ZGV2LnBhcmVudCwgZG1hX2RhdGEsIG10ZC0+d3JpdGVzaXplLAo+ICsJCQkJICBETUFfVE9f REVWSUNFKTsKPiArCXJrX25hbmRjX2RtYV91bm1hcF9zaW5nbGUobXRkLT5kZXYucGFyZW50LCBk bWFfb29iLCBkbWFfb29iX3NpemUsCj4gKwkJCQkgIERNQV9UT19ERVZJQ0UpOwo+ICsKPiArCWlm IChjdHJsLT5ib290cm9tYmxvY2tzKQo+ICsJCXJrX25hbmRjX2h3X2VjY19zZXR1cChuYW5kLCBj dHJsLT5lY2NfbW9kZSk7Cj4gKwo+ICsJcmV0dXJuIG5hbmRfcHJvZ19wYWdlX2VuZF9vcChuYW5k KTsKPiArfQo+ICsKPiArc3RhdGljIGludCBya19uYW5kY19od19lY2NfcmVhZF9vb2Ioc3RydWN0 IG5hbmRfY2hpcCAqbmFuZCwgaW50IHBhZ2UpCj4gK3sKPiArCXVpbnQ4X3QgKmJ1ZiA9IG5hbmRf Z2V0X2RhdGFfYnVmKG5hbmQpOwo+ICsKPiArCXJldHVybiBuYW5kLT5lY2MucmVhZF9wYWdlKG5h bmQsIGJ1ZiwgdHJ1ZSwgcGFnZSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcmtfbmFuZGNfaHdf ZWNjX3dyaXRlX29vYihzdHJ1Y3QgbmFuZF9jaGlwICpuYW5kLCBpbnQgcGFnZSkKPiArewo+ICsJ c3RydWN0IG10ZF9pbmZvICptdGQgPSBuYW5kX3RvX210ZChuYW5kKTsKPiArCWludCByZXQ7Cj4g Kwl1aW50OF90ICpidWYgPSBuYW5kX2dldF9kYXRhX2J1ZihuYW5kKTsKPiArCj4gKwltZW1zZXQo YnVmLCAweEZGLCBtdGQtPndyaXRlc2l6ZSk7Cj4gKwlyZXQgPSBuYW5kLT5lY2Mud3JpdGVfcGFn ZShuYW5kLCBidWYsIHRydWUsIHBhZ2UpOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1cm4gcmV0Owo+ ICsKPiArCXJldHVybiBuYW5kX3Byb2dfcGFnZV9lbmRfb3AobmFuZCk7Cj4gK30KPiArCj4gK3N0 YXRpYyB2b2lkIHJrX25hbmRjX3JlYWRfYnVmKHN0cnVjdCBuYW5kX2NoaXAgKm5hbmQsIHVpbnQ4 X3QgKmJ1ZiwgaW50IGxlbikKPiArewo+ICsJc3RydWN0IHJrX25hbmRfY29udHJvbGxlciAqY3Ry bCA9IG5hbmRfZ2V0X2NvbnRyb2xsZXJfZGF0YShuYW5kKTsKPiArCWludCBvZmZzID0gMDsKPiAr CXZvaWQgX19pb21lbSAqYmFua19iYXNlID0gY3RybC0+cmVncyArIE5BTkRDX1JFR19CQU5LMCAr Cj4gKwkJCQkgIGN0cmwtPnNlbGVjdGVkX2JhbmsgKiAweDEwMDsKCjB4MTAwOiBNYXliZSBhIGRl ZmluZQoKPiArCj4gKwlmb3IgKG9mZnMgPSAwOyBvZmZzIDwgbGVuOyBvZmZzKyspCj4gKwkJYnVm W29mZnNdID0gcmVhZGIoYmFua19iYXNlKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgcmtfbmFu ZGNfd3JpdGVfYnVmKHN0cnVjdCBuYW5kX2NoaXAgKm5hbmQsCj4gKwkJCSAgICAgICBjb25zdCB1 aW50OF90ICpidWYsIGludCBsZW4pCj4gK3sKPiArCXN0cnVjdCBya19uYW5kX2NvbnRyb2xsZXIg KmN0cmwgPSBuYW5kX2dldF9jb250cm9sbGVyX2RhdGEobmFuZCk7Cj4gKwlpbnQgb2ZmcyA9IDA7 Cj4gKwl2b2lkIF9faW9tZW0gKmJhbmtfYmFzZSA9IGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfQkFO SzAgKwo+ICsJCQkJICBjdHJsLT5zZWxlY3RlZF9iYW5rICogMHgxMDA7Cj4gKwo+ICsJZm9yIChv ZmZzID0gMDsgb2ZmcyA8IGxlbjsgb2ZmcysrKQo+ICsJCXdyaXRlYihidWZbb2Zmc10sIGJhbmtf YmFzZSk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHJrX25hbmRjX3dyaXRlX2NtZChzdHJ1Y3Qg bmFuZF9jaGlwICpuYW5kLCB1aW50OF90IGNtZCkKPiArewo+ICsJc3RydWN0IHJrX25hbmRfY29u dHJvbGxlciAqY3RybCA9IG5hbmRfZ2V0X2NvbnRyb2xsZXJfZGF0YShuYW5kKTsKPiArCj4gKwl2 b2lkIF9faW9tZW0gKmJhbmtfYmFzZSA9IGN0cmwtPnJlZ3MgKyBOQU5EQ19SRUdfQkFOSzAgKwo+ ICsJCQkJICBjdHJsLT5zZWxlY3RlZF9iYW5rICogMHgxMDAgKwo+ICsJCQkJICBOQU5EQ19SRUdf Q01EOwoKWW91IG1pZ2h0IHdhbnQgdG8gd3JpdGUgYW4gaGVscGVyIHRvIGNhbGN1bGF0ZSBiYW5r X2Jhc2UsIHRvIGF2b2lkCnJlcGVhdGluZyB0aGVzZSBsaW5lcy4KCj4gKwo+ICsJd3JpdGViKGNt ZCwgYmFua19iYXNlKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgcmtfbmFuZGNfd3JpdGVfYWRk cihzdHJ1Y3QgbmFuZF9jaGlwICpuYW5kLCB1aW50OF90IGFkZHIpCj4gK3sKPiArCXN0cnVjdCBy a19uYW5kX2NvbnRyb2xsZXIgKmN0cmwgPSBuYW5kX2dldF9jb250cm9sbGVyX2RhdGEobmFuZCk7 Cj4gKwo+ICsJdm9pZCBfX2lvbWVtICpiYW5rX2Jhc2UgPSBjdHJsLT5yZWdzICsgTkFORENfUkVH X0JBTkswICsKPiArCQkJCSAgY3RybC0+c2VsZWN0ZWRfYmFuayAqIDB4MTAwICsKPiArCQkJCSAg TkFORENfUkVHX0FERFI7Cj4gKwo+ICsJd3JpdGViKGFkZHIsIGJhbmtfYmFzZSk7Cj4gK30KPiAr Cj4gK3N0YXRpYyBpbnQgcmtfbmFuZGNfZGV2X3JlYWR5KHN0cnVjdCBuYW5kX2NoaXAgKm5hbmQp Cj4gK3sKPiArCXN0cnVjdCBya19uYW5kX2NvbnRyb2xsZXIgKmN0cmwgPSBuYW5kX2dldF9jb250 cm9sbGVyX2RhdGEobmFuZCk7Cj4gKwo+ICsJaWYgKHJlYWRsKGN0cmwtPnJlZ3MgKyBOQU5EQ19S RUdfVjZfRk1DVEwpICYgTkFORENfVjZfRk1fRlJFQURZKQo+ICsJCXJldHVybiAxOwo+ICsKPiAr CXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHJrX25hbmRjX29vYmxheW91dF9lY2Mo c3RydWN0IG10ZF9pbmZvICptdGQsIGludCBzZWN0aW9uLAo+ICsJCQkJICBzdHJ1Y3QgbXRkX29v Yl9yZWdpb24gKm9vYnJlZ2lvbikKPiArewo+ICsJc3RydWN0IG5hbmRfY2hpcCAqbmFuZCA9IG10 ZF90b19uYW5kKG10ZCk7Cj4gKwo+ICsJaWYgKHNlY3Rpb24gPj0gbmFuZC0+ZWNjLnN0ZXBzKQo+ ICsJCXJldHVybiAtRVJBTkdFOwo+ICsKPiArCW9vYnJlZ2lvbi0+b2Zmc2V0ID0gKG5hbmQtPmVj Yy5ieXRlcyArIG5hbmQtPmVjYy5wcmVwYWQpICogc2VjdGlvbiArCj4gKwkJCSAgICBuYW5kLT5l Y2MucHJlcGFkOwo+ICsJb29icmVnaW9uLT5sZW5ndGggPSBuYW5kLT5lY2Muc3RlcHMgKiBuYW5k LT5lY2MuYnl0ZXM7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcmtf bmFuZGNfb29ibGF5b3V0X2ZyZWUoc3RydWN0IG10ZF9pbmZvICptdGQsIGludCBzZWN0aW9uLAo+ ICsJCQkJICAgc3RydWN0IG10ZF9vb2JfcmVnaW9uICpvb2JyZWdpb24pCj4gK3sKPiArCXN0cnVj dCBuYW5kX2NoaXAgKm5hbmQgPSBtdGRfdG9fbmFuZChtdGQpOwo+ICsKPiArCWlmIChzZWN0aW9u ID49IG5hbmQtPmVjYy5zdGVwcykKPiArCQlyZXR1cm4gLUVSQU5HRTsKPiArCj4gKwlvb2JyZWdp b24tPm9mZnNldCA9IChuYW5kLT5lY2MuYnl0ZXMgKyBuYW5kLT5lY2MucHJlcGFkKSAqIHNlY3Rp b247Cj4gKwlvb2JyZWdpb24tPmxlbmd0aCA9IG5hbmQtPmVjYy5zdGVwcyAqIG5hbmQtPmVjYy5w cmVwYWQ7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qg bXRkX29vYmxheW91dF9vcHMgcmtfbmFuZGNfb29iX29wcyA9IHsKPiArCS5lY2MgPSBya19uYW5k Y19vb2JsYXlvdXRfZWNjLAo+ICsJLmZyZWUgPSBya19uYW5kY19vb2JsYXlvdXRfZnJlZSwKPiAr fTsKPiArCj4gK3N0YXRpYyB2b2lkIHJrX25hbmRjX2ZyZWVfYnVmZmVyKHN0cnVjdCBuYW5kX2No aXAgKm5hbmQpCj4gK3sKPiArCXN0cnVjdCBya19uYW5kX2NvbnRyb2xsZXIgKmN0cmwgPSBuYW5k X2dldF9jb250cm9sbGVyX2RhdGEobmFuZCk7Cj4gKwo+ICsJa2ZyZWUoY3RybC0+cGFnZV9idWYp Owo+ICsJa2ZyZWUoY3RybC0+b29iX2J1Zik7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcmtfbmFu ZGNfYnVmZmVyX2luaXQoc3RydWN0IG5hbmRfY2hpcCAqbmFuZCkKPiArewo+ICsJc3RydWN0IG10 ZF9pbmZvICptdGQgPSBuYW5kX3RvX210ZChuYW5kKTsKPiArCXN0cnVjdCBya19uYW5kX2NvbnRy b2xsZXIgKmN0cmwgPSBuYW5kX2dldF9jb250cm9sbGVyX2RhdGEobmFuZCk7Cj4gKwo+ICsJY3Ry bC0+cGFnZV9idWYgPSBrbWFsbG9jKG10ZC0+d3JpdGVzaXplLCBHRlBfS0VSTkVMIHwgR0ZQX0RN QSk7CgpkZXZpY2UgbWFuYWdlZCBhbGxvY2F0aW9ucyAoZGV2bV8uLi4pIHdvdWxkIGJlIG5pY2UK Cj4gKwlpZiAoIWN0cmwtPnBhZ2VfYnVmKQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCWN0 cmwtPm9vYl9idWYgPSBrbWFsbG9jKG5hbmQtPmVjYy5zdGVwcyAqIDEyOCwgR0ZQX0tFUk5FTCB8 IEdGUF9ETUEpOwo+ICsJaWYgKCFjdHJsLT5vb2JfYnVmKSB7Cj4gKwkJa2ZyZWUoY3RybC0+cGFn ZV9idWYpOwo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW50IHJrX25hbmRjX2h3X2VjY19jdHJsX2luaXQoc3RydWN0IG5hbmRf Y2hpcCAqbmFuZCkKPiArewo+ICsJdWludDhfdCBzdHJlbmd0aHNfdjZbXSA9IHs2MCwgNDAsIDI0 LCAxNn07Cj4gKwl1aW50OF90IHN0cmVuZ3Roc192OVtdID0gezcwLCA2MCwgNDAsIDE2fTsKPiAr CXN0cnVjdCBtdGRfaW5mbyAqbXRkID0gbmFuZF90b19tdGQobmFuZCk7Cj4gKwlzdHJ1Y3Qgcmtf bmFuZF9jb250cm9sbGVyICpjdHJsID0gbmFuZF9nZXRfY29udHJvbGxlcl9kYXRhKG5hbmQpOwo+ ICsJaW50IG1heF9zdHJlbmd0aDsKPiArCXVpbnQzMl90IGksIHZlcjsKPiArCj4gKwlpZiAobmFu ZC0+b3B0aW9ucyAmIE5BTkRfSVNfQk9PVF9NRURJVU0pCj4gKwkJY3RybC0+Ym9vdHJvbWJsb2Nr cyA9IHRydWU7Cj4gKwllbHNlCj4gKwkJY3RybC0+Ym9vdHJvbWJsb2NrcyA9IGZhbHNlOwo+ICsK PiArCW5hbmQtPmVjYy5wcmVwYWQgPSA0Owo+ICsJbmFuZC0+ZWNjLnN0ZXBzID0gbXRkLT53cml0 ZXNpemUgLyBuYW5kLT5lY2Muc2l6ZTsKPiArCj4gKwltYXhfc3RyZW5ndGggPSAoKG10ZC0+b29i c2l6ZSAvIG5hbmQtPmVjYy5zdGVwcykgLSA0KSAqIDggLyAxNDsKPiArCWlmIChjdHJsLT52ZXJz aW9uID09IFZFUlNJT05fOSkgewo+ICsJCWN0cmwtPm1heF9lY2Nfc3RyZW5ndGggPSA3MDsKPiAr CQl2ZXIgPSByZWFkbChjdHJsLT5yZWdzICsgTkFORENfUkVHX1Y5X1ZFUik7Cj4gKwkJaWYgKHZl ciAhPSBOQU5EQ19JRF9WOTAwKQo+ICsJCQlkZXZfZXJyKG10ZC0+ZGV2LnBhcmVudCwKPiArCQkJ CSJ1bnN1cHBvcnRlZCBuYW5kYyB2ZXJzaW9uICV4XG4iLCB2ZXIpOwo+ICsKPiArCQlpZiAobWF4 X3N0cmVuZ3RoID4gY3RybC0+bWF4X2VjY19zdHJlbmd0aCkKPiArCQkJbWF4X3N0cmVuZ3RoID0g Y3RybC0+bWF4X2VjY19zdHJlbmd0aDsKPiArCj4gKwkJZm9yIChpID0gMDsgaSA8IEFSUkFZX1NJ WkUoc3RyZW5ndGhzX3Y5KTsgaSsrKSB7Cj4gKwkJCWlmIChtYXhfc3RyZW5ndGggPj0gc3RyZW5n dGhzX3Y5W2ldKQo+ICsJCQkJYnJlYWs7Cj4gKwkJfQo+ICsKPiArCQlpZiAoaSA+PSBBUlJBWV9T SVpFKHN0cmVuZ3Roc192OSkpIHsKPiArCQkJZGV2X2VycihtdGQtPmRldi5wYXJlbnQsCj4gKwkJ CQkidW5zdXBwb3J0ZWQgc3RyZW5ndGhcbiIpOwo+ICsJCQlyZXR1cm4gLUVOT1RTVVBQOwo+ICsJ CX0KPiArCj4gKwkJY3RybC0+ZWNjX21vZGUgPSBzdHJlbmd0aHNfdjlbaV07Cj4gKwl9IGVsc2Ug ewo+ICsJCWN0cmwtPm1heF9lY2Nfc3RyZW5ndGggPSA2MDsKPiArCj4gKwkJdmVyID0gcmVhZGwo Y3RybC0+cmVncyArIE5BTkRDX1JFR19WNl9WRVIpOwo+ICsJCWlmICh2ZXIgPT0gTkFORENfSURf VjgwMSkKPiArCQkJY3RybC0+bWF4X2VjY19zdHJlbmd0aCA9IDE2Owo+ICsJCWVsc2UgaWYgKHZl ciA9PSBOQU5EQ19JRF9WNjAwIHx8Cj4gKwkJCSB2ZXIgPT0gTkFORENfSURfVjYyMiB8fAo+ICsJ CQkgdmVyID09IE5BTkRDX0lEX1Y3MDEgfHwKPiArCQkJIHZlciA9PSBOQU5EQ19JRF9WODAwKQo+ ICsJCQljdHJsLT5tYXhfZWNjX3N0cmVuZ3RoID0gNjA7Cj4gKwkJZWxzZQo+ICsJCQlkZXZfZXJy KG10ZC0+ZGV2LnBhcmVudCwKPiArCQkJCSJ1bnN1cHBvcnRlZCBuYW5kYyB2ZXJzaW9uICV4XG4i LCB2ZXIpOwo+ICsKPiArCQlpZiAobWF4X3N0cmVuZ3RoID4gY3RybC0+bWF4X2VjY19zdHJlbmd0 aCkKPiArCQkJbWF4X3N0cmVuZ3RoID0gY3RybC0+bWF4X2VjY19zdHJlbmd0aDsKPiArCj4gKwkJ Zm9yIChpID0gMDsgaSA8IEFSUkFZX1NJWkUoc3RyZW5ndGhzX3Y2KTsgaSsrKSB7Cj4gKwkJCWlm IChtYXhfc3RyZW5ndGggPj0gc3RyZW5ndGhzX3Y2W2ldKQo+ICsJCQkJYnJlYWs7Cj4gKwkJfQo+ ICsKPiArCQlpZiAoaSA+PSBBUlJBWV9TSVpFKHN0cmVuZ3Roc192NikpIHsKPiArCQkJZGV2X2Vy cihtdGQtPmRldi5wYXJlbnQsCj4gKwkJCQkidW5zdXBwb3J0ZWQgc3RyZW5ndGhcbiIpOwo+ICsJ CQlyZXR1cm4gLUVOT1RTVVBQOwo+ICsJCX0KPiArCj4gKwkJY3RybC0+ZWNjX21vZGUgPSBzdHJl bmd0aHNfdjZbaV07Cj4gKwl9Cj4gKwlya19uYW5kY19od19lY2Nfc2V0dXAobmFuZCwgY3RybC0+ ZWNjX21vZGUpOwo+ICsKPiArCW10ZF9zZXRfb29ibGF5b3V0KG10ZCwgJnJrX25hbmRjX29vYl9v cHMpOwo+ICsKPiArCWlmIChtdGQtPm9vYnNpemUgPCAoKG5hbmQtPmVjYy5ieXRlcyArIG5hbmQt PmVjYy5wcmVwYWQpICoKPiArCQkJICAgIG5hbmQtPmVjYy5zdGVwcykpIHsKPiArCQlyZXR1cm4g LUVJTlZBTDsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQg cmtfbmFuZGNfZGV0YWNoX2NoaXAoc3RydWN0IG5hbmRfY2hpcCAqbmFuZCkKPiArewo+ICsJc3dp dGNoIChuYW5kLT5lY2MubW9kZSkgewo+ICsJY2FzZSBOQU5EX0VDQ19IV19TWU5EUk9NRToKPiAr CQlya19uYW5kY19mcmVlX2J1ZmZlcihuYW5kKTsKPiArCQlicmVhazsKPiArCWRlZmF1bHQ6Cj4g KwkJYnJlYWs7Cj4gKwl9Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcmtfbmFuZGNfYXR0YWNoX2No aXAoc3RydWN0IG5hbmRfY2hpcCAqbmFuZCkKPiArewo+ICsJc3RydWN0IG10ZF9pbmZvICptdGQg PSBuYW5kX3RvX210ZChuYW5kKTsKPiArCWludCByZXQ7Cj4gKwo+ICsJc3dpdGNoIChuYW5kLT5l Y2MubW9kZSkgewo+ICsJY2FzZSBOQU5EX0VDQ19IV19TWU5EUk9NRToKPiArCQlyZXQgPSBya19u YW5kY19od19lY2NfY3RybF9pbml0KG5hbmQpOwo+ICsJCWlmIChyZXQpCj4gKwkJCXJldHVybiBy ZXQ7Cj4gKwkJcmV0ID0gcmtfbmFuZGNfYnVmZmVyX2luaXQobmFuZCk7Cj4gKwkJaWYgKHJldCkK PiArCQkJcmV0dXJuIC1FTk9NRU07Cj4gKwkJbmFuZC0+ZWNjLnJlYWRfcGFnZSA9IHJrX25hbmRj X2h3X3N5bmRyb21lX2VjY19yZWFkX3BhZ2U7Cj4gKwkJbmFuZC0+ZWNjLndyaXRlX3BhZ2UgPSBy a19uYW5kY19od19zeW5kcm9tZV9lY2Nfd3JpdGVfcGFnZTsKPiArCQluYW5kLT5lY2MucmVhZF9v b2IgPSBya19uYW5kY19od19lY2NfcmVhZF9vb2I7Cj4gKwkJbmFuZC0+ZWNjLndyaXRlX29vYiA9 IHJrX25hbmRjX2h3X2VjY193cml0ZV9vb2I7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIE5BTkRfRUND X0hXOgoKSSB3b3VsZCBlaXRoZXIgcmVmdXNlIEVDQ19IVyBvciBwdXQgaXQgYmVzaWRlcyBIV19T WU5EUk9NRS4KCj4gKwljYXNlIE5BTkRfRUNDX05PTkU6Cj4gKwljYXNlIE5BTkRfRUNDX1NPRlQ6 CgpIYXZlIHlvdSB0ZXN0ZWQgd2l0aCBTVyBCQ0g/Cgo+ICsJCWJyZWFrOwo+ICsJZGVmYXVsdDoK PiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiAr c3RhdGljIGludCBya19uYW5kY19leGVjX29wKHN0cnVjdCBuYW5kX2NoaXAgKm5hbmQsCj4gKwkJ CSAgICBjb25zdCBzdHJ1Y3QgbmFuZF9vcGVyYXRpb24gKm9wLAo+ICsJCQkgICAgYm9vbCBjaGVj a19vbmx5KQo+ICt7Cj4gKwlpbnQgaTsKPiArCXVuc2lnbmVkIGludCBvcF9pZDsKPiArCWNvbnN0 IHN0cnVjdCBuYW5kX29wX2luc3RyICppbnN0ciA9IE5VTEw7Cj4gKwo+ICsJcmtfbmFuZGNfc2Vs ZWN0X2NoaXAobmFuZCwgb3AtPmNzKTsKPiArCj4gKwlpZiAoY2hlY2tfb25seSkKPiArCQlyZXR1 cm4gMDsKPiArCj4gKwlmb3IgKG9wX2lkID0gMDsgb3BfaWQgPCBvcC0+bmluc3Ryczsgb3BfaWQr Kykgewo+ICsJCWluc3RyID0gJm9wLT5pbnN0cnNbb3BfaWRdOwo+ICsKPiArCQlzd2l0Y2ggKGlu c3RyLT50eXBlKSB7Cj4gKwkJY2FzZSBOQU5EX09QX0NNRF9JTlNUUjoKPiArCQkJcmtfbmFuZGNf d3JpdGVfY21kKG5hbmQsIGluc3RyLT5jdHguY21kLm9wY29kZSk7Cj4gKwkJCWJyZWFrOwo+ICsJ CWNhc2UgTkFORF9PUF9BRERSX0lOU1RSOgo+ICsJCQlmb3IgKGkgPSAwOyBpIDwgaW5zdHItPmN0 eC5hZGRyLm5hZGRyczsgaSsrKQo+ICsJCQkJcmtfbmFuZGNfd3JpdGVfYWRkcihuYW5kLAo+ICsJ CQkJCQkgICAgaW5zdHItPmN0eC5hZGRyLmFkZHJzW2ldKTsKPiArCQkJYnJlYWs7Cj4gKwkJY2Fz ZSBOQU5EX09QX0RBVEFfSU5fSU5TVFI6Cj4gKwkJCXJrX25hbmRjX3JlYWRfYnVmKG5hbmQsIGlu c3RyLT5jdHguZGF0YS5idWYuaW4sCj4gKwkJCQkJICBpbnN0ci0+Y3R4LmRhdGEubGVuKTsKPiAr CQkJYnJlYWs7Cj4gKwkJY2FzZSBOQU5EX09QX0RBVEFfT1VUX0lOU1RSOgo+ICsJCQlya19uYW5k Y193cml0ZV9idWYobmFuZCwgaW5zdHItPmN0eC5kYXRhLmJ1Zi5vdXQsCj4gKwkJCQkJICAgaW5z dHItPmN0eC5kYXRhLmxlbik7Cj4gKwkJCWJyZWFrOwo+ICsJCWNhc2UgTkFORF9PUF9XQUlUUkRZ X0lOU1RSOgo+ICsJCQlya19uYW5kY19kZXZfcmVhZHkobmFuZCk7Cj4gKwkJCWJyZWFrOwo+ICsJ CX0KPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVj dCBuYW5kX2NvbnRyb2xsZXJfb3BzIHJrX25hbmRfY29udHJvbGxlcl9vcHMgPSB7Cj4gKwkuYXR0 YWNoX2NoaXAgPSBya19uYW5kY19hdHRhY2hfY2hpcCwKPiArCS5kZXRhY2hfY2hpcCA9IHJrX25h bmRjX2RldGFjaF9jaGlwLAo+ICsJLmV4ZWNfb3AgPSBya19uYW5kY19leGVjX29wLAo+ICt9Owo+ ICsKPiArc3RhdGljIGludCBya19uYW5kY19jaGlwX2luaXQoc3RydWN0IGRldmljZSAqZGV2LAo+ ICsJCQkgICAgICBzdHJ1Y3QgcmtfbmFuZF9jb250cm9sbGVyICpjdHJsLAo+ICsJCQkgICAgICBz dHJ1Y3QgZGV2aWNlX25vZGUgKm5wLCB1bnNpZ25lZCBpbnQgY2hpcG5yKQo+ICt7Cj4gKwlzdHJ1 Y3QgcmtfbmFuZF9jaGlwICpub2RlOwo+ICsJc3RydWN0IG5hbmRfY2hpcCAqbmFuZDsKPiArCXN0 cnVjdCBtdGRfaW5mbyAqbXRkOwo+ICsJY29uc3QgX19iZTMyICpyZWc7Cj4gKwlpbnQgcmV0Owo+ ICsKPiArCXJlZyA9IG9mX2dldF9wcm9wZXJ0eShucCwgInJlZyIsIE5VTEwpOwo+ICsJaWYgKCFy ZWcpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJY3RybC0+YmFua3NbY2hpcG5yXSA9IGJl MzJfdG9fY3B1KCpyZWcpOwo+ICsKPiArCWlmIChjdHJsLT5iYW5rc1tjaGlwbnJdIDwgMCkKPiAr CQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwlub2RlID0gZGV2bV9remFsbG9jKGRldiwgc2l6ZW9m KCpub2RlKSwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIW5vZGUpCj4gKwkJcmV0dXJuIC1FTk9NRU07 Cj4gKwo+ICsJbmFuZCA9ICZub2RlLT5uYW5kOwo+ICsKPiArCW5hbmRfc2V0X2ZsYXNoX25vZGUo bmFuZCwgbnApOwo+ICsJbmFuZF9zZXRfY29udHJvbGxlcl9kYXRhKG5hbmQsIGN0cmwpOwo+ICsK PiArCW5hbmQtPmNvbnRyb2xsZXIgPSAmY3RybC0+Y29udHJvbGxlcjsKPiArCW5hbmQtPmNvbnRy b2xsZXItPm9wcyA9ICZya19uYW5kX2NvbnRyb2xsZXJfb3BzOwo+ICsKPiArCW5hbmQtPmVjYy5t b2RlID0gTkFORF9FQ0NfSFdfU1lORFJPTUU7Cj4gKwluYW5kLT5lY2Muc2l6ZSA9IDEwMjQ7Cj4g KwluYW5kLT5lY2Muc3RyZW5ndGggPSA0MDsKPiArCj4gKwluYW5kLT5vcHRpb25zID0gTkFORF9T S0lQX0JCVFNDQU4gfCBOQU5EX05PX1NVQlBBR0VfV1JJVEU7Cj4gKwo+ICsJbXRkID0gbmFuZF90 b19tdGQobmFuZCk7Cj4gKwltdGQtPmRldi5wYXJlbnQgPSBkZXY7Cj4gKwltdGQtPm5hbWUgPSBk ZXZtX2thc3ByaW50ZihkZXYsIEdGUF9LRVJORUwsICIlcy4lZCIsIGRldl9uYW1lKGRldiksCj4g KwkJCQkgICBjdHJsLT5iYW5rc1tjaGlwbnJdKTsKPiArCj4gKwlyZXQgPSBuYW5kX3NjYW4obmFu ZCwgMSk7CgpXaHkgMSBoZXJlPwoKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4g KwlyZXQgPSBtdGRfZGV2aWNlX3JlZ2lzdGVyKG10ZCwgTlVMTCwgMCk7Cj4gKwlpZiAocmV0KSB7 Cj4gKwkJZGV2X2VycihkZXYsICJtdGQgZGV2aWNlIHJlZ2lzdGVyIGZhaWxlZDogJWRcbiIsIHJl dCk7Cj4gKwkJbmFuZF9yZWxlYXNlKG5hbmQpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ ICsJbGlzdF9hZGRfdGFpbCgmbm9kZS0+Y2hpcF9saXN0LCAmY3RybC0+Y2hpcHMpOwo+ICsKPiAr CXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHJrX25hbmRjX2NsZWFudXBfY2hpcHMo c3RydWN0IHJrX25hbmRfY29udHJvbGxlciAqY3RybCkKPiArewo+ICsJc3RydWN0IHJrX25hbmRf Y2hpcCAqbm9kZTsKPiArCXN0cnVjdCBtdGRfaW5mbyAqbXRkOwo+ICsJaW50IHJldDsKPiArCj4g Kwl3aGlsZSAoIWxpc3RfZW1wdHkoJmN0cmwtPmNoaXBzKSkgewo+ICsJCW5vZGUgPSBsaXN0X2Zp cnN0X2VudHJ5KCZjdHJsLT5jaGlwcywgc3RydWN0IHJrX25hbmRfY2hpcCwKPiArCQkJCQljaGlw X2xpc3QpOwo+ICsJCW10ZCA9IG5hbmRfdG9fbXRkKCZub2RlLT5uYW5kKTsKPiArCQlyZXQgPSBt dGRfZGV2aWNlX3VucmVnaXN0ZXIobXRkKTsKPiArCQlpZiAocmV0KQo+ICsJCQlyZXR1cm4gcmV0 Owo+ICsKPiArCQlya19uYW5kY19mcmVlX2J1ZmZlcigmbm9kZS0+bmFuZCk7Cj4gKwkJbmFuZF9j bGVhbnVwKCZub2RlLT5uYW5kKTsKPiArCQlsaXN0X2RlbCgmbm9kZS0+Y2hpcF9saXN0KTsKPiAr CX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBya19uYW5kY19jaGlw c19pbml0KHN0cnVjdCBkZXZpY2UgKmRldiwKPiArCQkJICAgICAgIHN0cnVjdCBya19uYW5kX2Nv bnRyb2xsZXIgKmN0cmwpCj4gK3sKPiArCXN0cnVjdCBkZXZpY2Vfbm9kZSAqbnAgPSBkZXYtPm9m X25vZGU7Cj4gKwlzdHJ1Y3QgZGV2aWNlX25vZGUgKm5hbmRfbnA7Cj4gKwlpbnQgbmNoaXBzID0g b2ZfZ2V0X2NoaWxkX2NvdW50KG5wKTsKPiArCWludCBpID0gMDsKPiArCWludCByZXQ7Cj4gKwo+ ICsJaWYgKG5jaGlwcyA+IE5BTkRDX05VTV9CQU5LUykgewo+ICsJCWRldl9lcnIoZGV2LCAidG9v IG1hbnkgTkFORCBjaGlwczogJWQgKG1heCA9IDQpXG4iLCBuY2hpcHMpOwo+ICsJCXJldHVybiAt RUlOVkFMOwo+ICsJfQo+ICsKPiArCWZvcl9lYWNoX2NoaWxkX29mX25vZGUobnAsIG5hbmRfbnAp IHsKPiArCQlyZXQgPSBya19uYW5kY19jaGlwX2luaXQoZGV2LCBjdHJsLCBuYW5kX25wLCBpKTsK PiArCQlpZiAocmV0KSB7Cj4gKwkJCXJrX25hbmRjX2NsZWFudXBfY2hpcHMoY3RybCk7Cj4gKwkJ CW9mX25vZGVfcHV0KG5hbmRfbnApOwo+ICsJCQlyZXR1cm4gcmV0Owo+ICsJCX0KPiArCQlpKys7 Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcmtfbmFuZGNf cHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKPiArewo+ICsJY29uc3Qgc3RydWN0 IHJrX25hbmRjX2RhdGEgKmRhdGE7Cj4gKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSAmcGRldi0+ZGV2 Owo+ICsJc3RydWN0IGRldmljZV9ub2RlICpub2RlOwo+ICsJaW50IGlkOwo+ICsJaW50IHJldDsK PiArCj4gKwlkYXRhID0gb2ZfZGV2aWNlX2dldF9tYXRjaF9kYXRhKCZwZGV2LT5kZXYpOwo+ICsJ aWYgKCFkYXRhKQo+ICsJCXJldHVybiAtRU5PREVWOwo+ICsKPiArCW5vZGUgPSBwZGV2LT5kZXYu b2Zfbm9kZTsKPiArCj4gKwlpZCA9IG9mX2FsaWFzX2dldF9pZChub2RlLCAibmFuZGMiKTsKPiAr CWlmIChpZCA8IDApCj4gKwkJaWQgPSBnX2lkX2NvdW50ZXI7Cj4gKwlpZiAoKGlkID49IEFSUkFZ X1NJWkUoZ19uYW5kY19pbmZvKSB8fCBnX25hbmRjX2luZm9baWRdLnJlZ3MpKSB7Cj4gKwkJZGV2 X2VycigKPiArCQkJJnBkZXYtPmRldiwKPiArCQkJImZhaWxlZCB0byBnZXQgaWQgZm9yIG5hbmRj IG5vZGUgJyVwT0ZuJ1xuIiwKPiArCQkJbm9kZSk7Cj4gKwkJb2Zfbm9kZV9wdXQobm9kZSk7Cj4g KwkJcmV0dXJuIC1FTk9ERVY7Cj4gKwl9Cj4gKwkrK2dfaWRfY291bnRlcjsKPiArCj4gKwlnX25h bmRjX2luZm9baWRdLnZlcnNpb24gPSBkYXRhLT52ZXJzaW9uOwo+ICsKPiArCWdfbmFuZGNfaW5m b1tpZF0ucmVncyA9IGRldm1fcGxhdGZvcm1faW9yZW1hcF9yZXNvdXJjZShwZGV2LCAwKTsKPiAr CWlmIChJU19FUlIoZ19uYW5kY19pbmZvW2lkXS5yZWdzKSkgewo+ICsJCWRldl9lcnIoZGV2LCAi aW9yZW1hcCBmYWlsZWRcbiIpOwo+ICsJCXJldHVybiBQVFJfRVJSKGdfbmFuZGNfaW5mb1tpZF0u cmVncyk7Cj4gKwl9Cj4gKwo+ICsJZ19uYW5kY19pbmZvW2lkXS5pcnEgPSBwbGF0Zm9ybV9nZXRf aXJxKHBkZXYsIDApOwo+ICsJaWYgKGdfbmFuZGNfaW5mb1tpZF0uaXJxIDwgMCkgewo+ICsJCWRl dl9lcnIoZGV2LCAiZ2V0IGlycSBmYWlsZWRcbiIpOwo+ICsJCXJldHVybiBnX25hbmRjX2luZm9b aWRdLmlycTsKPiArCX0KPiArCj4gKwlnX25hbmRjX2luZm9baWRdLmhjbGsgPSBkZXZtX2Nsa19n ZXQoZGV2LCAiaGNsa19uYW5kYyIpOwo+ICsJaWYgKElTX0VSUihnX25hbmRjX2luZm9baWRdLmhj bGspKSB7Cj4gKwkJZGV2X2VycihkZXYsICJnZXQgaGNsa19uYW5kYyBmYWlsZWRcbiIpOwo+ICsJ CXJldHVybiBQVFJfRVJSKGdfbmFuZGNfaW5mb1tpZF0uaGNsayk7Cj4gKwl9Cj4gKwo+ICsJcmV0 ID0gY2xrX3ByZXBhcmVfZW5hYmxlKGdfbmFuZGNfaW5mb1tpZF0uaGNsayk7Cj4gKwlpZiAocmV0 KQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJZ19uYW5kY19pbmZvW2lkXS5jbGsgPSBkZXZtX2Ns a19nZXQoZGV2LCAiY2xrX25hbmRjIik7Cj4gKwlpZiAoIShJU19FUlIoZ19uYW5kY19pbmZvW2lk XS5jbGspKSkgewo+ICsJCWNsa19zZXRfcmF0ZShnX25hbmRjX2luZm9baWRdLmNsaywgMTUwICog MTAwMCAqIDEwMDApOwo+ICsKPiArCQlyZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoZ19uYW5kY19p bmZvW2lkXS5jbGspOwo+ICsJCWlmIChyZXQpCj4gKwkJCWdvdG8gZXJyX2Rpc2FibGVfaGNsazsK PiArCX0gZWxzZQo+ICsJCWRldl9lcnIoZGV2LCAiZ2V0IGNsa19uYW5kYyBmYWlsZWRcbiIpOwo+ ICsKPiArCWlmIChnX25hbmRjX2luZm9baWRdLnZlcnNpb24gPT0gVkVSU0lPTl85KQo+ICsJCXdy aXRlbCgwLCBnX25hbmRjX2luZm9baWRdLnJlZ3MgKyBOQU5EQ19SRUdfVjlfSU5URU4pOwo+ICsJ ZWxzZQo+ICsJCXdyaXRlbCgwLCBnX25hbmRjX2luZm9baWRdLnJlZ3MgKyBOQU5EQ19SRUdfVjZf SU5URU4pOwo+ICsJcmV0ID0gZGV2bV9yZXF1ZXN0X2lycShkZXYsIGdfbmFuZGNfaW5mb1tpZF0u aXJxLCBya19uYW5kY19pbnRlcnJ1cHQsCj4gKwkJCSAgICAgICAwLCAibmFuZGMiLCAmZ19uYW5k Y19pbmZvW2lkXSk7Cj4gKwlpZiAocmV0KQo+ICsJCWdvdG8gZXJyX2Rpc2FibGVfY2xrOwo+ICsK PiArCW5hbmRfY29udHJvbGxlcl9pbml0KCZnX25hbmRjX2luZm9baWRdLmNvbnRyb2xsZXIpOwo+ ICsJSU5JVF9MSVNUX0hFQUQoJmdfbmFuZGNfaW5mb1tpZF0uY2hpcHMpOwo+ICsKPiArCXJrX25h bmRjX2luaXQoJmdfbmFuZGNfaW5mb1tpZF0pOwo+ICsKPiArCXJldCA9IHJrX25hbmRjX2NoaXBz X2luaXQoZGV2LCAmZ19uYW5kY19pbmZvW2lkXSk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZGV2X2Vy cihkZXYsICJpbml0IG5hbmQgY2hpcHMgZmFpbGVkXG4iKTsKPiArCQlnb3RvIGVycl9kaXNhYmxl X2NsazsKPiArCX0KPiArCj4gKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2LCAmZ19uYW5kY19p bmZvW2lkXSk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gKwo+ICtlcnJfZGlzYWJsZV9jbGs6Cj4gKwlj bGtfZGlzYWJsZV91bnByZXBhcmUoZ19uYW5kY19pbmZvW2lkXS5jbGspOwo+ICtlcnJfZGlzYWJs ZV9oY2xrOgo+ICsJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKGdfbmFuZGNfaW5mb1tpZF0uaGNsayk7 Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGludCBya19uYW5kY19yZW1v dmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKPiArewo+ICsJc3RydWN0IHJrX25hbmRf Y29udHJvbGxlciAqY3RybCA9IHBsYXRmb3JtX2dldF9kcnZkYXRhKHBkZXYpOwo+ICsJaW50IHJl dDsKPiArCj4gKwlyZXQgPSBya19uYW5kY19jbGVhbnVwX2NoaXBzKGN0cmwpOwo+ICsJaWYgKHJl dCkKPiArCQlyZXR1cm4gcmV0Owo+ICsKPiArCWNsa19kaXNhYmxlX3VucHJlcGFyZShjdHJsLT5j bGspOwo+ICsJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKGN0cmwtPmhjbGspOwo+ICsJcGxhdGZvcm1f c2V0X2RydmRhdGEocGRldiwgTlVMTCk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0 YXRpYyB2b2lkIHJrX25hbmRjX3NodXRkb3duKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYp Cj4gK3sKPiArCXN0cnVjdCBya19uYW5kX2NvbnRyb2xsZXIgKmN0cmwgPSBwbGF0Zm9ybV9nZXRf ZHJ2ZGF0YShwZGV2KTsKPiArCWludCByZXQ7Cj4gKwo+ICsJcmV0ID0gcmtfbmFuZGNfY2xlYW51 cF9jaGlwcyhjdHJsKTsKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuOwo+ICsKPiArCWNsa19kaXNh YmxlX3VucHJlcGFyZShjdHJsLT5jbGspOwo+ICsJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKGN0cmwt PmhjbGspOwo+ICsJcGxhdGZvcm1fc2V0X2RydmRhdGEocGRldiwgTlVMTCk7Cj4gK30KPiArCj4g K3N0YXRpYyBjb25zdCBzdHJ1Y3QgcmtfbmFuZGNfZGF0YSBya19uYW5kY192Nl9kYXRhID0gewo+ ICsJLnZlcnNpb24gPSBWRVJTSU9OXzYsCj4gK307Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0 IHJrX25hbmRjX2RhdGEgcmtfbmFuZGNfdjlfZGF0YSA9IHsKPiArCS52ZXJzaW9uID0gVkVSU0lP Tl85LAo+ICt9Owo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgb2Zfcmtf bmFuZGNfbWF0Y2hbXSA9IHsKPiArCXsKPiArCQkuY29tcGF0aWJsZSA9ICJyb2NrY2hpcCxuYW5k Yy12NiIsCj4gKwkJLmRhdGEgPSAmcmtfbmFuZGNfdjZfZGF0YSwKPiArCX0sCj4gKwl7Cj4gKwkJ LmNvbXBhdGlibGUgPSAicm9ja2NoaXAsbmFuZGMtdjkiLAo+ICsJCS5kYXRhID0gJnJrX25hbmRj X3Y5X2RhdGEsCj4gKwl9LAo+ICsJeyAvKiBzZW50aW5lbCAqLyB9LAo+ICt9Owo+ICsKPiArc3Rh dGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgcmtfbmFuZGNfZHJpdmVyID0gewo+ICsJLnByb2Jl ICA9IHJrX25hbmRjX3Byb2JlLAo+ICsJLnJlbW92ZSA9IHJrX25hbmRjX3JlbW92ZSwKPiArCS5z aHV0ZG93biA9IHJrX25hbmRjX3NodXRkb3duLAo+ICsJLmRyaXZlciA9IHsKPiArCQkubmFtZSA9 ICJyb2NrY2hpcC1uYW5kYyIsCj4gKwkJLm9mX21hdGNoX3RhYmxlID0gb2ZfcmtfbmFuZGNfbWF0 Y2gsCj4gKwl9LAo+ICt9Owo+ICsKCk1vdmUgdGhpcyBlbXB0eSBsaW5lLi4uCgo+ICttb2R1bGVf cGxhdGZvcm1fZHJpdmVyKHJrX25hbmRjX2RyaXZlcik7CgouLi5IZXJlCgo+ICtNT0RVTEVfTElD RU5TRSgiR1BMIHYyIik7CgpUaGFua3MsCk1pcXXDqGwKCl9fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0Cmxp bnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFk Lm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK