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.3 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 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 29A78C433B4 for ; Sun, 2 May 2021 11:53:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DE4DF61106 for ; Sun, 2 May 2021 11:53:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230354AbhEBLtn (ORCPT ); Sun, 2 May 2021 07:49:43 -0400 Received: from mx2.suse.de ([195.135.220.15]:44296 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230222AbhEBLtm (ORCPT ); Sun, 2 May 2021 07:49:42 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 0CE55B199; Sun, 2 May 2021 11:48:50 +0000 (UTC) Subject: Re: [RFC PATCH v4 23/27] qedn: Add support of Task and SGL To: Shai Malin , netdev@vger.kernel.org, linux-nvme@lists.infradead.org, sagi@grimberg.me, hch@lst.de, axboe@fb.com, kbusch@kernel.org Cc: "David S . Miller davem @ davemloft . net --cc=Jakub Kicinski" , aelior@marvell.com, mkalderon@marvell.com, okulkarni@marvell.com, pkushwaha@marvell.com, malin1024@gmail.com References: <20210429190926.5086-1-smalin@marvell.com> <20210429190926.5086-24-smalin@marvell.com> From: Hannes Reinecke Message-ID: <3b9b048f-94e3-9bef-6d32-fc683636b649@suse.de> Date: Sun, 2 May 2021 13:48:49 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.8.0 MIME-Version: 1.0 In-Reply-To: <20210429190926.5086-24-smalin@marvell.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org On 4/29/21 9:09 PM, Shai Malin wrote: > From: Prabhakar Kushwaha > > This patch will add support of Task and SGL which is used > for slowpath and fast path IO. here Task is IO granule used > by firmware to perform tasks > > The internal implementation: > - Create task/sgl resources used by all connection > - Provide APIs to allocate and free task. > - Add task support during connection establishment i.e. slowpath > > Acked-by: Igor Russkikh > Signed-off-by: Prabhakar Kushwaha > Signed-off-by: Omkar Kulkarni > Signed-off-by: Michal Kalderon > Signed-off-by: Ariel Elior > Signed-off-by: Shai Malin > --- > drivers/nvme/hw/qedn/qedn.h | 66 +++++ > drivers/nvme/hw/qedn/qedn_conn.c | 43 +++- > drivers/nvme/hw/qedn/qedn_main.c | 34 ++- > drivers/nvme/hw/qedn/qedn_task.c | 411 +++++++++++++++++++++++++++++++ > 4 files changed, 550 insertions(+), 4 deletions(-) > > diff --git a/drivers/nvme/hw/qedn/qedn.h b/drivers/nvme/hw/qedn/qedn.h > index bd9a250cb2f5..880ca245b02c 100644 > --- a/drivers/nvme/hw/qedn/qedn.h > +++ b/drivers/nvme/hw/qedn/qedn.h > @@ -50,6 +50,21 @@ > #define QEDN_FW_CQ_FP_WQ_WORKQUEUE "qedn_fw_cq_fp_wq" > #define QEDN_NVME_REQ_FP_WQ_WORKQUEUE "qedn_nvme_req_fp_wq" > > +/* Protocol defines */ > +#define QEDN_MAX_IO_SIZE QED_NVMETCP_MAX_IO_SIZE > + > +#define QEDN_SGE_BUFF_SIZE 4096 > +#define QEDN_MAX_SGES_PER_TASK DIV_ROUND_UP(QEDN_MAX_IO_SIZE, QEDN_SGE_BUFF_SIZE) > +#define QEDN_FW_SGE_SIZE sizeof(struct nvmetcp_sge) > +#define QEDN_MAX_FW_SGL_SIZE ((QEDN_MAX_SGES_PER_TASK) * QEDN_FW_SGE_SIZE) > +#define QEDN_FW_SLOW_IO_MIN_SGE_LIMIT (9700 / 6) > + > +#define QEDN_MAX_HW_SECTORS (QEDN_MAX_IO_SIZE / 512) > +#define QEDN_MAX_SEGMENTS QEDN_MAX_SGES_PER_TASK > + > +#define QEDN_TASK_INSIST_TMO 1000 /* 1 sec */ > +#define QEDN_INVALID_ITID 0xFFFF > + > /* > * TCP offload stack default configurations and defines. > * Future enhancements will allow controlling the configurable > @@ -95,6 +110,15 @@ enum qedn_state { > QEDN_STATE_MODULE_REMOVE_ONGOING, > }; > > +struct qedn_io_resources { > + /* Lock for IO resources */ > + spinlock_t resources_lock; > + struct list_head task_free_list; > + u32 num_alloc_tasks; > + u32 num_free_tasks; > + u32 no_avail_resrc_cnt; > +}; > + > /* Per CPU core params */ > struct qedn_fp_queue { > struct qed_chain cq_chain; > @@ -104,6 +128,10 @@ struct qedn_fp_queue { > struct qed_sb_info *sb_info; > unsigned int cpu; > struct work_struct fw_cq_fp_wq_entry; > + > + /* IO related resources for host */ > + struct qedn_io_resources host_resrc; > + > u16 sb_id; > char irqname[QEDN_IRQ_NAME_LEN]; > }; > @@ -130,6 +158,8 @@ struct qedn_ctx { > /* Connections */ > DECLARE_HASHTABLE(conn_ctx_hash, 16); > > + u32 num_tasks_per_pool; > + > /* Fast path queues */ > u8 num_fw_cqs; > struct qedn_fp_queue *fp_q_arr; > @@ -137,6 +167,27 @@ struct qedn_ctx { > dma_addr_t fw_cq_array_phy; /* Physical address of fw_cq_array_virt */ > struct workqueue_struct *nvme_req_fp_wq; > struct workqueue_struct *fw_cq_fp_wq; > + > + /* Fast Path Tasks */ > + struct qed_nvmetcp_tid tasks; > +}; > + > +struct qedn_task_ctx { > + struct qedn_conn_ctx *qedn_conn; > + struct qedn_ctx *qedn; > + void *fw_task_ctx; > + struct qedn_fp_queue *fp_q; > + struct scatterlist *nvme_sg; > + struct nvme_tcp_ofld_req *req; /* currently proccessed request */ > + struct list_head entry; > + spinlock_t lock; /* To protect task resources */ > + bool valid; > + unsigned long flags; /* Used by qedn_task_flags */ > + u32 task_size; > + u16 itid; > + u16 cccid; > + int req_direction; > + struct storage_sgl_task_params sgl_task_params; > }; > > struct qedn_endpoint { > @@ -243,6 +294,7 @@ struct qedn_conn_ctx { > struct nvme_tcp_ofld_ctrl *ctrl; > u32 conn_handle; > u32 fw_cid; > + u8 default_cq; > > atomic_t est_conn_indicator; > atomic_t destroy_conn_indicator; > @@ -260,6 +312,11 @@ struct qedn_conn_ctx { > dma_addr_t host_cccid_itid_phy_addr; > struct qedn_endpoint ep; > int abrt_flag; > + /* Spinlock for accessing active_task_list */ > + spinlock_t task_list_lock; > + struct list_head active_task_list; > + atomic_t num_active_tasks; > + atomic_t num_active_fw_tasks; > > /* Connection resources - turned on to indicate what resource was > * allocated, to that it can later be released. > @@ -279,6 +336,7 @@ struct qedn_conn_ctx { > enum qedn_conn_resources_state { > QEDN_CONN_RESRC_FW_SQ, > QEDN_CONN_RESRC_ACQUIRE_CONN, > + QEDN_CONN_RESRC_TASKS, > QEDN_CONN_RESRC_CCCID_ITID_MAP, > QEDN_CONN_RESRC_TCP_PORT, > QEDN_CONN_RESRC_MAX = 64 > @@ -309,5 +367,13 @@ inline int qedn_validate_cccid_in_range(struct qedn_conn_ctx *conn_ctx, u16 ccci > void qedn_queue_request(struct qedn_conn_ctx *qedn_conn, struct nvme_tcp_ofld_req *req); > void qedn_nvme_req_fp_wq_handler(struct work_struct *work); > void qedn_io_work_cq(struct qedn_ctx *qedn, struct nvmetcp_fw_cqe *cqe); > +int qedn_alloc_tasks(struct qedn_conn_ctx *conn_ctx); > +inline int qedn_qid(struct nvme_tcp_ofld_queue *queue); > +struct qedn_task_ctx * > + qedn_get_task_from_pool_insist(struct qedn_conn_ctx *conn_ctx, u16 cccid); > +void qedn_common_clear_fw_sgl(struct storage_sgl_task_params *sgl_task_params); > +void qedn_return_active_tasks(struct qedn_conn_ctx *conn_ctx); > +void qedn_destroy_free_tasks(struct qedn_fp_queue *fp_q, > + struct qedn_io_resources *io_resrc); > > #endif /* _QEDN_H_ */ > diff --git a/drivers/nvme/hw/qedn/qedn_conn.c b/drivers/nvme/hw/qedn/qedn_conn.c > index 90d8aa36d219..10a80fbeac43 100644 > --- a/drivers/nvme/hw/qedn/qedn_conn.c > +++ b/drivers/nvme/hw/qedn/qedn_conn.c > @@ -29,6 +29,11 @@ static const char * const qedn_conn_state_str[] = { > NULL > }; > > +inline int qedn_qid(struct nvme_tcp_ofld_queue *queue) > +{ > + return queue - queue->ctrl->queues; > +} > + > int qedn_set_con_state(struct qedn_conn_ctx *conn_ctx, enum qedn_conn_state new_state) > { > spin_lock_bh(&conn_ctx->conn_state_lock); > @@ -146,6 +151,11 @@ static void qedn_release_conn_ctx(struct qedn_conn_ctx *conn_ctx) > clear_bit(QEDN_CONN_RESRC_ACQUIRE_CONN, &conn_ctx->resrc_state); > } > > + if (test_bit(QEDN_CONN_RESRC_TASKS, &conn_ctx->resrc_state)) { > + clear_bit(QEDN_CONN_RESRC_TASKS, &conn_ctx->resrc_state); > + qedn_return_active_tasks(conn_ctx); > + } > + > if (test_bit(QEDN_CONN_RESRC_CCCID_ITID_MAP, &conn_ctx->resrc_state)) { > dma_free_coherent(&qedn->pdev->dev, > conn_ctx->sq_depth * > @@ -247,6 +257,7 @@ static int qedn_nvmetcp_offload_conn(struct qedn_conn_ctx *conn_ctx) > offld_prms.max_rt_time = QEDN_TCP_MAX_RT_TIME; > offld_prms.sq_pbl_addr = > (u64)qed_chain_get_pbl_phys(&qedn_ep->fw_sq_chain); > + offld_prms.default_cq = conn_ctx->default_cq; > > rc = qed_ops->offload_conn(qedn->cdev, > conn_ctx->conn_handle, > @@ -375,6 +386,9 @@ int qedn_event_cb(void *context, u8 fw_event_code, void *event_ring_data) > static int qedn_prep_and_offload_queue(struct qedn_conn_ctx *conn_ctx) > { > struct qedn_ctx *qedn = conn_ctx->qedn; > + struct qedn_io_resources *io_resrc; > + struct qedn_fp_queue *fp_q; > + u8 default_cq_idx, qid; > size_t dma_size; > int rc; > > @@ -387,6 +401,8 @@ static int qedn_prep_and_offload_queue(struct qedn_conn_ctx *conn_ctx) > set_bit(QEDN_CONN_RESRC_FW_SQ, &conn_ctx->resrc_state); > INIT_LIST_HEAD(&conn_ctx->host_pend_req_list); > spin_lock_init(&conn_ctx->nvme_req_lock); > + atomic_set(&conn_ctx->num_active_tasks, 0); > + atomic_set(&conn_ctx->num_active_fw_tasks, 0); > > rc = qed_ops->acquire_conn(qedn->cdev, > &conn_ctx->conn_handle, > @@ -401,7 +417,32 @@ static int qedn_prep_and_offload_queue(struct qedn_conn_ctx *conn_ctx) > conn_ctx->conn_handle); > set_bit(QEDN_CONN_RESRC_ACQUIRE_CONN, &conn_ctx->resrc_state); > > - /* Placeholder - Allocate task resources and initialize fields */ > + qid = qedn_qid(conn_ctx->queue); > + default_cq_idx = qid ? qid - 1 : 0; /* Offset adminq */ > + > + conn_ctx->default_cq = (default_cq_idx % qedn->num_fw_cqs); > + fp_q = &qedn->fp_q_arr[conn_ctx->default_cq]; > + conn_ctx->fp_q = fp_q; > + io_resrc = &fp_q->host_resrc; > + > + /* The first connection on each fp_q will fill task > + * resources > + */ > + spin_lock(&io_resrc->resources_lock); > + if (io_resrc->num_alloc_tasks == 0) { > + rc = qedn_alloc_tasks(conn_ctx); > + if (rc) { > + pr_err("Failed allocating tasks: CID=0x%x\n", > + conn_ctx->fw_cid); > + spin_unlock(&io_resrc->resources_lock); > + goto rel_conn; > + } > + } > + spin_unlock(&io_resrc->resources_lock); > + > + spin_lock_init(&conn_ctx->task_list_lock); > + INIT_LIST_HEAD(&conn_ctx->active_task_list); > + set_bit(QEDN_CONN_RESRC_TASKS, &conn_ctx->resrc_state); > > rc = qedn_fetch_tcp_port(conn_ctx); > if (rc) > diff --git a/drivers/nvme/hw/qedn/qedn_main.c b/drivers/nvme/hw/qedn/qedn_main.c > index 38f23dbb03a5..8d9c19d63480 100644 > --- a/drivers/nvme/hw/qedn/qedn_main.c > +++ b/drivers/nvme/hw/qedn/qedn_main.c > @@ -30,6 +30,12 @@ __be16 qedn_get_in_port(struct sockaddr_storage *sa) > : ((struct sockaddr_in6 *)sa)->sin6_port; > } > > +static void qedn_init_io_resc(struct qedn_io_resources *io_resrc) > +{ > + spin_lock_init(&io_resrc->resources_lock); > + INIT_LIST_HEAD(&io_resrc->task_free_list); > +} > + > struct qedn_llh_filter *qedn_add_llh_filter(struct qedn_ctx *qedn, u16 tcp_port) > { > struct qedn_llh_filter *llh_filter = NULL; > @@ -436,6 +442,8 @@ static struct nvme_tcp_ofld_ops qedn_ofld_ops = { > * NVMF_OPT_HDR_DIGEST | NVMF_OPT_DATA_DIGEST | > * NVMF_OPT_NR_POLL_QUEUES | NVMF_OPT_TOS > */ > + .max_hw_sectors = QEDN_MAX_HW_SECTORS, > + .max_segments = QEDN_MAX_SEGMENTS, > .claim_dev = qedn_claim_dev, > .setup_ctrl = qedn_setup_ctrl, > .release_ctrl = qedn_release_ctrl, > @@ -657,8 +665,24 @@ static void qedn_remove_pf_from_gl_list(struct qedn_ctx *qedn) > mutex_unlock(&qedn_glb.glb_mutex); > } > > +static void qedn_call_destroy_free_tasks(struct qedn_fp_queue *fp_q, > + struct qedn_io_resources *io_resrc) > +{ > + if (list_empty(&io_resrc->task_free_list)) > + return; > + > + if (io_resrc->num_alloc_tasks != io_resrc->num_free_tasks) > + pr_err("Task Pool:Not all returned allocated=0x%x, free=0x%x\n", > + io_resrc->num_alloc_tasks, io_resrc->num_free_tasks); > + > + qedn_destroy_free_tasks(fp_q, io_resrc); > + if (io_resrc->num_free_tasks) > + pr_err("Expected num_free_tasks to be 0\n"); > +} > + > static void qedn_free_function_queues(struct qedn_ctx *qedn) > { > + struct qedn_io_resources *host_resrc; > struct qed_sb_info *sb_info = NULL; > struct qedn_fp_queue *fp_q; > int i; > @@ -673,6 +697,9 @@ static void qedn_free_function_queues(struct qedn_ctx *qedn) > /* Free the fast path queues*/ > for (i = 0; i < qedn->num_fw_cqs; i++) { > fp_q = &qedn->fp_q_arr[i]; > + host_resrc = &fp_q->host_resrc; > + > + qedn_call_destroy_free_tasks(fp_q, host_resrc); > > /* Free SB */ > sb_info = fp_q->sb_info; > @@ -769,7 +796,8 @@ static int qedn_alloc_function_queues(struct qedn_ctx *qedn) > goto mem_alloc_failure; > } > > - /* placeholder - create task pools */ > + qedn->num_tasks_per_pool = > + qedn->pf_params.nvmetcp_pf_params.num_tasks / qedn->num_fw_cqs; > > for (i = 0; i < qedn->num_fw_cqs; i++) { > fp_q = &qedn->fp_q_arr[i]; > @@ -811,7 +839,7 @@ static int qedn_alloc_function_queues(struct qedn_ctx *qedn) > fp_q->qedn = qedn; > INIT_WORK(&fp_q->fw_cq_fp_wq_entry, qedn_fw_cq_fq_wq_handler); > > - /* Placeholder - Init IO-path resources */ > + qedn_init_io_resc(&fp_q->host_resrc); > } > > return 0; > @@ -1005,7 +1033,7 @@ static int __qedn_probe(struct pci_dev *pdev) > > /* NVMeTCP start HW PF */ > rc = qed_ops->start(qedn->cdev, > - NULL /* Placeholder for FW IO-path resources */, > + &qedn->tasks, > qedn, > qedn_event_cb); > if (rc) { > diff --git a/drivers/nvme/hw/qedn/qedn_task.c b/drivers/nvme/hw/qedn/qedn_task.c > index d3474188efdc..54f2f4cba6ea 100644 > --- a/drivers/nvme/hw/qedn/qedn_task.c > +++ b/drivers/nvme/hw/qedn/qedn_task.c > @@ -11,6 +11,263 @@ > /* Driver includes */ > #include "qedn.h" > > +static bool qedn_sgl_has_small_mid_sge(struct nvmetcp_sge *sgl, u16 sge_count) > +{ > + u16 sge_num; > + > + if (sge_count > 8) { > + for (sge_num = 0; sge_num < sge_count; sge_num++) { > + if (le32_to_cpu(sgl[sge_num].sge_len) < > + QEDN_FW_SLOW_IO_MIN_SGE_LIMIT) > + return true; /* small middle SGE found */ > + } > + } > + > + return false; /* no small middle SGEs */ > +} > + > +static int qedn_init_sgl(struct qedn_ctx *qedn, struct qedn_task_ctx *qedn_task) > +{ > + struct storage_sgl_task_params *sgl_task_params; > + enum dma_data_direction dma_dir; > + struct scatterlist *sg; > + struct request *rq; > + u16 num_sges; > + int index; > + int rc; > + > + sgl_task_params = &qedn_task->sgl_task_params; > + rq = blk_mq_rq_from_pdu(qedn_task->req); > + if (qedn_task->task_size == 0) { > + sgl_task_params->num_sges = 0; > + > + return 0; > + } > + > + /* Convert BIO to scatterlist */ > + num_sges = blk_rq_map_sg(rq->q, rq, qedn_task->nvme_sg); > + if (qedn_task->req_direction == WRITE) > + dma_dir = DMA_TO_DEVICE; > + else > + dma_dir = DMA_FROM_DEVICE; > + > + /* DMA map the scatterlist */ > + if (dma_map_sg(&qedn->pdev->dev, qedn_task->nvme_sg, num_sges, dma_dir) != num_sges) { > + pr_err("Couldn't map sgl\n"); > + rc = -EPERM; > + > + return rc; > + } > + > + sgl_task_params->total_buffer_size = qedn_task->task_size; > + sgl_task_params->num_sges = num_sges; > + > + for_each_sg(qedn_task->nvme_sg, sg, num_sges, index) { > + DMA_REGPAIR_LE(sgl_task_params->sgl[index].sge_addr, sg_dma_address(sg)); > + sgl_task_params->sgl[index].sge_len = cpu_to_le32(sg_dma_len(sg)); > + } > + > + /* Relevant for Host Write Only */ > + sgl_task_params->small_mid_sge = (qedn_task->req_direction == READ) ? > + false : > + qedn_sgl_has_small_mid_sge(sgl_task_params->sgl, > + sgl_task_params->num_sges); > + > + return 0; > +} > + > +static void qedn_free_nvme_sg(struct qedn_task_ctx *qedn_task) > +{ > + kfree(qedn_task->nvme_sg); > + qedn_task->nvme_sg = NULL; > +} > + > +static void qedn_free_fw_sgl(struct qedn_task_ctx *qedn_task) > +{ > + struct qedn_ctx *qedn = qedn_task->qedn; > + dma_addr_t sgl_pa; > + > + sgl_pa = HILO_DMA_REGPAIR(qedn_task->sgl_task_params.sgl_phys_addr); > + dma_free_coherent(&qedn->pdev->dev, > + QEDN_MAX_FW_SGL_SIZE, > + qedn_task->sgl_task_params.sgl, > + sgl_pa); > + qedn_task->sgl_task_params.sgl = NULL; > +} > + > +static void qedn_destroy_single_task(struct qedn_task_ctx *qedn_task) > +{ > + u16 itid; > + > + itid = qedn_task->itid; > + list_del(&qedn_task->entry); > + qedn_free_nvme_sg(qedn_task); > + qedn_free_fw_sgl(qedn_task); > + kfree(qedn_task); > + qedn_task = NULL; > +} > + > +void qedn_destroy_free_tasks(struct qedn_fp_queue *fp_q, > + struct qedn_io_resources *io_resrc) > +{ > + struct qedn_task_ctx *qedn_task, *task_tmp; > + > + /* Destroy tasks from the free task list */ > + list_for_each_entry_safe(qedn_task, task_tmp, > + &io_resrc->task_free_list, entry) { > + qedn_destroy_single_task(qedn_task); > + io_resrc->num_free_tasks -= 1; > + } > +} > + > +static int qedn_alloc_nvme_sg(struct qedn_task_ctx *qedn_task) > +{ > + int rc; > + > + qedn_task->nvme_sg = kcalloc(QEDN_MAX_SGES_PER_TASK, > + sizeof(*qedn_task->nvme_sg), GFP_KERNEL); > + if (!qedn_task->nvme_sg) { > + rc = -ENOMEM; > + > + return rc; > + } > + > + return 0; > +} > + > +static int qedn_alloc_fw_sgl(struct qedn_task_ctx *qedn_task) > +{ > + struct qedn_ctx *qedn = qedn_task->qedn_conn->qedn; > + dma_addr_t fw_sgl_phys; > + > + qedn_task->sgl_task_params.sgl = > + dma_alloc_coherent(&qedn->pdev->dev, QEDN_MAX_FW_SGL_SIZE, > + &fw_sgl_phys, GFP_KERNEL); > + if (!qedn_task->sgl_task_params.sgl) { > + pr_err("Couldn't allocate FW sgl\n"); > + > + return -ENOMEM; > + } > + > + DMA_REGPAIR_LE(qedn_task->sgl_task_params.sgl_phys_addr, fw_sgl_phys); > + > + return 0; > +} > + > +static inline void *qedn_get_fw_task(struct qed_nvmetcp_tid *info, u16 itid) > +{ > + return (void *)(info->blocks[itid / info->num_tids_per_block] + > + (itid % info->num_tids_per_block) * info->size); > +} > + > +static struct qedn_task_ctx *qedn_alloc_task(struct qedn_conn_ctx *conn_ctx, u16 itid) > +{ > + struct qedn_ctx *qedn = conn_ctx->qedn; > + struct qedn_task_ctx *qedn_task; > + void *fw_task_ctx; > + int rc = 0; > + > + qedn_task = kzalloc(sizeof(*qedn_task), GFP_KERNEL); > + if (!qedn_task) > + return NULL; > + As this is a pool, why don't you use mempools here? > + spin_lock_init(&qedn_task->lock); > + fw_task_ctx = qedn_get_fw_task(&qedn->tasks, itid); > + if (!fw_task_ctx) { > + pr_err("iTID: 0x%x; Failed getting fw_task_ctx memory\n", itid); > + goto release_task; > + } > + > + /* No need to memset fw_task_ctx - its done in the HSI func */ > + qedn_task->qedn_conn = conn_ctx; > + qedn_task->qedn = qedn; > + qedn_task->fw_task_ctx = fw_task_ctx; > + qedn_task->valid = 0; > + qedn_task->flags = 0; > + qedn_task->itid = itid; > + rc = qedn_alloc_fw_sgl(qedn_task); > + if (rc) { > + pr_err("iTID: 0x%x; Failed allocating FW sgl\n", itid); > + goto release_task; > + } > + > + rc = qedn_alloc_nvme_sg(qedn_task); > + if (rc) { > + pr_err("iTID: 0x%x; Failed allocating FW sgl\n", itid); > + goto release_fw_sgl; > + } > + > + return qedn_task; > + > +release_fw_sgl: > + qedn_free_fw_sgl(qedn_task); > +release_task: > + kfree(qedn_task); > + > + return NULL; > +} > + > +int qedn_alloc_tasks(struct qedn_conn_ctx *conn_ctx) > +{ > + struct qedn_ctx *qedn = conn_ctx->qedn; > + struct qedn_task_ctx *qedn_task = NULL; > + struct qedn_io_resources *io_resrc; > + u16 itid, start_itid, offset; > + struct qedn_fp_queue *fp_q; > + int i, rc; > + > + fp_q = conn_ctx->fp_q; > + > + offset = fp_q->sb_id; > + io_resrc = &fp_q->host_resrc; > + > + start_itid = qedn->num_tasks_per_pool * offset; > + for (i = 0; i < qedn->num_tasks_per_pool; ++i) { > + itid = start_itid + i; > + qedn_task = qedn_alloc_task(conn_ctx, itid); > + if (!qedn_task) { > + pr_err("Failed allocating task\n"); > + rc = -ENOMEM; > + goto release_tasks; > + } > + > + qedn_task->fp_q = fp_q; > + io_resrc->num_free_tasks += 1; > + list_add_tail(&qedn_task->entry, &io_resrc->task_free_list); > + } > + > + io_resrc->num_alloc_tasks = io_resrc->num_free_tasks; > + > + return 0; > + > +release_tasks: > + qedn_destroy_free_tasks(fp_q, io_resrc); > + > + return rc; > +} > + > +void qedn_common_clear_fw_sgl(struct storage_sgl_task_params *sgl_task_params) > +{ > + u16 sge_cnt = sgl_task_params->num_sges; > + > + memset(&sgl_task_params->sgl[(sge_cnt - 1)], 0, > + sizeof(struct nvmetcp_sge)); > + sgl_task_params->total_buffer_size = 0; > + sgl_task_params->small_mid_sge = false; > + sgl_task_params->num_sges = 0; > +} > + > +inline void qedn_host_reset_cccid_itid_entry(struct qedn_conn_ctx *conn_ctx, > + u16 cccid) > +{ > + conn_ctx->host_cccid_itid[cccid].itid = cpu_to_le16(QEDN_INVALID_ITID); > +} > + > +inline void qedn_host_set_cccid_itid_entry(struct qedn_conn_ctx *conn_ctx, u16 cccid, u16 itid) > +{ > + conn_ctx->host_cccid_itid[cccid].itid = cpu_to_le16(itid); > +} > + > inline int qedn_validate_cccid_in_range(struct qedn_conn_ctx *conn_ctx, u16 cccid) > { > int rc = 0; > @@ -23,6 +280,160 @@ inline int qedn_validate_cccid_in_range(struct qedn_conn_ctx *conn_ctx, u16 ccci > return rc; > } > > +static void qedn_clear_sgl(struct qedn_ctx *qedn, > + struct qedn_task_ctx *qedn_task) > +{ > + struct storage_sgl_task_params *sgl_task_params; > + enum dma_data_direction dma_dir; > + u32 sge_cnt; > + > + sgl_task_params = &qedn_task->sgl_task_params; > + sge_cnt = sgl_task_params->num_sges; > + > + /* Nothing to do if no SGEs were used */ > + if (!qedn_task->task_size || !sge_cnt) > + return; > + > + dma_dir = (qedn_task->req_direction == WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE); > + dma_unmap_sg(&qedn->pdev->dev, qedn_task->nvme_sg, sge_cnt, dma_dir); > + memset(&qedn_task->nvme_sg[(sge_cnt - 1)], 0, sizeof(struct scatterlist)); > + qedn_common_clear_fw_sgl(sgl_task_params); > + qedn_task->task_size = 0; > +} > + > +static void qedn_clear_task(struct qedn_conn_ctx *conn_ctx, > + struct qedn_task_ctx *qedn_task) > +{ > + /* Task lock isn't needed since it is no longer in use */ > + qedn_clear_sgl(conn_ctx->qedn, qedn_task); > + qedn_task->valid = 0; > + qedn_task->flags = 0; > + > + atomic_dec(&conn_ctx->num_active_tasks); > +} > + > +void qedn_return_active_tasks(struct qedn_conn_ctx *conn_ctx) > +{ > + struct qedn_fp_queue *fp_q = conn_ctx->fp_q; > + struct qedn_task_ctx *qedn_task, *task_tmp; > + struct qedn_io_resources *io_resrc; > + int num_returned_tasks = 0; > + int num_active_tasks; > + > + io_resrc = &fp_q->host_resrc; > + > + /* Return tasks that aren't "Used by FW" to the pool */ > + list_for_each_entry_safe(qedn_task, task_tmp, > + &conn_ctx->active_task_list, entry) { > + qedn_clear_task(conn_ctx, qedn_task); > + num_returned_tasks++; > + } > + > + if (num_returned_tasks) { > + spin_lock(&io_resrc->resources_lock); > + /* Return tasks to FP_Q pool in one shot */ > + > + list_splice_tail_init(&conn_ctx->active_task_list, > + &io_resrc->task_free_list); > + io_resrc->num_free_tasks += num_returned_tasks; > + spin_unlock(&io_resrc->resources_lock); > + } > + > + num_active_tasks = atomic_read(&conn_ctx->num_active_tasks); > + if (num_active_tasks) > + pr_err("num_active_tasks is %u after cleanup.\n", num_active_tasks); > +} > + > +void qedn_return_task_to_pool(struct qedn_conn_ctx *conn_ctx, > + struct qedn_task_ctx *qedn_task) > +{ > + struct qedn_fp_queue *fp_q = conn_ctx->fp_q; > + struct qedn_io_resources *io_resrc; > + unsigned long lock_flags; > + > + io_resrc = &fp_q->host_resrc; > + > + spin_lock_irqsave(&qedn_task->lock, lock_flags); > + qedn_task->valid = 0; > + qedn_task->flags = 0; > + qedn_clear_sgl(conn_ctx->qedn, qedn_task); > + spin_unlock_irqrestore(&qedn_task->lock, lock_flags); > + > + spin_lock(&conn_ctx->task_list_lock); > + list_del(&qedn_task->entry); > + qedn_host_reset_cccid_itid_entry(conn_ctx, qedn_task->cccid); > + spin_unlock(&conn_ctx->task_list_lock); > + > + atomic_dec(&conn_ctx->num_active_tasks); > + atomic_dec(&conn_ctx->num_active_fw_tasks); > + > + spin_lock(&io_resrc->resources_lock); > + list_add_tail(&qedn_task->entry, &io_resrc->task_free_list); > + io_resrc->num_free_tasks += 1; > + spin_unlock(&io_resrc->resources_lock); > +} > + > +struct qedn_task_ctx * > +qedn_get_free_task_from_pool(struct qedn_conn_ctx *conn_ctx, u16 cccid) > +{ > + struct qedn_task_ctx *qedn_task = NULL; > + struct qedn_io_resources *io_resrc; > + struct qedn_fp_queue *fp_q; > + > + fp_q = conn_ctx->fp_q; > + io_resrc = &fp_q->host_resrc; > + > + spin_lock(&io_resrc->resources_lock); > + qedn_task = list_first_entry_or_null(&io_resrc->task_free_list, > + struct qedn_task_ctx, entry); > + if (unlikely(!qedn_task)) { > + spin_unlock(&io_resrc->resources_lock); > + > + return NULL; > + } > + list_del(&qedn_task->entry); > + io_resrc->num_free_tasks -= 1; > + spin_unlock(&io_resrc->resources_lock); > + > + spin_lock(&conn_ctx->task_list_lock); > + list_add_tail(&qedn_task->entry, &conn_ctx->active_task_list); > + qedn_host_set_cccid_itid_entry(conn_ctx, cccid, qedn_task->itid); > + spin_unlock(&conn_ctx->task_list_lock); > + > + atomic_inc(&conn_ctx->num_active_tasks); > + qedn_task->cccid = cccid; > + qedn_task->qedn_conn = conn_ctx; > + qedn_task->valid = 1; > + > + return qedn_task; > +} > + > +struct qedn_task_ctx * > +qedn_get_task_from_pool_insist(struct qedn_conn_ctx *conn_ctx, u16 cccid) > +{ > + struct qedn_task_ctx *qedn_task = NULL; > + unsigned long timeout; > + > + qedn_task = qedn_get_free_task_from_pool(conn_ctx, cccid); > + if (unlikely(!qedn_task)) { > + timeout = msecs_to_jiffies(QEDN_TASK_INSIST_TMO) + jiffies; > + while (1) { > + qedn_task = qedn_get_free_task_from_pool(conn_ctx, cccid); > + if (likely(qedn_task)) > + break; > + > + msleep(100); > + if (time_after(jiffies, timeout)) { > + pr_err("Failed on timeout of fetching task\n"); > + > + return NULL; > + } > + } > + } > + > + return qedn_task; > +} > + > static bool qedn_process_req(struct qedn_conn_ctx *qedn_conn) > { > return true; > Cheers, Hannes -- Dr. Hannes Reinecke Kernel Storage Architect hare@suse.de +49 911 74053 688 SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer 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.9 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,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS, USER_AGENT_SANE_1 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 656D4C433ED for ; Sun, 2 May 2021 11:49:06 +0000 (UTC) Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (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 A572761288 for ; Sun, 2 May 2021 11:49:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A572761288 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-nvme-bounces+linux-nvme=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Type: Content-Transfer-Encoding:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:Date:Message-ID:From: References:Cc:To:Subject:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=vPDQbonjki/Ulum1q8kNn14+DGiEaMFzVxwvLzsfHjA=; b=Zqv/ZtlXh4GmOUi/K+AxlYWiA mX6y9XwsBjM65lyUQHpspAWsOE7A8SkTF56VfJg2hjsFYJFAP9i9EO7/aROBaUFCXfdewVaOrxInD EZSvaeiiIH1n9TS0iqm3QG+oUVNMsRo8ispEf5bwzzC+juW7Cg5Ta2rALWS+o9rvyd8m7faI6KJua /oQyclFOYg3UwoUPv0uQm7VrQdgUpXD093LFdxTUMWeI4LOAEfVTGOtxPXLUfe1/vOa3ktu/FfZJ1 SNQG60wpEgMJLi3pIuv2LssD0J2nRQDrc3almyGWFpKmZOanPqhE7kgPwDptl19vBqq8UbTTAbIY2 A3C6FQHnQ==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1ldAap-00Bhpj-M8; Sun, 02 May 2021 11:48:59 +0000 Received: from bombadil.infradead.org ([2607:7c80:54:e::133]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1ldAam-00BhpQ-00 for linux-nvme@desiato.infradead.org; Sun, 02 May 2021 11:48:57 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: Content-Type:In-Reply-To:MIME-Version:Date:Message-ID:From:References:Cc:To: Subject:Sender:Reply-To:Content-ID:Content-Description; bh=kzCmbKGld5yc6C2I4cG2p4b3BMWUjy4uZggjb0ztRRA=; b=HLBsp1JkrS/UJyHpqImFaIvU/A h6L5ejM8tFsoFLrx0AO7RSLGqIdBUmS9cUwxTUHqEuQ8OtseCsq4N4jOJKH0AQZY30w4c3ukA6BMh k80QiQKjejlqkPIvTB9B12R3pveExwgBPWuwJ3+DnfL7ZTHexlEyMybUlzB9kUwwH+F+G9YrU6UV+ dCBPI6CYiwsoRsBHVSMsJnUT07CvqrFAOduJ/GWevGEZQUIleKppcAnXd+yU/53DXoEXq4MqMiAAx 4EkGMYbVmZY8lIjppd1wvx2tZm6Z/W6OeIQeqg0qMpWtZO/CsVeUDF1vKbRKnbZFbC3/qbo97qE/h EVGojdJw==; Received: from mx2.suse.de ([195.135.220.15]) by bombadil.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1ldAah-002VmP-FO for linux-nvme@lists.infradead.org; Sun, 02 May 2021 11:48:54 +0000 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 0CE55B199; Sun, 2 May 2021 11:48:50 +0000 (UTC) Subject: Re: [RFC PATCH v4 23/27] qedn: Add support of Task and SGL To: Shai Malin , netdev@vger.kernel.org, linux-nvme@lists.infradead.org, sagi@grimberg.me, hch@lst.de, axboe@fb.com, kbusch@kernel.org Cc: "David S . Miller davem @ davemloft . net --cc=Jakub Kicinski" , aelior@marvell.com, mkalderon@marvell.com, okulkarni@marvell.com, pkushwaha@marvell.com, malin1024@gmail.com References: <20210429190926.5086-1-smalin@marvell.com> <20210429190926.5086-24-smalin@marvell.com> From: Hannes Reinecke Message-ID: <3b9b048f-94e3-9bef-6d32-fc683636b649@suse.de> Date: Sun, 2 May 2021 13:48:49 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.8.0 MIME-Version: 1.0 In-Reply-To: <20210429190926.5086-24-smalin@marvell.com> Content-Language: en-US X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210502_044851_853997_DF7780E2 X-CRM114-Status: GOOD ( 39.02 ) X-BeenThere: linux-nvme@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Sender: "Linux-nvme" Errors-To: linux-nvme-bounces+linux-nvme=archiver.kernel.org@lists.infradead.org T24gNC8yOS8yMSA5OjA5IFBNLCBTaGFpIE1hbGluIHdyb3RlOgo+IEZyb206IFByYWJoYWthciBL dXNod2FoYSA8cGt1c2h3YWhhQG1hcnZlbGwuY29tPgo+IAo+IFRoaXMgcGF0Y2ggd2lsbCBhZGQg c3VwcG9ydCBvZiBUYXNrIGFuZCBTR0wgd2hpY2ggaXMgdXNlZAo+IGZvciBzbG93cGF0aCBhbmQg ZmFzdCBwYXRoIElPLiBoZXJlIFRhc2sgaXMgSU8gZ3JhbnVsZSB1c2VkCj4gYnkgZmlybXdhcmUg dG8gcGVyZm9ybSB0YXNrcwo+IAo+IFRoZSBpbnRlcm5hbCBpbXBsZW1lbnRhdGlvbjoKPiAtIENy ZWF0ZSB0YXNrL3NnbCByZXNvdXJjZXMgdXNlZCBieSBhbGwgY29ubmVjdGlvbgo+IC0gUHJvdmlk ZSBBUElzIHRvIGFsbG9jYXRlIGFuZCBmcmVlIHRhc2suCj4gLSBBZGQgdGFzayBzdXBwb3J0IGR1 cmluZyBjb25uZWN0aW9uIGVzdGFibGlzaG1lbnQgaS5lLiBzbG93cGF0aAo+IAo+IEFja2VkLWJ5 OiBJZ29yIFJ1c3NraWtoIDxpcnVzc2tpa2hAbWFydmVsbC5jb20+Cj4gU2lnbmVkLW9mZi1ieTog UHJhYmhha2FyIEt1c2h3YWhhIDxwa3VzaHdhaGFAbWFydmVsbC5jb20+Cj4gU2lnbmVkLW9mZi1i eTogT21rYXIgS3Vsa2FybmkgPG9rdWxrYXJuaUBtYXJ2ZWxsLmNvbT4KPiBTaWduZWQtb2ZmLWJ5 OiBNaWNoYWwgS2FsZGVyb24gPG1rYWxkZXJvbkBtYXJ2ZWxsLmNvbT4KPiBTaWduZWQtb2ZmLWJ5 OiBBcmllbCBFbGlvciA8YWVsaW9yQG1hcnZlbGwuY29tPgo+IFNpZ25lZC1vZmYtYnk6IFNoYWkg TWFsaW4gPHNtYWxpbkBtYXJ2ZWxsLmNvbT4KPiAtLS0KPiAgIGRyaXZlcnMvbnZtZS9ody9xZWRu L3FlZG4uaCAgICAgIHwgIDY2ICsrKysrCj4gICBkcml2ZXJzL252bWUvaHcvcWVkbi9xZWRuX2Nv bm4uYyB8ICA0MyArKystCj4gICBkcml2ZXJzL252bWUvaHcvcWVkbi9xZWRuX21haW4uYyB8ICAz NCArKy0KPiAgIGRyaXZlcnMvbnZtZS9ody9xZWRuL3FlZG5fdGFzay5jIHwgNDExICsrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysKPiAgIDQgZmlsZXMgY2hhbmdlZCwgNTUwIGluc2VydGlv bnMoKyksIDQgZGVsZXRpb25zKC0pCj4gCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbnZtZS9ody9x ZWRuL3FlZG4uaCBiL2RyaXZlcnMvbnZtZS9ody9xZWRuL3FlZG4uaAo+IGluZGV4IGJkOWEyNTBj YjJmNS4uODgwY2EyNDViMDJjIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvbnZtZS9ody9xZWRuL3Fl ZG4uaAo+ICsrKyBiL2RyaXZlcnMvbnZtZS9ody9xZWRuL3FlZG4uaAo+IEBAIC01MCw2ICs1MCwy MSBAQAo+ICAgI2RlZmluZSBRRUROX0ZXX0NRX0ZQX1dRX1dPUktRVUVVRSAicWVkbl9md19jcV9m cF93cSIKPiAgICNkZWZpbmUgUUVETl9OVk1FX1JFUV9GUF9XUV9XT1JLUVVFVUUgInFlZG5fbnZt ZV9yZXFfZnBfd3EiCj4gICAKPiArLyogUHJvdG9jb2wgZGVmaW5lcyAqLwo+ICsjZGVmaW5lIFFF RE5fTUFYX0lPX1NJWkUgUUVEX05WTUVUQ1BfTUFYX0lPX1NJWkUKPiArCj4gKyNkZWZpbmUgUUVE Tl9TR0VfQlVGRl9TSVpFIDQwOTYKPiArI2RlZmluZSBRRUROX01BWF9TR0VTX1BFUl9UQVNLIERJ Vl9ST1VORF9VUChRRUROX01BWF9JT19TSVpFLCBRRUROX1NHRV9CVUZGX1NJWkUpCj4gKyNkZWZp bmUgUUVETl9GV19TR0VfU0laRSBzaXplb2Yoc3RydWN0IG52bWV0Y3Bfc2dlKQo+ICsjZGVmaW5l IFFFRE5fTUFYX0ZXX1NHTF9TSVpFICgoUUVETl9NQVhfU0dFU19QRVJfVEFTSykgKiBRRUROX0ZX X1NHRV9TSVpFKQo+ICsjZGVmaW5lIFFFRE5fRldfU0xPV19JT19NSU5fU0dFX0xJTUlUICg5NzAw IC8gNikKPiArCj4gKyNkZWZpbmUgUUVETl9NQVhfSFdfU0VDVE9SUyAoUUVETl9NQVhfSU9fU0la RSAvIDUxMikKPiArI2RlZmluZSBRRUROX01BWF9TRUdNRU5UUyBRRUROX01BWF9TR0VTX1BFUl9U QVNLCj4gKwo+ICsjZGVmaW5lIFFFRE5fVEFTS19JTlNJU1RfVE1PIDEwMDAgLyogMSBzZWMgKi8K PiArI2RlZmluZSBRRUROX0lOVkFMSURfSVRJRCAweEZGRkYKPiArCj4gICAvKgo+ICAgICogVENQ IG9mZmxvYWQgc3RhY2sgZGVmYXVsdCBjb25maWd1cmF0aW9ucyBhbmQgZGVmaW5lcy4KPiAgICAq IEZ1dHVyZSBlbmhhbmNlbWVudHMgd2lsbCBhbGxvdyBjb250cm9sbGluZyB0aGUgY29uZmlndXJh YmxlCj4gQEAgLTk1LDYgKzExMCwxNSBAQCBlbnVtIHFlZG5fc3RhdGUgewo+ICAgCVFFRE5fU1RB VEVfTU9EVUxFX1JFTU9WRV9PTkdPSU5HLAo+ICAgfTsKPiAgIAo+ICtzdHJ1Y3QgcWVkbl9pb19y ZXNvdXJjZXMgewo+ICsJLyogTG9jayBmb3IgSU8gcmVzb3VyY2VzICovCj4gKwlzcGlubG9ja190 IHJlc291cmNlc19sb2NrOwo+ICsJc3RydWN0IGxpc3RfaGVhZCB0YXNrX2ZyZWVfbGlzdDsKPiAr CXUzMiBudW1fYWxsb2NfdGFza3M7Cj4gKwl1MzIgbnVtX2ZyZWVfdGFza3M7Cj4gKwl1MzIgbm9f YXZhaWxfcmVzcmNfY250Owo+ICt9Owo+ICsKPiAgIC8qIFBlciBDUFUgY29yZSBwYXJhbXMgKi8K PiAgIHN0cnVjdCBxZWRuX2ZwX3F1ZXVlIHsKPiAgIAlzdHJ1Y3QgcWVkX2NoYWluIGNxX2NoYWlu Owo+IEBAIC0xMDQsNiArMTI4LDEwIEBAIHN0cnVjdCBxZWRuX2ZwX3F1ZXVlIHsKPiAgIAlzdHJ1 Y3QgcWVkX3NiX2luZm8gKnNiX2luZm87Cj4gICAJdW5zaWduZWQgaW50IGNwdTsKPiAgIAlzdHJ1 Y3Qgd29ya19zdHJ1Y3QgZndfY3FfZnBfd3FfZW50cnk7Cj4gKwo+ICsJLyogSU8gcmVsYXRlZCBy ZXNvdXJjZXMgZm9yIGhvc3QgKi8KPiArCXN0cnVjdCBxZWRuX2lvX3Jlc291cmNlcyBob3N0X3Jl c3JjOwo+ICsKPiAgIAl1MTYgc2JfaWQ7Cj4gICAJY2hhciBpcnFuYW1lW1FFRE5fSVJRX05BTUVf TEVOXTsKPiAgIH07Cj4gQEAgLTEzMCw2ICsxNTgsOCBAQCBzdHJ1Y3QgcWVkbl9jdHggewo+ICAg CS8qIENvbm5lY3Rpb25zICovCj4gICAJREVDTEFSRV9IQVNIVEFCTEUoY29ubl9jdHhfaGFzaCwg MTYpOwo+ICAgCj4gKwl1MzIgbnVtX3Rhc2tzX3Blcl9wb29sOwo+ICsKPiAgIAkvKiBGYXN0IHBh dGggcXVldWVzICovCj4gICAJdTggbnVtX2Z3X2NxczsKPiAgIAlzdHJ1Y3QgcWVkbl9mcF9xdWV1 ZSAqZnBfcV9hcnI7Cj4gQEAgLTEzNyw2ICsxNjcsMjcgQEAgc3RydWN0IHFlZG5fY3R4IHsKPiAg IAlkbWFfYWRkcl90IGZ3X2NxX2FycmF5X3BoeTsgLyogUGh5c2ljYWwgYWRkcmVzcyBvZiBmd19j cV9hcnJheV92aXJ0ICovCj4gICAJc3RydWN0IHdvcmtxdWV1ZV9zdHJ1Y3QgKm52bWVfcmVxX2Zw X3dxOwo+ICAgCXN0cnVjdCB3b3JrcXVldWVfc3RydWN0ICpmd19jcV9mcF93cTsKPiArCj4gKwkv KiBGYXN0IFBhdGggVGFza3MgKi8KPiArCXN0cnVjdCBxZWRfbnZtZXRjcF90aWQJdGFza3M7Cj4g K307Cj4gKwo+ICtzdHJ1Y3QgcWVkbl90YXNrX2N0eCB7Cj4gKwlzdHJ1Y3QgcWVkbl9jb25uX2N0 eCAqcWVkbl9jb25uOwo+ICsJc3RydWN0IHFlZG5fY3R4ICpxZWRuOwo+ICsJdm9pZCAqZndfdGFz a19jdHg7Cj4gKwlzdHJ1Y3QgcWVkbl9mcF9xdWV1ZSAqZnBfcTsKPiArCXN0cnVjdCBzY2F0dGVy bGlzdCAqbnZtZV9zZzsKPiArCXN0cnVjdCBudm1lX3RjcF9vZmxkX3JlcSAqcmVxOyAvKiBjdXJy ZW50bHkgcHJvY2Nlc3NlZCByZXF1ZXN0ICovCj4gKwlzdHJ1Y3QgbGlzdF9oZWFkIGVudHJ5Owo+ ICsJc3BpbmxvY2tfdCBsb2NrOyAvKiBUbyBwcm90ZWN0IHRhc2sgcmVzb3VyY2VzICovCj4gKwli b29sIHZhbGlkOwo+ICsJdW5zaWduZWQgbG9uZyBmbGFnczsgLyogVXNlZCBieSBxZWRuX3Rhc2tf ZmxhZ3MgKi8KPiArCXUzMiB0YXNrX3NpemU7Cj4gKwl1MTYgaXRpZDsKPiArCXUxNiBjY2NpZDsK PiArCWludCByZXFfZGlyZWN0aW9uOwo+ICsJc3RydWN0IHN0b3JhZ2Vfc2dsX3Rhc2tfcGFyYW1z IHNnbF90YXNrX3BhcmFtczsKPiAgIH07Cj4gICAKPiAgIHN0cnVjdCBxZWRuX2VuZHBvaW50IHsK PiBAQCAtMjQzLDYgKzI5NCw3IEBAIHN0cnVjdCBxZWRuX2Nvbm5fY3R4IHsKPiAgIAlzdHJ1Y3Qg bnZtZV90Y3Bfb2ZsZF9jdHJsICpjdHJsOwo+ICAgCXUzMiBjb25uX2hhbmRsZTsKPiAgIAl1MzIg ZndfY2lkOwo+ICsJdTggZGVmYXVsdF9jcTsKPiAgIAo+ICAgCWF0b21pY190IGVzdF9jb25uX2lu ZGljYXRvcjsKPiAgIAlhdG9taWNfdCBkZXN0cm95X2Nvbm5faW5kaWNhdG9yOwo+IEBAIC0yNjAs NiArMzEyLDExIEBAIHN0cnVjdCBxZWRuX2Nvbm5fY3R4IHsKPiAgIAlkbWFfYWRkcl90IGhvc3Rf Y2NjaWRfaXRpZF9waHlfYWRkcjsKPiAgIAlzdHJ1Y3QgcWVkbl9lbmRwb2ludCBlcDsKPiAgIAlp bnQgYWJydF9mbGFnOwo+ICsJLyogU3BpbmxvY2sgZm9yIGFjY2Vzc2luZyBhY3RpdmVfdGFza19s aXN0ICovCj4gKwlzcGlubG9ja190IHRhc2tfbGlzdF9sb2NrOwo+ICsJc3RydWN0IGxpc3RfaGVh ZCBhY3RpdmVfdGFza19saXN0Owo+ICsJYXRvbWljX3QgbnVtX2FjdGl2ZV90YXNrczsKPiArCWF0 b21pY190IG51bV9hY3RpdmVfZndfdGFza3M7Cj4gICAKPiAgIAkvKiBDb25uZWN0aW9uIHJlc291 cmNlcyAtIHR1cm5lZCBvbiB0byBpbmRpY2F0ZSB3aGF0IHJlc291cmNlIHdhcwo+ICAgCSAqIGFs bG9jYXRlZCwgdG8gdGhhdCBpdCBjYW4gbGF0ZXIgYmUgcmVsZWFzZWQuCj4gQEAgLTI3OSw2ICsz MzYsNyBAQCBzdHJ1Y3QgcWVkbl9jb25uX2N0eCB7Cj4gICBlbnVtIHFlZG5fY29ubl9yZXNvdXJj ZXNfc3RhdGUgewo+ICAgCVFFRE5fQ09OTl9SRVNSQ19GV19TUSwKPiAgIAlRRUROX0NPTk5fUkVT UkNfQUNRVUlSRV9DT05OLAo+ICsJUUVETl9DT05OX1JFU1JDX1RBU0tTLAo+ICAgCVFFRE5fQ09O Tl9SRVNSQ19DQ0NJRF9JVElEX01BUCwKPiAgIAlRRUROX0NPTk5fUkVTUkNfVENQX1BPUlQsCj4g ICAJUUVETl9DT05OX1JFU1JDX01BWCA9IDY0Cj4gQEAgLTMwOSw1ICszNjcsMTMgQEAgaW5saW5l IGludCBxZWRuX3ZhbGlkYXRlX2NjY2lkX2luX3JhbmdlKHN0cnVjdCBxZWRuX2Nvbm5fY3R4ICpj b25uX2N0eCwgdTE2IGNjY2kKPiAgIHZvaWQgcWVkbl9xdWV1ZV9yZXF1ZXN0KHN0cnVjdCBxZWRu X2Nvbm5fY3R4ICpxZWRuX2Nvbm4sIHN0cnVjdCBudm1lX3RjcF9vZmxkX3JlcSAqcmVxKTsKPiAg IHZvaWQgcWVkbl9udm1lX3JlcV9mcF93cV9oYW5kbGVyKHN0cnVjdCB3b3JrX3N0cnVjdCAqd29y ayk7Cj4gICB2b2lkIHFlZG5faW9fd29ya19jcShzdHJ1Y3QgcWVkbl9jdHggKnFlZG4sIHN0cnVj dCBudm1ldGNwX2Z3X2NxZSAqY3FlKTsKPiAraW50IHFlZG5fYWxsb2NfdGFza3Moc3RydWN0IHFl ZG5fY29ubl9jdHggKmNvbm5fY3R4KTsKPiAraW5saW5lIGludCBxZWRuX3FpZChzdHJ1Y3QgbnZt ZV90Y3Bfb2ZsZF9xdWV1ZSAqcXVldWUpOwo+ICtzdHJ1Y3QgcWVkbl90YXNrX2N0eCAqCj4gKwlx ZWRuX2dldF90YXNrX2Zyb21fcG9vbF9pbnNpc3Qoc3RydWN0IHFlZG5fY29ubl9jdHggKmNvbm5f Y3R4LCB1MTYgY2NjaWQpOwo+ICt2b2lkIHFlZG5fY29tbW9uX2NsZWFyX2Z3X3NnbChzdHJ1Y3Qg c3RvcmFnZV9zZ2xfdGFza19wYXJhbXMgKnNnbF90YXNrX3BhcmFtcyk7Cj4gK3ZvaWQgcWVkbl9y ZXR1cm5fYWN0aXZlX3Rhc2tzKHN0cnVjdCBxZWRuX2Nvbm5fY3R4ICpjb25uX2N0eCk7Cj4gK3Zv aWQgcWVkbl9kZXN0cm95X2ZyZWVfdGFza3Moc3RydWN0IHFlZG5fZnBfcXVldWUgKmZwX3EsCj4g KwkJCSAgICAgc3RydWN0IHFlZG5faW9fcmVzb3VyY2VzICppb19yZXNyYyk7Cj4gICAKPiAgICNl bmRpZiAvKiBfUUVETl9IXyAqLwo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL252bWUvaHcvcWVkbi9x ZWRuX2Nvbm4uYyBiL2RyaXZlcnMvbnZtZS9ody9xZWRuL3FlZG5fY29ubi5jCj4gaW5kZXggOTBk OGFhMzZkMjE5Li4xMGE4MGZiZWFjNDMgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy9udm1lL2h3L3Fl ZG4vcWVkbl9jb25uLmMKPiArKysgYi9kcml2ZXJzL252bWUvaHcvcWVkbi9xZWRuX2Nvbm4uYwo+ IEBAIC0yOSw2ICsyOSwxMSBAQCBzdGF0aWMgY29uc3QgY2hhciAqIGNvbnN0IHFlZG5fY29ubl9z dGF0ZV9zdHJbXSA9IHsKPiAgIAlOVUxMCj4gICB9Owo+ICAgCj4gK2lubGluZSBpbnQgcWVkbl9x aWQoc3RydWN0IG52bWVfdGNwX29mbGRfcXVldWUgKnF1ZXVlKQo+ICt7Cj4gKwlyZXR1cm4gcXVl dWUgLSBxdWV1ZS0+Y3RybC0+cXVldWVzOwo+ICt9Cj4gKwo+ICAgaW50IHFlZG5fc2V0X2Nvbl9z dGF0ZShzdHJ1Y3QgcWVkbl9jb25uX2N0eCAqY29ubl9jdHgsIGVudW0gcWVkbl9jb25uX3N0YXRl IG5ld19zdGF0ZSkKPiAgIHsKPiAgIAlzcGluX2xvY2tfYmgoJmNvbm5fY3R4LT5jb25uX3N0YXRl X2xvY2spOwo+IEBAIC0xNDYsNiArMTUxLDExIEBAIHN0YXRpYyB2b2lkIHFlZG5fcmVsZWFzZV9j b25uX2N0eChzdHJ1Y3QgcWVkbl9jb25uX2N0eCAqY29ubl9jdHgpCj4gICAJCWNsZWFyX2JpdChR RUROX0NPTk5fUkVTUkNfQUNRVUlSRV9DT05OLCAmY29ubl9jdHgtPnJlc3JjX3N0YXRlKTsKPiAg IAl9Cj4gICAKPiArCWlmICh0ZXN0X2JpdChRRUROX0NPTk5fUkVTUkNfVEFTS1MsICZjb25uX2N0 eC0+cmVzcmNfc3RhdGUpKSB7Cj4gKwkJY2xlYXJfYml0KFFFRE5fQ09OTl9SRVNSQ19UQVNLUywg JmNvbm5fY3R4LT5yZXNyY19zdGF0ZSk7Cj4gKwkJCXFlZG5fcmV0dXJuX2FjdGl2ZV90YXNrcyhj b25uX2N0eCk7Cj4gKwl9Cj4gKwo+ICAgCWlmICh0ZXN0X2JpdChRRUROX0NPTk5fUkVTUkNfQ0ND SURfSVRJRF9NQVAsICZjb25uX2N0eC0+cmVzcmNfc3RhdGUpKSB7Cj4gICAJCWRtYV9mcmVlX2Nv aGVyZW50KCZxZWRuLT5wZGV2LT5kZXYsCj4gICAJCQkJICBjb25uX2N0eC0+c3FfZGVwdGggKgo+ IEBAIC0yNDcsNiArMjU3LDcgQEAgc3RhdGljIGludCBxZWRuX252bWV0Y3Bfb2ZmbG9hZF9jb25u KHN0cnVjdCBxZWRuX2Nvbm5fY3R4ICpjb25uX2N0eCkKPiAgIAlvZmZsZF9wcm1zLm1heF9ydF90 aW1lID0gUUVETl9UQ1BfTUFYX1JUX1RJTUU7Cj4gICAJb2ZmbGRfcHJtcy5zcV9wYmxfYWRkciA9 Cj4gICAJCSh1NjQpcWVkX2NoYWluX2dldF9wYmxfcGh5cygmcWVkbl9lcC0+Zndfc3FfY2hhaW4p Owo+ICsJb2ZmbGRfcHJtcy5kZWZhdWx0X2NxID0gY29ubl9jdHgtPmRlZmF1bHRfY3E7Cj4gICAK PiAgIAlyYyA9IHFlZF9vcHMtPm9mZmxvYWRfY29ubihxZWRuLT5jZGV2LAo+ICAgCQkJCSAgIGNv bm5fY3R4LT5jb25uX2hhbmRsZSwKPiBAQCAtMzc1LDYgKzM4Niw5IEBAIGludCBxZWRuX2V2ZW50 X2NiKHZvaWQgKmNvbnRleHQsIHU4IGZ3X2V2ZW50X2NvZGUsIHZvaWQgKmV2ZW50X3JpbmdfZGF0 YSkKPiAgIHN0YXRpYyBpbnQgcWVkbl9wcmVwX2FuZF9vZmZsb2FkX3F1ZXVlKHN0cnVjdCBxZWRu X2Nvbm5fY3R4ICpjb25uX2N0eCkKPiAgIHsKPiAgIAlzdHJ1Y3QgcWVkbl9jdHggKnFlZG4gPSBj b25uX2N0eC0+cWVkbjsKPiArCXN0cnVjdCBxZWRuX2lvX3Jlc291cmNlcyAqaW9fcmVzcmM7Cj4g KwlzdHJ1Y3QgcWVkbl9mcF9xdWV1ZSAqZnBfcTsKPiArCXU4IGRlZmF1bHRfY3FfaWR4LCBxaWQ7 Cj4gICAJc2l6ZV90IGRtYV9zaXplOwo+ICAgCWludCByYzsKPiAgIAo+IEBAIC0zODcsNiArNDAx LDggQEAgc3RhdGljIGludCBxZWRuX3ByZXBfYW5kX29mZmxvYWRfcXVldWUoc3RydWN0IHFlZG5f Y29ubl9jdHggKmNvbm5fY3R4KQo+ICAgCXNldF9iaXQoUUVETl9DT05OX1JFU1JDX0ZXX1NRLCAm Y29ubl9jdHgtPnJlc3JjX3N0YXRlKTsKPiAgIAlJTklUX0xJU1RfSEVBRCgmY29ubl9jdHgtPmhv c3RfcGVuZF9yZXFfbGlzdCk7Cj4gICAJc3Bpbl9sb2NrX2luaXQoJmNvbm5fY3R4LT5udm1lX3Jl cV9sb2NrKTsKPiArCWF0b21pY19zZXQoJmNvbm5fY3R4LT5udW1fYWN0aXZlX3Rhc2tzLCAwKTsK PiArCWF0b21pY19zZXQoJmNvbm5fY3R4LT5udW1fYWN0aXZlX2Z3X3Rhc2tzLCAwKTsKPiAgIAo+ ICAgCXJjID0gcWVkX29wcy0+YWNxdWlyZV9jb25uKHFlZG4tPmNkZXYsCj4gICAJCQkJICAgJmNv bm5fY3R4LT5jb25uX2hhbmRsZSwKPiBAQCAtNDAxLDcgKzQxNywzMiBAQCBzdGF0aWMgaW50IHFl ZG5fcHJlcF9hbmRfb2ZmbG9hZF9xdWV1ZShzdHJ1Y3QgcWVkbl9jb25uX2N0eCAqY29ubl9jdHgp Cj4gICAJCSBjb25uX2N0eC0+Y29ubl9oYW5kbGUpOwo+ICAgCXNldF9iaXQoUUVETl9DT05OX1JF U1JDX0FDUVVJUkVfQ09OTiwgJmNvbm5fY3R4LT5yZXNyY19zdGF0ZSk7Cj4gICAKPiAtCS8qIFBs YWNlaG9sZGVyIC0gQWxsb2NhdGUgdGFzayByZXNvdXJjZXMgYW5kIGluaXRpYWxpemUgZmllbGRz ICovCj4gKwlxaWQgPSBxZWRuX3FpZChjb25uX2N0eC0+cXVldWUpOwo+ICsJZGVmYXVsdF9jcV9p ZHggPSBxaWQgPyBxaWQgLSAxIDogMDsgLyogT2Zmc2V0IGFkbWlucSAqLwo+ICsKPiArCWNvbm5f Y3R4LT5kZWZhdWx0X2NxID0gKGRlZmF1bHRfY3FfaWR4ICUgcWVkbi0+bnVtX2Z3X2Nxcyk7Cj4g KwlmcF9xID0gJnFlZG4tPmZwX3FfYXJyW2Nvbm5fY3R4LT5kZWZhdWx0X2NxXTsKPiArCWNvbm5f Y3R4LT5mcF9xID0gZnBfcTsKPiArCWlvX3Jlc3JjID0gJmZwX3EtPmhvc3RfcmVzcmM7Cj4gKwo+ ICsJLyogVGhlIGZpcnN0IGNvbm5lY3Rpb24gb24gZWFjaCBmcF9xIHdpbGwgZmlsbCB0YXNrCj4g KwkgKiByZXNvdXJjZXMKPiArCSAqLwo+ICsJc3Bpbl9sb2NrKCZpb19yZXNyYy0+cmVzb3VyY2Vz X2xvY2spOwo+ICsJaWYgKGlvX3Jlc3JjLT5udW1fYWxsb2NfdGFza3MgPT0gMCkgewo+ICsJCXJj ID0gcWVkbl9hbGxvY190YXNrcyhjb25uX2N0eCk7Cj4gKwkJaWYgKHJjKSB7Cj4gKwkJCXByX2Vy cigiRmFpbGVkIGFsbG9jYXRpbmcgdGFza3M6IENJRD0weCV4XG4iLAo+ICsJCQkgICAgICAgY29u bl9jdHgtPmZ3X2NpZCk7Cj4gKwkJCXNwaW5fdW5sb2NrKCZpb19yZXNyYy0+cmVzb3VyY2VzX2xv Y2spOwo+ICsJCQlnb3RvIHJlbF9jb25uOwo+ICsJCX0KPiArCX0KPiArCXNwaW5fdW5sb2NrKCZp b19yZXNyYy0+cmVzb3VyY2VzX2xvY2spOwo+ICsKPiArCXNwaW5fbG9ja19pbml0KCZjb25uX2N0 eC0+dGFza19saXN0X2xvY2spOwo+ICsJSU5JVF9MSVNUX0hFQUQoJmNvbm5fY3R4LT5hY3RpdmVf dGFza19saXN0KTsKPiArCXNldF9iaXQoUUVETl9DT05OX1JFU1JDX1RBU0tTLCAmY29ubl9jdHgt PnJlc3JjX3N0YXRlKTsKPiAgICA+ICAgCXJjID0gcWVkbl9mZXRjaF90Y3BfcG9ydChjb25uX2N0 eCk7Cj4gICAJaWYgKHJjKQo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL252bWUvaHcvcWVkbi9xZWRu X21haW4uYyBiL2RyaXZlcnMvbnZtZS9ody9xZWRuL3FlZG5fbWFpbi5jCj4gaW5kZXggMzhmMjNk YmIwM2E1Li44ZDljMTlkNjM0ODAgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy9udm1lL2h3L3FlZG4v cWVkbl9tYWluLmMKPiArKysgYi9kcml2ZXJzL252bWUvaHcvcWVkbi9xZWRuX21haW4uYwo+IEBA IC0zMCw2ICszMCwxMiBAQCBfX2JlMTYgcWVkbl9nZXRfaW5fcG9ydChzdHJ1Y3Qgc29ja2FkZHJf c3RvcmFnZSAqc2EpCj4gICAJCTogKChzdHJ1Y3Qgc29ja2FkZHJfaW42ICopc2EpLT5zaW42X3Bv cnQ7Cj4gICB9Cj4gICAKPiArc3RhdGljIHZvaWQgcWVkbl9pbml0X2lvX3Jlc2Moc3RydWN0IHFl ZG5faW9fcmVzb3VyY2VzICppb19yZXNyYykKPiArewo+ICsJc3Bpbl9sb2NrX2luaXQoJmlvX3Jl c3JjLT5yZXNvdXJjZXNfbG9jayk7Cj4gKwlJTklUX0xJU1RfSEVBRCgmaW9fcmVzcmMtPnRhc2tf ZnJlZV9saXN0KTsKPiArfQo+ICsKPiAgIHN0cnVjdCBxZWRuX2xsaF9maWx0ZXIgKnFlZG5fYWRk X2xsaF9maWx0ZXIoc3RydWN0IHFlZG5fY3R4ICpxZWRuLCB1MTYgdGNwX3BvcnQpCj4gICB7Cj4g ICAJc3RydWN0IHFlZG5fbGxoX2ZpbHRlciAqbGxoX2ZpbHRlciA9IE5VTEw7Cj4gQEAgLTQzNiw2 ICs0NDIsOCBAQCBzdGF0aWMgc3RydWN0IG52bWVfdGNwX29mbGRfb3BzIHFlZG5fb2ZsZF9vcHMg PSB7Cj4gICAJCSAqCU5WTUZfT1BUX0hEUl9ESUdFU1QgfCBOVk1GX09QVF9EQVRBX0RJR0VTVCB8 Cj4gICAJCSAqCU5WTUZfT1BUX05SX1BPTExfUVVFVUVTIHwgTlZNRl9PUFRfVE9TCj4gICAJCSAq Lwo+ICsJLm1heF9od19zZWN0b3JzID0gUUVETl9NQVhfSFdfU0VDVE9SUywKPiArCS5tYXhfc2Vn bWVudHMgPSBRRUROX01BWF9TRUdNRU5UUywKPiAgIAkuY2xhaW1fZGV2ID0gcWVkbl9jbGFpbV9k ZXYsCj4gICAJLnNldHVwX2N0cmwgPSBxZWRuX3NldHVwX2N0cmwsCj4gICAJLnJlbGVhc2VfY3Ry bCA9IHFlZG5fcmVsZWFzZV9jdHJsLAo+IEBAIC02NTcsOCArNjY1LDI0IEBAIHN0YXRpYyB2b2lk IHFlZG5fcmVtb3ZlX3BmX2Zyb21fZ2xfbGlzdChzdHJ1Y3QgcWVkbl9jdHggKnFlZG4pCj4gICAJ bXV0ZXhfdW5sb2NrKCZxZWRuX2dsYi5nbGJfbXV0ZXgpOwo+ICAgfQo+ICAgCj4gK3N0YXRpYyB2 b2lkIHFlZG5fY2FsbF9kZXN0cm95X2ZyZWVfdGFza3Moc3RydWN0IHFlZG5fZnBfcXVldWUgKmZw X3EsCj4gKwkJCQkJIHN0cnVjdCBxZWRuX2lvX3Jlc291cmNlcyAqaW9fcmVzcmMpCj4gK3sKPiAr CWlmIChsaXN0X2VtcHR5KCZpb19yZXNyYy0+dGFza19mcmVlX2xpc3QpKQo+ICsJCXJldHVybjsK PiArCj4gKwlpZiAoaW9fcmVzcmMtPm51bV9hbGxvY190YXNrcyAhPSBpb19yZXNyYy0+bnVtX2Zy ZWVfdGFza3MpCj4gKwkJcHJfZXJyKCJUYXNrIFBvb2w6Tm90IGFsbCByZXR1cm5lZCBhbGxvY2F0 ZWQ9MHgleCwgZnJlZT0weCV4XG4iLAo+ICsJCSAgICAgICBpb19yZXNyYy0+bnVtX2FsbG9jX3Rh c2tzLCBpb19yZXNyYy0+bnVtX2ZyZWVfdGFza3MpOwo+ICsKPiArCXFlZG5fZGVzdHJveV9mcmVl X3Rhc2tzKGZwX3EsIGlvX3Jlc3JjKTsKPiArCWlmIChpb19yZXNyYy0+bnVtX2ZyZWVfdGFza3Mp Cj4gKwkJcHJfZXJyKCJFeHBlY3RlZCBudW1fZnJlZV90YXNrcyB0byBiZSAwXG4iKTsKPiArfQo+ ICsKPiAgIHN0YXRpYyB2b2lkIHFlZG5fZnJlZV9mdW5jdGlvbl9xdWV1ZXMoc3RydWN0IHFlZG5f Y3R4ICpxZWRuKQo+ICAgewo+ICsJc3RydWN0IHFlZG5faW9fcmVzb3VyY2VzICpob3N0X3Jlc3Jj Owo+ICAgCXN0cnVjdCBxZWRfc2JfaW5mbyAqc2JfaW5mbyA9IE5VTEw7Cj4gICAJc3RydWN0IHFl ZG5fZnBfcXVldWUgKmZwX3E7Cj4gICAJaW50IGk7Cj4gQEAgLTY3Myw2ICs2OTcsOSBAQCBzdGF0 aWMgdm9pZCBxZWRuX2ZyZWVfZnVuY3Rpb25fcXVldWVzKHN0cnVjdCBxZWRuX2N0eCAqcWVkbikK PiAgIAkvKiBGcmVlIHRoZSBmYXN0IHBhdGggcXVldWVzKi8KPiAgIAlmb3IgKGkgPSAwOyBpIDwg cWVkbi0+bnVtX2Z3X2NxczsgaSsrKSB7Cj4gICAJCWZwX3EgPSAmcWVkbi0+ZnBfcV9hcnJbaV07 Cj4gKwkJaG9zdF9yZXNyYyA9ICZmcF9xLT5ob3N0X3Jlc3JjOwo+ICsKPiArCQlxZWRuX2NhbGxf ZGVzdHJveV9mcmVlX3Rhc2tzKGZwX3EsIGhvc3RfcmVzcmMpOwo+ICAgCj4gICAJCS8qIEZyZWUg U0IgKi8KPiAgIAkJc2JfaW5mbyA9IGZwX3EtPnNiX2luZm87Cj4gQEAgLTc2OSw3ICs3OTYsOCBA QCBzdGF0aWMgaW50IHFlZG5fYWxsb2NfZnVuY3Rpb25fcXVldWVzKHN0cnVjdCBxZWRuX2N0eCAq cWVkbikKPiAgIAkJZ290byBtZW1fYWxsb2NfZmFpbHVyZTsKPiAgIAl9Cj4gICAKPiAtCS8qIHBs YWNlaG9sZGVyIC0gY3JlYXRlIHRhc2sgcG9vbHMgKi8KPiArCXFlZG4tPm51bV90YXNrc19wZXJf cG9vbCA9Cj4gKwkJcWVkbi0+cGZfcGFyYW1zLm52bWV0Y3BfcGZfcGFyYW1zLm51bV90YXNrcyAv IHFlZG4tPm51bV9md19jcXM7Cj4gICAKPiAgIAlmb3IgKGkgPSAwOyBpIDwgcWVkbi0+bnVtX2Z3 X2NxczsgaSsrKSB7Cj4gICAJCWZwX3EgPSAmcWVkbi0+ZnBfcV9hcnJbaV07Cj4gQEAgLTgxMSw3 ICs4MzksNyBAQCBzdGF0aWMgaW50IHFlZG5fYWxsb2NfZnVuY3Rpb25fcXVldWVzKHN0cnVjdCBx ZWRuX2N0eCAqcWVkbikKPiAgIAkJZnBfcS0+cWVkbiA9IHFlZG47Cj4gICAJCUlOSVRfV09SSygm ZnBfcS0+ZndfY3FfZnBfd3FfZW50cnksIHFlZG5fZndfY3FfZnFfd3FfaGFuZGxlcik7Cj4gICAK PiAtCQkvKiBQbGFjZWhvbGRlciAtIEluaXQgSU8tcGF0aCByZXNvdXJjZXMgKi8KPiArCQlxZWRu X2luaXRfaW9fcmVzYygmZnBfcS0+aG9zdF9yZXNyYyk7Cj4gICAJfQo+ICAgCj4gICAJcmV0dXJu IDA7Cj4gQEAgLTEwMDUsNyArMTAzMyw3IEBAIHN0YXRpYyBpbnQgX19xZWRuX3Byb2JlKHN0cnVj dCBwY2lfZGV2ICpwZGV2KQo+ICAgCj4gICAJLyogTlZNZVRDUCBzdGFydCBIVyBQRiAqLwo+ICAg CXJjID0gcWVkX29wcy0+c3RhcnQocWVkbi0+Y2RldiwKPiAtCQkJICAgIE5VTEwgLyogUGxhY2Vo b2xkZXIgZm9yIEZXIElPLXBhdGggcmVzb3VyY2VzICovLAo+ICsJCQkgICAgJnFlZG4tPnRhc2tz LAo+ICAgCQkJICAgIHFlZG4sCj4gICAJCQkgICAgcWVkbl9ldmVudF9jYik7Cj4gICAJaWYgKHJj KSB7Cj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbnZtZS9ody9xZWRuL3FlZG5fdGFzay5jIGIvZHJp dmVycy9udm1lL2h3L3FlZG4vcWVkbl90YXNrLmMKPiBpbmRleCBkMzQ3NDE4OGVmZGMuLjU0ZjJm NGNiYTZlYSAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL252bWUvaHcvcWVkbi9xZWRuX3Rhc2suYwo+ ICsrKyBiL2RyaXZlcnMvbnZtZS9ody9xZWRuL3FlZG5fdGFzay5jCj4gQEAgLTExLDYgKzExLDI2 MyBAQAo+ICAgLyogRHJpdmVyIGluY2x1ZGVzICovCj4gICAjaW5jbHVkZSAicWVkbi5oIgo+ICAg Cj4gK3N0YXRpYyBib29sIHFlZG5fc2dsX2hhc19zbWFsbF9taWRfc2dlKHN0cnVjdCBudm1ldGNw X3NnZSAqc2dsLCB1MTYgc2dlX2NvdW50KQo+ICt7Cj4gKwl1MTYgc2dlX251bTsKPiArCj4gKwlp ZiAoc2dlX2NvdW50ID4gOCkgewo+ICsJCWZvciAoc2dlX251bSA9IDA7IHNnZV9udW0gPCBzZ2Vf Y291bnQ7IHNnZV9udW0rKykgewo+ICsJCQlpZiAobGUzMl90b19jcHUoc2dsW3NnZV9udW1dLnNn ZV9sZW4pIDwKPiArCQkJICAgIFFFRE5fRldfU0xPV19JT19NSU5fU0dFX0xJTUlUKQo+ICsJCQkJ cmV0dXJuIHRydWU7IC8qIHNtYWxsIG1pZGRsZSBTR0UgZm91bmQgKi8KPiArCQl9Cj4gKwl9Cj4g Kwo+ICsJcmV0dXJuIGZhbHNlOyAvKiBubyBzbWFsbCBtaWRkbGUgU0dFcyAqLwo+ICt9Cj4gKwo+ ICtzdGF0aWMgaW50IHFlZG5faW5pdF9zZ2woc3RydWN0IHFlZG5fY3R4ICpxZWRuLCBzdHJ1Y3Qg cWVkbl90YXNrX2N0eCAqcWVkbl90YXNrKQo+ICt7Cj4gKwlzdHJ1Y3Qgc3RvcmFnZV9zZ2xfdGFz a19wYXJhbXMgKnNnbF90YXNrX3BhcmFtczsKPiArCWVudW0gZG1hX2RhdGFfZGlyZWN0aW9uIGRt YV9kaXI7Cj4gKwlzdHJ1Y3Qgc2NhdHRlcmxpc3QgKnNnOwo+ICsJc3RydWN0IHJlcXVlc3QgKnJx Owo+ICsJdTE2IG51bV9zZ2VzOwo+ICsJaW50IGluZGV4Owo+ICsJaW50IHJjOwo+ICsKPiArCXNn bF90YXNrX3BhcmFtcyA9ICZxZWRuX3Rhc2stPnNnbF90YXNrX3BhcmFtczsKPiArCXJxID0gYmxr X21xX3JxX2Zyb21fcGR1KHFlZG5fdGFzay0+cmVxKTsKPiArCWlmIChxZWRuX3Rhc2stPnRhc2tf c2l6ZSA9PSAwKSB7Cj4gKwkJc2dsX3Rhc2tfcGFyYW1zLT5udW1fc2dlcyA9IDA7Cj4gKwo+ICsJ CXJldHVybiAwOwo+ICsJfQo+ICsKPiArCS8qIENvbnZlcnQgQklPIHRvIHNjYXR0ZXJsaXN0ICov Cj4gKwludW1fc2dlcyA9IGJsa19ycV9tYXBfc2cocnEtPnEsIHJxLCBxZWRuX3Rhc2stPm52bWVf c2cpOwo+ICsJaWYgKHFlZG5fdGFzay0+cmVxX2RpcmVjdGlvbiA9PSBXUklURSkKPiArCQlkbWFf ZGlyID0gRE1BX1RPX0RFVklDRTsKPiArCWVsc2UKPiArCQlkbWFfZGlyID0gRE1BX0ZST01fREVW SUNFOwo+ICsKPiArCS8qIERNQSBtYXAgdGhlIHNjYXR0ZXJsaXN0ICovCj4gKwlpZiAoZG1hX21h cF9zZygmcWVkbi0+cGRldi0+ZGV2LCBxZWRuX3Rhc2stPm52bWVfc2csIG51bV9zZ2VzLCBkbWFf ZGlyKSAhPSBudW1fc2dlcykgewo+ICsJCXByX2VycigiQ291bGRuJ3QgbWFwIHNnbFxuIik7Cj4g KwkJcmMgPSAtRVBFUk07Cj4gKwo+ICsJCXJldHVybiByYzsKPiArCX0KPiArCj4gKwlzZ2xfdGFz a19wYXJhbXMtPnRvdGFsX2J1ZmZlcl9zaXplID0gcWVkbl90YXNrLT50YXNrX3NpemU7Cj4gKwlz Z2xfdGFza19wYXJhbXMtPm51bV9zZ2VzID0gbnVtX3NnZXM7Cj4gKwo+ICsJZm9yX2VhY2hfc2co cWVkbl90YXNrLT5udm1lX3NnLCBzZywgbnVtX3NnZXMsIGluZGV4KSB7Cj4gKwkJRE1BX1JFR1BB SVJfTEUoc2dsX3Rhc2tfcGFyYW1zLT5zZ2xbaW5kZXhdLnNnZV9hZGRyLCBzZ19kbWFfYWRkcmVz cyhzZykpOwo+ICsJCXNnbF90YXNrX3BhcmFtcy0+c2dsW2luZGV4XS5zZ2VfbGVuID0gY3B1X3Rv X2xlMzIoc2dfZG1hX2xlbihzZykpOwo+ICsJfQo+ICsKPiArCS8qIFJlbGV2YW50IGZvciBIb3N0 IFdyaXRlIE9ubHkgKi8KPiArCXNnbF90YXNrX3BhcmFtcy0+c21hbGxfbWlkX3NnZSA9IChxZWRu X3Rhc2stPnJlcV9kaXJlY3Rpb24gPT0gUkVBRCkgPwo+ICsJCWZhbHNlIDoKPiArCQlxZWRuX3Nn bF9oYXNfc21hbGxfbWlkX3NnZShzZ2xfdGFza19wYXJhbXMtPnNnbCwKPiArCQkJCQkgICBzZ2xf dGFza19wYXJhbXMtPm51bV9zZ2VzKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3Rh dGljIHZvaWQgcWVkbl9mcmVlX252bWVfc2coc3RydWN0IHFlZG5fdGFza19jdHggKnFlZG5fdGFz aykKPiArewo+ICsJa2ZyZWUocWVkbl90YXNrLT5udm1lX3NnKTsKPiArCXFlZG5fdGFzay0+bnZt ZV9zZyA9IE5VTEw7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHFlZG5fZnJlZV9md19zZ2woc3Ry dWN0IHFlZG5fdGFza19jdHggKnFlZG5fdGFzaykKPiArewo+ICsJc3RydWN0IHFlZG5fY3R4ICpx ZWRuID0gcWVkbl90YXNrLT5xZWRuOwo+ICsJZG1hX2FkZHJfdCBzZ2xfcGE7Cj4gKwo+ICsJc2ds X3BhID0gSElMT19ETUFfUkVHUEFJUihxZWRuX3Rhc2stPnNnbF90YXNrX3BhcmFtcy5zZ2xfcGh5 c19hZGRyKTsKPiArCWRtYV9mcmVlX2NvaGVyZW50KCZxZWRuLT5wZGV2LT5kZXYsCj4gKwkJCSAg UUVETl9NQVhfRldfU0dMX1NJWkUsCj4gKwkJCSAgcWVkbl90YXNrLT5zZ2xfdGFza19wYXJhbXMu c2dsLAo+ICsJCQkgIHNnbF9wYSk7Cj4gKwlxZWRuX3Rhc2stPnNnbF90YXNrX3BhcmFtcy5zZ2wg PSBOVUxMOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBxZWRuX2Rlc3Ryb3lfc2luZ2xlX3Rhc2so c3RydWN0IHFlZG5fdGFza19jdHggKnFlZG5fdGFzaykKPiArewo+ICsJdTE2IGl0aWQ7Cj4gKwo+ ICsJaXRpZCA9IHFlZG5fdGFzay0+aXRpZDsKPiArCWxpc3RfZGVsKCZxZWRuX3Rhc2stPmVudHJ5 KTsKPiArCXFlZG5fZnJlZV9udm1lX3NnKHFlZG5fdGFzayk7Cj4gKwlxZWRuX2ZyZWVfZndfc2ds KHFlZG5fdGFzayk7Cj4gKwlrZnJlZShxZWRuX3Rhc2spOwo+ICsJcWVkbl90YXNrID0gTlVMTDsK PiArfQo+ICsKPiArdm9pZCBxZWRuX2Rlc3Ryb3lfZnJlZV90YXNrcyhzdHJ1Y3QgcWVkbl9mcF9x dWV1ZSAqZnBfcSwKPiArCQkJICAgICBzdHJ1Y3QgcWVkbl9pb19yZXNvdXJjZXMgKmlvX3Jlc3Jj KQo+ICt7Cj4gKwlzdHJ1Y3QgcWVkbl90YXNrX2N0eCAqcWVkbl90YXNrLCAqdGFza190bXA7Cj4g Kwo+ICsJLyogRGVzdHJveSB0YXNrcyBmcm9tIHRoZSBmcmVlIHRhc2sgbGlzdCAqLwo+ICsJbGlz dF9mb3JfZWFjaF9lbnRyeV9zYWZlKHFlZG5fdGFzaywgdGFza190bXAsCj4gKwkJCQkgJmlvX3Jl c3JjLT50YXNrX2ZyZWVfbGlzdCwgZW50cnkpIHsKPiArCQlxZWRuX2Rlc3Ryb3lfc2luZ2xlX3Rh c2socWVkbl90YXNrKTsKPiArCQlpb19yZXNyYy0+bnVtX2ZyZWVfdGFza3MgLT0gMTsKPiArCX0K PiArfQo+ICsKPiArc3RhdGljIGludCBxZWRuX2FsbG9jX252bWVfc2coc3RydWN0IHFlZG5fdGFz a19jdHggKnFlZG5fdGFzaykKPiArewo+ICsJaW50IHJjOwo+ICsKPiArCXFlZG5fdGFzay0+bnZt ZV9zZyA9IGtjYWxsb2MoUUVETl9NQVhfU0dFU19QRVJfVEFTSywKPiArCQkJCSAgICAgc2l6ZW9m KCpxZWRuX3Rhc2stPm52bWVfc2cpLCBHRlBfS0VSTkVMKTsKPiArCWlmICghcWVkbl90YXNrLT5u dm1lX3NnKSB7Cj4gKwkJcmMgPSAtRU5PTUVNOwo+ICsKPiArCQlyZXR1cm4gcmM7Cj4gKwl9Cj4g Kwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgcWVkbl9hbGxvY19md19zZ2wo c3RydWN0IHFlZG5fdGFza19jdHggKnFlZG5fdGFzaykKPiArewo+ICsJc3RydWN0IHFlZG5fY3R4 ICpxZWRuID0gcWVkbl90YXNrLT5xZWRuX2Nvbm4tPnFlZG47Cj4gKwlkbWFfYWRkcl90IGZ3X3Nn bF9waHlzOwo+ICsKPiArCXFlZG5fdGFzay0+c2dsX3Rhc2tfcGFyYW1zLnNnbCA9Cj4gKwkJZG1h X2FsbG9jX2NvaGVyZW50KCZxZWRuLT5wZGV2LT5kZXYsIFFFRE5fTUFYX0ZXX1NHTF9TSVpFLAo+ ICsJCQkJICAgJmZ3X3NnbF9waHlzLCBHRlBfS0VSTkVMKTsKPiArCWlmICghcWVkbl90YXNrLT5z Z2xfdGFza19wYXJhbXMuc2dsKSB7Cj4gKwkJcHJfZXJyKCJDb3VsZG4ndCBhbGxvY2F0ZSBGVyBz Z2xcbiIpOwo+ICsKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCX0KPiArCj4gKwlETUFfUkVHUEFJ Ul9MRShxZWRuX3Rhc2stPnNnbF90YXNrX3BhcmFtcy5zZ2xfcGh5c19hZGRyLCBmd19zZ2xfcGh5 cyk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxpbmUgdm9pZCAqcWVk bl9nZXRfZndfdGFzayhzdHJ1Y3QgcWVkX252bWV0Y3BfdGlkICppbmZvLCB1MTYgaXRpZCkKPiAr ewo+ICsJcmV0dXJuICh2b2lkICopKGluZm8tPmJsb2Nrc1tpdGlkIC8gaW5mby0+bnVtX3RpZHNf cGVyX2Jsb2NrXSArCj4gKwkJCShpdGlkICUgaW5mby0+bnVtX3RpZHNfcGVyX2Jsb2NrKSAqIGlu Zm8tPnNpemUpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IHFlZG5fdGFza19jdHggKnFlZG5f YWxsb2NfdGFzayhzdHJ1Y3QgcWVkbl9jb25uX2N0eCAqY29ubl9jdHgsIHUxNiBpdGlkKQo+ICt7 Cj4gKwlzdHJ1Y3QgcWVkbl9jdHggKnFlZG4gPSBjb25uX2N0eC0+cWVkbjsKPiArCXN0cnVjdCBx ZWRuX3Rhc2tfY3R4ICpxZWRuX3Rhc2s7Cj4gKwl2b2lkICpmd190YXNrX2N0eDsKPiArCWludCBy YyA9IDA7Cj4gKwo+ICsJcWVkbl90YXNrID0ga3phbGxvYyhzaXplb2YoKnFlZG5fdGFzayksIEdG UF9LRVJORUwpOwo+ICsJaWYgKCFxZWRuX3Rhc2spCj4gKwkJcmV0dXJuIE5VTEw7Cj4gKwoKQXMg dGhpcyBpcyBhIHBvb2wsIHdoeSBkb24ndCB5b3UgdXNlIG1lbXBvb2xzIGhlcmU/Cgo+ICsJc3Bp bl9sb2NrX2luaXQoJnFlZG5fdGFzay0+bG9jayk7Cj4gKwlmd190YXNrX2N0eCA9IHFlZG5fZ2V0 X2Z3X3Rhc2soJnFlZG4tPnRhc2tzLCBpdGlkKTsKPiArCWlmICghZndfdGFza19jdHgpIHsKPiAr CQlwcl9lcnIoImlUSUQ6IDB4JXg7IEZhaWxlZCBnZXR0aW5nIGZ3X3Rhc2tfY3R4IG1lbW9yeVxu IiwgaXRpZCk7Cj4gKwkJZ290byByZWxlYXNlX3Rhc2s7Cj4gKwl9Cj4gKwo+ICsJLyogTm8gbmVl ZCB0byBtZW1zZXQgZndfdGFza19jdHggLSBpdHMgZG9uZSBpbiB0aGUgSFNJIGZ1bmMgKi8KPiAr CXFlZG5fdGFzay0+cWVkbl9jb25uID0gY29ubl9jdHg7Cj4gKwlxZWRuX3Rhc2stPnFlZG4gPSBx ZWRuOwo+ICsJcWVkbl90YXNrLT5md190YXNrX2N0eCA9IGZ3X3Rhc2tfY3R4Owo+ICsJcWVkbl90 YXNrLT52YWxpZCA9IDA7Cj4gKwlxZWRuX3Rhc2stPmZsYWdzID0gMDsKPiArCXFlZG5fdGFzay0+ aXRpZCA9IGl0aWQ7Cj4gKwlyYyA9IHFlZG5fYWxsb2NfZndfc2dsKHFlZG5fdGFzayk7Cj4gKwlp ZiAocmMpIHsKPiArCQlwcl9lcnIoImlUSUQ6IDB4JXg7IEZhaWxlZCBhbGxvY2F0aW5nIEZXIHNn bFxuIiwgaXRpZCk7Cj4gKwkJZ290byByZWxlYXNlX3Rhc2s7Cj4gKwl9Cj4gKwo+ICsJcmMgPSBx ZWRuX2FsbG9jX252bWVfc2cocWVkbl90YXNrKTsKPiArCWlmIChyYykgewo+ICsJCXByX2Vycigi aVRJRDogMHgleDsgRmFpbGVkIGFsbG9jYXRpbmcgRlcgc2dsXG4iLCBpdGlkKTsKPiArCQlnb3Rv IHJlbGVhc2VfZndfc2dsOwo+ICsJfQo+ICsKPiArCXJldHVybiBxZWRuX3Rhc2s7Cj4gKwo+ICty ZWxlYXNlX2Z3X3NnbDoKPiArCXFlZG5fZnJlZV9md19zZ2wocWVkbl90YXNrKTsKPiArcmVsZWFz ZV90YXNrOgo+ICsJa2ZyZWUocWVkbl90YXNrKTsKPiArCj4gKwlyZXR1cm4gTlVMTDsKPiArfQo+ ICsKPiAraW50IHFlZG5fYWxsb2NfdGFza3Moc3RydWN0IHFlZG5fY29ubl9jdHggKmNvbm5fY3R4 KQo+ICt7Cj4gKwlzdHJ1Y3QgcWVkbl9jdHggKnFlZG4gPSBjb25uX2N0eC0+cWVkbjsKPiArCXN0 cnVjdCBxZWRuX3Rhc2tfY3R4ICpxZWRuX3Rhc2sgPSBOVUxMOwo+ICsJc3RydWN0IHFlZG5faW9f cmVzb3VyY2VzICppb19yZXNyYzsKPiArCXUxNiBpdGlkLCBzdGFydF9pdGlkLCBvZmZzZXQ7Cj4g KwlzdHJ1Y3QgcWVkbl9mcF9xdWV1ZSAqZnBfcTsKPiArCWludCBpLCByYzsKPiArCj4gKwlmcF9x ID0gY29ubl9jdHgtPmZwX3E7Cj4gKwo+ICsJb2Zmc2V0ID0gZnBfcS0+c2JfaWQ7Cj4gKwlpb19y ZXNyYyA9ICZmcF9xLT5ob3N0X3Jlc3JjOwo+ICsKPiArCXN0YXJ0X2l0aWQgPSBxZWRuLT5udW1f dGFza3NfcGVyX3Bvb2wgKiBvZmZzZXQ7Cj4gKwlmb3IgKGkgPSAwOyBpIDwgcWVkbi0+bnVtX3Rh c2tzX3Blcl9wb29sOyArK2kpIHsKPiArCQlpdGlkID0gc3RhcnRfaXRpZCArIGk7Cj4gKwkJcWVk bl90YXNrID0gcWVkbl9hbGxvY190YXNrKGNvbm5fY3R4LCBpdGlkKTsKPiArCQlpZiAoIXFlZG5f dGFzaykgewo+ICsJCQlwcl9lcnIoIkZhaWxlZCBhbGxvY2F0aW5nIHRhc2tcbiIpOwo+ICsJCQly YyA9IC1FTk9NRU07Cj4gKwkJCWdvdG8gcmVsZWFzZV90YXNrczsKPiArCQl9Cj4gKwo+ICsJCXFl ZG5fdGFzay0+ZnBfcSA9IGZwX3E7Cj4gKwkJaW9fcmVzcmMtPm51bV9mcmVlX3Rhc2tzICs9IDE7 Cj4gKwkJbGlzdF9hZGRfdGFpbCgmcWVkbl90YXNrLT5lbnRyeSwgJmlvX3Jlc3JjLT50YXNrX2Zy ZWVfbGlzdCk7Cj4gKwl9Cj4gKwo+ICsJaW9fcmVzcmMtPm51bV9hbGxvY190YXNrcyA9IGlvX3Jl c3JjLT5udW1fZnJlZV90YXNrczsKPiArCj4gKwlyZXR1cm4gMDsKPiArCj4gK3JlbGVhc2VfdGFz a3M6Cj4gKwlxZWRuX2Rlc3Ryb3lfZnJlZV90YXNrcyhmcF9xLCBpb19yZXNyYyk7Cj4gKwo+ICsJ cmV0dXJuIHJjOwo+ICt9Cj4gKwo+ICt2b2lkIHFlZG5fY29tbW9uX2NsZWFyX2Z3X3NnbChzdHJ1 Y3Qgc3RvcmFnZV9zZ2xfdGFza19wYXJhbXMgKnNnbF90YXNrX3BhcmFtcykKPiArewo+ICsJdTE2 IHNnZV9jbnQgPSBzZ2xfdGFza19wYXJhbXMtPm51bV9zZ2VzOwo+ICsKPiArCW1lbXNldCgmc2ds X3Rhc2tfcGFyYW1zLT5zZ2xbKHNnZV9jbnQgLSAxKV0sIDAsCj4gKwkgICAgICAgc2l6ZW9mKHN0 cnVjdCBudm1ldGNwX3NnZSkpOwo+ICsJc2dsX3Rhc2tfcGFyYW1zLT50b3RhbF9idWZmZXJfc2l6 ZSA9IDA7Cj4gKwlzZ2xfdGFza19wYXJhbXMtPnNtYWxsX21pZF9zZ2UgPSBmYWxzZTsKPiArCXNn bF90YXNrX3BhcmFtcy0+bnVtX3NnZXMgPSAwOwo+ICt9Cj4gKwo+ICtpbmxpbmUgdm9pZCBxZWRu X2hvc3RfcmVzZXRfY2NjaWRfaXRpZF9lbnRyeShzdHJ1Y3QgcWVkbl9jb25uX2N0eCAqY29ubl9j dHgsCj4gKwkJCQkJICAgICB1MTYgY2NjaWQpCj4gK3sKPiArCWNvbm5fY3R4LT5ob3N0X2NjY2lk X2l0aWRbY2NjaWRdLml0aWQgPSBjcHVfdG9fbGUxNihRRUROX0lOVkFMSURfSVRJRCk7Cj4gK30K PiArCj4gK2lubGluZSB2b2lkIHFlZG5faG9zdF9zZXRfY2NjaWRfaXRpZF9lbnRyeShzdHJ1Y3Qg cWVkbl9jb25uX2N0eCAqY29ubl9jdHgsIHUxNiBjY2NpZCwgdTE2IGl0aWQpCj4gK3sKPiArCWNv bm5fY3R4LT5ob3N0X2NjY2lkX2l0aWRbY2NjaWRdLml0aWQgPSBjcHVfdG9fbGUxNihpdGlkKTsK PiArfQo+ICsKPiAgIGlubGluZSBpbnQgcWVkbl92YWxpZGF0ZV9jY2NpZF9pbl9yYW5nZShzdHJ1 Y3QgcWVkbl9jb25uX2N0eCAqY29ubl9jdHgsIHUxNiBjY2NpZCkKPiAgIHsKPiAgIAlpbnQgcmMg PSAwOwo+IEBAIC0yMyw2ICsyODAsMTYwIEBAIGlubGluZSBpbnQgcWVkbl92YWxpZGF0ZV9jY2Np ZF9pbl9yYW5nZShzdHJ1Y3QgcWVkbl9jb25uX2N0eCAqY29ubl9jdHgsIHUxNiBjY2NpCj4gICAJ cmV0dXJuIHJjOwo+ICAgfQo+ICAgCj4gK3N0YXRpYyB2b2lkIHFlZG5fY2xlYXJfc2dsKHN0cnVj dCBxZWRuX2N0eCAqcWVkbiwKPiArCQkJICAgc3RydWN0IHFlZG5fdGFza19jdHggKnFlZG5fdGFz aykKPiArewo+ICsJc3RydWN0IHN0b3JhZ2Vfc2dsX3Rhc2tfcGFyYW1zICpzZ2xfdGFza19wYXJh bXM7Cj4gKwllbnVtIGRtYV9kYXRhX2RpcmVjdGlvbiBkbWFfZGlyOwo+ICsJdTMyIHNnZV9jbnQ7 Cj4gKwo+ICsJc2dsX3Rhc2tfcGFyYW1zID0gJnFlZG5fdGFzay0+c2dsX3Rhc2tfcGFyYW1zOwo+ ICsJc2dlX2NudCA9IHNnbF90YXNrX3BhcmFtcy0+bnVtX3NnZXM7Cj4gKwo+ICsJLyogTm90aGlu ZyB0byBkbyBpZiBubyBTR0VzIHdlcmUgdXNlZCAqLwo+ICsJaWYgKCFxZWRuX3Rhc2stPnRhc2tf c2l6ZSB8fCAhc2dlX2NudCkKPiArCQlyZXR1cm47Cj4gKwo+ICsJZG1hX2RpciA9IChxZWRuX3Rh c2stPnJlcV9kaXJlY3Rpb24gPT0gV1JJVEUgPyBETUFfVE9fREVWSUNFIDogRE1BX0ZST01fREVW SUNFKTsKPiArCWRtYV91bm1hcF9zZygmcWVkbi0+cGRldi0+ZGV2LCBxZWRuX3Rhc2stPm52bWVf c2csIHNnZV9jbnQsIGRtYV9kaXIpOwo+ICsJbWVtc2V0KCZxZWRuX3Rhc2stPm52bWVfc2dbKHNn ZV9jbnQgLSAxKV0sIDAsIHNpemVvZihzdHJ1Y3Qgc2NhdHRlcmxpc3QpKTsKPiArCXFlZG5fY29t bW9uX2NsZWFyX2Z3X3NnbChzZ2xfdGFza19wYXJhbXMpOwo+ICsJcWVkbl90YXNrLT50YXNrX3Np emUgPSAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBxZWRuX2NsZWFyX3Rhc2soc3RydWN0IHFl ZG5fY29ubl9jdHggKmNvbm5fY3R4LAo+ICsJCQkgICAgc3RydWN0IHFlZG5fdGFza19jdHggKnFl ZG5fdGFzaykKPiArewo+ICsJLyogVGFzayBsb2NrIGlzbid0IG5lZWRlZCBzaW5jZSBpdCBpcyBu byBsb25nZXIgaW4gdXNlICovCj4gKwlxZWRuX2NsZWFyX3NnbChjb25uX2N0eC0+cWVkbiwgcWVk bl90YXNrKTsKPiArCXFlZG5fdGFzay0+dmFsaWQgPSAwOwo+ICsJcWVkbl90YXNrLT5mbGFncyA9 IDA7Cj4gKwo+ICsJYXRvbWljX2RlYygmY29ubl9jdHgtPm51bV9hY3RpdmVfdGFza3MpOwo+ICt9 Cj4gKwo+ICt2b2lkIHFlZG5fcmV0dXJuX2FjdGl2ZV90YXNrcyhzdHJ1Y3QgcWVkbl9jb25uX2N0 eCAqY29ubl9jdHgpCj4gK3sKPiArCXN0cnVjdCBxZWRuX2ZwX3F1ZXVlICpmcF9xID0gY29ubl9j dHgtPmZwX3E7Cj4gKwlzdHJ1Y3QgcWVkbl90YXNrX2N0eCAqcWVkbl90YXNrLCAqdGFza190bXA7 Cj4gKwlzdHJ1Y3QgcWVkbl9pb19yZXNvdXJjZXMgKmlvX3Jlc3JjOwo+ICsJaW50IG51bV9yZXR1 cm5lZF90YXNrcyA9IDA7Cj4gKwlpbnQgbnVtX2FjdGl2ZV90YXNrczsKPiArCj4gKwlpb19yZXNy YyA9ICZmcF9xLT5ob3N0X3Jlc3JjOwo+ICsKPiArCS8qIFJldHVybiB0YXNrcyB0aGF0IGFyZW4n dCAiVXNlZCBieSBGVyIgdG8gdGhlIHBvb2wgKi8KPiArCWxpc3RfZm9yX2VhY2hfZW50cnlfc2Fm ZShxZWRuX3Rhc2ssIHRhc2tfdG1wLAo+ICsJCQkJICZjb25uX2N0eC0+YWN0aXZlX3Rhc2tfbGlz dCwgZW50cnkpIHsKPiArCQlxZWRuX2NsZWFyX3Rhc2soY29ubl9jdHgsIHFlZG5fdGFzayk7Cj4g KwkJbnVtX3JldHVybmVkX3Rhc2tzKys7Cj4gKwl9Cj4gKwo+ICsJaWYgKG51bV9yZXR1cm5lZF90 YXNrcykgewo+ICsJCXNwaW5fbG9jaygmaW9fcmVzcmMtPnJlc291cmNlc19sb2NrKTsKPiArCQkv KiBSZXR1cm4gdGFza3MgdG8gRlBfUSBwb29sIGluIG9uZSBzaG90ICovCj4gKwo+ICsJCWxpc3Rf c3BsaWNlX3RhaWxfaW5pdCgmY29ubl9jdHgtPmFjdGl2ZV90YXNrX2xpc3QsCj4gKwkJCQkgICAg ICAmaW9fcmVzcmMtPnRhc2tfZnJlZV9saXN0KTsKPiArCQlpb19yZXNyYy0+bnVtX2ZyZWVfdGFz a3MgKz0gbnVtX3JldHVybmVkX3Rhc2tzOwo+ICsJCXNwaW5fdW5sb2NrKCZpb19yZXNyYy0+cmVz b3VyY2VzX2xvY2spOwo+ICsJfQo+ICsKPiArCW51bV9hY3RpdmVfdGFza3MgPSBhdG9taWNfcmVh ZCgmY29ubl9jdHgtPm51bV9hY3RpdmVfdGFza3MpOwo+ICsJaWYgKG51bV9hY3RpdmVfdGFza3Mp Cj4gKwkJcHJfZXJyKCJudW1fYWN0aXZlX3Rhc2tzIGlzICV1IGFmdGVyIGNsZWFudXAuXG4iLCBu dW1fYWN0aXZlX3Rhc2tzKTsKPiArfQo+ICsKPiArdm9pZCBxZWRuX3JldHVybl90YXNrX3RvX3Bv b2woc3RydWN0IHFlZG5fY29ubl9jdHggKmNvbm5fY3R4LAo+ICsJCQkgICAgICBzdHJ1Y3QgcWVk bl90YXNrX2N0eCAqcWVkbl90YXNrKQo+ICt7Cj4gKwlzdHJ1Y3QgcWVkbl9mcF9xdWV1ZSAqZnBf cSA9IGNvbm5fY3R4LT5mcF9xOwo+ICsJc3RydWN0IHFlZG5faW9fcmVzb3VyY2VzICppb19yZXNy YzsKPiArCXVuc2lnbmVkIGxvbmcgbG9ja19mbGFnczsKPiArCj4gKwlpb19yZXNyYyA9ICZmcF9x LT5ob3N0X3Jlc3JjOwo+ICsKPiArCXNwaW5fbG9ja19pcnFzYXZlKCZxZWRuX3Rhc2stPmxvY2ss IGxvY2tfZmxhZ3MpOwo+ICsJcWVkbl90YXNrLT52YWxpZCA9IDA7Cj4gKwlxZWRuX3Rhc2stPmZs YWdzID0gMDsKPiArCXFlZG5fY2xlYXJfc2dsKGNvbm5fY3R4LT5xZWRuLCBxZWRuX3Rhc2spOwo+ ICsJc3Bpbl91bmxvY2tfaXJxcmVzdG9yZSgmcWVkbl90YXNrLT5sb2NrLCBsb2NrX2ZsYWdzKTsK PiArCj4gKwlzcGluX2xvY2soJmNvbm5fY3R4LT50YXNrX2xpc3RfbG9jayk7Cj4gKwlsaXN0X2Rl bCgmcWVkbl90YXNrLT5lbnRyeSk7Cj4gKwlxZWRuX2hvc3RfcmVzZXRfY2NjaWRfaXRpZF9lbnRy eShjb25uX2N0eCwgcWVkbl90YXNrLT5jY2NpZCk7Cj4gKwlzcGluX3VubG9jaygmY29ubl9jdHgt PnRhc2tfbGlzdF9sb2NrKTsKPiArCj4gKwlhdG9taWNfZGVjKCZjb25uX2N0eC0+bnVtX2FjdGl2 ZV90YXNrcyk7Cj4gKwlhdG9taWNfZGVjKCZjb25uX2N0eC0+bnVtX2FjdGl2ZV9md190YXNrcyk7 Cj4gKwo+ICsJc3Bpbl9sb2NrKCZpb19yZXNyYy0+cmVzb3VyY2VzX2xvY2spOwo+ICsJbGlzdF9h ZGRfdGFpbCgmcWVkbl90YXNrLT5lbnRyeSwgJmlvX3Jlc3JjLT50YXNrX2ZyZWVfbGlzdCk7Cj4g Kwlpb19yZXNyYy0+bnVtX2ZyZWVfdGFza3MgKz0gMTsKPiArCXNwaW5fdW5sb2NrKCZpb19yZXNy Yy0+cmVzb3VyY2VzX2xvY2spOwo+ICt9Cj4gKwo+ICtzdHJ1Y3QgcWVkbl90YXNrX2N0eCAqCj4g K3FlZG5fZ2V0X2ZyZWVfdGFza19mcm9tX3Bvb2woc3RydWN0IHFlZG5fY29ubl9jdHggKmNvbm5f Y3R4LCB1MTYgY2NjaWQpCj4gK3sKPiArCXN0cnVjdCBxZWRuX3Rhc2tfY3R4ICpxZWRuX3Rhc2sg PSBOVUxMOwo+ICsJc3RydWN0IHFlZG5faW9fcmVzb3VyY2VzICppb19yZXNyYzsKPiArCXN0cnVj dCBxZWRuX2ZwX3F1ZXVlICpmcF9xOwo+ICsKPiArCWZwX3EgPSBjb25uX2N0eC0+ZnBfcTsKPiAr CWlvX3Jlc3JjID0gJmZwX3EtPmhvc3RfcmVzcmM7Cj4gKwo+ICsJc3Bpbl9sb2NrKCZpb19yZXNy Yy0+cmVzb3VyY2VzX2xvY2spOwo+ICsJcWVkbl90YXNrID0gbGlzdF9maXJzdF9lbnRyeV9vcl9u dWxsKCZpb19yZXNyYy0+dGFza19mcmVlX2xpc3QsCj4gKwkJCQkJICAgICBzdHJ1Y3QgcWVkbl90 YXNrX2N0eCwgZW50cnkpOwo+ICsJaWYgKHVubGlrZWx5KCFxZWRuX3Rhc2spKSB7Cj4gKwkJc3Bp bl91bmxvY2soJmlvX3Jlc3JjLT5yZXNvdXJjZXNfbG9jayk7Cj4gKwo+ICsJCXJldHVybiBOVUxM Owo+ICsJfQo+ICsJbGlzdF9kZWwoJnFlZG5fdGFzay0+ZW50cnkpOwo+ICsJaW9fcmVzcmMtPm51 bV9mcmVlX3Rhc2tzIC09IDE7Cj4gKwlzcGluX3VubG9jaygmaW9fcmVzcmMtPnJlc291cmNlc19s b2NrKTsKPiArCj4gKwlzcGluX2xvY2soJmNvbm5fY3R4LT50YXNrX2xpc3RfbG9jayk7Cj4gKwls aXN0X2FkZF90YWlsKCZxZWRuX3Rhc2stPmVudHJ5LCAmY29ubl9jdHgtPmFjdGl2ZV90YXNrX2xp c3QpOwo+ICsJcWVkbl9ob3N0X3NldF9jY2NpZF9pdGlkX2VudHJ5KGNvbm5fY3R4LCBjY2NpZCwg cWVkbl90YXNrLT5pdGlkKTsKPiArCXNwaW5fdW5sb2NrKCZjb25uX2N0eC0+dGFza19saXN0X2xv Y2spOwo+ICsKPiArCWF0b21pY19pbmMoJmNvbm5fY3R4LT5udW1fYWN0aXZlX3Rhc2tzKTsKPiAr CXFlZG5fdGFzay0+Y2NjaWQgPSBjY2NpZDsKPiArCXFlZG5fdGFzay0+cWVkbl9jb25uID0gY29u bl9jdHg7Cj4gKwlxZWRuX3Rhc2stPnZhbGlkID0gMTsKPiArCj4gKwlyZXR1cm4gcWVkbl90YXNr Owo+ICt9Cj4gKwo+ICtzdHJ1Y3QgcWVkbl90YXNrX2N0eCAqCj4gK3FlZG5fZ2V0X3Rhc2tfZnJv bV9wb29sX2luc2lzdChzdHJ1Y3QgcWVkbl9jb25uX2N0eCAqY29ubl9jdHgsIHUxNiBjY2NpZCkK PiArewo+ICsJc3RydWN0IHFlZG5fdGFza19jdHggKnFlZG5fdGFzayA9IE5VTEw7Cj4gKwl1bnNp Z25lZCBsb25nIHRpbWVvdXQ7Cj4gKwo+ICsJcWVkbl90YXNrID0gcWVkbl9nZXRfZnJlZV90YXNr X2Zyb21fcG9vbChjb25uX2N0eCwgY2NjaWQpOwo+ICsJaWYgKHVubGlrZWx5KCFxZWRuX3Rhc2sp KSB7Cj4gKwkJdGltZW91dCA9IG1zZWNzX3RvX2ppZmZpZXMoUUVETl9UQVNLX0lOU0lTVF9UTU8p ICsgamlmZmllczsKPiArCQl3aGlsZSAoMSkgewo+ICsJCQlxZWRuX3Rhc2sgPSBxZWRuX2dldF9m cmVlX3Rhc2tfZnJvbV9wb29sKGNvbm5fY3R4LCBjY2NpZCk7Cj4gKwkJCWlmIChsaWtlbHkocWVk bl90YXNrKSkKPiArCQkJCWJyZWFrOwo+ICsKPiArCQkJbXNsZWVwKDEwMCk7Cj4gKwkJCWlmICh0 aW1lX2FmdGVyKGppZmZpZXMsIHRpbWVvdXQpKSB7Cj4gKwkJCQlwcl9lcnIoIkZhaWxlZCBvbiB0 aW1lb3V0IG9mIGZldGNoaW5nIHRhc2tcbiIpOwo+ICsKPiArCQkJCXJldHVybiBOVUxMOwo+ICsJ CQl9Cj4gKwkJfQo+ICsJfQo+ICsKPiArCXJldHVybiBxZWRuX3Rhc2s7Cj4gK30KPiArCj4gICBz dGF0aWMgYm9vbCBxZWRuX3Byb2Nlc3NfcmVxKHN0cnVjdCBxZWRuX2Nvbm5fY3R4ICpxZWRuX2Nv bm4pCj4gICB7Cj4gICAJcmV0dXJuIHRydWU7Cj4gCkNoZWVycywKCkhhbm5lcwotLSAKRHIuIEhh bm5lcyBSZWluZWNrZSAgICAgICAgICAgICAgICBLZXJuZWwgU3RvcmFnZSBBcmNoaXRlY3QKaGFy ZUBzdXNlLmRlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKzQ5IDkxMSA3NDA1MyA2ODgK U1VTRSBTb2Z0d2FyZSBTb2x1dGlvbnMgR21iSCwgTWF4ZmVsZHN0ci4gNSwgOTA0MDkgTsO8cm5i ZXJnCkhSQiAzNjgwOSAoQUcgTsO8cm5iZXJnKSwgR2VzY2jDpGZ0c2bDvGhyZXI6IEZlbGl4IElt ZW5kw7ZyZmZlcgoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X18KTGludXgtbnZtZSBtYWlsaW5nIGxpc3QKTGludXgtbnZtZUBsaXN0cy5pbmZyYWRlYWQub3Jn Cmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtbnZtZQo=