From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (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 E832354720; Wed, 22 May 2024 09:43:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716370988; cv=none; b=hbXRWuwQKirE54m0NJUol4JkJNpIkbx+srBEzAkwow/GAopltEg5Prr34465I878qJ7/TyhiwEyakLD7ClVSgdlQyIBG5AUxtVf7QDjCSo3rsIw4RX/5GqH2cv5YQ8ZeAapQM6ROAabjbEOJfvuJ31A5vnq6THrdbzF9Sragl44= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716370988; c=relaxed/simple; bh=3aXCzXk03NlHrBEHPxRwQlzFDBo3nydDUQBJZy03syg=; h=Message-ID:Date:MIME-Version:Subject:To:CC:References:From: In-Reply-To:Content-Type; b=ooIeid3p549ea9IGy/J4VaMLaKs0BPnXVsWQNZMCOZCFHd2luXMwnYf0M9rU9wVe2ul2QafF9woGlLSJ4z3z/UJzC36EMNAONwySl/6r2RGE1nHWpY7D0M/HBRZqkopTjYJaU78RoNfHHP5wxQFomzOquwVJJhNbeF6BnWqgF+Q= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com; spf=pass smtp.mailfrom=quicinc.com; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b=ErTHYfsq; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="ErTHYfsq" Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 44M58Jgx009703; Wed, 22 May 2024 09:42:50 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= message-id:date:mime-version:subject:to:cc:references:from :in-reply-to:content-type:content-transfer-encoding; s= qcppdkim1; bh=igPoUkGtjpLFfsWeqO6/eaF8vOWZDWeOsDMGJNGygsM=; b=Er THYfsqxYy2QJ08d9dyl49Wy4HjR4J3VJfHdhhTPORSwe02TIqx3Pgkg3J/K5tqZ8 tvQW/HFtvgWxMcT7+GgbSlEeaXQFK56HTszLqeTZAbZeinGbqgUY6yXHrEsdw5kA fHvAvYbZibVQI9BPwYuxSp0fX1JoV6Tubk8deHrMyoN3/gCQ+12mou8UXgAnCQCh H9t9tKzW72019qFCc9rQTf47Hg89lW5Vnc6AuZO/UfNbXfdcpJsC5M9kjE83ohRb 7PzX2YdtTcF6FTP1/uk3RsMeC+TcNvdLZwbrDkVD9BtbdSc4gt1nzbQJ6ec2iZLK 6ZYpkfWMs1D6MKAkc83Q== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3y6pqard07-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 22 May 2024 09:42:49 +0000 (GMT) Received: from nasanex01a.na.qualcomm.com (nasanex01a.na.qualcomm.com [10.52.223.231]) by NASANPPMTA04.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 44M9glLw017082 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 22 May 2024 09:42:47 GMT Received: from [10.216.52.184] (10.80.80.8) by nasanex01a.na.qualcomm.com (10.52.223.231) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 22 May 2024 02:42:42 -0700 Message-ID: <5b96e24a-edcd-df85-9e70-332a6059ee73@quicinc.com> Date: Wed, 22 May 2024 15:12:38 +0530 Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.9.1 Subject: Re: [PATCH v6 6/8] spi: spi-qpic: add driver for QCOM SPI NAND flash Interface Content-Language: en-US To: Miquel Raynal CC: , , , , , , , , , , , , , , , References: <20240521105532.1537845-1-quic_mdalam@quicinc.com> <20240521105532.1537845-7-quic_mdalam@quicinc.com> <20240521152410.7cff71ab@xps-13> From: Md Sadre Alam In-Reply-To: <20240521152410.7cff71ab@xps-13> Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: 8bit X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nasanex01a.na.qualcomm.com (10.52.223.231) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: iAxuVzY5wOrwNqPjsjz0iMFqr-zx6Gcc X-Proofpoint-ORIG-GUID: iAxuVzY5wOrwNqPjsjz0iMFqr-zx6Gcc X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.650,FMLib:17.12.28.16 definitions=2024-05-22_04,2024-05-21_01,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 impostorscore=0 suspectscore=0 bulkscore=0 mlxscore=0 adultscore=0 spamscore=0 malwarescore=0 mlxlogscore=999 clxscore=1015 priorityscore=1501 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2405010000 definitions=main-2405220069 On 5/21/2024 6:54 PM, Miquel Raynal wrote: > 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) += nandcore.o >> obj-$(CONFIG_MTD_NAND_ECC_MEDIATEK) += ecc-mtk.o >> ifeq ($(CONFIG_MTD_NAND_QCOM),y) >> obj-y += qpic_common.o >> +else >> +ifeq ($(CONFIG_SPI_QPIC_SNAND),y) >> +obj-y += qpic_common.o >> +endif > > Same issue. ok, will fix in next patch. > >> endif >> obj-y += onenand/ >> obj-y += 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. >> > > ... > >> +static struct qcom_nand_controller *nand_to_qcom_snand(struct nand_device *nand) >> +{ >> + struct qpic_spi_nand *qspi; >> + struct nand_ecc_engine *eng = nand->ecc.engine; >> + >> + qspi = 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: Ok > > struct qpic_spi_nand *qspi = ecceng_to_qspi(eng); > >> + return qspi->snandc; >> +} >> + >> +static int qcom_spi_init(struct qcom_nand_controller *snandc) >> +{ >> + u32 snand_cfg_val = 0x0; >> + int ret; >> + >> + snand_cfg_val |= (LOAD_CLK_CNTR_INIT_EN | (CLK_CNTR_INIT_VAL_VEC << 16) | >> + (FEA_STATUS_DEV_ADDR << 8) | SPI_CFG); > > FIELD_PREP ? Ok > >> + >> + snandc->regs->spi_cfg = snand_cfg_val; >> + snandc->regs->num_addr_cycle = SPI_NUM_ADDR; >> + snandc->regs->busy_wait_cnt = SPI_WAIT_CNT; >> + >> + qcom_write_reg_dma(snandc, &snandc->regs->spi_cfg, NAND_FLASH_SPI_CFG, 1, 0); >> + >> + snand_cfg_val &= ~LOAD_CLK_CNTR_INIT_EN; >> + snandc->regs->spi_cfg = 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_CHECK_WAIT_CNT, 1, >> + NAND_BAM_NEXT_SGL); >> + >> + ret = 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 = mtd_to_nanddev(mtd); >> + struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); >> + struct qpic_ecc *qecc = snandc->qspi->ecc; >> + >> + if (section > 1) >> + return -ERANGE; >> + >> + if (!section) { >> + oobregion->length = (qecc->bytes * (qecc->steps - 1)) + qecc->bbm_size; >> + oobregion->offset = 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. QPIC NAND controller having its own page layout with ecc and without ecc. The same layout we are using in raw nand driver as well, so i used the same here. The below info is already there in qcom raw nand driver file in page layout info. QPIC NAND controller layout as below: Layout with ECC enabled: |----------------------| |---------------------------------| | xx.......yy| | *********xx.......yy| | DATA xx..ECC..yy| | DATA **SPARE**xx..ECC..yy| | (516) xx.......yy| | (516-n*4) **(n*4)**xx.......yy| | xx.......yy| | *********xx.......yy| |----------------------| |---------------------------------| codeword 1,2..n-1 codeword n <---(528/532 Bytes)--> <-------(528/532 Bytes)---------> n = Number of codewords in the page . = ECC bytes * = Spare/free bytes x = Unused byte(s) y = Reserved byte(s) 2K page: n = 4, spare = 16 bytes 4K page: n = 8, spare = 32 bytes 8K page: n = 16, spare = 64 bytes the qcom nand controller operates at a sub page/codeword level. each codeword is 528 and 532 bytes for 4 bit and 8 bit ECC modes respectively. the number of ECC bytes vary based on the ECC strength and the bus width. the first n - 1 codewords contains 516 bytes of user data, the remaining 12/16 bytes consist of ECC and reserved data. The nth codeword contains both user data and spare(oobavail) bytes that sum up to 516 bytes. When we access a page with ECC enabled, the reserved bytes(s) are not accessible at all. When reading, we fill up these unreadable positions with 0xffs. When writing, the controller skips writing the inaccessible bytes. Layout with ECC disabled: |------------------------------| |---------------------------------------| | yy xx.......| | bb *********xx.......| | DATA1 yy DATA2 xx..ECC..| | DATA1 bb DATA2 **SPARE**xx..ECC..| | (size1) yy (size2) xx.......| | (size1) bb (size2) **(n*4)**xx.......| | yy xx.......| | bb *********xx.......| |------------------------------| |---------------------------------------| codeword 1,2..n-1 codeword n <-------(528/532 Bytes)------> <-----------(528/532 Bytes)-----------> n = Number of codewords in the page . = ECC bytes * = Spare/free bytes x = Unused byte(s) y = Dummy Bad Bock byte(s) b = Real Bad Block byte(s) size1/size2 = function of codeword size and 'n' when the ECC block is disabled, one reserved byte (or two for 16 bit bus width) is now accessible. For the first n - 1 codewords, these are dummy Bad Block Markers. In the last codeword, this position contains the real BBM In order to have a consistent layout between RAW and ECC modes, we assume the following OOB layout arrangement: |-----------| |--------------------| |yyxx.......| |bb*********xx.......| |yyxx..ECC..| |bb*FREEOOB*xx..ECC..| |yyxx.......| |bb*********xx.......| |yyxx.......| |bb*********xx.......| |-----------| |--------------------| first n - 1 nth OOB region OOB regions n = Number of codewords in the page . = ECC bytes * = FREE OOB bytes y = Dummy bad block byte(s) (inaccessible when ECC enabled) x = Unused byte(s) b = Real bad block byte(s) (inaccessible when ECC enabled) This layout is read as is when ECC is disabled. When ECC is enabled, the inaccessible Bad Block byte(s) are ignored when we write to a page/oob, and assumed as 0xffs when we read a page/oob. The ECC, unused and dummy/real bad block bytes are grouped as ecc bytes (i.e, ecc->bytes is the sum of the three). > >> + } else { >> + oobregion->length = qecc->ecc_bytes_hw + qecc->spare_bytes; >> + oobregion->offset = 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 = mtd_to_nanddev(mtd); >> + struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); >> + struct qpic_ecc *qecc = snandc->qspi->ecc; >> + >> + if (section) >> + return -ERANGE; >> + >> + oobregion->length = qecc->steps * 4; >> + oobregion->offset = ((qecc->steps - 1) * qecc->bytes) + qecc->bbm_size; >> + >> + return 0; >> +} >> + > > ... > >> +static int qcom_spi_ecc_prepare_io_req_pipelined(struct nand_device *nand, >> + struct nand_page_io_req *req) >> +{ >> + struct qcom_nand_controller *snandc = nand_to_qcom_snand(nand); >> + struct qpic_ecc *ecc_cfg = nand_to_ecc_ctx(nand); >> + struct mtd_info *mtd = nanddev_to_mtd(nand); >> + >> + snandc->qspi->ecc = ecc_cfg; >> + snandc->qspi->pagesize = mtd->writesize; >> + snandc->qspi->raw_rw = false; >> + snandc->qspi->oob_rw = false; >> + snandc->qspi->page_rw = false; >> + >> + if (req->datalen) >> + snandc->qspi->page_rw = true; >> + >> + if (req->ooblen) { >> + snandc->qspi->oob_rw = true; >> + if (req->ooblen == BAD_BLOCK_MARKER_SIZE) >> + snandc->qspi->read_last_cw = true; > > ??? As per QPIC controller layout , the actual babd block marker will be present in last code word. Thats why i have added this check. to read only last codeword for bad block check. > >> + } >> + >> + if (req->mode == MTD_OPS_RAW) >> + snandc->qspi->raw_rw = 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 = nand_to_qcom_snand(nand); >> + struct mtd_info *mtd = nanddev_to_mtd(nand); >> + >> + if (req->mode == MTD_OPS_RAW || req->type != NAND_PAGE_READ) >> + return 0; >> + >> + if (snandc->qspi->ecc_stats.failed) >> + mtd->ecc_stats.failed += snandc->qspi->ecc_stats.failed; >> + mtd->ecc_stats.corrected += snandc->qspi->ecc_stats.corrected; > > Seems strange In flash error check for each code word i am updating the error value. So on finishing on io i am assigning that error to mtd variables so that upper layer check for error. > >> + >> + 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 = { >> + .init_ctx = qcom_spi_ecc_init_ctx_pipelined, >> + .cleanup_ctx = qcom_spi_ecc_cleanup_ctx_pipelined, >> + .prepare_io_req = qcom_spi_ecc_prepare_io_req_pipelined, >> + .finish_io_req = 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 = snandc->qspi->ecc; >> + u8 *data_buf = NULL, *oob_buf = NULL; >> + int ret, cw; >> + u32 num_cw = 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? This indirection needed due to QPIC controller will not take all the instruction one-by-one , once we will set CMD_EXEC = 1, then it will execute all the instruction at once. > > The hardware is already quite complex, but it feels like your adding > yet another pile of unnecessary complexity. Yes hardware is complex. let me check if i can further optimize as per spi-mem op as you suggested. > >> + data_buf = op->data.buf.in; >> + >> + if (snandc->qspi->oob_rw) >> + oob_buf = op->data.buf.in; > > Same buffer pointed by the two pointers? hum Ok , will fix in next patch. > >> + >> + if (!oob_buf) { >> + oob_buf = snandc->qspi->oob_buf; >> + memset(oob_buf, 0xff, OOB_BUF_SIZE); >> + } >> + >> + for (cw = 0; cw < num_cw; cw++) { >> + ret = qcom_spi_read_cw_raw(snandc, data_buf, oob_buf, cw); >> + if (ret) >> + return ret; >> + >> + if (data_buf) >> + data_buf += ecc_cfg->cw_data; >> + if (oob_buf) >> + oob_buf += 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 = snandc->qspi->ecc; >> + u8 *data_buf = NULL, *data_buf_start, *oob_buf = NULL, *oob_buf_start; >> + int ret, i; >> + u32 cfg0, cfg1, ecc_bch_cfg, num_cw = snandc->qspi->num_cw; >> + >> + if (snandc->qspi->page_rw) { >> + data_buf = op->data.buf.in; >> + data_buf_start = data_buf; >> + } >> + >> + if (snandc->qspi->oob_rw || snandc->qspi->raw_rw) { >> + oob_buf = op->data.buf.in; >> + oob_buf_start = 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 = 0; >> + snandc->buf_start = 0; >> + qcom_clear_read_regs(snandc); >> + >> + cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | >> + (num_cw - 1) << CW_PER_PAGE; >> + cfg1 = ecc_cfg->cfg1; >> + ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; >> + >> + snandc->regs->addr0 = snandc->qspi->addr1; >> + snandc->regs->addr1 = snandc->qspi->addr2; >> + snandc->regs->cmd = snandc->qspi->cmd; >> + snandc->regs->cfg0 = cfg0; >> + snandc->regs->cfg1 = cfg1; >> + snandc->regs->ecc_bch_cfg = ecc_bch_cfg; >> + snandc->regs->clrflashstatus = ecc_cfg->clrflashstatus; >> + snandc->regs->clrreadstatus = ecc_cfg->clrreadstatus; >> + snandc->regs->exec = 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 = 0; i < num_cw; i++) { >> + int data_size, oob_size; >> + >> + if (i == (num_cw - 1)) { >> + data_size = 512 - ((num_cw - 1) << 2); >> + oob_size = (num_cw << 2) + ecc_cfg->ecc_bytes_hw + >> + ecc_cfg->spare_bytes; >> + } else { >> + data_size = ecc_cfg->cw_data; >> + oob_size = 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 = 0; j < ecc_cfg->bbm_size; j++) >> + *oob_buf++ = 0xff; >> + >> + qcom_read_data_dma(snandc, FLASH_BUF_ACC + data_size, >> + oob_buf, oob_size, 0); >> + } >> + >> + if (data_buf) >> + data_buf += data_size; >> + if (oob_buf) >> + oob_buf += oob_size; >> + } >> + >> + ret = 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 *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->ecc_buf_cfg, NAND_EBI2_ECC_BUF_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_STATUS, 1, 0); >> + qcom_write_reg_dma(snandc, &snandc->regs->clrreadstatus, NAND_READ_STATUS, 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 = snandc->qspi->ecc; >> + u8 *data_buf = NULL, *oob_buf = NULL; >> + int i, ret; >> + int num_cw = snandc->qspi->num_cw; >> + u32 cfg0, cfg1, ecc_bch_cfg; >> + >> + cfg0 = (ecc_cfg->cfg0_raw & ~(7U << CW_PER_PAGE)) | >> + (num_cw - 1) << CW_PER_PAGE; >> + cfg1 = ecc_cfg->cfg1_raw; >> + ecc_bch_cfg = ECC_CFG_ECC_DISABLE; >> + >> + data_buf = snandc->qspi->data_buf; >> + >> + oob_buf = snandc->qspi->oob_buf; >> + memset(oob_buf, 0xff, OOB_BUF_SIZE); >> + >> + snandc->buf_count = 0; >> + snandc->buf_start = 0; >> + qcom_clear_read_regs(snandc); >> + qcom_clear_bam_transaction(snandc); >> + >> + snandc->regs->addr0 = snandc->qspi->addr1; >> + snandc->regs->addr1 = snandc->qspi->addr2; >> + snandc->regs->cmd = snandc->qspi->cmd; >> + snandc->regs->cfg0 = cfg0; >> + snandc->regs->cfg1 = cfg1; >> + snandc->regs->ecc_bch_cfg = ecc_bch_cfg; >> + snandc->regs->clrflashstatus = ecc_cfg->clrflashstatus; >> + snandc->regs->clrreadstatus = ecc_cfg->clrreadstatus; >> + snandc->regs->exec = 1; >> + >> + qcom_spi_config_page_write(snandc); >> + >> + for (i = 0; i < num_cw; i++) { >> + int data_size1, data_size2, oob_size1, oob_size2; >> + int reg_off = FLASH_BUF_ACC; >> + >> + data_size1 = snandc->qspi->pagesize - ecc_cfg->cw_size * (num_cw - 1); >> + oob_size1 = ecc_cfg->bbm_size; >> + >> + if ((i == (num_cw - 1))) { >> + data_size2 = NANDC_STEP_SIZE - data_size1 - >> + ((num_cw - 1) << 2); >> + oob_size2 = (num_cw << 2) + ecc_cfg->ecc_bytes_hw + >> + ecc_cfg->spare_bytes; >> + } else { >> + data_size2 = ecc_cfg->cw_data - data_size1; >> + oob_size2 = 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 += data_size1; >> + data_buf += data_size1; >> + >> + qcom_write_data_dma(snandc, reg_off, oob_buf, oob_size1, >> + NAND_BAM_NO_EOT); >> + oob_buf += oob_size1; >> + reg_off += oob_size1; >> + >> + qcom_write_data_dma(snandc, reg_off, data_buf, data_size2, >> + NAND_BAM_NO_EOT); >> + reg_off += data_size2; >> + data_buf += data_size2; >> + >> + qcom_write_data_dma(snandc, reg_off, oob_buf, oob_size2, 0); >> + oob_buf += oob_size2; >> + >> + qcom_spi_config_cw_write(snandc); >> + } >> + >> + ret = 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 = snandc->qspi->ecc; >> + u8 *data_buf = NULL, *oob_buf = NULL; >> + int i, ret; >> + int num_cw = snandc->qspi->num_cw; >> + u32 cfg0, cfg1, ecc_bch_cfg, ecc_buf_cfg; >> + >> + cfg0 = (ecc_cfg->cfg0 & ~(7U << CW_PER_PAGE)) | >> + (num_cw - 1) << CW_PER_PAGE; >> + cfg1 = ecc_cfg->cfg1; >> + ecc_bch_cfg = ecc_cfg->ecc_bch_cfg; >> + ecc_buf_cfg = 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 = snandc->qspi->data_buf; >> + >> + if (snandc->qspi->oob_buf) >> + oob_buf = snandc->qspi->oob_buf; >> + >> + snandc->buf_count = 0; >> + snandc->buf_start = 0; >> + qcom_clear_read_regs(snandc); >> + qcom_clear_bam_transaction(snandc); >> + >> + snandc->regs->addr0 = snandc->qspi->addr1; >> + snandc->regs->addr1 = snandc->qspi->addr2; >> + snandc->regs->cmd = snandc->qspi->cmd; >> + snandc->regs->cfg0 = cfg0; >> + snandc->regs->cfg1 = cfg1; >> + snandc->regs->ecc_bch_cfg = ecc_bch_cfg; >> + snandc->regs->ecc_buf_cfg = ecc_buf_cfg; >> + snandc->regs->exec = 1; >> + >> + qcom_spi_config_page_write(snandc); >> + >> + for (i = 0; i < num_cw; i++) { >> + int data_size, oob_size; >> + >> + if (i == (num_cw - 1)) { >> + data_size = NANDC_STEP_SIZE - ((num_cw - 1) << 2); >> + oob_size = (num_cw << 2) + ecc_cfg->ecc_bytes_hw + >> + ecc_cfg->spare_bytes; >> + } else { >> + data_size = ecc_cfg->cw_data; >> + oob_size = ecc_cfg->bytes; >> + } >> + >> + if (data_buf) >> + qcom_write_data_dma(snandc, FLASH_BUF_ACC, data_buf, data_size, >> + i == (num_cw - 1) ? NAND_BAM_NO_EOT : 0); >> + >> + if (i == (num_cw - 1)) { >> + if (oob_buf) { >> + oob_buf += 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 += data_size; >> + if (oob_buf) >> + oob_buf += oob_size; >> + } >> + >> + ret = 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 = 0x0; >> + >> + switch (opcode) { >> + case SPINAND_RESET: >> + cmd = (SPI_WP | SPI_HOLD | SPI_TRANSFER_MODE_x1 | OP_RESET_DEVICE); >> + break; >> + case SPINAND_READID: >> + cmd = (SPI_WP | SPI_HOLD | SPI_TRANSFER_MODE_x1 | OP_FETCH_ID); >> + break; >> + case SPINAND_GET_FEATURE: >> + cmd = (SPI_TRANSFER_MODE_x1 | SPI_WP | SPI_HOLD | ACC_FEATURE); >> + break; >> + case SPINAND_SET_FEATURE: >> + cmd = (SPI_TRANSFER_MODE_x1 | SPI_WP | SPI_HOLD | ACC_FEATURE | >> + QPIC_SET_FEATURE); >> + break; >> + case SPINAND_READ: >> + if (snandc->qspi->raw_rw) { >> + cmd = (PAGE_ACC | LAST_PAGE | SPI_TRANSFER_MODE_x1 | >> + SPI_WP | SPI_HOLD | OP_PAGE_READ); >> + } else { >> + cmd = (PAGE_ACC | LAST_PAGE | SPI_TRANSFER_MODE_x1 | >> + SPI_WP | SPI_HOLD | OP_PAGE_READ_WITH_ECC); >> + } >> + >> + break; >> + case SPINAND_ERASE: >> + cmd = OP_BLOCK_ERASE | PAGE_ACC | LAST_PAGE | SPI_WP | >> + SPI_HOLD | SPI_TRANSFER_MODE_x1; >> + break; >> + case SPINAND_WRITE_EN: >> + cmd = SPINAND_WRITE_EN; >> + break; >> + case SPINAND_PROGRAM_EXECUTE: >> + cmd = (PAGE_ACC | LAST_PAGE | SPI_TRANSFER_MODE_x1 | >> + SPI_WP | SPI_HOLD | OP_PROGRAM_PAGE); >> + break; >> + case SPINAND_PROGRAM_LOAD: >> + cmd = 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 = {}; >> + u32 cmd; >> + >> + cmd = 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. Ok, will fix in next patch. > >> + s_op.cmd_reg = cmd; >> + >> + if (op->cmd.opcode == SPINAND_PROGRAM_LOAD) { >> + if (snandc->qspi->page_rw) >> + snandc->qspi->data_buf = (u8 *)op->data.buf.out; > > What you do here does not write anything in a page cache. No here just updating the buffer , actual write will happen in program_execute. This is due to QPIC controller will not take all the instruction one-by-one. once we will set CMD_EXEC = 1, then it will execute all the instruction at once. So accumulating all the instruction and then executing at once in program_execute. > > I also don't understand why you would have to check against the > SPINAND_PROGRAM_LOAD opcode. Because the actual write will happen in program_execute. and here PROGRAM_EXECUTE command will also land, so that added the check. > >> + } >> + >> + 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 = {}; >> + u32 cmd; >> + int ret, opcode; >> + >> + cmd = qcom_spi_cmd_mapping(snandc, op->cmd.opcode); >> + >> + s_op.cmd_reg = cmd; >> + s_op.addr1_reg = op->addr.val; >> + s_op.addr2_reg = 0; >> + >> + opcode = op->cmd.opcode; >> + >> + switch (opcode) { >> + case SPINAND_WRITE_EN: >> + return 0; >> + case SPINAND_PROGRAM_EXECUTE: >> + s_op.addr1_reg = op->addr.val << 16; >> + s_op.addr2_reg = op->addr.val >> 16 & 0xff; >> + snandc->qspi->addr1 = s_op.addr1_reg; >> + snandc->qspi->addr2 = s_op.addr2_reg; >> + snandc->qspi->cmd = cmd; >> + return qcom_spi_program_execute(snandc, op); >> + case SPINAND_READ: >> + s_op.addr1_reg = (op->addr.val << 16); >> + s_op.addr2_reg = op->addr.val >> 16 & 0xff; >> + snandc->qspi->addr1 = s_op.addr1_reg; >> + snandc->qspi->addr2 = s_op.addr2_reg; >> + snandc->qspi->cmd = cmd; >> + return 0; >> + case SPINAND_ERASE: >> + s_op.addr2_reg = (op->addr.val >> 16) & 0xffff; >> + s_op.addr1_reg = op->addr.val; >> + snandc->qspi->addr1 = (s_op.addr1_reg << 16); >> + snandc->qspi->addr2 = s_op.addr2_reg; >> + snandc->qspi->cmd = cmd; >> + qcom_spi_block_erase(snandc); >> + return 0; >> + default: >> + break; >> + } >> + >> + snandc->buf_count = 0; >> + snandc->buf_start = 0; >> + qcom_clear_read_regs(snandc); >> + qcom_clear_bam_transaction(snandc); >> + >> + snandc->regs->cmd = s_op.cmd_reg; >> + snandc->regs->exec = 1; >> + snandc->regs->addr0 = s_op.addr1_reg; >> + snandc->regs->addr1 = 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 = qcom_submit_descs(snandc); >> + if (ret) >> + dev_err(snandc->dev, "failure in sbumitting cmd descriptor\n"); > > typo Ok , will fix in next patch. > >> + >> + return ret; >> +} >> + >> +static int qcom_spi_io_op(struct qcom_nand_controller *snandc, const struct spi_mem_op *op) >> +{ >> + int ret, val, opcode; >> + bool copy = false, copy_ftr = false; >> + >> + ret = qcom_spi_send_cmdaddr(snandc, op); >> + if (ret) >> + return ret; >> + >> + snandc->buf_count = 0; >> + snandc->buf_start = 0; >> + qcom_clear_read_regs(snandc); >> + qcom_clear_bam_transaction(snandc); >> + opcode = op->cmd.opcode; >> + >> + switch (opcode) { >> + case SPINAND_READID: >> + snandc->buf_count = 4; >> + qcom_read_reg_dma(snandc, NAND_READ_ID, 1, NAND_BAM_NEXT_SGL); >> + copy = true; >> + break; >> + case SPINAND_GET_FEATURE: >> + snandc->buf_count = 4; >> + qcom_read_reg_dma(snandc, NAND_FLASH_FEATURES, 1, NAND_BAM_NEXT_SGL); >> + copy_ftr = true; >> + break; >> + case SPINAND_SET_FEATURE: >> + snandc->regs->flash_feature = *(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 Ok > >> + default: >> + return -EOPNOTSUPP; >> + } >> + >> + ret = qcom_submit_descs(snandc); >> + if (ret) >> + dev_err(snandc->dev, "failure in submitting descriptor for:%d\n", opcode); >> + >> + 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 = le32_to_cpu(*(__le32 *)snandc->reg_read_buf); >> + val >>= 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 != 1 && op->addr.buswidth != 2 && op->addr.buswidth != 4) >> + return false; >> + >> + if (op->data.dir == SPI_MEM_DATA_IN) { >> + if (op->addr.buswidth == 4 && op->data.buswidth == 4) >> + return true; >> + >> + if (op->addr.nbytes == 2 && op->addr.buswidth == 1) >> + return true; >> + >> + } else if (op->data.dir == SPI_MEM_DATA_OUT) { >> + if (op->data.buswidth == 4) >> + return true; >> + if (op->addr.nbytes == 2 && op->addr.buswidth == 1) >> + return true; >> + } >> + >> + return false; >> +} >> + >> +static bool qcom_spi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) >> +{ >> + if (!spi_mem_default_supports_op(mem, op)) >> + return false; >> + >> + if (op->cmd.nbytes != 1 || op->cmd.buswidth != 1) >> + return false; >> + >> + if (qcom_spi_is_page_op(op)) >> + return true; >> + >> + return ((!op->addr.nbytes || op->addr.buswidth == 1) && >> + (!op->dummy.nbytes || op->dummy.buswidth == 1) && >> + (!op->data.nbytes || op->data.buswidth == 1)); >> +} >> + >> +static int qcom_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) >> +{ >> + struct qcom_nand_controller *snandc = spi_controller_get_devdata(mem->spi->controller); >> + >> + dev_dbg(snandc->dev, "OP %02x ADDR %08llX@%d:%u DATA %d:%u", op->cmd.opcode, >> + 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 == SPI_MEM_DATA_IN) >> + return qcom_spi_read_page_cache(snandc, op); >> + if (op->data.dir == 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 = { >> + .supports_op = qcom_spi_supports_op, >> + .exec_op = qcom_spi_exec_op, >> +}; >> + >> +static const struct spi_controller_mem_caps qcom_spi_mem_caps = { >> + .ecc = true, >> +}; >> + >> +static int qcom_spi_probe(struct platform_device *pdev) >> +{ >> + struct device *dev = &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 = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL); >> + if (!ecc) >> + return -ENOMEM; >> + >> + qspi = devm_kzalloc(dev, sizeof(*qspi), GFP_KERNEL); >> + if (!qspi) >> + return -ENOMEM; >> + >> + ctlr = __devm_spi_alloc_controller(dev, sizeof(*snandc), false); >> + if (!ctlr) >> + return -ENOMEM; >> + >> + platform_set_drvdata(pdev, ctlr); >> + >> + snandc = spi_controller_get_devdata(ctlr); >> + qspi->snandc = snandc; >> + >> + snandc->dev = dev; >> + snandc->qspi = qspi; >> + snandc->qspi->ctlr = ctlr; >> + snandc->qspi->ecc = ecc; >> + >> + snandc->qspi->oob_buf = devm_kzalloc(dev, OOB_BUF_SIZE, GFP_KERNEL); >> + if (!snandc->qspi->oob_buf) >> + return -ENOMEM; >> + >> + dev_data = of_device_get_match_data(dev); >> + if (!dev_data) { >> + dev_err(&pdev->dev, "failed to get device data\n"); >> + return -ENODEV; >> + } >> + >> + snandc->props = dev_data; >> + snandc->dev = &pdev->dev; >> + >> + snandc->core_clk = devm_clk_get(dev, "core"); >> + if (IS_ERR(snandc->core_clk)) >> + return PTR_ERR(snandc->core_clk); >> + >> + snandc->aon_clk = devm_clk_get(dev, "aon"); >> + if (IS_ERR(snandc->aon_clk)) >> + return PTR_ERR(snandc->aon_clk); >> + >> + snandc->qspi->iomacro_clk = devm_clk_get(dev, "iom"); >> + if (IS_ERR(snandc->qspi->iomacro_clk)) >> + return PTR_ERR(snandc->qspi->iomacro_clk); >> + >> + snandc->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); >> + if (IS_ERR(snandc->base)) >> + return PTR_ERR(snandc->base); >> + >> + snandc->base_phys = res->start; >> + snandc->base_dma = dma_map_resource(dev, res->start, resource_size(res), >> + DMA_BIDIRECTIONAL, 0); >> + if (dma_mapping_error(dev, snandc->base_dma)) >> + return -ENXIO; >> + >> + ret = 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. Ok > >> + >> + ret = clk_prepare_enable(snandc->aon_clk); >> + if (ret) >> + goto err_aon_clk; >> + >> + ret = clk_prepare_enable(snandc->qspi->iomacro_clk); >> + if (ret) >> + goto err_dis_iom_clk; >> + >> + ret = qcom_nandc_alloc(snandc); >> + if (ret) >> + goto err_snand_alloc; >> + >> + ret = qcom_spi_init(snandc); >> + if (ret) >> + goto err_init; >> + >> + /* setup ECC engine */ >> + snandc->qspi->ecc_eng.dev = &pdev->dev; >> + snandc->qspi->ecc_eng.integration = NAND_ECC_ENGINE_INTEGRATION_PIPELINED; >> + snandc->qspi->ecc_eng.ops = &qcom_spi_ecc_engine_ops_pipelined; >> + snandc->qspi->ecc_eng.priv = snandc; >> + >> + ret = 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 = QPIC_QSPI_NUM_CS; >> + ctlr->mem_ops = &qcom_spi_mem_ops; >> + ctlr->mem_caps = &qcom_spi_mem_caps; >> + ctlr->dev.of_node = pdev->dev.of_node; >> + ctlr->mode_bits = SPI_TX_DUAL | SPI_RX_DUAL | >> + SPI_TX_QUAD | SPI_RX_QUAD; >> + >> + ret = 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/ Ok > >> +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èl From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 5E3E4C25B77 for ; Wed, 22 May 2024 09:43:07 +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-Type: Content-Transfer-Encoding:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:From:References:CC:To:Subject: MIME-Version:Date:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=CGAS8OvD3tMOV50UJO1MutnojYOog0pJZk4T00XNJDk=; b=A6mleGZYQaB5Jg Cj+JjqG/+3+hnauaSPfSM38rbiy2KcmZKBwu17G5BJRMUuPm5Yp+KSWXljdTzpWrEnh5zkmM9O2Sv GE+pjNUAjSu+j2nclVVLTKncf+bnPV/RxAeCfUELjMuRGt2O3/vI4Jls1lSGRVqReDeqIvftNrzPg RXioHkXQcRAk2JCneqlOtt6s38y6Yl4TsfeklQFUAkW2t8zRd4o2hf+Ft43jndSEZLBRfvI5XC1RJ 5hVNsrMRGD7JreXI6BRLFAJLw33yXhd+z1t+btiXG9hj/E/HmnCmDcqjyEMomCc6P6OZRFbI4ltVh jGwbWlEj1DPJf5f1tUuw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1s9iUx-00000002X3q-1jaP; Wed, 22 May 2024 09:43:03 +0000 Received: from mx0a-0031df01.pphosted.com ([205.220.168.131]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1s9iUs-00000002X3N-2X2h for linux-mtd@lists.infradead.org; Wed, 22 May 2024 09:43:01 +0000 Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 44M58Jgx009703; Wed, 22 May 2024 09:42:50 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= message-id:date:mime-version:subject:to:cc:references:from :in-reply-to:content-type:content-transfer-encoding; s= qcppdkim1; bh=igPoUkGtjpLFfsWeqO6/eaF8vOWZDWeOsDMGJNGygsM=; b=Er THYfsqxYy2QJ08d9dyl49Wy4HjR4J3VJfHdhhTPORSwe02TIqx3Pgkg3J/K5tqZ8 tvQW/HFtvgWxMcT7+GgbSlEeaXQFK56HTszLqeTZAbZeinGbqgUY6yXHrEsdw5kA fHvAvYbZibVQI9BPwYuxSp0fX1JoV6Tubk8deHrMyoN3/gCQ+12mou8UXgAnCQCh H9t9tKzW72019qFCc9rQTf47Hg89lW5Vnc6AuZO/UfNbXfdcpJsC5M9kjE83ohRb 7PzX2YdtTcF6FTP1/uk3RsMeC+TcNvdLZwbrDkVD9BtbdSc4gt1nzbQJ6ec2iZLK 6ZYpkfWMs1D6MKAkc83Q== Received: from nasanppmta04.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3y6pqard07-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 22 May 2024 09:42:49 +0000 (GMT) Received: from nasanex01a.na.qualcomm.com (nasanex01a.na.qualcomm.com [10.52.223.231]) by NASANPPMTA04.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 44M9glLw017082 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 22 May 2024 09:42:47 GMT Received: from [10.216.52.184] (10.80.80.8) by nasanex01a.na.qualcomm.com (10.52.223.231) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.9; Wed, 22 May 2024 02:42:42 -0700 Message-ID: <5b96e24a-edcd-df85-9e70-332a6059ee73@quicinc.com> Date: Wed, 22 May 2024 15:12:38 +0530 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.9.1 Subject: Re: [PATCH v6 6/8] spi: spi-qpic: add driver for QCOM SPI NAND flash Interface Content-Language: en-US To: Miquel Raynal CC: , , , , , , , , , , , , , , , References: <20240521105532.1537845-1-quic_mdalam@quicinc.com> <20240521105532.1537845-7-quic_mdalam@quicinc.com> <20240521152410.7cff71ab@xps-13> From: Md Sadre Alam In-Reply-To: <20240521152410.7cff71ab@xps-13> X-Originating-IP: [10.80.80.8] X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nasanex01a.na.qualcomm.com (10.52.223.231) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: iAxuVzY5wOrwNqPjsjz0iMFqr-zx6Gcc X-Proofpoint-ORIG-GUID: iAxuVzY5wOrwNqPjsjz0iMFqr-zx6Gcc X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.650,FMLib:17.12.28.16 definitions=2024-05-22_04,2024-05-21_01,2024-05-17_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 lowpriorityscore=0 impostorscore=0 suspectscore=0 bulkscore=0 mlxscore=0 adultscore=0 spamscore=0 malwarescore=0 mlxlogscore=999 clxscore=1015 priorityscore=1501 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2405010000 definitions=main-2405220069 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240522_024258_712306_5875ED95 X-CRM114-Status: GOOD ( 30.33 ) 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-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Sender: "linux-mtd" Errors-To: linux-mtd-bounces+linux-mtd=archiver.kernel.org@lists.infradead.org CgpPbiA1LzIxLzIwMjQgNjo1NCBQTSwgTWlxdWVsIFJheW5hbCB3cm90ZToKPiBIaSwKPiAKPj4g ZGlmZiAtLWdpdCBhL2RyaXZlcnMvbXRkL25hbmQvTWFrZWZpbGUgYi9kcml2ZXJzL210ZC9uYW5k L01ha2VmaWxlCj4+IGluZGV4IGU1OTEwNmUwYTNhZi4uMTJlZTMzYzRhYzRlIDEwMDY0NAo+PiAt LS0gYS9kcml2ZXJzL210ZC9uYW5kL01ha2VmaWxlCj4+ICsrKyBiL2RyaXZlcnMvbXRkL25hbmQv TWFrZWZpbGUKPj4gQEAgLTUsNiArNSwxMCBAQCBvYmotJChDT05GSUdfTVREX05BTkRfQ09SRSkg Kz0gbmFuZGNvcmUubwo+PiAgIG9iai0kKENPTkZJR19NVERfTkFORF9FQ0NfTUVESUFURUspICs9 IGVjYy1tdGsubwo+PiAgIGlmZXEgKCQoQ09ORklHX01URF9OQU5EX1FDT00pLHkpCj4+ICAgb2Jq LXkJKz0gcXBpY19jb21tb24ubwo+PiArZWxzZQo+PiAraWZlcSAoJChDT05GSUdfU1BJX1FQSUNf U05BTkQpLHkpCj4+ICtvYmoteSAgICs9IHFwaWNfY29tbW9uLm8KPj4gK2VuZGlmCj4gCj4gU2Ft ZSBpc3N1ZS4KICBvaywgd2lsbCBmaXggaW4gbmV4dCBwYXRjaC4KPiAKPj4gICBlbmRpZgo+PiAg IG9iai15CSs9IG9uZW5hbmQvCj4+ICAgb2JqLXkJKz0gcmF3Lwo+PiBkaWZmIC0tZ2l0IGEvZHJp dmVycy9zcGkvS2NvbmZpZyBiL2RyaXZlcnMvc3BpL0tjb25maWcKPj4gaW5kZXggYTJjOTlmZjMz ZTBhLi5iYjc1NzkyNDZmMmYgMTAwNjQ0Cj4+IC0tLSBhL2RyaXZlcnMvc3BpL0tjb25maWcKPj4g KysrIGIvZHJpdmVycy9zcGkvS2NvbmZpZwo+PiBAQCAtODkyLDYgKzg5MiwxNCBAQCBjb25maWcg U1BJX1FDT01fUVNQSQo+PiAgIAloZWxwCj4+ICAgCSAgUVNQSShRdWFkIFNQSSkgZHJpdmVyIGZv ciBRdWFsY29tbSBRU1BJIGNvbnRyb2xsZXIuCj4+ICAgCj4gCj4gLi4uCj4gCj4+ICtzdGF0aWMg c3RydWN0IHFjb21fbmFuZF9jb250cm9sbGVyICpuYW5kX3RvX3Fjb21fc25hbmQoc3RydWN0IG5h bmRfZGV2aWNlICpuYW5kKQo+PiArewo+PiArCXN0cnVjdCBxcGljX3NwaV9uYW5kICpxc3BpOwo+ PiArCXN0cnVjdCBuYW5kX2VjY19lbmdpbmUgKmVuZyA9IG5hbmQtPmVjYy5lbmdpbmU7Cj4+ICsK Pj4gKwlxc3BpID0gY29udGFpbmVyX29mKGVuZywgc3RydWN0IHFwaWNfc3BpX25hbmQsIGVjY19l bmcpOwo+IAo+IFBsZWFzZSBlbmNvZGUgdGhpcyBpbnRvIGEgbWFjcm8gYW5kIHVzZSBpdCBvbiB0 aGUgc2Vjb25kIGxpbmUgb2YgdGhpcwo+IGZ1bmN0aW9uOgpPawo+IAo+IAlzdHJ1Y3QgcXBpY19z cGlfbmFuZCAqcXNwaSA9IGVjY2VuZ190b19xc3BpKGVuZyk7Cj4gCj4+ICsJcmV0dXJuIHFzcGkt PnNuYW5kYzsKPj4gK30KPj4gKwo+PiArc3RhdGljIGludCBxY29tX3NwaV9pbml0KHN0cnVjdCBx Y29tX25hbmRfY29udHJvbGxlciAqc25hbmRjKQo+PiArewo+PiArCXUzMiBzbmFuZF9jZmdfdmFs ID0gMHgwOwo+PiArCWludCByZXQ7Cj4+ICsKPj4gKwlzbmFuZF9jZmdfdmFsIHw9IChMT0FEX0NM S19DTlRSX0lOSVRfRU4gfCAoQ0xLX0NOVFJfSU5JVF9WQUxfVkVDIDw8IDE2KSB8Cj4+ICsJCQkg KEZFQV9TVEFUVVNfREVWX0FERFIgPDwgOCkgfCBTUElfQ0ZHKTsKPiAKPiBGSUVMRF9QUkVQID8K T2sKPiAKPj4gKwo+PiArCXNuYW5kYy0+cmVncy0+c3BpX2NmZyA9IHNuYW5kX2NmZ192YWw7Cj4+ ICsJc25hbmRjLT5yZWdzLT5udW1fYWRkcl9jeWNsZSA9IFNQSV9OVU1fQUREUjsKPj4gKwlzbmFu ZGMtPnJlZ3MtPmJ1c3lfd2FpdF9jbnQgPSBTUElfV0FJVF9DTlQ7Cj4+ICsKPj4gKwlxY29tX3dy aXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRjLT5yZWdzLT5zcGlfY2ZnLCBOQU5EX0ZMQVNIX1NQ SV9DRkcsIDEsIDApOwo+PiArCj4+ICsJc25hbmRfY2ZnX3ZhbCAmPSB+TE9BRF9DTEtfQ05UUl9J TklUX0VOOwo+PiArCXNuYW5kYy0+cmVncy0+c3BpX2NmZyA9IHNuYW5kX2NmZ192YWw7Cj4+ICsK Pj4gKwlxY29tX3dyaXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRjLT5yZWdzLT5zcGlfY2ZnLCBO QU5EX0ZMQVNIX1NQSV9DRkcsIDEsIDApOwo+PiArCj4+ICsJcWNvbV93cml0ZV9yZWdfZG1hKHNu YW5kYywgJnNuYW5kYy0+cmVncy0+bnVtX2FkZHJfY3ljbGUsIE5BTkRfTlVNX0FERFJfQ1lDTEVT LCAxLCAwKTsKPj4gKwlxY29tX3dyaXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRjLT5yZWdzLT5i dXN5X3dhaXRfY250LCBOQU5EX0JVU1lfQ0hFQ0tfV0FJVF9DTlQsIDEsCj4+ICsJCQkgICBOQU5E X0JBTV9ORVhUX1NHTCk7Cj4+ICsKPj4gKwlyZXQgPSBxY29tX3N1Ym1pdF9kZXNjcyhzbmFuZGMp Owo+PiArCWlmIChyZXQpIHsKPj4gKwkJZGV2X2VycihzbmFuZGMtPmRldiwgImZhaWx1cmUgaW4g c3VibWl0dGluZyBzcGkgaW5pdCBkZXNjcmlwdG9yXG4iKTsKPj4gKwkJcmV0dXJuIHJldDsKPj4g Kwl9Cj4+ICsKPj4gKwlyZXR1cm4gcmV0Owo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW50IHFjb21f c3BpX29vYmxheW91dF9lY2Moc3RydWN0IG10ZF9pbmZvICptdGQsIGludCBzZWN0aW9uLAo+PiAr CQkJCSAgc3RydWN0IG10ZF9vb2JfcmVnaW9uICpvb2JyZWdpb24pCj4+ICt7Cj4+ICsJc3RydWN0 IG5hbmRfZGV2aWNlICpuYW5kID0gbXRkX3RvX25hbmRkZXYobXRkKTsKPj4gKwlzdHJ1Y3QgcWNv bV9uYW5kX2NvbnRyb2xsZXIgKnNuYW5kYyA9IG5hbmRfdG9fcWNvbV9zbmFuZChuYW5kKTsKPj4g KwlzdHJ1Y3QgcXBpY19lY2MgKnFlY2MgPSBzbmFuZGMtPnFzcGktPmVjYzsKPj4gKwo+PiArCWlm IChzZWN0aW9uID4gMSkKPj4gKwkJcmV0dXJuIC1FUkFOR0U7Cj4+ICsKPj4gKwlpZiAoIXNlY3Rp b24pIHsKPj4gKwkJb29icmVnaW9uLT5sZW5ndGggPSAocWVjYy0+Ynl0ZXMgKiAocWVjYy0+c3Rl cHMgLSAxKSkgKyBxZWNjLT5iYm1fc2l6ZTsKPj4gKwkJb29icmVnaW9uLT5vZmZzZXQgPSAwOwo+ IAo+IE5vLCBvZmZzZXQgMCBpcyBmb3IgdGhlIEJCTS4gVGhpcyBpcyB3cm9uZy4KPiBUaGUgd2hv bGUgb29iIGxheW91dCBsb29rcyByZWFsbHkgcmVhbGx5IHdyb25nLgo+IAo+IEVDQyBieXRlcyBh cmUgd2hlcmUgdGhlIEVDQyBlbmdpbmUgcHV0cyBpdHMgYnl0ZXMgaW4gdGhlIE9PQiBhcmVhLgo+ IEZyZWUgYnl0ZXMgc3RhcnQgYWZ0ZXIgdGhlIEJCTSBhbmQgZmlsbCB0aGUgZ2FwcyB1bnRpbCB0 aGUgZW5kIG9mIHRoZQo+IGFyZWEsIGV4Y2VwdCB3aGVyZSB0aGVyZSBhcmUgRUNDIGJ5dGVzLgog IFFQSUMgTkFORCBjb250cm9sbGVyIGhhdmluZyBpdHMgb3duIHBhZ2UgbGF5b3V0IHdpdGggZWNj IGFuZCB3aXRob3V0IGVjYy4KICBUaGUgc2FtZSBsYXlvdXQgd2UgYXJlIHVzaW5nIGluIHJhdyBu YW5kIGRyaXZlciBhcyB3ZWxsLCBzbyBpIHVzZWQgdGhlCiAgc2FtZSBoZXJlLiBUaGUgYmVsb3cg aW5mbyBpcyBhbHJlYWR5IHRoZXJlIGluIHFjb20gcmF3IG5hbmQgZHJpdmVyIGZpbGUKICBpbiBw YWdlIGxheW91dCBpbmZvLgoKICBRUElDIE5BTkQgY29udHJvbGxlciBsYXlvdXQgYXMgYmVsb3c6 CgogICBMYXlvdXQgd2l0aCBFQ0MgZW5hYmxlZDoKCiAgICAgfC0tLS0tLS0tLS0tLS0tLS0tLS0t LS18ICB8LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAogICAgIHwgICAgICAgICAg IHh4Li4uLi4uLnl5fCAgfCAgICAgICAgICAgICAqKioqKioqKip4eC4uLi4uLi55eXwKICAgICB8 ICAgIERBVEEgICB4eC4uRUNDLi55eXwgIHwgICAgREFUQSAgICAgKipTUEFSRSoqeHguLkVDQy4u eXl8CiAgICAgfCAgICg1MTYpICAgeHguLi4uLi4ueXl8ICB8ICAoNTE2LW4qNCkgICoqKG4qNCkq Knh4Li4uLi4uLnl5fAogICAgIHwgICAgICAgICAgIHh4Li4uLi4uLnl5fCAgfCAgICAgICAgICAg ICAqKioqKioqKip4eC4uLi4uLi55eXwKICAgICB8LS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwgIHwt LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18CiAgICAgIGNvZGV3b3JkIDEsMi4ubi0x ICAgICAgICAgICAgICAgICAgY29kZXdvcmQgbgogICAgIDwtLS0oNTI4LzUzMiBCeXRlcyktLT4g ICAgPC0tLS0tLS0oNTI4LzUzMiBCeXRlcyktLS0tLS0tLS0+CgogICAgIG4gPSBOdW1iZXIgb2Yg Y29kZXdvcmRzIGluIHRoZSBwYWdlCiAgICAgLiA9IEVDQyBieXRlcwogICAgICogPSBTcGFyZS9m cmVlIGJ5dGVzCiAgICAgeCA9IFVudXNlZCBieXRlKHMpCiAgICAgeSA9IFJlc2VydmVkIGJ5dGUo cykKCiAgICAgMksgcGFnZTogbiA9IDQsIHNwYXJlID0gMTYgYnl0ZXMKICAgICA0SyBwYWdlOiBu ID0gOCwgc3BhcmUgPSAzMiBieXRlcwogICAgIDhLIHBhZ2U6IG4gPSAxNiwgc3BhcmUgPSA2NCBi eXRlcwoKICAgICB0aGUgcWNvbSBuYW5kIGNvbnRyb2xsZXIgb3BlcmF0ZXMgYXQgYSBzdWIgcGFn ZS9jb2Rld29yZCBsZXZlbC4gZWFjaAogICAgIGNvZGV3b3JkIGlzIDUyOCBhbmQgNTMyIGJ5dGVz IGZvciA0IGJpdCBhbmQgOCBiaXQgRUNDIG1vZGVzIHJlc3BlY3RpdmVseS4KICAgICB0aGUgbnVt YmVyIG9mIEVDQyBieXRlcyB2YXJ5IGJhc2VkIG9uIHRoZSBFQ0Mgc3RyZW5ndGggYW5kIHRoZSBi dXMgd2lkdGguCgogICAgIHRoZSBmaXJzdCBuIC0gMSBjb2Rld29yZHMgY29udGFpbnMgNTE2IGJ5 dGVzIG9mIHVzZXIgZGF0YSwgdGhlIHJlbWFpbmluZwogICAgIDEyLzE2IGJ5dGVzIGNvbnNpc3Qg b2YgRUNDIGFuZCByZXNlcnZlZCBkYXRhLiBUaGUgbnRoIGNvZGV3b3JkIGNvbnRhaW5zCiAgICAg Ym90aCB1c2VyIGRhdGEgYW5kIHNwYXJlKG9vYmF2YWlsKSBieXRlcyB0aGF0IHN1bSB1cCB0byA1 MTYgYnl0ZXMuCgogICAgIFdoZW4gd2UgYWNjZXNzIGEgcGFnZSB3aXRoIEVDQyBlbmFibGVkLCB0 aGUgcmVzZXJ2ZWQgYnl0ZXMocykgYXJlIG5vdAogICAgIGFjY2Vzc2libGUgYXQgYWxsLiBXaGVu IHJlYWRpbmcsIHdlIGZpbGwgdXAgdGhlc2UgdW5yZWFkYWJsZSBwb3NpdGlvbnMKICAgICB3aXRo IDB4ZmZzLiBXaGVuIHdyaXRpbmcsIHRoZSBjb250cm9sbGVyIHNraXBzIHdyaXRpbmcgdGhlIGlu YWNjZXNzaWJsZQogICAgIGJ5dGVzLgoKICAgICBMYXlvdXQgd2l0aCBFQ0MgZGlzYWJsZWQ6Cgog ICAgIHwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18ICB8LS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tfAogICAgIHwgICAgICAgICB5eSAgICAgICAgICB4eC4uLi4u Li58ICB8ICAgICAgICAgYmIgICAgICAgICAgKioqKioqKioqeHguLi4uLi4ufAogICAgIHwgIERB VEExICB5eSAgREFUQTIgICB4eC4uRUNDLi58ICB8ICBEQVRBMSAgYmIgIERBVEEyICAgKipTUEFS RSoqeHguLkVDQy4ufAogICAgIHwgKHNpemUxKSB5eSAoc2l6ZTIpICB4eC4uLi4uLi58ICB8IChz aXplMSkgYmIgKHNpemUyKSAgKioobio0KSoqeHguLi4uLi4ufAogICAgIHwgICAgICAgICB5eSAg ICAgICAgICB4eC4uLi4uLi58ICB8ICAgICAgICAgYmIgICAgICAgICAgKioqKioqKioqeHguLi4u Li4ufAogICAgIHwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18ICB8LS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfAogICAgICAgICAgY29kZXdvcmQgMSwyLi5uLTEg ICAgICAgICAgICAgICAgICAgICAgICBjb2Rld29yZCBuCiAgICAgPC0tLS0tLS0oNTI4LzUzMiBC eXRlcyktLS0tLS0+ICAgIDwtLS0tLS0tLS0tLSg1MjgvNTMyIEJ5dGVzKS0tLS0tLS0tLS0tPgoK ICAgICBuID0gTnVtYmVyIG9mIGNvZGV3b3JkcyBpbiB0aGUgcGFnZQogICAgIC4gPSBFQ0MgYnl0 ZXMKICAgICAqID0gU3BhcmUvZnJlZSBieXRlcwogICAgIHggPSBVbnVzZWQgYnl0ZShzKQogICAg IHkgPSBEdW1teSBCYWQgQm9jayBieXRlKHMpCiAgICAgYiA9IFJlYWwgQmFkIEJsb2NrIGJ5dGUo cykKICAgICBzaXplMS9zaXplMiA9IGZ1bmN0aW9uIG9mIGNvZGV3b3JkIHNpemUgYW5kICduJwoK ICAgICB3aGVuIHRoZSBFQ0MgYmxvY2sgaXMgZGlzYWJsZWQsIG9uZSByZXNlcnZlZCBieXRlIChv ciB0d28gZm9yIDE2IGJpdCBidXMKICAgICB3aWR0aCkgaXMgbm93IGFjY2Vzc2libGUuIEZvciB0 aGUgZmlyc3QgbiAtIDEgY29kZXdvcmRzLCB0aGVzZSBhcmUgZHVtbXkgQmFkCiAgICAgQmxvY2sg TWFya2Vycy4gSW4gdGhlIGxhc3QgY29kZXdvcmQsIHRoaXMgcG9zaXRpb24gY29udGFpbnMgdGhl IHJlYWwgQkJNCgogICAgIEluIG9yZGVyIHRvIGhhdmUgYSBjb25zaXN0ZW50IGxheW91dCBiZXR3 ZWVuIFJBVyBhbmQgRUNDIG1vZGVzLCB3ZSBhc3N1bWUKICAgICB0aGUgZm9sbG93aW5nIE9PQiBs YXlvdXQgYXJyYW5nZW1lbnQ6CgogICAgIHwtLS0tLS0tLS0tLXwgIHwtLS0tLS0tLS0tLS0tLS0t LS0tLXwKICAgICB8eXl4eC4uLi4uLi58ICB8YmIqKioqKioqKip4eC4uLi4uLi58CiAgICAgfHl5 eHguLkVDQy4ufCAgfGJiKkZSRUVPT0IqeHguLkVDQy4ufAogICAgIHx5eXh4Li4uLi4uLnwgIHxi YioqKioqKioqKnh4Li4uLi4uLnwKICAgICB8eXl4eC4uLi4uLi58ICB8YmIqKioqKioqKip4eC4u Li4uLi58CiAgICAgfC0tLS0tLS0tLS0tfCAgfC0tLS0tLS0tLS0tLS0tLS0tLS0tfAogICAgIGZp cnN0IG4gLSAxICAgICAgIG50aCBPT0IgcmVnaW9uCiAgICAgT09CIHJlZ2lvbnMKCiAgICAgbiA9 IE51bWJlciBvZiBjb2Rld29yZHMgaW4gdGhlIHBhZ2UKICAgICAuID0gRUNDIGJ5dGVzCiAgICAg KiA9IEZSRUUgT09CIGJ5dGVzCiAgICAgeSA9IER1bW15IGJhZCBibG9jayBieXRlKHMpIChpbmFj Y2Vzc2libGUgd2hlbiBFQ0MgZW5hYmxlZCkKICAgICB4ID0gVW51c2VkIGJ5dGUocykKICAgICBi ID0gUmVhbCBiYWQgYmxvY2sgYnl0ZShzKSAoaW5hY2Nlc3NpYmxlIHdoZW4gRUNDIGVuYWJsZWQp CgogICAgIFRoaXMgbGF5b3V0IGlzIHJlYWQgYXMgaXMgd2hlbiBFQ0MgaXMgZGlzYWJsZWQuIFdo ZW4gRUNDIGlzIGVuYWJsZWQsIHRoZQogICAgIGluYWNjZXNzaWJsZSBCYWQgQmxvY2sgYnl0ZShz KSBhcmUgaWdub3JlZCB3aGVuIHdlIHdyaXRlIHRvIGEgcGFnZS9vb2IsCiAgICAgYW5kIGFzc3Vt ZWQgYXMgMHhmZnMgd2hlbiB3ZSByZWFkIGEgcGFnZS9vb2IuIFRoZSBFQ0MsIHVudXNlZCBhbmQK ICAgICBkdW1teS9yZWFsIGJhZCBibG9jayBieXRlcyBhcmUgZ3JvdXBlZCBhcyBlY2MgYnl0ZXMg KGkuZSwgZWNjLT5ieXRlcyBpcwogICAgIHRoZSBzdW0gb2YgdGhlIHRocmVlKS4KCj4gCj4+ICsJ fSBlbHNlIHsKPj4gKwkJb29icmVnaW9uLT5sZW5ndGggPSBxZWNjLT5lY2NfYnl0ZXNfaHcgKyBx ZWNjLT5zcGFyZV9ieXRlczsKPj4gKwkJb29icmVnaW9uLT5vZmZzZXQgPSBtdGQtPm9vYnNpemUg LSBvb2JyZWdpb24tPmxlbmd0aDsKPj4gKwl9Cj4+ICsKPj4gKwlyZXR1cm4gMDsKPj4gK30KPj4g Kwo+PiArc3RhdGljIGludCBxY29tX3NwaV9vb2JsYXlvdXRfZnJlZShzdHJ1Y3QgbXRkX2luZm8g Km10ZCwgaW50IHNlY3Rpb24sCj4+ICsJCQkJICAgc3RydWN0IG10ZF9vb2JfcmVnaW9uICpvb2Jy ZWdpb24pCj4+ICt7Cj4+ICsJc3RydWN0IG5hbmRfZGV2aWNlICpuYW5kID0gbXRkX3RvX25hbmRk ZXYobXRkKTsKPj4gKwlzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRyb2xsZXIgKnNuYW5kYyA9IG5hbmRf dG9fcWNvbV9zbmFuZChuYW5kKTsKPj4gKwlzdHJ1Y3QgcXBpY19lY2MgKnFlY2MgPSBzbmFuZGMt PnFzcGktPmVjYzsKPj4gKwo+PiArCWlmIChzZWN0aW9uKQo+PiArCQlyZXR1cm4gLUVSQU5HRTsK Pj4gKwo+PiArCW9vYnJlZ2lvbi0+bGVuZ3RoID0gcWVjYy0+c3RlcHMgKiA0Owo+PiArCW9vYnJl Z2lvbi0+b2Zmc2V0ID0gKChxZWNjLT5zdGVwcyAtIDEpICogcWVjYy0+Ynl0ZXMpICsgcWVjYy0+ YmJtX3NpemU7Cj4+ICsKPj4gKwlyZXR1cm4gMDsKPj4gK30KPj4gKwo+IAo+IC4uLgo+IAo+PiAr c3RhdGljIGludCBxY29tX3NwaV9lY2NfcHJlcGFyZV9pb19yZXFfcGlwZWxpbmVkKHN0cnVjdCBu YW5kX2RldmljZSAqbmFuZCwKPj4gKwkJCQkJCSBzdHJ1Y3QgbmFuZF9wYWdlX2lvX3JlcSAqcmVx KQo+PiArewo+PiArCXN0cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqc25hbmRjID0gbmFuZF90 b19xY29tX3NuYW5kKG5hbmQpOwo+PiArCXN0cnVjdCBxcGljX2VjYyAqZWNjX2NmZyA9IG5hbmRf dG9fZWNjX2N0eChuYW5kKTsKPj4gKwlzdHJ1Y3QgbXRkX2luZm8gKm10ZCA9IG5hbmRkZXZfdG9f bXRkKG5hbmQpOwo+PiArCj4+ICsJc25hbmRjLT5xc3BpLT5lY2MgPSBlY2NfY2ZnOwo+PiArCXNu YW5kYy0+cXNwaS0+cGFnZXNpemUgPSBtdGQtPndyaXRlc2l6ZTsKPj4gKwlzbmFuZGMtPnFzcGkt PnJhd19ydyA9IGZhbHNlOwo+PiArCXNuYW5kYy0+cXNwaS0+b29iX3J3ID0gZmFsc2U7Cj4+ICsJ c25hbmRjLT5xc3BpLT5wYWdlX3J3ID0gZmFsc2U7Cj4+ICsKPj4gKwlpZiAocmVxLT5kYXRhbGVu KQo+PiArCQlzbmFuZGMtPnFzcGktPnBhZ2VfcncgPSB0cnVlOwo+PiArCj4+ICsJaWYgKHJlcS0+ b29ibGVuKSB7Cj4+ICsJCXNuYW5kYy0+cXNwaS0+b29iX3J3ID0gdHJ1ZTsKPj4gKwkJaWYgKHJl cS0+b29ibGVuID09IEJBRF9CTE9DS19NQVJLRVJfU0laRSkKPj4gKwkJCXNuYW5kYy0+cXNwaS0+ cmVhZF9sYXN0X2N3ID0gdHJ1ZTsKPiAKPiA/Pz8KICAgQXMgcGVyIFFQSUMgY29udHJvbGxlciBs YXlvdXQgLCB0aGUgYWN0dWFsIGJhYmQgYmxvY2sgbWFya2VyIHdpbGwKICAgYmUgcHJlc2VudCBp biBsYXN0IGNvZGUgd29yZC4gVGhhdHMgd2h5IGkgaGF2ZSBhZGRlZCB0aGlzIGNoZWNrLgogICB0 byByZWFkIG9ubHkgbGFzdCBjb2Rld29yZCBmb3IgYmFkIGJsb2NrIGNoZWNrLgo+IAo+PiArCX0K Pj4gKwo+PiArCWlmIChyZXEtPm1vZGUgPT0gTVREX09QU19SQVcpCj4+ICsJCXNuYW5kYy0+cXNw aS0+cmF3X3J3ID0gdHJ1ZTsKPj4gKwo+PiArCXJldHVybiAwOwo+PiArfQo+PiArCj4+ICtzdGF0 aWMgaW50IHFjb21fc3BpX2VjY19maW5pc2hfaW9fcmVxX3BpcGVsaW5lZChzdHJ1Y3QgbmFuZF9k ZXZpY2UgKm5hbmQsCj4+ICsJCQkJCQlzdHJ1Y3QgbmFuZF9wYWdlX2lvX3JlcSAqcmVxKQo+PiAr ewo+PiArCXN0cnVjdCBxY29tX25hbmRfY29udHJvbGxlciAqc25hbmRjID0gbmFuZF90b19xY29t X3NuYW5kKG5hbmQpOwo+PiArCXN0cnVjdCBtdGRfaW5mbyAqbXRkID0gbmFuZGRldl90b19tdGQo bmFuZCk7Cj4+ICsKPj4gKwlpZiAocmVxLT5tb2RlID09IE1URF9PUFNfUkFXIHx8IHJlcS0+dHlw ZSAhPSBOQU5EX1BBR0VfUkVBRCkKPj4gKwkJcmV0dXJuIDA7Cj4+ICsKPj4gKwlpZiAoc25hbmRj LT5xc3BpLT5lY2Nfc3RhdHMuZmFpbGVkKQo+PiArCQltdGQtPmVjY19zdGF0cy5mYWlsZWQgKz0g c25hbmRjLT5xc3BpLT5lY2Nfc3RhdHMuZmFpbGVkOwo+PiArCW10ZC0+ZWNjX3N0YXRzLmNvcnJl Y3RlZCArPSBzbmFuZGMtPnFzcGktPmVjY19zdGF0cy5jb3JyZWN0ZWQ7Cj4gCj4gU2VlbXMgc3Ry YW5nZQogICBJbiBmbGFzaCBlcnJvciBjaGVjayBmb3IgZWFjaCBjb2RlIHdvcmQgaSBhbSB1cGRh dGluZyB0aGUgZXJyb3IgdmFsdWUuCiAgIFNvIG9uIGZpbmlzaGluZyBvbiBpbyBpIGFtIGFzc2ln bmluZyB0aGF0IGVycm9yIHRvIG10ZCB2YXJpYWJsZXMgc28gdGhhdAogICB1cHBlciBsYXllciBj aGVjayBmb3IgZXJyb3IuCj4gCj4+ICsKPj4gKwlpZiAoc25hbmRjLT5xc3BpLT5lY2Nfc3RhdHMu ZmFpbGVkKQo+PiArCQlyZXR1cm4gLUVCQURNU0c7Cj4+ICsJZWxzZQo+PiArCQlyZXR1cm4gc25h bmRjLT5xc3BpLT5lY2Nfc3RhdHMuYml0ZmxpcHM7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBzdHJ1 Y3QgbmFuZF9lY2NfZW5naW5lX29wcyBxY29tX3NwaV9lY2NfZW5naW5lX29wc19waXBlbGluZWQg PSB7Cj4+ICsJLmluaXRfY3R4ID0gcWNvbV9zcGlfZWNjX2luaXRfY3R4X3BpcGVsaW5lZCwKPj4g KwkuY2xlYW51cF9jdHggPSBxY29tX3NwaV9lY2NfY2xlYW51cF9jdHhfcGlwZWxpbmVkLAo+PiAr CS5wcmVwYXJlX2lvX3JlcSA9IHFjb21fc3BpX2VjY19wcmVwYXJlX2lvX3JlcV9waXBlbGluZWQs Cj4+ICsJLmZpbmlzaF9pb19yZXEgPSBxY29tX3NwaV9lY2NfZmluaXNoX2lvX3JlcV9waXBlbGlu ZWQsCj4+ICt9Owo+PiArCj4gCj4gLi4uCj4gCj4+ICtzdGF0aWMgaW50IHFjb21fc3BpX3JlYWRf cGFnZV9yYXcoc3RydWN0IHFjb21fbmFuZF9jb250cm9sbGVyICpzbmFuZGMsCj4+ICsJCQkJICBj b25zdCBzdHJ1Y3Qgc3BpX21lbV9vcCAqb3ApCj4+ICt7Cj4+ICsJc3RydWN0IHFwaWNfZWNjICpl Y2NfY2ZnID0gc25hbmRjLT5xc3BpLT5lY2M7Cj4+ICsJdTggKmRhdGFfYnVmID0gTlVMTCwgKm9v Yl9idWYgPSBOVUxMOwo+PiArCWludCByZXQsIGN3Owo+PiArCXUzMiBudW1fY3cgPSBzbmFuZGMt PnFzcGktPm51bV9jdzsKPj4gKwo+PiArCWlmIChzbmFuZGMtPnFzcGktPnBhZ2VfcncpCj4gCj4g SSBkb24ndCBsaWtlIHRoaXMgaW5kaXJlY3Rpb24gdmVyeSBtdWNoLiBDYW4ndCB5b3Ugc2ltcGxp ZnkgdGhpcyBhbmQKPiBqdXN0IGZvbGxvdyB0aGUgc3BpLW1lbSBvcCBpbnN0ZWFkIG9mIGNvbnN0 YW50bHkgdHJ5aW5nIHRvIGFkZAo+IGFkZGl0aW9uYWwgc3R1ZmY/CiAgIFRoaXMgaW5kaXJlY3Rp b24gbmVlZGVkIGR1ZSB0byBRUElDIGNvbnRyb2xsZXIgd2lsbCBub3QgdGFrZSBhbGwgdGhlIGlu c3RydWN0aW9uCiAgIG9uZS1ieS1vbmUgLCBvbmNlIHdlIHdpbGwgc2V0IENNRF9FWEVDID0gMSwg dGhlbiBpdCB3aWxsIGV4ZWN1dGUgYWxsIHRoZSBpbnN0cnVjdGlvbgogICBhdCBvbmNlLgo+IAo+ IFRoZSBoYXJkd2FyZSBpcyBhbHJlYWR5IHF1aXRlIGNvbXBsZXgsIGJ1dCBpdCBmZWVscyBsaWtl IHlvdXIgYWRkaW5nCj4geWV0IGFub3RoZXIgcGlsZSBvZiB1bm5lY2Vzc2FyeSBjb21wbGV4aXR5 LgogICBZZXMgaGFyZHdhcmUgaXMgY29tcGxleC4gbGV0IG1lIGNoZWNrIGlmIGkgY2FuIGZ1cnRo ZXIgb3B0aW1pemUgYXMgcGVyIHNwaS1tZW0gb3AKICAgYXMgeW91IHN1Z2dlc3RlZC4KPiAKPj4g KwkJZGF0YV9idWYgPSBvcC0+ZGF0YS5idWYuaW47Cj4+ICsKPj4gKwlpZiAoc25hbmRjLT5xc3Bp LT5vb2JfcncpCj4+ICsJCW9vYl9idWYgPSBvcC0+ZGF0YS5idWYuaW47Cj4gCj4gU2FtZSBidWZm ZXIgcG9pbnRlZCBieSB0aGUgdHdvIHBvaW50ZXJzPyBodW0KICBPayAsIHdpbGwgZml4IGluIG5l eHQgcGF0Y2guCj4gCj4+ICsKPj4gKwlpZiAoIW9vYl9idWYpIHsKPj4gKwkJb29iX2J1ZiA9IHNu YW5kYy0+cXNwaS0+b29iX2J1ZjsKPj4gKwkJbWVtc2V0KG9vYl9idWYsIDB4ZmYsIE9PQl9CVUZf U0laRSk7Cj4+ICsJfQo+PiArCj4+ICsJZm9yIChjdyA9IDA7IGN3IDwgbnVtX2N3OyBjdysrKSB7 Cj4+ICsJCXJldCA9IHFjb21fc3BpX3JlYWRfY3dfcmF3KHNuYW5kYywgZGF0YV9idWYsIG9vYl9i dWYsIGN3KTsKPj4gKwkJaWYgKHJldCkKPj4gKwkJCXJldHVybiByZXQ7Cj4+ICsKPj4gKwkJaWYg KGRhdGFfYnVmKQo+PiArCQkJZGF0YV9idWYgKz0gZWNjX2NmZy0+Y3dfZGF0YTsKPj4gKwkJaWYg KG9vYl9idWYpCj4+ICsJCQlvb2JfYnVmICs9IGVjY19jZmctPmJ5dGVzOwo+PiArCX0KPj4gKwo+ PiArCXJldHVybiAwOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgaW50IHFjb21fc3BpX3JlYWRfcGFn ZV9jYWNoZShzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRyb2xsZXIgKnNuYW5kYywKPj4gKwkJCQkgICAg Y29uc3Qgc3RydWN0IHNwaV9tZW1fb3AgKm9wKQo+PiArewo+PiArCXN0cnVjdCBxcGljX2VjYyAq ZWNjX2NmZyA9IHNuYW5kYy0+cXNwaS0+ZWNjOwo+PiArCXU4ICpkYXRhX2J1ZiA9IE5VTEwsICpk YXRhX2J1Zl9zdGFydCwgKm9vYl9idWYgPSBOVUxMLCAqb29iX2J1Zl9zdGFydDsKPj4gKwlpbnQg cmV0LCBpOwo+PiArCXUzMiBjZmcwLCBjZmcxLCBlY2NfYmNoX2NmZywgbnVtX2N3ID0gc25hbmRj LT5xc3BpLT5udW1fY3c7Cj4+ICsKPj4gKwlpZiAoc25hbmRjLT5xc3BpLT5wYWdlX3J3KSB7Cj4+ ICsJCWRhdGFfYnVmID0gb3AtPmRhdGEuYnVmLmluOwo+PiArCQlkYXRhX2J1Zl9zdGFydCA9IGRh dGFfYnVmOwo+PiArCX0KPj4gKwo+PiArCWlmIChzbmFuZGMtPnFzcGktPm9vYl9ydyB8fCBzbmFu ZGMtPnFzcGktPnJhd19ydykgewo+PiArCQlvb2JfYnVmID0gb3AtPmRhdGEuYnVmLmluOwo+PiAr CQlvb2JfYnVmX3N0YXJ0ID0gb29iX2J1ZjsKPj4gKwl9Cj4+ICsKPj4gKwlpZiAoc25hbmRjLT5x c3BpLT5wYWdlX3J3ICYmIHNuYW5kYy0+cXNwaS0+cmF3X3J3KQo+PiArCQlyZXR1cm4gcWNvbV9z cGlfcmVhZF9wYWdlX3JhdyhzbmFuZGMsIG9wKTsKPj4gKwo+PiArCWlmIChzbmFuZGMtPnFzcGkt Pm9vYl9ydyAmJiBzbmFuZGMtPnFzcGktPnJhd19ydyAmJiBzbmFuZGMtPnFzcGktPnJlYWRfbGFz dF9jdykKPj4gKwkJcmV0dXJuIHFjb21fc3BpX3JlYWRfbGFzdF9jdyhzbmFuZGMsIG9wKTsKPj4g Kwo+PiArCXNuYW5kYy0+YnVmX2NvdW50ID0gMDsKPj4gKwlzbmFuZGMtPmJ1Zl9zdGFydCA9IDA7 Cj4+ICsJcWNvbV9jbGVhcl9yZWFkX3JlZ3Moc25hbmRjKTsKPj4gKwo+PiArCWNmZzAgPSAoZWNj X2NmZy0+Y2ZnMCAmIH4oN1UgPDwgQ1dfUEVSX1BBR0UpKSB8Cj4+ICsJCQkJKG51bV9jdyAtIDEp IDw8IENXX1BFUl9QQUdFOwo+PiArCWNmZzEgPSBlY2NfY2ZnLT5jZmcxOwo+PiArCWVjY19iY2hf Y2ZnID0gZWNjX2NmZy0+ZWNjX2JjaF9jZmc7Cj4+ICsKPj4gKwlzbmFuZGMtPnJlZ3MtPmFkZHIw ID0gc25hbmRjLT5xc3BpLT5hZGRyMTsKPj4gKwlzbmFuZGMtPnJlZ3MtPmFkZHIxID0gc25hbmRj LT5xc3BpLT5hZGRyMjsKPj4gKwlzbmFuZGMtPnJlZ3MtPmNtZCA9IHNuYW5kYy0+cXNwaS0+Y21k Owo+PiArCXNuYW5kYy0+cmVncy0+Y2ZnMCA9IGNmZzA7Cj4+ICsJc25hbmRjLT5yZWdzLT5jZmcx ID0gY2ZnMTsKPj4gKwlzbmFuZGMtPnJlZ3MtPmVjY19iY2hfY2ZnID0gZWNjX2JjaF9jZmc7Cj4+ ICsJc25hbmRjLT5yZWdzLT5jbHJmbGFzaHN0YXR1cyA9IGVjY19jZmctPmNscmZsYXNoc3RhdHVz Owo+PiArCXNuYW5kYy0+cmVncy0+Y2xycmVhZHN0YXR1cyA9IGVjY19jZmctPmNscnJlYWRzdGF0 dXM7Cj4+ICsJc25hbmRjLT5yZWdzLT5leGVjID0gMTsKPj4gKwo+PiArCXFjb21fc3BpX3NldF9y ZWFkX2xvYyhzbmFuZGMsIDAsIDAsIDAsIGVjY19jZmctPmN3X2RhdGEsIDEpOwo+PiArCj4+ICsJ cWNvbV9jbGVhcl9iYW1fdHJhbnNhY3Rpb24oc25hbmRjKTsKPj4gKwo+PiArCXFjb21fd3JpdGVf cmVnX2RtYShzbmFuZGMsICZzbmFuZGMtPnJlZ3MtPmFkZHIwLCBOQU5EX0FERFIwLCAyLCAwKTsK Pj4gKwlxY29tX3dyaXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRjLT5yZWdzLT5jZmcwLCBOQU5E X0RFVjBfQ0ZHMCwgMywgMCk7Cj4+ICsJcWNvbV93cml0ZV9yZWdfZG1hKHNuYW5kYywgJnNuYW5k Yy0+cmVncy0+ZXJhc2VkX2N3X2RldGVjdF9jZmdfY2xyLAo+PiArCQkJICAgTkFORF9FUkFTRURf Q1dfREVURUNUX0NGRywgMSwgMCk7Cj4+ICsJcWNvbV93cml0ZV9yZWdfZG1hKHNuYW5kYywgJnNu YW5kYy0+cmVncy0+ZXJhc2VkX2N3X2RldGVjdF9jZmdfc2V0LAo+PiArCQkJICAgTkFORF9FUkFT RURfQ1dfREVURUNUX0NGRywgMSwKPj4gKwkJCSAgIE5BTkRfRVJBU0VEX0NXX1NFVCB8IE5BTkRf QkFNX05FWFRfU0dMKTsKPj4gKwo+PiArCWZvciAoaSA9IDA7IGkgPCBudW1fY3c7IGkrKykgewo+ PiArCQlpbnQgZGF0YV9zaXplLCBvb2Jfc2l6ZTsKPj4gKwo+PiArCQlpZiAoaSA9PSAobnVtX2N3 IC0gMSkpIHsKPj4gKwkJCWRhdGFfc2l6ZSA9IDUxMiAtICgobnVtX2N3IC0gMSkgPDwgMik7Cj4+ ICsJCQlvb2Jfc2l6ZSA9IChudW1fY3cgPDwgMikgKyBlY2NfY2ZnLT5lY2NfYnl0ZXNfaHcgKwo+ PiArCQkJCSAgICBlY2NfY2ZnLT5zcGFyZV9ieXRlczsKPj4gKwkJfSBlbHNlIHsKPj4gKwkJCWRh dGFfc2l6ZSA9IGVjY19jZmctPmN3X2RhdGE7Cj4+ICsJCQlvb2Jfc2l6ZSA9IGVjY19jZmctPmVj Y19ieXRlc19odyArIGVjY19jZmctPnNwYXJlX2J5dGVzOwo+PiArCQl9Cj4+ICsKPj4gKwkJaWYg KGRhdGFfYnVmICYmIG9vYl9idWYpIHsKPj4gKwkJCXFjb21fc3BpX3NldF9yZWFkX2xvYyhzbmFu ZGMsIGksIDAsIDAsIGRhdGFfc2l6ZSwgMCk7Cj4+ICsJCQlxY29tX3NwaV9zZXRfcmVhZF9sb2Mo c25hbmRjLCBpLCAxLCBkYXRhX3NpemUsIG9vYl9zaXplLCAxKTsKPj4gKwkJfSBlbHNlIGlmIChk YXRhX2J1Zikgewo+PiArCQkJcWNvbV9zcGlfc2V0X3JlYWRfbG9jKHNuYW5kYywgaSwgMCwgMCwg ZGF0YV9zaXplLCAxKTsKPj4gKwkJfSBlbHNlIHsKPj4gKwkJCXFjb21fc3BpX3NldF9yZWFkX2xv YyhzbmFuZGMsIGksIDAsIGRhdGFfc2l6ZSwgb29iX3NpemUsIDEpOwo+PiArCQl9Cj4+ICsKPj4g KwkJcWNvbV9zcGlfY29uZmlnX2N3X3JlYWQoc25hbmRjLCB0cnVlLCBpKTsKPj4gKwo+PiArCQlp ZiAoZGF0YV9idWYpCj4+ICsJCQlxY29tX3JlYWRfZGF0YV9kbWEoc25hbmRjLCBGTEFTSF9CVUZf QUNDLCBkYXRhX2J1ZiwKPj4gKwkJCQkJICAgZGF0YV9zaXplLCAwKTsKPj4gKwkJaWYgKG9vYl9i dWYpIHsKPj4gKwkJCWludCBqOwo+PiArCj4+ICsJCQlmb3IgKGogPSAwOyBqIDwgZWNjX2NmZy0+ YmJtX3NpemU7IGorKykKPj4gKwkJCQkqb29iX2J1ZisrID0gMHhmZjsKPj4gKwo+PiArCQkJcWNv bV9yZWFkX2RhdGFfZG1hKHNuYW5kYywgRkxBU0hfQlVGX0FDQyArIGRhdGFfc2l6ZSwKPj4gKwkJ CQkJICAgb29iX2J1Ziwgb29iX3NpemUsIDApOwo+PiArCQl9Cj4+ICsKPj4gKwkJaWYgKGRhdGFf YnVmKQo+PiArCQkJZGF0YV9idWYgKz0gZGF0YV9zaXplOwo+PiArCQlpZiAob29iX2J1ZikKPj4g KwkJCW9vYl9idWYgKz0gb29iX3NpemU7Cj4+ICsJfQo+PiArCj4+ICsJcmV0ID0gcWNvbV9zdWJt aXRfZGVzY3Moc25hbmRjKTsKPj4gKwlpZiAocmV0KSB7Cj4+ICsJCWRldl9lcnIoc25hbmRjLT5k ZXYsICJmYWlsdXJlIHRvIHJlYWQgcGFnZVxuIik7Cj4+ICsJCXJldHVybiByZXQ7Cj4+ICsJfQo+ PiArCj4+ICsJcmV0dXJuIHFjb21fc3BpX2NoZWNrX2Vycm9yKHNuYW5kYywgZGF0YV9idWZfc3Rh cnQsIG9vYl9idWZfc3RhcnQpOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgdm9pZCBxY29tX3NwaV9j b25maWdfcGFnZV93cml0ZShzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRyb2xsZXIgKnNuYW5kYykKPj4g K3sKPj4gKwlxY29tX3dyaXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRjLT5yZWdzLT5hZGRyMCwg TkFORF9BRERSMCwgMiwgMCk7Cj4+ICsJcWNvbV93cml0ZV9yZWdfZG1hKHNuYW5kYywgJnNuYW5k Yy0+cmVncy0+Y2ZnMCwgTkFORF9ERVYwX0NGRzAsIDMsIDApOwo+PiArCXFjb21fd3JpdGVfcmVn X2RtYShzbmFuZGMsICZzbmFuZGMtPnJlZ3MtPmVjY19idWZfY2ZnLCBOQU5EX0VCSTJfRUNDX0JV Rl9DRkcsCj4+ICsJCQkgICAxLCBOQU5EX0JBTV9ORVhUX1NHTCk7Cj4+ICt9Cj4+ICsKPj4gK3N0 YXRpYyB2b2lkIHFjb21fc3BpX2NvbmZpZ19jd193cml0ZShzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRy b2xsZXIgKnNuYW5kYykKPj4gK3sKPj4gKwlxY29tX3dyaXRlX3JlZ19kbWEoc25hbmRjLCAmc25h bmRjLT5yZWdzLT5jbWQsIE5BTkRfRkxBU0hfQ01ELCAxLCBOQU5EX0JBTV9ORVhUX1NHTCk7Cj4+ ICsJcWNvbV93cml0ZV9yZWdfZG1hKHNuYW5kYywgJnNuYW5kYy0+cmVncy0+ZXhlYywgTkFORF9F WEVDX0NNRCwgMSwgTkFORF9CQU1fTkVYVF9TR0wpOwo+PiArCXFjb21fcmVhZF9yZWdfZG1hKHNu YW5kYywgTkFORF9GTEFTSF9TVEFUVVMsIDEsIE5BTkRfQkFNX05FWFRfU0dMKTsKPj4gKwo+PiAr CXFjb21fd3JpdGVfcmVnX2RtYShzbmFuZGMsICZzbmFuZGMtPnJlZ3MtPmNscmZsYXNoc3RhdHVz LCBOQU5EX0ZMQVNIX1NUQVRVUywgMSwgMCk7Cj4+ICsJcWNvbV93cml0ZV9yZWdfZG1hKHNuYW5k YywgJnNuYW5kYy0+cmVncy0+Y2xycmVhZHN0YXR1cywgTkFORF9SRUFEX1NUQVRVUywgMSwKPj4g KwkJCSAgIE5BTkRfQkFNX05FWFRfU0dMKTsKPj4gK30KPj4gKwo+PiArc3RhdGljIGludCBxY29t X3NwaV9wcm9ncmFtX3JhdyhzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRyb2xsZXIgKnNuYW5kYywKPj4g KwkJCQljb25zdCBzdHJ1Y3Qgc3BpX21lbV9vcCAqb3ApCj4+ICt7Cj4+ICsJc3RydWN0IHFwaWNf ZWNjICplY2NfY2ZnID0gc25hbmRjLT5xc3BpLT5lY2M7Cj4+ICsJdTggKmRhdGFfYnVmID0gTlVM TCwgKm9vYl9idWYgPSBOVUxMOwo+PiArCWludCBpLCByZXQ7Cj4+ICsJaW50IG51bV9jdyA9IHNu YW5kYy0+cXNwaS0+bnVtX2N3Owo+PiArCXUzMiBjZmcwLCBjZmcxLCBlY2NfYmNoX2NmZzsKPj4g Kwo+PiArCWNmZzAgPSAoZWNjX2NmZy0+Y2ZnMF9yYXcgJiB+KDdVIDw8IENXX1BFUl9QQUdFKSkg fAo+PiArCQkJKG51bV9jdyAtIDEpIDw8IENXX1BFUl9QQUdFOwo+PiArCWNmZzEgPSBlY2NfY2Zn LT5jZmcxX3JhdzsKPj4gKwllY2NfYmNoX2NmZyA9IEVDQ19DRkdfRUNDX0RJU0FCTEU7Cj4+ICsK Pj4gKwlkYXRhX2J1ZiA9IHNuYW5kYy0+cXNwaS0+ZGF0YV9idWY7Cj4+ICsKPj4gKwlvb2JfYnVm ID0gc25hbmRjLT5xc3BpLT5vb2JfYnVmOwo+PiArCW1lbXNldChvb2JfYnVmLCAweGZmLCBPT0Jf QlVGX1NJWkUpOwo+PiArCj4+ICsJc25hbmRjLT5idWZfY291bnQgPSAwOwo+PiArCXNuYW5kYy0+ YnVmX3N0YXJ0ID0gMDsKPj4gKwlxY29tX2NsZWFyX3JlYWRfcmVncyhzbmFuZGMpOwo+PiArCXFj b21fY2xlYXJfYmFtX3RyYW5zYWN0aW9uKHNuYW5kYyk7Cj4+ICsKPj4gKwlzbmFuZGMtPnJlZ3Mt PmFkZHIwID0gc25hbmRjLT5xc3BpLT5hZGRyMTsKPj4gKwlzbmFuZGMtPnJlZ3MtPmFkZHIxID0g c25hbmRjLT5xc3BpLT5hZGRyMjsKPj4gKwlzbmFuZGMtPnJlZ3MtPmNtZCA9IHNuYW5kYy0+cXNw aS0+Y21kOwo+PiArCXNuYW5kYy0+cmVncy0+Y2ZnMCA9IGNmZzA7Cj4+ICsJc25hbmRjLT5yZWdz LT5jZmcxID0gY2ZnMTsKPj4gKwlzbmFuZGMtPnJlZ3MtPmVjY19iY2hfY2ZnID0gZWNjX2JjaF9j Zmc7Cj4+ICsJc25hbmRjLT5yZWdzLT5jbHJmbGFzaHN0YXR1cyA9IGVjY19jZmctPmNscmZsYXNo c3RhdHVzOwo+PiArCXNuYW5kYy0+cmVncy0+Y2xycmVhZHN0YXR1cyA9IGVjY19jZmctPmNscnJl YWRzdGF0dXM7Cj4+ICsJc25hbmRjLT5yZWdzLT5leGVjID0gMTsKPj4gKwo+PiArCXFjb21fc3Bp X2NvbmZpZ19wYWdlX3dyaXRlKHNuYW5kYyk7Cj4+ICsKPj4gKwlmb3IgKGkgPSAwOyBpIDwgbnVt X2N3OyBpKyspIHsKPj4gKwkJaW50IGRhdGFfc2l6ZTEsIGRhdGFfc2l6ZTIsIG9vYl9zaXplMSwg b29iX3NpemUyOwo+PiArCQlpbnQgcmVnX29mZiA9IEZMQVNIX0JVRl9BQ0M7Cj4+ICsKPj4gKwkJ ZGF0YV9zaXplMSA9IHNuYW5kYy0+cXNwaS0+cGFnZXNpemUgLSBlY2NfY2ZnLT5jd19zaXplICog KG51bV9jdyAtIDEpOwo+PiArCQlvb2Jfc2l6ZTEgPSBlY2NfY2ZnLT5iYm1fc2l6ZTsKPj4gKwo+ PiArCQlpZiAoKGkgPT0gKG51bV9jdyAtIDEpKSkgewo+PiArCQkJZGF0YV9zaXplMiA9IE5BTkRD X1NURVBfU0laRSAtIGRhdGFfc2l6ZTEgLQo+PiArCQkJCSAgICAgKChudW1fY3cgLSAxKSA8PCAy KTsKPj4gKwkJCW9vYl9zaXplMiA9IChudW1fY3cgPDwgMikgKyBlY2NfY2ZnLT5lY2NfYnl0ZXNf aHcgKwo+PiArCQkJCSAgICBlY2NfY2ZnLT5zcGFyZV9ieXRlczsKPj4gKwkJfSBlbHNlIHsKPj4g KwkJCWRhdGFfc2l6ZTIgPSBlY2NfY2ZnLT5jd19kYXRhIC0gZGF0YV9zaXplMTsKPj4gKwkJCW9v Yl9zaXplMiA9IGVjY19jZmctPmVjY19ieXRlc19odyArIGVjY19jZmctPnNwYXJlX2J5dGVzOwo+ PiArCQl9Cj4+ICsKPj4gKwkJcWNvbV93cml0ZV9kYXRhX2RtYShzbmFuZGMsIHJlZ19vZmYsIGRh dGFfYnVmLCBkYXRhX3NpemUxLAo+PiArCQkJCSAgICBOQU5EX0JBTV9OT19FT1QpOwo+PiArCQly ZWdfb2ZmICs9IGRhdGFfc2l6ZTE7Cj4+ICsJCWRhdGFfYnVmICs9IGRhdGFfc2l6ZTE7Cj4+ICsK Pj4gKwkJcWNvbV93cml0ZV9kYXRhX2RtYShzbmFuZGMsIHJlZ19vZmYsIG9vYl9idWYsIG9vYl9z aXplMSwKPj4gKwkJCQkgICAgTkFORF9CQU1fTk9fRU9UKTsKPj4gKwkJb29iX2J1ZiArPSBvb2Jf c2l6ZTE7Cj4+ICsJCXJlZ19vZmYgKz0gb29iX3NpemUxOwo+PiArCj4+ICsJCXFjb21fd3JpdGVf ZGF0YV9kbWEoc25hbmRjLCByZWdfb2ZmLCBkYXRhX2J1ZiwgZGF0YV9zaXplMiwKPj4gKwkJCQkg ICAgTkFORF9CQU1fTk9fRU9UKTsKPj4gKwkJcmVnX29mZiArPSBkYXRhX3NpemUyOwo+PiArCQlk YXRhX2J1ZiArPSBkYXRhX3NpemUyOwo+PiArCj4+ICsJCXFjb21fd3JpdGVfZGF0YV9kbWEoc25h bmRjLCByZWdfb2ZmLCBvb2JfYnVmLCBvb2Jfc2l6ZTIsIDApOwo+PiArCQlvb2JfYnVmICs9IG9v Yl9zaXplMjsKPj4gKwo+PiArCQlxY29tX3NwaV9jb25maWdfY3dfd3JpdGUoc25hbmRjKTsKPj4g Kwl9Cj4+ICsKPj4gKwlyZXQgPSBxY29tX3N1Ym1pdF9kZXNjcyhzbmFuZGMpOwo+PiArCWlmIChy ZXQpIHsKPj4gKwkJZGV2X2VycihzbmFuZGMtPmRldiwgImZhaWx1cmUgdG8gd3JpdGUgcmF3IHBh Z2VcbiIpOwo+PiArCQlyZXR1cm4gcmV0Owo+PiArCX0KPj4gKwo+PiArCXJldHVybiAwOwo+PiAr fQo+PiArCj4+ICtzdGF0aWMgaW50IHFjb21fc3BpX3Byb2dyYW1fZXhlY3V0ZShzdHJ1Y3QgcWNv bV9uYW5kX2NvbnRyb2xsZXIgKnNuYW5kYywKPj4gKwkJCQkgICAgY29uc3Qgc3RydWN0IHNwaV9t ZW1fb3AgKm9wKQo+PiArewo+PiArCXN0cnVjdCBxcGljX2VjYyAqZWNjX2NmZyA9IHNuYW5kYy0+ cXNwaS0+ZWNjOwo+PiArCXU4ICpkYXRhX2J1ZiA9IE5VTEwsICpvb2JfYnVmID0gTlVMTDsKPj4g KwlpbnQgaSwgcmV0Owo+PiArCWludCBudW1fY3cgPSBzbmFuZGMtPnFzcGktPm51bV9jdzsKPj4g Kwl1MzIgY2ZnMCwgY2ZnMSwgZWNjX2JjaF9jZmcsIGVjY19idWZfY2ZnOwo+PiArCj4+ICsJY2Zn MCA9IChlY2NfY2ZnLT5jZmcwICYgfig3VSA8PCBDV19QRVJfUEFHRSkpIHwKPj4gKwkJCQkobnVt X2N3IC0gMSkgPDwgQ1dfUEVSX1BBR0U7Cj4+ICsJY2ZnMSA9IGVjY19jZmctPmNmZzE7Cj4+ICsJ ZWNjX2JjaF9jZmcgPSBlY2NfY2ZnLT5lY2NfYmNoX2NmZzsKPj4gKwllY2NfYnVmX2NmZyA9IGVj Y19jZmctPmVjY19idWZfY2ZnOwo+PiArCj4+ICsJaWYgKHNuYW5kYy0+cXNwaS0+cGFnZV9ydyAm JiBzbmFuZGMtPnFzcGktPnJhd19ydykKPj4gKwkJcmV0dXJuIHFjb21fc3BpX3Byb2dyYW1fcmF3 KHNuYW5kYywgb3ApOwo+PiArCj4+ICsJaWYgKHNuYW5kYy0+cXNwaS0+ZGF0YV9idWYpCj4+ICsJ CWRhdGFfYnVmID0gc25hbmRjLT5xc3BpLT5kYXRhX2J1ZjsKPj4gKwo+PiArCWlmIChzbmFuZGMt PnFzcGktPm9vYl9idWYpCj4+ICsJCW9vYl9idWYgPSBzbmFuZGMtPnFzcGktPm9vYl9idWY7Cj4+ ICsKPj4gKwlzbmFuZGMtPmJ1Zl9jb3VudCA9IDA7Cj4+ICsJc25hbmRjLT5idWZfc3RhcnQgPSAw Owo+PiArCXFjb21fY2xlYXJfcmVhZF9yZWdzKHNuYW5kYyk7Cj4+ICsJcWNvbV9jbGVhcl9iYW1f dHJhbnNhY3Rpb24oc25hbmRjKTsKPj4gKwo+PiArCXNuYW5kYy0+cmVncy0+YWRkcjAgPSBzbmFu ZGMtPnFzcGktPmFkZHIxOwo+PiArCXNuYW5kYy0+cmVncy0+YWRkcjEgPSBzbmFuZGMtPnFzcGkt PmFkZHIyOwo+PiArCXNuYW5kYy0+cmVncy0+Y21kID0gc25hbmRjLT5xc3BpLT5jbWQ7Cj4+ICsJ c25hbmRjLT5yZWdzLT5jZmcwID0gY2ZnMDsKPj4gKwlzbmFuZGMtPnJlZ3MtPmNmZzEgPSBjZmcx Owo+PiArCXNuYW5kYy0+cmVncy0+ZWNjX2JjaF9jZmcgPSBlY2NfYmNoX2NmZzsKPj4gKwlzbmFu ZGMtPnJlZ3MtPmVjY19idWZfY2ZnID0gZWNjX2J1Zl9jZmc7Cj4+ICsJc25hbmRjLT5yZWdzLT5l eGVjID0gMTsKPj4gKwo+PiArCXFjb21fc3BpX2NvbmZpZ19wYWdlX3dyaXRlKHNuYW5kYyk7Cj4+ ICsKPj4gKwlmb3IgKGkgPSAwOyBpIDwgbnVtX2N3OyBpKyspIHsKPj4gKwkJaW50IGRhdGFfc2l6 ZSwgb29iX3NpemU7Cj4+ICsKPj4gKwkJaWYgKGkgPT0gKG51bV9jdyAtIDEpKSB7Cj4+ICsJCQlk YXRhX3NpemUgPSBOQU5EQ19TVEVQX1NJWkUgLSAoKG51bV9jdyAtIDEpIDw8IDIpOwo+PiArCQkJ b29iX3NpemUgPSAobnVtX2N3IDw8IDIpICsgZWNjX2NmZy0+ZWNjX2J5dGVzX2h3ICsKPj4gKwkJ CQkgICAgZWNjX2NmZy0+c3BhcmVfYnl0ZXM7Cj4+ICsJCX0gZWxzZSB7Cj4+ICsJCQlkYXRhX3Np emUgPSBlY2NfY2ZnLT5jd19kYXRhOwo+PiArCQkJb29iX3NpemUgPSBlY2NfY2ZnLT5ieXRlczsK Pj4gKwkJfQo+PiArCj4+ICsJCWlmIChkYXRhX2J1ZikKPj4gKwkJCXFjb21fd3JpdGVfZGF0YV9k bWEoc25hbmRjLCBGTEFTSF9CVUZfQUNDLCBkYXRhX2J1ZiwgZGF0YV9zaXplLAo+PiArCQkJCQkg ICAgaSA9PSAobnVtX2N3IC0gMSkgPyBOQU5EX0JBTV9OT19FT1QgOiAwKTsKPj4gKwo+PiArCQlp ZiAoaSA9PSAobnVtX2N3IC0gMSkpIHsKPj4gKwkJCWlmIChvb2JfYnVmKSB7Cj4+ICsJCQkJb29i X2J1ZiArPSBlY2NfY2ZnLT5iYm1fc2l6ZTsKPj4gKwkJCQlxY29tX3dyaXRlX2RhdGFfZG1hKHNu YW5kYywgRkxBU0hfQlVGX0FDQyArIGRhdGFfc2l6ZSwKPj4gKwkJCQkJCSAgICBvb2JfYnVmLCBv b2Jfc2l6ZSwgMCk7Cj4+ICsJCQl9Cj4+ICsJCX0KPj4gKwo+PiArCQlxY29tX3NwaV9jb25maWdf Y3dfd3JpdGUoc25hbmRjKTsKPj4gKwo+PiArCQlpZiAoZGF0YV9idWYpCj4+ICsJCQlkYXRhX2J1 ZiArPSBkYXRhX3NpemU7Cj4+ICsJCWlmIChvb2JfYnVmKQo+PiArCQkJb29iX2J1ZiArPSBvb2Jf c2l6ZTsKPj4gKwl9Cj4+ICsKPj4gKwlyZXQgPSBxY29tX3N1Ym1pdF9kZXNjcyhzbmFuZGMpOwo+ PiArCWlmIChyZXQpIHsKPj4gKwkJZGV2X2VycihzbmFuZGMtPmRldiwgImZhaWx1cmUgdG8gd3Jp dGUgcGFnZVxuIik7Cj4+ICsJCXJldHVybiByZXQ7Cj4+ICsJfQo+PiArCj4+ICsJcmV0dXJuIDA7 Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyB1MzIgcWNvbV9zcGlfY21kX21hcHBpbmcoc3RydWN0IHFj b21fbmFuZF9jb250cm9sbGVyICpzbmFuZGMsIHUzMiBvcGNvZGUpCj4+ICt7Cj4+ICsJdTMyIGNt ZCA9IDB4MDsKPj4gKwo+PiArCXN3aXRjaCAob3Bjb2RlKSB7Cj4+ICsJY2FzZSBTUElOQU5EX1JF U0VUOgo+PiArCQljbWQgPSAoU1BJX1dQIHwgU1BJX0hPTEQgfCBTUElfVFJBTlNGRVJfTU9ERV94 MSB8IE9QX1JFU0VUX0RFVklDRSk7Cj4+ICsJCWJyZWFrOwo+PiArCWNhc2UgU1BJTkFORF9SRUFE SUQ6Cj4+ICsJCWNtZCA9IChTUElfV1AgfCBTUElfSE9MRCB8IFNQSV9UUkFOU0ZFUl9NT0RFX3gx IHwgT1BfRkVUQ0hfSUQpOwo+PiArCQlicmVhazsKPj4gKwljYXNlIFNQSU5BTkRfR0VUX0ZFQVRV UkU6Cj4+ICsJCWNtZCA9IChTUElfVFJBTlNGRVJfTU9ERV94MSB8IFNQSV9XUCB8IFNQSV9IT0xE IHwgQUNDX0ZFQVRVUkUpOwo+PiArCQlicmVhazsKPj4gKwljYXNlIFNQSU5BTkRfU0VUX0ZFQVRV UkU6Cj4+ICsJCWNtZCA9IChTUElfVFJBTlNGRVJfTU9ERV94MSB8IFNQSV9XUCB8IFNQSV9IT0xE IHwgQUNDX0ZFQVRVUkUgfAo+PiArCQkJUVBJQ19TRVRfRkVBVFVSRSk7Cj4+ICsJCWJyZWFrOwo+ PiArCWNhc2UgU1BJTkFORF9SRUFEOgo+PiArCQlpZiAoc25hbmRjLT5xc3BpLT5yYXdfcncpIHsK Pj4gKwkJCWNtZCA9IChQQUdFX0FDQyB8IExBU1RfUEFHRSB8IFNQSV9UUkFOU0ZFUl9NT0RFX3gx IHwKPj4gKwkJCQkJU1BJX1dQIHwgU1BJX0hPTEQgfCBPUF9QQUdFX1JFQUQpOwo+PiArCQl9IGVs c2Ugewo+PiArCQkJY21kID0gKFBBR0VfQUNDIHwgTEFTVF9QQUdFIHwgU1BJX1RSQU5TRkVSX01P REVfeDEgfAo+PiArCQkJCQlTUElfV1AgfCBTUElfSE9MRCB8IE9QX1BBR0VfUkVBRF9XSVRIX0VD Qyk7Cj4+ICsJCX0KPj4gKwo+PiArCQlicmVhazsKPj4gKwljYXNlIFNQSU5BTkRfRVJBU0U6Cj4+ ICsJCWNtZCA9IE9QX0JMT0NLX0VSQVNFIHwgUEFHRV9BQ0MgfCBMQVNUX1BBR0UgfCBTUElfV1Ag fAo+PiArCQkJU1BJX0hPTEQgfCBTUElfVFJBTlNGRVJfTU9ERV94MTsKPj4gKwkJYnJlYWs7Cj4+ ICsJY2FzZSBTUElOQU5EX1dSSVRFX0VOOgo+PiArCQljbWQgPSBTUElOQU5EX1dSSVRFX0VOOwo+ PiArCQlicmVhazsKPj4gKwljYXNlIFNQSU5BTkRfUFJPR1JBTV9FWEVDVVRFOgo+PiArCQljbWQg PSAoUEFHRV9BQ0MgfCBMQVNUX1BBR0UgfCBTUElfVFJBTlNGRVJfTU9ERV94MSB8Cj4+ICsJCQkJ U1BJX1dQIHwgU1BJX0hPTEQgfCBPUF9QUk9HUkFNX1BBR0UpOwo+PiArCQlicmVhazsKPj4gKwlj YXNlIFNQSU5BTkRfUFJPR1JBTV9MT0FEOgo+PiArCQljbWQgPSBTUElOQU5EX1BST0dSQU1fTE9B RDsKPj4gKwkJYnJlYWs7Cj4+ICsJZGVmYXVsdDoKPj4gKwkJZGV2X2VycihzbmFuZGMtPmRldiwg Ik9wY29kZSBub3Qgc3VwcG9ydGVkOiAldVxuIiwgb3Bjb2RlKTsKPj4gKwkJcmV0dXJuIC1FT1BO T1RTVVBQOwo+PiArCX0KPj4gKwo+PiArCXJldHVybiBjbWQ7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRp YyBpbnQgcWNvbV9zcGlfd3JpdGVfcGFnZV9jYWNoZShzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRyb2xs ZXIgKnNuYW5kYywKPj4gKwkJCQkgICAgIGNvbnN0IHN0cnVjdCBzcGlfbWVtX29wICpvcCkKPj4g K3sKPj4gKwlzdHJ1Y3QgcXBpY19zbmFuZF9vcCBzX29wID0ge307Cj4+ICsJdTMyIGNtZDsKPj4g Kwo+PiArCWNtZCA9IHFjb21fc3BpX2NtZF9tYXBwaW5nKHNuYW5kYywgb3AtPmNtZC5vcGNvZGUp Owo+IAo+IEkndmUgYXNrZWQgZm9yIHN3aXRjaCBjYXNlcyB0byByZXR1cm4gYW4gZXJyb3IgaW4g Y2FzZSB0aGV5IGNvdWxkIG5vdAo+IGhhbmRsZSB0aGUgcmVxdWVzdC4gSWYgeW91IGRvbid0IGNo ZWNrIHRoZSByZXR1cm5lZCB2YWx1ZXMsIGl0Cj4gZG9lcyBub3QgbWFrZSBhbnkgc2Vuc2UuCiAg T2ssIHdpbGwgZml4IGluIG5leHQgcGF0Y2guCj4gCj4+ICsJc19vcC5jbWRfcmVnID0gY21kOwo+ PiArCj4+ICsJaWYgKG9wLT5jbWQub3Bjb2RlID09IFNQSU5BTkRfUFJPR1JBTV9MT0FEKSB7Cj4+ ICsJCWlmIChzbmFuZGMtPnFzcGktPnBhZ2VfcncpCj4+ICsJCQlzbmFuZGMtPnFzcGktPmRhdGFf YnVmID0gKHU4ICopb3AtPmRhdGEuYnVmLm91dDsKPiAKPiBXaGF0IHlvdSBkbyBoZXJlIGRvZXMg bm90IHdyaXRlIGFueXRoaW5nIGluIGEgcGFnZSBjYWNoZS4KICAgTm8gaGVyZSBqdXN0IHVwZGF0 aW5nIHRoZSBidWZmZXIgLCBhY3R1YWwgd3JpdGUgd2lsbCBoYXBwZW4gaW4gcHJvZ3JhbV9leGVj dXRlLgogICBUaGlzIGlzIGR1ZSB0byBRUElDIGNvbnRyb2xsZXIgd2lsbCBub3QgdGFrZSBhbGwg dGhlIGluc3RydWN0aW9uIG9uZS1ieS1vbmUuCiAgIG9uY2Ugd2Ugd2lsbCBzZXQgQ01EX0VYRUMg PSAxLCB0aGVuIGl0IHdpbGwgZXhlY3V0ZSBhbGwgdGhlIGluc3RydWN0aW9uCiAgIGF0IG9uY2Uu IFNvIGFjY3VtdWxhdGluZyBhbGwgdGhlIGluc3RydWN0aW9uIGFuZCB0aGVuIGV4ZWN1dGluZyBh dCBvbmNlIGluCiAgIHByb2dyYW1fZXhlY3V0ZS4KPiAKPiBJIGFsc28gZG9uJ3QgdW5kZXJzdGFu ZCB3aHkgeW91IHdvdWxkIGhhdmUgdG8gY2hlY2sgYWdhaW5zdCB0aGUKPiBTUElOQU5EX1BST0dS QU1fTE9BRCBvcGNvZGUuCiAgIEJlY2F1c2UgdGhlIGFjdHVhbCB3cml0ZSB3aWxsIGhhcHBlbiBp biBwcm9ncmFtX2V4ZWN1dGUuIGFuZCBoZXJlCiAgIFBST0dSQU1fRVhFQ1VURSBjb21tYW5kIHdp bGwgYWxzbyBsYW5kLCBzbyB0aGF0IGFkZGVkIHRoZSBjaGVjay4KPiAKPj4gKwl9Cj4+ICsKPj4g KwlyZXR1cm4gMDsKPj4gK30KPj4gKwo+PiArc3RhdGljIGludCBxY29tX3NwaV9zZW5kX2NtZGFk ZHIoc3RydWN0IHFjb21fbmFuZF9jb250cm9sbGVyICpzbmFuZGMsCj4+ICsJCQkJIGNvbnN0IHN0 cnVjdCBzcGlfbWVtX29wICpvcCkKPj4gK3sKPj4gKwlzdHJ1Y3QgcXBpY19zbmFuZF9vcCBzX29w ID0ge307Cj4+ICsJdTMyIGNtZDsKPj4gKwlpbnQgcmV0LCBvcGNvZGU7Cj4+ICsKPj4gKwljbWQg PSBxY29tX3NwaV9jbWRfbWFwcGluZyhzbmFuZGMsIG9wLT5jbWQub3Bjb2RlKTsKPj4gKwo+PiAr CXNfb3AuY21kX3JlZyA9IGNtZDsKPj4gKwlzX29wLmFkZHIxX3JlZyA9IG9wLT5hZGRyLnZhbDsK Pj4gKwlzX29wLmFkZHIyX3JlZyA9IDA7Cj4+ICsKPj4gKwlvcGNvZGUgPSBvcC0+Y21kLm9wY29k ZTsKPj4gKwo+PiArCXN3aXRjaCAob3Bjb2RlKSB7Cj4+ICsJY2FzZSBTUElOQU5EX1dSSVRFX0VO Ogo+PiArCQlyZXR1cm4gMDsKPj4gKwljYXNlIFNQSU5BTkRfUFJPR1JBTV9FWEVDVVRFOgo+PiAr CQlzX29wLmFkZHIxX3JlZyA9IG9wLT5hZGRyLnZhbCA8PCAxNjsKPj4gKwkJc19vcC5hZGRyMl9y ZWcgPSBvcC0+YWRkci52YWwgPj4gMTYgJiAweGZmOwo+PiArCQlzbmFuZGMtPnFzcGktPmFkZHIx ID0gc19vcC5hZGRyMV9yZWc7Cj4+ICsJCXNuYW5kYy0+cXNwaS0+YWRkcjIgPSBzX29wLmFkZHIy X3JlZzsKPj4gKwkJc25hbmRjLT5xc3BpLT5jbWQgPSBjbWQ7Cj4+ICsJCXJldHVybiBxY29tX3Nw aV9wcm9ncmFtX2V4ZWN1dGUoc25hbmRjLCBvcCk7Cj4+ICsJY2FzZSBTUElOQU5EX1JFQUQ6Cj4+ ICsJCXNfb3AuYWRkcjFfcmVnID0gKG9wLT5hZGRyLnZhbCA8PCAxNik7Cj4+ICsJCXNfb3AuYWRk cjJfcmVnID0gb3AtPmFkZHIudmFsID4+IDE2ICYgMHhmZjsKPj4gKwkJc25hbmRjLT5xc3BpLT5h ZGRyMSA9IHNfb3AuYWRkcjFfcmVnOwo+PiArCQlzbmFuZGMtPnFzcGktPmFkZHIyID0gc19vcC5h ZGRyMl9yZWc7Cj4+ICsJCXNuYW5kYy0+cXNwaS0+Y21kID0gY21kOwo+PiArCQlyZXR1cm4gMDsK Pj4gKwljYXNlIFNQSU5BTkRfRVJBU0U6Cj4+ICsJCXNfb3AuYWRkcjJfcmVnID0gKG9wLT5hZGRy LnZhbCA+PiAxNikgJiAweGZmZmY7Cj4+ICsJCXNfb3AuYWRkcjFfcmVnID0gb3AtPmFkZHIudmFs Owo+PiArCQlzbmFuZGMtPnFzcGktPmFkZHIxID0gKHNfb3AuYWRkcjFfcmVnIDw8IDE2KTsKPj4g KwkJc25hbmRjLT5xc3BpLT5hZGRyMiA9IHNfb3AuYWRkcjJfcmVnOwo+PiArCQlzbmFuZGMtPnFz cGktPmNtZCA9IGNtZDsKPj4gKwkJcWNvbV9zcGlfYmxvY2tfZXJhc2Uoc25hbmRjKTsKPj4gKwkJ cmV0dXJuIDA7Cj4+ICsJZGVmYXVsdDoKPj4gKwkJYnJlYWs7Cj4+ICsJfQo+PiArCj4+ICsJc25h bmRjLT5idWZfY291bnQgPSAwOwo+PiArCXNuYW5kYy0+YnVmX3N0YXJ0ID0gMDsKPj4gKwlxY29t X2NsZWFyX3JlYWRfcmVncyhzbmFuZGMpOwo+PiArCXFjb21fY2xlYXJfYmFtX3RyYW5zYWN0aW9u KHNuYW5kYyk7Cj4+ICsKPj4gKwlzbmFuZGMtPnJlZ3MtPmNtZCA9IHNfb3AuY21kX3JlZzsKPj4g KwlzbmFuZGMtPnJlZ3MtPmV4ZWMgPSAxOwo+PiArCXNuYW5kYy0+cmVncy0+YWRkcjAgPSBzX29w LmFkZHIxX3JlZzsKPj4gKwlzbmFuZGMtPnJlZ3MtPmFkZHIxID0gc19vcC5hZGRyMl9yZWc7Cj4+ ICsKPj4gKwlxY29tX3dyaXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRjLT5yZWdzLT5jbWQsIE5B TkRfRkxBU0hfQ01ELCAzLCBOQU5EX0JBTV9ORVhUX1NHTCk7Cj4+ICsJcWNvbV93cml0ZV9yZWdf ZG1hKHNuYW5kYywgJnNuYW5kYy0+cmVncy0+ZXhlYywgTkFORF9FWEVDX0NNRCwgMSwgTkFORF9C QU1fTkVYVF9TR0wpOwo+PiArCj4+ICsJcmV0ID0gcWNvbV9zdWJtaXRfZGVzY3Moc25hbmRjKTsK Pj4gKwlpZiAocmV0KQo+PiArCQlkZXZfZXJyKHNuYW5kYy0+ZGV2LCAiZmFpbHVyZSBpbiBzYnVt aXR0aW5nIGNtZCBkZXNjcmlwdG9yXG4iKTsKPiAKPiB0eXBvCiAgT2sgLCB3aWxsIGZpeCBpbiBu ZXh0IHBhdGNoLgo+IAo+PiArCj4+ICsJcmV0dXJuIHJldDsKPj4gK30KPj4gKwo+PiArc3RhdGlj IGludCBxY29tX3NwaV9pb19vcChzdHJ1Y3QgcWNvbV9uYW5kX2NvbnRyb2xsZXIgKnNuYW5kYywg Y29uc3Qgc3RydWN0IHNwaV9tZW1fb3AgKm9wKQo+PiArewo+PiArCWludCByZXQsIHZhbCwgb3Bj b2RlOwo+PiArCWJvb2wgY29weSA9IGZhbHNlLCBjb3B5X2Z0ciA9IGZhbHNlOwo+PiArCj4+ICsJ cmV0ID0gcWNvbV9zcGlfc2VuZF9jbWRhZGRyKHNuYW5kYywgb3ApOwo+PiArCWlmIChyZXQpCj4+ ICsJCXJldHVybiByZXQ7Cj4+ICsKPj4gKwlzbmFuZGMtPmJ1Zl9jb3VudCA9IDA7Cj4+ICsJc25h bmRjLT5idWZfc3RhcnQgPSAwOwo+PiArCXFjb21fY2xlYXJfcmVhZF9yZWdzKHNuYW5kYyk7Cj4+ ICsJcWNvbV9jbGVhcl9iYW1fdHJhbnNhY3Rpb24oc25hbmRjKTsKPj4gKwlvcGNvZGUgPSBvcC0+ Y21kLm9wY29kZTsKPj4gKwo+PiArCXN3aXRjaCAob3Bjb2RlKSB7Cj4+ICsJY2FzZSBTUElOQU5E X1JFQURJRDoKPj4gKwkJc25hbmRjLT5idWZfY291bnQgPSA0Owo+PiArCQlxY29tX3JlYWRfcmVn X2RtYShzbmFuZGMsIE5BTkRfUkVBRF9JRCwgMSwgTkFORF9CQU1fTkVYVF9TR0wpOwo+PiArCQlj b3B5ID0gdHJ1ZTsKPj4gKwkJYnJlYWs7Cj4+ICsJY2FzZSBTUElOQU5EX0dFVF9GRUFUVVJFOgo+ PiArCQlzbmFuZGMtPmJ1Zl9jb3VudCA9IDQ7Cj4+ICsJCXFjb21fcmVhZF9yZWdfZG1hKHNuYW5k YywgTkFORF9GTEFTSF9GRUFUVVJFUywgMSwgTkFORF9CQU1fTkVYVF9TR0wpOwo+PiArCQljb3B5 X2Z0ciA9IHRydWU7Cj4+ICsJCWJyZWFrOwo+PiArCWNhc2UgU1BJTkFORF9TRVRfRkVBVFVSRToK Pj4gKwkJc25hbmRjLT5yZWdzLT5mbGFzaF9mZWF0dXJlID0gKih1MzIgKilvcC0+ZGF0YS5idWYu b3V0Owo+PiArCQlxY29tX3dyaXRlX3JlZ19kbWEoc25hbmRjLCAmc25hbmRjLT5yZWdzLT5mbGFz aF9mZWF0dXJlLAo+PiArCQkJCSAgIE5BTkRfRkxBU0hfRkVBVFVSRVMsIDEsIE5BTkRfQkFNX05F WFRfU0dMKTsKPj4gKwkJYnJlYWs7Cj4+ICsJY2FzZSBTUElOQU5EX1JFU0VUOgo+PiArCQlyZXR1 cm4gMDsKPj4gKwljYXNlIFNQSU5BTkRfUFJPR1JBTV9FWEVDVVRFOgo+PiArCQlyZXR1cm4gMDsK Pj4gKwljYXNlIFNQSU5BTkRfV1JJVEVfRU46Cj4+ICsJCXJldHVybiAwOwo+PiArCWNhc2UgU1BJ TkFORF9FUkFTRToKPj4gKwkJcmV0dXJuIDA7Cj4+ICsJY2FzZSBTUElOQU5EX1JFQUQ6Cj4+ICsJ CXJldHVybiAwOwo+IAo+IFlvdSBjYW4gc3RhY2sgdGhlIGNhc2VzCk9rCj4gCj4+ICsJZGVmYXVs dDoKPj4gKwkJcmV0dXJuIC1FT1BOT1RTVVBQOwo+PiArCX0KPj4gKwo+PiArCXJldCA9IHFjb21f c3VibWl0X2Rlc2NzKHNuYW5kYyk7Cj4+ICsJaWYgKHJldCkKPj4gKwkJZGV2X2VycihzbmFuZGMt PmRldiwgImZhaWx1cmUgaW4gc3VibWl0dGluZyBkZXNjcmlwdG9yIGZvcjolZFxuIiwgb3Bjb2Rl KTsKPj4gKwo+PiArCWlmIChjb3B5KSB7Cj4+ICsJCXFjb21fbmFuZGNfZGV2X3RvX21lbShzbmFu ZGMsIHRydWUpOwo+PiArCQltZW1jcHkob3AtPmRhdGEuYnVmLmluLCBzbmFuZGMtPnJlZ19yZWFk X2J1Ziwgc25hbmRjLT5idWZfY291bnQpOwo+PiArCX0KPj4gKwo+PiArCWlmIChjb3B5X2Z0cikg ewo+PiArCQlxY29tX25hbmRjX2Rldl90b19tZW0oc25hbmRjLCB0cnVlKTsKPj4gKwkJdmFsID0g bGUzMl90b19jcHUoKihfX2xlMzIgKilzbmFuZGMtPnJlZ19yZWFkX2J1Zik7Cj4+ICsJCXZhbCA+ Pj0gODsKPj4gKwkJbWVtY3B5KG9wLT5kYXRhLmJ1Zi5pbiwgJnZhbCwgc25hbmRjLT5idWZfY291 bnQpOwo+PiArCX0KPj4gKwo+PiArCXJldHVybiByZXQ7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBi b29sIHFjb21fc3BpX2lzX3BhZ2Vfb3AoY29uc3Qgc3RydWN0IHNwaV9tZW1fb3AgKm9wKQo+PiAr ewo+PiArCWlmIChvcC0+YWRkci5idXN3aWR0aCAhPSAxICYmIG9wLT5hZGRyLmJ1c3dpZHRoICE9 IDIgJiYgb3AtPmFkZHIuYnVzd2lkdGggIT0gNCkKPj4gKwkJcmV0dXJuIGZhbHNlOwo+PiArCj4+ ICsJaWYgKG9wLT5kYXRhLmRpciA9PSBTUElfTUVNX0RBVEFfSU4pIHsKPj4gKwkJaWYgKG9wLT5h ZGRyLmJ1c3dpZHRoID09IDQgJiYgb3AtPmRhdGEuYnVzd2lkdGggPT0gNCkKPj4gKwkJCXJldHVy biB0cnVlOwo+PiArCj4+ICsJCWlmIChvcC0+YWRkci5uYnl0ZXMgPT0gMiAmJiBvcC0+YWRkci5i dXN3aWR0aCA9PSAxKQo+PiArCQkJcmV0dXJuIHRydWU7Cj4+ICsKPj4gKwl9IGVsc2UgaWYgKG9w LT5kYXRhLmRpciA9PSBTUElfTUVNX0RBVEFfT1VUKSB7Cj4+ICsJCWlmIChvcC0+ZGF0YS5idXN3 aWR0aCA9PSA0KQo+PiArCQkJcmV0dXJuIHRydWU7Cj4+ICsJCWlmIChvcC0+YWRkci5uYnl0ZXMg PT0gMiAmJiBvcC0+YWRkci5idXN3aWR0aCA9PSAxKQo+PiArCQkJcmV0dXJuIHRydWU7Cj4+ICsJ fQo+PiArCj4+ICsJcmV0dXJuIGZhbHNlOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgYm9vbCBxY29t X3NwaV9zdXBwb3J0c19vcChzdHJ1Y3Qgc3BpX21lbSAqbWVtLCBjb25zdCBzdHJ1Y3Qgc3BpX21l bV9vcCAqb3ApCj4+ICt7Cj4+ICsJaWYgKCFzcGlfbWVtX2RlZmF1bHRfc3VwcG9ydHNfb3AobWVt LCBvcCkpCj4+ICsJCXJldHVybiBmYWxzZTsKPj4gKwo+PiArCWlmIChvcC0+Y21kLm5ieXRlcyAh PSAxIHx8IG9wLT5jbWQuYnVzd2lkdGggIT0gMSkKPj4gKwkJcmV0dXJuIGZhbHNlOwo+PiArCj4+ ICsJaWYgKHFjb21fc3BpX2lzX3BhZ2Vfb3Aob3ApKQo+PiArCQlyZXR1cm4gdHJ1ZTsKPj4gKwo+ PiArCXJldHVybiAoKCFvcC0+YWRkci5uYnl0ZXMgfHwgb3AtPmFkZHIuYnVzd2lkdGggPT0gMSkg JiYKPj4gKwkJKCFvcC0+ZHVtbXkubmJ5dGVzIHx8IG9wLT5kdW1teS5idXN3aWR0aCA9PSAxKSAm Jgo+PiArCQkoIW9wLT5kYXRhLm5ieXRlcyB8fCBvcC0+ZGF0YS5idXN3aWR0aCA9PSAxKSk7Cj4+ ICt9Cj4+ICsKPj4gK3N0YXRpYyBpbnQgcWNvbV9zcGlfZXhlY19vcChzdHJ1Y3Qgc3BpX21lbSAq bWVtLCBjb25zdCBzdHJ1Y3Qgc3BpX21lbV9vcCAqb3ApCj4+ICt7Cj4+ICsJc3RydWN0IHFjb21f bmFuZF9jb250cm9sbGVyICpzbmFuZGMgPSBzcGlfY29udHJvbGxlcl9nZXRfZGV2ZGF0YShtZW0t PnNwaS0+Y29udHJvbGxlcik7Cj4+ICsKPj4gKwlkZXZfZGJnKHNuYW5kYy0+ZGV2LCAiT1AgJTAy eCBBRERSICUwOGxsWEAlZDoldSBEQVRBICVkOiV1Iiwgb3AtPmNtZC5vcGNvZGUsCj4+ICsJCW9w LT5hZGRyLnZhbCwgb3AtPmFkZHIuYnVzd2lkdGgsIG9wLT5hZGRyLm5ieXRlcywKPj4gKwkJb3At PmRhdGEuYnVzd2lkdGgsIG9wLT5kYXRhLm5ieXRlcyk7Cj4+ICsKPj4gKwlpZiAocWNvbV9zcGlf aXNfcGFnZV9vcChvcCkpIHsKPj4gKwkJaWYgKG9wLT5kYXRhLmRpciA9PSBTUElfTUVNX0RBVEFf SU4pCj4+ICsJCQlyZXR1cm4gcWNvbV9zcGlfcmVhZF9wYWdlX2NhY2hlKHNuYW5kYywgb3ApOwo+ PiArCQlpZiAob3AtPmRhdGEuZGlyID09IFNQSV9NRU1fREFUQV9PVVQpCj4+ICsJCQlyZXR1cm4g cWNvbV9zcGlfd3JpdGVfcGFnZV9jYWNoZShzbmFuZGMsIG9wKTsKPj4gKwl9IGVsc2Ugewo+PiAr CQlyZXR1cm4gcWNvbV9zcGlfaW9fb3Aoc25hbmRjLCBvcCk7Cj4+ICsJfQo+PiArCj4+ICsJcmV0 dXJuIDA7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc3BpX2NvbnRyb2xsZXJf bWVtX29wcyBxY29tX3NwaV9tZW1fb3BzID0gewo+PiArCS5zdXBwb3J0c19vcCA9IHFjb21fc3Bp X3N1cHBvcnRzX29wLAo+PiArCS5leGVjX29wID0gcWNvbV9zcGlfZXhlY19vcCwKPj4gK307Cj4+ ICsKPj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgc3BpX2NvbnRyb2xsZXJfbWVtX2NhcHMgcWNvbV9z cGlfbWVtX2NhcHMgPSB7Cj4+ICsJLmVjYyA9IHRydWUsCj4+ICt9Owo+PiArCj4+ICtzdGF0aWMg aW50IHFjb21fc3BpX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4+ICt7Cj4+ ICsJc3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRldjsKPj4gKwlzdHJ1Y3Qgc3BpX2NvbnRy b2xsZXIgKmN0bHI7Cj4+ICsJc3RydWN0IHFjb21fbmFuZF9jb250cm9sbGVyICpzbmFuZGM7Cj4+ ICsJc3RydWN0IHFwaWNfc3BpX25hbmQgKnFzcGk7Cj4+ICsJc3RydWN0IHFwaWNfZWNjICplY2M7 Cj4+ICsJc3RydWN0IHJlc291cmNlICpyZXM7Cj4+ICsJY29uc3Qgdm9pZCAqZGV2X2RhdGE7Cj4+ ICsJaW50IHJldDsKPj4gKwo+PiArCWVjYyA9IGRldm1fa3phbGxvYyhkZXYsIHNpemVvZigqZWNj KSwgR0ZQX0tFUk5FTCk7Cj4+ICsJaWYgKCFlY2MpCj4+ICsJCXJldHVybiAtRU5PTUVNOwo+PiAr Cj4+ICsJcXNwaSA9IGRldm1fa3phbGxvYyhkZXYsIHNpemVvZigqcXNwaSksIEdGUF9LRVJORUwp Owo+PiArCWlmICghcXNwaSkKPj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4+ICsKPj4gKwljdGxyID0g X19kZXZtX3NwaV9hbGxvY19jb250cm9sbGVyKGRldiwgc2l6ZW9mKCpzbmFuZGMpLCBmYWxzZSk7 Cj4+ICsJaWYgKCFjdGxyKQo+PiArCQlyZXR1cm4gLUVOT01FTTsKPj4gKwo+PiArCXBsYXRmb3Jt X3NldF9kcnZkYXRhKHBkZXYsIGN0bHIpOwo+PiArCj4+ICsJc25hbmRjID0gc3BpX2NvbnRyb2xs ZXJfZ2V0X2RldmRhdGEoY3Rscik7Cj4+ICsJcXNwaS0+c25hbmRjID0gc25hbmRjOwo+PiArCj4+ ICsJc25hbmRjLT5kZXYgPSBkZXY7Cj4+ICsJc25hbmRjLT5xc3BpID0gcXNwaTsKPj4gKwlzbmFu ZGMtPnFzcGktPmN0bHIgPSBjdGxyOwo+PiArCXNuYW5kYy0+cXNwaS0+ZWNjID0gZWNjOwo+PiAr Cj4+ICsJc25hbmRjLT5xc3BpLT5vb2JfYnVmID0gZGV2bV9remFsbG9jKGRldiwgT09CX0JVRl9T SVpFLCBHRlBfS0VSTkVMKTsKPj4gKwlpZiAoIXNuYW5kYy0+cXNwaS0+b29iX2J1ZikKPj4gKwkJ cmV0dXJuIC1FTk9NRU07Cj4+ICsKPj4gKwlkZXZfZGF0YSA9IG9mX2RldmljZV9nZXRfbWF0Y2hf ZGF0YShkZXYpOwo+PiArCWlmICghZGV2X2RhdGEpIHsKPj4gKwkJZGV2X2VycigmcGRldi0+ZGV2 LCAiZmFpbGVkIHRvIGdldCBkZXZpY2UgZGF0YVxuIik7Cj4+ICsJCXJldHVybiAtRU5PREVWOwo+ PiArCX0KPj4gKwo+PiArCXNuYW5kYy0+cHJvcHMgPSBkZXZfZGF0YTsKPj4gKwlzbmFuZGMtPmRl diA9ICZwZGV2LT5kZXY7Cj4+ICsKPj4gKwlzbmFuZGMtPmNvcmVfY2xrID0gZGV2bV9jbGtfZ2V0 KGRldiwgImNvcmUiKTsKPj4gKwlpZiAoSVNfRVJSKHNuYW5kYy0+Y29yZV9jbGspKQo+PiArCQly ZXR1cm4gUFRSX0VSUihzbmFuZGMtPmNvcmVfY2xrKTsKPj4gKwo+PiArCXNuYW5kYy0+YW9uX2Ns ayA9IGRldm1fY2xrX2dldChkZXYsICJhb24iKTsKPj4gKwlpZiAoSVNfRVJSKHNuYW5kYy0+YW9u X2NsaykpCj4+ICsJCXJldHVybiBQVFJfRVJSKHNuYW5kYy0+YW9uX2Nsayk7Cj4+ICsKPj4gKwlz bmFuZGMtPnFzcGktPmlvbWFjcm9fY2xrID0gZGV2bV9jbGtfZ2V0KGRldiwgImlvbSIpOwo+PiAr CWlmIChJU19FUlIoc25hbmRjLT5xc3BpLT5pb21hY3JvX2NsaykpCj4+ICsJCXJldHVybiBQVFJf RVJSKHNuYW5kYy0+cXNwaS0+aW9tYWNyb19jbGspOwo+PiArCj4+ICsJc25hbmRjLT5iYXNlID0g ZGV2bV9wbGF0Zm9ybV9nZXRfYW5kX2lvcmVtYXBfcmVzb3VyY2UocGRldiwgMCwgJnJlcyk7Cj4+ ICsJaWYgKElTX0VSUihzbmFuZGMtPmJhc2UpKQo+PiArCQlyZXR1cm4gUFRSX0VSUihzbmFuZGMt PmJhc2UpOwo+PiArCj4+ICsJc25hbmRjLT5iYXNlX3BoeXMgPSByZXMtPnN0YXJ0Owo+PiArCXNu YW5kYy0+YmFzZV9kbWEgPSBkbWFfbWFwX3Jlc291cmNlKGRldiwgcmVzLT5zdGFydCwgcmVzb3Vy Y2Vfc2l6ZShyZXMpLAo+PiArCQkJCQkgICAgRE1BX0JJRElSRUNUSU9OQUwsIDApOwo+PiArCWlm IChkbWFfbWFwcGluZ19lcnJvcihkZXYsIHNuYW5kYy0+YmFzZV9kbWEpKQo+PiArCQlyZXR1cm4g LUVOWElPOwo+PiArCj4+ICsJcmV0ID0gY2xrX3ByZXBhcmVfZW5hYmxlKHNuYW5kYy0+Y29yZV9j bGspOwo+PiArCWlmIChyZXQpCj4+ICsJCWdvdG8gZXJyX2NvcmVfY2xrOwo+IAo+IEFnYWluLCB0 aGUgbGFiZWwgaXMgYmV0dGVyIG5hbWVkIHdoZW4gaXQgZGVzY3JpYmVzIHdoYXQgaXQgcG9pbnQg YXQsCj4gcmF0aGVyIHRoYW4gd2hlcmUgaXQgY29tZXMgZnJvbS4KT2sKPiAKPj4gKwo+PiArCXJl dCA9IGNsa19wcmVwYXJlX2VuYWJsZShzbmFuZGMtPmFvbl9jbGspOwo+PiArCWlmIChyZXQpCj4+ ICsJCWdvdG8gZXJyX2Fvbl9jbGs7Cj4+ICsKPj4gKwlyZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUo c25hbmRjLT5xc3BpLT5pb21hY3JvX2Nsayk7Cj4+ICsJaWYgKHJldCkKPj4gKwkJZ290byBlcnJf ZGlzX2lvbV9jbGs7Cj4+ICsKPj4gKwlyZXQgPSBxY29tX25hbmRjX2FsbG9jKHNuYW5kYyk7Cj4+ ICsJaWYgKHJldCkKPj4gKwkJZ290byBlcnJfc25hbmRfYWxsb2M7Cj4+ICsKPj4gKwlyZXQgPSBx Y29tX3NwaV9pbml0KHNuYW5kYyk7Cj4+ICsJaWYgKHJldCkKPj4gKwkJZ290byBlcnJfaW5pdDsK Pj4gKwo+PiArCS8qIHNldHVwIEVDQyBlbmdpbmUgKi8KPj4gKwlzbmFuZGMtPnFzcGktPmVjY19l bmcuZGV2ID0gJnBkZXYtPmRldjsKPj4gKwlzbmFuZGMtPnFzcGktPmVjY19lbmcuaW50ZWdyYXRp b24gPSBOQU5EX0VDQ19FTkdJTkVfSU5URUdSQVRJT05fUElQRUxJTkVEOwo+PiArCXNuYW5kYy0+ cXNwaS0+ZWNjX2VuZy5vcHMgPSAmcWNvbV9zcGlfZWNjX2VuZ2luZV9vcHNfcGlwZWxpbmVkOwo+ PiArCXNuYW5kYy0+cXNwaS0+ZWNjX2VuZy5wcml2ID0gc25hbmRjOwo+PiArCj4+ICsJcmV0ID0g bmFuZF9lY2NfcmVnaXN0ZXJfb25faG9zdF9od19lbmdpbmUoJnNuYW5kYy0+cXNwaS0+ZWNjX2Vu Zyk7Cj4+ICsJaWYgKHJldCkgewo+PiArCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJmYWlsZWQgdG8g cmVnaXN0ZXIgZWNjIGVuZ2luZTolZFxuIiwgcmV0KTsKPj4gKwkJZ290byBlcnJfaW5pdDsKPj4g Kwl9Cj4+ICsKPj4gKwljdGxyLT5udW1fY2hpcHNlbGVjdCA9IFFQSUNfUVNQSV9OVU1fQ1M7Cj4+ ICsJY3Rsci0+bWVtX29wcyA9ICZxY29tX3NwaV9tZW1fb3BzOwo+PiArCWN0bHItPm1lbV9jYXBz ID0gJnFjb21fc3BpX21lbV9jYXBzOwo+PiArCWN0bHItPmRldi5vZl9ub2RlID0gcGRldi0+ZGV2 Lm9mX25vZGU7Cj4+ICsJY3Rsci0+bW9kZV9iaXRzID0gU1BJX1RYX0RVQUwgfCBTUElfUlhfRFVB TCB8Cj4+ICsJCQkgICAgU1BJX1RYX1FVQUQgfCBTUElfUlhfUVVBRDsKPj4gKwo+PiArCXJldCA9 IHNwaV9yZWdpc3Rlcl9jb250cm9sbGVyKGN0bHIpOwo+PiArCWlmIChyZXQpIHsKPj4gKwkJZGV2 X2VycigmcGRldi0+ZGV2LCAic3BpX3JlZ2lzdGVyX2NvbnRyb2xsZXIgZmFpbGVkLlxuIik7Cj4+ ICsJCWdvdG8gZXJyX2luaXQ7Cj4+ICsJfQo+PiArCj4+ICsJcmV0dXJuIDA7Cj4+ICsKPj4gK2Vy cl9pbml0Ogo+PiArCXFjb21fbmFuZGNfdW5hbGxvYyhzbmFuZGMpOwo+IAo+IFNhbWU6IHMvdW5h bGxvYy9mcmVlfGNsZWFudXAvCk9rCj4gCj4+ICtlcnJfc25hbmRfYWxsb2M6Cj4+ICsJY2xrX2Rp c2FibGVfdW5wcmVwYXJlKHNuYW5kYy0+cXNwaS0+aW9tYWNyb19jbGspOwo+PiArZXJyX2Rpc19p b21fY2xrOgo+PiArCWNsa19kaXNhYmxlX3VucHJlcGFyZShzbmFuZGMtPmFvbl9jbGspOwo+PiAr ZXJyX2Fvbl9jbGs6Cj4+ICsJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKHNuYW5kYy0+Y29yZV9jbGsp Owo+PiArZXJyX2NvcmVfY2xrOgo+PiArCWRtYV91bm1hcF9yZXNvdXJjZShkZXYsIHJlcy0+c3Rh cnQsIHJlc291cmNlX3NpemUocmVzKSwKPj4gKwkJCSAgIERNQV9CSURJUkVDVElPTkFMLCAwKTsK Pj4gKwlyZXR1cm4gcmV0Owo+PiArfQo+IAo+IFRoYW5rcywKPiBNaXF1w6hsCgpfX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KTGludXggTVREIGRp c2N1c3Npb24gbWFpbGluZyBsaXN0Cmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4v bGlzdGluZm8vbGludXgtbXRkLwo=