From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1C4106EB5D; Tue, 21 May 2024 13:24:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716297860; cv=none; b=b7saaN/coe7Rf8Lgexc0lEZaliL6NqinpawdU1QfmgleqHkNWP8VjO5Ht+Hh4PZxUBF/qOHROH7jsXGIjOP4HEi70HUKBgEucaMhbs7/AB0QLfhht9AHMlOha7mzgSVoZCZmmYWrplghmTOrXNRyO5NuZbSmtc07mZ1gRFO9i48= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716297860; c=relaxed/simple; bh=XE5Cmajq4TtuVFbLGKV427sERkxiIaKB04dIKxJtm9A=; h=Date:From:To:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=SWTU6Ei0xF8ySWSmlnxAJ88pKnTV4H1sqXTV82yBaCP8I1h5/kY3QyBhBup/42ueWXM/71gckG8gF9ij6hi5f+9UU/fqpDziY2ihJtqNOHLQnSPAs287y94xhry0LfygtXsBcHDM216K95I2WdZ1IdaVamhYvtv1XtqmjAQLDIg= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=amP6BpdD; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="amP6BpdD" Received: by mail.gandi.net (Postfix) with ESMTPSA id 681B21BF20B; Tue, 21 May 2024 13:24:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1716297854; 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=VHW9yaCA5KhU/nX6IBStFBScnVjslIbk+98nChBlJnk=; b=amP6BpdDo3jDhLN+DuTG1V4g7L51bFDJKbyTdh71Z3DrlK/J6Ca/tX2qVOQnEe7IxQ+FUZ NccDgpHf/ZNF+QUW9q5r7euXwW+NTU+K3knGjz3MqndYuCA16ExDm0l7ad3qoXkK+s9N8f FSCihgo20KDNxr9lgbqBwVNXAlv2DmumUEOZkoAL39ouYtFsS0nZiJwdHV7Gb1AxtmDI3d +X3IEqr9uQaGJ8WRZ8xbqQCgdLBNfPtzDu+EWbOhGJbpbXzEeHeTHEUx15Kk08Qm4XlLrn Icb3adSrFDKpvhXZPIFErsc/O3uR0I2ySl0mKlTnR7qpY5wL5x2bo/uZZdyrkA== Date: Tue, 21 May 2024 15:24:10 +0200 From: Miquel Raynal To: Md Sadre Alam Cc: broonie@kernel.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org, richard@nod.at, vigneshr@ti.com, manivannan.sadhasivam@linaro.org, linux-arm-msm@vger.kernel.org, linux-spi@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, quic_srichara@quicinc.com, quic_varada@quicinc.com Subject: Re: [PATCH v6 6/8] spi: spi-qpic: add driver for QCOM SPI NAND flash Interface Message-ID: <20240521152410.7cff71ab@xps-13> In-Reply-To: <20240521105532.1537845-7-quic_mdalam@quicinc.com> References: <20240521105532.1537845-1-quic_mdalam@quicinc.com> <20240521105532.1537845-7-quic_mdalam@quicinc.com> Organization: Bootlin X-Mailer: Claws Mail 4.1.1 (GTK 3.24.38; x86_64-pc-linux-gnu) Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-GND-Sasl: miquel.raynal@bootlin.com Hi, > diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile > index e59106e0a3af..12ee33c4ac4e 100644 > --- a/drivers/mtd/nand/Makefile > +++ b/drivers/mtd/nand/Makefile > @@ -5,6 +5,10 @@ obj-$(CONFIG_MTD_NAND_CORE) +=3D nandcore.o > obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) +=3D ecc-mtk.o > ifeq ($(CONFIG_MTD_NAND_QCOM),y) > obj-y +=3D qpic_common.o > +else > +ifeq ($(CONFIG_SPI_QPIC_SNAND),y) > +obj-y +=3D qpic_common.o > +endif Same issue. > endif > obj-y +=3D onenand/ > obj-y +=3D raw/ > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig > index a2c99ff33e0a..bb7579246f2f 100644 > --- a/drivers/spi/Kconfig > +++ b/drivers/spi/Kconfig > @@ -892,6 +892,14 @@ config SPI_QCOM_QSPI > help > QSPI(Quad SPI) driver for Qualcomm QSPI controller. > =20 ... > +static struct qcom_nand_controller *nand_to_qcom_snand(struct nand_devic= e *nand) > +{ > + struct qpic_spi_nand *qspi; > + struct nand_ecc_engine *eng =3D nand->ecc.engine; > + > + qspi =3D container_of(eng, struct qpic_spi_nand, ecc_eng); Please encode this into a macro and use it on the second line of this function: struct qpic_spi_nand *qspi =3D ecceng_to_qspi(eng); > + return qspi->snandc; > +} > + > +static int qcom_spi_init(struct qcom_nand_controller *snandc) > +{ > + u32 snand_cfg_val =3D 0x0; > + int ret; > + > + snand_cfg_val |=3D (LOAD_CLK_CNTR_INIT_EN | (CLK_CNTR_INIT_VAL_VEC << 1= 6) | > + (FEA_STATUS_DEV_ADDR << 8) | SPI_CFG); FIELD_PREP ? > + > + snandc->regs->spi_cfg =3D snand_cfg_val; > + snandc->regs->num_addr_cycle =3D SPI_NUM_ADDR; > + snandc->regs->busy_wait_cnt =3D SPI_WAIT_CNT; > + > + qcom_write_reg_dma(snandc, &snandc->regs->spi_cfg, NAND_FLASH_SPI_CFG, = 1, 0); > + > + snand_cfg_val &=3D ~LOAD_CLK_CNTR_INIT_EN; > + snandc->regs->spi_cfg =3D snand_cfg_val; > + > + qcom_write_reg_dma(snandc, &snandc->regs->spi_cfg, NAND_FLASH_SPI_CFG, = 1, 0); > + > + qcom_write_reg_dma(snandc, &snandc->regs->num_addr_cycle, NAND_NUM_ADDR= _CYCLES, 1, 0); > + qcom_write_reg_dma(snandc, &snandc->regs->busy_wait_cnt, NAND_BUSY_CHEC= K_WAIT_CNT, 1, > + NAND_BAM_NEXT_SGL); > + > + ret =3D qcom_submit_descs(snandc); > + if (ret) { > + dev_err(snandc->dev, "failure in submitting spi init descriptor\n"); > + return ret; > + } > + > + return ret; > +} > + > +static int qcom_spi_ooblayout_ecc(struct mtd_info *mtd, int section, > + struct mtd_oob_region *oobregion) > +{ > + struct nand_device *nand =3D mtd_to_nanddev(mtd); > + struct qcom_nand_controller *snandc =3D nand_to_qcom_snand(nand); > + struct qpic_ecc *qecc =3D snandc->qspi->ecc; > + > + if (section > 1) > + return -ERANGE; > + > + if (!section) { > + oobregion->length =3D (qecc->bytes * (qecc->steps - 1)) + qecc->bbm_si= ze; > + oobregion->offset =3D 0; No, offset 0 is for the BBM. This is wrong. The whole oob layout looks really really wrong. ECC bytes are where the ECC engine puts its bytes in the OOB area. Free bytes start after the BBM and fill the gaps until the end of the area, except where there are ECC bytes. > + } else { > + oobregion->length =3D qecc->ecc_bytes_hw + qecc->spare_bytes; > + oobregion->offset =3D mtd->oobsize - oobregion->length; > + } > + > + return 0; > +} > + > +static int qcom_spi_ooblayout_free(struct mtd_info *mtd, int section, > + struct mtd_oob_region *oobregion) > +{ > + struct nand_device *nand =3D mtd_to_nanddev(mtd); > + struct qcom_nand_controller *snandc =3D nand_to_qcom_snand(nand); > + struct qpic_ecc *qecc =3D snandc->qspi->ecc; > + > + if (section) > + return -ERANGE; > + > + oobregion->length =3D qecc->steps * 4; > + oobregion->offset =3D ((qecc->steps - 1) * qecc->bytes) + qecc->bbm_siz= e; > + > + return 0; > +} > + ... > +static int qcom_spi_ecc_prepare_io_req_pipelined(struct nand_device *nan= d, > + struct nand_page_io_req *req) > +{ > + struct qcom_nand_controller *snandc =3D nand_to_qcom_snand(nand); > + struct qpic_ecc *ecc_cfg =3D nand_to_ecc_ctx(nand); > + struct mtd_info *mtd =3D nanddev_to_mtd(nand); > + > + snandc->qspi->ecc =3D ecc_cfg; > + snandc->qspi->pagesize =3D mtd->writesize; > + snandc->qspi->raw_rw =3D false; > + snandc->qspi->oob_rw =3D false; > + snandc->qspi->page_rw =3D false; > + > + if (req->datalen) > + snandc->qspi->page_rw =3D true; > + > + if (req->ooblen) { > + snandc->qspi->oob_rw =3D true; > + if (req->ooblen =3D=3D BAD_BLOCK_MARKER_SIZE) > + snandc->qspi->read_last_cw =3D true; ??? > + } > + > + if (req->mode =3D=3D MTD_OPS_RAW) > + snandc->qspi->raw_rw =3D true; > + > + return 0; > +} > + > +static int qcom_spi_ecc_finish_io_req_pipelined(struct nand_device *nand, > + struct nand_page_io_req *req) > +{ > + struct qcom_nand_controller *snandc =3D nand_to_qcom_snand(nand); > + struct mtd_info *mtd =3D nanddev_to_mtd(nand); > + > + if (req->mode =3D=3D MTD_OPS_RAW || req->type !=3D NAND_PAGE_READ) > + return 0; > + > + if (snandc->qspi->ecc_stats.failed) > + mtd->ecc_stats.failed +=3D snandc->qspi->ecc_stats.failed; > + mtd->ecc_stats.corrected +=3D snandc->qspi->ecc_stats.corrected; Seems strange > + > + if (snandc->qspi->ecc_stats.failed) > + return -EBADMSG; > + else > + return snandc->qspi->ecc_stats.bitflips; > +} > + > +static struct nand_ecc_engine_ops qcom_spi_ecc_engine_ops_pipelined =3D { > + .init_ctx =3D qcom_spi_ecc_init_ctx_pipelined, > + .cleanup_ctx =3D qcom_spi_ecc_cleanup_ctx_pipelined, > + .prepare_io_req =3D qcom_spi_ecc_prepare_io_req_pipelined, > + .finish_io_req =3D qcom_spi_ecc_finish_io_req_pipelined, > +}; > + ... > +static int qcom_spi_read_page_raw(struct qcom_nand_controller *snandc, > + const struct spi_mem_op *op) > +{ > + struct qpic_ecc *ecc_cfg =3D snandc->qspi->ecc; > + u8 *data_buf =3D NULL, *oob_buf =3D NULL; > + int ret, cw; > + u32 num_cw =3D snandc->qspi->num_cw; > + > + if (snandc->qspi->page_rw) I don't like this indirection very much. Can't you simplify this and just follow the spi-mem op instead of constantly trying to add additional stuff? The hardware is already quite complex, but it feels like your adding yet another pile of unnecessary complexity. > + data_buf =3D op->data.buf.in; > + > + if (snandc->qspi->oob_rw) > + oob_buf =3D op->data.buf.in; Same buffer pointed by the two pointers? hum > + > + if (!oob_buf) { > + oob_buf =3D snandc->qspi->oob_buf; > + memset(oob_buf, 0xff, OOB_BUF_SIZE); > + } > + > + for (cw =3D 0; cw < num_cw; cw++) { > + ret =3D qcom_spi_read_cw_raw(snandc, data_buf, oob_buf, cw); > + if (ret) > + return ret; > + > + if (data_buf) > + data_buf +=3D ecc_cfg->cw_data; > + if (oob_buf) > + oob_buf +=3D ecc_cfg->bytes; > + } > + > + return 0; > +} > + > +static int qcom_spi_read_page_cache(struct qcom_nand_controller *snandc, > + const struct spi_mem_op *op) > +{ > + struct qpic_ecc *ecc_cfg =3D snandc->qspi->ecc; > + u8 *data_buf =3D NULL, *data_buf_start, *oob_buf =3D NULL, *oob_buf_sta= rt; > + int ret, i; > + u32 cfg0, cfg1, ecc_bch_cfg, num_cw =3D snandc->qspi->num_cw; > + > + if (snandc->qspi->page_rw) { > + data_buf =3D op->data.buf.in; > + data_buf_start =3D data_buf; > + } > + > + if (snandc->qspi->oob_rw || snandc->qspi->raw_rw) { > + oob_buf =3D op->data.buf.in; > + oob_buf_start =3D oob_buf; > + } > + > + if (snandc->qspi->page_rw && snandc->qspi->raw_rw) > + return qcom_spi_read_page_raw(snandc, op); > + > + if (snandc->qspi->oob_rw && snandc->qspi->raw_rw && snandc->qspi->read_= last_cw) > + return qcom_spi_read_last_cw(snandc, op); > + > + snandc->buf_count =3D 0; > + snandc->buf_start =3D 0; > + qcom_clear_read_regs(snandc); > + > + cfg0 =3D (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | > + (num_cw - 1) << CW_PER_PAGE; > + cfg1 =3D ecc_cfg->cfg1; > + ecc_bch_cfg =3D ecc_cfg->ecc_bch_cfg; > + > + snandc->regs->addr0 =3D snandc->qspi->addr1; > + snandc->regs->addr1 =3D snandc->qspi->addr2; > + snandc->regs->cmd =3D snandc->qspi->cmd; > + snandc->regs->cfg0 =3D cfg0; > + snandc->regs->cfg1 =3D cfg1; > + snandc->regs->ecc_bch_cfg =3D ecc_bch_cfg; > + snandc->regs->clrflashstatus =3D ecc_cfg->clrflashstatus; > + snandc->regs->clrreadstatus =3D ecc_cfg->clrreadstatus; > + snandc->regs->exec =3D 1; > + > + qcom_spi_set_read_loc(snandc, 0, 0, 0, ecc_cfg->cw_data, 1); > + > + qcom_clear_bam_transaction(snandc); > + > + qcom_write_reg_dma(snandc, &snandc->regs->addr0, NAND_ADDR0, 2, 0); > + qcom_write_reg_dma(snandc, &snandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0); > + qcom_write_reg_dma(snandc, &snandc->regs->erased_cw_detect_cfg_clr, > + NAND_ERASED_CW_DETECT_CFG, 1, 0); > + qcom_write_reg_dma(snandc, &snandc->regs->erased_cw_detect_cfg_set, > + NAND_ERASED_CW_DETECT_CFG, 1, > + NAND_ERASED_CW_SET | NAND_BAM_NEXT_SGL); > + > + for (i =3D 0; i < num_cw; i++) { > + int data_size, oob_size; > + > + if (i =3D=3D (num_cw - 1)) { > + data_size =3D 512 - ((num_cw - 1) << 2); > + oob_size =3D (num_cw << 2) + ecc_cfg->ecc_bytes_hw + > + ecc_cfg->spare_bytes; > + } else { > + data_size =3D ecc_cfg->cw_data; > + oob_size =3D ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes; > + } > + > + if (data_buf && oob_buf) { > + qcom_spi_set_read_loc(snandc, i, 0, 0, data_size, 0); > + qcom_spi_set_read_loc(snandc, i, 1, data_size, oob_size, 1); > + } else if (data_buf) { > + qcom_spi_set_read_loc(snandc, i, 0, 0, data_size, 1); > + } else { > + qcom_spi_set_read_loc(snandc, i, 0, data_size, oob_size, 1); > + } > + > + qcom_spi_config_cw_read(snandc, true, i); > + > + if (data_buf) > + qcom_read_data_dma(snandc, FLASH_BUF_ACC, data_buf, > + data_size, 0); > + if (oob_buf) { > + int j; > + > + for (j =3D 0; j < ecc_cfg->bbm_size; j++) > + *oob_buf++ =3D 0xff; > + > + qcom_read_data_dma(snandc, FLASH_BUF_ACC + data_size, > + oob_buf, oob_size, 0); > + } > + > + if (data_buf) > + data_buf +=3D data_size; > + if (oob_buf) > + oob_buf +=3D oob_size; > + } > + > + ret =3D qcom_submit_descs(snandc); > + if (ret) { > + dev_err(snandc->dev, "failure to read page\n"); > + return ret; > + } > + > + return qcom_spi_check_error(snandc, data_buf_start, oob_buf_start); > +} > + > +static void qcom_spi_config_page_write(struct qcom_nand_controller *snan= dc) > +{ > + qcom_write_reg_dma(snandc, &snandc->regs->addr0, NAND_ADDR0, 2, 0); > + qcom_write_reg_dma(snandc, &snandc->regs->cfg0, NAND_DEV0_CFG0, 3, 0); > + qcom_write_reg_dma(snandc, &snandc->regs->ecc_buf_cfg, NAND_EBI2_ECC_BU= F_CFG, > + 1, NAND_BAM_NEXT_SGL); > +} > + > +static void qcom_spi_config_cw_write(struct qcom_nand_controller *snandc) > +{ > + qcom_write_reg_dma(snandc, &snandc->regs->cmd, NAND_FLASH_CMD, 1, NAND_= BAM_NEXT_SGL); > + qcom_write_reg_dma(snandc, &snandc->regs->exec, NAND_EXEC_CMD, 1, NAND_= BAM_NEXT_SGL); > + qcom_read_reg_dma(snandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL); > + > + qcom_write_reg_dma(snandc, &snandc->regs->clrflashstatus, NAND_FLASH_ST= ATUS, 1, 0); > + qcom_write_reg_dma(snandc, &snandc->regs->clrreadstatus, NAND_READ_STAT= US, 1, > + NAND_BAM_NEXT_SGL); > +} > + > +static int qcom_spi_program_raw(struct qcom_nand_controller *snandc, > + const struct spi_mem_op *op) > +{ > + struct qpic_ecc *ecc_cfg =3D snandc->qspi->ecc; > + u8 *data_buf =3D NULL, *oob_buf =3D NULL; > + int i, ret; > + int num_cw =3D snandc->qspi->num_cw; > + u32 cfg0, cfg1, ecc_bch_cfg; > + > + cfg0 =3D (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) | > + (num_cw - 1) << CW_PER_PAGE; > + cfg1 =3D ecc_cfg->cfg1_raw; > + ecc_bch_cfg =3D ECC_CFG_ECC_DISABLE; > + > + data_buf =3D snandc->qspi->data_buf; > + > + oob_buf =3D snandc->qspi->oob_buf; > + memset(oob_buf, 0xff, OOB_BUF_SIZE); > + > + snandc->buf_count =3D 0; > + snandc->buf_start =3D 0; > + qcom_clear_read_regs(snandc); > + qcom_clear_bam_transaction(snandc); > + > + snandc->regs->addr0 =3D snandc->qspi->addr1; > + snandc->regs->addr1 =3D snandc->qspi->addr2; > + snandc->regs->cmd =3D snandc->qspi->cmd; > + snandc->regs->cfg0 =3D cfg0; > + snandc->regs->cfg1 =3D cfg1; > + snandc->regs->ecc_bch_cfg =3D ecc_bch_cfg; > + snandc->regs->clrflashstatus =3D ecc_cfg->clrflashstatus; > + snandc->regs->clrreadstatus =3D ecc_cfg->clrreadstatus; > + snandc->regs->exec =3D 1; > + > + qcom_spi_config_page_write(snandc); > + > + for (i =3D 0; i < num_cw; i++) { > + int data_size1, data_size2, oob_size1, oob_size2; > + int reg_off =3D FLASH_BUF_ACC; > + > + data_size1 =3D snandc->qspi->pagesize - ecc_cfg->cw_size * (num_cw - 1= ); > + oob_size1 =3D ecc_cfg->bbm_size; > + > + if ((i =3D=3D (num_cw - 1))) { > + data_size2 =3D NANDC_STEP_SIZE - data_size1 - > + ((num_cw - 1) << 2); > + oob_size2 =3D (num_cw << 2) + ecc_cfg->ecc_bytes_hw + > + ecc_cfg->spare_bytes; > + } else { > + data_size2 =3D ecc_cfg->cw_data - data_size1; > + oob_size2 =3D ecc_cfg->ecc_bytes_hw + ecc_cfg->spare_bytes; > + } > + > + qcom_write_data_dma(snandc, reg_off, data_buf, data_size1, > + NAND_BAM_NO_EOT); > + reg_off +=3D data_size1; > + data_buf +=3D data_size1; > + > + qcom_write_data_dma(snandc, reg_off, oob_buf, oob_size1, > + NAND_BAM_NO_EOT); > + oob_buf +=3D oob_size1; > + reg_off +=3D oob_size1; > + > + qcom_write_data_dma(snandc, reg_off, data_buf, data_size2, > + NAND_BAM_NO_EOT); > + reg_off +=3D data_size2; > + data_buf +=3D data_size2; > + > + qcom_write_data_dma(snandc, reg_off, oob_buf, oob_size2, 0); > + oob_buf +=3D oob_size2; > + > + qcom_spi_config_cw_write(snandc); > + } > + > + ret =3D qcom_submit_descs(snandc); > + if (ret) { > + dev_err(snandc->dev, "failure to write raw page\n"); > + return ret; > + } > + > + return 0; > +} > + > +static int qcom_spi_program_execute(struct qcom_nand_controller *snandc, > + const struct spi_mem_op *op) > +{ > + struct qpic_ecc *ecc_cfg =3D snandc->qspi->ecc; > + u8 *data_buf =3D NULL, *oob_buf =3D NULL; > + int i, ret; > + int num_cw =3D snandc->qspi->num_cw; > + u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg; > + > + cfg0 =3D (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | > + (num_cw - 1) << CW_PER_PAGE; > + cfg1 =3D ecc_cfg->cfg1; > + ecc_bch_cfg =3D ecc_cfg->ecc_bch_cfg; > + ecc_buf_cfg =3D ecc_cfg->ecc_buf_cfg; > + > + if (snandc->qspi->page_rw && snandc->qspi->raw_rw) > + return qcom_spi_program_raw(snandc, op); > + > + if (snandc->qspi->data_buf) > + data_buf =3D snandc->qspi->data_buf; > + > + if (snandc->qspi->oob_buf) > + oob_buf =3D snandc->qspi->oob_buf; > + > + snandc->buf_count =3D 0; > + snandc->buf_start =3D 0; > + qcom_clear_read_regs(snandc); > + qcom_clear_bam_transaction(snandc); > + > + snandc->regs->addr0 =3D snandc->qspi->addr1; > + snandc->regs->addr1 =3D snandc->qspi->addr2; > + snandc->regs->cmd =3D snandc->qspi->cmd; > + snandc->regs->cfg0 =3D cfg0; > + snandc->regs->cfg1 =3D cfg1; > + snandc->regs->ecc_bch_cfg =3D ecc_bch_cfg; > + snandc->regs->ecc_buf_cfg =3D ecc_buf_cfg; > + snandc->regs->exec =3D 1; > + > + qcom_spi_config_page_write(snandc); > + > + for (i =3D 0; i < num_cw; i++) { > + int data_size, oob_size; > + > + if (i =3D=3D (num_cw - 1)) { > + data_size =3D NANDC_STEP_SIZE - ((num_cw - 1) << 2); > + oob_size =3D (num_cw << 2) + ecc_cfg->ecc_bytes_hw + > + ecc_cfg->spare_bytes; > + } else { > + data_size =3D ecc_cfg->cw_data; > + oob_size =3D ecc_cfg->bytes; > + } > + > + if (data_buf) > + qcom_write_data_dma(snandc, FLASH_BUF_ACC, data_buf, data_size, > + i =3D=3D (num_cw - 1) ? NAND_BAM_NO_EOT : 0); > + > + if (i =3D=3D (num_cw - 1)) { > + if (oob_buf) { > + oob_buf +=3D ecc_cfg->bbm_size; > + qcom_write_data_dma(snandc, FLASH_BUF_ACC + data_size, > + oob_buf, oob_size, 0); > + } > + } > + > + qcom_spi_config_cw_write(snandc); > + > + if (data_buf) > + data_buf +=3D data_size; > + if (oob_buf) > + oob_buf +=3D oob_size; > + } > + > + ret =3D qcom_submit_descs(snandc); > + if (ret) { > + dev_err(snandc->dev, "failure to write page\n"); > + return ret; > + } > + > + return 0; > +} > + > +static u32 qcom_spi_cmd_mapping(struct qcom_nand_controller *snandc, u32= opcode) > +{ > + u32 cmd =3D 0x0; > + > + switch (opcode) { > + case SPINAND_RESET: > + cmd =3D (SPI_WP | SPI_HOLD | SPI_TRANSFER_MODE_x1 | OP_RESET_DEVICE); > + break; > + case SPINAND_READID: > + cmd =3D (SPI_WP | SPI_HOLD | SPI_TRANSFER_MODE_x1 | OP_FETCH_ID); > + break; > + case SPINAND_GET_FEATURE: > + cmd =3D (SPI_TRANSFER_MODE_x1 | SPI_WP | SPI_HOLD | ACC_FEATURE); > + break; > + case SPINAND_SET_FEATURE: > + cmd =3D (SPI_TRANSFER_MODE_x1 | SPI_WP | SPI_HOLD | ACC_FEATURE | > + QPIC_SET_FEATURE); > + break; > + case SPINAND_READ: > + if (snandc->qspi->raw_rw) { > + cmd =3D (PAGE_ACC | LAST_PAGE | SPI_TRANSFER_MODE_x1 | > + SPI_WP | SPI_HOLD | OP_PAGE_READ); > + } else { > + cmd =3D (PAGE_ACC | LAST_PAGE | SPI_TRANSFER_MODE_x1 | > + SPI_WP | SPI_HOLD | OP_PAGE_READ_WITH_ECC); > + } > + > + break; > + case SPINAND_ERASE: > + cmd =3D OP_BLOCK_ERASE | PAGE_ACC | LAST_PAGE | SPI_WP | > + SPI_HOLD | SPI_TRANSFER_MODE_x1; > + break; > + case SPINAND_WRITE_EN: > + cmd =3D SPINAND_WRITE_EN; > + break; > + case SPINAND_PROGRAM_EXECUTE: > + cmd =3D (PAGE_ACC | LAST_PAGE | SPI_TRANSFER_MODE_x1 | > + SPI_WP | SPI_HOLD | OP_PROGRAM_PAGE); > + break; > + case SPINAND_PROGRAM_LOAD: > + cmd =3D SPINAND_PROGRAM_LOAD; > + break; > + default: > + dev_err(snandc->dev, "Opcode not supported: %u\n", opcode); > + return -EOPNOTSUPP; > + } > + > + return cmd; > +} > + > +static int qcom_spi_write_page_cache(struct qcom_nand_controller *snandc, > + const struct spi_mem_op *op) > +{ > + struct qpic_snand_op s_op =3D {}; > + u32 cmd; > + > + cmd =3D qcom_spi_cmd_mapping(snandc, op->cmd.opcode); I've asked for switch cases to return an error in case they could not handle the request. If you don't check the returned values, it does not make any sense. > + s_op.cmd_reg =3D cmd; > + > + if (op->cmd.opcode =3D=3D SPINAND_PROGRAM_LOAD) { > + if (snandc->qspi->page_rw) > + snandc->qspi->data_buf =3D (u8 *)op->data.buf.out; What you do here does not write anything in a page cache. I also don't understand why you would have to check against the SPINAND_PROGRAM_LOAD opcode. > + } > + > + return 0; > +} > + > +static int qcom_spi_send_cmdaddr(struct qcom_nand_controller *snandc, > + const struct spi_mem_op *op) > +{ > + struct qpic_snand_op s_op =3D {}; > + u32 cmd; > + int ret, opcode; > + > + cmd =3D qcom_spi_cmd_mapping(snandc, op->cmd.opcode); > + > + s_op.cmd_reg =3D cmd; > + s_op.addr1_reg =3D op->addr.val; > + s_op.addr2_reg =3D 0; > + > + opcode =3D op->cmd.opcode; > + > + switch (opcode) { > + case SPINAND_WRITE_EN: > + return 0; > + case SPINAND_PROGRAM_EXECUTE: > + s_op.addr1_reg =3D op->addr.val << 16; > + s_op.addr2_reg =3D op->addr.val >> 16 & 0xff; > + snandc->qspi->addr1 =3D s_op.addr1_reg; > + snandc->qspi->addr2 =3D s_op.addr2_reg; > + snandc->qspi->cmd =3D cmd; > + return qcom_spi_program_execute(snandc, op); > + case SPINAND_READ: > + s_op.addr1_reg =3D (op->addr.val << 16); > + s_op.addr2_reg =3D op->addr.val >> 16 & 0xff; > + snandc->qspi->addr1 =3D s_op.addr1_reg; > + snandc->qspi->addr2 =3D s_op.addr2_reg; > + snandc->qspi->cmd =3D cmd; > + return 0; > + case SPINAND_ERASE: > + s_op.addr2_reg =3D (op->addr.val >> 16) & 0xffff; > + s_op.addr1_reg =3D op->addr.val; > + snandc->qspi->addr1 =3D (s_op.addr1_reg << 16); > + snandc->qspi->addr2 =3D s_op.addr2_reg; > + snandc->qspi->cmd =3D cmd; > + qcom_spi_block_erase(snandc); > + return 0; > + default: > + break; > + } > + > + snandc->buf_count =3D 0; > + snandc->buf_start =3D 0; > + qcom_clear_read_regs(snandc); > + qcom_clear_bam_transaction(snandc); > + > + snandc->regs->cmd =3D s_op.cmd_reg; > + snandc->regs->exec =3D 1; > + snandc->regs->addr0 =3D s_op.addr1_reg; > + snandc->regs->addr1 =3D s_op.addr2_reg; > + > + qcom_write_reg_dma(snandc, &snandc->regs->cmd, NAND_FLASH_CMD, 3, NAND_= BAM_NEXT_SGL); > + qcom_write_reg_dma(snandc, &snandc->regs->exec, NAND_EXEC_CMD, 1, NAND_= BAM_NEXT_SGL); > + > + ret =3D qcom_submit_descs(snandc); > + if (ret) > + dev_err(snandc->dev, "failure in sbumitting cmd descriptor\n"); typo > + > + return ret; > +} > + > +static int qcom_spi_io_op(struct qcom_nand_controller *snandc, const str= uct spi_mem_op *op) > +{ > + int ret, val, opcode; > + bool copy =3D false, copy_ftr =3D false; > + > + ret =3D qcom_spi_send_cmdaddr(snandc, op); > + if (ret) > + return ret; > + > + snandc->buf_count =3D 0; > + snandc->buf_start =3D 0; > + qcom_clear_read_regs(snandc); > + qcom_clear_bam_transaction(snandc); > + opcode =3D op->cmd.opcode; > + > + switch (opcode) { > + case SPINAND_READID: > + snandc->buf_count =3D 4; > + qcom_read_reg_dma(snandc, NAND_READ_ID, 1, NAND_BAM_NEXT_SGL); > + copy =3D true; > + break; > + case SPINAND_GET_FEATURE: > + snandc->buf_count =3D 4; > + qcom_read_reg_dma(snandc, NAND_FLASH_FEATURES, 1, NAND_BAM_NEXT_SGL); > + copy_ftr =3D true; > + break; > + case SPINAND_SET_FEATURE: > + snandc->regs->flash_feature =3D *(u32 *)op->data.buf.out; > + qcom_write_reg_dma(snandc, &snandc->regs->flash_feature, > + NAND_FLASH_FEATURES, 1, NAND_BAM_NEXT_SGL); > + break; > + case SPINAND_RESET: > + return 0; > + case SPINAND_PROGRAM_EXECUTE: > + return 0; > + case SPINAND_WRITE_EN: > + return 0; > + case SPINAND_ERASE: > + return 0; > + case SPINAND_READ: > + return 0; You can stack the cases > + default: > + return -EOPNOTSUPP; > + } > + > + ret =3D qcom_submit_descs(snandc); > + if (ret) > + dev_err(snandc->dev, "failure in submitting descriptor for:%d\n", opco= de); > + > + if (copy) { > + qcom_nandc_dev_to_mem(snandc, true); > + memcpy(op->data.buf.in, snandc->reg_read_buf, snandc->buf_count); > + } > + > + if (copy_ftr) { > + qcom_nandc_dev_to_mem(snandc, true); > + val =3D le32_to_cpu(*(__le32 *)snandc->reg_read_buf); > + val >>=3D 8; > + memcpy(op->data.buf.in, &val, snandc->buf_count); > + } > + > + return ret; > +} > + > +static bool qcom_spi_is_page_op(const struct spi_mem_op *op) > +{ > + if (op->addr.buswidth !=3D 1 && op->addr.buswidth !=3D 2 && op->addr.bu= swidth !=3D 4) > + return false; > + > + if (op->data.dir =3D=3D SPI_MEM_DATA_IN) { > + if (op->addr.buswidth =3D=3D 4 && op->data.buswidth =3D=3D 4) > + return true; > + > + if (op->addr.nbytes =3D=3D 2 && op->addr.buswidth =3D=3D 1) > + return true; > + > + } else if (op->data.dir =3D=3D SPI_MEM_DATA_OUT) { > + if (op->data.buswidth =3D=3D 4) > + return true; > + if (op->addr.nbytes =3D=3D 2 && op->addr.buswidth =3D=3D 1) > + return true; > + } > + > + return false; > +} > + > +static bool qcom_spi_supports_op(struct spi_mem *mem, const struct spi_m= em_op *op) > +{ > + if (!spi_mem_default_supports_op(mem, op)) > + return false; > + > + if (op->cmd.nbytes !=3D 1 || op->cmd.buswidth !=3D 1) > + return false; > + > + if (qcom_spi_is_page_op(op)) > + return true; > + > + return ((!op->addr.nbytes || op->addr.buswidth =3D=3D 1) && > + (!op->dummy.nbytes || op->dummy.buswidth =3D=3D 1) && > + (!op->data.nbytes || op->data.buswidth =3D=3D 1)); > +} > + > +static int qcom_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op= *op) > +{ > + struct qcom_nand_controller *snandc =3D spi_controller_get_devdata(mem-= >spi->controller); > + > + dev_dbg(snandc->dev, "OP %02x ADDR %08llX@%d:%u DATA %d:%u", op->cmd.op= code, > + op->addr.val, op->addr.buswidth, op->addr.nbytes, > + op->data.buswidth, op->data.nbytes); > + > + if (qcom_spi_is_page_op(op)) { > + if (op->data.dir =3D=3D SPI_MEM_DATA_IN) > + return qcom_spi_read_page_cache(snandc, op); > + if (op->data.dir =3D=3D SPI_MEM_DATA_OUT) > + return qcom_spi_write_page_cache(snandc, op); > + } else { > + return qcom_spi_io_op(snandc, op); > + } > + > + return 0; > +} > + > +static const struct spi_controller_mem_ops qcom_spi_mem_ops =3D { > + .supports_op =3D qcom_spi_supports_op, > + .exec_op =3D qcom_spi_exec_op, > +}; > + > +static const struct spi_controller_mem_caps qcom_spi_mem_caps =3D { > + .ecc =3D true, > +}; > + > +static int qcom_spi_probe(struct platform_device *pdev) > +{ > + struct device *dev =3D &pdev->dev; > + struct spi_controller *ctlr; > + struct qcom_nand_controller *snandc; > + struct qpic_spi_nand *qspi; > + struct qpic_ecc *ecc; > + struct resource *res; > + const void *dev_data; > + int ret; > + > + ecc =3D devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL); > + if (!ecc) > + return -ENOMEM; > + > + qspi =3D devm_kzalloc(dev, sizeof(*qspi), GFP_KERNEL); > + if (!qspi) > + return -ENOMEM; > + > + ctlr =3D __devm_spi_alloc_controller(dev, sizeof(*snandc), false); > + if (!ctlr) > + return -ENOMEM; > + > + platform_set_drvdata(pdev, ctlr); > + > + snandc =3D spi_controller_get_devdata(ctlr); > + qspi->snandc =3D snandc; > + > + snandc->dev =3D dev; > + snandc->qspi =3D qspi; > + snandc->qspi->ctlr =3D ctlr; > + snandc->qspi->ecc =3D ecc; > + > + snandc->qspi->oob_buf =3D devm_kzalloc(dev, OOB_BUF_SIZE, GFP_KERNEL); > + if (!snandc->qspi->oob_buf) > + return -ENOMEM; > + > + dev_data =3D of_device_get_match_data(dev); > + if (!dev_data) { > + dev_err(&pdev->dev, "failed to get device data\n"); > + return -ENODEV; > + } > + > + snandc->props =3D dev_data; > + snandc->dev =3D &pdev->dev; > + > + snandc->core_clk =3D devm_clk_get(dev, "core"); > + if (IS_ERR(snandc->core_clk)) > + return PTR_ERR(snandc->core_clk); > + > + snandc->aon_clk =3D devm_clk_get(dev, "aon"); > + if (IS_ERR(snandc->aon_clk)) > + return PTR_ERR(snandc->aon_clk); > + > + snandc->qspi->iomacro_clk =3D devm_clk_get(dev, "iom"); > + if (IS_ERR(snandc->qspi->iomacro_clk)) > + return PTR_ERR(snandc->qspi->iomacro_clk); > + > + snandc->base =3D devm_platform_get_and_ioremap_resource(pdev, 0, &res); > + if (IS_ERR(snandc->base)) > + return PTR_ERR(snandc->base); > + > + snandc->base_phys =3D res->start; > + snandc->base_dma =3D dma_map_resource(dev, res->start, resource_size(re= s), > + DMA_BIDIRECTIONAL, 0); > + if (dma_mapping_error(dev, snandc->base_dma)) > + return -ENXIO; > + > + ret =3D clk_prepare_enable(snandc->core_clk); > + if (ret) > + goto err_core_clk; Again, the label is better named when it describes what it point at, rather than where it comes from. > + > + ret =3D clk_prepare_enable(snandc->aon_clk); > + if (ret) > + goto err_aon_clk; > + > + ret =3D clk_prepare_enable(snandc->qspi->iomacro_clk); > + if (ret) > + goto err_dis_iom_clk; > + > + ret =3D qcom_nandc_alloc(snandc); > + if (ret) > + goto err_snand_alloc; > + > + ret =3D qcom_spi_init(snandc); > + if (ret) > + goto err_init; > + > + /* setup ECC engine */ > + snandc->qspi->ecc_eng.dev =3D &pdev->dev; > + snandc->qspi->ecc_eng.integration =3D NAND_ECC_ENGINE_INTEGRATION_PIPEL= INED; > + snandc->qspi->ecc_eng.ops =3D &qcom_spi_ecc_engine_ops_pipelined; > + snandc->qspi->ecc_eng.priv =3D snandc; > + > + ret =3D nand_ecc_register_on_host_hw_engine(&snandc->qspi->ecc_eng); > + if (ret) { > + dev_err(&pdev->dev, "failed to register ecc engine:%d\n", ret); > + goto err_init; > + } > + > + ctlr->num_chipselect =3D QPIC_QSPI_NUM_CS; > + ctlr->mem_ops =3D &qcom_spi_mem_ops; > + ctlr->mem_caps =3D &qcom_spi_mem_caps; > + ctlr->dev.of_node =3D pdev->dev.of_node; > + ctlr->mode_bits =3D SPI_TX_DUAL | SPI_RX_DUAL | > + SPI_TX_QUAD | SPI_RX_QUAD; > + > + ret =3D spi_register_controller(ctlr); > + if (ret) { > + dev_err(&pdev->dev, "spi_register_controller failed.\n"); > + goto err_init; > + } > + > + return 0; > + > +err_init: > + qcom_nandc_unalloc(snandc); Same: s/unalloc/free|cleanup/ > +err_snand_alloc: > + clk_disable_unprepare(snandc->qspi->iomacro_clk); > +err_dis_iom_clk: > + clk_disable_unprepare(snandc->aon_clk); > +err_aon_clk: > + clk_disable_unprepare(snandc->core_clk); > +err_core_clk: > + dma_unmap_resource(dev, res->start, resource_size(res), > + DMA_BIDIRECTIONAL, 0); > + return ret; > +} 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 9C6A2C25B74 for ; Tue, 21 May 2024 13:24:28 +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=QaQhENQ5RBqP+JrjZy9FUx9V6MWbtB5HKyoZGMHEayI=; b=ephUEKRPdh/UR+ vTUEdBfT+CwB7SugWybW7eYG+SXJqIj+fHCDGL0UwpWgQtxU+wWvmzA1ZulBAReupMv58heFR2RVH V8ztnKnE/hXsdO2Fw1pJKLgL/laObr9owBRsEb2WYnB4Q5a48t5iWOR6cTRAPhxDGvombw5k+ez9T bmDCyWuSY75jlsuAxIuvUHWj5kiIm3efKCuOkF34XPObwXsnf2/WNx0sUPONBguumVIa7PphhOsnB U+/3tv7ajSsa1u2TugWiyoq3EqisMVhew689O3lETotIOBp09Zeo1seaWybAIwB78/47sb9RkwtM8 yCmg8l+YacwIkxnlqtgA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1s9PTa-0000000Haba-230s; Tue, 21 May 2024 13:24:22 +0000 Received: from relay8-d.mail.gandi.net ([2001:4b98:dc4:8::228]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1s9PTV-0000000HaZp-2pxD for linux-mtd@lists.infradead.org; Tue, 21 May 2024 13:24:20 +0000 Received: by mail.gandi.net (Postfix) with ESMTPSA id 681B21BF20B; Tue, 21 May 2024 13:24:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1716297854; 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=VHW9yaCA5KhU/nX6IBStFBScnVjslIbk+98nChBlJnk=; b=amP6BpdDo3jDhLN+DuTG1V4g7L51bFDJKbyTdh71Z3DrlK/J6Ca/tX2qVOQnEe7IxQ+FUZ NccDgpHf/ZNF+QUW9q5r7euXwW+NTU+K3knGjz3MqndYuCA16ExDm0l7ad3qoXkK+s9N8f FSCihgo20KDNxr9lgbqBwVNXAlv2DmumUEOZkoAL39ouYtFsS0nZiJwdHV7Gb1AxtmDI3d +X3IEqr9uQaGJ8WRZ8xbqQCgdLBNfPtzDu+EWbOhGJbpbXzEeHeTHEUx15Kk08Qm4XlLrn Icb3adSrFDKpvhXZPIFErsc/O3uR0I2ySl0mKlTnR7qpY5wL5x2bo/uZZdyrkA== Date: Tue, 21 May 2024 15:24:10 +0200 From: Miquel Raynal To: Md Sadre Alam Cc: broonie@kernel.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, andersson@kernel.org, konrad.dybcio@linaro.org, richard@nod.at, vigneshr@ti.com, manivannan.sadhasivam@linaro.org, linux-arm-msm@vger.kernel.org, linux-spi@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, quic_srichara@quicinc.com, quic_varada@quicinc.com Subject: Re: [PATCH v6 6/8] spi: spi-qpic: add driver for QCOM SPI NAND flash Interface Message-ID: <20240521152410.7cff71ab@xps-13> In-Reply-To: <20240521105532.1537845-7-quic_mdalam@quicinc.com> References: <20240521105532.1537845-1-quic_mdalam@quicinc.com> <20240521105532.1537845-7-quic_mdalam@quicinc.com> Organization: Bootlin X-Mailer: Claws Mail 4.1.1 (GTK 3.24.38; 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-20240521_062418_190684_E110A07E X-CRM114-Status: GOOD ( 22.04 ) 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 SGksCgo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL210ZC9uYW5kL01ha2VmaWxlIGIvZHJpdmVycy9t dGQvbmFuZC9NYWtlZmlsZQo+IGluZGV4IGU1OTEwNmUwYTNhZi4uMTJlZTMzYzRhYzRlIDEwMDY0 NAo+IC0tLSBhL2RyaXZlcnMvbXRkL25hbmQvTWFrZWZpbGUKPiArKysgYi9kcml2ZXJzL210ZC9u YW5kL01ha2VmaWxlCj4gQEAgLTUsNiArNSwxMCBAQCBvYmotJChDT05GSUdfTVREX05BTkRfQ09S RSkgKz0gbmFuZGNvcmUubwo+ICBvYmotJChDT05GSUdfTVREX05BTkRfRUNDX01FRElBVEVLKSAr PSBlY2MtbXRrLm8KPiAgaWZlcSAoJChDT05GSUdfTVREX05BTkRfUUNPTSkseSkKPiAgb2JqLXkJ Kz0gcXBpY19jb21tb24ubwo+ICtlbHNlCj4gK2lmZXEgKCQoQ09ORklHX1NQSV9RUElDX1NOQU5E KSx5KQo+ICtvYmoteSAgICs9IHFwaWNfY29tbW9uLm8KPiArZW5kaWYKClNhbWUgaXNzdWUuCgo+ ICBlbmRpZgo+ICBvYmoteQkrPSBvbmVuYW5kLwo+ICBvYmoteQkrPSByYXcvCj4gZGlmZiAtLWdp dCBhL2RyaXZlcnMvc3BpL0tjb25maWcgYi9kcml2ZXJzL3NwaS9LY29uZmlnCj4gaW5kZXggYTJj OTlmZjMzZTBhLi5iYjc1NzkyNDZmMmYgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy9zcGkvS2NvbmZp Zwo+ICsrKyBiL2RyaXZlcnMvc3BpL0tjb25maWcKPiBAQCAtODkyLDYgKzg5MiwxNCBAQCBjb25m aWcgU1BJX1FDT01fUVNQSQo+ICAJaGVscAo+ICAJICBRU1BJKFF1YWQgU1BJKSBkcml2ZXIgZm9y IFF1YWxjb21tIFFTUEkgY29udHJvbGxlci4KPiAgCgouLi4KCj4gK3N0YXRpYyBzdHJ1Y3QgcWNv bV9uYW5kX2NvbnRyb2xsZXIgKm5hbmRfdG9fcWNvbV9zbmFuZChzdHJ1Y3QgbmFuZF9kZXZpY2Ug Km5hbmQpCj4gK3sKPiArCXN0cnVjdCBxcGljX3NwaV9uYW5kICpxc3BpOwo+ICsJc3RydWN0IG5h bmRfZWNjX2VuZ2luZSAqZW5nID0gbmFuZC0+ZWNjLmVuZ2luZTsKPiArCj4gKwlxc3BpID0gY29u dGFpbmVyX29mKGVuZywgc3RydWN0IHFwaWNfc3BpX25hbmQsIGVjY19lbmcpOwoKUGxlYXNlIGVu Y29kZSB0aGlzIGludG8gYSBtYWNybyBhbmQgdXNlIGl0IG9uIHRoZSBzZWNvbmQgbGluZSBvZiB0 aGlzCmZ1bmN0aW9uOgoKCXN0cnVjdCBxcGljX3NwaV9uYW5kICpxc3BpID0gZWNjZW5nX3RvX3Fz cGkoZW5nKTsKCj4gKwlyZXR1cm4gcXNwaS0+c25hbmRjOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50 IHFjb21fc3BpX2luaXQoc3RydWN0IHFjb21fbmFuZF9jb250cm9sbGVyICpzbmFuZGMpCj4gK3sK PiArCXUzMiBzbmFuZF9jZmdfdmFsID0gMHgwOwo+ICsJaW50IHJldDsKPiArCj4gKwlzbmFuZF9j ZmdfdmFsIHw9IChMT0FEX0NMS19DTlRSX0lOSVRfRU4gfCAoQ0xLX0NOVFJfSU5JVF9WQUxfVkVD IDw8IDE2KSB8Cj4gKwkJCSAoRkVBX1NUQVRVU19ERVZfQUREUiA8PCA4KSB8IFNQSV9DRkcpOwoK RklFTERfUFJFUCA/Cgo+ICsKPiArCXNuYW5kYy0+cmVncy0+c3BpX2NmZyA9IHNuYW5kX2NmZ192 YWw7Cj4gKwlzbmFuZGMtPnJlZ3MtPm51bV9hZGRyX2N5Y2xlID0gU1BJX05VTV9BRERSOwo+ICsJ c25hbmRjLT5yZWdzLT5idXN5X3dhaXRfY250ID0gU1BJX1dBSVRfQ05UOwo+ICsKPiArCXFjb21f d3JpdGVfcmVnX2RtYShzbmFuZGMsICZzbmFuZGMtPnJlZ3MtPnNwaV9jZmcsIE5BTkRfRkxBU0hf U1BJX0NGRywgMSwgMCk7Cj4gKwo+ICsJc25hbmRfY2ZnX3ZhbCAmPSB+TE9BRF9DTEtfQ05UUl9J TklUX0VOOwo+ICsJc25hbmRjLT5yZWdzLT5zcGlfY2ZnID0gc25hbmRfY2ZnX3ZhbDsKPiArCj4g KwlxY29tX3dyaXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRjLT5yZWdzLT5zcGlfY2ZnLCBOQU5E X0ZMQVNIX1NQSV9DRkcsIDEsIDApOwo+ICsKPiArCXFjb21fd3JpdGVfcmVnX2RtYShzbmFuZGMs ICZzbmFuZGMtPnJlZ3MtPm51bV9hZGRyX2N5Y2xlLCBOQU5EX05VTV9BRERSX0NZQ0xFUywgMSwg MCk7Cj4gKwlxY29tX3dyaXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRjLT5yZWdzLT5idXN5X3dh aXRfY250LCBOQU5EX0JVU1lfQ0hFQ0tfV0FJVF9DTlQsIDEsCj4gKwkJCSAgIE5BTkRfQkFNX05F WFRfU0dMKTsKPiArCj4gKwlyZXQgPSBxY29tX3N1Ym1pdF9kZXNjcyhzbmFuZGMpOwo+ICsJaWYg KHJldCkgewo+ICsJCWRldl9lcnIoc25hbmRjLT5kZXYsICJmYWlsdXJlIGluIHN1Ym1pdHRpbmcg c3BpIGluaXQgZGVzY3JpcHRvclxuIik7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0KPiArCj4gKwly ZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHFjb21fc3BpX29vYmxheW91dF9lY2Mo c3RydWN0IG10ZF9pbmZvICptdGQsIGludCBzZWN0aW9uLAo+ICsJCQkJICBzdHJ1Y3QgbXRkX29v Yl9yZWdpb24gKm9vYnJlZ2lvbikKPiArewo+ICsJc3RydWN0IG5hbmRfZGV2aWNlICpuYW5kID0g bXRkX3RvX25hbmRkZXYobXRkKTsKPiArCXN0cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqc25h bmRjID0gbmFuZF90b19xY29tX3NuYW5kKG5hbmQpOwo+ICsJc3RydWN0IHFwaWNfZWNjICpxZWNj ID0gc25hbmRjLT5xc3BpLT5lY2M7Cj4gKwo+ICsJaWYgKHNlY3Rpb24gPiAxKQo+ICsJCXJldHVy biAtRVJBTkdFOwo+ICsKPiArCWlmICghc2VjdGlvbikgewo+ICsJCW9vYnJlZ2lvbi0+bGVuZ3Ro ID0gKHFlY2MtPmJ5dGVzICogKHFlY2MtPnN0ZXBzIC0gMSkpICsgcWVjYy0+YmJtX3NpemU7Cj4g KwkJb29icmVnaW9uLT5vZmZzZXQgPSAwOwoKTm8sIG9mZnNldCAwIGlzIGZvciB0aGUgQkJNLiBU aGlzIGlzIHdyb25nLgpUaGUgd2hvbGUgb29iIGxheW91dCBsb29rcyByZWFsbHkgcmVhbGx5IHdy b25nLgoKRUNDIGJ5dGVzIGFyZSB3aGVyZSB0aGUgRUNDIGVuZ2luZSBwdXRzIGl0cyBieXRlcyBp biB0aGUgT09CIGFyZWEuCkZyZWUgYnl0ZXMgc3RhcnQgYWZ0ZXIgdGhlIEJCTSBhbmQgZmlsbCB0 aGUgZ2FwcyB1bnRpbCB0aGUgZW5kIG9mIHRoZQphcmVhLCBleGNlcHQgd2hlcmUgdGhlcmUgYXJl IEVDQyBieXRlcy4KCj4gKwl9IGVsc2Ugewo+ICsJCW9vYnJlZ2lvbi0+bGVuZ3RoID0gcWVjYy0+ ZWNjX2J5dGVzX2h3ICsgcWVjYy0+c3BhcmVfYnl0ZXM7Cj4gKwkJb29icmVnaW9uLT5vZmZzZXQg PSBtdGQtPm9vYnNpemUgLSBvb2JyZWdpb24tPmxlbmd0aDsKPiArCX0KPiArCj4gKwlyZXR1cm4g MDsKPiArfQo+ICsKPiArc3RhdGljIGludCBxY29tX3NwaV9vb2JsYXlvdXRfZnJlZShzdHJ1Y3Qg bXRkX2luZm8gKm10ZCwgaW50IHNlY3Rpb24sCj4gKwkJCQkgICBzdHJ1Y3QgbXRkX29vYl9yZWdp b24gKm9vYnJlZ2lvbikKPiArewo+ICsJc3RydWN0IG5hbmRfZGV2aWNlICpuYW5kID0gbXRkX3Rv X25hbmRkZXYobXRkKTsKPiArCXN0cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqc25hbmRjID0g bmFuZF90b19xY29tX3NuYW5kKG5hbmQpOwo+ICsJc3RydWN0IHFwaWNfZWNjICpxZWNjID0gc25h bmRjLT5xc3BpLT5lY2M7Cj4gKwo+ICsJaWYgKHNlY3Rpb24pCj4gKwkJcmV0dXJuIC1FUkFOR0U7 Cj4gKwo+ICsJb29icmVnaW9uLT5sZW5ndGggPSBxZWNjLT5zdGVwcyAqIDQ7Cj4gKwlvb2JyZWdp b24tPm9mZnNldCA9ICgocWVjYy0+c3RlcHMgLSAxKSAqIHFlY2MtPmJ5dGVzKSArIHFlY2MtPmJi bV9zaXplOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwoKLi4uCgo+ICtzdGF0aWMgaW50IHFj b21fc3BpX2VjY19wcmVwYXJlX2lvX3JlcV9waXBlbGluZWQoc3RydWN0IG5hbmRfZGV2aWNlICpu YW5kLAo+ICsJCQkJCQkgc3RydWN0IG5hbmRfcGFnZV9pb19yZXEgKnJlcSkKPiArewo+ICsJc3Ry dWN0IHFjb21fbmFuZF9jb250cm9sbGVyICpzbmFuZGMgPSBuYW5kX3RvX3Fjb21fc25hbmQobmFu ZCk7Cj4gKwlzdHJ1Y3QgcXBpY19lY2MgKmVjY19jZmcgPSBuYW5kX3RvX2VjY19jdHgobmFuZCk7 Cj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IG5hbmRkZXZfdG9fbXRkKG5hbmQpOwo+ICsKPiAr CXNuYW5kYy0+cXNwaS0+ZWNjID0gZWNjX2NmZzsKPiArCXNuYW5kYy0+cXNwaS0+cGFnZXNpemUg PSBtdGQtPndyaXRlc2l6ZTsKPiArCXNuYW5kYy0+cXNwaS0+cmF3X3J3ID0gZmFsc2U7Cj4gKwlz bmFuZGMtPnFzcGktPm9vYl9ydyA9IGZhbHNlOwo+ICsJc25hbmRjLT5xc3BpLT5wYWdlX3J3ID0g ZmFsc2U7Cj4gKwo+ICsJaWYgKHJlcS0+ZGF0YWxlbikKPiArCQlzbmFuZGMtPnFzcGktPnBhZ2Vf cncgPSB0cnVlOwo+ICsKPiArCWlmIChyZXEtPm9vYmxlbikgewo+ICsJCXNuYW5kYy0+cXNwaS0+ b29iX3J3ID0gdHJ1ZTsKPiArCQlpZiAocmVxLT5vb2JsZW4gPT0gQkFEX0JMT0NLX01BUktFUl9T SVpFKQo+ICsJCQlzbmFuZGMtPnFzcGktPnJlYWRfbGFzdF9jdyA9IHRydWU7Cgo/Pz8KCj4gKwl9 Cj4gKwo+ICsJaWYgKHJlcS0+bW9kZSA9PSBNVERfT1BTX1JBVykKPiArCQlzbmFuZGMtPnFzcGkt PnJhd19ydyA9IHRydWU7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQg cWNvbV9zcGlfZWNjX2ZpbmlzaF9pb19yZXFfcGlwZWxpbmVkKHN0cnVjdCBuYW5kX2RldmljZSAq bmFuZCwKPiArCQkJCQkJc3RydWN0IG5hbmRfcGFnZV9pb19yZXEgKnJlcSkKPiArewo+ICsJc3Ry dWN0IHFjb21fbmFuZF9jb250cm9sbGVyICpzbmFuZGMgPSBuYW5kX3RvX3Fjb21fc25hbmQobmFu ZCk7Cj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IG5hbmRkZXZfdG9fbXRkKG5hbmQpOwo+ICsK PiArCWlmIChyZXEtPm1vZGUgPT0gTVREX09QU19SQVcgfHwgcmVxLT50eXBlICE9IE5BTkRfUEFH RV9SRUFEKQo+ICsJCXJldHVybiAwOwo+ICsKPiArCWlmIChzbmFuZGMtPnFzcGktPmVjY19zdGF0 cy5mYWlsZWQpCj4gKwkJbXRkLT5lY2Nfc3RhdHMuZmFpbGVkICs9IHNuYW5kYy0+cXNwaS0+ZWNj X3N0YXRzLmZhaWxlZDsKPiArCW10ZC0+ZWNjX3N0YXRzLmNvcnJlY3RlZCArPSBzbmFuZGMtPnFz cGktPmVjY19zdGF0cy5jb3JyZWN0ZWQ7CgpTZWVtcyBzdHJhbmdlCgo+ICsKPiArCWlmIChzbmFu ZGMtPnFzcGktPmVjY19zdGF0cy5mYWlsZWQpCj4gKwkJcmV0dXJuIC1FQkFETVNHOwo+ICsJZWxz ZQo+ICsJCXJldHVybiBzbmFuZGMtPnFzcGktPmVjY19zdGF0cy5iaXRmbGlwczsKPiArfQo+ICsK PiArc3RhdGljIHN0cnVjdCBuYW5kX2VjY19lbmdpbmVfb3BzIHFjb21fc3BpX2VjY19lbmdpbmVf b3BzX3BpcGVsaW5lZCA9IHsKPiArCS5pbml0X2N0eCA9IHFjb21fc3BpX2VjY19pbml0X2N0eF9w aXBlbGluZWQsCj4gKwkuY2xlYW51cF9jdHggPSBxY29tX3NwaV9lY2NfY2xlYW51cF9jdHhfcGlw ZWxpbmVkLAo+ICsJLnByZXBhcmVfaW9fcmVxID0gcWNvbV9zcGlfZWNjX3ByZXBhcmVfaW9fcmVx X3BpcGVsaW5lZCwKPiArCS5maW5pc2hfaW9fcmVxID0gcWNvbV9zcGlfZWNjX2ZpbmlzaF9pb19y ZXFfcGlwZWxpbmVkLAo+ICt9Owo+ICsKCi4uLgoKPiArc3RhdGljIGludCBxY29tX3NwaV9yZWFk X3BhZ2VfcmF3KHN0cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqc25hbmRjLAo+ICsJCQkJICBj b25zdCBzdHJ1Y3Qgc3BpX21lbV9vcCAqb3ApCj4gK3sKPiArCXN0cnVjdCBxcGljX2VjYyAqZWNj X2NmZyA9IHNuYW5kYy0+cXNwaS0+ZWNjOwo+ICsJdTggKmRhdGFfYnVmID0gTlVMTCwgKm9vYl9i dWYgPSBOVUxMOwo+ICsJaW50IHJldCwgY3c7Cj4gKwl1MzIgbnVtX2N3ID0gc25hbmRjLT5xc3Bp LT5udW1fY3c7Cj4gKwo+ICsJaWYgKHNuYW5kYy0+cXNwaS0+cGFnZV9ydykKCkkgZG9uJ3QgbGlr ZSB0aGlzIGluZGlyZWN0aW9uIHZlcnkgbXVjaC4gQ2FuJ3QgeW91IHNpbXBsaWZ5IHRoaXMgYW5k Cmp1c3QgZm9sbG93IHRoZSBzcGktbWVtIG9wIGluc3RlYWQgb2YgY29uc3RhbnRseSB0cnlpbmcg dG8gYWRkCmFkZGl0aW9uYWwgc3R1ZmY/CgpUaGUgaGFyZHdhcmUgaXMgYWxyZWFkeSBxdWl0ZSBj b21wbGV4LCBidXQgaXQgZmVlbHMgbGlrZSB5b3VyIGFkZGluZwp5ZXQgYW5vdGhlciBwaWxlIG9m IHVubmVjZXNzYXJ5IGNvbXBsZXhpdHkuCgo+ICsJCWRhdGFfYnVmID0gb3AtPmRhdGEuYnVmLmlu Owo+ICsKPiArCWlmIChzbmFuZGMtPnFzcGktPm9vYl9ydykKPiArCQlvb2JfYnVmID0gb3AtPmRh dGEuYnVmLmluOwoKU2FtZSBidWZmZXIgcG9pbnRlZCBieSB0aGUgdHdvIHBvaW50ZXJzPyBodW0K Cj4gKwo+ICsJaWYgKCFvb2JfYnVmKSB7Cj4gKwkJb29iX2J1ZiA9IHNuYW5kYy0+cXNwaS0+b29i X2J1ZjsKPiArCQltZW1zZXQob29iX2J1ZiwgMHhmZiwgT09CX0JVRl9TSVpFKTsKPiArCX0KPiAr Cj4gKwlmb3IgKGN3ID0gMDsgY3cgPCBudW1fY3c7IGN3KyspIHsKPiArCQlyZXQgPSBxY29tX3Nw aV9yZWFkX2N3X3JhdyhzbmFuZGMsIGRhdGFfYnVmLCBvb2JfYnVmLCBjdyk7Cj4gKwkJaWYgKHJl dCkKPiArCQkJcmV0dXJuIHJldDsKPiArCj4gKwkJaWYgKGRhdGFfYnVmKQo+ICsJCQlkYXRhX2J1 ZiArPSBlY2NfY2ZnLT5jd19kYXRhOwo+ICsJCWlmIChvb2JfYnVmKQo+ICsJCQlvb2JfYnVmICs9 IGVjY19jZmctPmJ5dGVzOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgaW50IHFjb21fc3BpX3JlYWRfcGFnZV9jYWNoZShzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRyb2xs ZXIgKnNuYW5kYywKPiArCQkJCSAgICBjb25zdCBzdHJ1Y3Qgc3BpX21lbV9vcCAqb3ApCj4gK3sK PiArCXN0cnVjdCBxcGljX2VjYyAqZWNjX2NmZyA9IHNuYW5kYy0+cXNwaS0+ZWNjOwo+ICsJdTgg KmRhdGFfYnVmID0gTlVMTCwgKmRhdGFfYnVmX3N0YXJ0LCAqb29iX2J1ZiA9IE5VTEwsICpvb2Jf YnVmX3N0YXJ0Owo+ICsJaW50IHJldCwgaTsKPiArCXUzMiBjZmcwLCBjZmcxLCBlY2NfYmNoX2Nm ZywgbnVtX2N3ID0gc25hbmRjLT5xc3BpLT5udW1fY3c7Cj4gKwo+ICsJaWYgKHNuYW5kYy0+cXNw aS0+cGFnZV9ydykgewo+ICsJCWRhdGFfYnVmID0gb3AtPmRhdGEuYnVmLmluOwo+ICsJCWRhdGFf YnVmX3N0YXJ0ID0gZGF0YV9idWY7Cj4gKwl9Cj4gKwo+ICsJaWYgKHNuYW5kYy0+cXNwaS0+b29i X3J3IHx8IHNuYW5kYy0+cXNwaS0+cmF3X3J3KSB7Cj4gKwkJb29iX2J1ZiA9IG9wLT5kYXRhLmJ1 Zi5pbjsKPiArCQlvb2JfYnVmX3N0YXJ0ID0gb29iX2J1ZjsKPiArCX0KPiArCj4gKwlpZiAoc25h bmRjLT5xc3BpLT5wYWdlX3J3ICYmIHNuYW5kYy0+cXNwaS0+cmF3X3J3KQo+ICsJCXJldHVybiBx Y29tX3NwaV9yZWFkX3BhZ2VfcmF3KHNuYW5kYywgb3ApOwo+ICsKPiArCWlmIChzbmFuZGMtPnFz cGktPm9vYl9ydyAmJiBzbmFuZGMtPnFzcGktPnJhd19ydyAmJiBzbmFuZGMtPnFzcGktPnJlYWRf bGFzdF9jdykKPiArCQlyZXR1cm4gcWNvbV9zcGlfcmVhZF9sYXN0X2N3KHNuYW5kYywgb3ApOwo+ ICsKPiArCXNuYW5kYy0+YnVmX2NvdW50ID0gMDsKPiArCXNuYW5kYy0+YnVmX3N0YXJ0ID0gMDsK PiArCXFjb21fY2xlYXJfcmVhZF9yZWdzKHNuYW5kYyk7Cj4gKwo+ICsJY2ZnMCA9IChlY2NfY2Zn LT5jZmcwICYgfig3VSA8PCBDV19QRVJfUEFHRSkpIHwKPiArCQkJCShudW1fY3cgLSAxKSA8PCBD V19QRVJfUEFHRTsKPiArCWNmZzEgPSBlY2NfY2ZnLT5jZmcxOwo+ICsJZWNjX2JjaF9jZmcgPSBl Y2NfY2ZnLT5lY2NfYmNoX2NmZzsKPiArCj4gKwlzbmFuZGMtPnJlZ3MtPmFkZHIwID0gc25hbmRj LT5xc3BpLT5hZGRyMTsKPiArCXNuYW5kYy0+cmVncy0+YWRkcjEgPSBzbmFuZGMtPnFzcGktPmFk ZHIyOwo+ICsJc25hbmRjLT5yZWdzLT5jbWQgPSBzbmFuZGMtPnFzcGktPmNtZDsKPiArCXNuYW5k Yy0+cmVncy0+Y2ZnMCA9IGNmZzA7Cj4gKwlzbmFuZGMtPnJlZ3MtPmNmZzEgPSBjZmcxOwo+ICsJ c25hbmRjLT5yZWdzLT5lY2NfYmNoX2NmZyA9IGVjY19iY2hfY2ZnOwo+ICsJc25hbmRjLT5yZWdz LT5jbHJmbGFzaHN0YXR1cyA9IGVjY19jZmctPmNscmZsYXNoc3RhdHVzOwo+ICsJc25hbmRjLT5y ZWdzLT5jbHJyZWFkc3RhdHVzID0gZWNjX2NmZy0+Y2xycmVhZHN0YXR1czsKPiArCXNuYW5kYy0+ cmVncy0+ZXhlYyA9IDE7Cj4gKwo+ICsJcWNvbV9zcGlfc2V0X3JlYWRfbG9jKHNuYW5kYywgMCwg MCwgMCwgZWNjX2NmZy0+Y3dfZGF0YSwgMSk7Cj4gKwo+ICsJcWNvbV9jbGVhcl9iYW1fdHJhbnNh Y3Rpb24oc25hbmRjKTsKPiArCj4gKwlxY29tX3dyaXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRj LT5yZWdzLT5hZGRyMCwgTkFORF9BRERSMCwgMiwgMCk7Cj4gKwlxY29tX3dyaXRlX3JlZ19kbWEo c25hbmRjLCAmc25hbmRjLT5yZWdzLT5jZmcwLCBOQU5EX0RFVjBfQ0ZHMCwgMywgMCk7Cj4gKwlx Y29tX3dyaXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRjLT5yZWdzLT5lcmFzZWRfY3dfZGV0ZWN0 X2NmZ19jbHIsCj4gKwkJCSAgIE5BTkRfRVJBU0VEX0NXX0RFVEVDVF9DRkcsIDEsIDApOwo+ICsJ cWNvbV93cml0ZV9yZWdfZG1hKHNuYW5kYywgJnNuYW5kYy0+cmVncy0+ZXJhc2VkX2N3X2RldGVj dF9jZmdfc2V0LAo+ICsJCQkgICBOQU5EX0VSQVNFRF9DV19ERVRFQ1RfQ0ZHLCAxLAo+ICsJCQkg ICBOQU5EX0VSQVNFRF9DV19TRVQgfCBOQU5EX0JBTV9ORVhUX1NHTCk7Cj4gKwo+ICsJZm9yIChp ID0gMDsgaSA8IG51bV9jdzsgaSsrKSB7Cj4gKwkJaW50IGRhdGFfc2l6ZSwgb29iX3NpemU7Cj4g Kwo+ICsJCWlmIChpID09IChudW1fY3cgLSAxKSkgewo+ICsJCQlkYXRhX3NpemUgPSA1MTIgLSAo KG51bV9jdyAtIDEpIDw8IDIpOwo+ICsJCQlvb2Jfc2l6ZSA9IChudW1fY3cgPDwgMikgKyBlY2Nf Y2ZnLT5lY2NfYnl0ZXNfaHcgKwo+ICsJCQkJICAgIGVjY19jZmctPnNwYXJlX2J5dGVzOwo+ICsJ CX0gZWxzZSB7Cj4gKwkJCWRhdGFfc2l6ZSA9IGVjY19jZmctPmN3X2RhdGE7Cj4gKwkJCW9vYl9z aXplID0gZWNjX2NmZy0+ZWNjX2J5dGVzX2h3ICsgZWNjX2NmZy0+c3BhcmVfYnl0ZXM7Cj4gKwkJ fQo+ICsKPiArCQlpZiAoZGF0YV9idWYgJiYgb29iX2J1Zikgewo+ICsJCQlxY29tX3NwaV9zZXRf cmVhZF9sb2Moc25hbmRjLCBpLCAwLCAwLCBkYXRhX3NpemUsIDApOwo+ICsJCQlxY29tX3NwaV9z ZXRfcmVhZF9sb2Moc25hbmRjLCBpLCAxLCBkYXRhX3NpemUsIG9vYl9zaXplLCAxKTsKPiArCQl9 IGVsc2UgaWYgKGRhdGFfYnVmKSB7Cj4gKwkJCXFjb21fc3BpX3NldF9yZWFkX2xvYyhzbmFuZGMs IGksIDAsIDAsIGRhdGFfc2l6ZSwgMSk7Cj4gKwkJfSBlbHNlIHsKPiArCQkJcWNvbV9zcGlfc2V0 X3JlYWRfbG9jKHNuYW5kYywgaSwgMCwgZGF0YV9zaXplLCBvb2Jfc2l6ZSwgMSk7Cj4gKwkJfQo+ ICsKPiArCQlxY29tX3NwaV9jb25maWdfY3dfcmVhZChzbmFuZGMsIHRydWUsIGkpOwo+ICsKPiAr CQlpZiAoZGF0YV9idWYpCj4gKwkJCXFjb21fcmVhZF9kYXRhX2RtYShzbmFuZGMsIEZMQVNIX0JV Rl9BQ0MsIGRhdGFfYnVmLAo+ICsJCQkJCSAgIGRhdGFfc2l6ZSwgMCk7Cj4gKwkJaWYgKG9vYl9i dWYpIHsKPiArCQkJaW50IGo7Cj4gKwo+ICsJCQlmb3IgKGogPSAwOyBqIDwgZWNjX2NmZy0+YmJt X3NpemU7IGorKykKPiArCQkJCSpvb2JfYnVmKysgPSAweGZmOwo+ICsKPiArCQkJcWNvbV9yZWFk X2RhdGFfZG1hKHNuYW5kYywgRkxBU0hfQlVGX0FDQyArIGRhdGFfc2l6ZSwKPiArCQkJCQkgICBv b2JfYnVmLCBvb2Jfc2l6ZSwgMCk7Cj4gKwkJfQo+ICsKPiArCQlpZiAoZGF0YV9idWYpCj4gKwkJ CWRhdGFfYnVmICs9IGRhdGFfc2l6ZTsKPiArCQlpZiAob29iX2J1ZikKPiArCQkJb29iX2J1ZiAr PSBvb2Jfc2l6ZTsKPiArCX0KPiArCj4gKwlyZXQgPSBxY29tX3N1Ym1pdF9kZXNjcyhzbmFuZGMp Owo+ICsJaWYgKHJldCkgewo+ICsJCWRldl9lcnIoc25hbmRjLT5kZXYsICJmYWlsdXJlIHRvIHJl YWQgcGFnZVxuIik7Cj4gKwkJcmV0dXJuIHJldDsKPiArCX0KPiArCj4gKwlyZXR1cm4gcWNvbV9z cGlfY2hlY2tfZXJyb3Ioc25hbmRjLCBkYXRhX2J1Zl9zdGFydCwgb29iX2J1Zl9zdGFydCk7Cj4g K30KPiArCj4gK3N0YXRpYyB2b2lkIHFjb21fc3BpX2NvbmZpZ19wYWdlX3dyaXRlKHN0cnVjdCBx Y29tX25hbmRfY29udHJvbGxlciAqc25hbmRjKQo+ICt7Cj4gKwlxY29tX3dyaXRlX3JlZ19kbWEo c25hbmRjLCAmc25hbmRjLT5yZWdzLT5hZGRyMCwgTkFORF9BRERSMCwgMiwgMCk7Cj4gKwlxY29t X3dyaXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRjLT5yZWdzLT5jZmcwLCBOQU5EX0RFVjBfQ0ZH MCwgMywgMCk7Cj4gKwlxY29tX3dyaXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRjLT5yZWdzLT5l Y2NfYnVmX2NmZywgTkFORF9FQkkyX0VDQ19CVUZfQ0ZHLAo+ICsJCQkgICAxLCBOQU5EX0JBTV9O RVhUX1NHTCk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHFjb21fc3BpX2NvbmZpZ19jd193cml0 ZShzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRyb2xsZXIgKnNuYW5kYykKPiArewo+ICsJcWNvbV93cml0 ZV9yZWdfZG1hKHNuYW5kYywgJnNuYW5kYy0+cmVncy0+Y21kLCBOQU5EX0ZMQVNIX0NNRCwgMSwg TkFORF9CQU1fTkVYVF9TR0wpOwo+ICsJcWNvbV93cml0ZV9yZWdfZG1hKHNuYW5kYywgJnNuYW5k Yy0+cmVncy0+ZXhlYywgTkFORF9FWEVDX0NNRCwgMSwgTkFORF9CQU1fTkVYVF9TR0wpOwo+ICsJ cWNvbV9yZWFkX3JlZ19kbWEoc25hbmRjLCBOQU5EX0ZMQVNIX1NUQVRVUywgMSwgTkFORF9CQU1f TkVYVF9TR0wpOwo+ICsKPiArCXFjb21fd3JpdGVfcmVnX2RtYShzbmFuZGMsICZzbmFuZGMtPnJl Z3MtPmNscmZsYXNoc3RhdHVzLCBOQU5EX0ZMQVNIX1NUQVRVUywgMSwgMCk7Cj4gKwlxY29tX3dy aXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRjLT5yZWdzLT5jbHJyZWFkc3RhdHVzLCBOQU5EX1JF QURfU1RBVFVTLCAxLAo+ICsJCQkgICBOQU5EX0JBTV9ORVhUX1NHTCk7Cj4gK30KPiArCj4gK3N0 YXRpYyBpbnQgcWNvbV9zcGlfcHJvZ3JhbV9yYXcoc3RydWN0IHFjb21fbmFuZF9jb250cm9sbGVy ICpzbmFuZGMsCj4gKwkJCQljb25zdCBzdHJ1Y3Qgc3BpX21lbV9vcCAqb3ApCj4gK3sKPiArCXN0 cnVjdCBxcGljX2VjYyAqZWNjX2NmZyA9IHNuYW5kYy0+cXNwaS0+ZWNjOwo+ICsJdTggKmRhdGFf YnVmID0gTlVMTCwgKm9vYl9idWYgPSBOVUxMOwo+ICsJaW50IGksIHJldDsKPiArCWludCBudW1f Y3cgPSBzbmFuZGMtPnFzcGktPm51bV9jdzsKPiArCXUzMiBjZmcwLCBjZmcxLCBlY2NfYmNoX2Nm ZzsKPiArCj4gKwljZmcwID0gKGVjY19jZmctPmNmZzBfcmF3ICYgfig3VSA8PCBDV19QRVJfUEFH RSkpIHwKPiArCQkJKG51bV9jdyAtIDEpIDw8IENXX1BFUl9QQUdFOwo+ICsJY2ZnMSA9IGVjY19j ZmctPmNmZzFfcmF3Owo+ICsJZWNjX2JjaF9jZmcgPSBFQ0NfQ0ZHX0VDQ19ESVNBQkxFOwo+ICsK PiArCWRhdGFfYnVmID0gc25hbmRjLT5xc3BpLT5kYXRhX2J1ZjsKPiArCj4gKwlvb2JfYnVmID0g c25hbmRjLT5xc3BpLT5vb2JfYnVmOwo+ICsJbWVtc2V0KG9vYl9idWYsIDB4ZmYsIE9PQl9CVUZf U0laRSk7Cj4gKwo+ICsJc25hbmRjLT5idWZfY291bnQgPSAwOwo+ICsJc25hbmRjLT5idWZfc3Rh cnQgPSAwOwo+ICsJcWNvbV9jbGVhcl9yZWFkX3JlZ3Moc25hbmRjKTsKPiArCXFjb21fY2xlYXJf YmFtX3RyYW5zYWN0aW9uKHNuYW5kYyk7Cj4gKwo+ICsJc25hbmRjLT5yZWdzLT5hZGRyMCA9IHNu YW5kYy0+cXNwaS0+YWRkcjE7Cj4gKwlzbmFuZGMtPnJlZ3MtPmFkZHIxID0gc25hbmRjLT5xc3Bp LT5hZGRyMjsKPiArCXNuYW5kYy0+cmVncy0+Y21kID0gc25hbmRjLT5xc3BpLT5jbWQ7Cj4gKwlz bmFuZGMtPnJlZ3MtPmNmZzAgPSBjZmcwOwo+ICsJc25hbmRjLT5yZWdzLT5jZmcxID0gY2ZnMTsK PiArCXNuYW5kYy0+cmVncy0+ZWNjX2JjaF9jZmcgPSBlY2NfYmNoX2NmZzsKPiArCXNuYW5kYy0+ cmVncy0+Y2xyZmxhc2hzdGF0dXMgPSBlY2NfY2ZnLT5jbHJmbGFzaHN0YXR1czsKPiArCXNuYW5k Yy0+cmVncy0+Y2xycmVhZHN0YXR1cyA9IGVjY19jZmctPmNscnJlYWRzdGF0dXM7Cj4gKwlzbmFu ZGMtPnJlZ3MtPmV4ZWMgPSAxOwo+ICsKPiArCXFjb21fc3BpX2NvbmZpZ19wYWdlX3dyaXRlKHNu YW5kYyk7Cj4gKwo+ICsJZm9yIChpID0gMDsgaSA8IG51bV9jdzsgaSsrKSB7Cj4gKwkJaW50IGRh dGFfc2l6ZTEsIGRhdGFfc2l6ZTIsIG9vYl9zaXplMSwgb29iX3NpemUyOwo+ICsJCWludCByZWdf b2ZmID0gRkxBU0hfQlVGX0FDQzsKPiArCj4gKwkJZGF0YV9zaXplMSA9IHNuYW5kYy0+cXNwaS0+ cGFnZXNpemUgLSBlY2NfY2ZnLT5jd19zaXplICogKG51bV9jdyAtIDEpOwo+ICsJCW9vYl9zaXpl MSA9IGVjY19jZmctPmJibV9zaXplOwo+ICsKPiArCQlpZiAoKGkgPT0gKG51bV9jdyAtIDEpKSkg ewo+ICsJCQlkYXRhX3NpemUyID0gTkFORENfU1RFUF9TSVpFIC0gZGF0YV9zaXplMSAtCj4gKwkJ CQkgICAgICgobnVtX2N3IC0gMSkgPDwgMik7Cj4gKwkJCW9vYl9zaXplMiA9IChudW1fY3cgPDwg MikgKyBlY2NfY2ZnLT5lY2NfYnl0ZXNfaHcgKwo+ICsJCQkJICAgIGVjY19jZmctPnNwYXJlX2J5 dGVzOwo+ICsJCX0gZWxzZSB7Cj4gKwkJCWRhdGFfc2l6ZTIgPSBlY2NfY2ZnLT5jd19kYXRhIC0g ZGF0YV9zaXplMTsKPiArCQkJb29iX3NpemUyID0gZWNjX2NmZy0+ZWNjX2J5dGVzX2h3ICsgZWNj X2NmZy0+c3BhcmVfYnl0ZXM7Cj4gKwkJfQo+ICsKPiArCQlxY29tX3dyaXRlX2RhdGFfZG1hKHNu YW5kYywgcmVnX29mZiwgZGF0YV9idWYsIGRhdGFfc2l6ZTEsCj4gKwkJCQkgICAgTkFORF9CQU1f Tk9fRU9UKTsKPiArCQlyZWdfb2ZmICs9IGRhdGFfc2l6ZTE7Cj4gKwkJZGF0YV9idWYgKz0gZGF0 YV9zaXplMTsKPiArCj4gKwkJcWNvbV93cml0ZV9kYXRhX2RtYShzbmFuZGMsIHJlZ19vZmYsIG9v Yl9idWYsIG9vYl9zaXplMSwKPiArCQkJCSAgICBOQU5EX0JBTV9OT19FT1QpOwo+ICsJCW9vYl9i dWYgKz0gb29iX3NpemUxOwo+ICsJCXJlZ19vZmYgKz0gb29iX3NpemUxOwo+ICsKPiArCQlxY29t X3dyaXRlX2RhdGFfZG1hKHNuYW5kYywgcmVnX29mZiwgZGF0YV9idWYsIGRhdGFfc2l6ZTIsCj4g KwkJCQkgICAgTkFORF9CQU1fTk9fRU9UKTsKPiArCQlyZWdfb2ZmICs9IGRhdGFfc2l6ZTI7Cj4g KwkJZGF0YV9idWYgKz0gZGF0YV9zaXplMjsKPiArCj4gKwkJcWNvbV93cml0ZV9kYXRhX2RtYShz bmFuZGMsIHJlZ19vZmYsIG9vYl9idWYsIG9vYl9zaXplMiwgMCk7Cj4gKwkJb29iX2J1ZiArPSBv b2Jfc2l6ZTI7Cj4gKwo+ICsJCXFjb21fc3BpX2NvbmZpZ19jd193cml0ZShzbmFuZGMpOwo+ICsJ fQo+ICsKPiArCXJldCA9IHFjb21fc3VibWl0X2Rlc2NzKHNuYW5kYyk7Cj4gKwlpZiAocmV0KSB7 Cj4gKwkJZGV2X2VycihzbmFuZGMtPmRldiwgImZhaWx1cmUgdG8gd3JpdGUgcmF3IHBhZ2VcbiIp Owo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0 YXRpYyBpbnQgcWNvbV9zcGlfcHJvZ3JhbV9leGVjdXRlKHN0cnVjdCBxY29tX25hbmRfY29udHJv bGxlciAqc25hbmRjLAo+ICsJCQkJICAgIGNvbnN0IHN0cnVjdCBzcGlfbWVtX29wICpvcCkKPiAr ewo+ICsJc3RydWN0IHFwaWNfZWNjICplY2NfY2ZnID0gc25hbmRjLT5xc3BpLT5lY2M7Cj4gKwl1 OCAqZGF0YV9idWYgPSBOVUxMLCAqb29iX2J1ZiA9IE5VTEw7Cj4gKwlpbnQgaSwgcmV0Owo+ICsJ aW50IG51bV9jdyA9IHNuYW5kYy0+cXNwaS0+bnVtX2N3Owo+ICsJdTMyIGNmZzAsIGNmZzEsIGVj Y19iY2hfY2ZnLCBlY2NfYnVmX2NmZzsKPiArCj4gKwljZmcwID0gKGVjY19jZmctPmNmZzAgJiB+ KDdVIDw8IENXX1BFUl9QQUdFKSkgfAo+ICsJCQkJKG51bV9jdyAtIDEpIDw8IENXX1BFUl9QQUdF Owo+ICsJY2ZnMSA9IGVjY19jZmctPmNmZzE7Cj4gKwllY2NfYmNoX2NmZyA9IGVjY19jZmctPmVj Y19iY2hfY2ZnOwo+ICsJZWNjX2J1Zl9jZmcgPSBlY2NfY2ZnLT5lY2NfYnVmX2NmZzsKPiArCj4g KwlpZiAoc25hbmRjLT5xc3BpLT5wYWdlX3J3ICYmIHNuYW5kYy0+cXNwaS0+cmF3X3J3KQo+ICsJ CXJldHVybiBxY29tX3NwaV9wcm9ncmFtX3JhdyhzbmFuZGMsIG9wKTsKPiArCj4gKwlpZiAoc25h bmRjLT5xc3BpLT5kYXRhX2J1ZikKPiArCQlkYXRhX2J1ZiA9IHNuYW5kYy0+cXNwaS0+ZGF0YV9i dWY7Cj4gKwo+ICsJaWYgKHNuYW5kYy0+cXNwaS0+b29iX2J1ZikKPiArCQlvb2JfYnVmID0gc25h bmRjLT5xc3BpLT5vb2JfYnVmOwo+ICsKPiArCXNuYW5kYy0+YnVmX2NvdW50ID0gMDsKPiArCXNu YW5kYy0+YnVmX3N0YXJ0ID0gMDsKPiArCXFjb21fY2xlYXJfcmVhZF9yZWdzKHNuYW5kYyk7Cj4g KwlxY29tX2NsZWFyX2JhbV90cmFuc2FjdGlvbihzbmFuZGMpOwo+ICsKPiArCXNuYW5kYy0+cmVn cy0+YWRkcjAgPSBzbmFuZGMtPnFzcGktPmFkZHIxOwo+ICsJc25hbmRjLT5yZWdzLT5hZGRyMSA9 IHNuYW5kYy0+cXNwaS0+YWRkcjI7Cj4gKwlzbmFuZGMtPnJlZ3MtPmNtZCA9IHNuYW5kYy0+cXNw aS0+Y21kOwo+ICsJc25hbmRjLT5yZWdzLT5jZmcwID0gY2ZnMDsKPiArCXNuYW5kYy0+cmVncy0+ Y2ZnMSA9IGNmZzE7Cj4gKwlzbmFuZGMtPnJlZ3MtPmVjY19iY2hfY2ZnID0gZWNjX2JjaF9jZmc7 Cj4gKwlzbmFuZGMtPnJlZ3MtPmVjY19idWZfY2ZnID0gZWNjX2J1Zl9jZmc7Cj4gKwlzbmFuZGMt PnJlZ3MtPmV4ZWMgPSAxOwo+ICsKPiArCXFjb21fc3BpX2NvbmZpZ19wYWdlX3dyaXRlKHNuYW5k Yyk7Cj4gKwo+ICsJZm9yIChpID0gMDsgaSA8IG51bV9jdzsgaSsrKSB7Cj4gKwkJaW50IGRhdGFf c2l6ZSwgb29iX3NpemU7Cj4gKwo+ICsJCWlmIChpID09IChudW1fY3cgLSAxKSkgewo+ICsJCQlk YXRhX3NpemUgPSBOQU5EQ19TVEVQX1NJWkUgLSAoKG51bV9jdyAtIDEpIDw8IDIpOwo+ICsJCQlv b2Jfc2l6ZSA9IChudW1fY3cgPDwgMikgKyBlY2NfY2ZnLT5lY2NfYnl0ZXNfaHcgKwo+ICsJCQkJ ICAgIGVjY19jZmctPnNwYXJlX2J5dGVzOwo+ICsJCX0gZWxzZSB7Cj4gKwkJCWRhdGFfc2l6ZSA9 IGVjY19jZmctPmN3X2RhdGE7Cj4gKwkJCW9vYl9zaXplID0gZWNjX2NmZy0+Ynl0ZXM7Cj4gKwkJ fQo+ICsKPiArCQlpZiAoZGF0YV9idWYpCj4gKwkJCXFjb21fd3JpdGVfZGF0YV9kbWEoc25hbmRj LCBGTEFTSF9CVUZfQUNDLCBkYXRhX2J1ZiwgZGF0YV9zaXplLAo+ICsJCQkJCSAgICBpID09IChu dW1fY3cgLSAxKSA/IE5BTkRfQkFNX05PX0VPVCA6IDApOwo+ICsKPiArCQlpZiAoaSA9PSAobnVt X2N3IC0gMSkpIHsKPiArCQkJaWYgKG9vYl9idWYpIHsKPiArCQkJCW9vYl9idWYgKz0gZWNjX2Nm Zy0+YmJtX3NpemU7Cj4gKwkJCQlxY29tX3dyaXRlX2RhdGFfZG1hKHNuYW5kYywgRkxBU0hfQlVG X0FDQyArIGRhdGFfc2l6ZSwKPiArCQkJCQkJICAgIG9vYl9idWYsIG9vYl9zaXplLCAwKTsKPiAr CQkJfQo+ICsJCX0KPiArCj4gKwkJcWNvbV9zcGlfY29uZmlnX2N3X3dyaXRlKHNuYW5kYyk7Cj4g Kwo+ICsJCWlmIChkYXRhX2J1ZikKPiArCQkJZGF0YV9idWYgKz0gZGF0YV9zaXplOwo+ICsJCWlm IChvb2JfYnVmKQo+ICsJCQlvb2JfYnVmICs9IG9vYl9zaXplOwo+ICsJfQo+ICsKPiArCXJldCA9 IHFjb21fc3VibWl0X2Rlc2NzKHNuYW5kYyk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZGV2X2Vycihz bmFuZGMtPmRldiwgImZhaWx1cmUgdG8gd3JpdGUgcGFnZVxuIik7Cj4gKwkJcmV0dXJuIHJldDsK PiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHUzMiBxY29tX3NwaV9j bWRfbWFwcGluZyhzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRyb2xsZXIgKnNuYW5kYywgdTMyIG9wY29k ZSkKPiArewo+ICsJdTMyIGNtZCA9IDB4MDsKPiArCj4gKwlzd2l0Y2ggKG9wY29kZSkgewo+ICsJ Y2FzZSBTUElOQU5EX1JFU0VUOgo+ICsJCWNtZCA9IChTUElfV1AgfCBTUElfSE9MRCB8IFNQSV9U UkFOU0ZFUl9NT0RFX3gxIHwgT1BfUkVTRVRfREVWSUNFKTsKPiArCQlicmVhazsKPiArCWNhc2Ug U1BJTkFORF9SRUFESUQ6Cj4gKwkJY21kID0gKFNQSV9XUCB8IFNQSV9IT0xEIHwgU1BJX1RSQU5T RkVSX01PREVfeDEgfCBPUF9GRVRDSF9JRCk7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFNQSU5BTkRf R0VUX0ZFQVRVUkU6Cj4gKwkJY21kID0gKFNQSV9UUkFOU0ZFUl9NT0RFX3gxIHwgU1BJX1dQIHwg U1BJX0hPTEQgfCBBQ0NfRkVBVFVSRSk7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFNQSU5BTkRfU0VU X0ZFQVRVUkU6Cj4gKwkJY21kID0gKFNQSV9UUkFOU0ZFUl9NT0RFX3gxIHwgU1BJX1dQIHwgU1BJ X0hPTEQgfCBBQ0NfRkVBVFVSRSB8Cj4gKwkJCVFQSUNfU0VUX0ZFQVRVUkUpOwo+ICsJCWJyZWFr Owo+ICsJY2FzZSBTUElOQU5EX1JFQUQ6Cj4gKwkJaWYgKHNuYW5kYy0+cXNwaS0+cmF3X3J3KSB7 Cj4gKwkJCWNtZCA9IChQQUdFX0FDQyB8IExBU1RfUEFHRSB8IFNQSV9UUkFOU0ZFUl9NT0RFX3gx IHwKPiArCQkJCQlTUElfV1AgfCBTUElfSE9MRCB8IE9QX1BBR0VfUkVBRCk7Cj4gKwkJfSBlbHNl IHsKPiArCQkJY21kID0gKFBBR0VfQUNDIHwgTEFTVF9QQUdFIHwgU1BJX1RSQU5TRkVSX01PREVf eDEgfAo+ICsJCQkJCVNQSV9XUCB8IFNQSV9IT0xEIHwgT1BfUEFHRV9SRUFEX1dJVEhfRUNDKTsK PiArCQl9Cj4gKwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBTUElOQU5EX0VSQVNFOgo+ICsJCWNtZCA9 IE9QX0JMT0NLX0VSQVNFIHwgUEFHRV9BQ0MgfCBMQVNUX1BBR0UgfCBTUElfV1AgfAo+ICsJCQlT UElfSE9MRCB8IFNQSV9UUkFOU0ZFUl9NT0RFX3gxOwo+ICsJCWJyZWFrOwo+ICsJY2FzZSBTUElO QU5EX1dSSVRFX0VOOgo+ICsJCWNtZCA9IFNQSU5BTkRfV1JJVEVfRU47Cj4gKwkJYnJlYWs7Cj4g KwljYXNlIFNQSU5BTkRfUFJPR1JBTV9FWEVDVVRFOgo+ICsJCWNtZCA9IChQQUdFX0FDQyB8IExB U1RfUEFHRSB8IFNQSV9UUkFOU0ZFUl9NT0RFX3gxIHwKPiArCQkJCVNQSV9XUCB8IFNQSV9IT0xE IHwgT1BfUFJPR1JBTV9QQUdFKTsKPiArCQlicmVhazsKPiArCWNhc2UgU1BJTkFORF9QUk9HUkFN X0xPQUQ6Cj4gKwkJY21kID0gU1BJTkFORF9QUk9HUkFNX0xPQUQ7Cj4gKwkJYnJlYWs7Cj4gKwlk ZWZhdWx0Ogo+ICsJCWRldl9lcnIoc25hbmRjLT5kZXYsICJPcGNvZGUgbm90IHN1cHBvcnRlZDog JXVcbiIsIG9wY29kZSk7Cj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+ICsJfQo+ICsKPiArCXJl dHVybiBjbWQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcWNvbV9zcGlfd3JpdGVfcGFnZV9jYWNo ZShzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRyb2xsZXIgKnNuYW5kYywKPiArCQkJCSAgICAgY29uc3Qg c3RydWN0IHNwaV9tZW1fb3AgKm9wKQo+ICt7Cj4gKwlzdHJ1Y3QgcXBpY19zbmFuZF9vcCBzX29w ID0ge307Cj4gKwl1MzIgY21kOwo+ICsKPiArCWNtZCA9IHFjb21fc3BpX2NtZF9tYXBwaW5nKHNu YW5kYywgb3AtPmNtZC5vcGNvZGUpOwoKSSd2ZSBhc2tlZCBmb3Igc3dpdGNoIGNhc2VzIHRvIHJl dHVybiBhbiBlcnJvciBpbiBjYXNlIHRoZXkgY291bGQgbm90CmhhbmRsZSB0aGUgcmVxdWVzdC4g SWYgeW91IGRvbid0IGNoZWNrIHRoZSByZXR1cm5lZCB2YWx1ZXMsIGl0CmRvZXMgbm90IG1ha2Ug YW55IHNlbnNlLgoKPiArCXNfb3AuY21kX3JlZyA9IGNtZDsKPiArCj4gKwlpZiAob3AtPmNtZC5v cGNvZGUgPT0gU1BJTkFORF9QUk9HUkFNX0xPQUQpIHsKPiArCQlpZiAoc25hbmRjLT5xc3BpLT5w YWdlX3J3KQo+ICsJCQlzbmFuZGMtPnFzcGktPmRhdGFfYnVmID0gKHU4ICopb3AtPmRhdGEuYnVm Lm91dDsKCldoYXQgeW91IGRvIGhlcmUgZG9lcyBub3Qgd3JpdGUgYW55dGhpbmcgaW4gYSBwYWdl IGNhY2hlLgoKSSBhbHNvIGRvbid0IHVuZGVyc3RhbmQgd2h5IHlvdSB3b3VsZCBoYXZlIHRvIGNo ZWNrIGFnYWluc3QgdGhlClNQSU5BTkRfUFJPR1JBTV9MT0FEIG9wY29kZS4KCj4gKwl9Cj4gKwo+ ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcWNvbV9zcGlfc2VuZF9jbWRhZGRy KHN0cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqc25hbmRjLAo+ICsJCQkJIGNvbnN0IHN0cnVj dCBzcGlfbWVtX29wICpvcCkKPiArewo+ICsJc3RydWN0IHFwaWNfc25hbmRfb3Agc19vcCA9IHt9 Owo+ICsJdTMyIGNtZDsKPiArCWludCByZXQsIG9wY29kZTsKPiArCj4gKwljbWQgPSBxY29tX3Nw aV9jbWRfbWFwcGluZyhzbmFuZGMsIG9wLT5jbWQub3Bjb2RlKTsKPiArCj4gKwlzX29wLmNtZF9y ZWcgPSBjbWQ7Cj4gKwlzX29wLmFkZHIxX3JlZyA9IG9wLT5hZGRyLnZhbDsKPiArCXNfb3AuYWRk cjJfcmVnID0gMDsKPiArCj4gKwlvcGNvZGUgPSBvcC0+Y21kLm9wY29kZTsKPiArCj4gKwlzd2l0 Y2ggKG9wY29kZSkgewo+ICsJY2FzZSBTUElOQU5EX1dSSVRFX0VOOgo+ICsJCXJldHVybiAwOwo+ ICsJY2FzZSBTUElOQU5EX1BST0dSQU1fRVhFQ1VURToKPiArCQlzX29wLmFkZHIxX3JlZyA9IG9w LT5hZGRyLnZhbCA8PCAxNjsKPiArCQlzX29wLmFkZHIyX3JlZyA9IG9wLT5hZGRyLnZhbCA+PiAx NiAmIDB4ZmY7Cj4gKwkJc25hbmRjLT5xc3BpLT5hZGRyMSA9IHNfb3AuYWRkcjFfcmVnOwo+ICsJ CXNuYW5kYy0+cXNwaS0+YWRkcjIgPSBzX29wLmFkZHIyX3JlZzsKPiArCQlzbmFuZGMtPnFzcGkt PmNtZCA9IGNtZDsKPiArCQlyZXR1cm4gcWNvbV9zcGlfcHJvZ3JhbV9leGVjdXRlKHNuYW5kYywg b3ApOwo+ICsJY2FzZSBTUElOQU5EX1JFQUQ6Cj4gKwkJc19vcC5hZGRyMV9yZWcgPSAob3AtPmFk ZHIudmFsIDw8IDE2KTsKPiArCQlzX29wLmFkZHIyX3JlZyA9IG9wLT5hZGRyLnZhbCA+PiAxNiAm IDB4ZmY7Cj4gKwkJc25hbmRjLT5xc3BpLT5hZGRyMSA9IHNfb3AuYWRkcjFfcmVnOwo+ICsJCXNu YW5kYy0+cXNwaS0+YWRkcjIgPSBzX29wLmFkZHIyX3JlZzsKPiArCQlzbmFuZGMtPnFzcGktPmNt ZCA9IGNtZDsKPiArCQlyZXR1cm4gMDsKPiArCWNhc2UgU1BJTkFORF9FUkFTRToKPiArCQlzX29w LmFkZHIyX3JlZyA9IChvcC0+YWRkci52YWwgPj4gMTYpICYgMHhmZmZmOwo+ICsJCXNfb3AuYWRk cjFfcmVnID0gb3AtPmFkZHIudmFsOwo+ICsJCXNuYW5kYy0+cXNwaS0+YWRkcjEgPSAoc19vcC5h ZGRyMV9yZWcgPDwgMTYpOwo+ICsJCXNuYW5kYy0+cXNwaS0+YWRkcjIgPSBzX29wLmFkZHIyX3Jl ZzsKPiArCQlzbmFuZGMtPnFzcGktPmNtZCA9IGNtZDsKPiArCQlxY29tX3NwaV9ibG9ja19lcmFz ZShzbmFuZGMpOwo+ICsJCXJldHVybiAwOwo+ICsJZGVmYXVsdDoKPiArCQlicmVhazsKPiArCX0K PiArCj4gKwlzbmFuZGMtPmJ1Zl9jb3VudCA9IDA7Cj4gKwlzbmFuZGMtPmJ1Zl9zdGFydCA9IDA7 Cj4gKwlxY29tX2NsZWFyX3JlYWRfcmVncyhzbmFuZGMpOwo+ICsJcWNvbV9jbGVhcl9iYW1fdHJh bnNhY3Rpb24oc25hbmRjKTsKPiArCj4gKwlzbmFuZGMtPnJlZ3MtPmNtZCA9IHNfb3AuY21kX3Jl ZzsKPiArCXNuYW5kYy0+cmVncy0+ZXhlYyA9IDE7Cj4gKwlzbmFuZGMtPnJlZ3MtPmFkZHIwID0g c19vcC5hZGRyMV9yZWc7Cj4gKwlzbmFuZGMtPnJlZ3MtPmFkZHIxID0gc19vcC5hZGRyMl9yZWc7 Cj4gKwo+ICsJcWNvbV93cml0ZV9yZWdfZG1hKHNuYW5kYywgJnNuYW5kYy0+cmVncy0+Y21kLCBO QU5EX0ZMQVNIX0NNRCwgMywgTkFORF9CQU1fTkVYVF9TR0wpOwo+ICsJcWNvbV93cml0ZV9yZWdf ZG1hKHNuYW5kYywgJnNuYW5kYy0+cmVncy0+ZXhlYywgTkFORF9FWEVDX0NNRCwgMSwgTkFORF9C QU1fTkVYVF9TR0wpOwo+ICsKPiArCXJldCA9IHFjb21fc3VibWl0X2Rlc2NzKHNuYW5kYyk7Cj4g KwlpZiAocmV0KQo+ICsJCWRldl9lcnIoc25hbmRjLT5kZXYsICJmYWlsdXJlIGluIHNidW1pdHRp bmcgY21kIGRlc2NyaXB0b3JcbiIpOwoKdHlwbwoKPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4g Kwo+ICtzdGF0aWMgaW50IHFjb21fc3BpX2lvX29wKHN0cnVjdCBxY29tX25hbmRfY29udHJvbGxl ciAqc25hbmRjLCBjb25zdCBzdHJ1Y3Qgc3BpX21lbV9vcCAqb3ApCj4gK3sKPiArCWludCByZXQs IHZhbCwgb3Bjb2RlOwo+ICsJYm9vbCBjb3B5ID0gZmFsc2UsIGNvcHlfZnRyID0gZmFsc2U7Cj4g Kwo+ICsJcmV0ID0gcWNvbV9zcGlfc2VuZF9jbWRhZGRyKHNuYW5kYywgb3ApOwo+ICsJaWYgKHJl dCkKPiArCQlyZXR1cm4gcmV0Owo+ICsKPiArCXNuYW5kYy0+YnVmX2NvdW50ID0gMDsKPiArCXNu YW5kYy0+YnVmX3N0YXJ0ID0gMDsKPiArCXFjb21fY2xlYXJfcmVhZF9yZWdzKHNuYW5kYyk7Cj4g KwlxY29tX2NsZWFyX2JhbV90cmFuc2FjdGlvbihzbmFuZGMpOwo+ICsJb3Bjb2RlID0gb3AtPmNt ZC5vcGNvZGU7Cj4gKwo+ICsJc3dpdGNoIChvcGNvZGUpIHsKPiArCWNhc2UgU1BJTkFORF9SRUFE SUQ6Cj4gKwkJc25hbmRjLT5idWZfY291bnQgPSA0Owo+ICsJCXFjb21fcmVhZF9yZWdfZG1hKHNu YW5kYywgTkFORF9SRUFEX0lELCAxLCBOQU5EX0JBTV9ORVhUX1NHTCk7Cj4gKwkJY29weSA9IHRy dWU7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFNQSU5BTkRfR0VUX0ZFQVRVUkU6Cj4gKwkJc25hbmRj LT5idWZfY291bnQgPSA0Owo+ICsJCXFjb21fcmVhZF9yZWdfZG1hKHNuYW5kYywgTkFORF9GTEFT SF9GRUFUVVJFUywgMSwgTkFORF9CQU1fTkVYVF9TR0wpOwo+ICsJCWNvcHlfZnRyID0gdHJ1ZTsK PiArCQlicmVhazsKPiArCWNhc2UgU1BJTkFORF9TRVRfRkVBVFVSRToKPiArCQlzbmFuZGMtPnJl Z3MtPmZsYXNoX2ZlYXR1cmUgPSAqKHUzMiAqKW9wLT5kYXRhLmJ1Zi5vdXQ7Cj4gKwkJcWNvbV93 cml0ZV9yZWdfZG1hKHNuYW5kYywgJnNuYW5kYy0+cmVncy0+Zmxhc2hfZmVhdHVyZSwKPiArCQkJ CSAgIE5BTkRfRkxBU0hfRkVBVFVSRVMsIDEsIE5BTkRfQkFNX05FWFRfU0dMKTsKPiArCQlicmVh azsKPiArCWNhc2UgU1BJTkFORF9SRVNFVDoKPiArCQlyZXR1cm4gMDsKPiArCWNhc2UgU1BJTkFO RF9QUk9HUkFNX0VYRUNVVEU6Cj4gKwkJcmV0dXJuIDA7Cj4gKwljYXNlIFNQSU5BTkRfV1JJVEVf RU46Cj4gKwkJcmV0dXJuIDA7Cj4gKwljYXNlIFNQSU5BTkRfRVJBU0U6Cj4gKwkJcmV0dXJuIDA7 Cj4gKwljYXNlIFNQSU5BTkRfUkVBRDoKPiArCQlyZXR1cm4gMDsKCllvdSBjYW4gc3RhY2sgdGhl IGNhc2VzCgo+ICsJZGVmYXVsdDoKPiArCQlyZXR1cm4gLUVPUE5PVFNVUFA7Cj4gKwl9Cj4gKwo+ ICsJcmV0ID0gcWNvbV9zdWJtaXRfZGVzY3Moc25hbmRjKTsKPiArCWlmIChyZXQpCj4gKwkJZGV2 X2VycihzbmFuZGMtPmRldiwgImZhaWx1cmUgaW4gc3VibWl0dGluZyBkZXNjcmlwdG9yIGZvcjol ZFxuIiwgb3Bjb2RlKTsKPiArCj4gKwlpZiAoY29weSkgewo+ICsJCXFjb21fbmFuZGNfZGV2X3Rv X21lbShzbmFuZGMsIHRydWUpOwo+ICsJCW1lbWNweShvcC0+ZGF0YS5idWYuaW4sIHNuYW5kYy0+ cmVnX3JlYWRfYnVmLCBzbmFuZGMtPmJ1Zl9jb3VudCk7Cj4gKwl9Cj4gKwo+ICsJaWYgKGNvcHlf ZnRyKSB7Cj4gKwkJcWNvbV9uYW5kY19kZXZfdG9fbWVtKHNuYW5kYywgdHJ1ZSk7Cj4gKwkJdmFs ID0gbGUzMl90b19jcHUoKihfX2xlMzIgKilzbmFuZGMtPnJlZ19yZWFkX2J1Zik7Cj4gKwkJdmFs ID4+PSA4Owo+ICsJCW1lbWNweShvcC0+ZGF0YS5idWYuaW4sICZ2YWwsIHNuYW5kYy0+YnVmX2Nv dW50KTsKPiArCX0KPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgYm9vbCBx Y29tX3NwaV9pc19wYWdlX29wKGNvbnN0IHN0cnVjdCBzcGlfbWVtX29wICpvcCkKPiArewo+ICsJ aWYgKG9wLT5hZGRyLmJ1c3dpZHRoICE9IDEgJiYgb3AtPmFkZHIuYnVzd2lkdGggIT0gMiAmJiBv cC0+YWRkci5idXN3aWR0aCAhPSA0KQo+ICsJCXJldHVybiBmYWxzZTsKPiArCj4gKwlpZiAob3At PmRhdGEuZGlyID09IFNQSV9NRU1fREFUQV9JTikgewo+ICsJCWlmIChvcC0+YWRkci5idXN3aWR0 aCA9PSA0ICYmIG9wLT5kYXRhLmJ1c3dpZHRoID09IDQpCj4gKwkJCXJldHVybiB0cnVlOwo+ICsK PiArCQlpZiAob3AtPmFkZHIubmJ5dGVzID09IDIgJiYgb3AtPmFkZHIuYnVzd2lkdGggPT0gMSkK PiArCQkJcmV0dXJuIHRydWU7Cj4gKwo+ICsJfSBlbHNlIGlmIChvcC0+ZGF0YS5kaXIgPT0gU1BJ X01FTV9EQVRBX09VVCkgewo+ICsJCWlmIChvcC0+ZGF0YS5idXN3aWR0aCA9PSA0KQo+ICsJCQly ZXR1cm4gdHJ1ZTsKPiArCQlpZiAob3AtPmFkZHIubmJ5dGVzID09IDIgJiYgb3AtPmFkZHIuYnVz d2lkdGggPT0gMSkKPiArCQkJcmV0dXJuIHRydWU7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIGZhbHNl Owo+ICt9Cj4gKwo+ICtzdGF0aWMgYm9vbCBxY29tX3NwaV9zdXBwb3J0c19vcChzdHJ1Y3Qgc3Bp X21lbSAqbWVtLCBjb25zdCBzdHJ1Y3Qgc3BpX21lbV9vcCAqb3ApCj4gK3sKPiArCWlmICghc3Bp X21lbV9kZWZhdWx0X3N1cHBvcnRzX29wKG1lbSwgb3ApKQo+ICsJCXJldHVybiBmYWxzZTsKPiAr Cj4gKwlpZiAob3AtPmNtZC5uYnl0ZXMgIT0gMSB8fCBvcC0+Y21kLmJ1c3dpZHRoICE9IDEpCj4g KwkJcmV0dXJuIGZhbHNlOwo+ICsKPiArCWlmIChxY29tX3NwaV9pc19wYWdlX29wKG9wKSkKPiAr CQlyZXR1cm4gdHJ1ZTsKPiArCj4gKwlyZXR1cm4gKCghb3AtPmFkZHIubmJ5dGVzIHx8IG9wLT5h ZGRyLmJ1c3dpZHRoID09IDEpICYmCj4gKwkJKCFvcC0+ZHVtbXkubmJ5dGVzIHx8IG9wLT5kdW1t eS5idXN3aWR0aCA9PSAxKSAmJgo+ICsJCSghb3AtPmRhdGEubmJ5dGVzIHx8IG9wLT5kYXRhLmJ1 c3dpZHRoID09IDEpKTsKPiArfQo+ICsKPiArc3RhdGljIGludCBxY29tX3NwaV9leGVjX29wKHN0 cnVjdCBzcGlfbWVtICptZW0sIGNvbnN0IHN0cnVjdCBzcGlfbWVtX29wICpvcCkKPiArewo+ICsJ c3RydWN0IHFjb21fbmFuZF9jb250cm9sbGVyICpzbmFuZGMgPSBzcGlfY29udHJvbGxlcl9nZXRf ZGV2ZGF0YShtZW0tPnNwaS0+Y29udHJvbGxlcik7Cj4gKwo+ICsJZGV2X2RiZyhzbmFuZGMtPmRl diwgIk9QICUwMnggQUREUiAlMDhsbFhAJWQ6JXUgREFUQSAlZDoldSIsIG9wLT5jbWQub3Bjb2Rl LAo+ICsJCW9wLT5hZGRyLnZhbCwgb3AtPmFkZHIuYnVzd2lkdGgsIG9wLT5hZGRyLm5ieXRlcywK PiArCQlvcC0+ZGF0YS5idXN3aWR0aCwgb3AtPmRhdGEubmJ5dGVzKTsKPiArCj4gKwlpZiAocWNv bV9zcGlfaXNfcGFnZV9vcChvcCkpIHsKPiArCQlpZiAob3AtPmRhdGEuZGlyID09IFNQSV9NRU1f REFUQV9JTikKPiArCQkJcmV0dXJuIHFjb21fc3BpX3JlYWRfcGFnZV9jYWNoZShzbmFuZGMsIG9w KTsKPiArCQlpZiAob3AtPmRhdGEuZGlyID09IFNQSV9NRU1fREFUQV9PVVQpCj4gKwkJCXJldHVy biBxY29tX3NwaV93cml0ZV9wYWdlX2NhY2hlKHNuYW5kYywgb3ApOwo+ICsJfSBlbHNlIHsKPiAr CQlyZXR1cm4gcWNvbV9zcGlfaW9fb3Aoc25hbmRjLCBvcCk7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJu IDA7Cj4gK30KPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc3BpX2NvbnRyb2xsZXJfbWVtX29w cyBxY29tX3NwaV9tZW1fb3BzID0gewo+ICsJLnN1cHBvcnRzX29wID0gcWNvbV9zcGlfc3VwcG9y dHNfb3AsCj4gKwkuZXhlY19vcCA9IHFjb21fc3BpX2V4ZWNfb3AsCj4gK307Cj4gKwo+ICtzdGF0 aWMgY29uc3Qgc3RydWN0IHNwaV9jb250cm9sbGVyX21lbV9jYXBzIHFjb21fc3BpX21lbV9jYXBz ID0gewo+ICsJLmVjYyA9IHRydWUsCj4gK307Cj4gKwo+ICtzdGF0aWMgaW50IHFjb21fc3BpX3By b2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiArCXN0cnVjdCBkZXZpY2Ug KmRldiA9ICZwZGV2LT5kZXY7Cj4gKwlzdHJ1Y3Qgc3BpX2NvbnRyb2xsZXIgKmN0bHI7Cj4gKwlz dHJ1Y3QgcWNvbV9uYW5kX2NvbnRyb2xsZXIgKnNuYW5kYzsKPiArCXN0cnVjdCBxcGljX3NwaV9u YW5kICpxc3BpOwo+ICsJc3RydWN0IHFwaWNfZWNjICplY2M7Cj4gKwlzdHJ1Y3QgcmVzb3VyY2Ug KnJlczsKPiArCWNvbnN0IHZvaWQgKmRldl9kYXRhOwo+ICsJaW50IHJldDsKPiArCj4gKwllY2Mg PSBkZXZtX2t6YWxsb2MoZGV2LCBzaXplb2YoKmVjYyksIEdGUF9LRVJORUwpOwo+ICsJaWYgKCFl Y2MpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwo+ICsJcXNwaSA9IGRldm1fa3phbGxvYyhkZXYs IHNpemVvZigqcXNwaSksIEdGUF9LRVJORUwpOwo+ICsJaWYgKCFxc3BpKQo+ICsJCXJldHVybiAt RU5PTUVNOwo+ICsKPiArCWN0bHIgPSBfX2Rldm1fc3BpX2FsbG9jX2NvbnRyb2xsZXIoZGV2LCBz aXplb2YoKnNuYW5kYyksIGZhbHNlKTsKPiArCWlmICghY3RscikKPiArCQlyZXR1cm4gLUVOT01F TTsKPiArCj4gKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2LCBjdGxyKTsKPiArCj4gKwlzbmFu ZGMgPSBzcGlfY29udHJvbGxlcl9nZXRfZGV2ZGF0YShjdGxyKTsKPiArCXFzcGktPnNuYW5kYyA9 IHNuYW5kYzsKPiArCj4gKwlzbmFuZGMtPmRldiA9IGRldjsKPiArCXNuYW5kYy0+cXNwaSA9IHFz cGk7Cj4gKwlzbmFuZGMtPnFzcGktPmN0bHIgPSBjdGxyOwo+ICsJc25hbmRjLT5xc3BpLT5lY2Mg PSBlY2M7Cj4gKwo+ICsJc25hbmRjLT5xc3BpLT5vb2JfYnVmID0gZGV2bV9remFsbG9jKGRldiwg T09CX0JVRl9TSVpFLCBHRlBfS0VSTkVMKTsKPiArCWlmICghc25hbmRjLT5xc3BpLT5vb2JfYnVm KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCWRldl9kYXRhID0gb2ZfZGV2aWNlX2dldF9t YXRjaF9kYXRhKGRldik7Cj4gKwlpZiAoIWRldl9kYXRhKSB7Cj4gKwkJZGV2X2VycigmcGRldi0+ ZGV2LCAiZmFpbGVkIHRvIGdldCBkZXZpY2UgZGF0YVxuIik7Cj4gKwkJcmV0dXJuIC1FTk9ERVY7 Cj4gKwl9Cj4gKwo+ICsJc25hbmRjLT5wcm9wcyA9IGRldl9kYXRhOwo+ICsJc25hbmRjLT5kZXYg PSAmcGRldi0+ZGV2Owo+ICsKPiArCXNuYW5kYy0+Y29yZV9jbGsgPSBkZXZtX2Nsa19nZXQoZGV2 LCAiY29yZSIpOwo+ICsJaWYgKElTX0VSUihzbmFuZGMtPmNvcmVfY2xrKSkKPiArCQlyZXR1cm4g UFRSX0VSUihzbmFuZGMtPmNvcmVfY2xrKTsKPiArCj4gKwlzbmFuZGMtPmFvbl9jbGsgPSBkZXZt X2Nsa19nZXQoZGV2LCAiYW9uIik7Cj4gKwlpZiAoSVNfRVJSKHNuYW5kYy0+YW9uX2NsaykpCj4g KwkJcmV0dXJuIFBUUl9FUlIoc25hbmRjLT5hb25fY2xrKTsKPiArCj4gKwlzbmFuZGMtPnFzcGkt PmlvbWFjcm9fY2xrID0gZGV2bV9jbGtfZ2V0KGRldiwgImlvbSIpOwo+ICsJaWYgKElTX0VSUihz bmFuZGMtPnFzcGktPmlvbWFjcm9fY2xrKSkKPiArCQlyZXR1cm4gUFRSX0VSUihzbmFuZGMtPnFz cGktPmlvbWFjcm9fY2xrKTsKPiArCj4gKwlzbmFuZGMtPmJhc2UgPSBkZXZtX3BsYXRmb3JtX2dl dF9hbmRfaW9yZW1hcF9yZXNvdXJjZShwZGV2LCAwLCAmcmVzKTsKPiArCWlmIChJU19FUlIoc25h bmRjLT5iYXNlKSkKPiArCQlyZXR1cm4gUFRSX0VSUihzbmFuZGMtPmJhc2UpOwo+ICsKPiArCXNu YW5kYy0+YmFzZV9waHlzID0gcmVzLT5zdGFydDsKPiArCXNuYW5kYy0+YmFzZV9kbWEgPSBkbWFf bWFwX3Jlc291cmNlKGRldiwgcmVzLT5zdGFydCwgcmVzb3VyY2Vfc2l6ZShyZXMpLAo+ICsJCQkJ CSAgICBETUFfQklESVJFQ1RJT05BTCwgMCk7Cj4gKwlpZiAoZG1hX21hcHBpbmdfZXJyb3IoZGV2 LCBzbmFuZGMtPmJhc2VfZG1hKSkKPiArCQlyZXR1cm4gLUVOWElPOwo+ICsKPiArCXJldCA9IGNs a19wcmVwYXJlX2VuYWJsZShzbmFuZGMtPmNvcmVfY2xrKTsKPiArCWlmIChyZXQpCj4gKwkJZ290 byBlcnJfY29yZV9jbGs7CgpBZ2FpbiwgdGhlIGxhYmVsIGlzIGJldHRlciBuYW1lZCB3aGVuIGl0 IGRlc2NyaWJlcyB3aGF0IGl0IHBvaW50IGF0LApyYXRoZXIgdGhhbiB3aGVyZSBpdCBjb21lcyBm cm9tLgoKPiArCj4gKwlyZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoc25hbmRjLT5hb25fY2xrKTsK PiArCWlmIChyZXQpCj4gKwkJZ290byBlcnJfYW9uX2NsazsKPiArCj4gKwlyZXQgPSBjbGtfcHJl cGFyZV9lbmFibGUoc25hbmRjLT5xc3BpLT5pb21hY3JvX2Nsayk7Cj4gKwlpZiAocmV0KQo+ICsJ CWdvdG8gZXJyX2Rpc19pb21fY2xrOwo+ICsKPiArCXJldCA9IHFjb21fbmFuZGNfYWxsb2Moc25h bmRjKTsKPiArCWlmIChyZXQpCj4gKwkJZ290byBlcnJfc25hbmRfYWxsb2M7Cj4gKwo+ICsJcmV0 ID0gcWNvbV9zcGlfaW5pdChzbmFuZGMpOwo+ICsJaWYgKHJldCkKPiArCQlnb3RvIGVycl9pbml0 Owo+ICsKPiArCS8qIHNldHVwIEVDQyBlbmdpbmUgKi8KPiArCXNuYW5kYy0+cXNwaS0+ZWNjX2Vu Zy5kZXYgPSAmcGRldi0+ZGV2Owo+ICsJc25hbmRjLT5xc3BpLT5lY2NfZW5nLmludGVncmF0aW9u ID0gTkFORF9FQ0NfRU5HSU5FX0lOVEVHUkFUSU9OX1BJUEVMSU5FRDsKPiArCXNuYW5kYy0+cXNw aS0+ZWNjX2VuZy5vcHMgPSAmcWNvbV9zcGlfZWNjX2VuZ2luZV9vcHNfcGlwZWxpbmVkOwo+ICsJ c25hbmRjLT5xc3BpLT5lY2NfZW5nLnByaXYgPSBzbmFuZGM7Cj4gKwo+ICsJcmV0ID0gbmFuZF9l Y2NfcmVnaXN0ZXJfb25faG9zdF9od19lbmdpbmUoJnNuYW5kYy0+cXNwaS0+ZWNjX2VuZyk7Cj4g KwlpZiAocmV0KSB7Cj4gKwkJZGV2X2VycigmcGRldi0+ZGV2LCAiZmFpbGVkIHRvIHJlZ2lzdGVy IGVjYyBlbmdpbmU6JWRcbiIsIHJldCk7Cj4gKwkJZ290byBlcnJfaW5pdDsKPiArCX0KPiArCj4g KwljdGxyLT5udW1fY2hpcHNlbGVjdCA9IFFQSUNfUVNQSV9OVU1fQ1M7Cj4gKwljdGxyLT5tZW1f b3BzID0gJnFjb21fc3BpX21lbV9vcHM7Cj4gKwljdGxyLT5tZW1fY2FwcyA9ICZxY29tX3NwaV9t ZW1fY2FwczsKPiArCWN0bHItPmRldi5vZl9ub2RlID0gcGRldi0+ZGV2Lm9mX25vZGU7Cj4gKwlj dGxyLT5tb2RlX2JpdHMgPSBTUElfVFhfRFVBTCB8IFNQSV9SWF9EVUFMIHwKPiArCQkJICAgIFNQ SV9UWF9RVUFEIHwgU1BJX1JYX1FVQUQ7Cj4gKwo+ICsJcmV0ID0gc3BpX3JlZ2lzdGVyX2NvbnRy b2xsZXIoY3Rscik7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZGV2X2VycigmcGRldi0+ZGV2LCAic3Bp X3JlZ2lzdGVyX2NvbnRyb2xsZXIgZmFpbGVkLlxuIik7Cj4gKwkJZ290byBlcnJfaW5pdDsKPiAr CX0KPiArCj4gKwlyZXR1cm4gMDsKPiArCj4gK2Vycl9pbml0Ogo+ICsJcWNvbV9uYW5kY191bmFs bG9jKHNuYW5kYyk7CgpTYW1lOiBzL3VuYWxsb2MvZnJlZXxjbGVhbnVwLwoKPiArZXJyX3NuYW5k X2FsbG9jOgo+ICsJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKHNuYW5kYy0+cXNwaS0+aW9tYWNyb19j bGspOwo+ICtlcnJfZGlzX2lvbV9jbGs6Cj4gKwljbGtfZGlzYWJsZV91bnByZXBhcmUoc25hbmRj LT5hb25fY2xrKTsKPiArZXJyX2Fvbl9jbGs6Cj4gKwljbGtfZGlzYWJsZV91bnByZXBhcmUoc25h bmRjLT5jb3JlX2Nsayk7Cj4gK2Vycl9jb3JlX2NsazoKPiArCWRtYV91bm1hcF9yZXNvdXJjZShk ZXYsIHJlcy0+c3RhcnQsIHJlc291cmNlX3NpemUocmVzKSwKPiArCQkJICAgRE1BX0JJRElSRUNU SU9OQUwsIDApOwo+ICsJcmV0dXJuIHJldDsKPiArfQoKVGhhbmtzLApNaXF1w6hsCgpfX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KTGludXggTVRE IGRpc2N1c3Npb24gbWFpbGluZyBsaXN0Cmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxt YW4vbGlzdGluZm8vbGludXgtbXRkLwo=