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=-13.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable 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 A5E09C4332F for ; Wed, 22 Sep 2021 13:10:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7795E6103C for ; Wed, 22 Sep 2021 13:10:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231629AbhIVNLt (ORCPT ); Wed, 22 Sep 2021 09:11:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38768 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230338AbhIVNLs (ORCPT ); Wed, 22 Sep 2021 09:11:48 -0400 Received: from mail-qt1-x835.google.com (mail-qt1-x835.google.com [IPv6:2607:f8b0:4864:20::835]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0CED2C061756 for ; Wed, 22 Sep 2021 06:10:18 -0700 (PDT) Received: by mail-qt1-x835.google.com with SMTP id c20so2583594qtb.2 for ; Wed, 22 Sep 2021 06:10:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ndufresne-ca.20210112.gappssmtp.com; s=20210112; h=message-id:subject:from:to:cc:date:in-reply-to:references :user-agent:mime-version:content-transfer-encoding; bh=yGvWn4rdW0UXt2zbvpR5gmgtOURbpSljCQDnJpSEN0I=; b=krsC7I6hr5gky16LQq4vrfa4aUfIrsrNCVl6MTDOpu0hQcpbav6ikr34iCzYtm3LMh mBfE/H5MEWzU76omrTSrJLv2BjwZK0FNWRadXTa489xiym0+AbmY9FbUQrUakrEOF6OP zUWAsrut0MVq2Xxeoj8rngQ9ThlprHv6+zvq3BUjqmpOelqlPHeUOCFwx+uDAZvMMKvY /YeYwbtY5TrUnDZaOxfFZ4DHGNL4iZbcD0yhK1a1B2mUmCtsJ4tc7usqmVwlrAsJYyNG jE557aynHGrHV99SMKb22MjFkZ2/AfteCa3s1N5E0SNEBe75PLJVMxwkFbk8FnShMGyd j1jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:subject:from:to:cc:date:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=yGvWn4rdW0UXt2zbvpR5gmgtOURbpSljCQDnJpSEN0I=; b=d44GIK1wxwkbO+eE/aBBMJrV/qTYRP9FZzPkGtwngbtKV/Z3d4IrhhXnZs4Nc0hjl4 f6vGMNtFvgYaIeB9hK7bt3E9h/ErpFUuL/eEYcUrECesWV8oE1KiSYQEeLqsH/5PDjFm HI+aZUE0FQ8GephkYosHAMVSr5CLU6EEDtUCQUBbdURKR271Yv4CEtcmxvd9TtMEzBE/ NIB1LArgOcs0esldEHXh9KItqmh4ILDc6UAbTeZLKvJ5dwsGVzpcdhYI3QiuqZ+sjBPz vRjCqmT+Y2ikCgqHbMoFqq2z7Xd7u31d+hAkIRYBDCjoO/Ir2hoUtGAe6dVBvdQtwJIB pg+Q== X-Gm-Message-State: AOAM531Q8sUqA3j8Sx4CbeObJykRvQGBHCmMJe9FddTNTaVgtMN8vFMg 6YwkQFesshBXE1rzvH8zEjs1Fw== X-Google-Smtp-Source: ABdhPJy+lDtsygYSoHPvGDFRuVgjA26MinT+HBCCQqjffafgkVeKPIscJcjS6QaqeO3/amVEWf1GVw== X-Received: by 2002:ac8:71cd:: with SMTP id i13mr15956998qtp.159.1632316216588; Wed, 22 Sep 2021 06:10:16 -0700 (PDT) Received: from nicolas-tpx395.localdomain (173-246-12-168.qc.cable.ebox.net. [173.246.12.168]) by smtp.gmail.com with ESMTPSA id g19sm1616534qki.58.2021.09.22.06.10.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Sep 2021 06:10:16 -0700 (PDT) Message-ID: <2b543d1c86c2ba3ac507f196ee326908138c1186.camel@ndufresne.ca> Subject: Re: [PATCH v9 04/13] media: amphion: add vpu core driver From: Nicolas Dufresne To: Ming Qian , mchehab@kernel.org, shawnguo@kernel.org, robh+dt@kernel.org, s.hauer@pengutronix.de Cc: hverkuil-cisco@xs4all.nl, kernel@pengutronix.de, festevam@gmail.com, linux-imx@nxp.com, aisheng.dong@nxp.com, linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org Date: Wed, 22 Sep 2021 09:10:14 -0400 In-Reply-To: <51ba61663ce92a9fe71343578689a0e196d0dfea.1631521295.git.ming.qian@nxp.com> References: <51ba61663ce92a9fe71343578689a0e196d0dfea.1631521295.git.ming.qian@nxp.com> Content-Type: text/plain; charset="UTF-8" User-Agent: Evolution 3.40.4 (3.40.4-1.fc34) MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Ming, seem comment below. gLe lundi 13 septembre 2021 à 17:11 +0800, Ming Qian a écrit : > The vpu supports encoder and decoder. > it needs mu core to handle it. > core will run either encoder or decoder firmware. > > This driver is for support the vpu core. > > Signed-off-by: Ming Qian > Signed-off-by: Shijie Qin > Signed-off-by: Zhou Peng > --- > drivers/media/platform/amphion/vpu_codec.h | 68 ++ > drivers/media/platform/amphion/vpu_core.c | 901 +++++++++++++++++++++ > drivers/media/platform/amphion/vpu_core.h | 16 + > drivers/media/platform/amphion/vpu_dbg.c | 496 ++++++++++++ > drivers/media/platform/amphion/vpu_log.h | 44 + When loading this driver, I immediately stumbled across non-standard logging. [ 29.617994] [VPU CORE]core vpu_core probe [ 29.666447] [VPU CORE][0] decoder boot-region : <0x0000000084000000, 0x2000000> [ 29.738152] [VPU IMX8Q]imx8q fuse = 0x0 [ 29.799421] [VPU CORE]core vpu_core probe< [ 30.111805] [VPU CORE][0] decoder boot I remember a thread related to Venus driver, and it seems that its best to remove this custom logging infrastructure and use the existing infrastructure. > drivers/media/platform/amphion/vpu_rpc.c | 263 ++++++ > drivers/media/platform/amphion/vpu_rpc.h | 463 +++++++++++ > 7 files changed, 2251 insertions(+) > create mode 100644 drivers/media/platform/amphion/vpu_codec.h > create mode 100644 drivers/media/platform/amphion/vpu_core.c > create mode 100644 drivers/media/platform/amphion/vpu_core.h > create mode 100644 drivers/media/platform/amphion/vpu_dbg.c > create mode 100644 drivers/media/platform/amphion/vpu_log.h > create mode 100644 drivers/media/platform/amphion/vpu_rpc.c > create mode 100644 drivers/media/platform/amphion/vpu_rpc.h > > diff --git a/drivers/media/platform/amphion/vpu_codec.h b/drivers/media/platform/amphion/vpu_codec.h > new file mode 100644 > index 000000000000..4dc41d6808b1 > --- /dev/null > +++ b/drivers/media/platform/amphion/vpu_codec.h > @@ -0,0 +1,68 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright 2020-2021 NXP > + */ > + > +#ifndef _AMPHION_VPU_CODEC_H > +#define _AMPHION_VPU_CODEC_H > + > +struct vpu_encode_params { > + u32 input_format; > + u32 codec_format; > + u32 profile; > + u32 tier; > + u32 level; > + u32 frame_rate_num; > + u32 frame_rate_den; > + u32 src_stride; > + u32 src_width; > + u32 src_height; > + struct v4l2_rect crop; > + u32 out_width; > + u32 out_height; > + > + u32 gop_length; > + u32 bframes; > + > + u32 rc_mode; > + u32 bitrate; > + u32 bitrate_min; > + u32 bitrate_max; > + > + u32 i_frame_qp; > + u32 p_frame_qp; > + u32 b_frame_qp; > + u32 qp_min; > + u32 qp_max; > + u32 qp_min_i; > + u32 qp_max_i; > + > + struct { > + u32 enable; > + u32 idc; > + u32 width; > + u32 height; > + } sar; > + > + struct { > + u32 primaries; > + u32 transfer; > + u32 matrix; > + u32 full_range; > + } color; > +}; > + > +struct vpu_decode_params { > + u32 codec_format; > + u32 output_format; > + u32 b_dis_reorder; > + u32 b_non_frame; > + u32 frame_count; > + u32 end_flag; > + struct { > + u32 base; > + u32 size; > + } udata; > +}; > + > +#endif > diff --git a/drivers/media/platform/amphion/vpu_core.c b/drivers/media/platform/amphion/vpu_core.c > new file mode 100644 > index 000000000000..332ad3710abe > --- /dev/null > +++ b/drivers/media/platform/amphion/vpu_core.c > @@ -0,0 +1,901 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright 2020-2021 NXP > + */ > + > +#define TAG "CORE" > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "vpu.h" > +#include "vpu_defs.h" > +#include "vpu_core.h" > +#include "vpu_mbox.h" > +#include "vpu_msgs.h" > +#include "vpu_rpc.h" > +#include "vpu_log.h" > +#include "vpu_cmds.h" > + > +unsigned int vpu_dbg_level = LVL_ERR | LVL_WARN | LVL_INFO; > +module_param(vpu_dbg_level, uint, 0644); > + > +void csr_writel(struct vpu_core *core, u32 reg, u32 val) > +{ > + writel(val, core->base + reg); > +} > + > +u32 csr_readl(struct vpu_core *core, u32 reg) > +{ > + return readl(core->base + reg); > +} > + > +static int vpu_core_load_firmware(struct vpu_core *core) > +{ > + const struct firmware *pfw = NULL; > + int ret = 0; > + > + WARN_ON(!core || !core->res || !core->res->fwname); > + if (!core->fw.virt) { > + core_err(core, "firmware buffer is not ready\n"); > + return -EINVAL; > + } > + > + ret = request_firmware(&pfw, core->res->fwname, core->dev); > + core_dbg(core, LVL_DEBUG, "request_firmware %s : %d\n", core->res->fwname, ret); > + if (ret) { > + core_err(core, "request firmware %s failed, ret = %d\n", > + core->res->fwname, ret); > + return ret; > + } > + > + if (core->fw.length < pfw->size) { > + core_err(core, "firmware buffer size want %zu, but %d\n", > + pfw->size, core->fw.length); > + ret = -EINVAL; > + goto exit; > + } > + > + memset_io(core->fw.virt, 0, core->fw.length); > + memcpy(core->fw.virt, pfw->data, pfw->size); > + core->fw.bytesused = pfw->size; > + ret = vpu_iface_on_firmware_loaded(core); > +exit: > + release_firmware(pfw); > + pfw = NULL; > + > + return ret; > +} > + > +static int vpu_core_wait_boot_done(struct vpu_core *core) > +{ > + int ret; > + u32 fw_version; > + > + ret = wait_for_completion_timeout(&core->cmp, VPU_TIMEOUT); > + if (!ret) { > + core_err(core, "boot timeout\n"); > + return -EINVAL; > + } > + > + fw_version = vpu_iface_get_version(core); > + core_dbg(core, LVL_WARN, "firmware version : %d.%d.%d\n", > + (fw_version >> 16) & 0xff, > + (fw_version >> 8) & 0xff, > + fw_version & 0xff); > + core->supported_instance_count = vpu_iface_get_max_instance_count(core); > + if (core->res->act_size) { > + u32 count = core->act.length / core->res->act_size; > + > + core->supported_instance_count = min(core->supported_instance_count, count); > + } > + core->fw_version = fw_version; > + > + return 0; > +} > + > +static int vpu_core_boot(struct vpu_core *core, bool load) > +{ > + int ret; > + > + WARN_ON(!core); > + > + if (!core->res->standalone) > + return 0; > + > + core_dbg(core, LVL_WARN, "boot\n"); > + reinit_completion(&core->cmp); > + if (load) { > + ret = vpu_core_load_firmware(core); > + if (ret) > + return ret; > + } > + > + vpu_iface_boot_core(core); > + return vpu_core_wait_boot_done(core); > +} > + > +static int vpu_core_shutdown(struct vpu_core *core) > +{ > + if (!core->res->standalone) > + return 0; > + return vpu_iface_shutdown_core(core); > +} > + > +static int vpu_core_restore(struct vpu_core *core) > +{ > + if (!core->res->standalone) > + return 0; > + return vpu_iface_restore_core(core); > +} > + > +static int __vpu_alloc_dma(struct device *dev, struct vpu_buffer *buf) > +{ > + gfp_t gfp = GFP_KERNEL | GFP_DMA32; > + > + WARN_ON(!dev || !buf); > + > + if (!buf->length) > + return 0; > + > + buf->virt = dma_alloc_coherent(dev, buf->length, &buf->phys, gfp); > + if (!buf->virt) > + return -ENOMEM; > + > + buf->dev = dev; > + > + return 0; > +} > + > +void vpu_free_dma(struct vpu_buffer *buf) > +{ > + WARN_ON(!buf); > + > + if (!buf->virt || !buf->dev) > + return; > + > + dma_free_coherent(buf->dev, buf->length, buf->virt, buf->phys); > + buf->virt = NULL; > + buf->phys = 0; > + buf->length = 0; > + buf->bytesused = 0; > + buf->dev = NULL; > +} > + > +int vpu_alloc_dma(struct vpu_core *core, struct vpu_buffer *buf) > +{ > + WARN_ON(!core || !buf); > + > + return __vpu_alloc_dma(core->dev, buf); > +} > + > +static struct vpu_core *vpu_core_find_next_by_type(struct vpu_dev *vpu, u32 type) > +{ > + struct vpu_core *c; > + > + WARN_ON(!vpu); > + > + list_for_each_entry(c, &vpu->cores, list) { > + if (c->type == type) > + return c; > + } > + > + return NULL; > +} > + > +int vpu_core_check_fmt(struct vpu_core *core, u32 pixelfmt) > +{ > + if (!core) > + return -EINVAL; > + > + if (vpu_iface_check_format(core, pixelfmt)) > + return 0; > + > + return -EINVAL; > +} > + > +static void vpu_core_check_hang(struct vpu_core *core) > +{ > + if (core->hang_mask) > + core->state = VPU_CORE_HANG; > +} > + > +static struct vpu_core *vpu_core_find_proper_by_type(struct vpu_dev *vpu, u32 type) > +{ > + struct vpu_core *core = NULL; > + int request_count = INT_MAX; > + struct vpu_core *c; > + > + WARN_ON(!vpu); > + > + list_for_each_entry(c, &vpu->cores, list) { > + core_dbg(c, LVL_DEBUG, "instance_mask = 0x%lx, state = %d\n", > + c->instance_mask, > + c->state); > + if (c->type != type) > + continue; > + if (c->state == VPU_CORE_DEINIT) { > + core = c; > + break; > + } > + vpu_core_check_hang(c); > + if (c->state != VPU_CORE_ACTIVE) > + continue; > + if (c->request_count < request_count) { > + request_count = c->request_count; > + core = c; > + } > + if (!request_count) > + break; > + } > + > + return core; > +} > + > +static bool vpu_core_is_exist(struct vpu_dev *vpu, struct vpu_core *core) > +{ > + struct vpu_core *c; > + > + list_for_each_entry(c, &vpu->cores, list) { > + if (c == core) > + return true; > + } > + > + return false; > +} > + > +static void vpu_core_get_vpu(struct vpu_core *core) > +{ > + core->vpu->get_vpu(core->vpu); > + if (core->type == VPU_CORE_TYPE_ENC) > + core->vpu->get_enc(core->vpu); > + if (core->type == VPU_CORE_TYPE_DEC) > + core->vpu->get_dec(core->vpu); > +} > + > +static int vpu_core_register(struct device *dev, struct vpu_core *core) > +{ > + struct vpu_dev *vpu = dev_get_drvdata(dev); > + int ret = 0; > + > + core_dbg(core, LVL_DEBUG, "register core\n"); > + if (vpu_core_is_exist(vpu, core)) > + return 0; > + > + core->workqueue = alloc_workqueue("vpu", WQ_UNBOUND | WQ_MEM_RECLAIM, 1); > + if (!core->workqueue) { > + core_err(core, "fail to alloc workqueue\n"); > + return -ENOMEM; > + } > + INIT_WORK(&core->msg_work, vpu_msg_run_work); > + INIT_DELAYED_WORK(&core->msg_delayed_work, vpu_msg_delayed_work); > + core->msg_buffer_size = roundup_pow_of_two(VPU_MSG_BUFFER_SIZE); > + core->msg_buffer = vzalloc(core->msg_buffer_size); > + if (!core->msg_buffer) { > + core_err(core, "failed allocate buffer for fifo\n"); > + ret = -ENOMEM; > + goto error; > + } > + ret = kfifo_init(&core->msg_fifo, core->msg_buffer, core->msg_buffer_size); > + if (ret) { > + core_err(core, "failed init kfifo\n"); > + goto error; > + } > + > + list_add_tail(&core->list, &vpu->cores); > + > + vpu_core_get_vpu(core); > + > + if (core->type == VPU_CORE_TYPE_ENC && !vpu->vdev_enc) > + venc_create_video_device(vpu); > + if (core->type == VPU_CORE_TYPE_DEC && !vpu->vdev_dec) > + vdec_create_video_device(vpu); > + > + return 0; > +error: > + if (core->msg_buffer) { > + vfree(core->msg_buffer); > + core->msg_buffer = NULL; > + } > + if (core->workqueue) { > + destroy_workqueue(core->workqueue); > + core->workqueue = NULL; > + } > + return ret; > +} > + > +static void vpu_core_put_vpu(struct vpu_core *core) > +{ > + if (core->type == VPU_CORE_TYPE_ENC) > + core->vpu->put_enc(core->vpu); > + if (core->type == VPU_CORE_TYPE_DEC) > + core->vpu->put_dec(core->vpu); > + core->vpu->put_vpu(core->vpu); > +} > + > +static int vpu_core_unregister(struct device *dev, struct vpu_core *core) > +{ > + struct vpu_dev *vpu = dev_get_drvdata(dev); > + > + list_del_init(&core->list); > + > + vpu_core_put_vpu(core); > + core->vpu = NULL; > + vfree(core->msg_buffer); > + core->msg_buffer = NULL; > + > + if (core->workqueue) { > + cancel_work_sync(&core->msg_work); > + cancel_delayed_work_sync(&core->msg_delayed_work); > + destroy_workqueue(core->workqueue); > + core->workqueue = NULL; > + } > + > + if (vpu_core_find_next_by_type(vpu, core->type)) > + return 0; > + > + if (core->type == VPU_CORE_TYPE_ENC) > + video_unregister_device(vpu->vdev_enc); > + if (core->type == VPU_CORE_TYPE_DEC) > + video_unregister_device(vpu->vdev_dec); > + > + return 0; > +} > + > +static int vpu_core_acquire_instance(struct vpu_core *core) > +{ > + int id; > + > + WARN_ON(!core); > + > + id = ffz(core->instance_mask); > + if (id >= core->supported_instance_count) > + return -EINVAL; > + > + set_bit(id, &core->instance_mask); > + > + return id; > +} > + > +static void vpu_core_release_instance(struct vpu_core *core, int id) > +{ > + WARN_ON(!core); > + > + if (id < 0 || id >= core->supported_instance_count) > + return; > + > + clear_bit(id, &core->instance_mask); > +} > + > +struct vpu_inst *vpu_inst_get(struct vpu_inst *inst) > +{ > + if (!inst) > + return NULL; > + > + atomic_inc(&inst->ref_count); > + > + return inst; > +} > + > +void vpu_inst_put(struct vpu_inst *inst) > +{ > + if (!inst) > + return; > + if (atomic_dec_and_test(&inst->ref_count)) { > + if (inst->release) > + inst->release(inst); > + } > +} > + > +struct vpu_core *vpu_request_core(struct vpu_dev *vpu, enum vpu_core_type type) > +{ > + struct vpu_core *core = NULL; > + int ret; > + > + mutex_lock(&vpu->lock); > + > + core = vpu_core_find_proper_by_type(vpu, type); > + if (!core) > + goto exit; > + > + core_dbg(core, LVL_DEBUG, "is found\n"); > + mutex_lock(&core->lock); > + pm_runtime_get_sync(core->dev); > + > + if (core->state == VPU_CORE_DEINIT) { > + ret = vpu_core_boot(core, true); > + if (ret) { > + pm_runtime_put_sync(core->dev); > + mutex_unlock(&core->lock); > + core = NULL; > + goto exit; > + } > + core->state = VPU_CORE_ACTIVE; > + } > + > + core->request_count++; > + > + mutex_unlock(&core->lock); > +exit: > + mutex_unlock(&vpu->lock); > + > + return core; > +} > + > +void vpu_release_core(struct vpu_core *core) > +{ > + if (!core) > + return; > + > + mutex_lock(&core->lock); > + pm_runtime_put_sync(core->dev); > + if (core->request_count) > + core->request_count--; > + mutex_unlock(&core->lock); > +} > + > +int vpu_inst_register(struct vpu_inst *inst) > +{ > + struct vpu_core *core; > + int ret = 0; > + > + WARN_ON(!inst || !inst->core); > + > + core = inst->core; > + mutex_lock(&core->lock); > + if (inst->id >= 0 && inst->id < core->supported_instance_count) > + goto exit; > + > + ret = vpu_core_acquire_instance(core); > + if (ret < 0) > + goto exit; > + > + inst->id = ret; > + list_add_tail(&inst->list, &core->instances); > + ret = 0; > + if (core->res->act_size) { > + inst->act.phys = core->act.phys + core->res->act_size * inst->id; > + inst->act.virt = core->act.virt + core->res->act_size * inst->id; > + inst->act.length = core->res->act_size; > + } > + vpu_inst_create_dbgfs_file(inst); > +exit: > + mutex_unlock(&core->lock); > + > + if (ret) > + core_err(core, "register instance fail\n"); > + return ret; > +} > + > +int vpu_inst_unregister(struct vpu_inst *inst) > +{ > + struct vpu_core *core; > + > + WARN_ON(!inst); > + > + core = inst->core; > + > + vpu_clear_request(inst); > + mutex_lock(&core->lock); > + if (inst->id >= 0 && inst->id < core->supported_instance_count) { > + vpu_inst_remove_dbgfs_file(inst); > + list_del_init(&inst->list); > + vpu_core_release_instance(core, inst->id); > + inst->id = VPU_INST_NULL_ID; > + } > + vpu_core_check_hang(core); > + if (core->state == VPU_CORE_HANG && !core->instance_mask) { > + core_dbg(core, LVL_WARN, "reset hang core\n"); > + if (!vpu_core_sw_reset(core)) { > + core->state = VPU_CORE_ACTIVE; > + core->hang_mask = 0; > + } > + } > + mutex_unlock(&core->lock); > + > + return 0; > +} > + > +struct vpu_inst *vpu_core_find_instance(struct vpu_core *core, u32 index) > +{ > + struct vpu_inst *inst = NULL; > + struct vpu_inst *tmp; > + > + mutex_lock(&core->lock); > + if (!test_bit(index, &core->instance_mask)) > + goto exit; > + list_for_each_entry(tmp, &core->instances, list) { > + if (tmp->id == index) { > + inst = vpu_inst_get(tmp); > + break; > + } > + } > +exit: > + mutex_unlock(&core->lock); > + > + return inst; > +} > + > +static int vpu_core_parse_dt(struct vpu_core *core, struct device_node *np) > +{ > + struct device_node *node; > + struct resource res; > + > + if (of_count_phandle_with_args(np, "memory-region", NULL) < 2) { > + core_err(core, "need 2 memory-region for boot and rpc\n"); > + return -ENODEV; > + } > + > + node = of_parse_phandle(np, "memory-region", 0); > + if (!node) { > + core_err(core, "boot-region of_parse_phandle error\n"); > + return -ENODEV; > + } > + if (of_address_to_resource(node, 0, &res)) { > + core_err(core, "boot-region of_address_to_resource error\n"); > + return -EINVAL; > + } > + core->fw.phys = res.start; > + core->fw.length = resource_size(&res); > + core_dbg(core, LVL_INFO, "boot-region : <%pad, 0x%x>\n", > + &core->fw.phys, core->fw.length); > + > + node = of_parse_phandle(np, "memory-region", 1); > + if (!node) { > + core_err(core, "rpc-region of_parse_phandle error\n"); > + return -ENODEV; > + } > + if (of_address_to_resource(node, 0, &res)) { > + core_err(core, "rpc-region of_address_to_resource error\n"); > + return -EINVAL; > + } > + core->rpc.phys = res.start; > + core->rpc.length = resource_size(&res); > + core_dbg(core, LVL_DEBUG, "rpc-region : <%pad, 0x%x>\n", > + &core->rpc.phys, core->rpc.length); > + > + if (core->rpc.length < core->res->rpc_size + core->res->fwlog_size) { > + core_err(core, "the rpc-region <%pad, 0x%x> is not enough\n", > + &core->rpc.phys, core->rpc.length); > + return -EINVAL; > + } > + > + core->fw.virt = ioremap_wc(core->fw.phys, core->fw.length); > + core->rpc.virt = ioremap_wc(core->rpc.phys, core->rpc.length); > + memset_io(core->rpc.virt, 0, core->rpc.length); > + > + if (vpu_iface_check_memory_region(core, > + core->rpc.phys, > + core->rpc.length) != VPU_CORE_MEMORY_UNCACHED) { > + core_err(core, "rpc region<%pad, 0x%x> isn't uncached\n", > + &core->rpc.phys, core->rpc.length); > + return -EINVAL; > + } > + > + core->log.phys = core->rpc.phys + core->res->rpc_size; > + core->log.virt = core->rpc.virt + core->res->rpc_size; > + core->log.length = core->res->fwlog_size; > + core->act.phys = core->log.phys + core->log.length; > + core->act.virt = core->log.virt + core->log.length; > + core->act.length = core->rpc.length - core->res->rpc_size - core->log.length; > + core->rpc.length = core->res->rpc_size; > + > + return 0; > +} > + > +static int vpu_core_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct vpu_core *core; > + struct vpu_dev *vpu = dev_get_drvdata(dev->parent); > + struct vpu_shared_addr *iface; > + u32 iface_data_size; > + int ret; > + > + vpu_dbg(LVL_WARN, "core %s probe\n", pdev->dev.of_node->name); > + if (!vpu) > + return -EINVAL; > + core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL); > + if (!core) > + return -ENOMEM; > + > + core->pdev = pdev; > + core->dev = dev; > + platform_set_drvdata(pdev, core); > + core->vpu = vpu; > + INIT_LIST_HEAD(&core->instances); > + mutex_init(&core->lock); > + mutex_init(&core->cmd_lock); > + init_completion(&core->cmp); > + init_waitqueue_head(&core->ack_wq); > + core->state = VPU_CORE_DEINIT; > + > + core->res = of_device_get_match_data(dev); > + if (!core->res) > + return -ENODEV; > + > + core->type = core->res->type; > + core->id = of_alias_get_id(dev->of_node, "vpu_core"); > + if (core->id < 0) { > + vpu_err("can't get vpu core id\n"); > + return core->id; > + } > + ret = vpu_core_parse_dt(core, dev->of_node); > + if (ret) > + return ret; > + > + core->base = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(core->base)) > + return PTR_ERR(core->base); > + > + if (!vpu_iface_check_codec(core)) { > + core_err(core, "is not supported\n"); > + return -EINVAL; > + } > + > + ret = vpu_mbox_init(core); > + if (ret) > + return ret; > + > + iface = devm_kzalloc(dev, sizeof(*iface), GFP_KERNEL); > + if (!iface) > + return -ENOMEM; > + > + iface_data_size = vpu_iface_get_data_size(core); > + if (iface_data_size) { > + iface->priv = devm_kzalloc(dev, iface_data_size, GFP_KERNEL); > + if (!iface->priv) > + return -ENOMEM; > + } > + > + ret = vpu_iface_init(core, iface, &core->rpc, core->fw.phys); > + if (ret) { > + core_err(core, "init iface fail, ret = %d\n", ret); > + return ret; > + } > + > + vpu_iface_config_system(core, vpu->res->mreg_base, vpu->base); > + vpu_iface_set_log_buf(core, &core->log); > + > + pm_runtime_enable(dev); > + ret = pm_runtime_get_sync(dev); > + if (ret) { > + pm_runtime_put_noidle(dev); > + pm_runtime_set_suspended(dev); > + goto err_runtime_disable; > + } > + > + if (vpu_iface_get_power_state(core)) > + ret = vpu_core_restore(core); > + if (ret) > + goto err_core_boot; > + > + ret = vpu_core_register(dev->parent, core); > + if (ret) > + goto err_core_register; > + core->parent = dev->parent; > + > + pm_runtime_put_sync(dev); > + vpu_core_create_dbgfs_file(core); > + > + return 0; > + > +err_core_register: > + vpu_core_shutdown(core); > +err_core_boot: > + pm_runtime_put_sync(dev); > +err_runtime_disable: > + pm_runtime_disable(dev); > + > + return ret; > +} > + > +static int vpu_core_remove(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct vpu_core *core = platform_get_drvdata(pdev); > + int ret; > + > + vpu_core_remove_dbgfs_file(core); > + ret = pm_runtime_get_sync(dev); > + WARN_ON(ret < 0); > + > + vpu_core_shutdown(core); > + pm_runtime_put_sync(dev); > + pm_runtime_disable(dev); > + > + vpu_core_unregister(core->parent, core); > + iounmap(core->fw.virt); > + iounmap(core->rpc.virt); > + mutex_destroy(&core->lock); > + mutex_destroy(&core->cmd_lock); > + > + return 0; > +} > + > +static int __maybe_unused vpu_core_runtime_resume(struct device *dev) > +{ > + struct vpu_core *core = dev_get_drvdata(dev); > + > + return vpu_mbox_request(core); > +} > + > +static int __maybe_unused vpu_core_runtime_suspend(struct device *dev) > +{ > + struct vpu_core *core = dev_get_drvdata(dev); > + > + vpu_mbox_free(core); > + return 0; > +} > + > +static void vpu_core_cancel_work(struct vpu_core *core) > +{ > + struct vpu_inst *inst = NULL; > + > + cancel_work_sync(&core->msg_work); > + cancel_delayed_work_sync(&core->msg_delayed_work); > + > + mutex_lock(&core->lock); > + list_for_each_entry(inst, &core->instances, list) > + cancel_work_sync(&inst->msg_work); > + mutex_unlock(&core->lock); > +} > + > +static void vpu_core_resume_work(struct vpu_core *core) > +{ > + struct vpu_inst *inst = NULL; > + unsigned long delay = msecs_to_jiffies(10); > + > + queue_work(core->workqueue, &core->msg_work); > + queue_delayed_work(core->workqueue, &core->msg_delayed_work, delay); > + > + mutex_lock(&core->lock); > + list_for_each_entry(inst, &core->instances, list) > + queue_work(inst->workqueue, &inst->msg_work); > + mutex_unlock(&core->lock); > +} > + > +static int __maybe_unused vpu_core_resume(struct device *dev) > +{ > + struct vpu_core *core = dev_get_drvdata(dev); > + int ret = 0; > + > + if (!core->res->standalone) > + return 0; > + > + mutex_lock(&core->lock); > + pm_runtime_get_sync(dev); > + vpu_core_get_vpu(core); > + if (core->state != VPU_CORE_SNAPSHOT) > + goto exit; > + > + if (!vpu_iface_get_power_state(core)) { > + if (!list_empty(&core->instances)) { > + ret = vpu_core_boot(core, false); > + if (ret) { > + core_err(core, "%s boot fail\n", __func__); > + core->state = VPU_CORE_DEINIT; > + goto exit; > + } > + core->state = VPU_CORE_ACTIVE; > + } else { > + core->state = VPU_CORE_DEINIT; > + } > + } else { > + if (!list_empty(&core->instances)) { > + ret = vpu_core_sw_reset(core); > + if (ret) { > + core_err(core, "%s sw_reset fail\n", __func__); > + core->state = VPU_CORE_HANG; > + goto exit; > + } > + } > + core->state = VPU_CORE_ACTIVE; > + } > + > +exit: > + pm_runtime_put_sync(dev); > + mutex_unlock(&core->lock); > + > + vpu_core_resume_work(core); > + return ret; > +} > + > +static int __maybe_unused vpu_core_suspend(struct device *dev) > +{ > + struct vpu_core *core = dev_get_drvdata(dev); > + int ret = 0; > + > + if (!core->res->standalone) > + return 0; > + > + mutex_lock(&core->lock); > + if (core->state == VPU_CORE_ACTIVE) { > + if (!list_empty(&core->instances)) { > + ret = vpu_core_snapshot(core); > + if (ret) { > + mutex_unlock(&core->lock); > + return ret; > + } > + } > + > + core->state = VPU_CORE_SNAPSHOT; > + } > + mutex_unlock(&core->lock); > + > + vpu_core_cancel_work(core); > + > + mutex_lock(&core->lock); > + vpu_core_put_vpu(core); > + mutex_unlock(&core->lock); > + return ret; > +} > + > +static const struct dev_pm_ops vpu_core_pm_ops = { > + SET_RUNTIME_PM_OPS(vpu_core_runtime_suspend, vpu_core_runtime_resume, NULL) > + SET_SYSTEM_SLEEP_PM_OPS(vpu_core_suspend, vpu_core_resume) > +}; > + > +static struct vpu_core_resources imx8q_enc = { > + .type = VPU_CORE_TYPE_ENC, > + .fwname = "vpu/vpu_fw_imx8_enc.bin", > + .stride = 16, > + .max_width = 1920, > + .max_height = 1920, > + .min_width = 64, > + .min_height = 48, > + .step_width = 2, > + .step_height = 2, > + .rpc_size = 0x80000, > + .fwlog_size = 0x80000, > + .act_size = 0xc0000, > + .standalone = true, > +}; > + > +static struct vpu_core_resources imx8q_dec = { > + .type = VPU_CORE_TYPE_DEC, > + .fwname = "vpu/vpu_fw_imx8_dec.bin", > + .stride = 256, > + .max_width = 8188, > + .max_height = 8188, > + .min_width = 16, > + .min_height = 16, > + .step_width = 1, > + .step_height = 1, > + .rpc_size = 0x80000, > + .fwlog_size = 0x80000, > + .standalone = true, > +}; > + > +static const struct of_device_id vpu_core_dt_match[] = { > + { .compatible = "nxp,imx8q-vpu-encoder", .data = &imx8q_enc }, > + { .compatible = "nxp,imx8q-vpu-decoder", .data = &imx8q_dec }, > + {} > +}; > +MODULE_DEVICE_TABLE(of, vpu_core_dt_match); > + > +static struct platform_driver amphion_vpu_core_driver = { > + .probe = vpu_core_probe, > + .remove = vpu_core_remove, > + .driver = { > + .name = "amphion-vpu-core", > + .of_match_table = vpu_core_dt_match, > + .pm = &vpu_core_pm_ops, > + }, > +}; > +module_platform_driver(amphion_vpu_core_driver); > + > +MODULE_AUTHOR("Freescale Semiconductor, Inc."); > +MODULE_DESCRIPTION("Linux VPU driver for Freescale i.MX8Q"); > +MODULE_LICENSE("GPL v2"); > diff --git a/drivers/media/platform/amphion/vpu_core.h b/drivers/media/platform/amphion/vpu_core.h > new file mode 100644 > index 000000000000..12880e2e14b2 > --- /dev/null > +++ b/drivers/media/platform/amphion/vpu_core.h > @@ -0,0 +1,16 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright 2020-2021 NXP > + */ > + > +#ifndef _AMPHION_VPU_CORE_H > +#define _AMPHION_VPU_CORE_H > + > +void csr_writel(struct vpu_core *core, u32 reg, u32 val); > +u32 csr_readl(struct vpu_core *core, u32 reg); > +int vpu_alloc_dma(struct vpu_core *core, struct vpu_buffer *buf); > +void vpu_free_dma(struct vpu_buffer *buf); > +struct vpu_inst *vpu_core_find_instance(struct vpu_core *core, u32 index); > +int vpu_core_check_fmt(struct vpu_core *core, u32 pixelfmt); > + > +#endif > diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c > new file mode 100644 > index 000000000000..4dbfbd6d2f46 > --- /dev/null > +++ b/drivers/media/platform/amphion/vpu_dbg.c > @@ -0,0 +1,496 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright 2020-2021 NXP > + */ > + > +#define TAG "DEBUG" > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "vpu.h" > +#include "vpu_defs.h" > +#include "vpu_helpers.h" > +#include "vpu_cmds.h" > +#include "vpu_rpc.h" > +#include "vpu_log.h" > + > +struct print_buf_desc { > + u32 start_h_phy; > + u32 start_h_vir; > + u32 start_m; > + u32 bytes; > + u32 read; > + u32 write; > + char buffer[0]; > +}; > + > +static char *vb2_stat_name[] = { > + [VB2_BUF_STATE_DEQUEUED] = "dequeued", > + [VB2_BUF_STATE_IN_REQUEST] = "in_request", > + [VB2_BUF_STATE_PREPARING] = "preparing", > + [VB2_BUF_STATE_QUEUED] = "queued", > + [VB2_BUF_STATE_ACTIVE] = "active", > + [VB2_BUF_STATE_DONE] = "done", > + [VB2_BUF_STATE_ERROR] = "error", > +}; > + > +static char *vpu_stat_name[] = { > + [VPU_BUF_STATE_IDLE] = "idle", > + [VPU_BUF_STATE_INUSE] = "inuse", > + [VPU_BUF_STATE_DECODED] = "decoded", > + [VPU_BUF_STATE_READY] = "ready", > + [VPU_BUF_STATE_SKIP] = "skip", > + [VPU_BUF_STATE_ERROR] = "error", > +}; > + > +static int vpu_dbg_instance(struct seq_file *s, void *data) > +{ > + struct vpu_inst *inst = s->private; > + char str[128]; > + int num; > + struct vb2_queue *vq; > + int i; > + > + num = scnprintf(str, sizeof(str), "[%s]\n", vpu_core_type_desc(inst->type)); > + if (seq_write(s, str, num)) > + return 0; > + > + num = scnprintf(str, sizeof(str), "tgig = %d,pid = %d\n", inst->tgid, inst->pid); > + if (seq_write(s, str, num)) > + return 0; > + num = scnprintf(str, sizeof(str), "state = %d\n", inst->state); > + if (seq_write(s, str, num)) > + return 0; > + num = scnprintf(str, sizeof(str), > + "min_buffer_out = %d, min_buffer_cap = %d\n", > + inst->min_buffer_out, inst->min_buffer_cap); > + if (seq_write(s, str, num)) > + return 0; > + > + > + vq = v4l2_m2m_get_src_vq(inst->m2m_ctx); > + num = scnprintf(str, sizeof(str), > + "output(%d) : fmt = %c%c%c%c %d x %d, %d;", > + vb2_is_streaming(vq), > + inst->out_format.pixfmt, > + inst->out_format.pixfmt >> 8, > + inst->out_format.pixfmt >> 16, > + inst->out_format.pixfmt >> 24, > + inst->out_format.width, > + inst->out_format.height, > + vq->last_buffer_dequeued); > + if (seq_write(s, str, num)) > + return 0; > + for (i = 0; i < inst->out_format.num_planes; i++) { > + num = scnprintf(str, sizeof(str), " %d(%d)", > + inst->out_format.sizeimage[i], > + inst->out_format.bytesperline[i]); > + if (seq_write(s, str, num)) > + return 0; > + } > + if (seq_write(s, "\n", 1)) > + return 0; > + > + vq = v4l2_m2m_get_dst_vq(inst->m2m_ctx); > + num = scnprintf(str, sizeof(str), > + "capture(%d): fmt = %c%c%c%c %d x %d, %d;", > + vb2_is_streaming(vq), > + inst->cap_format.pixfmt, > + inst->cap_format.pixfmt >> 8, > + inst->cap_format.pixfmt >> 16, > + inst->cap_format.pixfmt >> 24, > + inst->cap_format.width, > + inst->cap_format.height, > + vq->last_buffer_dequeued); > + if (seq_write(s, str, num)) > + return 0; > + for (i = 0; i < inst->cap_format.num_planes; i++) { > + num = scnprintf(str, sizeof(str), " %d(%d)", > + inst->cap_format.sizeimage[i], > + inst->cap_format.bytesperline[i]); > + if (seq_write(s, str, num)) > + return 0; > + } > + if (seq_write(s, "\n", 1)) > + return 0; > + num = scnprintf(str, sizeof(str), "crop: (%d, %d) %d x %d\n", > + inst->crop.left, > + inst->crop.top, > + inst->crop.width, > + inst->crop.height); > + if (seq_write(s, str, num)) > + return 0; > + > + vq = v4l2_m2m_get_src_vq(inst->m2m_ctx); > + for (i = 0; i < vq->num_buffers; i++) { > + struct vb2_buffer *vb = vq->bufs[i]; > + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); > + struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf); > + > + if (vb->state == VB2_BUF_STATE_DEQUEUED) > + continue; > + num = scnprintf(str, sizeof(str), > + "output [%2d] state = %10s, %8s\n", > + i, vb2_stat_name[vb->state], > + vpu_stat_name[vpu_buf->state]); > + if (seq_write(s, str, num)) > + return 0; > + } > + > + vq = v4l2_m2m_get_dst_vq(inst->m2m_ctx); > + for (i = 0; i < vq->num_buffers; i++) { > + struct vb2_buffer *vb = vq->bufs[i]; > + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); > + struct vpu_vb2_buffer *vpu_buf = to_vpu_vb2_buffer(vbuf); > + > + if (vb->state == VB2_BUF_STATE_DEQUEUED) > + continue; > + num = scnprintf(str, sizeof(str), > + "capture[%2d] state = %10s, %8s\n", > + i, vb2_stat_name[vb->state], > + vpu_stat_name[vpu_buf->state]); > + if (seq_write(s, str, num)) > + return 0; > + } > + > + num = scnprintf(str, sizeof(str), "sequence = %d\n", inst->sequence); > + if (seq_write(s, str, num)) > + return 0; > + > + if (inst->use_stream_buffer) { > + num = scnprintf(str, sizeof(str), "stream_buffer = %d / %d, <%pad, 0x%x>\n", > + vpu_helper_get_used_space(inst), > + inst->stream_buffer.length, > + &inst->stream_buffer.phys, > + inst->stream_buffer.length); > + if (seq_write(s, str, num)) > + return 0; > + } > + num = scnprintf(str, sizeof(str), "kfifo len = 0x%x\n", kfifo_len(&inst->msg_fifo)); > + if (seq_write(s, str, num)) > + return 0; > + > + num = scnprintf(str, sizeof(str), "flow :\n"); > + if (seq_write(s, str, num)) > + return 0; > + > + mutex_lock(&inst->core->cmd_lock); > + for (i = 0; i < ARRAY_SIZE(inst->flows); i++) { > + u32 idx = (inst->flow_idx + i) % (ARRAY_SIZE(inst->flows)); > + > + if (!inst->flows[idx]) > + continue; > + num = scnprintf(str, sizeof(str), "\t[%s]0x%x\n", > + inst->flows[idx] >= VPU_MSG_ID_NOOP ? "M" : "C", > + inst->flows[idx]); > + if (seq_write(s, str, num)) { > + mutex_unlock(&inst->core->cmd_lock); > + return 0; > + } > + } > + mutex_unlock(&inst->core->cmd_lock); > + > + i = 0; > + while (true) { > + num = call_vop(inst, get_debug_info, str, sizeof(str), i++); > + if (num <= 0) > + break; > + if (seq_write(s, str, num)) > + return 0; > + } > + > + return 0; > +} > + > +static int vpu_dbg_core(struct seq_file *s, void *data) > +{ > + struct vpu_core *core = s->private; > + struct vpu_shared_addr *iface = core->iface; > + char str[128]; > + int num; > + > + num = scnprintf(str, sizeof(str), "[%s]\n", vpu_core_type_desc(core->type)); > + if (seq_write(s, str, num)) > + return 0; > + > + num = scnprintf(str, sizeof(str), "boot_region = <%pad, 0x%x>\n", > + &core->fw.phys, core->fw.length); > + if (seq_write(s, str, num)) > + return 0; > + num = scnprintf(str, sizeof(str), "rpc_region = <%pad, 0x%x> used = 0x%x\n", > + &core->rpc.phys, core->rpc.length, core->rpc.bytesused); > + if (seq_write(s, str, num)) > + return 0; > + num = scnprintf(str, sizeof(str), "fwlog_region = <%pad, 0x%x>\n", > + &core->log.phys, core->log.length); > + if (seq_write(s, str, num)) > + return 0; > + > + num = scnprintf(str, sizeof(str), "state = %d\n", core->state); > + if (seq_write(s, str, num)) > + return 0; > + if (core->state == VPU_CORE_DEINIT) > + return 0; > + num = scnprintf(str, sizeof(str), "fw version = %d.%d.%d\n", > + (core->fw_version >> 16) & 0xff, > + (core->fw_version >> 8) & 0xff, > + core->fw_version & 0xff); > + if (seq_write(s, str, num)) > + return 0; > + num = scnprintf(str, sizeof(str), "instances = %d/%d (0x%02lx), %d\n", > + hweight32(core->instance_mask), > + core->supported_instance_count, > + core->instance_mask, > + core->request_count); > + if (seq_write(s, str, num)) > + return 0; > + num = scnprintf(str, sizeof(str), "kfifo len = 0x%x\n", kfifo_len(&core->msg_fifo)); > + if (seq_write(s, str, num)) > + return 0; > + num = scnprintf(str, sizeof(str), > + "cmd_buf:[0x%x, 0x%x], wptr = 0x%x, rptr = 0x%x\n", > + iface->cmd_desc->start, > + iface->cmd_desc->end, > + iface->cmd_desc->wptr, > + iface->cmd_desc->rptr); > + if (seq_write(s, str, num)) > + return 0; > + num = scnprintf(str, sizeof(str), > + "msg_buf:[0x%x, 0x%x], wptr = 0x%x, rptr = 0x%x\n", > + iface->msg_desc->start, > + iface->msg_desc->end, > + iface->msg_desc->wptr, > + iface->msg_desc->rptr); > + if (seq_write(s, str, num)) > + return 0; > + > + return 0; > +} > + > +static int vpu_dbg_fwlog(struct seq_file *s, void *data) > +{ > + struct vpu_core *core = s->private; > + struct print_buf_desc *print_buf; > + int length; > + u32 rptr; > + u32 wptr; > + int ret = 0; > + > + if (!core->log.virt || core->state == VPU_CORE_DEINIT) > + return 0; > + > + print_buf = core->log.virt; > + rptr = print_buf->read; > + wptr = print_buf->write; > + > + if (rptr == wptr) > + return 0; > + else if (rptr < wptr) > + length = wptr - rptr; > + else > + length = print_buf->bytes + wptr - rptr; > + > + if (s->count + length >= s->size) { > + s->count = s->size; > + return 0; > + } > + > + if (rptr + length >= print_buf->bytes) { > + int num = print_buf->bytes - rptr; > + > + if (seq_write(s, print_buf->buffer + rptr, num)) > + ret = -1; > + length -= num; > + rptr = 0; > + } > + > + if (length) { > + if (seq_write(s, print_buf->buffer + rptr, length)) > + ret = -1; > + rptr += length; > + } > + if (!ret) > + print_buf->read = rptr; > + > + return 0; > +} > + > +static int vpu_dbg_inst_open(struct inode *inode, struct file *filp) > +{ > + return single_open(filp, vpu_dbg_instance, inode->i_private); > +} > + > +static ssize_t vpu_dbg_inst_write(struct file *file, > + const char __user *user_buf, size_t size, loff_t *ppos) > +{ > + struct seq_file *s = file->private_data; > + struct vpu_inst *inst = s->private; > + > + vpu_session_debug(inst); > + > + return size; > +} > + > +static ssize_t vpu_dbg_core_write(struct file *file, > + const char __user *user_buf, size_t size, loff_t *ppos) > +{ > + struct seq_file *s = file->private_data; > + struct vpu_core *core = s->private; > + > + pm_runtime_get_sync(core->dev); > + mutex_lock(&core->lock); > + if (core->state != VPU_CORE_DEINIT && !core->instance_mask) { > + core_dbg(core, LVL_INFO, "reset core\n"); > + if (!vpu_core_sw_reset(core)) { > + core->state = VPU_CORE_ACTIVE; > + core->hang_mask = 0; > + } > + } > + mutex_unlock(&core->lock); > + pm_runtime_put_sync(core->dev); > + > + return size; > +} > + > +static int vpu_dbg_core_open(struct inode *inode, struct file *filp) > +{ > + return single_open(filp, vpu_dbg_core, inode->i_private); > +} > + > +static int vpu_dbg_fwlog_open(struct inode *inode, struct file *filp) > +{ > + return single_open(filp, vpu_dbg_fwlog, inode->i_private); > +} > + > +static const struct file_operations vpu_dbg_inst_fops = { > + .owner = THIS_MODULE, > + .open = vpu_dbg_inst_open, > + .release = single_release, > + .read = seq_read, > + .write = vpu_dbg_inst_write, > +}; > + > +static const struct file_operations vpu_dbg_core_fops = { > + .owner = THIS_MODULE, > + .open = vpu_dbg_core_open, > + .release = single_release, > + .read = seq_read, > + .write = vpu_dbg_core_write, > +}; > + > +static const struct file_operations vpu_dbg_fwlog_fops = { > + .owner = THIS_MODULE, > + .open = vpu_dbg_fwlog_open, > + .release = single_release, > + .read = seq_read, > +}; > + > +int vpu_inst_create_dbgfs_file(struct vpu_inst *inst) > +{ > + struct vpu_dev *vpu; > + char name[64]; > + > + if (!inst || !inst->core || !inst->core->vpu) > + return -EINVAL; > + > + vpu = inst->core->vpu; > + if (!vpu->debugfs) > + return -EINVAL; > + > + if (inst->debugfs) > + return 0; > + > + scnprintf(name, sizeof(name), "instance.%d.%d", > + inst->core->id, inst->id); > + inst->debugfs = debugfs_create_file((const char *)name, > + VERIFY_OCTAL_PERMISSIONS(0644), > + vpu->debugfs, > + inst, > + &vpu_dbg_inst_fops); > + if (!inst->debugfs) { > + vpu_err("vpu create debugfs %s fail\n", name); > + return -EINVAL; > + } > + > + return 0; > +} > + > +int vpu_inst_remove_dbgfs_file(struct vpu_inst *inst) > +{ > + if (!inst) > + return 0; > + > + debugfs_remove(inst->debugfs); > + inst->debugfs = NULL; > + > + return 0; > +} > + > +int vpu_core_create_dbgfs_file(struct vpu_core *core) > +{ > + struct vpu_dev *vpu; > + char name[64]; > + > + if (!core || !core->vpu) > + return -EINVAL; > + > + vpu = core->vpu; > + if (!vpu->debugfs) > + return -EINVAL; > + > + if (!core->debugfs) { > + scnprintf(name, sizeof(name), "core.%d", core->id); > + core->debugfs = debugfs_create_file((const char *)name, > + VERIFY_OCTAL_PERMISSIONS(0644), > + vpu->debugfs, > + core, > + &vpu_dbg_core_fops); > + if (!core->debugfs) { > + vpu_err("vpu create debugfs %s fail\n", name); > + return -EINVAL; > + } > + } > + if (!core->debugfs_fwlog) { > + scnprintf(name, sizeof(name), "fwlog.%d", core->id); > + core->debugfs_fwlog = debugfs_create_file((const char *)name, > + VERIFY_OCTAL_PERMISSIONS(0444), > + vpu->debugfs, > + core, > + &vpu_dbg_fwlog_fops); > + if (!core->debugfs_fwlog) { > + vpu_err("vpu create debugfs %s fail\n", name); > + return -EINVAL; > + } > + } > + > + return 0; > +} > + > +int vpu_core_remove_dbgfs_file(struct vpu_core *core) > +{ > + if (!core) > + return 0; > + debugfs_remove(core->debugfs); > + core->debugfs = NULL; > + debugfs_remove(core->debugfs_fwlog); > + core->debugfs_fwlog = NULL; > + > + return 0; > +} > + > +void vpu_inst_record_flow(struct vpu_inst *inst, u32 flow) > +{ > + if (!inst) > + return; > + > + inst->flows[inst->flow_idx] = flow; > + inst->flow_idx = (inst->flow_idx + 1) % (ARRAY_SIZE(inst->flows)); > +} > diff --git a/drivers/media/platform/amphion/vpu_log.h b/drivers/media/platform/amphion/vpu_log.h > new file mode 100644 > index 000000000000..fec98368fad1 > --- /dev/null > +++ b/drivers/media/platform/amphion/vpu_log.h > @@ -0,0 +1,44 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright 2020-2021 NXP > + */ > + > +#ifndef _AMPHION_VPU_LOG_H > +#define _AMPHION_VPU_LOG_H > + > +#define LVL_ERR (1 << 0) > +#define LVL_WARN (1 << 1) > +#define LVL_INFO (1 << 2) > +#define LVL_DEBUG (1 << 3) > +#define LVL_IRQ (1 << 4) > +#define LVL_CMD (1 << 5) > +#define LVL_EVT (1 << 6) > +#define LVL_CTRL (1 << 7) > +#define LVL_TS (1 << 8) > +#define LVL_FLOW (1 << 13) > + > +extern unsigned int vpu_dbg_level; > + > +#ifdef TAG > +#define vpu_dbg(level, fmt, arg...) \ > + do { \ > + if ((vpu_dbg_level & (level)) || ((level) & LVL_ERR)) \ > + pr_info("[VPU "TAG"]"fmt, ## arg); \ > + } while (0) > +#else > +#define vpu_dbg(level, fmt, arg...) \ > + do { \ > + if ((vpu_dbg_level & (level)) || ((level) & LVL_ERR)) \ > + pr_info("[VPU]"fmt, ## arg); \ > + } while (0) > +#endif > + > +#define vpu_err(fmt, arg...) vpu_dbg(LVL_ERR, fmt, ##arg) > +#define inst_dbg(inst, level, fmt, arg...) \ > + vpu_dbg(level, "[%d:%d] "fmt, inst->core->id, inst->id, ## arg) > +#define inst_err(inst, fmt, arg...) inst_dbg(inst, LVL_ERR, fmt, ## arg) > +#define core_dbg(core, level, fmt, arg...) \ > + vpu_dbg(level, "[%d] %s "fmt, core->id, vpu_core_type_desc(core->type), ## arg) > +#define core_err(core, fmt, arg...) core_dbg(core, LVL_ERR, fmt, ## arg) > + > +#endif > diff --git a/drivers/media/platform/amphion/vpu_rpc.c b/drivers/media/platform/amphion/vpu_rpc.c > new file mode 100644 > index 000000000000..21c95b20d48d > --- /dev/null > +++ b/drivers/media/platform/amphion/vpu_rpc.c > @@ -0,0 +1,263 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright 2020-2021 NXP > + */ > + > +#define TAG "RPC" > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "vpu.h" > +#include "vpu_rpc.h" > +#include "vpu_imx8q.h" > +#include "vpu_windsor.h" > +#include "vpu_malone.h" > +#include "vpu_log.h" > + > +u32 vpu_iface_check_memory_region(struct vpu_core *core, dma_addr_t addr, u32 size) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (!ops || !ops->check_memory_region) > + return VPU_CORE_MEMORY_INVALID; > + > + return ops->check_memory_region(core->fw.phys, addr, size); > +} > + > +static u32 vpu_rpc_check_buffer_space(struct vpu_rpc_buffer_desc *desc, bool write) > +{ > + u32 ptr1; > + u32 ptr2; > + u32 size; > + > + WARN_ON(!desc); > + > + size = desc->end - desc->start; > + if (write) { > + ptr1 = desc->wptr; > + ptr2 = desc->rptr; > + } else { > + ptr1 = desc->rptr; > + ptr2 = desc->wptr; > + } > + > + if (ptr1 == ptr2) { > + if (!write) > + return 0; > + else > + return size; > + } > + > + return (ptr2 + size - ptr1) % size; > +} > + > +static int vpu_rpc_send_cmd_buf(struct vpu_shared_addr *shared, > + struct vpu_rpc_event *cmd) > +{ > + struct vpu_rpc_buffer_desc *desc; > + u32 space = 0; > + u32 *data; > + u32 wptr; > + u32 i; > + > + WARN_ON(!shared || !shared->cmd_mem_vir || !cmd); > + > + desc = shared->cmd_desc; > + space = vpu_rpc_check_buffer_space(desc, true); > + if (space < (((cmd->hdr.num + 1) << 2) + 16)) { > + vpu_err("Cmd Buffer is no space for [%d] %d\n", > + cmd->hdr.index, cmd->hdr.id); > + return -EINVAL; > + } > + wptr = desc->wptr; > + data = (u32 *)(shared->cmd_mem_vir + desc->wptr - desc->start); > + *data = 0; > + *data |= ((cmd->hdr.index & 0xff) << 24); > + *data |= ((cmd->hdr.num & 0xff) << 16); > + *data |= (cmd->hdr.id & 0x3fff); > + wptr += 4; > + data++; > + if (wptr >= desc->end) { > + wptr = desc->start; > + data = shared->cmd_mem_vir; > + } > + > + for (i = 0; i < cmd->hdr.num; i++) { > + *data = cmd->data[i]; > + wptr += 4; > + data++; > + if (wptr >= desc->end) { > + wptr = desc->start; > + data = shared->cmd_mem_vir; > + } > + } > + > + /*update wptr after data is written*/ > + mb(); > + desc->wptr = wptr; > + > + return 0; > +} > + > +static bool vpu_rpc_check_msg(struct vpu_shared_addr *shared) > +{ > + struct vpu_rpc_buffer_desc *desc; > + u32 space = 0; > + u32 msgword; > + u32 msgnum; > + > + WARN_ON(!shared || !shared->msg_desc); > + > + desc = shared->msg_desc; > + space = vpu_rpc_check_buffer_space(desc, 0); > + space = (space >> 2); > + > + if (space) { > + msgword = *(u32 *)(shared->msg_mem_vir + desc->rptr - desc->start); > + msgnum = (msgword & 0xff0000) >> 16; > + if (msgnum <= space) > + return true; > + } > + > + return false; > +} > + > +static int vpu_rpc_receive_msg_buf(struct vpu_shared_addr *shared, struct vpu_rpc_event *msg) > +{ > + struct vpu_rpc_buffer_desc *desc; > + u32 *data; > + u32 msgword; > + u32 rptr; > + u32 i; > + > + WARN_ON(!shared || !shared->msg_desc || !msg); > + > + if (!vpu_rpc_check_msg(shared)) > + return -EINVAL; > + > + desc = shared->msg_desc; > + data = (u32 *)(shared->msg_mem_vir + desc->rptr - desc->start); > + rptr = desc->rptr; > + msgword = *data; > + data++; > + rptr += 4; > + if (rptr >= desc->end) { > + rptr = desc->start; > + data = shared->msg_mem_vir; > + } > + > + msg->hdr.index = (msgword >> 24) & 0xff; > + msg->hdr.num = (msgword >> 16) & 0xff; > + msg->hdr.id = msgword & 0x3fff; > + > + if (msg->hdr.num > ARRAY_SIZE(msg->data)) { > + vpu_err("msg(%d) data length(%d) is out of range\n", > + msg->hdr.id, msg->hdr.num); > + return -EINVAL; > + } > + > + for (i = 0; i < msg->hdr.num; i++) { > + msg->data[i] = *data; > + data++; > + rptr += 4; > + if (rptr >= desc->end) { > + rptr = desc->start; > + data = shared->msg_mem_vir; > + } > + } > + > + /*update rptr after data is read*/ > + mb(); > + desc->rptr = rptr; > + > + return 0; > +} > + > +struct vpu_iface_ops imx8q_rpc_ops[] = { > + [VPU_CORE_TYPE_ENC] = { > + .check_codec = vpu_imx8q_check_codec, > + .check_fmt = vpu_imx8q_check_fmt, > + .boot_core = vpu_imx8q_boot_core, > + .get_power_state = vpu_imx8q_get_power_state, > + .on_firmware_loaded = vpu_imx8q_on_firmware_loaded, > + .get_data_size = vpu_windsor_get_data_size, > + .check_memory_region = vpu_imx8q_check_memory_region, > + .init_rpc = vpu_windsor_init_rpc, > + .set_log_buf = vpu_windsor_set_log_buf, > + .set_system_cfg = vpu_windsor_set_system_cfg, > + .get_version = vpu_windsor_get_version, > + .send_cmd_buf = vpu_rpc_send_cmd_buf, > + .receive_msg_buf = vpu_rpc_receive_msg_buf, > + .pack_cmd = vpu_windsor_pack_cmd, > + .convert_msg_id = vpu_windsor_convert_msg_id, > + .unpack_msg_data = vpu_windsor_unpack_msg_data, > + .config_memory_resource = vpu_windsor_config_memory_resource, > + .get_stream_buffer_size = vpu_windsor_get_stream_buffer_size, > + .config_stream_buffer = vpu_windsor_config_stream_buffer, > + .get_stream_buffer_desc = vpu_windsor_get_stream_buffer_desc, > + .update_stream_buffer = vpu_windsor_update_stream_buffer, > + .set_encode_params = vpu_windsor_set_encode_params, > + .input_frame = vpu_windsor_input_frame, > + .get_max_instance_count = vpu_windsor_get_max_instance_count, > + }, > + [VPU_CORE_TYPE_DEC] = { > + .check_codec = vpu_imx8q_check_codec, > + .check_fmt = vpu_imx8q_check_fmt, > + .boot_core = vpu_imx8q_boot_core, > + .get_power_state = vpu_imx8q_get_power_state, > + .on_firmware_loaded = vpu_imx8q_on_firmware_loaded, > + .get_data_size = vpu_malone_get_data_size, > + .check_memory_region = vpu_imx8q_check_memory_region, > + .init_rpc = vpu_malone_init_rpc, > + .set_log_buf = vpu_malone_set_log_buf, > + .set_system_cfg = vpu_malone_set_system_cfg, > + .get_version = vpu_malone_get_version, > + .send_cmd_buf = vpu_rpc_send_cmd_buf, > + .receive_msg_buf = vpu_rpc_receive_msg_buf, > + .get_stream_buffer_size = vpu_malone_get_stream_buffer_size, > + .config_stream_buffer = vpu_malone_config_stream_buffer, > + .set_decode_params = vpu_malone_set_decode_params, > + .pack_cmd = vpu_malone_pack_cmd, > + .convert_msg_id = vpu_malone_convert_msg_id, > + .unpack_msg_data = vpu_malone_unpack_msg_data, > + .get_stream_buffer_desc = vpu_malone_get_stream_buffer_desc, > + .update_stream_buffer = vpu_malone_update_stream_buffer, > + .add_scode = vpu_malone_add_scode, > + .input_frame = vpu_malone_input_frame, > + .pre_send_cmd = vpu_malone_pre_cmd, > + .post_send_cmd = vpu_malone_post_cmd, > + .init_instance = vpu_malone_init_instance, > + .get_max_instance_count = vpu_malone_get_max_instance_count, > + }, > +}; > + > +struct vpu_iface_ops *vpu_iface_get(struct vpu_core *core) > +{ > + struct vpu_iface_ops *rpc_ops = NULL; > + u32 size = 0; > + > + WARN_ON(!core || !core->vpu || !core->vpu->res); > + > + switch (core->vpu->res->plat_type) { > + case IMX8QXP: > + case IMX8QM: > + rpc_ops = imx8q_rpc_ops; > + size = ARRAY_SIZE(imx8q_rpc_ops); > + break; > + default: > + return NULL; > + } > + > + if (core->type >= size) > + return NULL; > + > + return &rpc_ops[core->type]; > +} > diff --git a/drivers/media/platform/amphion/vpu_rpc.h b/drivers/media/platform/amphion/vpu_rpc.h > new file mode 100644 > index 000000000000..b066a83e67d3 > --- /dev/null > +++ b/drivers/media/platform/amphion/vpu_rpc.h > @@ -0,0 +1,463 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * Copyright 2020-2021 NXP > + */ > + > +#ifndef _AMPHION_VPU_RPC_H > +#define _AMPHION_VPU_RPC_H > + > +#include > +#include "vpu_codec.h" > + > +struct vpu_rpc_buffer_desc { > + u32 wptr; > + u32 rptr; > + u32 start; > + u32 end; > +}; > + > +struct vpu_shared_addr { > + void *iface; > + struct vpu_rpc_buffer_desc *cmd_desc; > + void *cmd_mem_vir; > + struct vpu_rpc_buffer_desc *msg_desc; > + void *msg_mem_vir; > + > + unsigned long boot_addr; > + struct vpu_core *core; > + void *priv; > +}; > + > +struct vpu_rpc_event_header { > + u32 index; > + u32 id; > + u32 num; > +}; > + > +struct vpu_rpc_event { > + struct vpu_rpc_event_header hdr; > + u32 data[128]; > +}; > + > +struct vpu_iface_ops { > + bool (*check_codec)(enum vpu_core_type type); > + bool (*check_fmt)(enum vpu_core_type type, u32 pixelfmt); > + u32 (*get_data_size)(void); > + u32 (*check_memory_region)(dma_addr_t base, dma_addr_t addr, u32 size); > + int (*boot_core)(struct vpu_core *core); > + int (*shutdown_core)(struct vpu_core *core); > + int (*restore_core)(struct vpu_core *core); > + int (*get_power_state)(struct vpu_core *core); > + int (*on_firmware_loaded)(struct vpu_core *core); > + void (*init_rpc)(struct vpu_shared_addr *shared, > + struct vpu_buffer *rpc, dma_addr_t boot_addr); > + void (*set_log_buf)(struct vpu_shared_addr *shared, > + struct vpu_buffer *log); > + void (*set_system_cfg)(struct vpu_shared_addr *shared, > + u32 regs_base, void __iomem *regs, u32 index); > + void (*set_stream_cfg)(struct vpu_shared_addr *shared, u32 index); > + u32 (*get_version)(struct vpu_shared_addr *shared); > + u32 (*get_max_instance_count)(struct vpu_shared_addr *shared); > + int (*get_stream_buffer_size)(struct vpu_shared_addr *shared); > + int (*send_cmd_buf)(struct vpu_shared_addr *shared, > + struct vpu_rpc_event *cmd); > + int (*receive_msg_buf)(struct vpu_shared_addr *shared, > + struct vpu_rpc_event *msg); > + int (*pack_cmd)(struct vpu_rpc_event *pkt, u32 index, u32 id, void *data); > + int (*convert_msg_id)(u32 msg_id); > + int (*unpack_msg_data)(struct vpu_rpc_event *pkt, void *data); > + int (*input_frame)(struct vpu_shared_addr *shared, > + struct vpu_inst *inst, struct vb2_buffer *vb); > + int (*config_memory_resource)(struct vpu_shared_addr *shared, > + u32 instance, > + u32 type, > + u32 index, > + struct vpu_buffer *buf); > + int (*config_stream_buffer)(struct vpu_shared_addr *shared, > + u32 instance, > + struct vpu_buffer *buf); > + int (*update_stream_buffer)(struct vpu_shared_addr *shared, > + u32 instance, u32 ptr, bool write); > + int (*get_stream_buffer_desc)(struct vpu_shared_addr *shared, > + u32 instance, > + struct vpu_rpc_buffer_desc *desc); > + int (*set_encode_params)(struct vpu_shared_addr *shared, > + u32 instance, > + struct vpu_encode_params *params, u32 update); > + int (*set_decode_params)(struct vpu_shared_addr *shared, > + u32 instance, > + struct vpu_decode_params *params, u32 update); > + int (*add_scode)(struct vpu_shared_addr *shared, > + u32 instance, > + struct vpu_buffer *stream_buffer, > + u32 pixelformat, > + u32 scode_type); > + int (*pre_send_cmd)(struct vpu_shared_addr *shared, u32 instance); > + int (*post_send_cmd)(struct vpu_shared_addr *shared, u32 instance); > + int (*init_instance)(struct vpu_shared_addr *shared, u32 instance); > +}; > + > +enum { > + VPU_CORE_MEMORY_INVALID = 0, > + VPU_CORE_MEMORY_CACHED, > + VPU_CORE_MEMORY_UNCACHED > +}; > + > +struct vpu_rpc_region_t { > + dma_addr_t start; > + dma_addr_t end; > + dma_addr_t type; > +}; > + > +struct vpu_iface_ops *vpu_iface_get(struct vpu_core *core); > +u32 vpu_iface_check_memory_region(struct vpu_core *core, dma_addr_t addr, u32 size); > + > +static inline bool vpu_iface_check_codec(struct vpu_core *core) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (ops && ops->check_codec) > + return ops->check_codec(core->type); > + > + return true; > +} > + > +static inline bool vpu_iface_check_format(struct vpu_core *core, u32 pixelfmt) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (ops && ops->check_fmt) > + return ops->check_fmt(core->type, pixelfmt); > + > + return true; > +} > + > +static inline int vpu_iface_boot_core(struct vpu_core *core) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (ops && ops->boot_core) > + return ops->boot_core(core); > + return 0; > +} > + > +static inline int vpu_iface_get_power_state(struct vpu_core *core) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (ops && ops->get_power_state) > + return ops->get_power_state(core); > + return 1; > +} > + > +static inline int vpu_iface_shutdown_core(struct vpu_core *core) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (ops && ops->shutdown_core) > + return ops->shutdown_core(core); > + return 0; > +} > + > +static inline int vpu_iface_restore_core(struct vpu_core *core) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (ops && ops->restore_core) > + return ops->restore_core(core); > + return -EINVAL; > +} > + > +static inline int vpu_iface_on_firmware_loaded(struct vpu_core *core) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (ops && ops->on_firmware_loaded) > + return ops->on_firmware_loaded(core); > + > + return 0; > +} > + > +static inline u32 vpu_iface_get_data_size(struct vpu_core *core) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (!ops || !ops->get_data_size) > + return 0; > + > + return ops->get_data_size(); > +} > + > +static inline int vpu_iface_init(struct vpu_core *core, > + struct vpu_shared_addr *shared, > + struct vpu_buffer *rpc, > + dma_addr_t boot_addr) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (!ops || !ops->init_rpc) > + return -EINVAL; > + > + ops->init_rpc(shared, rpc, boot_addr); > + core->iface = shared; > + shared->core = core; > + if (rpc->bytesused > rpc->length) > + return -ENOSPC; > + return 0; > +} > + > +static inline int vpu_iface_set_log_buf(struct vpu_core *core, > + struct vpu_buffer *log) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (!ops) > + return -EINVAL; > + > + if (ops->set_log_buf) > + ops->set_log_buf(core->iface, log); > + > + return 0; > +} > + > +static inline int vpu_iface_config_system(struct vpu_core *core, > + u32 regs_base, void __iomem *regs) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (!ops) > + return -EINVAL; > + if (ops->set_system_cfg) > + ops->set_system_cfg(core->iface, regs_base, regs, core->id); > + > + return 0; > +} > + > +static inline int vpu_iface_get_stream_buffer_size(struct vpu_core *core) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (!ops || !ops->get_stream_buffer_size) > + return 0; > + > + return ops->get_stream_buffer_size(core->iface); > +} > + > +static inline int vpu_iface_config_stream(struct vpu_inst *inst) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(inst->core); > + > + WARN_ON(inst->id < 0); > + if (!ops) > + return -EINVAL; > + if (ops->set_stream_cfg) > + ops->set_stream_cfg(inst->core->iface, inst->id); > + return 0; > +} > + > +static inline int vpu_iface_send_cmd(struct vpu_core *core, struct vpu_rpc_event *cmd) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (!ops || !ops->send_cmd_buf) > + return -EINVAL; > + > + return ops->send_cmd_buf(core->iface, cmd); > +} > + > +static inline int vpu_iface_receive_msg(struct vpu_core *core, struct vpu_rpc_event *msg) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (!ops || !ops->receive_msg_buf) > + return -EINVAL; > + > + return ops->receive_msg_buf(core->iface, msg); > +} > + > +static inline int vpu_iface_pack_cmd(struct vpu_core *core, > + struct vpu_rpc_event *pkt, > + u32 index, u32 id, void *data) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (!ops || !ops->pack_cmd) > + return -EINVAL; > + return ops->pack_cmd(pkt, index, id, data); > +} > + > +static inline int vpu_iface_convert_msg_id(struct vpu_core *core, u32 msg_id) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (!ops || !ops->convert_msg_id) > + return -EINVAL; > + > + return ops->convert_msg_id(msg_id); > +} > + > +static inline int vpu_iface_unpack_msg_data(struct vpu_core *core, > + struct vpu_rpc_event *pkt, void *data) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (!ops || !ops->unpack_msg_data) > + return -EINVAL; > + > + return ops->unpack_msg_data(pkt, data); > +} > + > +static inline int vpu_iface_input_frame(struct vpu_inst *inst, > + struct vb2_buffer *vb) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(inst->core); > + > + if (!ops || !ops->input_frame) > + return -EINVAL; > + > + return ops->input_frame(inst->core->iface, inst, vb); > +} > + > +static inline int vpu_iface_config_memory_resource(struct vpu_inst *inst, > + u32 type, u32 index, struct vpu_buffer *buf) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(inst->core); > + > + WARN_ON(inst->id < 0); > + if (!ops || !ops->config_memory_resource) > + return -EINVAL; > + > + return ops->config_memory_resource(inst->core->iface, > + inst->id, > + type, index, buf); > +} > + > +static inline int vpu_iface_config_stream_buffer(struct vpu_inst *inst, > + struct vpu_buffer *buf) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(inst->core); > + > + WARN_ON(inst->id < 0); > + if (!ops || !ops->config_stream_buffer) > + return -EINVAL; > + > + return ops->config_stream_buffer(inst->core->iface, inst->id, buf); > +} > + > +static inline int vpu_iface_update_stream_buffer(struct vpu_inst *inst, > + u32 ptr, bool write) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(inst->core); > + > + WARN_ON(inst->id < 0); > + if (!ops || !ops->update_stream_buffer) > + return -EINVAL; > + > + return ops->update_stream_buffer(inst->core->iface, inst->id, ptr, write); > +} > + > +static inline int vpu_iface_get_stream_buffer_desc(struct vpu_inst *inst, > + struct vpu_rpc_buffer_desc *desc) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(inst->core); > + > + WARN_ON(inst->id < 0); > + if (!ops || !ops->get_stream_buffer_desc) > + return -EINVAL; > + > + if (!desc) > + return 0; > + > + return ops->get_stream_buffer_desc(inst->core->iface, inst->id, desc); > +} > + > +static inline u32 vpu_iface_get_version(struct vpu_core *core) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (!ops || !ops->get_version) > + return 0; > + > + return ops->get_version(core->iface); > +} > + > +static inline u32 vpu_iface_get_max_instance_count(struct vpu_core *core) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(core); > + > + if (!ops || !ops->get_max_instance_count) > + return 0; > + > + return ops->get_max_instance_count(core->iface); > +} > + > +static inline int vpu_iface_set_encode_params(struct vpu_inst *inst, > + struct vpu_encode_params *params, u32 update) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(inst->core); > + > + WARN_ON(inst->id < 0); > + if (!ops || !ops->set_encode_params) > + return -EINVAL; > + > + return ops->set_encode_params(inst->core->iface, inst->id, params, update); > +} > + > +static inline int vpu_iface_set_decode_params(struct vpu_inst *inst, > + struct vpu_decode_params *params, u32 update) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(inst->core); > + > + WARN_ON(inst->id < 0); > + if (!ops || !ops->set_decode_params) > + return -EINVAL; > + > + return ops->set_decode_params(inst->core->iface, inst->id, params, update); > +} > + > +static inline int vpu_iface_add_scode(struct vpu_inst *inst, u32 scode_type) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(inst->core); > + > + WARN_ON(inst->id < 0); > + if (!ops || !ops->add_scode) > + return -EINVAL; > + > + return ops->add_scode(inst->core->iface, inst->id, > + &inst->stream_buffer, > + inst->out_format.pixfmt, > + scode_type); > +} > + > +static inline int vpu_iface_pre_send_cmd(struct vpu_inst *inst) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(inst->core); > + > + WARN_ON(inst->id < 0); > + if (ops && ops->pre_send_cmd) > + return ops->pre_send_cmd(inst->core->iface, inst->id); > + return 0; > +} > + > +static inline int vpu_iface_post_send_cmd(struct vpu_inst *inst) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(inst->core); > + > + WARN_ON(inst->id < 0); > + if (ops && ops->post_send_cmd) > + return ops->post_send_cmd(inst->core->iface, inst->id); > + return 0; > +} > + > +static inline int vpu_iface_init_instance(struct vpu_inst *inst) > +{ > + struct vpu_iface_ops *ops = vpu_iface_get(inst->core); > + > + WARN_ON(inst->id < 0); > + if (ops && ops->init_instance) > + return ops->init_instance(inst->core->iface, inst->id); > + > + return 0; > +} > + > +#endif 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=-15.2 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS 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 3C654C433F5 for ; Wed, 22 Sep 2021 13:16:12 +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 07A1C61100 for ; Wed, 22 Sep 2021 13:16:12 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 07A1C61100 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=ndufresne.ca Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Date:Cc: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=nfi7Z/cZMHweJ6FviME/S/ZQXV1dRvbFppL7kTXWRKA=; b=Q6nwtJl3tTLUPX G8BbEoagAvUdWF4wj96cZha2RcW4Nvn+i8xtnXy+p7JnDjfMiDvzqe4KEYfzmp/KlISpWwSQEs27O zOd6WTxyLM+FNQBwZmG9E2coaYSb6N/M9RPFY3NR13v0UK9kEm7UffyPh76FYr1uGnxOQo/rMPPyX HeBYlFoaSlXa2KtNw5XSpZPvFiaDfGL6XKW3KgPD534ZJscqqKeK5dESBwYOWzBLrNQ4wZZ1Lw+Qq VL4+29va03gyy9C2arwirDpOgbFXjStKprSomc3Jlw1/N+CbyXuofiUNwQMlF7xNaUgQnSXrB7UGr sKvCcXLo/Stn1mCjgyMA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mT23g-008ZE5-UJ; Wed, 22 Sep 2021 13:13:09 +0000 Received: from mail-qt1-x831.google.com ([2607:f8b0:4864:20::831]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mT20w-008YIb-Kq for linux-arm-kernel@lists.infradead.org; Wed, 22 Sep 2021 13:10:25 +0000 Received: by mail-qt1-x831.google.com with SMTP id j13so2540391qtq.6 for ; Wed, 22 Sep 2021 06:10:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ndufresne-ca.20210112.gappssmtp.com; s=20210112; h=message-id:subject:from:to:cc:date:in-reply-to:references :user-agent:mime-version:content-transfer-encoding; bh=yGvWn4rdW0UXt2zbvpR5gmgtOURbpSljCQDnJpSEN0I=; b=krsC7I6hr5gky16LQq4vrfa4aUfIrsrNCVl6MTDOpu0hQcpbav6ikr34iCzYtm3LMh mBfE/H5MEWzU76omrTSrJLv2BjwZK0FNWRadXTa489xiym0+AbmY9FbUQrUakrEOF6OP zUWAsrut0MVq2Xxeoj8rngQ9ThlprHv6+zvq3BUjqmpOelqlPHeUOCFwx+uDAZvMMKvY /YeYwbtY5TrUnDZaOxfFZ4DHGNL4iZbcD0yhK1a1B2mUmCtsJ4tc7usqmVwlrAsJYyNG jE557aynHGrHV99SMKb22MjFkZ2/AfteCa3s1N5E0SNEBe75PLJVMxwkFbk8FnShMGyd j1jw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:subject:from:to:cc:date:in-reply-to :references:user-agent:mime-version:content-transfer-encoding; bh=yGvWn4rdW0UXt2zbvpR5gmgtOURbpSljCQDnJpSEN0I=; b=POlaIacZqpVjgzOOhDEXYfZGJPSbCY5mSACdur1FWF0+9EhAViMlCmbe3rQHbAO90R 7DnfLfqCgNe9ZS6Kik68yvRXkowoFr0FwA4z1nNcYf6b94RKeJg/h5+tORSE4bCfBQF4 dAaj6HKaty1ZvLdDeL2/51TT4TMT44ggmuMz2YZJ+lgpN/GiLPsB6zJDRN8EkwauGCcs vqmCJLlvzDZp2UTNiWjuNn1KkTu1BkkHhLpt9fzYiJZA12R2wHN8Hbq6K6a0leN1LvjZ hgQfgOMxafH95xGtdJCbrkGvOzIYgSjvdDcK4U5aQhS0wr2hIR2ci7kJcVeH1QBEFO8X /tjw== X-Gm-Message-State: AOAM530zIP0/7R0YjqPMhP3u3779jpsVVShK3mld5B/xqLfVfCSc+0sl ZYce0PvIy+Y1JY0R2sRgmKtwF3rTZb2jD3s9 X-Google-Smtp-Source: ABdhPJy+lDtsygYSoHPvGDFRuVgjA26MinT+HBCCQqjffafgkVeKPIscJcjS6QaqeO3/amVEWf1GVw== X-Received: by 2002:ac8:71cd:: with SMTP id i13mr15956998qtp.159.1632316216588; Wed, 22 Sep 2021 06:10:16 -0700 (PDT) Received: from nicolas-tpx395.localdomain (173-246-12-168.qc.cable.ebox.net. [173.246.12.168]) by smtp.gmail.com with ESMTPSA id g19sm1616534qki.58.2021.09.22.06.10.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Sep 2021 06:10:16 -0700 (PDT) Message-ID: <2b543d1c86c2ba3ac507f196ee326908138c1186.camel@ndufresne.ca> Subject: Re: [PATCH v9 04/13] media: amphion: add vpu core driver From: Nicolas Dufresne To: Ming Qian , mchehab@kernel.org, shawnguo@kernel.org, robh+dt@kernel.org, s.hauer@pengutronix.de Cc: hverkuil-cisco@xs4all.nl, kernel@pengutronix.de, festevam@gmail.com, linux-imx@nxp.com, aisheng.dong@nxp.com, linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org Date: Wed, 22 Sep 2021 09:10:14 -0400 In-Reply-To: <51ba61663ce92a9fe71343578689a0e196d0dfea.1631521295.git.ming.qian@nxp.com> References: <51ba61663ce92a9fe71343578689a0e196d0dfea.1631521295.git.ming.qian@nxp.com> User-Agent: Evolution 3.40.4 (3.40.4-1.fc34) MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210922_061018_936944_31228421 X-CRM114-Status: GOOD ( 28.62 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org SGkgTWluZywKCnNlZW0gY29tbWVudCBiZWxvdy4KCmdMZSBsdW5kaSAxMyBzZXB0ZW1icmUgMjAy MSDDoCAxNzoxMSArMDgwMCwgTWluZyBRaWFuIGEgw6ljcml0wqA6Cj4gVGhlIHZwdSBzdXBwb3J0 cyBlbmNvZGVyIGFuZCBkZWNvZGVyLgo+IGl0IG5lZWRzIG11IGNvcmUgdG8gaGFuZGxlIGl0Lgo+ IGNvcmUgd2lsbCBydW4gZWl0aGVyIGVuY29kZXIgb3IgZGVjb2RlciBmaXJtd2FyZS4KPiAKPiBU aGlzIGRyaXZlciBpcyBmb3Igc3VwcG9ydCB0aGUgdnB1IGNvcmUuCj4gCj4gU2lnbmVkLW9mZi1i eTogTWluZyBRaWFuIDxtaW5nLnFpYW5AbnhwLmNvbT4KPiBTaWduZWQtb2ZmLWJ5OiBTaGlqaWUg UWluIDxzaGlqaWUucWluQG54cC5jb20+Cj4gU2lnbmVkLW9mZi1ieTogWmhvdSBQZW5nIDxlYWds ZS56aG91QG54cC5jb20+Cj4gLS0tCj4gIGRyaXZlcnMvbWVkaWEvcGxhdGZvcm0vYW1waGlvbi92 cHVfY29kZWMuaCB8ICA2OCArKwo+ICBkcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1 X2NvcmUuYyAgfCA5MDEgKysrKysrKysrKysrKysrKysrKysrCj4gIGRyaXZlcnMvbWVkaWEvcGxh dGZvcm0vYW1waGlvbi92cHVfY29yZS5oICB8ICAxNiArCj4gIGRyaXZlcnMvbWVkaWEvcGxhdGZv cm0vYW1waGlvbi92cHVfZGJnLmMgICB8IDQ5NiArKysrKysrKysrKysKPiAgZHJpdmVycy9tZWRp YS9wbGF0Zm9ybS9hbXBoaW9uL3ZwdV9sb2cuaCAgIHwgIDQ0ICsKCldoZW4gbG9hZGluZyB0aGlz IGRyaXZlciwgSSBpbW1lZGlhdGVseSBzdHVtYmxlZCBhY3Jvc3Mgbm9uLXN0YW5kYXJkIGxvZ2dp bmcuCgogICBbICAgMjkuNjE3OTk0XSBbVlBVIENPUkVdY29yZSB2cHVfY29yZSBwcm9iZQogICBb ICAgMjkuNjY2NDQ3XSBbVlBVIENPUkVdWzBdIGRlY29kZXIgYm9vdC1yZWdpb24gOiA8MHgwMDAw MDAwMDg0MDAwMDAwLAogICAweDIwMDAwMDA+CiAgIFsgICAyOS43MzgxNTJdIFtWUFUgSU1YOFFd aW14OHEgZnVzZSA9IDB4MAogICBbICAgMjkuNzk5NDIxXSBbVlBVIENPUkVdY29yZSB2cHVfY29y ZSBwcm9iZTwKICAgWyAgIDMwLjExMTgwNV0gW1ZQVSBDT1JFXVswXSBkZWNvZGVyIGJvb3QKCkkg cmVtZW1iZXIgYSB0aHJlYWQgcmVsYXRlZCB0byBWZW51cyBkcml2ZXIsIGFuZCBpdCBzZWVtcyB0 aGF0IGl0cyBiZXN0IHRvCnJlbW92ZSB0aGlzIGN1c3RvbSBsb2dnaW5nIGluZnJhc3RydWN0dXJl IGFuZCB1c2UgdGhlIGV4aXN0aW5nIGluZnJhc3RydWN0dXJlLgoKPiAgZHJpdmVycy9tZWRpYS9w bGF0Zm9ybS9hbXBoaW9uL3ZwdV9ycGMuYyAgIHwgMjYzICsrKysrKwo+ICBkcml2ZXJzL21lZGlh L3BsYXRmb3JtL2FtcGhpb24vdnB1X3JwYy5oICAgfCA0NjMgKysrKysrKysrKysKPiAgNyBmaWxl cyBjaGFuZ2VkLCAyMjUxIGluc2VydGlvbnMoKykKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZl cnMvbWVkaWEvcGxhdGZvcm0vYW1waGlvbi92cHVfY29kZWMuaAo+ICBjcmVhdGUgbW9kZSAxMDA2 NDQgZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9hbXBoaW9uL3ZwdV9jb3JlLmMKPiAgY3JlYXRlIG1v ZGUgMTAwNjQ0IGRyaXZlcnMvbWVkaWEvcGxhdGZvcm0vYW1waGlvbi92cHVfY29yZS5oCj4gIGNy ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X2RiZy5j Cj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1 X2xvZy5oCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhp b24vdnB1X3JwYy5jCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21lZGlhL3BsYXRmb3Jt L2FtcGhpb24vdnB1X3JwYy5oCj4gCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWVkaWEvcGxhdGZv cm0vYW1waGlvbi92cHVfY29kZWMuaCBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vYW1waGlvbi92 cHVfY29kZWMuaAo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMDAwMDAwLi40 ZGM0MWQ2ODA4YjEKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9y bS9hbXBoaW9uL3ZwdV9jb2RlYy5oCj4gQEAgLTAsMCArMSw2OCBAQAo+ICsvKiBTUERYLUxpY2Vu c2UtSWRlbnRpZmllcjogR1BMLTIuMCAqLwo+ICsvKgo+ICsgKiBDb3B5cmlnaHQgMjAyMC0yMDIx IE5YUAo+ICsgKi8KPiArCj4gKyNpZm5kZWYgX0FNUEhJT05fVlBVX0NPREVDX0gKPiArI2RlZmlu ZSBfQU1QSElPTl9WUFVfQ09ERUNfSAo+ICsKPiArc3RydWN0IHZwdV9lbmNvZGVfcGFyYW1zIHsK PiArCXUzMiBpbnB1dF9mb3JtYXQ7Cj4gKwl1MzIgY29kZWNfZm9ybWF0Owo+ICsJdTMyIHByb2Zp bGU7Cj4gKwl1MzIgdGllcjsKPiArCXUzMiBsZXZlbDsKPiArCXUzMiBmcmFtZV9yYXRlX251bTsK PiArCXUzMiBmcmFtZV9yYXRlX2RlbjsKPiArCXUzMiBzcmNfc3RyaWRlOwo+ICsJdTMyIHNyY193 aWR0aDsKPiArCXUzMiBzcmNfaGVpZ2h0Owo+ICsJc3RydWN0IHY0bDJfcmVjdCBjcm9wOwo+ICsJ dTMyIG91dF93aWR0aDsKPiArCXUzMiBvdXRfaGVpZ2h0Owo+ICsKPiArCXUzMiBnb3BfbGVuZ3Ro Owo+ICsJdTMyIGJmcmFtZXM7Cj4gKwo+ICsJdTMyIHJjX21vZGU7Cj4gKwl1MzIgYml0cmF0ZTsK PiArCXUzMiBiaXRyYXRlX21pbjsKPiArCXUzMiBiaXRyYXRlX21heDsKPiArCj4gKwl1MzIgaV9m cmFtZV9xcDsKPiArCXUzMiBwX2ZyYW1lX3FwOwo+ICsJdTMyIGJfZnJhbWVfcXA7Cj4gKwl1MzIg cXBfbWluOwo+ICsJdTMyIHFwX21heDsKPiArCXUzMiBxcF9taW5faTsKPiArCXUzMiBxcF9tYXhf aTsKPiArCj4gKwlzdHJ1Y3Qgewo+ICsJCXUzMiBlbmFibGU7Cj4gKwkJdTMyIGlkYzsKPiArCQl1 MzIgd2lkdGg7Cj4gKwkJdTMyIGhlaWdodDsKPiArCX0gc2FyOwo+ICsKPiArCXN0cnVjdCB7Cj4g KwkJdTMyIHByaW1hcmllczsKPiArCQl1MzIgdHJhbnNmZXI7Cj4gKwkJdTMyIG1hdHJpeDsKPiAr CQl1MzIgZnVsbF9yYW5nZTsKPiArCX0gY29sb3I7Cj4gK307Cj4gKwo+ICtzdHJ1Y3QgdnB1X2Rl Y29kZV9wYXJhbXMgewo+ICsJdTMyIGNvZGVjX2Zvcm1hdDsKPiArCXUzMiBvdXRwdXRfZm9ybWF0 Owo+ICsJdTMyIGJfZGlzX3Jlb3JkZXI7Cj4gKwl1MzIgYl9ub25fZnJhbWU7Cj4gKwl1MzIgZnJh bWVfY291bnQ7Cj4gKwl1MzIgZW5kX2ZsYWc7Cj4gKwlzdHJ1Y3Qgewo+ICsJCXUzMiBiYXNlOwo+ ICsJCXUzMiBzaXplOwo+ICsJfSB1ZGF0YTsKPiArfTsKPiArCj4gKyNlbmRpZgo+IGRpZmYgLS1n aXQgYS9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X2NvcmUuYyBiL2RyaXZlcnMv bWVkaWEvcGxhdGZvcm0vYW1waGlvbi92cHVfY29yZS5jCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQK PiBpbmRleCAwMDAwMDAwMDAwMDAuLjMzMmFkMzcxMGFiZQo+IC0tLSAvZGV2L251bGwKPiArKysg Yi9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X2NvcmUuYwo+IEBAIC0wLDAgKzEs OTAxIEBACj4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wCj4gKy8qCj4gKyAq IENvcHlyaWdodCAyMDIwLTIwMjEgTlhQCj4gKyAqLwo+ICsKPiArI2RlZmluZSBUQUcJCSJDT1JF Igo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2ludGVy Y29ubmVjdC5oPgo+ICsjaW5jbHVkZSA8bGludXgvaW9jdGwuaD4KPiArI2luY2x1ZGUgPGxpbnV4 L2xpc3QuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgo+ICsjaW5jbHVkZSA8bGludXgv bW9kdWxlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9vZl9kZXZpY2UuaD4KPiArI2luY2x1ZGUgPGxp bnV4L29mX2FkZHJlc3MuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPgo+ ICsjaW5jbHVkZSA8bGludXgvc2xhYi5oPgo+ICsjaW5jbHVkZSA8bGludXgvdHlwZXMuaD4KPiAr I2luY2x1ZGUgPGxpbnV4L3BtX3J1bnRpbWUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3BtX2RvbWFp bi5oPgo+ICsjaW5jbHVkZSA8bGludXgvZmlybXdhcmUuaD4KPiArI2luY2x1ZGUgInZwdS5oIgo+ ICsjaW5jbHVkZSAidnB1X2RlZnMuaCIKPiArI2luY2x1ZGUgInZwdV9jb3JlLmgiCj4gKyNpbmNs dWRlICJ2cHVfbWJveC5oIgo+ICsjaW5jbHVkZSAidnB1X21zZ3MuaCIKPiArI2luY2x1ZGUgInZw dV9ycGMuaCIKPiArI2luY2x1ZGUgInZwdV9sb2cuaCIKPiArI2luY2x1ZGUgInZwdV9jbWRzLmgi Cj4gKwo+ICt1bnNpZ25lZCBpbnQgdnB1X2RiZ19sZXZlbCA9IExWTF9FUlIgfCBMVkxfV0FSTiB8 IExWTF9JTkZPOwo+ICttb2R1bGVfcGFyYW0odnB1X2RiZ19sZXZlbCwgdWludCwgMDY0NCk7Cj4g Kwo+ICt2b2lkIGNzcl93cml0ZWwoc3RydWN0IHZwdV9jb3JlICpjb3JlLCB1MzIgcmVnLCB1MzIg dmFsKQo+ICt7Cj4gKwl3cml0ZWwodmFsLCBjb3JlLT5iYXNlICsgcmVnKTsKPiArfQo+ICsKPiAr dTMyIGNzcl9yZWFkbChzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUsIHUzMiByZWcpCj4gK3sKPiArCXJl dHVybiByZWFkbChjb3JlLT5iYXNlICsgcmVnKTsKPiArfQo+ICsKPiArc3RhdGljIGludCB2cHVf Y29yZV9sb2FkX2Zpcm13YXJlKHN0cnVjdCB2cHVfY29yZSAqY29yZSkKPiArewo+ICsJY29uc3Qg c3RydWN0IGZpcm13YXJlICpwZncgPSBOVUxMOwo+ICsJaW50IHJldCA9IDA7Cj4gKwo+ICsJV0FS Tl9PTighY29yZSB8fCAhY29yZS0+cmVzIHx8ICFjb3JlLT5yZXMtPmZ3bmFtZSk7Cj4gKwlpZiAo IWNvcmUtPmZ3LnZpcnQpIHsKPiArCQljb3JlX2Vycihjb3JlLCAiZmlybXdhcmUgYnVmZmVyIGlz IG5vdCByZWFkeVxuIik7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9Cj4gKwo+ICsJcmV0ID0g cmVxdWVzdF9maXJtd2FyZSgmcGZ3LCBjb3JlLT5yZXMtPmZ3bmFtZSwgY29yZS0+ZGV2KTsKPiAr CWNvcmVfZGJnKGNvcmUsIExWTF9ERUJVRywgInJlcXVlc3RfZmlybXdhcmUgJXMgOiAlZFxuIiwg Y29yZS0+cmVzLT5md25hbWUsIHJldCk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJY29yZV9lcnIoY29y ZSwgInJlcXVlc3QgZmlybXdhcmUgJXMgZmFpbGVkLCByZXQgPSAlZFxuIiwKPiArCQkJCWNvcmUt PnJlcy0+ZnduYW1lLCByZXQpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ICsJaWYgKGNv cmUtPmZ3Lmxlbmd0aCA8IHBmdy0+c2l6ZSkgewo+ICsJCWNvcmVfZXJyKGNvcmUsICJmaXJtd2Fy ZSBidWZmZXIgc2l6ZSB3YW50ICV6dSwgYnV0ICVkXG4iLAo+ICsJCQkJcGZ3LT5zaXplLCBjb3Jl LT5mdy5sZW5ndGgpOwo+ICsJCXJldCA9IC1FSU5WQUw7Cj4gKwkJZ290byBleGl0Owo+ICsJfQo+ ICsKPiArCW1lbXNldF9pbyhjb3JlLT5mdy52aXJ0LCAwLCBjb3JlLT5mdy5sZW5ndGgpOwo+ICsJ bWVtY3B5KGNvcmUtPmZ3LnZpcnQsIHBmdy0+ZGF0YSwgcGZ3LT5zaXplKTsKPiArCWNvcmUtPmZ3 LmJ5dGVzdXNlZCA9IHBmdy0+c2l6ZTsKPiArCXJldCA9IHZwdV9pZmFjZV9vbl9maXJtd2FyZV9s b2FkZWQoY29yZSk7Cj4gK2V4aXQ6Cj4gKwlyZWxlYXNlX2Zpcm13YXJlKHBmdyk7Cj4gKwlwZncg PSBOVUxMOwo+ICsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdnB1X2Nv cmVfd2FpdF9ib290X2RvbmUoc3RydWN0IHZwdV9jb3JlICpjb3JlKQo+ICt7Cj4gKwlpbnQgcmV0 Owo+ICsJdTMyIGZ3X3ZlcnNpb247Cj4gKwo+ICsJcmV0ID0gd2FpdF9mb3JfY29tcGxldGlvbl90 aW1lb3V0KCZjb3JlLT5jbXAsIFZQVV9USU1FT1VUKTsKPiArCWlmICghcmV0KSB7Cj4gKwkJY29y ZV9lcnIoY29yZSwgImJvb3QgdGltZW91dFxuIik7Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwl9 Cj4gKwo+ICsJZndfdmVyc2lvbiA9IHZwdV9pZmFjZV9nZXRfdmVyc2lvbihjb3JlKTsKPiArCWNv cmVfZGJnKGNvcmUsIExWTF9XQVJOLCAiZmlybXdhcmUgdmVyc2lvbiA6ICVkLiVkLiVkXG4iLAo+ ICsJCQkoZndfdmVyc2lvbiA+PiAxNikgJiAweGZmLAo+ICsJCQkoZndfdmVyc2lvbiA+PiA4KSAm IDB4ZmYsCj4gKwkJCWZ3X3ZlcnNpb24gJiAweGZmKTsKPiArCWNvcmUtPnN1cHBvcnRlZF9pbnN0 YW5jZV9jb3VudCA9IHZwdV9pZmFjZV9nZXRfbWF4X2luc3RhbmNlX2NvdW50KGNvcmUpOwo+ICsJ aWYgKGNvcmUtPnJlcy0+YWN0X3NpemUpIHsKPiArCQl1MzIgY291bnQgPSBjb3JlLT5hY3QubGVu Z3RoIC8gY29yZS0+cmVzLT5hY3Rfc2l6ZTsKPiArCj4gKwkJY29yZS0+c3VwcG9ydGVkX2luc3Rh bmNlX2NvdW50ID0gbWluKGNvcmUtPnN1cHBvcnRlZF9pbnN0YW5jZV9jb3VudCwgY291bnQpOwo+ ICsJfQo+ICsJY29yZS0+ZndfdmVyc2lvbiA9IGZ3X3ZlcnNpb247Cj4gKwo+ICsJcmV0dXJuIDA7 Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdnB1X2NvcmVfYm9vdChzdHJ1Y3QgdnB1X2NvcmUgKmNv cmUsIGJvb2wgbG9hZCkKPiArewo+ICsJaW50IHJldDsKPiArCj4gKwlXQVJOX09OKCFjb3JlKTsK PiArCj4gKwlpZiAoIWNvcmUtPnJlcy0+c3RhbmRhbG9uZSkKPiArCQlyZXR1cm4gMDsKPiArCj4g Kwljb3JlX2RiZyhjb3JlLCBMVkxfV0FSTiwgImJvb3RcbiIpOwo+ICsJcmVpbml0X2NvbXBsZXRp b24oJmNvcmUtPmNtcCk7Cj4gKwlpZiAobG9hZCkgewo+ICsJCXJldCA9IHZwdV9jb3JlX2xvYWRf ZmlybXdhcmUoY29yZSk7Cj4gKwkJaWYgKHJldCkKPiArCQkJcmV0dXJuIHJldDsKPiArCX0KPiAr Cj4gKwl2cHVfaWZhY2VfYm9vdF9jb3JlKGNvcmUpOwo+ICsJcmV0dXJuIHZwdV9jb3JlX3dhaXRf Ym9vdF9kb25lKGNvcmUpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHZwdV9jb3JlX3NodXRkb3du KHN0cnVjdCB2cHVfY29yZSAqY29yZSkKPiArewo+ICsJaWYgKCFjb3JlLT5yZXMtPnN0YW5kYWxv bmUpCj4gKwkJcmV0dXJuIDA7Cj4gKwlyZXR1cm4gdnB1X2lmYWNlX3NodXRkb3duX2NvcmUoY29y ZSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdnB1X2NvcmVfcmVzdG9yZShzdHJ1Y3QgdnB1X2Nv cmUgKmNvcmUpCj4gK3sKPiArCWlmICghY29yZS0+cmVzLT5zdGFuZGFsb25lKQo+ICsJCXJldHVy biAwOwo+ICsJcmV0dXJuIHZwdV9pZmFjZV9yZXN0b3JlX2NvcmUoY29yZSk7Cj4gK30KPiArCj4g K3N0YXRpYyBpbnQgX192cHVfYWxsb2NfZG1hKHN0cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IHZw dV9idWZmZXIgKmJ1ZikKPiArewo+ICsJZ2ZwX3QgZ2ZwID0gR0ZQX0tFUk5FTCB8IEdGUF9ETUEz MjsKPiArCj4gKwlXQVJOX09OKCFkZXYgfHwgIWJ1Zik7Cj4gKwo+ICsJaWYgKCFidWYtPmxlbmd0 aCkKPiArCQlyZXR1cm4gMDsKPiArCj4gKwlidWYtPnZpcnQgPSBkbWFfYWxsb2NfY29oZXJlbnQo ZGV2LCBidWYtPmxlbmd0aCwgJmJ1Zi0+cGh5cywgZ2ZwKTsKPiArCWlmICghYnVmLT52aXJ0KQo+ ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCWJ1Zi0+ZGV2ID0gZGV2Owo+ICsKPiArCXJldHVy biAwOwo+ICt9Cj4gKwo+ICt2b2lkIHZwdV9mcmVlX2RtYShzdHJ1Y3QgdnB1X2J1ZmZlciAqYnVm KQo+ICt7Cj4gKwlXQVJOX09OKCFidWYpOwo+ICsKPiArCWlmICghYnVmLT52aXJ0IHx8ICFidWYt PmRldikKPiArCQlyZXR1cm47Cj4gKwo+ICsJZG1hX2ZyZWVfY29oZXJlbnQoYnVmLT5kZXYsIGJ1 Zi0+bGVuZ3RoLCBidWYtPnZpcnQsIGJ1Zi0+cGh5cyk7Cj4gKwlidWYtPnZpcnQgPSBOVUxMOwo+ ICsJYnVmLT5waHlzID0gMDsKPiArCWJ1Zi0+bGVuZ3RoID0gMDsKPiArCWJ1Zi0+Ynl0ZXN1c2Vk ID0gMDsKPiArCWJ1Zi0+ZGV2ID0gTlVMTDsKPiArfQo+ICsKPiAraW50IHZwdV9hbGxvY19kbWEo c3RydWN0IHZwdV9jb3JlICpjb3JlLCBzdHJ1Y3QgdnB1X2J1ZmZlciAqYnVmKQo+ICt7Cj4gKwlX QVJOX09OKCFjb3JlIHx8ICFidWYpOwo+ICsKPiArCXJldHVybiBfX3ZwdV9hbGxvY19kbWEoY29y ZS0+ZGV2LCBidWYpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IHZwdV9jb3JlICp2cHVfY29y ZV9maW5kX25leHRfYnlfdHlwZShzdHJ1Y3QgdnB1X2RldiAqdnB1LCB1MzIgdHlwZSkKPiArewo+ ICsJc3RydWN0IHZwdV9jb3JlICpjOwo+ICsKPiArCVdBUk5fT04oIXZwdSk7Cj4gKwo+ICsJbGlz dF9mb3JfZWFjaF9lbnRyeShjLCAmdnB1LT5jb3JlcywgbGlzdCkgewo+ICsJCWlmIChjLT50eXBl ID09IHR5cGUpCj4gKwkJCXJldHVybiBjOwo+ICsJfQo+ICsKPiArCXJldHVybiBOVUxMOwo+ICt9 Cj4gKwo+ICtpbnQgdnB1X2NvcmVfY2hlY2tfZm10KHN0cnVjdCB2cHVfY29yZSAqY29yZSwgdTMy IHBpeGVsZm10KQo+ICt7Cj4gKwlpZiAoIWNvcmUpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ ICsJaWYgKHZwdV9pZmFjZV9jaGVja19mb3JtYXQoY29yZSwgcGl4ZWxmbXQpKQo+ICsJCXJldHVy biAwOwo+ICsKPiArCXJldHVybiAtRUlOVkFMOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2cHVf Y29yZV9jaGVja19oYW5nKHN0cnVjdCB2cHVfY29yZSAqY29yZSkKPiArewo+ICsJaWYgKGNvcmUt PmhhbmdfbWFzaykKPiArCQljb3JlLT5zdGF0ZSA9IFZQVV9DT1JFX0hBTkc7Cj4gK30KPiArCj4g K3N0YXRpYyBzdHJ1Y3QgdnB1X2NvcmUgKnZwdV9jb3JlX2ZpbmRfcHJvcGVyX2J5X3R5cGUoc3Ry dWN0IHZwdV9kZXYgKnZwdSwgdTMyIHR5cGUpCj4gK3sKPiArCXN0cnVjdCB2cHVfY29yZSAqY29y ZSA9IE5VTEw7Cj4gKwlpbnQgcmVxdWVzdF9jb3VudCA9IElOVF9NQVg7Cj4gKwlzdHJ1Y3QgdnB1 X2NvcmUgKmM7Cj4gKwo+ICsJV0FSTl9PTighdnB1KTsKPiArCj4gKwlsaXN0X2Zvcl9lYWNoX2Vu dHJ5KGMsICZ2cHUtPmNvcmVzLCBsaXN0KSB7Cj4gKwkJY29yZV9kYmcoYywgTFZMX0RFQlVHLCAi aW5zdGFuY2VfbWFzayA9IDB4JWx4LCBzdGF0ZSA9ICVkXG4iLAo+ICsJCQkJYy0+aW5zdGFuY2Vf bWFzaywKPiArCQkJCWMtPnN0YXRlKTsKPiArCQlpZiAoYy0+dHlwZSAhPSB0eXBlKQo+ICsJCQlj b250aW51ZTsKPiArCQlpZiAoYy0+c3RhdGUgPT0gVlBVX0NPUkVfREVJTklUKSB7Cj4gKwkJCWNv cmUgPSBjOwo+ICsJCQlicmVhazsKPiArCQl9Cj4gKwkJdnB1X2NvcmVfY2hlY2tfaGFuZyhjKTsK PiArCQlpZiAoYy0+c3RhdGUgIT0gVlBVX0NPUkVfQUNUSVZFKQo+ICsJCQljb250aW51ZTsKPiAr CQlpZiAoYy0+cmVxdWVzdF9jb3VudCA8IHJlcXVlc3RfY291bnQpIHsKPiArCQkJcmVxdWVzdF9j b3VudCA9IGMtPnJlcXVlc3RfY291bnQ7Cj4gKwkJCWNvcmUgPSBjOwo+ICsJCX0KPiArCQlpZiAo IXJlcXVlc3RfY291bnQpCj4gKwkJCWJyZWFrOwo+ICsJfQo+ICsKPiArCXJldHVybiBjb3JlOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgYm9vbCB2cHVfY29yZV9pc19leGlzdChzdHJ1Y3QgdnB1X2RldiAq dnB1LCBzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUpCj4gK3sKPiArCXN0cnVjdCB2cHVfY29yZSAqYzsK PiArCj4gKwlsaXN0X2Zvcl9lYWNoX2VudHJ5KGMsICZ2cHUtPmNvcmVzLCBsaXN0KSB7Cj4gKwkJ aWYgKGMgPT0gY29yZSkKPiArCQkJcmV0dXJuIHRydWU7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIGZh bHNlOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2cHVfY29yZV9nZXRfdnB1KHN0cnVjdCB2cHVf Y29yZSAqY29yZSkKPiArewo+ICsJY29yZS0+dnB1LT5nZXRfdnB1KGNvcmUtPnZwdSk7Cj4gKwlp ZiAoY29yZS0+dHlwZSA9PSBWUFVfQ09SRV9UWVBFX0VOQykKPiArCQljb3JlLT52cHUtPmdldF9l bmMoY29yZS0+dnB1KTsKPiArCWlmIChjb3JlLT50eXBlID09IFZQVV9DT1JFX1RZUEVfREVDKQo+ ICsJCWNvcmUtPnZwdS0+Z2V0X2RlYyhjb3JlLT52cHUpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50 IHZwdV9jb3JlX3JlZ2lzdGVyKHN0cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IHZwdV9jb3JlICpj b3JlKQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X2RldiAqdnB1ID0gZGV2X2dldF9kcnZkYXRhKGRldik7 Cj4gKwlpbnQgcmV0ID0gMDsKPiArCj4gKwljb3JlX2RiZyhjb3JlLCBMVkxfREVCVUcsICJyZWdp c3RlciBjb3JlXG4iKTsKPiArCWlmICh2cHVfY29yZV9pc19leGlzdCh2cHUsIGNvcmUpKQo+ICsJ CXJldHVybiAwOwo+ICsKPiArCWNvcmUtPndvcmtxdWV1ZSA9IGFsbG9jX3dvcmtxdWV1ZSgidnB1 IiwgV1FfVU5CT1VORCB8IFdRX01FTV9SRUNMQUlNLCAxKTsKPiArCWlmICghY29yZS0+d29ya3F1 ZXVlKSB7Cj4gKwkJY29yZV9lcnIoY29yZSwgImZhaWwgdG8gYWxsb2Mgd29ya3F1ZXVlXG4iKTsK PiArCQlyZXR1cm4gLUVOT01FTTsKPiArCX0KPiArCUlOSVRfV09SSygmY29yZS0+bXNnX3dvcmss IHZwdV9tc2dfcnVuX3dvcmspOwo+ICsJSU5JVF9ERUxBWUVEX1dPUksoJmNvcmUtPm1zZ19kZWxh eWVkX3dvcmssIHZwdV9tc2dfZGVsYXllZF93b3JrKTsKPiArCWNvcmUtPm1zZ19idWZmZXJfc2l6 ZSA9IHJvdW5kdXBfcG93X29mX3R3byhWUFVfTVNHX0JVRkZFUl9TSVpFKTsKPiArCWNvcmUtPm1z Z19idWZmZXIgPSB2emFsbG9jKGNvcmUtPm1zZ19idWZmZXJfc2l6ZSk7Cj4gKwlpZiAoIWNvcmUt Pm1zZ19idWZmZXIpIHsKPiArCQljb3JlX2Vycihjb3JlLCAiZmFpbGVkIGFsbG9jYXRlIGJ1ZmZl ciBmb3IgZmlmb1xuIik7Cj4gKwkJcmV0ID0gLUVOT01FTTsKPiArCQlnb3RvIGVycm9yOwo+ICsJ fQo+ICsJcmV0ID0ga2ZpZm9faW5pdCgmY29yZS0+bXNnX2ZpZm8sIGNvcmUtPm1zZ19idWZmZXIs IGNvcmUtPm1zZ19idWZmZXJfc2l6ZSk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJY29yZV9lcnIoY29y ZSwgImZhaWxlZCBpbml0IGtmaWZvXG4iKTsKPiArCQlnb3RvIGVycm9yOwo+ICsJfQo+ICsKPiAr CWxpc3RfYWRkX3RhaWwoJmNvcmUtPmxpc3QsICZ2cHUtPmNvcmVzKTsKPiArCj4gKwl2cHVfY29y ZV9nZXRfdnB1KGNvcmUpOwo+ICsKPiArCWlmIChjb3JlLT50eXBlID09IFZQVV9DT1JFX1RZUEVf RU5DICYmICF2cHUtPnZkZXZfZW5jKQo+ICsJCXZlbmNfY3JlYXRlX3ZpZGVvX2RldmljZSh2cHUp Owo+ICsJaWYgKGNvcmUtPnR5cGUgPT0gVlBVX0NPUkVfVFlQRV9ERUMgJiYgIXZwdS0+dmRldl9k ZWMpCj4gKwkJdmRlY19jcmVhdGVfdmlkZW9fZGV2aWNlKHZwdSk7Cj4gKwo+ICsJcmV0dXJuIDA7 Cj4gK2Vycm9yOgo+ICsJaWYgKGNvcmUtPm1zZ19idWZmZXIpIHsKPiArCQl2ZnJlZShjb3JlLT5t c2dfYnVmZmVyKTsKPiArCQljb3JlLT5tc2dfYnVmZmVyID0gTlVMTDsKPiArCX0KPiArCWlmIChj b3JlLT53b3JrcXVldWUpIHsKPiArCQlkZXN0cm95X3dvcmtxdWV1ZShjb3JlLT53b3JrcXVldWUp Owo+ICsJCWNvcmUtPndvcmtxdWV1ZSA9IE5VTEw7Cj4gKwl9Cj4gKwlyZXR1cm4gcmV0Owo+ICt9 Cj4gKwo+ICtzdGF0aWMgdm9pZCB2cHVfY29yZV9wdXRfdnB1KHN0cnVjdCB2cHVfY29yZSAqY29y ZSkKPiArewo+ICsJaWYgKGNvcmUtPnR5cGUgPT0gVlBVX0NPUkVfVFlQRV9FTkMpCj4gKwkJY29y ZS0+dnB1LT5wdXRfZW5jKGNvcmUtPnZwdSk7Cj4gKwlpZiAoY29yZS0+dHlwZSA9PSBWUFVfQ09S RV9UWVBFX0RFQykKPiArCQljb3JlLT52cHUtPnB1dF9kZWMoY29yZS0+dnB1KTsKPiArCWNvcmUt PnZwdS0+cHV0X3ZwdShjb3JlLT52cHUpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHZwdV9jb3Jl X3VucmVnaXN0ZXIoc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUpCj4g K3sKPiArCXN0cnVjdCB2cHVfZGV2ICp2cHUgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCj4g KwlsaXN0X2RlbF9pbml0KCZjb3JlLT5saXN0KTsKPiArCj4gKwl2cHVfY29yZV9wdXRfdnB1KGNv cmUpOwo+ICsJY29yZS0+dnB1ID0gTlVMTDsKPiArCXZmcmVlKGNvcmUtPm1zZ19idWZmZXIpOwo+ ICsJY29yZS0+bXNnX2J1ZmZlciA9IE5VTEw7Cj4gKwo+ICsJaWYgKGNvcmUtPndvcmtxdWV1ZSkg ewo+ICsJCWNhbmNlbF93b3JrX3N5bmMoJmNvcmUtPm1zZ193b3JrKTsKPiArCQljYW5jZWxfZGVs YXllZF93b3JrX3N5bmMoJmNvcmUtPm1zZ19kZWxheWVkX3dvcmspOwo+ICsJCWRlc3Ryb3lfd29y a3F1ZXVlKGNvcmUtPndvcmtxdWV1ZSk7Cj4gKwkJY29yZS0+d29ya3F1ZXVlID0gTlVMTDsKPiAr CX0KPiArCj4gKwlpZiAodnB1X2NvcmVfZmluZF9uZXh0X2J5X3R5cGUodnB1LCBjb3JlLT50eXBl KSkKPiArCQlyZXR1cm4gMDsKPiArCj4gKwlpZiAoY29yZS0+dHlwZSA9PSBWUFVfQ09SRV9UWVBF X0VOQykKPiArCQl2aWRlb191bnJlZ2lzdGVyX2RldmljZSh2cHUtPnZkZXZfZW5jKTsKPiArCWlm IChjb3JlLT50eXBlID09IFZQVV9DT1JFX1RZUEVfREVDKQo+ICsJCXZpZGVvX3VucmVnaXN0ZXJf ZGV2aWNlKHZwdS0+dmRldl9kZWMpOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgaW50IHZwdV9jb3JlX2FjcXVpcmVfaW5zdGFuY2Uoc3RydWN0IHZwdV9jb3JlICpjb3JlKQo+ ICt7Cj4gKwlpbnQgaWQ7Cj4gKwo+ICsJV0FSTl9PTighY29yZSk7Cj4gKwo+ICsJaWQgPSBmZnoo Y29yZS0+aW5zdGFuY2VfbWFzayk7Cj4gKwlpZiAoaWQgPj0gY29yZS0+c3VwcG9ydGVkX2luc3Rh bmNlX2NvdW50KQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXNldF9iaXQoaWQsICZjb3Jl LT5pbnN0YW5jZV9tYXNrKTsKPiArCj4gKwlyZXR1cm4gaWQ7Cj4gK30KPiArCj4gK3N0YXRpYyB2 b2lkIHZwdV9jb3JlX3JlbGVhc2VfaW5zdGFuY2Uoc3RydWN0IHZwdV9jb3JlICpjb3JlLCBpbnQg aWQpCj4gK3sKPiArCVdBUk5fT04oIWNvcmUpOwo+ICsKPiArCWlmIChpZCA8IDAgfHwgaWQgPj0g Y29yZS0+c3VwcG9ydGVkX2luc3RhbmNlX2NvdW50KQo+ICsJCXJldHVybjsKPiArCj4gKwljbGVh cl9iaXQoaWQsICZjb3JlLT5pbnN0YW5jZV9tYXNrKTsKPiArfQo+ICsKPiArc3RydWN0IHZwdV9p bnN0ICp2cHVfaW5zdF9nZXQoc3RydWN0IHZwdV9pbnN0ICppbnN0KQo+ICt7Cj4gKwlpZiAoIWlu c3QpCj4gKwkJcmV0dXJuIE5VTEw7Cj4gKwo+ICsJYXRvbWljX2luYygmaW5zdC0+cmVmX2NvdW50 KTsKPiArCj4gKwlyZXR1cm4gaW5zdDsKPiArfQo+ICsKPiArdm9pZCB2cHVfaW5zdF9wdXQoc3Ry dWN0IHZwdV9pbnN0ICppbnN0KQo+ICt7Cj4gKwlpZiAoIWluc3QpCj4gKwkJcmV0dXJuOwo+ICsJ aWYgKGF0b21pY19kZWNfYW5kX3Rlc3QoJmluc3QtPnJlZl9jb3VudCkpIHsKPiArCQlpZiAoaW5z dC0+cmVsZWFzZSkKPiArCQkJaW5zdC0+cmVsZWFzZShpbnN0KTsKPiArCX0KPiArfQo+ICsKPiAr c3RydWN0IHZwdV9jb3JlICp2cHVfcmVxdWVzdF9jb3JlKHN0cnVjdCB2cHVfZGV2ICp2cHUsIGVu dW0gdnB1X2NvcmVfdHlwZSB0eXBlKQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUgPSBO VUxMOwo+ICsJaW50IHJldDsKPiArCj4gKwltdXRleF9sb2NrKCZ2cHUtPmxvY2spOwo+ICsKPiAr CWNvcmUgPSB2cHVfY29yZV9maW5kX3Byb3Blcl9ieV90eXBlKHZwdSwgdHlwZSk7Cj4gKwlpZiAo IWNvcmUpCj4gKwkJZ290byBleGl0Owo+ICsKPiArCWNvcmVfZGJnKGNvcmUsIExWTF9ERUJVRywg ImlzIGZvdW5kXG4iKTsKPiArCW11dGV4X2xvY2soJmNvcmUtPmxvY2spOwo+ICsJcG1fcnVudGlt ZV9nZXRfc3luYyhjb3JlLT5kZXYpOwo+ICsKPiArCWlmIChjb3JlLT5zdGF0ZSA9PSBWUFVfQ09S RV9ERUlOSVQpIHsKPiArCQlyZXQgPSB2cHVfY29yZV9ib290KGNvcmUsIHRydWUpOwo+ICsJCWlm IChyZXQpIHsKPiArCQkJcG1fcnVudGltZV9wdXRfc3luYyhjb3JlLT5kZXYpOwo+ICsJCQltdXRl eF91bmxvY2soJmNvcmUtPmxvY2spOwo+ICsJCQljb3JlID0gTlVMTDsKPiArCQkJZ290byBleGl0 Owo+ICsJCX0KPiArCQljb3JlLT5zdGF0ZSA9IFZQVV9DT1JFX0FDVElWRTsKPiArCX0KPiArCj4g Kwljb3JlLT5yZXF1ZXN0X2NvdW50Kys7Cj4gKwo+ICsJbXV0ZXhfdW5sb2NrKCZjb3JlLT5sb2Nr KTsKPiArZXhpdDoKPiArCW11dGV4X3VubG9jaygmdnB1LT5sb2NrKTsKPiArCj4gKwlyZXR1cm4g Y29yZTsKPiArfQo+ICsKPiArdm9pZCB2cHVfcmVsZWFzZV9jb3JlKHN0cnVjdCB2cHVfY29yZSAq Y29yZSkKPiArewo+ICsJaWYgKCFjb3JlKQo+ICsJCXJldHVybjsKPiArCj4gKwltdXRleF9sb2Nr KCZjb3JlLT5sb2NrKTsKPiArCXBtX3J1bnRpbWVfcHV0X3N5bmMoY29yZS0+ZGV2KTsKPiArCWlm IChjb3JlLT5yZXF1ZXN0X2NvdW50KQo+ICsJCWNvcmUtPnJlcXVlc3RfY291bnQtLTsKPiArCW11 dGV4X3VubG9jaygmY29yZS0+bG9jayk7Cj4gK30KPiArCj4gK2ludCB2cHVfaW5zdF9yZWdpc3Rl cihzdHJ1Y3QgdnB1X2luc3QgKmluc3QpCj4gK3sKPiArCXN0cnVjdCB2cHVfY29yZSAqY29yZTsK PiArCWludCByZXQgPSAwOwo+ICsKPiArCVdBUk5fT04oIWluc3QgfHwgIWluc3QtPmNvcmUpOwo+ ICsKPiArCWNvcmUgPSBpbnN0LT5jb3JlOwo+ICsJbXV0ZXhfbG9jaygmY29yZS0+bG9jayk7Cj4g KwlpZiAoaW5zdC0+aWQgPj0gMCAmJiBpbnN0LT5pZCA8IGNvcmUtPnN1cHBvcnRlZF9pbnN0YW5j ZV9jb3VudCkKPiArCQlnb3RvIGV4aXQ7Cj4gKwo+ICsJcmV0ID0gdnB1X2NvcmVfYWNxdWlyZV9p bnN0YW5jZShjb3JlKTsKPiArCWlmIChyZXQgPCAwKQo+ICsJCWdvdG8gZXhpdDsKPiArCj4gKwlp bnN0LT5pZCA9IHJldDsKPiArCWxpc3RfYWRkX3RhaWwoJmluc3QtPmxpc3QsICZjb3JlLT5pbnN0 YW5jZXMpOwo+ICsJcmV0ID0gMDsKPiArCWlmIChjb3JlLT5yZXMtPmFjdF9zaXplKSB7Cj4gKwkJ aW5zdC0+YWN0LnBoeXMgPSBjb3JlLT5hY3QucGh5cyArIGNvcmUtPnJlcy0+YWN0X3NpemUgKiBp bnN0LT5pZDsKPiArCQlpbnN0LT5hY3QudmlydCA9IGNvcmUtPmFjdC52aXJ0ICsgY29yZS0+cmVz LT5hY3Rfc2l6ZSAqIGluc3QtPmlkOwo+ICsJCWluc3QtPmFjdC5sZW5ndGggPSBjb3JlLT5yZXMt PmFjdF9zaXplOwo+ICsJfQo+ICsJdnB1X2luc3RfY3JlYXRlX2RiZ2ZzX2ZpbGUoaW5zdCk7Cj4g K2V4aXQ6Cj4gKwltdXRleF91bmxvY2soJmNvcmUtPmxvY2spOwo+ICsKPiArCWlmIChyZXQpCj4g KwkJY29yZV9lcnIoY29yZSwgInJlZ2lzdGVyIGluc3RhbmNlIGZhaWxcbiIpOwo+ICsJcmV0dXJu IHJldDsKPiArfQo+ICsKPiAraW50IHZwdV9pbnN0X3VucmVnaXN0ZXIoc3RydWN0IHZwdV9pbnN0 ICppbnN0KQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X2NvcmUgKmNvcmU7Cj4gKwo+ICsJV0FSTl9PTigh aW5zdCk7Cj4gKwo+ICsJY29yZSA9IGluc3QtPmNvcmU7Cj4gKwo+ICsJdnB1X2NsZWFyX3JlcXVl c3QoaW5zdCk7Cj4gKwltdXRleF9sb2NrKCZjb3JlLT5sb2NrKTsKPiArCWlmIChpbnN0LT5pZCA+ PSAwICYmIGluc3QtPmlkIDwgY29yZS0+c3VwcG9ydGVkX2luc3RhbmNlX2NvdW50KSB7Cj4gKwkJ dnB1X2luc3RfcmVtb3ZlX2RiZ2ZzX2ZpbGUoaW5zdCk7Cj4gKwkJbGlzdF9kZWxfaW5pdCgmaW5z dC0+bGlzdCk7Cj4gKwkJdnB1X2NvcmVfcmVsZWFzZV9pbnN0YW5jZShjb3JlLCBpbnN0LT5pZCk7 Cj4gKwkJaW5zdC0+aWQgPSBWUFVfSU5TVF9OVUxMX0lEOwo+ICsJfQo+ICsJdnB1X2NvcmVfY2hl Y2tfaGFuZyhjb3JlKTsKPiArCWlmIChjb3JlLT5zdGF0ZSA9PSBWUFVfQ09SRV9IQU5HICYmICFj b3JlLT5pbnN0YW5jZV9tYXNrKSB7Cj4gKwkJY29yZV9kYmcoY29yZSwgTFZMX1dBUk4sICJyZXNl dCBoYW5nIGNvcmVcbiIpOwo+ICsJCWlmICghdnB1X2NvcmVfc3dfcmVzZXQoY29yZSkpIHsKPiAr CQkJY29yZS0+c3RhdGUgPSBWUFVfQ09SRV9BQ1RJVkU7Cj4gKwkJCWNvcmUtPmhhbmdfbWFzayA9 IDA7Cj4gKwkJfQo+ICsJfQo+ICsJbXV0ZXhfdW5sb2NrKCZjb3JlLT5sb2NrKTsKPiArCj4gKwly ZXR1cm4gMDsKPiArfQo+ICsKPiArc3RydWN0IHZwdV9pbnN0ICp2cHVfY29yZV9maW5kX2luc3Rh bmNlKHN0cnVjdCB2cHVfY29yZSAqY29yZSwgdTMyIGluZGV4KQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1 X2luc3QgKmluc3QgPSBOVUxMOwo+ICsJc3RydWN0IHZwdV9pbnN0ICp0bXA7Cj4gKwo+ICsJbXV0 ZXhfbG9jaygmY29yZS0+bG9jayk7Cj4gKwlpZiAoIXRlc3RfYml0KGluZGV4LCAmY29yZS0+aW5z dGFuY2VfbWFzaykpCj4gKwkJZ290byBleGl0Owo+ICsJbGlzdF9mb3JfZWFjaF9lbnRyeSh0bXAs ICZjb3JlLT5pbnN0YW5jZXMsIGxpc3QpIHsKPiArCQlpZiAodG1wLT5pZCA9PSBpbmRleCkgewo+ ICsJCQlpbnN0ID0gdnB1X2luc3RfZ2V0KHRtcCk7Cj4gKwkJCWJyZWFrOwo+ICsJCX0KPiArCX0K PiArZXhpdDoKPiArCW11dGV4X3VubG9jaygmY29yZS0+bG9jayk7Cj4gKwo+ICsJcmV0dXJuIGlu c3Q7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdnB1X2NvcmVfcGFyc2VfZHQoc3RydWN0IHZwdV9j b3JlICpjb3JlLCBzdHJ1Y3QgZGV2aWNlX25vZGUgKm5wKQo+ICt7Cj4gKwlzdHJ1Y3QgZGV2aWNl X25vZGUgKm5vZGU7Cj4gKwlzdHJ1Y3QgcmVzb3VyY2UgcmVzOwo+ICsKPiArCWlmIChvZl9jb3Vu dF9waGFuZGxlX3dpdGhfYXJncyhucCwgIm1lbW9yeS1yZWdpb24iLCBOVUxMKSA8IDIpIHsKPiAr CQljb3JlX2Vycihjb3JlLCAibmVlZCAyIG1lbW9yeS1yZWdpb24gZm9yIGJvb3QgYW5kIHJwY1xu Iik7Cj4gKwkJcmV0dXJuIC1FTk9ERVY7Cj4gKwl9Cj4gKwo+ICsJbm9kZSA9IG9mX3BhcnNlX3Bo YW5kbGUobnAsICJtZW1vcnktcmVnaW9uIiwgMCk7Cj4gKwlpZiAoIW5vZGUpIHsKPiArCQljb3Jl X2Vycihjb3JlLCAiYm9vdC1yZWdpb24gb2ZfcGFyc2VfcGhhbmRsZSBlcnJvclxuIik7Cj4gKwkJ cmV0dXJuIC1FTk9ERVY7Cj4gKwl9Cj4gKwlpZiAob2ZfYWRkcmVzc190b19yZXNvdXJjZShub2Rl LCAwLCAmcmVzKSkgewo+ICsJCWNvcmVfZXJyKGNvcmUsICJib290LXJlZ2lvbiBvZl9hZGRyZXNz X3RvX3Jlc291cmNlIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCWNv cmUtPmZ3LnBoeXMgPSByZXMuc3RhcnQ7Cj4gKwljb3JlLT5mdy5sZW5ndGggPSByZXNvdXJjZV9z aXplKCZyZXMpOwo+ICsJY29yZV9kYmcoY29yZSwgTFZMX0lORk8sICJib290LXJlZ2lvbiA6IDwl cGFkLCAweCV4PlxuIiwKPiArCQkJJmNvcmUtPmZ3LnBoeXMsIGNvcmUtPmZ3Lmxlbmd0aCk7Cj4g Kwo+ICsJbm9kZSA9IG9mX3BhcnNlX3BoYW5kbGUobnAsICJtZW1vcnktcmVnaW9uIiwgMSk7Cj4g KwlpZiAoIW5vZGUpIHsKPiArCQljb3JlX2Vycihjb3JlLCAicnBjLXJlZ2lvbiBvZl9wYXJzZV9w aGFuZGxlIGVycm9yXG4iKTsKPiArCQlyZXR1cm4gLUVOT0RFVjsKPiArCX0KPiArCWlmIChvZl9h ZGRyZXNzX3RvX3Jlc291cmNlKG5vZGUsIDAsICZyZXMpKSB7Cj4gKwkJY29yZV9lcnIoY29yZSwg InJwYy1yZWdpb24gb2ZfYWRkcmVzc190b19yZXNvdXJjZSBlcnJvclxuIik7Cj4gKwkJcmV0dXJu IC1FSU5WQUw7Cj4gKwl9Cj4gKwljb3JlLT5ycGMucGh5cyA9IHJlcy5zdGFydDsKPiArCWNvcmUt PnJwYy5sZW5ndGggPSByZXNvdXJjZV9zaXplKCZyZXMpOwo+ICsJY29yZV9kYmcoY29yZSwgTFZM X0RFQlVHLCAicnBjLXJlZ2lvbiA6IDwlcGFkLCAweCV4PlxuIiwKPiArCQkJJmNvcmUtPnJwYy5w aHlzLCBjb3JlLT5ycGMubGVuZ3RoKTsKPiArCj4gKwlpZiAoY29yZS0+cnBjLmxlbmd0aCA8IGNv cmUtPnJlcy0+cnBjX3NpemUgKyBjb3JlLT5yZXMtPmZ3bG9nX3NpemUpIHsKPiArCQljb3JlX2Vy cihjb3JlLCAidGhlIHJwYy1yZWdpb24gPCVwYWQsIDB4JXg+IGlzIG5vdCBlbm91Z2hcbiIsCj4g KwkJCQkmY29yZS0+cnBjLnBoeXMsIGNvcmUtPnJwYy5sZW5ndGgpOwo+ICsJCXJldHVybiAtRUlO VkFMOwo+ICsJfQo+ICsKPiArCWNvcmUtPmZ3LnZpcnQgPSBpb3JlbWFwX3djKGNvcmUtPmZ3LnBo eXMsIGNvcmUtPmZ3Lmxlbmd0aCk7Cj4gKwljb3JlLT5ycGMudmlydCA9IGlvcmVtYXBfd2MoY29y ZS0+cnBjLnBoeXMsIGNvcmUtPnJwYy5sZW5ndGgpOwo+ICsJbWVtc2V0X2lvKGNvcmUtPnJwYy52 aXJ0LCAwLCBjb3JlLT5ycGMubGVuZ3RoKTsKPiArCj4gKwlpZiAodnB1X2lmYWNlX2NoZWNrX21l bW9yeV9yZWdpb24oY29yZSwKPiArCQkJCWNvcmUtPnJwYy5waHlzLAo+ICsJCQkJY29yZS0+cnBj Lmxlbmd0aCkgIT0gVlBVX0NPUkVfTUVNT1JZX1VOQ0FDSEVEKSB7Cj4gKwkJY29yZV9lcnIoY29y ZSwgInJwYyByZWdpb248JXBhZCwgMHgleD4gaXNuJ3QgdW5jYWNoZWRcbiIsCj4gKwkJCQkmY29y ZS0+cnBjLnBoeXMsIGNvcmUtPnJwYy5sZW5ndGgpOwo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsJ fQo+ICsKPiArCWNvcmUtPmxvZy5waHlzID0gY29yZS0+cnBjLnBoeXMgKyBjb3JlLT5yZXMtPnJw Y19zaXplOwo+ICsJY29yZS0+bG9nLnZpcnQgPSBjb3JlLT5ycGMudmlydCArIGNvcmUtPnJlcy0+ cnBjX3NpemU7Cj4gKwljb3JlLT5sb2cubGVuZ3RoID0gY29yZS0+cmVzLT5md2xvZ19zaXplOwo+ ICsJY29yZS0+YWN0LnBoeXMgPSBjb3JlLT5sb2cucGh5cyArIGNvcmUtPmxvZy5sZW5ndGg7Cj4g Kwljb3JlLT5hY3QudmlydCA9IGNvcmUtPmxvZy52aXJ0ICsgY29yZS0+bG9nLmxlbmd0aDsKPiAr CWNvcmUtPmFjdC5sZW5ndGggPSBjb3JlLT5ycGMubGVuZ3RoIC0gY29yZS0+cmVzLT5ycGNfc2l6 ZSAtIGNvcmUtPmxvZy5sZW5ndGg7Cj4gKwljb3JlLT5ycGMubGVuZ3RoID0gY29yZS0+cmVzLT5y cGNfc2l6ZTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCB2cHVfY29y ZV9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+ICt7Cj4gKwlzdHJ1Y3QgZGV2 aWNlICpkZXYgPSAmcGRldi0+ZGV2Owo+ICsJc3RydWN0IHZwdV9jb3JlICpjb3JlOwo+ICsJc3Ry dWN0IHZwdV9kZXYgKnZwdSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYtPnBhcmVudCk7Cj4gKwlzdHJ1 Y3QgdnB1X3NoYXJlZF9hZGRyICppZmFjZTsKPiArCXUzMiBpZmFjZV9kYXRhX3NpemU7Cj4gKwlp bnQgcmV0Owo+ICsKPiArCXZwdV9kYmcoTFZMX1dBUk4sICJjb3JlICVzIHByb2JlXG4iLCBwZGV2 LT5kZXYub2Zfbm9kZS0+bmFtZSk7Cj4gKwlpZiAoIXZwdSkKPiArCQlyZXR1cm4gLUVJTlZBTDsK PiArCWNvcmUgPSBkZXZtX2t6YWxsb2MoZGV2LCBzaXplb2YoKmNvcmUpLCBHRlBfS0VSTkVMKTsK PiArCWlmICghY29yZSkKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwljb3JlLT5wZGV2ID0g cGRldjsKPiArCWNvcmUtPmRldiA9IGRldjsKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYs IGNvcmUpOwo+ICsJY29yZS0+dnB1ID0gdnB1Owo+ICsJSU5JVF9MSVNUX0hFQUQoJmNvcmUtPmlu c3RhbmNlcyk7Cj4gKwltdXRleF9pbml0KCZjb3JlLT5sb2NrKTsKPiArCW11dGV4X2luaXQoJmNv cmUtPmNtZF9sb2NrKTsKPiArCWluaXRfY29tcGxldGlvbigmY29yZS0+Y21wKTsKPiArCWluaXRf d2FpdHF1ZXVlX2hlYWQoJmNvcmUtPmFja193cSk7Cj4gKwljb3JlLT5zdGF0ZSA9IFZQVV9DT1JF X0RFSU5JVDsKPiArCj4gKwljb3JlLT5yZXMgPSBvZl9kZXZpY2VfZ2V0X21hdGNoX2RhdGEoZGV2 KTsKPiArCWlmICghY29yZS0+cmVzKQo+ICsJCXJldHVybiAtRU5PREVWOwo+ICsKPiArCWNvcmUt PnR5cGUgPSBjb3JlLT5yZXMtPnR5cGU7Cj4gKwljb3JlLT5pZCA9IG9mX2FsaWFzX2dldF9pZChk ZXYtPm9mX25vZGUsICJ2cHVfY29yZSIpOwo+ICsJaWYgKGNvcmUtPmlkIDwgMCkgewo+ICsJCXZw dV9lcnIoImNhbid0IGdldCB2cHUgY29yZSBpZFxuIik7Cj4gKwkJcmV0dXJuIGNvcmUtPmlkOwo+ ICsJfQo+ICsJcmV0ID0gdnB1X2NvcmVfcGFyc2VfZHQoY29yZSwgZGV2LT5vZl9ub2RlKTsKPiAr CWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwljb3JlLT5iYXNlID0gZGV2bV9wbGF0 Zm9ybV9pb3JlbWFwX3Jlc291cmNlKHBkZXYsIDApOwo+ICsJaWYgKElTX0VSUihjb3JlLT5iYXNl KSkKPiArCQlyZXR1cm4gUFRSX0VSUihjb3JlLT5iYXNlKTsKPiArCj4gKwlpZiAoIXZwdV9pZmFj ZV9jaGVja19jb2RlYyhjb3JlKSkgewo+ICsJCWNvcmVfZXJyKGNvcmUsICJpcyBub3Qgc3VwcG9y dGVkXG4iKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlyZXQgPSB2cHVfbWJv eF9pbml0KGNvcmUpOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1cm4gcmV0Owo+ICsKPiArCWlmYWNl ID0gZGV2bV9remFsbG9jKGRldiwgc2l6ZW9mKCppZmFjZSksIEdGUF9LRVJORUwpOwo+ICsJaWYg KCFpZmFjZSkKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwlpZmFjZV9kYXRhX3NpemUgPSB2 cHVfaWZhY2VfZ2V0X2RhdGFfc2l6ZShjb3JlKTsKPiArCWlmIChpZmFjZV9kYXRhX3NpemUpIHsK PiArCQlpZmFjZS0+cHJpdiA9IGRldm1fa3phbGxvYyhkZXYsIGlmYWNlX2RhdGFfc2l6ZSwgR0ZQ X0tFUk5FTCk7Cj4gKwkJaWYgKCFpZmFjZS0+cHJpdikKPiArCQkJcmV0dXJuIC1FTk9NRU07Cj4g Kwl9Cj4gKwo+ICsJcmV0ID0gdnB1X2lmYWNlX2luaXQoY29yZSwgaWZhY2UsICZjb3JlLT5ycGMs IGNvcmUtPmZ3LnBoeXMpOwo+ICsJaWYgKHJldCkgewo+ICsJCWNvcmVfZXJyKGNvcmUsICJpbml0 IGlmYWNlIGZhaWwsIHJldCA9ICVkXG4iLCByZXQpOwo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4g Kwo+ICsJdnB1X2lmYWNlX2NvbmZpZ19zeXN0ZW0oY29yZSwgdnB1LT5yZXMtPm1yZWdfYmFzZSwg dnB1LT5iYXNlKTsKPiArCXZwdV9pZmFjZV9zZXRfbG9nX2J1Zihjb3JlLCAmY29yZS0+bG9nKTsK PiArCj4gKwlwbV9ydW50aW1lX2VuYWJsZShkZXYpOwo+ICsJcmV0ID0gcG1fcnVudGltZV9nZXRf c3luYyhkZXYpOwo+ICsJaWYgKHJldCkgewo+ICsJCXBtX3J1bnRpbWVfcHV0X25vaWRsZShkZXYp Owo+ICsJCXBtX3J1bnRpbWVfc2V0X3N1c3BlbmRlZChkZXYpOwo+ICsJCWdvdG8gZXJyX3J1bnRp bWVfZGlzYWJsZTsKPiArCX0KPiArCj4gKwlpZiAodnB1X2lmYWNlX2dldF9wb3dlcl9zdGF0ZShj b3JlKSkKPiArCQlyZXQgPSB2cHVfY29yZV9yZXN0b3JlKGNvcmUpOwo+ICsJaWYgKHJldCkKPiAr CQlnb3RvIGVycl9jb3JlX2Jvb3Q7Cj4gKwo+ICsJcmV0ID0gdnB1X2NvcmVfcmVnaXN0ZXIoZGV2 LT5wYXJlbnQsIGNvcmUpOwo+ICsJaWYgKHJldCkKPiArCQlnb3RvIGVycl9jb3JlX3JlZ2lzdGVy Owo+ICsJY29yZS0+cGFyZW50ID0gZGV2LT5wYXJlbnQ7Cj4gKwo+ICsJcG1fcnVudGltZV9wdXRf c3luYyhkZXYpOwo+ICsJdnB1X2NvcmVfY3JlYXRlX2RiZ2ZzX2ZpbGUoY29yZSk7Cj4gKwo+ICsJ cmV0dXJuIDA7Cj4gKwo+ICtlcnJfY29yZV9yZWdpc3RlcjoKPiArCXZwdV9jb3JlX3NodXRkb3du KGNvcmUpOwo+ICtlcnJfY29yZV9ib290Ogo+ICsJcG1fcnVudGltZV9wdXRfc3luYyhkZXYpOwo+ ICtlcnJfcnVudGltZV9kaXNhYmxlOgo+ICsJcG1fcnVudGltZV9kaXNhYmxlKGRldik7Cj4gKwo+ ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIGludCB2cHVfY29yZV9yZW1vdmUoc3Ry dWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKPiArewo+ICsJc3RydWN0IGRldmljZSAqZGV2ID0g JnBkZXYtPmRldjsKPiArCXN0cnVjdCB2cHVfY29yZSAqY29yZSA9IHBsYXRmb3JtX2dldF9kcnZk YXRhKHBkZXYpOwo+ICsJaW50IHJldDsKPiArCj4gKwl2cHVfY29yZV9yZW1vdmVfZGJnZnNfZmls ZShjb3JlKTsKPiArCXJldCA9IHBtX3J1bnRpbWVfZ2V0X3N5bmMoZGV2KTsKPiArCVdBUk5fT04o cmV0IDwgMCk7Cj4gKwo+ICsJdnB1X2NvcmVfc2h1dGRvd24oY29yZSk7Cj4gKwlwbV9ydW50aW1l X3B1dF9zeW5jKGRldik7Cj4gKwlwbV9ydW50aW1lX2Rpc2FibGUoZGV2KTsKPiArCj4gKwl2cHVf Y29yZV91bnJlZ2lzdGVyKGNvcmUtPnBhcmVudCwgY29yZSk7Cj4gKwlpb3VubWFwKGNvcmUtPmZ3 LnZpcnQpOwo+ICsJaW91bm1hcChjb3JlLT5ycGMudmlydCk7Cj4gKwltdXRleF9kZXN0cm95KCZj b3JlLT5sb2NrKTsKPiArCW11dGV4X2Rlc3Ryb3koJmNvcmUtPmNtZF9sb2NrKTsKPiArCj4gKwly ZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBfX21heWJlX3VudXNlZCB2cHVfY29yZV9y dW50aW1lX3Jlc3VtZShzdHJ1Y3QgZGV2aWNlICpkZXYpCj4gK3sKPiArCXN0cnVjdCB2cHVfY29y ZSAqY29yZSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsKPiArCXJldHVybiB2cHVfbWJveF9y ZXF1ZXN0KGNvcmUpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IF9fbWF5YmVfdW51c2VkIHZwdV9j b3JlX3J1bnRpbWVfc3VzcGVuZChzdHJ1Y3QgZGV2aWNlICpkZXYpCj4gK3sKPiArCXN0cnVjdCB2 cHVfY29yZSAqY29yZSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsKPiArCXZwdV9tYm94X2Zy ZWUoY29yZSk7Cj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgdnB1X2NvcmVf Y2FuY2VsX3dvcmsoc3RydWN0IHZwdV9jb3JlICpjb3JlKQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X2lu c3QgKmluc3QgPSBOVUxMOwo+ICsKPiArCWNhbmNlbF93b3JrX3N5bmMoJmNvcmUtPm1zZ193b3Jr KTsKPiArCWNhbmNlbF9kZWxheWVkX3dvcmtfc3luYygmY29yZS0+bXNnX2RlbGF5ZWRfd29yayk7 Cj4gKwo+ICsJbXV0ZXhfbG9jaygmY29yZS0+bG9jayk7Cj4gKwlsaXN0X2Zvcl9lYWNoX2VudHJ5 KGluc3QsICZjb3JlLT5pbnN0YW5jZXMsIGxpc3QpCj4gKwkJY2FuY2VsX3dvcmtfc3luYygmaW5z dC0+bXNnX3dvcmspOwo+ICsJbXV0ZXhfdW5sb2NrKCZjb3JlLT5sb2NrKTsKPiArfQo+ICsKPiAr c3RhdGljIHZvaWQgdnB1X2NvcmVfcmVzdW1lX3dvcmsoc3RydWN0IHZwdV9jb3JlICpjb3JlKQo+ ICt7Cj4gKwlzdHJ1Y3QgdnB1X2luc3QgKmluc3QgPSBOVUxMOwo+ICsJdW5zaWduZWQgbG9uZyBk ZWxheSA9IG1zZWNzX3RvX2ppZmZpZXMoMTApOwo+ICsKPiArCXF1ZXVlX3dvcmsoY29yZS0+d29y a3F1ZXVlLCAmY29yZS0+bXNnX3dvcmspOwo+ICsJcXVldWVfZGVsYXllZF93b3JrKGNvcmUtPndv cmtxdWV1ZSwgJmNvcmUtPm1zZ19kZWxheWVkX3dvcmssIGRlbGF5KTsKPiArCj4gKwltdXRleF9s b2NrKCZjb3JlLT5sb2NrKTsKPiArCWxpc3RfZm9yX2VhY2hfZW50cnkoaW5zdCwgJmNvcmUtPmlu c3RhbmNlcywgbGlzdCkKPiArCQlxdWV1ZV93b3JrKGluc3QtPndvcmtxdWV1ZSwgJmluc3QtPm1z Z193b3JrKTsKPiArCW11dGV4X3VubG9jaygmY29yZS0+bG9jayk7Cj4gK30KPiArCj4gK3N0YXRp YyBpbnQgX19tYXliZV91bnVzZWQgdnB1X2NvcmVfcmVzdW1lKHN0cnVjdCBkZXZpY2UgKmRldikK PiArewo+ICsJc3RydWN0IHZwdV9jb3JlICpjb3JlID0gZGV2X2dldF9kcnZkYXRhKGRldik7Cj4g KwlpbnQgcmV0ID0gMDsKPiArCj4gKwlpZiAoIWNvcmUtPnJlcy0+c3RhbmRhbG9uZSkKPiArCQly ZXR1cm4gMDsKPiArCj4gKwltdXRleF9sb2NrKCZjb3JlLT5sb2NrKTsKPiArCXBtX3J1bnRpbWVf Z2V0X3N5bmMoZGV2KTsKPiArCXZwdV9jb3JlX2dldF92cHUoY29yZSk7Cj4gKwlpZiAoY29yZS0+ c3RhdGUgIT0gVlBVX0NPUkVfU05BUFNIT1QpCj4gKwkJZ290byBleGl0Owo+ICsKPiArCWlmICgh dnB1X2lmYWNlX2dldF9wb3dlcl9zdGF0ZShjb3JlKSkgewo+ICsJCWlmICghbGlzdF9lbXB0eSgm Y29yZS0+aW5zdGFuY2VzKSkgewo+ICsJCQlyZXQgPSB2cHVfY29yZV9ib290KGNvcmUsIGZhbHNl KTsKPiArCQkJaWYgKHJldCkgewo+ICsJCQkJY29yZV9lcnIoY29yZSwgIiVzIGJvb3QgZmFpbFxu IiwgX19mdW5jX18pOwo+ICsJCQkJY29yZS0+c3RhdGUgPSBWUFVfQ09SRV9ERUlOSVQ7Cj4gKwkJ CQlnb3RvIGV4aXQ7Cj4gKwkJCX0KPiArCQkJY29yZS0+c3RhdGUgPSBWUFVfQ09SRV9BQ1RJVkU7 Cj4gKwkJfSBlbHNlIHsKPiArCQkJY29yZS0+c3RhdGUgPSBWUFVfQ09SRV9ERUlOSVQ7Cj4gKwkJ fQo+ICsJfSBlbHNlIHsKPiArCQlpZiAoIWxpc3RfZW1wdHkoJmNvcmUtPmluc3RhbmNlcykpIHsK PiArCQkJcmV0ID0gdnB1X2NvcmVfc3dfcmVzZXQoY29yZSk7Cj4gKwkJCWlmIChyZXQpIHsKPiAr CQkJCWNvcmVfZXJyKGNvcmUsICIlcyBzd19yZXNldCBmYWlsXG4iLCBfX2Z1bmNfXyk7Cj4gKwkJ CQljb3JlLT5zdGF0ZSA9IFZQVV9DT1JFX0hBTkc7Cj4gKwkJCQlnb3RvIGV4aXQ7Cj4gKwkJCX0K PiArCQl9Cj4gKwkJY29yZS0+c3RhdGUgPSBWUFVfQ09SRV9BQ1RJVkU7Cj4gKwl9Cj4gKwo+ICtl eGl0Ogo+ICsJcG1fcnVudGltZV9wdXRfc3luYyhkZXYpOwo+ICsJbXV0ZXhfdW5sb2NrKCZjb3Jl LT5sb2NrKTsKPiArCj4gKwl2cHVfY29yZV9yZXN1bWVfd29yayhjb3JlKTsKPiArCXJldHVybiBy ZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgX19tYXliZV91bnVzZWQgdnB1X2NvcmVfc3VzcGVu ZChzdHJ1Y3QgZGV2aWNlICpkZXYpCj4gK3sKPiArCXN0cnVjdCB2cHVfY29yZSAqY29yZSA9IGRl dl9nZXRfZHJ2ZGF0YShkZXYpOwo+ICsJaW50IHJldCA9IDA7Cj4gKwo+ICsJaWYgKCFjb3JlLT5y ZXMtPnN0YW5kYWxvbmUpCj4gKwkJcmV0dXJuIDA7Cj4gKwo+ICsJbXV0ZXhfbG9jaygmY29yZS0+ bG9jayk7Cj4gKwlpZiAoY29yZS0+c3RhdGUgPT0gVlBVX0NPUkVfQUNUSVZFKSB7Cj4gKwkJaWYg KCFsaXN0X2VtcHR5KCZjb3JlLT5pbnN0YW5jZXMpKSB7Cj4gKwkJCXJldCA9IHZwdV9jb3JlX3Nu YXBzaG90KGNvcmUpOwo+ICsJCQlpZiAocmV0KSB7Cj4gKwkJCQltdXRleF91bmxvY2soJmNvcmUt PmxvY2spOwo+ICsJCQkJcmV0dXJuIHJldDsKPiArCQkJfQo+ICsJCX0KPiArCj4gKwkJY29yZS0+ c3RhdGUgPSBWUFVfQ09SRV9TTkFQU0hPVDsKPiArCX0KPiArCW11dGV4X3VubG9jaygmY29yZS0+ bG9jayk7Cj4gKwo+ICsJdnB1X2NvcmVfY2FuY2VsX3dvcmsoY29yZSk7Cj4gKwo+ICsJbXV0ZXhf bG9jaygmY29yZS0+bG9jayk7Cj4gKwl2cHVfY29yZV9wdXRfdnB1KGNvcmUpOwo+ICsJbXV0ZXhf dW5sb2NrKCZjb3JlLT5sb2NrKTsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBj b25zdCBzdHJ1Y3QgZGV2X3BtX29wcyB2cHVfY29yZV9wbV9vcHMgPSB7Cj4gKwlTRVRfUlVOVElN RV9QTV9PUFModnB1X2NvcmVfcnVudGltZV9zdXNwZW5kLCB2cHVfY29yZV9ydW50aW1lX3Jlc3Vt ZSwgTlVMTCkKPiArCVNFVF9TWVNURU1fU0xFRVBfUE1fT1BTKHZwdV9jb3JlX3N1c3BlbmQsIHZw dV9jb3JlX3Jlc3VtZSkKPiArfTsKPiArCj4gK3N0YXRpYyBzdHJ1Y3QgdnB1X2NvcmVfcmVzb3Vy Y2VzIGlteDhxX2VuYyA9IHsKPiArCS50eXBlID0gVlBVX0NPUkVfVFlQRV9FTkMsCj4gKwkuZndu YW1lID0gInZwdS92cHVfZndfaW14OF9lbmMuYmluIiwKPiArCS5zdHJpZGUgPSAxNiwKPiArCS5t YXhfd2lkdGggPSAxOTIwLAo+ICsJLm1heF9oZWlnaHQgPSAxOTIwLAo+ICsJLm1pbl93aWR0aCA9 IDY0LAo+ICsJLm1pbl9oZWlnaHQgPSA0OCwKPiArCS5zdGVwX3dpZHRoID0gMiwKPiArCS5zdGVw X2hlaWdodCA9IDIsCj4gKwkucnBjX3NpemUgPSAweDgwMDAwLAo+ICsJLmZ3bG9nX3NpemUgPSAw eDgwMDAwLAo+ICsJLmFjdF9zaXplID0gMHhjMDAwMCwKPiArCS5zdGFuZGFsb25lID0gdHJ1ZSwK PiArfTsKPiArCj4gK3N0YXRpYyBzdHJ1Y3QgdnB1X2NvcmVfcmVzb3VyY2VzIGlteDhxX2RlYyA9 IHsKPiArCS50eXBlID0gVlBVX0NPUkVfVFlQRV9ERUMsCj4gKwkuZnduYW1lID0gInZwdS92cHVf ZndfaW14OF9kZWMuYmluIiwKPiArCS5zdHJpZGUgPSAyNTYsCj4gKwkubWF4X3dpZHRoID0gODE4 OCwKPiArCS5tYXhfaGVpZ2h0ID0gODE4OCwKPiArCS5taW5fd2lkdGggPSAxNiwKPiArCS5taW5f aGVpZ2h0ID0gMTYsCj4gKwkuc3RlcF93aWR0aCA9IDEsCj4gKwkuc3RlcF9oZWlnaHQgPSAxLAo+ ICsJLnJwY19zaXplID0gMHg4MDAwMCwKPiArCS5md2xvZ19zaXplID0gMHg4MDAwMCwKPiArCS5z dGFuZGFsb25lID0gdHJ1ZSwKPiArfTsKPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgb2ZfZGV2 aWNlX2lkIHZwdV9jb3JlX2R0X21hdGNoW10gPSB7Cj4gKwl7IC5jb21wYXRpYmxlID0gIm54cCxp bXg4cS12cHUtZW5jb2RlciIsIC5kYXRhID0gJmlteDhxX2VuYyB9LAo+ICsJeyAuY29tcGF0aWJs ZSA9ICJueHAsaW14OHEtdnB1LWRlY29kZXIiLCAuZGF0YSA9ICZpbXg4cV9kZWMgfSwKPiArCXt9 Cj4gK307Cj4gK01PRFVMRV9ERVZJQ0VfVEFCTEUob2YsIHZwdV9jb3JlX2R0X21hdGNoKTsKPiAr Cj4gK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1fZHJpdmVyIGFtcGhpb25fdnB1X2NvcmVfZHJpdmVy ID0gewo+ICsJLnByb2JlID0gdnB1X2NvcmVfcHJvYmUsCj4gKwkucmVtb3ZlID0gdnB1X2NvcmVf cmVtb3ZlLAo+ICsJLmRyaXZlciA9IHsKPiArCQkubmFtZSA9ICJhbXBoaW9uLXZwdS1jb3JlIiwK PiArCQkub2ZfbWF0Y2hfdGFibGUgPSB2cHVfY29yZV9kdF9tYXRjaCwKPiArCQkucG0gPSAmdnB1 X2NvcmVfcG1fb3BzLAo+ICsJfSwKPiArfTsKPiArbW9kdWxlX3BsYXRmb3JtX2RyaXZlcihhbXBo aW9uX3ZwdV9jb3JlX2RyaXZlcik7Cj4gKwo+ICtNT0RVTEVfQVVUSE9SKCJGcmVlc2NhbGUgU2Vt aWNvbmR1Y3RvciwgSW5jLiIpOwo+ICtNT0RVTEVfREVTQ1JJUFRJT04oIkxpbnV4IFZQVSBkcml2 ZXIgZm9yIEZyZWVzY2FsZSBpLk1YOFEiKTsKPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCB2MiIpOwo+ IGRpZmYgLS1naXQgYS9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X2NvcmUuaCBi L2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vYW1waGlvbi92cHVfY29yZS5oCj4gbmV3IGZpbGUgbW9k ZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAwMDAuLjEyODgwZTJlMTRiMgo+IC0tLSAvZGV2L251 bGwKPiArKysgYi9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X2NvcmUuaAo+IEBA IC0wLDAgKzEsMTYgQEAKPiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAgKi8K PiArLyoKPiArICogQ29weXJpZ2h0IDIwMjAtMjAyMSBOWFAKPiArICovCj4gKwo+ICsjaWZuZGVm IF9BTVBISU9OX1ZQVV9DT1JFX0gKPiArI2RlZmluZSBfQU1QSElPTl9WUFVfQ09SRV9ICj4gKwo+ ICt2b2lkIGNzcl93cml0ZWwoc3RydWN0IHZwdV9jb3JlICpjb3JlLCB1MzIgcmVnLCB1MzIgdmFs KTsKPiArdTMyIGNzcl9yZWFkbChzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUsIHUzMiByZWcpOwo+ICtp bnQgdnB1X2FsbG9jX2RtYShzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUsIHN0cnVjdCB2cHVfYnVmZmVy ICpidWYpOwo+ICt2b2lkIHZwdV9mcmVlX2RtYShzdHJ1Y3QgdnB1X2J1ZmZlciAqYnVmKTsKPiAr c3RydWN0IHZwdV9pbnN0ICp2cHVfY29yZV9maW5kX2luc3RhbmNlKHN0cnVjdCB2cHVfY29yZSAq Y29yZSwgdTMyIGluZGV4KTsKPiAraW50IHZwdV9jb3JlX2NoZWNrX2ZtdChzdHJ1Y3QgdnB1X2Nv cmUgKmNvcmUsIHUzMiBwaXhlbGZtdCk7Cj4gKwo+ICsjZW5kaWYKPiBkaWZmIC0tZ2l0IGEvZHJp dmVycy9tZWRpYS9wbGF0Zm9ybS9hbXBoaW9uL3ZwdV9kYmcuYyBiL2RyaXZlcnMvbWVkaWEvcGxh dGZvcm0vYW1waGlvbi92cHVfZGJnLmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAw MDAwMDAwMDAwMC4uNGRiZmJkNmQyZjQ2Cj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2RyaXZlcnMv bWVkaWEvcGxhdGZvcm0vYW1waGlvbi92cHVfZGJnLmMKPiBAQCAtMCwwICsxLDQ5NiBAQAo+ICsv LyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAo+ICsvKgo+ICsgKiBDb3B5cmlnaHQg MjAyMC0yMDIxIE5YUAo+ICsgKi8KPiArCj4gKyNkZWZpbmUgVEFHCQkiREVCVUciCj4gKwo+ICsj aW5jbHVkZSA8bGludXgvaW5pdC5oPgo+ICsjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+Cj4gKyNp bmNsdWRlIDxsaW51eC9pb2N0bC5oPgo+ICsjaW5jbHVkZSA8bGludXgvbGlzdC5oPgo+ICsjaW5j bHVkZSA8bGludXgvbW9kdWxlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4KPiArI2lu Y2x1ZGUgPGxpbnV4L3R5cGVzLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9wbV9ydW50aW1lLmg+Cj4g KyNpbmNsdWRlIDxtZWRpYS92NGwyLWRldmljZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvZGVidWdm cy5oPgo+ICsjaW5jbHVkZSAidnB1LmgiCj4gKyNpbmNsdWRlICJ2cHVfZGVmcy5oIgo+ICsjaW5j bHVkZSAidnB1X2hlbHBlcnMuaCIKPiArI2luY2x1ZGUgInZwdV9jbWRzLmgiCj4gKyNpbmNsdWRl ICJ2cHVfcnBjLmgiCj4gKyNpbmNsdWRlICJ2cHVfbG9nLmgiCj4gKwo+ICtzdHJ1Y3QgcHJpbnRf YnVmX2Rlc2Mgewo+ICsJdTMyIHN0YXJ0X2hfcGh5Owo+ICsJdTMyIHN0YXJ0X2hfdmlyOwo+ICsJ dTMyIHN0YXJ0X207Cj4gKwl1MzIgYnl0ZXM7Cj4gKwl1MzIgcmVhZDsKPiArCXUzMiB3cml0ZTsK PiArCWNoYXIgYnVmZmVyWzBdOwo+ICt9Owo+ICsKPiArc3RhdGljIGNoYXIgKnZiMl9zdGF0X25h bWVbXSA9IHsKPiArCVtWQjJfQlVGX1NUQVRFX0RFUVVFVUVEXSA9ICJkZXF1ZXVlZCIsCj4gKwlb VkIyX0JVRl9TVEFURV9JTl9SRVFVRVNUXSA9ICJpbl9yZXF1ZXN0IiwKPiArCVtWQjJfQlVGX1NU QVRFX1BSRVBBUklOR10gPSAicHJlcGFyaW5nIiwKPiArCVtWQjJfQlVGX1NUQVRFX1FVRVVFRF0g PSAicXVldWVkIiwKPiArCVtWQjJfQlVGX1NUQVRFX0FDVElWRV0gPSAiYWN0aXZlIiwKPiArCVtW QjJfQlVGX1NUQVRFX0RPTkVdID0gImRvbmUiLAo+ICsJW1ZCMl9CVUZfU1RBVEVfRVJST1JdID0g ImVycm9yIiwKPiArfTsKPiArCj4gK3N0YXRpYyBjaGFyICp2cHVfc3RhdF9uYW1lW10gPSB7Cj4g KwlbVlBVX0JVRl9TVEFURV9JRExFXSA9ICJpZGxlIiwKPiArCVtWUFVfQlVGX1NUQVRFX0lOVVNF XSA9ICJpbnVzZSIsCj4gKwlbVlBVX0JVRl9TVEFURV9ERUNPREVEXSA9ICJkZWNvZGVkIiwKPiAr CVtWUFVfQlVGX1NUQVRFX1JFQURZXSA9ICJyZWFkeSIsCj4gKwlbVlBVX0JVRl9TVEFURV9TS0lQ XSA9ICJza2lwIiwKPiArCVtWUFVfQlVGX1NUQVRFX0VSUk9SXSA9ICJlcnJvciIsCj4gK307Cj4g Kwo+ICtzdGF0aWMgaW50IHZwdV9kYmdfaW5zdGFuY2Uoc3RydWN0IHNlcV9maWxlICpzLCB2b2lk ICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X2luc3QgKmluc3QgPSBzLT5wcml2YXRlOwo+ICsJ Y2hhciBzdHJbMTI4XTsKPiArCWludCBudW07Cj4gKwlzdHJ1Y3QgdmIyX3F1ZXVlICp2cTsKPiAr CWludCBpOwo+ICsKPiArCW51bSA9IHNjbnByaW50ZihzdHIsIHNpemVvZihzdHIpLCAiWyVzXVxu IiwgdnB1X2NvcmVfdHlwZV9kZXNjKGluc3QtPnR5cGUpKTsKPiArCWlmIChzZXFfd3JpdGUocywg c3RyLCBudW0pKQo+ICsJCXJldHVybiAwOwo+ICsKPiArCW51bSA9IHNjbnByaW50ZihzdHIsIHNp emVvZihzdHIpLCAidGdpZyA9ICVkLHBpZCA9ICVkXG4iLCBpbnN0LT50Z2lkLCBpbnN0LT5waWQp Owo+ICsJaWYgKHNlcV93cml0ZShzLCBzdHIsIG51bSkpCj4gKwkJcmV0dXJuIDA7Cj4gKwludW0g PSBzY25wcmludGYoc3RyLCBzaXplb2Yoc3RyKSwgInN0YXRlID0gJWRcbiIsIGluc3QtPnN0YXRl KTsKPiArCWlmIChzZXFfd3JpdGUocywgc3RyLCBudW0pKQo+ICsJCXJldHVybiAwOwo+ICsJbnVt ID0gc2NucHJpbnRmKHN0ciwgc2l6ZW9mKHN0ciksCj4gKwkJCSJtaW5fYnVmZmVyX291dCA9ICVk LCBtaW5fYnVmZmVyX2NhcCA9ICVkXG4iLAo+ICsJCQlpbnN0LT5taW5fYnVmZmVyX291dCwgaW5z dC0+bWluX2J1ZmZlcl9jYXApOwo+ICsJaWYgKHNlcV93cml0ZShzLCBzdHIsIG51bSkpCj4gKwkJ cmV0dXJuIDA7Cj4gKwo+ICsKPiArCXZxID0gdjRsMl9tMm1fZ2V0X3NyY192cShpbnN0LT5tMm1f Y3R4KTsKPiArCW51bSA9IHNjbnByaW50ZihzdHIsIHNpemVvZihzdHIpLAo+ICsJCQkib3V0cHV0 KCVkKSA6IGZtdCA9ICVjJWMlYyVjICVkIHggJWQsICVkOyIsCj4gKwkJCXZiMl9pc19zdHJlYW1p bmcodnEpLAo+ICsJCQlpbnN0LT5vdXRfZm9ybWF0LnBpeGZtdCwKPiArCQkJaW5zdC0+b3V0X2Zv cm1hdC5waXhmbXQgPj4gOCwKPiArCQkJaW5zdC0+b3V0X2Zvcm1hdC5waXhmbXQgPj4gMTYsCj4g KwkJCWluc3QtPm91dF9mb3JtYXQucGl4Zm10ID4+IDI0LAo+ICsJCQlpbnN0LT5vdXRfZm9ybWF0 LndpZHRoLAo+ICsJCQlpbnN0LT5vdXRfZm9ybWF0LmhlaWdodCwKPiArCQkJdnEtPmxhc3RfYnVm ZmVyX2RlcXVldWVkKTsKPiArCWlmIChzZXFfd3JpdGUocywgc3RyLCBudW0pKQo+ICsJCXJldHVy biAwOwo+ICsJZm9yIChpID0gMDsgaSA8IGluc3QtPm91dF9mb3JtYXQubnVtX3BsYW5lczsgaSsr KSB7Cj4gKwkJbnVtID0gc2NucHJpbnRmKHN0ciwgc2l6ZW9mKHN0ciksICIgJWQoJWQpIiwKPiAr CQkJCWluc3QtPm91dF9mb3JtYXQuc2l6ZWltYWdlW2ldLAo+ICsJCQkJaW5zdC0+b3V0X2Zvcm1h dC5ieXRlc3BlcmxpbmVbaV0pOwo+ICsJCWlmIChzZXFfd3JpdGUocywgc3RyLCBudW0pKQo+ICsJ CQlyZXR1cm4gMDsKPiArCX0KPiArCWlmIChzZXFfd3JpdGUocywgIlxuIiwgMSkpCj4gKwkJcmV0 dXJuIDA7Cj4gKwo+ICsJdnEgPSB2NGwyX20ybV9nZXRfZHN0X3ZxKGluc3QtPm0ybV9jdHgpOwo+ ICsJbnVtID0gc2NucHJpbnRmKHN0ciwgc2l6ZW9mKHN0ciksCj4gKwkJCSJjYXB0dXJlKCVkKTog Zm10ID0gJWMlYyVjJWMgJWQgeCAlZCwgJWQ7IiwKPiArCQkJdmIyX2lzX3N0cmVhbWluZyh2cSks Cj4gKwkJCWluc3QtPmNhcF9mb3JtYXQucGl4Zm10LAo+ICsJCQlpbnN0LT5jYXBfZm9ybWF0LnBp eGZtdCA+PiA4LAo+ICsJCQlpbnN0LT5jYXBfZm9ybWF0LnBpeGZtdCA+PiAxNiwKPiArCQkJaW5z dC0+Y2FwX2Zvcm1hdC5waXhmbXQgPj4gMjQsCj4gKwkJCWluc3QtPmNhcF9mb3JtYXQud2lkdGgs Cj4gKwkJCWluc3QtPmNhcF9mb3JtYXQuaGVpZ2h0LAo+ICsJCQl2cS0+bGFzdF9idWZmZXJfZGVx dWV1ZWQpOwo+ICsJaWYgKHNlcV93cml0ZShzLCBzdHIsIG51bSkpCj4gKwkJcmV0dXJuIDA7Cj4g Kwlmb3IgKGkgPSAwOyBpIDwgaW5zdC0+Y2FwX2Zvcm1hdC5udW1fcGxhbmVzOyBpKyspIHsKPiAr CQludW0gPSBzY25wcmludGYoc3RyLCBzaXplb2Yoc3RyKSwgIiAlZCglZCkiLAo+ICsJCQkJaW5z dC0+Y2FwX2Zvcm1hdC5zaXplaW1hZ2VbaV0sCj4gKwkJCQlpbnN0LT5jYXBfZm9ybWF0LmJ5dGVz cGVybGluZVtpXSk7Cj4gKwkJaWYgKHNlcV93cml0ZShzLCBzdHIsIG51bSkpCj4gKwkJCXJldHVy biAwOwo+ICsJfQo+ICsJaWYgKHNlcV93cml0ZShzLCAiXG4iLCAxKSkKPiArCQlyZXR1cm4gMDsK PiArCW51bSA9IHNjbnByaW50ZihzdHIsIHNpemVvZihzdHIpLCAiY3JvcDogKCVkLCAlZCkgJWQg eCAlZFxuIiwKPiArCQkJaW5zdC0+Y3JvcC5sZWZ0LAo+ICsJCQlpbnN0LT5jcm9wLnRvcCwKPiAr CQkJaW5zdC0+Y3JvcC53aWR0aCwKPiArCQkJaW5zdC0+Y3JvcC5oZWlnaHQpOwo+ICsJaWYgKHNl cV93cml0ZShzLCBzdHIsIG51bSkpCj4gKwkJcmV0dXJuIDA7Cj4gKwo+ICsJdnEgPSB2NGwyX20y bV9nZXRfc3JjX3ZxKGluc3QtPm0ybV9jdHgpOwo+ICsJZm9yIChpID0gMDsgaSA8IHZxLT5udW1f YnVmZmVyczsgaSsrKSB7Cj4gKwkJc3RydWN0IHZiMl9idWZmZXIgKnZiID0gdnEtPmJ1ZnNbaV07 Cj4gKwkJc3RydWN0IHZiMl92NGwyX2J1ZmZlciAqdmJ1ZiA9IHRvX3ZiMl92NGwyX2J1ZmZlcih2 Yik7Cj4gKwkJc3RydWN0IHZwdV92YjJfYnVmZmVyICp2cHVfYnVmID0gdG9fdnB1X3ZiMl9idWZm ZXIodmJ1Zik7Cj4gKwo+ICsJCWlmICh2Yi0+c3RhdGUgPT0gVkIyX0JVRl9TVEFURV9ERVFVRVVF RCkKPiArCQkJY29udGludWU7Cj4gKwkJbnVtID0gc2NucHJpbnRmKHN0ciwgc2l6ZW9mKHN0ciks Cj4gKwkJCQkib3V0cHV0IFslMmRdIHN0YXRlID0gJTEwcywgJThzXG4iLAo+ICsJCQkJaSwgdmIy X3N0YXRfbmFtZVt2Yi0+c3RhdGVdLAo+ICsJCQkJdnB1X3N0YXRfbmFtZVt2cHVfYnVmLT5zdGF0 ZV0pOwo+ICsJCWlmIChzZXFfd3JpdGUocywgc3RyLCBudW0pKQo+ICsJCQlyZXR1cm4gMDsKPiAr CX0KPiArCj4gKwl2cSA9IHY0bDJfbTJtX2dldF9kc3RfdnEoaW5zdC0+bTJtX2N0eCk7Cj4gKwlm b3IgKGkgPSAwOyBpIDwgdnEtPm51bV9idWZmZXJzOyBpKyspIHsKPiArCQlzdHJ1Y3QgdmIyX2J1 ZmZlciAqdmIgPSB2cS0+YnVmc1tpXTsKPiArCQlzdHJ1Y3QgdmIyX3Y0bDJfYnVmZmVyICp2YnVm ID0gdG9fdmIyX3Y0bDJfYnVmZmVyKHZiKTsKPiArCQlzdHJ1Y3QgdnB1X3ZiMl9idWZmZXIgKnZw dV9idWYgPSB0b192cHVfdmIyX2J1ZmZlcih2YnVmKTsKPiArCj4gKwkJaWYgKHZiLT5zdGF0ZSA9 PSBWQjJfQlVGX1NUQVRFX0RFUVVFVUVEKQo+ICsJCQljb250aW51ZTsKPiArCQludW0gPSBzY25w cmludGYoc3RyLCBzaXplb2Yoc3RyKSwKPiArCQkJCSJjYXB0dXJlWyUyZF0gc3RhdGUgPSAlMTBz LCAlOHNcbiIsCj4gKwkJCQlpLCB2YjJfc3RhdF9uYW1lW3ZiLT5zdGF0ZV0sCj4gKwkJCQl2cHVf c3RhdF9uYW1lW3ZwdV9idWYtPnN0YXRlXSk7Cj4gKwkJaWYgKHNlcV93cml0ZShzLCBzdHIsIG51 bSkpCj4gKwkJCXJldHVybiAwOwo+ICsJfQo+ICsKPiArCW51bSA9IHNjbnByaW50ZihzdHIsIHNp emVvZihzdHIpLCAic2VxdWVuY2UgPSAlZFxuIiwgaW5zdC0+c2VxdWVuY2UpOwo+ICsJaWYgKHNl cV93cml0ZShzLCBzdHIsIG51bSkpCj4gKwkJcmV0dXJuIDA7Cj4gKwo+ICsJaWYgKGluc3QtPnVz ZV9zdHJlYW1fYnVmZmVyKSB7Cj4gKwkJbnVtID0gc2NucHJpbnRmKHN0ciwgc2l6ZW9mKHN0ciks ICJzdHJlYW1fYnVmZmVyID0gJWQgLyAlZCwgPCVwYWQsIDB4JXg+XG4iLAo+ICsJCQkJdnB1X2hl bHBlcl9nZXRfdXNlZF9zcGFjZShpbnN0KSwKPiArCQkJCWluc3QtPnN0cmVhbV9idWZmZXIubGVu Z3RoLAo+ICsJCQkJJmluc3QtPnN0cmVhbV9idWZmZXIucGh5cywKPiArCQkJCWluc3QtPnN0cmVh bV9idWZmZXIubGVuZ3RoKTsKPiArCQlpZiAoc2VxX3dyaXRlKHMsIHN0ciwgbnVtKSkKPiArCQkJ cmV0dXJuIDA7Cj4gKwl9Cj4gKwludW0gPSBzY25wcmludGYoc3RyLCBzaXplb2Yoc3RyKSwgImtm aWZvIGxlbiA9IDB4JXhcbiIsIGtmaWZvX2xlbigmaW5zdC0+bXNnX2ZpZm8pKTsKPiArCWlmIChz ZXFfd3JpdGUocywgc3RyLCBudW0pKQo+ICsJCXJldHVybiAwOwo+ICsKPiArCW51bSA9IHNjbnBy aW50ZihzdHIsIHNpemVvZihzdHIpLCAiZmxvdyA6XG4iKTsKPiArCWlmIChzZXFfd3JpdGUocywg c3RyLCBudW0pKQo+ICsJCXJldHVybiAwOwo+ICsKPiArCW11dGV4X2xvY2soJmluc3QtPmNvcmUt PmNtZF9sb2NrKTsKPiArCWZvciAoaSA9IDA7IGkgPCBBUlJBWV9TSVpFKGluc3QtPmZsb3dzKTsg aSsrKSB7Cj4gKwkJdTMyIGlkeCA9IChpbnN0LT5mbG93X2lkeCArIGkpICUgKEFSUkFZX1NJWkUo aW5zdC0+Zmxvd3MpKTsKPiArCj4gKwkJaWYgKCFpbnN0LT5mbG93c1tpZHhdKQo+ICsJCQljb250 aW51ZTsKPiArCQludW0gPSBzY25wcmludGYoc3RyLCBzaXplb2Yoc3RyKSwgIlx0WyVzXTB4JXhc biIsCj4gKwkJCQlpbnN0LT5mbG93c1tpZHhdID49IFZQVV9NU0dfSURfTk9PUCA/ICJNIiA6ICJD IiwKPiArCQkJCWluc3QtPmZsb3dzW2lkeF0pOwo+ICsJCWlmIChzZXFfd3JpdGUocywgc3RyLCBu dW0pKSB7Cj4gKwkJCW11dGV4X3VubG9jaygmaW5zdC0+Y29yZS0+Y21kX2xvY2spOwo+ICsJCQly ZXR1cm4gMDsKPiArCQl9Cj4gKwl9Cj4gKwltdXRleF91bmxvY2soJmluc3QtPmNvcmUtPmNtZF9s b2NrKTsKPiArCj4gKwlpID0gMDsKPiArCXdoaWxlICh0cnVlKSB7Cj4gKwkJbnVtID0gY2FsbF92 b3AoaW5zdCwgZ2V0X2RlYnVnX2luZm8sIHN0ciwgc2l6ZW9mKHN0ciksIGkrKyk7Cj4gKwkJaWYg KG51bSA8PSAwKQo+ICsJCQlicmVhazsKPiArCQlpZiAoc2VxX3dyaXRlKHMsIHN0ciwgbnVtKSkK PiArCQkJcmV0dXJuIDA7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRp YyBpbnQgdnB1X2RiZ19jb3JlKHN0cnVjdCBzZXFfZmlsZSAqcywgdm9pZCAqZGF0YSkKPiArewo+ ICsJc3RydWN0IHZwdV9jb3JlICpjb3JlID0gcy0+cHJpdmF0ZTsKPiArCXN0cnVjdCB2cHVfc2hh cmVkX2FkZHIgKmlmYWNlID0gY29yZS0+aWZhY2U7Cj4gKwljaGFyIHN0clsxMjhdOwo+ICsJaW50 IG51bTsKPiArCj4gKwludW0gPSBzY25wcmludGYoc3RyLCBzaXplb2Yoc3RyKSwgIlslc11cbiIs IHZwdV9jb3JlX3R5cGVfZGVzYyhjb3JlLT50eXBlKSk7Cj4gKwlpZiAoc2VxX3dyaXRlKHMsIHN0 ciwgbnVtKSkKPiArCQlyZXR1cm4gMDsKPiArCj4gKwludW0gPSBzY25wcmludGYoc3RyLCBzaXpl b2Yoc3RyKSwgImJvb3RfcmVnaW9uICA9IDwlcGFkLCAweCV4PlxuIiwKPiArCQkJJmNvcmUtPmZ3 LnBoeXMsIGNvcmUtPmZ3Lmxlbmd0aCk7Cj4gKwlpZiAoc2VxX3dyaXRlKHMsIHN0ciwgbnVtKSkK PiArCQlyZXR1cm4gMDsKPiArCW51bSA9IHNjbnByaW50ZihzdHIsIHNpemVvZihzdHIpLCAicnBj X3JlZ2lvbiAgID0gPCVwYWQsIDB4JXg+IHVzZWQgPSAweCV4XG4iLAo+ICsJCQkmY29yZS0+cnBj LnBoeXMsIGNvcmUtPnJwYy5sZW5ndGgsIGNvcmUtPnJwYy5ieXRlc3VzZWQpOwo+ICsJaWYgKHNl cV93cml0ZShzLCBzdHIsIG51bSkpCj4gKwkJcmV0dXJuIDA7Cj4gKwludW0gPSBzY25wcmludGYo c3RyLCBzaXplb2Yoc3RyKSwgImZ3bG9nX3JlZ2lvbiA9IDwlcGFkLCAweCV4PlxuIiwKPiArCQkJ JmNvcmUtPmxvZy5waHlzLCBjb3JlLT5sb2cubGVuZ3RoKTsKPiArCWlmIChzZXFfd3JpdGUocywg c3RyLCBudW0pKQo+ICsJCXJldHVybiAwOwo+ICsKPiArCW51bSA9IHNjbnByaW50ZihzdHIsIHNp emVvZihzdHIpLCAic3RhdGUgPSAlZFxuIiwgY29yZS0+c3RhdGUpOwo+ICsJaWYgKHNlcV93cml0 ZShzLCBzdHIsIG51bSkpCj4gKwkJcmV0dXJuIDA7Cj4gKwlpZiAoY29yZS0+c3RhdGUgPT0gVlBV X0NPUkVfREVJTklUKQo+ICsJCXJldHVybiAwOwo+ICsJbnVtID0gc2NucHJpbnRmKHN0ciwgc2l6 ZW9mKHN0ciksICJmdyB2ZXJzaW9uID0gJWQuJWQuJWRcbiIsCj4gKwkJCQkoY29yZS0+ZndfdmVy c2lvbiA+PiAxNikgJiAweGZmLAo+ICsJCQkJKGNvcmUtPmZ3X3ZlcnNpb24gPj4gOCkgJiAweGZm LAo+ICsJCQkJY29yZS0+ZndfdmVyc2lvbiAmIDB4ZmYpOwo+ICsJaWYgKHNlcV93cml0ZShzLCBz dHIsIG51bSkpCj4gKwkJcmV0dXJuIDA7Cj4gKwludW0gPSBzY25wcmludGYoc3RyLCBzaXplb2Yo c3RyKSwgImluc3RhbmNlcyA9ICVkLyVkICgweCUwMmx4KSwgJWRcbiIsCj4gKwkJCWh3ZWlnaHQz Mihjb3JlLT5pbnN0YW5jZV9tYXNrKSwKPiArCQkJY29yZS0+c3VwcG9ydGVkX2luc3RhbmNlX2Nv dW50LAo+ICsJCQljb3JlLT5pbnN0YW5jZV9tYXNrLAo+ICsJCQljb3JlLT5yZXF1ZXN0X2NvdW50 KTsKPiArCWlmIChzZXFfd3JpdGUocywgc3RyLCBudW0pKQo+ICsJCXJldHVybiAwOwo+ICsJbnVt ID0gc2NucHJpbnRmKHN0ciwgc2l6ZW9mKHN0ciksICJrZmlmbyBsZW4gPSAweCV4XG4iLCBrZmlm b19sZW4oJmNvcmUtPm1zZ19maWZvKSk7Cj4gKwlpZiAoc2VxX3dyaXRlKHMsIHN0ciwgbnVtKSkK PiArCQlyZXR1cm4gMDsKPiArCW51bSA9IHNjbnByaW50ZihzdHIsIHNpemVvZihzdHIpLAo+ICsJ CQkiY21kX2J1ZjpbMHgleCwgMHgleF0sIHdwdHIgPSAweCV4LCBycHRyID0gMHgleFxuIiwKPiAr CQkJaWZhY2UtPmNtZF9kZXNjLT5zdGFydCwKPiArCQkJaWZhY2UtPmNtZF9kZXNjLT5lbmQsCj4g KwkJCWlmYWNlLT5jbWRfZGVzYy0+d3B0ciwKPiArCQkJaWZhY2UtPmNtZF9kZXNjLT5ycHRyKTsK PiArCWlmIChzZXFfd3JpdGUocywgc3RyLCBudW0pKQo+ICsJCXJldHVybiAwOwo+ICsJbnVtID0g c2NucHJpbnRmKHN0ciwgc2l6ZW9mKHN0ciksCj4gKwkJCSJtc2dfYnVmOlsweCV4LCAweCV4XSwg d3B0ciA9IDB4JXgsIHJwdHIgPSAweCV4XG4iLAo+ICsJCQlpZmFjZS0+bXNnX2Rlc2MtPnN0YXJ0 LAo+ICsJCQlpZmFjZS0+bXNnX2Rlc2MtPmVuZCwKPiArCQkJaWZhY2UtPm1zZ19kZXNjLT53cHRy LAo+ICsJCQlpZmFjZS0+bXNnX2Rlc2MtPnJwdHIpOwo+ICsJaWYgKHNlcV93cml0ZShzLCBzdHIs IG51bSkpCj4gKwkJcmV0dXJuIDA7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRp YyBpbnQgdnB1X2RiZ19md2xvZyhzdHJ1Y3Qgc2VxX2ZpbGUgKnMsIHZvaWQgKmRhdGEpCj4gK3sK PiArCXN0cnVjdCB2cHVfY29yZSAqY29yZSA9IHMtPnByaXZhdGU7Cj4gKwlzdHJ1Y3QgcHJpbnRf YnVmX2Rlc2MgKnByaW50X2J1ZjsKPiArCWludCBsZW5ndGg7Cj4gKwl1MzIgcnB0cjsKPiArCXUz MiB3cHRyOwo+ICsJaW50IHJldCA9IDA7Cj4gKwo+ICsJaWYgKCFjb3JlLT5sb2cudmlydCB8fCBj b3JlLT5zdGF0ZSA9PSBWUFVfQ09SRV9ERUlOSVQpCj4gKwkJcmV0dXJuIDA7Cj4gKwo+ICsJcHJp bnRfYnVmID0gY29yZS0+bG9nLnZpcnQ7Cj4gKwlycHRyID0gcHJpbnRfYnVmLT5yZWFkOwo+ICsJ d3B0ciA9IHByaW50X2J1Zi0+d3JpdGU7Cj4gKwo+ICsJaWYgKHJwdHIgPT0gd3B0cikKPiArCQly ZXR1cm4gMDsKPiArCWVsc2UgaWYgKHJwdHIgPCB3cHRyKQo+ICsJCWxlbmd0aCA9IHdwdHIgLSBy cHRyOwo+ICsJZWxzZQo+ICsJCWxlbmd0aCA9IHByaW50X2J1Zi0+Ynl0ZXMgKyB3cHRyIC0gcnB0 cjsKPiArCj4gKwlpZiAocy0+Y291bnQgKyBsZW5ndGggPj0gcy0+c2l6ZSkgewo+ICsJCXMtPmNv dW50ID0gcy0+c2l6ZTsKPiArCQlyZXR1cm4gMDsKPiArCX0KPiArCj4gKwlpZiAocnB0ciArIGxl bmd0aCA+PSBwcmludF9idWYtPmJ5dGVzKSB7Cj4gKwkJaW50IG51bSA9IHByaW50X2J1Zi0+Ynl0 ZXMgLSBycHRyOwo+ICsKPiArCQlpZiAoc2VxX3dyaXRlKHMsIHByaW50X2J1Zi0+YnVmZmVyICsg cnB0ciwgbnVtKSkKPiArCQkJcmV0ID0gLTE7Cj4gKwkJbGVuZ3RoIC09IG51bTsKPiArCQlycHRy ID0gMDsKPiArCX0KPiArCj4gKwlpZiAobGVuZ3RoKSB7Cj4gKwkJaWYgKHNlcV93cml0ZShzLCBw cmludF9idWYtPmJ1ZmZlciArIHJwdHIsIGxlbmd0aCkpCj4gKwkJCXJldCA9IC0xOwo+ICsJCXJw dHIgKz0gbGVuZ3RoOwo+ICsJfQo+ICsJaWYgKCFyZXQpCj4gKwkJcHJpbnRfYnVmLT5yZWFkID0g cnB0cjsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCB2cHVfZGJnX2lu c3Rfb3BlbihzdHJ1Y3QgaW5vZGUgKmlub2RlLCBzdHJ1Y3QgZmlsZSAqZmlscCkKPiArewo+ICsJ cmV0dXJuIHNpbmdsZV9vcGVuKGZpbHAsIHZwdV9kYmdfaW5zdGFuY2UsIGlub2RlLT5pX3ByaXZh dGUpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgc3NpemVfdCB2cHVfZGJnX2luc3Rfd3JpdGUoc3RydWN0 IGZpbGUgKmZpbGUsCj4gKwkJCWNvbnN0IGNoYXIgX191c2VyICp1c2VyX2J1Ziwgc2l6ZV90IHNp emUsIGxvZmZfdCAqcHBvcykKPiArewo+ICsJc3RydWN0IHNlcV9maWxlICpzID0gZmlsZS0+cHJp dmF0ZV9kYXRhOwo+ICsJc3RydWN0IHZwdV9pbnN0ICppbnN0ID0gcy0+cHJpdmF0ZTsKPiArCj4g Kwl2cHVfc2Vzc2lvbl9kZWJ1ZyhpbnN0KTsKPiArCj4gKwlyZXR1cm4gc2l6ZTsKPiArfQo+ICsK PiArc3RhdGljIHNzaXplX3QgdnB1X2RiZ19jb3JlX3dyaXRlKHN0cnVjdCBmaWxlICpmaWxlLAo+ ICsJCQljb25zdCBjaGFyIF9fdXNlciAqdXNlcl9idWYsIHNpemVfdCBzaXplLCBsb2ZmX3QgKnBw b3MpCj4gK3sKPiArCXN0cnVjdCBzZXFfZmlsZSAqcyA9IGZpbGUtPnByaXZhdGVfZGF0YTsKPiAr CXN0cnVjdCB2cHVfY29yZSAqY29yZSA9IHMtPnByaXZhdGU7Cj4gKwo+ICsJcG1fcnVudGltZV9n ZXRfc3luYyhjb3JlLT5kZXYpOwo+ICsJbXV0ZXhfbG9jaygmY29yZS0+bG9jayk7Cj4gKwlpZiAo Y29yZS0+c3RhdGUgIT0gVlBVX0NPUkVfREVJTklUICYmICFjb3JlLT5pbnN0YW5jZV9tYXNrKSB7 Cj4gKwkJY29yZV9kYmcoY29yZSwgTFZMX0lORk8sICJyZXNldCBjb3JlXG4iKTsKPiArCQlpZiAo IXZwdV9jb3JlX3N3X3Jlc2V0KGNvcmUpKSB7Cj4gKwkJCWNvcmUtPnN0YXRlID0gVlBVX0NPUkVf QUNUSVZFOwo+ICsJCQljb3JlLT5oYW5nX21hc2sgPSAwOwo+ICsJCX0KPiArCX0KPiArCW11dGV4 X3VubG9jaygmY29yZS0+bG9jayk7Cj4gKwlwbV9ydW50aW1lX3B1dF9zeW5jKGNvcmUtPmRldik7 Cj4gKwo+ICsJcmV0dXJuIHNpemU7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdnB1X2RiZ19jb3Jl X29wZW4oc3RydWN0IGlub2RlICppbm9kZSwgc3RydWN0IGZpbGUgKmZpbHApCj4gK3sKPiArCXJl dHVybiBzaW5nbGVfb3BlbihmaWxwLCB2cHVfZGJnX2NvcmUsIGlub2RlLT5pX3ByaXZhdGUpOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHZwdV9kYmdfZndsb2dfb3BlbihzdHJ1Y3QgaW5vZGUgKmlu b2RlLCBzdHJ1Y3QgZmlsZSAqZmlscCkKPiArewo+ICsJcmV0dXJuIHNpbmdsZV9vcGVuKGZpbHAs IHZwdV9kYmdfZndsb2csIGlub2RlLT5pX3ByaXZhdGUpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgY29u c3Qgc3RydWN0IGZpbGVfb3BlcmF0aW9ucyB2cHVfZGJnX2luc3RfZm9wcyA9IHsKPiArCS5vd25l ciA9IFRISVNfTU9EVUxFLAo+ICsJLm9wZW4gPSB2cHVfZGJnX2luc3Rfb3BlbiwKPiArCS5yZWxl YXNlID0gc2luZ2xlX3JlbGVhc2UsCj4gKwkucmVhZCA9IHNlcV9yZWFkLAo+ICsJLndyaXRlID0g dnB1X2RiZ19pbnN0X3dyaXRlLAo+ICt9Owo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBmaWxl X29wZXJhdGlvbnMgdnB1X2RiZ19jb3JlX2ZvcHMgPSB7Cj4gKwkub3duZXIgPSBUSElTX01PRFVM RSwKPiArCS5vcGVuID0gdnB1X2RiZ19jb3JlX29wZW4sCj4gKwkucmVsZWFzZSA9IHNpbmdsZV9y ZWxlYXNlLAo+ICsJLnJlYWQgPSBzZXFfcmVhZCwKPiArCS53cml0ZSA9IHZwdV9kYmdfY29yZV93 cml0ZSwKPiArfTsKPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgZmlsZV9vcGVyYXRpb25zIHZw dV9kYmdfZndsb2dfZm9wcyA9IHsKPiArCS5vd25lciA9IFRISVNfTU9EVUxFLAo+ICsJLm9wZW4g PSB2cHVfZGJnX2Z3bG9nX29wZW4sCj4gKwkucmVsZWFzZSA9IHNpbmdsZV9yZWxlYXNlLAo+ICsJ LnJlYWQgPSBzZXFfcmVhZCwKPiArfTsKPiArCj4gK2ludCB2cHVfaW5zdF9jcmVhdGVfZGJnZnNf ZmlsZShzdHJ1Y3QgdnB1X2luc3QgKmluc3QpCj4gK3sKPiArCXN0cnVjdCB2cHVfZGV2ICp2cHU7 Cj4gKwljaGFyIG5hbWVbNjRdOwo+ICsKPiArCWlmICghaW5zdCB8fCAhaW5zdC0+Y29yZSB8fCAh aW5zdC0+Y29yZS0+dnB1KQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXZwdSA9IGluc3Qt PmNvcmUtPnZwdTsKPiArCWlmICghdnB1LT5kZWJ1Z2ZzKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ ICsKPiArCWlmIChpbnN0LT5kZWJ1Z2ZzKQo+ICsJCXJldHVybiAwOwo+ICsKPiArCXNjbnByaW50 ZihuYW1lLCBzaXplb2YobmFtZSksICJpbnN0YW5jZS4lZC4lZCIsCj4gKwkJCWluc3QtPmNvcmUt PmlkLCBpbnN0LT5pZCk7Cj4gKwlpbnN0LT5kZWJ1Z2ZzID0gZGVidWdmc19jcmVhdGVfZmlsZSgo Y29uc3QgY2hhciAqKW5hbWUsCj4gKwkJCQlWRVJJRllfT0NUQUxfUEVSTUlTU0lPTlMoMDY0NCks Cj4gKwkJCQl2cHUtPmRlYnVnZnMsCj4gKwkJCQlpbnN0LAo+ICsJCQkJJnZwdV9kYmdfaW5zdF9m b3BzKTsKPiArCWlmICghaW5zdC0+ZGVidWdmcykgewo+ICsJCXZwdV9lcnIoInZwdSBjcmVhdGUg ZGVidWdmcyAlcyBmYWlsXG4iLCBuYW1lKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiAr Cj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiAraW50IHZwdV9pbnN0X3JlbW92ZV9kYmdmc19maWxl KHN0cnVjdCB2cHVfaW5zdCAqaW5zdCkKPiArewo+ICsJaWYgKCFpbnN0KQo+ICsJCXJldHVybiAw Owo+ICsKPiArCWRlYnVnZnNfcmVtb3ZlKGluc3QtPmRlYnVnZnMpOwo+ICsJaW5zdC0+ZGVidWdm cyA9IE5VTEw7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK2ludCB2cHVfY29yZV9jcmVh dGVfZGJnZnNfZmlsZShzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUpCj4gK3sKPiArCXN0cnVjdCB2cHVf ZGV2ICp2cHU7Cj4gKwljaGFyIG5hbWVbNjRdOwo+ICsKPiArCWlmICghY29yZSB8fCAhY29yZS0+ dnB1KQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXZwdSA9IGNvcmUtPnZwdTsKPiArCWlm ICghdnB1LT5kZWJ1Z2ZzKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCWlmICghY29yZS0+ ZGVidWdmcykgewo+ICsJCXNjbnByaW50ZihuYW1lLCBzaXplb2YobmFtZSksICJjb3JlLiVkIiwg Y29yZS0+aWQpOwo+ICsJCWNvcmUtPmRlYnVnZnMgPSBkZWJ1Z2ZzX2NyZWF0ZV9maWxlKChjb25z dCBjaGFyICopbmFtZSwKPiArCQkJCQlWRVJJRllfT0NUQUxfUEVSTUlTU0lPTlMoMDY0NCksCj4g KwkJCQkJdnB1LT5kZWJ1Z2ZzLAo+ICsJCQkJCWNvcmUsCj4gKwkJCQkJJnZwdV9kYmdfY29yZV9m b3BzKTsKPiArCQlpZiAoIWNvcmUtPmRlYnVnZnMpIHsKPiArCQkJdnB1X2VycigidnB1IGNyZWF0 ZSBkZWJ1Z2ZzICVzIGZhaWxcbiIsIG5hbWUpOwo+ICsJCQlyZXR1cm4gLUVJTlZBTDsKPiArCQl9 Cj4gKwl9Cj4gKwlpZiAoIWNvcmUtPmRlYnVnZnNfZndsb2cpIHsKPiArCQlzY25wcmludGYobmFt ZSwgc2l6ZW9mKG5hbWUpLCAiZndsb2cuJWQiLCBjb3JlLT5pZCk7Cj4gKwkJY29yZS0+ZGVidWdm c19md2xvZyA9IGRlYnVnZnNfY3JlYXRlX2ZpbGUoKGNvbnN0IGNoYXIgKiluYW1lLAo+ICsJCQkJ CVZFUklGWV9PQ1RBTF9QRVJNSVNTSU9OUygwNDQ0KSwKPiArCQkJCQl2cHUtPmRlYnVnZnMsCj4g KwkJCQkJY29yZSwKPiArCQkJCQkmdnB1X2RiZ19md2xvZ19mb3BzKTsKPiArCQlpZiAoIWNvcmUt PmRlYnVnZnNfZndsb2cpIHsKPiArCQkJdnB1X2VycigidnB1IGNyZWF0ZSBkZWJ1Z2ZzICVzIGZh aWxcbiIsIG5hbWUpOwo+ICsJCQlyZXR1cm4gLUVJTlZBTDsKPiArCQl9Cj4gKwl9Cj4gKwo+ICsJ cmV0dXJuIDA7Cj4gK30KPiArCj4gK2ludCB2cHVfY29yZV9yZW1vdmVfZGJnZnNfZmlsZShzdHJ1 Y3QgdnB1X2NvcmUgKmNvcmUpCj4gK3sKPiArCWlmICghY29yZSkKPiArCQlyZXR1cm4gMDsKPiAr CWRlYnVnZnNfcmVtb3ZlKGNvcmUtPmRlYnVnZnMpOwo+ICsJY29yZS0+ZGVidWdmcyA9IE5VTEw7 Cj4gKwlkZWJ1Z2ZzX3JlbW92ZShjb3JlLT5kZWJ1Z2ZzX2Z3bG9nKTsKPiArCWNvcmUtPmRlYnVn ZnNfZndsb2cgPSBOVUxMOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICt2b2lkIHZwdV9p bnN0X3JlY29yZF9mbG93KHN0cnVjdCB2cHVfaW5zdCAqaW5zdCwgdTMyIGZsb3cpCj4gK3sKPiAr CWlmICghaW5zdCkKPiArCQlyZXR1cm47Cj4gKwo+ICsJaW5zdC0+Zmxvd3NbaW5zdC0+Zmxvd19p ZHhdID0gZmxvdzsKPiArCWluc3QtPmZsb3dfaWR4ID0gKGluc3QtPmZsb3dfaWR4ICsgMSkgJSAo QVJSQVlfU0laRShpbnN0LT5mbG93cykpOwo+ICt9Cj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWVk aWEvcGxhdGZvcm0vYW1waGlvbi92cHVfbG9nLmggYi9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL2Ft cGhpb24vdnB1X2xvZy5oCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAw MDAuLmZlYzk4MzY4ZmFkMQo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL21lZGlhL3Bs YXRmb3JtL2FtcGhpb24vdnB1X2xvZy5oCj4gQEAgLTAsMCArMSw0NCBAQAo+ICsvKiBTUERYLUxp Y2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMCAqLwo+ICsvKgo+ICsgKiBDb3B5cmlnaHQgMjAyMC0y MDIxIE5YUAo+ICsgKi8KPiArCj4gKyNpZm5kZWYgX0FNUEhJT05fVlBVX0xPR19ICj4gKyNkZWZp bmUgX0FNUEhJT05fVlBVX0xPR19ICj4gKwo+ICsjZGVmaW5lIExWTF9FUlIJCSgxIDw8IDApCj4g KyNkZWZpbmUgTFZMX1dBUk4JKDEgPDwgMSkKPiArI2RlZmluZSBMVkxfSU5GTwkoMSA8PCAyKQo+ ICsjZGVmaW5lIExWTF9ERUJVRwkoMSA8PCAzKQo+ICsjZGVmaW5lIExWTF9JUlEJCSgxIDw8IDQp Cj4gKyNkZWZpbmUgTFZMX0NNRAkJKDEgPDwgNSkKPiArI2RlZmluZSBMVkxfRVZUCQkoMSA8PCA2 KQo+ICsjZGVmaW5lIExWTF9DVFJMCSgxIDw8IDcpCj4gKyNkZWZpbmUgTFZMX1RTCQkoMSA8PCA4 KQo+ICsjZGVmaW5lIExWTF9GTE9XCSgxIDw8IDEzKQo+ICsKPiArZXh0ZXJuIHVuc2lnbmVkIGlu dCB2cHVfZGJnX2xldmVsOwo+ICsKPiArI2lmZGVmIFRBRwo+ICsjZGVmaW5lIHZwdV9kYmcobGV2 ZWwsIGZtdCwgYXJnLi4uKSBcCj4gKwlkbyB7IFwKPiArCQlpZiAoKHZwdV9kYmdfbGV2ZWwgJiAo bGV2ZWwpKSB8fCAoKGxldmVsKSAmIExWTF9FUlIpKSBcCj4gKwkJCXByX2luZm8oIltWUFUgIlRB RyJdImZtdCwgIyMgYXJnKTsgXAo+ICsJfSB3aGlsZSAoMCkKPiArI2Vsc2UKPiArI2RlZmluZSB2 cHVfZGJnKGxldmVsLCBmbXQsIGFyZy4uLikgXAo+ICsJZG8geyBcCj4gKwkJaWYgKCh2cHVfZGJn X2xldmVsICYgKGxldmVsKSkgfHwgKChsZXZlbCkgJiBMVkxfRVJSKSkgXAo+ICsJCQlwcl9pbmZv KCJbVlBVXSJmbXQsICMjIGFyZyk7IFwKPiArCX0gd2hpbGUgKDApCj4gKyNlbmRpZgo+ICsKPiAr I2RlZmluZSB2cHVfZXJyKGZtdCwgYXJnLi4uKQl2cHVfZGJnKExWTF9FUlIsIGZtdCwgIyNhcmcp Cj4gKyNkZWZpbmUgaW5zdF9kYmcoaW5zdCwgbGV2ZWwsIGZtdCwgYXJnLi4uKQkJXAo+ICsJCXZw dV9kYmcobGV2ZWwsICJbJWQ6JWRdICJmbXQsIGluc3QtPmNvcmUtPmlkLCBpbnN0LT5pZCwgIyMg YXJnKQo+ICsjZGVmaW5lIGluc3RfZXJyKGluc3QsIGZtdCwgYXJnLi4uKQlpbnN0X2RiZyhpbnN0 LCBMVkxfRVJSLCBmbXQsICMjIGFyZykKPiArI2RlZmluZSBjb3JlX2RiZyhjb3JlLCBsZXZlbCwg Zm10LCBhcmcuLi4pCQlcCj4gKwkJdnB1X2RiZyhsZXZlbCwgIlslZF0gJXMgImZtdCwgY29yZS0+ aWQsIHZwdV9jb3JlX3R5cGVfZGVzYyhjb3JlLT50eXBlKSwgIyMgYXJnKQo+ICsjZGVmaW5lIGNv cmVfZXJyKGNvcmUsIGZtdCwgYXJnLi4uKQljb3JlX2RiZyhjb3JlLCBMVkxfRVJSLCBmbXQsICMj IGFyZykKPiArCj4gKyNlbmRpZgo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL21lZGlhL3BsYXRmb3Jt L2FtcGhpb24vdnB1X3JwYy5jIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9hbXBoaW9uL3ZwdV9y cGMuYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMDAwMDAwLi4yMWM5NWIy MGQ0OGQKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9hbXBo aW9uL3ZwdV9ycGMuYwo+IEBAIC0wLDAgKzEsMjYzIEBACj4gKy8vIFNQRFgtTGljZW5zZS1JZGVu dGlmaWVyOiBHUEwtMi4wCj4gKy8qCj4gKyAqIENvcHlyaWdodCAyMDIwLTIwMjEgTlhQCj4gKyAq Lwo+ICsKPiArI2RlZmluZSBUQUcJCSJSUEMiCj4gKyNpbmNsdWRlIDxsaW51eC9pbml0Lmg+Cj4g KyNpbmNsdWRlIDxsaW51eC9pbnRlcmNvbm5lY3QuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2lvY3Rs Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9saXN0Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwu aD4KPiArI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvb2ZfZGV2 aWNlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9vZl9hZGRyZXNzLmg+Cj4gKyNpbmNsdWRlIDxsaW51 eC9wbGF0Zm9ybV9kZXZpY2UuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2Zpcm13YXJlL2lteC9pcGMu aD4KPiArI2luY2x1ZGUgPGxpbnV4L2Zpcm13YXJlL2lteC9zdmMvbWlzYy5oPgo+ICsjaW5jbHVk ZSAidnB1LmgiCj4gKyNpbmNsdWRlICJ2cHVfcnBjLmgiCj4gKyNpbmNsdWRlICJ2cHVfaW14OHEu aCIKPiArI2luY2x1ZGUgInZwdV93aW5kc29yLmgiCj4gKyNpbmNsdWRlICJ2cHVfbWFsb25lLmgi Cj4gKyNpbmNsdWRlICJ2cHVfbG9nLmgiCj4gKwo+ICt1MzIgdnB1X2lmYWNlX2NoZWNrX21lbW9y eV9yZWdpb24oc3RydWN0IHZwdV9jb3JlICpjb3JlLCBkbWFfYWRkcl90IGFkZHIsIHUzMiBzaXpl KQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X2lmYWNlX29wcyAqb3BzID0gdnB1X2lmYWNlX2dldChjb3Jl KTsKPiArCj4gKwlpZiAoIW9wcyB8fCAhb3BzLT5jaGVja19tZW1vcnlfcmVnaW9uKQo+ICsJCXJl dHVybiBWUFVfQ09SRV9NRU1PUllfSU5WQUxJRDsKPiArCj4gKwlyZXR1cm4gb3BzLT5jaGVja19t ZW1vcnlfcmVnaW9uKGNvcmUtPmZ3LnBoeXMsIGFkZHIsIHNpemUpOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgdTMyIHZwdV9ycGNfY2hlY2tfYnVmZmVyX3NwYWNlKHN0cnVjdCB2cHVfcnBjX2J1ZmZlcl9k ZXNjICpkZXNjLCBib29sIHdyaXRlKQo+ICt7Cj4gKwl1MzIgcHRyMTsKPiArCXUzMiBwdHIyOwo+ ICsJdTMyIHNpemU7Cj4gKwo+ICsJV0FSTl9PTighZGVzYyk7Cj4gKwo+ICsJc2l6ZSA9IGRlc2Mt PmVuZCAtIGRlc2MtPnN0YXJ0Owo+ICsJaWYgKHdyaXRlKSB7Cj4gKwkJcHRyMSA9IGRlc2MtPndw dHI7Cj4gKwkJcHRyMiA9IGRlc2MtPnJwdHI7Cj4gKwl9IGVsc2Ugewo+ICsJCXB0cjEgPSBkZXNj LT5ycHRyOwo+ICsJCXB0cjIgPSBkZXNjLT53cHRyOwo+ICsJfQo+ICsKPiArCWlmIChwdHIxID09 IHB0cjIpIHsKPiArCQlpZiAoIXdyaXRlKQo+ICsJCQlyZXR1cm4gMDsKPiArCQllbHNlCj4gKwkJ CXJldHVybiBzaXplOwo+ICsJfQo+ICsKPiArCXJldHVybiAocHRyMiArIHNpemUgLSBwdHIxKSAl IHNpemU7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdnB1X3JwY19zZW5kX2NtZF9idWYoc3RydWN0 IHZwdV9zaGFyZWRfYWRkciAqc2hhcmVkLAo+ICsJCQlzdHJ1Y3QgdnB1X3JwY19ldmVudCAqY21k KQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X3JwY19idWZmZXJfZGVzYyAqZGVzYzsKPiArCXUzMiBzcGFj ZSA9IDA7Cj4gKwl1MzIgKmRhdGE7Cj4gKwl1MzIgd3B0cjsKPiArCXUzMiBpOwo+ICsKPiArCVdB Uk5fT04oIXNoYXJlZCB8fCAhc2hhcmVkLT5jbWRfbWVtX3ZpciB8fCAhY21kKTsKPiArCj4gKwlk ZXNjID0gc2hhcmVkLT5jbWRfZGVzYzsKPiArCXNwYWNlID0gdnB1X3JwY19jaGVja19idWZmZXJf c3BhY2UoZGVzYywgdHJ1ZSk7Cj4gKwlpZiAoc3BhY2UgPCAoKChjbWQtPmhkci5udW0gKyAxKSA8 PCAyKSArIDE2KSkgewo+ICsJCXZwdV9lcnIoIkNtZCBCdWZmZXIgaXMgbm8gc3BhY2UgZm9yIFsl ZF0gJWRcbiIsCj4gKwkJCQljbWQtPmhkci5pbmRleCwgY21kLT5oZHIuaWQpOwo+ICsJCXJldHVy biAtRUlOVkFMOwo+ICsJfQo+ICsJd3B0ciA9IGRlc2MtPndwdHI7Cj4gKwlkYXRhID0gKHUzMiAq KShzaGFyZWQtPmNtZF9tZW1fdmlyICsgZGVzYy0+d3B0ciAtIGRlc2MtPnN0YXJ0KTsKPiArCSpk YXRhID0gMDsKPiArCSpkYXRhIHw9ICgoY21kLT5oZHIuaW5kZXggJiAweGZmKSA8PCAyNCk7Cj4g KwkqZGF0YSB8PSAoKGNtZC0+aGRyLm51bSAmIDB4ZmYpIDw8IDE2KTsKPiArCSpkYXRhIHw9IChj bWQtPmhkci5pZCAmIDB4M2ZmZik7Cj4gKwl3cHRyICs9IDQ7Cj4gKwlkYXRhKys7Cj4gKwlpZiAo d3B0ciA+PSBkZXNjLT5lbmQpIHsKPiArCQl3cHRyID0gZGVzYy0+c3RhcnQ7Cj4gKwkJZGF0YSA9 IHNoYXJlZC0+Y21kX21lbV92aXI7Cj4gKwl9Cj4gKwo+ICsJZm9yIChpID0gMDsgaSA8IGNtZC0+ aGRyLm51bTsgaSsrKSB7Cj4gKwkJKmRhdGEgPSBjbWQtPmRhdGFbaV07Cj4gKwkJd3B0ciArPSA0 Owo+ICsJCWRhdGErKzsKPiArCQlpZiAod3B0ciA+PSBkZXNjLT5lbmQpIHsKPiArCQkJd3B0ciA9 IGRlc2MtPnN0YXJ0Owo+ICsJCQlkYXRhID0gc2hhcmVkLT5jbWRfbWVtX3ZpcjsKPiArCQl9Cj4g Kwl9Cj4gKwo+ICsJLyp1cGRhdGUgd3B0ciBhZnRlciBkYXRhIGlzIHdyaXR0ZW4qLwo+ICsJbWIo KTsKPiArCWRlc2MtPndwdHIgPSB3cHRyOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtz dGF0aWMgYm9vbCB2cHVfcnBjX2NoZWNrX21zZyhzdHJ1Y3QgdnB1X3NoYXJlZF9hZGRyICpzaGFy ZWQpCj4gK3sKPiArCXN0cnVjdCB2cHVfcnBjX2J1ZmZlcl9kZXNjICpkZXNjOwo+ICsJdTMyIHNw YWNlID0gMDsKPiArCXUzMiBtc2d3b3JkOwo+ICsJdTMyIG1zZ251bTsKPiArCj4gKwlXQVJOX09O KCFzaGFyZWQgfHwgIXNoYXJlZC0+bXNnX2Rlc2MpOwo+ICsKPiArCWRlc2MgPSBzaGFyZWQtPm1z Z19kZXNjOwo+ICsJc3BhY2UgPSB2cHVfcnBjX2NoZWNrX2J1ZmZlcl9zcGFjZShkZXNjLCAwKTsK PiArCXNwYWNlID0gKHNwYWNlID4+IDIpOwo+ICsKPiArCWlmIChzcGFjZSkgewo+ICsJCW1zZ3dv cmQgPSAqKHUzMiAqKShzaGFyZWQtPm1zZ19tZW1fdmlyICsgZGVzYy0+cnB0ciAtIGRlc2MtPnN0 YXJ0KTsKPiArCQltc2dudW0gPSAobXNnd29yZCAmIDB4ZmYwMDAwKSA+PiAxNjsKPiArCQlpZiAo bXNnbnVtIDw9IHNwYWNlKQo+ICsJCQlyZXR1cm4gdHJ1ZTsKPiArCX0KPiArCj4gKwlyZXR1cm4g ZmFsc2U7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdnB1X3JwY19yZWNlaXZlX21zZ19idWYoc3Ry dWN0IHZwdV9zaGFyZWRfYWRkciAqc2hhcmVkLCBzdHJ1Y3QgdnB1X3JwY19ldmVudCAqbXNnKQo+ ICt7Cj4gKwlzdHJ1Y3QgdnB1X3JwY19idWZmZXJfZGVzYyAqZGVzYzsKPiArCXUzMiAqZGF0YTsK PiArCXUzMiBtc2d3b3JkOwo+ICsJdTMyIHJwdHI7Cj4gKwl1MzIgaTsKPiArCj4gKwlXQVJOX09O KCFzaGFyZWQgfHwgIXNoYXJlZC0+bXNnX2Rlc2MgfHwgIW1zZyk7Cj4gKwo+ICsJaWYgKCF2cHVf cnBjX2NoZWNrX21zZyhzaGFyZWQpKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCWRlc2Mg PSBzaGFyZWQtPm1zZ19kZXNjOwo+ICsJZGF0YSA9ICh1MzIgKikoc2hhcmVkLT5tc2dfbWVtX3Zp ciArIGRlc2MtPnJwdHIgLSBkZXNjLT5zdGFydCk7Cj4gKwlycHRyID0gZGVzYy0+cnB0cjsKPiAr CW1zZ3dvcmQgPSAqZGF0YTsKPiArCWRhdGErKzsKPiArCXJwdHIgKz0gNDsKPiArCWlmIChycHRy ID49IGRlc2MtPmVuZCkgewo+ICsJCXJwdHIgPSBkZXNjLT5zdGFydDsKPiArCQlkYXRhID0gc2hh cmVkLT5tc2dfbWVtX3ZpcjsKPiArCX0KPiArCj4gKwltc2ctPmhkci5pbmRleCA9IChtc2d3b3Jk ID4+IDI0KSAmIDB4ZmY7Cj4gKwltc2ctPmhkci5udW0gPSAobXNnd29yZCA+PiAxNikgJiAweGZm Owo+ICsJbXNnLT5oZHIuaWQgPSBtc2d3b3JkICYgMHgzZmZmOwo+ICsKPiArCWlmIChtc2ctPmhk ci5udW0gPiBBUlJBWV9TSVpFKG1zZy0+ZGF0YSkpIHsKPiArCQl2cHVfZXJyKCJtc2coJWQpIGRh dGEgbGVuZ3RoKCVkKSBpcyBvdXQgb2YgcmFuZ2VcbiIsCj4gKwkJCQltc2ctPmhkci5pZCwgbXNn LT5oZHIubnVtKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlmb3IgKGkgPSAw OyBpIDwgbXNnLT5oZHIubnVtOyBpKyspIHsKPiArCQltc2ctPmRhdGFbaV0gPSAqZGF0YTsKPiAr CQlkYXRhKys7Cj4gKwkJcnB0ciArPSA0Owo+ICsJCWlmIChycHRyID49IGRlc2MtPmVuZCkgewo+ ICsJCQlycHRyID0gZGVzYy0+c3RhcnQ7Cj4gKwkJCWRhdGEgPSBzaGFyZWQtPm1zZ19tZW1fdmly Owo+ICsJCX0KPiArCX0KPiArCj4gKwkvKnVwZGF0ZSBycHRyIGFmdGVyIGRhdGEgaXMgcmVhZCov Cj4gKwltYigpOwo+ICsJZGVzYy0+cnB0ciA9IHJwdHI7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30K PiArCj4gK3N0cnVjdCB2cHVfaWZhY2Vfb3BzIGlteDhxX3JwY19vcHNbXSA9IHsKPiArCVtWUFVf Q09SRV9UWVBFX0VOQ10gPSB7Cj4gKwkJLmNoZWNrX2NvZGVjID0gdnB1X2lteDhxX2NoZWNrX2Nv ZGVjLAo+ICsJCS5jaGVja19mbXQgPSB2cHVfaW14OHFfY2hlY2tfZm10LAo+ICsJCS5ib290X2Nv cmUgPSB2cHVfaW14OHFfYm9vdF9jb3JlLAo+ICsJCS5nZXRfcG93ZXJfc3RhdGUgPSB2cHVfaW14 OHFfZ2V0X3Bvd2VyX3N0YXRlLAo+ICsJCS5vbl9maXJtd2FyZV9sb2FkZWQgPSB2cHVfaW14OHFf b25fZmlybXdhcmVfbG9hZGVkLAo+ICsJCS5nZXRfZGF0YV9zaXplID0gdnB1X3dpbmRzb3JfZ2V0 X2RhdGFfc2l6ZSwKPiArCQkuY2hlY2tfbWVtb3J5X3JlZ2lvbiA9IHZwdV9pbXg4cV9jaGVja19t ZW1vcnlfcmVnaW9uLAo+ICsJCS5pbml0X3JwYyA9IHZwdV93aW5kc29yX2luaXRfcnBjLAo+ICsJ CS5zZXRfbG9nX2J1ZiA9IHZwdV93aW5kc29yX3NldF9sb2dfYnVmLAo+ICsJCS5zZXRfc3lzdGVt X2NmZyA9IHZwdV93aW5kc29yX3NldF9zeXN0ZW1fY2ZnLAo+ICsJCS5nZXRfdmVyc2lvbiA9IHZw dV93aW5kc29yX2dldF92ZXJzaW9uLAo+ICsJCS5zZW5kX2NtZF9idWYgPSB2cHVfcnBjX3NlbmRf Y21kX2J1ZiwKPiArCQkucmVjZWl2ZV9tc2dfYnVmID0gdnB1X3JwY19yZWNlaXZlX21zZ19idWYs Cj4gKwkJLnBhY2tfY21kID0gdnB1X3dpbmRzb3JfcGFja19jbWQsCj4gKwkJLmNvbnZlcnRfbXNn X2lkID0gdnB1X3dpbmRzb3JfY29udmVydF9tc2dfaWQsCj4gKwkJLnVucGFja19tc2dfZGF0YSA9 IHZwdV93aW5kc29yX3VucGFja19tc2dfZGF0YSwKPiArCQkuY29uZmlnX21lbW9yeV9yZXNvdXJj ZSA9IHZwdV93aW5kc29yX2NvbmZpZ19tZW1vcnlfcmVzb3VyY2UsCj4gKwkJLmdldF9zdHJlYW1f YnVmZmVyX3NpemUgPSB2cHVfd2luZHNvcl9nZXRfc3RyZWFtX2J1ZmZlcl9zaXplLAo+ICsJCS5j b25maWdfc3RyZWFtX2J1ZmZlciA9IHZwdV93aW5kc29yX2NvbmZpZ19zdHJlYW1fYnVmZmVyLAo+ ICsJCS5nZXRfc3RyZWFtX2J1ZmZlcl9kZXNjID0gdnB1X3dpbmRzb3JfZ2V0X3N0cmVhbV9idWZm ZXJfZGVzYywKPiArCQkudXBkYXRlX3N0cmVhbV9idWZmZXIgPSB2cHVfd2luZHNvcl91cGRhdGVf c3RyZWFtX2J1ZmZlciwKPiArCQkuc2V0X2VuY29kZV9wYXJhbXMgPSB2cHVfd2luZHNvcl9zZXRf ZW5jb2RlX3BhcmFtcywKPiArCQkuaW5wdXRfZnJhbWUgPSB2cHVfd2luZHNvcl9pbnB1dF9mcmFt ZSwKPiArCQkuZ2V0X21heF9pbnN0YW5jZV9jb3VudCA9IHZwdV93aW5kc29yX2dldF9tYXhfaW5z dGFuY2VfY291bnQsCj4gKwl9LAo+ICsJW1ZQVV9DT1JFX1RZUEVfREVDXSA9IHsKPiArCQkuY2hl Y2tfY29kZWMgPSB2cHVfaW14OHFfY2hlY2tfY29kZWMsCj4gKwkJLmNoZWNrX2ZtdCA9IHZwdV9p bXg4cV9jaGVja19mbXQsCj4gKwkJLmJvb3RfY29yZSA9IHZwdV9pbXg4cV9ib290X2NvcmUsCj4g KwkJLmdldF9wb3dlcl9zdGF0ZSA9IHZwdV9pbXg4cV9nZXRfcG93ZXJfc3RhdGUsCj4gKwkJLm9u X2Zpcm13YXJlX2xvYWRlZCA9IHZwdV9pbXg4cV9vbl9maXJtd2FyZV9sb2FkZWQsCj4gKwkJLmdl dF9kYXRhX3NpemUgPSB2cHVfbWFsb25lX2dldF9kYXRhX3NpemUsCj4gKwkJLmNoZWNrX21lbW9y eV9yZWdpb24gPSB2cHVfaW14OHFfY2hlY2tfbWVtb3J5X3JlZ2lvbiwKPiArCQkuaW5pdF9ycGMg PSB2cHVfbWFsb25lX2luaXRfcnBjLAo+ICsJCS5zZXRfbG9nX2J1ZiA9IHZwdV9tYWxvbmVfc2V0 X2xvZ19idWYsCj4gKwkJLnNldF9zeXN0ZW1fY2ZnID0gdnB1X21hbG9uZV9zZXRfc3lzdGVtX2Nm ZywKPiArCQkuZ2V0X3ZlcnNpb24gPSB2cHVfbWFsb25lX2dldF92ZXJzaW9uLAo+ICsJCS5zZW5k X2NtZF9idWYgPSB2cHVfcnBjX3NlbmRfY21kX2J1ZiwKPiArCQkucmVjZWl2ZV9tc2dfYnVmID0g dnB1X3JwY19yZWNlaXZlX21zZ19idWYsCj4gKwkJLmdldF9zdHJlYW1fYnVmZmVyX3NpemUgPSB2 cHVfbWFsb25lX2dldF9zdHJlYW1fYnVmZmVyX3NpemUsCj4gKwkJLmNvbmZpZ19zdHJlYW1fYnVm ZmVyID0gdnB1X21hbG9uZV9jb25maWdfc3RyZWFtX2J1ZmZlciwKPiArCQkuc2V0X2RlY29kZV9w YXJhbXMgPSB2cHVfbWFsb25lX3NldF9kZWNvZGVfcGFyYW1zLAo+ICsJCS5wYWNrX2NtZCA9IHZw dV9tYWxvbmVfcGFja19jbWQsCj4gKwkJLmNvbnZlcnRfbXNnX2lkID0gdnB1X21hbG9uZV9jb252 ZXJ0X21zZ19pZCwKPiArCQkudW5wYWNrX21zZ19kYXRhID0gdnB1X21hbG9uZV91bnBhY2tfbXNn X2RhdGEsCj4gKwkJLmdldF9zdHJlYW1fYnVmZmVyX2Rlc2MgPSB2cHVfbWFsb25lX2dldF9zdHJl YW1fYnVmZmVyX2Rlc2MsCj4gKwkJLnVwZGF0ZV9zdHJlYW1fYnVmZmVyID0gdnB1X21hbG9uZV91 cGRhdGVfc3RyZWFtX2J1ZmZlciwKPiArCQkuYWRkX3Njb2RlID0gdnB1X21hbG9uZV9hZGRfc2Nv ZGUsCj4gKwkJLmlucHV0X2ZyYW1lID0gdnB1X21hbG9uZV9pbnB1dF9mcmFtZSwKPiArCQkucHJl X3NlbmRfY21kID0gdnB1X21hbG9uZV9wcmVfY21kLAo+ICsJCS5wb3N0X3NlbmRfY21kID0gdnB1 X21hbG9uZV9wb3N0X2NtZCwKPiArCQkuaW5pdF9pbnN0YW5jZSA9IHZwdV9tYWxvbmVfaW5pdF9p bnN0YW5jZSwKPiArCQkuZ2V0X21heF9pbnN0YW5jZV9jb3VudCA9IHZwdV9tYWxvbmVfZ2V0X21h eF9pbnN0YW5jZV9jb3VudCwKPiArCX0sCj4gK307Cj4gKwo+ICtzdHJ1Y3QgdnB1X2lmYWNlX29w cyAqdnB1X2lmYWNlX2dldChzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUpCj4gK3sKPiArCXN0cnVjdCB2 cHVfaWZhY2Vfb3BzICpycGNfb3BzID0gTlVMTDsKPiArCXUzMiBzaXplID0gMDsKPiArCj4gKwlX QVJOX09OKCFjb3JlIHx8ICFjb3JlLT52cHUgfHwgIWNvcmUtPnZwdS0+cmVzKTsKPiArCj4gKwlz d2l0Y2ggKGNvcmUtPnZwdS0+cmVzLT5wbGF0X3R5cGUpIHsKPiArCWNhc2UgSU1YOFFYUDoKPiAr CWNhc2UgSU1YOFFNOgo+ICsJCXJwY19vcHMgPSBpbXg4cV9ycGNfb3BzOwo+ICsJCXNpemUgPSBB UlJBWV9TSVpFKGlteDhxX3JwY19vcHMpOwo+ICsJCWJyZWFrOwo+ICsJZGVmYXVsdDoKPiArCQly ZXR1cm4gTlVMTDsKPiArCX0KPiArCj4gKwlpZiAoY29yZS0+dHlwZSA+PSBzaXplKQo+ICsJCXJl dHVybiBOVUxMOwo+ICsKPiArCXJldHVybiAmcnBjX29wc1tjb3JlLT50eXBlXTsKPiArfQo+IGRp ZmYgLS1naXQgYS9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL2FtcGhpb24vdnB1X3JwYy5oIGIvZHJp dmVycy9tZWRpYS9wbGF0Zm9ybS9hbXBoaW9uL3ZwdV9ycGMuaAo+IG5ldyBmaWxlIG1vZGUgMTAw NjQ0Cj4gaW5kZXggMDAwMDAwMDAwMDAwLi5iMDY2YTgzZTY3ZDMKPiAtLS0gL2Rldi9udWxsCj4g KysrIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9hbXBoaW9uL3ZwdV9ycGMuaAo+IEBAIC0wLDAg KzEsNDYzIEBACj4gKy8qIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wICovCj4gKy8q Cj4gKyAqIENvcHlyaWdodCAyMDIwLTIwMjEgTlhQCj4gKyAqLwo+ICsKPiArI2lmbmRlZiBfQU1Q SElPTl9WUFVfUlBDX0gKPiArI2RlZmluZSBfQU1QSElPTl9WUFVfUlBDX0gKPiArCj4gKyNpbmNs dWRlIDxtZWRpYS92aWRlb2J1ZjItY29yZS5oPgo+ICsjaW5jbHVkZSAidnB1X2NvZGVjLmgiCj4g Kwo+ICtzdHJ1Y3QgdnB1X3JwY19idWZmZXJfZGVzYyB7Cj4gKwl1MzIgd3B0cjsKPiArCXUzMiBy cHRyOwo+ICsJdTMyIHN0YXJ0Owo+ICsJdTMyIGVuZDsKPiArfTsKPiArCj4gK3N0cnVjdCB2cHVf c2hhcmVkX2FkZHIgewo+ICsJdm9pZCAqaWZhY2U7Cj4gKwlzdHJ1Y3QgdnB1X3JwY19idWZmZXJf ZGVzYyAqY21kX2Rlc2M7Cj4gKwl2b2lkICpjbWRfbWVtX3ZpcjsKPiArCXN0cnVjdCB2cHVfcnBj X2J1ZmZlcl9kZXNjICptc2dfZGVzYzsKPiArCXZvaWQgKm1zZ19tZW1fdmlyOwo+ICsKPiArCXVu c2lnbmVkIGxvbmcgYm9vdF9hZGRyOwo+ICsJc3RydWN0IHZwdV9jb3JlICpjb3JlOwo+ICsJdm9p ZCAqcHJpdjsKPiArfTsKPiArCj4gK3N0cnVjdCB2cHVfcnBjX2V2ZW50X2hlYWRlciB7Cj4gKwl1 MzIgaW5kZXg7Cj4gKwl1MzIgaWQ7Cj4gKwl1MzIgbnVtOwo+ICt9Owo+ICsKPiArc3RydWN0IHZw dV9ycGNfZXZlbnQgewo+ICsJc3RydWN0IHZwdV9ycGNfZXZlbnRfaGVhZGVyIGhkcjsKPiArCXUz MiBkYXRhWzEyOF07Cj4gK307Cj4gKwo+ICtzdHJ1Y3QgdnB1X2lmYWNlX29wcyB7Cj4gKwlib29s ICgqY2hlY2tfY29kZWMpKGVudW0gdnB1X2NvcmVfdHlwZSB0eXBlKTsKPiArCWJvb2wgKCpjaGVj a19mbXQpKGVudW0gdnB1X2NvcmVfdHlwZSB0eXBlLCB1MzIgcGl4ZWxmbXQpOwo+ICsJdTMyICgq Z2V0X2RhdGFfc2l6ZSkodm9pZCk7Cj4gKwl1MzIgKCpjaGVja19tZW1vcnlfcmVnaW9uKShkbWFf YWRkcl90IGJhc2UsIGRtYV9hZGRyX3QgYWRkciwgdTMyIHNpemUpOwo+ICsJaW50ICgqYm9vdF9j b3JlKShzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUpOwo+ICsJaW50ICgqc2h1dGRvd25fY29yZSkoc3Ry dWN0IHZwdV9jb3JlICpjb3JlKTsKPiArCWludCAoKnJlc3RvcmVfY29yZSkoc3RydWN0IHZwdV9j b3JlICpjb3JlKTsKPiArCWludCAoKmdldF9wb3dlcl9zdGF0ZSkoc3RydWN0IHZwdV9jb3JlICpj b3JlKTsKPiArCWludCAoKm9uX2Zpcm13YXJlX2xvYWRlZCkoc3RydWN0IHZwdV9jb3JlICpjb3Jl KTsKPiArCXZvaWQgKCppbml0X3JwYykoc3RydWN0IHZwdV9zaGFyZWRfYWRkciAqc2hhcmVkLAo+ ICsJCQlzdHJ1Y3QgdnB1X2J1ZmZlciAqcnBjLCBkbWFfYWRkcl90IGJvb3RfYWRkcik7Cj4gKwl2 b2lkICgqc2V0X2xvZ19idWYpKHN0cnVjdCB2cHVfc2hhcmVkX2FkZHIgKnNoYXJlZCwKPiArCQkJ c3RydWN0IHZwdV9idWZmZXIgKmxvZyk7Cj4gKwl2b2lkICgqc2V0X3N5c3RlbV9jZmcpKHN0cnVj dCB2cHVfc2hhcmVkX2FkZHIgKnNoYXJlZCwKPiArCQkJdTMyIHJlZ3NfYmFzZSwgdm9pZCBfX2lv bWVtICpyZWdzLCB1MzIgaW5kZXgpOwo+ICsJdm9pZCAoKnNldF9zdHJlYW1fY2ZnKShzdHJ1Y3Qg dnB1X3NoYXJlZF9hZGRyICpzaGFyZWQsIHUzMiBpbmRleCk7Cj4gKwl1MzIgKCpnZXRfdmVyc2lv bikoc3RydWN0IHZwdV9zaGFyZWRfYWRkciAqc2hhcmVkKTsKPiArCXUzMiAoKmdldF9tYXhfaW5z dGFuY2VfY291bnQpKHN0cnVjdCB2cHVfc2hhcmVkX2FkZHIgKnNoYXJlZCk7Cj4gKwlpbnQgKCpn ZXRfc3RyZWFtX2J1ZmZlcl9zaXplKShzdHJ1Y3QgdnB1X3NoYXJlZF9hZGRyICpzaGFyZWQpOwo+ ICsJaW50ICgqc2VuZF9jbWRfYnVmKShzdHJ1Y3QgdnB1X3NoYXJlZF9hZGRyICpzaGFyZWQsCj4g KwkJCXN0cnVjdCB2cHVfcnBjX2V2ZW50ICpjbWQpOwo+ICsJaW50ICgqcmVjZWl2ZV9tc2dfYnVm KShzdHJ1Y3QgdnB1X3NoYXJlZF9hZGRyICpzaGFyZWQsCj4gKwkJCXN0cnVjdCB2cHVfcnBjX2V2 ZW50ICptc2cpOwo+ICsJaW50ICgqcGFja19jbWQpKHN0cnVjdCB2cHVfcnBjX2V2ZW50ICpwa3Qs IHUzMiBpbmRleCwgdTMyIGlkLCB2b2lkICpkYXRhKTsKPiArCWludCAoKmNvbnZlcnRfbXNnX2lk KSh1MzIgbXNnX2lkKTsKPiArCWludCAoKnVucGFja19tc2dfZGF0YSkoc3RydWN0IHZwdV9ycGNf ZXZlbnQgKnBrdCwgdm9pZCAqZGF0YSk7Cj4gKwlpbnQgKCppbnB1dF9mcmFtZSkoc3RydWN0IHZw dV9zaGFyZWRfYWRkciAqc2hhcmVkLAo+ICsJCQlzdHJ1Y3QgdnB1X2luc3QgKmluc3QsIHN0cnVj dCB2YjJfYnVmZmVyICp2Yik7Cj4gKwlpbnQgKCpjb25maWdfbWVtb3J5X3Jlc291cmNlKShzdHJ1 Y3QgdnB1X3NoYXJlZF9hZGRyICpzaGFyZWQsCj4gKwkJCQkJdTMyIGluc3RhbmNlLAo+ICsJCQkJ CXUzMiB0eXBlLAo+ICsJCQkJCXUzMiBpbmRleCwKPiArCQkJCQlzdHJ1Y3QgdnB1X2J1ZmZlciAq YnVmKTsKPiArCWludCAoKmNvbmZpZ19zdHJlYW1fYnVmZmVyKShzdHJ1Y3QgdnB1X3NoYXJlZF9h ZGRyICpzaGFyZWQsCj4gKwkJCQkJdTMyIGluc3RhbmNlLAo+ICsJCQkJCXN0cnVjdCB2cHVfYnVm ZmVyICpidWYpOwo+ICsJaW50ICgqdXBkYXRlX3N0cmVhbV9idWZmZXIpKHN0cnVjdCB2cHVfc2hh cmVkX2FkZHIgKnNoYXJlZCwKPiArCQkJCQl1MzIgaW5zdGFuY2UsIHUzMiBwdHIsIGJvb2wgd3Jp dGUpOwo+ICsJaW50ICgqZ2V0X3N0cmVhbV9idWZmZXJfZGVzYykoc3RydWN0IHZwdV9zaGFyZWRf YWRkciAqc2hhcmVkLAo+ICsJCQkJCXUzMiBpbnN0YW5jZSwKPiArCQkJCQlzdHJ1Y3QgdnB1X3Jw Y19idWZmZXJfZGVzYyAqZGVzYyk7Cj4gKwlpbnQgKCpzZXRfZW5jb2RlX3BhcmFtcykoc3RydWN0 IHZwdV9zaGFyZWRfYWRkciAqc2hhcmVkLAo+ICsJCQl1MzIgaW5zdGFuY2UsCj4gKwkJCXN0cnVj dCB2cHVfZW5jb2RlX3BhcmFtcyAqcGFyYW1zLCB1MzIgdXBkYXRlKTsKPiArCWludCAoKnNldF9k ZWNvZGVfcGFyYW1zKShzdHJ1Y3QgdnB1X3NoYXJlZF9hZGRyICpzaGFyZWQsCj4gKwkJCXUzMiBp bnN0YW5jZSwKPiArCQkJc3RydWN0IHZwdV9kZWNvZGVfcGFyYW1zICpwYXJhbXMsIHUzMiB1cGRh dGUpOwo+ICsJaW50ICgqYWRkX3Njb2RlKShzdHJ1Y3QgdnB1X3NoYXJlZF9hZGRyICpzaGFyZWQs Cj4gKwkJCQl1MzIgaW5zdGFuY2UsCj4gKwkJCQlzdHJ1Y3QgdnB1X2J1ZmZlciAqc3RyZWFtX2J1 ZmZlciwKPiArCQkJCXUzMiBwaXhlbGZvcm1hdCwKPiArCQkJCXUzMiBzY29kZV90eXBlKTsKPiAr CWludCAoKnByZV9zZW5kX2NtZCkoc3RydWN0IHZwdV9zaGFyZWRfYWRkciAqc2hhcmVkLCB1MzIg aW5zdGFuY2UpOwo+ICsJaW50ICgqcG9zdF9zZW5kX2NtZCkoc3RydWN0IHZwdV9zaGFyZWRfYWRk ciAqc2hhcmVkLCB1MzIgaW5zdGFuY2UpOwo+ICsJaW50ICgqaW5pdF9pbnN0YW5jZSkoc3RydWN0 IHZwdV9zaGFyZWRfYWRkciAqc2hhcmVkLCB1MzIgaW5zdGFuY2UpOwo+ICt9Owo+ICsKPiArZW51 bSB7Cj4gKwlWUFVfQ09SRV9NRU1PUllfSU5WQUxJRCA9IDAsCj4gKwlWUFVfQ09SRV9NRU1PUllf Q0FDSEVELAo+ICsJVlBVX0NPUkVfTUVNT1JZX1VOQ0FDSEVECj4gK307Cj4gKwo+ICtzdHJ1Y3Qg dnB1X3JwY19yZWdpb25fdCB7Cj4gKwlkbWFfYWRkcl90IHN0YXJ0Owo+ICsJZG1hX2FkZHJfdCBl bmQ7Cj4gKwlkbWFfYWRkcl90IHR5cGU7Cj4gK307Cj4gKwo+ICtzdHJ1Y3QgdnB1X2lmYWNlX29w cyAqdnB1X2lmYWNlX2dldChzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUpOwo+ICt1MzIgdnB1X2lmYWNl X2NoZWNrX21lbW9yeV9yZWdpb24oc3RydWN0IHZwdV9jb3JlICpjb3JlLCBkbWFfYWRkcl90IGFk ZHIsIHUzMiBzaXplKTsKPiArCj4gK3N0YXRpYyBpbmxpbmUgYm9vbCB2cHVfaWZhY2VfY2hlY2tf Y29kZWMoc3RydWN0IHZwdV9jb3JlICpjb3JlKQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X2lmYWNlX29w cyAqb3BzID0gdnB1X2lmYWNlX2dldChjb3JlKTsKPiArCj4gKwlpZiAob3BzICYmIG9wcy0+Y2hl Y2tfY29kZWMpCj4gKwkJcmV0dXJuIG9wcy0+Y2hlY2tfY29kZWMoY29yZS0+dHlwZSk7Cj4gKwo+ ICsJcmV0dXJuIHRydWU7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgYm9vbCB2cHVfaWZhY2Vf Y2hlY2tfZm9ybWF0KHN0cnVjdCB2cHVfY29yZSAqY29yZSwgdTMyIHBpeGVsZm10KQo+ICt7Cj4g KwlzdHJ1Y3QgdnB1X2lmYWNlX29wcyAqb3BzID0gdnB1X2lmYWNlX2dldChjb3JlKTsKPiArCj4g KwlpZiAob3BzICYmIG9wcy0+Y2hlY2tfZm10KQo+ICsJCXJldHVybiBvcHMtPmNoZWNrX2ZtdChj b3JlLT50eXBlLCBwaXhlbGZtdCk7Cj4gKwo+ICsJcmV0dXJuIHRydWU7Cj4gK30KPiArCj4gK3N0 YXRpYyBpbmxpbmUgaW50IHZwdV9pZmFjZV9ib290X2NvcmUoc3RydWN0IHZwdV9jb3JlICpjb3Jl KQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X2lmYWNlX29wcyAqb3BzID0gdnB1X2lmYWNlX2dldChjb3Jl KTsKPiArCj4gKwlpZiAob3BzICYmIG9wcy0+Ym9vdF9jb3JlKQo+ICsJCXJldHVybiBvcHMtPmJv b3RfY29yZShjb3JlKTsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIGlu dCB2cHVfaWZhY2VfZ2V0X3Bvd2VyX3N0YXRlKHN0cnVjdCB2cHVfY29yZSAqY29yZSkKPiArewo+ ICsJc3RydWN0IHZwdV9pZmFjZV9vcHMgKm9wcyA9IHZwdV9pZmFjZV9nZXQoY29yZSk7Cj4gKwo+ ICsJaWYgKG9wcyAmJiBvcHMtPmdldF9wb3dlcl9zdGF0ZSkKPiArCQlyZXR1cm4gb3BzLT5nZXRf cG93ZXJfc3RhdGUoY29yZSk7Cj4gKwlyZXR1cm4gMTsKPiArfQo+ICsKPiArc3RhdGljIGlubGlu ZSBpbnQgdnB1X2lmYWNlX3NodXRkb3duX2NvcmUoc3RydWN0IHZwdV9jb3JlICpjb3JlKQo+ICt7 Cj4gKwlzdHJ1Y3QgdnB1X2lmYWNlX29wcyAqb3BzID0gdnB1X2lmYWNlX2dldChjb3JlKTsKPiAr Cj4gKwlpZiAob3BzICYmIG9wcy0+c2h1dGRvd25fY29yZSkKPiArCQlyZXR1cm4gb3BzLT5zaHV0 ZG93bl9jb3JlKGNvcmUpOwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUg aW50IHZwdV9pZmFjZV9yZXN0b3JlX2NvcmUoc3RydWN0IHZwdV9jb3JlICpjb3JlKQo+ICt7Cj4g KwlzdHJ1Y3QgdnB1X2lmYWNlX29wcyAqb3BzID0gdnB1X2lmYWNlX2dldChjb3JlKTsKPiArCj4g KwlpZiAob3BzICYmIG9wcy0+cmVzdG9yZV9jb3JlKQo+ICsJCXJldHVybiBvcHMtPnJlc3RvcmVf Y29yZShjb3JlKTsKPiArCXJldHVybiAtRUlOVkFMOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5l IGludCB2cHVfaWZhY2Vfb25fZmlybXdhcmVfbG9hZGVkKHN0cnVjdCB2cHVfY29yZSAqY29yZSkK PiArewo+ICsJc3RydWN0IHZwdV9pZmFjZV9vcHMgKm9wcyA9IHZwdV9pZmFjZV9nZXQoY29yZSk7 Cj4gKwo+ICsJaWYgKG9wcyAmJiBvcHMtPm9uX2Zpcm13YXJlX2xvYWRlZCkKPiArCQlyZXR1cm4g b3BzLT5vbl9maXJtd2FyZV9sb2FkZWQoY29yZSk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiAr Cj4gK3N0YXRpYyBpbmxpbmUgdTMyIHZwdV9pZmFjZV9nZXRfZGF0YV9zaXplKHN0cnVjdCB2cHVf Y29yZSAqY29yZSkKPiArewo+ICsJc3RydWN0IHZwdV9pZmFjZV9vcHMgKm9wcyA9IHZwdV9pZmFj ZV9nZXQoY29yZSk7Cj4gKwo+ICsJaWYgKCFvcHMgfHwgIW9wcy0+Z2V0X2RhdGFfc2l6ZSkKPiAr CQlyZXR1cm4gMDsKPiArCj4gKwlyZXR1cm4gb3BzLT5nZXRfZGF0YV9zaXplKCk7Cj4gK30KPiAr Cj4gK3N0YXRpYyBpbmxpbmUgaW50IHZwdV9pZmFjZV9pbml0KHN0cnVjdCB2cHVfY29yZSAqY29y ZSwKPiArCQkJCXN0cnVjdCB2cHVfc2hhcmVkX2FkZHIgKnNoYXJlZCwKPiArCQkJCXN0cnVjdCB2 cHVfYnVmZmVyICpycGMsCj4gKwkJCQlkbWFfYWRkcl90IGJvb3RfYWRkcikKPiArewo+ICsJc3Ry dWN0IHZwdV9pZmFjZV9vcHMgKm9wcyA9IHZwdV9pZmFjZV9nZXQoY29yZSk7Cj4gKwo+ICsJaWYg KCFvcHMgfHwgIW9wcy0+aW5pdF9ycGMpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJb3Bz LT5pbml0X3JwYyhzaGFyZWQsIHJwYywgYm9vdF9hZGRyKTsKPiArCWNvcmUtPmlmYWNlID0gc2hh cmVkOwo+ICsJc2hhcmVkLT5jb3JlID0gY29yZTsKPiArCWlmIChycGMtPmJ5dGVzdXNlZCA+IHJw Yy0+bGVuZ3RoKQo+ICsJCXJldHVybiAtRU5PU1BDOwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4g K3N0YXRpYyBpbmxpbmUgaW50IHZwdV9pZmFjZV9zZXRfbG9nX2J1ZihzdHJ1Y3QgdnB1X2NvcmUg KmNvcmUsCj4gKwkJCQkJc3RydWN0IHZwdV9idWZmZXIgKmxvZykKPiArewo+ICsJc3RydWN0IHZw dV9pZmFjZV9vcHMgKm9wcyA9IHZwdV9pZmFjZV9nZXQoY29yZSk7Cj4gKwo+ICsJaWYgKCFvcHMp Cj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJaWYgKG9wcy0+c2V0X2xvZ19idWYpCj4gKwkJ b3BzLT5zZXRfbG9nX2J1Zihjb3JlLT5pZmFjZSwgbG9nKTsKPiArCj4gKwlyZXR1cm4gMDsKPiAr fQo+ICsKPiArc3RhdGljIGlubGluZSBpbnQgdnB1X2lmYWNlX2NvbmZpZ19zeXN0ZW0oc3RydWN0 IHZwdV9jb3JlICpjb3JlLAo+ICsJCXUzMiByZWdzX2Jhc2UsIHZvaWQgX19pb21lbSAqcmVncykK PiArewo+ICsJc3RydWN0IHZwdV9pZmFjZV9vcHMgKm9wcyA9IHZwdV9pZmFjZV9nZXQoY29yZSk7 Cj4gKwo+ICsJaWYgKCFvcHMpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwlpZiAob3BzLT5zZXRf c3lzdGVtX2NmZykKPiArCQlvcHMtPnNldF9zeXN0ZW1fY2ZnKGNvcmUtPmlmYWNlLCByZWdzX2Jh c2UsIHJlZ3MsIGNvcmUtPmlkKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGlj IGlubGluZSBpbnQgdnB1X2lmYWNlX2dldF9zdHJlYW1fYnVmZmVyX3NpemUoc3RydWN0IHZwdV9j b3JlICpjb3JlKQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X2lmYWNlX29wcyAqb3BzID0gdnB1X2lmYWNl X2dldChjb3JlKTsKPiArCj4gKwlpZiAoIW9wcyB8fCAhb3BzLT5nZXRfc3RyZWFtX2J1ZmZlcl9z aXplKQo+ICsJCXJldHVybiAwOwo+ICsKPiArCXJldHVybiBvcHMtPmdldF9zdHJlYW1fYnVmZmVy X3NpemUoY29yZS0+aWZhY2UpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIGludCB2cHVfaWZh Y2VfY29uZmlnX3N0cmVhbShzdHJ1Y3QgdnB1X2luc3QgKmluc3QpCj4gK3sKPiArCXN0cnVjdCB2 cHVfaWZhY2Vfb3BzICpvcHMgPSB2cHVfaWZhY2VfZ2V0KGluc3QtPmNvcmUpOwo+ICsKPiArCVdB Uk5fT04oaW5zdC0+aWQgPCAwKTsKPiArCWlmICghb3BzKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ ICsJaWYgKG9wcy0+c2V0X3N0cmVhbV9jZmcpCj4gKwkJb3BzLT5zZXRfc3RyZWFtX2NmZyhpbnN0 LT5jb3JlLT5pZmFjZSwgaW5zdC0+aWQpOwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRp YyBpbmxpbmUgaW50IHZwdV9pZmFjZV9zZW5kX2NtZChzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUsIHN0 cnVjdCB2cHVfcnBjX2V2ZW50ICpjbWQpCj4gK3sKPiArCXN0cnVjdCB2cHVfaWZhY2Vfb3BzICpv cHMgPSB2cHVfaWZhY2VfZ2V0KGNvcmUpOwo+ICsKPiArCWlmICghb3BzIHx8ICFvcHMtPnNlbmRf Y21kX2J1ZikKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwlyZXR1cm4gb3BzLT5zZW5kX2Nt ZF9idWYoY29yZS0+aWZhY2UsIGNtZCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgaW50IHZw dV9pZmFjZV9yZWNlaXZlX21zZyhzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUsIHN0cnVjdCB2cHVfcnBj X2V2ZW50ICptc2cpCj4gK3sKPiArCXN0cnVjdCB2cHVfaWZhY2Vfb3BzICpvcHMgPSB2cHVfaWZh Y2VfZ2V0KGNvcmUpOwo+ICsKPiArCWlmICghb3BzIHx8ICFvcHMtPnJlY2VpdmVfbXNnX2J1ZikK PiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwlyZXR1cm4gb3BzLT5yZWNlaXZlX21zZ19idWYo Y29yZS0+aWZhY2UsIG1zZyk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgaW50IHZwdV9pZmFj ZV9wYWNrX2NtZChzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUsCj4gKwkJCQkJc3RydWN0IHZwdV9ycGNf ZXZlbnQgKnBrdCwKPiArCQkJCQl1MzIgaW5kZXgsIHUzMiBpZCwgdm9pZCAqZGF0YSkKPiArewo+ ICsJc3RydWN0IHZwdV9pZmFjZV9vcHMgKm9wcyA9IHZwdV9pZmFjZV9nZXQoY29yZSk7Cj4gKwo+ ICsJaWYgKCFvcHMgfHwgIW9wcy0+cGFja19jbWQpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwly ZXR1cm4gb3BzLT5wYWNrX2NtZChwa3QsIGluZGV4LCBpZCwgZGF0YSk7Cj4gK30KPiArCj4gK3N0 YXRpYyBpbmxpbmUgaW50IHZwdV9pZmFjZV9jb252ZXJ0X21zZ19pZChzdHJ1Y3QgdnB1X2NvcmUg KmNvcmUsIHUzMiBtc2dfaWQpCj4gK3sKPiArCXN0cnVjdCB2cHVfaWZhY2Vfb3BzICpvcHMgPSB2 cHVfaWZhY2VfZ2V0KGNvcmUpOwo+ICsKPiArCWlmICghb3BzIHx8ICFvcHMtPmNvbnZlcnRfbXNn X2lkKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXJldHVybiBvcHMtPmNvbnZlcnRfbXNn X2lkKG1zZ19pZCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgaW50IHZwdV9pZmFjZV91bnBh Y2tfbXNnX2RhdGEoc3RydWN0IHZwdV9jb3JlICpjb3JlLAo+ICsJCQkJCQlzdHJ1Y3QgdnB1X3Jw Y19ldmVudCAqcGt0LCB2b2lkICpkYXRhKQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X2lmYWNlX29wcyAq b3BzID0gdnB1X2lmYWNlX2dldChjb3JlKTsKPiArCj4gKwlpZiAoIW9wcyB8fCAhb3BzLT51bnBh Y2tfbXNnX2RhdGEpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJcmV0dXJuIG9wcy0+dW5w YWNrX21zZ19kYXRhKHBrdCwgZGF0YSk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgaW50IHZw dV9pZmFjZV9pbnB1dF9mcmFtZShzdHJ1Y3QgdnB1X2luc3QgKmluc3QsCj4gKwkJCQkJCXN0cnVj dCB2YjJfYnVmZmVyICp2YikKPiArewo+ICsJc3RydWN0IHZwdV9pZmFjZV9vcHMgKm9wcyA9IHZw dV9pZmFjZV9nZXQoaW5zdC0+Y29yZSk7Cj4gKwo+ICsJaWYgKCFvcHMgfHwgIW9wcy0+aW5wdXRf ZnJhbWUpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJcmV0dXJuIG9wcy0+aW5wdXRfZnJh bWUoaW5zdC0+Y29yZS0+aWZhY2UsIGluc3QsIHZiKTsKPiArfQo+ICsKPiArc3RhdGljIGlubGlu ZSBpbnQgdnB1X2lmYWNlX2NvbmZpZ19tZW1vcnlfcmVzb3VyY2Uoc3RydWN0IHZwdV9pbnN0ICpp bnN0LAo+ICsJCQl1MzIgdHlwZSwgdTMyIGluZGV4LCBzdHJ1Y3QgdnB1X2J1ZmZlciAqYnVmKQo+ ICt7Cj4gKwlzdHJ1Y3QgdnB1X2lmYWNlX29wcyAqb3BzID0gdnB1X2lmYWNlX2dldChpbnN0LT5j b3JlKTsKPiArCj4gKwlXQVJOX09OKGluc3QtPmlkIDwgMCk7Cj4gKwlpZiAoIW9wcyB8fCAhb3Bz LT5jb25maWdfbWVtb3J5X3Jlc291cmNlKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXJl dHVybiBvcHMtPmNvbmZpZ19tZW1vcnlfcmVzb3VyY2UoaW5zdC0+Y29yZS0+aWZhY2UsCj4gKwkJ CQkJaW5zdC0+aWQsCj4gKwkJCQkJdHlwZSwgaW5kZXgsIGJ1Zik7Cj4gK30KPiArCj4gK3N0YXRp YyBpbmxpbmUgaW50IHZwdV9pZmFjZV9jb25maWdfc3RyZWFtX2J1ZmZlcihzdHJ1Y3QgdnB1X2lu c3QgKmluc3QsCj4gKwkJCQkJCXN0cnVjdCB2cHVfYnVmZmVyICpidWYpCj4gK3sKPiArCXN0cnVj dCB2cHVfaWZhY2Vfb3BzICpvcHMgPSB2cHVfaWZhY2VfZ2V0KGluc3QtPmNvcmUpOwo+ICsKPiAr CVdBUk5fT04oaW5zdC0+aWQgPCAwKTsKPiArCWlmICghb3BzIHx8ICFvcHMtPmNvbmZpZ19zdHJl YW1fYnVmZmVyKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXJldHVybiBvcHMtPmNvbmZp Z19zdHJlYW1fYnVmZmVyKGluc3QtPmNvcmUtPmlmYWNlLCBpbnN0LT5pZCwgYnVmKTsKPiArfQo+ ICsKPiArc3RhdGljIGlubGluZSBpbnQgdnB1X2lmYWNlX3VwZGF0ZV9zdHJlYW1fYnVmZmVyKHN0 cnVjdCB2cHVfaW5zdCAqaW5zdCwKPiArCQkJCQkJdTMyIHB0ciwgYm9vbCB3cml0ZSkKPiArewo+ ICsJc3RydWN0IHZwdV9pZmFjZV9vcHMgKm9wcyA9IHZwdV9pZmFjZV9nZXQoaW5zdC0+Y29yZSk7 Cj4gKwo+ICsJV0FSTl9PTihpbnN0LT5pZCA8IDApOwo+ICsJaWYgKCFvcHMgfHwgIW9wcy0+dXBk YXRlX3N0cmVhbV9idWZmZXIpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJcmV0dXJuIG9w cy0+dXBkYXRlX3N0cmVhbV9idWZmZXIoaW5zdC0+Y29yZS0+aWZhY2UsIGluc3QtPmlkLCBwdHIs IHdyaXRlKTsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSBpbnQgdnB1X2lmYWNlX2dldF9zdHJl YW1fYnVmZmVyX2Rlc2Moc3RydWN0IHZwdV9pbnN0ICppbnN0LAo+ICsJCQkJCXN0cnVjdCB2cHVf cnBjX2J1ZmZlcl9kZXNjICpkZXNjKQo+ICt7Cj4gKwlzdHJ1Y3QgdnB1X2lmYWNlX29wcyAqb3Bz ID0gdnB1X2lmYWNlX2dldChpbnN0LT5jb3JlKTsKPiArCj4gKwlXQVJOX09OKGluc3QtPmlkIDwg MCk7Cj4gKwlpZiAoIW9wcyB8fCAhb3BzLT5nZXRfc3RyZWFtX2J1ZmZlcl9kZXNjKQo+ICsJCXJl dHVybiAtRUlOVkFMOwo+ICsKPiArCWlmICghZGVzYykKPiArCQlyZXR1cm4gMDsKPiArCj4gKwly ZXR1cm4gb3BzLT5nZXRfc3RyZWFtX2J1ZmZlcl9kZXNjKGluc3QtPmNvcmUtPmlmYWNlLCBpbnN0 LT5pZCwgZGVzYyk7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgdTMyIHZwdV9pZmFjZV9nZXRf dmVyc2lvbihzdHJ1Y3QgdnB1X2NvcmUgKmNvcmUpCj4gK3sKPiArCXN0cnVjdCB2cHVfaWZhY2Vf b3BzICpvcHMgPSB2cHVfaWZhY2VfZ2V0KGNvcmUpOwo+ICsKPiArCWlmICghb3BzIHx8ICFvcHMt PmdldF92ZXJzaW9uKQo+ICsJCXJldHVybiAwOwo+ICsKPiArCXJldHVybiBvcHMtPmdldF92ZXJz aW9uKGNvcmUtPmlmYWNlKTsKPiArfQo+ICsKPiArc3RhdGljIGlubGluZSB1MzIgdnB1X2lmYWNl X2dldF9tYXhfaW5zdGFuY2VfY291bnQoc3RydWN0IHZwdV9jb3JlICpjb3JlKQo+ICt7Cj4gKwlz dHJ1Y3QgdnB1X2lmYWNlX29wcyAqb3BzID0gdnB1X2lmYWNlX2dldChjb3JlKTsKPiArCj4gKwlp ZiAoIW9wcyB8fCAhb3BzLT5nZXRfbWF4X2luc3RhbmNlX2NvdW50KQo+ICsJCXJldHVybiAwOwo+ ICsKPiArCXJldHVybiBvcHMtPmdldF9tYXhfaW5zdGFuY2VfY291bnQoY29yZS0+aWZhY2UpOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIGludCB2cHVfaWZhY2Vfc2V0X2VuY29kZV9wYXJhbXMo c3RydWN0IHZwdV9pbnN0ICppbnN0LAo+ICsJCQkJc3RydWN0IHZwdV9lbmNvZGVfcGFyYW1zICpw YXJhbXMsIHUzMiB1cGRhdGUpCj4gK3sKPiArCXN0cnVjdCB2cHVfaWZhY2Vfb3BzICpvcHMgPSB2 cHVfaWZhY2VfZ2V0KGluc3QtPmNvcmUpOwo+ICsKPiArCVdBUk5fT04oaW5zdC0+aWQgPCAwKTsK PiArCWlmICghb3BzIHx8ICFvcHMtPnNldF9lbmNvZGVfcGFyYW1zKQo+ICsJCXJldHVybiAtRUlO VkFMOwo+ICsKPiArCXJldHVybiBvcHMtPnNldF9lbmNvZGVfcGFyYW1zKGluc3QtPmNvcmUtPmlm YWNlLCBpbnN0LT5pZCwgcGFyYW1zLCB1cGRhdGUpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5l IGludCB2cHVfaWZhY2Vfc2V0X2RlY29kZV9wYXJhbXMoc3RydWN0IHZwdV9pbnN0ICppbnN0LAo+ ICsJCQkJc3RydWN0IHZwdV9kZWNvZGVfcGFyYW1zICpwYXJhbXMsIHUzMiB1cGRhdGUpCj4gK3sK PiArCXN0cnVjdCB2cHVfaWZhY2Vfb3BzICpvcHMgPSB2cHVfaWZhY2VfZ2V0KGluc3QtPmNvcmUp Owo+ICsKPiArCVdBUk5fT04oaW5zdC0+aWQgPCAwKTsKPiArCWlmICghb3BzIHx8ICFvcHMtPnNl dF9kZWNvZGVfcGFyYW1zKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXJldHVybiBvcHMt PnNldF9kZWNvZGVfcGFyYW1zKGluc3QtPmNvcmUtPmlmYWNlLCBpbnN0LT5pZCwgcGFyYW1zLCB1 cGRhdGUpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIGludCB2cHVfaWZhY2VfYWRkX3Njb2Rl KHN0cnVjdCB2cHVfaW5zdCAqaW5zdCwgdTMyIHNjb2RlX3R5cGUpCj4gK3sKPiArCXN0cnVjdCB2 cHVfaWZhY2Vfb3BzICpvcHMgPSB2cHVfaWZhY2VfZ2V0KGluc3QtPmNvcmUpOwo+ICsKPiArCVdB Uk5fT04oaW5zdC0+aWQgPCAwKTsKPiArCWlmICghb3BzIHx8ICFvcHMtPmFkZF9zY29kZSkKPiAr CQlyZXR1cm4gLUVJTlZBTDsKPiArCj4gKwlyZXR1cm4gb3BzLT5hZGRfc2NvZGUoaW5zdC0+Y29y ZS0+aWZhY2UsIGluc3QtPmlkLAo+ICsJCQkJJmluc3QtPnN0cmVhbV9idWZmZXIsCj4gKwkJCQlp bnN0LT5vdXRfZm9ybWF0LnBpeGZtdCwKPiArCQkJCXNjb2RlX3R5cGUpOwo+ICt9Cj4gKwo+ICtz dGF0aWMgaW5saW5lIGludCB2cHVfaWZhY2VfcHJlX3NlbmRfY21kKHN0cnVjdCB2cHVfaW5zdCAq aW5zdCkKPiArewo+ICsJc3RydWN0IHZwdV9pZmFjZV9vcHMgKm9wcyA9IHZwdV9pZmFjZV9nZXQo aW5zdC0+Y29yZSk7Cj4gKwo+ICsJV0FSTl9PTihpbnN0LT5pZCA8IDApOwo+ICsJaWYgKG9wcyAm JiBvcHMtPnByZV9zZW5kX2NtZCkKPiArCQlyZXR1cm4gb3BzLT5wcmVfc2VuZF9jbWQoaW5zdC0+ Y29yZS0+aWZhY2UsIGluc3QtPmlkKTsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMg aW5saW5lIGludCB2cHVfaWZhY2VfcG9zdF9zZW5kX2NtZChzdHJ1Y3QgdnB1X2luc3QgKmluc3Qp Cj4gK3sKPiArCXN0cnVjdCB2cHVfaWZhY2Vfb3BzICpvcHMgPSB2cHVfaWZhY2VfZ2V0KGluc3Qt PmNvcmUpOwo+ICsKPiArCVdBUk5fT04oaW5zdC0+aWQgPCAwKTsKPiArCWlmIChvcHMgJiYgb3Bz LT5wb3N0X3NlbmRfY21kKQo+ICsJCXJldHVybiBvcHMtPnBvc3Rfc2VuZF9jbWQoaW5zdC0+Y29y ZS0+aWZhY2UsIGluc3QtPmlkKTsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5s aW5lIGludCB2cHVfaWZhY2VfaW5pdF9pbnN0YW5jZShzdHJ1Y3QgdnB1X2luc3QgKmluc3QpCj4g K3sKPiArCXN0cnVjdCB2cHVfaWZhY2Vfb3BzICpvcHMgPSB2cHVfaWZhY2VfZ2V0KGluc3QtPmNv cmUpOwo+ICsKPiArCVdBUk5fT04oaW5zdC0+aWQgPCAwKTsKPiArCWlmIChvcHMgJiYgb3BzLT5p bml0X2luc3RhbmNlKQo+ICsJCXJldHVybiBvcHMtPmluaXRfaW5zdGFuY2UoaW5zdC0+Y29yZS0+ aWZhY2UsIGluc3QtPmlkKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArI2VuZGlmCgoK Cl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LWFy bS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9y ZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LWFybS1r ZXJuZWwK