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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3BF90C4167B for ; Tue, 31 Oct 2023 15:54:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344793AbjJaPyS (ORCPT ); Tue, 31 Oct 2023 11:54:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34794 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344795AbjJaPyS (ORCPT ); Tue, 31 Oct 2023 11:54:18 -0400 Received: from relay3-d.mail.gandi.net (relay3-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::223]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 15A048F; Tue, 31 Oct 2023 08:54:12 -0700 (PDT) Received: by mail.gandi.net (Postfix) with ESMTPSA id A01FC6000D; Tue, 31 Oct 2023 15:54:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1698767650; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pFpuhFdEBzHaLiA0OeJ+8Qf/mgpHnhSrpmbF/xo4GW0=; b=JHsOAC+H3igsiQMlOeBjGjQxduzkExQYnyjrg+5kZ90nf+FVEeKWVAJlfAxE2yU8EwbdaC bVTNPziOMVzhcxKXd6pW+BX+lm4/IsOVxOjnnIzYNmU7inGzoPR6wXNHen8qi5VU6Rc5dx VFA0BODYV79rl3OuPgQmgNx+pBkE0urd9NwaAjXw5Ib1mnXVrdBR4iEeea5easVrDiV3jI qnKGR5hM41dbmNPXsiniPLo7gYaCC2BdGKDMWhfesoDqY/b/L3ZoyKwDnPQ/Gsf33YPNkS QQstiaHt0OrRFQ4Hp+eKXsLmrn9sQUWYiShXik7oAj7pczWpT5LJBkIZ38hfFA== Date: Tue, 31 Oct 2023 16:54:06 +0100 From: Miquel Raynal To: Md Sadre Alam Cc: agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org, robh+dt@kernel.org, conor+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, richard@nod.at, vigneshr@ti.com, broonie@kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, linux-spi@vger.kernel.org, quic_srichara@quicinc.com, qpic_varada@quicinc.com Subject: Re: [RFC PATCH 3/5] mtd: nand: qpic_common: Add support for qpic common API Message-ID: <20231031165406.33e486a3@xps-13> In-Reply-To: <20231031120307.1600689-4-quic_mdalam@quicinc.com> References: <20231031120307.1600689-1-quic_mdalam@quicinc.com> <20231031120307.1600689-4-quic_mdalam@quicinc.com> Organization: Bootlin X-Mailer: Claws Mail 4.0.0 (GTK+ 3.24.33; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-GND-Sasl: miquel.raynal@bootlin.com Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Hi, quic_mdalam@quicinc.com wrote on Tue, 31 Oct 2023 17:33:05 +0530: > Add qpic command API in sperate file so that it will be > use by both spi and request and raw nand request. nand? >=20 > Signed-off-by: Md Sadre Alam > Signed-off-by: Sricharan R > --- > drivers/mtd/nand/qpic_common.c | 840 +++++++++++++++++++++++++++ > include/linux/mtd/nand-qpic-common.h | 641 ++++++++++++++++++++ > 2 files changed, 1481 insertions(+) > create mode 100644 drivers/mtd/nand/qpic_common.c > create mode 100644 include/linux/mtd/nand-qpic-common.h >=20 > diff --git a/drivers/mtd/nand/qpic_common.c b/drivers/mtd/nand/qpic_commo= n.c > new file mode 100644 > index 000000000000..983768a1ea94 > --- /dev/null > +++ b/drivers/mtd/nand/qpic_common.c > @@ -0,0 +1,840 @@ > +// SPDX-License-Identifier: GPL-2.0 OR MIT > +/* > + * QPIC common API file. > + * Copyright (C) 2023 Qualcomm Inc. > + * Authors: Md sadre Alam > + * Sricharan R > + */ > + > +#include > + > +/* Frees the BAM transaction memory */ > +void free_bam_transaction(struct qcom_nand_controller *nandc) This is not a generic object, it's not meant to be shared with spi. So if it's meant to be used in a single place, please don't share it. Otherwise please use a more generic name. > +{ > + struct bam_transaction *bam_txn =3D nandc->bam_txn; > + > + devm_kfree(nandc->dev, bam_txn); > +} > +EXPORT_SYMBOL(free_bam_transaction); > + > +/* Callback for DMA descriptor completion */ > +void qpic_bam_dma_done(void *data) > +{ > + struct bam_transaction *bam_txn =3D data; Just provide the right pointer in the first place. > + > + /* > + * In case of data transfer with NAND, 2 callbacks will be generated. What if we are not dealing with a NAND? > + * One for command channel and another one for data channel. > + * If current transaction has data descriptors > + * (i.e. wait_second_completion is true), then set this to false Why do you need a boolean for that if having a data descriptor is the condition you want to check against? > + * and wait for second DMA descriptor completion. > + */ > + if (bam_txn->wait_second_completion) > + bam_txn->wait_second_completion =3D false; This looks very racy. > + else > + complete(&bam_txn->txn_done); > +} > +EXPORT_SYMBOL(qpic_bam_dma_done); > + > +u32 nandc_read(struct qcom_nand_controller *nandc, int offset) > +{ > + return ioread32(nandc->base + offset); I don't see the need for that. > +} > +EXPORT_SYMBOL(nandc_read); > + > +void nandc_write(struct qcom_nand_controller *nandc, int offset, > + u32 val) > +{ > + iowrite32(val, nandc->base + offset); Same here. > +} > +EXPORT_SYMBOL(nandc_write); > + > +void nandc_read_buffer_sync(struct qcom_nand_controller *nandc, > + bool is_cpu) > +{ > + if (!nandc->props->is_bam) > + return; I thought BAM was a per transaction thing, and here you check it against a controller parameter. It looks wrong. > + > + if (is_cpu) Whuut? naming, naming, naming, naming. Please. > + dma_sync_single_for_cpu(nandc->dev, nandc->reg_read_dma, > + MAX_REG_RD * Remove this new line > + sizeof(*nandc->reg_read_buf), Are you sure this sizeof() is safe? > + DMA_FROM_DEVICE); > + else > + dma_sync_single_for_device(nandc->dev, nandc->reg_read_dma, > + MAX_REG_RD * > + sizeof(*nandc->reg_read_buf), > + DMA_FROM_DEVICE); > +} You better have a really good reason to sync in the middle of an operation... > +EXPORT_SYMBOL(nandc_read_buffer_sync); > + > +__le32 *offset_to_nandc_reg(struct nandc_regs *regs, int offset) > +{ > + switch (offset) { > + case NAND_FLASH_CMD: > + return ®s->cmd; > + case NAND_ADDR0: > + return ®s->addr0; > + case NAND_ADDR1: > + return ®s->addr1; > + case NAND_FLASH_CHIP_SELECT: > + return ®s->chip_sel; > + case NAND_EXEC_CMD: > + return ®s->exec; > + case NAND_FLASH_STATUS: > + return ®s->clrflashstatus; > + case NAND_DEV0_CFG0: > + return ®s->cfg0; > + case NAND_DEV0_CFG1: > + return ®s->cfg1; > + case NAND_DEV0_ECC_CFG: > + return ®s->ecc_bch_cfg; > + case NAND_READ_STATUS: > + return ®s->clrreadstatus; > + case NAND_DEV_CMD1: > + return ®s->cmd1; > + case NAND_DEV_CMD1_RESTORE: > + return ®s->orig_cmd1; > + case NAND_DEV_CMD_VLD: > + return ®s->vld; > + case NAND_DEV_CMD_VLD_RESTORE: > + return ®s->orig_vld; > + case NAND_EBI2_ECC_BUF_CFG: > + return ®s->ecc_buf_cfg; > + case NAND_READ_LOCATION_0: > + return ®s->read_location0; > + case NAND_READ_LOCATION_1: > + return ®s->read_location1; > + case NAND_READ_LOCATION_2: > + return ®s->read_location2; > + case NAND_READ_LOCATION_3: > + return ®s->read_location3; > + case NAND_READ_LOCATION_LAST_CW_0: > + return ®s->read_location_last0; > + case NAND_READ_LOCATION_LAST_CW_1: > + return ®s->read_location_last1; > + case NAND_READ_LOCATION_LAST_CW_2: > + return ®s->read_location_last2; > + case NAND_READ_LOCATION_LAST_CW_3: > + return ®s->read_location_last3; > + case NAND_FLASH_SPI_CFG: > + return ®s->spi_cfg; > + case NAND_NUM_ADDR_CYCLES: > + return ®s->num_addr_cycle; > + case NAND_BUSY_CHECK_WAIT_CNT: > + return ®s->busy_wait_cnt; > + case NAND_MSTR_CONFIG: > + return ®s->mstr_cfg; > + case NAND_FLASH_FEATURES: > + return ®s->flash_feature; Just... no? What is the point of using an intermediate int here? just dereference the right value? > + default: > + return NULL; > + } > +} > +EXPORT_SYMBOL(offset_to_nandc_reg); > + > +/* reset the register read buffer for next NAND operation */ > +void clear_read_regs(struct qcom_nand_controller *nandc) > +{ > + nandc->reg_read_pos =3D 0; > + nandc_read_buffer_sync(nandc, false); > +} > +EXPORT_SYMBOL(clear_read_regs); > + > +int prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read, adm? Please always prefix your symbols (especially when exporting them) with a decent a easy to recognize prefix. > + int reg_off, const void *vaddr, int size, > + bool flow_control) > +{ > + struct desc_info *desc; > + struct dma_async_tx_descriptor *dma_desc; > + struct scatterlist *sgl; > + struct dma_slave_config slave_conf; > + struct qcom_adm_peripheral_config periph_conf =3D {}; > + enum dma_transfer_direction dir_eng; > + int ret; > + > + desc =3D kzalloc(sizeof(*desc), GFP_KERNEL); > + if (!desc) > + return -ENOMEM; > + > + sgl =3D &desc->adm_sgl; > + > + sg_init_one(sgl, vaddr, size); > + > + if (read) { > + dir_eng =3D DMA_DEV_TO_MEM; > + desc->dir =3D DMA_FROM_DEVICE; > + } else { > + dir_eng =3D DMA_MEM_TO_DEV; > + desc->dir =3D DMA_TO_DEVICE; > + } > + > + ret =3D dma_map_sg(nandc->dev, sgl, 1, desc->dir); > + if (ret =3D=3D 0) { > + ret =3D -ENOMEM; > + goto err; > + } > + > + memset(&slave_conf, 0x00, sizeof(slave_conf)); > + > + slave_conf.device_fc =3D flow_control; > + if (read) { > + slave_conf.src_maxburst =3D 16; > + slave_conf.src_addr =3D nandc->base_dma + reg_off; > + if (nandc->data_crci) { > + periph_conf.crci =3D nandc->data_crci; > + slave_conf.peripheral_config =3D &periph_conf; > + slave_conf.peripheral_size =3D sizeof(periph_conf); > + } > + } else { > + slave_conf.dst_maxburst =3D 16; > + slave_conf.dst_addr =3D nandc->base_dma + reg_off; > + if (nandc->cmd_crci) { > + periph_conf.crci =3D nandc->cmd_crci; > + slave_conf.peripheral_config =3D &periph_conf; > + slave_conf.peripheral_size =3D sizeof(periph_conf); > + } > + } > + > + ret =3D dmaengine_slave_config(nandc->chan, &slave_conf); > + if (ret) { > + dev_err(nandc->dev, "failed to configure dma channel\n"); > + goto err; > + } > + > + dma_desc =3D dmaengine_prep_slave_sg(nandc->chan, sgl, 1, dir_eng, 0); > + if (!dma_desc) { > + dev_err(nandc->dev, "failed to prepare desc\n"); > + ret =3D -EINVAL; > + goto err; > + } > + > + desc->dma_desc =3D dma_desc; > + > + list_add_tail(&desc->node, &nandc->desc_list); > + > + return 0; > +err: your error path is missing steps > + kfree(desc); > + > + return ret; > +} > + > +/* helpers to submit/free our list of dma descriptors */ > +int submit_descs(struct qcom_nand_controller *nandc) > +{ > + struct desc_info *desc; > + dma_cookie_t cookie =3D 0; > + struct bam_transaction *bam_txn =3D nandc->bam_txn; > + int r; > + > + if (nandc->props->is_bam) { > + if (bam_txn->rx_sgl_pos > bam_txn->rx_sgl_start) { > + r =3D prepare_bam_async_desc(nandc, nandc->rx_chan, 0); > + if (r) > + return r; > + } > + > + if (bam_txn->tx_sgl_pos > bam_txn->tx_sgl_start) { > + r =3D prepare_bam_async_desc(nandc, nandc->tx_chan, > + DMA_PREP_INTERRUPT); > + if (r) > + return r; > + } > + > + if (bam_txn->cmd_sgl_pos > bam_txn->cmd_sgl_start) { > + r =3D prepare_bam_async_desc(nandc, nandc->cmd_chan, > + DMA_PREP_CMD); > + if (r) > + return r; > + } > + } > + > + list_for_each_entry(desc, &nandc->desc_list, node) > + cookie =3D dmaengine_submit(desc->dma_desc); > + > + if (nandc->props->is_bam) { > + bam_txn->last_cmd_desc->callback =3D qpic_bam_dma_done; > + bam_txn->last_cmd_desc->callback_param =3D bam_txn; > + if (bam_txn->last_data_desc) { > + bam_txn->last_data_desc->callback =3D qpic_bam_dma_done; > + bam_txn->last_data_desc->callback_param =3D bam_txn; > + bam_txn->wait_second_completion =3D true; > + } > + > + dma_async_issue_pending(nandc->tx_chan); > + dma_async_issue_pending(nandc->rx_chan); > + dma_async_issue_pending(nandc->cmd_chan); > + > + if (!wait_for_completion_timeout(&bam_txn->txn_done, > + QPIC_NAND_COMPLETION_TIMEOUT)) > + return -ETIMEDOUT; > + } else { > + if (dma_sync_wait(nandc->chan, cookie) !=3D DMA_COMPLETE) > + return -ETIMEDOUT; > + } > + > + return 0; > +} > +EXPORT_SYMBOL(submit_descs); > + > +void free_descs(struct qcom_nand_controller *nandc) > +{ > + struct desc_info *desc, *n; > + > + list_for_each_entry_safe(desc, n, &nandc->desc_list, node) { > + list_del(&desc->node); > + > + if (nandc->props->is_bam) > + dma_unmap_sg(nandc->dev, desc->bam_sgl, > + desc->sgl_cnt, desc->dir); > + else > + dma_unmap_sg(nandc->dev, &desc->adm_sgl, 1, > + desc->dir); > + > + kfree(desc); > + } > +} > +EXPORT_SYMBOL(free_descs); > + > +/* > + * Maps the scatter gather list for DMA transfer and forms the DMA descr= iptor > + * for BAM. This descriptor will be added in the NAND DMA descriptor que= ue > + * which will be submitted to DMA engine. > + */ > +int prepare_bam_async_desc(struct qcom_nand_controller *nandc, > + struct dma_chan *chan, > + unsigned long flags) > +{ > + struct desc_info *desc; > + struct scatterlist *sgl; > + unsigned int sgl_cnt; > + int ret; > + struct bam_transaction *bam_txn =3D nandc->bam_txn; > + enum dma_transfer_direction dir_eng; > + struct dma_async_tx_descriptor *dma_desc; > + > + desc =3D kzalloc(sizeof(*desc), GFP_KERNEL); > + if (!desc) > + return -ENOMEM; > + > + if (chan =3D=3D nandc->cmd_chan) { > + sgl =3D &bam_txn->cmd_sgl[bam_txn->cmd_sgl_start]; > + sgl_cnt =3D bam_txn->cmd_sgl_pos - bam_txn->cmd_sgl_start; > + bam_txn->cmd_sgl_start =3D bam_txn->cmd_sgl_pos; > + dir_eng =3D DMA_MEM_TO_DEV; > + desc->dir =3D DMA_TO_DEVICE; > + } else if (chan =3D=3D nandc->tx_chan) { > + sgl =3D &bam_txn->data_sgl[bam_txn->tx_sgl_start]; > + sgl_cnt =3D bam_txn->tx_sgl_pos - bam_txn->tx_sgl_start; > + bam_txn->tx_sgl_start =3D bam_txn->tx_sgl_pos; > + dir_eng =3D DMA_MEM_TO_DEV; > + desc->dir =3D DMA_TO_DEVICE; > + } else { > + sgl =3D &bam_txn->data_sgl[bam_txn->rx_sgl_start]; > + sgl_cnt =3D bam_txn->rx_sgl_pos - bam_txn->rx_sgl_start; > + bam_txn->rx_sgl_start =3D bam_txn->rx_sgl_pos; > + dir_eng =3D DMA_DEV_TO_MEM; > + desc->dir =3D DMA_FROM_DEVICE; > + } > + > + sg_mark_end(sgl + sgl_cnt - 1); > + ret =3D dma_map_sg(nandc->dev, sgl, sgl_cnt, desc->dir); > + if (ret =3D=3D 0) { > + dev_err(nandc->dev, "failure in mapping desc\n"); > + kfree(desc); > + return -ENOMEM; > + } > + > + desc->sgl_cnt =3D sgl_cnt; > + desc->bam_sgl =3D sgl; > + > + dma_desc =3D dmaengine_prep_slave_sg(chan, sgl, sgl_cnt, dir_eng, > + flags); > + > + if (!dma_desc) { > + dev_err(nandc->dev, "failure in prep desc\n"); > + dma_unmap_sg(nandc->dev, sgl, sgl_cnt, desc->dir); > + kfree(desc); > + return -EINVAL; > + } > + > + desc->dma_desc =3D dma_desc; > + > + /* update last data/command descriptor */ > + if (chan =3D=3D nandc->cmd_chan) > + bam_txn->last_cmd_desc =3D dma_desc; > + else > + bam_txn->last_data_desc =3D dma_desc; > + > + list_add_tail(&desc->node, &nandc->desc_list); > + > + return 0; > +} > +EXPORT_SYMBOL(prepare_bam_async_desc); > + > +/* > + * Prepares the command descriptor for BAM DMA which will be used for NA= ND > + * register reads and writes. The command descriptor requires the command > + * to be formed in command element type so this function uses the command > + * element from bam transaction ce array and fills the same with required ce? > + * data. A single SGL can contain multiple command elements so > + * NAND_BAM_NEXT_SGL will be used for starting the separate SGL > + * after the current command element. > + */ > +int prep_bam_dma_desc_cmd(struct qcom_nand_controller *nandc, bool read, > + int reg_off, const void *vaddr, > + int size, unsigned int flags) > +{ > + int bam_ce_size; > + int i, ret; > + struct bam_cmd_element *bam_ce_buffer; > + struct bam_transaction *bam_txn =3D nandc->bam_txn; > + > + bam_ce_buffer =3D &bam_txn->bam_ce[bam_txn->bam_ce_pos]; > + > + /* fill the command desc */ > + for (i =3D 0; i < size; i++) { > + if (read) > + bam_prep_ce(&bam_ce_buffer[i], > + nandc_reg_phys(nandc, reg_off + 4 * i), > + BAM_READ_COMMAND, > + reg_buf_dma_addr(nandc, > + (__le32 *)vaddr + i)); > + else > + bam_prep_ce_le32(&bam_ce_buffer[i], > + nandc_reg_phys(nandc, reg_off + 4 * i), > + BAM_WRITE_COMMAND, > + *((__le32 *)vaddr + i)); The _le handling looks really fragile. > + } > + > + bam_txn->bam_ce_pos +=3D size; > + > + /* use the separate sgl after this command */ > + if (flags & NAND_BAM_NEXT_SGL) { > + bam_ce_buffer =3D &bam_txn->bam_ce[bam_txn->bam_ce_start]; > + bam_ce_size =3D (bam_txn->bam_ce_pos - > + bam_txn->bam_ce_start) * > + sizeof(struct bam_cmd_element); > + sg_set_buf(&bam_txn->cmd_sgl[bam_txn->cmd_sgl_pos], > + bam_ce_buffer, bam_ce_size); > + bam_txn->cmd_sgl_pos++; > + bam_txn->bam_ce_start =3D bam_txn->bam_ce_pos; > + > + if (flags & NAND_BAM_NWD) { > + ret =3D prepare_bam_async_desc(nandc, nandc->cmd_chan, > + DMA_PREP_FENCE | > + DMA_PREP_CMD); > + if (ret) > + return ret; > + } > + } > + > + return 0; > +} > +EXPORT_SYMBOL(prep_bam_dma_desc_cmd); > + > +/* > + * Prepares the data descriptor for BAM DMA which will be used for NAND > + * data reads and writes. > + */ > +int prep_bam_dma_desc_data(struct qcom_nand_controller *nandc, bool read, > + const void *vaddr, > + int size, unsigned int flags) > +{ > + int ret; > + struct bam_transaction *bam_txn =3D nandc->bam_txn; > + > + if (read) { > + sg_set_buf(&bam_txn->data_sgl[bam_txn->rx_sgl_pos], > + vaddr, size); > + bam_txn->rx_sgl_pos++; > + } else { > + sg_set_buf(&bam_txn->data_sgl[bam_txn->tx_sgl_pos], > + vaddr, size); > + bam_txn->tx_sgl_pos++; > + > + /* > + * BAM will only set EOT for DMA_PREP_INTERRUPT so if this flag > + * is not set, form the DMA descriptor > + */ > + if (!(flags & NAND_BAM_NO_EOT)) { > + ret =3D prepare_bam_async_desc(nandc, nandc->tx_chan, > + DMA_PREP_INTERRUPT); > + if (ret) > + return ret; > + } > + } > + > + return 0; > +} > +EXPORT_SYMBOL(prep_bam_dma_desc_data); > + > +/* > + * read_reg_dma: prepares a descriptor to read a given number of > + * contiguous registers to the reg_read_buf pointer > + * > + * @first: offset of the first register in the contiguous block > + * @num_regs: number of registers to read > + * @flags: flags to control DMA descriptor preparation > + */ > +int read_reg_dma(struct qcom_nand_controller *nandc, int first, > + int num_regs, unsigned int flags) > +{ > + bool flow_control =3D false; > + void *vaddr; > + > + vaddr =3D nandc->reg_read_buf + nandc->reg_read_pos; > + nandc->reg_read_pos +=3D num_regs; > + > + if (first =3D=3D NAND_DEV_CMD_VLD || first =3D=3D NAND_DEV_CMD1) > + first =3D dev_cmd_reg_addr(nandc, first); > + > + if (nandc->props->is_bam) > + return prep_bam_dma_desc_cmd(nandc, true, first, vaddr, > + num_regs, flags); > + > + if (first =3D=3D NAND_READ_ID || first =3D=3D NAND_FLASH_STATUS) > + flow_control =3D true; This flow_control property really bothers me. > + > + return prep_adm_dma_desc(nandc, true, first, vaddr, > + num_regs * sizeof(u32), flow_control); > +} > +EXPORT_SYMBOL(read_reg_dma); > + > +/* > + * write_reg_dma: prepares a descriptor to write a given number of > + * contiguous registers > + * > + * @first: offset of the first register in the contiguous block > + * @num_regs: number of registers to write > + * @flags: flags to control DMA descriptor preparation > + */ > +int write_reg_dma(struct qcom_nand_controller *nandc, int first, > + int num_regs, unsigned int flags) > +{ > + bool flow_control =3D false; > + struct nandc_regs *regs =3D nandc->regs; > + void *vaddr; > + > + vaddr =3D offset_to_nandc_reg(regs, first); > + > + if (first =3D=3D NAND_ERASED_CW_DETECT_CFG) { > + if (flags & NAND_ERASED_CW_SET) > + vaddr =3D ®s->erased_cw_detect_cfg_set; > + else > + vaddr =3D ®s->erased_cw_detect_cfg_clr; > + } > + > + if (first =3D=3D NAND_EXEC_CMD) > + flags |=3D NAND_BAM_NWD; > + > + if (first =3D=3D NAND_FLASH_SPI_CFG || first =3D=3D NAND_NUM_ADDR_CYCLES > + || first =3D=3D NAND_BUSY_CHECK_WAIT_CNT > + || first =3D=3D NAND_MSTR_CONFIG) > + first =3D dev_cmd_reg_addr(nandc, first); > + > + if (first =3D=3D NAND_DEV_CMD1_RESTORE || first =3D=3D NAND_DEV_CMD1) > + first =3D dev_cmd_reg_addr(nandc, NAND_DEV_CMD1); > + > + if (first =3D=3D NAND_DEV_CMD_VLD_RESTORE || first =3D=3D NAND_DEV_CMD_= VLD) > + first =3D dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD); > + What about a switch case here? > + if (nandc->props->is_bam) > + return prep_bam_dma_desc_cmd(nandc, false, first, vaddr, > + num_regs, flags); > + > + if (first =3D=3D NAND_FLASH_CMD) > + flow_control =3D true; > + > + return prep_adm_dma_desc(nandc, false, first, vaddr, > + num_regs * sizeof(u32), flow_control); > +} > +EXPORT_SYMBOL(write_reg_dma); > + > +/* > + * read_data_dma: prepares a DMA descriptor to transfer data from the > + * controller's internal buffer to the buffer 'vaddr' > + * > + * @reg_off: offset within the controller's data buffer > + * @vaddr: virtual address of the buffer we want to write to > + * @size: DMA transaction size in bytes > + * @flags: flags to control DMA descriptor preparation > + */ > +int read_data_dma(struct qcom_nand_controller *nandc, int reg_off, > + const u8 *vaddr, int size, unsigned int flags) > +{ > + if (nandc->props->is_bam) > + return prep_bam_dma_desc_data(nandc, true, vaddr, size, flags); > + > + return prep_adm_dma_desc(nandc, true, reg_off, vaddr, size, false); > +} > +EXPORT_SYMBOL(read_data_dma); > + > +/* > + * write_data_dma: prepares a DMA descriptor to transfer data from > + * 'vaddr' to the controller's internal buffer > + * > + * @reg_off: offset within the controller's data buffer > + * @vaddr: virtual address of the buffer we want to read from > + * @size: DMA transaction size in bytes > + * @flags: flags to control DMA descriptor preparation > + */ > +int write_data_dma(struct qcom_nand_controller *nandc, int reg_off, > + const u8 *vaddr, int size, unsigned int flags) > +{ > + if (nandc->props->is_bam) > + return prep_bam_dma_desc_data(nandc, false, vaddr, size, flags); > + > + return prep_adm_dma_desc(nandc, false, reg_off, vaddr, size, false); > +} > +EXPORT_SYMBOL(write_data_dma); > + > +void nandc_set_reg(struct qcom_nand_controller *nandc, int offset, > + u32 val) > +{ > + struct nandc_regs *regs =3D nandc->regs; > + __le32 *reg; > + > + reg =3D offset_to_nandc_reg(regs, offset); > + if (reg) > + *reg =3D cpu_to_le32(val); > +} > +EXPORT_SYMBOL(nandc_set_reg); > + > +/* Allocates and Initializes the BAM transaction */ > +struct bam_transaction * > +alloc_bam_transaction(struct qcom_nand_controller *nandc) > +{ > + struct bam_transaction *bam_txn; > + size_t bam_txn_size; > + unsigned int num_cw =3D nandc->max_cwperpage; > + void *bam_txn_buf; > + > + bam_txn_size =3D > + sizeof(*bam_txn) + num_cw * > + ((sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS) + > + (sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL) + > + (sizeof(*bam_txn->data_sgl) * QPIC_PER_CW_DATA_SGL)); > + > + bam_txn_buf =3D devm_kzalloc(nandc->dev, bam_txn_size, GFP_KERNEL); > + if (!bam_txn_buf) > + return NULL; > + > + bam_txn =3D bam_txn_buf; > + bam_txn_buf +=3D sizeof(*bam_txn); > + > + bam_txn->bam_ce =3D bam_txn_buf; > + bam_txn_buf +=3D > + sizeof(*bam_txn->bam_ce) * QPIC_PER_CW_CMD_ELEMENTS * num_cw; > + > + bam_txn->cmd_sgl =3D bam_txn_buf; > + bam_txn_buf +=3D > + sizeof(*bam_txn->cmd_sgl) * QPIC_PER_CW_CMD_SGL * num_cw; > + > + bam_txn->data_sgl =3D bam_txn_buf; > + > + init_completion(&bam_txn->txn_done); > + > + return bam_txn; > +} > +EXPORT_SYMBOL(alloc_bam_transaction); > + > +/* Clears the BAM transaction indexes */ > +void clear_bam_transaction(struct qcom_nand_controller *nandc) > +{ > + struct bam_transaction *bam_txn =3D nandc->bam_txn; > + > + if (!nandc->props->is_bam) > + return; > + > + bam_txn->bam_ce_pos =3D 0; > + bam_txn->bam_ce_start =3D 0; > + bam_txn->cmd_sgl_pos =3D 0; > + bam_txn->cmd_sgl_start =3D 0; > + bam_txn->tx_sgl_pos =3D 0; > + bam_txn->tx_sgl_start =3D 0; > + bam_txn->rx_sgl_pos =3D 0; > + bam_txn->rx_sgl_start =3D 0; > + bam_txn->last_data_desc =3D NULL; > + bam_txn->wait_second_completion =3D false; > + > + sg_init_table(bam_txn->cmd_sgl, nandc->max_cwperpage * > + QPIC_PER_CW_CMD_SGL); > + sg_init_table(bam_txn->data_sgl, nandc->max_cwperpage * > + QPIC_PER_CW_DATA_SGL); > + > + reinit_completion(&bam_txn->txn_done); > +} > +EXPORT_SYMBOL(clear_bam_transaction); > + > +/* one time setup of a few nand controller registers */ Does this needs to be shared? > +int qcom_nandc_setup(struct qcom_nand_controller *nandc) > +{ > + u32 nand_ctrl; > + > + /* kill onenand */ > + if (!nandc->props->is_qpic) > + nandc_write(nandc, SFLASHC_BURST_CFG, 0); > + > + if (!nandc->props->qpic_v2) > + nandc_write(nandc, dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD), > + NAND_DEV_CMD_VLD_VAL); > + > + /* enable ADM or BAM DMA */ > + if (nandc->props->is_bam) { > + nand_ctrl =3D nandc_read(nandc, NAND_CTRL); > + > + /* > + *NAND_CTRL is an operational registers, and CPU > + * access to operational registers are read only > + * in BAM mode. So update the NAND_CTRL register > + * only if it is not in BAM mode. In most cases BAM > + * mode will be enabled in bootloader > + */ > + if (!(nand_ctrl & BAM_MODE_EN)) > + nandc_write(nandc, NAND_CTRL, nand_ctrl | BAM_MODE_EN); > + } else { > + nandc_write(nandc, NAND_FLASH_CHIP_SELECT, DM_EN); > + } > + > + /* save the original values of these registers */ > + if (!nandc->props->qpic_v2) { > + nandc->cmd1 =3D nandc_read(nandc, dev_cmd_reg_addr(nandc, NAND_DEV_CMD= 1)); > + nandc->vld =3D NAND_DEV_CMD_VLD_VAL; > + } > + > + return 0; > +} > +EXPORT_SYMBOL(qcom_nandc_setup); > + > +void qcom_nandc_unalloc(struct qcom_nand_controller *nandc) > +{ > + if (nandc->props->is_bam) { > + if (!dma_mapping_error(nandc->dev, nandc->reg_read_dma)) > + dma_unmap_single(nandc->dev, nandc->reg_read_dma, > + MAX_REG_RD * > + sizeof(*nandc->reg_read_buf), > + DMA_FROM_DEVICE); > + > + if (nandc->tx_chan) > + dma_release_channel(nandc->tx_chan); > + > + if (nandc->rx_chan) > + dma_release_channel(nandc->rx_chan); > + > + if (nandc->cmd_chan) > + dma_release_channel(nandc->cmd_chan); > + } else { > + if (nandc->chan) > + dma_release_channel(nandc->chan); > + } > +} > +EXPORT_SYMBOL(qcom_nandc_unalloc); > + > +int qcom_nandc_alloc(struct qcom_nand_controller *nandc) > +{ > + int ret; > + > + ret =3D dma_set_coherent_mask(nandc->dev, DMA_BIT_MASK(32)); > + if (ret) { > + dev_err(nandc->dev, "failed to set DMA mask\n"); > + return ret; > + } > + > + /* > + * we use the internal buffer for reading ONFI params, reading small > + * data like ID and status, and preforming read-copy-write operations performing Please run checkpatch.pl, I believe the tool should catch these. > + * when writing to a codeword partially. 532 is the maximum possible > + * size of a codeword for our nand controller > + */ > + nandc->buf_size =3D 532; > + > + nandc->data_buffer =3D devm_kzalloc(nandc->dev, nandc->buf_size, > + GFP_KERNEL); > + if (!nandc->data_buffer) > + return -ENOMEM; > + > + nandc->regs =3D devm_kzalloc(nandc->dev, sizeof(*nandc->regs), > + GFP_KERNEL); > + if (!nandc->regs) > + return -ENOMEM; > + > + nandc->reg_read_buf =3D devm_kcalloc(nandc->dev, > + MAX_REG_RD, sizeof(*nandc->reg_read_buf), > + GFP_KERNEL); > + if (!nandc->reg_read_buf) > + return -ENOMEM; > + > + if (nandc->props->is_bam) { It's probably the 10th time I ask, but what the heck is this is_bam parameter showing? It looks like you're handling two different controllers in the same driver without using different compatibles. > + nandc->reg_read_dma =3D > + dma_map_single(nandc->dev, nandc->reg_read_buf, > + MAX_REG_RD * > + sizeof(*nandc->reg_read_buf), > + DMA_FROM_DEVICE); > + if (dma_mapping_error(nandc->dev, nandc->reg_read_dma)) { > + dev_err(nandc->dev, "failed to DMA MAP reg buffer\n"); > + return -EIO; > + } > + > + nandc->tx_chan =3D dma_request_chan(nandc->dev, "tx"); > + if (IS_ERR(nandc->tx_chan)) { > + ret =3D PTR_ERR(nandc->tx_chan); > + nandc->tx_chan =3D NULL; > + dev_err_probe(nandc->dev, ret, > + "tx DMA channel request failed\n"); > + goto unalloc; > + } > + > + nandc->rx_chan =3D dma_request_chan(nandc->dev, "rx"); > + if (IS_ERR(nandc->rx_chan)) { > + ret =3D PTR_ERR(nandc->rx_chan); > + nandc->rx_chan =3D NULL; > + dev_err_probe(nandc->dev, ret, > + "rx DMA channel request failed\n"); > + goto unalloc; > + } > + > + nandc->cmd_chan =3D dma_request_chan(nandc->dev, "cmd"); > + if (IS_ERR(nandc->cmd_chan)) { > + ret =3D PTR_ERR(nandc->cmd_chan); > + nandc->cmd_chan =3D NULL; > + dev_err_probe(nandc->dev, ret, > + "cmd DMA channel request failed\n"); > + goto unalloc; > + } > + > + /* > + * Initially allocate BAM transaction to read ONFI param page. > + * After detecting all the devices, this BAM transaction will > + * be freed and the next BAM tranasction will be allocated with Typo > + * maximum codeword size > + */ > + nandc->max_cwperpage =3D 1; > + nandc->bam_txn =3D alloc_bam_transaction(nandc); > + if (!nandc->bam_txn) { > + dev_err(nandc->dev, > + "failed to allocate bam transaction\n"); > + ret =3D -ENOMEM; > + goto unalloc; > + } > + } else { > + nandc->chan =3D dma_request_chan(nandc->dev, "rxtx"); > + if (IS_ERR(nandc->chan)) { > + ret =3D PTR_ERR(nandc->chan); > + nandc->chan =3D NULL; > + dev_err_probe(nandc->dev, ret, > + "rxtx DMA channel request failed\n"); > + return ret; > + } > + } > + > + INIT_LIST_HEAD(&nandc->desc_list); > + INIT_LIST_HEAD(&nandc->host_list); > + > + return 0; > +unalloc: > + qcom_nandc_unalloc(nandc); > + return ret; > +} > +EXPORT_SYMBOL(qcom_nandc_alloc); > diff --git a/include/linux/mtd/nand-qpic-common.h b/include/linux/mtd/nan= d-qpic-common.h > new file mode 100644 > index 000000000000..c461c1781330 > --- /dev/null > +++ b/include/linux/mtd/nand-qpic-common.h ... > + u32 cmd1, vld; > + bool exec_opwrite; > +}; > + > +/* > + * NAND chip structure qcom_nand_host is a nand chip structure? > + * > + * @boot_partitions: array of boot partitions where offset and size of = the > + * boot partitions are stored > + * > + * @chip: base NAND chip structure > + * @node: list node to add itself to host_list in > + * qcom_nand_controller > + * > + * @nr_boot_partitions: count of the boot partitions where spare data i= s not > + * protected by ECC > + * > + * @cs: chip select value for this chip > + * @cw_size: the number of bytes in a single step/codeword > + * of a page, consisting of all data, ecc, spare > + * and reserved bytes > + * @cw_data: the number of bytes within a codeword protected > + * by ECC > + * @ecc_bytes_hw: ECC bytes used by controller hardware for this > + * chip > + * > + * @last_command: keeps track of last command on this chip. used > + * for reading correct status > + * > + * @cfg0, cfg1, cfg0_raw..: NANDc register configurations needed for > + * ecc/non-ecc mode for the current nand flash > + * device > + * > + * @status: value to be returned if NAND_CMD_STATUS command > + * is executed > + * @codeword_fixup: keep track of the current layout used by > + * the driver for read/write operation. > + * @use_ecc: request the controller to use ECC for the > + * upcoming read/write > + * @bch_enabled: flag to tell whether BCH ECC mode is used > + */ > +struct qcom_nand_host { > + struct qcom_nand_boot_partition *boot_partitions; > + > + struct nand_chip chip; > + struct list_head node; > + > + int nr_boot_partitions; > + > + int cs; > + int cw_size; > + int cw_data; > + int ecc_bytes_hw; > + int spare_bytes; > + int bbm_size; > + > + int last_command; > + > + u32 cfg0, cfg1; > + u32 cfg0_raw, cfg1_raw; > + u32 ecc_buf_cfg; > + u32 ecc_bch_cfg; > + u32 clrflashstatus; > + u32 clrreadstatus; > + > + u8 status; > + bool codeword_fixup; > + bool use_ecc; > + bool bch_enabled; > +}; > + I would like to see how useful are all these exports. I believe the current NAND controller driver already has some of these functions defined, could you please move the functions rather than adding them here without removing them in the other driver? Thanks, Miqu=C3=A8l 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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 14BF7C4332F for ; Tue, 31 Oct 2023 15:54:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Subject:Cc: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=cmM849ydzdHWRha9/6yLuZ/rOn/5JEUCSp+H/kdgzxM=; b=pqZ7VO4nT3Bo1H EMhPB6KdDPUi9wdFYUg8Bkx47cKVU1GUm7MhKA5mTB/MqcKdONN9Vnybt+2LmSJcPAcYGLaA2KGFU 5b8iDeh5PgqlNqSxTtnFBu2G0SNvRUThngc78fJkAsqk7Rhwn3eUWgRUamOQV62DwY7RXRtJINsvR CyJtPHZF8CHApKs31pXCQXDvBgRW4HPwBxlXYONao2ykOIRUGxGpeMsd3FnPVas1i08DKgeE6SRcc GoqHV88WXk5gGASf/q4cuufdvm4aQ33ujQDNBnpWvd8QHcEBnHGV+8yXN4T3uTrBMMM/AumC6hor3 /CitNYckPKVVerU+exQg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.96 #2 (Red Hat Linux)) id 1qxr4M-005Yfu-2x; Tue, 31 Oct 2023 15:54:18 +0000 Received: from relay3-d.mail.gandi.net ([2001:4b98:dc4:8::223]) by bombadil.infradead.org with esmtps (Exim 4.96 #2 (Red Hat Linux)) id 1qxr4H-005YfB-2o for linux-mtd@lists.infradead.org; Tue, 31 Oct 2023 15:54:17 +0000 Received: by mail.gandi.net (Postfix) with ESMTPSA id A01FC6000D; Tue, 31 Oct 2023 15:54:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1698767650; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pFpuhFdEBzHaLiA0OeJ+8Qf/mgpHnhSrpmbF/xo4GW0=; b=JHsOAC+H3igsiQMlOeBjGjQxduzkExQYnyjrg+5kZ90nf+FVEeKWVAJlfAxE2yU8EwbdaC bVTNPziOMVzhcxKXd6pW+BX+lm4/IsOVxOjnnIzYNmU7inGzoPR6wXNHen8qi5VU6Rc5dx VFA0BODYV79rl3OuPgQmgNx+pBkE0urd9NwaAjXw5Ib1mnXVrdBR4iEeea5easVrDiV3jI qnKGR5hM41dbmNPXsiniPLo7gYaCC2BdGKDMWhfesoDqY/b/L3ZoyKwDnPQ/Gsf33YPNkS QQstiaHt0OrRFQ4Hp+eKXsLmrn9sQUWYiShXik7oAj7pczWpT5LJBkIZ38hfFA== Date: Tue, 31 Oct 2023 16:54:06 +0100 From: Miquel Raynal To: Md Sadre Alam Cc: agross@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org, robh+dt@kernel.org, conor+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, richard@nod.at, vigneshr@ti.com, broonie@kernel.org, linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, linux-spi@vger.kernel.org, quic_srichara@quicinc.com, qpic_varada@quicinc.com Subject: Re: [RFC PATCH 3/5] mtd: nand: qpic_common: Add support for qpic common API Message-ID: <20231031165406.33e486a3@xps-13> In-Reply-To: <20231031120307.1600689-4-quic_mdalam@quicinc.com> References: <20231031120307.1600689-1-quic_mdalam@quicinc.com> <20231031120307.1600689-4-quic_mdalam@quicinc.com> Organization: Bootlin X-Mailer: Claws Mail 4.0.0 (GTK+ 3.24.33; x86_64-pc-linux-gnu) MIME-Version: 1.0 X-GND-Sasl: miquel.raynal@bootlin.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20231031_085414_211779_E383BF1D X-CRM114-Status: GOOD ( 36.00 ) X-BeenThere: linux-mtd@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , 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 SGksCgpxdWljX21kYWxhbUBxdWljaW5jLmNvbSB3cm90ZSBvbiBUdWUsIDMxIE9jdCAyMDIzIDE3 OjMzOjA1ICswNTMwOgoKPiBBZGQgcXBpYyBjb21tYW5kIEFQSSBpbiBzcGVyYXRlIGZpbGUgc28g dGhhdCBpdCB3aWxsIGJlCj4gdXNlIGJ5IGJvdGggc3BpIGFuZCByZXF1ZXN0IGFuZCByYXcgbmFu ZCByZXF1ZXN0LgoKCQluYW5kPwoKPiAKPiBTaWduZWQtb2ZmLWJ5OiBNZCBTYWRyZSBBbGFtIDxx dWljX21kYWxhbUBxdWljaW5jLmNvbT4KPiBTaWduZWQtb2ZmLWJ5OiBTcmljaGFyYW4gUiA8cXVp Y19zcmljaGFyYUBxdWljaW5jLmNvbT4KPiAtLS0KPiAgZHJpdmVycy9tdGQvbmFuZC9xcGljX2Nv bW1vbi5jICAgICAgIHwgODQwICsrKysrKysrKysrKysrKysrKysrKysrKysrKwo+ICBpbmNsdWRl L2xpbnV4L210ZC9uYW5kLXFwaWMtY29tbW9uLmggfCA2NDEgKysrKysrKysrKysrKysrKysrKysK PiAgMiBmaWxlcyBjaGFuZ2VkLCAxNDgxIGluc2VydGlvbnMoKykKPiAgY3JlYXRlIG1vZGUgMTAw NjQ0IGRyaXZlcnMvbXRkL25hbmQvcXBpY19jb21tb24uYwo+ICBjcmVhdGUgbW9kZSAxMDA2NDQg aW5jbHVkZS9saW51eC9tdGQvbmFuZC1xcGljLWNvbW1vbi5oCj4gCj4gZGlmZiAtLWdpdCBhL2Ry aXZlcnMvbXRkL25hbmQvcXBpY19jb21tb24uYyBiL2RyaXZlcnMvbXRkL25hbmQvcXBpY19jb21t b24uYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMDAwMDAwLi45ODM3Njhh MWVhOTQKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy9tdGQvbmFuZC9xcGljX2NvbW1v bi5jCj4gQEAgLTAsMCArMSw4NDAgQEAKPiArLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQ TC0yLjAgT1IgTUlUCj4gKy8qCj4gKyAqIFFQSUMgY29tbW9uIEFQSSBmaWxlLgo+ICsgKiBDb3B5 cmlnaHQgKEMpIDIwMjMgIFF1YWxjb21tIEluYy4KPiArICogQXV0aG9yczoJTWQgc2FkcmUgQWxh bQkJPHF1aWNfbWRhbGFtQHF1aWNpbmMuY29tPgo+ICsgKgkJU3JpY2hhcmFuIFIJCTxxdWljX3Ny aWNoYXJhQHF1aWNpbmMuY29tPgo+ICsgKi8KPiArCj4gKyNpbmNsdWRlIDxsaW51eC9tdGQvbmFu ZC1xcGljLWNvbW1vbi5oPgo+ICsKPiArLyogRnJlZXMgdGhlIEJBTSB0cmFuc2FjdGlvbiBtZW1v cnkgKi8KPiArdm9pZCBmcmVlX2JhbV90cmFuc2FjdGlvbihzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRy b2xsZXIgKm5hbmRjKQoKVGhpcyBpcyBub3QgYSBnZW5lcmljIG9iamVjdCwgaXQncyBub3QgbWVh bnQgdG8gYmUgc2hhcmVkIHdpdGggc3BpLiBTbwppZiBpdCdzIG1lYW50IHRvIGJlIHVzZWQgaW4g YSBzaW5nbGUgcGxhY2UsIHBsZWFzZSBkb24ndCBzaGFyZSBpdC4KT3RoZXJ3aXNlIHBsZWFzZSB1 c2UgYSBtb3JlIGdlbmVyaWMgbmFtZS4KCj4gK3sKPiArCXN0cnVjdCBiYW1fdHJhbnNhY3Rpb24g KmJhbV90eG4gPSBuYW5kYy0+YmFtX3R4bjsKPiArCj4gKwlkZXZtX2tmcmVlKG5hbmRjLT5kZXYs IGJhbV90eG4pOwo+ICt9Cj4gK0VYUE9SVF9TWU1CT0woZnJlZV9iYW1fdHJhbnNhY3Rpb24pOwo+ ICsKPiArLyogQ2FsbGJhY2sgZm9yIERNQSBkZXNjcmlwdG9yIGNvbXBsZXRpb24gKi8KPiArdm9p ZCBxcGljX2JhbV9kbWFfZG9uZSh2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3QgYmFtX3RyYW5z YWN0aW9uICpiYW1fdHhuID0gZGF0YTsKCkp1c3QgcHJvdmlkZSB0aGUgcmlnaHQgcG9pbnRlciBp biB0aGUgZmlyc3QgcGxhY2UuCgo+ICsKPiArCS8qCj4gKwkgKiBJbiBjYXNlIG9mIGRhdGEgdHJh bnNmZXIgd2l0aCBOQU5ELCAyIGNhbGxiYWNrcyB3aWxsIGJlIGdlbmVyYXRlZC4KCldoYXQgaWYg d2UgYXJlIG5vdCBkZWFsaW5nIHdpdGggYSBOQU5EPwoKPiArCSAqIE9uZSBmb3IgY29tbWFuZCBj aGFubmVsIGFuZCBhbm90aGVyIG9uZSBmb3IgZGF0YSBjaGFubmVsLgo+ICsJICogSWYgY3VycmVu dCB0cmFuc2FjdGlvbiBoYXMgZGF0YSBkZXNjcmlwdG9ycwo+ICsJICogKGkuZS4gd2FpdF9zZWNv bmRfY29tcGxldGlvbiBpcyB0cnVlKSwgdGhlbiBzZXQgdGhpcyB0byBmYWxzZQoKV2h5IGRvIHlv dSBuZWVkIGEgYm9vbGVhbiBmb3IgdGhhdCBpZiBoYXZpbmcgYSBkYXRhIGRlc2NyaXB0b3IgaXMg dGhlCmNvbmRpdGlvbiB5b3Ugd2FudCB0byBjaGVjayBhZ2FpbnN0PwoKPiArCSAqIGFuZCB3YWl0 IGZvciBzZWNvbmQgRE1BIGRlc2NyaXB0b3IgY29tcGxldGlvbi4KPiArCSAqLwo+ICsJaWYgKGJh bV90eG4tPndhaXRfc2Vjb25kX2NvbXBsZXRpb24pCj4gKwkJYmFtX3R4bi0+d2FpdF9zZWNvbmRf Y29tcGxldGlvbiA9IGZhbHNlOwoKVGhpcyBsb29rcyB2ZXJ5IHJhY3kuCgo+ICsJZWxzZQo+ICsJ CWNvbXBsZXRlKCZiYW1fdHhuLT50eG5fZG9uZSk7Cj4gK30KPiArRVhQT1JUX1NZTUJPTChxcGlj X2JhbV9kbWFfZG9uZSk7Cj4gKwo+ICt1MzIgbmFuZGNfcmVhZChzdHJ1Y3QgcWNvbV9uYW5kX2Nv bnRyb2xsZXIgKm5hbmRjLCBpbnQgb2Zmc2V0KQo+ICt7Cj4gKwlyZXR1cm4gaW9yZWFkMzIobmFu ZGMtPmJhc2UgKyBvZmZzZXQpOwoKSSBkb24ndCBzZWUgdGhlIG5lZWQgZm9yIHRoYXQuCgo+ICt9 Cj4gK0VYUE9SVF9TWU1CT0wobmFuZGNfcmVhZCk7Cj4gKwo+ICt2b2lkIG5hbmRjX3dyaXRlKHN0 cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqbmFuZGMsIGludCBvZmZzZXQsCj4gKwkJCSAgICAg ICB1MzIgdmFsKQo+ICt7Cj4gKwlpb3dyaXRlMzIodmFsLCBuYW5kYy0+YmFzZSArIG9mZnNldCk7 CgpTYW1lIGhlcmUuCgo+ICt9Cj4gK0VYUE9SVF9TWU1CT0wobmFuZGNfd3JpdGUpOwo+ICsKPiAr dm9pZCBuYW5kY19yZWFkX2J1ZmZlcl9zeW5jKHN0cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAq bmFuZGMsCj4gKwkJCQkJICBib29sIGlzX2NwdSkKPiArewo+ICsJaWYgKCFuYW5kYy0+cHJvcHMt PmlzX2JhbSkKPiArCQlyZXR1cm47CgpJIHRob3VnaHQgQkFNIHdhcyBhIHBlciB0cmFuc2FjdGlv biB0aGluZywgYW5kIGhlcmUgeW91IGNoZWNrIGl0CmFnYWluc3QgYSBjb250cm9sbGVyIHBhcmFt ZXRlci4gSXQgbG9va3Mgd3JvbmcuCgo+ICsKPiArCWlmIChpc19jcHUpCgpXaHV1dD8gbmFtaW5n LCBuYW1pbmcsIG5hbWluZywgbmFtaW5nLiBQbGVhc2UuCgo+ICsJCWRtYV9zeW5jX3NpbmdsZV9m b3JfY3B1KG5hbmRjLT5kZXYsIG5hbmRjLT5yZWdfcmVhZF9kbWEsCj4gKwkJCQkJTUFYX1JFR19S RCAqCgpSZW1vdmUgdGhpcyBuZXcgbGluZQoKPiArCQkJCQlzaXplb2YoKm5hbmRjLT5yZWdfcmVh ZF9idWYpLAoKQXJlIHlvdSBzdXJlIHRoaXMgc2l6ZW9mKCkgaXMgc2FmZT8KCj4gKwkJCQkJRE1B X0ZST01fREVWSUNFKTsKPiArCWVsc2UKPiArCQlkbWFfc3luY19zaW5nbGVfZm9yX2RldmljZShu YW5kYy0+ZGV2LCBuYW5kYy0+cmVnX3JlYWRfZG1hLAo+ICsJCQkJCSAgIE1BWF9SRUdfUkQgKgo+ ICsJCQkJCSAgIHNpemVvZigqbmFuZGMtPnJlZ19yZWFkX2J1ZiksCj4gKwkJCQkJICAgRE1BX0ZS T01fREVWSUNFKTsKPiArfQoKWW91IGJldHRlciBoYXZlIGEgcmVhbGx5IGdvb2QgcmVhc29uIHRv IHN5bmMgaW4gdGhlIG1pZGRsZSBvZiBhbgpvcGVyYXRpb24uLi4KCj4gK0VYUE9SVF9TWU1CT0wo bmFuZGNfcmVhZF9idWZmZXJfc3luYyk7Cj4gKwo+ICtfX2xlMzIgKm9mZnNldF90b19uYW5kY19y ZWcoc3RydWN0IG5hbmRjX3JlZ3MgKnJlZ3MsIGludCBvZmZzZXQpCj4gK3sKPiArCXN3aXRjaCAo b2Zmc2V0KSB7Cj4gKwljYXNlIE5BTkRfRkxBU0hfQ01EOgo+ICsJCXJldHVybiAmcmVncy0+Y21k Owo+ICsJY2FzZSBOQU5EX0FERFIwOgo+ICsJCXJldHVybiAmcmVncy0+YWRkcjA7Cj4gKwljYXNl IE5BTkRfQUREUjE6Cj4gKwkJcmV0dXJuICZyZWdzLT5hZGRyMTsKPiArCWNhc2UgTkFORF9GTEFT SF9DSElQX1NFTEVDVDoKPiArCQlyZXR1cm4gJnJlZ3MtPmNoaXBfc2VsOwo+ICsJY2FzZSBOQU5E X0VYRUNfQ01EOgo+ICsJCXJldHVybiAmcmVncy0+ZXhlYzsKPiArCWNhc2UgTkFORF9GTEFTSF9T VEFUVVM6Cj4gKwkJcmV0dXJuICZyZWdzLT5jbHJmbGFzaHN0YXR1czsKPiArCWNhc2UgTkFORF9E RVYwX0NGRzA6Cj4gKwkJcmV0dXJuICZyZWdzLT5jZmcwOwo+ICsJY2FzZSBOQU5EX0RFVjBfQ0ZH MToKPiArCQlyZXR1cm4gJnJlZ3MtPmNmZzE7Cj4gKwljYXNlIE5BTkRfREVWMF9FQ0NfQ0ZHOgo+ ICsJCXJldHVybiAmcmVncy0+ZWNjX2JjaF9jZmc7Cj4gKwljYXNlIE5BTkRfUkVBRF9TVEFUVVM6 Cj4gKwkJcmV0dXJuICZyZWdzLT5jbHJyZWFkc3RhdHVzOwo+ICsJY2FzZSBOQU5EX0RFVl9DTUQx Ogo+ICsJCXJldHVybiAmcmVncy0+Y21kMTsKPiArCWNhc2UgTkFORF9ERVZfQ01EMV9SRVNUT1JF Ogo+ICsJCXJldHVybiAmcmVncy0+b3JpZ19jbWQxOwo+ICsJY2FzZSBOQU5EX0RFVl9DTURfVkxE Ogo+ICsJCXJldHVybiAmcmVncy0+dmxkOwo+ICsJY2FzZSBOQU5EX0RFVl9DTURfVkxEX1JFU1RP UkU6Cj4gKwkJcmV0dXJuICZyZWdzLT5vcmlnX3ZsZDsKPiArCWNhc2UgTkFORF9FQkkyX0VDQ19C VUZfQ0ZHOgo+ICsJCXJldHVybiAmcmVncy0+ZWNjX2J1Zl9jZmc7Cj4gKwljYXNlIE5BTkRfUkVB RF9MT0NBVElPTl8wOgo+ICsJCXJldHVybiAmcmVncy0+cmVhZF9sb2NhdGlvbjA7Cj4gKwljYXNl IE5BTkRfUkVBRF9MT0NBVElPTl8xOgo+ICsJCXJldHVybiAmcmVncy0+cmVhZF9sb2NhdGlvbjE7 Cj4gKwljYXNlIE5BTkRfUkVBRF9MT0NBVElPTl8yOgo+ICsJCXJldHVybiAmcmVncy0+cmVhZF9s b2NhdGlvbjI7Cj4gKwljYXNlIE5BTkRfUkVBRF9MT0NBVElPTl8zOgo+ICsJCXJldHVybiAmcmVn cy0+cmVhZF9sb2NhdGlvbjM7Cj4gKwljYXNlIE5BTkRfUkVBRF9MT0NBVElPTl9MQVNUX0NXXzA6 Cj4gKwkJcmV0dXJuICZyZWdzLT5yZWFkX2xvY2F0aW9uX2xhc3QwOwo+ICsJY2FzZSBOQU5EX1JF QURfTE9DQVRJT05fTEFTVF9DV18xOgo+ICsJCXJldHVybiAmcmVncy0+cmVhZF9sb2NhdGlvbl9s YXN0MTsKPiArCWNhc2UgTkFORF9SRUFEX0xPQ0FUSU9OX0xBU1RfQ1dfMjoKPiArCQlyZXR1cm4g JnJlZ3MtPnJlYWRfbG9jYXRpb25fbGFzdDI7Cj4gKwljYXNlIE5BTkRfUkVBRF9MT0NBVElPTl9M QVNUX0NXXzM6Cj4gKwkJcmV0dXJuICZyZWdzLT5yZWFkX2xvY2F0aW9uX2xhc3QzOwo+ICsJY2Fz ZSBOQU5EX0ZMQVNIX1NQSV9DRkc6Cj4gKwkJcmV0dXJuICZyZWdzLT5zcGlfY2ZnOwo+ICsJY2Fz ZSBOQU5EX05VTV9BRERSX0NZQ0xFUzoKPiArCQlyZXR1cm4gJnJlZ3MtPm51bV9hZGRyX2N5Y2xl Owo+ICsJY2FzZSBOQU5EX0JVU1lfQ0hFQ0tfV0FJVF9DTlQ6Cj4gKwkJcmV0dXJuICZyZWdzLT5i dXN5X3dhaXRfY250Owo+ICsJY2FzZSBOQU5EX01TVFJfQ09ORklHOgo+ICsJCXJldHVybiAmcmVn cy0+bXN0cl9jZmc7Cj4gKwljYXNlIE5BTkRfRkxBU0hfRkVBVFVSRVM6Cj4gKwkJcmV0dXJuICZy ZWdzLT5mbGFzaF9mZWF0dXJlOwoKSnVzdC4uLiBubz8gV2hhdCBpcyB0aGUgcG9pbnQgb2YgdXNp bmcgYW4gaW50ZXJtZWRpYXRlIGludCBoZXJlPyBqdXN0CmRlcmVmZXJlbmNlIHRoZSByaWdodCB2 YWx1ZT8KCj4gKwlkZWZhdWx0Ogo+ICsJCXJldHVybiBOVUxMOwo+ICsJfQo+ICt9Cj4gK0VYUE9S VF9TWU1CT0wob2Zmc2V0X3RvX25hbmRjX3JlZyk7Cj4gKwo+ICsvKiByZXNldCB0aGUgcmVnaXN0 ZXIgcmVhZCBidWZmZXIgZm9yIG5leHQgTkFORCBvcGVyYXRpb24gKi8KPiArdm9pZCBjbGVhcl9y ZWFkX3JlZ3Moc3RydWN0IHFjb21fbmFuZF9jb250cm9sbGVyICpuYW5kYykKPiArewo+ICsJbmFu ZGMtPnJlZ19yZWFkX3BvcyA9IDA7Cj4gKwluYW5kY19yZWFkX2J1ZmZlcl9zeW5jKG5hbmRjLCBm YWxzZSk7Cj4gK30KPiArRVhQT1JUX1NZTUJPTChjbGVhcl9yZWFkX3JlZ3MpOwo+ICsKPiAraW50 IHByZXBfYWRtX2RtYV9kZXNjKHN0cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqbmFuZGMsIGJv b2wgcmVhZCwKCmFkbT8KCgpQbGVhc2UgYWx3YXlzIHByZWZpeCB5b3VyIHN5bWJvbHMgKGVzcGVj aWFsbHkgd2hlbiBleHBvcnRpbmcgdGhlbSkgd2l0aAphIGRlY2VudCBhIGVhc3kgdG8gcmVjb2du aXplIHByZWZpeC4KCj4gKwkJCSAgICAgaW50IHJlZ19vZmYsIGNvbnN0IHZvaWQgKnZhZGRyLCBp bnQgc2l6ZSwKPiArCQkJICAgICBib29sIGZsb3dfY29udHJvbCkKPiArewo+ICsJc3RydWN0IGRl c2NfaW5mbyAqZGVzYzsKPiArCXN0cnVjdCBkbWFfYXN5bmNfdHhfZGVzY3JpcHRvciAqZG1hX2Rl c2M7Cj4gKwlzdHJ1Y3Qgc2NhdHRlcmxpc3QgKnNnbDsKPiArCXN0cnVjdCBkbWFfc2xhdmVfY29u ZmlnIHNsYXZlX2NvbmY7Cj4gKwlzdHJ1Y3QgcWNvbV9hZG1fcGVyaXBoZXJhbF9jb25maWcgcGVy aXBoX2NvbmYgPSB7fTsKPiArCWVudW0gZG1hX3RyYW5zZmVyX2RpcmVjdGlvbiBkaXJfZW5nOwo+ ICsJaW50IHJldDsKPiArCj4gKwlkZXNjID0ga3phbGxvYyhzaXplb2YoKmRlc2MpLCBHRlBfS0VS TkVMKTsKPiArCWlmICghZGVzYykKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwlzZ2wgPSAm ZGVzYy0+YWRtX3NnbDsKPiArCj4gKwlzZ19pbml0X29uZShzZ2wsIHZhZGRyLCBzaXplKTsKPiAr Cj4gKwlpZiAocmVhZCkgewo+ICsJCWRpcl9lbmcgPSBETUFfREVWX1RPX01FTTsKPiArCQlkZXNj LT5kaXIgPSBETUFfRlJPTV9ERVZJQ0U7Cj4gKwl9IGVsc2Ugewo+ICsJCWRpcl9lbmcgPSBETUFf TUVNX1RPX0RFVjsKPiArCQlkZXNjLT5kaXIgPSBETUFfVE9fREVWSUNFOwo+ICsJfQo+ICsKPiAr CXJldCA9IGRtYV9tYXBfc2cobmFuZGMtPmRldiwgc2dsLCAxLCBkZXNjLT5kaXIpOwo+ICsJaWYg KHJldCA9PSAwKSB7Cj4gKwkJcmV0ID0gLUVOT01FTTsKPiArCQlnb3RvIGVycjsKPiArCX0KPiAr Cj4gKwltZW1zZXQoJnNsYXZlX2NvbmYsIDB4MDAsIHNpemVvZihzbGF2ZV9jb25mKSk7Cj4gKwo+ ICsJc2xhdmVfY29uZi5kZXZpY2VfZmMgPSBmbG93X2NvbnRyb2w7Cj4gKwlpZiAocmVhZCkgewo+ ICsJCXNsYXZlX2NvbmYuc3JjX21heGJ1cnN0ID0gMTY7Cj4gKwkJc2xhdmVfY29uZi5zcmNfYWRk ciA9IG5hbmRjLT5iYXNlX2RtYSArIHJlZ19vZmY7Cj4gKwkJaWYgKG5hbmRjLT5kYXRhX2NyY2kp IHsKPiArCQkJcGVyaXBoX2NvbmYuY3JjaSA9IG5hbmRjLT5kYXRhX2NyY2k7Cj4gKwkJCXNsYXZl X2NvbmYucGVyaXBoZXJhbF9jb25maWcgPSAmcGVyaXBoX2NvbmY7Cj4gKwkJCXNsYXZlX2NvbmYu cGVyaXBoZXJhbF9zaXplID0gc2l6ZW9mKHBlcmlwaF9jb25mKTsKPiArCQl9Cj4gKwl9IGVsc2Ug ewo+ICsJCXNsYXZlX2NvbmYuZHN0X21heGJ1cnN0ID0gMTY7Cj4gKwkJc2xhdmVfY29uZi5kc3Rf YWRkciA9IG5hbmRjLT5iYXNlX2RtYSArIHJlZ19vZmY7Cj4gKwkJaWYgKG5hbmRjLT5jbWRfY3Jj aSkgewo+ICsJCQlwZXJpcGhfY29uZi5jcmNpID0gbmFuZGMtPmNtZF9jcmNpOwo+ICsJCQlzbGF2 ZV9jb25mLnBlcmlwaGVyYWxfY29uZmlnID0gJnBlcmlwaF9jb25mOwo+ICsJCQlzbGF2ZV9jb25m LnBlcmlwaGVyYWxfc2l6ZSA9IHNpemVvZihwZXJpcGhfY29uZik7Cj4gKwkJfQo+ICsJfQo+ICsK PiArCXJldCA9IGRtYWVuZ2luZV9zbGF2ZV9jb25maWcobmFuZGMtPmNoYW4sICZzbGF2ZV9jb25m KTsKPiArCWlmIChyZXQpIHsKPiArCQlkZXZfZXJyKG5hbmRjLT5kZXYsICJmYWlsZWQgdG8gY29u ZmlndXJlIGRtYSBjaGFubmVsXG4iKTsKPiArCQlnb3RvIGVycjsKPiArCX0KPiArCj4gKwlkbWFf ZGVzYyA9IGRtYWVuZ2luZV9wcmVwX3NsYXZlX3NnKG5hbmRjLT5jaGFuLCBzZ2wsIDEsIGRpcl9l bmcsIDApOwo+ICsJaWYgKCFkbWFfZGVzYykgewo+ICsJCWRldl9lcnIobmFuZGMtPmRldiwgImZh aWxlZCB0byBwcmVwYXJlIGRlc2NcbiIpOwo+ICsJCXJldCA9IC1FSU5WQUw7Cj4gKwkJZ290byBl cnI7Cj4gKwl9Cj4gKwo+ICsJZGVzYy0+ZG1hX2Rlc2MgPSBkbWFfZGVzYzsKPiArCj4gKwlsaXN0 X2FkZF90YWlsKCZkZXNjLT5ub2RlLCAmbmFuZGMtPmRlc2NfbGlzdCk7Cj4gKwo+ICsJcmV0dXJu IDA7Cj4gK2VycjoKCnlvdXIgZXJyb3IgcGF0aCBpcyBtaXNzaW5nIHN0ZXBzCgo+ICsJa2ZyZWUo ZGVzYyk7Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArLyogaGVscGVycyB0byBzdWJt aXQvZnJlZSBvdXIgbGlzdCBvZiBkbWEgZGVzY3JpcHRvcnMgKi8KPiAraW50IHN1Ym1pdF9kZXNj cyhzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRyb2xsZXIgKm5hbmRjKQo+ICt7Cj4gKwlzdHJ1Y3QgZGVz Y19pbmZvICpkZXNjOwo+ICsJZG1hX2Nvb2tpZV90IGNvb2tpZSA9IDA7Cj4gKwlzdHJ1Y3QgYmFt X3RyYW5zYWN0aW9uICpiYW1fdHhuID0gbmFuZGMtPmJhbV90eG47Cj4gKwlpbnQgcjsKPiArCj4g KwlpZiAobmFuZGMtPnByb3BzLT5pc19iYW0pIHsKPiArCQlpZiAoYmFtX3R4bi0+cnhfc2dsX3Bv cyA+IGJhbV90eG4tPnJ4X3NnbF9zdGFydCkgewo+ICsJCQlyID0gcHJlcGFyZV9iYW1fYXN5bmNf ZGVzYyhuYW5kYywgbmFuZGMtPnJ4X2NoYW4sIDApOwo+ICsJCQlpZiAocikKPiArCQkJCXJldHVy biByOwo+ICsJCX0KPiArCj4gKwkJaWYgKGJhbV90eG4tPnR4X3NnbF9wb3MgPiBiYW1fdHhuLT50 eF9zZ2xfc3RhcnQpIHsKPiArCQkJciA9IHByZXBhcmVfYmFtX2FzeW5jX2Rlc2MobmFuZGMsIG5h bmRjLT50eF9jaGFuLAo+ICsJCQkJCQkgICBETUFfUFJFUF9JTlRFUlJVUFQpOwo+ICsJCQlpZiAo cikKPiArCQkJCXJldHVybiByOwo+ICsJCX0KPiArCj4gKwkJaWYgKGJhbV90eG4tPmNtZF9zZ2xf cG9zID4gYmFtX3R4bi0+Y21kX3NnbF9zdGFydCkgewo+ICsJCQlyID0gcHJlcGFyZV9iYW1fYXN5 bmNfZGVzYyhuYW5kYywgbmFuZGMtPmNtZF9jaGFuLAo+ICsJCQkJCQkgICBETUFfUFJFUF9DTUQp Owo+ICsJCQlpZiAocikKPiArCQkJCXJldHVybiByOwo+ICsJCX0KPiArCX0KPiArCj4gKwlsaXN0 X2Zvcl9lYWNoX2VudHJ5KGRlc2MsICZuYW5kYy0+ZGVzY19saXN0LCBub2RlKQo+ICsJCWNvb2tp ZSA9IGRtYWVuZ2luZV9zdWJtaXQoZGVzYy0+ZG1hX2Rlc2MpOwo+ICsKPiArCWlmIChuYW5kYy0+ cHJvcHMtPmlzX2JhbSkgewo+ICsJCWJhbV90eG4tPmxhc3RfY21kX2Rlc2MtPmNhbGxiYWNrID0g cXBpY19iYW1fZG1hX2RvbmU7Cj4gKwkJYmFtX3R4bi0+bGFzdF9jbWRfZGVzYy0+Y2FsbGJhY2tf cGFyYW0gPSBiYW1fdHhuOwo+ICsJCWlmIChiYW1fdHhuLT5sYXN0X2RhdGFfZGVzYykgewo+ICsJ CQliYW1fdHhuLT5sYXN0X2RhdGFfZGVzYy0+Y2FsbGJhY2sgPSBxcGljX2JhbV9kbWFfZG9uZTsK PiArCQkJYmFtX3R4bi0+bGFzdF9kYXRhX2Rlc2MtPmNhbGxiYWNrX3BhcmFtID0gYmFtX3R4bjsK PiArCQkJYmFtX3R4bi0+d2FpdF9zZWNvbmRfY29tcGxldGlvbiA9IHRydWU7Cj4gKwkJfQo+ICsK PiArCQlkbWFfYXN5bmNfaXNzdWVfcGVuZGluZyhuYW5kYy0+dHhfY2hhbik7Cj4gKwkJZG1hX2Fz eW5jX2lzc3VlX3BlbmRpbmcobmFuZGMtPnJ4X2NoYW4pOwo+ICsJCWRtYV9hc3luY19pc3N1ZV9w ZW5kaW5nKG5hbmRjLT5jbWRfY2hhbik7Cj4gKwo+ICsJCWlmICghd2FpdF9mb3JfY29tcGxldGlv bl90aW1lb3V0KCZiYW1fdHhuLT50eG5fZG9uZSwKPiArCQkJCQkJIFFQSUNfTkFORF9DT01QTEVU SU9OX1RJTUVPVVQpKQo+ICsJCQlyZXR1cm4gLUVUSU1FRE9VVDsKPiArCX0gZWxzZSB7Cj4gKwkJ aWYgKGRtYV9zeW5jX3dhaXQobmFuZGMtPmNoYW4sIGNvb2tpZSkgIT0gRE1BX0NPTVBMRVRFKQo+ ICsJCQlyZXR1cm4gLUVUSU1FRE9VVDsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICtF WFBPUlRfU1lNQk9MKHN1Ym1pdF9kZXNjcyk7Cj4gKwo+ICt2b2lkIGZyZWVfZGVzY3Moc3RydWN0 IHFjb21fbmFuZF9jb250cm9sbGVyICpuYW5kYykKPiArewo+ICsJc3RydWN0IGRlc2NfaW5mbyAq ZGVzYywgKm47Cj4gKwo+ICsJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKGRlc2MsIG4sICZuYW5k Yy0+ZGVzY19saXN0LCBub2RlKSB7Cj4gKwkJbGlzdF9kZWwoJmRlc2MtPm5vZGUpOwo+ICsKPiAr CQlpZiAobmFuZGMtPnByb3BzLT5pc19iYW0pCj4gKwkJCWRtYV91bm1hcF9zZyhuYW5kYy0+ZGV2 LCBkZXNjLT5iYW1fc2dsLAo+ICsJCQkJICAgICBkZXNjLT5zZ2xfY250LCBkZXNjLT5kaXIpOwo+ ICsJCWVsc2UKPiArCQkJZG1hX3VubWFwX3NnKG5hbmRjLT5kZXYsICZkZXNjLT5hZG1fc2dsLCAx LAo+ICsJCQkJICAgICBkZXNjLT5kaXIpOwo+ICsKPiArCQlrZnJlZShkZXNjKTsKPiArCX0KPiAr fQo+ICtFWFBPUlRfU1lNQk9MKGZyZWVfZGVzY3MpOwo+ICsKPiArLyoKPiArICogTWFwcyB0aGUg c2NhdHRlciBnYXRoZXIgbGlzdCBmb3IgRE1BIHRyYW5zZmVyIGFuZCBmb3JtcyB0aGUgRE1BIGRl c2NyaXB0b3IKPiArICogZm9yIEJBTS4gVGhpcyBkZXNjcmlwdG9yIHdpbGwgYmUgYWRkZWQgaW4g dGhlIE5BTkQgRE1BIGRlc2NyaXB0b3IgcXVldWUKPiArICogd2hpY2ggd2lsbCBiZSBzdWJtaXR0 ZWQgdG8gRE1BIGVuZ2luZS4KPiArICovCj4gK2ludCBwcmVwYXJlX2JhbV9hc3luY19kZXNjKHN0 cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqbmFuZGMsCj4gKwkJCQkgIHN0cnVjdCBkbWFfY2hh biAqY2hhbiwKPiArCQkJCSAgdW5zaWduZWQgbG9uZyBmbGFncykKPiArewo+ICsJc3RydWN0IGRl c2NfaW5mbyAqZGVzYzsKPiArCXN0cnVjdCBzY2F0dGVybGlzdCAqc2dsOwo+ICsJdW5zaWduZWQg aW50IHNnbF9jbnQ7Cj4gKwlpbnQgcmV0Owo+ICsJc3RydWN0IGJhbV90cmFuc2FjdGlvbiAqYmFt X3R4biA9IG5hbmRjLT5iYW1fdHhuOwo+ICsJZW51bSBkbWFfdHJhbnNmZXJfZGlyZWN0aW9uIGRp cl9lbmc7Cj4gKwlzdHJ1Y3QgZG1hX2FzeW5jX3R4X2Rlc2NyaXB0b3IgKmRtYV9kZXNjOwo+ICsK PiArCWRlc2MgPSBremFsbG9jKHNpemVvZigqZGVzYyksIEdGUF9LRVJORUwpOwo+ICsJaWYgKCFk ZXNjKQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCWlmIChjaGFuID09IG5hbmRjLT5jbWRf Y2hhbikgewo+ICsJCXNnbCA9ICZiYW1fdHhuLT5jbWRfc2dsW2JhbV90eG4tPmNtZF9zZ2xfc3Rh cnRdOwo+ICsJCXNnbF9jbnQgPSBiYW1fdHhuLT5jbWRfc2dsX3BvcyAtIGJhbV90eG4tPmNtZF9z Z2xfc3RhcnQ7Cj4gKwkJYmFtX3R4bi0+Y21kX3NnbF9zdGFydCA9IGJhbV90eG4tPmNtZF9zZ2xf cG9zOwo+ICsJCWRpcl9lbmcgPSBETUFfTUVNX1RPX0RFVjsKPiArCQlkZXNjLT5kaXIgPSBETUFf VE9fREVWSUNFOwo+ICsJfSBlbHNlIGlmIChjaGFuID09IG5hbmRjLT50eF9jaGFuKSB7Cj4gKwkJ c2dsID0gJmJhbV90eG4tPmRhdGFfc2dsW2JhbV90eG4tPnR4X3NnbF9zdGFydF07Cj4gKwkJc2ds X2NudCA9IGJhbV90eG4tPnR4X3NnbF9wb3MgLSBiYW1fdHhuLT50eF9zZ2xfc3RhcnQ7Cj4gKwkJ YmFtX3R4bi0+dHhfc2dsX3N0YXJ0ID0gYmFtX3R4bi0+dHhfc2dsX3BvczsKPiArCQlkaXJfZW5n ID0gRE1BX01FTV9UT19ERVY7Cj4gKwkJZGVzYy0+ZGlyID0gRE1BX1RPX0RFVklDRTsKPiArCX0g ZWxzZSB7Cj4gKwkJc2dsID0gJmJhbV90eG4tPmRhdGFfc2dsW2JhbV90eG4tPnJ4X3NnbF9zdGFy dF07Cj4gKwkJc2dsX2NudCA9IGJhbV90eG4tPnJ4X3NnbF9wb3MgLSBiYW1fdHhuLT5yeF9zZ2xf c3RhcnQ7Cj4gKwkJYmFtX3R4bi0+cnhfc2dsX3N0YXJ0ID0gYmFtX3R4bi0+cnhfc2dsX3BvczsK PiArCQlkaXJfZW5nID0gRE1BX0RFVl9UT19NRU07Cj4gKwkJZGVzYy0+ZGlyID0gRE1BX0ZST01f REVWSUNFOwo+ICsJfQo+ICsKPiArCXNnX21hcmtfZW5kKHNnbCArIHNnbF9jbnQgLSAxKTsKPiAr CXJldCA9IGRtYV9tYXBfc2cobmFuZGMtPmRldiwgc2dsLCBzZ2xfY250LCBkZXNjLT5kaXIpOwo+ ICsJaWYgKHJldCA9PSAwKSB7Cj4gKwkJZGV2X2VycihuYW5kYy0+ZGV2LCAiZmFpbHVyZSBpbiBt YXBwaW5nIGRlc2NcbiIpOwo+ICsJCWtmcmVlKGRlc2MpOwo+ICsJCXJldHVybiAtRU5PTUVNOwo+ ICsJfQo+ICsKPiArCWRlc2MtPnNnbF9jbnQgPSBzZ2xfY250Owo+ICsJZGVzYy0+YmFtX3NnbCA9 IHNnbDsKPiArCj4gKwlkbWFfZGVzYyA9IGRtYWVuZ2luZV9wcmVwX3NsYXZlX3NnKGNoYW4sIHNn bCwgc2dsX2NudCwgZGlyX2VuZywKPiArCQkJCQkgICBmbGFncyk7Cj4gKwo+ICsJaWYgKCFkbWFf ZGVzYykgewo+ICsJCWRldl9lcnIobmFuZGMtPmRldiwgImZhaWx1cmUgaW4gcHJlcCBkZXNjXG4i KTsKPiArCQlkbWFfdW5tYXBfc2cobmFuZGMtPmRldiwgc2dsLCBzZ2xfY250LCBkZXNjLT5kaXIp Owo+ICsJCWtmcmVlKGRlc2MpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCWRl c2MtPmRtYV9kZXNjID0gZG1hX2Rlc2M7Cj4gKwo+ICsJLyogdXBkYXRlIGxhc3QgZGF0YS9jb21t YW5kIGRlc2NyaXB0b3IgKi8KPiArCWlmIChjaGFuID09IG5hbmRjLT5jbWRfY2hhbikKPiArCQli YW1fdHhuLT5sYXN0X2NtZF9kZXNjID0gZG1hX2Rlc2M7Cj4gKwllbHNlCj4gKwkJYmFtX3R4bi0+ bGFzdF9kYXRhX2Rlc2MgPSBkbWFfZGVzYzsKPiArCj4gKwlsaXN0X2FkZF90YWlsKCZkZXNjLT5u b2RlLCAmbmFuZGMtPmRlc2NfbGlzdCk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArRVhQT1JU X1NZTUJPTChwcmVwYXJlX2JhbV9hc3luY19kZXNjKTsKPiArCj4gKy8qCj4gKyAqIFByZXBhcmVz IHRoZSBjb21tYW5kIGRlc2NyaXB0b3IgZm9yIEJBTSBETUEgd2hpY2ggd2lsbCBiZSB1c2VkIGZv ciBOQU5ECj4gKyAqIHJlZ2lzdGVyIHJlYWRzIGFuZCB3cml0ZXMuIFRoZSBjb21tYW5kIGRlc2Ny aXB0b3IgcmVxdWlyZXMgdGhlIGNvbW1hbmQKPiArICogdG8gYmUgZm9ybWVkIGluIGNvbW1hbmQg ZWxlbWVudCB0eXBlIHNvIHRoaXMgZnVuY3Rpb24gdXNlcyB0aGUgY29tbWFuZAo+ICsgKiBlbGVt ZW50IGZyb20gYmFtIHRyYW5zYWN0aW9uIGNlIGFycmF5IGFuZCBmaWxscyB0aGUgc2FtZSB3aXRo IHJlcXVpcmVkCgpjZT8KCj4gKyAqIGRhdGEuIEEgc2luZ2xlIFNHTCBjYW4gY29udGFpbiBtdWx0 aXBsZSBjb21tYW5kIGVsZW1lbnRzIHNvCj4gKyAqIE5BTkRfQkFNX05FWFRfU0dMIHdpbGwgYmUg dXNlZCBmb3Igc3RhcnRpbmcgdGhlIHNlcGFyYXRlIFNHTAo+ICsgKiBhZnRlciB0aGUgY3VycmVu dCBjb21tYW5kIGVsZW1lbnQuCj4gKyAqLwo+ICtpbnQgcHJlcF9iYW1fZG1hX2Rlc2NfY21kKHN0 cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqbmFuZGMsIGJvb2wgcmVhZCwKPiArCQkJCSBpbnQg cmVnX29mZiwgY29uc3Qgdm9pZCAqdmFkZHIsCj4gKwkJCQkgaW50IHNpemUsIHVuc2lnbmVkIGlu dCBmbGFncykKPiArewo+ICsJaW50IGJhbV9jZV9zaXplOwo+ICsJaW50IGksIHJldDsKPiArCXN0 cnVjdCBiYW1fY21kX2VsZW1lbnQgKmJhbV9jZV9idWZmZXI7Cj4gKwlzdHJ1Y3QgYmFtX3RyYW5z YWN0aW9uICpiYW1fdHhuID0gbmFuZGMtPmJhbV90eG47Cj4gKwo+ICsJYmFtX2NlX2J1ZmZlciA9 ICZiYW1fdHhuLT5iYW1fY2VbYmFtX3R4bi0+YmFtX2NlX3Bvc107Cj4gKwo+ICsJLyogZmlsbCB0 aGUgY29tbWFuZCBkZXNjICovCj4gKwlmb3IgKGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7Cj4gKwkJ aWYgKHJlYWQpCj4gKwkJCWJhbV9wcmVwX2NlKCZiYW1fY2VfYnVmZmVyW2ldLAo+ICsJCQkJICAg IG5hbmRjX3JlZ19waHlzKG5hbmRjLCByZWdfb2ZmICsgNCAqIGkpLAo+ICsJCQkJICAgIEJBTV9S RUFEX0NPTU1BTkQsCj4gKwkJCQkgICAgcmVnX2J1Zl9kbWFfYWRkcihuYW5kYywKPiArCQkJCQkJ ICAgICAoX19sZTMyICopdmFkZHIgKyBpKSk7Cj4gKwkJZWxzZQo+ICsJCQliYW1fcHJlcF9jZV9s ZTMyKCZiYW1fY2VfYnVmZmVyW2ldLAo+ICsJCQkJCSBuYW5kY19yZWdfcGh5cyhuYW5kYywgcmVn X29mZiArIDQgKiBpKSwKPiArCQkJCQkgQkFNX1dSSVRFX0NPTU1BTkQsCj4gKwkJCQkJICooKF9f bGUzMiAqKXZhZGRyICsgaSkpOwoKVGhlIF9sZSBoYW5kbGluZyBsb29rcyByZWFsbHkgZnJhZ2ls ZS4KCj4gKwl9Cj4gKwo+ICsJYmFtX3R4bi0+YmFtX2NlX3BvcyArPSBzaXplOwo+ICsKPiArCS8q IHVzZSB0aGUgc2VwYXJhdGUgc2dsIGFmdGVyIHRoaXMgY29tbWFuZCAqLwo+ICsJaWYgKGZsYWdz ICYgTkFORF9CQU1fTkVYVF9TR0wpIHsKPiArCQliYW1fY2VfYnVmZmVyID0gJmJhbV90eG4tPmJh bV9jZVtiYW1fdHhuLT5iYW1fY2Vfc3RhcnRdOwo+ICsJCWJhbV9jZV9zaXplID0gKGJhbV90eG4t PmJhbV9jZV9wb3MgLQo+ICsJCQkJYmFtX3R4bi0+YmFtX2NlX3N0YXJ0KSAqCj4gKwkJCQlzaXpl b2Yoc3RydWN0IGJhbV9jbWRfZWxlbWVudCk7Cj4gKwkJc2dfc2V0X2J1ZigmYmFtX3R4bi0+Y21k X3NnbFtiYW1fdHhuLT5jbWRfc2dsX3Bvc10sCj4gKwkJCSAgIGJhbV9jZV9idWZmZXIsIGJhbV9j ZV9zaXplKTsKPiArCQliYW1fdHhuLT5jbWRfc2dsX3BvcysrOwo+ICsJCWJhbV90eG4tPmJhbV9j ZV9zdGFydCA9IGJhbV90eG4tPmJhbV9jZV9wb3M7Cj4gKwo+ICsJCWlmIChmbGFncyAmIE5BTkRf QkFNX05XRCkgewo+ICsJCQlyZXQgPSBwcmVwYXJlX2JhbV9hc3luY19kZXNjKG5hbmRjLCBuYW5k Yy0+Y21kX2NoYW4sCj4gKwkJCQkJCSAgICAgRE1BX1BSRVBfRkVOQ0UgfAo+ICsJCQkJCQkgICAg IERNQV9QUkVQX0NNRCk7Cj4gKwkJCWlmIChyZXQpCj4gKwkJCQlyZXR1cm4gcmV0Owo+ICsJCX0K PiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICtFWFBPUlRfU1lNQk9MKHByZXBfYmFtX2Rt YV9kZXNjX2NtZCk7Cj4gKwo+ICsvKgo+ICsgKiBQcmVwYXJlcyB0aGUgZGF0YSBkZXNjcmlwdG9y IGZvciBCQU0gRE1BIHdoaWNoIHdpbGwgYmUgdXNlZCBmb3IgTkFORAo+ICsgKiBkYXRhIHJlYWRz IGFuZCB3cml0ZXMuCj4gKyAqLwo+ICtpbnQgcHJlcF9iYW1fZG1hX2Rlc2NfZGF0YShzdHJ1Y3Qg cWNvbV9uYW5kX2NvbnRyb2xsZXIgKm5hbmRjLCBib29sIHJlYWQsCj4gKwkJCQkgIGNvbnN0IHZv aWQgKnZhZGRyLAo+ICsJCQkJICBpbnQgc2l6ZSwgdW5zaWduZWQgaW50IGZsYWdzKQo+ICt7Cj4g KwlpbnQgcmV0Owo+ICsJc3RydWN0IGJhbV90cmFuc2FjdGlvbiAqYmFtX3R4biA9IG5hbmRjLT5i YW1fdHhuOwo+ICsKPiArCWlmIChyZWFkKSB7Cj4gKwkJc2dfc2V0X2J1ZigmYmFtX3R4bi0+ZGF0 YV9zZ2xbYmFtX3R4bi0+cnhfc2dsX3Bvc10sCj4gKwkJCSAgIHZhZGRyLCBzaXplKTsKPiArCQli YW1fdHhuLT5yeF9zZ2xfcG9zKys7Cj4gKwl9IGVsc2Ugewo+ICsJCXNnX3NldF9idWYoJmJhbV90 eG4tPmRhdGFfc2dsW2JhbV90eG4tPnR4X3NnbF9wb3NdLAo+ICsJCQkgICB2YWRkciwgc2l6ZSk7 Cj4gKwkJYmFtX3R4bi0+dHhfc2dsX3BvcysrOwo+ICsKPiArCQkvKgo+ICsJCSAqIEJBTSB3aWxs IG9ubHkgc2V0IEVPVCBmb3IgRE1BX1BSRVBfSU5URVJSVVBUIHNvIGlmIHRoaXMgZmxhZwo+ICsJ CSAqIGlzIG5vdCBzZXQsIGZvcm0gdGhlIERNQSBkZXNjcmlwdG9yCj4gKwkJICovCj4gKwkJaWYg KCEoZmxhZ3MgJiBOQU5EX0JBTV9OT19FT1QpKSB7Cj4gKwkJCXJldCA9IHByZXBhcmVfYmFtX2Fz eW5jX2Rlc2MobmFuZGMsIG5hbmRjLT50eF9jaGFuLAo+ICsJCQkJCQkgICAgIERNQV9QUkVQX0lO VEVSUlVQVCk7Cj4gKwkJCWlmIChyZXQpCj4gKwkJCQlyZXR1cm4gcmV0Owo+ICsJCX0KPiArCX0K PiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICtFWFBPUlRfU1lNQk9MKHByZXBfYmFtX2RtYV9kZXNj X2RhdGEpOwo+ICsKPiArLyoKPiArICogcmVhZF9yZWdfZG1hOglwcmVwYXJlcyBhIGRlc2NyaXB0 b3IgdG8gcmVhZCBhIGdpdmVuIG51bWJlciBvZgo+ICsgKgkJCWNvbnRpZ3VvdXMgcmVnaXN0ZXJz IHRvIHRoZSByZWdfcmVhZF9idWYgcG9pbnRlcgo+ICsgKgo+ICsgKiBAZmlyc3Q6CQlvZmZzZXQg b2YgdGhlIGZpcnN0IHJlZ2lzdGVyIGluIHRoZSBjb250aWd1b3VzIGJsb2NrCj4gKyAqIEBudW1f cmVnczoJCW51bWJlciBvZiByZWdpc3RlcnMgdG8gcmVhZAo+ICsgKiBAZmxhZ3M6CQlmbGFncyB0 byBjb250cm9sIERNQSBkZXNjcmlwdG9yIHByZXBhcmF0aW9uCj4gKyAqLwo+ICtpbnQgcmVhZF9y ZWdfZG1hKHN0cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqbmFuZGMsIGludCBmaXJzdCwKPiAr CQkJaW50IG51bV9yZWdzLCB1bnNpZ25lZCBpbnQgZmxhZ3MpCj4gK3sKPiArCWJvb2wgZmxvd19j b250cm9sID0gZmFsc2U7Cj4gKwl2b2lkICp2YWRkcjsKPiArCj4gKwl2YWRkciA9IG5hbmRjLT5y ZWdfcmVhZF9idWYgKyBuYW5kYy0+cmVnX3JlYWRfcG9zOwo+ICsJbmFuZGMtPnJlZ19yZWFkX3Bv cyArPSBudW1fcmVnczsKPiArCj4gKwlpZiAoZmlyc3QgPT0gTkFORF9ERVZfQ01EX1ZMRCB8fCBm aXJzdCA9PSBOQU5EX0RFVl9DTUQxKQo+ICsJCWZpcnN0ID0gZGV2X2NtZF9yZWdfYWRkcihuYW5k YywgZmlyc3QpOwo+ICsKPiArCWlmIChuYW5kYy0+cHJvcHMtPmlzX2JhbSkKPiArCQlyZXR1cm4g cHJlcF9iYW1fZG1hX2Rlc2NfY21kKG5hbmRjLCB0cnVlLCBmaXJzdCwgdmFkZHIsCj4gKwkJCQkJ ICAgICBudW1fcmVncywgZmxhZ3MpOwo+ICsKPiArCWlmIChmaXJzdCA9PSBOQU5EX1JFQURfSUQg fHwgZmlyc3QgPT0gTkFORF9GTEFTSF9TVEFUVVMpCj4gKwkJZmxvd19jb250cm9sID0gdHJ1ZTsK ClRoaXMgZmxvd19jb250cm9sIHByb3BlcnR5IHJlYWxseSBib3RoZXJzIG1lLgoKPiArCj4gKwly ZXR1cm4gcHJlcF9hZG1fZG1hX2Rlc2MobmFuZGMsIHRydWUsIGZpcnN0LCB2YWRkciwKPiArCQkJ CSBudW1fcmVncyAqIHNpemVvZih1MzIpLCBmbG93X2NvbnRyb2wpOwo+ICt9Cj4gK0VYUE9SVF9T WU1CT0wocmVhZF9yZWdfZG1hKTsKPiArCj4gKy8qCj4gKyAqIHdyaXRlX3JlZ19kbWE6CXByZXBh cmVzIGEgZGVzY3JpcHRvciB0byB3cml0ZSBhIGdpdmVuIG51bWJlciBvZgo+ICsgKgkJCWNvbnRp Z3VvdXMgcmVnaXN0ZXJzCj4gKyAqCj4gKyAqIEBmaXJzdDoJCW9mZnNldCBvZiB0aGUgZmlyc3Qg cmVnaXN0ZXIgaW4gdGhlIGNvbnRpZ3VvdXMgYmxvY2sKPiArICogQG51bV9yZWdzOgkJbnVtYmVy IG9mIHJlZ2lzdGVycyB0byB3cml0ZQo+ICsgKiBAZmxhZ3M6CQlmbGFncyB0byBjb250cm9sIERN QSBkZXNjcmlwdG9yIHByZXBhcmF0aW9uCj4gKyAqLwo+ICtpbnQgd3JpdGVfcmVnX2RtYShzdHJ1 Y3QgcWNvbV9uYW5kX2NvbnRyb2xsZXIgKm5hbmRjLCBpbnQgZmlyc3QsCj4gKwkJCSBpbnQgbnVt X3JlZ3MsIHVuc2lnbmVkIGludCBmbGFncykKPiArewo+ICsJYm9vbCBmbG93X2NvbnRyb2wgPSBm YWxzZTsKPiArCXN0cnVjdCBuYW5kY19yZWdzICpyZWdzID0gbmFuZGMtPnJlZ3M7Cj4gKwl2b2lk ICp2YWRkcjsKPiArCj4gKwl2YWRkciA9IG9mZnNldF90b19uYW5kY19yZWcocmVncywgZmlyc3Qp Owo+ICsKPiArCWlmIChmaXJzdCA9PSBOQU5EX0VSQVNFRF9DV19ERVRFQ1RfQ0ZHKSB7Cj4gKwkJ aWYgKGZsYWdzICYgTkFORF9FUkFTRURfQ1dfU0VUKQo+ICsJCQl2YWRkciA9ICZyZWdzLT5lcmFz ZWRfY3dfZGV0ZWN0X2NmZ19zZXQ7Cj4gKwkJZWxzZQo+ICsJCQl2YWRkciA9ICZyZWdzLT5lcmFz ZWRfY3dfZGV0ZWN0X2NmZ19jbHI7Cj4gKwl9Cj4gKwo+ICsJaWYgKGZpcnN0ID09IE5BTkRfRVhF Q19DTUQpCj4gKwkJZmxhZ3MgfD0gTkFORF9CQU1fTldEOwo+ICsKPiArCWlmIChmaXJzdCA9PSBO QU5EX0ZMQVNIX1NQSV9DRkcgfHwgZmlyc3QgPT0gTkFORF9OVU1fQUREUl9DWUNMRVMKPiArCQl8 fCBmaXJzdCA9PSBOQU5EX0JVU1lfQ0hFQ0tfV0FJVF9DTlQKPiArCQl8fCBmaXJzdCA9PSBOQU5E X01TVFJfQ09ORklHKQo+ICsJCWZpcnN0ID0gZGV2X2NtZF9yZWdfYWRkcihuYW5kYywgZmlyc3Qp Owo+ICsKPiArCWlmIChmaXJzdCA9PSBOQU5EX0RFVl9DTUQxX1JFU1RPUkUgfHwgZmlyc3QgPT0g TkFORF9ERVZfQ01EMSkKPiArCQlmaXJzdCA9IGRldl9jbWRfcmVnX2FkZHIobmFuZGMsIE5BTkRf REVWX0NNRDEpOwo+ICsKPiArCWlmIChmaXJzdCA9PSBOQU5EX0RFVl9DTURfVkxEX1JFU1RPUkUg fHwgZmlyc3QgPT0gTkFORF9ERVZfQ01EX1ZMRCkKPiArCQlmaXJzdCA9IGRldl9jbWRfcmVnX2Fk ZHIobmFuZGMsIE5BTkRfREVWX0NNRF9WTEQpOwo+ICsKCldoYXQgYWJvdXQgYSBzd2l0Y2ggY2Fz ZSBoZXJlPwoKPiArCWlmIChuYW5kYy0+cHJvcHMtPmlzX2JhbSkKPiArCQlyZXR1cm4gcHJlcF9i YW1fZG1hX2Rlc2NfY21kKG5hbmRjLCBmYWxzZSwgZmlyc3QsIHZhZGRyLAo+ICsJCQkJCSAgICAg bnVtX3JlZ3MsIGZsYWdzKTsKPiArCj4gKwlpZiAoZmlyc3QgPT0gTkFORF9GTEFTSF9DTUQpCj4g KwkJZmxvd19jb250cm9sID0gdHJ1ZTsKPiArCj4gKwlyZXR1cm4gcHJlcF9hZG1fZG1hX2Rlc2Mo bmFuZGMsIGZhbHNlLCBmaXJzdCwgdmFkZHIsCj4gKwkJCQkgbnVtX3JlZ3MgKiBzaXplb2YodTMy KSwgZmxvd19jb250cm9sKTsKPiArfQo+ICtFWFBPUlRfU1lNQk9MKHdyaXRlX3JlZ19kbWEpOwo+ ICsKPiArLyoKPiArICogcmVhZF9kYXRhX2RtYToJcHJlcGFyZXMgYSBETUEgZGVzY3JpcHRvciB0 byB0cmFuc2ZlciBkYXRhIGZyb20gdGhlCj4gKyAqCQkJY29udHJvbGxlcidzIGludGVybmFsIGJ1 ZmZlciB0byB0aGUgYnVmZmVyICd2YWRkcicKPiArICoKPiArICogQHJlZ19vZmY6CQlvZmZzZXQg d2l0aGluIHRoZSBjb250cm9sbGVyJ3MgZGF0YSBidWZmZXIKPiArICogQHZhZGRyOgkJdmlydHVh bCBhZGRyZXNzIG9mIHRoZSBidWZmZXIgd2Ugd2FudCB0byB3cml0ZSB0bwo+ICsgKiBAc2l6ZToJ CURNQSB0cmFuc2FjdGlvbiBzaXplIGluIGJ5dGVzCj4gKyAqIEBmbGFnczoJCWZsYWdzIHRvIGNv bnRyb2wgRE1BIGRlc2NyaXB0b3IgcHJlcGFyYXRpb24KPiArICovCj4gK2ludCByZWFkX2RhdGFf ZG1hKHN0cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqbmFuZGMsIGludCByZWdfb2ZmLAo+ICsJ CQkgY29uc3QgdTggKnZhZGRyLCBpbnQgc2l6ZSwgdW5zaWduZWQgaW50IGZsYWdzKQo+ICt7Cj4g KwlpZiAobmFuZGMtPnByb3BzLT5pc19iYW0pCj4gKwkJcmV0dXJuIHByZXBfYmFtX2RtYV9kZXNj X2RhdGEobmFuZGMsIHRydWUsIHZhZGRyLCBzaXplLCBmbGFncyk7Cj4gKwo+ICsJcmV0dXJuIHBy ZXBfYWRtX2RtYV9kZXNjKG5hbmRjLCB0cnVlLCByZWdfb2ZmLCB2YWRkciwgc2l6ZSwgZmFsc2Up Owo+ICt9Cj4gK0VYUE9SVF9TWU1CT0wocmVhZF9kYXRhX2RtYSk7Cj4gKwo+ICsvKgo+ICsgKiB3 cml0ZV9kYXRhX2RtYToJcHJlcGFyZXMgYSBETUEgZGVzY3JpcHRvciB0byB0cmFuc2ZlciBkYXRh IGZyb20KPiArICoJCQkndmFkZHInIHRvIHRoZSBjb250cm9sbGVyJ3MgaW50ZXJuYWwgYnVmZmVy Cj4gKyAqCj4gKyAqIEByZWdfb2ZmOgkJb2Zmc2V0IHdpdGhpbiB0aGUgY29udHJvbGxlcidzIGRh dGEgYnVmZmVyCj4gKyAqIEB2YWRkcjoJCXZpcnR1YWwgYWRkcmVzcyBvZiB0aGUgYnVmZmVyIHdl IHdhbnQgdG8gcmVhZCBmcm9tCj4gKyAqIEBzaXplOgkJRE1BIHRyYW5zYWN0aW9uIHNpemUgaW4g Ynl0ZXMKPiArICogQGZsYWdzOgkJZmxhZ3MgdG8gY29udHJvbCBETUEgZGVzY3JpcHRvciBwcmVw YXJhdGlvbgo+ICsgKi8KPiAraW50IHdyaXRlX2RhdGFfZG1hKHN0cnVjdCBxY29tX25hbmRfY29u dHJvbGxlciAqbmFuZGMsIGludCByZWdfb2ZmLAo+ICsJCQkgIGNvbnN0IHU4ICp2YWRkciwgaW50 IHNpemUsIHVuc2lnbmVkIGludCBmbGFncykKPiArewo+ICsJaWYgKG5hbmRjLT5wcm9wcy0+aXNf YmFtKQo+ICsJCXJldHVybiBwcmVwX2JhbV9kbWFfZGVzY19kYXRhKG5hbmRjLCBmYWxzZSwgdmFk ZHIsIHNpemUsIGZsYWdzKTsKPiArCj4gKwlyZXR1cm4gcHJlcF9hZG1fZG1hX2Rlc2MobmFuZGMs IGZhbHNlLCByZWdfb2ZmLCB2YWRkciwgc2l6ZSwgZmFsc2UpOwo+ICt9Cj4gK0VYUE9SVF9TWU1C T0wod3JpdGVfZGF0YV9kbWEpOwo+ICsKPiArdm9pZCBuYW5kY19zZXRfcmVnKHN0cnVjdCBxY29t X25hbmRfY29udHJvbGxlciAqbmFuZGMsIGludCBvZmZzZXQsCj4gKwkJCSAgdTMyIHZhbCkKPiAr ewo+ICsJc3RydWN0IG5hbmRjX3JlZ3MgKnJlZ3MgPSBuYW5kYy0+cmVnczsKPiArCV9fbGUzMiAq cmVnOwo+ICsKPiArCXJlZyA9IG9mZnNldF90b19uYW5kY19yZWcocmVncywgb2Zmc2V0KTsKPiAr CWlmIChyZWcpCj4gKwkJKnJlZyA9IGNwdV90b19sZTMyKHZhbCk7Cj4gK30KPiArRVhQT1JUX1NZ TUJPTChuYW5kY19zZXRfcmVnKTsKPiArCj4gKy8qIEFsbG9jYXRlcyBhbmQgSW5pdGlhbGl6ZXMg dGhlIEJBTSB0cmFuc2FjdGlvbiAqLwo+ICtzdHJ1Y3QgYmFtX3RyYW5zYWN0aW9uICoKPiArYWxs b2NfYmFtX3RyYW5zYWN0aW9uKHN0cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqbmFuZGMpCj4g K3sKPiArCXN0cnVjdCBiYW1fdHJhbnNhY3Rpb24gKmJhbV90eG47Cj4gKwlzaXplX3QgYmFtX3R4 bl9zaXplOwo+ICsJdW5zaWduZWQgaW50IG51bV9jdyA9IG5hbmRjLT5tYXhfY3dwZXJwYWdlOwo+ ICsJdm9pZCAqYmFtX3R4bl9idWY7Cj4gKwo+ICsJYmFtX3R4bl9zaXplID0KPiArCQlzaXplb2Yo KmJhbV90eG4pICsgbnVtX2N3ICoKPiArCQkoKHNpemVvZigqYmFtX3R4bi0+YmFtX2NlKSAqIFFQ SUNfUEVSX0NXX0NNRF9FTEVNRU5UUykgKwo+ICsJCShzaXplb2YoKmJhbV90eG4tPmNtZF9zZ2wp ICogUVBJQ19QRVJfQ1dfQ01EX1NHTCkgKwo+ICsJCShzaXplb2YoKmJhbV90eG4tPmRhdGFfc2ds KSAqIFFQSUNfUEVSX0NXX0RBVEFfU0dMKSk7Cj4gKwo+ICsJYmFtX3R4bl9idWYgPSBkZXZtX2t6 YWxsb2MobmFuZGMtPmRldiwgYmFtX3R4bl9zaXplLCBHRlBfS0VSTkVMKTsKPiArCWlmICghYmFt X3R4bl9idWYpCj4gKwkJcmV0dXJuIE5VTEw7Cj4gKwo+ICsJYmFtX3R4biA9IGJhbV90eG5fYnVm Owo+ICsJYmFtX3R4bl9idWYgKz0gc2l6ZW9mKCpiYW1fdHhuKTsKPiArCj4gKwliYW1fdHhuLT5i YW1fY2UgPSBiYW1fdHhuX2J1ZjsKPiArCWJhbV90eG5fYnVmICs9Cj4gKwkJc2l6ZW9mKCpiYW1f dHhuLT5iYW1fY2UpICogUVBJQ19QRVJfQ1dfQ01EX0VMRU1FTlRTICogbnVtX2N3Owo+ICsKPiAr CWJhbV90eG4tPmNtZF9zZ2wgPSBiYW1fdHhuX2J1ZjsKPiArCWJhbV90eG5fYnVmICs9Cj4gKwkJ c2l6ZW9mKCpiYW1fdHhuLT5jbWRfc2dsKSAqIFFQSUNfUEVSX0NXX0NNRF9TR0wgKiBudW1fY3c7 Cj4gKwo+ICsJYmFtX3R4bi0+ZGF0YV9zZ2wgPSBiYW1fdHhuX2J1ZjsKPiArCj4gKwlpbml0X2Nv bXBsZXRpb24oJmJhbV90eG4tPnR4bl9kb25lKTsKPiArCj4gKwlyZXR1cm4gYmFtX3R4bjsKPiAr fQo+ICtFWFBPUlRfU1lNQk9MKGFsbG9jX2JhbV90cmFuc2FjdGlvbik7Cj4gKwo+ICsvKiBDbGVh cnMgdGhlIEJBTSB0cmFuc2FjdGlvbiBpbmRleGVzICovCj4gK3ZvaWQgY2xlYXJfYmFtX3RyYW5z YWN0aW9uKHN0cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqbmFuZGMpCj4gK3sKPiArCXN0cnVj dCBiYW1fdHJhbnNhY3Rpb24gKmJhbV90eG4gPSBuYW5kYy0+YmFtX3R4bjsKPiArCj4gKwlpZiAo IW5hbmRjLT5wcm9wcy0+aXNfYmFtKQo+ICsJCXJldHVybjsKPiArCj4gKwliYW1fdHhuLT5iYW1f Y2VfcG9zID0gMDsKPiArCWJhbV90eG4tPmJhbV9jZV9zdGFydCA9IDA7Cj4gKwliYW1fdHhuLT5j bWRfc2dsX3BvcyA9IDA7Cj4gKwliYW1fdHhuLT5jbWRfc2dsX3N0YXJ0ID0gMDsKPiArCWJhbV90 eG4tPnR4X3NnbF9wb3MgPSAwOwo+ICsJYmFtX3R4bi0+dHhfc2dsX3N0YXJ0ID0gMDsKPiArCWJh bV90eG4tPnJ4X3NnbF9wb3MgPSAwOwo+ICsJYmFtX3R4bi0+cnhfc2dsX3N0YXJ0ID0gMDsKPiAr CWJhbV90eG4tPmxhc3RfZGF0YV9kZXNjID0gTlVMTDsKPiArCWJhbV90eG4tPndhaXRfc2Vjb25k X2NvbXBsZXRpb24gPSBmYWxzZTsKPiArCj4gKwlzZ19pbml0X3RhYmxlKGJhbV90eG4tPmNtZF9z Z2wsIG5hbmRjLT5tYXhfY3dwZXJwYWdlICoKPiArCQkgICAgICBRUElDX1BFUl9DV19DTURfU0dM KTsKPiArCXNnX2luaXRfdGFibGUoYmFtX3R4bi0+ZGF0YV9zZ2wsIG5hbmRjLT5tYXhfY3dwZXJw YWdlICoKPiArCQkgICAgICBRUElDX1BFUl9DV19EQVRBX1NHTCk7Cj4gKwo+ICsJcmVpbml0X2Nv bXBsZXRpb24oJmJhbV90eG4tPnR4bl9kb25lKTsKPiArfQo+ICtFWFBPUlRfU1lNQk9MKGNsZWFy X2JhbV90cmFuc2FjdGlvbik7Cj4gKwo+ICsvKiBvbmUgdGltZSBzZXR1cCBvZiBhIGZldyBuYW5k IGNvbnRyb2xsZXIgcmVnaXN0ZXJzICovCgpEb2VzIHRoaXMgbmVlZHMgdG8gYmUgc2hhcmVkPwoK PiAraW50IHFjb21fbmFuZGNfc2V0dXAoc3RydWN0IHFjb21fbmFuZF9jb250cm9sbGVyICpuYW5k YykKPiArewo+ICsJdTMyIG5hbmRfY3RybDsKPiArCj4gKwkvKiBraWxsIG9uZW5hbmQgKi8KPiAr CWlmICghbmFuZGMtPnByb3BzLT5pc19xcGljKQo+ICsJCW5hbmRjX3dyaXRlKG5hbmRjLCBTRkxB U0hDX0JVUlNUX0NGRywgMCk7Cj4gKwo+ICsJaWYgKCFuYW5kYy0+cHJvcHMtPnFwaWNfdjIpCj4g KwkJbmFuZGNfd3JpdGUobmFuZGMsIGRldl9jbWRfcmVnX2FkZHIobmFuZGMsIE5BTkRfREVWX0NN RF9WTEQpLAo+ICsJCQkgICAgTkFORF9ERVZfQ01EX1ZMRF9WQUwpOwo+ICsKPiArCS8qIGVuYWJs ZSBBRE0gb3IgQkFNIERNQSAqLwo+ICsJaWYgKG5hbmRjLT5wcm9wcy0+aXNfYmFtKSB7Cj4gKwkJ bmFuZF9jdHJsID0gbmFuZGNfcmVhZChuYW5kYywgTkFORF9DVFJMKTsKPiArCj4gKwkJLyoKPiAr CQkgKk5BTkRfQ1RSTCBpcyBhbiBvcGVyYXRpb25hbCByZWdpc3RlcnMsIGFuZCBDUFUKPiArCQkg KiBhY2Nlc3MgdG8gb3BlcmF0aW9uYWwgcmVnaXN0ZXJzIGFyZSByZWFkIG9ubHkKPiArCQkgKiBp biBCQU0gbW9kZS4gU28gdXBkYXRlIHRoZSBOQU5EX0NUUkwgcmVnaXN0ZXIKPiArCQkgKiBvbmx5 IGlmIGl0IGlzIG5vdCBpbiBCQU0gbW9kZS4gSW4gbW9zdCBjYXNlcyBCQU0KPiArCQkgKiBtb2Rl IHdpbGwgYmUgZW5hYmxlZCBpbiBib290bG9hZGVyCj4gKwkJICovCj4gKwkJaWYgKCEobmFuZF9j dHJsICYgQkFNX01PREVfRU4pKQo+ICsJCQluYW5kY193cml0ZShuYW5kYywgTkFORF9DVFJMLCBu YW5kX2N0cmwgfCBCQU1fTU9ERV9FTik7Cj4gKwl9IGVsc2Ugewo+ICsJCW5hbmRjX3dyaXRlKG5h bmRjLCBOQU5EX0ZMQVNIX0NISVBfU0VMRUNULCBETV9FTik7Cj4gKwl9Cj4gKwo+ICsJLyogc2F2 ZSB0aGUgb3JpZ2luYWwgdmFsdWVzIG9mIHRoZXNlIHJlZ2lzdGVycyAqLwo+ICsJaWYgKCFuYW5k Yy0+cHJvcHMtPnFwaWNfdjIpIHsKPiArCQluYW5kYy0+Y21kMSA9IG5hbmRjX3JlYWQobmFuZGMs IGRldl9jbWRfcmVnX2FkZHIobmFuZGMsIE5BTkRfREVWX0NNRDEpKTsKPiArCQluYW5kYy0+dmxk ID0gTkFORF9ERVZfQ01EX1ZMRF9WQUw7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiAr RVhQT1JUX1NZTUJPTChxY29tX25hbmRjX3NldHVwKTsKPiArCj4gK3ZvaWQgcWNvbV9uYW5kY191 bmFsbG9jKHN0cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqbmFuZGMpCj4gK3sKPiArCWlmIChu YW5kYy0+cHJvcHMtPmlzX2JhbSkgewo+ICsJCWlmICghZG1hX21hcHBpbmdfZXJyb3IobmFuZGMt PmRldiwgbmFuZGMtPnJlZ19yZWFkX2RtYSkpCj4gKwkJCWRtYV91bm1hcF9zaW5nbGUobmFuZGMt PmRldiwgbmFuZGMtPnJlZ19yZWFkX2RtYSwKPiArCQkJCQkgTUFYX1JFR19SRCAqCj4gKwkJCQkJ IHNpemVvZigqbmFuZGMtPnJlZ19yZWFkX2J1ZiksCj4gKwkJCQkJIERNQV9GUk9NX0RFVklDRSk7 Cj4gKwo+ICsJCWlmIChuYW5kYy0+dHhfY2hhbikKPiArCQkJZG1hX3JlbGVhc2VfY2hhbm5lbChu YW5kYy0+dHhfY2hhbik7Cj4gKwo+ICsJCWlmIChuYW5kYy0+cnhfY2hhbikKPiArCQkJZG1hX3Jl bGVhc2VfY2hhbm5lbChuYW5kYy0+cnhfY2hhbik7Cj4gKwo+ICsJCWlmIChuYW5kYy0+Y21kX2No YW4pCj4gKwkJCWRtYV9yZWxlYXNlX2NoYW5uZWwobmFuZGMtPmNtZF9jaGFuKTsKPiArCX0gZWxz ZSB7Cj4gKwkJaWYgKG5hbmRjLT5jaGFuKQo+ICsJCQlkbWFfcmVsZWFzZV9jaGFubmVsKG5hbmRj LT5jaGFuKTsKPiArCX0KPiArfQo+ICtFWFBPUlRfU1lNQk9MKHFjb21fbmFuZGNfdW5hbGxvYyk7 Cj4gKwo+ICtpbnQgcWNvbV9uYW5kY19hbGxvYyhzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRyb2xsZXIg Km5hbmRjKQo+ICt7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXJldCA9IGRtYV9zZXRfY29oZXJlbnRf bWFzayhuYW5kYy0+ZGV2LCBETUFfQklUX01BU0soMzIpKTsKPiArCWlmIChyZXQpIHsKPiArCQlk ZXZfZXJyKG5hbmRjLT5kZXYsICJmYWlsZWQgdG8gc2V0IERNQSBtYXNrXG4iKTsKPiArCQlyZXR1 cm4gcmV0Owo+ICsJfQo+ICsKPiArCS8qCj4gKwkgKiB3ZSB1c2UgdGhlIGludGVybmFsIGJ1ZmZl ciBmb3IgcmVhZGluZyBPTkZJIHBhcmFtcywgcmVhZGluZyBzbWFsbAo+ICsJICogZGF0YSBsaWtl IElEIGFuZCBzdGF0dXMsIGFuZCBwcmVmb3JtaW5nIHJlYWQtY29weS13cml0ZSBvcGVyYXRpb25z CgpwZXJmb3JtaW5nCgpQbGVhc2UgcnVuIGNoZWNrcGF0Y2gucGwsIEkgYmVsaWV2ZSB0aGUgdG9v bCBzaG91bGQgY2F0Y2ggdGhlc2UuCgo+ICsJICogd2hlbiB3cml0aW5nIHRvIGEgY29kZXdvcmQg cGFydGlhbGx5LiA1MzIgaXMgdGhlIG1heGltdW0gcG9zc2libGUKPiArCSAqIHNpemUgb2YgYSBj b2Rld29yZCBmb3Igb3VyIG5hbmQgY29udHJvbGxlcgo+ICsJICovCj4gKwluYW5kYy0+YnVmX3Np emUgPSA1MzI7Cj4gKwo+ICsJbmFuZGMtPmRhdGFfYnVmZmVyID0gZGV2bV9remFsbG9jKG5hbmRj LT5kZXYsIG5hbmRjLT5idWZfc2l6ZSwKPiArCQkJCQlHRlBfS0VSTkVMKTsKPiArCWlmICghbmFu ZGMtPmRhdGFfYnVmZmVyKQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCW5hbmRjLT5yZWdz ID0gZGV2bV9remFsbG9jKG5hbmRjLT5kZXYsIHNpemVvZigqbmFuZGMtPnJlZ3MpLAo+ICsJCQkJ CUdGUF9LRVJORUwpOwo+ICsJaWYgKCFuYW5kYy0+cmVncykKPiArCQlyZXR1cm4gLUVOT01FTTsK PiArCj4gKwluYW5kYy0+cmVnX3JlYWRfYnVmID0gZGV2bV9rY2FsbG9jKG5hbmRjLT5kZXYsCj4g KwkJCQlNQVhfUkVHX1JELCBzaXplb2YoKm5hbmRjLT5yZWdfcmVhZF9idWYpLAo+ICsJCQkJR0ZQ X0tFUk5FTCk7Cj4gKwlpZiAoIW5hbmRjLT5yZWdfcmVhZF9idWYpCj4gKwkJcmV0dXJuIC1FTk9N RU07Cj4gKwo+ICsJaWYgKG5hbmRjLT5wcm9wcy0+aXNfYmFtKSB7CgpJdCdzIHByb2JhYmx5IHRo ZSAxMHRoIHRpbWUgSSBhc2ssIGJ1dCB3aGF0IHRoZSBoZWNrIGlzIHRoaXMgaXNfYmFtCnBhcmFt ZXRlciBzaG93aW5nPyBJdCBsb29rcyBsaWtlIHlvdSdyZSBoYW5kbGluZyB0d28gZGlmZmVyZW50 CmNvbnRyb2xsZXJzIGluIHRoZSBzYW1lIGRyaXZlciB3aXRob3V0IHVzaW5nIGRpZmZlcmVudCBj b21wYXRpYmxlcy4KCj4gKwkJbmFuZGMtPnJlZ19yZWFkX2RtYSA9Cj4gKwkJCWRtYV9tYXBfc2lu Z2xlKG5hbmRjLT5kZXYsIG5hbmRjLT5yZWdfcmVhZF9idWYsCj4gKwkJCQkgICAgICAgTUFYX1JF R19SRCAqCj4gKwkJCQkgICAgICAgc2l6ZW9mKCpuYW5kYy0+cmVnX3JlYWRfYnVmKSwKPiArCQkJ CSAgICAgICBETUFfRlJPTV9ERVZJQ0UpOwo+ICsJCWlmIChkbWFfbWFwcGluZ19lcnJvcihuYW5k Yy0+ZGV2LCBuYW5kYy0+cmVnX3JlYWRfZG1hKSkgewo+ICsJCQlkZXZfZXJyKG5hbmRjLT5kZXYs ICJmYWlsZWQgdG8gRE1BIE1BUCByZWcgYnVmZmVyXG4iKTsKPiArCQkJcmV0dXJuIC1FSU87Cj4g KwkJfQo+ICsKPiArCQluYW5kYy0+dHhfY2hhbiA9IGRtYV9yZXF1ZXN0X2NoYW4obmFuZGMtPmRl diwgInR4Iik7Cj4gKwkJaWYgKElTX0VSUihuYW5kYy0+dHhfY2hhbikpIHsKPiArCQkJcmV0ID0g UFRSX0VSUihuYW5kYy0+dHhfY2hhbik7Cj4gKwkJCW5hbmRjLT50eF9jaGFuID0gTlVMTDsKPiAr CQkJZGV2X2Vycl9wcm9iZShuYW5kYy0+ZGV2LCByZXQsCj4gKwkJCQkgICAgICAidHggRE1BIGNo YW5uZWwgcmVxdWVzdCBmYWlsZWRcbiIpOwo+ICsJCQlnb3RvIHVuYWxsb2M7Cj4gKwkJfQo+ICsK PiArCQluYW5kYy0+cnhfY2hhbiA9IGRtYV9yZXF1ZXN0X2NoYW4obmFuZGMtPmRldiwgInJ4Iik7 Cj4gKwkJaWYgKElTX0VSUihuYW5kYy0+cnhfY2hhbikpIHsKPiArCQkJcmV0ID0gUFRSX0VSUihu YW5kYy0+cnhfY2hhbik7Cj4gKwkJCW5hbmRjLT5yeF9jaGFuID0gTlVMTDsKPiArCQkJZGV2X2Vy cl9wcm9iZShuYW5kYy0+ZGV2LCByZXQsCj4gKwkJCQkgICAgICAicnggRE1BIGNoYW5uZWwgcmVx dWVzdCBmYWlsZWRcbiIpOwo+ICsJCQlnb3RvIHVuYWxsb2M7Cj4gKwkJfQo+ICsKPiArCQluYW5k Yy0+Y21kX2NoYW4gPSBkbWFfcmVxdWVzdF9jaGFuKG5hbmRjLT5kZXYsICJjbWQiKTsKPiArCQlp ZiAoSVNfRVJSKG5hbmRjLT5jbWRfY2hhbikpIHsKPiArCQkJcmV0ID0gUFRSX0VSUihuYW5kYy0+ Y21kX2NoYW4pOwo+ICsJCQluYW5kYy0+Y21kX2NoYW4gPSBOVUxMOwo+ICsJCQlkZXZfZXJyX3By b2JlKG5hbmRjLT5kZXYsIHJldCwKPiArCQkJCSAgICAgICJjbWQgRE1BIGNoYW5uZWwgcmVxdWVz dCBmYWlsZWRcbiIpOwo+ICsJCQlnb3RvIHVuYWxsb2M7Cj4gKwkJfQo+ICsKPiArCQkvKgo+ICsJ CSAqIEluaXRpYWxseSBhbGxvY2F0ZSBCQU0gdHJhbnNhY3Rpb24gdG8gcmVhZCBPTkZJIHBhcmFt IHBhZ2UuCj4gKwkJICogQWZ0ZXIgZGV0ZWN0aW5nIGFsbCB0aGUgZGV2aWNlcywgdGhpcyBCQU0g dHJhbnNhY3Rpb24gd2lsbAo+ICsJCSAqIGJlIGZyZWVkIGFuZCB0aGUgbmV4dCBCQU0gdHJhbmFz Y3Rpb24gd2lsbCBiZSBhbGxvY2F0ZWQgd2l0aAoKVHlwbwoKPiArCQkgKiBtYXhpbXVtIGNvZGV3 b3JkIHNpemUKPiArCQkgKi8KPiArCQluYW5kYy0+bWF4X2N3cGVycGFnZSA9IDE7Cj4gKwkJbmFu ZGMtPmJhbV90eG4gPSBhbGxvY19iYW1fdHJhbnNhY3Rpb24obmFuZGMpOwo+ICsJCWlmICghbmFu ZGMtPmJhbV90eG4pIHsKPiArCQkJZGV2X2VycihuYW5kYy0+ZGV2LAo+ICsJCQkJImZhaWxlZCB0 byBhbGxvY2F0ZSBiYW0gdHJhbnNhY3Rpb25cbiIpOwo+ICsJCQlyZXQgPSAtRU5PTUVNOwo+ICsJ CQlnb3RvIHVuYWxsb2M7Cj4gKwkJfQo+ICsJfSBlbHNlIHsKPiArCQluYW5kYy0+Y2hhbiA9IGRt YV9yZXF1ZXN0X2NoYW4obmFuZGMtPmRldiwgInJ4dHgiKTsKPiArCQlpZiAoSVNfRVJSKG5hbmRj LT5jaGFuKSkgewo+ICsJCQlyZXQgPSBQVFJfRVJSKG5hbmRjLT5jaGFuKTsKPiArCQkJbmFuZGMt PmNoYW4gPSBOVUxMOwo+ICsJCQlkZXZfZXJyX3Byb2JlKG5hbmRjLT5kZXYsIHJldCwKPiArCQkJ CSAgICAgICJyeHR4IERNQSBjaGFubmVsIHJlcXVlc3QgZmFpbGVkXG4iKTsKPiArCQkJcmV0dXJu IHJldDsKPiArCQl9Cj4gKwl9Cj4gKwo+ICsJSU5JVF9MSVNUX0hFQUQoJm5hbmRjLT5kZXNjX2xp c3QpOwo+ICsJSU5JVF9MSVNUX0hFQUQoJm5hbmRjLT5ob3N0X2xpc3QpOwo+ICsKPiArCXJldHVy biAwOwo+ICt1bmFsbG9jOgo+ICsJcWNvbV9uYW5kY191bmFsbG9jKG5hbmRjKTsKPiArCXJldHVy biByZXQ7Cj4gK30KPiArRVhQT1JUX1NZTUJPTChxY29tX25hbmRjX2FsbG9jKTsKPiBkaWZmIC0t Z2l0IGEvaW5jbHVkZS9saW51eC9tdGQvbmFuZC1xcGljLWNvbW1vbi5oIGIvaW5jbHVkZS9saW51 eC9tdGQvbmFuZC1xcGljLWNvbW1vbi5oCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAw MDAwMDAwMDAwMDAuLmM0NjFjMTc4MTMzMAo+IC0tLSAvZGV2L251bGwKPiArKysgYi9pbmNsdWRl L2xpbnV4L210ZC9uYW5kLXFwaWMtY29tbW9uLmgKCi4uLgoKPiArCXUzMiBjbWQxLCB2bGQ7Cj4g Kwlib29sIGV4ZWNfb3B3cml0ZTsKPiArfTsKPiArCj4gKy8qCj4gKyAqIE5BTkQgY2hpcCBzdHJ1 Y3R1cmUKCnFjb21fbmFuZF9ob3N0IGlzIGEgbmFuZCBjaGlwIHN0cnVjdHVyZT8KCj4gKyAqCj4g KyAqIEBib290X3BhcnRpdGlvbnM6CQlhcnJheSBvZiBib290IHBhcnRpdGlvbnMgd2hlcmUgb2Zm c2V0IGFuZCBzaXplIG9mIHRoZQo+ICsgKgkJCQlib290IHBhcnRpdGlvbnMgYXJlIHN0b3JlZAo+ ICsgKgo+ICsgKiBAY2hpcDoJCQliYXNlIE5BTkQgY2hpcCBzdHJ1Y3R1cmUKPiArICogQG5vZGU6 CQkJbGlzdCBub2RlIHRvIGFkZCBpdHNlbGYgdG8gaG9zdF9saXN0IGluCj4gKyAqCQkJCXFjb21f bmFuZF9jb250cm9sbGVyCj4gKyAqCj4gKyAqIEBucl9ib290X3BhcnRpdGlvbnM6CQljb3VudCBv ZiB0aGUgYm9vdCBwYXJ0aXRpb25zIHdoZXJlIHNwYXJlIGRhdGEgaXMgbm90Cj4gKyAqCQkJCXBy b3RlY3RlZCBieSBFQ0MKPiArICoKPiArICogQGNzOgkJCQljaGlwIHNlbGVjdCB2YWx1ZSBmb3Ig dGhpcyBjaGlwCj4gKyAqIEBjd19zaXplOgkJCXRoZSBudW1iZXIgb2YgYnl0ZXMgaW4gYSBzaW5n bGUgc3RlcC9jb2Rld29yZAo+ICsgKgkJCQlvZiBhIHBhZ2UsIGNvbnNpc3Rpbmcgb2YgYWxsIGRh dGEsIGVjYywgc3BhcmUKPiArICoJCQkJYW5kIHJlc2VydmVkIGJ5dGVzCj4gKyAqIEBjd19kYXRh OgkJCXRoZSBudW1iZXIgb2YgYnl0ZXMgd2l0aGluIGEgY29kZXdvcmQgcHJvdGVjdGVkCj4gKyAq CQkJCWJ5IEVDQwo+ICsgKiBAZWNjX2J5dGVzX2h3OgkJRUNDIGJ5dGVzIHVzZWQgYnkgY29udHJv bGxlciBoYXJkd2FyZSBmb3IgdGhpcwo+ICsgKgkJCQljaGlwCj4gKyAqCj4gKyAqIEBsYXN0X2Nv bW1hbmQ6CQlrZWVwcyB0cmFjayBvZiBsYXN0IGNvbW1hbmQgb24gdGhpcyBjaGlwLiB1c2VkCj4g KyAqCQkJCWZvciByZWFkaW5nIGNvcnJlY3Qgc3RhdHVzCj4gKyAqCj4gKyAqIEBjZmcwLCBjZmcx LCBjZmcwX3Jhdy4uOglOQU5EYyByZWdpc3RlciBjb25maWd1cmF0aW9ucyBuZWVkZWQgZm9yCj4g KyAqCQkJCWVjYy9ub24tZWNjIG1vZGUgZm9yIHRoZSBjdXJyZW50IG5hbmQgZmxhc2gKPiArICoJ CQkJZGV2aWNlCj4gKyAqCj4gKyAqIEBzdGF0dXM6CQkJdmFsdWUgdG8gYmUgcmV0dXJuZWQgaWYg TkFORF9DTURfU1RBVFVTIGNvbW1hbmQKPiArICoJCQkJaXMgZXhlY3V0ZWQKPiArICogQGNvZGV3 b3JkX2ZpeHVwOgkJa2VlcCB0cmFjayBvZiB0aGUgY3VycmVudCBsYXlvdXQgdXNlZCBieQo+ICsg KgkJCQl0aGUgZHJpdmVyIGZvciByZWFkL3dyaXRlIG9wZXJhdGlvbi4KPiArICogQHVzZV9lY2M6 CQkJcmVxdWVzdCB0aGUgY29udHJvbGxlciB0byB1c2UgRUNDIGZvciB0aGUKPiArICoJCQkJdXBj b21pbmcgcmVhZC93cml0ZQo+ICsgKiBAYmNoX2VuYWJsZWQ6CQlmbGFnIHRvIHRlbGwgd2hldGhl ciBCQ0ggRUNDIG1vZGUgaXMgdXNlZAo+ICsgKi8KPiArc3RydWN0IHFjb21fbmFuZF9ob3N0IHsK PiArCXN0cnVjdCBxY29tX25hbmRfYm9vdF9wYXJ0aXRpb24gKmJvb3RfcGFydGl0aW9uczsKPiAr Cj4gKwlzdHJ1Y3QgbmFuZF9jaGlwIGNoaXA7Cj4gKwlzdHJ1Y3QgbGlzdF9oZWFkIG5vZGU7Cj4g Kwo+ICsJaW50IG5yX2Jvb3RfcGFydGl0aW9uczsKPiArCj4gKwlpbnQgY3M7Cj4gKwlpbnQgY3df c2l6ZTsKPiArCWludCBjd19kYXRhOwo+ICsJaW50IGVjY19ieXRlc19odzsKPiArCWludCBzcGFy ZV9ieXRlczsKPiArCWludCBiYm1fc2l6ZTsKPiArCj4gKwlpbnQgbGFzdF9jb21tYW5kOwo+ICsK PiArCXUzMiBjZmcwLCBjZmcxOwo+ICsJdTMyIGNmZzBfcmF3LCBjZmcxX3JhdzsKPiArCXUzMiBl Y2NfYnVmX2NmZzsKPiArCXUzMiBlY2NfYmNoX2NmZzsKPiArCXUzMiBjbHJmbGFzaHN0YXR1czsK PiArCXUzMiBjbHJyZWFkc3RhdHVzOwo+ICsKPiArCXU4IHN0YXR1czsKPiArCWJvb2wgY29kZXdv cmRfZml4dXA7Cj4gKwlib29sIHVzZV9lY2M7Cj4gKwlib29sIGJjaF9lbmFibGVkOwo+ICt9Owo+ ICsKCkkgd291bGQgbGlrZSB0byBzZWUgaG93IHVzZWZ1bCBhcmUgYWxsIHRoZXNlIGV4cG9ydHMu IEkgYmVsaWV2ZSB0aGUKY3VycmVudCBOQU5EIGNvbnRyb2xsZXIgZHJpdmVyIGFscmVhZHkgaGFz IHNvbWUgb2YgdGhlc2UgZnVuY3Rpb25zCmRlZmluZWQsIGNvdWxkIHlvdSBwbGVhc2UgbW92ZSB0 aGUgZnVuY3Rpb25zIHJhdGhlciB0aGFuIGFkZGluZyB0aGVtCmhlcmUgd2l0aG91dCByZW1vdmlu ZyB0aGVtIGluIHRoZSBvdGhlciBkcml2ZXI/CgpUaGFua3MsIE1pcXXDqGwKCl9fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpMaW51eCBNVEQgZGlz Y3Vzc2lvbiBtYWlsaW5nIGxpc3QKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9s aXN0aW5mby9saW51eC1tdGQvCg==