From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.2 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED, USER_AGENT_SANE_2 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8E663C2BA2B for ; Thu, 9 Apr 2020 03:00:02 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 47FE420730 for ; Thu, 9 Apr 2020 03:00:02 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="SL1nK/Yp"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="DbepZAp1" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 47FE420730 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=mediatek.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Date:To:From:Subject:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=F5GU1JKvxuSskKpW0RNnHaNaousBrYMYnVTTBXrY1hA=; b=SL1nK/YpJBpduJ kcFd1jI2d6bRHU+nrye8oAYOSaiISnch5tqIzEPv1hbP9N26jqfFM/1xuOpBIqMZYkwsptCawEXMU b/c2whGVRsDViEEZQXrQ7nK1Wxf/IcO78i4mPhMBaryg3g3E9gAQQZs/okzB1wPmnS9TeswZg2O5T edaofZbqgvY6Jtv25MAJUjbRHwk41m7mw6M8iKcsJ4EYhI/y8GyskZ1T/cdHeGMdK2QnTYKxMdz8n 8+/frmySM7DbsXcUxyQDLgDIo7orkk3lGOhQvVZDHqzLFgI2JA9rPDJKG5uk3NPFL6nHykfgiN9pS xrciP4dOVH7DVvF6iLxA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1jMNPu-0005za-O3; Thu, 09 Apr 2020 02:59:46 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1jMNPp-0005y8-Gm; Thu, 09 Apr 2020 02:59:45 +0000 X-UUID: d2578c696d9d45ec86e86b0bd01cd0f3-20200408 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:MIME-Version:Content-Type:References:In-Reply-To:Date:CC:To:From:Subject:Message-ID; bh=Fusn7+SqpvbI1DscbYxHx41zYWHRTLYrZmwYicK/xuY=; b=DbepZAp1YjVk1EztdVk+xW9NDZ4yIkqvjDQiwdAcYEIgS9M00+Rt1EtkUOjpuNc8vTZopnyrsAocyRvDyoE+DeMQQlfgr+B1Rgq6oiLqQAbjpTNuuzVJly4Zjk6fCdpLF3YY1eam7lPhhVM7ptDjNxdNxRQqiAwmePlwmpAPQzc=; X-UUID: d2578c696d9d45ec86e86b0bd01cd0f3-20200408 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLS) with ESMTP id 1942689736; Wed, 08 Apr 2020 18:59:40 -0800 Received: from MTKMBS06N1.mediatek.inc (172.21.101.129) by MTKMBS62N2.mediatek.inc (172.29.193.42) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Wed, 8 Apr 2020 19:49:34 -0700 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs06n1.mediatek.inc (172.21.101.129) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 9 Apr 2020 10:49:11 +0800 Received: from [172.21.84.99] (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Thu, 9 Apr 2020 10:49:32 +0800 Message-ID: <1586400573.8406.80.camel@mtksdccf07> Subject: Re: [v6, 5/5] media: platform: Add Mediatek ISP P1 V4L2 device driver From: Jungo Lin To: Dafna Hirschfeld Date: Thu, 9 Apr 2020 10:49:33 +0800 In-Reply-To: References: <20191219054930.29513-1-jungo.lin@mediatek.com> <20191219054930.29513-6-jungo.lin@mediatek.com> X-Mailer: Evolution 3.2.3-0ubuntu6 MIME-Version: 1.0 X-MTK: N X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: ryan.yu@mediatek.com, frankie.chiu@mediatek.com, laurent.pinchart@ideasonboard.com, robh@kernel.org, Rynn.Wu@mediatek.com, suleiman@chromium.org, Jerry-ch.Chen@mediatek.com, frederic.chen@mediatek.com, linux-media@vger.kernel.org, devicetree@vger.kernel.org, hverkuil-cisco@xs4all.nl, sj.huang@mediatek.com, yuzhao@chromium.org, linux-mediatek@lists.infradead.org, Pi-Hsun Shih , matthias.bgg@gmail.com, mchehab@kernel.org, linux-arm-kernel@lists.infradead.org, Sean.Cheng@mediatek.com, srv_heupstream@mediatek.com, shik@chromium.org, tfiga@chromium.org, zwisler@chromium.org, ddavenport@chromium.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Hi, Dafna: Thanks for your comments. On Thu, 2020-04-02 at 18:45 +0200, Dafna Hirschfeld wrote: > > On 19.12.19 06:49, Jungo Lin wrote: > > This patch adds the Mediatek ISP P1 HW control device driver. > > It handles the ISP HW configuration, provides interrupt handling and > > initializes the V4L2 device nodes and other V4L2 functions. Moreover, > > implement standard V4L2 video driver that utilizes V4L2 and media > > framework APIs. It supports one media device, one sub-device and > > several video devices during initialization. Moreover, it also connects > > with sensor and seninf drivers with V4L2 async APIs. Communicate with > > co-process via SCP communication to compose ISP registers in the > > firmware. > > > > (The current metadata interface used in meta input and partial > > meta nodes is only a temporary solution to kick off the driver > > development and is not ready to be reviewed yet.) > > > > Signed-off-by: Jungo Lin > > Signed-off-by: Tomasz Figa > > Signed-off-by: Pi-Hsun Shih > > --- > > Changes from v6: > > - Revise help description for VIDEO_MEDIATEK_ISP_PASS1 > > - Apply SCP v21 change in P1 driver by Pi-Hsun Shih > > - Correct auto suspend timer value for suspend/resume issue > > - Increase IPI guard timer to 1 second to avoid false alarm command timeout event > > - Fix KE due to no sen-inf sub-device > > --- > > drivers/media/platform/mtk-isp/Kconfig | 20 + > > .../media/platform/mtk-isp/isp_50/Makefile | 3 + > > .../platform/mtk-isp/isp_50/cam/Makefile | 6 + > > .../platform/mtk-isp/isp_50/cam/mtk_cam-hw.c | 636 +++++ > > .../platform/mtk-isp/isp_50/cam/mtk_cam-hw.h | 64 + > > .../platform/mtk-isp/isp_50/cam/mtk_cam-ipi.h | 222 ++ > > .../mtk-isp/isp_50/cam/mtk_cam-regs.h | 95 + > > .../platform/mtk-isp/isp_50/cam/mtk_cam.c | 2087 +++++++++++++++++ > > .../platform/mtk-isp/isp_50/cam/mtk_cam.h | 244 ++ > > 9 files changed, 3377 insertions(+) > > create mode 100644 drivers/media/platform/mtk-isp/Kconfig > > create mode 100644 drivers/media/platform/mtk-isp/isp_50/Makefile > > create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/Makefile > > create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.c > > create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.h > > create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-ipi.h > > create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-regs.h > > create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.c > > create mode 100644 drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.h > > > > diff --git a/drivers/media/platform/mtk-isp/Kconfig b/drivers/media/platform/mtk-isp/Kconfig > > new file mode 100644 > > index 000000000000..f86e1b59ad1e > > --- /dev/null > > +++ b/drivers/media/platform/mtk-isp/Kconfig > > @@ -0,0 +1,20 @@ > > +config VIDEO_MEDIATEK_ISP_PASS1 > > + tristate "Mediatek ISP Pass 1 driver" > > + depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API > > + depends on ARCH_MEDIATEK > > + select V4L2_FWNODE > > + select VIDEOBUF2_VMALLOC > > + select VIDEOBUF2_DMA_CONTIG > > + select MTK_SCP > > + default n > > + help > > + Pass 1 driver controls 3A (auto-focus, exposure, > > + and white balance) with tuning feature and outputs > > + the captured image buffers in Mediatek's camera system. > > + > > + Choose Y if you want to use Mediatek SoCs to create image > > + captured application such as video recording and still image > > + capturing. > > + > > + To compile this driver as a module, choose M here; the module > > + will be called mtk-cam-isp. > > diff --git a/drivers/media/platform/mtk-isp/isp_50/Makefile b/drivers/media/platform/mtk-isp/isp_50/Makefile > > new file mode 100644 > > index 000000000000..ce79d283b209 > > --- /dev/null > > +++ b/drivers/media/platform/mtk-isp/isp_50/Makefile > > @@ -0,0 +1,3 @@ > > +# SPDX-License-Identifier: GPL-2.0 > > + > > +obj-$(CONFIG_VIDEO_MEDIATEK_ISP_PASS1) += cam/ > > \ No newline at end of file > > diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/Makefile b/drivers/media/platform/mtk-isp/isp_50/cam/Makefile > > new file mode 100644 > > index 000000000000..53b54d3c26a0 > > --- /dev/null > > +++ b/drivers/media/platform/mtk-isp/isp_50/cam/Makefile > > @@ -0,0 +1,6 @@ > > +# SPDX-License-Identifier: GPL-2.0 > > + > > +mtk-cam-isp-objs += mtk_cam.o > > +mtk-cam-isp-objs += mtk_cam-hw.o > > + > > +obj-$(CONFIG_VIDEO_MEDIATEK_ISP_PASS1) += mtk-cam-isp.o > > \ No newline at end of file > > diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.c b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.c > > new file mode 100644 > > index 000000000000..4065d0d29b7f > > --- /dev/null > > +++ b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.c > > @@ -0,0 +1,636 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +// > > +// Copyright (c) 2019 MediaTek Inc. > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > + > > +#include "mtk_cam.h" > > +#include "mtk_cam-hw.h" > > +#include "mtk_cam-regs.h" > > + > > +#define MTK_ISP_COMPOSER_MEM_SIZE 0x200000 > > +#define MTK_ISP_CQ_BUFFER_COUNT 3 > > +#define MTK_ISP_CQ_ADDRESS_OFFSET 0x640 > > + > > +/* > > + * > > + * MTK Camera ISP P1 HW supports 3 ISP HW (CAM A/B/C). > > + * The T-put capability of CAM B is the maximum (max line buffer: 5376 pixels) > > + * For CAM A/C, it only supports max line buffer with 3328 pixels. > > + * In current driver, only supports CAM B. > > + * > > + */ > > +#define MTK_ISP_CAM_ID_B 3 > > +#define MTK_ISP_AUTOSUSPEND_DELAY_MS 66 > > +#define MTK_ISP_IPI_SEND_TIMEOUT 1000 > > +#define MTK_ISP_STOP_HW_TIMEOUT (33 * USEC_PER_MSEC) > > + > > +static void isp_tx_frame_worker(struct work_struct *work) > > +{ > > + struct mtk_cam_dev_request *req = > > + container_of(work, struct mtk_cam_dev_request, frame_work); > > + struct mtk_cam_dev *cam = > > + container_of(req->req.mdev, struct mtk_cam_dev, media_dev); > > + struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(cam->dev); > > + > > + scp_ipi_send(p1_dev->scp, SCP_IPI_ISP_FRAME, &req->frame_params, > > + sizeof(req->frame_params), MTK_ISP_IPI_SEND_TIMEOUT); > > +} > > + > > +static void isp_composer_handler(void *data, unsigned int len, void *priv) > > +{ > > + struct mtk_isp_p1_device *p1_dev = (struct mtk_isp_p1_device *)priv; > > + struct device *dev = p1_dev->dev; > > + struct mtk_isp_scp_p1_cmd *ipi_msg; > > + > > + ipi_msg = (struct mtk_isp_scp_p1_cmd *)data; > > + > > + if (len < offsetofend(struct mtk_isp_scp_p1_cmd, ack_info)) { > > + dev_err(dev, "wrong IPI len:%d\n", len); > > + return; > > + } > > + > > + if (ipi_msg->cmd_id != ISP_CMD_ACK || > > + ipi_msg->ack_info.cmd_id != ISP_CMD_FRAME_ACK) > > + return; > > + > > + p1_dev->composed_frame_seq_no = ipi_msg->ack_info.frame_seq_no; > > + dev_dbg(dev, "ack frame_num:%d\n", p1_dev->composed_frame_seq_no); > > +} > > + > > +static int isp_composer_init(struct mtk_isp_p1_device *p1_dev) > > +{ > > + struct device *dev = p1_dev->dev; > > + int ret; > > + > > + ret = scp_ipi_register(p1_dev->scp, SCP_IPI_ISP_CMD, > > + isp_composer_handler, p1_dev); > > + if (ret) { > > + dev_err(dev, "failed to register IPI cmd\n"); > > + return ret; > > + } > > + ret = scp_ipi_register(p1_dev->scp, SCP_IPI_ISP_FRAME, > > + isp_composer_handler, p1_dev); > > + if (ret) { > > + dev_err(dev, "failed to register IPI frame\n"); > > + goto unreg_ipi_cmd; > > + } > > + > > + p1_dev->composer_wq = > > + alloc_ordered_workqueue(dev_name(p1_dev->dev), > > + __WQ_LEGACY | WQ_MEM_RECLAIM | > > + WQ_FREEZABLE); > > + if (!p1_dev->composer_wq) { > > + dev_err(dev, "failed to alloc composer workqueue\n"); > > + goto unreg_ipi_frame; > > + } > > + > > + return 0; > > + > > +unreg_ipi_frame: > > + scp_ipi_unregister(p1_dev->scp, SCP_IPI_ISP_FRAME); > > +unreg_ipi_cmd: > > + scp_ipi_unregister(p1_dev->scp, SCP_IPI_ISP_CMD); > > + > > + return ret; > > +} > > + > > +static void isp_composer_uninit(struct mtk_isp_p1_device *p1_dev) > > +{ > > + destroy_workqueue(p1_dev->composer_wq); > > + scp_ipi_unregister(p1_dev->scp, SCP_IPI_ISP_CMD); > > + scp_ipi_unregister(p1_dev->scp, SCP_IPI_ISP_FRAME); > > +} > > + > > +static void isp_composer_hw_init(struct mtk_isp_p1_device *p1_dev) > > +{ > > + struct mtk_isp_scp_p1_cmd composer_tx_cmd; > > + > > + memset(&composer_tx_cmd, 0, sizeof(composer_tx_cmd)); > > + composer_tx_cmd.cmd_id = ISP_CMD_INIT; > > + composer_tx_cmd.init_param.hw_module = MTK_ISP_CAM_ID_B; > > + > > + /* > > + * Passed coherent reserved memory info. for SCP firmware usage. > > + * This buffer is used for SCP's ISP composer to compose. > > + * The size of is fixed to 0x200000 for the requirement of composer. > > + */ > > + composer_tx_cmd.init_param.cq_addr.iova = p1_dev->composer_iova; > > + composer_tx_cmd.init_param.cq_addr.scp_addr = p1_dev->composer_scp_addr; > > + > > + scp_ipi_send(p1_dev->scp, SCP_IPI_ISP_CMD, &composer_tx_cmd, > > + sizeof(composer_tx_cmd), MTK_ISP_IPI_SEND_TIMEOUT); > > +} > > + > > +static void isp_composer_hw_deinit(struct mtk_isp_p1_device *p1_dev) > > +{ > > + struct mtk_isp_scp_p1_cmd composer_tx_cmd; > > + > > + memset(&composer_tx_cmd, 0, sizeof(composer_tx_cmd)); > > + composer_tx_cmd.cmd_id = ISP_CMD_DEINIT; > > + > > + scp_ipi_send(p1_dev->scp, SCP_IPI_ISP_CMD, &composer_tx_cmd, > > + sizeof(composer_tx_cmd), MTK_ISP_IPI_SEND_TIMEOUT); > > + > > + isp_composer_uninit(p1_dev); > > +} > > + > > +void mtk_isp_hw_config(struct mtk_cam_dev *cam, > > + struct p1_config_param *config_param) > > +{ > > + struct mtk_isp_scp_p1_cmd composer_tx_cmd; > > + struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(cam->dev); > > + > > + memset(&composer_tx_cmd, 0, sizeof(composer_tx_cmd)); > > + composer_tx_cmd.cmd_id = ISP_CMD_CONFIG; > > + memcpy(&composer_tx_cmd.config_param, config_param, > > + sizeof(*config_param)); > > + > > + scp_ipi_send(p1_dev->scp, SCP_IPI_ISP_CMD, &composer_tx_cmd, > > + sizeof(composer_tx_cmd), MTK_ISP_IPI_SEND_TIMEOUT); > > +} > > + > > +void mtk_isp_stream(struct mtk_cam_dev *cam, int on) > > +{ > > + struct mtk_isp_scp_p1_cmd composer_tx_cmd; > > + struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(cam->dev); > > + > > + memset(&composer_tx_cmd, 0, sizeof(composer_tx_cmd)); > > + composer_tx_cmd.cmd_id = ISP_CMD_STREAM; > > + composer_tx_cmd.is_stream_on = on; > > + > > + scp_ipi_send(p1_dev->scp, SCP_IPI_ISP_CMD, &composer_tx_cmd, > > + sizeof(composer_tx_cmd), MTK_ISP_IPI_SEND_TIMEOUT); > > +} > > + > > +int mtk_isp_hw_init(struct mtk_cam_dev *cam) > > +{ > > + struct device *dev = cam->dev; > > + struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev); > > + int ret; > > + > > + ret = rproc_boot(p1_dev->rproc_handle); > > + if (ret) { > > + dev_err(dev, "failed to rproc_boot\n"); > > + return ret; > > + } > > + > > + ret = isp_composer_init(p1_dev); > > + if (ret) > > + return ret; > > + > > + pm_runtime_get_sync(dev); > > + isp_composer_hw_init(p1_dev); > > + > > + p1_dev->enqueued_frame_seq_no = 0; > > + p1_dev->dequeued_frame_seq_no = 0; > > + p1_dev->composed_frame_seq_no = 0; > > + p1_dev->sof_count = 0; > > + > > + dev_dbg(dev, "%s done\n", __func__); > > + > > + return 0; > > +} > > + > > +int mtk_isp_hw_release(struct mtk_cam_dev *cam) > > +{ > > + struct device *dev = cam->dev; > > + struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev); > > + > > + isp_composer_hw_deinit(p1_dev); > > + pm_runtime_mark_last_busy(dev); > > + pm_runtime_put_autosuspend(dev); > > + rproc_shutdown(p1_dev->rproc_handle); > > + > > + dev_dbg(dev, "%s done\n", __func__); > > + > > + return 0; > > +} > > + > > +void mtk_isp_req_enqueue(struct mtk_cam_dev *cam, > > + struct mtk_cam_dev_request *req) > > +{ > > + struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(cam->dev); > > + > > + /* Accumulated frame sequence number */ > > + req->frame_params.frame_seq_no = ++p1_dev->enqueued_frame_seq_no; > > + > > + INIT_WORK(&req->frame_work, isp_tx_frame_worker); > > + queue_work(p1_dev->composer_wq, &req->frame_work); > > + dev_dbg(cam->dev, "enqueue fd:%s frame_seq_no:%d job cnt:%d\n", > > + req->req.debug_str, req->frame_params.frame_seq_no, > > + cam->running_job_count); > > +} > > + > > +static void isp_irq_handle_sof(struct mtk_isp_p1_device *p1_dev, > > + unsigned int dequeued_frame_seq_no) > > +{ > > + dma_addr_t base_addr = p1_dev->composer_iova; > > + struct device *dev = p1_dev->dev; > > + struct mtk_cam_dev_request *req; > > + int composed_frame_seq_no = p1_dev->composed_frame_seq_no; > > + unsigned int addr_offset; > > + > > + /* Send V4L2_EVENT_FRAME_SYNC event */ > > + mtk_cam_dev_event_frame_sync(&p1_dev->cam_dev, dequeued_frame_seq_no); > > + > > + p1_dev->sof_count += 1; > > + /* Save frame information */ > > + p1_dev->dequeued_frame_seq_no = dequeued_frame_seq_no; > > + > > + req = mtk_cam_dev_get_req(&p1_dev->cam_dev, dequeued_frame_seq_no); > > + if (req) > > + req->timestamp = ktime_get_boottime_ns(); > > + > > + /* Update CQ base address if needed */ > > + if (composed_frame_seq_no <= dequeued_frame_seq_no) { > > + dev_dbg(dev, > > + "SOF_INT_ST, no update, cq_num:%d, frame_seq:%d\n", > > + composed_frame_seq_no, dequeued_frame_seq_no); > > + return; > > + } > > + addr_offset = MTK_ISP_CQ_ADDRESS_OFFSET * > > + (dequeued_frame_seq_no % MTK_ISP_CQ_BUFFER_COUNT); > > + writel(base_addr + addr_offset, p1_dev->regs + REG_CQ_THR0_BASEADDR); > > + dev_dbg(dev, > > + "SOF_INT_ST, update next, cq_num:%d, frame_seq:%d cq_addr:0x%x\n", > > + composed_frame_seq_no, dequeued_frame_seq_no, addr_offset); > > +} > > + > > +static void isp_irq_handle_dma_err(struct mtk_isp_p1_device *p1_dev) > > +{ > > + u32 val; > > + > > + dev_err(p1_dev->dev, > > + "IMGO:0x%x, RRZO:0x%x, AAO=0x%x, AFO=0x%x, LMVO=0x%x\n", > > + readl(p1_dev->regs + REG_IMGO_ERR_STAT), > > + readl(p1_dev->regs + REG_RRZO_ERR_STAT), > > + readl(p1_dev->regs + REG_AAO_ERR_STAT), > > + readl(p1_dev->regs + REG_AFO_ERR_STAT), > > + readl(p1_dev->regs + REG_LMVO_ERR_STAT)); > > + dev_err(p1_dev->dev, > > + "LCSO=0x%x, PSO=0x%x, FLKO=0x%x, BPCI:0x%x, LSCI=0x%x\n", > > + readl(p1_dev->regs + REG_LCSO_ERR_STAT), > > + readl(p1_dev->regs + REG_PSO_ERR_STAT), > > + readl(p1_dev->regs + REG_FLKO_ERR_STAT), > > + readl(p1_dev->regs + REG_BPCI_ERR_STAT), > > + readl(p1_dev->regs + REG_LSCI_ERR_STAT)); > > + > > + /* Disable DMA error mask to avoid too much error log */ > > + val = readl(p1_dev->regs + REG_CTL_RAW_INT_EN); > > + writel((val & (~DMA_ERR_INT_EN)), p1_dev->regs + REG_CTL_RAW_INT_EN); > > + dev_dbg(p1_dev->dev, "disable DMA error mask:0x%x\n", val); > > +} > > + > > +static irqreturn_t isp_irq_cam(int irq, void *data) > > +{ > > + struct mtk_isp_p1_device *p1_dev = (struct mtk_isp_p1_device *)data; > > + struct device *dev = p1_dev->dev; > > + unsigned int dequeued_frame_seq_no; > > + unsigned int irq_status, err_status, dma_status; > > + unsigned long flags; > > + > > + spin_lock_irqsave(&p1_dev->spinlock_irq, flags); > > + irq_status = readl(p1_dev->regs + REG_CTL_RAW_INT_STAT); > > + err_status = irq_status & INT_ST_MASK_CAM_ERR; > > + dma_status = readl(p1_dev->regs + REG_CTL_RAW_INT2_STAT); > > + dequeued_frame_seq_no = readl(p1_dev->regs + REG_FRAME_SEQ_NUM); > > + spin_unlock_irqrestore(&p1_dev->spinlock_irq, flags); > > + > > + /* > > + * In normal case, the next SOF ISR should come after HW PASS1 DONE ISR. > > + * If these two ISRs come together, print warning msg to hint. > > + */ > > + if ((irq_status & SOF_INT_ST) && (irq_status & HW_PASS1_DON_ST)) > > + dev_dbg(dev, "sof_done block cnt:%d\n", p1_dev->sof_count); > > + > > + /* De-queue frame */ > > + if (irq_status & SW_PASS1_DON_ST) { > > + mtk_cam_dev_dequeue_req_frame(&p1_dev->cam_dev, > > + p1_dev->dequeued_frame_seq_no); > > + mtk_cam_dev_req_try_queue(&p1_dev->cam_dev); > > + } > > + > > + /* Save frame info. & update CQ address for frame HW en-queue */ > > + if (irq_status & SOF_INT_ST) > > + isp_irq_handle_sof(p1_dev, dequeued_frame_seq_no); > > + > > + /* Check ISP error status */ > > + if (err_status) { > > + dev_err(dev, "int_err:0x%x 0x%x\n", irq_status, err_status); > > + /* Show DMA errors in detail */ > > + if (err_status & DMA_ERR_ST) > > + isp_irq_handle_dma_err(p1_dev); > > + } > > + > > + dev_dbg(dev, "SOF:%d irq:0x%x, dma:0x%x, frame_num:%d\n", > > + p1_dev->sof_count, irq_status, dma_status, > > + dequeued_frame_seq_no); > > + > > + return IRQ_HANDLED; > > +} > > + > > +static int isp_setup_scp_rproc(struct mtk_isp_p1_device *p1_dev, > > + struct platform_device *pdev) > > +{ > > + struct device *dev = p1_dev->dev; > > + dma_addr_t addr; > > + void *ptr; > > + int ret; > > + > > + p1_dev->scp = scp_get(pdev); > > + if (!p1_dev->scp) { > > + dev_err(dev, "failed to get scp device\n"); > > + return -ENODEV; > > + } > > + > > + p1_dev->rproc_handle = scp_get_rproc(p1_dev->scp); > > + dev_dbg(dev, "p1 rproc_phandle: 0x%pK\n", p1_dev->rproc_handle); > > + p1_dev->cam_dev.smem_dev = scp_get_device(p1_dev->scp); > > + > > + /* > > + * Allocate coherent reserved memory for SCP firmware usage. > > + * The size of SCP composer's memory is fixed to 0x200000 > > + * for the requirement of firmware. > > + */ > > + ptr = dma_alloc_coherent(p1_dev->cam_dev.smem_dev, > > + MTK_ISP_COMPOSER_MEM_SIZE, &addr, GFP_KERNEL); > > + if (!ptr) { > > + ret = -ENOMEM; > > + goto fail_put_scp; > > + } > > + > > + p1_dev->composer_scp_addr = addr; > > + p1_dev->composer_virt_addr = ptr; > > + dev_dbg(dev, "scp addr:%pad va:%pK\n", &addr, ptr); > > + > > + /* > > + * This reserved memory is also be used by ISP P1 HW. > > + * Need to get iova address for ISP P1 DMA. > > + */ > > + addr = dma_map_resource(dev, addr, MTK_ISP_COMPOSER_MEM_SIZE, > > + DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); > > + if (dma_mapping_error(dev, addr)) { > > + dev_err(dev, "failed to map scp iova\n"); > > + ret = -ENOMEM; > > + goto fail_free_mem; > > + } > > + p1_dev->composer_iova = addr; > > + dev_dbg(dev, "scp iova addr:%pad\n", &addr); > > + > > + return 0; > > + > > +fail_free_mem: > > + dma_free_coherent(p1_dev->cam_dev.smem_dev, MTK_ISP_COMPOSER_MEM_SIZE, > > + p1_dev->composer_virt_addr, > > + p1_dev->composer_scp_addr); > > + p1_dev->composer_scp_addr = 0; > > +fail_put_scp: > > + scp_put(p1_dev->scp); > > + > > + return ret; > > +} > > + > > +static void isp_teardown_scp_rproc(struct mtk_isp_p1_device *p1_dev) > > +{ > > + dma_free_coherent(p1_dev->cam_dev.smem_dev, MTK_ISP_COMPOSER_MEM_SIZE, > > + p1_dev->composer_virt_addr, > > + p1_dev->composer_scp_addr); > > + p1_dev->composer_scp_addr = 0; > > + scp_put(p1_dev->scp); > > +} > > + > > +static int mtk_isp_pm_suspend(struct device *dev) > > +{ > > + struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev); > > + u32 val; > > + int ret; > > + > > + dev_dbg(dev, "- %s\n", __func__); > > + > > + if (pm_runtime_suspended(dev)) > > + return 0; > > + > > + /* Disable ISP's view finder and wait for TG idle if possible */ > > + dev_dbg(dev, "cam suspend, disable VF\n"); > > + val = readl(p1_dev->regs + REG_TG_VF_CON); > > + writel(val & (~TG_VF_CON_VFDATA_EN), p1_dev->regs + REG_TG_VF_CON); > > + readl_poll_timeout_atomic(p1_dev->regs + REG_TG_INTER_ST, val, > > + (val & TG_CS_MASK) == TG_IDLE_ST, > > + USEC_PER_MSEC, MTK_ISP_STOP_HW_TIMEOUT); > > + > > + /* Disable CMOS */ > > + val = readl(p1_dev->regs + REG_TG_SEN_MODE); > > + writel(val & (~TG_SEN_MODE_CMOS_EN), p1_dev->regs + REG_TG_SEN_MODE); > > + > > + /* Force ISP HW to idle */ > > + ret = pm_runtime_force_suspend(dev); > > + if (ret) { > > + dev_err(dev, "failed to force suspend:%d\n", ret); > > + goto reenable_hw; > > + } > > + > > + return 0; > > + > > +reenable_hw: > > + val = readl(p1_dev->regs + REG_TG_SEN_MODE); > > + writel(val | TG_SEN_MODE_CMOS_EN, p1_dev->regs + REG_TG_SEN_MODE); > > + val = readl(p1_dev->regs + REG_TG_VF_CON); > > + writel(val | TG_VF_CON_VFDATA_EN, p1_dev->regs + REG_TG_VF_CON); > > + > > + return ret; > > +} > > + > > +static int mtk_isp_pm_resume(struct device *dev) > > +{ > > + struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev); > > + u32 val; > > + int ret; > > + > > + dev_dbg(dev, "- %s\n", __func__); > > + > > + if (pm_runtime_suspended(dev)) > > + return 0; > > + > > + /* Force ISP HW to resume */ > > + ret = pm_runtime_force_resume(dev); > > + if (ret) > > + return ret; > > + > > + /* Enable CMOS */ > > + dev_dbg(dev, "cam resume, enable CMOS/VF\n"); > > + val = readl(p1_dev->regs + REG_TG_SEN_MODE); > > + writel(val | TG_SEN_MODE_CMOS_EN, p1_dev->regs + REG_TG_SEN_MODE); > > + > > + /* Enable VF */ > > + val = readl(p1_dev->regs + REG_TG_VF_CON); > > + writel(val | TG_VF_CON_VFDATA_EN, p1_dev->regs + REG_TG_VF_CON); > > + > > + return 0; > > +} > > + > > +static int mtk_isp_runtime_suspend(struct device *dev) > > +{ > > + struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev); > > + > > + dev_dbg(dev, "%s:disable clock\n", __func__); > > + clk_bulk_disable_unprepare(p1_dev->num_clks, p1_dev->clks); > > + > > + return 0; > > +} > > + > > +static int mtk_isp_runtime_resume(struct device *dev) > > +{ > > + struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev); > > + int ret; > > + > > + dev_dbg(dev, "%s:enable clock\n", __func__); > > + ret = clk_bulk_prepare_enable(p1_dev->num_clks, p1_dev->clks); > > + if (ret) { > > + dev_err(dev, "failed to enable clock:%d\n", ret); > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > +static int mtk_isp_probe(struct platform_device *pdev) > > +{ > > + /* List of clocks required by isp cam */ > > + static const char * const clk_names[] = { > > + "camsys_cam_cgpdn", "camsys_camtg_cgpdn" > > + }; > > + struct mtk_isp_p1_device *p1_dev; > > + struct device *dev = &pdev->dev; > > + struct resource *res; > > + int irq, ret, i; > > + > > + p1_dev = devm_kzalloc(dev, sizeof(*p1_dev), GFP_KERNEL); > > + if (!p1_dev) > > + return -ENOMEM; > > + > > + p1_dev->dev = dev; > > + dev_set_drvdata(dev, p1_dev); > > + > > + /* > > + * Now only support single CAM with CAM B. > > + * Get CAM B register base with CAM B index. > > + * Support multiple CAMs in future. > > + */ > > + res = platform_get_resource(pdev, IORESOURCE_MEM, MTK_ISP_CAM_ID_B); > > + p1_dev->regs = devm_ioremap_resource(dev, res); > > + if (IS_ERR(p1_dev->regs)) { > > + dev_err(dev, "failed to map reister base\n"); > > + return PTR_ERR(p1_dev->regs); > > + } > > + dev_dbg(dev, "cam, map_addr=0x%pK\n", p1_dev->regs); > > + > > + /* > > + * The cam_sys unit only supports reg., but has no IRQ support. > > + * The reg. & IRQ index is shifted with 1 for CAM B in DTS. > > + */ > > + irq = platform_get_irq(pdev, MTK_ISP_CAM_ID_B - 1); > > + if (!irq) { > > + dev_err(dev, "failed to get irq\n"); > > + return -ENODEV; > > + } > > + ret = devm_request_irq(dev, irq, isp_irq_cam, 0, dev_name(dev), > > + p1_dev); > > + if (ret) { > > + dev_err(dev, "failed to request irq=%d\n", irq); > > + return ret; > > + } > > + dev_dbg(dev, "registered irq=%d\n", irq); > > + spin_lock_init(&p1_dev->spinlock_irq); > > + > > + p1_dev->num_clks = ARRAY_SIZE(clk_names); > > + p1_dev->clks = devm_kcalloc(dev, p1_dev->num_clks, > > + sizeof(*p1_dev->clks), GFP_KERNEL); > > + if (!p1_dev->clks) > > + return -ENOMEM; > > + > > + for (i = 0; i < p1_dev->num_clks; ++i) > > + p1_dev->clks[i].id = clk_names[i]; > > + > > + ret = devm_clk_bulk_get(dev, p1_dev->num_clks, p1_dev->clks); > > + if (ret) { > > + dev_err(dev, "failed to get isp cam clock:%d\n", ret); > > + return ret; > > + } > > + > > + ret = isp_setup_scp_rproc(p1_dev, pdev); > > + if (ret) > > + return ret; > > + > > + pm_runtime_set_autosuspend_delay(dev, MTK_ISP_AUTOSUSPEND_DELAY_MS); > > + pm_runtime_use_autosuspend(dev); > > + pm_runtime_enable(dev); > > + > > + /* Initialize the v4l2 common part */ > > + ret = mtk_cam_dev_init(pdev, &p1_dev->cam_dev); > > + if (ret) { > > + isp_teardown_scp_rproc(p1_dev); > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > +static int mtk_isp_remove(struct platform_device *pdev) > > +{ > > + struct device *dev = &pdev->dev; > > + struct mtk_isp_p1_device *p1_dev = dev_get_drvdata(dev); > > + > > + mtk_cam_dev_cleanup(&p1_dev->cam_dev); > > + pm_runtime_dont_use_autosuspend(dev); > > + pm_runtime_disable(dev); > > + dma_unmap_page_attrs(dev, p1_dev->composer_iova, > > + MTK_ISP_COMPOSER_MEM_SIZE, DMA_TO_DEVICE, > > + DMA_ATTR_SKIP_CPU_SYNC); > > + isp_teardown_scp_rproc(p1_dev); > > + > > + return 0; > > +} > > + > > +static const struct dev_pm_ops mtk_isp_pm_ops = { > > + SET_SYSTEM_SLEEP_PM_OPS(mtk_isp_pm_suspend, mtk_isp_pm_resume) > > + SET_RUNTIME_PM_OPS(mtk_isp_runtime_suspend, mtk_isp_runtime_resume, > > + NULL) > > +}; > > + > > +static const struct of_device_id mtk_isp_of_ids[] = { > > + {.compatible = "mediatek,mt8183-camisp",}, > > + {} > > +}; > > +MODULE_DEVICE_TABLE(of, mtk_isp_of_ids); > > + > > +static struct platform_driver mtk_isp_driver = { > > + .probe = mtk_isp_probe, > > + .remove = mtk_isp_remove, > > + .driver = { > > + .name = "mtk-cam-p1", > > + .of_match_table = of_match_ptr(mtk_isp_of_ids), > > + .pm = &mtk_isp_pm_ops, > > + } > > +}; > > + > > +module_platform_driver(mtk_isp_driver); > > + > > +MODULE_DESCRIPTION("Mediatek ISP P1 driver"); > > +MODULE_LICENSE("GPL v2"); > > diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.h b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.h > > new file mode 100644 > > index 000000000000..837662f92a5e > > --- /dev/null > > +++ b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-hw.h > > @@ -0,0 +1,64 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +/* > > + * Copyright (c) 2019 MediaTek Inc. > > + */ > > + > > +#ifndef __MTK_CAM_HW_H__ > > +#define __MTK_CAM_HW_H__ > > + > > +#include > > + > > +#include "mtk_cam.h" > > +#include "mtk_cam-ipi.h" > > + > > +/* > > + * struct mtk_isp_p1_device - the Mediatek ISP P1 device information > > + * > > + * @dev: Pointer to device. > > + * @scp_pdev: Pointer to SCP platform device. > > + * @rproc_handle: Pointer to new remoteproc instance. > > + * @cam_dev: Embedded struct cam_dev > > + * @regs: Camera ISP HW base register address > > + * @num_clks: The number of driver's clocks > > + * @clks: The clock data array > > + * @spinlock_irq: Used to protect register read/write data > > + * @enqueued_frame_seq_no: Frame sequence number of enqueued frame > > + * @dequeued_frame_seq_no: Frame sequence number of dequeued frame > > + * @composed_frame_seq_no: Frame sequence number of composed frame > > + * @timestamp: Frame timestamp in ns > > + * @sof_count: SOF counter > > + * @composer_wq: The work queue for frame request composing > > + * @composer_scp_addr: SCP address of ISP composer memory > > + * @composer_iova: DMA address of ISP composer memory > > + * @virt_addr: Virtual address of ISP composer memory > > + * > > + */ > > +struct mtk_isp_p1_device { > > + struct device *dev; > > + struct mtk_scp *scp; > > + struct rproc *rproc_handle; > > + struct mtk_cam_dev cam_dev; > > + void __iomem *regs; > > + unsigned int num_clks; > > + struct clk_bulk_data *clks; > > + /* Used to protect register read/write data */ > > + spinlock_t spinlock_irq; > > + unsigned int enqueued_frame_seq_no; > > + unsigned int dequeued_frame_seq_no; > > + unsigned int composed_frame_seq_no; > > + u8 sof_count; > > + struct workqueue_struct *composer_wq; > > + dma_addr_t composer_scp_addr; > > + dma_addr_t composer_iova; > > + void *composer_virt_addr; > > +}; > > + > > +int mtk_isp_hw_init(struct mtk_cam_dev *cam_dev); > > +int mtk_isp_hw_release(struct mtk_cam_dev *cam_dev); > > +void mtk_isp_hw_config(struct mtk_cam_dev *cam_dev, > > + struct p1_config_param *config_param); > > +void mtk_isp_stream(struct mtk_cam_dev *cam_dev, int on); > > +void mtk_isp_req_enqueue(struct mtk_cam_dev *cam_dev, > > + struct mtk_cam_dev_request *req); > > + > > +#endif /* __MTK_CAM_HW_H__ */ > > diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-ipi.h b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-ipi.h > > new file mode 100644 > > index 000000000000..981b634dd91f > > --- /dev/null > > +++ b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-ipi.h > > @@ -0,0 +1,222 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +/* > > + * Copyright (c) 2019 MediaTek Inc. > > + */ > > + > > +#ifndef __MTK_CAM_IPI_H__ > > +#define __MTK_CAM_IPI_H__ > > + > > +#include > > + > > +/* > > + * struct img_size - Image size information. > > + * > > + * @w: Image width, the unit is pixel > > + * @h: Image height, the unit is pixel > > + * @xsize: Bytes per line based on width. > > + * @stride: Bytes per line when changing line. > > + * Stride is based on xsize + HW constrain(byte align). > > + * > > + */ > > +struct img_size { > > + u32 w; > > + u32 h; > > + u32 xsize; > > + u32 stride; > > +} __packed; > > + > > +/* > > + * struct p1_img_crop - image corp information > > + * > > + * @left: The left of crop area. > > + * @top: The top of crop area. > > + * @width: The width of crop area. > > + * @height: The height of crop area. > > + * > > + */ > > +struct p1_img_crop { > > + u32 left; > > + u32 top; > > + u32 width; > > + u32 height; > > +} __packed; > > + > > +/* > > + * struct dma_buffer - DMA buffer address information > > + * > > + * @iova: DMA address for ISP DMA device > > + * @scp_addr: SCP address for external co-process unit > > + * > > + */ > > +struct dma_buffer { > > + u32 iova; > > + u32 scp_addr; > > +} __packed; > > + > > +/* > > + * struct p1_img_output - ISP P1 image output information > > + * > > + * @buffer: DMA buffer address of image. > > + * @size: The image size configuration. > > + * @crop: The crop configuration. > > + * @pixel_bits: The bits per image pixel. > > + * @img_fmt: The image format. > > + * > > + */ > > +struct p1_img_output { > > + struct dma_buffer buffer; > > + struct img_size size; > > + struct p1_img_crop crop; > > + u8 pixel_bits; > > + u32 img_fmt; > > +} __packed; > > + > > +/* > > + * struct cfg_in_param - Image input parameters structure. > > + * Normally, it comes from sensor information. > > + * > > + * @continuous: Indicate the sensor mode. Continuous or single shot. > > + * @subsample: Indicate to enables SOF subsample or not. > > + * @pixel_mode: Describe 1/2/4 pixels per clock cycle. > > + * @data_pattern: Describe input data pattern. > > + * @raw_pixel_id: Bayer sequence. > > + * @tg_fps: The fps rate of TG (time generator). > > + * @img_fmt: The image format of input source. > > + * @p1_img_crop: The crop configuration of input source. > > + * > > + */ > > +struct cfg_in_param { > > + u8 continuous; > > + u8 subsample; > > + u8 pixel_mode; > > + u8 data_pattern; > > + u8 raw_pixel_id; > > + u16 tg_fps; > > + u32 img_fmt; > > + struct p1_img_crop crop; > > +} __packed; > > + > > +/* > > + * struct cfg_main_out_param - The image output parameters of main stream. > > + * > > + * @bypass: Indicate this device is enabled or disabled or not. > > + * @pure_raw: Indicate the image path control. > > + * True: pure raw > > + * False: processing raw > > + * @pure_raw_pack: Indicate the image is packed or not. > > + * True: packed mode > > + * False: unpacked mode > > + * @p1_img_output: The output image information. > > + * > > + */ > > +struct cfg_main_out_param { > > + u8 bypass; > > + u8 pure_raw; > > + u8 pure_raw_pack; > > + struct p1_img_output output; > > +} __packed; > > + > > +/* > > + * struct cfg_resize_out_param - The image output parameters of > > + * packed out stream. > > + * > > + * @bypass: Indicate this device is enabled or disabled or not. > > + * @p1_img_output: The output image information. > > + * > > + */ > > +struct cfg_resize_out_param { > > + u8 bypass; > > + struct p1_img_output output; > > +} __packed; > > + > > +/* > > + * struct p1_config_param - ISP P1 configuration parameters. > > + * > > + * @cfg_in_param: The Image input parameters. > > + * @cfg_main_param: The main output image parameters. > > + * @cfg_resize_out_param: The packed output image parameters. > > + * @enabled_dmas: The enabled DMA port information. > > + * > > + */ > > +struct p1_config_param { > > + struct cfg_in_param cfg_in_param; > > + struct cfg_main_out_param cfg_main_param; > > + struct cfg_resize_out_param cfg_resize_param; > > + u32 enabled_dmas; > > +} __packed; > > + > > +/* > > + * struct P1_meta_frame - ISP P1 meta frame information. > > + * > > + * @enabled_dma: The enabled DMA port information. > > + * @vb_index: The VB2 index of meta buffer. > > + * @meta_addr: DMA buffer address of meta buffer. > > + * > > + */ > > +struct P1_meta_frame { > > + u32 enabled_dma; > > + u32 vb_index; > > + struct dma_buffer meta_addr; > > +} __packed; > > + > > +/* > > + * struct isp_init_info - ISP P1 composer init information. > > + * > > + * @hw_module: The ISP Camera HW module ID. > > + * @cq_addr: The DMA address of composer memory. > > + * > > + */ > > +struct isp_init_info { > > + u8 hw_module; > > + struct dma_buffer cq_addr; > > +} __packed; > > + > > +/* > > + * struct isp_ack_info - ISP P1 IPI command ack information. > > + * > > + * @cmd_id: The IPI command ID is acked. > > + * @frame_seq_no: The IPI frame sequence number is acked. > > + * > > + */ > > +struct isp_ack_info { > > + u8 cmd_id; > > + u32 frame_seq_no; > > +} __packed; > > + > > +/* > > + * The IPI command enumeration. > > + */ > > +enum mtk_isp_scp_cmds { > > + ISP_CMD_INIT, > > + ISP_CMD_CONFIG, > > + ISP_CMD_STREAM, > > + ISP_CMD_DEINIT, > > + ISP_CMD_ACK, > > + ISP_CMD_FRAME_ACK, > > + ISP_CMD_RESERVED, > > +}; > > + > > +/* > > + * struct mtk_isp_scp_p1_cmd - ISP P1 IPI command strcture. > > + * > > + * @cmd_id: The IPI command ID. > > + * @init_param: The init formation for ISP_CMD_INIT. > > + * @config_param: The cmd configuration for ISP_CMD_CONFIG. > > + * @enabled_dmas: The meta configuration information for ISP_CMD_CONFIG_META. > > + * @is_stream_on: The stream information for ISP_CMD_STREAM. > > + * @ack_info: The cmd ack. information for ISP_CMD_ACK. > > + * > > + */ > > +struct mtk_isp_scp_p1_cmd { > > + u8 cmd_id; > > + union { > > + struct isp_init_info init_param; > > + struct p1_config_param config_param; > > + u32 enabled_dmas; > > + struct P1_meta_frame meta_frame; > > + u8 is_stream_on; > > + struct isp_ack_info ack_info; > > + }; > > +} __packed; > > + > > +#endif /* __MTK_CAM_IPI_H__ */ > > diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-regs.h b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-regs.h > > new file mode 100644 > > index 000000000000..ab2277f45fa4 > > --- /dev/null > > +++ b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam-regs.h > > @@ -0,0 +1,95 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +/* > > + * Copyright (c) 2019 MediaTek Inc. > > + */ > > + > > +#ifndef __MTK_CAM_REGS_H__ > > +#define __MTK_CAM_REGS_H__ > > + > > +/* ISP interrupt enable */ > > +#define REG_CTL_RAW_INT_EN 0x0020 > > +#define DMA_ERR_INT_EN BIT(29) > > + > > +/* ISP interrupt status */ > > +#define REG_CTL_RAW_INT_STAT 0x0024 > > +#define VS_INT_ST BIT(0) > > +#define TG_ERR_ST BIT(4) > > +#define TG_GBERR_ST BIT(5) > > +#define CQ_CODE_ERR_ST BIT(6) > > +#define CQ_APB_ERR_ST BIT(7) > > +#define CQ_VS_ERR_ST BIT(8) > > +#define HW_PASS1_DON_ST BIT(11) > > +#define SOF_INT_ST BIT(12) > > +#define AMX_ERR_ST BIT(15) > > +#define RMX_ERR_ST BIT(16) > > +#define BMX_ERR_ST BIT(17) > > +#define RRZO_ERR_ST BIT(18) > > +#define AFO_ERR_ST BIT(19) > > +#define IMGO_ERR_ST BIT(20) > > +#define AAO_ERR_ST BIT(21) > > +#define PSO_ERR_ST BIT(22) > > +#define LCSO_ERR_ST BIT(23) > > +#define BNR_ERR_ST BIT(24) > > +#define LSCI_ERR_ST BIT(25) > > +#define DMA_ERR_ST BIT(29) > > +#define SW_PASS1_DON_ST BIT(30) > > + > > +/* ISP interrupt 2 status */ > > +#define REG_CTL_RAW_INT2_STAT 0x0034 > > +#define AFO_DONE_ST BIT(5) > > +#define AAO_DONE_ST BIT(7) > > + > > +/* Configures sensor mode */ > > +#define REG_TG_SEN_MODE 0x0230 > > +#define TG_SEN_MODE_CMOS_EN BIT(0) > > + > > +/* View finder mode control */ > > +#define REG_TG_VF_CON 0x0234 > > +#define TG_VF_CON_VFDATA_EN BIT(0) > > + > > +/* View finder mode control */ > > +#define REG_TG_INTER_ST 0x026c > > +#define TG_CS_MASK 0x3f00 > > +#define TG_IDLE_ST BIT(8) > > + > > +/* IMGO error status register */ > > +#define REG_IMGO_ERR_STAT 0x1360 > > +/* RRZO error status register */ > > +#define REG_RRZO_ERR_STAT 0x1364 > > +/* AAO error status register */ > > +#define REG_AAO_ERR_STAT 0x1368 > > +/* AFO error status register */ > > +#define REG_AFO_ERR_STAT 0x136c > > +/* LCSO error status register */ > > +#define REG_LCSO_ERR_STAT 0x1370 > > +/* BPCI error status register */ > > +#define REG_BPCI_ERR_STAT 0x137c > > +/* LSCI error status register */ > > +#define REG_LSCI_ERR_STAT 0x1384 > > +/* LMVO error status register */ > > +#define REG_LMVO_ERR_STAT 0x1390 > > +/* FLKO error status register */ > > +#define REG_FLKO_ERR_STAT 0x1394 > > +/* PSO error status register */ > > +#define REG_PSO_ERR_STAT 0x13a0 > > + > > +/* CQ0 base address */ > > +#define REG_CQ_THR0_BASEADDR 0x0198 > > +/* Frame sequence number */ > > +#define REG_FRAME_SEQ_NUM 0x13b8 > > + > > +/* IRQ Error Mask */ > > +#define INT_ST_MASK_CAM_ERR ( \ > > + TG_ERR_ST |\ > > + TG_GBERR_ST |\ > > + CQ_CODE_ERR_ST |\ > > + CQ_APB_ERR_ST |\ > > + CQ_VS_ERR_ST |\ > > + BNR_ERR_ST |\ > > + RMX_ERR_ST |\ > > + BMX_ERR_ST |\ > > + BNR_ERR_ST |\ > > + LSCI_ERR_ST |\ > > + DMA_ERR_ST) > > + > > +#endif /* __MTK_CAM_REGS_H__ */ > > diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.c b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.c > > new file mode 100644 > > index 000000000000..23fdb8b4abc5 > > --- /dev/null > > +++ b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.c > > @@ -0,0 +1,2087 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +// Copyright (c) 2019 MediaTek Inc. > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "mtk_cam.h" > > +#include "mtk_cam-hw.h" > > + > > +#define R_IMGO BIT(0) > > +#define R_RRZO BIT(1) > > +#define R_AAO BIT(3) > > +#define R_AFO BIT(4) > > +#define R_LCSO BIT(5) > > +#define R_LMVO BIT(7) > > +#define R_FLKO BIT(8) > > +#define R_PSO BIT(10) > > + > > +#define MTK_ISP_ONE_PIXEL_MODE 1 > > +#define MTK_ISP_MIN_RESIZE_RATIO 6 > > +#define MTK_ISP_MAX_RUNNING_JOBS 3 > > + > > +#define MTK_CAM_CIO_PAD_SRC 4 > > +#define MTK_CAM_CIO_PAD_SINK 11 > > + > > +static inline struct mtk_cam_video_device * > > +file_to_mtk_cam_node(struct file *__file) > > +{ > > + return container_of(video_devdata(__file), > > + struct mtk_cam_video_device, vdev); > > +} > > + > > +static inline struct mtk_cam_video_device * > > +mtk_cam_vbq_to_vdev(struct vb2_queue *__vq) > > +{ > > + return container_of(__vq, struct mtk_cam_video_device, vbq); > > +} > > + > > +static inline struct mtk_cam_dev_request * > > +mtk_cam_req_to_dev_req(struct media_request *__req) > > +{ > > + return container_of(__req, struct mtk_cam_dev_request, req); > > +} > > + > > +static inline struct mtk_cam_dev_buffer * > > +mtk_cam_vb2_buf_to_dev_buf(struct vb2_buffer *__vb) > > +{ > > + return container_of(__vb, struct mtk_cam_dev_buffer, vbb.vb2_buf); > > +} > > + > > +static void mtk_cam_dev_job_done(struct mtk_cam_dev *cam, > > + struct mtk_cam_dev_request *req, > > + enum vb2_buffer_state state) > > +{ > > + struct media_request_object *obj, *obj_prev; > > + unsigned long flags; > > + u64 ts_eof = ktime_get_boottime_ns(); > > + > > + if (!cam->streaming) > > + return; > > + > > + dev_dbg(cam->dev, "job done request:%s frame_seq:%d state:%d\n", > > + req->req.debug_str, req->frame_params.frame_seq_no, state); > > + > > + list_for_each_entry_safe(obj, obj_prev, &req->req.objects, list) { > > + struct vb2_buffer *vb; > > + struct mtk_cam_dev_buffer *buf; > > + struct mtk_cam_video_device *node; > > + > > + if (!vb2_request_object_is_buffer(obj)) > > + continue; > > + vb = container_of(obj, struct vb2_buffer, req_obj); > > + buf = mtk_cam_vb2_buf_to_dev_buf(vb); > > + node = mtk_cam_vbq_to_vdev(vb->vb2_queue); > > + spin_lock_irqsave(&node->buf_list_lock, flags); > > + list_del(&buf->list); > > + spin_unlock_irqrestore(&node->buf_list_lock, flags); > > + buf->vbb.sequence = req->frame_params.frame_seq_no; > > + if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) > > + vb->timestamp = ts_eof; > > + else > > + vb->timestamp = req->timestamp; > > + vb2_buffer_done(&buf->vbb.vb2_buf, state); > > + } > > +} > > + > > +struct mtk_cam_dev_request *mtk_cam_dev_get_req(struct mtk_cam_dev *cam, > > + unsigned int frame_seq_no) > > +{ > > + struct mtk_cam_dev_request *req, *req_prev; > > + unsigned long flags; > > + > > + spin_lock_irqsave(&cam->running_job_lock, flags); > > + list_for_each_entry_safe(req, req_prev, &cam->running_job_list, list) { > > + dev_dbg(cam->dev, "frame_seq:%d, get frame_seq:%d\n", > > + req->frame_params.frame_seq_no, frame_seq_no); > > + > > + /* Match by the en-queued request number */ > > + if (req->frame_params.frame_seq_no == frame_seq_no) { > > + spin_unlock_irqrestore(&cam->running_job_lock, flags); > > + return req; > > + } > > + } > > + spin_unlock_irqrestore(&cam->running_job_lock, flags); > > + > > + return NULL; > > +} > > + > > +void mtk_cam_dev_dequeue_req_frame(struct mtk_cam_dev *cam, > > + unsigned int frame_seq_no) > > +{ > > + struct mtk_cam_dev_request *req, *req_prev; > > + unsigned long flags; > > + > > + spin_lock_irqsave(&cam->running_job_lock, flags); > > + list_for_each_entry_safe(req, req_prev, &cam->running_job_list, list) { > > + dev_dbg(cam->dev, "frame_seq:%d, de-queue frame_seq:%d\n", > > + req->frame_params.frame_seq_no, frame_seq_no); > > + > > + /* Match by the en-queued request number */ > > + if (req->frame_params.frame_seq_no == frame_seq_no) { > > + cam->running_job_count--; > > + /* Pass to user space */ > > + mtk_cam_dev_job_done(cam, req, VB2_BUF_STATE_DONE); > > + list_del(&req->list); > > + break; > > + } else if (req->frame_params.frame_seq_no < frame_seq_no) { > > + cam->running_job_count--; > > + /* Pass to user space for frame drop */ > > + mtk_cam_dev_job_done(cam, req, VB2_BUF_STATE_ERROR); > Hi, I see that frame_params.frame_seq_no is incremented when a request is queued > and frame_seq_no is read from a register, so if the first is lower than the latter > it means userspace was queueing request too slowly and missed frames right? > So userspace will have to catch up in order not to get "ERROR" buffers. > Maybe the driver can just skip lost frames. In the rkisp1 for example, > if there is no buffer available, the driver just write to a dummy buffer that is > never sent to userspace. This way userspace always get valid buffers back when > dequeueing. > Q1. We will update frame_params.frame_seq_no into HW per frame. So the frame_seq_no is read from HW register should not be large than frame_params.frame_seq_no. If userspace was queueing request too slowly, ISP HW just skip frame output due to no available buffers. Q2. For this code block, it handles the heavy system loading. e.g abnormal ISR execution. In this scenario, ISP HW will keep output frame buffers and update frame_seq_no into HW. So ISP P1 driver miss some interrupt timing and just got the latest frame_seq_no from HW. With this check, we will return all frame buffers which have be proceed by HW. Otherwise, userspace may not en-queue any frame buffers due to some frame buffers are not returned from kernel driver. > > + dev_warn(cam->dev, "frame_seq:%d drop\n", > > + req->frame_params.frame_seq_no); > > + list_del(&req->list); > > + } else { > > + break; > Does this case can ever occur? > > Thanks, > Dafna > To be honest, it never happened. I will remove this. Best regards, Jungo > > + } > > + } > > + spin_unlock_irqrestore(&cam->running_job_lock, flags); > > +} > > + > > +static void mtk_cam_dev_req_cleanup(struct mtk_cam_dev *cam) > > +{ > > + struct mtk_cam_dev_request *req, *req_prev; > > + unsigned long flags; > > + > > + dev_dbg(cam->dev, "%s\n", __func__); > > + > > + spin_lock_irqsave(&cam->pending_job_lock, flags); > > + list_for_each_entry_safe(req, req_prev, &cam->pending_job_list, list) > > + list_del(&req->list); > > + spin_unlock_irqrestore(&cam->pending_job_lock, flags); > > + > > + spin_lock_irqsave(&cam->running_job_lock, flags); > > + list_for_each_entry_safe(req, req_prev, &cam->running_job_list, list) > > + list_del(&req->list); > > + spin_unlock_irqrestore(&cam->running_job_lock, flags); > > +} > > + > > +void mtk_cam_dev_req_try_queue(struct mtk_cam_dev *cam) > > +{ > > + struct mtk_cam_dev_request *req, *req_prev; > > + unsigned long flags; > > + > > + if (!cam->streaming) { > > + dev_dbg(cam->dev, "stream is off\n"); > > + return; > > + } > > + > > + spin_lock_irqsave(&cam->pending_job_lock, flags); > > + spin_lock_irqsave(&cam->running_job_lock, flags); > > + list_for_each_entry_safe(req, req_prev, &cam->pending_job_list, list) { > > + if (cam->running_job_count >= MTK_ISP_MAX_RUNNING_JOBS) { > > + dev_dbg(cam->dev, "jobs are full\n"); > > + break; > > + } > > + cam->running_job_count++; > > + list_del(&req->list); > > + list_add_tail(&req->list, &cam->running_job_list); > > + mtk_isp_req_enqueue(cam, req); > > + } > > + spin_unlock_irqrestore(&cam->running_job_lock, flags); > > + spin_unlock_irqrestore(&cam->pending_job_lock, flags); > > +} > > + > > +static struct media_request *mtk_cam_req_alloc(struct media_device *mdev) > > +{ > > + struct mtk_cam_dev_request *cam_dev_req; > > + > > + cam_dev_req = kzalloc(sizeof(*cam_dev_req), GFP_KERNEL); > > + > > + return &cam_dev_req->req; > > +} > > + > > +static void mtk_cam_req_free(struct media_request *req) > > +{ > > + struct mtk_cam_dev_request *cam_dev_req = mtk_cam_req_to_dev_req(req); > > + > > + kfree(cam_dev_req); > > +} > > + > > +static void mtk_cam_req_queue(struct media_request *req) > > +{ > > + struct mtk_cam_dev_request *cam_req = mtk_cam_req_to_dev_req(req); > > + struct mtk_cam_dev *cam = container_of(req->mdev, struct mtk_cam_dev, > > + media_dev); > > + unsigned long flags; > > + > > + /* update frame_params's dma_bufs in mtk_cam_vb2_buf_queue */ > > + vb2_request_queue(req); > > + > > + /* add to pending job list */ > > + spin_lock_irqsave(&cam->pending_job_lock, flags); > > + list_add_tail(&cam_req->list, &cam->pending_job_list); > > + spin_unlock_irqrestore(&cam->pending_job_lock, flags); > > + > > + mtk_cam_dev_req_try_queue(cam); > > +} > > + > > +static unsigned int get_pixel_bits(unsigned int pix_fmt) > > +{ > > + switch (pix_fmt) { > > + case V4L2_PIX_FMT_MTISP_SBGGR8: > > + case V4L2_PIX_FMT_MTISP_SGBRG8: > > + case V4L2_PIX_FMT_MTISP_SGRBG8: > > + case V4L2_PIX_FMT_MTISP_SRGGB8: > > + case V4L2_PIX_FMT_MTISP_SBGGR8F: > > + case V4L2_PIX_FMT_MTISP_SGBRG8F: > > + case V4L2_PIX_FMT_MTISP_SGRBG8F: > > + case V4L2_PIX_FMT_MTISP_SRGGB8F: > > + return 8; > > + case V4L2_PIX_FMT_MTISP_SBGGR10: > > + case V4L2_PIX_FMT_MTISP_SGBRG10: > > + case V4L2_PIX_FMT_MTISP_SGRBG10: > > + case V4L2_PIX_FMT_MTISP_SRGGB10: > > + case V4L2_PIX_FMT_MTISP_SBGGR10F: > > + case V4L2_PIX_FMT_MTISP_SGBRG10F: > > + case V4L2_PIX_FMT_MTISP_SGRBG10F: > > + case V4L2_PIX_FMT_MTISP_SRGGB10F: > > + return 10; > > + case V4L2_PIX_FMT_MTISP_SBGGR12: > > + case V4L2_PIX_FMT_MTISP_SGBRG12: > > + case V4L2_PIX_FMT_MTISP_SGRBG12: > > + case V4L2_PIX_FMT_MTISP_SRGGB12: > > + case V4L2_PIX_FMT_MTISP_SBGGR12F: > > + case V4L2_PIX_FMT_MTISP_SGBRG12F: > > + case V4L2_PIX_FMT_MTISP_SGRBG12F: > > + case V4L2_PIX_FMT_MTISP_SRGGB12F: > > + return 12; > > + case V4L2_PIX_FMT_MTISP_SBGGR14: > > + case V4L2_PIX_FMT_MTISP_SGBRG14: > > + case V4L2_PIX_FMT_MTISP_SGRBG14: > > + case V4L2_PIX_FMT_MTISP_SRGGB14: > > + case V4L2_PIX_FMT_MTISP_SBGGR14F: > > + case V4L2_PIX_FMT_MTISP_SGBRG14F: > > + case V4L2_PIX_FMT_MTISP_SGRBG14F: > > + case V4L2_PIX_FMT_MTISP_SRGGB14F: > > + return 14; > > + default: > > + return 0; > > + } > > +} > > + > > +static void cal_image_pix_mp(struct mtk_cam_dev *cam, unsigned int node_id, > > + struct v4l2_pix_format_mplane *mp) > > +{ > > + unsigned int bpl, ppl; > > + unsigned int pixel_bits = get_pixel_bits(mp->pixelformat); > > + unsigned int width = mp->width; > > + > > + bpl = 0; > > + if (node_id == MTK_CAM_P1_MAIN_STREAM_OUT) { > > + /* Bayer encoding format & 2 bytes alignment */ > > + bpl = ALIGN(DIV_ROUND_UP(width * pixel_bits, 8), 2); > > + } else if (node_id == MTK_CAM_P1_PACKED_BIN_OUT) { > > + /* > > + * The FULL-G encoding format > > + * 1 G component per pixel > > + * 1 R component per 4 pixel > > + * 1 B component per 4 pixel > > + * Total 4G/1R/1B in 4 pixel (pixel per line:ppl) > > + */ > > + ppl = DIV_ROUND_UP(width * 6, 4); > > + bpl = DIV_ROUND_UP(ppl * pixel_bits, 8); > > + > > + /* 4 bytes alignment for 10 bit & others are 8 bytes */ > > + if (pixel_bits == 10) > > + bpl = ALIGN(bpl, 4); > > + else > > + bpl = ALIGN(bpl, 8); > > + } > > + /* > > + * This image output buffer will be input buffer of MTK CAM DIP HW > > + * For MTK CAM DIP HW constrained, it needs 4 bytes alignment > > + */ > > + bpl = ALIGN(bpl, 4); > > + > > + mp->plane_fmt[0].bytesperline = bpl; > > + mp->plane_fmt[0].sizeimage = bpl * mp->height; > > + > > + dev_dbg(cam->dev, "node:%d width:%d bytesperline:%d sizeimage:%d\n", > > + node_id, width, bpl, mp->plane_fmt[0].sizeimage); > > +} > > + > > +static const struct v4l2_format * > > +mtk_cam_dev_find_fmt(struct mtk_cam_dev_node_desc *desc, u32 format) > > +{ > > + int i; > > + const struct v4l2_format *dev_fmt; > > + > > + for (i = 0; i < desc->num_fmts; i++) { > > + dev_fmt = &desc->fmts[i]; > > + if (dev_fmt->fmt.pix_mp.pixelformat == format) > > + return dev_fmt; > > + } > > + > > + return NULL; > > +} > > + > > +/* Get the default format setting */ > > +static void > > +mtk_cam_dev_load_default_fmt(struct mtk_cam_dev *cam, > > + struct mtk_cam_dev_node_desc *queue_desc, > > + struct v4l2_format *dest) > > +{ > > + const struct v4l2_format *default_fmt = > > + &queue_desc->fmts[queue_desc->default_fmt_idx]; > > + > > + dest->type = queue_desc->buf_type; > > + > > + /* Configure default format based on node type */ > > + if (!queue_desc->image) { > > + dest->fmt.meta.dataformat = default_fmt->fmt.meta.dataformat; > > + dest->fmt.meta.buffersize = default_fmt->fmt.meta.buffersize; > > + return; > > + } > > + > > + dest->fmt.pix_mp.pixelformat = default_fmt->fmt.pix_mp.pixelformat; > > + dest->fmt.pix_mp.width = default_fmt->fmt.pix_mp.width; > > + dest->fmt.pix_mp.height = default_fmt->fmt.pix_mp.height; > > + /* bytesperline & sizeimage calculation */ > > + cal_image_pix_mp(cam, queue_desc->id, &dest->fmt.pix_mp); > > + dest->fmt.pix_mp.num_planes = 1; > > + > > + dest->fmt.pix_mp.colorspace = V4L2_COLORSPACE_SRGB; > > + dest->fmt.pix_mp.field = V4L2_FIELD_NONE; > > + dest->fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; > > + dest->fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; > > + dest->fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_SRGB; > > +} > > + > > +/* Utility functions */ > > +static unsigned int get_sensor_pixel_id(unsigned int fmt) > > +{ > > + switch (fmt) { > > + case MEDIA_BUS_FMT_SBGGR8_1X8: > > + case MEDIA_BUS_FMT_SBGGR10_1X10: > > + case MEDIA_BUS_FMT_SBGGR12_1X12: > > + case MEDIA_BUS_FMT_SBGGR14_1X14: > > + return MTK_CAM_RAW_PXL_ID_B; > > + case MEDIA_BUS_FMT_SGBRG8_1X8: > > + case MEDIA_BUS_FMT_SGBRG10_1X10: > > + case MEDIA_BUS_FMT_SGBRG12_1X12: > > + case MEDIA_BUS_FMT_SGBRG14_1X14: > > + return MTK_CAM_RAW_PXL_ID_GB; > > + case MEDIA_BUS_FMT_SGRBG8_1X8: > > + case MEDIA_BUS_FMT_SGRBG10_1X10: > > + case MEDIA_BUS_FMT_SGRBG12_1X12: > > + case MEDIA_BUS_FMT_SGRBG14_1X14: > > + return MTK_CAM_RAW_PXL_ID_GR; > > + case MEDIA_BUS_FMT_SRGGB8_1X8: > > + case MEDIA_BUS_FMT_SRGGB10_1X10: > > + case MEDIA_BUS_FMT_SRGGB12_1X12: > > + case MEDIA_BUS_FMT_SRGGB14_1X14: > > + return MTK_CAM_RAW_PXL_ID_R; > > + default: > > + return MTK_CAM_RAW_PXL_ID_UNKNOWN; > > + } > > +} > > + > > +static unsigned int get_sensor_fmt(unsigned int fmt) > > +{ > > + switch (fmt) { > > + case MEDIA_BUS_FMT_SBGGR8_1X8: > > + case MEDIA_BUS_FMT_SGBRG8_1X8: > > + case MEDIA_BUS_FMT_SGRBG8_1X8: > > + case MEDIA_BUS_FMT_SRGGB8_1X8: > > + return MTK_CAM_IMG_FMT_BAYER8; > > + case MEDIA_BUS_FMT_SBGGR10_1X10: > > + case MEDIA_BUS_FMT_SGBRG10_1X10: > > + case MEDIA_BUS_FMT_SGRBG10_1X10: > > + case MEDIA_BUS_FMT_SRGGB10_1X10: > > + return MTK_CAM_IMG_FMT_BAYER10; > > + case MEDIA_BUS_FMT_SBGGR12_1X12: > > + case MEDIA_BUS_FMT_SGBRG12_1X12: > > + case MEDIA_BUS_FMT_SGRBG12_1X12: > > + case MEDIA_BUS_FMT_SRGGB12_1X12: > > + return MTK_CAM_IMG_FMT_BAYER12; > > + case MEDIA_BUS_FMT_SBGGR14_1X14: > > + case MEDIA_BUS_FMT_SGBRG14_1X14: > > + case MEDIA_BUS_FMT_SGRBG14_1X14: > > + case MEDIA_BUS_FMT_SRGGB14_1X14: > > + return MTK_CAM_IMG_FMT_BAYER14; > > + default: > > + return MTK_CAM_IMG_FMT_UNKNOWN; > > + } > > +} > > + > > +static unsigned int get_img_fmt(unsigned int fourcc) > > +{ > > + switch (fourcc) { > > + case V4L2_PIX_FMT_MTISP_SBGGR8: > > + case V4L2_PIX_FMT_MTISP_SGBRG8: > > + case V4L2_PIX_FMT_MTISP_SGRBG8: > > + case V4L2_PIX_FMT_MTISP_SRGGB8: > > + return MTK_CAM_IMG_FMT_BAYER8; > > + case V4L2_PIX_FMT_MTISP_SBGGR8F: > > + case V4L2_PIX_FMT_MTISP_SGBRG8F: > > + case V4L2_PIX_FMT_MTISP_SGRBG8F: > > + case V4L2_PIX_FMT_MTISP_SRGGB8F: > > + return MTK_CAM_IMG_FMT_FG_BAYER8; > > + case V4L2_PIX_FMT_MTISP_SBGGR10: > > + case V4L2_PIX_FMT_MTISP_SGBRG10: > > + case V4L2_PIX_FMT_MTISP_SGRBG10: > > + case V4L2_PIX_FMT_MTISP_SRGGB10: > > + return MTK_CAM_IMG_FMT_BAYER10; > > + case V4L2_PIX_FMT_MTISP_SBGGR10F: > > + case V4L2_PIX_FMT_MTISP_SGBRG10F: > > + case V4L2_PIX_FMT_MTISP_SGRBG10F: > > + case V4L2_PIX_FMT_MTISP_SRGGB10F: > > + return MTK_CAM_IMG_FMT_FG_BAYER10; > > + case V4L2_PIX_FMT_MTISP_SBGGR12: > > + case V4L2_PIX_FMT_MTISP_SGBRG12: > > + case V4L2_PIX_FMT_MTISP_SGRBG12: > > + case V4L2_PIX_FMT_MTISP_SRGGB12: > > + return MTK_CAM_IMG_FMT_BAYER12; > > + case V4L2_PIX_FMT_MTISP_SBGGR12F: > > + case V4L2_PIX_FMT_MTISP_SGBRG12F: > > + case V4L2_PIX_FMT_MTISP_SGRBG12F: > > + case V4L2_PIX_FMT_MTISP_SRGGB12F: > > + return MTK_CAM_IMG_FMT_FG_BAYER12; > > + case V4L2_PIX_FMT_MTISP_SBGGR14: > > + case V4L2_PIX_FMT_MTISP_SGBRG14: > > + case V4L2_PIX_FMT_MTISP_SGRBG14: > > + case V4L2_PIX_FMT_MTISP_SRGGB14: > > + return MTK_CAM_IMG_FMT_BAYER14; > > + case V4L2_PIX_FMT_MTISP_SBGGR14F: > > + case V4L2_PIX_FMT_MTISP_SGBRG14F: > > + case V4L2_PIX_FMT_MTISP_SGRBG14F: > > + case V4L2_PIX_FMT_MTISP_SRGGB14F: > > + return MTK_CAM_IMG_FMT_FG_BAYER14; > > + default: > > + return MTK_CAM_IMG_FMT_UNKNOWN; > > + } > > +} > > + > > +static int config_img_fmt(struct mtk_cam_dev *cam, unsigned int node_id, > > + struct p1_img_output *out_fmt, int sd_width, > > + int sd_height) > > +{ > > + const struct v4l2_format *cfg_fmt = &cam->vdev_nodes[node_id].vdev_fmt; > > + > > + /* Check output & input image size dimension */ > > + if (cfg_fmt->fmt.pix_mp.width > sd_width || > > + cfg_fmt->fmt.pix_mp.height > sd_height) { > > + dev_err(cam->dev, "node:%d cfg size is larger than sensor\n", > > + node_id); > > + return -EINVAL; > > + } > > + > > + /* Check resize ratio for resize out stream due to HW constraint */ > > + if (((cfg_fmt->fmt.pix_mp.width * 100 / sd_width) < > > + MTK_ISP_MIN_RESIZE_RATIO) || > > + ((cfg_fmt->fmt.pix_mp.height * 100 / sd_height) < > > + MTK_ISP_MIN_RESIZE_RATIO)) { > > + dev_err(cam->dev, "node:%d resize ratio is less than %d%%\n", > > + node_id, MTK_ISP_MIN_RESIZE_RATIO); > > + return -EINVAL; > > + } > > + > > + out_fmt->img_fmt = get_img_fmt(cfg_fmt->fmt.pix_mp.pixelformat); > > + out_fmt->pixel_bits = get_pixel_bits(cfg_fmt->fmt.pix_mp.pixelformat); > > + if (out_fmt->img_fmt == MTK_CAM_IMG_FMT_UNKNOWN || > > + !out_fmt->pixel_bits) { > > + dev_err(cam->dev, "node:%d unknown pixel fmt:%d\n", > > + node_id, cfg_fmt->fmt.pix_mp.pixelformat); > > + return -EINVAL; > > + } > > + dev_dbg(cam->dev, "node:%d pixel_bits:%d img_fmt:0x%x\n", > > + node_id, out_fmt->pixel_bits, out_fmt->img_fmt); > > + > > + out_fmt->size.w = cfg_fmt->fmt.pix_mp.width; > > + out_fmt->size.h = cfg_fmt->fmt.pix_mp.height; > > + out_fmt->size.stride = cfg_fmt->fmt.pix_mp.plane_fmt[0].bytesperline; > > + out_fmt->size.xsize = cfg_fmt->fmt.pix_mp.plane_fmt[0].bytesperline; > > + > > + out_fmt->crop.left = 0; > > + out_fmt->crop.top = 0; > > + out_fmt->crop.width = sd_width; > > + out_fmt->crop.height = sd_height; > > + > > + dev_dbg(cam->dev, > > + "node:%d size=%0dx%0d, stride:%d, xsize:%d, crop=%0dx%0d\n", > > + node_id, out_fmt->size.w, out_fmt->size.h, > > + out_fmt->size.stride, out_fmt->size.xsize, > > + out_fmt->crop.width, out_fmt->crop.height); > > + > > + return 0; > > +} > > + > > +static void mtk_cam_dev_init_stream(struct mtk_cam_dev *cam) > > +{ > > + int i; > > + > > + cam->enabled_count = 0; > > + cam->enabled_dmas = 0; > > + cam->stream_count = 0; > > + cam->running_job_count = 0; > > + > > + /* Get the enabled meta DMA ports */ > > + for (i = 0; i < MTK_CAM_P1_TOTAL_NODES; i++) { > > + if (!cam->vdev_nodes[i].enabled) > > + continue; > > + cam->enabled_count++; > > + cam->enabled_dmas |= cam->vdev_nodes[i].desc.dma_port; > > + } > > + > > + dev_dbg(cam->dev, "%s:%d:0x%x\n", __func__, cam->enabled_count, > > + cam->enabled_dmas); > > +} > > + > > +static int mtk_cam_dev_isp_config(struct mtk_cam_dev *cam) > > +{ > > + struct device *dev = cam->dev; > > + struct p1_config_param config_param; > > + struct cfg_in_param *cfg_in_param; > > + struct v4l2_subdev_format sd_fmt; > > + int sd_width, sd_height, sd_code; > > + unsigned int enabled_dma_ports = cam->enabled_dmas; > > + int ret; > > + > > + /* Get sensor format configuration */ > > + sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; > > + ret = v4l2_subdev_call(cam->sensor, pad, get_fmt, NULL, &sd_fmt); > > + if (ret) { > > + dev_dbg(dev, "sensor g_fmt failed:%d\n", ret); > > + return ret; > > + } > > + sd_width = sd_fmt.format.width; > > + sd_height = sd_fmt.format.height; > > + sd_code = sd_fmt.format.code; > > + dev_dbg(dev, "sd fmt w*h=%d*%d, code=0x%x\n", sd_width, sd_height, > > + sd_code); > > + > > + memset(&config_param, 0, sizeof(config_param)); > > + > > + /* Update cfg_in_param */ > > + cfg_in_param = &config_param.cfg_in_param; > > + cfg_in_param->continuous = true; > > + /* Fix to one pixel mode in default */ > > + cfg_in_param->pixel_mode = MTK_ISP_ONE_PIXEL_MODE; > > + cfg_in_param->crop.width = sd_width; > > + cfg_in_param->crop.height = sd_height; > > + cfg_in_param->raw_pixel_id = get_sensor_pixel_id(sd_code); > > + cfg_in_param->img_fmt = get_sensor_fmt(sd_code); > > + if (cfg_in_param->img_fmt == MTK_CAM_IMG_FMT_UNKNOWN || > > + cfg_in_param->raw_pixel_id == MTK_CAM_RAW_PXL_ID_UNKNOWN) { > > + dev_err(dev, "unknown sd code:%d\n", sd_code); > > + return -EINVAL; > > + } > > + > > + /* Update cfg_main_param */ > > + config_param.cfg_main_param.pure_raw = true; > > + config_param.cfg_main_param.pure_raw_pack = true; > > + ret = config_img_fmt(cam, MTK_CAM_P1_MAIN_STREAM_OUT, > > + &config_param.cfg_main_param.output, > > + sd_width, sd_height); > > + if (ret) > > + return ret; > > + > > + /* Update cfg_resize_param */ > > + if (enabled_dma_ports & R_RRZO) { > > + ret = config_img_fmt(cam, MTK_CAM_P1_PACKED_BIN_OUT, > > + &config_param.cfg_resize_param.output, > > + sd_width, sd_height); > > + if (ret) > > + return ret; > > + } else { > > + config_param.cfg_resize_param.bypass = true; > > + } > > + > > + /* Update enabled_dmas */ > > + config_param.enabled_dmas = enabled_dma_ports; > > + mtk_isp_hw_config(cam, &config_param); > > + dev_dbg(dev, "%s done\n", __func__); > > + > > + return 0; > > +} > > + > > +void mtk_cam_dev_event_frame_sync(struct mtk_cam_dev *cam, > > + unsigned int frame_seq_no) > > +{ > > + struct v4l2_event event = { > > + .type = V4L2_EVENT_FRAME_SYNC, > > + .u.frame_sync.frame_sequence = frame_seq_no, > > + }; > > + > > + v4l2_event_queue(cam->subdev.devnode, &event); > > +} > > + > > +static struct v4l2_subdev * > > +mtk_cam_cio_get_active_sensor(struct mtk_cam_dev *cam) > > +{ > > + struct media_device *mdev = cam->seninf->entity.graph_obj.mdev; > > + struct device *dev = cam->dev; > > + struct media_entity *entity; > > + struct v4l2_subdev *sensor; > > + > > + sensor = NULL; > > + media_device_for_each_entity(entity, mdev) { > > + dev_dbg(dev, "media entity: %s:0x%x:%d\n", > > + entity->name, entity->function, entity->stream_count); > > + if (entity->function == MEDIA_ENT_F_CAM_SENSOR && > > + entity->stream_count) { > > + sensor = media_entity_to_v4l2_subdev(entity); > > + dev_dbg(dev, "sensor found: %s\n", entity->name); > > + break; > > + } > > + } > > + > > + if (!sensor) > > + dev_err(dev, "no seninf connected\n"); > > + > > + return sensor; > > +} > > + > > +static int mtk_cam_cio_stream_on(struct mtk_cam_dev *cam) > > +{ > > + struct device *dev = cam->dev; > > + int ret; > > + > > + if (!cam->seninf) { > > + dev_err(dev, "no seninf connected\n"); > > + return -ENODEV; > > + } > > + > > + /* Get active sensor from graph topology */ > > + cam->sensor = mtk_cam_cio_get_active_sensor(cam); > > + if (!cam->sensor) > > + return -ENODEV; > > + > > + /* Seninf must stream on first */ > > + ret = v4l2_subdev_call(cam->seninf, video, s_stream, 1); > > + if (ret) { > > + dev_err(dev, "failed to stream on %s:%d\n", > > + cam->seninf->entity.name, ret); > > + return ret; > > + } > > + > > + ret = v4l2_subdev_call(cam->sensor, video, s_stream, 1); > > + if (ret) { > > + dev_err(dev, "failed to stream on %s:%d\n", > > + cam->sensor->entity.name, ret); > > + goto fail_seninf_off; > > + } > > + > > + ret = mtk_cam_dev_isp_config(cam); > > + if (ret) > > + goto fail_sensor_off; > > + > > + cam->streaming = true; > > + mtk_isp_stream(cam, 1); > > + mtk_cam_dev_req_try_queue(cam); > > + dev_dbg(dev, "streamed on Pass 1\n"); > > + > > + return 0; > > + > > +fail_sensor_off: > > + v4l2_subdev_call(cam->sensor, video, s_stream, 0); > > +fail_seninf_off: > > + v4l2_subdev_call(cam->seninf, video, s_stream, 0); > > + > > + return ret; > > +} > > + > > +static int mtk_cam_cio_stream_off(struct mtk_cam_dev *cam) > > +{ > > + struct device *dev = cam->dev; > > + int ret; > > + > > + ret = v4l2_subdev_call(cam->sensor, video, s_stream, 0); > > + if (ret) { > > + dev_err(dev, "failed to stream off %s:%d\n", > > + cam->sensor->entity.name, ret); > > + return -EPERM; > > + } > > + > > + ret = v4l2_subdev_call(cam->seninf, video, s_stream, 0); > > + if (ret) { > > + dev_err(dev, "failed to stream off %s:%d\n", > > + cam->seninf->entity.name, ret); > > + return -EPERM; > > + } > > + > > + cam->streaming = false; > > + mtk_isp_stream(cam, 0); > > + mtk_isp_hw_release(cam); > > + > > + dev_dbg(dev, "streamed off Pass 1\n"); > > + > > + return 0; > > +} > > + > > +static int mtk_cam_sd_s_stream(struct v4l2_subdev *sd, int enable) > > +{ > > + struct mtk_cam_dev *cam = container_of(sd, struct mtk_cam_dev, subdev); > > + > > + if (enable) { > > + /* Align vb2_core_streamon design */ > > + if (cam->streaming) { > > + dev_warn(cam->dev, "already streaming on\n"); > > + return 0; > > + } > > + return mtk_cam_cio_stream_on(cam); > > + } > > + > > + if (!cam->streaming) { > > + dev_warn(cam->dev, "already streaming off\n"); > > + return 0; > > + } > > + return mtk_cam_cio_stream_off(cam); > > +} > > + > > +static int mtk_cam_sd_subscribe_event(struct v4l2_subdev *subdev, > > + struct v4l2_fh *fh, > > + struct v4l2_event_subscription *sub) > > +{ > > + switch (sub->type) { > > + case V4L2_EVENT_FRAME_SYNC: > > + return v4l2_event_subscribe(fh, sub, 0, NULL); > > + default: > > + return -EINVAL; > > + } > > +} > > + > > +static int mtk_cam_media_link_setup(struct media_entity *entity, > > + const struct media_pad *local, > > + const struct media_pad *remote, u32 flags) > > +{ > > + struct mtk_cam_dev *cam = > > + container_of(entity, struct mtk_cam_dev, subdev.entity); > > + u32 pad = local->index; > > + > > + dev_dbg(cam->dev, "%s: %d->%d flags:0x%x\n", > > + __func__, pad, remote->index, flags); > > + > > + /* > > + * The video nodes exposed by the driver have pads indexes > > + * from 0 to MTK_CAM_P1_TOTAL_NODES - 1. > > + */ > > + if (pad < MTK_CAM_P1_TOTAL_NODES) > > + cam->vdev_nodes[pad].enabled = > > + !!(flags & MEDIA_LNK_FL_ENABLED); > > + > > + return 0; > > +} > > + > > +static void mtk_cam_vb2_buf_queue(struct vb2_buffer *vb) > > +{ > > + struct mtk_cam_dev *cam = vb2_get_drv_priv(vb->vb2_queue); > > + struct mtk_cam_dev_buffer *buf = mtk_cam_vb2_buf_to_dev_buf(vb); > > + struct mtk_cam_dev_request *req = mtk_cam_req_to_dev_req(vb->request); > > + struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vb->vb2_queue); > > + struct device *dev = cam->dev; > > + unsigned long flags; > > + > > + dev_dbg(dev, "%s: node:%d fd:%d idx:%d\n", __func__, > > + node->id, buf->vbb.request_fd, buf->vbb.vb2_buf.index); > > + > > + /* added the buffer into the tracking list */ > > + spin_lock_irqsave(&node->buf_list_lock, flags); > > + list_add_tail(&buf->list, &node->buf_list); > > + spin_unlock_irqrestore(&node->buf_list_lock, flags); > > + > > + /* update buffer internal address */ > > + req->frame_params.dma_bufs[buf->node_id].iova = buf->daddr; > > + req->frame_params.dma_bufs[buf->node_id].scp_addr = buf->scp_addr; > > +} > > + > > +static int mtk_cam_vb2_buf_init(struct vb2_buffer *vb) > > +{ > > + struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vb->vb2_queue); > > + struct mtk_cam_dev *cam = vb2_get_drv_priv(vb->vb2_queue); > > + struct device *dev = cam->dev; > > + struct mtk_cam_dev_buffer *buf; > > + dma_addr_t addr; > > + > > + buf = mtk_cam_vb2_buf_to_dev_buf(vb); > > + buf->node_id = node->id; > > + buf->daddr = vb2_dma_contig_plane_dma_addr(vb, 0); > > + buf->scp_addr = 0; > > + > > + /* SCP address is only valid for meta input buffer */ > > + if (!node->desc.smem_alloc) > > + return 0; > > + > > + buf = mtk_cam_vb2_buf_to_dev_buf(vb); > > + /* Use coherent address to get iova address */ > > + addr = dma_map_resource(dev, buf->daddr, vb->planes[0].length, > > + DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC); > > + if (dma_mapping_error(dev, addr)) { > > + dev_err(dev, "failed to map meta addr:%pad\n", &buf->daddr); > > + return -EFAULT; > > + } > > + buf->scp_addr = buf->daddr; > > + buf->daddr = addr; > > + > > + return 0; > > +} > > + > > +static int mtk_cam_vb2_buf_prepare(struct vb2_buffer *vb) > > +{ > > + struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vb->vb2_queue); > > + struct mtk_cam_dev *cam = vb2_get_drv_priv(vb->vb2_queue); > > + struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb); > > + const struct v4l2_format *fmt = &node->vdev_fmt; > > + unsigned int size; > > + > > + if (vb->vb2_queue->type == V4L2_BUF_TYPE_META_OUTPUT || > > + vb->vb2_queue->type == V4L2_BUF_TYPE_META_CAPTURE) > > + size = fmt->fmt.meta.buffersize; > > + else > > + size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; > > + > > + if (vb2_plane_size(vb, 0) < size) { > > + dev_dbg(cam->dev, "plane size is too small:%lu<%u\n", > > + vb2_plane_size(vb, 0), size); > > + return -EINVAL; > > + } > > + > > + if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) { > > + if (vb2_get_plane_payload(vb, 0) != size) { > > + dev_dbg(cam->dev, "plane payload is mismatch:%lu:%u\n", > > + vb2_get_plane_payload(vb, 0), size); > > + return -EINVAL; > > + } > > + return 0; > > + } > > + > > + v4l2_buf->field = V4L2_FIELD_NONE; > > + vb2_set_plane_payload(vb, 0, size); > > + > > + return 0; > > +} > > + > > +static void mtk_cam_vb2_buf_cleanup(struct vb2_buffer *vb) > > +{ > > + struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vb->vb2_queue); > > + struct mtk_cam_dev *cam = vb2_get_drv_priv(vb->vb2_queue); > > + struct mtk_cam_dev_buffer *buf; > > + struct device *dev = cam->dev; > > + > > + if (!node->desc.smem_alloc) > > + return; > > + > > + buf = mtk_cam_vb2_buf_to_dev_buf(vb); > > + dma_unmap_page_attrs(dev, buf->daddr, > > + vb->planes[0].length, > > + DMA_BIDIRECTIONAL, > > + DMA_ATTR_SKIP_CPU_SYNC); > > +} > > + > > +static void mtk_cam_vb2_request_complete(struct vb2_buffer *vb) > > +{ > > + struct mtk_cam_dev *cam = vb2_get_drv_priv(vb->vb2_queue); > > + > > + dev_dbg(cam->dev, "%s\n", __func__); > > +} > > + > > +static int mtk_cam_vb2_queue_setup(struct vb2_queue *vq, > > + unsigned int *num_buffers, > > + unsigned int *num_planes, > > + unsigned int sizes[], > > + struct device *alloc_devs[]) > > +{ > > + struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vq); > > + unsigned int max_buffer_count = node->desc.max_buf_count; > > + const struct v4l2_format *fmt = &node->vdev_fmt; > > + unsigned int size; > > + > > + /* Check the limitation of buffer size */ > > + if (max_buffer_count) > > + *num_buffers = clamp_val(*num_buffers, 1, max_buffer_count); > > + > > + if (node->desc.smem_alloc) > > + vq->dma_attrs |= DMA_ATTR_NO_KERNEL_MAPPING; > > + > > + if (vq->type == V4L2_BUF_TYPE_META_OUTPUT || > > + vq->type == V4L2_BUF_TYPE_META_CAPTURE) > > + size = fmt->fmt.meta.buffersize; > > + else > > + size = fmt->fmt.pix_mp.plane_fmt[0].sizeimage; > > + > > + /* Add for q.create_bufs with fmt.g_sizeimage(p) / 2 test */ > > + if (*num_planes) { > > + if (sizes[0] < size || *num_planes != 1) > > + return -EINVAL; > > + } else { > > + *num_planes = 1; > > + sizes[0] = size; > > + } > > + > > + return 0; > > +} > > + > > +static void mtk_cam_vb2_return_all_buffers(struct mtk_cam_dev *cam, > > + struct mtk_cam_video_device *node, > > + enum vb2_buffer_state state) > > +{ > > + struct mtk_cam_dev_buffer *buf, *buf_prev; > > + unsigned long flags; > > + > > + spin_lock_irqsave(&node->buf_list_lock, flags); > > + list_for_each_entry_safe(buf, buf_prev, &node->buf_list, list) { > > + list_del(&buf->list); > > + vb2_buffer_done(&buf->vbb.vb2_buf, state); > > + } > > + spin_unlock_irqrestore(&node->buf_list_lock, flags); > > +} > > + > > +static int mtk_cam_vb2_start_streaming(struct vb2_queue *vq, > > + unsigned int count) > > +{ > > + struct mtk_cam_dev *cam = vb2_get_drv_priv(vq); > > + struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vq); > > + struct device *dev = cam->dev; > > + int ret; > > + > > + if (!node->enabled) { > > + dev_err(dev, "Node:%d is not enabled\n", node->id); > > + ret = -ENOLINK; > > + goto fail_ret_buf; > > + } > > + > > + mutex_lock(&cam->op_lock); > > + /* Start streaming of the whole pipeline now*/ > > + if (!cam->pipeline.streaming_count) { > > + ret = media_pipeline_start(&node->vdev.entity, &cam->pipeline); > > + if (ret) { > > + dev_err(dev, "failed to start pipeline:%d\n", ret); > > + goto fail_unlock; > > + } > > + mtk_cam_dev_init_stream(cam); > > + ret = mtk_isp_hw_init(cam); > > + if (ret) { > > + dev_err(dev, "failed to init HW:%d\n", ret); > > + goto fail_stop_pipeline; > > + } > > + } > > + > > + /* Media links are fixed after media_pipeline_start */ > > + cam->stream_count++; > > + dev_dbg(dev, "%s: count info:%d:%d\n", __func__, cam->stream_count, > > + cam->enabled_count); > > + if (cam->stream_count < cam->enabled_count) { > > + mutex_unlock(&cam->op_lock); > > + return 0; > > + } > > + > > + /* Stream on sub-devices node */ > > + ret = v4l2_subdev_call(&cam->subdev, video, s_stream, 1); > > + if (ret) > > + goto fail_no_stream; > > + mutex_unlock(&cam->op_lock); > > + > > + return 0; > > + > > +fail_no_stream: > > + cam->stream_count--; > > +fail_stop_pipeline: > > + if (cam->stream_count == 0) > > + media_pipeline_stop(&node->vdev.entity); > > +fail_unlock: > > + mutex_unlock(&cam->op_lock); > > +fail_ret_buf: > > + mtk_cam_vb2_return_all_buffers(cam, node, VB2_BUF_STATE_QUEUED); > > + > > + return ret; > > +} > > + > > +static void mtk_cam_vb2_stop_streaming(struct vb2_queue *vq) > > +{ > > + struct mtk_cam_dev *cam = vb2_get_drv_priv(vq); > > + struct mtk_cam_video_device *node = mtk_cam_vbq_to_vdev(vq); > > + struct device *dev = cam->dev; > > + > > + mutex_lock(&cam->op_lock); > > + dev_dbg(dev, "%s node:%d count info:%d\n", __func__, node->id, > > + cam->stream_count); > > + /* Check the first node to stream-off */ > > + if (cam->stream_count == cam->enabled_count) > > + v4l2_subdev_call(&cam->subdev, video, s_stream, 0); > > + > > + mtk_cam_vb2_return_all_buffers(cam, node, VB2_BUF_STATE_ERROR); > > + cam->stream_count--; > > + if (cam->stream_count) { > > + mutex_unlock(&cam->op_lock); > > + return; > > + } > > + mutex_unlock(&cam->op_lock); > > + > > + mtk_cam_dev_req_cleanup(cam); > > + media_pipeline_stop(&node->vdev.entity); > > +} > > + > > +static int mtk_cam_vidioc_querycap(struct file *file, void *fh, > > + struct v4l2_capability *cap) > > +{ > > + struct mtk_cam_dev *cam = video_drvdata(file); > > + > > + strscpy(cap->driver, dev_driver_string(cam->dev), sizeof(cap->driver)); > > + strscpy(cap->card, dev_driver_string(cam->dev), sizeof(cap->card)); > > + snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", > > + dev_name(cam->dev)); > > + > > + return 0; > > +} > > + > > +static int mtk_cam_vidioc_enum_fmt(struct file *file, void *fh, > > + struct v4l2_fmtdesc *f) > > +{ > > + struct mtk_cam_video_device *node = file_to_mtk_cam_node(file); > > + > > + if (f->index >= node->desc.num_fmts) > > + return -EINVAL; > > + > > + /* f->description is filled in v4l_fill_fmtdesc function */ > > + f->pixelformat = node->desc.fmts[f->index].fmt.pix_mp.pixelformat; > > + f->flags = 0; > > + > > + return 0; > > +} > > + > > +static int mtk_cam_vidioc_g_fmt(struct file *file, void *fh, > > + struct v4l2_format *f) > > +{ > > + struct mtk_cam_video_device *node = file_to_mtk_cam_node(file); > > + > > + f->fmt = node->vdev_fmt.fmt; > > + > > + return 0; > > +} > > + > > +static int mtk_cam_vidioc_try_fmt(struct file *file, void *fh, > > + struct v4l2_format *f) > > +{ > > + struct mtk_cam_dev *cam = video_drvdata(file); > > + struct mtk_cam_video_device *node = file_to_mtk_cam_node(file); > > + struct device *dev = cam->dev; > > + const struct v4l2_format *dev_fmt; > > + struct v4l2_format try_fmt; > > + > > + memset(&try_fmt, 0, sizeof(try_fmt)); > > + try_fmt.type = f->type; > > + > > + /* Validate pixelformat */ > > + dev_fmt = mtk_cam_dev_find_fmt(&node->desc, f->fmt.pix_mp.pixelformat); > > + if (!dev_fmt) { > > + dev_dbg(dev, "unknown fmt:%d\n", f->fmt.pix_mp.pixelformat); > > + dev_fmt = &node->desc.fmts[node->desc.default_fmt_idx]; > > + } > > + try_fmt.fmt.pix_mp.pixelformat = dev_fmt->fmt.pix_mp.pixelformat; > > + > > + /* Validate image width & height range */ > > + try_fmt.fmt.pix_mp.width = clamp_val(f->fmt.pix_mp.width, > > + IMG_MIN_WIDTH, IMG_MAX_WIDTH); > > + try_fmt.fmt.pix_mp.height = clamp_val(f->fmt.pix_mp.height, > > + IMG_MIN_HEIGHT, IMG_MAX_HEIGHT); > > + /* 4 bytes alignment for width */ > > + try_fmt.fmt.pix_mp.width = ALIGN(try_fmt.fmt.pix_mp.width, 4); > > + > > + /* Only support one plane */ > > + try_fmt.fmt.pix_mp.num_planes = 1; > > + > > + /* bytesperline & sizeimage calculation */ > > + cal_image_pix_mp(cam, node->id, &try_fmt.fmt.pix_mp); > > + > > + /* Constant format fields */ > > + try_fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_SRGB; > > + try_fmt.fmt.pix_mp.field = V4L2_FIELD_NONE; > > + try_fmt.fmt.pix_mp.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; > > + try_fmt.fmt.pix_mp.quantization = V4L2_QUANTIZATION_DEFAULT; > > + try_fmt.fmt.pix_mp.xfer_func = V4L2_XFER_FUNC_SRGB; > > + > > + *f = try_fmt; > > + > > + return 0; > > +} > > + > > +static int mtk_cam_vidioc_s_fmt(struct file *file, void *fh, > > + struct v4l2_format *f) > > +{ > > + struct mtk_cam_dev *cam = video_drvdata(file); > > + struct mtk_cam_video_device *node = file_to_mtk_cam_node(file); > > + > > + if (vb2_is_busy(node->vdev.queue)) { > > + dev_dbg(cam->dev, "%s: queue is busy\n", __func__); > > + return -EBUSY; > > + } > > + > > + /* Get the valid format */ > > + mtk_cam_vidioc_try_fmt(file, fh, f); > > + /* Configure to video device */ > > + node->vdev_fmt = *f; > > + > > + return 0; > > +} > > + > > +static int mtk_cam_vidioc_enum_framesizes(struct file *filp, void *priv, > > + struct v4l2_frmsizeenum *sizes) > > +{ > > + struct mtk_cam_video_device *node = file_to_mtk_cam_node(filp); > > + const struct v4l2_format *dev_fmt; > > + > > + dev_fmt = mtk_cam_dev_find_fmt(&node->desc, sizes->pixel_format); > > + if (!dev_fmt || sizes->index) > > + return -EINVAL; > > + > > + sizes->type = node->desc.frmsizes->type; > > + memcpy(&sizes->stepwise, &node->desc.frmsizes->stepwise, > > + sizeof(sizes->stepwise)); > > + > > + return 0; > > +} > > + > > +static int mtk_cam_vidioc_meta_enum_fmt(struct file *file, void *fh, > > + struct v4l2_fmtdesc *f) > > +{ > > + struct mtk_cam_video_device *node = file_to_mtk_cam_node(file); > > + > > + if (f->index) > > + return -EINVAL; > > + > > + /* f->description is filled in v4l_fill_fmtdesc function */ > > + f->pixelformat = node->vdev_fmt.fmt.meta.dataformat; > > + f->flags = 0; > > + > > + return 0; > > +} > > + > > +static int mtk_cam_vidioc_g_meta_fmt(struct file *file, void *fh, > > + struct v4l2_format *f) > > +{ > > + struct mtk_cam_video_device *node = file_to_mtk_cam_node(file); > > + > > + f->fmt.meta.dataformat = node->vdev_fmt.fmt.meta.dataformat; > > + f->fmt.meta.buffersize = node->vdev_fmt.fmt.meta.buffersize; > > + > > + return 0; > > +} > > + > > +static const struct v4l2_subdev_core_ops mtk_cam_subdev_core_ops = { > > + .subscribe_event = mtk_cam_sd_subscribe_event, > > + .unsubscribe_event = v4l2_event_subdev_unsubscribe, > > +}; > > + > > +static const struct v4l2_subdev_video_ops mtk_cam_subdev_video_ops = { > > + .s_stream = mtk_cam_sd_s_stream, > > +}; > > + > > +static const struct v4l2_subdev_ops mtk_cam_subdev_ops = { > > + .core = &mtk_cam_subdev_core_ops, > > + .video = &mtk_cam_subdev_video_ops, > > +}; > > + > > +static const struct media_entity_operations mtk_cam_media_entity_ops = { > > + .link_setup = mtk_cam_media_link_setup, > > + .link_validate = v4l2_subdev_link_validate, > > +}; > > + > > +static const struct vb2_ops mtk_cam_vb2_ops = { > > + .queue_setup = mtk_cam_vb2_queue_setup, > > + .wait_prepare = vb2_ops_wait_prepare, > > + .wait_finish = vb2_ops_wait_finish, > > + .buf_init = mtk_cam_vb2_buf_init, > > + .buf_prepare = mtk_cam_vb2_buf_prepare, > > + .start_streaming = mtk_cam_vb2_start_streaming, > > + .stop_streaming = mtk_cam_vb2_stop_streaming, > > + .buf_queue = mtk_cam_vb2_buf_queue, > > + .buf_cleanup = mtk_cam_vb2_buf_cleanup, > > + .buf_request_complete = mtk_cam_vb2_request_complete, > > +}; > > + > > +static const struct v4l2_file_operations mtk_cam_v4l2_fops = { > > + .unlocked_ioctl = video_ioctl2, > > + .open = v4l2_fh_open, > > + .release = vb2_fop_release, > > + .poll = vb2_fop_poll, > > + .mmap = vb2_fop_mmap, > > +#ifdef CONFIG_COMPAT > > + .compat_ioctl32 = v4l2_compat_ioctl32, > > +#endif > > +}; > > + > > +static const struct media_device_ops mtk_cam_media_ops = { > > + .req_alloc = mtk_cam_req_alloc, > > + .req_free = mtk_cam_req_free, > > + .req_validate = vb2_request_validate, > > + .req_queue = mtk_cam_req_queue, > > +}; > > + > > +static int mtk_cam_media_register(struct mtk_cam_dev *cam, > > + struct media_device *media_dev) > > +{ > > + /* Reserved MTK_CAM_CIO_PAD_SINK + 1 pads to use */ > > + unsigned int num_pads = MTK_CAM_CIO_PAD_SINK + 1; > > + struct device *dev = cam->dev; > > + int i, ret; > > + > > + media_dev->dev = cam->dev; > > + strscpy(media_dev->model, dev_driver_string(dev), > > + sizeof(media_dev->model)); > > + snprintf(media_dev->bus_info, sizeof(media_dev->bus_info), > > + "platform:%s", dev_name(dev)); > > + media_dev->hw_revision = 0; > > + media_device_init(media_dev); > > + media_dev->ops = &mtk_cam_media_ops; > > + > > + ret = media_device_register(media_dev); > > + if (ret) { > > + dev_err(dev, "failed to register media device:%d\n", ret); > > + return ret; > > + } > > + > > + /* Initialize subdev pads */ > > + cam->subdev_pads = devm_kcalloc(dev, num_pads, > > + sizeof(*cam->subdev_pads), > > + GFP_KERNEL); > > + if (!cam->subdev_pads) { > > + dev_err(dev, "failed to allocate subdev_pads\n"); > > + ret = -ENOMEM; > > + goto fail_media_unreg; > > + } > > + > > + ret = media_entity_pads_init(&cam->subdev.entity, num_pads, > > + cam->subdev_pads); > > + if (ret) { > > + dev_err(dev, "failed to initialize media pads:%d\n", ret); > > + goto fail_media_unreg; > > + } > > + > > + /* Initialize all pads with MEDIA_PAD_FL_SOURCE */ > > + for (i = 0; i < num_pads; i++) > > + cam->subdev_pads[i].flags = MEDIA_PAD_FL_SOURCE; > > + > > + /* Customize the last one pad as CIO sink pad. */ > > + cam->subdev_pads[MTK_CAM_CIO_PAD_SINK].flags = MEDIA_PAD_FL_SINK; > > + > > + return 0; > > + > > +fail_media_unreg: > > + media_device_unregister(&cam->media_dev); > > + media_device_cleanup(&cam->media_dev); > > + > > + return ret; > > +} > > + > > +static int > > +mtk_cam_video_register_device(struct mtk_cam_dev *cam, > > + struct mtk_cam_video_device *node) > > +{ > > + struct device *dev = cam->dev; > > + struct video_device *vdev = &node->vdev; > > + struct vb2_queue *vbq = &node->vbq; > > + unsigned int output = V4L2_TYPE_IS_OUTPUT(node->desc.buf_type); > > + unsigned int link_flags = node->desc.link_flags; > > + int ret; > > + > > + /* Initialize mtk_cam_video_device */ > > + if (link_flags & MEDIA_LNK_FL_IMMUTABLE) > > + node->enabled = true; > > + else > > + node->enabled = false; > > + mtk_cam_dev_load_default_fmt(cam, &node->desc, &node->vdev_fmt); > > + > > + cam->subdev_pads[node->id].flags = output ? > > + MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE; > > + > > + /* Initialize media entities */ > > + ret = media_entity_pads_init(&vdev->entity, 1, &node->vdev_pad); > > + if (ret) { > > + dev_err(dev, "failed to initialize media pad:%d\n", ret); > > + return ret; > > + } > > + node->vdev_pad.flags = output ? MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK; > > + > > + /* Initialize vbq */ > > + vbq->type = node->desc.buf_type; > > + if (vbq->type == V4L2_BUF_TYPE_META_OUTPUT) > > + vbq->io_modes = VB2_MMAP; > > + else > > + vbq->io_modes = VB2_MMAP | VB2_DMABUF; > > + > > + if (node->desc.smem_alloc) { > > + vbq->bidirectional = 1; > > + vbq->dev = cam->smem_dev; > > + } else { > > + vbq->dev = dev; > > + } > > + vbq->ops = &mtk_cam_vb2_ops; > > + vbq->mem_ops = &vb2_dma_contig_memops; > > + vbq->buf_struct_size = sizeof(struct mtk_cam_dev_buffer); > > + vbq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_BOOTIME; > > + if (output) > > + vbq->timestamp_flags |= V4L2_BUF_FLAG_TSTAMP_SRC_EOF; > > + else > > + vbq->timestamp_flags |= V4L2_BUF_FLAG_TSTAMP_SRC_SOE; > > + /* No minimum buffers limitation */ > > + vbq->min_buffers_needed = 0; > > + vbq->drv_priv = cam; > > + vbq->lock = &node->vdev_lock; > > + vbq->supports_requests = true; > > + vbq->requires_requests = true; > > + > > + ret = vb2_queue_init(vbq); > > + if (ret) { > > + dev_err(dev, "failed to init. vb2 queue:%d\n", ret); > > + goto fail_media_clean; > > + } > > + > > + /* Initialize vdev */ > > + snprintf(vdev->name, sizeof(vdev->name), "%s %s", > > + dev_driver_string(dev), node->desc.name); > > + /* set cap/type/ioctl_ops of the video device */ > > + vdev->device_caps = node->desc.cap | V4L2_CAP_STREAMING; > > + vdev->ioctl_ops = node->desc.ioctl_ops; > > + vdev->fops = &mtk_cam_v4l2_fops; > > + vdev->release = video_device_release_empty; > > + vdev->lock = &node->vdev_lock; > > + vdev->v4l2_dev = &cam->v4l2_dev; > > + vdev->queue = &node->vbq; > > + vdev->vfl_dir = output ? VFL_DIR_TX : VFL_DIR_RX; > > + vdev->entity.function = MEDIA_ENT_F_IO_V4L; > > + vdev->entity.ops = NULL; > > + video_set_drvdata(vdev, cam); > > + dev_dbg(dev, "registered vdev:%d:%s\n", node->id, vdev->name); > > + > > + /* Initialize miscellaneous variables */ > > + mutex_init(&node->vdev_lock); > > + INIT_LIST_HEAD(&node->buf_list); > > + spin_lock_init(&node->buf_list_lock); > > + > > + ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); > > + if (ret) { > > + dev_err(dev, "failed to register vde:%d\n", ret); > > + goto fail_vb2_rel; > > + } > > + > > + /* Create link between video node and the subdev pad */ > > + if (output) { > > + ret = media_create_pad_link(&vdev->entity, 0, > > + &cam->subdev.entity, > > + node->id, link_flags); > > + } else { > > + ret = media_create_pad_link(&cam->subdev.entity, > > + node->id, &vdev->entity, 0, > > + link_flags); > > + } > > + if (ret) > > + goto fail_vdev_ureg; > > + > > + return 0; > > + > > +fail_vdev_ureg: > > + video_unregister_device(vdev); > > +fail_vb2_rel: > > + mutex_destroy(&node->vdev_lock); > > + vb2_queue_release(vbq); > > +fail_media_clean: > > + media_entity_cleanup(&vdev->entity); > > + > > + return ret; > > +} > > + > > +static void > > +mtk_cam_video_unregister_device(struct mtk_cam_video_device *node) > > +{ > > + video_unregister_device(&node->vdev); > > + vb2_queue_release(&node->vbq); > > + media_entity_cleanup(&node->vdev.entity); > > + mutex_destroy(&node->vdev_lock); > > +} > > + > > +static int mtk_cam_v4l2_register(struct mtk_cam_dev *cam) > > +{ > > + struct device *dev = cam->dev; > > + int i, ret; > > + > > + /* Set up media device & pads */ > > + ret = mtk_cam_media_register(cam, &cam->media_dev); > > + if (ret) > > + return ret; > > + dev_info(dev, "Registered media%d\n", cam->media_dev.devnode->minor); > > + > > + /* Set up v4l2 device */ > > + cam->v4l2_dev.mdev = &cam->media_dev; > > + ret = v4l2_device_register(dev, &cam->v4l2_dev); > > + if (ret) { > > + dev_err(dev, "failed to register V4L2 device:%d\n", ret); > > + goto fail_media_unreg; > > + } > > + dev_info(dev, "Registered %s\n", cam->v4l2_dev.name); > > + > > + /* Initialize subdev */ > > + v4l2_subdev_init(&cam->subdev, &mtk_cam_subdev_ops); > > + cam->subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; > > + cam->subdev.entity.ops = &mtk_cam_media_entity_ops; > > + cam->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE | > > + V4L2_SUBDEV_FL_HAS_EVENTS; > > + snprintf(cam->subdev.name, sizeof(cam->subdev.name), > > + "%s", dev_driver_string(dev)); > > + v4l2_set_subdevdata(&cam->subdev, cam); > > + > > + ret = v4l2_device_register_subdev(&cam->v4l2_dev, &cam->subdev); > > + if (ret) { > > + dev_err(dev, "failed to initialize subdev:%d\n", ret); > > + goto fail_clean_media_entiy; > > + } > > + dev_dbg(dev, "registered %s\n", cam->subdev.name); > > + > > + /* Create video nodes and links */ > > + for (i = 0; i < MTK_CAM_P1_TOTAL_NODES; i++) { > > + struct mtk_cam_video_device *node = &cam->vdev_nodes[i]; > > + > > + node->id = node->desc.id; > > + ret = mtk_cam_video_register_device(cam, node); > > + if (ret) > > + goto fail_vdev_unreg; > > + } > > + vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); > > + > > + return 0; > > + > > +fail_vdev_unreg: > > + for (i--; i >= 0; i--) > > + mtk_cam_video_unregister_device(&cam->vdev_nodes[i]); > > +fail_clean_media_entiy: > > + media_entity_cleanup(&cam->subdev.entity); > > + v4l2_device_unregister(&cam->v4l2_dev); > > +fail_media_unreg: > > + media_device_unregister(&cam->media_dev); > > + media_device_cleanup(&cam->media_dev); > > + > > + return ret; > > +} > > + > > +static int mtk_cam_v4l2_unregister(struct mtk_cam_dev *cam) > > +{ > > + int i; > > + > > + for (i = 0; i < MTK_CAM_P1_TOTAL_NODES; i++) > > + mtk_cam_video_unregister_device(&cam->vdev_nodes[i]); > > + > > + vb2_dma_contig_clear_max_seg_size(cam->dev); > > + v4l2_device_unregister_subdev(&cam->subdev); > > + v4l2_device_unregister(&cam->v4l2_dev); > > + media_entity_cleanup(&cam->subdev.entity); > > + media_device_unregister(&cam->media_dev); > > + media_device_cleanup(&cam->media_dev); > > + > > + return 0; > > +} > > + > > +static int mtk_cam_dev_notifier_bound(struct v4l2_async_notifier *notifier, > > + struct v4l2_subdev *sd, > > + struct v4l2_async_subdev *asd) > > +{ > > + struct mtk_cam_dev *cam = > > + container_of(notifier, struct mtk_cam_dev, notifier); > > + > > + if (!(sd->entity.function & MEDIA_ENT_F_VID_IF_BRIDGE)) { > > + dev_dbg(cam->dev, "no MEDIA_ENT_F_VID_IF_BRIDGE function\n"); > > + return -ENODEV; > > + } > > + > > + cam->seninf = sd; > > + dev_dbg(cam->dev, "%s is bound\n", sd->entity.name); > > + > > + return 0; > > +} > > + > > +static void mtk_cam_dev_notifier_unbind(struct v4l2_async_notifier *notifier, > > + struct v4l2_subdev *sd, > > + struct v4l2_async_subdev *asd) > > +{ > > + struct mtk_cam_dev *cam = > > + container_of(notifier, struct mtk_cam_dev, notifier); > > + > > + cam->seninf = NULL; > > + dev_dbg(cam->dev, "%s is unbound\n", sd->entity.name); > > +} > > + > > +static int mtk_cam_dev_notifier_complete(struct v4l2_async_notifier *notifier) > > +{ > > + struct mtk_cam_dev *cam = > > + container_of(notifier, struct mtk_cam_dev, notifier); > > + struct device *dev = cam->dev; > > + int ret; > > + > > + if (!cam->seninf) { > > + dev_err(dev, "No seninf subdev\n"); > > + return -ENODEV; > > + } > > + > > + ret = media_create_pad_link(&cam->seninf->entity, MTK_CAM_CIO_PAD_SRC, > > + &cam->subdev.entity, MTK_CAM_CIO_PAD_SINK, > > + MEDIA_LNK_FL_IMMUTABLE | > > + MEDIA_LNK_FL_ENABLED); > > + if (ret) { > > + dev_err(dev, "failed to create pad link %s %s err:%d\n", > > + cam->seninf->entity.name, cam->subdev.entity.name, > > + ret); > > + return ret; > > + } > > + > > + ret = v4l2_device_register_subdev_nodes(&cam->v4l2_dev); > > + if (ret) { > > + dev_err(dev, "failed to initialize subdev nodes:%d\n", ret); > > + return ret; > > + } > > + > > + return ret; > > +} > > + > > +static const struct v4l2_async_notifier_operations mtk_cam_v4l2_async_ops = { > > + .bound = mtk_cam_dev_notifier_bound, > > + .unbind = mtk_cam_dev_notifier_unbind, > > + .complete = mtk_cam_dev_notifier_complete, > > +}; > > + > > +static int mtk_cam_v4l2_async_register(struct mtk_cam_dev *cam) > > +{ > > + struct device *dev = cam->dev; > > + int ret; > > + > > + v4l2_async_notifier_init(&cam->notifier); > > + ret = v4l2_async_notifier_parse_fwnode_endpoints(dev, > > + &cam->notifier, sizeof(struct v4l2_async_subdev), NULL); > > + if (ret) { > > + dev_err(dev, "failed to parse fwnode endpoints:%d\n", ret); > > + return ret; > > + } > > + > > + cam->notifier.ops = &mtk_cam_v4l2_async_ops; > > + dev_dbg(dev, "mtk_cam v4l2_async_notifier_register\n"); > > + ret = v4l2_async_notifier_register(&cam->v4l2_dev, &cam->notifier); > > + if (ret) { > > + dev_err(dev, "failed to register async notifier : %d\n", ret); > > + v4l2_async_notifier_cleanup(&cam->notifier); > > + } > > + > > + return ret; > > +} > > + > > +static void mtk_cam_v4l2_async_unregister(struct mtk_cam_dev *cam) > > +{ > > + v4l2_async_notifier_unregister(&cam->notifier); > > + v4l2_async_notifier_cleanup(&cam->notifier); > > +} > > + > > +static const struct v4l2_ioctl_ops mtk_cam_v4l2_vcap_ioctl_ops = { > > + .vidioc_querycap = mtk_cam_vidioc_querycap, > > + .vidioc_enum_framesizes = mtk_cam_vidioc_enum_framesizes, > > + .vidioc_enum_fmt_vid_cap = mtk_cam_vidioc_enum_fmt, > > + .vidioc_g_fmt_vid_cap_mplane = mtk_cam_vidioc_g_fmt, > > + .vidioc_s_fmt_vid_cap_mplane = mtk_cam_vidioc_s_fmt, > > + .vidioc_try_fmt_vid_cap_mplane = mtk_cam_vidioc_try_fmt, > > + .vidioc_reqbufs = vb2_ioctl_reqbufs, > > + .vidioc_create_bufs = vb2_ioctl_create_bufs, > > + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, > > + .vidioc_querybuf = vb2_ioctl_querybuf, > > + .vidioc_qbuf = vb2_ioctl_qbuf, > > + .vidioc_dqbuf = vb2_ioctl_dqbuf, > > + .vidioc_streamon = vb2_ioctl_streamon, > > + .vidioc_streamoff = vb2_ioctl_streamoff, > > + .vidioc_expbuf = vb2_ioctl_expbuf, > > + .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, > > + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, > > +}; > > + > > +static const struct v4l2_ioctl_ops mtk_cam_v4l2_meta_cap_ioctl_ops = { > > + .vidioc_querycap = mtk_cam_vidioc_querycap, > > + .vidioc_enum_fmt_meta_cap = mtk_cam_vidioc_meta_enum_fmt, > > + .vidioc_g_fmt_meta_cap = mtk_cam_vidioc_g_meta_fmt, > > + .vidioc_s_fmt_meta_cap = mtk_cam_vidioc_g_meta_fmt, > > + .vidioc_try_fmt_meta_cap = mtk_cam_vidioc_g_meta_fmt, > > + .vidioc_reqbufs = vb2_ioctl_reqbufs, > > + .vidioc_create_bufs = vb2_ioctl_create_bufs, > > + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, > > + .vidioc_querybuf = vb2_ioctl_querybuf, > > + .vidioc_qbuf = vb2_ioctl_qbuf, > > + .vidioc_dqbuf = vb2_ioctl_dqbuf, > > + .vidioc_streamon = vb2_ioctl_streamon, > > + .vidioc_streamoff = vb2_ioctl_streamoff, > > + .vidioc_expbuf = vb2_ioctl_expbuf, > > +}; > > + > > +static const struct v4l2_ioctl_ops mtk_cam_v4l2_meta_out_ioctl_ops = { > > + .vidioc_querycap = mtk_cam_vidioc_querycap, > > + .vidioc_enum_fmt_meta_out = mtk_cam_vidioc_meta_enum_fmt, > > + .vidioc_g_fmt_meta_out = mtk_cam_vidioc_g_meta_fmt, > > + .vidioc_s_fmt_meta_out = mtk_cam_vidioc_g_meta_fmt, > > + .vidioc_try_fmt_meta_out = mtk_cam_vidioc_g_meta_fmt, > > + .vidioc_reqbufs = vb2_ioctl_reqbufs, > > + .vidioc_create_bufs = vb2_ioctl_create_bufs, > > + .vidioc_prepare_buf = vb2_ioctl_prepare_buf, > > + .vidioc_querybuf = vb2_ioctl_querybuf, > > + .vidioc_qbuf = vb2_ioctl_qbuf, > > + .vidioc_dqbuf = vb2_ioctl_dqbuf, > > + .vidioc_streamon = vb2_ioctl_streamon, > > + .vidioc_streamoff = vb2_ioctl_streamoff, > > + .vidioc_expbuf = vb2_ioctl_expbuf, > > +}; > > + > > +static const struct v4l2_format meta_fmts[] = { > > + { > > + .fmt.meta = { > > + .dataformat = V4L2_META_FMT_MTISP_PARAMS, > > + .buffersize = 512 * SZ_1K, > > + }, > > + }, > > + { > > + .fmt.meta = { > > + .dataformat = V4L2_META_FMT_MTISP_3A, > > + .buffersize = 1200 * SZ_1K, > > + }, > > + }, > > + { > > + .fmt.meta = { > > + .dataformat = V4L2_META_FMT_MTISP_AF, > > + .buffersize = 640 * SZ_1K, > > + }, > > + }, > > + { > > + .fmt.meta = { > > + .dataformat = V4L2_META_FMT_MTISP_LCS, > > + .buffersize = 288 * SZ_1K, > > + }, > > + }, > > + { > > + .fmt.meta = { > > + .dataformat = V4L2_META_FMT_MTISP_LMV, > > + .buffersize = 256, > > + }, > > + }, > > +}; > > + > > +static const struct v4l2_format stream_out_fmts[] = { > > + /* This is a default image format */ > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR10, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR8, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR12, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR14, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG8, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG10, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG12, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG14, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG8, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG10, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG12, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG14, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB8, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB10, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB12, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB14, > > + }, > > + }, > > +}; > > + > > +static const struct v4l2_format bin_out_fmts[] = { > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR8F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR10F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR12F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SBGGR14F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG8F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG10F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG12F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGBRG14F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG8F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG10F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG12F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SGRBG14F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB8F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB10F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB12F, > > + }, > > + }, > > + { > > + .fmt.pix_mp = { > > + .width = IMG_MAX_WIDTH, > > + .height = IMG_MAX_HEIGHT, > > + .pixelformat = V4L2_PIX_FMT_MTISP_SRGGB14F, > > + }, > > + }, > > +}; > > + > > +static const struct > > +mtk_cam_dev_node_desc output_queues[] = { > > + { > > + .id = MTK_CAM_P1_META_IN_0, > > + .name = "meta input", > > + .cap = V4L2_CAP_META_OUTPUT, > > + .buf_type = V4L2_BUF_TYPE_META_OUTPUT, > > + .link_flags = 0, > > + .image = false, > > + .smem_alloc = true, > > + .fmts = meta_fmts, > > + .default_fmt_idx = 0, > > + .max_buf_count = 10, > > + .ioctl_ops = &mtk_cam_v4l2_meta_out_ioctl_ops, > > + }, > > +}; > > + > > +static const struct > > +mtk_cam_dev_node_desc capture_queues[] = { > > + { > > + .id = MTK_CAM_P1_MAIN_STREAM_OUT, > > + .name = "main stream", > > + .cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE, > > + .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, > > + .link_flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED, > > + .image = true, > > + .smem_alloc = false, > > + .dma_port = R_IMGO, > > + .fmts = stream_out_fmts, > > + .num_fmts = ARRAY_SIZE(stream_out_fmts), > > + .default_fmt_idx = 0, > > + .ioctl_ops = &mtk_cam_v4l2_vcap_ioctl_ops, > > + .frmsizes = &(struct v4l2_frmsizeenum) { > > + .index = 0, > > + .type = V4L2_FRMSIZE_TYPE_CONTINUOUS, > > + .stepwise = { > > + .max_width = IMG_MAX_WIDTH, > > + .min_width = IMG_MIN_WIDTH, > > + .max_height = IMG_MAX_HEIGHT, > > + .min_height = IMG_MIN_HEIGHT, > > + .step_height = 1, > > + .step_width = 1, > > + }, > > + }, > > + }, > > + { > > + .id = MTK_CAM_P1_PACKED_BIN_OUT, > > + .name = "packed out", > > + .cap = V4L2_CAP_VIDEO_CAPTURE_MPLANE, > > + .buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, > > + .link_flags = 0, > > + .image = true, > > + .smem_alloc = false, > > + .dma_port = R_RRZO, > > + .fmts = bin_out_fmts, > > + .num_fmts = ARRAY_SIZE(bin_out_fmts), > > + .default_fmt_idx = 0, > > + .ioctl_ops = &mtk_cam_v4l2_vcap_ioctl_ops, > > + .frmsizes = &(struct v4l2_frmsizeenum) { > > + .index = 0, > > + .type = V4L2_FRMSIZE_TYPE_CONTINUOUS, > > + .stepwise = { > > + .max_width = IMG_MAX_WIDTH, > > + .min_width = IMG_MIN_WIDTH, > > + .max_height = IMG_MAX_HEIGHT, > > + .min_height = IMG_MIN_HEIGHT, > > + .step_height = 1, > > + .step_width = 1, > > + }, > > + }, > > + }, > > + { > > + .id = MTK_CAM_P1_META_OUT_0, > > + .name = "partial meta 0", > > + .cap = V4L2_CAP_META_CAPTURE, > > + .buf_type = V4L2_BUF_TYPE_META_CAPTURE, > > + .link_flags = 0, > > + .image = false, > > + .smem_alloc = false, > > + .dma_port = R_AAO | R_FLKO | R_PSO, > > + .fmts = meta_fmts, > > + .default_fmt_idx = 1, > > + .max_buf_count = 5, > > + .ioctl_ops = &mtk_cam_v4l2_meta_cap_ioctl_ops, > > + }, > > + { > > + .id = MTK_CAM_P1_META_OUT_1, > > + .name = "partial meta 1", > > + .cap = V4L2_CAP_META_CAPTURE, > > + .buf_type = V4L2_BUF_TYPE_META_CAPTURE, > > + .link_flags = 0, > > + .image = false, > > + .smem_alloc = false, > > + .dma_port = R_AFO, > > + .fmts = meta_fmts, > > + .default_fmt_idx = 2, > > + .max_buf_count = 5, > > + .ioctl_ops = &mtk_cam_v4l2_meta_cap_ioctl_ops, > > + }, > > + { > > + .id = MTK_CAM_P1_META_OUT_2, > > + .name = "partial meta 2", > > + .cap = V4L2_CAP_META_CAPTURE, > > + .buf_type = V4L2_BUF_TYPE_META_CAPTURE, > > + .link_flags = 0, > > + .image = false, > > + .smem_alloc = false, > > + .dma_port = R_LCSO, > > + .fmts = meta_fmts, > > + .default_fmt_idx = 3, > > + .max_buf_count = 10, > > + .ioctl_ops = &mtk_cam_v4l2_meta_cap_ioctl_ops, > > + }, > > + { > > + .id = MTK_CAM_P1_META_OUT_3, > > + .name = "partial meta 3", > > + .cap = V4L2_CAP_META_CAPTURE, > > + .buf_type = V4L2_BUF_TYPE_META_CAPTURE, > > + .link_flags = 0, > > + .image = false, > > + .smem_alloc = false, > > + .dma_port = R_LMVO, > > + .fmts = meta_fmts, > > + .default_fmt_idx = 4, > > + .max_buf_count = 10, > > + .ioctl_ops = &mtk_cam_v4l2_meta_cap_ioctl_ops, > > + }, > > +}; > > + > > +/* The helper to configure the device context */ > > +static void mtk_cam_dev_queue_setup(struct mtk_cam_dev *cam) > > +{ > > + unsigned int node_idx; > > + int i; > > + > > + node_idx = 0; > > + /* Setup the output queue */ > > + for (i = 0; i < ARRAY_SIZE(output_queues); i++) > > + cam->vdev_nodes[node_idx++].desc = output_queues[i]; > > + > > + /* Setup the capture queue */ > > + for (i = 0; i < ARRAY_SIZE(capture_queues); i++) > > + cam->vdev_nodes[node_idx++].desc = capture_queues[i]; > > +} > > + > > +int mtk_cam_dev_init(struct platform_device *pdev, > > + struct mtk_cam_dev *cam) > > +{ > > + int ret; > > + > > + cam->dev = &pdev->dev; > > + mtk_cam_dev_queue_setup(cam); > > + > > + spin_lock_init(&cam->pending_job_lock); > > + spin_lock_init(&cam->running_job_lock); > > + INIT_LIST_HEAD(&cam->pending_job_list); > > + INIT_LIST_HEAD(&cam->running_job_list); > > + mutex_init(&cam->op_lock); > > + > > + /* v4l2 sub-device registration */ > > + ret = mtk_cam_v4l2_register(cam); > > + if (ret) > > + return ret; > > + > > + ret = mtk_cam_v4l2_async_register(cam); > > + if (ret) > > + goto fail_v4l2_unreg; > > + > > + return 0; > > + > > +fail_v4l2_unreg: > > + mutex_destroy(&cam->op_lock); > > + mtk_cam_v4l2_unregister(cam); > > + > > + return ret; > > +} > > + > > +void mtk_cam_dev_cleanup(struct mtk_cam_dev *cam) > > +{ > > + mtk_cam_v4l2_async_unregister(cam); > > + mtk_cam_v4l2_unregister(cam); > > + mutex_destroy(&cam->op_lock); > > +} > > + > > diff --git a/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.h b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.h > > new file mode 100644 > > index 000000000000..0a340a1e65ea > > --- /dev/null > > +++ b/drivers/media/platform/mtk-isp/isp_50/cam/mtk_cam.h > > @@ -0,0 +1,244 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +/* > > + * Copyright (c) 2019 MediaTek Inc. > > + */ > > + > > +#ifndef __MTK_CAM_H__ > > +#define __MTK_CAM_H__ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "mtk_cam-ipi.h" > > + > > +#define IMG_MAX_WIDTH 5376 > > +#define IMG_MAX_HEIGHT 4032 > > +#define IMG_MIN_WIDTH 80 > > +#define IMG_MIN_HEIGHT 60 > > + > > +/* > > + * ID enum value for struct mtk_cam_dev_node_desc:id > > + * or mtk_cam_video_device:id > > + */ > > +enum { > > + MTK_CAM_P1_META_IN_0 = 0, > > + MTK_CAM_P1_MAIN_STREAM_OUT, > > + MTK_CAM_P1_PACKED_BIN_OUT, > > + MTK_CAM_P1_META_OUT_0, > > + MTK_CAM_P1_META_OUT_1, > > + MTK_CAM_P1_META_OUT_2, > > + MTK_CAM_P1_META_OUT_3, > > + MTK_CAM_P1_TOTAL_NODES > > +}; > > + > > +/* Supported image format list */ > > +#define MTK_CAM_IMG_FMT_UNKNOWN 0x0000 > > +#define MTK_CAM_IMG_FMT_BAYER8 0x2200 > > +#define MTK_CAM_IMG_FMT_BAYER10 0x2201 > > +#define MTK_CAM_IMG_FMT_BAYER12 0x2202 > > +#define MTK_CAM_IMG_FMT_BAYER14 0x2203 > > +#define MTK_CAM_IMG_FMT_FG_BAYER8 0x2204 > > +#define MTK_CAM_IMG_FMT_FG_BAYER10 0x2205 > > +#define MTK_CAM_IMG_FMT_FG_BAYER12 0x2206 > > +#define MTK_CAM_IMG_FMT_FG_BAYER14 0x2207 > > + > > +/* Supported bayer pixel order */ > > +#define MTK_CAM_RAW_PXL_ID_B 0 > > +#define MTK_CAM_RAW_PXL_ID_GB 1 > > +#define MTK_CAM_RAW_PXL_ID_GR 2 > > +#define MTK_CAM_RAW_PXL_ID_R 3 > > +#define MTK_CAM_RAW_PXL_ID_UNKNOWN 4 > > + > > +/* > > + * struct mtk_p1_frame_param - MTK ISP P1 driver frame parameters. > > + * > > + * @frame_seq_no: The frame sequence of frame in driver layer. > > + * @dma_bufs: The DMA buffer address information of enabled DMA nodes. > > + * > > + */ > > +struct mtk_p1_frame_param { > > + unsigned int frame_seq_no; > > + struct dma_buffer dma_bufs[MTK_CAM_P1_TOTAL_NODES]; > > +} __packed; > > + > > +/* > > + * struct mtk_cam_dev_request - MTK camera device request. > > + * > > + * @req: Embedded struct media request. > > + * @frame_params: The frame info. & address info. of enabled DMA nodes. > > + * @frame_work: work queue entry for frame transmission to SCP. > > + * @list: List entry of the object for @struct mtk_cam_dev: > > + * pending_job_list or running_job_list. > > + * @timestamp: Start of frame timestamp in ns > > + * > > + */ > > +struct mtk_cam_dev_request { > > + struct media_request req; > > + struct mtk_p1_frame_param frame_params; > > + struct work_struct frame_work; > > + struct list_head list; > > + u64 timestamp; > > +}; > > + > > +/* > > + * struct mtk_cam_dev_buffer - MTK camera device buffer. > > + * > > + * @vbb: Embedded struct vb2_v4l2_buffer. > > + * @list: List entry of the object for @struct mtk_cam_video_device: > > + * buf_list. > > + * @daddr: The DMA address of this buffer. > > + * @scp_addr: The SCP address of this buffer which > > + * is only supported for meta input node. > > + * @node_id: The vidoe node id which this buffer belongs to. > > + * > > + */ > > +struct mtk_cam_dev_buffer { > > + struct vb2_v4l2_buffer vbb; > > + struct list_head list; > > + /* Intenal part */ > > + dma_addr_t daddr; > > + dma_addr_t scp_addr; > > + unsigned int node_id; > > +}; > > + > > +/* > > + * struct mtk_cam_dev_node_desc - MTK camera device node descriptor > > + * > > + * @id: id of the node > > + * @name: name of the node > > + * @cap: supported V4L2 capabilities > > + * @buf_type: supported V4L2 buffer type > > + * @dma_port: the dma ports associated to the node > > + * @link_flags: default media link flags > > + * @smem_alloc: using the smem_dev as alloc device or not > > + * @image: true for image node, false for meta node > > + * @num_fmts: the number of supported node formats > > + * @default_fmt_idx: default format of this node > > + * @max_buf_count: maximum VB2 buffer count > > + * @ioctl_ops: mapped to v4l2_ioctl_ops > > + * @fmts: supported format > > + * @frmsizes: supported V4L2 frame size number > > + * > > + */ > > +struct mtk_cam_dev_node_desc { > > + u8 id; > > + const char *name; > > + u32 cap; > > + u32 buf_type; > > + u32 dma_port; > > + u32 link_flags; > > + u8 smem_alloc:1; > > + u8 image:1; > > + u8 num_fmts; > > + u8 default_fmt_idx; > > + u8 max_buf_count; > > + const struct v4l2_ioctl_ops *ioctl_ops; > > + const struct v4l2_format *fmts; > > + const struct v4l2_frmsizeenum *frmsizes; > > +}; > > + > > +/* > > + * struct mtk_cam_video_device - Mediatek video device structure > > + * > > + * @id: Id for index of mtk_cam_dev:vdev_nodes array > > + * @enabled: Indicate the video device is enabled or not > > + * @desc: The node description of video device > > + * @vdev_fmt: The V4L2 format of video device > > + * @vdev_pad: The media pad graph object of video device > > + * @vbq: A videobuf queue of video device > > + * @vdev: The video device instance > > + * @vdev_lock: Serializes vb2 queue and video device operations > > + * @buf_list: List for enqueue buffers > > + * @buf_list_lock: Lock used to protect buffer list. > > + * > > + */ > > +struct mtk_cam_video_device { > > + unsigned int id; > > + unsigned int enabled; > > + struct mtk_cam_dev_node_desc desc; > > + struct v4l2_format vdev_fmt; > > + struct media_pad vdev_pad; > > + struct vb2_queue vbq; > > + struct video_device vdev; > > + /* Serializes vb2 queue and video device operations */ > > + struct mutex vdev_lock; > > + struct list_head buf_list; > > + /* Lock used to protect buffer list */ > > + spinlock_t buf_list_lock; > > +}; > > + > > +/* > > + * struct mtk_cam_dev - Mediatek camera device structure. > > + * > > + * @dev: Pointer to device. > > + * @smem_pdev: Pointer to shared memory device. > > + * @pipeline: Media pipeline information. > > + * @media_dev: Media device instance. > > + * @subdev: The V4L2 sub-device instance. > > + * @v4l2_dev: The V4L2 device driver instance. > > + * @notifier: The v4l2_device notifier data. > > + * @subdev_pads: Pointer to the number of media pads of this sub-device. > > + * @vdev_nodes: The array list of mtk_cam_video_device nodes. > > + * @seninf: Pointer to the seninf sub-device. > > + * @sensor: Pointer to the active sensor V4L2 sub-device when streaming on. > > + * @streaming: Indicate the overall streaming status is on or off. > > + * @enabled_dmas: The enabled dma port information when streaming on. > > + * @enabled_count: Number of enabled video nodes > > + * @stream_count: Number of streaming video nodes > > + * @running_job_count: Nunber of running jobs in the HW driver. > > + * @pending_job_list: List to keep the media requests before en-queue into > > + * HW driver. > > + * @pending_job_lock: Protect the pending_job_list data & running_job_count. > > + * @running_job_list: List to keep the media requests after en-queue into > > + * HW driver. > > + * @running_job_lock: Protect the running_job_list data. > > + * @op_lock: Serializes driver's VB2 callback operations. > > + * > > + */ > > +struct mtk_cam_dev { > > + struct device *dev; > > + struct device *smem_dev; > > + struct media_pipeline pipeline; > > + struct media_device media_dev; > > + struct v4l2_subdev subdev; > > + struct v4l2_device v4l2_dev; > > + struct v4l2_async_notifier notifier; > > + struct media_pad *subdev_pads; > > + struct mtk_cam_video_device vdev_nodes[MTK_CAM_P1_TOTAL_NODES]; > > + struct v4l2_subdev *seninf; > > + struct v4l2_subdev *sensor; > > + unsigned int streaming; > > + unsigned int enabled_dmas; > > + unsigned int enabled_count; > > + unsigned int stream_count; > > + unsigned int running_job_count; > > + struct list_head pending_job_list; > > + /* Protect the pending_job_list data */ > > + spinlock_t pending_job_lock; > > + struct list_head running_job_list; > > + /* Protect the running_job_list data & running_job_count */ > > + spinlock_t running_job_lock; > > + /* Serializes driver's VB2 callback operations */ > > + struct mutex op_lock; > > +}; > > + > > +int mtk_cam_dev_init(struct platform_device *pdev, > > + struct mtk_cam_dev *cam_dev); > > +void mtk_cam_dev_cleanup(struct mtk_cam_dev *cam_dev); > > +void mtk_cam_dev_req_try_queue(struct mtk_cam_dev *cam_dev); > > +void mtk_cam_dev_dequeue_req_frame(struct mtk_cam_dev *cam_dev, > > + unsigned int frame_seq_no); > > +void mtk_cam_dev_event_frame_sync(struct mtk_cam_dev *cam_dev, > > + unsigned int frame_seq_no); > > +struct mtk_cam_dev_request *mtk_cam_dev_get_req(struct mtk_cam_dev *cam, > > + unsigned int frame_seq_no); > > + > > +#endif /* __MTK_CAM_H__ */ > > > > _______________________________________________ > Linux-mediatek mailing list > Linux-mediatek@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-mediatek _______________________________________________ Linux-mediatek mailing list Linux-mediatek@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-mediatek From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.3 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED, USER_AGENT_SANE_2 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DFCBAC2BA2B for ; Thu, 9 Apr 2020 02:50:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6472720757 for ; Thu, 9 Apr 2020 02:50:11 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=mediatek.com header.i=@mediatek.com header.b="DbepZAp1" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726523AbgDICuK (ORCPT ); Wed, 8 Apr 2020 22:50:10 -0400 Received: from mailgw02.mediatek.com ([210.61.82.184]:62027 "EHLO mailgw02.mediatek.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1726521AbgDICuK (ORCPT ); Wed, 8 Apr 2020 22:50:10 -0400 X-UUID: ef9229ddf3f04f05a784a37cfb06e57c-20200409 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Transfer-Encoding:MIME-Version:Content-Type:References:In-Reply-To:Date:CC:To:From:Subject:Message-ID; bh=Fusn7+SqpvbI1DscbYxHx41zYWHRTLYrZmwYicK/xuY=; b=DbepZAp1YjVk1EztdVk+xW9NDZ4yIkqvjDQiwdAcYEIgS9M00+Rt1EtkUOjpuNc8vTZopnyrsAocyRvDyoE+DeMQQlfgr+B1Rgq6oiLqQAbjpTNuuzVJly4Zjk6fCdpLF3YY1eam7lPhhVM7ptDjNxdNxRQqiAwmePlwmpAPQzc=; X-UUID: ef9229ddf3f04f05a784a37cfb06e57c-20200409 Received: from mtkcas10.mediatek.inc [(172.21.101.39)] by mailgw02.mediatek.com (envelope-from ) (Cellopoint E-mail Firewall v4.1.10 Build 0809 with TLS) with ESMTP id 1332397617; Thu, 09 Apr 2020 10:49:35 +0800 Received: from MTKCAS06.mediatek.inc (172.21.101.30) by mtkmbs06n1.mediatek.inc (172.21.101.129) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Thu, 9 Apr 2020 10:49:11 +0800 Received: from [172.21.84.99] (172.21.84.99) by MTKCAS06.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Thu, 9 Apr 2020 10:49:32 +0800 Message-ID: <1586400573.8406.80.camel@mtksdccf07> Subject: Re: [v6, 5/5] media: platform: Add Mediatek ISP P1 V4L2 device driver From: Jungo Lin To: Dafna Hirschfeld CC: , , , , , , , , , , Pi-Hsun Shih , , , , , , , , , , , , , Date: Thu, 9 Apr 2020 10:49:33 +0800 In-Reply-To: References: <20191219054930.29513-1-jungo.lin@mediatek.com> <20191219054930.29513-6-jungo.lin@mediatek.com> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.2.3-0ubuntu6 MIME-Version: 1.0 X-MTK: N Content-Transfer-Encoding: base64 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org SGksIERhZm5hOg0KDQpUaGFua3MgZm9yIHlvdXIgY29tbWVudHMuDQoNCk9uIFRodSwgMjAyMC0w NC0wMiBhdCAxODo0NSArMDIwMCwgRGFmbmEgSGlyc2NoZmVsZCB3cm90ZToNCj4gDQo+IE9uIDE5 LjEyLjE5IDA2OjQ5LCBKdW5nbyBMaW4gd3JvdGU6DQo+ID4gVGhpcyBwYXRjaCBhZGRzIHRoZSBN ZWRpYXRlayBJU1AgUDEgSFcgY29udHJvbCBkZXZpY2UgZHJpdmVyLg0KPiA+IEl0IGhhbmRsZXMg dGhlIElTUCBIVyBjb25maWd1cmF0aW9uLCBwcm92aWRlcyBpbnRlcnJ1cHQgaGFuZGxpbmcgYW5k DQo+ID4gaW5pdGlhbGl6ZXMgdGhlIFY0TDIgZGV2aWNlIG5vZGVzIGFuZCBvdGhlciBWNEwyIGZ1 bmN0aW9ucy4gTW9yZW92ZXIsDQo+ID4gaW1wbGVtZW50IHN0YW5kYXJkIFY0TDIgdmlkZW8gZHJp dmVyIHRoYXQgdXRpbGl6ZXMgVjRMMiBhbmQgbWVkaWENCj4gPiBmcmFtZXdvcmsgQVBJcy4gSXQg c3VwcG9ydHMgb25lIG1lZGlhIGRldmljZSwgb25lIHN1Yi1kZXZpY2UgYW5kDQo+ID4gc2V2ZXJh bCB2aWRlbyBkZXZpY2VzIGR1cmluZyBpbml0aWFsaXphdGlvbi4gTW9yZW92ZXIsIGl0IGFsc28g Y29ubmVjdHMNCj4gPiB3aXRoIHNlbnNvciBhbmQgc2VuaW5mIGRyaXZlcnMgd2l0aCBWNEwyIGFz eW5jIEFQSXMuIENvbW11bmljYXRlIHdpdGgNCj4gPiBjby1wcm9jZXNzIHZpYSBTQ1AgY29tbXVu aWNhdGlvbiB0byBjb21wb3NlIElTUCByZWdpc3RlcnMgaW4gdGhlDQo+ID4gZmlybXdhcmUuDQo+ ID4gDQo+ID4gKFRoZSBjdXJyZW50IG1ldGFkYXRhIGludGVyZmFjZSB1c2VkIGluIG1ldGEgaW5w dXQgYW5kIHBhcnRpYWwNCj4gPiBtZXRhIG5vZGVzIGlzIG9ubHkgYSB0ZW1wb3Jhcnkgc29sdXRp b24gdG8ga2ljayBvZmYgdGhlIGRyaXZlcg0KPiA+IGRldmVsb3BtZW50IGFuZCBpcyBub3QgcmVh ZHkgdG8gYmUgcmV2aWV3ZWQgeWV0LikNCj4gPiANCj4gPiBTaWduZWQtb2ZmLWJ5OiBKdW5nbyBM aW4gPGp1bmdvLmxpbkBtZWRpYXRlay5jb20+DQo+ID4gU2lnbmVkLW9mZi1ieTogVG9tYXN6IEZp Z2EgPHRmaWdhQGNocm9taXVtLm9yZz4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBQaS1Ic3VuIFNoaWgg PHBpaHN1bkBjaHJvbWl1bS5vcmc+DQo+ID4gLS0tDQo+ID4gQ2hhbmdlcyBmcm9tIHY2Og0KPiA+ ICAgLSBSZXZpc2UgaGVscCBkZXNjcmlwdGlvbiBmb3IgVklERU9fTUVESUFURUtfSVNQX1BBU1Mx DQo+ID4gICAtIEFwcGx5IFNDUCB2MjEgY2hhbmdlIGluIFAxIGRyaXZlciBieSBQaS1Ic3VuIFNo aWgNCj4gPiAgIC0gQ29ycmVjdCBhdXRvIHN1c3BlbmQgdGltZXIgdmFsdWUgZm9yIHN1c3BlbmQv cmVzdW1lIGlzc3VlDQo+ID4gICAtIEluY3JlYXNlIElQSSBndWFyZCB0aW1lciB0byAxIHNlY29u ZCB0byBhdm9pZCBmYWxzZSBhbGFybSBjb21tYW5kIHRpbWVvdXQgZXZlbnQNCj4gPiAgIC0gRml4 IEtFIGR1ZSB0byBubyBzZW4taW5mIHN1Yi1kZXZpY2UNCj4gPiAtLS0NCj4gPiAgIGRyaXZlcnMv bWVkaWEvcGxhdGZvcm0vbXRrLWlzcC9LY29uZmlnICAgICAgICB8ICAgMjAgKw0KPiA+ICAgLi4u L21lZGlhL3BsYXRmb3JtL210ay1pc3AvaXNwXzUwL01ha2VmaWxlICAgIHwgICAgMyArDQo+ID4g ICAuLi4vcGxhdGZvcm0vbXRrLWlzcC9pc3BfNTAvY2FtL01ha2VmaWxlICAgICAgfCAgICA2ICsN Cj4gPiAgIC4uLi9wbGF0Zm9ybS9tdGstaXNwL2lzcF81MC9jYW0vbXRrX2NhbS1ody5jICB8ICA2 MzYgKysrKysNCj4gPiAgIC4uLi9wbGF0Zm9ybS9tdGstaXNwL2lzcF81MC9jYW0vbXRrX2NhbS1o dy5oICB8ICAgNjQgKw0KPiA+ICAgLi4uL3BsYXRmb3JtL210ay1pc3AvaXNwXzUwL2NhbS9tdGtf Y2FtLWlwaS5oIHwgIDIyMiArKw0KPiA+ICAgLi4uL210ay1pc3AvaXNwXzUwL2NhbS9tdGtfY2Ft LXJlZ3MuaCAgICAgICAgIHwgICA5NSArDQo+ID4gICAuLi4vcGxhdGZvcm0vbXRrLWlzcC9pc3Bf NTAvY2FtL210a19jYW0uYyAgICAgfCAyMDg3ICsrKysrKysrKysrKysrKysrDQo+ID4gICAuLi4v cGxhdGZvcm0vbXRrLWlzcC9pc3BfNTAvY2FtL210a19jYW0uaCAgICAgfCAgMjQ0ICsrDQo+ID4g ICA5IGZpbGVzIGNoYW5nZWQsIDMzNzcgaW5zZXJ0aW9ucygrKQ0KPiA+ICAgY3JlYXRlIG1vZGUg MTAwNjQ0IGRyaXZlcnMvbWVkaWEvcGxhdGZvcm0vbXRrLWlzcC9LY29uZmlnDQo+ID4gICBjcmVh dGUgbW9kZSAxMDA2NDQgZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL2lzcF81MC9NYWtl ZmlsZQ0KPiA+ICAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvbWVkaWEvcGxhdGZvcm0vbXRr LWlzcC9pc3BfNTAvY2FtL01ha2VmaWxlDQo+ID4gICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVy cy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL2lzcF81MC9jYW0vbXRrX2NhbS1ody5jDQo+ID4gICBj cmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL2lzcF81MC9j YW0vbXRrX2NhbS1ody5oDQo+ID4gICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9tZWRpYS9w bGF0Zm9ybS9tdGstaXNwL2lzcF81MC9jYW0vbXRrX2NhbS1pcGkuaA0KPiA+ICAgY3JlYXRlIG1v ZGUgMTAwNjQ0IGRyaXZlcnMvbWVkaWEvcGxhdGZvcm0vbXRrLWlzcC9pc3BfNTAvY2FtL210a19j YW0tcmVncy5oDQo+ID4gICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9tZWRpYS9wbGF0Zm9y bS9tdGstaXNwL2lzcF81MC9jYW0vbXRrX2NhbS5jDQo+ID4gICBjcmVhdGUgbW9kZSAxMDA2NDQg ZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL2lzcF81MC9jYW0vbXRrX2NhbS5oDQo+ID4g DQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vbXRrLWlzcC9LY29uZmln IGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL0tjb25maWcNCj4gPiBuZXcgZmlsZSBt b2RlIDEwMDY0NA0KPiA+IGluZGV4IDAwMDAwMDAwMDAwMC4uZjg2ZTFiNTlhZDFlDQo+ID4gLS0t IC9kZXYvbnVsbA0KPiA+ICsrKyBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vbXRrLWlzcC9LY29u ZmlnDQo+ID4gQEAgLTAsMCArMSwyMCBAQA0KPiA+ICtjb25maWcgVklERU9fTUVESUFURUtfSVNQ X1BBU1MxDQo+ID4gKwl0cmlzdGF0ZSAiTWVkaWF0ZWsgSVNQIFBhc3MgMSBkcml2ZXIiDQo+ID4g KwlkZXBlbmRzIG9uIFZJREVPX1Y0TDIgJiYgVklERU9fVjRMMl9TVUJERVZfQVBJDQo+ID4gKwlk ZXBlbmRzIG9uIEFSQ0hfTUVESUFURUsNCj4gPiArCXNlbGVjdCBWNEwyX0ZXTk9ERQ0KPiA+ICsJ c2VsZWN0IFZJREVPQlVGMl9WTUFMTE9DDQo+ID4gKwlzZWxlY3QgVklERU9CVUYyX0RNQV9DT05U SUcNCj4gPiArCXNlbGVjdCBNVEtfU0NQDQo+ID4gKwlkZWZhdWx0IG4NCj4gPiArCWhlbHANCj4g PiArCQlQYXNzIDEgZHJpdmVyIGNvbnRyb2xzIDNBIChhdXRvLWZvY3VzLCBleHBvc3VyZSwNCj4g PiArCQlhbmQgd2hpdGUgYmFsYW5jZSkgd2l0aCB0dW5pbmcgZmVhdHVyZSBhbmQgb3V0cHV0cw0K PiA+ICsJCXRoZSBjYXB0dXJlZCBpbWFnZSBidWZmZXJzIGluIE1lZGlhdGVrJ3MgY2FtZXJhIHN5 c3RlbS4NCj4gPiArDQo+ID4gKwkJQ2hvb3NlIFkgaWYgeW91IHdhbnQgdG8gdXNlIE1lZGlhdGVr IFNvQ3MgdG8gY3JlYXRlIGltYWdlDQo+ID4gKwkJY2FwdHVyZWQgYXBwbGljYXRpb24gc3VjaCBh cyB2aWRlbyByZWNvcmRpbmcgYW5kIHN0aWxsIGltYWdlDQo+ID4gKwkJY2FwdHVyaW5nLg0KPiA+ ICsNCj4gPiArCQlUbyBjb21waWxlIHRoaXMgZHJpdmVyIGFzIGEgbW9kdWxlLCBjaG9vc2UgTSBo ZXJlOyB0aGUgbW9kdWxlDQo+ID4gKwkJd2lsbCBiZSBjYWxsZWQgbXRrLWNhbS1pc3AuDQo+ID4g ZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vbXRrLWlzcC9pc3BfNTAvTWFrZWZp bGUgYi9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL210ay1pc3AvaXNwXzUwL01ha2VmaWxlDQo+ID4g bmV3IGZpbGUgbW9kZSAxMDA2NDQNCj4gPiBpbmRleCAwMDAwMDAwMDAwMDAuLmNlNzlkMjgzYjIw OQ0KPiA+IC0tLSAvZGV2L251bGwNCj4gPiArKysgYi9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL210 ay1pc3AvaXNwXzUwL01ha2VmaWxlDQo+ID4gQEAgLTAsMCArMSwzIEBADQo+ID4gKyMgU1BEWC1M aWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjANCj4gPiArDQo+ID4gK29iai0kKENPTkZJR19WSURF T19NRURJQVRFS19JU1BfUEFTUzEpICs9IGNhbS8NCj4gPiBcIE5vIG5ld2xpbmUgYXQgZW5kIG9m IGZpbGUNCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL2lz cF81MC9jYW0vTWFrZWZpbGUgYi9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL210ay1pc3AvaXNwXzUw L2NhbS9NYWtlZmlsZQ0KPiA+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0DQo+ID4gaW5kZXggMDAwMDAw MDAwMDAwLi41M2I1NGQzYzI2YTANCj4gPiAtLS0gL2Rldi9udWxsDQo+ID4gKysrIGIvZHJpdmVy cy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL2lzcF81MC9jYW0vTWFrZWZpbGUNCj4gPiBAQCAtMCww ICsxLDYgQEANCj4gPiArIyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMA0KPiA+ICsN Cj4gPiArbXRrLWNhbS1pc3Atb2JqcyArPSBtdGtfY2FtLm8NCj4gPiArbXRrLWNhbS1pc3Atb2Jq cyArPSBtdGtfY2FtLWh3Lm8NCj4gPiArDQo+ID4gK29iai0kKENPTkZJR19WSURFT19NRURJQVRF S19JU1BfUEFTUzEpICs9IG10ay1jYW0taXNwLm8NCj4gPiBcIE5vIG5ld2xpbmUgYXQgZW5kIG9m IGZpbGUNCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL2lz cF81MC9jYW0vbXRrX2NhbS1ody5jIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL2lz cF81MC9jYW0vbXRrX2NhbS1ody5jDQo+ID4gbmV3IGZpbGUgbW9kZSAxMDA2NDQNCj4gPiBpbmRl eCAwMDAwMDAwMDAwMDAuLjQwNjVkMGQyOWI3Zg0KPiA+IC0tLSAvZGV2L251bGwNCj4gPiArKysg Yi9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL210ay1pc3AvaXNwXzUwL2NhbS9tdGtfY2FtLWh3LmMN Cj4gPiBAQCAtMCwwICsxLDYzNiBAQA0KPiA+ICsvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjog R1BMLTIuMA0KPiA+ICsvLw0KPiA+ICsvLyBDb3B5cmlnaHQgKGMpIDIwMTkgTWVkaWFUZWsgSW5j Lg0KPiA+ICsNCj4gPiArI2luY2x1ZGUgPGxpbnV4L2F0b21pYy5oPg0KPiA+ICsjaW5jbHVkZSA8 bGludXgvY2xrLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9pbnRlcnJ1cHQuaD4NCj4gPiArI2lu Y2x1ZGUgPGxpbnV4L2lvcG9sbC5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvb2ZfcGxhdGZvcm0u aD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L29mX2lycS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgv bW9kdWxlLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9yZW1vdGVwcm9jL210a19zY3AuaD4NCj4g PiArI2luY2x1ZGUgPGxpbnV4L3BtX3J1bnRpbWUuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3Jl bW90ZXByb2MuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3NjaGVkLmg+DQo+ID4gKyNpbmNsdWRl IDxsaW51eC9zcGlubG9jay5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvdHlwZXMuaD4NCj4gPiAr I2luY2x1ZGUgPGxpbnV4L3ZpZGVvZGV2Mi5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvdm1hbGxv Yy5oPg0KPiA+ICsNCj4gPiArI2luY2x1ZGUgPG1lZGlhL3Y0bDItZXZlbnQuaD4NCj4gPiArDQo+ ID4gKyNpbmNsdWRlICJtdGtfY2FtLmgiDQo+ID4gKyNpbmNsdWRlICJtdGtfY2FtLWh3LmgiDQo+ ID4gKyNpbmNsdWRlICJtdGtfY2FtLXJlZ3MuaCINCj4gPiArDQo+ID4gKyNkZWZpbmUgTVRLX0lT UF9DT01QT1NFUl9NRU1fU0laRQkJMHgyMDAwMDANCj4gPiArI2RlZmluZSBNVEtfSVNQX0NRX0JV RkZFUl9DT1VOVAkJCTMNCj4gPiArI2RlZmluZSBNVEtfSVNQX0NRX0FERFJFU1NfT0ZGU0VUCQkw eDY0MA0KPiA+ICsNCj4gPiArLyoNCj4gPiArICoNCj4gPiArICogTVRLIENhbWVyYSBJU1AgUDEg SFcgc3VwcG9ydHMgMyBJU1AgSFcgKENBTSBBL0IvQykuDQo+ID4gKyAqIFRoZSBULXB1dCBjYXBh YmlsaXR5IG9mIENBTSBCIGlzIHRoZSBtYXhpbXVtIChtYXggbGluZSBidWZmZXI6IDUzNzYgcGl4 ZWxzKQ0KPiA+ICsgKiBGb3IgQ0FNIEEvQywgaXQgb25seSBzdXBwb3J0cyBtYXggbGluZSBidWZm ZXIgd2l0aCAzMzI4IHBpeGVscy4NCj4gPiArICogSW4gY3VycmVudCBkcml2ZXIsIG9ubHkgc3Vw cG9ydHMgQ0FNIEIuDQo+ID4gKyAqDQo+ID4gKyAqLw0KPiA+ICsjZGVmaW5lIE1US19JU1BfQ0FN X0lEX0IJCQkzDQo+ID4gKyNkZWZpbmUgTVRLX0lTUF9BVVRPU1VTUEVORF9ERUxBWV9NUwkJNjYN Cj4gPiArI2RlZmluZSBNVEtfSVNQX0lQSV9TRU5EX1RJTUVPVVQJCTEwMDANCj4gPiArI2RlZmlu ZSBNVEtfSVNQX1NUT1BfSFdfVElNRU9VVAkJCSgzMyAqIFVTRUNfUEVSX01TRUMpDQo+ID4gKw0K PiA+ICtzdGF0aWMgdm9pZCBpc3BfdHhfZnJhbWVfd29ya2VyKHN0cnVjdCB3b3JrX3N0cnVjdCAq d29yaykNCj4gPiArew0KPiA+ICsJc3RydWN0IG10a19jYW1fZGV2X3JlcXVlc3QgKnJlcSA9DQo+ ID4gKwkJY29udGFpbmVyX29mKHdvcmssIHN0cnVjdCBtdGtfY2FtX2Rldl9yZXF1ZXN0LCBmcmFt ZV93b3JrKTsNCj4gPiArCXN0cnVjdCBtdGtfY2FtX2RldiAqY2FtID0NCj4gPiArCQljb250YWlu ZXJfb2YocmVxLT5yZXEubWRldiwgc3RydWN0IG10a19jYW1fZGV2LCBtZWRpYV9kZXYpOw0KPiA+ ICsJc3RydWN0IG10a19pc3BfcDFfZGV2aWNlICpwMV9kZXYgPSBkZXZfZ2V0X2RydmRhdGEoY2Ft LT5kZXYpOw0KPiA+ICsNCj4gPiArCXNjcF9pcGlfc2VuZChwMV9kZXYtPnNjcCwgU0NQX0lQSV9J U1BfRlJBTUUsICZyZXEtPmZyYW1lX3BhcmFtcywNCj4gPiArCQkgICAgIHNpemVvZihyZXEtPmZy YW1lX3BhcmFtcyksIE1US19JU1BfSVBJX1NFTkRfVElNRU9VVCk7DQo+ID4gK30NCj4gPiArDQo+ ID4gK3N0YXRpYyB2b2lkIGlzcF9jb21wb3Nlcl9oYW5kbGVyKHZvaWQgKmRhdGEsIHVuc2lnbmVk IGludCBsZW4sIHZvaWQgKnByaXYpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtfaXNwX3AxX2Rl dmljZSAqcDFfZGV2ID0gKHN0cnVjdCBtdGtfaXNwX3AxX2RldmljZSAqKXByaXY7DQo+ID4gKwlz dHJ1Y3QgZGV2aWNlICpkZXYgPSBwMV9kZXYtPmRldjsNCj4gPiArCXN0cnVjdCBtdGtfaXNwX3Nj cF9wMV9jbWQgKmlwaV9tc2c7DQo+ID4gKw0KPiA+ICsJaXBpX21zZyA9IChzdHJ1Y3QgbXRrX2lz cF9zY3BfcDFfY21kICopZGF0YTsNCj4gPiArDQo+ID4gKwlpZiAobGVuIDwgb2Zmc2V0b2ZlbmQo c3RydWN0IG10a19pc3Bfc2NwX3AxX2NtZCwgYWNrX2luZm8pKSB7DQo+ID4gKwkJZGV2X2Vycihk ZXYsICJ3cm9uZyBJUEkgbGVuOiVkXG4iLCBsZW4pOw0KPiA+ICsJCXJldHVybjsNCj4gPiArCX0N Cj4gPiArDQo+ID4gKwlpZiAoaXBpX21zZy0+Y21kX2lkICE9IElTUF9DTURfQUNLIHx8DQo+ID4g KwkgICAgaXBpX21zZy0+YWNrX2luZm8uY21kX2lkICE9IElTUF9DTURfRlJBTUVfQUNLKQ0KPiA+ ICsJCXJldHVybjsNCj4gPiArDQo+ID4gKwlwMV9kZXYtPmNvbXBvc2VkX2ZyYW1lX3NlcV9ubyA9 IGlwaV9tc2ctPmFja19pbmZvLmZyYW1lX3NlcV9ubzsNCj4gPiArCWRldl9kYmcoZGV2LCAiYWNr IGZyYW1lX251bTolZFxuIiwgcDFfZGV2LT5jb21wb3NlZF9mcmFtZV9zZXFfbm8pOw0KPiA+ICt9 DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGlzcF9jb21wb3Nlcl9pbml0KHN0cnVjdCBtdGtfaXNw X3AxX2RldmljZSAqcDFfZGV2KQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSBw MV9kZXYtPmRldjsNCj4gPiArCWludCByZXQ7DQo+ID4gKw0KPiA+ICsJcmV0ID0gc2NwX2lwaV9y ZWdpc3RlcihwMV9kZXYtPnNjcCwgU0NQX0lQSV9JU1BfQ01ELA0KPiA+ICsJCQkgICAgICAgaXNw X2NvbXBvc2VyX2hhbmRsZXIsIHAxX2Rldik7DQo+ID4gKwlpZiAocmV0KSB7DQo+ID4gKwkJZGV2 X2VycihkZXYsICJmYWlsZWQgdG8gcmVnaXN0ZXIgSVBJIGNtZFxuIik7DQo+ID4gKwkJcmV0dXJu IHJldDsNCj4gPiArCX0NCj4gPiArCXJldCA9IHNjcF9pcGlfcmVnaXN0ZXIocDFfZGV2LT5zY3As IFNDUF9JUElfSVNQX0ZSQU1FLA0KPiA+ICsJCQkgICAgICAgaXNwX2NvbXBvc2VyX2hhbmRsZXIs IHAxX2Rldik7DQo+ID4gKwlpZiAocmV0KSB7DQo+ID4gKwkJZGV2X2VycihkZXYsICJmYWlsZWQg dG8gcmVnaXN0ZXIgSVBJIGZyYW1lXG4iKTsNCj4gPiArCQlnb3RvIHVucmVnX2lwaV9jbWQ7DQo+ ID4gKwl9DQo+ID4gKw0KPiA+ICsJcDFfZGV2LT5jb21wb3Nlcl93cSA9DQo+ID4gKwkJYWxsb2Nf b3JkZXJlZF93b3JrcXVldWUoZGV2X25hbWUocDFfZGV2LT5kZXYpLA0KPiA+ICsJCQkJCV9fV1Ff TEVHQUNZIHwgV1FfTUVNX1JFQ0xBSU0gfA0KPiA+ICsJCQkJCVdRX0ZSRUVaQUJMRSk7DQo+ID4g KwlpZiAoIXAxX2Rldi0+Y29tcG9zZXJfd3EpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgImZhaWxl ZCB0byBhbGxvYyBjb21wb3NlciB3b3JrcXVldWVcbiIpOw0KPiA+ICsJCWdvdG8gdW5yZWdfaXBp X2ZyYW1lOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICsNCj4gPiArdW5y ZWdfaXBpX2ZyYW1lOg0KPiA+ICsJc2NwX2lwaV91bnJlZ2lzdGVyKHAxX2Rldi0+c2NwLCBTQ1Bf SVBJX0lTUF9GUkFNRSk7DQo+ID4gK3VucmVnX2lwaV9jbWQ6DQo+ID4gKwlzY3BfaXBpX3VucmVn aXN0ZXIocDFfZGV2LT5zY3AsIFNDUF9JUElfSVNQX0NNRCk7DQo+ID4gKw0KPiA+ICsJcmV0dXJu IHJldDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIHZvaWQgaXNwX2NvbXBvc2VyX3VuaW5p dChzdHJ1Y3QgbXRrX2lzcF9wMV9kZXZpY2UgKnAxX2RldikNCj4gPiArew0KPiA+ICsJZGVzdHJv eV93b3JrcXVldWUocDFfZGV2LT5jb21wb3Nlcl93cSk7DQo+ID4gKwlzY3BfaXBpX3VucmVnaXN0 ZXIocDFfZGV2LT5zY3AsIFNDUF9JUElfSVNQX0NNRCk7DQo+ID4gKwlzY3BfaXBpX3VucmVnaXN0 ZXIocDFfZGV2LT5zY3AsIFNDUF9JUElfSVNQX0ZSQU1FKTsNCj4gPiArfQ0KPiA+ICsNCj4gPiAr c3RhdGljIHZvaWQgaXNwX2NvbXBvc2VyX2h3X2luaXQoc3RydWN0IG10a19pc3BfcDFfZGV2aWNl ICpwMV9kZXYpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtfaXNwX3NjcF9wMV9jbWQgY29tcG9z ZXJfdHhfY21kOw0KPiA+ICsNCj4gPiArCW1lbXNldCgmY29tcG9zZXJfdHhfY21kLCAwLCBzaXpl b2YoY29tcG9zZXJfdHhfY21kKSk7DQo+ID4gKwljb21wb3Nlcl90eF9jbWQuY21kX2lkID0gSVNQ X0NNRF9JTklUOw0KPiA+ICsJY29tcG9zZXJfdHhfY21kLmluaXRfcGFyYW0uaHdfbW9kdWxlID0g TVRLX0lTUF9DQU1fSURfQjsNCj4gPiArDQo+ID4gKwkvKg0KPiA+ICsJICogUGFzc2VkIGNvaGVy ZW50IHJlc2VydmVkIG1lbW9yeSBpbmZvLiBmb3IgU0NQIGZpcm13YXJlIHVzYWdlLg0KPiA+ICsJ ICogVGhpcyBidWZmZXIgaXMgdXNlZCBmb3IgU0NQJ3MgSVNQIGNvbXBvc2VyIHRvIGNvbXBvc2Uu DQo+ID4gKwkgKiBUaGUgc2l6ZSBvZiBpcyBmaXhlZCB0byAweDIwMDAwMCBmb3IgdGhlIHJlcXVp cmVtZW50IG9mIGNvbXBvc2VyLg0KPiA+ICsJICovDQo+ID4gKwljb21wb3Nlcl90eF9jbWQuaW5p dF9wYXJhbS5jcV9hZGRyLmlvdmEgPSBwMV9kZXYtPmNvbXBvc2VyX2lvdmE7DQo+ID4gKwljb21w b3Nlcl90eF9jbWQuaW5pdF9wYXJhbS5jcV9hZGRyLnNjcF9hZGRyID0gcDFfZGV2LT5jb21wb3Nl cl9zY3BfYWRkcjsNCj4gPiArDQo+ID4gKwlzY3BfaXBpX3NlbmQocDFfZGV2LT5zY3AsIFNDUF9J UElfSVNQX0NNRCwgJmNvbXBvc2VyX3R4X2NtZCwNCj4gPiArCQkgICAgIHNpemVvZihjb21wb3Nl cl90eF9jbWQpLCBNVEtfSVNQX0lQSV9TRU5EX1RJTUVPVVQpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ ICtzdGF0aWMgdm9pZCBpc3BfY29tcG9zZXJfaHdfZGVpbml0KHN0cnVjdCBtdGtfaXNwX3AxX2Rl dmljZSAqcDFfZGV2KQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgbXRrX2lzcF9zY3BfcDFfY21kIGNv bXBvc2VyX3R4X2NtZDsNCj4gPiArDQo+ID4gKwltZW1zZXQoJmNvbXBvc2VyX3R4X2NtZCwgMCwg c2l6ZW9mKGNvbXBvc2VyX3R4X2NtZCkpOw0KPiA+ICsJY29tcG9zZXJfdHhfY21kLmNtZF9pZCA9 IElTUF9DTURfREVJTklUOw0KPiA+ICsNCj4gPiArCXNjcF9pcGlfc2VuZChwMV9kZXYtPnNjcCwg U0NQX0lQSV9JU1BfQ01ELCAmY29tcG9zZXJfdHhfY21kLA0KPiA+ICsJCSAgICAgc2l6ZW9mKGNv bXBvc2VyX3R4X2NtZCksIE1US19JU1BfSVBJX1NFTkRfVElNRU9VVCk7DQo+ID4gKw0KPiA+ICsJ aXNwX2NvbXBvc2VyX3VuaW5pdChwMV9kZXYpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICt2b2lkIG10 a19pc3BfaHdfY29uZmlnKHN0cnVjdCBtdGtfY2FtX2RldiAqY2FtLA0KPiA+ICsJCSAgICAgICBz dHJ1Y3QgcDFfY29uZmlnX3BhcmFtICpjb25maWdfcGFyYW0pDQo+ID4gK3sNCj4gPiArCXN0cnVj dCBtdGtfaXNwX3NjcF9wMV9jbWQgY29tcG9zZXJfdHhfY21kOw0KPiA+ICsJc3RydWN0IG10a19p c3BfcDFfZGV2aWNlICpwMV9kZXYgPSBkZXZfZ2V0X2RydmRhdGEoY2FtLT5kZXYpOw0KPiA+ICsN Cj4gPiArCW1lbXNldCgmY29tcG9zZXJfdHhfY21kLCAwLCBzaXplb2YoY29tcG9zZXJfdHhfY21k KSk7DQo+ID4gKwljb21wb3Nlcl90eF9jbWQuY21kX2lkID0gSVNQX0NNRF9DT05GSUc7DQo+ID4g KwltZW1jcHkoJmNvbXBvc2VyX3R4X2NtZC5jb25maWdfcGFyYW0sIGNvbmZpZ19wYXJhbSwNCj4g PiArCSAgICAgICBzaXplb2YoKmNvbmZpZ19wYXJhbSkpOw0KPiA+ICsNCj4gPiArCXNjcF9pcGlf c2VuZChwMV9kZXYtPnNjcCwgU0NQX0lQSV9JU1BfQ01ELCAmY29tcG9zZXJfdHhfY21kLA0KPiA+ ICsJCSAgICAgc2l6ZW9mKGNvbXBvc2VyX3R4X2NtZCksIE1US19JU1BfSVBJX1NFTkRfVElNRU9V VCk7DQo+ID4gK30NCj4gPiArDQo+ID4gK3ZvaWQgbXRrX2lzcF9zdHJlYW0oc3RydWN0IG10a19j YW1fZGV2ICpjYW0sIGludCBvbikNCj4gPiArew0KPiA+ICsJc3RydWN0IG10a19pc3Bfc2NwX3Ax X2NtZCBjb21wb3Nlcl90eF9jbWQ7DQo+ID4gKwlzdHJ1Y3QgbXRrX2lzcF9wMV9kZXZpY2UgKnAx X2RldiA9IGRldl9nZXRfZHJ2ZGF0YShjYW0tPmRldik7DQo+ID4gKw0KPiA+ICsJbWVtc2V0KCZj b21wb3Nlcl90eF9jbWQsIDAsIHNpemVvZihjb21wb3Nlcl90eF9jbWQpKTsNCj4gPiArCWNvbXBv c2VyX3R4X2NtZC5jbWRfaWQgPSBJU1BfQ01EX1NUUkVBTTsNCj4gPiArCWNvbXBvc2VyX3R4X2Nt ZC5pc19zdHJlYW1fb24gPSBvbjsNCj4gPiArDQo+ID4gKwlzY3BfaXBpX3NlbmQocDFfZGV2LT5z Y3AsIFNDUF9JUElfSVNQX0NNRCwgJmNvbXBvc2VyX3R4X2NtZCwNCj4gPiArCQkgICAgIHNpemVv Zihjb21wb3Nlcl90eF9jbWQpLCBNVEtfSVNQX0lQSV9TRU5EX1RJTUVPVVQpOw0KPiA+ICt9DQo+ ID4gKw0KPiA+ICtpbnQgbXRrX2lzcF9od19pbml0KHN0cnVjdCBtdGtfY2FtX2RldiAqY2FtKQ0K PiA+ICt7DQo+ID4gKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSBjYW0tPmRldjsNCj4gPiArCXN0cnVj dCBtdGtfaXNwX3AxX2RldmljZSAqcDFfZGV2ID0gZGV2X2dldF9kcnZkYXRhKGRldik7DQo+ID4g KwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCXJldCA9IHJwcm9jX2Jvb3QocDFfZGV2LT5ycHJvY19o YW5kbGUpOw0KPiA+ICsJaWYgKHJldCkgew0KPiA+ICsJCWRldl9lcnIoZGV2LCAiZmFpbGVkIHRv IHJwcm9jX2Jvb3RcbiIpOw0KPiA+ICsJCXJldHVybiByZXQ7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ ICsJcmV0ID0gaXNwX2NvbXBvc2VyX2luaXQocDFfZGV2KTsNCj4gPiArCWlmIChyZXQpDQo+ID4g KwkJcmV0dXJuIHJldDsNCj4gPiArDQo+ID4gKwlwbV9ydW50aW1lX2dldF9zeW5jKGRldik7DQo+ ID4gKwlpc3BfY29tcG9zZXJfaHdfaW5pdChwMV9kZXYpOw0KPiA+ICsNCj4gPiArCXAxX2Rldi0+ ZW5xdWV1ZWRfZnJhbWVfc2VxX25vID0gMDsNCj4gPiArCXAxX2Rldi0+ZGVxdWV1ZWRfZnJhbWVf c2VxX25vID0gMDsNCj4gPiArCXAxX2Rldi0+Y29tcG9zZWRfZnJhbWVfc2VxX25vID0gMDsNCj4g PiArCXAxX2Rldi0+c29mX2NvdW50ID0gMDsNCj4gPiArDQo+ID4gKwlkZXZfZGJnKGRldiwgIiVz IGRvbmVcbiIsIF9fZnVuY19fKTsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ ICsNCj4gPiAraW50IG10a19pc3BfaHdfcmVsZWFzZShzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSkN Cj4gPiArew0KPiA+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gY2FtLT5kZXY7DQo+ID4gKwlzdHJ1 Y3QgbXRrX2lzcF9wMV9kZXZpY2UgKnAxX2RldiA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOw0KPiA+ ICsNCj4gPiArCWlzcF9jb21wb3Nlcl9od19kZWluaXQocDFfZGV2KTsNCj4gPiArCXBtX3J1bnRp bWVfbWFya19sYXN0X2J1c3koZGV2KTsNCj4gPiArCXBtX3J1bnRpbWVfcHV0X2F1dG9zdXNwZW5k KGRldik7DQo+ID4gKwlycHJvY19zaHV0ZG93bihwMV9kZXYtPnJwcm9jX2hhbmRsZSk7DQo+ID4g Kw0KPiA+ICsJZGV2X2RiZyhkZXYsICIlcyBkb25lXG4iLCBfX2Z1bmNfXyk7DQo+ID4gKw0KPiA+ ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3ZvaWQgbXRrX2lzcF9yZXFfZW5xdWV1 ZShzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSwNCj4gPiArCQkJIHN0cnVjdCBtdGtfY2FtX2Rldl9y ZXF1ZXN0ICpyZXEpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtfaXNwX3AxX2RldmljZSAqcDFf ZGV2ID0gZGV2X2dldF9kcnZkYXRhKGNhbS0+ZGV2KTsNCj4gPiArDQo+ID4gKwkvKiBBY2N1bXVs YXRlZCBmcmFtZSBzZXF1ZW5jZSBudW1iZXIgKi8NCj4gPiArCXJlcS0+ZnJhbWVfcGFyYW1zLmZy YW1lX3NlcV9ubyA9ICsrcDFfZGV2LT5lbnF1ZXVlZF9mcmFtZV9zZXFfbm87DQo+ID4gKw0KPiA+ ICsJSU5JVF9XT1JLKCZyZXEtPmZyYW1lX3dvcmssIGlzcF90eF9mcmFtZV93b3JrZXIpOw0KPiA+ ICsJcXVldWVfd29yayhwMV9kZXYtPmNvbXBvc2VyX3dxLCAmcmVxLT5mcmFtZV93b3JrKTsNCj4g PiArCWRldl9kYmcoY2FtLT5kZXYsICJlbnF1ZXVlIGZkOiVzIGZyYW1lX3NlcV9ubzolZCBqb2Ig Y250OiVkXG4iLA0KPiA+ICsJCXJlcS0+cmVxLmRlYnVnX3N0ciwgcmVxLT5mcmFtZV9wYXJhbXMu ZnJhbWVfc2VxX25vLA0KPiA+ICsJCWNhbS0+cnVubmluZ19qb2JfY291bnQpOw0KPiA+ICt9DQo+ ID4gKw0KPiA+ICtzdGF0aWMgdm9pZCBpc3BfaXJxX2hhbmRsZV9zb2Yoc3RydWN0IG10a19pc3Bf cDFfZGV2aWNlICpwMV9kZXYsDQo+ID4gKwkJCSAgICAgICB1bnNpZ25lZCBpbnQgZGVxdWV1ZWRf ZnJhbWVfc2VxX25vKQ0KPiA+ICt7DQo+ID4gKwlkbWFfYWRkcl90IGJhc2VfYWRkciA9IHAxX2Rl di0+Y29tcG9zZXJfaW92YTsNCj4gPiArCXN0cnVjdCBkZXZpY2UgKmRldiA9IHAxX2Rldi0+ZGV2 Ow0KPiA+ICsJc3RydWN0IG10a19jYW1fZGV2X3JlcXVlc3QgKnJlcTsNCj4gPiArCWludCBjb21w b3NlZF9mcmFtZV9zZXFfbm8gPSBwMV9kZXYtPmNvbXBvc2VkX2ZyYW1lX3NlcV9ubzsNCj4gPiAr CXVuc2lnbmVkIGludCBhZGRyX29mZnNldDsNCj4gPiArDQo+ID4gKwkvKiBTZW5kIFY0TDJfRVZF TlRfRlJBTUVfU1lOQyBldmVudCAqLw0KPiA+ICsJbXRrX2NhbV9kZXZfZXZlbnRfZnJhbWVfc3lu YygmcDFfZGV2LT5jYW1fZGV2LCBkZXF1ZXVlZF9mcmFtZV9zZXFfbm8pOw0KPiA+ICsNCj4gPiAr CXAxX2Rldi0+c29mX2NvdW50ICs9IDE7DQo+ID4gKwkvKiBTYXZlIGZyYW1lIGluZm9ybWF0aW9u ICovDQo+ID4gKwlwMV9kZXYtPmRlcXVldWVkX2ZyYW1lX3NlcV9ubyA9IGRlcXVldWVkX2ZyYW1l X3NlcV9ubzsNCj4gPiArDQo+ID4gKwlyZXEgPSBtdGtfY2FtX2Rldl9nZXRfcmVxKCZwMV9kZXYt PmNhbV9kZXYsIGRlcXVldWVkX2ZyYW1lX3NlcV9ubyk7DQo+ID4gKwlpZiAocmVxKQ0KPiA+ICsJ CXJlcS0+dGltZXN0YW1wID0ga3RpbWVfZ2V0X2Jvb3R0aW1lX25zKCk7DQo+ID4gKw0KPiA+ICsJ LyogVXBkYXRlIENRIGJhc2UgYWRkcmVzcyBpZiBuZWVkZWQgKi8NCj4gPiArCWlmIChjb21wb3Nl ZF9mcmFtZV9zZXFfbm8gPD0gZGVxdWV1ZWRfZnJhbWVfc2VxX25vKSB7DQo+ID4gKwkJZGV2X2Ri ZyhkZXYsDQo+ID4gKwkJCSJTT0ZfSU5UX1NULCBubyB1cGRhdGUsIGNxX251bTolZCwgZnJhbWVf c2VxOiVkXG4iLA0KPiA+ICsJCQljb21wb3NlZF9mcmFtZV9zZXFfbm8sIGRlcXVldWVkX2ZyYW1l X3NlcV9ubyk7DQo+ID4gKwkJcmV0dXJuOw0KPiA+ICsJfQ0KPiA+ICsJYWRkcl9vZmZzZXQgPSBN VEtfSVNQX0NRX0FERFJFU1NfT0ZGU0VUICoNCj4gPiArCQkoZGVxdWV1ZWRfZnJhbWVfc2VxX25v ICUgTVRLX0lTUF9DUV9CVUZGRVJfQ09VTlQpOw0KPiA+ICsJd3JpdGVsKGJhc2VfYWRkciArIGFk ZHJfb2Zmc2V0LCBwMV9kZXYtPnJlZ3MgKyBSRUdfQ1FfVEhSMF9CQVNFQUREUik7DQo+ID4gKwlk ZXZfZGJnKGRldiwNCj4gPiArCQkiU09GX0lOVF9TVCwgdXBkYXRlIG5leHQsIGNxX251bTolZCwg ZnJhbWVfc2VxOiVkIGNxX2FkZHI6MHgleFxuIiwNCj4gPiArCQljb21wb3NlZF9mcmFtZV9zZXFf bm8sIGRlcXVldWVkX2ZyYW1lX3NlcV9ubywgYWRkcl9vZmZzZXQpOw0KPiA+ICt9DQo+ID4gKw0K PiA+ICtzdGF0aWMgdm9pZCBpc3BfaXJxX2hhbmRsZV9kbWFfZXJyKHN0cnVjdCBtdGtfaXNwX3Ax X2RldmljZSAqcDFfZGV2KQ0KPiA+ICt7DQo+ID4gKwl1MzIgdmFsOw0KPiA+ICsNCj4gPiArCWRl dl9lcnIocDFfZGV2LT5kZXYsDQo+ID4gKwkJIklNR086MHgleCwgUlJaTzoweCV4LCBBQU89MHgl eCwgQUZPPTB4JXgsIExNVk89MHgleFxuIiwNCj4gPiArCQlyZWFkbChwMV9kZXYtPnJlZ3MgKyBS RUdfSU1HT19FUlJfU1RBVCksDQo+ID4gKwkJcmVhZGwocDFfZGV2LT5yZWdzICsgUkVHX1JSWk9f RVJSX1NUQVQpLA0KPiA+ICsJCXJlYWRsKHAxX2Rldi0+cmVncyArIFJFR19BQU9fRVJSX1NUQVQp LA0KPiA+ICsJCXJlYWRsKHAxX2Rldi0+cmVncyArIFJFR19BRk9fRVJSX1NUQVQpLA0KPiA+ICsJ CXJlYWRsKHAxX2Rldi0+cmVncyArIFJFR19MTVZPX0VSUl9TVEFUKSk7DQo+ID4gKwlkZXZfZXJy KHAxX2Rldi0+ZGV2LA0KPiA+ICsJCSJMQ1NPPTB4JXgsIFBTTz0weCV4LCBGTEtPPTB4JXgsIEJQ Q0k6MHgleCwgTFNDST0weCV4XG4iLA0KPiA+ICsJCXJlYWRsKHAxX2Rldi0+cmVncyArIFJFR19M Q1NPX0VSUl9TVEFUKSwNCj4gPiArCQlyZWFkbChwMV9kZXYtPnJlZ3MgKyBSRUdfUFNPX0VSUl9T VEFUKSwNCj4gPiArCQlyZWFkbChwMV9kZXYtPnJlZ3MgKyBSRUdfRkxLT19FUlJfU1RBVCksDQo+ ID4gKwkJcmVhZGwocDFfZGV2LT5yZWdzICsgUkVHX0JQQ0lfRVJSX1NUQVQpLA0KPiA+ICsJCXJl YWRsKHAxX2Rldi0+cmVncyArIFJFR19MU0NJX0VSUl9TVEFUKSk7DQo+ID4gKw0KPiA+ICsJLyog RGlzYWJsZSBETUEgZXJyb3IgbWFzayB0byBhdm9pZCB0b28gbXVjaCBlcnJvciBsb2cgKi8NCj4g PiArCXZhbCA9IHJlYWRsKHAxX2Rldi0+cmVncyArIFJFR19DVExfUkFXX0lOVF9FTik7DQo+ID4g Kwl3cml0ZWwoKHZhbCAmICh+RE1BX0VSUl9JTlRfRU4pKSwgcDFfZGV2LT5yZWdzICsgUkVHX0NU TF9SQVdfSU5UX0VOKTsNCj4gPiArCWRldl9kYmcocDFfZGV2LT5kZXYsICJkaXNhYmxlIERNQSBl cnJvciBtYXNrOjB4JXhcbiIsIHZhbCk7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpcnFy ZXR1cm5fdCBpc3BfaXJxX2NhbShpbnQgaXJxLCB2b2lkICpkYXRhKQ0KPiA+ICt7DQo+ID4gKwlz dHJ1Y3QgbXRrX2lzcF9wMV9kZXZpY2UgKnAxX2RldiA9IChzdHJ1Y3QgbXRrX2lzcF9wMV9kZXZp Y2UgKilkYXRhOw0KPiA+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gcDFfZGV2LT5kZXY7DQo+ID4g Kwl1bnNpZ25lZCBpbnQgZGVxdWV1ZWRfZnJhbWVfc2VxX25vOw0KPiA+ICsJdW5zaWduZWQgaW50 IGlycV9zdGF0dXMsIGVycl9zdGF0dXMsIGRtYV9zdGF0dXM7DQo+ID4gKwl1bnNpZ25lZCBsb25n IGZsYWdzOw0KPiA+ICsNCj4gPiArCXNwaW5fbG9ja19pcnFzYXZlKCZwMV9kZXYtPnNwaW5sb2Nr X2lycSwgZmxhZ3MpOw0KPiA+ICsJaXJxX3N0YXR1cyA9IHJlYWRsKHAxX2Rldi0+cmVncyArIFJF R19DVExfUkFXX0lOVF9TVEFUKTsNCj4gPiArCWVycl9zdGF0dXMgPSBpcnFfc3RhdHVzICYgSU5U X1NUX01BU0tfQ0FNX0VSUjsNCj4gPiArCWRtYV9zdGF0dXMgPSByZWFkbChwMV9kZXYtPnJlZ3Mg KyBSRUdfQ1RMX1JBV19JTlQyX1NUQVQpOw0KPiA+ICsJZGVxdWV1ZWRfZnJhbWVfc2VxX25vID0g cmVhZGwocDFfZGV2LT5yZWdzICsgUkVHX0ZSQU1FX1NFUV9OVU0pOw0KPiA+ICsJc3Bpbl91bmxv Y2tfaXJxcmVzdG9yZSgmcDFfZGV2LT5zcGlubG9ja19pcnEsIGZsYWdzKTsNCj4gPiArDQo+ID4g KwkvKg0KPiA+ICsJICogSW4gbm9ybWFsIGNhc2UsIHRoZSBuZXh0IFNPRiBJU1Igc2hvdWxkIGNv bWUgYWZ0ZXIgSFcgUEFTUzEgRE9ORSBJU1IuDQo+ID4gKwkgKiBJZiB0aGVzZSB0d28gSVNScyBj b21lIHRvZ2V0aGVyLCBwcmludCB3YXJuaW5nIG1zZyB0byBoaW50Lg0KPiA+ICsJICovDQo+ID4g KwlpZiAoKGlycV9zdGF0dXMgJiBTT0ZfSU5UX1NUKSAmJiAoaXJxX3N0YXR1cyAmIEhXX1BBU1Mx X0RPTl9TVCkpDQo+ID4gKwkJZGV2X2RiZyhkZXYsICJzb2ZfZG9uZSBibG9jayBjbnQ6JWRcbiIs IHAxX2Rldi0+c29mX2NvdW50KTsNCj4gPiArDQo+ID4gKwkvKiBEZS1xdWV1ZSBmcmFtZSAqLw0K PiA+ICsJaWYgKGlycV9zdGF0dXMgJiBTV19QQVNTMV9ET05fU1QpIHsNCj4gPiArCQltdGtfY2Ft X2Rldl9kZXF1ZXVlX3JlcV9mcmFtZSgmcDFfZGV2LT5jYW1fZGV2LA0KPiA+ICsJCQkJCSAgICAg IHAxX2Rldi0+ZGVxdWV1ZWRfZnJhbWVfc2VxX25vKTsNCj4gPiArCQltdGtfY2FtX2Rldl9yZXFf dHJ5X3F1ZXVlKCZwMV9kZXYtPmNhbV9kZXYpOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCS8qIFNh dmUgZnJhbWUgaW5mby4gJiB1cGRhdGUgQ1EgYWRkcmVzcyBmb3IgZnJhbWUgSFcgZW4tcXVldWUg Ki8NCj4gPiArCWlmIChpcnFfc3RhdHVzICYgU09GX0lOVF9TVCkNCj4gPiArCQlpc3BfaXJxX2hh bmRsZV9zb2YocDFfZGV2LCBkZXF1ZXVlZF9mcmFtZV9zZXFfbm8pOw0KPiA+ICsNCj4gPiArCS8q IENoZWNrIElTUCBlcnJvciBzdGF0dXMgKi8NCj4gPiArCWlmIChlcnJfc3RhdHVzKSB7DQo+ID4g KwkJZGV2X2VycihkZXYsICJpbnRfZXJyOjB4JXggMHgleFxuIiwgaXJxX3N0YXR1cywgZXJyX3N0 YXR1cyk7DQo+ID4gKwkJLyogU2hvdyBETUEgZXJyb3JzIGluIGRldGFpbCAqLw0KPiA+ICsJCWlm IChlcnJfc3RhdHVzICYgRE1BX0VSUl9TVCkNCj4gPiArCQkJaXNwX2lycV9oYW5kbGVfZG1hX2Vy cihwMV9kZXYpOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCWRldl9kYmcoZGV2LCAiU09GOiVkIGly cToweCV4LCBkbWE6MHgleCwgZnJhbWVfbnVtOiVkXG4iLA0KPiA+ICsJCXAxX2Rldi0+c29mX2Nv dW50LCBpcnFfc3RhdHVzLCBkbWFfc3RhdHVzLA0KPiA+ICsJCWRlcXVldWVkX2ZyYW1lX3NlcV9u byk7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIElSUV9IQU5ETEVEOw0KPiA+ICt9DQo+ID4gKw0KPiA+ ICtzdGF0aWMgaW50IGlzcF9zZXR1cF9zY3BfcnByb2Moc3RydWN0IG10a19pc3BfcDFfZGV2aWNl ICpwMV9kZXYsDQo+ID4gKwkJCSAgICAgICBzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQ0K PiA+ICt7DQo+ID4gKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSBwMV9kZXYtPmRldjsNCj4gPiArCWRt YV9hZGRyX3QgYWRkcjsNCj4gPiArCXZvaWQgKnB0cjsNCj4gPiArCWludCByZXQ7DQo+ID4gKw0K PiA+ICsJcDFfZGV2LT5zY3AgPSBzY3BfZ2V0KHBkZXYpOw0KPiA+ICsJaWYgKCFwMV9kZXYtPnNj cCkgew0KPiA+ICsJCWRldl9lcnIoZGV2LCAiZmFpbGVkIHRvIGdldCBzY3AgZGV2aWNlXG4iKTsN Cj4gPiArCQlyZXR1cm4gLUVOT0RFVjsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlwMV9kZXYtPnJw cm9jX2hhbmRsZSA9IHNjcF9nZXRfcnByb2MocDFfZGV2LT5zY3ApOw0KPiA+ICsJZGV2X2RiZyhk ZXYsICJwMSBycHJvY19waGFuZGxlOiAweCVwS1xuIiwgcDFfZGV2LT5ycHJvY19oYW5kbGUpOw0K PiA+ICsJcDFfZGV2LT5jYW1fZGV2LnNtZW1fZGV2ID0gc2NwX2dldF9kZXZpY2UocDFfZGV2LT5z Y3ApOw0KPiA+ICsNCj4gPiArCS8qDQo+ID4gKwkgKiBBbGxvY2F0ZSBjb2hlcmVudCByZXNlcnZl ZCBtZW1vcnkgZm9yIFNDUCBmaXJtd2FyZSB1c2FnZS4NCj4gPiArCSAqIFRoZSBzaXplIG9mIFND UCBjb21wb3NlcidzIG1lbW9yeSBpcyBmaXhlZCB0byAweDIwMDAwMA0KPiA+ICsJICogZm9yIHRo ZSByZXF1aXJlbWVudCBvZiBmaXJtd2FyZS4NCj4gPiArCSAqLw0KPiA+ICsJcHRyID0gZG1hX2Fs bG9jX2NvaGVyZW50KHAxX2Rldi0+Y2FtX2Rldi5zbWVtX2RldiwNCj4gPiArCQkJCSBNVEtfSVNQ X0NPTVBPU0VSX01FTV9TSVpFLCAmYWRkciwgR0ZQX0tFUk5FTCk7DQo+ID4gKwlpZiAoIXB0cikg ew0KPiA+ICsJCXJldCA9IC1FTk9NRU07DQo+ID4gKwkJZ290byBmYWlsX3B1dF9zY3A7DQo+ID4g Kwl9DQo+ID4gKw0KPiA+ICsJcDFfZGV2LT5jb21wb3Nlcl9zY3BfYWRkciA9IGFkZHI7DQo+ID4g KwlwMV9kZXYtPmNvbXBvc2VyX3ZpcnRfYWRkciA9IHB0cjsNCj4gPiArCWRldl9kYmcoZGV2LCAi c2NwIGFkZHI6JXBhZCB2YTolcEtcbiIsICZhZGRyLCBwdHIpOw0KPiA+ICsNCj4gPiArCS8qDQo+ ID4gKwkgKiBUaGlzIHJlc2VydmVkIG1lbW9yeSBpcyBhbHNvIGJlIHVzZWQgYnkgSVNQIFAxIEhX Lg0KPiA+ICsJICogTmVlZCB0byBnZXQgaW92YSBhZGRyZXNzIGZvciBJU1AgUDEgRE1BLg0KPiA+ ICsJICovDQo+ID4gKwlhZGRyID0gZG1hX21hcF9yZXNvdXJjZShkZXYsIGFkZHIsIE1US19JU1Bf Q09NUE9TRVJfTUVNX1NJWkUsDQo+ID4gKwkJCQlETUFfVE9fREVWSUNFLCBETUFfQVRUUl9TS0lQ X0NQVV9TWU5DKTsNCj4gPiArCWlmIChkbWFfbWFwcGluZ19lcnJvcihkZXYsIGFkZHIpKSB7DQo+ ID4gKwkJZGV2X2VycihkZXYsICJmYWlsZWQgdG8gbWFwIHNjcCBpb3ZhXG4iKTsNCj4gPiArCQly ZXQgPSAtRU5PTUVNOw0KPiA+ICsJCWdvdG8gZmFpbF9mcmVlX21lbTsNCj4gPiArCX0NCj4gPiAr CXAxX2Rldi0+Y29tcG9zZXJfaW92YSA9IGFkZHI7DQo+ID4gKwlkZXZfZGJnKGRldiwgInNjcCBp b3ZhIGFkZHI6JXBhZFxuIiwgJmFkZHIpOw0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICsN Cj4gPiArZmFpbF9mcmVlX21lbToNCj4gPiArCWRtYV9mcmVlX2NvaGVyZW50KHAxX2Rldi0+Y2Ft X2Rldi5zbWVtX2RldiwgTVRLX0lTUF9DT01QT1NFUl9NRU1fU0laRSwNCj4gPiArCQkJICBwMV9k ZXYtPmNvbXBvc2VyX3ZpcnRfYWRkciwNCj4gPiArCQkJICBwMV9kZXYtPmNvbXBvc2VyX3NjcF9h ZGRyKTsNCj4gPiArCXAxX2Rldi0+Y29tcG9zZXJfc2NwX2FkZHIgPSAwOw0KPiA+ICtmYWlsX3B1 dF9zY3A6DQo+ID4gKwlzY3BfcHV0KHAxX2Rldi0+c2NwKTsNCj4gPiArDQo+ID4gKwlyZXR1cm4g cmV0Ow0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgdm9pZCBpc3BfdGVhcmRvd25fc2NwX3Jw cm9jKHN0cnVjdCBtdGtfaXNwX3AxX2RldmljZSAqcDFfZGV2KQ0KPiA+ICt7DQo+ID4gKwlkbWFf ZnJlZV9jb2hlcmVudChwMV9kZXYtPmNhbV9kZXYuc21lbV9kZXYsIE1US19JU1BfQ09NUE9TRVJf TUVNX1NJWkUsDQo+ID4gKwkJCSAgcDFfZGV2LT5jb21wb3Nlcl92aXJ0X2FkZHIsDQo+ID4gKwkJ CSAgcDFfZGV2LT5jb21wb3Nlcl9zY3BfYWRkcik7DQo+ID4gKwlwMV9kZXYtPmNvbXBvc2VyX3Nj cF9hZGRyID0gMDsNCj4gPiArCXNjcF9wdXQocDFfZGV2LT5zY3ApOw0KPiA+ICt9DQo+ID4gKw0K PiA+ICtzdGF0aWMgaW50IG10a19pc3BfcG1fc3VzcGVuZChzdHJ1Y3QgZGV2aWNlICpkZXYpDQo+ ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtfaXNwX3AxX2RldmljZSAqcDFfZGV2ID0gZGV2X2dldF9k cnZkYXRhKGRldik7DQo+ID4gKwl1MzIgdmFsOw0KPiA+ICsJaW50IHJldDsNCj4gPiArDQo+ID4g KwlkZXZfZGJnKGRldiwgIi0gJXNcbiIsIF9fZnVuY19fKTsNCj4gPiArDQo+ID4gKwlpZiAocG1f cnVudGltZV9zdXNwZW5kZWQoZGV2KSkNCj4gPiArCQlyZXR1cm4gMDsNCj4gPiArDQo+ID4gKwkv KiBEaXNhYmxlIElTUCdzIHZpZXcgZmluZGVyIGFuZCB3YWl0IGZvciBURyBpZGxlIGlmIHBvc3Np YmxlICovDQo+ID4gKwlkZXZfZGJnKGRldiwgImNhbSBzdXNwZW5kLCBkaXNhYmxlIFZGXG4iKTsN Cj4gPiArCXZhbCA9IHJlYWRsKHAxX2Rldi0+cmVncyArIFJFR19UR19WRl9DT04pOw0KPiA+ICsJ d3JpdGVsKHZhbCAmICh+VEdfVkZfQ09OX1ZGREFUQV9FTiksIHAxX2Rldi0+cmVncyArIFJFR19U R19WRl9DT04pOw0KPiA+ICsJcmVhZGxfcG9sbF90aW1lb3V0X2F0b21pYyhwMV9kZXYtPnJlZ3Mg KyBSRUdfVEdfSU5URVJfU1QsIHZhbCwNCj4gPiArCQkJCSAgKHZhbCAmIFRHX0NTX01BU0spID09 IFRHX0lETEVfU1QsDQo+ID4gKwkJCQkgIFVTRUNfUEVSX01TRUMsIE1US19JU1BfU1RPUF9IV19U SU1FT1VUKTsNCj4gPiArDQo+ID4gKwkvKiBEaXNhYmxlIENNT1MgKi8NCj4gPiArCXZhbCA9IHJl YWRsKHAxX2Rldi0+cmVncyArIFJFR19UR19TRU5fTU9ERSk7DQo+ID4gKwl3cml0ZWwodmFsICYg KH5UR19TRU5fTU9ERV9DTU9TX0VOKSwgcDFfZGV2LT5yZWdzICsgUkVHX1RHX1NFTl9NT0RFKTsN Cj4gPiArDQo+ID4gKwkvKiBGb3JjZSBJU1AgSFcgdG8gaWRsZSAqLw0KPiA+ICsJcmV0ID0gcG1f cnVudGltZV9mb3JjZV9zdXNwZW5kKGRldik7DQo+ID4gKwlpZiAocmV0KSB7DQo+ID4gKwkJZGV2 X2VycihkZXYsICJmYWlsZWQgdG8gZm9yY2Ugc3VzcGVuZDolZFxuIiwgcmV0KTsNCj4gPiArCQln b3RvIHJlZW5hYmxlX2h3Ow0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICsN Cj4gPiArcmVlbmFibGVfaHc6DQo+ID4gKwl2YWwgPSByZWFkbChwMV9kZXYtPnJlZ3MgKyBSRUdf VEdfU0VOX01PREUpOw0KPiA+ICsJd3JpdGVsKHZhbCB8IFRHX1NFTl9NT0RFX0NNT1NfRU4sIHAx X2Rldi0+cmVncyArIFJFR19UR19TRU5fTU9ERSk7DQo+ID4gKwl2YWwgPSByZWFkbChwMV9kZXYt PnJlZ3MgKyBSRUdfVEdfVkZfQ09OKTsNCj4gPiArCXdyaXRlbCh2YWwgfCBUR19WRl9DT05fVkZE QVRBX0VOLCBwMV9kZXYtPnJlZ3MgKyBSRUdfVEdfVkZfQ09OKTsNCj4gPiArDQo+ID4gKwlyZXR1 cm4gcmV0Ow0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IG10a19pc3BfcG1fcmVzdW1l KHN0cnVjdCBkZXZpY2UgKmRldikNCj4gPiArew0KPiA+ICsJc3RydWN0IG10a19pc3BfcDFfZGV2 aWNlICpwMV9kZXYgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsNCj4gPiArCXUzMiB2YWw7DQo+ID4g KwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCWRldl9kYmcoZGV2LCAiLSAlc1xuIiwgX19mdW5jX18p Ow0KPiA+ICsNCj4gPiArCWlmIChwbV9ydW50aW1lX3N1c3BlbmRlZChkZXYpKQ0KPiA+ICsJCXJl dHVybiAwOw0KPiA+ICsNCj4gPiArCS8qIEZvcmNlIElTUCBIVyB0byByZXN1bWUgKi8NCj4gPiAr CXJldCA9IHBtX3J1bnRpbWVfZm9yY2VfcmVzdW1lKGRldik7DQo+ID4gKwlpZiAocmV0KQ0KPiA+ ICsJCXJldHVybiByZXQ7DQo+ID4gKw0KPiA+ICsJLyogRW5hYmxlIENNT1MgKi8NCj4gPiArCWRl dl9kYmcoZGV2LCAiY2FtIHJlc3VtZSwgZW5hYmxlIENNT1MvVkZcbiIpOw0KPiA+ICsJdmFsID0g cmVhZGwocDFfZGV2LT5yZWdzICsgUkVHX1RHX1NFTl9NT0RFKTsNCj4gPiArCXdyaXRlbCh2YWwg fCBUR19TRU5fTU9ERV9DTU9TX0VOLCBwMV9kZXYtPnJlZ3MgKyBSRUdfVEdfU0VOX01PREUpOw0K PiA+ICsNCj4gPiArCS8qIEVuYWJsZSBWRiAqLw0KPiA+ICsJdmFsID0gcmVhZGwocDFfZGV2LT5y ZWdzICsgUkVHX1RHX1ZGX0NPTik7DQo+ID4gKwl3cml0ZWwodmFsIHwgVEdfVkZfQ09OX1ZGREFU QV9FTiwgcDFfZGV2LT5yZWdzICsgUkVHX1RHX1ZGX0NPTik7DQo+ID4gKw0KPiA+ICsJcmV0dXJu IDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgbXRrX2lzcF9ydW50aW1lX3N1c3Bl bmQoc3RydWN0IGRldmljZSAqZGV2KQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgbXRrX2lzcF9wMV9k ZXZpY2UgKnAxX2RldiA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOw0KPiA+ICsNCj4gPiArCWRldl9k YmcoZGV2LCAiJXM6ZGlzYWJsZSBjbG9ja1xuIiwgX19mdW5jX18pOw0KPiA+ICsJY2xrX2J1bGtf ZGlzYWJsZV91bnByZXBhcmUocDFfZGV2LT5udW1fY2xrcywgcDFfZGV2LT5jbGtzKTsNCj4gPiAr DQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBtdGtfaXNw X3J1bnRpbWVfcmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRldikNCj4gPiArew0KPiA+ICsJc3RydWN0 IG10a19pc3BfcDFfZGV2aWNlICpwMV9kZXYgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsNCj4gPiAr CWludCByZXQ7DQo+ID4gKw0KPiA+ICsJZGV2X2RiZyhkZXYsICIlczplbmFibGUgY2xvY2tcbiIs IF9fZnVuY19fKTsNCj4gPiArCXJldCA9IGNsa19idWxrX3ByZXBhcmVfZW5hYmxlKHAxX2Rldi0+ bnVtX2Nsa3MsIHAxX2Rldi0+Y2xrcyk7DQo+ID4gKwlpZiAocmV0KSB7DQo+ID4gKwkJZGV2X2Vy cihkZXYsICJmYWlsZWQgdG8gZW5hYmxlIGNsb2NrOiVkXG4iLCByZXQpOw0KPiA+ICsJCXJldHVy biByZXQ7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ ID4gK3N0YXRpYyBpbnQgbXRrX2lzcF9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2 KQ0KPiA+ICt7DQo+ID4gKwkvKiBMaXN0IG9mIGNsb2NrcyByZXF1aXJlZCBieSBpc3AgY2FtICov DQo+ID4gKwlzdGF0aWMgY29uc3QgY2hhciAqIGNvbnN0IGNsa19uYW1lc1tdID0gew0KPiA+ICsJ CSJjYW1zeXNfY2FtX2NncGRuIiwgImNhbXN5c19jYW10Z19jZ3BkbiINCj4gPiArCX07DQo+ID4g KwlzdHJ1Y3QgbXRrX2lzcF9wMV9kZXZpY2UgKnAxX2RldjsNCj4gPiArCXN0cnVjdCBkZXZpY2Ug KmRldiA9ICZwZGV2LT5kZXY7DQo+ID4gKwlzdHJ1Y3QgcmVzb3VyY2UgKnJlczsNCj4gPiArCWlu dCBpcnEsIHJldCwgaTsNCj4gPiArDQo+ID4gKwlwMV9kZXYgPSBkZXZtX2t6YWxsb2MoZGV2LCBz aXplb2YoKnAxX2RldiksIEdGUF9LRVJORUwpOw0KPiA+ICsJaWYgKCFwMV9kZXYpDQo+ID4gKwkJ cmV0dXJuIC1FTk9NRU07DQo+ID4gKw0KPiA+ICsJcDFfZGV2LT5kZXYgPSBkZXY7DQo+ID4gKwlk ZXZfc2V0X2RydmRhdGEoZGV2LCBwMV9kZXYpOw0KPiA+ICsNCj4gPiArCS8qDQo+ID4gKwkgKiBO b3cgb25seSBzdXBwb3J0IHNpbmdsZSBDQU0gd2l0aCBDQU0gQi4NCj4gPiArCSAqIEdldCBDQU0g QiByZWdpc3RlciBiYXNlIHdpdGggQ0FNIEIgaW5kZXguDQo+ID4gKwkgKiBTdXBwb3J0IG11bHRp cGxlIENBTXMgaW4gZnV0dXJlLg0KPiA+ICsJICovDQo+ID4gKwlyZXMgPSBwbGF0Zm9ybV9nZXRf cmVzb3VyY2UocGRldiwgSU9SRVNPVVJDRV9NRU0sIE1US19JU1BfQ0FNX0lEX0IpOw0KPiA+ICsJ cDFfZGV2LT5yZWdzID0gZGV2bV9pb3JlbWFwX3Jlc291cmNlKGRldiwgcmVzKTsNCj4gPiArCWlm IChJU19FUlIocDFfZGV2LT5yZWdzKSkgew0KPiA+ICsJCWRldl9lcnIoZGV2LCAiZmFpbGVkIHRv IG1hcCByZWlzdGVyIGJhc2VcbiIpOw0KPiA+ICsJCXJldHVybiBQVFJfRVJSKHAxX2Rldi0+cmVn cyk7DQo+ID4gKwl9DQo+ID4gKwlkZXZfZGJnKGRldiwgImNhbSwgbWFwX2FkZHI9MHglcEtcbiIs IHAxX2Rldi0+cmVncyk7DQo+ID4gKw0KPiA+ICsJLyoNCj4gPiArCSAqIFRoZSBjYW1fc3lzIHVu aXQgb25seSBzdXBwb3J0cyByZWcuLCBidXQgaGFzIG5vIElSUSBzdXBwb3J0Lg0KPiA+ICsJICog VGhlIHJlZy4gJiBJUlEgaW5kZXggaXMgc2hpZnRlZCB3aXRoIDEgZm9yIENBTSBCIGluIERUUy4N Cj4gPiArCSAqLw0KPiA+ICsJaXJxID0gcGxhdGZvcm1fZ2V0X2lycShwZGV2LCBNVEtfSVNQX0NB TV9JRF9CIC0gMSk7DQo+ID4gKwlpZiAoIWlycSkgew0KPiA+ICsJCWRldl9lcnIoZGV2LCAiZmFp bGVkIHRvIGdldCBpcnFcbiIpOw0KPiA+ICsJCXJldHVybiAtRU5PREVWOw0KPiA+ICsJfQ0KPiA+ ICsJcmV0ID0gZGV2bV9yZXF1ZXN0X2lycShkZXYsIGlycSwgaXNwX2lycV9jYW0sIDAsIGRldl9u YW1lKGRldiksDQo+ID4gKwkJCSAgICAgICBwMV9kZXYpOw0KPiA+ICsJaWYgKHJldCkgew0KPiA+ ICsJCWRldl9lcnIoZGV2LCAiZmFpbGVkIHRvIHJlcXVlc3QgaXJxPSVkXG4iLCBpcnEpOw0KPiA+ ICsJCXJldHVybiByZXQ7DQo+ID4gKwl9DQo+ID4gKwlkZXZfZGJnKGRldiwgInJlZ2lzdGVyZWQg aXJxPSVkXG4iLCBpcnEpOw0KPiA+ICsJc3Bpbl9sb2NrX2luaXQoJnAxX2Rldi0+c3BpbmxvY2tf aXJxKTsNCj4gPiArDQo+ID4gKwlwMV9kZXYtPm51bV9jbGtzID0gQVJSQVlfU0laRShjbGtfbmFt ZXMpOw0KPiA+ICsJcDFfZGV2LT5jbGtzID0gZGV2bV9rY2FsbG9jKGRldiwgcDFfZGV2LT5udW1f Y2xrcywNCj4gPiArCQkJCSAgICBzaXplb2YoKnAxX2Rldi0+Y2xrcyksIEdGUF9LRVJORUwpOw0K PiA+ICsJaWYgKCFwMV9kZXYtPmNsa3MpDQo+ID4gKwkJcmV0dXJuIC1FTk9NRU07DQo+ID4gKw0K PiA+ICsJZm9yIChpID0gMDsgaSA8IHAxX2Rldi0+bnVtX2Nsa3M7ICsraSkNCj4gPiArCQlwMV9k ZXYtPmNsa3NbaV0uaWQgPSBjbGtfbmFtZXNbaV07DQo+ID4gKw0KPiA+ICsJcmV0ID0gZGV2bV9j bGtfYnVsa19nZXQoZGV2LCBwMV9kZXYtPm51bV9jbGtzLCBwMV9kZXYtPmNsa3MpOw0KPiA+ICsJ aWYgKHJldCkgew0KPiA+ICsJCWRldl9lcnIoZGV2LCAiZmFpbGVkIHRvIGdldCBpc3AgY2FtIGNs b2NrOiVkXG4iLCByZXQpOw0KPiA+ICsJCXJldHVybiByZXQ7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ ICsJcmV0ID0gaXNwX3NldHVwX3NjcF9ycHJvYyhwMV9kZXYsIHBkZXYpOw0KPiA+ICsJaWYgKHJl dCkNCj4gPiArCQlyZXR1cm4gcmV0Ow0KPiA+ICsNCj4gPiArCXBtX3J1bnRpbWVfc2V0X2F1dG9z dXNwZW5kX2RlbGF5KGRldiwgTVRLX0lTUF9BVVRPU1VTUEVORF9ERUxBWV9NUyk7DQo+ID4gKwlw bV9ydW50aW1lX3VzZV9hdXRvc3VzcGVuZChkZXYpOw0KPiA+ICsJcG1fcnVudGltZV9lbmFibGUo ZGV2KTsNCj4gPiArDQo+ID4gKwkvKiBJbml0aWFsaXplIHRoZSB2NGwyIGNvbW1vbiBwYXJ0ICov DQo+ID4gKwlyZXQgPSBtdGtfY2FtX2Rldl9pbml0KHBkZXYsICZwMV9kZXYtPmNhbV9kZXYpOw0K PiA+ICsJaWYgKHJldCkgew0KPiA+ICsJCWlzcF90ZWFyZG93bl9zY3BfcnByb2MocDFfZGV2KTsN Cj4gPiArCQlyZXR1cm4gcmV0Ow0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IG10a19pc3BfcmVtb3ZlKHN0cnVjdCBwbGF0Zm9y bV9kZXZpY2UgKnBkZXYpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBkZXZpY2UgKmRldiA9ICZwZGV2 LT5kZXY7DQo+ID4gKwlzdHJ1Y3QgbXRrX2lzcF9wMV9kZXZpY2UgKnAxX2RldiA9IGRldl9nZXRf ZHJ2ZGF0YShkZXYpOw0KPiA+ICsNCj4gPiArCW10a19jYW1fZGV2X2NsZWFudXAoJnAxX2Rldi0+ Y2FtX2Rldik7DQo+ID4gKwlwbV9ydW50aW1lX2RvbnRfdXNlX2F1dG9zdXNwZW5kKGRldik7DQo+ ID4gKwlwbV9ydW50aW1lX2Rpc2FibGUoZGV2KTsNCj4gPiArCWRtYV91bm1hcF9wYWdlX2F0dHJz KGRldiwgcDFfZGV2LT5jb21wb3Nlcl9pb3ZhLA0KPiA+ICsJCQkgICAgIE1US19JU1BfQ09NUE9T RVJfTUVNX1NJWkUsIERNQV9UT19ERVZJQ0UsDQo+ID4gKwkJCSAgICAgRE1BX0FUVFJfU0tJUF9D UFVfU1lOQyk7DQo+ID4gKwlpc3BfdGVhcmRvd25fc2NwX3Jwcm9jKHAxX2Rldik7DQo+ID4gKw0K PiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qg ZGV2X3BtX29wcyBtdGtfaXNwX3BtX29wcyA9IHsNCj4gPiArCVNFVF9TWVNURU1fU0xFRVBfUE1f T1BTKG10a19pc3BfcG1fc3VzcGVuZCwgbXRrX2lzcF9wbV9yZXN1bWUpDQo+ID4gKwlTRVRfUlVO VElNRV9QTV9PUFMobXRrX2lzcF9ydW50aW1lX3N1c3BlbmQsIG10a19pc3BfcnVudGltZV9yZXN1 bWUsDQo+ID4gKwkJCSAgIE5VTEwpDQo+ID4gK307DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3Qg c3RydWN0IG9mX2RldmljZV9pZCBtdGtfaXNwX29mX2lkc1tdID0gew0KPiA+ICsJey5jb21wYXRp YmxlID0gIm1lZGlhdGVrLG10ODE4My1jYW1pc3AiLH0sDQo+ID4gKwl7fQ0KPiA+ICt9Ow0KPiA+ ICtNT0RVTEVfREVWSUNFX1RBQkxFKG9mLCBtdGtfaXNwX29mX2lkcyk7DQo+ID4gKw0KPiA+ICtz dGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBtdGtfaXNwX2RyaXZlciA9IHsNCj4gPiArCS5w cm9iZSAgID0gbXRrX2lzcF9wcm9iZSwNCj4gPiArCS5yZW1vdmUgID0gbXRrX2lzcF9yZW1vdmUs DQo+ID4gKwkuZHJpdmVyICA9IHsNCj4gPiArCQkubmFtZSAgPSAibXRrLWNhbS1wMSIsDQo+ID4g KwkJLm9mX21hdGNoX3RhYmxlID0gb2ZfbWF0Y2hfcHRyKG10a19pc3Bfb2ZfaWRzKSwNCj4gPiAr CQkucG0gICAgID0gJm10a19pc3BfcG1fb3BzLA0KPiA+ICsJfQ0KPiA+ICt9Ow0KPiA+ICsNCj4g PiArbW9kdWxlX3BsYXRmb3JtX2RyaXZlcihtdGtfaXNwX2RyaXZlcik7DQo+ID4gKw0KPiA+ICtN T0RVTEVfREVTQ1JJUFRJT04oIk1lZGlhdGVrIElTUCBQMSBkcml2ZXIiKTsNCj4gPiArTU9EVUxF X0xJQ0VOU0UoIkdQTCB2MiIpOw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL21lZGlhL3BsYXRm b3JtL210ay1pc3AvaXNwXzUwL2NhbS9tdGtfY2FtLWh3LmggYi9kcml2ZXJzL21lZGlhL3BsYXRm b3JtL210ay1pc3AvaXNwXzUwL2NhbS9tdGtfY2FtLWh3LmgNCj4gPiBuZXcgZmlsZSBtb2RlIDEw MDY0NA0KPiA+IGluZGV4IDAwMDAwMDAwMDAwMC4uODM3NjYyZjkyYTVlDQo+ID4gLS0tIC9kZXYv bnVsbA0KPiA+ICsrKyBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vbXRrLWlzcC9pc3BfNTAvY2Ft L210a19jYW0taHcuaA0KPiA+IEBAIC0wLDAgKzEsNjQgQEANCj4gPiArLyogU1BEWC1MaWNlbnNl LUlkZW50aWZpZXI6IEdQTC0yLjAgKi8NCj4gPiArLyoNCj4gPiArICogQ29weXJpZ2h0IChjKSAy MDE5IE1lZGlhVGVrIEluYy4NCj4gPiArICovDQo+ID4gKw0KPiA+ICsjaWZuZGVmIF9fTVRLX0NB TV9IV19IX18NCj4gPiArI2RlZmluZSBfX01US19DQU1fSFdfSF9fDQo+ID4gKw0KPiA+ICsjaW5j bHVkZSA8bGludXgvdHlwZXMuaD4NCj4gPiArDQo+ID4gKyNpbmNsdWRlICJtdGtfY2FtLmgiDQo+ ID4gKyNpbmNsdWRlICJtdGtfY2FtLWlwaS5oIg0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogc3Ry dWN0IG10a19pc3BfcDFfZGV2aWNlIC0gdGhlIE1lZGlhdGVrIElTUCBQMSBkZXZpY2UgaW5mb3Jt YXRpb24NCj4gPiArICoNCj4gPiArICogQGRldjogUG9pbnRlciB0byBkZXZpY2UuDQo+ID4gKyAq IEBzY3BfcGRldjogUG9pbnRlciB0byBTQ1AgcGxhdGZvcm0gZGV2aWNlLg0KPiA+ICsgKiBAcnBy b2NfaGFuZGxlOiBQb2ludGVyIHRvIG5ldyByZW1vdGVwcm9jIGluc3RhbmNlLg0KPiA+ICsgKiBA Y2FtX2RldjogRW1iZWRkZWQgc3RydWN0IGNhbV9kZXYNCj4gPiArICogQHJlZ3M6IENhbWVyYSBJ U1AgSFcgYmFzZSByZWdpc3RlciBhZGRyZXNzDQo+ID4gKyAqIEBudW1fY2xrczogVGhlIG51bWJl ciBvZiBkcml2ZXIncyBjbG9ja3MNCj4gPiArICogQGNsa3M6IFRoZSBjbG9jayBkYXRhIGFycmF5 DQo+ID4gKyAqIEBzcGlubG9ja19pcnE6IFVzZWQgdG8gcHJvdGVjdCByZWdpc3RlciByZWFkL3dy aXRlIGRhdGENCj4gPiArICogQGVucXVldWVkX2ZyYW1lX3NlcV9ubzogRnJhbWUgc2VxdWVuY2Ug bnVtYmVyIG9mIGVucXVldWVkIGZyYW1lDQo+ID4gKyAqIEBkZXF1ZXVlZF9mcmFtZV9zZXFfbm86 IEZyYW1lIHNlcXVlbmNlIG51bWJlciBvZiBkZXF1ZXVlZCBmcmFtZQ0KPiA+ICsgKiBAY29tcG9z ZWRfZnJhbWVfc2VxX25vOiBGcmFtZSBzZXF1ZW5jZSBudW1iZXIgb2YgY29tcG9zZWQgZnJhbWUN Cj4gPiArICogQHRpbWVzdGFtcDogRnJhbWUgdGltZXN0YW1wIGluIG5zDQo+ID4gKyAqIEBzb2Zf Y291bnQ6IFNPRiBjb3VudGVyDQo+ID4gKyAqIEBjb21wb3Nlcl93cTogVGhlIHdvcmsgcXVldWUg Zm9yIGZyYW1lIHJlcXVlc3QgY29tcG9zaW5nDQo+ID4gKyAqIEBjb21wb3Nlcl9zY3BfYWRkcjog U0NQIGFkZHJlc3Mgb2YgSVNQIGNvbXBvc2VyIG1lbW9yeQ0KPiA+ICsgKiBAY29tcG9zZXJfaW92 YTogRE1BIGFkZHJlc3Mgb2YgSVNQIGNvbXBvc2VyIG1lbW9yeQ0KPiA+ICsgKiBAdmlydF9hZGRy OiBWaXJ0dWFsIGFkZHJlc3Mgb2YgSVNQIGNvbXBvc2VyIG1lbW9yeQ0KPiA+ICsgKg0KPiA+ICsg Ki8NCj4gPiArc3RydWN0IG10a19pc3BfcDFfZGV2aWNlIHsNCj4gPiArCXN0cnVjdCBkZXZpY2Ug KmRldjsNCj4gPiArCXN0cnVjdCBtdGtfc2NwICpzY3A7DQo+ID4gKwlzdHJ1Y3QgcnByb2MgKnJw cm9jX2hhbmRsZTsNCj4gPiArCXN0cnVjdCBtdGtfY2FtX2RldiBjYW1fZGV2Ow0KPiA+ICsJdm9p ZCBfX2lvbWVtICpyZWdzOw0KPiA+ICsJdW5zaWduZWQgaW50IG51bV9jbGtzOw0KPiA+ICsJc3Ry dWN0IGNsa19idWxrX2RhdGEgKmNsa3M7DQo+ID4gKwkvKiBVc2VkIHRvIHByb3RlY3QgcmVnaXN0 ZXIgcmVhZC93cml0ZSBkYXRhICovDQo+ID4gKwlzcGlubG9ja190IHNwaW5sb2NrX2lycTsNCj4g PiArCXVuc2lnbmVkIGludCBlbnF1ZXVlZF9mcmFtZV9zZXFfbm87DQo+ID4gKwl1bnNpZ25lZCBp bnQgZGVxdWV1ZWRfZnJhbWVfc2VxX25vOw0KPiA+ICsJdW5zaWduZWQgaW50IGNvbXBvc2VkX2Zy YW1lX3NlcV9ubzsNCj4gPiArCXU4IHNvZl9jb3VudDsNCj4gPiArCXN0cnVjdCB3b3JrcXVldWVf c3RydWN0ICpjb21wb3Nlcl93cTsNCj4gPiArCWRtYV9hZGRyX3QgY29tcG9zZXJfc2NwX2FkZHI7 DQo+ID4gKwlkbWFfYWRkcl90IGNvbXBvc2VyX2lvdmE7DQo+ID4gKwl2b2lkICpjb21wb3Nlcl92 aXJ0X2FkZHI7DQo+ID4gK307DQo+ID4gKw0KPiA+ICtpbnQgbXRrX2lzcF9od19pbml0KHN0cnVj dCBtdGtfY2FtX2RldiAqY2FtX2Rldik7DQo+ID4gK2ludCBtdGtfaXNwX2h3X3JlbGVhc2Uoc3Ry dWN0IG10a19jYW1fZGV2ICpjYW1fZGV2KTsNCj4gPiArdm9pZCBtdGtfaXNwX2h3X2NvbmZpZyhz dHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbV9kZXYsDQo+ID4gKwkJICAgICAgIHN0cnVjdCBwMV9jb25m aWdfcGFyYW0gKmNvbmZpZ19wYXJhbSk7DQo+ID4gK3ZvaWQgbXRrX2lzcF9zdHJlYW0oc3RydWN0 IG10a19jYW1fZGV2ICpjYW1fZGV2LCBpbnQgb24pOw0KPiA+ICt2b2lkIG10a19pc3BfcmVxX2Vu cXVldWUoc3RydWN0IG10a19jYW1fZGV2ICpjYW1fZGV2LA0KPiA+ICsJCQkgc3RydWN0IG10a19j YW1fZGV2X3JlcXVlc3QgKnJlcSk7DQo+ID4gKw0KPiA+ICsjZW5kaWYgLyogX19NVEtfQ0FNX0hX X0hfXyAqLw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL210ay1pc3Av aXNwXzUwL2NhbS9tdGtfY2FtLWlwaS5oIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNw L2lzcF81MC9jYW0vbXRrX2NhbS1pcGkuaA0KPiA+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0DQo+ID4g aW5kZXggMDAwMDAwMDAwMDAwLi45ODFiNjM0ZGQ5MWYNCj4gPiAtLS0gL2Rldi9udWxsDQo+ID4g KysrIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL2lzcF81MC9jYW0vbXRrX2NhbS1p cGkuaA0KPiA+IEBAIC0wLDAgKzEsMjIyIEBADQo+ID4gKy8qIFNQRFgtTGljZW5zZS1JZGVudGlm aWVyOiBHUEwtMi4wICovDQo+ID4gKy8qDQo+ID4gKyAqIENvcHlyaWdodCAoYykgMjAxOSBNZWRp YVRlayBJbmMuDQo+ID4gKyAqLw0KPiA+ICsNCj4gPiArI2lmbmRlZiBfX01US19DQU1fSVBJX0hf Xw0KPiA+ICsjZGVmaW5lIF9fTVRLX0NBTV9JUElfSF9fDQo+ID4gKw0KPiA+ICsjaW5jbHVkZSA8 bGludXgvdHlwZXMuaD4NCj4gPiArDQo+ID4gKy8qDQo+ID4gKyAqIHN0cnVjdCBpbWdfc2l6ZSAt IEltYWdlIHNpemUgaW5mb3JtYXRpb24uDQo+ID4gKyAqDQo+ID4gKyAqIEB3OiBJbWFnZSB3aWR0 aCwgdGhlIHVuaXQgaXMgcGl4ZWwNCj4gPiArICogQGg6IEltYWdlIGhlaWdodCwgdGhlIHVuaXQg aXMgcGl4ZWwNCj4gPiArICogQHhzaXplOiBCeXRlcyBwZXIgbGluZSBiYXNlZCBvbiB3aWR0aC4N Cj4gPiArICogQHN0cmlkZTogQnl0ZXMgcGVyIGxpbmUgd2hlbiBjaGFuZ2luZyBsaW5lLg0KPiA+ ICsgKiAgICAgICAgICBTdHJpZGUgaXMgYmFzZWQgb24geHNpemUgKyBIVyBjb25zdHJhaW4oYnl0 ZSBhbGlnbikuDQo+ID4gKyAqDQo+ID4gKyAqLw0KPiA+ICtzdHJ1Y3QgaW1nX3NpemUgew0KPiA+ ICsJdTMyIHc7DQo+ID4gKwl1MzIgaDsNCj4gPiArCXUzMiB4c2l6ZTsNCj4gPiArCXUzMiBzdHJp ZGU7DQo+ID4gK30gX19wYWNrZWQ7DQo+ID4gKw0KPiA+ICsvKg0KPiA+ICsgKiBzdHJ1Y3QgcDFf aW1nX2Nyb3AgLSBpbWFnZSBjb3JwIGluZm9ybWF0aW9uDQo+ID4gKyAqDQo+ID4gKyAqIEBsZWZ0 OiBUaGUgbGVmdCBvZiBjcm9wIGFyZWEuDQo+ID4gKyAqIEB0b3A6IFRoZSB0b3Agb2YgY3JvcCBh cmVhLg0KPiA+ICsgKiBAd2lkdGg6IFRoZSB3aWR0aCBvZiBjcm9wIGFyZWEuDQo+ID4gKyAqIEBo ZWlnaHQ6IFRoZSBoZWlnaHQgb2YgY3JvcCBhcmVhLg0KPiA+ICsgKg0KPiA+ICsgKi8NCj4gPiAr c3RydWN0IHAxX2ltZ19jcm9wIHsNCj4gPiArCXUzMiBsZWZ0Ow0KPiA+ICsJdTMyIHRvcDsNCj4g PiArCXUzMiB3aWR0aDsNCj4gPiArCXUzMiBoZWlnaHQ7DQo+ID4gK30gX19wYWNrZWQ7DQo+ID4g Kw0KPiA+ICsvKg0KPiA+ICsgKiBzdHJ1Y3QgZG1hX2J1ZmZlciAtIERNQSBidWZmZXIgYWRkcmVz cyBpbmZvcm1hdGlvbg0KPiA+ICsgKg0KPiA+ICsgKiBAaW92YTogRE1BIGFkZHJlc3MgZm9yIElT UCBETUEgZGV2aWNlDQo+ID4gKyAqIEBzY3BfYWRkcjogU0NQIGFkZHJlc3MgZm9yIGV4dGVybmFs IGNvLXByb2Nlc3MgdW5pdA0KPiA+ICsgKg0KPiA+ICsgKi8NCj4gPiArc3RydWN0IGRtYV9idWZm ZXIgew0KPiA+ICsJdTMyIGlvdmE7DQo+ID4gKwl1MzIgc2NwX2FkZHI7DQo+ID4gK30gX19wYWNr ZWQ7DQo+ID4gKw0KPiA+ICsvKg0KPiA+ICsgKiBzdHJ1Y3QgcDFfaW1nX291dHB1dCAtIElTUCBQ MSBpbWFnZSBvdXRwdXQgaW5mb3JtYXRpb24NCj4gPiArICoNCj4gPiArICogQGJ1ZmZlcjogRE1B IGJ1ZmZlciBhZGRyZXNzIG9mIGltYWdlLg0KPiA+ICsgKiBAc2l6ZTogVGhlIGltYWdlIHNpemUg Y29uZmlndXJhdGlvbi4NCj4gPiArICogQGNyb3A6IFRoZSBjcm9wIGNvbmZpZ3VyYXRpb24uDQo+ ID4gKyAqIEBwaXhlbF9iaXRzOiBUaGUgYml0cyBwZXIgaW1hZ2UgcGl4ZWwuDQo+ID4gKyAqIEBp bWdfZm10OiBUaGUgaW1hZ2UgZm9ybWF0Lg0KPiA+ICsgKg0KPiA+ICsgKi8NCj4gPiArc3RydWN0 IHAxX2ltZ19vdXRwdXQgew0KPiA+ICsJc3RydWN0IGRtYV9idWZmZXIgYnVmZmVyOw0KPiA+ICsJ c3RydWN0IGltZ19zaXplIHNpemU7DQo+ID4gKwlzdHJ1Y3QgcDFfaW1nX2Nyb3AgY3JvcDsNCj4g PiArCXU4IHBpeGVsX2JpdHM7DQo+ID4gKwl1MzIgaW1nX2ZtdDsNCj4gPiArfSBfX3BhY2tlZDsN Cj4gPiArDQo+ID4gKy8qDQo+ID4gKyAqIHN0cnVjdCBjZmdfaW5fcGFyYW0gLSBJbWFnZSBpbnB1 dCBwYXJhbWV0ZXJzIHN0cnVjdHVyZS4NCj4gPiArICogICAgICAgICAgICAgICAgICAgICAgIE5v cm1hbGx5LCBpdCBjb21lcyBmcm9tIHNlbnNvciBpbmZvcm1hdGlvbi4NCj4gPiArICoNCj4gPiAr ICogQGNvbnRpbnVvdXM6IEluZGljYXRlIHRoZSBzZW5zb3IgbW9kZS4gQ29udGludW91cyBvciBz aW5nbGUgc2hvdC4NCj4gPiArICogQHN1YnNhbXBsZTogSW5kaWNhdGUgdG8gZW5hYmxlcyBTT0Yg c3Vic2FtcGxlIG9yIG5vdC4NCj4gPiArICogQHBpeGVsX21vZGU6IERlc2NyaWJlIDEvMi80IHBp eGVscyBwZXIgY2xvY2sgY3ljbGUuDQo+ID4gKyAqIEBkYXRhX3BhdHRlcm46IERlc2NyaWJlIGlu cHV0IGRhdGEgcGF0dGVybi4NCj4gPiArICogQHJhd19waXhlbF9pZDogQmF5ZXIgc2VxdWVuY2Uu DQo+ID4gKyAqIEB0Z19mcHM6IFRoZSBmcHMgcmF0ZSBvZiBURyAodGltZSBnZW5lcmF0b3IpLg0K PiA+ICsgKiBAaW1nX2ZtdDogVGhlIGltYWdlIGZvcm1hdCBvZiBpbnB1dCBzb3VyY2UuDQo+ID4g KyAqIEBwMV9pbWdfY3JvcDogVGhlIGNyb3AgY29uZmlndXJhdGlvbiBvZiBpbnB1dCBzb3VyY2Uu DQo+ID4gKyAqDQo+ID4gKyAqLw0KPiA+ICtzdHJ1Y3QgY2ZnX2luX3BhcmFtIHsNCj4gPiArCXU4 IGNvbnRpbnVvdXM7DQo+ID4gKwl1OCBzdWJzYW1wbGU7DQo+ID4gKwl1OCBwaXhlbF9tb2RlOw0K PiA+ICsJdTggZGF0YV9wYXR0ZXJuOw0KPiA+ICsJdTggcmF3X3BpeGVsX2lkOw0KPiA+ICsJdTE2 IHRnX2ZwczsNCj4gPiArCXUzMiBpbWdfZm10Ow0KPiA+ICsJc3RydWN0IHAxX2ltZ19jcm9wIGNy b3A7DQo+ID4gK30gX19wYWNrZWQ7DQo+ID4gKw0KPiA+ICsvKg0KPiA+ICsgKiBzdHJ1Y3QgY2Zn X21haW5fb3V0X3BhcmFtIC0gVGhlIGltYWdlIG91dHB1dCBwYXJhbWV0ZXJzIG9mIG1haW4gc3Ry ZWFtLg0KPiA+ICsgKg0KPiA+ICsgKiBAYnlwYXNzOiBJbmRpY2F0ZSB0aGlzIGRldmljZSBpcyBl bmFibGVkIG9yIGRpc2FibGVkIG9yIG5vdC4NCj4gPiArICogQHB1cmVfcmF3OiBJbmRpY2F0ZSB0 aGUgaW1hZ2UgcGF0aCBjb250cm9sLg0KPiA+ICsgKiAgICAgICAgICAgIFRydWU6IHB1cmUgcmF3 DQo+ID4gKyAqICAgICAgICAgICAgRmFsc2U6IHByb2Nlc3NpbmcgcmF3DQo+ID4gKyAqIEBwdXJl X3Jhd19wYWNrOiBJbmRpY2F0ZSB0aGUgaW1hZ2UgaXMgcGFja2VkIG9yIG5vdC4NCj4gPiArICog ICAgICAgICAgICAgICAgIFRydWU6IHBhY2tlZCBtb2RlDQo+ID4gKyAqICAgICAgICAgICAgICAg ICBGYWxzZTogdW5wYWNrZWQgbW9kZQ0KPiA+ICsgKiBAcDFfaW1nX291dHB1dDogVGhlIG91dHB1 dCBpbWFnZSBpbmZvcm1hdGlvbi4NCj4gPiArICoNCj4gPiArICovDQo+ID4gK3N0cnVjdCBjZmdf bWFpbl9vdXRfcGFyYW0gew0KPiA+ICsJdTggYnlwYXNzOw0KPiA+ICsJdTggcHVyZV9yYXc7DQo+ ID4gKwl1OCBwdXJlX3Jhd19wYWNrOw0KPiA+ICsJc3RydWN0IHAxX2ltZ19vdXRwdXQgb3V0cHV0 Ow0KPiA+ICt9IF9fcGFja2VkOw0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogc3RydWN0IGNmZ19y ZXNpemVfb3V0X3BhcmFtIC0gVGhlIGltYWdlIG91dHB1dCBwYXJhbWV0ZXJzIG9mDQo+ID4gKyAq ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhY2tlZCBvdXQgc3RyZWFtLg0KPiA+ICsg Kg0KPiA+ICsgKiBAYnlwYXNzOiBJbmRpY2F0ZSB0aGlzIGRldmljZSBpcyBlbmFibGVkIG9yIGRp c2FibGVkIG9yIG5vdC4NCj4gPiArICogQHAxX2ltZ19vdXRwdXQ6IFRoZSBvdXRwdXQgaW1hZ2Ug aW5mb3JtYXRpb24uDQo+ID4gKyAqDQo+ID4gKyAqLw0KPiA+ICtzdHJ1Y3QgY2ZnX3Jlc2l6ZV9v dXRfcGFyYW0gew0KPiA+ICsJdTggYnlwYXNzOw0KPiA+ICsJc3RydWN0IHAxX2ltZ19vdXRwdXQg b3V0cHV0Ow0KPiA+ICt9IF9fcGFja2VkOw0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogc3RydWN0 IHAxX2NvbmZpZ19wYXJhbSAtIElTUCBQMSBjb25maWd1cmF0aW9uIHBhcmFtZXRlcnMuDQo+ID4g KyAqDQo+ID4gKyAqIEBjZmdfaW5fcGFyYW06IFRoZSBJbWFnZSBpbnB1dCBwYXJhbWV0ZXJzLg0K PiA+ICsgKiBAY2ZnX21haW5fcGFyYW06IFRoZSBtYWluIG91dHB1dCBpbWFnZSBwYXJhbWV0ZXJz Lg0KPiA+ICsgKiBAY2ZnX3Jlc2l6ZV9vdXRfcGFyYW06IFRoZSBwYWNrZWQgb3V0cHV0IGltYWdl IHBhcmFtZXRlcnMuDQo+ID4gKyAqIEBlbmFibGVkX2RtYXM6IFRoZSBlbmFibGVkIERNQSBwb3J0 IGluZm9ybWF0aW9uLg0KPiA+ICsgKg0KPiA+ICsgKi8NCj4gPiArc3RydWN0IHAxX2NvbmZpZ19w YXJhbSB7DQo+ID4gKwlzdHJ1Y3QgY2ZnX2luX3BhcmFtIGNmZ19pbl9wYXJhbTsNCj4gPiArCXN0 cnVjdCBjZmdfbWFpbl9vdXRfcGFyYW0gY2ZnX21haW5fcGFyYW07DQo+ID4gKwlzdHJ1Y3QgY2Zn X3Jlc2l6ZV9vdXRfcGFyYW0gY2ZnX3Jlc2l6ZV9wYXJhbTsNCj4gPiArCXUzMiBlbmFibGVkX2Rt YXM7DQo+ID4gK30gX19wYWNrZWQ7DQo+ID4gKw0KPiA+ICsvKg0KPiA+ICsgKiBzdHJ1Y3QgUDFf bWV0YV9mcmFtZSAtIElTUCBQMSBtZXRhIGZyYW1lIGluZm9ybWF0aW9uLg0KPiA+ICsgKg0KPiA+ ICsgKiBAZW5hYmxlZF9kbWE6IFRoZSBlbmFibGVkIERNQSBwb3J0IGluZm9ybWF0aW9uLg0KPiA+ ICsgKiBAdmJfaW5kZXg6IFRoZSBWQjIgaW5kZXggb2YgbWV0YSBidWZmZXIuDQo+ID4gKyAqIEBt ZXRhX2FkZHI6IERNQSBidWZmZXIgYWRkcmVzcyBvZiBtZXRhIGJ1ZmZlci4NCj4gPiArICoNCj4g PiArICovDQo+ID4gK3N0cnVjdCBQMV9tZXRhX2ZyYW1lIHsNCj4gPiArCXUzMiBlbmFibGVkX2Rt YTsNCj4gPiArCXUzMiB2Yl9pbmRleDsNCj4gPiArCXN0cnVjdCBkbWFfYnVmZmVyIG1ldGFfYWRk cjsNCj4gPiArfSBfX3BhY2tlZDsNCj4gPiArDQo+ID4gKy8qDQo+ID4gKyAqIHN0cnVjdCBpc3Bf aW5pdF9pbmZvIC0gSVNQIFAxIGNvbXBvc2VyIGluaXQgaW5mb3JtYXRpb24uDQo+ID4gKyAqDQo+ ID4gKyAqIEBod19tb2R1bGU6IFRoZSBJU1AgQ2FtZXJhIEhXIG1vZHVsZSBJRC4NCj4gPiArICog QGNxX2FkZHI6IFRoZSBETUEgYWRkcmVzcyBvZiBjb21wb3NlciBtZW1vcnkuDQo+ID4gKyAqDQo+ ID4gKyAqLw0KPiA+ICtzdHJ1Y3QgaXNwX2luaXRfaW5mbyB7DQo+ID4gKwl1OCBod19tb2R1bGU7 DQo+ID4gKwlzdHJ1Y3QgZG1hX2J1ZmZlciBjcV9hZGRyOw0KPiA+ICt9IF9fcGFja2VkOw0KPiA+ ICsNCj4gPiArLyoNCj4gPiArICogc3RydWN0IGlzcF9hY2tfaW5mbyAtIElTUCBQMSBJUEkgY29t bWFuZCBhY2sgaW5mb3JtYXRpb24uDQo+ID4gKyAqDQo+ID4gKyAqIEBjbWRfaWQ6IFRoZSBJUEkg Y29tbWFuZCBJRCBpcyBhY2tlZC4NCj4gPiArICogQGZyYW1lX3NlcV9ubzogVGhlIElQSSBmcmFt ZSBzZXF1ZW5jZSBudW1iZXIgaXMgYWNrZWQuDQo+ID4gKyAqDQo+ID4gKyAqLw0KPiA+ICtzdHJ1 Y3QgaXNwX2Fja19pbmZvIHsNCj4gPiArCXU4IGNtZF9pZDsNCj4gPiArCXUzMiBmcmFtZV9zZXFf bm87DQo+ID4gK30gX19wYWNrZWQ7DQo+ID4gKw0KPiA+ICsvKg0KPiA+ICsgKiBUaGUgSVBJIGNv bW1hbmQgZW51bWVyYXRpb24uDQo+ID4gKyAqLw0KPiA+ICtlbnVtIG10a19pc3Bfc2NwX2NtZHMg ew0KPiA+ICsJSVNQX0NNRF9JTklULA0KPiA+ICsJSVNQX0NNRF9DT05GSUcsDQo+ID4gKwlJU1Bf Q01EX1NUUkVBTSwNCj4gPiArCUlTUF9DTURfREVJTklULA0KPiA+ICsJSVNQX0NNRF9BQ0ssDQo+ ID4gKwlJU1BfQ01EX0ZSQU1FX0FDSywNCj4gPiArCUlTUF9DTURfUkVTRVJWRUQsDQo+ID4gK307 DQo+ID4gKw0KPiA+ICsvKg0KPiA+ICsgKiBzdHJ1Y3QgbXRrX2lzcF9zY3BfcDFfY21kIC0gSVNQ IFAxIElQSSBjb21tYW5kIHN0cmN0dXJlLg0KPiA+ICsgKg0KPiA+ICsgKiBAY21kX2lkOiBUaGUg SVBJIGNvbW1hbmQgSUQuDQo+ID4gKyAqIEBpbml0X3BhcmFtOiBUaGUgaW5pdCBmb3JtYXRpb24g Zm9yIElTUF9DTURfSU5JVC4NCj4gPiArICogQGNvbmZpZ19wYXJhbTogVGhlIGNtZCBjb25maWd1 cmF0aW9uIGZvciBJU1BfQ01EX0NPTkZJRy4NCj4gPiArICogQGVuYWJsZWRfZG1hczogVGhlIG1l dGEgY29uZmlndXJhdGlvbiBpbmZvcm1hdGlvbiBmb3IgSVNQX0NNRF9DT05GSUdfTUVUQS4NCj4g PiArICogQGlzX3N0cmVhbV9vbjogVGhlIHN0cmVhbSBpbmZvcm1hdGlvbiBmb3IgSVNQX0NNRF9T VFJFQU0uDQo+ID4gKyAqIEBhY2tfaW5mbzogVGhlIGNtZCBhY2suIGluZm9ybWF0aW9uIGZvciBJ U1BfQ01EX0FDSy4NCj4gPiArICoNCj4gPiArICovDQo+ID4gK3N0cnVjdCBtdGtfaXNwX3NjcF9w MV9jbWQgew0KPiA+ICsJdTggY21kX2lkOw0KPiA+ICsJdW5pb24gew0KPiA+ICsJCXN0cnVjdCBp c3BfaW5pdF9pbmZvIGluaXRfcGFyYW07DQo+ID4gKwkJc3RydWN0IHAxX2NvbmZpZ19wYXJhbSBj b25maWdfcGFyYW07DQo+ID4gKwkJdTMyIGVuYWJsZWRfZG1hczsNCj4gPiArCQlzdHJ1Y3QgUDFf bWV0YV9mcmFtZSBtZXRhX2ZyYW1lOw0KPiA+ICsJCXU4IGlzX3N0cmVhbV9vbjsNCj4gPiArCQlz dHJ1Y3QgaXNwX2Fja19pbmZvIGFja19pbmZvOw0KPiA+ICsJfTsNCj4gPiArfSBfX3BhY2tlZDsN Cj4gPiArDQo+ID4gKyNlbmRpZiAvKiBfX01US19DQU1fSVBJX0hfXyAqLw0KPiA+IGRpZmYgLS1n aXQgYS9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL210ay1pc3AvaXNwXzUwL2NhbS9tdGtfY2FtLXJl Z3MuaCBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vbXRrLWlzcC9pc3BfNTAvY2FtL210a19jYW0t cmVncy5oDQo+ID4gbmV3IGZpbGUgbW9kZSAxMDA2NDQNCj4gPiBpbmRleCAwMDAwMDAwMDAwMDAu LmFiMjI3N2Y0NWZhNA0KPiA+IC0tLSAvZGV2L251bGwNCj4gPiArKysgYi9kcml2ZXJzL21lZGlh L3BsYXRmb3JtL210ay1pc3AvaXNwXzUwL2NhbS9tdGtfY2FtLXJlZ3MuaA0KPiA+IEBAIC0wLDAg KzEsOTUgQEANCj4gPiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAgKi8NCj4g PiArLyoNCj4gPiArICogQ29weXJpZ2h0IChjKSAyMDE5IE1lZGlhVGVrIEluYy4NCj4gPiArICov DQo+ID4gKw0KPiA+ICsjaWZuZGVmIF9fTVRLX0NBTV9SRUdTX0hfXw0KPiA+ICsjZGVmaW5lIF9f TVRLX0NBTV9SRUdTX0hfXw0KPiA+ICsNCj4gPiArLyogSVNQIGludGVycnVwdCBlbmFibGUgKi8N Cj4gPiArI2RlZmluZSBSRUdfQ1RMX1JBV19JTlRfRU4JCTB4MDAyMA0KPiA+ICsjZGVmaW5lIERN QV9FUlJfSU5UX0VOCQkJQklUKDI5KQ0KPiA+ICsNCj4gPiArLyogSVNQIGludGVycnVwdCBzdGF0 dXMgKi8NCj4gPiArI2RlZmluZSBSRUdfQ1RMX1JBV19JTlRfU1RBVAkJMHgwMDI0DQo+ID4gKyNk ZWZpbmUgVlNfSU5UX1NUCQkJQklUKDApDQo+ID4gKyNkZWZpbmUgVEdfRVJSX1NUCQkJQklUKDQp DQo+ID4gKyNkZWZpbmUgVEdfR0JFUlJfU1QJCQlCSVQoNSkNCj4gPiArI2RlZmluZSBDUV9DT0RF X0VSUl9TVAkJCUJJVCg2KQ0KPiA+ICsjZGVmaW5lIENRX0FQQl9FUlJfU1QJCQlCSVQoNykNCj4g PiArI2RlZmluZSBDUV9WU19FUlJfU1QJCQlCSVQoOCkNCj4gPiArI2RlZmluZSBIV19QQVNTMV9E T05fU1QJCQlCSVQoMTEpDQo+ID4gKyNkZWZpbmUgU09GX0lOVF9TVAkJCUJJVCgxMikNCj4gPiAr I2RlZmluZSBBTVhfRVJSX1NUCQkJQklUKDE1KQ0KPiA+ICsjZGVmaW5lIFJNWF9FUlJfU1QJCQlC SVQoMTYpDQo+ID4gKyNkZWZpbmUgQk1YX0VSUl9TVAkJCUJJVCgxNykNCj4gPiArI2RlZmluZSBS UlpPX0VSUl9TVAkJCUJJVCgxOCkNCj4gPiArI2RlZmluZSBBRk9fRVJSX1NUCQkJQklUKDE5KQ0K PiA+ICsjZGVmaW5lIElNR09fRVJSX1NUCQkJQklUKDIwKQ0KPiA+ICsjZGVmaW5lIEFBT19FUlJf U1QJCQlCSVQoMjEpDQo+ID4gKyNkZWZpbmUgUFNPX0VSUl9TVAkJCUJJVCgyMikNCj4gPiArI2Rl ZmluZSBMQ1NPX0VSUl9TVAkJCUJJVCgyMykNCj4gPiArI2RlZmluZSBCTlJfRVJSX1NUCQkJQklU KDI0KQ0KPiA+ICsjZGVmaW5lIExTQ0lfRVJSX1NUCQkJQklUKDI1KQ0KPiA+ICsjZGVmaW5lIERN QV9FUlJfU1QJCQlCSVQoMjkpDQo+ID4gKyNkZWZpbmUgU1dfUEFTUzFfRE9OX1NUCQkJQklUKDMw KQ0KPiA+ICsNCj4gPiArLyogSVNQIGludGVycnVwdCAyIHN0YXR1cyAqLw0KPiA+ICsjZGVmaW5l IFJFR19DVExfUkFXX0lOVDJfU1RBVAkJMHgwMDM0DQo+ID4gKyNkZWZpbmUgQUZPX0RPTkVfU1QJ CQlCSVQoNSkNCj4gPiArI2RlZmluZSBBQU9fRE9ORV9TVAkJCUJJVCg3KQ0KPiA+ICsNCj4gPiAr LyogQ29uZmlndXJlcyBzZW5zb3IgbW9kZSAqLw0KPiA+ICsjZGVmaW5lIFJFR19UR19TRU5fTU9E RQkJCTB4MDIzMA0KPiA+ICsjZGVmaW5lIFRHX1NFTl9NT0RFX0NNT1NfRU4JCUJJVCgwKQ0KPiA+ ICsNCj4gPiArLyogVmlldyBmaW5kZXIgbW9kZSBjb250cm9sICovDQo+ID4gKyNkZWZpbmUgUkVH X1RHX1ZGX0NPTgkJCTB4MDIzNA0KPiA+ICsjZGVmaW5lIFRHX1ZGX0NPTl9WRkRBVEFfRU4JCUJJ VCgwKQ0KPiA+ICsNCj4gPiArLyogVmlldyBmaW5kZXIgbW9kZSBjb250cm9sICovDQo+ID4gKyNk ZWZpbmUgUkVHX1RHX0lOVEVSX1NUCQkJMHgwMjZjDQo+ID4gKyNkZWZpbmUgVEdfQ1NfTUFTSwkJ CTB4M2YwMA0KPiA+ICsjZGVmaW5lIFRHX0lETEVfU1QJCQlCSVQoOCkNCj4gPiArDQo+ID4gKy8q IElNR08gZXJyb3Igc3RhdHVzIHJlZ2lzdGVyICovDQo+ID4gKyNkZWZpbmUgUkVHX0lNR09fRVJS X1NUQVQJCTB4MTM2MA0KPiA+ICsvKiBSUlpPIGVycm9yIHN0YXR1cyByZWdpc3RlciAqLw0KPiA+ ICsjZGVmaW5lIFJFR19SUlpPX0VSUl9TVEFUCQkweDEzNjQNCj4gPiArLyogQUFPIGVycm9yIHN0 YXR1cyByZWdpc3RlciAqLw0KPiA+ICsjZGVmaW5lIFJFR19BQU9fRVJSX1NUQVQJCTB4MTM2OA0K PiA+ICsvKiBBRk8gZXJyb3Igc3RhdHVzIHJlZ2lzdGVyICovDQo+ID4gKyNkZWZpbmUgUkVHX0FG T19FUlJfU1RBVAkJMHgxMzZjDQo+ID4gKy8qIExDU08gZXJyb3Igc3RhdHVzIHJlZ2lzdGVyICov DQo+ID4gKyNkZWZpbmUgUkVHX0xDU09fRVJSX1NUQVQJCTB4MTM3MA0KPiA+ICsvKiBCUENJIGVy cm9yIHN0YXR1cyByZWdpc3RlciAqLw0KPiA+ICsjZGVmaW5lIFJFR19CUENJX0VSUl9TVEFUCQkw eDEzN2MNCj4gPiArLyogTFNDSSBlcnJvciBzdGF0dXMgcmVnaXN0ZXIgKi8NCj4gPiArI2RlZmlu ZSBSRUdfTFNDSV9FUlJfU1RBVAkJMHgxMzg0DQo+ID4gKy8qIExNVk8gZXJyb3Igc3RhdHVzIHJl Z2lzdGVyICovDQo+ID4gKyNkZWZpbmUgUkVHX0xNVk9fRVJSX1NUQVQJCTB4MTM5MA0KPiA+ICsv KiBGTEtPIGVycm9yIHN0YXR1cyByZWdpc3RlciAqLw0KPiA+ICsjZGVmaW5lIFJFR19GTEtPX0VS Ul9TVEFUCQkweDEzOTQNCj4gPiArLyogUFNPIGVycm9yIHN0YXR1cyByZWdpc3RlciAqLw0KPiA+ ICsjZGVmaW5lIFJFR19QU09fRVJSX1NUQVQJCTB4MTNhMA0KPiA+ICsNCj4gPiArLyogQ1EwIGJh c2UgYWRkcmVzcyAqLw0KPiA+ICsjZGVmaW5lIFJFR19DUV9USFIwX0JBU0VBRERSCQkweDAxOTgN Cj4gPiArLyogRnJhbWUgc2VxdWVuY2UgbnVtYmVyICovDQo+ID4gKyNkZWZpbmUgUkVHX0ZSQU1F X1NFUV9OVU0JCTB4MTNiOA0KPiA+ICsNCj4gPiArLyogSVJRIEVycm9yIE1hc2sgKi8NCj4gPiAr I2RlZmluZSBJTlRfU1RfTUFTS19DQU1fRVJSCQkoIFwNCj4gPiArCQkJCQlUR19FUlJfU1QgfFwN Cj4gPiArCQkJCQlUR19HQkVSUl9TVCB8XA0KPiA+ICsJCQkJCUNRX0NPREVfRVJSX1NUIHxcDQo+ ID4gKwkJCQkJQ1FfQVBCX0VSUl9TVCB8XA0KPiA+ICsJCQkJCUNRX1ZTX0VSUl9TVCB8XA0KPiA+ ICsJCQkJCUJOUl9FUlJfU1QgfFwNCj4gPiArCQkJCQlSTVhfRVJSX1NUIHxcDQo+ID4gKwkJCQkJ Qk1YX0VSUl9TVCB8XA0KPiA+ICsJCQkJCUJOUl9FUlJfU1QgfFwNCj4gPiArCQkJCQlMU0NJX0VS Ul9TVCB8XA0KPiA+ICsJCQkJCURNQV9FUlJfU1QpDQo+ID4gKw0KPiA+ICsjZW5kaWYJLyogX19N VEtfQ0FNX1JFR1NfSF9fICovDQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWVkaWEvcGxhdGZv cm0vbXRrLWlzcC9pc3BfNTAvY2FtL210a19jYW0uYyBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0v bXRrLWlzcC9pc3BfNTAvY2FtL210a19jYW0uYw0KPiA+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0DQo+ ID4gaW5kZXggMDAwMDAwMDAwMDAwLi4yM2ZkYjhiNGFiYzUNCj4gPiAtLS0gL2Rldi9udWxsDQo+ ID4gKysrIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL2lzcF81MC9jYW0vbXRrX2Nh bS5jDQo+ID4gQEAgLTAsMCArMSwyMDg3IEBADQo+ID4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlm aWVyOiBHUEwtMi4wDQo+ID4gKy8vIENvcHlyaWdodCAoYykgMjAxOSBNZWRpYVRlayBJbmMuDQo+ ID4gKw0KPiA+ICsjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51 eC9kbWEtbWFwcGluZy5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvb2YuaD4NCj4gPiArI2luY2x1 ZGUgPGxpbnV4L29mX2dyYXBoLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9vZl9wbGF0Zm9ybS5o Pg0KPiA+ICsjaW5jbHVkZSA8bGludXgvbW9kdWxlLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9w bGF0Zm9ybV9kZXZpY2UuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3BtX3J1bnRpbWUuaD4NCj4g PiArI2luY2x1ZGUgPGxpbnV4L3ZpZGVvZGV2Mi5oPg0KPiA+ICsjaW5jbHVkZSA8bWVkaWEvbWVk aWEtZW50aXR5Lmg+DQo+ID4gKyNpbmNsdWRlIDxtZWRpYS92NGwyLWFzeW5jLmg+DQo+ID4gKyNp bmNsdWRlIDxtZWRpYS92NGwyLWNvbW1vbi5oPg0KPiA+ICsjaW5jbHVkZSA8bWVkaWEvdjRsMi1l dmVudC5oPg0KPiA+ICsjaW5jbHVkZSA8bWVkaWEvdjRsMi1md25vZGUuaD4NCj4gPiArI2luY2x1 ZGUgPG1lZGlhL3Y0bDItaW9jdGwuaD4NCj4gPiArI2luY2x1ZGUgPG1lZGlhL3Y0bDItbWMuaD4N Cj4gPiArI2luY2x1ZGUgPG1lZGlhL3Y0bDItc3ViZGV2Lmg+DQo+ID4gKyNpbmNsdWRlIDxtZWRp YS92aWRlb2J1ZjItZG1hLWNvbnRpZy5oPg0KPiA+ICsNCj4gPiArI2luY2x1ZGUgIm10a19jYW0u aCINCj4gPiArI2luY2x1ZGUgIm10a19jYW0taHcuaCINCj4gPiArDQo+ID4gKyNkZWZpbmUgUl9J TUdPCQlCSVQoMCkNCj4gPiArI2RlZmluZSBSX1JSWk8JCUJJVCgxKQ0KPiA+ICsjZGVmaW5lIFJf QUFPCQlCSVQoMykNCj4gPiArI2RlZmluZSBSX0FGTwkJQklUKDQpDQo+ID4gKyNkZWZpbmUgUl9M Q1NPCQlCSVQoNSkNCj4gPiArI2RlZmluZSBSX0xNVk8JCUJJVCg3KQ0KPiA+ICsjZGVmaW5lIFJf RkxLTwkJQklUKDgpDQo+ID4gKyNkZWZpbmUgUl9QU08JCUJJVCgxMCkNCj4gPiArDQo+ID4gKyNk ZWZpbmUgTVRLX0lTUF9PTkVfUElYRUxfTU9ERQkJMQ0KPiA+ICsjZGVmaW5lIE1US19JU1BfTUlO X1JFU0laRV9SQVRJTwk2DQo+ID4gKyNkZWZpbmUgTVRLX0lTUF9NQVhfUlVOTklOR19KT0JTCTMN Cj4gPiArDQo+ID4gKyNkZWZpbmUgTVRLX0NBTV9DSU9fUEFEX1NSQwkJNA0KPiA+ICsjZGVmaW5l IE1US19DQU1fQ0lPX1BBRF9TSU5LCQkxMQ0KPiA+ICsNCj4gPiArc3RhdGljIGlubGluZSBzdHJ1 Y3QgbXRrX2NhbV92aWRlb19kZXZpY2UgKg0KPiA+ICtmaWxlX3RvX210a19jYW1fbm9kZShzdHJ1 Y3QgZmlsZSAqX19maWxlKQ0KPiA+ICt7DQo+ID4gKwlyZXR1cm4gY29udGFpbmVyX29mKHZpZGVv X2RldmRhdGEoX19maWxlKSwNCj4gPiArCQlzdHJ1Y3QgbXRrX2NhbV92aWRlb19kZXZpY2UsIHZk ZXYpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW5saW5lIHN0cnVjdCBtdGtfY2FtX3Zp ZGVvX2RldmljZSAqDQo+ID4gK210a19jYW1fdmJxX3RvX3ZkZXYoc3RydWN0IHZiMl9xdWV1ZSAq X192cSkNCj4gPiArew0KPiA+ICsJcmV0dXJuIGNvbnRhaW5lcl9vZihfX3ZxLCBzdHJ1Y3QgbXRr X2NhbV92aWRlb19kZXZpY2UsIHZicSk7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbmxp bmUgc3RydWN0IG10a19jYW1fZGV2X3JlcXVlc3QgKg0KPiA+ICttdGtfY2FtX3JlcV90b19kZXZf cmVxKHN0cnVjdCBtZWRpYV9yZXF1ZXN0ICpfX3JlcSkNCj4gPiArew0KPiA+ICsJcmV0dXJuIGNv bnRhaW5lcl9vZihfX3JlcSwgc3RydWN0IG10a19jYW1fZGV2X3JlcXVlc3QsIHJlcSk7DQo+ID4g K30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbmxpbmUgc3RydWN0IG10a19jYW1fZGV2X2J1ZmZlciAq DQo+ID4gK210a19jYW1fdmIyX2J1Zl90b19kZXZfYnVmKHN0cnVjdCB2YjJfYnVmZmVyICpfX3Zi KQ0KPiA+ICt7DQo+ID4gKwlyZXR1cm4gY29udGFpbmVyX29mKF9fdmIsIHN0cnVjdCBtdGtfY2Ft X2Rldl9idWZmZXIsIHZiYi52YjJfYnVmKTsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIHZv aWQgbXRrX2NhbV9kZXZfam9iX2RvbmUoc3RydWN0IG10a19jYW1fZGV2ICpjYW0sDQo+ID4gKwkJ CQkgc3RydWN0IG10a19jYW1fZGV2X3JlcXVlc3QgKnJlcSwNCj4gPiArCQkJCSBlbnVtIHZiMl9i dWZmZXJfc3RhdGUgc3RhdGUpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtZWRpYV9yZXF1ZXN0X29i amVjdCAqb2JqLCAqb2JqX3ByZXY7DQo+ID4gKwl1bnNpZ25lZCBsb25nIGZsYWdzOw0KPiA+ICsJ dTY0IHRzX2VvZiA9IGt0aW1lX2dldF9ib290dGltZV9ucygpOw0KPiA+ICsNCj4gPiArCWlmICgh Y2FtLT5zdHJlYW1pbmcpDQo+ID4gKwkJcmV0dXJuOw0KPiA+ICsNCj4gPiArCWRldl9kYmcoY2Ft LT5kZXYsICJqb2IgZG9uZSByZXF1ZXN0OiVzIGZyYW1lX3NlcTolZCBzdGF0ZTolZFxuIiwNCj4g PiArCQlyZXEtPnJlcS5kZWJ1Z19zdHIsIHJlcS0+ZnJhbWVfcGFyYW1zLmZyYW1lX3NlcV9ubywg c3RhdGUpOw0KPiA+ICsNCj4gPiArCWxpc3RfZm9yX2VhY2hfZW50cnlfc2FmZShvYmosIG9ial9w cmV2LCAmcmVxLT5yZXEub2JqZWN0cywgbGlzdCkgew0KPiA+ICsJCXN0cnVjdCB2YjJfYnVmZmVy ICp2YjsNCj4gPiArCQlzdHJ1Y3QgbXRrX2NhbV9kZXZfYnVmZmVyICpidWY7DQo+ID4gKwkJc3Ry dWN0IG10a19jYW1fdmlkZW9fZGV2aWNlICpub2RlOw0KPiA+ICsNCj4gPiArCQlpZiAoIXZiMl9y ZXF1ZXN0X29iamVjdF9pc19idWZmZXIob2JqKSkNCj4gPiArCQkJY29udGludWU7DQo+ID4gKwkJ dmIgPSBjb250YWluZXJfb2Yob2JqLCBzdHJ1Y3QgdmIyX2J1ZmZlciwgcmVxX29iaik7DQo+ID4g KwkJYnVmID0gbXRrX2NhbV92YjJfYnVmX3RvX2Rldl9idWYodmIpOw0KPiA+ICsJCW5vZGUgPSBt dGtfY2FtX3ZicV90b192ZGV2KHZiLT52YjJfcXVldWUpOw0KPiA+ICsJCXNwaW5fbG9ja19pcnFz YXZlKCZub2RlLT5idWZfbGlzdF9sb2NrLCBmbGFncyk7DQo+ID4gKwkJbGlzdF9kZWwoJmJ1Zi0+ bGlzdCk7DQo+ID4gKwkJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmbm9kZS0+YnVmX2xpc3RfbG9j aywgZmxhZ3MpOw0KPiA+ICsJCWJ1Zi0+dmJiLnNlcXVlbmNlID0gcmVxLT5mcmFtZV9wYXJhbXMu ZnJhbWVfc2VxX25vOw0KPiA+ICsJCWlmIChWNEwyX1RZUEVfSVNfT1VUUFVUKHZiLT52YjJfcXVl dWUtPnR5cGUpKQ0KPiA+ICsJCQl2Yi0+dGltZXN0YW1wID0gdHNfZW9mOw0KPiA+ICsJCWVsc2UN Cj4gPiArCQkJdmItPnRpbWVzdGFtcCA9IHJlcS0+dGltZXN0YW1wOw0KPiA+ICsJCXZiMl9idWZm ZXJfZG9uZSgmYnVmLT52YmIudmIyX2J1Ziwgc3RhdGUpOw0KPiA+ICsJfQ0KPiA+ICt9DQo+ID4g Kw0KPiA+ICtzdHJ1Y3QgbXRrX2NhbV9kZXZfcmVxdWVzdCAqbXRrX2NhbV9kZXZfZ2V0X3JlcShz dHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSwNCj4gPiArCQkJCQkJdW5zaWduZWQgaW50IGZyYW1lX3Nl cV9ubykNCj4gPiArew0KPiA+ICsJc3RydWN0IG10a19jYW1fZGV2X3JlcXVlc3QgKnJlcSwgKnJl cV9wcmV2Ow0KPiA+ICsJdW5zaWduZWQgbG9uZyBmbGFnczsNCj4gPiArDQo+ID4gKwlzcGluX2xv Y2tfaXJxc2F2ZSgmY2FtLT5ydW5uaW5nX2pvYl9sb2NrLCBmbGFncyk7DQo+ID4gKwlsaXN0X2Zv cl9lYWNoX2VudHJ5X3NhZmUocmVxLCByZXFfcHJldiwgJmNhbS0+cnVubmluZ19qb2JfbGlzdCwg bGlzdCkgew0KPiA+ICsJCWRldl9kYmcoY2FtLT5kZXYsICJmcmFtZV9zZXE6JWQsIGdldCBmcmFt ZV9zZXE6JWRcbiIsDQo+ID4gKwkJCXJlcS0+ZnJhbWVfcGFyYW1zLmZyYW1lX3NlcV9ubywgZnJh bWVfc2VxX25vKTsNCj4gPiArDQo+ID4gKwkJLyogTWF0Y2ggYnkgdGhlIGVuLXF1ZXVlZCByZXF1 ZXN0IG51bWJlciAqLw0KPiA+ICsJCWlmIChyZXEtPmZyYW1lX3BhcmFtcy5mcmFtZV9zZXFfbm8g PT0gZnJhbWVfc2VxX25vKSB7DQo+ID4gKwkJCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmNhbS0+ cnVubmluZ19qb2JfbG9jaywgZmxhZ3MpOw0KPiA+ICsJCQlyZXR1cm4gcmVxOw0KPiA+ICsJCX0N Cj4gPiArCX0NCj4gPiArCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmNhbS0+cnVubmluZ19qb2Jf bG9jaywgZmxhZ3MpOw0KPiA+ICsNCj4gPiArCXJldHVybiBOVUxMOw0KPiA+ICt9DQo+ID4gKw0K PiA+ICt2b2lkIG10a19jYW1fZGV2X2RlcXVldWVfcmVxX2ZyYW1lKHN0cnVjdCBtdGtfY2FtX2Rl diAqY2FtLA0KPiA+ICsJCQkJICAgdW5zaWduZWQgaW50IGZyYW1lX3NlcV9ubykNCj4gPiArew0K PiA+ICsJc3RydWN0IG10a19jYW1fZGV2X3JlcXVlc3QgKnJlcSwgKnJlcV9wcmV2Ow0KPiA+ICsJ dW5zaWduZWQgbG9uZyBmbGFnczsNCj4gPiArDQo+ID4gKwlzcGluX2xvY2tfaXJxc2F2ZSgmY2Ft LT5ydW5uaW5nX2pvYl9sb2NrLCBmbGFncyk7DQo+ID4gKwlsaXN0X2Zvcl9lYWNoX2VudHJ5X3Nh ZmUocmVxLCByZXFfcHJldiwgJmNhbS0+cnVubmluZ19qb2JfbGlzdCwgbGlzdCkgew0KPiA+ICsJ CWRldl9kYmcoY2FtLT5kZXYsICJmcmFtZV9zZXE6JWQsIGRlLXF1ZXVlIGZyYW1lX3NlcTolZFxu IiwNCj4gPiArCQkJcmVxLT5mcmFtZV9wYXJhbXMuZnJhbWVfc2VxX25vLCBmcmFtZV9zZXFfbm8p Ow0KPiA+ICsNCj4gPiArCQkvKiBNYXRjaCBieSB0aGUgZW4tcXVldWVkIHJlcXVlc3QgbnVtYmVy ICovDQo+ID4gKwkJaWYgKHJlcS0+ZnJhbWVfcGFyYW1zLmZyYW1lX3NlcV9ubyA9PSBmcmFtZV9z ZXFfbm8pIHsNCj4gPiArCQkJY2FtLT5ydW5uaW5nX2pvYl9jb3VudC0tOw0KPiA+ICsJCQkvKiBQ YXNzIHRvIHVzZXIgc3BhY2UgKi8NCj4gPiArCQkJbXRrX2NhbV9kZXZfam9iX2RvbmUoY2FtLCBy ZXEsIFZCMl9CVUZfU1RBVEVfRE9ORSk7DQo+ID4gKwkJCWxpc3RfZGVsKCZyZXEtPmxpc3QpOw0K PiA+ICsJCQlicmVhazsNCj4gPiArCQl9IGVsc2UgaWYgKHJlcS0+ZnJhbWVfcGFyYW1zLmZyYW1l X3NlcV9ubyA8IGZyYW1lX3NlcV9ubykgew0KPiA+ICsJCQljYW0tPnJ1bm5pbmdfam9iX2NvdW50 LS07DQo+ID4gKwkJCS8qIFBhc3MgdG8gdXNlciBzcGFjZSBmb3IgZnJhbWUgZHJvcCAqLw0KPiA+ ICsJCQltdGtfY2FtX2Rldl9qb2JfZG9uZShjYW0sIHJlcSwgVkIyX0JVRl9TVEFURV9FUlJPUik7 DQo+IEhpLCBJIHNlZSB0aGF0IGZyYW1lX3BhcmFtcy5mcmFtZV9zZXFfbm8gaXMgaW5jcmVtZW50 ZWQgd2hlbiBhIHJlcXVlc3QgaXMgcXVldWVkDQo+IGFuZCBmcmFtZV9zZXFfbm8gaXMgcmVhZCBm cm9tIGEgcmVnaXN0ZXIsIHNvIGlmIHRoZSBmaXJzdCBpcyBsb3dlciB0aGFuIHRoZSBsYXR0ZXIN Cj4gaXQgbWVhbnMgdXNlcnNwYWNlIHdhcyBxdWV1ZWluZyByZXF1ZXN0IHRvbyBzbG93bHkgYW5k IG1pc3NlZCBmcmFtZXMgcmlnaHQ/DQo+IFNvIHVzZXJzcGFjZSB3aWxsIGhhdmUgdG8gY2F0Y2gg dXAgaW4gb3JkZXIgbm90IHRvIGdldCAiRVJST1IiIGJ1ZmZlcnMuDQo+IE1heWJlIHRoZSBkcml2 ZXIgY2FuIGp1c3Qgc2tpcCBsb3N0IGZyYW1lcy4gSW4gdGhlIHJraXNwMSBmb3IgZXhhbXBsZSwN Cj4gaWYgdGhlcmUgaXMgbm8gYnVmZmVyIGF2YWlsYWJsZSwgdGhlIGRyaXZlciBqdXN0IHdyaXRl IHRvIGEgZHVtbXkgYnVmZmVyIHRoYXQgaXMNCj4gbmV2ZXIgc2VudCB0byB1c2Vyc3BhY2UuIFRo aXMgd2F5IHVzZXJzcGFjZSBhbHdheXMgZ2V0IHZhbGlkIGJ1ZmZlcnMgYmFjayB3aGVuDQo+IGRl cXVldWVpbmcuDQo+IA0KDQpRMS4gV2Ugd2lsbCB1cGRhdGUgZnJhbWVfcGFyYW1zLmZyYW1lX3Nl cV9ubyBpbnRvIEhXIHBlciBmcmFtZS4NClNvIHRoZSBmcmFtZV9zZXFfbm8gaXMgcmVhZCBmcm9t IEhXIHJlZ2lzdGVyIHNob3VsZCBub3QgYmUgbGFyZ2UgdGhhbg0KZnJhbWVfcGFyYW1zLmZyYW1l X3NlcV9uby4gSWYgdXNlcnNwYWNlIHdhcyBxdWV1ZWluZyByZXF1ZXN0IHRvbyBzbG93bHksDQpJ U1AgSFcganVzdCBza2lwIGZyYW1lIG91dHB1dCBkdWUgdG8gbm8gYXZhaWxhYmxlIGJ1ZmZlcnMu DQoNClEyLiBGb3IgdGhpcyBjb2RlIGJsb2NrLCBpdCBoYW5kbGVzIHRoZSBoZWF2eSBzeXN0ZW0g bG9hZGluZy4gZS5nDQphYm5vcm1hbCBJU1IgZXhlY3V0aW9uLiBJbiB0aGlzIHNjZW5hcmlvLCBJ U1AgSFcgd2lsbCBrZWVwIG91dHB1dCBmcmFtZQ0KYnVmZmVycyBhbmQgdXBkYXRlIGZyYW1lX3Nl cV9ubyBpbnRvIEhXLiBTbyBJU1AgUDEgZHJpdmVyIG1pc3Mgc29tZQ0KaW50ZXJydXB0IHRpbWlu ZyBhbmQganVzdCBnb3QgdGhlIGxhdGVzdCBmcmFtZV9zZXFfbm8gZnJvbSBIVy4NCldpdGggdGhp cyBjaGVjaywgd2Ugd2lsbCByZXR1cm4gYWxsIGZyYW1lIGJ1ZmZlcnMgd2hpY2ggaGF2ZSBiZSBw cm9jZWVkDQpieSBIVy4gT3RoZXJ3aXNlLCB1c2Vyc3BhY2UgbWF5IG5vdCBlbi1xdWV1ZSBhbnkg ZnJhbWUgYnVmZmVycyBkdWUgdG8NCnNvbWUgZnJhbWUgYnVmZmVycyBhcmUgbm90IHJldHVybmVk IGZyb20ga2VybmVsIGRyaXZlci4NCg0KPiA+ICsJCQlkZXZfd2FybihjYW0tPmRldiwgImZyYW1l X3NlcTolZCBkcm9wXG4iLA0KPiA+ICsJCQkJIHJlcS0+ZnJhbWVfcGFyYW1zLmZyYW1lX3NlcV9u byk7DQo+ID4gKwkJCWxpc3RfZGVsKCZyZXEtPmxpc3QpOw0KPiA+ICsJCX0gZWxzZSB7DQo+ID4g KwkJCWJyZWFrOw0KPiBEb2VzIHRoaXMgY2FzZSBjYW4gZXZlciBvY2N1cj8NCj4gDQo+IFRoYW5r cywNCj4gRGFmbmENCj4gDQoNClRvIGJlIGhvbmVzdCwgaXQgbmV2ZXIgaGFwcGVuZWQuDQpJIHdp bGwgcmVtb3ZlIHRoaXMuDQoNCkJlc3QgcmVnYXJkcywNCg0KSnVuZ28NCg0KPiA+ICsJCX0NCj4g PiArCX0NCj4gPiArCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmNhbS0+cnVubmluZ19qb2JfbG9j aywgZmxhZ3MpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgdm9pZCBtdGtfY2FtX2Rldl9y ZXFfY2xlYW51cChzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSkNCj4gPiArew0KPiA+ICsJc3RydWN0 IG10a19jYW1fZGV2X3JlcXVlc3QgKnJlcSwgKnJlcV9wcmV2Ow0KPiA+ICsJdW5zaWduZWQgbG9u ZyBmbGFnczsNCj4gPiArDQo+ID4gKwlkZXZfZGJnKGNhbS0+ZGV2LCAiJXNcbiIsIF9fZnVuY19f KTsNCj4gPiArDQo+ID4gKwlzcGluX2xvY2tfaXJxc2F2ZSgmY2FtLT5wZW5kaW5nX2pvYl9sb2Nr LCBmbGFncyk7DQo+ID4gKwlsaXN0X2Zvcl9lYWNoX2VudHJ5X3NhZmUocmVxLCByZXFfcHJldiwg JmNhbS0+cGVuZGluZ19qb2JfbGlzdCwgbGlzdCkNCj4gPiArCQlsaXN0X2RlbCgmcmVxLT5saXN0 KTsNCj4gPiArCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmNhbS0+cGVuZGluZ19qb2JfbG9jaywg ZmxhZ3MpOw0KPiA+ICsNCj4gPiArCXNwaW5fbG9ja19pcnFzYXZlKCZjYW0tPnJ1bm5pbmdfam9i X2xvY2ssIGZsYWdzKTsNCj4gPiArCWxpc3RfZm9yX2VhY2hfZW50cnlfc2FmZShyZXEsIHJlcV9w cmV2LCAmY2FtLT5ydW5uaW5nX2pvYl9saXN0LCBsaXN0KQ0KPiA+ICsJCWxpc3RfZGVsKCZyZXEt Pmxpc3QpOw0KPiA+ICsJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmY2FtLT5ydW5uaW5nX2pvYl9s b2NrLCBmbGFncyk7DQo+ID4gK30NCj4gPiArDQo+ID4gK3ZvaWQgbXRrX2NhbV9kZXZfcmVxX3Ry eV9xdWV1ZShzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSkNCj4gPiArew0KPiA+ICsJc3RydWN0IG10 a19jYW1fZGV2X3JlcXVlc3QgKnJlcSwgKnJlcV9wcmV2Ow0KPiA+ICsJdW5zaWduZWQgbG9uZyBm bGFnczsNCj4gPiArDQo+ID4gKwlpZiAoIWNhbS0+c3RyZWFtaW5nKSB7DQo+ID4gKwkJZGV2X2Ri ZyhjYW0tPmRldiwgInN0cmVhbSBpcyBvZmZcbiIpOw0KPiA+ICsJCXJldHVybjsNCj4gPiArCX0N Cj4gPiArDQo+ID4gKwlzcGluX2xvY2tfaXJxc2F2ZSgmY2FtLT5wZW5kaW5nX2pvYl9sb2NrLCBm bGFncyk7DQo+ID4gKwlzcGluX2xvY2tfaXJxc2F2ZSgmY2FtLT5ydW5uaW5nX2pvYl9sb2NrLCBm bGFncyk7DQo+ID4gKwlsaXN0X2Zvcl9lYWNoX2VudHJ5X3NhZmUocmVxLCByZXFfcHJldiwgJmNh bS0+cGVuZGluZ19qb2JfbGlzdCwgbGlzdCkgew0KPiA+ICsJCWlmIChjYW0tPnJ1bm5pbmdfam9i X2NvdW50ID49IE1US19JU1BfTUFYX1JVTk5JTkdfSk9CUykgew0KPiA+ICsJCQlkZXZfZGJnKGNh bS0+ZGV2LCAiam9icyBhcmUgZnVsbFxuIik7DQo+ID4gKwkJCWJyZWFrOw0KPiA+ICsJCX0NCj4g PiArCQljYW0tPnJ1bm5pbmdfam9iX2NvdW50Kys7DQo+ID4gKwkJbGlzdF9kZWwoJnJlcS0+bGlz dCk7DQo+ID4gKwkJbGlzdF9hZGRfdGFpbCgmcmVxLT5saXN0LCAmY2FtLT5ydW5uaW5nX2pvYl9s aXN0KTsNCj4gPiArCQltdGtfaXNwX3JlcV9lbnF1ZXVlKGNhbSwgcmVxKTsNCj4gPiArCX0NCj4g PiArCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJmNhbS0+cnVubmluZ19qb2JfbG9jaywgZmxhZ3Mp Ow0KPiA+ICsJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmY2FtLT5wZW5kaW5nX2pvYl9sb2NrLCBm bGFncyk7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBzdHJ1Y3QgbWVkaWFfcmVxdWVzdCAq bXRrX2NhbV9yZXFfYWxsb2Moc3RydWN0IG1lZGlhX2RldmljZSAqbWRldikNCj4gPiArew0KPiA+ ICsJc3RydWN0IG10a19jYW1fZGV2X3JlcXVlc3QgKmNhbV9kZXZfcmVxOw0KPiA+ICsNCj4gPiAr CWNhbV9kZXZfcmVxID0ga3phbGxvYyhzaXplb2YoKmNhbV9kZXZfcmVxKSwgR0ZQX0tFUk5FTCk7 DQo+ID4gKw0KPiA+ICsJcmV0dXJuICZjYW1fZGV2X3JlcS0+cmVxOw0KPiA+ICt9DQo+ID4gKw0K PiA+ICtzdGF0aWMgdm9pZCBtdGtfY2FtX3JlcV9mcmVlKHN0cnVjdCBtZWRpYV9yZXF1ZXN0ICpy ZXEpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtfY2FtX2Rldl9yZXF1ZXN0ICpjYW1fZGV2X3Jl cSA9IG10a19jYW1fcmVxX3RvX2Rldl9yZXEocmVxKTsNCj4gPiArDQo+ID4gKwlrZnJlZShjYW1f ZGV2X3JlcSk7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyB2b2lkIG10a19jYW1fcmVxX3F1 ZXVlKHN0cnVjdCBtZWRpYV9yZXF1ZXN0ICpyZXEpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtf Y2FtX2Rldl9yZXF1ZXN0ICpjYW1fcmVxID0gbXRrX2NhbV9yZXFfdG9fZGV2X3JlcShyZXEpOw0K PiA+ICsJc3RydWN0IG10a19jYW1fZGV2ICpjYW0gPSBjb250YWluZXJfb2YocmVxLT5tZGV2LCBz dHJ1Y3QgbXRrX2NhbV9kZXYsDQo+ID4gKwkJCQkJICAgICAgIG1lZGlhX2Rldik7DQo+ID4gKwl1 bnNpZ25lZCBsb25nIGZsYWdzOw0KPiA+ICsNCj4gPiArCS8qIHVwZGF0ZSBmcmFtZV9wYXJhbXMn cyBkbWFfYnVmcyBpbiBtdGtfY2FtX3ZiMl9idWZfcXVldWUgKi8NCj4gPiArCXZiMl9yZXF1ZXN0 X3F1ZXVlKHJlcSk7DQo+ID4gKw0KPiA+ICsJLyogYWRkIHRvIHBlbmRpbmcgam9iIGxpc3QgKi8N Cj4gPiArCXNwaW5fbG9ja19pcnFzYXZlKCZjYW0tPnBlbmRpbmdfam9iX2xvY2ssIGZsYWdzKTsN Cj4gPiArCWxpc3RfYWRkX3RhaWwoJmNhbV9yZXEtPmxpc3QsICZjYW0tPnBlbmRpbmdfam9iX2xp c3QpOw0KPiA+ICsJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmY2FtLT5wZW5kaW5nX2pvYl9sb2Nr LCBmbGFncyk7DQo+ID4gKw0KPiA+ICsJbXRrX2NhbV9kZXZfcmVxX3RyeV9xdWV1ZShjYW0pOw0K PiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgdW5zaWduZWQgaW50IGdldF9waXhlbF9iaXRzKHVu c2lnbmVkIGludCBwaXhfZm10KQ0KPiA+ICt7DQo+ID4gKwlzd2l0Y2ggKHBpeF9mbXQpIHsNCj4g PiArCWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NCR0dSODoNCj4gPiArCWNhc2UgVjRMMl9QSVhf Rk1UX01USVNQX1NHQlJHODoNCj4gPiArCWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NHUkJHODoN Cj4gPiArCWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NSR0dCODoNCj4gPiArCWNhc2UgVjRMMl9Q SVhfRk1UX01USVNQX1NCR0dSOEY6DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TR0JS RzhGOg0KPiA+ICsJY2FzZSBWNEwyX1BJWF9GTVRfTVRJU1BfU0dSQkc4RjoNCj4gPiArCWNhc2Ug VjRMMl9QSVhfRk1UX01USVNQX1NSR0dCOEY6DQo+ID4gKwkJcmV0dXJuIDg7DQo+ID4gKwljYXNl IFY0TDJfUElYX0ZNVF9NVElTUF9TQkdHUjEwOg0KPiA+ICsJY2FzZSBWNEwyX1BJWF9GTVRfTVRJ U1BfU0dCUkcxMDoNCj4gPiArCWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NHUkJHMTA6DQo+ID4g KwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TUkdHQjEwOg0KPiA+ICsJY2FzZSBWNEwyX1BJWF9G TVRfTVRJU1BfU0JHR1IxMEY6DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TR0JSRzEw RjoNCj4gPiArCWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NHUkJHMTBGOg0KPiA+ICsJY2FzZSBW NEwyX1BJWF9GTVRfTVRJU1BfU1JHR0IxMEY6DQo+ID4gKwkJcmV0dXJuIDEwOw0KPiA+ICsJY2Fz ZSBWNEwyX1BJWF9GTVRfTVRJU1BfU0JHR1IxMjoNCj4gPiArCWNhc2UgVjRMMl9QSVhfRk1UX01U SVNQX1NHQlJHMTI6DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TR1JCRzEyOg0KPiA+ ICsJY2FzZSBWNEwyX1BJWF9GTVRfTVRJU1BfU1JHR0IxMjoNCj4gPiArCWNhc2UgVjRMMl9QSVhf Rk1UX01USVNQX1NCR0dSMTJGOg0KPiA+ICsJY2FzZSBWNEwyX1BJWF9GTVRfTVRJU1BfU0dCUkcx MkY6DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TR1JCRzEyRjoNCj4gPiArCWNhc2Ug VjRMMl9QSVhfRk1UX01USVNQX1NSR0dCMTJGOg0KPiA+ICsJCXJldHVybiAxMjsNCj4gPiArCWNh c2UgVjRMMl9QSVhfRk1UX01USVNQX1NCR0dSMTQ6DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9N VElTUF9TR0JSRzE0Og0KPiA+ICsJY2FzZSBWNEwyX1BJWF9GTVRfTVRJU1BfU0dSQkcxNDoNCj4g PiArCWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NSR0dCMTQ6DQo+ID4gKwljYXNlIFY0TDJfUElY X0ZNVF9NVElTUF9TQkdHUjE0RjoNCj4gPiArCWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NHQlJH MTRGOg0KPiA+ICsJY2FzZSBWNEwyX1BJWF9GTVRfTVRJU1BfU0dSQkcxNEY6DQo+ID4gKwljYXNl IFY0TDJfUElYX0ZNVF9NVElTUF9TUkdHQjE0RjoNCj4gPiArCQlyZXR1cm4gMTQ7DQo+ID4gKwlk ZWZhdWx0Og0KPiA+ICsJCXJldHVybiAwOw0KPiA+ICsJfQ0KPiA+ICt9DQo+ID4gKw0KPiA+ICtz dGF0aWMgdm9pZCBjYWxfaW1hZ2VfcGl4X21wKHN0cnVjdCBtdGtfY2FtX2RldiAqY2FtLCB1bnNp Z25lZCBpbnQgbm9kZV9pZCwNCj4gPiArCQkJICAgICBzdHJ1Y3QgdjRsMl9waXhfZm9ybWF0X21w bGFuZSAqbXApDQo+ID4gK3sNCj4gPiArCXVuc2lnbmVkIGludCBicGwsIHBwbDsNCj4gPiArCXVu c2lnbmVkIGludCBwaXhlbF9iaXRzID0gZ2V0X3BpeGVsX2JpdHMobXAtPnBpeGVsZm9ybWF0KTsN Cj4gPiArCXVuc2lnbmVkIGludCB3aWR0aCA9IG1wLT53aWR0aDsNCj4gPiArDQo+ID4gKwlicGwg PSAwOw0KPiA+ICsJaWYgKG5vZGVfaWQgPT0gTVRLX0NBTV9QMV9NQUlOX1NUUkVBTV9PVVQpIHsN Cj4gPiArCQkvKiBCYXllciBlbmNvZGluZyBmb3JtYXQgJiAyIGJ5dGVzIGFsaWdubWVudCAqLw0K PiA+ICsJCWJwbCA9IEFMSUdOKERJVl9ST1VORF9VUCh3aWR0aCAqIHBpeGVsX2JpdHMsIDgpLCAy KTsNCj4gPiArCX0gZWxzZSBpZiAobm9kZV9pZCA9PSBNVEtfQ0FNX1AxX1BBQ0tFRF9CSU5fT1VU KSB7DQo+ID4gKwkJLyoNCj4gPiArCQkgKiBUaGUgRlVMTC1HIGVuY29kaW5nIGZvcm1hdA0KPiA+ ICsJCSAqIDEgRyBjb21wb25lbnQgcGVyIHBpeGVsDQo+ID4gKwkJICogMSBSIGNvbXBvbmVudCBw ZXIgNCBwaXhlbA0KPiA+ICsJCSAqIDEgQiBjb21wb25lbnQgcGVyIDQgcGl4ZWwNCj4gPiArCQkg KiBUb3RhbCA0Ry8xUi8xQiBpbiA0IHBpeGVsIChwaXhlbCBwZXIgbGluZTpwcGwpDQo+ID4gKwkJ ICovDQo+ID4gKwkJcHBsID0gRElWX1JPVU5EX1VQKHdpZHRoICogNiwgNCk7DQo+ID4gKwkJYnBs ID0gRElWX1JPVU5EX1VQKHBwbCAqIHBpeGVsX2JpdHMsIDgpOw0KPiA+ICsNCj4gPiArCQkvKiA0 IGJ5dGVzIGFsaWdubWVudCBmb3IgMTAgYml0ICYgb3RoZXJzIGFyZSA4IGJ5dGVzICovDQo+ID4g KwkJaWYgKHBpeGVsX2JpdHMgPT0gMTApDQo+ID4gKwkJCWJwbCA9IEFMSUdOKGJwbCwgNCk7DQo+ ID4gKwkJZWxzZQ0KPiA+ICsJCQlicGwgPSBBTElHTihicGwsIDgpOw0KPiA+ICsJfQ0KPiA+ICsJ LyoNCj4gPiArCSAqIFRoaXMgaW1hZ2Ugb3V0cHV0IGJ1ZmZlciB3aWxsIGJlIGlucHV0IGJ1ZmZl ciBvZiBNVEsgQ0FNIERJUCBIVw0KPiA+ICsJICogRm9yIE1USyBDQU0gRElQIEhXIGNvbnN0cmFp bmVkLCBpdCBuZWVkcyA0IGJ5dGVzIGFsaWdubWVudA0KPiA+ICsJICovDQo+ID4gKwlicGwgPSBB TElHTihicGwsIDQpOw0KPiA+ICsNCj4gPiArCW1wLT5wbGFuZV9mbXRbMF0uYnl0ZXNwZXJsaW5l ID0gYnBsOw0KPiA+ICsJbXAtPnBsYW5lX2ZtdFswXS5zaXplaW1hZ2UgPSBicGwgKiBtcC0+aGVp Z2h0Ow0KPiA+ICsNCj4gPiArCWRldl9kYmcoY2FtLT5kZXYsICJub2RlOiVkIHdpZHRoOiVkIGJ5 dGVzcGVybGluZTolZCBzaXplaW1hZ2U6JWRcbiIsDQo+ID4gKwkJbm9kZV9pZCwgd2lkdGgsIGJw bCwgbXAtPnBsYW5lX2ZtdFswXS5zaXplaW1hZ2UpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0 aWMgY29uc3Qgc3RydWN0IHY0bDJfZm9ybWF0ICoNCj4gPiArbXRrX2NhbV9kZXZfZmluZF9mbXQo c3RydWN0IG10a19jYW1fZGV2X25vZGVfZGVzYyAqZGVzYywgdTMyIGZvcm1hdCkNCj4gPiArew0K PiA+ICsJaW50IGk7DQo+ID4gKwljb25zdCBzdHJ1Y3QgdjRsMl9mb3JtYXQgKmRldl9mbXQ7DQo+ ID4gKw0KPiA+ICsJZm9yIChpID0gMDsgaSA8IGRlc2MtPm51bV9mbXRzOyBpKyspIHsNCj4gPiAr CQlkZXZfZm10ID0gJmRlc2MtPmZtdHNbaV07DQo+ID4gKwkJaWYgKGRldl9mbXQtPmZtdC5waXhf bXAucGl4ZWxmb3JtYXQgPT0gZm9ybWF0KQ0KPiA+ICsJCQlyZXR1cm4gZGV2X2ZtdDsNCj4gPiAr CX0NCj4gPiArDQo+ID4gKwlyZXR1cm4gTlVMTDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArLyogR2V0 IHRoZSBkZWZhdWx0IGZvcm1hdCBzZXR0aW5nICovDQo+ID4gK3N0YXRpYyB2b2lkDQo+ID4gK210 a19jYW1fZGV2X2xvYWRfZGVmYXVsdF9mbXQoc3RydWN0IG10a19jYW1fZGV2ICpjYW0sDQo+ID4g KwkJCSAgICAgc3RydWN0IG10a19jYW1fZGV2X25vZGVfZGVzYyAqcXVldWVfZGVzYywNCj4gPiAr CQkJICAgICBzdHJ1Y3QgdjRsMl9mb3JtYXQgKmRlc3QpDQo+ID4gK3sNCj4gPiArCWNvbnN0IHN0 cnVjdCB2NGwyX2Zvcm1hdCAqZGVmYXVsdF9mbXQgPQ0KPiA+ICsJCSZxdWV1ZV9kZXNjLT5mbXRz W3F1ZXVlX2Rlc2MtPmRlZmF1bHRfZm10X2lkeF07DQo+ID4gKw0KPiA+ICsJZGVzdC0+dHlwZSA9 IHF1ZXVlX2Rlc2MtPmJ1Zl90eXBlOw0KPiA+ICsNCj4gPiArCS8qIENvbmZpZ3VyZSBkZWZhdWx0 IGZvcm1hdCBiYXNlZCBvbiBub2RlIHR5cGUgKi8NCj4gPiArCWlmICghcXVldWVfZGVzYy0+aW1h Z2UpIHsNCj4gPiArCQlkZXN0LT5mbXQubWV0YS5kYXRhZm9ybWF0ID0gZGVmYXVsdF9mbXQtPmZt dC5tZXRhLmRhdGFmb3JtYXQ7DQo+ID4gKwkJZGVzdC0+Zm10Lm1ldGEuYnVmZmVyc2l6ZSA9IGRl ZmF1bHRfZm10LT5mbXQubWV0YS5idWZmZXJzaXplOw0KPiA+ICsJCXJldHVybjsNCj4gPiArCX0N Cj4gPiArDQo+ID4gKwlkZXN0LT5mbXQucGl4X21wLnBpeGVsZm9ybWF0ID0gZGVmYXVsdF9mbXQt PmZtdC5waXhfbXAucGl4ZWxmb3JtYXQ7DQo+ID4gKwlkZXN0LT5mbXQucGl4X21wLndpZHRoID0g ZGVmYXVsdF9mbXQtPmZtdC5waXhfbXAud2lkdGg7DQo+ID4gKwlkZXN0LT5mbXQucGl4X21wLmhl aWdodCA9IGRlZmF1bHRfZm10LT5mbXQucGl4X21wLmhlaWdodDsNCj4gPiArCS8qIGJ5dGVzcGVy bGluZSAmIHNpemVpbWFnZSBjYWxjdWxhdGlvbiAqLw0KPiA+ICsJY2FsX2ltYWdlX3BpeF9tcChj YW0sIHF1ZXVlX2Rlc2MtPmlkLCAmZGVzdC0+Zm10LnBpeF9tcCk7DQo+ID4gKwlkZXN0LT5mbXQu cGl4X21wLm51bV9wbGFuZXMgPSAxOw0KPiA+ICsNCj4gPiArCWRlc3QtPmZtdC5waXhfbXAuY29s b3JzcGFjZSA9IFY0TDJfQ09MT1JTUEFDRV9TUkdCOw0KPiA+ICsJZGVzdC0+Zm10LnBpeF9tcC5m aWVsZCA9IFY0TDJfRklFTERfTk9ORTsNCj4gPiArCWRlc3QtPmZtdC5waXhfbXAueWNiY3JfZW5j ID0gVjRMMl9ZQ0JDUl9FTkNfREVGQVVMVDsNCj4gPiArCWRlc3QtPmZtdC5waXhfbXAucXVhbnRp emF0aW9uID0gVjRMMl9RVUFOVElaQVRJT05fREVGQVVMVDsNCj4gPiArCWRlc3QtPmZtdC5waXhf bXAueGZlcl9mdW5jID0gVjRMMl9YRkVSX0ZVTkNfU1JHQjsNCj4gPiArfQ0KPiA+ICsNCj4gPiAr LyogVXRpbGl0eSBmdW5jdGlvbnMgKi8NCj4gPiArc3RhdGljIHVuc2lnbmVkIGludCBnZXRfc2Vu c29yX3BpeGVsX2lkKHVuc2lnbmVkIGludCBmbXQpDQo+ID4gK3sNCj4gPiArCXN3aXRjaCAoZm10 KSB7DQo+ID4gKwljYXNlIE1FRElBX0JVU19GTVRfU0JHR1I4XzFYODoNCj4gPiArCWNhc2UgTUVE SUFfQlVTX0ZNVF9TQkdHUjEwXzFYMTA6DQo+ID4gKwljYXNlIE1FRElBX0JVU19GTVRfU0JHR1Ix Ml8xWDEyOg0KPiA+ICsJY2FzZSBNRURJQV9CVVNfRk1UX1NCR0dSMTRfMVgxNDoNCj4gPiArCQly ZXR1cm4gTVRLX0NBTV9SQVdfUFhMX0lEX0I7DQo+ID4gKwljYXNlIE1FRElBX0JVU19GTVRfU0dC Ukc4XzFYODoNCj4gPiArCWNhc2UgTUVESUFfQlVTX0ZNVF9TR0JSRzEwXzFYMTA6DQo+ID4gKwlj YXNlIE1FRElBX0JVU19GTVRfU0dCUkcxMl8xWDEyOg0KPiA+ICsJY2FzZSBNRURJQV9CVVNfRk1U X1NHQlJHMTRfMVgxNDoNCj4gPiArCQlyZXR1cm4gTVRLX0NBTV9SQVdfUFhMX0lEX0dCOw0KPiA+ ICsJY2FzZSBNRURJQV9CVVNfRk1UX1NHUkJHOF8xWDg6DQo+ID4gKwljYXNlIE1FRElBX0JVU19G TVRfU0dSQkcxMF8xWDEwOg0KPiA+ICsJY2FzZSBNRURJQV9CVVNfRk1UX1NHUkJHMTJfMVgxMjoN Cj4gPiArCWNhc2UgTUVESUFfQlVTX0ZNVF9TR1JCRzE0XzFYMTQ6DQo+ID4gKwkJcmV0dXJuIE1U S19DQU1fUkFXX1BYTF9JRF9HUjsNCj4gPiArCWNhc2UgTUVESUFfQlVTX0ZNVF9TUkdHQjhfMVg4 Og0KPiA+ICsJY2FzZSBNRURJQV9CVVNfRk1UX1NSR0dCMTBfMVgxMDoNCj4gPiArCWNhc2UgTUVE SUFfQlVTX0ZNVF9TUkdHQjEyXzFYMTI6DQo+ID4gKwljYXNlIE1FRElBX0JVU19GTVRfU1JHR0Ix NF8xWDE0Og0KPiA+ICsJCXJldHVybiBNVEtfQ0FNX1JBV19QWExfSURfUjsNCj4gPiArCWRlZmF1 bHQ6DQo+ID4gKwkJcmV0dXJuIE1US19DQU1fUkFXX1BYTF9JRF9VTktOT1dOOw0KPiA+ICsJfQ0K PiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgdW5zaWduZWQgaW50IGdldF9zZW5zb3JfZm10KHVu c2lnbmVkIGludCBmbXQpDQo+ID4gK3sNCj4gPiArCXN3aXRjaCAoZm10KSB7DQo+ID4gKwljYXNl IE1FRElBX0JVU19GTVRfU0JHR1I4XzFYODoNCj4gPiArCWNhc2UgTUVESUFfQlVTX0ZNVF9TR0JS RzhfMVg4Og0KPiA+ICsJY2FzZSBNRURJQV9CVVNfRk1UX1NHUkJHOF8xWDg6DQo+ID4gKwljYXNl IE1FRElBX0JVU19GTVRfU1JHR0I4XzFYODoNCj4gPiArCQlyZXR1cm4gTVRLX0NBTV9JTUdfRk1U X0JBWUVSODsNCj4gPiArCWNhc2UgTUVESUFfQlVTX0ZNVF9TQkdHUjEwXzFYMTA6DQo+ID4gKwlj YXNlIE1FRElBX0JVU19GTVRfU0dCUkcxMF8xWDEwOg0KPiA+ICsJY2FzZSBNRURJQV9CVVNfRk1U X1NHUkJHMTBfMVgxMDoNCj4gPiArCWNhc2UgTUVESUFfQlVTX0ZNVF9TUkdHQjEwXzFYMTA6DQo+ ID4gKwkJcmV0dXJuIE1US19DQU1fSU1HX0ZNVF9CQVlFUjEwOw0KPiA+ICsJY2FzZSBNRURJQV9C VVNfRk1UX1NCR0dSMTJfMVgxMjoNCj4gPiArCWNhc2UgTUVESUFfQlVTX0ZNVF9TR0JSRzEyXzFY MTI6DQo+ID4gKwljYXNlIE1FRElBX0JVU19GTVRfU0dSQkcxMl8xWDEyOg0KPiA+ICsJY2FzZSBN RURJQV9CVVNfRk1UX1NSR0dCMTJfMVgxMjoNCj4gPiArCQlyZXR1cm4gTVRLX0NBTV9JTUdfRk1U X0JBWUVSMTI7DQo+ID4gKwljYXNlIE1FRElBX0JVU19GTVRfU0JHR1IxNF8xWDE0Og0KPiA+ICsJ Y2FzZSBNRURJQV9CVVNfRk1UX1NHQlJHMTRfMVgxNDoNCj4gPiArCWNhc2UgTUVESUFfQlVTX0ZN VF9TR1JCRzE0XzFYMTQ6DQo+ID4gKwljYXNlIE1FRElBX0JVU19GTVRfU1JHR0IxNF8xWDE0Og0K PiA+ICsJCXJldHVybiBNVEtfQ0FNX0lNR19GTVRfQkFZRVIxNDsNCj4gPiArCWRlZmF1bHQ6DQo+ ID4gKwkJcmV0dXJuIE1US19DQU1fSU1HX0ZNVF9VTktOT1dOOw0KPiA+ICsJfQ0KPiA+ICt9DQo+ ID4gKw0KPiA+ICtzdGF0aWMgdW5zaWduZWQgaW50IGdldF9pbWdfZm10KHVuc2lnbmVkIGludCBm b3VyY2MpDQo+ID4gK3sNCj4gPiArCXN3aXRjaCAoZm91cmNjKSB7DQo+ID4gKwljYXNlIFY0TDJf UElYX0ZNVF9NVElTUF9TQkdHUjg6DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TR0JS Rzg6DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TR1JCRzg6DQo+ID4gKwljYXNlIFY0 TDJfUElYX0ZNVF9NVElTUF9TUkdHQjg6DQo+ID4gKwkJcmV0dXJuIE1US19DQU1fSU1HX0ZNVF9C QVlFUjg7DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TQkdHUjhGOg0KPiA+ICsJY2Fz ZSBWNEwyX1BJWF9GTVRfTVRJU1BfU0dCUkc4RjoNCj4gPiArCWNhc2UgVjRMMl9QSVhfRk1UX01U SVNQX1NHUkJHOEY6DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TUkdHQjhGOg0KPiA+ ICsJCXJldHVybiBNVEtfQ0FNX0lNR19GTVRfRkdfQkFZRVI4Ow0KPiA+ICsJY2FzZSBWNEwyX1BJ WF9GTVRfTVRJU1BfU0JHR1IxMDoNCj4gPiArCWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NHQlJH MTA6DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TR1JCRzEwOg0KPiA+ICsJY2FzZSBW NEwyX1BJWF9GTVRfTVRJU1BfU1JHR0IxMDoNCj4gPiArCQlyZXR1cm4gTVRLX0NBTV9JTUdfRk1U X0JBWUVSMTA7DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TQkdHUjEwRjoNCj4gPiAr CWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NHQlJHMTBGOg0KPiA+ICsJY2FzZSBWNEwyX1BJWF9G TVRfTVRJU1BfU0dSQkcxMEY6DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TUkdHQjEw RjoNCj4gPiArCQlyZXR1cm4gTVRLX0NBTV9JTUdfRk1UX0ZHX0JBWUVSMTA7DQo+ID4gKwljYXNl IFY0TDJfUElYX0ZNVF9NVElTUF9TQkdHUjEyOg0KPiA+ICsJY2FzZSBWNEwyX1BJWF9GTVRfTVRJ U1BfU0dCUkcxMjoNCj4gPiArCWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NHUkJHMTI6DQo+ID4g KwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TUkdHQjEyOg0KPiA+ICsJCXJldHVybiBNVEtfQ0FN X0lNR19GTVRfQkFZRVIxMjsNCj4gPiArCWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NCR0dSMTJG Og0KPiA+ICsJY2FzZSBWNEwyX1BJWF9GTVRfTVRJU1BfU0dCUkcxMkY6DQo+ID4gKwljYXNlIFY0 TDJfUElYX0ZNVF9NVElTUF9TR1JCRzEyRjoNCj4gPiArCWNhc2UgVjRMMl9QSVhfRk1UX01USVNQ X1NSR0dCMTJGOg0KPiA+ICsJCXJldHVybiBNVEtfQ0FNX0lNR19GTVRfRkdfQkFZRVIxMjsNCj4g PiArCWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NCR0dSMTQ6DQo+ID4gKwljYXNlIFY0TDJfUElY X0ZNVF9NVElTUF9TR0JSRzE0Og0KPiA+ICsJY2FzZSBWNEwyX1BJWF9GTVRfTVRJU1BfU0dSQkcx NDoNCj4gPiArCWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NSR0dCMTQ6DQo+ID4gKwkJcmV0dXJu IE1US19DQU1fSU1HX0ZNVF9CQVlFUjE0Ow0KPiA+ICsJY2FzZSBWNEwyX1BJWF9GTVRfTVRJU1Bf U0JHR1IxNEY6DQo+ID4gKwljYXNlIFY0TDJfUElYX0ZNVF9NVElTUF9TR0JSRzE0RjoNCj4gPiAr CWNhc2UgVjRMMl9QSVhfRk1UX01USVNQX1NHUkJHMTRGOg0KPiA+ICsJY2FzZSBWNEwyX1BJWF9G TVRfTVRJU1BfU1JHR0IxNEY6DQo+ID4gKwkJcmV0dXJuIE1US19DQU1fSU1HX0ZNVF9GR19CQVlF UjE0Ow0KPiA+ICsJZGVmYXVsdDoNCj4gPiArCQlyZXR1cm4gTVRLX0NBTV9JTUdfRk1UX1VOS05P V047DQo+ID4gKwl9DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgY29uZmlnX2ltZ19m bXQoc3RydWN0IG10a19jYW1fZGV2ICpjYW0sIHVuc2lnbmVkIGludCBub2RlX2lkLA0KPiA+ICsJ CQkgIHN0cnVjdCBwMV9pbWdfb3V0cHV0ICpvdXRfZm10LCBpbnQgc2Rfd2lkdGgsDQo+ID4gKwkJ CSAgaW50IHNkX2hlaWdodCkNCj4gPiArew0KPiA+ICsJY29uc3Qgc3RydWN0IHY0bDJfZm9ybWF0 ICpjZmdfZm10ID0gJmNhbS0+dmRldl9ub2Rlc1tub2RlX2lkXS52ZGV2X2ZtdDsNCj4gPiArDQo+ ID4gKwkvKiBDaGVjayBvdXRwdXQgJiBpbnB1dCBpbWFnZSBzaXplIGRpbWVuc2lvbiAqLw0KPiA+ ICsJaWYgKGNmZ19mbXQtPmZtdC5waXhfbXAud2lkdGggPiBzZF93aWR0aCB8fA0KPiA+ICsJICAg IGNmZ19mbXQtPmZtdC5waXhfbXAuaGVpZ2h0ID4gc2RfaGVpZ2h0KSB7DQo+ID4gKwkJZGV2X2Vy cihjYW0tPmRldiwgIm5vZGU6JWQgY2ZnIHNpemUgaXMgbGFyZ2VyIHRoYW4gc2Vuc29yXG4iLA0K PiA+ICsJCQlub2RlX2lkKTsNCj4gPiArCQlyZXR1cm4gLUVJTlZBTDsNCj4gPiArCX0NCj4gPiAr DQo+ID4gKwkvKiBDaGVjayByZXNpemUgcmF0aW8gZm9yIHJlc2l6ZSBvdXQgc3RyZWFtIGR1ZSB0 byBIVyBjb25zdHJhaW50ICovDQo+ID4gKwlpZiAoKChjZmdfZm10LT5mbXQucGl4X21wLndpZHRo ICogMTAwIC8gc2Rfd2lkdGgpIDwNCj4gPiArCSAgICBNVEtfSVNQX01JTl9SRVNJWkVfUkFUSU8p IHx8DQo+ID4gKwkgICAgKChjZmdfZm10LT5mbXQucGl4X21wLmhlaWdodCAqIDEwMCAvIHNkX2hl aWdodCkgPA0KPiA+ICsJICAgIE1US19JU1BfTUlOX1JFU0laRV9SQVRJTykpIHsNCj4gPiArCQlk ZXZfZXJyKGNhbS0+ZGV2LCAibm9kZTolZCByZXNpemUgcmF0aW8gaXMgbGVzcyB0aGFuICVkJSVc biIsDQo+ID4gKwkJCW5vZGVfaWQsIE1US19JU1BfTUlOX1JFU0laRV9SQVRJTyk7DQo+ID4gKwkJ cmV0dXJuIC1FSU5WQUw7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJb3V0X2ZtdC0+aW1nX2ZtdCA9 IGdldF9pbWdfZm10KGNmZ19mbXQtPmZtdC5waXhfbXAucGl4ZWxmb3JtYXQpOw0KPiA+ICsJb3V0 X2ZtdC0+cGl4ZWxfYml0cyA9IGdldF9waXhlbF9iaXRzKGNmZ19mbXQtPmZtdC5waXhfbXAucGl4 ZWxmb3JtYXQpOw0KPiA+ICsJaWYgKG91dF9mbXQtPmltZ19mbXQgPT0gTVRLX0NBTV9JTUdfRk1U X1VOS05PV04gfHwNCj4gPiArCSAgICAhb3V0X2ZtdC0+cGl4ZWxfYml0cykgew0KPiA+ICsJCWRl dl9lcnIoY2FtLT5kZXYsICJub2RlOiVkIHVua25vd24gcGl4ZWwgZm10OiVkXG4iLA0KPiA+ICsJ CQlub2RlX2lkLCBjZmdfZm10LT5mbXQucGl4X21wLnBpeGVsZm9ybWF0KTsNCj4gPiArCQlyZXR1 cm4gLUVJTlZBTDsNCj4gPiArCX0NCj4gPiArCWRldl9kYmcoY2FtLT5kZXYsICJub2RlOiVkIHBp eGVsX2JpdHM6JWQgaW1nX2ZtdDoweCV4XG4iLA0KPiA+ICsJCW5vZGVfaWQsIG91dF9mbXQtPnBp eGVsX2JpdHMsIG91dF9mbXQtPmltZ19mbXQpOw0KPiA+ICsNCj4gPiArCW91dF9mbXQtPnNpemUu dyA9IGNmZ19mbXQtPmZtdC5waXhfbXAud2lkdGg7DQo+ID4gKwlvdXRfZm10LT5zaXplLmggPSBj ZmdfZm10LT5mbXQucGl4X21wLmhlaWdodDsNCj4gPiArCW91dF9mbXQtPnNpemUuc3RyaWRlID0g Y2ZnX2ZtdC0+Zm10LnBpeF9tcC5wbGFuZV9mbXRbMF0uYnl0ZXNwZXJsaW5lOw0KPiA+ICsJb3V0 X2ZtdC0+c2l6ZS54c2l6ZSA9IGNmZ19mbXQtPmZtdC5waXhfbXAucGxhbmVfZm10WzBdLmJ5dGVz cGVybGluZTsNCj4gPiArDQo+ID4gKwlvdXRfZm10LT5jcm9wLmxlZnQgPSAwOw0KPiA+ICsJb3V0 X2ZtdC0+Y3JvcC50b3AgPSAwOw0KPiA+ICsJb3V0X2ZtdC0+Y3JvcC53aWR0aCA9IHNkX3dpZHRo Ow0KPiA+ICsJb3V0X2ZtdC0+Y3JvcC5oZWlnaHQgPSBzZF9oZWlnaHQ7DQo+ID4gKw0KPiA+ICsJ ZGV2X2RiZyhjYW0tPmRldiwNCj4gPiArCQkibm9kZTolZCBzaXplPSUwZHglMGQsIHN0cmlkZTol ZCwgeHNpemU6JWQsIGNyb3A9JTBkeCUwZFxuIiwNCj4gPiArCQlub2RlX2lkLCBvdXRfZm10LT5z aXplLncsIG91dF9mbXQtPnNpemUuaCwNCj4gPiArCQlvdXRfZm10LT5zaXplLnN0cmlkZSwgb3V0 X2ZtdC0+c2l6ZS54c2l6ZSwNCj4gPiArCQlvdXRfZm10LT5jcm9wLndpZHRoLCBvdXRfZm10LT5j cm9wLmhlaWdodCk7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4g K3N0YXRpYyB2b2lkIG10a19jYW1fZGV2X2luaXRfc3RyZWFtKHN0cnVjdCBtdGtfY2FtX2RldiAq Y2FtKQ0KPiA+ICt7DQo+ID4gKwlpbnQgaTsNCj4gPiArDQo+ID4gKwljYW0tPmVuYWJsZWRfY291 bnQgPSAwOw0KPiA+ICsJY2FtLT5lbmFibGVkX2RtYXMgPSAwOw0KPiA+ICsJY2FtLT5zdHJlYW1f Y291bnQgPSAwOw0KPiA+ICsJY2FtLT5ydW5uaW5nX2pvYl9jb3VudCA9IDA7DQo+ID4gKw0KPiA+ ICsJLyogR2V0IHRoZSBlbmFibGVkIG1ldGEgRE1BIHBvcnRzICovDQo+ID4gKwlmb3IgKGkgPSAw OyBpIDwgTVRLX0NBTV9QMV9UT1RBTF9OT0RFUzsgaSsrKSB7DQo+ID4gKwkJaWYgKCFjYW0tPnZk ZXZfbm9kZXNbaV0uZW5hYmxlZCkNCj4gPiArCQkJY29udGludWU7DQo+ID4gKwkJY2FtLT5lbmFi bGVkX2NvdW50Kys7DQo+ID4gKwkJY2FtLT5lbmFibGVkX2RtYXMgfD0gY2FtLT52ZGV2X25vZGVz W2ldLmRlc2MuZG1hX3BvcnQ7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJZGV2X2RiZyhjYW0tPmRl diwgIiVzOiVkOjB4JXhcbiIsIF9fZnVuY19fLCBjYW0tPmVuYWJsZWRfY291bnQsDQo+ID4gKwkJ Y2FtLT5lbmFibGVkX2RtYXMpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IG10a19j YW1fZGV2X2lzcF9jb25maWcoc3RydWN0IG10a19jYW1fZGV2ICpjYW0pDQo+ID4gK3sNCj4gPiAr CXN0cnVjdCBkZXZpY2UgKmRldiA9IGNhbS0+ZGV2Ow0KPiA+ICsJc3RydWN0IHAxX2NvbmZpZ19w YXJhbSBjb25maWdfcGFyYW07DQo+ID4gKwlzdHJ1Y3QgY2ZnX2luX3BhcmFtICpjZmdfaW5fcGFy YW07DQo+ID4gKwlzdHJ1Y3QgdjRsMl9zdWJkZXZfZm9ybWF0IHNkX2ZtdDsNCj4gPiArCWludCBz ZF93aWR0aCwgc2RfaGVpZ2h0LCBzZF9jb2RlOw0KPiA+ICsJdW5zaWduZWQgaW50IGVuYWJsZWRf ZG1hX3BvcnRzID0gY2FtLT5lbmFibGVkX2RtYXM7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsNCj4g PiArCS8qIEdldCBzZW5zb3IgZm9ybWF0IGNvbmZpZ3VyYXRpb24gKi8NCj4gPiArCXNkX2ZtdC53 aGljaCA9IFY0TDJfU1VCREVWX0ZPUk1BVF9BQ1RJVkU7DQo+ID4gKwlyZXQgPSB2NGwyX3N1YmRl dl9jYWxsKGNhbS0+c2Vuc29yLCBwYWQsIGdldF9mbXQsIE5VTEwsICZzZF9mbXQpOw0KPiA+ICsJ aWYgKHJldCkgew0KPiA+ICsJCWRldl9kYmcoZGV2LCAic2Vuc29yIGdfZm10IGZhaWxlZDolZFxu IiwgcmV0KTsNCj4gPiArCQlyZXR1cm4gcmV0Ow0KPiA+ICsJfQ0KPiA+ICsJc2Rfd2lkdGggPSBz ZF9mbXQuZm9ybWF0LndpZHRoOw0KPiA+ICsJc2RfaGVpZ2h0ID0gc2RfZm10LmZvcm1hdC5oZWln aHQ7DQo+ID4gKwlzZF9jb2RlID0gc2RfZm10LmZvcm1hdC5jb2RlOw0KPiA+ICsJZGV2X2RiZyhk ZXYsICJzZCBmbXQgdypoPSVkKiVkLCBjb2RlPTB4JXhcbiIsIHNkX3dpZHRoLCBzZF9oZWlnaHQs DQo+ID4gKwkJc2RfY29kZSk7DQo+ID4gKw0KPiA+ICsJbWVtc2V0KCZjb25maWdfcGFyYW0sIDAs IHNpemVvZihjb25maWdfcGFyYW0pKTsNCj4gPiArDQo+ID4gKwkvKiBVcGRhdGUgY2ZnX2luX3Bh cmFtICovDQo+ID4gKwljZmdfaW5fcGFyYW0gPSAmY29uZmlnX3BhcmFtLmNmZ19pbl9wYXJhbTsN Cj4gPiArCWNmZ19pbl9wYXJhbS0+Y29udGludW91cyA9IHRydWU7DQo+ID4gKwkvKiBGaXggdG8g b25lIHBpeGVsIG1vZGUgaW4gZGVmYXVsdCAqLw0KPiA+ICsJY2ZnX2luX3BhcmFtLT5waXhlbF9t b2RlID0gTVRLX0lTUF9PTkVfUElYRUxfTU9ERTsNCj4gPiArCWNmZ19pbl9wYXJhbS0+Y3JvcC53 aWR0aCA9IHNkX3dpZHRoOw0KPiA+ICsJY2ZnX2luX3BhcmFtLT5jcm9wLmhlaWdodCA9IHNkX2hl aWdodDsNCj4gPiArCWNmZ19pbl9wYXJhbS0+cmF3X3BpeGVsX2lkID0gZ2V0X3NlbnNvcl9waXhl bF9pZChzZF9jb2RlKTsNCj4gPiArCWNmZ19pbl9wYXJhbS0+aW1nX2ZtdCA9IGdldF9zZW5zb3Jf Zm10KHNkX2NvZGUpOw0KPiA+ICsJaWYgKGNmZ19pbl9wYXJhbS0+aW1nX2ZtdCA9PSBNVEtfQ0FN X0lNR19GTVRfVU5LTk9XTiB8fA0KPiA+ICsJICAgIGNmZ19pbl9wYXJhbS0+cmF3X3BpeGVsX2lk ID09IE1US19DQU1fUkFXX1BYTF9JRF9VTktOT1dOKSB7DQo+ID4gKwkJZGV2X2VycihkZXYsICJ1 bmtub3duIHNkIGNvZGU6JWRcbiIsIHNkX2NvZGUpOw0KPiA+ICsJCXJldHVybiAtRUlOVkFMOw0K PiA+ICsJfQ0KPiA+ICsNCj4gPiArCS8qIFVwZGF0ZSBjZmdfbWFpbl9wYXJhbSAqLw0KPiA+ICsJ Y29uZmlnX3BhcmFtLmNmZ19tYWluX3BhcmFtLnB1cmVfcmF3ID0gdHJ1ZTsNCj4gPiArCWNvbmZp Z19wYXJhbS5jZmdfbWFpbl9wYXJhbS5wdXJlX3Jhd19wYWNrID0gdHJ1ZTsNCj4gPiArCXJldCA9 IGNvbmZpZ19pbWdfZm10KGNhbSwgTVRLX0NBTV9QMV9NQUlOX1NUUkVBTV9PVVQsDQo+ID4gKwkJ CSAgICAgJmNvbmZpZ19wYXJhbS5jZmdfbWFpbl9wYXJhbS5vdXRwdXQsDQo+ID4gKwkJCSAgICAg c2Rfd2lkdGgsIHNkX2hlaWdodCk7DQo+ID4gKwlpZiAocmV0KQ0KPiA+ICsJCXJldHVybiByZXQ7 DQo+ID4gKw0KPiA+ICsJLyogVXBkYXRlIGNmZ19yZXNpemVfcGFyYW0gKi8NCj4gPiArCWlmIChl bmFibGVkX2RtYV9wb3J0cyAmIFJfUlJaTykgew0KPiA+ICsJCXJldCA9IGNvbmZpZ19pbWdfZm10 KGNhbSwgTVRLX0NBTV9QMV9QQUNLRURfQklOX09VVCwNCj4gPiArCQkJCSAgICAgJmNvbmZpZ19w YXJhbS5jZmdfcmVzaXplX3BhcmFtLm91dHB1dCwNCj4gPiArCQkJCSAgICAgc2Rfd2lkdGgsIHNk X2hlaWdodCk7DQo+ID4gKwkJaWYgKHJldCkNCj4gPiArCQkJcmV0dXJuIHJldDsNCj4gPiArCX0g ZWxzZSB7DQo+ID4gKwkJY29uZmlnX3BhcmFtLmNmZ19yZXNpemVfcGFyYW0uYnlwYXNzID0gdHJ1 ZTsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwkvKiBVcGRhdGUgZW5hYmxlZF9kbWFzICovDQo+ID4g Kwljb25maWdfcGFyYW0uZW5hYmxlZF9kbWFzID0gZW5hYmxlZF9kbWFfcG9ydHM7DQo+ID4gKwlt dGtfaXNwX2h3X2NvbmZpZyhjYW0sICZjb25maWdfcGFyYW0pOw0KPiA+ICsJZGV2X2RiZyhkZXYs ICIlcyBkb25lXG4iLCBfX2Z1bmNfXyk7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30N Cj4gPiArDQo+ID4gK3ZvaWQgbXRrX2NhbV9kZXZfZXZlbnRfZnJhbWVfc3luYyhzdHJ1Y3QgbXRr X2NhbV9kZXYgKmNhbSwNCj4gPiArCQkJCSAgdW5zaWduZWQgaW50IGZyYW1lX3NlcV9ubykNCj4g PiArew0KPiA+ICsJc3RydWN0IHY0bDJfZXZlbnQgZXZlbnQgPSB7DQo+ID4gKwkJLnR5cGUgPSBW NEwyX0VWRU5UX0ZSQU1FX1NZTkMsDQo+ID4gKwkJLnUuZnJhbWVfc3luYy5mcmFtZV9zZXF1ZW5j ZSA9IGZyYW1lX3NlcV9ubywNCj4gPiArCX07DQo+ID4gKw0KPiA+ICsJdjRsMl9ldmVudF9xdWV1 ZShjYW0tPnN1YmRldi5kZXZub2RlLCAmZXZlbnQpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0 aWMgc3RydWN0IHY0bDJfc3ViZGV2ICoNCj4gPiArbXRrX2NhbV9jaW9fZ2V0X2FjdGl2ZV9zZW5z b3Ioc3RydWN0IG10a19jYW1fZGV2ICpjYW0pDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtZWRpYV9k ZXZpY2UgKm1kZXYgPSBjYW0tPnNlbmluZi0+ZW50aXR5LmdyYXBoX29iai5tZGV2Ow0KPiA+ICsJ c3RydWN0IGRldmljZSAqZGV2ID0gY2FtLT5kZXY7DQo+ID4gKwlzdHJ1Y3QgbWVkaWFfZW50aXR5 ICplbnRpdHk7DQo+ID4gKwlzdHJ1Y3QgdjRsMl9zdWJkZXYgKnNlbnNvcjsNCj4gPiArDQo+ID4g KwlzZW5zb3IgPSBOVUxMOw0KPiA+ICsJbWVkaWFfZGV2aWNlX2Zvcl9lYWNoX2VudGl0eShlbnRp dHksIG1kZXYpIHsNCj4gPiArCQlkZXZfZGJnKGRldiwgIm1lZGlhIGVudGl0eTogJXM6MHgleDol ZFxuIiwNCj4gPiArCQkJZW50aXR5LT5uYW1lLCBlbnRpdHktPmZ1bmN0aW9uLCBlbnRpdHktPnN0 cmVhbV9jb3VudCk7DQo+ID4gKwkJaWYgKGVudGl0eS0+ZnVuY3Rpb24gPT0gTUVESUFfRU5UX0Zf Q0FNX1NFTlNPUiAmJg0KPiA+ICsJCSAgICBlbnRpdHktPnN0cmVhbV9jb3VudCkgew0KPiA+ICsJ CQlzZW5zb3IgPSBtZWRpYV9lbnRpdHlfdG9fdjRsMl9zdWJkZXYoZW50aXR5KTsNCj4gPiArCQkJ ZGV2X2RiZyhkZXYsICJzZW5zb3IgZm91bmQ6ICVzXG4iLCBlbnRpdHktPm5hbWUpOw0KPiA+ICsJ CQlicmVhazsNCj4gPiArCQl9DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJaWYgKCFzZW5zb3IpDQo+ ID4gKwkJZGV2X2VycihkZXYsICJubyBzZW5pbmYgY29ubmVjdGVkXG4iKTsNCj4gPiArDQo+ID4g KwlyZXR1cm4gc2Vuc29yOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IG10a19jYW1f Y2lvX3N0cmVhbV9vbihzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSkNCj4gPiArew0KPiA+ICsJc3Ry dWN0IGRldmljZSAqZGV2ID0gY2FtLT5kZXY7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiAr CWlmICghY2FtLT5zZW5pbmYpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgIm5vIHNlbmluZiBjb25u ZWN0ZWRcbiIpOw0KPiA+ICsJCXJldHVybiAtRU5PREVWOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiAr CS8qIEdldCBhY3RpdmUgc2Vuc29yIGZyb20gZ3JhcGggdG9wb2xvZ3kgKi8NCj4gPiArCWNhbS0+ c2Vuc29yID0gbXRrX2NhbV9jaW9fZ2V0X2FjdGl2ZV9zZW5zb3IoY2FtKTsNCj4gPiArCWlmICgh Y2FtLT5zZW5zb3IpDQo+ID4gKwkJcmV0dXJuIC1FTk9ERVY7DQo+ID4gKw0KPiA+ICsJLyogU2Vu aW5mIG11c3Qgc3RyZWFtIG9uIGZpcnN0ICovDQo+ID4gKwlyZXQgPSB2NGwyX3N1YmRldl9jYWxs KGNhbS0+c2VuaW5mLCB2aWRlbywgc19zdHJlYW0sIDEpOw0KPiA+ICsJaWYgKHJldCkgew0KPiA+ ICsJCWRldl9lcnIoZGV2LCAiZmFpbGVkIHRvIHN0cmVhbSBvbiAlczolZFxuIiwNCj4gPiArCQkJ Y2FtLT5zZW5pbmYtPmVudGl0eS5uYW1lLCByZXQpOw0KPiA+ICsJCXJldHVybiByZXQ7DQo+ID4g Kwl9DQo+ID4gKw0KPiA+ICsJcmV0ID0gdjRsMl9zdWJkZXZfY2FsbChjYW0tPnNlbnNvciwgdmlk ZW8sIHNfc3RyZWFtLCAxKTsNCj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwg ImZhaWxlZCB0byBzdHJlYW0gb24gJXM6JWRcbiIsDQo+ID4gKwkJCWNhbS0+c2Vuc29yLT5lbnRp dHkubmFtZSwgcmV0KTsNCj4gPiArCQlnb3RvIGZhaWxfc2VuaW5mX29mZjsNCj4gPiArCX0NCj4g PiArDQo+ID4gKwlyZXQgPSBtdGtfY2FtX2Rldl9pc3BfY29uZmlnKGNhbSk7DQo+ID4gKwlpZiAo cmV0KQ0KPiA+ICsJCWdvdG8gZmFpbF9zZW5zb3Jfb2ZmOw0KPiA+ICsNCj4gPiArCWNhbS0+c3Ry ZWFtaW5nID0gdHJ1ZTsNCj4gPiArCW10a19pc3Bfc3RyZWFtKGNhbSwgMSk7DQo+ID4gKwltdGtf Y2FtX2Rldl9yZXFfdHJ5X3F1ZXVlKGNhbSk7DQo+ID4gKwlkZXZfZGJnKGRldiwgInN0cmVhbWVk IG9uIFBhc3MgMVxuIik7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gKw0KPiA+ICtmYWls X3NlbnNvcl9vZmY6DQo+ID4gKwl2NGwyX3N1YmRldl9jYWxsKGNhbS0+c2Vuc29yLCB2aWRlbywg c19zdHJlYW0sIDApOw0KPiA+ICtmYWlsX3NlbmluZl9vZmY6DQo+ID4gKwl2NGwyX3N1YmRldl9j YWxsKGNhbS0+c2VuaW5mLCB2aWRlbywgc19zdHJlYW0sIDApOw0KPiA+ICsNCj4gPiArCXJldHVy biByZXQ7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgbXRrX2NhbV9jaW9fc3RyZWFt X29mZihzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSkNCj4gPiArew0KPiA+ICsJc3RydWN0IGRldmlj ZSAqZGV2ID0gY2FtLT5kZXY7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCXJldCA9IHY0 bDJfc3ViZGV2X2NhbGwoY2FtLT5zZW5zb3IsIHZpZGVvLCBzX3N0cmVhbSwgMCk7DQo+ID4gKwlp ZiAocmV0KSB7DQo+ID4gKwkJZGV2X2VycihkZXYsICJmYWlsZWQgdG8gc3RyZWFtIG9mZiAlczol ZFxuIiwNCj4gPiArCQkJY2FtLT5zZW5zb3ItPmVudGl0eS5uYW1lLCByZXQpOw0KPiA+ICsJCXJl dHVybiAtRVBFUk07DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0ID0gdjRsMl9zdWJkZXZfY2Fs bChjYW0tPnNlbmluZiwgdmlkZW8sIHNfc3RyZWFtLCAwKTsNCj4gPiArCWlmIChyZXQpIHsNCj4g PiArCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0byBzdHJlYW0gb2ZmICVzOiVkXG4iLA0KPiA+ICsJ CQljYW0tPnNlbmluZi0+ZW50aXR5Lm5hbWUsIHJldCk7DQo+ID4gKwkJcmV0dXJuIC1FUEVSTTsN Cj4gPiArCX0NCj4gPiArDQo+ID4gKwljYW0tPnN0cmVhbWluZyA9IGZhbHNlOw0KPiA+ICsJbXRr X2lzcF9zdHJlYW0oY2FtLCAwKTsNCj4gPiArCW10a19pc3BfaHdfcmVsZWFzZShjYW0pOw0KPiA+ ICsNCj4gPiArCWRldl9kYmcoZGV2LCAic3RyZWFtZWQgb2ZmIFBhc3MgMVxuIik7DQo+ID4gKw0K PiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgbXRrX2NhbV9z ZF9zX3N0cmVhbShzdHJ1Y3QgdjRsMl9zdWJkZXYgKnNkLCBpbnQgZW5hYmxlKQ0KPiA+ICt7DQo+ ID4gKwlzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSA9IGNvbnRhaW5lcl9vZihzZCwgc3RydWN0IG10 a19jYW1fZGV2LCBzdWJkZXYpOw0KPiA+ICsNCj4gPiArCWlmIChlbmFibGUpIHsNCj4gPiArCQkv KiBBbGlnbiB2YjJfY29yZV9zdHJlYW1vbiBkZXNpZ24gKi8NCj4gPiArCQlpZiAoY2FtLT5zdHJl YW1pbmcpIHsNCj4gPiArCQkJZGV2X3dhcm4oY2FtLT5kZXYsICJhbHJlYWR5IHN0cmVhbWluZyBv blxuIik7DQo+ID4gKwkJCXJldHVybiAwOw0KPiA+ICsJCX0NCj4gPiArCQlyZXR1cm4gbXRrX2Nh bV9jaW9fc3RyZWFtX29uKGNhbSk7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJaWYgKCFjYW0tPnN0 cmVhbWluZykgew0KPiA+ICsJCWRldl93YXJuKGNhbS0+ZGV2LCAiYWxyZWFkeSBzdHJlYW1pbmcg b2ZmXG4iKTsNCj4gPiArCQlyZXR1cm4gMDsNCj4gPiArCX0NCj4gPiArCXJldHVybiBtdGtfY2Ft X2Npb19zdHJlYW1fb2ZmKGNhbSk7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgbXRr X2NhbV9zZF9zdWJzY3JpYmVfZXZlbnQoc3RydWN0IHY0bDJfc3ViZGV2ICpzdWJkZXYsDQo+ID4g KwkJCQkgICAgICBzdHJ1Y3QgdjRsMl9maCAqZmgsDQo+ID4gKwkJCQkgICAgICBzdHJ1Y3QgdjRs Ml9ldmVudF9zdWJzY3JpcHRpb24gKnN1YikNCj4gPiArew0KPiA+ICsJc3dpdGNoIChzdWItPnR5 cGUpIHsNCj4gPiArCWNhc2UgVjRMMl9FVkVOVF9GUkFNRV9TWU5DOg0KPiA+ICsJCXJldHVybiB2 NGwyX2V2ZW50X3N1YnNjcmliZShmaCwgc3ViLCAwLCBOVUxMKTsNCj4gPiArCWRlZmF1bHQ6DQo+ ID4gKwkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gKwl9DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRp YyBpbnQgbXRrX2NhbV9tZWRpYV9saW5rX3NldHVwKHN0cnVjdCBtZWRpYV9lbnRpdHkgKmVudGl0 eSwNCj4gPiArCQkJCSAgICBjb25zdCBzdHJ1Y3QgbWVkaWFfcGFkICpsb2NhbCwNCj4gPiArCQkJ CSAgICBjb25zdCBzdHJ1Y3QgbWVkaWFfcGFkICpyZW1vdGUsIHUzMiBmbGFncykNCj4gPiArew0K PiA+ICsJc3RydWN0IG10a19jYW1fZGV2ICpjYW0gPQ0KPiA+ICsJCWNvbnRhaW5lcl9vZihlbnRp dHksIHN0cnVjdCBtdGtfY2FtX2Rldiwgc3ViZGV2LmVudGl0eSk7DQo+ID4gKwl1MzIgcGFkID0g bG9jYWwtPmluZGV4Ow0KPiA+ICsNCj4gPiArCWRldl9kYmcoY2FtLT5kZXYsICIlczogJWQtPiVk IGZsYWdzOjB4JXhcbiIsDQo+ID4gKwkJX19mdW5jX18sIHBhZCwgcmVtb3RlLT5pbmRleCwgZmxh Z3MpOw0KPiA+ICsNCj4gPiArCS8qDQo+ID4gKwkgKiBUaGUgdmlkZW8gbm9kZXMgZXhwb3NlZCBi eSB0aGUgZHJpdmVyIGhhdmUgcGFkcyBpbmRleGVzDQo+ID4gKwkgKiBmcm9tIDAgdG8gTVRLX0NB TV9QMV9UT1RBTF9OT0RFUyAtIDEuDQo+ID4gKwkgKi8NCj4gPiArCWlmIChwYWQgPCBNVEtfQ0FN X1AxX1RPVEFMX05PREVTKQ0KPiA+ICsJCWNhbS0+dmRldl9ub2Rlc1twYWRdLmVuYWJsZWQgPQ0K PiA+ICsJCQkhIShmbGFncyAmIE1FRElBX0xOS19GTF9FTkFCTEVEKTsNCj4gPiArDQo+ID4gKwly ZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIHZvaWQgbXRrX2NhbV92YjJfYnVm X3F1ZXVlKHN0cnVjdCB2YjJfYnVmZmVyICp2YikNCj4gPiArew0KPiA+ICsJc3RydWN0IG10a19j YW1fZGV2ICpjYW0gPSB2YjJfZ2V0X2Rydl9wcml2KHZiLT52YjJfcXVldWUpOw0KPiA+ICsJc3Ry dWN0IG10a19jYW1fZGV2X2J1ZmZlciAqYnVmID0gbXRrX2NhbV92YjJfYnVmX3RvX2Rldl9idWYo dmIpOw0KPiA+ICsJc3RydWN0IG10a19jYW1fZGV2X3JlcXVlc3QgKnJlcSA9IG10a19jYW1fcmVx X3RvX2Rldl9yZXEodmItPnJlcXVlc3QpOw0KPiA+ICsJc3RydWN0IG10a19jYW1fdmlkZW9fZGV2 aWNlICpub2RlID0gbXRrX2NhbV92YnFfdG9fdmRldih2Yi0+dmIyX3F1ZXVlKTsNCj4gPiArCXN0 cnVjdCBkZXZpY2UgKmRldiA9IGNhbS0+ZGV2Ow0KPiA+ICsJdW5zaWduZWQgbG9uZyBmbGFnczsN Cj4gPiArDQo+ID4gKwlkZXZfZGJnKGRldiwgIiVzOiBub2RlOiVkIGZkOiVkIGlkeDolZFxuIiwg X19mdW5jX18sDQo+ID4gKwkJbm9kZS0+aWQsIGJ1Zi0+dmJiLnJlcXVlc3RfZmQsIGJ1Zi0+dmJi LnZiMl9idWYuaW5kZXgpOw0KPiA+ICsNCj4gPiArCS8qIGFkZGVkIHRoZSBidWZmZXIgaW50byB0 aGUgdHJhY2tpbmcgbGlzdCAqLw0KPiA+ICsJc3Bpbl9sb2NrX2lycXNhdmUoJm5vZGUtPmJ1Zl9s aXN0X2xvY2ssIGZsYWdzKTsNCj4gPiArCWxpc3RfYWRkX3RhaWwoJmJ1Zi0+bGlzdCwgJm5vZGUt PmJ1Zl9saXN0KTsNCj4gPiArCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJm5vZGUtPmJ1Zl9saXN0 X2xvY2ssIGZsYWdzKTsNCj4gPiArDQo+ID4gKwkvKiB1cGRhdGUgYnVmZmVyIGludGVybmFsIGFk ZHJlc3MgKi8NCj4gPiArCXJlcS0+ZnJhbWVfcGFyYW1zLmRtYV9idWZzW2J1Zi0+bm9kZV9pZF0u aW92YSA9IGJ1Zi0+ZGFkZHI7DQo+ID4gKwlyZXEtPmZyYW1lX3BhcmFtcy5kbWFfYnVmc1tidWYt Pm5vZGVfaWRdLnNjcF9hZGRyID0gYnVmLT5zY3BfYWRkcjsNCj4gPiArfQ0KPiA+ICsNCj4gPiAr c3RhdGljIGludCBtdGtfY2FtX3ZiMl9idWZfaW5pdChzdHJ1Y3QgdmIyX2J1ZmZlciAqdmIpDQo+ ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtfY2FtX3ZpZGVvX2RldmljZSAqbm9kZSA9IG10a19jYW1f dmJxX3RvX3ZkZXYodmItPnZiMl9xdWV1ZSk7DQo+ID4gKwlzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNh bSA9IHZiMl9nZXRfZHJ2X3ByaXYodmItPnZiMl9xdWV1ZSk7DQo+ID4gKwlzdHJ1Y3QgZGV2aWNl ICpkZXYgPSBjYW0tPmRldjsNCj4gPiArCXN0cnVjdCBtdGtfY2FtX2Rldl9idWZmZXIgKmJ1ZjsN Cj4gPiArCWRtYV9hZGRyX3QgYWRkcjsNCj4gPiArDQo+ID4gKwlidWYgPSBtdGtfY2FtX3ZiMl9i dWZfdG9fZGV2X2J1Zih2Yik7DQo+ID4gKwlidWYtPm5vZGVfaWQgPSBub2RlLT5pZDsNCj4gPiAr CWJ1Zi0+ZGFkZHIgPSB2YjJfZG1hX2NvbnRpZ19wbGFuZV9kbWFfYWRkcih2YiwgMCk7DQo+ID4g KwlidWYtPnNjcF9hZGRyID0gMDsNCj4gPiArDQo+ID4gKwkvKiBTQ1AgYWRkcmVzcyBpcyBvbmx5 IHZhbGlkIGZvciBtZXRhIGlucHV0IGJ1ZmZlciAqLw0KPiA+ICsJaWYgKCFub2RlLT5kZXNjLnNt ZW1fYWxsb2MpDQo+ID4gKwkJcmV0dXJuIDA7DQo+ID4gKw0KPiA+ICsJYnVmID0gbXRrX2NhbV92 YjJfYnVmX3RvX2Rldl9idWYodmIpOw0KPiA+ICsJLyogVXNlIGNvaGVyZW50IGFkZHJlc3MgdG8g Z2V0IGlvdmEgYWRkcmVzcyAqLw0KPiA+ICsJYWRkciA9IGRtYV9tYXBfcmVzb3VyY2UoZGV2LCBi dWYtPmRhZGRyLCB2Yi0+cGxhbmVzWzBdLmxlbmd0aCwNCj4gPiArCQkJCURNQV9CSURJUkVDVElP TkFMLCBETUFfQVRUUl9TS0lQX0NQVV9TWU5DKTsNCj4gPiArCWlmIChkbWFfbWFwcGluZ19lcnJv cihkZXYsIGFkZHIpKSB7DQo+ID4gKwkJZGV2X2VycihkZXYsICJmYWlsZWQgdG8gbWFwIG1ldGEg YWRkcjolcGFkXG4iLCAmYnVmLT5kYWRkcik7DQo+ID4gKwkJcmV0dXJuIC1FRkFVTFQ7DQo+ID4g Kwl9DQo+ID4gKwlidWYtPnNjcF9hZGRyID0gYnVmLT5kYWRkcjsNCj4gPiArCWJ1Zi0+ZGFkZHIg PSBhZGRyOw0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0 aWMgaW50IG10a19jYW1fdmIyX2J1Zl9wcmVwYXJlKHN0cnVjdCB2YjJfYnVmZmVyICp2YikNCj4g PiArew0KPiA+ICsJc3RydWN0IG10a19jYW1fdmlkZW9fZGV2aWNlICpub2RlID0gbXRrX2NhbV92 YnFfdG9fdmRldih2Yi0+dmIyX3F1ZXVlKTsNCj4gPiArCXN0cnVjdCBtdGtfY2FtX2RldiAqY2Ft ID0gdmIyX2dldF9kcnZfcHJpdih2Yi0+dmIyX3F1ZXVlKTsNCj4gPiArCXN0cnVjdCB2YjJfdjRs Ml9idWZmZXIgKnY0bDJfYnVmID0gdG9fdmIyX3Y0bDJfYnVmZmVyKHZiKTsNCj4gPiArCWNvbnN0 IHN0cnVjdCB2NGwyX2Zvcm1hdCAqZm10ID0gJm5vZGUtPnZkZXZfZm10Ow0KPiA+ICsJdW5zaWdu ZWQgaW50IHNpemU7DQo+ID4gKw0KPiA+ICsJaWYgKHZiLT52YjJfcXVldWUtPnR5cGUgPT0gVjRM Ml9CVUZfVFlQRV9NRVRBX09VVFBVVCB8fA0KPiA+ICsJICAgIHZiLT52YjJfcXVldWUtPnR5cGUg PT0gVjRMMl9CVUZfVFlQRV9NRVRBX0NBUFRVUkUpDQo+ID4gKwkJc2l6ZSA9IGZtdC0+Zm10Lm1l dGEuYnVmZmVyc2l6ZTsNCj4gPiArCWVsc2UNCj4gPiArCQlzaXplID0gZm10LT5mbXQucGl4X21w LnBsYW5lX2ZtdFswXS5zaXplaW1hZ2U7DQo+ID4gKw0KPiA+ICsJaWYgKHZiMl9wbGFuZV9zaXpl KHZiLCAwKSA8IHNpemUpIHsNCj4gPiArCQlkZXZfZGJnKGNhbS0+ZGV2LCAicGxhbmUgc2l6ZSBp cyB0b28gc21hbGw6JWx1PCV1XG4iLA0KPiA+ICsJCQl2YjJfcGxhbmVfc2l6ZSh2YiwgMCksIHNp emUpOw0KPiA+ICsJCXJldHVybiAtRUlOVkFMOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCWlmIChW NEwyX1RZUEVfSVNfT1VUUFVUKHZiLT52YjJfcXVldWUtPnR5cGUpKSB7DQo+ID4gKwkJaWYgKHZi Ml9nZXRfcGxhbmVfcGF5bG9hZCh2YiwgMCkgIT0gc2l6ZSkgew0KPiA+ICsJCQlkZXZfZGJnKGNh bS0+ZGV2LCAicGxhbmUgcGF5bG9hZCBpcyBtaXNtYXRjaDolbHU6JXVcbiIsDQo+ID4gKwkJCQl2 YjJfZ2V0X3BsYW5lX3BheWxvYWQodmIsIDApLCBzaXplKTsNCj4gPiArCQkJcmV0dXJuIC1FSU5W QUw7DQo+ID4gKwkJfQ0KPiA+ICsJCXJldHVybiAwOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXY0 bDJfYnVmLT5maWVsZCA9IFY0TDJfRklFTERfTk9ORTsNCj4gPiArCXZiMl9zZXRfcGxhbmVfcGF5 bG9hZCh2YiwgMCwgc2l6ZSk7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiAr DQo+ID4gK3N0YXRpYyB2b2lkIG10a19jYW1fdmIyX2J1Zl9jbGVhbnVwKHN0cnVjdCB2YjJfYnVm ZmVyICp2YikNCj4gPiArew0KPiA+ICsJc3RydWN0IG10a19jYW1fdmlkZW9fZGV2aWNlICpub2Rl ID0gbXRrX2NhbV92YnFfdG9fdmRldih2Yi0+dmIyX3F1ZXVlKTsNCj4gPiArCXN0cnVjdCBtdGtf Y2FtX2RldiAqY2FtID0gdmIyX2dldF9kcnZfcHJpdih2Yi0+dmIyX3F1ZXVlKTsNCj4gPiArCXN0 cnVjdCBtdGtfY2FtX2Rldl9idWZmZXIgKmJ1ZjsNCj4gPiArCXN0cnVjdCBkZXZpY2UgKmRldiA9 IGNhbS0+ZGV2Ow0KPiA+ICsNCj4gPiArCWlmICghbm9kZS0+ZGVzYy5zbWVtX2FsbG9jKQ0KPiA+ ICsJCXJldHVybjsNCj4gPiArDQo+ID4gKwlidWYgPSBtdGtfY2FtX3ZiMl9idWZfdG9fZGV2X2J1 Zih2Yik7DQo+ID4gKwlkbWFfdW5tYXBfcGFnZV9hdHRycyhkZXYsIGJ1Zi0+ZGFkZHIsDQo+ID4g KwkJCSAgICAgdmItPnBsYW5lc1swXS5sZW5ndGgsDQo+ID4gKwkJCSAgICAgRE1BX0JJRElSRUNU SU9OQUwsDQo+ID4gKwkJCSAgICAgRE1BX0FUVFJfU0tJUF9DUFVfU1lOQyk7DQo+ID4gK30NCj4g PiArDQo+ID4gK3N0YXRpYyB2b2lkIG10a19jYW1fdmIyX3JlcXVlc3RfY29tcGxldGUoc3RydWN0 IHZiMl9idWZmZXIgKnZiKQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSA9 IHZiMl9nZXRfZHJ2X3ByaXYodmItPnZiMl9xdWV1ZSk7DQo+ID4gKw0KPiA+ICsJZGV2X2RiZyhj YW0tPmRldiwgIiVzXG4iLCBfX2Z1bmNfXyk7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBp bnQgbXRrX2NhbV92YjJfcXVldWVfc2V0dXAoc3RydWN0IHZiMl9xdWV1ZSAqdnEsDQo+ID4gKwkJ CQkgICB1bnNpZ25lZCBpbnQgKm51bV9idWZmZXJzLA0KPiA+ICsJCQkJICAgdW5zaWduZWQgaW50 ICpudW1fcGxhbmVzLA0KPiA+ICsJCQkJICAgdW5zaWduZWQgaW50IHNpemVzW10sDQo+ID4gKwkJ CQkgICBzdHJ1Y3QgZGV2aWNlICphbGxvY19kZXZzW10pDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBt dGtfY2FtX3ZpZGVvX2RldmljZSAqbm9kZSA9IG10a19jYW1fdmJxX3RvX3ZkZXYodnEpOw0KPiA+ ICsJdW5zaWduZWQgaW50IG1heF9idWZmZXJfY291bnQgPSBub2RlLT5kZXNjLm1heF9idWZfY291 bnQ7DQo+ID4gKwljb25zdCBzdHJ1Y3QgdjRsMl9mb3JtYXQgKmZtdCA9ICZub2RlLT52ZGV2X2Zt dDsNCj4gPiArCXVuc2lnbmVkIGludCBzaXplOw0KPiA+ICsNCj4gPiArCS8qIENoZWNrIHRoZSBs aW1pdGF0aW9uIG9mIGJ1ZmZlciBzaXplICovDQo+ID4gKwlpZiAobWF4X2J1ZmZlcl9jb3VudCkN Cj4gPiArCQkqbnVtX2J1ZmZlcnMgPSBjbGFtcF92YWwoKm51bV9idWZmZXJzLCAxLCBtYXhfYnVm ZmVyX2NvdW50KTsNCj4gPiArDQo+ID4gKwlpZiAobm9kZS0+ZGVzYy5zbWVtX2FsbG9jKQ0KPiA+ ICsJCXZxLT5kbWFfYXR0cnMgfD0gRE1BX0FUVFJfTk9fS0VSTkVMX01BUFBJTkc7DQo+ID4gKw0K PiA+ICsJaWYgKHZxLT50eXBlID09IFY0TDJfQlVGX1RZUEVfTUVUQV9PVVRQVVQgfHwNCj4gPiAr CSAgICB2cS0+dHlwZSA9PSBWNEwyX0JVRl9UWVBFX01FVEFfQ0FQVFVSRSkNCj4gPiArCQlzaXpl ID0gZm10LT5mbXQubWV0YS5idWZmZXJzaXplOw0KPiA+ICsJZWxzZQ0KPiA+ICsJCXNpemUgPSBm bXQtPmZtdC5waXhfbXAucGxhbmVfZm10WzBdLnNpemVpbWFnZTsNCj4gPiArDQo+ID4gKwkvKiBB ZGQgZm9yIHEuY3JlYXRlX2J1ZnMgd2l0aCBmbXQuZ19zaXplaW1hZ2UocCkgLyAyIHRlc3QgKi8N Cj4gPiArCWlmICgqbnVtX3BsYW5lcykgew0KPiA+ICsJCWlmIChzaXplc1swXSA8IHNpemUgfHwg Km51bV9wbGFuZXMgIT0gMSkNCj4gPiArCQkJcmV0dXJuIC1FSU5WQUw7DQo+ID4gKwl9IGVsc2Ug ew0KPiA+ICsJCSpudW1fcGxhbmVzID0gMTsNCj4gPiArCQlzaXplc1swXSA9IHNpemU7DQo+ID4g Kwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyB2 b2lkIG10a19jYW1fdmIyX3JldHVybl9hbGxfYnVmZmVycyhzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNh bSwNCj4gPiArCQkJCQkgICBzdHJ1Y3QgbXRrX2NhbV92aWRlb19kZXZpY2UgKm5vZGUsDQo+ID4g KwkJCQkJICAgZW51bSB2YjJfYnVmZmVyX3N0YXRlIHN0YXRlKQ0KPiA+ICt7DQo+ID4gKwlzdHJ1 Y3QgbXRrX2NhbV9kZXZfYnVmZmVyICpidWYsICpidWZfcHJldjsNCj4gPiArCXVuc2lnbmVkIGxv bmcgZmxhZ3M7DQo+ID4gKw0KPiA+ICsJc3Bpbl9sb2NrX2lycXNhdmUoJm5vZGUtPmJ1Zl9saXN0 X2xvY2ssIGZsYWdzKTsNCj4gPiArCWxpc3RfZm9yX2VhY2hfZW50cnlfc2FmZShidWYsIGJ1Zl9w cmV2LCAmbm9kZS0+YnVmX2xpc3QsIGxpc3QpIHsNCj4gPiArCQlsaXN0X2RlbCgmYnVmLT5saXN0 KTsNCj4gPiArCQl2YjJfYnVmZmVyX2RvbmUoJmJ1Zi0+dmJiLnZiMl9idWYsIHN0YXRlKTsNCj4g PiArCX0NCj4gPiArCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUoJm5vZGUtPmJ1Zl9saXN0X2xvY2ss IGZsYWdzKTsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBtdGtfY2FtX3ZiMl9zdGFy dF9zdHJlYW1pbmcoc3RydWN0IHZiMl9xdWV1ZSAqdnEsDQo+ID4gKwkJCQkgICAgICAgdW5zaWdu ZWQgaW50IGNvdW50KQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSA9IHZi Ml9nZXRfZHJ2X3ByaXYodnEpOw0KPiA+ICsJc3RydWN0IG10a19jYW1fdmlkZW9fZGV2aWNlICpu b2RlID0gbXRrX2NhbV92YnFfdG9fdmRldih2cSk7DQo+ID4gKwlzdHJ1Y3QgZGV2aWNlICpkZXYg PSBjYW0tPmRldjsNCj4gPiArCWludCByZXQ7DQo+ID4gKw0KPiA+ICsJaWYgKCFub2RlLT5lbmFi bGVkKSB7DQo+ID4gKwkJZGV2X2VycihkZXYsICJOb2RlOiVkIGlzIG5vdCBlbmFibGVkXG4iLCBu b2RlLT5pZCk7DQo+ID4gKwkJcmV0ID0gLUVOT0xJTks7DQo+ID4gKwkJZ290byBmYWlsX3JldF9i dWY7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJbXV0ZXhfbG9jaygmY2FtLT5vcF9sb2NrKTsNCj4g PiArCS8qIFN0YXJ0IHN0cmVhbWluZyBvZiB0aGUgd2hvbGUgcGlwZWxpbmUgbm93Ki8NCj4gPiAr CWlmICghY2FtLT5waXBlbGluZS5zdHJlYW1pbmdfY291bnQpIHsNCj4gPiArCQlyZXQgPSBtZWRp YV9waXBlbGluZV9zdGFydCgmbm9kZS0+dmRldi5lbnRpdHksICZjYW0tPnBpcGVsaW5lKTsNCj4g PiArCQlpZiAocmV0KSB7DQo+ID4gKwkJCWRldl9lcnIoZGV2LCAiZmFpbGVkIHRvIHN0YXJ0IHBp cGVsaW5lOiVkXG4iLCByZXQpOw0KPiA+ICsJCQlnb3RvIGZhaWxfdW5sb2NrOw0KPiA+ICsJCX0N Cj4gPiArCQltdGtfY2FtX2Rldl9pbml0X3N0cmVhbShjYW0pOw0KPiA+ICsJCXJldCA9IG10a19p c3BfaHdfaW5pdChjYW0pOw0KPiA+ICsJCWlmIChyZXQpIHsNCj4gPiArCQkJZGV2X2VycihkZXYs ICJmYWlsZWQgdG8gaW5pdCBIVzolZFxuIiwgcmV0KTsNCj4gPiArCQkJZ290byBmYWlsX3N0b3Bf cGlwZWxpbmU7DQo+ID4gKwkJfQ0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCS8qIE1lZGlhIGxpbmtz IGFyZSBmaXhlZCBhZnRlciBtZWRpYV9waXBlbGluZV9zdGFydCAqLw0KPiA+ICsJY2FtLT5zdHJl YW1fY291bnQrKzsNCj4gPiArCWRldl9kYmcoZGV2LCAiJXM6IGNvdW50IGluZm86JWQ6JWRcbiIs IF9fZnVuY19fLCBjYW0tPnN0cmVhbV9jb3VudCwNCj4gPiArCQljYW0tPmVuYWJsZWRfY291bnQp Ow0KPiA+ICsJaWYgKGNhbS0+c3RyZWFtX2NvdW50IDwgY2FtLT5lbmFibGVkX2NvdW50KSB7DQo+ ID4gKwkJbXV0ZXhfdW5sb2NrKCZjYW0tPm9wX2xvY2spOw0KPiA+ICsJCXJldHVybiAwOw0KPiA+ ICsJfQ0KPiA+ICsNCj4gPiArCS8qIFN0cmVhbSBvbiBzdWItZGV2aWNlcyBub2RlICovDQo+ID4g KwlyZXQgPSB2NGwyX3N1YmRldl9jYWxsKCZjYW0tPnN1YmRldiwgdmlkZW8sIHNfc3RyZWFtLCAx KTsNCj4gPiArCWlmIChyZXQpDQo+ID4gKwkJZ290byBmYWlsX25vX3N0cmVhbTsNCj4gPiArCW11 dGV4X3VubG9jaygmY2FtLT5vcF9sb2NrKTsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiAr DQo+ID4gK2ZhaWxfbm9fc3RyZWFtOg0KPiA+ICsJY2FtLT5zdHJlYW1fY291bnQtLTsNCj4gPiAr ZmFpbF9zdG9wX3BpcGVsaW5lOg0KPiA+ICsJaWYgKGNhbS0+c3RyZWFtX2NvdW50ID09IDApDQo+ ID4gKwkJbWVkaWFfcGlwZWxpbmVfc3RvcCgmbm9kZS0+dmRldi5lbnRpdHkpOw0KPiA+ICtmYWls X3VubG9jazoNCj4gPiArCW11dGV4X3VubG9jaygmY2FtLT5vcF9sb2NrKTsNCj4gPiArZmFpbF9y ZXRfYnVmOg0KPiA+ICsJbXRrX2NhbV92YjJfcmV0dXJuX2FsbF9idWZmZXJzKGNhbSwgbm9kZSwg VkIyX0JVRl9TVEFURV9RVUVVRUQpOw0KPiA+ICsNCj4gPiArCXJldHVybiByZXQ7DQo+ID4gK30N Cj4gPiArDQo+ID4gK3N0YXRpYyB2b2lkIG10a19jYW1fdmIyX3N0b3Bfc3RyZWFtaW5nKHN0cnVj dCB2YjJfcXVldWUgKnZxKQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSA9 IHZiMl9nZXRfZHJ2X3ByaXYodnEpOw0KPiA+ICsJc3RydWN0IG10a19jYW1fdmlkZW9fZGV2aWNl ICpub2RlID0gbXRrX2NhbV92YnFfdG9fdmRldih2cSk7DQo+ID4gKwlzdHJ1Y3QgZGV2aWNlICpk ZXYgPSBjYW0tPmRldjsNCj4gPiArDQo+ID4gKwltdXRleF9sb2NrKCZjYW0tPm9wX2xvY2spOw0K PiA+ICsJZGV2X2RiZyhkZXYsICIlcyBub2RlOiVkIGNvdW50IGluZm86JWRcbiIsIF9fZnVuY19f LCBub2RlLT5pZCwNCj4gPiArCQljYW0tPnN0cmVhbV9jb3VudCk7DQo+ID4gKwkvKiBDaGVjayB0 aGUgZmlyc3Qgbm9kZSB0byBzdHJlYW0tb2ZmICovDQo+ID4gKwlpZiAoY2FtLT5zdHJlYW1fY291 bnQgPT0gY2FtLT5lbmFibGVkX2NvdW50KQ0KPiA+ICsJCXY0bDJfc3ViZGV2X2NhbGwoJmNhbS0+ c3ViZGV2LCB2aWRlbywgc19zdHJlYW0sIDApOw0KPiA+ICsNCj4gPiArCW10a19jYW1fdmIyX3Jl dHVybl9hbGxfYnVmZmVycyhjYW0sIG5vZGUsIFZCMl9CVUZfU1RBVEVfRVJST1IpOw0KPiA+ICsJ Y2FtLT5zdHJlYW1fY291bnQtLTsNCj4gPiArCWlmIChjYW0tPnN0cmVhbV9jb3VudCkgew0KPiA+ ICsJCW11dGV4X3VubG9jaygmY2FtLT5vcF9sb2NrKTsNCj4gPiArCQlyZXR1cm47DQo+ID4gKwl9 DQo+ID4gKwltdXRleF91bmxvY2soJmNhbS0+b3BfbG9jayk7DQo+ID4gKw0KPiA+ICsJbXRrX2Nh bV9kZXZfcmVxX2NsZWFudXAoY2FtKTsNCj4gPiArCW1lZGlhX3BpcGVsaW5lX3N0b3AoJm5vZGUt PnZkZXYuZW50aXR5KTsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBtdGtfY2FtX3Zp ZGlvY19xdWVyeWNhcChzdHJ1Y3QgZmlsZSAqZmlsZSwgdm9pZCAqZmgsDQo+ID4gKwkJCQkgICBz dHJ1Y3QgdjRsMl9jYXBhYmlsaXR5ICpjYXApDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtfY2Ft X2RldiAqY2FtID0gdmlkZW9fZHJ2ZGF0YShmaWxlKTsNCj4gPiArDQo+ID4gKwlzdHJzY3B5KGNh cC0+ZHJpdmVyLCBkZXZfZHJpdmVyX3N0cmluZyhjYW0tPmRldiksIHNpemVvZihjYXAtPmRyaXZl cikpOw0KPiA+ICsJc3Ryc2NweShjYXAtPmNhcmQsIGRldl9kcml2ZXJfc3RyaW5nKGNhbS0+ZGV2 KSwgc2l6ZW9mKGNhcC0+Y2FyZCkpOw0KPiA+ICsJc25wcmludGYoY2FwLT5idXNfaW5mbywgc2l6 ZW9mKGNhcC0+YnVzX2luZm8pLCAicGxhdGZvcm06JXMiLA0KPiA+ICsJCSBkZXZfbmFtZShjYW0t PmRldikpOw0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0 aWMgaW50IG10a19jYW1fdmlkaW9jX2VudW1fZm10KHN0cnVjdCBmaWxlICpmaWxlLCB2b2lkICpm aCwNCj4gPiArCQkJCSAgIHN0cnVjdCB2NGwyX2ZtdGRlc2MgKmYpDQo+ID4gK3sNCj4gPiArCXN0 cnVjdCBtdGtfY2FtX3ZpZGVvX2RldmljZSAqbm9kZSA9IGZpbGVfdG9fbXRrX2NhbV9ub2RlKGZp bGUpOw0KPiA+ICsNCj4gPiArCWlmIChmLT5pbmRleCA+PSBub2RlLT5kZXNjLm51bV9mbXRzKQ0K PiA+ICsJCXJldHVybiAtRUlOVkFMOw0KPiA+ICsNCj4gPiArCS8qIGYtPmRlc2NyaXB0aW9uIGlz IGZpbGxlZCBpbiB2NGxfZmlsbF9mbXRkZXNjIGZ1bmN0aW9uICovDQo+ID4gKwlmLT5waXhlbGZv cm1hdCA9IG5vZGUtPmRlc2MuZm10c1tmLT5pbmRleF0uZm10LnBpeF9tcC5waXhlbGZvcm1hdDsN Cj4gPiArCWYtPmZsYWdzID0gMDsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ ICsNCj4gPiArc3RhdGljIGludCBtdGtfY2FtX3ZpZGlvY19nX2ZtdChzdHJ1Y3QgZmlsZSAqZmls ZSwgdm9pZCAqZmgsDQo+ID4gKwkJCQlzdHJ1Y3QgdjRsMl9mb3JtYXQgKmYpDQo+ID4gK3sNCj4g PiArCXN0cnVjdCBtdGtfY2FtX3ZpZGVvX2RldmljZSAqbm9kZSA9IGZpbGVfdG9fbXRrX2NhbV9u b2RlKGZpbGUpOw0KPiA+ICsNCj4gPiArCWYtPmZtdCA9IG5vZGUtPnZkZXZfZm10LmZtdDsNCj4g PiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBtdGtf Y2FtX3ZpZGlvY190cnlfZm10KHN0cnVjdCBmaWxlICpmaWxlLCB2b2lkICpmaCwNCj4gPiArCQkJ CSAgc3RydWN0IHY0bDJfZm9ybWF0ICpmKQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgbXRrX2NhbV9k ZXYgKmNhbSA9IHZpZGVvX2RydmRhdGEoZmlsZSk7DQo+ID4gKwlzdHJ1Y3QgbXRrX2NhbV92aWRl b19kZXZpY2UgKm5vZGUgPSBmaWxlX3RvX210a19jYW1fbm9kZShmaWxlKTsNCj4gPiArCXN0cnVj dCBkZXZpY2UgKmRldiA9IGNhbS0+ZGV2Ow0KPiA+ICsJY29uc3Qgc3RydWN0IHY0bDJfZm9ybWF0 ICpkZXZfZm10Ow0KPiA+ICsJc3RydWN0IHY0bDJfZm9ybWF0IHRyeV9mbXQ7DQo+ID4gKw0KPiA+ ICsJbWVtc2V0KCZ0cnlfZm10LCAwLCBzaXplb2YodHJ5X2ZtdCkpOw0KPiA+ICsJdHJ5X2ZtdC50 eXBlID0gZi0+dHlwZTsNCj4gPiArDQo+ID4gKwkvKiBWYWxpZGF0ZSBwaXhlbGZvcm1hdCAqLw0K PiA+ICsJZGV2X2ZtdCA9IG10a19jYW1fZGV2X2ZpbmRfZm10KCZub2RlLT5kZXNjLCBmLT5mbXQu cGl4X21wLnBpeGVsZm9ybWF0KTsNCj4gPiArCWlmICghZGV2X2ZtdCkgew0KPiA+ICsJCWRldl9k YmcoZGV2LCAidW5rbm93biBmbXQ6JWRcbiIsIGYtPmZtdC5waXhfbXAucGl4ZWxmb3JtYXQpOw0K PiA+ICsJCWRldl9mbXQgPSAmbm9kZS0+ZGVzYy5mbXRzW25vZGUtPmRlc2MuZGVmYXVsdF9mbXRf aWR4XTsNCj4gPiArCX0NCj4gPiArCXRyeV9mbXQuZm10LnBpeF9tcC5waXhlbGZvcm1hdCA9IGRl dl9mbXQtPmZtdC5waXhfbXAucGl4ZWxmb3JtYXQ7DQo+ID4gKw0KPiA+ICsJLyogVmFsaWRhdGUg aW1hZ2Ugd2lkdGggJiBoZWlnaHQgcmFuZ2UgKi8NCj4gPiArCXRyeV9mbXQuZm10LnBpeF9tcC53 aWR0aCA9IGNsYW1wX3ZhbChmLT5mbXQucGl4X21wLndpZHRoLA0KPiA+ICsJCQkJCSAgICAgSU1H X01JTl9XSURUSCwgSU1HX01BWF9XSURUSCk7DQo+ID4gKwl0cnlfZm10LmZtdC5waXhfbXAuaGVp Z2h0ID0gY2xhbXBfdmFsKGYtPmZtdC5waXhfbXAuaGVpZ2h0LA0KPiA+ICsJCQkJCSAgICAgIElN R19NSU5fSEVJR0hULCBJTUdfTUFYX0hFSUdIVCk7DQo+ID4gKwkvKiA0IGJ5dGVzIGFsaWdubWVu dCBmb3Igd2lkdGggKi8NCj4gPiArCXRyeV9mbXQuZm10LnBpeF9tcC53aWR0aCA9IEFMSUdOKHRy eV9mbXQuZm10LnBpeF9tcC53aWR0aCwgNCk7DQo+ID4gKw0KPiA+ICsJLyogT25seSBzdXBwb3J0 IG9uZSBwbGFuZSAqLw0KPiA+ICsJdHJ5X2ZtdC5mbXQucGl4X21wLm51bV9wbGFuZXMgPSAxOw0K PiA+ICsNCj4gPiArCS8qIGJ5dGVzcGVybGluZSAmIHNpemVpbWFnZSBjYWxjdWxhdGlvbiAqLw0K PiA+ICsJY2FsX2ltYWdlX3BpeF9tcChjYW0sIG5vZGUtPmlkLCAmdHJ5X2ZtdC5mbXQucGl4X21w KTsNCj4gPiArDQo+ID4gKwkvKiBDb25zdGFudCBmb3JtYXQgZmllbGRzICovDQo+ID4gKwl0cnlf Zm10LmZtdC5waXhfbXAuY29sb3JzcGFjZSA9IFY0TDJfQ09MT1JTUEFDRV9TUkdCOw0KPiA+ICsJ dHJ5X2ZtdC5mbXQucGl4X21wLmZpZWxkID0gVjRMMl9GSUVMRF9OT05FOw0KPiA+ICsJdHJ5X2Zt dC5mbXQucGl4X21wLnljYmNyX2VuYyA9IFY0TDJfWUNCQ1JfRU5DX0RFRkFVTFQ7DQo+ID4gKwl0 cnlfZm10LmZtdC5waXhfbXAucXVhbnRpemF0aW9uID0gVjRMMl9RVUFOVElaQVRJT05fREVGQVVM VDsNCj4gPiArCXRyeV9mbXQuZm10LnBpeF9tcC54ZmVyX2Z1bmMgPSBWNEwyX1hGRVJfRlVOQ19T UkdCOw0KPiA+ICsNCj4gPiArCSpmID0gdHJ5X2ZtdDsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsN Cj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBtdGtfY2FtX3ZpZGlvY19zX2ZtdChzdHJ1 Y3QgZmlsZSAqZmlsZSwgdm9pZCAqZmgsDQo+ID4gKwkJCQlzdHJ1Y3QgdjRsMl9mb3JtYXQgKmYp DQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtfY2FtX2RldiAqY2FtID0gdmlkZW9fZHJ2ZGF0YShm aWxlKTsNCj4gPiArCXN0cnVjdCBtdGtfY2FtX3ZpZGVvX2RldmljZSAqbm9kZSA9IGZpbGVfdG9f bXRrX2NhbV9ub2RlKGZpbGUpOw0KPiA+ICsNCj4gPiArCWlmICh2YjJfaXNfYnVzeShub2RlLT52 ZGV2LnF1ZXVlKSkgew0KPiA+ICsJCWRldl9kYmcoY2FtLT5kZXYsICIlczogcXVldWUgaXMgYnVz eVxuIiwgX19mdW5jX18pOw0KPiA+ICsJCXJldHVybiAtRUJVU1k7DQo+ID4gKwl9DQo+ID4gKw0K PiA+ICsJLyogR2V0IHRoZSB2YWxpZCBmb3JtYXQgKi8NCj4gPiArCW10a19jYW1fdmlkaW9jX3Ry eV9mbXQoZmlsZSwgZmgsIGYpOw0KPiA+ICsJLyogQ29uZmlndXJlIHRvIHZpZGVvIGRldmljZSAq Lw0KPiA+ICsJbm9kZS0+dmRldl9mbXQgPSAqZjsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4g PiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBtdGtfY2FtX3ZpZGlvY19lbnVtX2ZyYW1lc2l6 ZXMoc3RydWN0IGZpbGUgKmZpbHAsIHZvaWQgKnByaXYsDQo+ID4gKwkJCQkJICBzdHJ1Y3QgdjRs Ml9mcm1zaXplZW51bSAqc2l6ZXMpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtfY2FtX3ZpZGVv X2RldmljZSAqbm9kZSA9IGZpbGVfdG9fbXRrX2NhbV9ub2RlKGZpbHApOw0KPiA+ICsJY29uc3Qg c3RydWN0IHY0bDJfZm9ybWF0ICpkZXZfZm10Ow0KPiA+ICsNCj4gPiArCWRldl9mbXQgPSBtdGtf Y2FtX2Rldl9maW5kX2ZtdCgmbm9kZS0+ZGVzYywgc2l6ZXMtPnBpeGVsX2Zvcm1hdCk7DQo+ID4g KwlpZiAoIWRldl9mbXQgfHwgc2l6ZXMtPmluZGV4KQ0KPiA+ICsJCXJldHVybiAtRUlOVkFMOw0K PiA+ICsNCj4gPiArCXNpemVzLT50eXBlID0gbm9kZS0+ZGVzYy5mcm1zaXplcy0+dHlwZTsNCj4g PiArCW1lbWNweSgmc2l6ZXMtPnN0ZXB3aXNlLCAmbm9kZS0+ZGVzYy5mcm1zaXplcy0+c3RlcHdp c2UsDQo+ID4gKwkgICAgICAgc2l6ZW9mKHNpemVzLT5zdGVwd2lzZSkpOw0KPiA+ICsNCj4gPiAr CXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IG10a19jYW1fdmlkaW9j X21ldGFfZW51bV9mbXQoc3RydWN0IGZpbGUgKmZpbGUsIHZvaWQgKmZoLA0KPiA+ICsJCQkJCXN0 cnVjdCB2NGwyX2ZtdGRlc2MgKmYpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtfY2FtX3ZpZGVv X2RldmljZSAqbm9kZSA9IGZpbGVfdG9fbXRrX2NhbV9ub2RlKGZpbGUpOw0KPiA+ICsNCj4gPiAr CWlmIChmLT5pbmRleCkNCj4gPiArCQlyZXR1cm4gLUVJTlZBTDsNCj4gPiArDQo+ID4gKwkvKiBm LT5kZXNjcmlwdGlvbiBpcyBmaWxsZWQgaW4gdjRsX2ZpbGxfZm10ZGVzYyBmdW5jdGlvbiAqLw0K PiA+ICsJZi0+cGl4ZWxmb3JtYXQgPSBub2RlLT52ZGV2X2ZtdC5mbXQubWV0YS5kYXRhZm9ybWF0 Ow0KPiA+ICsJZi0+ZmxhZ3MgPSAwOw0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ ID4gKw0KPiA+ICtzdGF0aWMgaW50IG10a19jYW1fdmlkaW9jX2dfbWV0YV9mbXQoc3RydWN0IGZp bGUgKmZpbGUsIHZvaWQgKmZoLA0KPiA+ICsJCQkJICAgICBzdHJ1Y3QgdjRsMl9mb3JtYXQgKmYp DQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtfY2FtX3ZpZGVvX2RldmljZSAqbm9kZSA9IGZpbGVf dG9fbXRrX2NhbV9ub2RlKGZpbGUpOw0KPiA+ICsNCj4gPiArCWYtPmZtdC5tZXRhLmRhdGFmb3Jt YXQgPSBub2RlLT52ZGV2X2ZtdC5mbXQubWV0YS5kYXRhZm9ybWF0Ow0KPiA+ICsJZi0+Zm10Lm1l dGEuYnVmZmVyc2l6ZSA9IG5vZGUtPnZkZXZfZm10LmZtdC5tZXRhLmJ1ZmZlcnNpemU7DQo+ID4g Kw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1 Y3QgdjRsMl9zdWJkZXZfY29yZV9vcHMgbXRrX2NhbV9zdWJkZXZfY29yZV9vcHMgPSB7DQo+ID4g Kwkuc3Vic2NyaWJlX2V2ZW50ID0gbXRrX2NhbV9zZF9zdWJzY3JpYmVfZXZlbnQsDQo+ID4gKwku dW5zdWJzY3JpYmVfZXZlbnQgPSB2NGwyX2V2ZW50X3N1YmRldl91bnN1YnNjcmliZSwNCj4gPiAr fTsNCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgdjRsMl9zdWJkZXZfdmlkZW9fb3Bz IG10a19jYW1fc3ViZGV2X3ZpZGVvX29wcyA9IHsNCj4gPiArCS5zX3N0cmVhbSA9ICBtdGtfY2Ft X3NkX3Nfc3RyZWFtLA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCB2 NGwyX3N1YmRldl9vcHMgbXRrX2NhbV9zdWJkZXZfb3BzID0gew0KPiA+ICsJLmNvcmUgPSAmbXRr X2NhbV9zdWJkZXZfY29yZV9vcHMsDQo+ID4gKwkudmlkZW8gPSAmbXRrX2NhbV9zdWJkZXZfdmlk ZW9fb3BzLA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBtZWRpYV9l bnRpdHlfb3BlcmF0aW9ucyBtdGtfY2FtX21lZGlhX2VudGl0eV9vcHMgPSB7DQo+ID4gKwkubGlu a19zZXR1cCA9IG10a19jYW1fbWVkaWFfbGlua19zZXR1cCwNCj4gPiArCS5saW5rX3ZhbGlkYXRl ID0gdjRsMl9zdWJkZXZfbGlua192YWxpZGF0ZSwNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRp YyBjb25zdCBzdHJ1Y3QgdmIyX29wcyBtdGtfY2FtX3ZiMl9vcHMgPSB7DQo+ID4gKwkucXVldWVf c2V0dXAgPSBtdGtfY2FtX3ZiMl9xdWV1ZV9zZXR1cCwNCj4gPiArCS53YWl0X3ByZXBhcmUgPSB2 YjJfb3BzX3dhaXRfcHJlcGFyZSwNCj4gPiArCS53YWl0X2ZpbmlzaCA9IHZiMl9vcHNfd2FpdF9m aW5pc2gsDQo+ID4gKwkuYnVmX2luaXQgPSBtdGtfY2FtX3ZiMl9idWZfaW5pdCwNCj4gPiArCS5i dWZfcHJlcGFyZSA9IG10a19jYW1fdmIyX2J1Zl9wcmVwYXJlLA0KPiA+ICsJLnN0YXJ0X3N0cmVh bWluZyA9IG10a19jYW1fdmIyX3N0YXJ0X3N0cmVhbWluZywNCj4gPiArCS5zdG9wX3N0cmVhbWlu ZyA9IG10a19jYW1fdmIyX3N0b3Bfc3RyZWFtaW5nLA0KPiA+ICsJLmJ1Zl9xdWV1ZSA9IG10a19j YW1fdmIyX2J1Zl9xdWV1ZSwNCj4gPiArCS5idWZfY2xlYW51cCA9IG10a19jYW1fdmIyX2J1Zl9j bGVhbnVwLA0KPiA+ICsJLmJ1Zl9yZXF1ZXN0X2NvbXBsZXRlID0gbXRrX2NhbV92YjJfcmVxdWVz dF9jb21wbGV0ZSwNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgdjRs Ml9maWxlX29wZXJhdGlvbnMgbXRrX2NhbV92NGwyX2ZvcHMgPSB7DQo+ID4gKwkudW5sb2NrZWRf aW9jdGwgPSB2aWRlb19pb2N0bDIsDQo+ID4gKwkub3BlbiA9IHY0bDJfZmhfb3BlbiwNCj4gPiAr CS5yZWxlYXNlID0gdmIyX2ZvcF9yZWxlYXNlLA0KPiA+ICsJLnBvbGwgPSB2YjJfZm9wX3BvbGws DQo+ID4gKwkubW1hcCA9IHZiMl9mb3BfbW1hcCwNCj4gPiArI2lmZGVmIENPTkZJR19DT01QQVQN Cj4gPiArCS5jb21wYXRfaW9jdGwzMiA9IHY0bDJfY29tcGF0X2lvY3RsMzIsDQo+ID4gKyNlbmRp Zg0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBtZWRpYV9kZXZpY2Vf b3BzIG10a19jYW1fbWVkaWFfb3BzID0gew0KPiA+ICsJLnJlcV9hbGxvYyA9IG10a19jYW1fcmVx X2FsbG9jLA0KPiA+ICsJLnJlcV9mcmVlID0gbXRrX2NhbV9yZXFfZnJlZSwNCj4gPiArCS5yZXFf dmFsaWRhdGUgPSB2YjJfcmVxdWVzdF92YWxpZGF0ZSwNCj4gPiArCS5yZXFfcXVldWUgPSBtdGtf Y2FtX3JlcV9xdWV1ZSwNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgbXRrX2NhbV9t ZWRpYV9yZWdpc3RlcihzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSwNCj4gPiArCQkJCSAgc3RydWN0 IG1lZGlhX2RldmljZSAqbWVkaWFfZGV2KQ0KPiA+ICt7DQo+ID4gKwkvKiBSZXNlcnZlZCBNVEtf Q0FNX0NJT19QQURfU0lOSyArIDEgcGFkcyB0byB1c2UgKi8NCj4gPiArCXVuc2lnbmVkIGludCBu dW1fcGFkcyA9IE1US19DQU1fQ0lPX1BBRF9TSU5LICsgMTsNCj4gPiArCXN0cnVjdCBkZXZpY2Ug KmRldiA9IGNhbS0+ZGV2Ow0KPiA+ICsJaW50IGksIHJldDsNCj4gPiArDQo+ID4gKwltZWRpYV9k ZXYtPmRldiA9IGNhbS0+ZGV2Ow0KPiA+ICsJc3Ryc2NweShtZWRpYV9kZXYtPm1vZGVsLCBkZXZf ZHJpdmVyX3N0cmluZyhkZXYpLA0KPiA+ICsJCXNpemVvZihtZWRpYV9kZXYtPm1vZGVsKSk7DQo+ ID4gKwlzbnByaW50ZihtZWRpYV9kZXYtPmJ1c19pbmZvLCBzaXplb2YobWVkaWFfZGV2LT5idXNf aW5mbyksDQo+ID4gKwkJICJwbGF0Zm9ybTolcyIsIGRldl9uYW1lKGRldikpOw0KPiA+ICsJbWVk aWFfZGV2LT5od19yZXZpc2lvbiA9IDA7DQo+ID4gKwltZWRpYV9kZXZpY2VfaW5pdChtZWRpYV9k ZXYpOw0KPiA+ICsJbWVkaWFfZGV2LT5vcHMgPSAmbXRrX2NhbV9tZWRpYV9vcHM7DQo+ID4gKw0K PiA+ICsJcmV0ID0gbWVkaWFfZGV2aWNlX3JlZ2lzdGVyKG1lZGlhX2Rldik7DQo+ID4gKwlpZiAo cmV0KSB7DQo+ID4gKwkJZGV2X2VycihkZXYsICJmYWlsZWQgdG8gcmVnaXN0ZXIgbWVkaWEgZGV2 aWNlOiVkXG4iLCByZXQpOw0KPiA+ICsJCXJldHVybiByZXQ7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ ICsJLyogSW5pdGlhbGl6ZSBzdWJkZXYgcGFkcyAqLw0KPiA+ICsJY2FtLT5zdWJkZXZfcGFkcyA9 IGRldm1fa2NhbGxvYyhkZXYsIG51bV9wYWRzLA0KPiA+ICsJCQkJCXNpemVvZigqY2FtLT5zdWJk ZXZfcGFkcyksDQo+ID4gKwkJCQkJR0ZQX0tFUk5FTCk7DQo+ID4gKwlpZiAoIWNhbS0+c3ViZGV2 X3BhZHMpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0byBhbGxvY2F0ZSBzdWJkZXZf cGFkc1xuIik7DQo+ID4gKwkJcmV0ID0gLUVOT01FTTsNCj4gPiArCQlnb3RvIGZhaWxfbWVkaWFf dW5yZWc7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0ID0gbWVkaWFfZW50aXR5X3BhZHNfaW5p dCgmY2FtLT5zdWJkZXYuZW50aXR5LCBudW1fcGFkcywNCj4gPiArCQkJCSAgICAgY2FtLT5zdWJk ZXZfcGFkcyk7DQo+ID4gKwlpZiAocmV0KSB7DQo+ID4gKwkJZGV2X2VycihkZXYsICJmYWlsZWQg dG8gaW5pdGlhbGl6ZSBtZWRpYSBwYWRzOiVkXG4iLCByZXQpOw0KPiA+ICsJCWdvdG8gZmFpbF9t ZWRpYV91bnJlZzsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwkvKiBJbml0aWFsaXplIGFsbCBwYWRz IHdpdGggTUVESUFfUEFEX0ZMX1NPVVJDRSAqLw0KPiA+ICsJZm9yIChpID0gMDsgaSA8IG51bV9w YWRzOyBpKyspDQo+ID4gKwkJY2FtLT5zdWJkZXZfcGFkc1tpXS5mbGFncyA9IE1FRElBX1BBRF9G TF9TT1VSQ0U7DQo+ID4gKw0KPiA+ICsJLyogQ3VzdG9taXplIHRoZSBsYXN0IG9uZSBwYWQgYXMg Q0lPIHNpbmsgcGFkLiAqLw0KPiA+ICsJY2FtLT5zdWJkZXZfcGFkc1tNVEtfQ0FNX0NJT19QQURf U0lOS10uZmxhZ3MgPSBNRURJQV9QQURfRkxfU0lOSzsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsN Cj4gPiArDQo+ID4gK2ZhaWxfbWVkaWFfdW5yZWc6DQo+ID4gKwltZWRpYV9kZXZpY2VfdW5yZWdp c3RlcigmY2FtLT5tZWRpYV9kZXYpOw0KPiA+ICsJbWVkaWFfZGV2aWNlX2NsZWFudXAoJmNhbS0+ bWVkaWFfZGV2KTsNCj4gPiArDQo+ID4gKwlyZXR1cm4gcmV0Ow0KPiA+ICt9DQo+ID4gKw0KPiA+ ICtzdGF0aWMgaW50DQo+ID4gK210a19jYW1fdmlkZW9fcmVnaXN0ZXJfZGV2aWNlKHN0cnVjdCBt dGtfY2FtX2RldiAqY2FtLA0KPiA+ICsJCQkgICAgICBzdHJ1Y3QgbXRrX2NhbV92aWRlb19kZXZp Y2UgKm5vZGUpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBkZXZpY2UgKmRldiA9IGNhbS0+ZGV2Ow0K PiA+ICsJc3RydWN0IHZpZGVvX2RldmljZSAqdmRldiA9ICZub2RlLT52ZGV2Ow0KPiA+ICsJc3Ry dWN0IHZiMl9xdWV1ZSAqdmJxID0gJm5vZGUtPnZicTsNCj4gPiArCXVuc2lnbmVkIGludCBvdXRw dXQgPSBWNEwyX1RZUEVfSVNfT1VUUFVUKG5vZGUtPmRlc2MuYnVmX3R5cGUpOw0KPiA+ICsJdW5z aWduZWQgaW50IGxpbmtfZmxhZ3MgPSBub2RlLT5kZXNjLmxpbmtfZmxhZ3M7DQo+ID4gKwlpbnQg cmV0Ow0KPiA+ICsNCj4gPiArCS8qIEluaXRpYWxpemUgbXRrX2NhbV92aWRlb19kZXZpY2UgKi8N Cj4gPiArCWlmIChsaW5rX2ZsYWdzICYgTUVESUFfTE5LX0ZMX0lNTVVUQUJMRSkNCj4gPiArCQlu b2RlLT5lbmFibGVkID0gdHJ1ZTsNCj4gPiArCWVsc2UNCj4gPiArCQlub2RlLT5lbmFibGVkID0g ZmFsc2U7DQo+ID4gKwltdGtfY2FtX2Rldl9sb2FkX2RlZmF1bHRfZm10KGNhbSwgJm5vZGUtPmRl c2MsICZub2RlLT52ZGV2X2ZtdCk7DQo+ID4gKw0KPiA+ICsJY2FtLT5zdWJkZXZfcGFkc1tub2Rl LT5pZF0uZmxhZ3MgPSBvdXRwdXQgPw0KPiA+ICsJCU1FRElBX1BBRF9GTF9TSU5LIDogTUVESUFf UEFEX0ZMX1NPVVJDRTsNCj4gPiArDQo+ID4gKwkvKiBJbml0aWFsaXplIG1lZGlhIGVudGl0aWVz ICovDQo+ID4gKwlyZXQgPSBtZWRpYV9lbnRpdHlfcGFkc19pbml0KCZ2ZGV2LT5lbnRpdHksIDEs ICZub2RlLT52ZGV2X3BhZCk7DQo+ID4gKwlpZiAocmV0KSB7DQo+ID4gKwkJZGV2X2VycihkZXYs ICJmYWlsZWQgdG8gaW5pdGlhbGl6ZSBtZWRpYSBwYWQ6JWRcbiIsIHJldCk7DQo+ID4gKwkJcmV0 dXJuIHJldDsNCj4gPiArCX0NCj4gPiArCW5vZGUtPnZkZXZfcGFkLmZsYWdzID0gb3V0cHV0ID8g TUVESUFfUEFEX0ZMX1NPVVJDRSA6IE1FRElBX1BBRF9GTF9TSU5LOw0KPiA+ICsNCj4gPiArCS8q IEluaXRpYWxpemUgdmJxICovDQo+ID4gKwl2YnEtPnR5cGUgPSBub2RlLT5kZXNjLmJ1Zl90eXBl Ow0KPiA+ICsJaWYgKHZicS0+dHlwZSA9PSBWNEwyX0JVRl9UWVBFX01FVEFfT1VUUFVUKQ0KPiA+ ICsJCXZicS0+aW9fbW9kZXMgPSBWQjJfTU1BUDsNCj4gPiArCWVsc2UNCj4gPiArCQl2YnEtPmlv X21vZGVzID0gVkIyX01NQVAgfCBWQjJfRE1BQlVGOw0KPiA+ICsNCj4gPiArCWlmIChub2RlLT5k ZXNjLnNtZW1fYWxsb2MpIHsNCj4gPiArCQl2YnEtPmJpZGlyZWN0aW9uYWwgPSAxOw0KPiA+ICsJ CXZicS0+ZGV2ID0gY2FtLT5zbWVtX2RldjsNCj4gPiArCX0gZWxzZSB7DQo+ID4gKwkJdmJxLT5k ZXYgPSBkZXY7DQo+ID4gKwl9DQo+ID4gKwl2YnEtPm9wcyA9ICZtdGtfY2FtX3ZiMl9vcHM7DQo+ ID4gKwl2YnEtPm1lbV9vcHMgPSAmdmIyX2RtYV9jb250aWdfbWVtb3BzOw0KPiA+ICsJdmJxLT5i dWZfc3RydWN0X3NpemUgPSBzaXplb2Yoc3RydWN0IG10a19jYW1fZGV2X2J1ZmZlcik7DQo+ID4g Kwl2YnEtPnRpbWVzdGFtcF9mbGFncyA9IFY0TDJfQlVGX0ZMQUdfVElNRVNUQU1QX0JPT1RJTUU7 DQo+ID4gKwlpZiAob3V0cHV0KQ0KPiA+ICsJCXZicS0+dGltZXN0YW1wX2ZsYWdzIHw9IFY0TDJf QlVGX0ZMQUdfVFNUQU1QX1NSQ19FT0Y7DQo+ID4gKwllbHNlDQo+ID4gKwkJdmJxLT50aW1lc3Rh bXBfZmxhZ3MgfD0gVjRMMl9CVUZfRkxBR19UU1RBTVBfU1JDX1NPRTsNCj4gPiArCS8qIE5vIG1p bmltdW0gYnVmZmVycyBsaW1pdGF0aW9uICovDQo+ID4gKwl2YnEtPm1pbl9idWZmZXJzX25lZWRl ZCA9IDA7DQo+ID4gKwl2YnEtPmRydl9wcml2ID0gY2FtOw0KPiA+ICsJdmJxLT5sb2NrID0gJm5v ZGUtPnZkZXZfbG9jazsNCj4gPiArCXZicS0+c3VwcG9ydHNfcmVxdWVzdHMgPSB0cnVlOw0KPiA+ ICsJdmJxLT5yZXF1aXJlc19yZXF1ZXN0cyA9IHRydWU7DQo+ID4gKw0KPiA+ICsJcmV0ID0gdmIy X3F1ZXVlX2luaXQodmJxKTsNCj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwg ImZhaWxlZCB0byBpbml0LiB2YjIgcXVldWU6JWRcbiIsIHJldCk7DQo+ID4gKwkJZ290byBmYWls X21lZGlhX2NsZWFuOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCS8qIEluaXRpYWxpemUgdmRldiAq Lw0KPiA+ICsJc25wcmludGYodmRldi0+bmFtZSwgc2l6ZW9mKHZkZXYtPm5hbWUpLCAiJXMgJXMi LA0KPiA+ICsJCSBkZXZfZHJpdmVyX3N0cmluZyhkZXYpLCBub2RlLT5kZXNjLm5hbWUpOw0KPiA+ ICsJLyogc2V0IGNhcC90eXBlL2lvY3RsX29wcyBvZiB0aGUgdmlkZW8gZGV2aWNlICovDQo+ID4g Kwl2ZGV2LT5kZXZpY2VfY2FwcyA9IG5vZGUtPmRlc2MuY2FwIHwgVjRMMl9DQVBfU1RSRUFNSU5H Ow0KPiA+ICsJdmRldi0+aW9jdGxfb3BzID0gbm9kZS0+ZGVzYy5pb2N0bF9vcHM7DQo+ID4gKwl2 ZGV2LT5mb3BzID0gJm10a19jYW1fdjRsMl9mb3BzOw0KPiA+ICsJdmRldi0+cmVsZWFzZSA9IHZp ZGVvX2RldmljZV9yZWxlYXNlX2VtcHR5Ow0KPiA+ICsJdmRldi0+bG9jayA9ICZub2RlLT52ZGV2 X2xvY2s7DQo+ID4gKwl2ZGV2LT52NGwyX2RldiA9ICZjYW0tPnY0bDJfZGV2Ow0KPiA+ICsJdmRl di0+cXVldWUgPSAmbm9kZS0+dmJxOw0KPiA+ICsJdmRldi0+dmZsX2RpciA9IG91dHB1dCA/IFZG TF9ESVJfVFggOiBWRkxfRElSX1JYOw0KPiA+ICsJdmRldi0+ZW50aXR5LmZ1bmN0aW9uID0gTUVE SUFfRU5UX0ZfSU9fVjRMOw0KPiA+ICsJdmRldi0+ZW50aXR5Lm9wcyA9IE5VTEw7DQo+ID4gKwl2 aWRlb19zZXRfZHJ2ZGF0YSh2ZGV2LCBjYW0pOw0KPiA+ICsJZGV2X2RiZyhkZXYsICJyZWdpc3Rl cmVkIHZkZXY6JWQ6JXNcbiIsIG5vZGUtPmlkLCB2ZGV2LT5uYW1lKTsNCj4gPiArDQo+ID4gKwkv KiBJbml0aWFsaXplIG1pc2NlbGxhbmVvdXMgdmFyaWFibGVzICovDQo+ID4gKwltdXRleF9pbml0 KCZub2RlLT52ZGV2X2xvY2spOw0KPiA+ICsJSU5JVF9MSVNUX0hFQUQoJm5vZGUtPmJ1Zl9saXN0 KTsNCj4gPiArCXNwaW5fbG9ja19pbml0KCZub2RlLT5idWZfbGlzdF9sb2NrKTsNCj4gPiArDQo+ ID4gKwlyZXQgPSB2aWRlb19yZWdpc3Rlcl9kZXZpY2UodmRldiwgVkZMX1RZUEVfR1JBQkJFUiwg LTEpOw0KPiA+ICsJaWYgKHJldCkgew0KPiA+ICsJCWRldl9lcnIoZGV2LCAiZmFpbGVkIHRvIHJl Z2lzdGVyIHZkZTolZFxuIiwgcmV0KTsNCj4gPiArCQlnb3RvIGZhaWxfdmIyX3JlbDsNCj4gPiAr CX0NCj4gPiArDQo+ID4gKwkvKiBDcmVhdGUgbGluayBiZXR3ZWVuIHZpZGVvIG5vZGUgYW5kIHRo ZSBzdWJkZXYgcGFkICovDQo+ID4gKwlpZiAob3V0cHV0KSB7DQo+ID4gKwkJcmV0ID0gbWVkaWFf Y3JlYXRlX3BhZF9saW5rKCZ2ZGV2LT5lbnRpdHksIDAsDQo+ID4gKwkJCQkJICAgICZjYW0tPnN1 YmRldi5lbnRpdHksDQo+ID4gKwkJCQkJICAgIG5vZGUtPmlkLCBsaW5rX2ZsYWdzKTsNCj4gPiAr CX0gZWxzZSB7DQo+ID4gKwkJcmV0ID0gbWVkaWFfY3JlYXRlX3BhZF9saW5rKCZjYW0tPnN1YmRl di5lbnRpdHksDQo+ID4gKwkJCQkJICAgIG5vZGUtPmlkLCAmdmRldi0+ZW50aXR5LCAwLA0KPiA+ ICsJCQkJCSAgICBsaW5rX2ZsYWdzKTsNCj4gPiArCX0NCj4gPiArCWlmIChyZXQpDQo+ID4gKwkJ Z290byBmYWlsX3ZkZXZfdXJlZzsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArDQo+ID4g K2ZhaWxfdmRldl91cmVnOg0KPiA+ICsJdmlkZW9fdW5yZWdpc3Rlcl9kZXZpY2UodmRldik7DQo+ ID4gK2ZhaWxfdmIyX3JlbDoNCj4gPiArCW11dGV4X2Rlc3Ryb3koJm5vZGUtPnZkZXZfbG9jayk7 DQo+ID4gKwl2YjJfcXVldWVfcmVsZWFzZSh2YnEpOw0KPiA+ICtmYWlsX21lZGlhX2NsZWFuOg0K PiA+ICsJbWVkaWFfZW50aXR5X2NsZWFudXAoJnZkZXYtPmVudGl0eSk7DQo+ID4gKw0KPiA+ICsJ cmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIHZvaWQNCj4gPiArbXRrX2Nh bV92aWRlb191bnJlZ2lzdGVyX2RldmljZShzdHJ1Y3QgbXRrX2NhbV92aWRlb19kZXZpY2UgKm5v ZGUpDQo+ID4gK3sNCj4gPiArCXZpZGVvX3VucmVnaXN0ZXJfZGV2aWNlKCZub2RlLT52ZGV2KTsN Cj4gPiArCXZiMl9xdWV1ZV9yZWxlYXNlKCZub2RlLT52YnEpOw0KPiA+ICsJbWVkaWFfZW50aXR5 X2NsZWFudXAoJm5vZGUtPnZkZXYuZW50aXR5KTsNCj4gPiArCW11dGV4X2Rlc3Ryb3koJm5vZGUt PnZkZXZfbG9jayk7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgbXRrX2NhbV92NGwy X3JlZ2lzdGVyKHN0cnVjdCBtdGtfY2FtX2RldiAqY2FtKQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3Qg ZGV2aWNlICpkZXYgPSBjYW0tPmRldjsNCj4gPiArCWludCBpLCByZXQ7DQo+ID4gKw0KPiA+ICsJ LyogU2V0IHVwIG1lZGlhIGRldmljZSAmIHBhZHMgKi8NCj4gPiArCXJldCA9IG10a19jYW1fbWVk aWFfcmVnaXN0ZXIoY2FtLCAmY2FtLT5tZWRpYV9kZXYpOw0KPiA+ICsJaWYgKHJldCkNCj4gPiAr CQlyZXR1cm4gcmV0Ow0KPiA+ICsJZGV2X2luZm8oZGV2LCAiUmVnaXN0ZXJlZCBtZWRpYSVkXG4i LCBjYW0tPm1lZGlhX2Rldi5kZXZub2RlLT5taW5vcik7DQo+ID4gKw0KPiA+ICsJLyogU2V0IHVw IHY0bDIgZGV2aWNlICovDQo+ID4gKwljYW0tPnY0bDJfZGV2Lm1kZXYgPSAmY2FtLT5tZWRpYV9k ZXY7DQo+ID4gKwlyZXQgPSB2NGwyX2RldmljZV9yZWdpc3RlcihkZXYsICZjYW0tPnY0bDJfZGV2 KTsNCj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0byByZWdp c3RlciBWNEwyIGRldmljZTolZFxuIiwgcmV0KTsNCj4gPiArCQlnb3RvIGZhaWxfbWVkaWFfdW5y ZWc7DQo+ID4gKwl9DQo+ID4gKwlkZXZfaW5mbyhkZXYsICJSZWdpc3RlcmVkICVzXG4iLCBjYW0t PnY0bDJfZGV2Lm5hbWUpOw0KPiA+ICsNCj4gPiArCS8qIEluaXRpYWxpemUgc3ViZGV2ICovDQo+ ID4gKwl2NGwyX3N1YmRldl9pbml0KCZjYW0tPnN1YmRldiwgJm10a19jYW1fc3ViZGV2X29wcyk7 DQo+ID4gKwljYW0tPnN1YmRldi5lbnRpdHkuZnVuY3Rpb24gPSBNRURJQV9FTlRfRl9QUk9DX1ZJ REVPX1BJWEVMX0ZPUk1BVFRFUjsNCj4gPiArCWNhbS0+c3ViZGV2LmVudGl0eS5vcHMgPSAmbXRr X2NhbV9tZWRpYV9lbnRpdHlfb3BzOw0KPiA+ICsJY2FtLT5zdWJkZXYuZmxhZ3MgPSBWNEwyX1NV QkRFVl9GTF9IQVNfREVWTk9ERSB8DQo+ID4gKwkJCQlWNEwyX1NVQkRFVl9GTF9IQVNfRVZFTlRT Ow0KPiA+ICsJc25wcmludGYoY2FtLT5zdWJkZXYubmFtZSwgc2l6ZW9mKGNhbS0+c3ViZGV2Lm5h bWUpLA0KPiA+ICsJCSAiJXMiLCBkZXZfZHJpdmVyX3N0cmluZyhkZXYpKTsNCj4gPiArCXY0bDJf c2V0X3N1YmRldmRhdGEoJmNhbS0+c3ViZGV2LCBjYW0pOw0KPiA+ICsNCj4gPiArCXJldCA9IHY0 bDJfZGV2aWNlX3JlZ2lzdGVyX3N1YmRldigmY2FtLT52NGwyX2RldiwgJmNhbS0+c3ViZGV2KTsN Cj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0byBpbml0aWFs aXplIHN1YmRldjolZFxuIiwgcmV0KTsNCj4gPiArCQlnb3RvIGZhaWxfY2xlYW5fbWVkaWFfZW50 aXk7DQo+ID4gKwl9DQo+ID4gKwlkZXZfZGJnKGRldiwgInJlZ2lzdGVyZWQgJXNcbiIsIGNhbS0+ c3ViZGV2Lm5hbWUpOw0KPiA+ICsNCj4gPiArCS8qIENyZWF0ZSB2aWRlbyBub2RlcyBhbmQgbGlu a3MgKi8NCj4gPiArCWZvciAoaSA9IDA7IGkgPCBNVEtfQ0FNX1AxX1RPVEFMX05PREVTOyBpKysp IHsNCj4gPiArCQlzdHJ1Y3QgbXRrX2NhbV92aWRlb19kZXZpY2UgKm5vZGUgPSAmY2FtLT52ZGV2 X25vZGVzW2ldOw0KPiA+ICsNCj4gPiArCQlub2RlLT5pZCA9IG5vZGUtPmRlc2MuaWQ7DQo+ID4g KwkJcmV0ID0gbXRrX2NhbV92aWRlb19yZWdpc3Rlcl9kZXZpY2UoY2FtLCBub2RlKTsNCj4gPiAr CQlpZiAocmV0KQ0KPiA+ICsJCQlnb3RvIGZhaWxfdmRldl91bnJlZzsNCj4gPiArCX0NCj4gPiAr CXZiMl9kbWFfY29udGlnX3NldF9tYXhfc2VnX3NpemUoZGV2LCBETUFfQklUX01BU0soMzIpKTsN Cj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArDQo+ID4gK2ZhaWxfdmRldl91bnJlZzoNCj4g PiArCWZvciAoaS0tOyBpID49IDA7IGktLSkNCj4gPiArCQltdGtfY2FtX3ZpZGVvX3VucmVnaXN0 ZXJfZGV2aWNlKCZjYW0tPnZkZXZfbm9kZXNbaV0pOw0KPiA+ICtmYWlsX2NsZWFuX21lZGlhX2Vu dGl5Og0KPiA+ICsJbWVkaWFfZW50aXR5X2NsZWFudXAoJmNhbS0+c3ViZGV2LmVudGl0eSk7DQo+ ID4gKwl2NGwyX2RldmljZV91bnJlZ2lzdGVyKCZjYW0tPnY0bDJfZGV2KTsNCj4gPiArZmFpbF9t ZWRpYV91bnJlZzoNCj4gPiArCW1lZGlhX2RldmljZV91bnJlZ2lzdGVyKCZjYW0tPm1lZGlhX2Rl dik7DQo+ID4gKwltZWRpYV9kZXZpY2VfY2xlYW51cCgmY2FtLT5tZWRpYV9kZXYpOw0KPiA+ICsN Cj4gPiArCXJldHVybiByZXQ7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgbXRrX2Nh bV92NGwyX3VucmVnaXN0ZXIoc3RydWN0IG10a19jYW1fZGV2ICpjYW0pDQo+ID4gK3sNCj4gPiAr CWludCBpOw0KPiA+ICsNCj4gPiArCWZvciAoaSA9IDA7IGkgPCBNVEtfQ0FNX1AxX1RPVEFMX05P REVTOyBpKyspDQo+ID4gKwkJbXRrX2NhbV92aWRlb191bnJlZ2lzdGVyX2RldmljZSgmY2FtLT52 ZGV2X25vZGVzW2ldKTsNCj4gPiArDQo+ID4gKwl2YjJfZG1hX2NvbnRpZ19jbGVhcl9tYXhfc2Vn X3NpemUoY2FtLT5kZXYpOw0KPiA+ICsJdjRsMl9kZXZpY2VfdW5yZWdpc3Rlcl9zdWJkZXYoJmNh bS0+c3ViZGV2KTsNCj4gPiArCXY0bDJfZGV2aWNlX3VucmVnaXN0ZXIoJmNhbS0+djRsMl9kZXYp Ow0KPiA+ICsJbWVkaWFfZW50aXR5X2NsZWFudXAoJmNhbS0+c3ViZGV2LmVudGl0eSk7DQo+ID4g KwltZWRpYV9kZXZpY2VfdW5yZWdpc3RlcigmY2FtLT5tZWRpYV9kZXYpOw0KPiA+ICsJbWVkaWFf ZGV2aWNlX2NsZWFudXAoJmNhbS0+bWVkaWFfZGV2KTsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsN Cj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBtdGtfY2FtX2Rldl9ub3RpZmllcl9ib3Vu ZChzdHJ1Y3QgdjRsMl9hc3luY19ub3RpZmllciAqbm90aWZpZXIsDQo+ID4gKwkJCQkgICAgICBz dHJ1Y3QgdjRsMl9zdWJkZXYgKnNkLA0KPiA+ICsJCQkJICAgICAgc3RydWN0IHY0bDJfYXN5bmNf c3ViZGV2ICphc2QpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtfY2FtX2RldiAqY2FtID0NCj4g PiArCQljb250YWluZXJfb2Yobm90aWZpZXIsIHN0cnVjdCBtdGtfY2FtX2Rldiwgbm90aWZpZXIp Ow0KPiA+ICsNCj4gPiArCWlmICghKHNkLT5lbnRpdHkuZnVuY3Rpb24gJiBNRURJQV9FTlRfRl9W SURfSUZfQlJJREdFKSkgew0KPiA+ICsJCWRldl9kYmcoY2FtLT5kZXYsICJubyBNRURJQV9FTlRf Rl9WSURfSUZfQlJJREdFIGZ1bmN0aW9uXG4iKTsNCj4gPiArCQlyZXR1cm4gLUVOT0RFVjsNCj4g PiArCX0NCj4gPiArDQo+ID4gKwljYW0tPnNlbmluZiA9IHNkOw0KPiA+ICsJZGV2X2RiZyhjYW0t PmRldiwgIiVzIGlzIGJvdW5kXG4iLCBzZC0+ZW50aXR5Lm5hbWUpOw0KPiA+ICsNCj4gPiArCXJl dHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgdm9pZCBtdGtfY2FtX2Rldl9ub3Rp Zmllcl91bmJpbmQoc3RydWN0IHY0bDJfYXN5bmNfbm90aWZpZXIgKm5vdGlmaWVyLA0KPiA+ICsJ CQkJCXN0cnVjdCB2NGwyX3N1YmRldiAqc2QsDQo+ID4gKwkJCQkJc3RydWN0IHY0bDJfYXN5bmNf c3ViZGV2ICphc2QpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBtdGtfY2FtX2RldiAqY2FtID0NCj4g PiArCQljb250YWluZXJfb2Yobm90aWZpZXIsIHN0cnVjdCBtdGtfY2FtX2Rldiwgbm90aWZpZXIp Ow0KPiA+ICsNCj4gPiArCWNhbS0+c2VuaW5mID0gTlVMTDsNCj4gPiArCWRldl9kYmcoY2FtLT5k ZXYsICIlcyBpcyB1bmJvdW5kXG4iLCBzZC0+ZW50aXR5Lm5hbWUpOw0KPiA+ICt9DQo+ID4gKw0K PiA+ICtzdGF0aWMgaW50IG10a19jYW1fZGV2X25vdGlmaWVyX2NvbXBsZXRlKHN0cnVjdCB2NGwy X2FzeW5jX25vdGlmaWVyICpub3RpZmllcikNCj4gPiArew0KPiA+ICsJc3RydWN0IG10a19jYW1f ZGV2ICpjYW0gPQ0KPiA+ICsJCWNvbnRhaW5lcl9vZihub3RpZmllciwgc3RydWN0IG10a19jYW1f ZGV2LCBub3RpZmllcik7DQo+ID4gKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSBjYW0tPmRldjsNCj4g PiArCWludCByZXQ7DQo+ID4gKw0KPiA+ICsJaWYgKCFjYW0tPnNlbmluZikgew0KPiA+ICsJCWRl dl9lcnIoZGV2LCAiTm8gc2VuaW5mIHN1YmRldlxuIik7DQo+ID4gKwkJcmV0dXJuIC1FTk9ERVY7 DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0ID0gbWVkaWFfY3JlYXRlX3BhZF9saW5rKCZjYW0t PnNlbmluZi0+ZW50aXR5LCBNVEtfQ0FNX0NJT19QQURfU1JDLA0KPiA+ICsJCQkJICAgICZjYW0t PnN1YmRldi5lbnRpdHksIE1US19DQU1fQ0lPX1BBRF9TSU5LLA0KPiA+ICsJCQkJICAgIE1FRElB X0xOS19GTF9JTU1VVEFCTEUgfA0KPiA+ICsJCQkJICAgIE1FRElBX0xOS19GTF9FTkFCTEVEKTsN Cj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0byBjcmVhdGUg cGFkIGxpbmsgJXMgJXMgZXJyOiVkXG4iLA0KPiA+ICsJCQljYW0tPnNlbmluZi0+ZW50aXR5Lm5h bWUsIGNhbS0+c3ViZGV2LmVudGl0eS5uYW1lLA0KPiA+ICsJCQlyZXQpOw0KPiA+ICsJCXJldHVy biByZXQ7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0ID0gdjRsMl9kZXZpY2VfcmVnaXN0ZXJf c3ViZGV2X25vZGVzKCZjYW0tPnY0bDJfZGV2KTsNCj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlk ZXZfZXJyKGRldiwgImZhaWxlZCB0byBpbml0aWFsaXplIHN1YmRldiBub2RlczolZFxuIiwgcmV0 KTsNCj4gPiArCQlyZXR1cm4gcmV0Ow0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldHVybiByZXQ7 DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgdjRsMl9hc3luY19ub3Rp Zmllcl9vcGVyYXRpb25zIG10a19jYW1fdjRsMl9hc3luY19vcHMgPSB7DQo+ID4gKwkuYm91bmQg PSBtdGtfY2FtX2Rldl9ub3RpZmllcl9ib3VuZCwNCj4gPiArCS51bmJpbmQgPSBtdGtfY2FtX2Rl dl9ub3RpZmllcl91bmJpbmQsDQo+ID4gKwkuY29tcGxldGUgPSBtdGtfY2FtX2Rldl9ub3RpZmll cl9jb21wbGV0ZSwNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgbXRrX2NhbV92NGwy X2FzeW5jX3JlZ2lzdGVyKHN0cnVjdCBtdGtfY2FtX2RldiAqY2FtKQ0KPiA+ICt7DQo+ID4gKwlz dHJ1Y3QgZGV2aWNlICpkZXYgPSBjYW0tPmRldjsNCj4gPiArCWludCByZXQ7DQo+ID4gKw0KPiA+ ICsJdjRsMl9hc3luY19ub3RpZmllcl9pbml0KCZjYW0tPm5vdGlmaWVyKTsNCj4gPiArCXJldCA9 IHY0bDJfYXN5bmNfbm90aWZpZXJfcGFyc2VfZndub2RlX2VuZHBvaW50cyhkZXYsDQo+ID4gKwkJ JmNhbS0+bm90aWZpZXIsIHNpemVvZihzdHJ1Y3QgdjRsMl9hc3luY19zdWJkZXYpLCBOVUxMKTsN Cj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgImZhaWxlZCB0byBwYXJzZSBm d25vZGUgZW5kcG9pbnRzOiVkXG4iLCByZXQpOw0KPiA+ICsJCXJldHVybiByZXQ7DQo+ID4gKwl9 DQo+ID4gKw0KPiA+ICsJY2FtLT5ub3RpZmllci5vcHMgPSAmbXRrX2NhbV92NGwyX2FzeW5jX29w czsNCj4gPiArCWRldl9kYmcoZGV2LCAibXRrX2NhbSB2NGwyX2FzeW5jX25vdGlmaWVyX3JlZ2lz dGVyXG4iKTsNCj4gPiArCXJldCA9IHY0bDJfYXN5bmNfbm90aWZpZXJfcmVnaXN0ZXIoJmNhbS0+ djRsMl9kZXYsICZjYW0tPm5vdGlmaWVyKTsNCj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlkZXZf ZXJyKGRldiwgImZhaWxlZCB0byByZWdpc3RlciBhc3luYyBub3RpZmllciA6ICVkXG4iLCByZXQp Ow0KPiA+ICsJCXY0bDJfYXN5bmNfbm90aWZpZXJfY2xlYW51cCgmY2FtLT5ub3RpZmllcik7DQo+ ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3Rh dGljIHZvaWQgbXRrX2NhbV92NGwyX2FzeW5jX3VucmVnaXN0ZXIoc3RydWN0IG10a19jYW1fZGV2 ICpjYW0pDQo+ID4gK3sNCj4gPiArCXY0bDJfYXN5bmNfbm90aWZpZXJfdW5yZWdpc3RlcigmY2Ft LT5ub3RpZmllcik7DQo+ID4gKwl2NGwyX2FzeW5jX25vdGlmaWVyX2NsZWFudXAoJmNhbS0+bm90 aWZpZXIpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IHY0bDJfaW9j dGxfb3BzIG10a19jYW1fdjRsMl92Y2FwX2lvY3RsX29wcyA9IHsNCj4gPiArCS52aWRpb2NfcXVl cnljYXAgPSBtdGtfY2FtX3ZpZGlvY19xdWVyeWNhcCwNCj4gPiArCS52aWRpb2NfZW51bV9mcmFt ZXNpemVzID0gbXRrX2NhbV92aWRpb2NfZW51bV9mcmFtZXNpemVzLA0KPiA+ICsJLnZpZGlvY19l bnVtX2ZtdF92aWRfY2FwID0gbXRrX2NhbV92aWRpb2NfZW51bV9mbXQsDQo+ID4gKwkudmlkaW9j X2dfZm10X3ZpZF9jYXBfbXBsYW5lID0gbXRrX2NhbV92aWRpb2NfZ19mbXQsDQo+ID4gKwkudmlk aW9jX3NfZm10X3ZpZF9jYXBfbXBsYW5lID0gbXRrX2NhbV92aWRpb2Nfc19mbXQsDQo+ID4gKwku dmlkaW9jX3RyeV9mbXRfdmlkX2NhcF9tcGxhbmUgPSBtdGtfY2FtX3ZpZGlvY190cnlfZm10LA0K PiA+ICsJLnZpZGlvY19yZXFidWZzID0gdmIyX2lvY3RsX3JlcWJ1ZnMsDQo+ID4gKwkudmlkaW9j X2NyZWF0ZV9idWZzID0gdmIyX2lvY3RsX2NyZWF0ZV9idWZzLA0KPiA+ICsJLnZpZGlvY19wcmVw YXJlX2J1ZiA9IHZiMl9pb2N0bF9wcmVwYXJlX2J1ZiwNCj4gPiArCS52aWRpb2NfcXVlcnlidWYg PSB2YjJfaW9jdGxfcXVlcnlidWYsDQo+ID4gKwkudmlkaW9jX3FidWYgPSB2YjJfaW9jdGxfcWJ1 ZiwNCj4gPiArCS52aWRpb2NfZHFidWYgPSB2YjJfaW9jdGxfZHFidWYsDQo+ID4gKwkudmlkaW9j X3N0cmVhbW9uID0gdmIyX2lvY3RsX3N0cmVhbW9uLA0KPiA+ICsJLnZpZGlvY19zdHJlYW1vZmYg PSB2YjJfaW9jdGxfc3RyZWFtb2ZmLA0KPiA+ICsJLnZpZGlvY19leHBidWYgPSB2YjJfaW9jdGxf ZXhwYnVmLA0KPiA+ICsJLnZpZGlvY19zdWJzY3JpYmVfZXZlbnQgPSB2NGwyX2N0cmxfc3Vic2Ny aWJlX2V2ZW50LA0KPiA+ICsJLnZpZGlvY191bnN1YnNjcmliZV9ldmVudCA9IHY0bDJfZXZlbnRf dW5zdWJzY3JpYmUsDQo+ID4gK307DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IHY0 bDJfaW9jdGxfb3BzIG10a19jYW1fdjRsMl9tZXRhX2NhcF9pb2N0bF9vcHMgPSB7DQo+ID4gKwku dmlkaW9jX3F1ZXJ5Y2FwID0gbXRrX2NhbV92aWRpb2NfcXVlcnljYXAsDQo+ID4gKwkudmlkaW9j X2VudW1fZm10X21ldGFfY2FwID0gbXRrX2NhbV92aWRpb2NfbWV0YV9lbnVtX2ZtdCwNCj4gPiAr CS52aWRpb2NfZ19mbXRfbWV0YV9jYXAgPSBtdGtfY2FtX3ZpZGlvY19nX21ldGFfZm10LA0KPiA+ ICsJLnZpZGlvY19zX2ZtdF9tZXRhX2NhcCA9IG10a19jYW1fdmlkaW9jX2dfbWV0YV9mbXQsDQo+ ID4gKwkudmlkaW9jX3RyeV9mbXRfbWV0YV9jYXAgPSBtdGtfY2FtX3ZpZGlvY19nX21ldGFfZm10 LA0KPiA+ICsJLnZpZGlvY19yZXFidWZzID0gdmIyX2lvY3RsX3JlcWJ1ZnMsDQo+ID4gKwkudmlk aW9jX2NyZWF0ZV9idWZzID0gdmIyX2lvY3RsX2NyZWF0ZV9idWZzLA0KPiA+ICsJLnZpZGlvY19w cmVwYXJlX2J1ZiA9IHZiMl9pb2N0bF9wcmVwYXJlX2J1ZiwNCj4gPiArCS52aWRpb2NfcXVlcnli dWYgPSB2YjJfaW9jdGxfcXVlcnlidWYsDQo+ID4gKwkudmlkaW9jX3FidWYgPSB2YjJfaW9jdGxf cWJ1ZiwNCj4gPiArCS52aWRpb2NfZHFidWYgPSB2YjJfaW9jdGxfZHFidWYsDQo+ID4gKwkudmlk aW9jX3N0cmVhbW9uID0gdmIyX2lvY3RsX3N0cmVhbW9uLA0KPiA+ICsJLnZpZGlvY19zdHJlYW1v ZmYgPSB2YjJfaW9jdGxfc3RyZWFtb2ZmLA0KPiA+ICsJLnZpZGlvY19leHBidWYgPSB2YjJfaW9j dGxfZXhwYnVmLA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCB2NGwy X2lvY3RsX29wcyBtdGtfY2FtX3Y0bDJfbWV0YV9vdXRfaW9jdGxfb3BzID0gew0KPiA+ICsJLnZp ZGlvY19xdWVyeWNhcCA9IG10a19jYW1fdmlkaW9jX3F1ZXJ5Y2FwLA0KPiA+ICsJLnZpZGlvY19l bnVtX2ZtdF9tZXRhX291dCA9IG10a19jYW1fdmlkaW9jX21ldGFfZW51bV9mbXQsDQo+ID4gKwku dmlkaW9jX2dfZm10X21ldGFfb3V0ID0gbXRrX2NhbV92aWRpb2NfZ19tZXRhX2ZtdCwNCj4gPiAr CS52aWRpb2Nfc19mbXRfbWV0YV9vdXQgPSBtdGtfY2FtX3ZpZGlvY19nX21ldGFfZm10LA0KPiA+ ICsJLnZpZGlvY190cnlfZm10X21ldGFfb3V0ID0gbXRrX2NhbV92aWRpb2NfZ19tZXRhX2ZtdCwN Cj4gPiArCS52aWRpb2NfcmVxYnVmcyA9IHZiMl9pb2N0bF9yZXFidWZzLA0KPiA+ICsJLnZpZGlv Y19jcmVhdGVfYnVmcyA9IHZiMl9pb2N0bF9jcmVhdGVfYnVmcywNCj4gPiArCS52aWRpb2NfcHJl cGFyZV9idWYgPSB2YjJfaW9jdGxfcHJlcGFyZV9idWYsDQo+ID4gKwkudmlkaW9jX3F1ZXJ5YnVm ID0gdmIyX2lvY3RsX3F1ZXJ5YnVmLA0KPiA+ICsJLnZpZGlvY19xYnVmID0gdmIyX2lvY3RsX3Fi dWYsDQo+ID4gKwkudmlkaW9jX2RxYnVmID0gdmIyX2lvY3RsX2RxYnVmLA0KPiA+ICsJLnZpZGlv Y19zdHJlYW1vbiA9IHZiMl9pb2N0bF9zdHJlYW1vbiwNCj4gPiArCS52aWRpb2Nfc3RyZWFtb2Zm ID0gdmIyX2lvY3RsX3N0cmVhbW9mZiwNCj4gPiArCS52aWRpb2NfZXhwYnVmID0gdmIyX2lvY3Rs X2V4cGJ1ZiwNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgdjRsMl9m b3JtYXQgbWV0YV9mbXRzW10gPSB7DQo+ID4gKwl7DQo+ID4gKwkJLmZtdC5tZXRhID0gew0KPiA+ ICsJCQkuZGF0YWZvcm1hdCA9IFY0TDJfTUVUQV9GTVRfTVRJU1BfUEFSQU1TLA0KPiA+ICsJCQku YnVmZmVyc2l6ZSA9IDUxMiAqIFNaXzFLLA0KPiA+ICsJCX0sDQo+ID4gKwl9LA0KPiA+ICsJew0K PiA+ICsJCS5mbXQubWV0YSA9IHsNCj4gPiArCQkJLmRhdGFmb3JtYXQgPSBWNEwyX01FVEFfRk1U X01USVNQXzNBLA0KPiA+ICsJCQkuYnVmZmVyc2l6ZSA9IDEyMDAgKiBTWl8xSywNCj4gPiArCQl9 LA0KPiA+ICsJfSwNCj4gPiArCXsNCj4gPiArCQkuZm10Lm1ldGEgPSB7DQo+ID4gKwkJCS5kYXRh Zm9ybWF0ID0gVjRMMl9NRVRBX0ZNVF9NVElTUF9BRiwNCj4gPiArCQkJLmJ1ZmZlcnNpemUgPSA2 NDAgKiBTWl8xSywNCj4gPiArCQl9LA0KPiA+ICsJfSwNCj4gPiArCXsNCj4gPiArCQkuZm10Lm1l dGEgPSB7DQo+ID4gKwkJCS5kYXRhZm9ybWF0ID0gVjRMMl9NRVRBX0ZNVF9NVElTUF9MQ1MsDQo+ ID4gKwkJCS5idWZmZXJzaXplID0gMjg4ICogU1pfMUssDQo+ID4gKwkJfSwNCj4gPiArCX0sDQo+ ID4gKwl7DQo+ID4gKwkJLmZtdC5tZXRhID0gew0KPiA+ICsJCQkuZGF0YWZvcm1hdCA9IFY0TDJf TUVUQV9GTVRfTVRJU1BfTE1WLA0KPiA+ICsJCQkuYnVmZmVyc2l6ZSA9IDI1NiwNCj4gPiArCQl9 LA0KPiA+ICsJfSwNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgdjRs Ml9mb3JtYXQgc3RyZWFtX291dF9mbXRzW10gPSB7DQo+ID4gKwkvKiBUaGlzIGlzIGEgZGVmYXVs dCBpbWFnZSBmb3JtYXQgKi8NCj4gPiArCXsNCj4gPiArCQkuZm10LnBpeF9tcCA9IHsNCj4gPiAr CQkJLndpZHRoID0gSU1HX01BWF9XSURUSCwNCj4gPiArCQkJLmhlaWdodCA9IElNR19NQVhfSEVJ R0hULA0KPiA+ICsJCQkucGl4ZWxmb3JtYXQgPSBWNEwyX1BJWF9GTVRfTVRJU1BfU0JHR1IxMCwN Cj4gPiArCQl9LA0KPiA+ICsJfSwNCj4gPiArCXsNCj4gPiArCQkuZm10LnBpeF9tcCA9IHsNCj4g PiArCQkJLndpZHRoID0gSU1HX01BWF9XSURUSCwNCj4gPiArCQkJLmhlaWdodCA9IElNR19NQVhf SEVJR0hULA0KPiA+ICsJCQkucGl4ZWxmb3JtYXQgPSBWNEwyX1BJWF9GTVRfTVRJU1BfU0JHR1I4 LA0KPiA+ICsJCX0sDQo+ID4gKwl9LA0KPiA+ICsJew0KPiA+ICsJCS5mbXQucGl4X21wID0gew0K PiA+ICsJCQkud2lkdGggPSBJTUdfTUFYX1dJRFRILA0KPiA+ICsJCQkuaGVpZ2h0ID0gSU1HX01B WF9IRUlHSFQsDQo+ID4gKwkJCS5waXhlbGZvcm1hdCA9IFY0TDJfUElYX0ZNVF9NVElTUF9TQkdH UjEyLA0KPiA+ICsJCX0sDQo+ID4gKwl9LA0KPiA+ICsJew0KPiA+ICsJCS5mbXQucGl4X21wID0g ew0KPiA+ICsJCQkud2lkdGggPSBJTUdfTUFYX1dJRFRILA0KPiA+ICsJCQkuaGVpZ2h0ID0gSU1H X01BWF9IRUlHSFQsDQo+ID4gKwkJCS5waXhlbGZvcm1hdCA9IFY0TDJfUElYX0ZNVF9NVElTUF9T QkdHUjE0LA0KPiA+ICsJCX0sDQo+ID4gKwl9LA0KPiA+ICsJew0KPiA+ICsJCS5mbXQucGl4X21w ID0gew0KPiA+ICsJCQkud2lkdGggPSBJTUdfTUFYX1dJRFRILA0KPiA+ICsJCQkuaGVpZ2h0ID0g SU1HX01BWF9IRUlHSFQsDQo+ID4gKwkJCS5waXhlbGZvcm1hdCA9IFY0TDJfUElYX0ZNVF9NVElT UF9TR0JSRzgsDQo+ID4gKwkJfSwNCj4gPiArCX0sDQo+ID4gKwl7DQo+ID4gKwkJLmZtdC5waXhf bXAgPSB7DQo+ID4gKwkJCS53aWR0aCA9IElNR19NQVhfV0lEVEgsDQo+ID4gKwkJCS5oZWlnaHQg PSBJTUdfTUFYX0hFSUdIVCwNCj4gPiArCQkJLnBpeGVsZm9ybWF0ID0gVjRMMl9QSVhfRk1UX01U SVNQX1NHQlJHMTAsDQo+ID4gKwkJfSwNCj4gPiArCX0sDQo+ID4gKwl7DQo+ID4gKwkJLmZtdC5w aXhfbXAgPSB7DQo+ID4gKwkJCS53aWR0aCA9IElNR19NQVhfV0lEVEgsDQo+ID4gKwkJCS5oZWln aHQgPSBJTUdfTUFYX0hFSUdIVCwNCj4gPiArCQkJLnBpeGVsZm9ybWF0ID0gVjRMMl9QSVhfRk1U X01USVNQX1NHQlJHMTIsDQo+ID4gKwkJfSwNCj4gPiArCX0sDQo+ID4gKwl7DQo+ID4gKwkJLmZt dC5waXhfbXAgPSB7DQo+ID4gKwkJCS53aWR0aCA9IElNR19NQVhfV0lEVEgsDQo+ID4gKwkJCS5o ZWlnaHQgPSBJTUdfTUFYX0hFSUdIVCwNCj4gPiArCQkJLnBpeGVsZm9ybWF0ID0gVjRMMl9QSVhf Rk1UX01USVNQX1NHQlJHMTQsDQo+ID4gKwkJfSwNCj4gPiArCX0sDQo+ID4gKwl7DQo+ID4gKwkJ LmZtdC5waXhfbXAgPSB7DQo+ID4gKwkJCS53aWR0aCA9IElNR19NQVhfV0lEVEgsDQo+ID4gKwkJ CS5oZWlnaHQgPSBJTUdfTUFYX0hFSUdIVCwNCj4gPiArCQkJLnBpeGVsZm9ybWF0ID0gVjRMMl9Q SVhfRk1UX01USVNQX1NHUkJHOCwNCj4gPiArCQl9LA0KPiA+ICsJfSwNCj4gPiArCXsNCj4gPiAr CQkuZm10LnBpeF9tcCA9IHsNCj4gPiArCQkJLndpZHRoID0gSU1HX01BWF9XSURUSCwNCj4gPiAr CQkJLmhlaWdodCA9IElNR19NQVhfSEVJR0hULA0KPiA+ICsJCQkucGl4ZWxmb3JtYXQgPSBWNEwy X1BJWF9GTVRfTVRJU1BfU0dSQkcxMCwNCj4gPiArCQl9LA0KPiA+ICsJfSwNCj4gPiArCXsNCj4g PiArCQkuZm10LnBpeF9tcCA9IHsNCj4gPiArCQkJLndpZHRoID0gSU1HX01BWF9XSURUSCwNCj4g PiArCQkJLmhlaWdodCA9IElNR19NQVhfSEVJR0hULA0KPiA+ICsJCQkucGl4ZWxmb3JtYXQgPSBW NEwyX1BJWF9GTVRfTVRJU1BfU0dSQkcxMiwNCj4gPiArCQl9LA0KPiA+ICsJfSwNCj4gPiArCXsN Cj4gPiArCQkuZm10LnBpeF9tcCA9IHsNCj4gPiArCQkJLndpZHRoID0gSU1HX01BWF9XSURUSCwN Cj4gPiArCQkJLmhlaWdodCA9IElNR19NQVhfSEVJR0hULA0KPiA+ICsJCQkucGl4ZWxmb3JtYXQg PSBWNEwyX1BJWF9GTVRfTVRJU1BfU0dSQkcxNCwNCj4gPiArCQl9LA0KPiA+ICsJfSwNCj4gPiAr CXsNCj4gPiArCQkuZm10LnBpeF9tcCA9IHsNCj4gPiArCQkJLndpZHRoID0gSU1HX01BWF9XSURU SCwNCj4gPiArCQkJLmhlaWdodCA9IElNR19NQVhfSEVJR0hULA0KPiA+ICsJCQkucGl4ZWxmb3Jt YXQgPSBWNEwyX1BJWF9GTVRfTVRJU1BfU1JHR0I4LA0KPiA+ICsJCX0sDQo+ID4gKwl9LA0KPiA+ ICsJew0KPiA+ICsJCS5mbXQucGl4X21wID0gew0KPiA+ICsJCQkud2lkdGggPSBJTUdfTUFYX1dJ RFRILA0KPiA+ICsJCQkuaGVpZ2h0ID0gSU1HX01BWF9IRUlHSFQsDQo+ID4gKwkJCS5waXhlbGZv cm1hdCA9IFY0TDJfUElYX0ZNVF9NVElTUF9TUkdHQjEwLA0KPiA+ICsJCX0sDQo+ID4gKwl9LA0K PiA+ICsJew0KPiA+ICsJCS5mbXQucGl4X21wID0gew0KPiA+ICsJCQkud2lkdGggPSBJTUdfTUFY X1dJRFRILA0KPiA+ICsJCQkuaGVpZ2h0ID0gSU1HX01BWF9IRUlHSFQsDQo+ID4gKwkJCS5waXhl bGZvcm1hdCA9IFY0TDJfUElYX0ZNVF9NVElTUF9TUkdHQjEyLA0KPiA+ICsJCX0sDQo+ID4gKwl9 LA0KPiA+ICsJew0KPiA+ICsJCS5mbXQucGl4X21wID0gew0KPiA+ICsJCQkud2lkdGggPSBJTUdf TUFYX1dJRFRILA0KPiA+ICsJCQkuaGVpZ2h0ID0gSU1HX01BWF9IRUlHSFQsDQo+ID4gKwkJCS5w aXhlbGZvcm1hdCA9IFY0TDJfUElYX0ZNVF9NVElTUF9TUkdHQjE0LA0KPiA+ICsJCX0sDQo+ID4g Kwl9LA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCB2NGwyX2Zvcm1h dCBiaW5fb3V0X2ZtdHNbXSA9IHsNCj4gPiArCXsNCj4gPiArCQkuZm10LnBpeF9tcCA9IHsNCj4g PiArCQkJLndpZHRoID0gSU1HX01BWF9XSURUSCwNCj4gPiArCQkJLmhlaWdodCA9IElNR19NQVhf SEVJR0hULA0KPiA+ICsJCQkucGl4ZWxmb3JtYXQgPSBWNEwyX1BJWF9GTVRfTVRJU1BfU0JHR1I4 RiwNCj4gPiArCQl9LA0KPiA+ICsJfSwNCj4gPiArCXsNCj4gPiArCQkuZm10LnBpeF9tcCA9IHsN Cj4gPiArCQkJLndpZHRoID0gSU1HX01BWF9XSURUSCwNCj4gPiArCQkJLmhlaWdodCA9IElNR19N QVhfSEVJR0hULA0KPiA+ICsJCQkucGl4ZWxmb3JtYXQgPSBWNEwyX1BJWF9GTVRfTVRJU1BfU0JH R1IxMEYsDQo+ID4gKwkJfSwNCj4gPiArCX0sDQo+ID4gKwl7DQo+ID4gKwkJLmZtdC5waXhfbXAg PSB7DQo+ID4gKwkJCS53aWR0aCA9IElNR19NQVhfV0lEVEgsDQo+ID4gKwkJCS5oZWlnaHQgPSBJ TUdfTUFYX0hFSUdIVCwNCj4gPiArCQkJLnBpeGVsZm9ybWF0ID0gVjRMMl9QSVhfRk1UX01USVNQ X1NCR0dSMTJGLA0KPiA+ICsJCX0sDQo+ID4gKwl9LA0KPiA+ICsJew0KPiA+ICsJCS5mbXQucGl4 X21wID0gew0KPiA+ICsJCQkud2lkdGggPSBJTUdfTUFYX1dJRFRILA0KPiA+ICsJCQkuaGVpZ2h0 ID0gSU1HX01BWF9IRUlHSFQsDQo+ID4gKwkJCS5waXhlbGZvcm1hdCA9IFY0TDJfUElYX0ZNVF9N VElTUF9TQkdHUjE0RiwNCj4gPiArCQl9LA0KPiA+ICsJfSwNCj4gPiArCXsNCj4gPiArCQkuZm10 LnBpeF9tcCA9IHsNCj4gPiArCQkJLndpZHRoID0gSU1HX01BWF9XSURUSCwNCj4gPiArCQkJLmhl aWdodCA9IElNR19NQVhfSEVJR0hULA0KPiA+ICsJCQkucGl4ZWxmb3JtYXQgPSBWNEwyX1BJWF9G TVRfTVRJU1BfU0dCUkc4RiwNCj4gPiArCQl9LA0KPiA+ICsJfSwNCj4gPiArCXsNCj4gPiArCQku Zm10LnBpeF9tcCA9IHsNCj4gPiArCQkJLndpZHRoID0gSU1HX01BWF9XSURUSCwNCj4gPiArCQkJ LmhlaWdodCA9IElNR19NQVhfSEVJR0hULA0KPiA+ICsJCQkucGl4ZWxmb3JtYXQgPSBWNEwyX1BJ WF9GTVRfTVRJU1BfU0dCUkcxMEYsDQo+ID4gKwkJfSwNCj4gPiArCX0sDQo+ID4gKwl7DQo+ID4g KwkJLmZtdC5waXhfbXAgPSB7DQo+ID4gKwkJCS53aWR0aCA9IElNR19NQVhfV0lEVEgsDQo+ID4g KwkJCS5oZWlnaHQgPSBJTUdfTUFYX0hFSUdIVCwNCj4gPiArCQkJLnBpeGVsZm9ybWF0ID0gVjRM Ml9QSVhfRk1UX01USVNQX1NHQlJHMTJGLA0KPiA+ICsJCX0sDQo+ID4gKwl9LA0KPiA+ICsJew0K PiA+ICsJCS5mbXQucGl4X21wID0gew0KPiA+ICsJCQkud2lkdGggPSBJTUdfTUFYX1dJRFRILA0K PiA+ICsJCQkuaGVpZ2h0ID0gSU1HX01BWF9IRUlHSFQsDQo+ID4gKwkJCS5waXhlbGZvcm1hdCA9 IFY0TDJfUElYX0ZNVF9NVElTUF9TR0JSRzE0RiwNCj4gPiArCQl9LA0KPiA+ICsJfSwNCj4gPiAr CXsNCj4gPiArCQkuZm10LnBpeF9tcCA9IHsNCj4gPiArCQkJLndpZHRoID0gSU1HX01BWF9XSURU SCwNCj4gPiArCQkJLmhlaWdodCA9IElNR19NQVhfSEVJR0hULA0KPiA+ICsJCQkucGl4ZWxmb3Jt YXQgPSBWNEwyX1BJWF9GTVRfTVRJU1BfU0dSQkc4RiwNCj4gPiArCQl9LA0KPiA+ICsJfSwNCj4g PiArCXsNCj4gPiArCQkuZm10LnBpeF9tcCA9IHsNCj4gPiArCQkJLndpZHRoID0gSU1HX01BWF9X SURUSCwNCj4gPiArCQkJLmhlaWdodCA9IElNR19NQVhfSEVJR0hULA0KPiA+ICsJCQkucGl4ZWxm b3JtYXQgPSBWNEwyX1BJWF9GTVRfTVRJU1BfU0dSQkcxMEYsDQo+ID4gKwkJfSwNCj4gPiArCX0s DQo+ID4gKwl7DQo+ID4gKwkJLmZtdC5waXhfbXAgPSB7DQo+ID4gKwkJCS53aWR0aCA9IElNR19N QVhfV0lEVEgsDQo+ID4gKwkJCS5oZWlnaHQgPSBJTUdfTUFYX0hFSUdIVCwNCj4gPiArCQkJLnBp eGVsZm9ybWF0ID0gVjRMMl9QSVhfRk1UX01USVNQX1NHUkJHMTJGLA0KPiA+ICsJCX0sDQo+ID4g Kwl9LA0KPiA+ICsJew0KPiA+ICsJCS5mbXQucGl4X21wID0gew0KPiA+ICsJCQkud2lkdGggPSBJ TUdfTUFYX1dJRFRILA0KPiA+ICsJCQkuaGVpZ2h0ID0gSU1HX01BWF9IRUlHSFQsDQo+ID4gKwkJ CS5waXhlbGZvcm1hdCA9IFY0TDJfUElYX0ZNVF9NVElTUF9TR1JCRzE0RiwNCj4gPiArCQl9LA0K PiA+ICsJfSwNCj4gPiArCXsNCj4gPiArCQkuZm10LnBpeF9tcCA9IHsNCj4gPiArCQkJLndpZHRo ID0gSU1HX01BWF9XSURUSCwNCj4gPiArCQkJLmhlaWdodCA9IElNR19NQVhfSEVJR0hULA0KPiA+ ICsJCQkucGl4ZWxmb3JtYXQgPSBWNEwyX1BJWF9GTVRfTVRJU1BfU1JHR0I4RiwNCj4gPiArCQl9 LA0KPiA+ICsJfSwNCj4gPiArCXsNCj4gPiArCQkuZm10LnBpeF9tcCA9IHsNCj4gPiArCQkJLndp ZHRoID0gSU1HX01BWF9XSURUSCwNCj4gPiArCQkJLmhlaWdodCA9IElNR19NQVhfSEVJR0hULA0K PiA+ICsJCQkucGl4ZWxmb3JtYXQgPSBWNEwyX1BJWF9GTVRfTVRJU1BfU1JHR0IxMEYsDQo+ID4g KwkJfSwNCj4gPiArCX0sDQo+ID4gKwl7DQo+ID4gKwkJLmZtdC5waXhfbXAgPSB7DQo+ID4gKwkJ CS53aWR0aCA9IElNR19NQVhfV0lEVEgsDQo+ID4gKwkJCS5oZWlnaHQgPSBJTUdfTUFYX0hFSUdI VCwNCj4gPiArCQkJLnBpeGVsZm9ybWF0ID0gVjRMMl9QSVhfRk1UX01USVNQX1NSR0dCMTJGLA0K PiA+ICsJCX0sDQo+ID4gKwl9LA0KPiA+ICsJew0KPiA+ICsJCS5mbXQucGl4X21wID0gew0KPiA+ ICsJCQkud2lkdGggPSBJTUdfTUFYX1dJRFRILA0KPiA+ICsJCQkuaGVpZ2h0ID0gSU1HX01BWF9I RUlHSFQsDQo+ID4gKwkJCS5waXhlbGZvcm1hdCA9IFY0TDJfUElYX0ZNVF9NVElTUF9TUkdHQjE0 RiwNCj4gPiArCQl9LA0KPiA+ICsJfSwNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBjb25z dCBzdHJ1Y3QNCj4gPiArbXRrX2NhbV9kZXZfbm9kZV9kZXNjIG91dHB1dF9xdWV1ZXNbXSA9IHsN Cj4gPiArCXsNCj4gPiArCQkuaWQgPSBNVEtfQ0FNX1AxX01FVEFfSU5fMCwNCj4gPiArCQkubmFt ZSA9ICJtZXRhIGlucHV0IiwNCj4gPiArCQkuY2FwID0gVjRMMl9DQVBfTUVUQV9PVVRQVVQsDQo+ ID4gKwkJLmJ1Zl90eXBlID0gVjRMMl9CVUZfVFlQRV9NRVRBX09VVFBVVCwNCj4gPiArCQkubGlu a19mbGFncyA9IDAsDQo+ID4gKwkJLmltYWdlID0gZmFsc2UsDQo+ID4gKwkJLnNtZW1fYWxsb2Mg PSB0cnVlLA0KPiA+ICsJCS5mbXRzID0gbWV0YV9mbXRzLA0KPiA+ICsJCS5kZWZhdWx0X2ZtdF9p ZHggPSAwLA0KPiA+ICsJCS5tYXhfYnVmX2NvdW50ID0gMTAsDQo+ID4gKwkJLmlvY3RsX29wcyA9 ICZtdGtfY2FtX3Y0bDJfbWV0YV9vdXRfaW9jdGxfb3BzLA0KPiA+ICsJfSwNCj4gPiArfTsNCj4g PiArDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QNCj4gPiArbXRrX2NhbV9kZXZfbm9kZV9kZXNj IGNhcHR1cmVfcXVldWVzW10gPSB7DQo+ID4gKwl7DQo+ID4gKwkJLmlkID0gTVRLX0NBTV9QMV9N QUlOX1NUUkVBTV9PVVQsDQo+ID4gKwkJLm5hbWUgPSAibWFpbiBzdHJlYW0iLA0KPiA+ICsJCS5j YXAgPSBWNEwyX0NBUF9WSURFT19DQVBUVVJFX01QTEFORSwNCj4gPiArCQkuYnVmX3R5cGUgPSBW NEwyX0JVRl9UWVBFX1ZJREVPX0NBUFRVUkVfTVBMQU5FLA0KPiA+ICsJCS5saW5rX2ZsYWdzID0g TUVESUFfTE5LX0ZMX0lNTVVUQUJMRSB8IE1FRElBX0xOS19GTF9FTkFCTEVELA0KPiA+ICsJCS5p bWFnZSA9IHRydWUsDQo+ID4gKwkJLnNtZW1fYWxsb2MgPSBmYWxzZSwNCj4gPiArCQkuZG1hX3Bv cnQgPSBSX0lNR08sDQo+ID4gKwkJLmZtdHMgPSBzdHJlYW1fb3V0X2ZtdHMsDQo+ID4gKwkJLm51 bV9mbXRzID0gQVJSQVlfU0laRShzdHJlYW1fb3V0X2ZtdHMpLA0KPiA+ICsJCS5kZWZhdWx0X2Zt dF9pZHggPSAwLA0KPiA+ICsJCS5pb2N0bF9vcHMgPSAmbXRrX2NhbV92NGwyX3ZjYXBfaW9jdGxf b3BzLA0KPiA+ICsJCS5mcm1zaXplcyA9ICYoc3RydWN0IHY0bDJfZnJtc2l6ZWVudW0pIHsNCj4g PiArCQkJLmluZGV4ID0gMCwNCj4gPiArCQkJLnR5cGUgPSBWNEwyX0ZSTVNJWkVfVFlQRV9DT05U SU5VT1VTLA0KPiA+ICsJCQkuc3RlcHdpc2UgPSB7DQo+ID4gKwkJCQkubWF4X3dpZHRoID0gSU1H X01BWF9XSURUSCwNCj4gPiArCQkJCS5taW5fd2lkdGggPSBJTUdfTUlOX1dJRFRILA0KPiA+ICsJ CQkJLm1heF9oZWlnaHQgPSBJTUdfTUFYX0hFSUdIVCwNCj4gPiArCQkJCS5taW5faGVpZ2h0ID0g SU1HX01JTl9IRUlHSFQsDQo+ID4gKwkJCQkuc3RlcF9oZWlnaHQgPSAxLA0KPiA+ICsJCQkJLnN0 ZXBfd2lkdGggPSAxLA0KPiA+ICsJCQl9LA0KPiA+ICsJCX0sDQo+ID4gKwl9LA0KPiA+ICsJew0K PiA+ICsJCS5pZCA9IE1US19DQU1fUDFfUEFDS0VEX0JJTl9PVVQsDQo+ID4gKwkJLm5hbWUgPSAi cGFja2VkIG91dCIsDQo+ID4gKwkJLmNhcCA9IFY0TDJfQ0FQX1ZJREVPX0NBUFRVUkVfTVBMQU5F LA0KPiA+ICsJCS5idWZfdHlwZSA9IFY0TDJfQlVGX1RZUEVfVklERU9fQ0FQVFVSRV9NUExBTkUs DQo+ID4gKwkJLmxpbmtfZmxhZ3MgPSAwLA0KPiA+ICsJCS5pbWFnZSA9IHRydWUsDQo+ID4gKwkJ LnNtZW1fYWxsb2MgPSBmYWxzZSwNCj4gPiArCQkuZG1hX3BvcnQgPSBSX1JSWk8sDQo+ID4gKwkJ LmZtdHMgPSBiaW5fb3V0X2ZtdHMsDQo+ID4gKwkJLm51bV9mbXRzID0gQVJSQVlfU0laRShiaW5f b3V0X2ZtdHMpLA0KPiA+ICsJCS5kZWZhdWx0X2ZtdF9pZHggPSAwLA0KPiA+ICsJCS5pb2N0bF9v cHMgPSAmbXRrX2NhbV92NGwyX3ZjYXBfaW9jdGxfb3BzLA0KPiA+ICsJCS5mcm1zaXplcyA9ICYo c3RydWN0IHY0bDJfZnJtc2l6ZWVudW0pIHsNCj4gPiArCQkJLmluZGV4ID0gMCwNCj4gPiArCQkJ LnR5cGUgPSBWNEwyX0ZSTVNJWkVfVFlQRV9DT05USU5VT1VTLA0KPiA+ICsJCQkuc3RlcHdpc2Ug PSB7DQo+ID4gKwkJCQkubWF4X3dpZHRoID0gSU1HX01BWF9XSURUSCwNCj4gPiArCQkJCS5taW5f d2lkdGggPSBJTUdfTUlOX1dJRFRILA0KPiA+ICsJCQkJLm1heF9oZWlnaHQgPSBJTUdfTUFYX0hF SUdIVCwNCj4gPiArCQkJCS5taW5faGVpZ2h0ID0gSU1HX01JTl9IRUlHSFQsDQo+ID4gKwkJCQku c3RlcF9oZWlnaHQgPSAxLA0KPiA+ICsJCQkJLnN0ZXBfd2lkdGggPSAxLA0KPiA+ICsJCQl9LA0K PiA+ICsJCX0sDQo+ID4gKwl9LA0KPiA+ICsJew0KPiA+ICsJCS5pZCA9IE1US19DQU1fUDFfTUVU QV9PVVRfMCwNCj4gPiArCQkubmFtZSA9ICJwYXJ0aWFsIG1ldGEgMCIsDQo+ID4gKwkJLmNhcCA9 IFY0TDJfQ0FQX01FVEFfQ0FQVFVSRSwNCj4gPiArCQkuYnVmX3R5cGUgPSBWNEwyX0JVRl9UWVBF X01FVEFfQ0FQVFVSRSwNCj4gPiArCQkubGlua19mbGFncyA9IDAsDQo+ID4gKwkJLmltYWdlID0g ZmFsc2UsDQo+ID4gKwkJLnNtZW1fYWxsb2MgPSBmYWxzZSwNCj4gPiArCQkuZG1hX3BvcnQgPSBS X0FBTyB8IFJfRkxLTyB8IFJfUFNPLA0KPiA+ICsJCS5mbXRzID0gbWV0YV9mbXRzLA0KPiA+ICsJ CS5kZWZhdWx0X2ZtdF9pZHggPSAxLA0KPiA+ICsJCS5tYXhfYnVmX2NvdW50ID0gNSwNCj4gPiAr CQkuaW9jdGxfb3BzID0gJm10a19jYW1fdjRsMl9tZXRhX2NhcF9pb2N0bF9vcHMsDQo+ID4gKwl9 LA0KPiA+ICsJew0KPiA+ICsJCS5pZCA9IE1US19DQU1fUDFfTUVUQV9PVVRfMSwNCj4gPiArCQku bmFtZSA9ICJwYXJ0aWFsIG1ldGEgMSIsDQo+ID4gKwkJLmNhcCA9IFY0TDJfQ0FQX01FVEFfQ0FQ VFVSRSwNCj4gPiArCQkuYnVmX3R5cGUgPSBWNEwyX0JVRl9UWVBFX01FVEFfQ0FQVFVSRSwNCj4g PiArCQkubGlua19mbGFncyA9IDAsDQo+ID4gKwkJLmltYWdlID0gZmFsc2UsDQo+ID4gKwkJLnNt ZW1fYWxsb2MgPSBmYWxzZSwNCj4gPiArCQkuZG1hX3BvcnQgPSBSX0FGTywNCj4gPiArCQkuZm10 cyA9IG1ldGFfZm10cywNCj4gPiArCQkuZGVmYXVsdF9mbXRfaWR4ID0gMiwNCj4gPiArCQkubWF4 X2J1Zl9jb3VudCA9IDUsDQo+ID4gKwkJLmlvY3RsX29wcyA9ICZtdGtfY2FtX3Y0bDJfbWV0YV9j YXBfaW9jdGxfb3BzLA0KPiA+ICsJfSwNCj4gPiArCXsNCj4gPiArCQkuaWQgPSBNVEtfQ0FNX1Ax X01FVEFfT1VUXzIsDQo+ID4gKwkJLm5hbWUgPSAicGFydGlhbCBtZXRhIDIiLA0KPiA+ICsJCS5j YXAgPSBWNEwyX0NBUF9NRVRBX0NBUFRVUkUsDQo+ID4gKwkJLmJ1Zl90eXBlID0gVjRMMl9CVUZf VFlQRV9NRVRBX0NBUFRVUkUsDQo+ID4gKwkJLmxpbmtfZmxhZ3MgPSAwLA0KPiA+ICsJCS5pbWFn ZSA9IGZhbHNlLA0KPiA+ICsJCS5zbWVtX2FsbG9jID0gZmFsc2UsDQo+ID4gKwkJLmRtYV9wb3J0 ID0gUl9MQ1NPLA0KPiA+ICsJCS5mbXRzID0gbWV0YV9mbXRzLA0KPiA+ICsJCS5kZWZhdWx0X2Zt dF9pZHggPSAzLA0KPiA+ICsJCS5tYXhfYnVmX2NvdW50ID0gMTAsDQo+ID4gKwkJLmlvY3RsX29w cyA9ICZtdGtfY2FtX3Y0bDJfbWV0YV9jYXBfaW9jdGxfb3BzLA0KPiA+ICsJfSwNCj4gPiArCXsN Cj4gPiArCQkuaWQgPSBNVEtfQ0FNX1AxX01FVEFfT1VUXzMsDQo+ID4gKwkJLm5hbWUgPSAicGFy dGlhbCBtZXRhIDMiLA0KPiA+ICsJCS5jYXAgPSBWNEwyX0NBUF9NRVRBX0NBUFRVUkUsDQo+ID4g KwkJLmJ1Zl90eXBlID0gVjRMMl9CVUZfVFlQRV9NRVRBX0NBUFRVUkUsDQo+ID4gKwkJLmxpbmtf ZmxhZ3MgPSAwLA0KPiA+ICsJCS5pbWFnZSA9IGZhbHNlLA0KPiA+ICsJCS5zbWVtX2FsbG9jID0g ZmFsc2UsDQo+ID4gKwkJLmRtYV9wb3J0ID0gUl9MTVZPLA0KPiA+ICsJCS5mbXRzID0gbWV0YV9m bXRzLA0KPiA+ICsJCS5kZWZhdWx0X2ZtdF9pZHggPSA0LA0KPiA+ICsJCS5tYXhfYnVmX2NvdW50 ID0gMTAsDQo+ID4gKwkJLmlvY3RsX29wcyA9ICZtdGtfY2FtX3Y0bDJfbWV0YV9jYXBfaW9jdGxf b3BzLA0KPiA+ICsJfSwNCj4gPiArfTsNCj4gPiArDQo+ID4gKy8qIFRoZSBoZWxwZXIgdG8gY29u ZmlndXJlIHRoZSBkZXZpY2UgY29udGV4dCAqLw0KPiA+ICtzdGF0aWMgdm9pZCBtdGtfY2FtX2Rl dl9xdWV1ZV9zZXR1cChzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSkNCj4gPiArew0KPiA+ICsJdW5z aWduZWQgaW50IG5vZGVfaWR4Ow0KPiA+ICsJaW50IGk7DQo+ID4gKw0KPiA+ICsJbm9kZV9pZHgg PSAwOw0KPiA+ICsJLyogU2V0dXAgdGhlIG91dHB1dCBxdWV1ZSAqLw0KPiA+ICsJZm9yIChpID0g MDsgaSA8IEFSUkFZX1NJWkUob3V0cHV0X3F1ZXVlcyk7IGkrKykNCj4gPiArCQljYW0tPnZkZXZf bm9kZXNbbm9kZV9pZHgrK10uZGVzYyA9IG91dHB1dF9xdWV1ZXNbaV07DQo+ID4gKw0KPiA+ICsJ LyogU2V0dXAgdGhlIGNhcHR1cmUgcXVldWUgKi8NCj4gPiArCWZvciAoaSA9IDA7IGkgPCBBUlJB WV9TSVpFKGNhcHR1cmVfcXVldWVzKTsgaSsrKQ0KPiA+ICsJCWNhbS0+dmRldl9ub2Rlc1tub2Rl X2lkeCsrXS5kZXNjID0gY2FwdHVyZV9xdWV1ZXNbaV07DQo+ID4gK30NCj4gPiArDQo+ID4gK2lu dCBtdGtfY2FtX2Rldl9pbml0KHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYsDQo+ID4gKwkJ ICAgICBzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSkNCj4gPiArew0KPiA+ICsJaW50IHJldDsNCj4g PiArDQo+ID4gKwljYW0tPmRldiA9ICZwZGV2LT5kZXY7DQo+ID4gKwltdGtfY2FtX2Rldl9xdWV1 ZV9zZXR1cChjYW0pOw0KPiA+ICsNCj4gPiArCXNwaW5fbG9ja19pbml0KCZjYW0tPnBlbmRpbmdf am9iX2xvY2spOw0KPiA+ICsJc3Bpbl9sb2NrX2luaXQoJmNhbS0+cnVubmluZ19qb2JfbG9jayk7 DQo+ID4gKwlJTklUX0xJU1RfSEVBRCgmY2FtLT5wZW5kaW5nX2pvYl9saXN0KTsNCj4gPiArCUlO SVRfTElTVF9IRUFEKCZjYW0tPnJ1bm5pbmdfam9iX2xpc3QpOw0KPiA+ICsJbXV0ZXhfaW5pdCgm Y2FtLT5vcF9sb2NrKTsNCj4gPiArDQo+ID4gKwkvKiB2NGwyIHN1Yi1kZXZpY2UgcmVnaXN0cmF0 aW9uICovDQo+ID4gKwlyZXQgPSBtdGtfY2FtX3Y0bDJfcmVnaXN0ZXIoY2FtKTsNCj4gPiArCWlm IChyZXQpDQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArDQo+ID4gKwlyZXQgPSBtdGtfY2FtX3Y0 bDJfYXN5bmNfcmVnaXN0ZXIoY2FtKTsNCj4gPiArCWlmIChyZXQpDQo+ID4gKwkJZ290byBmYWls X3Y0bDJfdW5yZWc7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gKw0KPiA+ICtmYWlsX3Y0 bDJfdW5yZWc6DQo+ID4gKwltdXRleF9kZXN0cm95KCZjYW0tPm9wX2xvY2spOw0KPiA+ICsJbXRr X2NhbV92NGwyX3VucmVnaXN0ZXIoY2FtKTsNCj4gPiArDQo+ID4gKwlyZXR1cm4gcmV0Ow0KPiA+ ICt9DQo+ID4gKw0KPiA+ICt2b2lkIG10a19jYW1fZGV2X2NsZWFudXAoc3RydWN0IG10a19jYW1f ZGV2ICpjYW0pDQo+ID4gK3sNCj4gPiArCW10a19jYW1fdjRsMl9hc3luY191bnJlZ2lzdGVyKGNh bSk7DQo+ID4gKwltdGtfY2FtX3Y0bDJfdW5yZWdpc3RlcihjYW0pOw0KPiA+ICsJbXV0ZXhfZGVz dHJveSgmY2FtLT5vcF9sb2NrKTsNCj4gPiArfQ0KPiA+ICsNCj4gPiBkaWZmIC0tZ2l0IGEvZHJp dmVycy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL2lzcF81MC9jYW0vbXRrX2NhbS5oIGIvZHJpdmVy cy9tZWRpYS9wbGF0Zm9ybS9tdGstaXNwL2lzcF81MC9jYW0vbXRrX2NhbS5oDQo+ID4gbmV3IGZp bGUgbW9kZSAxMDA2NDQNCj4gPiBpbmRleCAwMDAwMDAwMDAwMDAuLjBhMzQwYTFlNjVlYQ0KPiA+ IC0tLSAvZGV2L251bGwNCj4gPiArKysgYi9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL210ay1pc3Av aXNwXzUwL2NhbS9tdGtfY2FtLmgNCj4gPiBAQCAtMCwwICsxLDI0NCBAQA0KPiA+ICsvKiBTUERY LUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMCAqLw0KPiA+ICsvKg0KPiA+ICsgKiBDb3B5cmln aHQgKGMpIDIwMTkgTWVkaWFUZWsgSW5jLg0KPiA+ICsgKi8NCj4gPiArDQo+ID4gKyNpZm5kZWYg X19NVEtfQ0FNX0hfXw0KPiA+ICsjZGVmaW5lIF9fTVRLX0NBTV9IX18NCj4gPiArDQo+ID4gKyNp bmNsdWRlIDxsaW51eC9kZXZpY2UuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3R5cGVzLmg+DQo+ ID4gKyNpbmNsdWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZpY2UuaD4NCj4gPiArI2luY2x1ZGUgPGxp bnV4L3NwaW5sb2NrLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC92aWRlb2RldjIuaD4NCj4gPiAr I2luY2x1ZGUgPG1lZGlhL3Y0bDItZGV2aWNlLmg+DQo+ID4gKyNpbmNsdWRlIDxtZWRpYS92NGwy LWN0cmxzLmg+DQo+ID4gKyNpbmNsdWRlIDxtZWRpYS92NGwyLXN1YmRldi5oPg0KPiA+ICsjaW5j bHVkZSA8bWVkaWEvdmlkZW9idWYyLWNvcmUuaD4NCj4gPiArI2luY2x1ZGUgPG1lZGlhL3ZpZGVv YnVmMi12NGwyLmg+DQo+ID4gKw0KPiA+ICsjaW5jbHVkZSAibXRrX2NhbS1pcGkuaCINCj4gPiAr DQo+ID4gKyNkZWZpbmUgSU1HX01BWF9XSURUSAkJNTM3Ng0KPiA+ICsjZGVmaW5lIElNR19NQVhf SEVJR0hUCQk0MDMyDQo+ID4gKyNkZWZpbmUgSU1HX01JTl9XSURUSAkJODANCj4gPiArI2RlZmlu ZSBJTUdfTUlOX0hFSUdIVAkJNjANCj4gPiArDQo+ID4gKy8qDQo+ID4gKyAqIElEIGVudW0gdmFs dWUgZm9yIHN0cnVjdCBtdGtfY2FtX2Rldl9ub2RlX2Rlc2M6aWQNCj4gPiArICogb3IgbXRrX2Nh bV92aWRlb19kZXZpY2U6aWQNCj4gPiArICovDQo+ID4gK2VudW0gIHsNCj4gPiArCU1US19DQU1f UDFfTUVUQV9JTl8wID0gMCwNCj4gPiArCU1US19DQU1fUDFfTUFJTl9TVFJFQU1fT1VULA0KPiA+ ICsJTVRLX0NBTV9QMV9QQUNLRURfQklOX09VVCwNCj4gPiArCU1US19DQU1fUDFfTUVUQV9PVVRf MCwNCj4gPiArCU1US19DQU1fUDFfTUVUQV9PVVRfMSwNCj4gPiArCU1US19DQU1fUDFfTUVUQV9P VVRfMiwNCj4gPiArCU1US19DQU1fUDFfTUVUQV9PVVRfMywNCj4gPiArCU1US19DQU1fUDFfVE9U QUxfTk9ERVMNCj4gPiArfTsNCj4gPiArDQo+ID4gKy8qIFN1cHBvcnRlZCBpbWFnZSBmb3JtYXQg bGlzdCAqLw0KPiA+ICsjZGVmaW5lIE1US19DQU1fSU1HX0ZNVF9VTktOT1dOCQkweDAwMDANCj4g PiArI2RlZmluZSBNVEtfQ0FNX0lNR19GTVRfQkFZRVI4CQkweDIyMDANCj4gPiArI2RlZmluZSBN VEtfQ0FNX0lNR19GTVRfQkFZRVIxMAkJMHgyMjAxDQo+ID4gKyNkZWZpbmUgTVRLX0NBTV9JTUdf Rk1UX0JBWUVSMTIJCTB4MjIwMg0KPiA+ICsjZGVmaW5lIE1US19DQU1fSU1HX0ZNVF9CQVlFUjE0 CQkweDIyMDMNCj4gPiArI2RlZmluZSBNVEtfQ0FNX0lNR19GTVRfRkdfQkFZRVI4CTB4MjIwNA0K PiA+ICsjZGVmaW5lIE1US19DQU1fSU1HX0ZNVF9GR19CQVlFUjEwCTB4MjIwNQ0KPiA+ICsjZGVm aW5lIE1US19DQU1fSU1HX0ZNVF9GR19CQVlFUjEyCTB4MjIwNg0KPiA+ICsjZGVmaW5lIE1US19D QU1fSU1HX0ZNVF9GR19CQVlFUjE0CTB4MjIwNw0KPiA+ICsNCj4gPiArLyogU3VwcG9ydGVkIGJh eWVyIHBpeGVsIG9yZGVyICovDQo+ID4gKyNkZWZpbmUgTVRLX0NBTV9SQVdfUFhMX0lEX0IJCTAN Cj4gPiArI2RlZmluZSBNVEtfQ0FNX1JBV19QWExfSURfR0IJCTENCj4gPiArI2RlZmluZSBNVEtf Q0FNX1JBV19QWExfSURfR1IJCTINCj4gPiArI2RlZmluZSBNVEtfQ0FNX1JBV19QWExfSURfUgkJ Mw0KPiA+ICsjZGVmaW5lIE1US19DQU1fUkFXX1BYTF9JRF9VTktOT1dOCTQNCj4gPiArDQo+ID4g Ky8qDQo+ID4gKyAqIHN0cnVjdCBtdGtfcDFfZnJhbWVfcGFyYW0gLSBNVEsgSVNQIFAxIGRyaXZl ciBmcmFtZSBwYXJhbWV0ZXJzLg0KPiA+ICsgKg0KPiA+ICsgKiBAZnJhbWVfc2VxX25vOiBUaGUg ZnJhbWUgc2VxdWVuY2Ugb2YgZnJhbWUgaW4gZHJpdmVyIGxheWVyLg0KPiA+ICsgKiBAZG1hX2J1 ZnM6IFRoZSBETUEgYnVmZmVyIGFkZHJlc3MgaW5mb3JtYXRpb24gb2YgZW5hYmxlZCBETUEgbm9k ZXMuDQo+ID4gKyAqDQo+ID4gKyAqLw0KPiA+ICtzdHJ1Y3QgbXRrX3AxX2ZyYW1lX3BhcmFtIHsN Cj4gPiArCXVuc2lnbmVkIGludCBmcmFtZV9zZXFfbm87DQo+ID4gKwlzdHJ1Y3QgZG1hX2J1ZmZl ciBkbWFfYnVmc1tNVEtfQ0FNX1AxX1RPVEFMX05PREVTXTsNCj4gPiArfSBfX3BhY2tlZDsNCj4g PiArDQo+ID4gKy8qDQo+ID4gKyAqIHN0cnVjdCBtdGtfY2FtX2Rldl9yZXF1ZXN0IC0gTVRLIGNh bWVyYSBkZXZpY2UgcmVxdWVzdC4NCj4gPiArICoNCj4gPiArICogQHJlcTogRW1iZWRkZWQgc3Ry dWN0IG1lZGlhIHJlcXVlc3QuDQo+ID4gKyAqIEBmcmFtZV9wYXJhbXM6IFRoZSBmcmFtZSBpbmZv LiAmIGFkZHJlc3MgaW5mby4gb2YgZW5hYmxlZCBETUEgbm9kZXMuDQo+ID4gKyAqIEBmcmFtZV93 b3JrOiB3b3JrIHF1ZXVlIGVudHJ5IGZvciBmcmFtZSB0cmFuc21pc3Npb24gdG8gU0NQLg0KPiA+ ICsgKiBAbGlzdDogTGlzdCBlbnRyeSBvZiB0aGUgb2JqZWN0IGZvciBAc3RydWN0IG10a19jYW1f ZGV2Og0KPiA+ICsgKiAgICAgICAgcGVuZGluZ19qb2JfbGlzdCBvciBydW5uaW5nX2pvYl9saXN0 Lg0KPiA+ICsgKiBAdGltZXN0YW1wOiBTdGFydCBvZiBmcmFtZSB0aW1lc3RhbXAgaW4gbnMNCj4g PiArICoNCj4gPiArICovDQo+ID4gK3N0cnVjdCBtdGtfY2FtX2Rldl9yZXF1ZXN0IHsNCj4gPiAr CXN0cnVjdCBtZWRpYV9yZXF1ZXN0IHJlcTsNCj4gPiArCXN0cnVjdCBtdGtfcDFfZnJhbWVfcGFy YW0gZnJhbWVfcGFyYW1zOw0KPiA+ICsJc3RydWN0IHdvcmtfc3RydWN0IGZyYW1lX3dvcms7DQo+ ID4gKwlzdHJ1Y3QgbGlzdF9oZWFkIGxpc3Q7DQo+ID4gKwl1NjQgdGltZXN0YW1wOw0KPiA+ICt9 Ow0KPiA+ICsNCj4gPiArLyoNCj4gPiArICogc3RydWN0IG10a19jYW1fZGV2X2J1ZmZlciAtIE1U SyBjYW1lcmEgZGV2aWNlIGJ1ZmZlci4NCj4gPiArICoNCj4gPiArICogQHZiYjogRW1iZWRkZWQg c3RydWN0IHZiMl92NGwyX2J1ZmZlci4NCj4gPiArICogQGxpc3Q6IExpc3QgZW50cnkgb2YgdGhl IG9iamVjdCBmb3IgQHN0cnVjdCBtdGtfY2FtX3ZpZGVvX2RldmljZToNCj4gPiArICogICAgICAg IGJ1Zl9saXN0Lg0KPiA+ICsgKiBAZGFkZHI6IFRoZSBETUEgYWRkcmVzcyBvZiB0aGlzIGJ1ZmZl ci4NCj4gPiArICogQHNjcF9hZGRyOiBUaGUgU0NQIGFkZHJlc3Mgb2YgdGhpcyBidWZmZXIgd2hp Y2gNCj4gPiArICogICAgICAgICAgICBpcyBvbmx5IHN1cHBvcnRlZCBmb3IgbWV0YSBpbnB1dCBu b2RlLg0KPiA+ICsgKiBAbm9kZV9pZDogVGhlIHZpZG9lIG5vZGUgaWQgd2hpY2ggdGhpcyBidWZm ZXIgYmVsb25ncyB0by4NCj4gPiArICoNCj4gPiArICovDQo+ID4gK3N0cnVjdCBtdGtfY2FtX2Rl dl9idWZmZXIgew0KPiA+ICsJc3RydWN0IHZiMl92NGwyX2J1ZmZlciB2YmI7DQo+ID4gKwlzdHJ1 Y3QgbGlzdF9oZWFkIGxpc3Q7DQo+ID4gKwkvKiBJbnRlbmFsIHBhcnQgKi8NCj4gPiArCWRtYV9h ZGRyX3QgZGFkZHI7DQo+ID4gKwlkbWFfYWRkcl90IHNjcF9hZGRyOw0KPiA+ICsJdW5zaWduZWQg aW50IG5vZGVfaWQ7DQo+ID4gK307DQo+ID4gKw0KPiA+ICsvKg0KPiA+ICsgKiBzdHJ1Y3QgbXRr X2NhbV9kZXZfbm9kZV9kZXNjIC0gTVRLIGNhbWVyYSBkZXZpY2Ugbm9kZSBkZXNjcmlwdG9yDQo+ ID4gKyAqDQo+ID4gKyAqIEBpZDogaWQgb2YgdGhlIG5vZGUNCj4gPiArICogQG5hbWU6IG5hbWUg b2YgdGhlIG5vZGUNCj4gPiArICogQGNhcDogc3VwcG9ydGVkIFY0TDIgY2FwYWJpbGl0aWVzDQo+ ID4gKyAqIEBidWZfdHlwZTogc3VwcG9ydGVkIFY0TDIgYnVmZmVyIHR5cGUNCj4gPiArICogQGRt YV9wb3J0OiB0aGUgZG1hIHBvcnRzIGFzc29jaWF0ZWQgdG8gdGhlIG5vZGUNCj4gPiArICogQGxp bmtfZmxhZ3M6IGRlZmF1bHQgbWVkaWEgbGluayBmbGFncw0KPiA+ICsgKiBAc21lbV9hbGxvYzog dXNpbmcgdGhlIHNtZW1fZGV2IGFzIGFsbG9jIGRldmljZSBvciBub3QNCj4gPiArICogQGltYWdl OiB0cnVlIGZvciBpbWFnZSBub2RlLCBmYWxzZSBmb3IgbWV0YSBub2RlDQo+ID4gKyAqIEBudW1f Zm10czogdGhlIG51bWJlciBvZiBzdXBwb3J0ZWQgbm9kZSBmb3JtYXRzDQo+ID4gKyAqIEBkZWZh dWx0X2ZtdF9pZHg6IGRlZmF1bHQgZm9ybWF0IG9mIHRoaXMgbm9kZQ0KPiA+ICsgKiBAbWF4X2J1 Zl9jb3VudDogbWF4aW11bSBWQjIgYnVmZmVyIGNvdW50DQo+ID4gKyAqIEBpb2N0bF9vcHM6ICBt YXBwZWQgdG8gdjRsMl9pb2N0bF9vcHMNCj4gPiArICogQGZtdHM6IHN1cHBvcnRlZCBmb3JtYXQN Cj4gPiArICogQGZybXNpemVzOiBzdXBwb3J0ZWQgVjRMMiBmcmFtZSBzaXplIG51bWJlcg0KPiA+ ICsgKg0KPiA+ICsgKi8NCj4gPiArc3RydWN0IG10a19jYW1fZGV2X25vZGVfZGVzYyB7DQo+ID4g Kwl1OCBpZDsNCj4gPiArCWNvbnN0IGNoYXIgKm5hbWU7DQo+ID4gKwl1MzIgY2FwOw0KPiA+ICsJ dTMyIGJ1Zl90eXBlOw0KPiA+ICsJdTMyIGRtYV9wb3J0Ow0KPiA+ICsJdTMyIGxpbmtfZmxhZ3M7 DQo+ID4gKwl1OCBzbWVtX2FsbG9jOjE7DQo+ID4gKwl1OCBpbWFnZToxOw0KPiA+ICsJdTggbnVt X2ZtdHM7DQo+ID4gKwl1OCBkZWZhdWx0X2ZtdF9pZHg7DQo+ID4gKwl1OCBtYXhfYnVmX2NvdW50 Ow0KPiA+ICsJY29uc3Qgc3RydWN0IHY0bDJfaW9jdGxfb3BzICppb2N0bF9vcHM7DQo+ID4gKwlj b25zdCBzdHJ1Y3QgdjRsMl9mb3JtYXQgKmZtdHM7DQo+ID4gKwljb25zdCBzdHJ1Y3QgdjRsMl9m cm1zaXplZW51bSAqZnJtc2l6ZXM7DQo+ID4gK307DQo+ID4gKw0KPiA+ICsvKg0KPiA+ICsgKiBz dHJ1Y3QgbXRrX2NhbV92aWRlb19kZXZpY2UgLSBNZWRpYXRlayB2aWRlbyBkZXZpY2Ugc3RydWN0 dXJlDQo+ID4gKyAqDQo+ID4gKyAqIEBpZDogSWQgZm9yIGluZGV4IG9mIG10a19jYW1fZGV2OnZk ZXZfbm9kZXMgYXJyYXkNCj4gPiArICogQGVuYWJsZWQ6IEluZGljYXRlIHRoZSB2aWRlbyBkZXZp Y2UgaXMgZW5hYmxlZCBvciBub3QNCj4gPiArICogQGRlc2M6IFRoZSBub2RlIGRlc2NyaXB0aW9u IG9mIHZpZGVvIGRldmljZQ0KPiA+ICsgKiBAdmRldl9mbXQ6IFRoZSBWNEwyIGZvcm1hdCBvZiB2 aWRlbyBkZXZpY2UNCj4gPiArICogQHZkZXZfcGFkOiBUaGUgbWVkaWEgcGFkIGdyYXBoIG9iamVj dCBvZiB2aWRlbyBkZXZpY2UNCj4gPiArICogQHZicTogQSB2aWRlb2J1ZiBxdWV1ZSBvZiB2aWRl byBkZXZpY2UNCj4gPiArICogQHZkZXY6IFRoZSB2aWRlbyBkZXZpY2UgaW5zdGFuY2UNCj4gPiAr ICogQHZkZXZfbG9jazogU2VyaWFsaXplcyB2YjIgcXVldWUgYW5kIHZpZGVvIGRldmljZSBvcGVy YXRpb25zDQo+ID4gKyAqIEBidWZfbGlzdDogTGlzdCBmb3IgZW5xdWV1ZSBidWZmZXJzDQo+ID4g KyAqIEBidWZfbGlzdF9sb2NrOiBMb2NrIHVzZWQgdG8gcHJvdGVjdCBidWZmZXIgbGlzdC4NCj4g PiArICoNCj4gPiArICovDQo+ID4gK3N0cnVjdCBtdGtfY2FtX3ZpZGVvX2RldmljZSB7DQo+ID4g Kwl1bnNpZ25lZCBpbnQgaWQ7DQo+ID4gKwl1bnNpZ25lZCBpbnQgZW5hYmxlZDsNCj4gPiArCXN0 cnVjdCBtdGtfY2FtX2Rldl9ub2RlX2Rlc2MgZGVzYzsNCj4gPiArCXN0cnVjdCB2NGwyX2Zvcm1h dCB2ZGV2X2ZtdDsNCj4gPiArCXN0cnVjdCBtZWRpYV9wYWQgdmRldl9wYWQ7DQo+ID4gKwlzdHJ1 Y3QgdmIyX3F1ZXVlIHZicTsNCj4gPiArCXN0cnVjdCB2aWRlb19kZXZpY2UgdmRldjsNCj4gPiAr CS8qIFNlcmlhbGl6ZXMgdmIyIHF1ZXVlIGFuZCB2aWRlbyBkZXZpY2Ugb3BlcmF0aW9ucyAqLw0K PiA+ICsJc3RydWN0IG11dGV4IHZkZXZfbG9jazsNCj4gPiArCXN0cnVjdCBsaXN0X2hlYWQgYnVm X2xpc3Q7DQo+ID4gKwkvKiBMb2NrIHVzZWQgdG8gcHJvdGVjdCBidWZmZXIgbGlzdCAqLw0KPiA+ ICsJc3BpbmxvY2tfdCBidWZfbGlzdF9sb2NrOw0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArLyoNCj4g PiArICogc3RydWN0IG10a19jYW1fZGV2IC0gTWVkaWF0ZWsgY2FtZXJhIGRldmljZSBzdHJ1Y3R1 cmUuDQo+ID4gKyAqDQo+ID4gKyAqIEBkZXY6IFBvaW50ZXIgdG8gZGV2aWNlLg0KPiA+ICsgKiBA c21lbV9wZGV2OiBQb2ludGVyIHRvIHNoYXJlZCBtZW1vcnkgZGV2aWNlLg0KPiA+ICsgKiBAcGlw ZWxpbmU6IE1lZGlhIHBpcGVsaW5lIGluZm9ybWF0aW9uLg0KPiA+ICsgKiBAbWVkaWFfZGV2OiBN ZWRpYSBkZXZpY2UgaW5zdGFuY2UuDQo+ID4gKyAqIEBzdWJkZXY6IFRoZSBWNEwyIHN1Yi1kZXZp Y2UgaW5zdGFuY2UuDQo+ID4gKyAqIEB2NGwyX2RldjogVGhlIFY0TDIgZGV2aWNlIGRyaXZlciBp bnN0YW5jZS4NCj4gPiArICogQG5vdGlmaWVyOiBUaGUgdjRsMl9kZXZpY2Ugbm90aWZpZXIgZGF0 YS4NCj4gPiArICogQHN1YmRldl9wYWRzOiBQb2ludGVyIHRvIHRoZSBudW1iZXIgb2YgbWVkaWEg cGFkcyBvZiB0aGlzIHN1Yi1kZXZpY2UuDQo+ID4gKyAqIEB2ZGV2X25vZGVzOiBUaGUgYXJyYXkg bGlzdCBvZiBtdGtfY2FtX3ZpZGVvX2RldmljZSBub2Rlcy4NCj4gPiArICogQHNlbmluZjogUG9p bnRlciB0byB0aGUgc2VuaW5mIHN1Yi1kZXZpY2UuDQo+ID4gKyAqIEBzZW5zb3I6IFBvaW50ZXIg dG8gdGhlIGFjdGl2ZSBzZW5zb3IgVjRMMiBzdWItZGV2aWNlIHdoZW4gc3RyZWFtaW5nIG9uLg0K PiA+ICsgKiBAc3RyZWFtaW5nOiBJbmRpY2F0ZSB0aGUgb3ZlcmFsbCBzdHJlYW1pbmcgc3RhdHVz IGlzIG9uIG9yIG9mZi4NCj4gPiArICogQGVuYWJsZWRfZG1hczogVGhlIGVuYWJsZWQgZG1hIHBv cnQgaW5mb3JtYXRpb24gd2hlbiBzdHJlYW1pbmcgb24uDQo+ID4gKyAqIEBlbmFibGVkX2NvdW50 OiBOdW1iZXIgb2YgZW5hYmxlZCB2aWRlbyBub2Rlcw0KPiA+ICsgKiBAc3RyZWFtX2NvdW50OiBO dW1iZXIgb2Ygc3RyZWFtaW5nIHZpZGVvIG5vZGVzDQo+ID4gKyAqIEBydW5uaW5nX2pvYl9jb3Vu dDogTnVuYmVyIG9mIHJ1bm5pbmcgam9icyBpbiB0aGUgSFcgZHJpdmVyLg0KPiA+ICsgKiBAcGVu ZGluZ19qb2JfbGlzdDogTGlzdCB0byBrZWVwIHRoZSBtZWRpYSByZXF1ZXN0cyBiZWZvcmUgZW4t cXVldWUgaW50bw0KPiA+ICsgKiAgICAgICAgICAgICAgICAgICAgSFcgZHJpdmVyLg0KPiA+ICsg KiBAcGVuZGluZ19qb2JfbG9jazogUHJvdGVjdCB0aGUgcGVuZGluZ19qb2JfbGlzdCBkYXRhICYg cnVubmluZ19qb2JfY291bnQuDQo+ID4gKyAqIEBydW5uaW5nX2pvYl9saXN0OiBMaXN0IHRvIGtl ZXAgdGhlIG1lZGlhIHJlcXVlc3RzIGFmdGVyIGVuLXF1ZXVlIGludG8NCj4gPiArICogICAgICAg ICAgICAgICAgICAgIEhXIGRyaXZlci4NCj4gPiArICogQHJ1bm5pbmdfam9iX2xvY2s6IFByb3Rl Y3QgdGhlIHJ1bm5pbmdfam9iX2xpc3QgZGF0YS4NCj4gPiArICogQG9wX2xvY2s6IFNlcmlhbGl6 ZXMgZHJpdmVyJ3MgVkIyIGNhbGxiYWNrIG9wZXJhdGlvbnMuDQo+ID4gKyAqDQo+ID4gKyAqLw0K PiA+ICtzdHJ1Y3QgbXRrX2NhbV9kZXYgew0KPiA+ICsJc3RydWN0IGRldmljZSAqZGV2Ow0KPiA+ ICsJc3RydWN0IGRldmljZSAqc21lbV9kZXY7DQo+ID4gKwlzdHJ1Y3QgbWVkaWFfcGlwZWxpbmUg cGlwZWxpbmU7DQo+ID4gKwlzdHJ1Y3QgbWVkaWFfZGV2aWNlIG1lZGlhX2RldjsNCj4gPiArCXN0 cnVjdCB2NGwyX3N1YmRldiBzdWJkZXY7DQo+ID4gKwlzdHJ1Y3QgdjRsMl9kZXZpY2UgdjRsMl9k ZXY7DQo+ID4gKwlzdHJ1Y3QgdjRsMl9hc3luY19ub3RpZmllciBub3RpZmllcjsNCj4gPiArCXN0 cnVjdCBtZWRpYV9wYWQgKnN1YmRldl9wYWRzOw0KPiA+ICsJc3RydWN0IG10a19jYW1fdmlkZW9f ZGV2aWNlIHZkZXZfbm9kZXNbTVRLX0NBTV9QMV9UT1RBTF9OT0RFU107DQo+ID4gKwlzdHJ1Y3Qg djRsMl9zdWJkZXYgKnNlbmluZjsNCj4gPiArCXN0cnVjdCB2NGwyX3N1YmRldiAqc2Vuc29yOw0K PiA+ICsJdW5zaWduZWQgaW50IHN0cmVhbWluZzsNCj4gPiArCXVuc2lnbmVkIGludCBlbmFibGVk X2RtYXM7DQo+ID4gKwl1bnNpZ25lZCBpbnQgZW5hYmxlZF9jb3VudDsNCj4gPiArCXVuc2lnbmVk IGludCBzdHJlYW1fY291bnQ7DQo+ID4gKwl1bnNpZ25lZCBpbnQgcnVubmluZ19qb2JfY291bnQ7 DQo+ID4gKwlzdHJ1Y3QgbGlzdF9oZWFkIHBlbmRpbmdfam9iX2xpc3Q7DQo+ID4gKwkvKiBQcm90 ZWN0IHRoZSBwZW5kaW5nX2pvYl9saXN0IGRhdGEgKi8NCj4gPiArCXNwaW5sb2NrX3QgcGVuZGlu Z19qb2JfbG9jazsNCj4gPiArCXN0cnVjdCBsaXN0X2hlYWQgcnVubmluZ19qb2JfbGlzdDsNCj4g PiArCS8qIFByb3RlY3QgdGhlIHJ1bm5pbmdfam9iX2xpc3QgZGF0YSAmIHJ1bm5pbmdfam9iX2Nv dW50ICovDQo+ID4gKwlzcGlubG9ja190IHJ1bm5pbmdfam9iX2xvY2s7DQo+ID4gKwkvKiBTZXJp YWxpemVzIGRyaXZlcidzIFZCMiBjYWxsYmFjayBvcGVyYXRpb25zICovDQo+ID4gKwlzdHJ1Y3Qg bXV0ZXggb3BfbG9jazsNCj4gPiArfTsNCj4gPiArDQo+ID4gK2ludCBtdGtfY2FtX2Rldl9pbml0 KHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYsDQo+ID4gKwkJICAgICBzdHJ1Y3QgbXRrX2Nh bV9kZXYgKmNhbV9kZXYpOw0KPiA+ICt2b2lkIG10a19jYW1fZGV2X2NsZWFudXAoc3RydWN0IG10 a19jYW1fZGV2ICpjYW1fZGV2KTsNCj4gPiArdm9pZCBtdGtfY2FtX2Rldl9yZXFfdHJ5X3F1ZXVl KHN0cnVjdCBtdGtfY2FtX2RldiAqY2FtX2Rldik7DQo+ID4gK3ZvaWQgbXRrX2NhbV9kZXZfZGVx dWV1ZV9yZXFfZnJhbWUoc3RydWN0IG10a19jYW1fZGV2ICpjYW1fZGV2LA0KPiA+ICsJCQkJICAg dW5zaWduZWQgaW50IGZyYW1lX3NlcV9ubyk7DQo+ID4gK3ZvaWQgbXRrX2NhbV9kZXZfZXZlbnRf ZnJhbWVfc3luYyhzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbV9kZXYsDQo+ID4gKwkJCQkgIHVuc2ln bmVkIGludCBmcmFtZV9zZXFfbm8pOw0KPiA+ICtzdHJ1Y3QgbXRrX2NhbV9kZXZfcmVxdWVzdCAq bXRrX2NhbV9kZXZfZ2V0X3JlcShzdHJ1Y3QgbXRrX2NhbV9kZXYgKmNhbSwNCj4gPiArCQkJCQkJ dW5zaWduZWQgaW50IGZyYW1lX3NlcV9ubyk7DQo+ID4gKw0KPiA+ICsjZW5kaWYgLyogX19NVEtf Q0FNX0hfXyAqLw0KPiA+IA0KPiANCj4gX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX18NCj4gTGludXgtbWVkaWF0ZWsgbWFpbGluZyBsaXN0DQo+IExpbnV4LW1l ZGlhdGVrQGxpc3RzLmluZnJhZGVhZC5vcmcNCj4gaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcv bWFpbG1hbi9saXN0aW5mby9saW51eC1tZWRpYXRlaw0KDQo=