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=-5.3 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS, USER_AGENT_SANE_2 autolearn=no 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 0F58DC43461 for ; Mon, 7 Sep 2020 17:26:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D2EBC206E6 for ; Mon, 7 Sep 2020 17:26:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729790AbgIGR0N convert rfc822-to-8bit (ORCPT ); Mon, 7 Sep 2020 13:26:13 -0400 Received: from relay7-d.mail.gandi.net ([217.70.183.200]:34247 "EHLO relay7-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729538AbgIGNUv (ORCPT ); Mon, 7 Sep 2020 09:20:51 -0400 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 9485620007; Mon, 7 Sep 2020 13:20:27 +0000 (UTC) Date: Mon, 7 Sep 2020 15:20:25 +0200 From: Miquel Raynal To: "Ramuthevar,Vadivel MuruganX" Cc: linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, devicetree@vger.kernel.org, richard@nod.at, vigneshr@ti.com, arnd@arndb.de, brendanhiggins@google.com, tglx@linutronix.de, boris.brezillon@collabora.com, anders.roxell@linaro.org, masonccyang@mxic.com.tw, robh+dt@kernel.org, linux-mips@vger.kernel.org, hauke.mehrtens@intel.com, andriy.shevchenko@intel.com, cheol.yong.kim@intel.com, qi-ming.wu@intel.com Subject: Re: [RESEND PATCH v12 2/2] mtd: rawnand: Add NAND controller support on Intel LGM SoC Message-ID: <20200907152025.66c18f5e@xps13> In-Reply-To: <20200817052709.47035-3-vadivel.muruganx.ramuthevar@linux.intel.com> References: <20200817052709.47035-1-vadivel.muruganx.ramuthevar@linux.intel.com> <20200817052709.47035-3-vadivel.muruganx.ramuthevar@linux.intel.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 Murugan, A few more comments below, but I guess the driver looks better now. > +struct ebu_nand_controller { > + struct nand_controller controller; > + struct nand_chip chip; > + struct device *dev; > + void __iomem *ebu; > + void __iomem *hsnand; > + struct dma_chan *dma_tx; > + struct dma_chan *dma_rx; > + struct completion dma_access_complete; > + unsigned long clk_rate; > + struct clk *clk; > + u32 nd_para0; > + u8 cs_num; > + struct ebu_nand_cs cs[MAX_CS]; > +}; > + > +static inline struct ebu_nand_controller *nand_to_ebu(struct nand_chip *chip) > +{ > + return container_of(chip, struct ebu_nand_controller, chip); > +} > + > +static u8 ebu_nand_readb(struct nand_chip *chip) Can't you prefix with intel_ instead of ebu_ ? > +{ > + struct ebu_nand_controller *ebu_host = nand_get_controller_data(chip); > + void __iomem *nand_wait = ebu_host->ebu + EBU_WAIT; > + u8 cs_num = ebu_host->cs_num; > + u32 stat; > + int ret; > + u8 val; > + > + val = readb(ebu_host->cs[cs_num].chipaddr + HSNAND_CS_OFFS); > + > + ret = readl_poll_timeout(nand_wait, stat, stat & EBU_WAIT_WR_C, > + 20, 1000); If you do this operation each time a byte is read/written, you probable want to shrink the polling delay a little bit, to 1 or even 0. > + if (ret) > + dev_warn(ebu_host->dev, > + "ebu nand write timeout. nand_wait(0x%p)=0x%x\n", > + nand_wait, readl(nand_wait)); > + > + return val; You should not return val if ret is !0 I guess > +} > + > +static void ebu_nand_writeb(struct nand_chip *chip, u32 offset, u8 value) > +{ > + struct ebu_nand_controller *ebu_host = nand_get_controller_data(chip); > + void __iomem *nand_wait = ebu_host->ebu + EBU_WAIT; > + u8 cs_num = ebu_host->cs_num; > + u32 stat; > + int ret; > + > + writeb(value, ebu_host->cs[cs_num].chipaddr + offset); > + > + ret = readl_poll_timeout(nand_wait, stat, stat & EBU_WAIT_WR_C, > + 20, 1000); Here as well > + if (ret) > + dev_warn(ebu_host->dev, > + "ebu nand write timeout. nand_wait(0x%p)=0x%x\n", > + nand_wait, readl(nand_wait)); If this can fail, then the helper should return an error and be treated. > +} > + > +static void ebu_read_buf(struct nand_chip *chip, u_char *buf, unsigned int len) > +{ > + int i; > + > + for (i = 0; i < len; i++) > + buf[i] = ebu_nand_readb(chip); > +} > + > +static void ebu_write_buf(struct nand_chip *chip, const u_char *buf, int len) > +{ > + int i; > + > + for (i = 0; i < len; i++) > + ebu_nand_writeb(chip, HSNAND_CS_OFFS, buf[i]); > +} > + > +static void ebu_nand_disable(struct nand_chip *chip) > +{ > + struct ebu_nand_controller *ebu_host = nand_get_controller_data(chip); > + > + writel(0, ebu_host->ebu + EBU_CON); > +} > + > +static void ebu_select_chip(struct nand_chip *chip) > +{ > + struct ebu_nand_controller *ebu_host = nand_get_controller_data(chip); > + void __iomem *nand_con = ebu_host->ebu + EBU_CON; > + u32 cs = ebu_host->cs_num; > + > + writel(EBU_CON_NANDM_EN | EBU_CON_CSMUX_E_EN | EBU_CON_CS_P_LOW | > + EBU_CON_SE_P_LOW | EBU_CON_WP_P_LOW | EBU_CON_PRE_P_LOW | > + EBU_CON_IN_CS_S(cs) | EBU_CON_OUT_CS_S(cs) | > + EBU_CON_LAT_EN_CS_P, nand_con); > +} > + > +static void ebu_nand_setup_timing(struct ebu_nand_controller *ctrl, > + const struct nand_sdr_timings *timings) > +{ > + unsigned int rate = clk_get_rate(ctrl->clk) / 1000000; > + unsigned int period = DIV_ROUND_UP(1000000, rate); > + u32 trecov, thold, twrwait, trdwait; > + u32 reg = 0; > + > + trecov = DIV_ROUND_UP(max(timings->tREA_max, timings->tREH_min), > + period); > + reg |= EBU_BUSCON_RECOVC(trecov); > + > + thold = DIV_ROUND_UP(max(timings->tDH_min, timings->tDS_min), period); > + reg |= EBU_BUSCON_HOLDC(thold); > + > + trdwait = DIV_ROUND_UP(max(timings->tRC_min, timings->tREH_min), > + period); > + reg |= EBU_BUSCON_WAITRDC(trdwait); > + > + twrwait = DIV_ROUND_UP(max(timings->tWC_min, timings->tWH_min), period); > + reg |= EBU_BUSCON_WAITWRC(twrwait); > + > + reg |= EBU_BUSCON_CMULT_V4 | EBU_BUSCON_BCGEN_CS | EBU_BUSCON_ALEC | > + EBU_BUSCON_SETUP_EN; > + > + writel(reg, ctrl->ebu + EBU_BUSCON(ctrl->cs_num)); > +} > + > +static int ebu_nand_setup_data_interface(struct nand_chip *chip, int csline, > + const struct nand_data_interface *conf) I recently changed the naming around the data interface, please have a look at the recent commits and update the namings here as well. > +{ > + struct ebu_nand_controller *ctrl = nand_to_ebu(chip); > + const struct nand_sdr_timings *timings; > + > + timings = nand_get_sdr_timings(conf); > + if (IS_ERR(timings)) > + return PTR_ERR(timings); > + > + if (csline == NAND_DATA_IFACE_CHECK_ONLY) > + return 0; > + > + ebu_nand_setup_timing(ctrl, timings); > + > + return 0; > +} > + > +static int ebu_nand_ooblayout_ecc(struct mtd_info *mtd, int section, > + struct mtd_oob_region *oobregion) > +{ > + struct nand_chip *chip = mtd_to_nand(mtd); > + > + if (section) > + return -ERANGE; > + > + oobregion->offset = HSNAND_ECC_OFFSET; > + oobregion->length = chip->ecc.total; > + > + return 0; > +} > + > +static int ebu_nand_ooblayout_free(struct mtd_info *mtd, int section, > + struct mtd_oob_region *oobregion) > +{ > + struct nand_chip *chip = mtd_to_nand(mtd); > + > + if (section) > + return -ERANGE; > + > + oobregion->offset = chip->ecc.total + HSNAND_ECC_OFFSET; > + oobregion->length = mtd->oobsize - oobregion->offset; > + > + return 0; > +} > + > +static const struct mtd_ooblayout_ops ebu_nand_ooblayout_ops = { > + .ecc = ebu_nand_ooblayout_ecc, > + .free = ebu_nand_ooblayout_free, > +}; > + > +static void ebu_dma_rx_callback(void *cookie) > +{ > + struct ebu_nand_controller *ebu_host = cookie; > + > + dmaengine_terminate_async(ebu_host->dma_rx); > + > + complete(&ebu_host->dma_access_complete); > +} > + > +static void ebu_dma_tx_callback(void *cookie) > +{ > + struct ebu_nand_controller *ebu_host = cookie; > + > + dmaengine_terminate_async(ebu_host->dma_tx); > + > + complete(&ebu_host->dma_access_complete); > +} > + > +static int ebu_dma_start(struct ebu_nand_controller *ebu_host, u32 dir, > + const u8 *buf, u32 len) > +{ > + struct dma_async_tx_descriptor *tx; > + struct completion *dma_completion; > + dma_async_tx_callback callback; > + struct dma_chan *chan; > + dma_cookie_t cookie; > + unsigned long flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; > + dma_addr_t buf_dma; > + int ret; > + u32 timeout; > + > + if (dir == DMA_DEV_TO_MEM) { > + chan = ebu_host->dma_rx; > + dma_completion = &ebu_host->dma_access_complete; > + callback = ebu_dma_rx_callback; > + } else { > + chan = ebu_host->dma_tx; > + dma_completion = &ebu_host->dma_access_complete; > + callback = ebu_dma_tx_callback; > + } > + > + buf_dma = dma_map_single(chan->device->dev, (void *)buf, len, dir); > + if (dma_mapping_error(chan->device->dev, buf_dma)) { > + dev_err(ebu_host->dev, "Failed to map DMA buffer\n"); > + ret = -EIO; > + goto err_unmap; > + } > + > + tx = dmaengine_prep_slave_single(chan, buf_dma, len, dir, flags); > + if (!tx) > + return -ENXIO; > + > + tx->callback = callback; > + tx->callback_param = ebu_host; > + cookie = tx->tx_submit(tx); > + > + ret = dma_submit_error(cookie); > + if (ret) { > + dev_err(ebu_host->dev, "dma_submit_error %d\n", cookie); > + ret = -EIO; > + goto err_unmap; > + } > + > + init_completion(dma_completion); > + dma_async_issue_pending(chan); > + > + /* Wait DMA to finish the data transfer.*/ > + timeout = Don't break the line here > + wait_for_completion_timeout(dma_completion, msecs_to_jiffies(1000)); > + if (!timeout) { > + dev_err(ebu_host->dev, "I/O Error in DMA RX (status %d)\n", > + dmaengine_tx_status(chan, cookie, NULL)); > + dmaengine_terminate_sync(chan); > + ret = -ETIMEDOUT; > + goto err_unmap; > + } > + > + return 0; > + > +err_unmap: > + dma_unmap_single(ebu_host->dev, buf_dma, len, dir); > + > + return ret; > +} > + > +static void ebu_nand_trigger(struct ebu_nand_controller *ebu_host, > + int page, u32 cmd) > +{ > + unsigned int val; > + > + val = cmd | (page & 0xFF) << HSNAND_CTL1_ADDR_SHIFT; > + writel(val, ebu_host->hsnand + HSNAND_CTL1); > + val = (page & 0xFFFF00) >> 8 | HSNAND_CTL2_CYC_N_V5; > + writel(val, ebu_host->hsnand + HSNAND_CTL2); > + > + writel(ebu_host->nd_para0, ebu_host->hsnand + HSNAND_PARA0); > + > + /* clear first, will update later */ > + writel(0xFFFFFFFF, ebu_host->hsnand + HSNAND_CMSG_0); > + writel(0xFFFFFFFF, ebu_host->hsnand + HSNAND_CMSG_1); > + > + writel(HSNAND_INT_MSK_CTL_WR_C, > + ebu_host->hsnand + HSNAND_INT_MSK_CTL); > + > + val = cmd == NAND_CMD_READ0 ? HSNAND_CTL_RW_READ : HSNAND_CTL_RW_WRITE; I don't like this, prefer having a "read/write" boolean as a parameter. > + > + writel(HSNAND_CTL_MSG_EN | HSNAND_CTL_CKFF_EN | > + HSNAND_CTL_ECC_OFF_V8TH | HSNAND_CTL_CE_SEL_CS(ebu_host->cs_num) | > + HSNAND_CTL_ENABLE_ECC | HSNAND_CTL_GO | val, > + ebu_host->hsnand + HSNAND_CTL); > +} > + > +static int ebu_nand_read_page_hwecc(struct nand_chip *chip, u8 *buf, > + int oob_required, int page) > +{ > + struct mtd_info *mtd = nand_to_mtd(chip); > + struct ebu_nand_controller *ebu_host = nand_get_controller_data(chip); > + int ret, x; > + > + ebu_nand_trigger(ebu_host, page, NAND_CMD_READ0); > + > + ret = ebu_dma_start(ebu_host, DMA_DEV_TO_MEM, buf, mtd->writesize); > + if (ret) > + return ret; > + > + if (oob_required) > + chip->ecc.read_oob(chip, page); > + > + x = readl(ebu_host->hsnand + HSNAND_CTL); > + x &= ~HSNAND_CTL_GO; > + writel(x, ebu_host->hsnand + HSNAND_CTL); > + > + return 0; > +} > + > +static int ebu_nand_write_page_hwecc(struct nand_chip *chip, const u8 *buf, > + int oob_required, int page) > +{ > + struct mtd_info *mtd = nand_to_mtd(chip); > + struct ebu_nand_controller *ebu_host = nand_get_controller_data(chip); > + void __iomem *int_sta = ebu_host->hsnand + HSNAND_INT_STA; > + int ret, val, x; > + u32 reg; > + > + ebu_nand_trigger(ebu_host, page, NAND_CMD_SEQIN); > + > + ret = ebu_dma_start(ebu_host, DMA_MEM_TO_DEV, buf, mtd->writesize); > + if (ret) > + return ret; > + > + if (oob_required) { > + reg = (chip->oob_poi[3] << 24) | (chip->oob_poi[2] << 16) | > + (chip->oob_poi[1] << 8) | chip->oob_poi[0]; > + > + writel(reg, ebu_host->hsnand + HSNAND_CMSG_0); > + > + reg = (chip->oob_poi[7] << 24) | (chip->oob_poi[6] << 16) | > + (chip->oob_poi[5] << 8) | chip->oob_poi[4]; > + > + writel(reg, ebu_host->hsnand + HSNAND_CMSG_1); > + } > + > + ret = readl_poll_timeout_atomic(int_sta, val, > + !(val & HSNAND_INT_STA_WR_C), 10, 1000); > + if (ret) > + return -EIO; return ret ? > + > + x = readl(ebu_host->hsnand + HSNAND_CTL); > + x &= ~HSNAND_CTL_GO; > + writel(x, ebu_host->hsnand + HSNAND_CTL); What is this? Looks like it deserves a helper with a nice name. > + > + return 0; > +} > + > +static const u8 ecc_strength[] = { 1, 1, 4, 8, 24, 32, 40, 60, }; ^ is this normal? > + > +static int ebu_nand_attach_chip(struct nand_chip *chip) > +{ > + struct mtd_info *mtd = nand_to_mtd(chip); > + struct ebu_nand_controller *ebu_host = nand_get_controller_data(chip); > + u32 ecc_steps, ecc_bytes, ecc_total, pagesize, pg_per_blk; > + u32 ecc_strength_ds = chip->ecc.strength; > + u32 ecc_size = chip->ecc.size; > + u32 writesize = mtd->writesize; > + u32 blocksize = mtd->erasesize; > + int bch_algo, start, val; > + > + if (chip->ecc.mode != NAND_ECC_HW) > + return 0; > + > + /* Default to an ECC size of 512 */ > + if (!chip->ecc.size) > + chip->ecc.size = 512; > + > + switch (ecc_size) { > + case 512: > + start = 1; > + if (!ecc_strength_ds) > + ecc_strength_ds = 4; > + break; > + case 1024: > + start = 4; > + if (!ecc_strength_ds) > + ecc_strength_ds = 32; > + break; > + default: > + return -EINVAL; > + } > + > + /* BCH ECC algorithm Settings for number of bits per 512B/1024B */ > + bch_algo = round_up(start + 1, 4); > + for (val = start; val < bch_algo; val++) { > + if (ecc_strength_ds == ecc_strength[val]) > + break; > + } > + if (val == bch_algo) > + return -EINVAL; > + > + if (ecc_strength_ds == 8) > + ecc_bytes = 14; > + else > + ecc_bytes = DIV_ROUND_UP(ecc_strength_ds * fls(8 * ecc_size), 8); > + > + ecc_steps = writesize / ecc_size; > + ecc_total = ecc_steps * ecc_bytes; > + if ((ecc_total + 8) > mtd->oobsize) > + return -ERANGE; > + > + chip->ecc.total = ecc_total; > + pagesize = fls(writesize >> 11); > + if (pagesize > HSNAND_PARA0_PAGE_V8192) > + return -ERANGE; > + > + pg_per_blk = fls((blocksize / writesize) >> 6) << 4; If << 4 is here to mean / 8, then I don't want a shift operation because it is highly unreadable and compilers know how to optimize this. > + if (pg_per_blk > HSNAND_PARA0_PIB_V256) > + return -ERANGE; > + > + ebu_host->nd_para0 = pagesize | pg_per_blk | HSNAND_PARA0_BYP_EN_NP | > + HSNAND_PARA0_BYP_DEC_NP | HSNAND_PARA0_ADEP_EN | > + HSNAND_PARA0_TYPE_ONFI | (val << 29); > + > + mtd_set_ooblayout(mtd, &ebu_nand_ooblayout_ops); > + chip->ecc.read_page = ebu_nand_read_page_hwecc; > + chip->ecc.write_page = ebu_nand_write_page_hwecc; > + > + return 0; > +} > + > +static int ebu_nand_exec_op(struct nand_chip *chip, > + const struct nand_operation *op, bool check_only) > +{ > + struct ebu_nand_controller *ctrl = nand_to_ebu(chip); > + const struct nand_op_instr *instr = NULL; > + unsigned int op_id; > + int i, time_out, ret = 0; > + u32 stat; > + > + if (check_only) > + ebu_select_chip(chip); What is the point of selecting the chip if check_only is true? > + > + for (op_id = 0; op_id < op->ninstrs; op_id++) { > + instr = &op->instrs[op_id]; > + > + switch (instr->type) { > + case NAND_OP_CMD_INSTR: > + ebu_nand_writeb(chip, HSNAND_CLE_OFFS | HSNAND_CS_OFFS, > + instr->ctx.cmd.opcode); > + break; > + > + case NAND_OP_ADDR_INSTR: > + for (i = 0; i < instr->ctx.addr.naddrs; i++) > + ebu_nand_writeb(chip, > + HSNAND_ALE_OFFS | HSNAND_CS_OFFS, > + instr->ctx.addr.addrs[i]); > + break; > + > + case NAND_OP_DATA_IN_INSTR: > + ebu_read_buf(chip, instr->ctx.data.buf.in, > + instr->ctx.data.len); > + break; > + > + case NAND_OP_DATA_OUT_INSTR: > + ebu_write_buf(chip, instr->ctx.data.buf.out, > + instr->ctx.data.len); > + break; > + > + case NAND_OP_WAITRDY_INSTR: > + time_out = instr->ctx.waitrdy.timeout_ms * 1000; > + ret = readl_poll_timeout(ctrl->ebu + EBU_WAIT, > + stat, stat & EBU_WAIT_RDBY, > + 20, time_out); > + break; > + } > + } > + > + return ret; > +} 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=-5.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_2 autolearn=no 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 6B139C43461 for ; Mon, 7 Sep 2020 13:21:38 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (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 C32A2207C3 for ; Mon, 7 Sep 2020 13:21:37 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="LqmyoDj6" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C32A2207C3 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=merlin.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=e2IPPCGPmsB0FHUz0s/KFGeEEM4kDTq5ntAYfXM+Tmg=; b=LqmyoDj6kl4kBwWmBDf1/p5JY bwF9kbrIOYaEK2kKIyp8JrK7/i/wurJ47+zj+LqqLpjkpHNYbeCjPLcBbifNZ9THPZByfieWkVGB4 37eicUW8tbjrtPsMMTm9JSxszbQZNhTJW7HOTVKpeUXR1npID7JPKnOehKZA7mzgY5sZQD7gw5xUS 2sjjV2cw7wDHtpJy3zNHMDJvyjOshjEGPiLUI7ZWHM11xV4ubzCtuAmvUYS4nff7Kjw2+5nxng1Hi cLCy1SlTryf8L4KdqQ3A4ZBX9FoXfA5NA3yj1BKtH8mlImdDhXLsvaSStxboxkOcjDWuoaUniD12h Yfutn1WJg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kFH4X-0000JL-9C; Mon, 07 Sep 2020 13:20:37 +0000 Received: from relay7-d.mail.gandi.net ([217.70.183.200]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kFH4U-0000Cq-Lo for linux-mtd@lists.infradead.org; Mon, 07 Sep 2020 13:20:36 +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 9485620007; Mon, 7 Sep 2020 13:20:27 +0000 (UTC) Date: Mon, 7 Sep 2020 15:20:25 +0200 From: Miquel Raynal To: "Ramuthevar,Vadivel MuruganX" Subject: Re: [RESEND PATCH v12 2/2] mtd: rawnand: Add NAND controller support on Intel LGM SoC Message-ID: <20200907152025.66c18f5e@xps13> In-Reply-To: <20200817052709.47035-3-vadivel.muruganx.ramuthevar@linux.intel.com> References: <20200817052709.47035-1-vadivel.muruganx.ramuthevar@linux.intel.com> <20200817052709.47035-3-vadivel.muruganx.ramuthevar@linux.intel.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-20200907_092034_889463_CAC44E63 X-CRM114-Status: GOOD ( 26.62 ) 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: cheol.yong.kim@intel.com, devicetree@vger.kernel.org, qi-ming.wu@intel.com, anders.roxell@linaro.org, vigneshr@ti.com, arnd@arndb.de, hauke.mehrtens@intel.com, richard@nod.at, brendanhiggins@google.com, linux-kernel@vger.kernel.org, robh+dt@kernel.org, linux-mips@vger.kernel.org, boris.brezillon@collabora.com, linux-mtd@lists.infradead.org, tglx@linutronix.de, masonccyang@mxic.com.tw, andriy.shevchenko@intel.com 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 SGkgTXVydWdhbiwKCkEgZmV3IG1vcmUgY29tbWVudHMgYmVsb3csIGJ1dCBJIGd1ZXNzIHRoZSBk cml2ZXIgbG9va3MgYmV0dGVyIG5vdy4KCj4gK3N0cnVjdCBlYnVfbmFuZF9jb250cm9sbGVyIHsK PiArCXN0cnVjdCBuYW5kX2NvbnRyb2xsZXIgY29udHJvbGxlcjsKPiArCXN0cnVjdCBuYW5kX2No aXAgY2hpcDsKPiArCXN0cnVjdCBkZXZpY2UgKmRldjsKPiArCXZvaWQgX19pb21lbSAqZWJ1Owo+ ICsJdm9pZCBfX2lvbWVtICpoc25hbmQ7Cj4gKwlzdHJ1Y3QgZG1hX2NoYW4gKmRtYV90eDsKPiAr CXN0cnVjdCBkbWFfY2hhbiAqZG1hX3J4Owo+ICsJc3RydWN0IGNvbXBsZXRpb24gZG1hX2FjY2Vz c19jb21wbGV0ZTsKPiArCXVuc2lnbmVkIGxvbmcgY2xrX3JhdGU7Cj4gKwlzdHJ1Y3QgY2xrICpj bGs7Cj4gKwl1MzIgbmRfcGFyYTA7Cj4gKwl1OCBjc19udW07Cj4gKwlzdHJ1Y3QgZWJ1X25hbmRf Y3MgY3NbTUFYX0NTXTsKPiArfTsKPiArCj4gK3N0YXRpYyBpbmxpbmUgc3RydWN0IGVidV9uYW5k X2NvbnRyb2xsZXIgKm5hbmRfdG9fZWJ1KHN0cnVjdCBuYW5kX2NoaXAgKmNoaXApCj4gK3sKPiAr CXJldHVybiBjb250YWluZXJfb2YoY2hpcCwgc3RydWN0IGVidV9uYW5kX2NvbnRyb2xsZXIsIGNo aXApOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdTggZWJ1X25hbmRfcmVhZGIoc3RydWN0IG5hbmRfY2hp cCAqY2hpcCkKCkNhbid0IHlvdSBwcmVmaXggd2l0aCBpbnRlbF8gaW5zdGVhZCBvZiBlYnVfID8K Cj4gK3sKPiArCXN0cnVjdCBlYnVfbmFuZF9jb250cm9sbGVyICplYnVfaG9zdCA9IG5hbmRfZ2V0 X2NvbnRyb2xsZXJfZGF0YShjaGlwKTsKPiArCXZvaWQgX19pb21lbSAqbmFuZF93YWl0ID0gZWJ1 X2hvc3QtPmVidSArIEVCVV9XQUlUOwo+ICsJdTggY3NfbnVtID0gZWJ1X2hvc3QtPmNzX251bTsK PiArCXUzMiBzdGF0Owo+ICsJaW50IHJldDsKPiArCXU4IHZhbDsKPiArCj4gKwl2YWwgPSByZWFk YihlYnVfaG9zdC0+Y3NbY3NfbnVtXS5jaGlwYWRkciArIEhTTkFORF9DU19PRkZTKTsKPiArCj4g KwlyZXQgPSByZWFkbF9wb2xsX3RpbWVvdXQobmFuZF93YWl0LCBzdGF0LCBzdGF0ICYgRUJVX1dB SVRfV1JfQywKPiArCQkJCSAyMCwgMTAwMCk7CgpJZiB5b3UgZG8gdGhpcyBvcGVyYXRpb24gZWFj aCB0aW1lIGEgYnl0ZSBpcyByZWFkL3dyaXR0ZW4sIHlvdSBwcm9iYWJsZQp3YW50IHRvIHNocmlu ayB0aGUgcG9sbGluZyBkZWxheSBhIGxpdHRsZSBiaXQsIHRvIDEgb3IgZXZlbiAwLgoKPiArCWlm IChyZXQpCj4gKwkJZGV2X3dhcm4oZWJ1X2hvc3QtPmRldiwKPiArCQkJICJlYnUgbmFuZCB3cml0 ZSB0aW1lb3V0LiBuYW5kX3dhaXQoMHglcCk9MHgleFxuIiwKPiArCQkJIG5hbmRfd2FpdCwgcmVh ZGwobmFuZF93YWl0KSk7Cj4gKwo+ICsJcmV0dXJuIHZhbDsKCllvdSBzaG91bGQgbm90IHJldHVy biB2YWwgaWYgcmV0IGlzICEwIEkgZ3Vlc3MKCj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIGVidV9u YW5kX3dyaXRlYihzdHJ1Y3QgbmFuZF9jaGlwICpjaGlwLCB1MzIgb2Zmc2V0LCB1OCB2YWx1ZSkK PiArewo+ICsJc3RydWN0IGVidV9uYW5kX2NvbnRyb2xsZXIgKmVidV9ob3N0ID0gbmFuZF9nZXRf Y29udHJvbGxlcl9kYXRhKGNoaXApOwo+ICsJdm9pZCBfX2lvbWVtICpuYW5kX3dhaXQgPSBlYnVf aG9zdC0+ZWJ1ICsgRUJVX1dBSVQ7Cj4gKwl1OCBjc19udW0gPSBlYnVfaG9zdC0+Y3NfbnVtOwo+ ICsJdTMyIHN0YXQ7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXdyaXRlYih2YWx1ZSwgZWJ1X2hvc3Qt PmNzW2NzX251bV0uY2hpcGFkZHIgKyBvZmZzZXQpOwo+ICsKPiArCXJldCA9IHJlYWRsX3BvbGxf dGltZW91dChuYW5kX3dhaXQsIHN0YXQsIHN0YXQgJiBFQlVfV0FJVF9XUl9DLAo+ICsJCQkJIDIw LCAxMDAwKTsKCkhlcmUgYXMgd2VsbAoKPiArCWlmIChyZXQpCj4gKwkJZGV2X3dhcm4oZWJ1X2hv c3QtPmRldiwKPiArCQkJICJlYnUgbmFuZCB3cml0ZSB0aW1lb3V0LiBuYW5kX3dhaXQoMHglcCk9 MHgleFxuIiwKPiArCQkJIG5hbmRfd2FpdCwgcmVhZGwobmFuZF93YWl0KSk7CgpJZiB0aGlzIGNh biBmYWlsLCB0aGVuIHRoZSBoZWxwZXIgc2hvdWxkIHJldHVybiBhbiBlcnJvciBhbmQgYmUgdHJl YXRlZC4KCj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIGVidV9yZWFkX2J1ZihzdHJ1Y3QgbmFuZF9j aGlwICpjaGlwLCB1X2NoYXIgKmJ1ZiwgdW5zaWduZWQgaW50IGxlbikKPiArewo+ICsJaW50IGk7 Cj4gKwo+ICsJZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKQo+ICsJCWJ1ZltpXSA9IGVidV9uYW5k X3JlYWRiKGNoaXApOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBlYnVfd3JpdGVfYnVmKHN0cnVj dCBuYW5kX2NoaXAgKmNoaXAsIGNvbnN0IHVfY2hhciAqYnVmLCBpbnQgbGVuKQo+ICt7Cj4gKwlp bnQgaTsKPiArCj4gKwlmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspCj4gKwkJZWJ1X25hbmRfd3Jp dGViKGNoaXAsIEhTTkFORF9DU19PRkZTLCBidWZbaV0pOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9p ZCBlYnVfbmFuZF9kaXNhYmxlKHN0cnVjdCBuYW5kX2NoaXAgKmNoaXApCj4gK3sKPiArCXN0cnVj dCBlYnVfbmFuZF9jb250cm9sbGVyICplYnVfaG9zdCA9IG5hbmRfZ2V0X2NvbnRyb2xsZXJfZGF0 YShjaGlwKTsKPiArCj4gKwl3cml0ZWwoMCwgZWJ1X2hvc3QtPmVidSArIEVCVV9DT04pOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgdm9pZCBlYnVfc2VsZWN0X2NoaXAoc3RydWN0IG5hbmRfY2hpcCAqY2hp cCkKPiArewo+ICsJc3RydWN0IGVidV9uYW5kX2NvbnRyb2xsZXIgKmVidV9ob3N0ID0gbmFuZF9n ZXRfY29udHJvbGxlcl9kYXRhKGNoaXApOwo+ICsJdm9pZCBfX2lvbWVtICpuYW5kX2NvbiA9IGVi dV9ob3N0LT5lYnUgKyBFQlVfQ09OOwo+ICsJdTMyIGNzID0gZWJ1X2hvc3QtPmNzX251bTsKPiAr Cj4gKwl3cml0ZWwoRUJVX0NPTl9OQU5ETV9FTiB8IEVCVV9DT05fQ1NNVVhfRV9FTiB8IEVCVV9D T05fQ1NfUF9MT1cgfAo+ICsJICAgICAgIEVCVV9DT05fU0VfUF9MT1cgfCBFQlVfQ09OX1dQX1Bf TE9XIHwgRUJVX0NPTl9QUkVfUF9MT1cgfAo+ICsJICAgICAgIEVCVV9DT05fSU5fQ1NfUyhjcykg fCBFQlVfQ09OX09VVF9DU19TKGNzKSB8Cj4gKwkgICAgICAgRUJVX0NPTl9MQVRfRU5fQ1NfUCwg bmFuZF9jb24pOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBlYnVfbmFuZF9zZXR1cF90aW1pbmco c3RydWN0IGVidV9uYW5kX2NvbnRyb2xsZXIgKmN0cmwsCj4gKwkJCQkgIGNvbnN0IHN0cnVjdCBu YW5kX3Nkcl90aW1pbmdzICp0aW1pbmdzKQo+ICt7Cj4gKwl1bnNpZ25lZCBpbnQgcmF0ZSA9IGNs a19nZXRfcmF0ZShjdHJsLT5jbGspIC8gMTAwMDAwMDsKPiArCXVuc2lnbmVkIGludCBwZXJpb2Qg PSBESVZfUk9VTkRfVVAoMTAwMDAwMCwgcmF0ZSk7Cj4gKwl1MzIgdHJlY292LCB0aG9sZCwgdHdy d2FpdCwgdHJkd2FpdDsKPiArCXUzMiByZWcgPSAwOwo+ICsKPiArCXRyZWNvdiA9IERJVl9ST1VO RF9VUChtYXgodGltaW5ncy0+dFJFQV9tYXgsIHRpbWluZ3MtPnRSRUhfbWluKSwKPiArCQkJICAg ICAgcGVyaW9kKTsKPiArCXJlZyB8PSBFQlVfQlVTQ09OX1JFQ09WQyh0cmVjb3YpOwo+ICsKPiAr CXRob2xkID0gRElWX1JPVU5EX1VQKG1heCh0aW1pbmdzLT50REhfbWluLCB0aW1pbmdzLT50RFNf bWluKSwgcGVyaW9kKTsKPiArCXJlZyB8PSBFQlVfQlVTQ09OX0hPTERDKHRob2xkKTsKPiArCj4g Kwl0cmR3YWl0ID0gRElWX1JPVU5EX1VQKG1heCh0aW1pbmdzLT50UkNfbWluLCB0aW1pbmdzLT50 UkVIX21pbiksCj4gKwkJCSAgICAgICBwZXJpb2QpOwo+ICsJcmVnIHw9IEVCVV9CVVNDT05fV0FJ VFJEQyh0cmR3YWl0KTsKPiArCj4gKwl0d3J3YWl0ID0gRElWX1JPVU5EX1VQKG1heCh0aW1pbmdz LT50V0NfbWluLCB0aW1pbmdzLT50V0hfbWluKSwgcGVyaW9kKTsKPiArCXJlZyB8PSBFQlVfQlVT Q09OX1dBSVRXUkModHdyd2FpdCk7Cj4gKwo+ICsJcmVnIHw9IEVCVV9CVVNDT05fQ01VTFRfVjQg fCBFQlVfQlVTQ09OX0JDR0VOX0NTIHwgRUJVX0JVU0NPTl9BTEVDIHwKPiArCQlFQlVfQlVTQ09O X1NFVFVQX0VOOwo+ICsKPiArCXdyaXRlbChyZWcsIGN0cmwtPmVidSArIEVCVV9CVVNDT04oY3Ry bC0+Y3NfbnVtKSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgZWJ1X25hbmRfc2V0dXBfZGF0YV9p bnRlcmZhY2Uoc3RydWN0IG5hbmRfY2hpcCAqY2hpcCwgaW50IGNzbGluZSwKPiArCQkJCQkgY29u c3Qgc3RydWN0IG5hbmRfZGF0YV9pbnRlcmZhY2UgKmNvbmYpCgpJIHJlY2VudGx5IGNoYW5nZWQg dGhlIG5hbWluZyBhcm91bmQgdGhlIGRhdGEgaW50ZXJmYWNlLCBwbGVhc2UKaGF2ZSBhIGxvb2sg YXQgdGhlIHJlY2VudCBjb21taXRzIGFuZCB1cGRhdGUgdGhlIG5hbWluZ3MgaGVyZSBhcwp3ZWxs LgoKPiArewo+ICsJc3RydWN0IGVidV9uYW5kX2NvbnRyb2xsZXIgKmN0cmwgPSBuYW5kX3RvX2Vi dShjaGlwKTsKPiArCWNvbnN0IHN0cnVjdCBuYW5kX3Nkcl90aW1pbmdzICp0aW1pbmdzOwo+ICsK PiArCXRpbWluZ3MgPSBuYW5kX2dldF9zZHJfdGltaW5ncyhjb25mKTsKPiArCWlmIChJU19FUlIo dGltaW5ncykpCj4gKwkJcmV0dXJuIFBUUl9FUlIodGltaW5ncyk7Cj4gKwo+ICsJaWYgKGNzbGlu ZSA9PSBOQU5EX0RBVEFfSUZBQ0VfQ0hFQ0tfT05MWSkKPiArCQlyZXR1cm4gMDsKPiArCj4gKwll YnVfbmFuZF9zZXR1cF90aW1pbmcoY3RybCwgdGltaW5ncyk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4g K30KPiArCj4gK3N0YXRpYyBpbnQgZWJ1X25hbmRfb29ibGF5b3V0X2VjYyhzdHJ1Y3QgbXRkX2lu Zm8gKm10ZCwgaW50IHNlY3Rpb24sCj4gKwkJCQkgIHN0cnVjdCBtdGRfb29iX3JlZ2lvbiAqb29i cmVnaW9uKQo+ICt7Cj4gKwlzdHJ1Y3QgbmFuZF9jaGlwICpjaGlwID0gbXRkX3RvX25hbmQobXRk KTsKPiArCj4gKwlpZiAoc2VjdGlvbikKPiArCQlyZXR1cm4gLUVSQU5HRTsKPiArCj4gKwlvb2Jy ZWdpb24tPm9mZnNldCA9IEhTTkFORF9FQ0NfT0ZGU0VUOwo+ICsJb29icmVnaW9uLT5sZW5ndGgg PSBjaGlwLT5lY2MudG90YWw7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBp bnQgZWJ1X25hbmRfb29ibGF5b3V0X2ZyZWUoc3RydWN0IG10ZF9pbmZvICptdGQsIGludCBzZWN0 aW9uLAo+ICsJCQkJICAgc3RydWN0IG10ZF9vb2JfcmVnaW9uICpvb2JyZWdpb24pCj4gK3sKPiAr CXN0cnVjdCBuYW5kX2NoaXAgKmNoaXAgPSBtdGRfdG9fbmFuZChtdGQpOwo+ICsKPiArCWlmIChz ZWN0aW9uKQo+ICsJCXJldHVybiAtRVJBTkdFOwo+ICsKPiArCW9vYnJlZ2lvbi0+b2Zmc2V0ID0g Y2hpcC0+ZWNjLnRvdGFsICsgSFNOQU5EX0VDQ19PRkZTRVQ7Cj4gKwlvb2JyZWdpb24tPmxlbmd0 aCA9IG10ZC0+b29ic2l6ZSAtIG9vYnJlZ2lvbi0+b2Zmc2V0Owo+ICsKPiArCXJldHVybiAwOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IG10ZF9vb2JsYXlvdXRfb3BzIGVidV9uYW5k X29vYmxheW91dF9vcHMgPSB7Cj4gKwkuZWNjID0gZWJ1X25hbmRfb29ibGF5b3V0X2VjYywKPiAr CS5mcmVlID0gZWJ1X25hbmRfb29ibGF5b3V0X2ZyZWUsCj4gK307Cj4gKwo+ICtzdGF0aWMgdm9p ZCBlYnVfZG1hX3J4X2NhbGxiYWNrKHZvaWQgKmNvb2tpZSkKPiArewo+ICsJc3RydWN0IGVidV9u YW5kX2NvbnRyb2xsZXIgKmVidV9ob3N0ID0gY29va2llOwo+ICsKPiArCWRtYWVuZ2luZV90ZXJt aW5hdGVfYXN5bmMoZWJ1X2hvc3QtPmRtYV9yeCk7Cj4gKwo+ICsJY29tcGxldGUoJmVidV9ob3N0 LT5kbWFfYWNjZXNzX2NvbXBsZXRlKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgZWJ1X2RtYV90 eF9jYWxsYmFjayh2b2lkICpjb29raWUpCj4gK3sKPiArCXN0cnVjdCBlYnVfbmFuZF9jb250cm9s bGVyICplYnVfaG9zdCA9IGNvb2tpZTsKPiArCj4gKwlkbWFlbmdpbmVfdGVybWluYXRlX2FzeW5j KGVidV9ob3N0LT5kbWFfdHgpOwo+ICsKPiArCWNvbXBsZXRlKCZlYnVfaG9zdC0+ZG1hX2FjY2Vz c19jb21wbGV0ZSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgZWJ1X2RtYV9zdGFydChzdHJ1Y3Qg ZWJ1X25hbmRfY29udHJvbGxlciAqZWJ1X2hvc3QsIHUzMiBkaXIsCj4gKwkJCSBjb25zdCB1OCAq YnVmLCB1MzIgbGVuKQo+ICt7Cj4gKwlzdHJ1Y3QgZG1hX2FzeW5jX3R4X2Rlc2NyaXB0b3IgKnR4 Owo+ICsJc3RydWN0IGNvbXBsZXRpb24gKmRtYV9jb21wbGV0aW9uOwo+ICsJZG1hX2FzeW5jX3R4 X2NhbGxiYWNrIGNhbGxiYWNrOwo+ICsJc3RydWN0IGRtYV9jaGFuICpjaGFuOwo+ICsJZG1hX2Nv b2tpZV90IGNvb2tpZTsKPiArCXVuc2lnbmVkIGxvbmcgZmxhZ3MgPSBETUFfQ1RSTF9BQ0sgfCBE TUFfUFJFUF9JTlRFUlJVUFQ7Cj4gKwlkbWFfYWRkcl90IGJ1Zl9kbWE7Cj4gKwlpbnQgcmV0Owo+ ICsJdTMyIHRpbWVvdXQ7Cj4gKwo+ICsJaWYgKGRpciA9PSBETUFfREVWX1RPX01FTSkgewo+ICsJ CWNoYW4gPSBlYnVfaG9zdC0+ZG1hX3J4Owo+ICsJCWRtYV9jb21wbGV0aW9uID0gJmVidV9ob3N0 LT5kbWFfYWNjZXNzX2NvbXBsZXRlOwo+ICsJCWNhbGxiYWNrID0gZWJ1X2RtYV9yeF9jYWxsYmFj azsKPiArCX0gZWxzZSB7Cj4gKwkJY2hhbiA9IGVidV9ob3N0LT5kbWFfdHg7Cj4gKwkJZG1hX2Nv bXBsZXRpb24gPSAmZWJ1X2hvc3QtPmRtYV9hY2Nlc3NfY29tcGxldGU7Cj4gKwkJY2FsbGJhY2sg PSBlYnVfZG1hX3R4X2NhbGxiYWNrOwo+ICsJfQo+ICsKPiArCWJ1Zl9kbWEgPSBkbWFfbWFwX3Np bmdsZShjaGFuLT5kZXZpY2UtPmRldiwgKHZvaWQgKilidWYsIGxlbiwgZGlyKTsKPiArCWlmIChk bWFfbWFwcGluZ19lcnJvcihjaGFuLT5kZXZpY2UtPmRldiwgYnVmX2RtYSkpIHsKPiArCQlkZXZf ZXJyKGVidV9ob3N0LT5kZXYsICJGYWlsZWQgdG8gbWFwIERNQSBidWZmZXJcbiIpOwo+ICsJCXJl dCA9IC1FSU87Cj4gKwkJZ290byBlcnJfdW5tYXA7Cj4gKwl9Cj4gKwo+ICsJdHggPSBkbWFlbmdp bmVfcHJlcF9zbGF2ZV9zaW5nbGUoY2hhbiwgYnVmX2RtYSwgbGVuLCBkaXIsIGZsYWdzKTsKPiAr CWlmICghdHgpCj4gKwkJcmV0dXJuIC1FTlhJTzsKPiArCj4gKwl0eC0+Y2FsbGJhY2sgPSBjYWxs YmFjazsKPiArCXR4LT5jYWxsYmFja19wYXJhbSA9IGVidV9ob3N0Owo+ICsJY29va2llID0gdHgt PnR4X3N1Ym1pdCh0eCk7Cj4gKwo+ICsJcmV0ID0gZG1hX3N1Ym1pdF9lcnJvcihjb29raWUpOwo+ ICsJaWYgKHJldCkgewo+ICsJCWRldl9lcnIoZWJ1X2hvc3QtPmRldiwgImRtYV9zdWJtaXRfZXJy b3IgJWRcbiIsIGNvb2tpZSk7Cj4gKwkJcmV0ID0gLUVJTzsKPiArCQlnb3RvIGVycl91bm1hcDsK PiArCX0KPiArCj4gKwlpbml0X2NvbXBsZXRpb24oZG1hX2NvbXBsZXRpb24pOwo+ICsJZG1hX2Fz eW5jX2lzc3VlX3BlbmRpbmcoY2hhbik7Cj4gKwo+ICsJLyogV2FpdCBETUEgdG8gZmluaXNoIHRo ZSBkYXRhIHRyYW5zZmVyLiovCj4gKwl0aW1lb3V0ID0KCkRvbid0IGJyZWFrIHRoZSBsaW5lIGhl cmUKCj4gKwl3YWl0X2Zvcl9jb21wbGV0aW9uX3RpbWVvdXQoZG1hX2NvbXBsZXRpb24sIG1zZWNz X3RvX2ppZmZpZXMoMTAwMCkpOwo+ICsJaWYgKCF0aW1lb3V0KSB7Cj4gKwkJZGV2X2VycihlYnVf aG9zdC0+ZGV2LCAiSS9PIEVycm9yIGluIERNQSBSWCAoc3RhdHVzICVkKVxuIiwKPiArCQkJZG1h ZW5naW5lX3R4X3N0YXR1cyhjaGFuLCBjb29raWUsIE5VTEwpKTsKPiArCQlkbWFlbmdpbmVfdGVy bWluYXRlX3N5bmMoY2hhbik7Cj4gKwkJcmV0ID0gLUVUSU1FRE9VVDsKPiArCQlnb3RvIGVycl91 bm1hcDsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArCj4gK2Vycl91bm1hcDoKPiArCWRtYV91 bm1hcF9zaW5nbGUoZWJ1X2hvc3QtPmRldiwgYnVmX2RtYSwgbGVuLCBkaXIpOwo+ICsKPiArCXJl dHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIGVidV9uYW5kX3RyaWdnZXIoc3RydWN0 IGVidV9uYW5kX2NvbnRyb2xsZXIgKmVidV9ob3N0LAo+ICsJCQkgICAgIGludCBwYWdlLCB1MzIg Y21kKQo+ICt7Cj4gKwl1bnNpZ25lZCBpbnQgdmFsOwo+ICsKPiArCXZhbCA9IGNtZCB8IChwYWdl ICYgMHhGRikgPDwgSFNOQU5EX0NUTDFfQUREUl9TSElGVDsKPiArCXdyaXRlbCh2YWwsIGVidV9o b3N0LT5oc25hbmQgKyBIU05BTkRfQ1RMMSk7Cj4gKwl2YWwgPSAocGFnZSAmIDB4RkZGRjAwKSA+ PiA4IHwgSFNOQU5EX0NUTDJfQ1lDX05fVjU7Cj4gKwl3cml0ZWwodmFsLCBlYnVfaG9zdC0+aHNu YW5kICsgSFNOQU5EX0NUTDIpOwo+ICsKPiArCXdyaXRlbChlYnVfaG9zdC0+bmRfcGFyYTAsIGVi dV9ob3N0LT5oc25hbmQgKyBIU05BTkRfUEFSQTApOwo+ICsKPiArCS8qIGNsZWFyIGZpcnN0LCB3 aWxsIHVwZGF0ZSBsYXRlciAqLwo+ICsJd3JpdGVsKDB4RkZGRkZGRkYsIGVidV9ob3N0LT5oc25h bmQgKyBIU05BTkRfQ01TR18wKTsKPiArCXdyaXRlbCgweEZGRkZGRkZGLCBlYnVfaG9zdC0+aHNu YW5kICsgSFNOQU5EX0NNU0dfMSk7Cj4gKwo+ICsJd3JpdGVsKEhTTkFORF9JTlRfTVNLX0NUTF9X Ul9DLAo+ICsJICAgICAgIGVidV9ob3N0LT5oc25hbmQgKyBIU05BTkRfSU5UX01TS19DVEwpOwo+ ICsKPiArCXZhbCA9IGNtZCA9PSBOQU5EX0NNRF9SRUFEMCA/IEhTTkFORF9DVExfUldfUkVBRCA6 IEhTTkFORF9DVExfUldfV1JJVEU7CgpJIGRvbid0IGxpa2UgdGhpcywgcHJlZmVyIGhhdmluZyBh ICJyZWFkL3dyaXRlIiBib29sZWFuIGFzIGEgcGFyYW1ldGVyLgoKPiArCj4gKwl3cml0ZWwoSFNO QU5EX0NUTF9NU0dfRU4gfCBIU05BTkRfQ1RMX0NLRkZfRU4gfAo+ICsJICAgICAgIEhTTkFORF9D VExfRUNDX09GRl9WOFRIIHwgSFNOQU5EX0NUTF9DRV9TRUxfQ1MoZWJ1X2hvc3QtPmNzX251bSkg fAo+ICsJICAgICAgIEhTTkFORF9DVExfRU5BQkxFX0VDQyB8IEhTTkFORF9DVExfR08gfCB2YWws Cj4gKwkgICAgICAgZWJ1X2hvc3QtPmhzbmFuZCArIEhTTkFORF9DVEwpOwo+ICt9Cj4gKwo+ICtz dGF0aWMgaW50IGVidV9uYW5kX3JlYWRfcGFnZV9od2VjYyhzdHJ1Y3QgbmFuZF9jaGlwICpjaGlw LCB1OCAqYnVmLAo+ICsJCQkJICAgIGludCBvb2JfcmVxdWlyZWQsIGludCBwYWdlKQo+ICt7Cj4g KwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IG5hbmRfdG9fbXRkKGNoaXApOwo+ICsJc3RydWN0IGVi dV9uYW5kX2NvbnRyb2xsZXIgKmVidV9ob3N0ID0gbmFuZF9nZXRfY29udHJvbGxlcl9kYXRhKGNo aXApOwo+ICsJaW50IHJldCwgeDsKPiArCj4gKwllYnVfbmFuZF90cmlnZ2VyKGVidV9ob3N0LCBw YWdlLCBOQU5EX0NNRF9SRUFEMCk7Cj4gKwo+ICsJcmV0ID0gZWJ1X2RtYV9zdGFydChlYnVfaG9z dCwgRE1BX0RFVl9UT19NRU0sIGJ1ZiwgbXRkLT53cml0ZXNpemUpOwo+ICsJaWYgKHJldCkKPiAr CQlyZXR1cm4gcmV0Owo+ICsKPiArCWlmIChvb2JfcmVxdWlyZWQpCj4gKwkJY2hpcC0+ZWNjLnJl YWRfb29iKGNoaXAsIHBhZ2UpOwo+ICsKPiArCXggPSByZWFkbChlYnVfaG9zdC0+aHNuYW5kICsg SFNOQU5EX0NUTCk7Cj4gKwl4ICY9IH5IU05BTkRfQ1RMX0dPOwo+ICsJd3JpdGVsKHgsIGVidV9o b3N0LT5oc25hbmQgKyBIU05BTkRfQ1RMKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiAr c3RhdGljIGludCBlYnVfbmFuZF93cml0ZV9wYWdlX2h3ZWNjKHN0cnVjdCBuYW5kX2NoaXAgKmNo aXAsIGNvbnN0IHU4ICpidWYsCj4gKwkJCQkgICAgIGludCBvb2JfcmVxdWlyZWQsIGludCBwYWdl KQo+ICt7Cj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IG5hbmRfdG9fbXRkKGNoaXApOwo+ICsJ c3RydWN0IGVidV9uYW5kX2NvbnRyb2xsZXIgKmVidV9ob3N0ID0gbmFuZF9nZXRfY29udHJvbGxl cl9kYXRhKGNoaXApOwo+ICsJdm9pZCBfX2lvbWVtICppbnRfc3RhID0gZWJ1X2hvc3QtPmhzbmFu ZCArIEhTTkFORF9JTlRfU1RBOwo+ICsJaW50IHJldCwgdmFsLCB4Owo+ICsJdTMyIHJlZzsKPiAr Cj4gKwllYnVfbmFuZF90cmlnZ2VyKGVidV9ob3N0LCBwYWdlLCBOQU5EX0NNRF9TRVFJTik7Cj4g Kwo+ICsJcmV0ID0gZWJ1X2RtYV9zdGFydChlYnVfaG9zdCwgRE1BX01FTV9UT19ERVYsIGJ1Ziwg bXRkLT53cml0ZXNpemUpOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1cm4gcmV0Owo+ICsKPiArCWlm IChvb2JfcmVxdWlyZWQpIHsKPiArCQlyZWcgPSAoY2hpcC0+b29iX3BvaVszXSA8PCAyNCkgfCAo Y2hpcC0+b29iX3BvaVsyXSA8PCAxNikgfAo+ICsJCQkoY2hpcC0+b29iX3BvaVsxXSA8PCA4KSB8 IGNoaXAtPm9vYl9wb2lbMF07Cj4gKwo+ICsJCXdyaXRlbChyZWcsIGVidV9ob3N0LT5oc25hbmQg KyBIU05BTkRfQ01TR18wKTsKPiArCj4gKwkJcmVnID0gKGNoaXAtPm9vYl9wb2lbN10gPDwgMjQp IHwgKGNoaXAtPm9vYl9wb2lbNl0gPDwgMTYpIHwKPiArCQkJKGNoaXAtPm9vYl9wb2lbNV0gPDwg OCkgfCBjaGlwLT5vb2JfcG9pWzRdOwo+ICsKPiArCQl3cml0ZWwocmVnLCBlYnVfaG9zdC0+aHNu YW5kICsgSFNOQU5EX0NNU0dfMSk7Cj4gKwl9Cj4gKwo+ICsJcmV0ID0gcmVhZGxfcG9sbF90aW1l b3V0X2F0b21pYyhpbnRfc3RhLCB2YWwsCj4gKwkJCQkJISh2YWwgJiBIU05BTkRfSU5UX1NUQV9X Ul9DKSwgMTAsIDEwMDApOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1cm4gLUVJTzsKCnJldHVybiBy ZXQgPwoKPiArCj4gKwl4ID0gcmVhZGwoZWJ1X2hvc3QtPmhzbmFuZCArIEhTTkFORF9DVEwpOwo+ ICsJeCAmPSB+SFNOQU5EX0NUTF9HTzsKPiArCXdyaXRlbCh4LCBlYnVfaG9zdC0+aHNuYW5kICsg SFNOQU5EX0NUTCk7CgpXaGF0IGlzIHRoaXM/IExvb2tzIGxpa2UgaXQgZGVzZXJ2ZXMgYSBoZWxw ZXIgd2l0aCBhIG5pY2UgbmFtZS4KCj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRp YyBjb25zdCB1OCBlY2Nfc3RyZW5ndGhbXSA9IHsgMSwgMSwgNCwgOCwgMjQsIDMyLCA0MCwgNjAs IH07CgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF4gaXMgdGhpcyBu b3JtYWw/Cgo+ICsKPiArc3RhdGljIGludCBlYnVfbmFuZF9hdHRhY2hfY2hpcChzdHJ1Y3QgbmFu ZF9jaGlwICpjaGlwKQo+ICt7Cj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IG5hbmRfdG9fbXRk KGNoaXApOwo+ICsJc3RydWN0IGVidV9uYW5kX2NvbnRyb2xsZXIgKmVidV9ob3N0ID0gbmFuZF9n ZXRfY29udHJvbGxlcl9kYXRhKGNoaXApOwo+ICsJdTMyIGVjY19zdGVwcywgZWNjX2J5dGVzLCBl Y2NfdG90YWwsIHBhZ2VzaXplLCBwZ19wZXJfYmxrOwo+ICsJdTMyIGVjY19zdHJlbmd0aF9kcyA9 IGNoaXAtPmVjYy5zdHJlbmd0aDsKPiArCXUzMiBlY2Nfc2l6ZSA9IGNoaXAtPmVjYy5zaXplOwo+ ICsJdTMyIHdyaXRlc2l6ZSA9IG10ZC0+d3JpdGVzaXplOwo+ICsJdTMyIGJsb2Nrc2l6ZSA9IG10 ZC0+ZXJhc2VzaXplOwo+ICsJaW50IGJjaF9hbGdvLCBzdGFydCwgdmFsOwo+ICsKPiArCWlmIChj aGlwLT5lY2MubW9kZSAhPSBOQU5EX0VDQ19IVykKPiArCQlyZXR1cm4gMDsKPiArCj4gKwkvKiBE ZWZhdWx0IHRvIGFuIEVDQyBzaXplIG9mIDUxMiAqLwo+ICsJaWYgKCFjaGlwLT5lY2Muc2l6ZSkK PiArCQljaGlwLT5lY2Muc2l6ZSA9IDUxMjsKPiArCj4gKwlzd2l0Y2ggKGVjY19zaXplKSB7Cj4g KwljYXNlIDUxMjoKPiArCQlzdGFydCA9IDE7Cj4gKwkJaWYgKCFlY2Nfc3RyZW5ndGhfZHMpCj4g KwkJCWVjY19zdHJlbmd0aF9kcyA9IDQ7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIDEwMjQ6Cj4gKwkJ c3RhcnQgPSA0Owo+ICsJCWlmICghZWNjX3N0cmVuZ3RoX2RzKQo+ICsJCQllY2Nfc3RyZW5ndGhf ZHMgPSAzMjsKPiArCQlicmVhazsKPiArCWRlZmF1bHQ6Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4g Kwl9Cj4gKwo+ICsJLyogQkNIIEVDQyBhbGdvcml0aG0gU2V0dGluZ3MgZm9yIG51bWJlciBvZiBi aXRzIHBlciA1MTJCLzEwMjRCICovCj4gKwliY2hfYWxnbyA9IHJvdW5kX3VwKHN0YXJ0ICsgMSwg NCk7Cj4gKwlmb3IgKHZhbCA9IHN0YXJ0OyB2YWwgPCBiY2hfYWxnbzsgdmFsKyspIHsKPiArCQlp ZiAoZWNjX3N0cmVuZ3RoX2RzID09IGVjY19zdHJlbmd0aFt2YWxdKQo+ICsJCQlicmVhazsKPiAr CX0KPiArCWlmICh2YWwgPT0gYmNoX2FsZ28pCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJ aWYgKGVjY19zdHJlbmd0aF9kcyA9PSA4KQo+ICsJCWVjY19ieXRlcyA9IDE0Owo+ICsJZWxzZQo+ ICsJCWVjY19ieXRlcyA9IERJVl9ST1VORF9VUChlY2Nfc3RyZW5ndGhfZHMgKiBmbHMoOCAqIGVj Y19zaXplKSwgOCk7Cj4gKwo+ICsJZWNjX3N0ZXBzID0gd3JpdGVzaXplIC8gZWNjX3NpemU7Cj4g KwllY2NfdG90YWwgPSBlY2Nfc3RlcHMgKiBlY2NfYnl0ZXM7Cj4gKwlpZiAoKGVjY190b3RhbCAr IDgpID4gbXRkLT5vb2JzaXplKQo+ICsJCXJldHVybiAtRVJBTkdFOwo+ICsKPiArCWNoaXAtPmVj Yy50b3RhbCA9IGVjY190b3RhbDsKPiArCXBhZ2VzaXplID0gZmxzKHdyaXRlc2l6ZSA+PiAxMSk7 Cj4gKwlpZiAocGFnZXNpemUgPiBIU05BTkRfUEFSQTBfUEFHRV9WODE5MikKPiArCQlyZXR1cm4g LUVSQU5HRTsKPiArCj4gKwlwZ19wZXJfYmxrID0gZmxzKChibG9ja3NpemUgLyB3cml0ZXNpemUp ID4+IDYpIDw8IDQ7CgpJZiA8PCA0IGlzIGhlcmUgdG8gbWVhbiAvIDgsIHRoZW4gSSBkb24ndCB3 YW50IGEgc2hpZnQgb3BlcmF0aW9uCmJlY2F1c2UgaXQgaXMgaGlnaGx5IHVucmVhZGFibGUgYW5k IGNvbXBpbGVycyBrbm93IGhvdyB0byBvcHRpbWl6ZQp0aGlzLgoKPiArCWlmIChwZ19wZXJfYmxr ID4gSFNOQU5EX1BBUkEwX1BJQl9WMjU2KQo+ICsJCXJldHVybiAtRVJBTkdFOwo+ICsKPiArCWVi dV9ob3N0LT5uZF9wYXJhMCA9IHBhZ2VzaXplIHwgcGdfcGVyX2JsayB8IEhTTkFORF9QQVJBMF9C WVBfRU5fTlAgfAo+ICsJCQkgICAgIEhTTkFORF9QQVJBMF9CWVBfREVDX05QIHwgSFNOQU5EX1BB UkEwX0FERVBfRU4gfAo+ICsJCQkgICAgIEhTTkFORF9QQVJBMF9UWVBFX09ORkkgfCAodmFsIDw8 IDI5KTsKPiArCj4gKwltdGRfc2V0X29vYmxheW91dChtdGQsICZlYnVfbmFuZF9vb2JsYXlvdXRf b3BzKTsKPiArCWNoaXAtPmVjYy5yZWFkX3BhZ2UgPSBlYnVfbmFuZF9yZWFkX3BhZ2VfaHdlY2M7 Cj4gKwljaGlwLT5lY2Mud3JpdGVfcGFnZSA9IGVidV9uYW5kX3dyaXRlX3BhZ2VfaHdlY2M7Cj4g Kwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgZWJ1X25hbmRfZXhlY19vcChz dHJ1Y3QgbmFuZF9jaGlwICpjaGlwLAo+ICsJCQkgICAgY29uc3Qgc3RydWN0IG5hbmRfb3BlcmF0 aW9uICpvcCwgYm9vbCBjaGVja19vbmx5KQo+ICt7Cj4gKwlzdHJ1Y3QgZWJ1X25hbmRfY29udHJv bGxlciAqY3RybCA9IG5hbmRfdG9fZWJ1KGNoaXApOwo+ICsJY29uc3Qgc3RydWN0IG5hbmRfb3Bf aW5zdHIgKmluc3RyID0gTlVMTDsKPiArCXVuc2lnbmVkIGludCBvcF9pZDsKPiArCWludCBpLCB0 aW1lX291dCwgcmV0ID0gMDsKPiArCXUzMiBzdGF0Owo+ICsKPiArCWlmIChjaGVja19vbmx5KQo+ ICsJCWVidV9zZWxlY3RfY2hpcChjaGlwKTsKCldoYXQgaXMgdGhlIHBvaW50IG9mIHNlbGVjdGlu ZyB0aGUgY2hpcCBpZiBjaGVja19vbmx5IGlzIHRydWU/Cgo+ICsKPiArCWZvciAob3BfaWQgPSAw OyBvcF9pZCA8IG9wLT5uaW5zdHJzOyBvcF9pZCsrKSB7Cj4gKwkJaW5zdHIgPSAmb3AtPmluc3Ry c1tvcF9pZF07Cj4gKwo+ICsJCXN3aXRjaCAoaW5zdHItPnR5cGUpIHsKPiArCQljYXNlIE5BTkRf T1BfQ01EX0lOU1RSOgo+ICsJCQllYnVfbmFuZF93cml0ZWIoY2hpcCwgSFNOQU5EX0NMRV9PRkZT IHwgSFNOQU5EX0NTX09GRlMsCj4gKwkJCQkJaW5zdHItPmN0eC5jbWQub3Bjb2RlKTsKPiArCQkJ YnJlYWs7Cj4gKwo+ICsJCWNhc2UgTkFORF9PUF9BRERSX0lOU1RSOgo+ICsJCQlmb3IgKGkgPSAw OyBpIDwgaW5zdHItPmN0eC5hZGRyLm5hZGRyczsgaSsrKQo+ICsJCQkJZWJ1X25hbmRfd3JpdGVi KGNoaXAsCj4gKwkJCQkJCUhTTkFORF9BTEVfT0ZGUyB8IEhTTkFORF9DU19PRkZTLAo+ICsJCQkJ CQlpbnN0ci0+Y3R4LmFkZHIuYWRkcnNbaV0pOwo+ICsJCQlicmVhazsKPiArCj4gKwkJY2FzZSBO QU5EX09QX0RBVEFfSU5fSU5TVFI6Cj4gKwkJCWVidV9yZWFkX2J1ZihjaGlwLCBpbnN0ci0+Y3R4 LmRhdGEuYnVmLmluLAo+ICsJCQkJICAgICBpbnN0ci0+Y3R4LmRhdGEubGVuKTsKPiArCQkJYnJl YWs7Cj4gKwo+ICsJCWNhc2UgTkFORF9PUF9EQVRBX09VVF9JTlNUUjoKPiArCQkJZWJ1X3dyaXRl X2J1ZihjaGlwLCBpbnN0ci0+Y3R4LmRhdGEuYnVmLm91dCwKPiArCQkJCSAgICAgIGluc3RyLT5j dHguZGF0YS5sZW4pOwo+ICsJCQlicmVhazsKPiArCj4gKwkJY2FzZSBOQU5EX09QX1dBSVRSRFlf SU5TVFI6Cj4gKwkJCXRpbWVfb3V0ID0gaW5zdHItPmN0eC53YWl0cmR5LnRpbWVvdXRfbXMgKiAx MDAwOwo+ICsJCQlyZXQgPSByZWFkbF9wb2xsX3RpbWVvdXQoY3RybC0+ZWJ1ICsgRUJVX1dBSVQs Cj4gKwkJCQkJCSBzdGF0LCBzdGF0ICYgRUJVX1dBSVRfUkRCWSwKPiArCQkJCQkJIDIwLCB0aW1l X291dCk7Cj4gKwkJCWJyZWFrOwo+ICsJCX0KPiArCX0KPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9 CgoKVGhhbmtzLApNaXF1w6hsCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX18KTGludXggTVREIGRpc2N1c3Npb24gbWFpbGluZyBsaXN0Cmh0dHA6 Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtbXRkLwo=