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=-7.1 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED 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 87090C43381 for ; Thu, 21 Mar 2019 20:44:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 36828218A5 for ; Thu, 21 Mar 2019 20:44:26 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ti.com header.i=@ti.com header.b="X8MduItl" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726727AbfCUUoY (ORCPT ); Thu, 21 Mar 2019 16:44:24 -0400 Received: from fllv0016.ext.ti.com ([198.47.19.142]:45004 "EHLO fllv0016.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726506AbfCUUoY (ORCPT ); Thu, 21 Mar 2019 16:44:24 -0400 Received: from lelv0266.itg.ti.com ([10.180.67.225]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id x2LKhxkG064096; Thu, 21 Mar 2019 15:43:59 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1553201039; bh=3jhKq5Z6S9uwczQA0Wh2CAk/AwoJNysn9bZycSOnWWc=; h=Subject:To:CC:References:From:Date:In-Reply-To; b=X8MduItlUFQOeDF38RYPjFskYUFR/Khgtz3gHtPKy44md8Pl47nU8yXnzZ+Fn4tDL 8HtokKGXEye7DzdATje9+hBU6lQHI7ACbrw9a0egjCkIs/o6ZPCunlnBxvB9cnVjsz NJhlF98JH/82VREda0kMturjRYCcPpTO/IftHR0U= Received: from DFLE103.ent.ti.com (dfle103.ent.ti.com [10.64.6.24]) by lelv0266.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x2LKhxTq073822 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 21 Mar 2019 15:43:59 -0500 Received: from DFLE104.ent.ti.com (10.64.6.25) by DFLE103.ent.ti.com (10.64.6.24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5; Thu, 21 Mar 2019 15:43:59 -0500 Received: from dlep33.itg.ti.com (157.170.170.75) by DFLE104.ent.ti.com (10.64.6.25) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1713.5 via Frontend Transport; Thu, 21 Mar 2019 15:43:59 -0500 Received: from [10.250.67.168] (ileax41-snat.itg.ti.com [10.172.224.153]) by dlep33.itg.ti.com (8.14.3/8.13.8) with ESMTP id x2LKhwNJ032526; Thu, 21 Mar 2019 15:43:58 -0500 Subject: Re: [RFC][PATCH 2/5 v2] dma-buf: heaps: Add heap helpers To: John Stultz , lkml CC: Laura Abbott , Benjamin Gaignard , Greg KH , Sumit Semwal , Liam Mark , Brian Starkey , Chenbo Feng , Alistair Strachan , References: <1551819273-640-1-git-send-email-john.stultz@linaro.org> <1551819273-640-3-git-send-email-john.stultz@linaro.org> From: "Andrew F. Davis" Message-ID: <135e2f67-ebb1-da37-a0b0-6bbdd248333a@ti.com> Date: Thu, 21 Mar 2019 15:43:58 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.4.0 MIME-Version: 1.0 In-Reply-To: <1551819273-640-3-git-send-email-john.stultz@linaro.org> Content-Type: text/plain; charset="utf-8" Content-Language: en-US Content-Transfer-Encoding: 7bit X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 3/5/19 2:54 PM, John Stultz wrote: > Add generic helper dmabuf ops for dma heaps, so we can reduce > the amount of duplicative code for the exported dmabufs. > > This code is an evolution of the Android ION implementation, so > thanks to its original authors and maintainters: > Rebecca Schultz Zavin, Colin Cross, Laura Abbott, and others! > > Cc: Laura Abbott > Cc: Benjamin Gaignard > Cc: Greg KH > Cc: Sumit Semwal > Cc: Liam Mark > Cc: Brian Starkey > Cc: Andrew F. Davis > Cc: Chenbo Feng > Cc: Alistair Strachan > Cc: dri-devel@lists.freedesktop.org > Signed-off-by: John Stultz > --- > v2: > * Removed cache management performance hack that I had > accidentally folded in. > * Removed stats code that was in helpers > * Lots of checkpatch cleanups > --- > drivers/dma-buf/Makefile | 1 + > drivers/dma-buf/heaps/Makefile | 2 + > drivers/dma-buf/heaps/heap-helpers.c | 335 +++++++++++++++++++++++++++++++++++ > drivers/dma-buf/heaps/heap-helpers.h | 48 +++++ > 4 files changed, 386 insertions(+) > create mode 100644 drivers/dma-buf/heaps/Makefile > create mode 100644 drivers/dma-buf/heaps/heap-helpers.c > create mode 100644 drivers/dma-buf/heaps/heap-helpers.h > > diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile > index b0332f1..09c2f2d 100644 > --- a/drivers/dma-buf/Makefile > +++ b/drivers/dma-buf/Makefile > @@ -1,4 +1,5 @@ > obj-y := dma-buf.o dma-fence.o dma-fence-array.o reservation.o seqno-fence.o > +obj-$(CONFIG_DMABUF_HEAPS) += heaps/ > obj-$(CONFIG_DMABUF_HEAPS) += dma-heap.o > obj-$(CONFIG_SYNC_FILE) += sync_file.o > obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o > diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile > new file mode 100644 > index 0000000..de49898 > --- /dev/null > +++ b/drivers/dma-buf/heaps/Makefile > @@ -0,0 +1,2 @@ > +# SPDX-License-Identifier: GPL-2.0 > +obj-y += heap-helpers.o > diff --git a/drivers/dma-buf/heaps/heap-helpers.c b/drivers/dma-buf/heaps/heap-helpers.c > new file mode 100644 > index 0000000..ae5e9d0 > --- /dev/null > +++ b/drivers/dma-buf/heaps/heap-helpers.c > @@ -0,0 +1,335 @@ > +// SPDX-License-Identifier: GPL-2.0 > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "heap-helpers.h" > + > + > +static void *dma_heap_map_kernel(struct heap_helper_buffer *buffer) > +{ > + struct scatterlist *sg; > + int i, j; > + void *vaddr; > + pgprot_t pgprot; > + struct sg_table *table = buffer->sg_table; > + int npages = PAGE_ALIGN(buffer->heap_buffer.size) / PAGE_SIZE; > + struct page **pages = vmalloc(array_size(npages, > + sizeof(struct page *))); > + struct page **tmp = pages; > + > + if (!pages) > + return ERR_PTR(-ENOMEM); > + > + pgprot = PAGE_KERNEL; > + > + for_each_sg(table->sgl, sg, table->nents, i) { > + int npages_this_entry = PAGE_ALIGN(sg->length) / PAGE_SIZE; > + struct page *page = sg_page(sg); > + > + WARN_ON(i >= npages); > + for (j = 0; j < npages_this_entry; j++) > + *(tmp++) = page++; > + } > + vaddr = vmap(pages, npages, VM_MAP, pgprot); > + vfree(pages); > + > + if (!vaddr) > + return ERR_PTR(-ENOMEM); > + > + return vaddr; > +} > + > +static int dma_heap_map_user(struct heap_helper_buffer *buffer, > + struct vm_area_struct *vma) > +{ > + struct sg_table *table = buffer->sg_table; > + unsigned long addr = vma->vm_start; > + unsigned long offset = vma->vm_pgoff * PAGE_SIZE; > + struct scatterlist *sg; > + int i; > + int ret; > + > + for_each_sg(table->sgl, sg, table->nents, i) { > + struct page *page = sg_page(sg); > + unsigned long remainder = vma->vm_end - addr; > + unsigned long len = sg->length; > + > + if (offset >= sg->length) { > + offset -= sg->length; > + continue; > + } else if (offset) { > + page += offset / PAGE_SIZE; > + len = sg->length - offset; > + offset = 0; > + } > + len = min(len, remainder); > + ret = remap_pfn_range(vma, addr, page_to_pfn(page), len, > + vma->vm_page_prot); > + if (ret) > + return ret; > + addr += len; > + if (addr >= vma->vm_end) > + return 0; > + } > + > + return 0; > +} > + > + > +void dma_heap_buffer_destroy(struct dma_heap_buffer *heap_buffer) > +{ > + struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer); > + > + if (buffer->kmap_cnt > 0) { > + pr_warn_once("%s: buffer still mapped in the kernel\n", > + __func__); > + vunmap(buffer->vaddr); > + } > + > + buffer->free(buffer); > +} > + > +static void *dma_heap_buffer_kmap_get(struct dma_heap_buffer *heap_buffer) > +{ > + struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer); > + void *vaddr; > + > + if (buffer->kmap_cnt) { > + buffer->kmap_cnt++; > + return buffer->vaddr; > + } > + vaddr = dma_heap_map_kernel(buffer); The function is called "kmap" but here we go and vmap the whole buffer. The function names are not consistent here. > + if (WARN_ONCE(!vaddr, > + "heap->ops->map_kernel should return ERR_PTR on error")) > + return ERR_PTR(-EINVAL); > + if (IS_ERR(vaddr)) > + return vaddr; > + buffer->vaddr = vaddr; > + buffer->kmap_cnt++; > + return vaddr; > +} > + > +static void dma_heap_buffer_kmap_put(struct dma_heap_buffer *heap_buffer) > +{ > + struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer); > + > + buffer->kmap_cnt--; > + if (!buffer->kmap_cnt) { > + vunmap(buffer->vaddr); > + buffer->vaddr = NULL; > + } > +} > + > +static struct sg_table *dup_sg_table(struct sg_table *table) > +{ > + struct sg_table *new_table; > + int ret, i; > + struct scatterlist *sg, *new_sg; > + > + new_table = kzalloc(sizeof(*new_table), GFP_KERNEL); > + if (!new_table) > + return ERR_PTR(-ENOMEM); > + > + ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL); > + if (ret) { > + kfree(new_table); > + return ERR_PTR(-ENOMEM); > + } > + > + new_sg = new_table->sgl; > + for_each_sg(table->sgl, sg, table->nents, i) { > + memcpy(new_sg, sg, sizeof(*sg)); > + new_sg->dma_address = 0; > + new_sg = sg_next(new_sg); > + } > + > + return new_table; > +} > + > +static void free_duped_table(struct sg_table *table) > +{ > + sg_free_table(table); > + kfree(table); > +} > + > +struct dma_heaps_attachment { > + struct device *dev; > + struct sg_table *table; > + struct list_head list; > +}; > + > +static int dma_heap_attach(struct dma_buf *dmabuf, > + struct dma_buf_attachment *attachment) > +{ > + struct dma_heaps_attachment *a; > + struct sg_table *table; > + struct dma_heap_buffer *heap_buffer = dmabuf->priv; > + struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer); > + > + a = kzalloc(sizeof(*a), GFP_KERNEL); > + if (!a) > + return -ENOMEM; > + > + table = dup_sg_table(buffer->sg_table); > + if (IS_ERR(table)) { > + kfree(a); > + return -ENOMEM; > + } > + > + a->table = table; > + a->dev = attachment->dev; > + INIT_LIST_HEAD(&a->list); > + > + attachment->priv = a; > + > + mutex_lock(&buffer->lock); > + list_add(&a->list, &buffer->attachments); > + mutex_unlock(&buffer->lock); > + > + return 0; > +} > + > +static void dma_heap_detatch(struct dma_buf *dmabuf, > + struct dma_buf_attachment *attachment) > +{ > + struct dma_heaps_attachment *a = attachment->priv; > + struct dma_heap_buffer *heap_buffer = dmabuf->priv; > + struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer); > + > + mutex_lock(&buffer->lock); > + list_del(&a->list); > + mutex_unlock(&buffer->lock); > + free_duped_table(a->table); > + > + kfree(a); > +} > + > +static struct sg_table *dma_heap_map_dma_buf( > + struct dma_buf_attachment *attachment, > + enum dma_data_direction direction) > +{ > + struct dma_heaps_attachment *a = attachment->priv; > + struct sg_table *table; > + > + table = a->table; > + > + if (!dma_map_sg(attachment->dev, table->sgl, table->nents, > + direction)) > + table = ERR_PTR(-ENOMEM); > + return table; > +} > + > +static void dma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, > + struct sg_table *table, > + enum dma_data_direction direction) > +{ > + dma_unmap_sg(attachment->dev, table->sgl, table->nents, direction); > +} > + > +static int dma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) > +{ > + struct dma_heap_buffer *heap_buffer = dmabuf->priv; > + struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer); > + int ret = 0; > + > + mutex_lock(&buffer->lock); > + /* now map it to userspace */ > + ret = dma_heap_map_user(buffer, vma); Only used here, we can just put is functions code here. Also do we need this locked? What can race here? Everything accessed is static for the buffers lifetime. > + mutex_unlock(&buffer->lock); > + > + if (ret) > + pr_err("%s: failure mapping buffer to userspace\n", > + __func__); > + > + return ret; > +} > + > +static void dma_heap_dma_buf_release(struct dma_buf *dmabuf) > +{ > + struct dma_heap_buffer *buffer = dmabuf->priv; > + > + dma_heap_buffer_destroy(buffer); > +} > + > +static void *dma_heap_dma_buf_kmap(struct dma_buf *dmabuf, > + unsigned long offset) > +{ > + struct dma_heap_buffer *heap_buffer = dmabuf->priv; > + struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer); > + > + return buffer->vaddr + offset * PAGE_SIZE; > +} > + > +static void dma_heap_dma_buf_kunmap(struct dma_buf *dmabuf, > + unsigned long offset, > + void *ptr) > +{ > +} > + > +static int dma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, > + enum dma_data_direction direction) > +{ > + struct dma_heap_buffer *heap_buffer = dmabuf->priv; > + struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer); > + void *vaddr; > + struct dma_heaps_attachment *a; > + int ret = 0; > + > + mutex_lock(&buffer->lock); > + vaddr = dma_heap_buffer_kmap_get(heap_buffer); Not needed here, this can be dropped and so can the dma_heap_buffer_kmap_put() below. Andrew > + if (IS_ERR(vaddr)) { > + ret = PTR_ERR(vaddr); > + goto unlock; > + } > + mutex_unlock(&buffer->lock); > + > + mutex_lock(&buffer->lock); > + list_for_each_entry(a, &buffer->attachments, list) { > + dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents, > + direction); > + } > + > +unlock: > + mutex_unlock(&buffer->lock); > + return ret; > +} > + > +static int dma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, > + enum dma_data_direction direction) > +{ > + struct dma_heap_buffer *heap_buffer = dmabuf->priv; > + struct heap_helper_buffer *buffer = to_helper_buffer(heap_buffer); > + struct dma_heaps_attachment *a; > + > + mutex_lock(&buffer->lock); > + dma_heap_buffer_kmap_put(heap_buffer); > + mutex_unlock(&buffer->lock); > + > + mutex_lock(&buffer->lock); > + list_for_each_entry(a, &buffer->attachments, list) { > + dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents, > + direction); > + } > + mutex_unlock(&buffer->lock); > + > + return 0; > +} > + > +const struct dma_buf_ops heap_helper_ops = { > + .map_dma_buf = dma_heap_map_dma_buf, > + .unmap_dma_buf = dma_heap_unmap_dma_buf, > + .mmap = dma_heap_mmap, > + .release = dma_heap_dma_buf_release, > + .attach = dma_heap_attach, > + .detach = dma_heap_detatch, > + .begin_cpu_access = dma_heap_dma_buf_begin_cpu_access, > + .end_cpu_access = dma_heap_dma_buf_end_cpu_access, > + .map = dma_heap_dma_buf_kmap, > + .unmap = dma_heap_dma_buf_kunmap, > +}; > diff --git a/drivers/dma-buf/heaps/heap-helpers.h b/drivers/dma-buf/heaps/heap-helpers.h > new file mode 100644 > index 0000000..0bd8643 > --- /dev/null > +++ b/drivers/dma-buf/heaps/heap-helpers.h > @@ -0,0 +1,48 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* > + * DMABUF Heaps helper code > + * > + * Copyright (C) 2011 Google, Inc. > + * Copyright (C) 2019 Linaro Ltd. > + */ > + > +#ifndef _HEAP_HELPERS_H > +#define _HEAP_HELPERS_H > + > +#include > +#include > + > +struct heap_helper_buffer { > + struct dma_heap_buffer heap_buffer; > + > + unsigned long private_flags; > + void *priv_virt; > + struct mutex lock; > + int kmap_cnt; > + void *vaddr; > + struct sg_table *sg_table; > + struct list_head attachments; > + > + void (*free)(struct heap_helper_buffer *buffer); > + > +}; > + > +#define to_helper_buffer(x) \ > + container_of(x, struct heap_helper_buffer, heap_buffer) > + > +static inline void INIT_HEAP_HELPER_BUFFER(struct heap_helper_buffer *buffer, > + void (*free)(struct heap_helper_buffer *)) > +{ > + buffer->private_flags = 0; > + buffer->priv_virt = NULL; > + mutex_init(&buffer->lock); > + buffer->kmap_cnt = 0; > + buffer->vaddr = NULL; > + buffer->sg_table = NULL; > + INIT_LIST_HEAD(&buffer->attachments); > + buffer->free = free; > +} > + > +extern const struct dma_buf_ops heap_helper_ops; > + > +#endif /* _HEAP_HELPERS_H */ > From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Andrew F. Davis" Subject: Re: [RFC][PATCH 2/5 v2] dma-buf: heaps: Add heap helpers Date: Thu, 21 Mar 2019 15:43:58 -0500 Message-ID: <135e2f67-ebb1-da37-a0b0-6bbdd248333a@ti.com> References: <1551819273-640-1-git-send-email-john.stultz@linaro.org> <1551819273-640-3-git-send-email-john.stultz@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from fllv0016.ext.ti.com (fllv0016.ext.ti.com [198.47.19.142]) by gabe.freedesktop.org (Postfix) with ESMTPS id 8D89D6E14D for ; Thu, 21 Mar 2019 20:44:08 +0000 (UTC) In-Reply-To: <1551819273-640-3-git-send-email-john.stultz@linaro.org> Content-Language: en-US List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: John Stultz , lkml Cc: Greg KH , Chenbo Feng , Alistair Strachan , Liam Mark , dri-devel@lists.freedesktop.org List-Id: dri-devel@lists.freedesktop.org T24gMy81LzE5IDI6NTQgUE0sIEpvaG4gU3R1bHR6IHdyb3RlOgo+IEFkZCBnZW5lcmljIGhlbHBl ciBkbWFidWYgb3BzIGZvciBkbWEgaGVhcHMsIHNvIHdlIGNhbiByZWR1Y2UKPiB0aGUgYW1vdW50 IG9mIGR1cGxpY2F0aXZlIGNvZGUgZm9yIHRoZSBleHBvcnRlZCBkbWFidWZzLgo+IAo+IFRoaXMg Y29kZSBpcyBhbiBldm9sdXRpb24gb2YgdGhlIEFuZHJvaWQgSU9OIGltcGxlbWVudGF0aW9uLCBz bwo+IHRoYW5rcyB0byBpdHMgb3JpZ2luYWwgYXV0aG9ycyBhbmQgbWFpbnRhaW50ZXJzOgo+ICAg UmViZWNjYSBTY2h1bHR6IFphdmluLCBDb2xpbiBDcm9zcywgTGF1cmEgQWJib3R0LCBhbmQgb3Ro ZXJzIQo+IAo+IENjOiBMYXVyYSBBYmJvdHQgPGxhYmJvdHRAcmVkaGF0LmNvbT4KPiBDYzogQmVu amFtaW4gR2FpZ25hcmQgPGJlbmphbWluLmdhaWduYXJkQGxpbmFyby5vcmc+Cj4gQ2M6IEdyZWcg S0ggPGdyZWdraEBsaW51eGZvdW5kYXRpb24ub3JnPgo+IENjOiBTdW1pdCBTZW13YWwgPHN1bWl0 LnNlbXdhbEBsaW5hcm8ub3JnPgo+IENjOiBMaWFtIE1hcmsgPGxtYXJrQGNvZGVhdXJvcmEub3Jn Pgo+IENjOiBCcmlhbiBTdGFya2V5IDxCcmlhbi5TdGFya2V5QGFybS5jb20+Cj4gQ2M6IEFuZHJl dyBGLiBEYXZpcyA8YWZkQHRpLmNvbT4KPiBDYzogQ2hlbmJvIEZlbmcgPGZlbmdjQGdvb2dsZS5j b20+Cj4gQ2M6IEFsaXN0YWlyIFN0cmFjaGFuIDxhc3RyYWNoYW5AZ29vZ2xlLmNvbT4KPiBDYzog ZHJpLWRldmVsQGxpc3RzLmZyZWVkZXNrdG9wLm9yZwo+IFNpZ25lZC1vZmYtYnk6IEpvaG4gU3R1 bHR6IDxqb2huLnN0dWx0ekBsaW5hcm8ub3JnPgo+IC0tLQo+IHYyOgo+ICogUmVtb3ZlZCBjYWNo ZSBtYW5hZ2VtZW50IHBlcmZvcm1hbmNlIGhhY2sgdGhhdCBJIGhhZAo+ICAgYWNjaWRlbnRhbGx5 IGZvbGRlZCBpbi4KPiAqIFJlbW92ZWQgc3RhdHMgY29kZSB0aGF0IHdhcyBpbiBoZWxwZXJzCj4g KiBMb3RzIG9mIGNoZWNrcGF0Y2ggY2xlYW51cHMKPiAtLS0KPiAgZHJpdmVycy9kbWEtYnVmL01h a2VmaWxlICAgICAgICAgICAgIHwgICAxICsKPiAgZHJpdmVycy9kbWEtYnVmL2hlYXBzL01ha2Vm aWxlICAgICAgIHwgICAyICsKPiAgZHJpdmVycy9kbWEtYnVmL2hlYXBzL2hlYXAtaGVscGVycy5j IHwgMzM1ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCj4gIGRyaXZlcnMvZG1h LWJ1Zi9oZWFwcy9oZWFwLWhlbHBlcnMuaCB8ICA0OCArKysrKwo+ICA0IGZpbGVzIGNoYW5nZWQs IDM4NiBpbnNlcnRpb25zKCspCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2RtYS1idWYv aGVhcHMvTWFrZWZpbGUKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvZG1hLWJ1Zi9oZWFw cy9oZWFwLWhlbHBlcnMuYwo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9kbWEtYnVmL2hl YXBzL2hlYXAtaGVscGVycy5oCj4gCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvZG1hLWJ1Zi9NYWtl ZmlsZSBiL2RyaXZlcnMvZG1hLWJ1Zi9NYWtlZmlsZQo+IGluZGV4IGIwMzMyZjEuLjA5YzJmMmQg MTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy9kbWEtYnVmL01ha2VmaWxlCj4gKysrIGIvZHJpdmVycy9k bWEtYnVmL01ha2VmaWxlCj4gQEAgLTEsNCArMSw1IEBACj4gIG9iai15IDo9IGRtYS1idWYubyBk bWEtZmVuY2UubyBkbWEtZmVuY2UtYXJyYXkubyByZXNlcnZhdGlvbi5vIHNlcW5vLWZlbmNlLm8K PiArb2JqLSQoQ09ORklHX0RNQUJVRl9IRUFQUykJKz0gaGVhcHMvCj4gIG9iai0kKENPTkZJR19E TUFCVUZfSEVBUFMpCSs9IGRtYS1oZWFwLm8KPiAgb2JqLSQoQ09ORklHX1NZTkNfRklMRSkJCSs9 IHN5bmNfZmlsZS5vCj4gIG9iai0kKENPTkZJR19TV19TWU5DKQkJKz0gc3dfc3luYy5vIHN5bmNf ZGVidWcubwo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2RtYS1idWYvaGVhcHMvTWFrZWZpbGUgYi9k cml2ZXJzL2RtYS1idWYvaGVhcHMvTWFrZWZpbGUKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGlu ZGV4IDAwMDAwMDAuLmRlNDk4OTgKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy9kbWEt YnVmL2hlYXBzL01ha2VmaWxlCj4gQEAgLTAsMCArMSwyIEBACj4gKyMgU1BEWC1MaWNlbnNlLUlk ZW50aWZpZXI6IEdQTC0yLjAKPiArb2JqLXkJCQkJCSs9IGhlYXAtaGVscGVycy5vCj4gZGlmZiAt LWdpdCBhL2RyaXZlcnMvZG1hLWJ1Zi9oZWFwcy9oZWFwLWhlbHBlcnMuYyBiL2RyaXZlcnMvZG1h LWJ1Zi9oZWFwcy9oZWFwLWhlbHBlcnMuYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXgg MDAwMDAwMC4uYWU1ZTlkMAo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL2RtYS1idWYv aGVhcHMvaGVhcC1oZWxwZXJzLmMKPiBAQCAtMCwwICsxLDMzNSBAQAo+ICsvLyBTUERYLUxpY2Vu c2UtSWRlbnRpZmllcjogR1BMLTIuMAo+ICsjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+Cj4gKyNp bmNsdWRlIDxsaW51eC9kbWEtYnVmLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9lcnIuaD4KPiArI2lu Y2x1ZGUgPGxpbnV4L2lkci5oPgo+ICsjaW5jbHVkZSA8bGludXgvbGlzdC5oPgo+ICsjaW5jbHVk ZSA8bGludXgvc2xhYi5oPgo+ICsjaW5jbHVkZSA8bGludXgvdWFjY2Vzcy5oPgo+ICsjaW5jbHVk ZSA8dWFwaS9saW51eC9kbWEtaGVhcC5oPgo+ICsKPiArI2luY2x1ZGUgImhlYXAtaGVscGVycy5o Igo+ICsKPiArCj4gK3N0YXRpYyB2b2lkICpkbWFfaGVhcF9tYXBfa2VybmVsKHN0cnVjdCBoZWFw X2hlbHBlcl9idWZmZXIgKmJ1ZmZlcikKPiArewo+ICsJc3RydWN0IHNjYXR0ZXJsaXN0ICpzZzsK PiArCWludCBpLCBqOwo+ICsJdm9pZCAqdmFkZHI7Cj4gKwlwZ3Byb3RfdCBwZ3Byb3Q7Cj4gKwlz dHJ1Y3Qgc2dfdGFibGUgKnRhYmxlID0gYnVmZmVyLT5zZ190YWJsZTsKPiArCWludCBucGFnZXMg PSBQQUdFX0FMSUdOKGJ1ZmZlci0+aGVhcF9idWZmZXIuc2l6ZSkgLyBQQUdFX1NJWkU7Cj4gKwlz dHJ1Y3QgcGFnZSAqKnBhZ2VzID0gdm1hbGxvYyhhcnJheV9zaXplKG5wYWdlcywKPiArCQkJCQkJ IHNpemVvZihzdHJ1Y3QgcGFnZSAqKSkpOwo+ICsJc3RydWN0IHBhZ2UgKip0bXAgPSBwYWdlczsK PiArCj4gKwlpZiAoIXBhZ2VzKQo+ICsJCXJldHVybiBFUlJfUFRSKC1FTk9NRU0pOwo+ICsKPiAr CXBncHJvdCA9IFBBR0VfS0VSTkVMOwo+ICsKPiArCWZvcl9lYWNoX3NnKHRhYmxlLT5zZ2wsIHNn LCB0YWJsZS0+bmVudHMsIGkpIHsKPiArCQlpbnQgbnBhZ2VzX3RoaXNfZW50cnkgPSBQQUdFX0FM SUdOKHNnLT5sZW5ndGgpIC8gUEFHRV9TSVpFOwo+ICsJCXN0cnVjdCBwYWdlICpwYWdlID0gc2df cGFnZShzZyk7Cj4gKwo+ICsJCVdBUk5fT04oaSA+PSBucGFnZXMpOwo+ICsJCWZvciAoaiA9IDA7 IGogPCBucGFnZXNfdGhpc19lbnRyeTsgaisrKQo+ICsJCQkqKHRtcCsrKSA9IHBhZ2UrKzsKPiAr CX0KPiArCXZhZGRyID0gdm1hcChwYWdlcywgbnBhZ2VzLCBWTV9NQVAsIHBncHJvdCk7Cj4gKwl2 ZnJlZShwYWdlcyk7Cj4gKwo+ICsJaWYgKCF2YWRkcikKPiArCQlyZXR1cm4gRVJSX1BUUigtRU5P TUVNKTsKPiArCj4gKwlyZXR1cm4gdmFkZHI7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgZG1hX2hl YXBfbWFwX3VzZXIoc3RydWN0IGhlYXBfaGVscGVyX2J1ZmZlciAqYnVmZmVyLAo+ICsJCQkgc3Ry dWN0IHZtX2FyZWFfc3RydWN0ICp2bWEpCj4gK3sKPiArCXN0cnVjdCBzZ190YWJsZSAqdGFibGUg PSBidWZmZXItPnNnX3RhYmxlOwo+ICsJdW5zaWduZWQgbG9uZyBhZGRyID0gdm1hLT52bV9zdGFy dDsKPiArCXVuc2lnbmVkIGxvbmcgb2Zmc2V0ID0gdm1hLT52bV9wZ29mZiAqIFBBR0VfU0laRTsK PiArCXN0cnVjdCBzY2F0dGVybGlzdCAqc2c7Cj4gKwlpbnQgaTsKPiArCWludCByZXQ7Cj4gKwo+ ICsJZm9yX2VhY2hfc2codGFibGUtPnNnbCwgc2csIHRhYmxlLT5uZW50cywgaSkgewo+ICsJCXN0 cnVjdCBwYWdlICpwYWdlID0gc2dfcGFnZShzZyk7Cj4gKwkJdW5zaWduZWQgbG9uZyByZW1haW5k ZXIgPSB2bWEtPnZtX2VuZCAtIGFkZHI7Cj4gKwkJdW5zaWduZWQgbG9uZyBsZW4gPSBzZy0+bGVu Z3RoOwo+ICsKPiArCQlpZiAob2Zmc2V0ID49IHNnLT5sZW5ndGgpIHsKPiArCQkJb2Zmc2V0IC09 IHNnLT5sZW5ndGg7Cj4gKwkJCWNvbnRpbnVlOwo+ICsJCX0gZWxzZSBpZiAob2Zmc2V0KSB7Cj4g KwkJCXBhZ2UgKz0gb2Zmc2V0IC8gUEFHRV9TSVpFOwo+ICsJCQlsZW4gPSBzZy0+bGVuZ3RoIC0g b2Zmc2V0Owo+ICsJCQlvZmZzZXQgPSAwOwo+ICsJCX0KPiArCQlsZW4gPSBtaW4obGVuLCByZW1h aW5kZXIpOwo+ICsJCXJldCA9IHJlbWFwX3Bmbl9yYW5nZSh2bWEsIGFkZHIsIHBhZ2VfdG9fcGZu KHBhZ2UpLCBsZW4sCj4gKwkJCQkgICAgICB2bWEtPnZtX3BhZ2VfcHJvdCk7Cj4gKwkJaWYgKHJl dCkKPiArCQkJcmV0dXJuIHJldDsKPiArCQlhZGRyICs9IGxlbjsKPiArCQlpZiAoYWRkciA+PSB2 bWEtPnZtX2VuZCkKPiArCQkJcmV0dXJuIDA7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30K PiArCj4gKwo+ICt2b2lkIGRtYV9oZWFwX2J1ZmZlcl9kZXN0cm95KHN0cnVjdCBkbWFfaGVhcF9i dWZmZXIgKmhlYXBfYnVmZmVyKQo+ICt7Cj4gKwlzdHJ1Y3QgaGVhcF9oZWxwZXJfYnVmZmVyICpi dWZmZXIgPSB0b19oZWxwZXJfYnVmZmVyKGhlYXBfYnVmZmVyKTsKPiArCj4gKwlpZiAoYnVmZmVy LT5rbWFwX2NudCA+IDApIHsKPiArCQlwcl93YXJuX29uY2UoIiVzOiBidWZmZXIgc3RpbGwgbWFw cGVkIGluIHRoZSBrZXJuZWxcbiIsCj4gKwkJCSAgICAgX19mdW5jX18pOwo+ICsJCXZ1bm1hcChi dWZmZXItPnZhZGRyKTsKPiArCX0KPiArCj4gKwlidWZmZXItPmZyZWUoYnVmZmVyKTsKPiArfQo+ ICsKPiArc3RhdGljIHZvaWQgKmRtYV9oZWFwX2J1ZmZlcl9rbWFwX2dldChzdHJ1Y3QgZG1hX2hl YXBfYnVmZmVyICpoZWFwX2J1ZmZlcikKPiArewo+ICsJc3RydWN0IGhlYXBfaGVscGVyX2J1ZmZl ciAqYnVmZmVyID0gdG9faGVscGVyX2J1ZmZlcihoZWFwX2J1ZmZlcik7Cj4gKwl2b2lkICp2YWRk cjsKPiArCj4gKwlpZiAoYnVmZmVyLT5rbWFwX2NudCkgewo+ICsJCWJ1ZmZlci0+a21hcF9jbnQr KzsKPiArCQlyZXR1cm4gYnVmZmVyLT52YWRkcjsKPiArCX0KPiArCXZhZGRyID0gZG1hX2hlYXBf bWFwX2tlcm5lbChidWZmZXIpOwoKVGhlIGZ1bmN0aW9uIGlzIGNhbGxlZCAia21hcCIgYnV0IGhl cmUgd2UgZ28gYW5kIHZtYXAgdGhlIHdob2xlIGJ1ZmZlci4KVGhlIGZ1bmN0aW9uIG5hbWVzIGFy ZSBub3QgY29uc2lzdGVudCBoZXJlLgoKPiArCWlmIChXQVJOX09OQ0UoIXZhZGRyLAo+ICsJCSAg ICAgICJoZWFwLT5vcHMtPm1hcF9rZXJuZWwgc2hvdWxkIHJldHVybiBFUlJfUFRSIG9uIGVycm9y IikpCj4gKwkJcmV0dXJuIEVSUl9QVFIoLUVJTlZBTCk7Cj4gKwlpZiAoSVNfRVJSKHZhZGRyKSkK PiArCQlyZXR1cm4gdmFkZHI7Cj4gKwlidWZmZXItPnZhZGRyID0gdmFkZHI7Cj4gKwlidWZmZXIt PmttYXBfY250Kys7Cj4gKwlyZXR1cm4gdmFkZHI7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIGRt YV9oZWFwX2J1ZmZlcl9rbWFwX3B1dChzdHJ1Y3QgZG1hX2hlYXBfYnVmZmVyICpoZWFwX2J1ZmZl cikKPiArewo+ICsJc3RydWN0IGhlYXBfaGVscGVyX2J1ZmZlciAqYnVmZmVyID0gdG9faGVscGVy X2J1ZmZlcihoZWFwX2J1ZmZlcik7Cj4gKwo+ICsJYnVmZmVyLT5rbWFwX2NudC0tOwo+ICsJaWYg KCFidWZmZXItPmttYXBfY250KSB7Cj4gKwkJdnVubWFwKGJ1ZmZlci0+dmFkZHIpOwo+ICsJCWJ1 ZmZlci0+dmFkZHIgPSBOVUxMOwo+ICsJfQo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IHNnX3Rh YmxlICpkdXBfc2dfdGFibGUoc3RydWN0IHNnX3RhYmxlICp0YWJsZSkKPiArewo+ICsJc3RydWN0 IHNnX3RhYmxlICpuZXdfdGFibGU7Cj4gKwlpbnQgcmV0LCBpOwo+ICsJc3RydWN0IHNjYXR0ZXJs aXN0ICpzZywgKm5ld19zZzsKPiArCj4gKwluZXdfdGFibGUgPSBremFsbG9jKHNpemVvZigqbmV3 X3RhYmxlKSwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIW5ld190YWJsZSkKPiArCQlyZXR1cm4gRVJS X1BUUigtRU5PTUVNKTsKPiArCj4gKwlyZXQgPSBzZ19hbGxvY190YWJsZShuZXdfdGFibGUsIHRh YmxlLT5uZW50cywgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJa2ZyZWUobmV3X3Rh YmxlKTsKPiArCQlyZXR1cm4gRVJSX1BUUigtRU5PTUVNKTsKPiArCX0KPiArCj4gKwluZXdfc2cg PSBuZXdfdGFibGUtPnNnbDsKPiArCWZvcl9lYWNoX3NnKHRhYmxlLT5zZ2wsIHNnLCB0YWJsZS0+ bmVudHMsIGkpIHsKPiArCQltZW1jcHkobmV3X3NnLCBzZywgc2l6ZW9mKCpzZykpOwo+ICsJCW5l d19zZy0+ZG1hX2FkZHJlc3MgPSAwOwo+ICsJCW5ld19zZyA9IHNnX25leHQobmV3X3NnKTsKPiAr CX0KPiArCj4gKwlyZXR1cm4gbmV3X3RhYmxlOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBmcmVl X2R1cGVkX3RhYmxlKHN0cnVjdCBzZ190YWJsZSAqdGFibGUpCj4gK3sKPiArCXNnX2ZyZWVfdGFi bGUodGFibGUpOwo+ICsJa2ZyZWUodGFibGUpOwo+ICt9Cj4gKwo+ICtzdHJ1Y3QgZG1hX2hlYXBz X2F0dGFjaG1lbnQgewo+ICsJc3RydWN0IGRldmljZSAqZGV2Owo+ICsJc3RydWN0IHNnX3RhYmxl ICp0YWJsZTsKPiArCXN0cnVjdCBsaXN0X2hlYWQgbGlzdDsKPiArfTsKPiArCj4gK3N0YXRpYyBp bnQgZG1hX2hlYXBfYXR0YWNoKHN0cnVjdCBkbWFfYnVmICpkbWFidWYsCj4gKwkJCSAgICAgIHN0 cnVjdCBkbWFfYnVmX2F0dGFjaG1lbnQgKmF0dGFjaG1lbnQpCj4gK3sKPiArCXN0cnVjdCBkbWFf aGVhcHNfYXR0YWNobWVudCAqYTsKPiArCXN0cnVjdCBzZ190YWJsZSAqdGFibGU7Cj4gKwlzdHJ1 Y3QgZG1hX2hlYXBfYnVmZmVyICpoZWFwX2J1ZmZlciA9IGRtYWJ1Zi0+cHJpdjsKPiArCXN0cnVj dCBoZWFwX2hlbHBlcl9idWZmZXIgKmJ1ZmZlciA9IHRvX2hlbHBlcl9idWZmZXIoaGVhcF9idWZm ZXIpOwo+ICsKPiArCWEgPSBremFsbG9jKHNpemVvZigqYSksIEdGUF9LRVJORUwpOwo+ICsJaWYg KCFhKQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCXRhYmxlID0gZHVwX3NnX3RhYmxlKGJ1 ZmZlci0+c2dfdGFibGUpOwo+ICsJaWYgKElTX0VSUih0YWJsZSkpIHsKPiArCQlrZnJlZShhKTsK PiArCQlyZXR1cm4gLUVOT01FTTsKPiArCX0KPiArCj4gKwlhLT50YWJsZSA9IHRhYmxlOwo+ICsJ YS0+ZGV2ID0gYXR0YWNobWVudC0+ZGV2Owo+ICsJSU5JVF9MSVNUX0hFQUQoJmEtPmxpc3QpOwo+ ICsKPiArCWF0dGFjaG1lbnQtPnByaXYgPSBhOwo+ICsKPiArCW11dGV4X2xvY2soJmJ1ZmZlci0+ bG9jayk7Cj4gKwlsaXN0X2FkZCgmYS0+bGlzdCwgJmJ1ZmZlci0+YXR0YWNobWVudHMpOwo+ICsJ bXV0ZXhfdW5sb2NrKCZidWZmZXItPmxvY2spOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgdm9pZCBkbWFfaGVhcF9kZXRhdGNoKHN0cnVjdCBkbWFfYnVmICpkbWFidWYsCj4g KwkJCQlzdHJ1Y3QgZG1hX2J1Zl9hdHRhY2htZW50ICphdHRhY2htZW50KQo+ICt7Cj4gKwlzdHJ1 Y3QgZG1hX2hlYXBzX2F0dGFjaG1lbnQgKmEgPSBhdHRhY2htZW50LT5wcml2Owo+ICsJc3RydWN0 IGRtYV9oZWFwX2J1ZmZlciAqaGVhcF9idWZmZXIgPSBkbWFidWYtPnByaXY7Cj4gKwlzdHJ1Y3Qg aGVhcF9oZWxwZXJfYnVmZmVyICpidWZmZXIgPSB0b19oZWxwZXJfYnVmZmVyKGhlYXBfYnVmZmVy KTsKPiArCj4gKwltdXRleF9sb2NrKCZidWZmZXItPmxvY2spOwo+ICsJbGlzdF9kZWwoJmEtPmxp c3QpOwo+ICsJbXV0ZXhfdW5sb2NrKCZidWZmZXItPmxvY2spOwo+ICsJZnJlZV9kdXBlZF90YWJs ZShhLT50YWJsZSk7Cj4gKwo+ICsJa2ZyZWUoYSk7Cj4gK30KPiArCj4gK3N0YXRpYyBzdHJ1Y3Qg c2dfdGFibGUgKmRtYV9oZWFwX21hcF9kbWFfYnVmKAo+ICsJCQkJCXN0cnVjdCBkbWFfYnVmX2F0 dGFjaG1lbnQgKmF0dGFjaG1lbnQsCj4gKwkJCQkJZW51bSBkbWFfZGF0YV9kaXJlY3Rpb24gZGly ZWN0aW9uKQo+ICt7Cj4gKwlzdHJ1Y3QgZG1hX2hlYXBzX2F0dGFjaG1lbnQgKmEgPSBhdHRhY2ht ZW50LT5wcml2Owo+ICsJc3RydWN0IHNnX3RhYmxlICp0YWJsZTsKPiArCj4gKwl0YWJsZSA9IGEt PnRhYmxlOwo+ICsKPiArCWlmICghZG1hX21hcF9zZyhhdHRhY2htZW50LT5kZXYsIHRhYmxlLT5z Z2wsIHRhYmxlLT5uZW50cywKPiArCQkJZGlyZWN0aW9uKSkKPiArCQl0YWJsZSA9IEVSUl9QVFIo LUVOT01FTSk7Cj4gKwlyZXR1cm4gdGFibGU7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIGRtYV9o ZWFwX3VubWFwX2RtYV9idWYoc3RydWN0IGRtYV9idWZfYXR0YWNobWVudCAqYXR0YWNobWVudCwK PiArCQkJICAgICAgc3RydWN0IHNnX3RhYmxlICp0YWJsZSwKPiArCQkJICAgICAgZW51bSBkbWFf ZGF0YV9kaXJlY3Rpb24gZGlyZWN0aW9uKQo+ICt7Cj4gKwlkbWFfdW5tYXBfc2coYXR0YWNobWVu dC0+ZGV2LCB0YWJsZS0+c2dsLCB0YWJsZS0+bmVudHMsIGRpcmVjdGlvbik7Cj4gK30KPiArCj4g K3N0YXRpYyBpbnQgZG1hX2hlYXBfbW1hcChzdHJ1Y3QgZG1hX2J1ZiAqZG1hYnVmLCBzdHJ1Y3Qg dm1fYXJlYV9zdHJ1Y3QgKnZtYSkKPiArewo+ICsJc3RydWN0IGRtYV9oZWFwX2J1ZmZlciAqaGVh cF9idWZmZXIgPSBkbWFidWYtPnByaXY7Cj4gKwlzdHJ1Y3QgaGVhcF9oZWxwZXJfYnVmZmVyICpi dWZmZXIgPSB0b19oZWxwZXJfYnVmZmVyKGhlYXBfYnVmZmVyKTsKPiArCWludCByZXQgPSAwOwo+ ICsKPiArCW11dGV4X2xvY2soJmJ1ZmZlci0+bG9jayk7Cj4gKwkvKiBub3cgbWFwIGl0IHRvIHVz ZXJzcGFjZSAqLwo+ICsJcmV0ID0gZG1hX2hlYXBfbWFwX3VzZXIoYnVmZmVyLCB2bWEpOwoKT25s eSB1c2VkIGhlcmUsIHdlIGNhbiBqdXN0IHB1dCBpcyBmdW5jdGlvbnMgY29kZSBoZXJlLiBBbHNv IGRvIHdlIG5lZWQKdGhpcyBsb2NrZWQ/IFdoYXQgY2FuIHJhY2UgaGVyZT8gRXZlcnl0aGluZyBh Y2Nlc3NlZCBpcyBzdGF0aWMgZm9yIHRoZQpidWZmZXJzIGxpZmV0aW1lLgoKPiArCW11dGV4X3Vu bG9jaygmYnVmZmVyLT5sb2NrKTsKPiArCj4gKwlpZiAocmV0KQo+ICsJCXByX2VycigiJXM6IGZh aWx1cmUgbWFwcGluZyBidWZmZXIgdG8gdXNlcnNwYWNlXG4iLAo+ICsJCSAgICAgICBfX2Z1bmNf Xyk7Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgZG1hX2hlYXBf ZG1hX2J1Zl9yZWxlYXNlKHN0cnVjdCBkbWFfYnVmICpkbWFidWYpCj4gK3sKPiArCXN0cnVjdCBk bWFfaGVhcF9idWZmZXIgKmJ1ZmZlciA9IGRtYWJ1Zi0+cHJpdjsKPiArCj4gKwlkbWFfaGVhcF9i dWZmZXJfZGVzdHJveShidWZmZXIpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCAqZG1hX2hlYXBf ZG1hX2J1Zl9rbWFwKHN0cnVjdCBkbWFfYnVmICpkbWFidWYsCj4gKwkJCQkJdW5zaWduZWQgbG9u ZyBvZmZzZXQpCj4gK3sKPiArCXN0cnVjdCBkbWFfaGVhcF9idWZmZXIgKmhlYXBfYnVmZmVyID0g ZG1hYnVmLT5wcml2Owo+ICsJc3RydWN0IGhlYXBfaGVscGVyX2J1ZmZlciAqYnVmZmVyID0gdG9f aGVscGVyX2J1ZmZlcihoZWFwX2J1ZmZlcik7Cj4gKwo+ICsJcmV0dXJuIGJ1ZmZlci0+dmFkZHIg KyBvZmZzZXQgKiBQQUdFX1NJWkU7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIGRtYV9oZWFwX2Rt YV9idWZfa3VubWFwKHN0cnVjdCBkbWFfYnVmICpkbWFidWYsCj4gKwkJCQkJdW5zaWduZWQgbG9u ZyBvZmZzZXQsCj4gKwkJCQkJdm9pZCAqcHRyKQo+ICt7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQg ZG1hX2hlYXBfZG1hX2J1Zl9iZWdpbl9jcHVfYWNjZXNzKHN0cnVjdCBkbWFfYnVmICpkbWFidWYs Cj4gKwkJCQkJZW51bSBkbWFfZGF0YV9kaXJlY3Rpb24gZGlyZWN0aW9uKQo+ICt7Cj4gKwlzdHJ1 Y3QgZG1hX2hlYXBfYnVmZmVyICpoZWFwX2J1ZmZlciA9IGRtYWJ1Zi0+cHJpdjsKPiArCXN0cnVj dCBoZWFwX2hlbHBlcl9idWZmZXIgKmJ1ZmZlciA9IHRvX2hlbHBlcl9idWZmZXIoaGVhcF9idWZm ZXIpOwo+ICsJdm9pZCAqdmFkZHI7Cj4gKwlzdHJ1Y3QgZG1hX2hlYXBzX2F0dGFjaG1lbnQgKmE7 Cj4gKwlpbnQgcmV0ID0gMDsKPiArCj4gKwltdXRleF9sb2NrKCZidWZmZXItPmxvY2spOwo+ICsJ dmFkZHIgPSBkbWFfaGVhcF9idWZmZXJfa21hcF9nZXQoaGVhcF9idWZmZXIpOwoKCk5vdCBuZWVk ZWQgaGVyZSwgdGhpcyBjYW4gYmUgZHJvcHBlZCBhbmQgc28gY2FuIHRoZQpkbWFfaGVhcF9idWZm ZXJfa21hcF9wdXQoKSBiZWxvdy4KCkFuZHJldwoKPiArCWlmIChJU19FUlIodmFkZHIpKSB7Cj4g KwkJcmV0ID0gUFRSX0VSUih2YWRkcik7Cj4gKwkJZ290byB1bmxvY2s7Cj4gKwl9Cj4gKwltdXRl eF91bmxvY2soJmJ1ZmZlci0+bG9jayk7Cj4gKwo+ICsJbXV0ZXhfbG9jaygmYnVmZmVyLT5sb2Nr KTsKPiArCWxpc3RfZm9yX2VhY2hfZW50cnkoYSwgJmJ1ZmZlci0+YXR0YWNobWVudHMsIGxpc3Qp IHsKPiArCQlkbWFfc3luY19zZ19mb3JfY3B1KGEtPmRldiwgYS0+dGFibGUtPnNnbCwgYS0+dGFi bGUtPm5lbnRzLAo+ICsJCQkJICAgIGRpcmVjdGlvbik7Cj4gKwl9Cj4gKwo+ICt1bmxvY2s6Cj4g KwltdXRleF91bmxvY2soJmJ1ZmZlci0+bG9jayk7Cj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ ICtzdGF0aWMgaW50IGRtYV9oZWFwX2RtYV9idWZfZW5kX2NwdV9hY2Nlc3Moc3RydWN0IGRtYV9i dWYgKmRtYWJ1ZiwKPiArCQkJCSAgICAgIGVudW0gZG1hX2RhdGFfZGlyZWN0aW9uIGRpcmVjdGlv bikKPiArewo+ICsJc3RydWN0IGRtYV9oZWFwX2J1ZmZlciAqaGVhcF9idWZmZXIgPSBkbWFidWYt PnByaXY7Cj4gKwlzdHJ1Y3QgaGVhcF9oZWxwZXJfYnVmZmVyICpidWZmZXIgPSB0b19oZWxwZXJf YnVmZmVyKGhlYXBfYnVmZmVyKTsKPiArCXN0cnVjdCBkbWFfaGVhcHNfYXR0YWNobWVudCAqYTsK PiArCj4gKwltdXRleF9sb2NrKCZidWZmZXItPmxvY2spOwo+ICsJZG1hX2hlYXBfYnVmZmVyX2tt YXBfcHV0KGhlYXBfYnVmZmVyKTsKPiArCW11dGV4X3VubG9jaygmYnVmZmVyLT5sb2NrKTsKPiAr Cj4gKwltdXRleF9sb2NrKCZidWZmZXItPmxvY2spOwo+ICsJbGlzdF9mb3JfZWFjaF9lbnRyeShh LCAmYnVmZmVyLT5hdHRhY2htZW50cywgbGlzdCkgewo+ICsJCWRtYV9zeW5jX3NnX2Zvcl9kZXZp Y2UoYS0+ZGV2LCBhLT50YWJsZS0+c2dsLCBhLT50YWJsZS0+bmVudHMsCj4gKwkJCQkgICAgICAg ZGlyZWN0aW9uKTsKPiArCX0KPiArCW11dGV4X3VubG9jaygmYnVmZmVyLT5sb2NrKTsKPiArCj4g KwlyZXR1cm4gMDsKPiArfQo+ICsKPiArY29uc3Qgc3RydWN0IGRtYV9idWZfb3BzIGhlYXBfaGVs cGVyX29wcyA9IHsKPiArCS5tYXBfZG1hX2J1ZiA9IGRtYV9oZWFwX21hcF9kbWFfYnVmLAo+ICsJ LnVubWFwX2RtYV9idWYgPSBkbWFfaGVhcF91bm1hcF9kbWFfYnVmLAo+ICsJLm1tYXAgPSBkbWFf aGVhcF9tbWFwLAo+ICsJLnJlbGVhc2UgPSBkbWFfaGVhcF9kbWFfYnVmX3JlbGVhc2UsCj4gKwku YXR0YWNoID0gZG1hX2hlYXBfYXR0YWNoLAo+ICsJLmRldGFjaCA9IGRtYV9oZWFwX2RldGF0Y2gs Cj4gKwkuYmVnaW5fY3B1X2FjY2VzcyA9IGRtYV9oZWFwX2RtYV9idWZfYmVnaW5fY3B1X2FjY2Vz cywKPiArCS5lbmRfY3B1X2FjY2VzcyA9IGRtYV9oZWFwX2RtYV9idWZfZW5kX2NwdV9hY2Nlc3Ms Cj4gKwkubWFwID0gZG1hX2hlYXBfZG1hX2J1Zl9rbWFwLAo+ICsJLnVubWFwID0gZG1hX2hlYXBf ZG1hX2J1Zl9rdW5tYXAsCj4gK307Cj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvZG1hLWJ1Zi9oZWFw cy9oZWFwLWhlbHBlcnMuaCBiL2RyaXZlcnMvZG1hLWJ1Zi9oZWFwcy9oZWFwLWhlbHBlcnMuaAo+ IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMC4uMGJkODY0Mwo+IC0tLSAvZGV2 L251bGwKPiArKysgYi9kcml2ZXJzL2RtYS1idWYvaGVhcHMvaGVhcC1oZWxwZXJzLmgKPiBAQCAt MCwwICsxLDQ4IEBACj4gKy8qIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wICovCj4g Ky8qCj4gKyAqIERNQUJVRiBIZWFwcyBoZWxwZXIgY29kZQo+ICsgKgo+ICsgKiBDb3B5cmlnaHQg KEMpIDIwMTEgR29vZ2xlLCBJbmMuCj4gKyAqIENvcHlyaWdodCAoQykgMjAxOSBMaW5hcm8gTHRk Lgo+ICsgKi8KPiArCj4gKyNpZm5kZWYgX0hFQVBfSEVMUEVSU19ICj4gKyNkZWZpbmUgX0hFQVBf SEVMUEVSU19ICj4gKwo+ICsjaW5jbHVkZSA8bGludXgvZG1hLWhlYXAuaD4KPiArI2luY2x1ZGUg PGxpbnV4L2xpc3QuaD4KPiArCj4gK3N0cnVjdCBoZWFwX2hlbHBlcl9idWZmZXIgewo+ICsJc3Ry dWN0IGRtYV9oZWFwX2J1ZmZlciBoZWFwX2J1ZmZlcjsKPiArCj4gKwl1bnNpZ25lZCBsb25nIHBy aXZhdGVfZmxhZ3M7Cj4gKwl2b2lkICpwcml2X3ZpcnQ7Cj4gKwlzdHJ1Y3QgbXV0ZXggbG9jazsK PiArCWludCBrbWFwX2NudDsKPiArCXZvaWQgKnZhZGRyOwo+ICsJc3RydWN0IHNnX3RhYmxlICpz Z190YWJsZTsKPiArCXN0cnVjdCBsaXN0X2hlYWQgYXR0YWNobWVudHM7Cj4gKwo+ICsJdm9pZCAo KmZyZWUpKHN0cnVjdCBoZWFwX2hlbHBlcl9idWZmZXIgKmJ1ZmZlcik7Cj4gKwo+ICt9Owo+ICsK PiArI2RlZmluZSB0b19oZWxwZXJfYnVmZmVyKHgpIFwKPiArCWNvbnRhaW5lcl9vZih4LCBzdHJ1 Y3QgaGVhcF9oZWxwZXJfYnVmZmVyLCBoZWFwX2J1ZmZlcikKPiArCj4gK3N0YXRpYyBpbmxpbmUg dm9pZCBJTklUX0hFQVBfSEVMUEVSX0JVRkZFUihzdHJ1Y3QgaGVhcF9oZWxwZXJfYnVmZmVyICpi dWZmZXIsCj4gKwkJCQkgdm9pZCAoKmZyZWUpKHN0cnVjdCBoZWFwX2hlbHBlcl9idWZmZXIgKikp Cj4gK3sKPiArCWJ1ZmZlci0+cHJpdmF0ZV9mbGFncyA9IDA7Cj4gKwlidWZmZXItPnByaXZfdmly dCA9IE5VTEw7Cj4gKwltdXRleF9pbml0KCZidWZmZXItPmxvY2spOwo+ICsJYnVmZmVyLT5rbWFw X2NudCA9IDA7Cj4gKwlidWZmZXItPnZhZGRyID0gTlVMTDsKPiArCWJ1ZmZlci0+c2dfdGFibGUg PSBOVUxMOwo+ICsJSU5JVF9MSVNUX0hFQUQoJmJ1ZmZlci0+YXR0YWNobWVudHMpOwo+ICsJYnVm ZmVyLT5mcmVlID0gZnJlZTsKPiArfQo+ICsKPiArZXh0ZXJuIGNvbnN0IHN0cnVjdCBkbWFfYnVm X29wcyBoZWFwX2hlbHBlcl9vcHM7Cj4gKwo+ICsjZW5kaWYgLyogX0hFQVBfSEVMUEVSU19IICov Cj4gCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmRyaS1k ZXZlbCBtYWlsaW5nIGxpc3QKZHJpLWRldmVsQGxpc3RzLmZyZWVkZXNrdG9wLm9yZwpodHRwczov L2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2RyaS1kZXZlbA==