From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from galahad.ideasonboard.com ([185.26.127.97]:40845 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750707AbeC2HIf (ORCPT ); Thu, 29 Mar 2018 03:08:35 -0400 From: Laurent Pinchart To: Kieran Bingham Cc: Laurent Pinchart , linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org Subject: Re: [PATCH 07/15] v4l: vsp1: Move DRM atomic commit pipeline setup to separate function Date: Thu, 29 Mar 2018 10:08:35 +0300 Message-ID: <2427732.6RX94pHpa3@avalon> In-Reply-To: <80250bdd-dda3-5a2f-02e8-1121197949f5@ideasonboard.com> References: <20180226214516.11559-1-laurent.pinchart+renesas@ideasonboard.com> <20180226214516.11559-8-laurent.pinchart+renesas@ideasonboard.com> <80250bdd-dda3-5a2f-02e8-1121197949f5@ideasonboard.com> MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Sender: linux-renesas-soc-owner@vger.kernel.org List-ID: Hi Kieran, On Wednesday, 28 March 2018 17:43:13 EEST Kieran Bingham wrote: > On 26/02/18 21:45, Laurent Pinchart wrote: > > The DRM pipeline setup code used at atomic commit time is similar to the > > setup code used when enabling the pipeline. Move it to a separate > > function in order to share it. > > > > Signed-off-by: Laurent Pinchart > > > > Assuming no hidden secret code addition in this code move that I haven't > seen.. > > Only a minor nit below asking if the function should be pluralised (_inputs, > rather than _input) I'll fix that in v2, thanks. > Reviewed-by: Kieran Bingham > > > --- > > > > drivers/media/platform/vsp1/vsp1_drm.c | 347 > > +++++++++++++++++---------------- 1 file changed, 180 insertions(+), 167 > > deletions(-) > > > > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c > > b/drivers/media/platform/vsp1/vsp1_drm.c index 9a043a915c0b..7bf697ba7969 > > 100644 > > --- a/drivers/media/platform/vsp1/vsp1_drm.c > > +++ b/drivers/media/platform/vsp1/vsp1_drm.c > > @@ -46,6 +46,185 @@ static void vsp1_du_pipeline_frame_end(struct > > vsp1_pipeline *pipe,> > > * Pipeline Configuration > > */ > > > > +/* Setup one RPF and the connected BRU sink pad. */ > > +static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1, > > + struct vsp1_pipeline *pipe, > > + struct vsp1_rwpf *rpf, > > + unsigned int bru_input) > > +{ > > + struct v4l2_subdev_selection sel; > > + struct v4l2_subdev_format format; > > + const struct v4l2_rect *crop; > > + int ret; > > + > > + /* > > + * Configure the format on the RPF sink pad and propagate it up to the > > + * BRU sink pad. > > + */ > > + crop = &vsp1->drm->inputs[rpf->entity.index].crop; > > + > > + memset(&format, 0, sizeof(format)); > > + format.which = V4L2_SUBDEV_FORMAT_ACTIVE; > > + format.pad = RWPF_PAD_SINK; > > + format.format.width = crop->width + crop->left; > > + format.format.height = crop->height + crop->top; > > + format.format.code = rpf->fmtinfo->mbus; > > + format.format.field = V4L2_FIELD_NONE; > > + > > + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, > > + &format); > > + if (ret < 0) > > + return ret; > > + > > + dev_dbg(vsp1->dev, > > + "%s: set format %ux%u (%x) on RPF%u sink\n", > > + __func__, format.format.width, format.format.height, > > + format.format.code, rpf->entity.index); > > + > > + memset(&sel, 0, sizeof(sel)); > > + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; > > + sel.pad = RWPF_PAD_SINK; > > + sel.target = V4L2_SEL_TGT_CROP; > > + sel.r = *crop; > > + > > + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_selection, NULL, > > + &sel); > > + if (ret < 0) > > + return ret; > > + > > + dev_dbg(vsp1->dev, > > + "%s: set selection (%u,%u)/%ux%u on RPF%u sink\n", > > + __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height, > > + rpf->entity.index); > > + > > + /* > > + * RPF source, hardcode the format to ARGB8888 to turn on format > > + * conversion if needed. > > + */ > > + format.pad = RWPF_PAD_SOURCE; > > + > > + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, get_fmt, NULL, > > + &format); > > + if (ret < 0) > > + return ret; > > + > > + dev_dbg(vsp1->dev, > > + "%s: got format %ux%u (%x) on RPF%u source\n", > > + __func__, format.format.width, format.format.height, > > + format.format.code, rpf->entity.index); > > + > > + format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; > > + > > + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, > > + &format); > > + if (ret < 0) > > + return ret; > > + > > + /* BRU sink, propagate the format from the RPF source. */ > > + format.pad = bru_input; > > + > > + ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL, > > + &format); > > + if (ret < 0) > > + return ret; > > + > > + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n", > > + __func__, format.format.width, format.format.height, > > + format.format.code, BRU_NAME(pipe->bru), format.pad); > > + > > + sel.pad = bru_input; > > + sel.target = V4L2_SEL_TGT_COMPOSE; > > + sel.r = vsp1->drm->inputs[rpf->entity.index].compose; > > + > > + ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL, > > + &sel); > > + if (ret < 0) > > + return ret; > > + > > + dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n", > > + __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height, > > + BRU_NAME(pipe->bru), sel.pad); > > + > > + return 0; > > +} > > + > > +static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf > > *rpf) +{ > > + return vsp1->drm->inputs[rpf->entity.index].zpos; > > +} > > + > > +/* Setup the input side of the pipeline (RPFs and BRU sink pads). */ > > +static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1, > > Minor nit - shouldn't this be _setup_inputs(..) > as we could have multiple inputs, and it configures them all. > > > + struct vsp1_pipeline *pipe) > > +{ > > + struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, }; > > + struct vsp1_bru *bru = to_bru(&pipe->bru->subdev); > > + unsigned int i; > > + int ret; > > + > > + /* Count the number of enabled inputs and sort them by Z-order. */ > > + pipe->num_inputs = 0; > > + > > + for (i = 0; i < vsp1->info->rpf_count; ++i) { > > + struct vsp1_rwpf *rpf = vsp1->rpf[i]; > > + unsigned int j; > > + > > + /* > > + * Make sure we don't accept more inputs than the hardware can > > + * handle. This is a temporary fix to avoid display stall, we > > + * need to instead allocate the BRU or BRS to display pipelines > > + * dynamically based on the number of planes they each use. > > + */ > > + if (pipe->num_inputs >= pipe->bru->source_pad) > > + pipe->inputs[i] = NULL; > > + > > + if (!pipe->inputs[i]) > > + continue; > > + > > + /* Insert the RPF in the sorted RPFs array. */ > > + for (j = pipe->num_inputs++; j > 0; --j) { > > + if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf)) > > + break; > > + inputs[j] = inputs[j-1]; > > + } > > + > > + inputs[j] = rpf; > > + } > > + > > + /* Setup the RPF input pipeline for every enabled input. */ > > + for (i = 0; i < pipe->bru->source_pad; ++i) { > > + struct vsp1_rwpf *rpf = inputs[i]; > > + > > + if (!rpf) { > > + bru->inputs[i].rpf = NULL; > > + continue; > > + } > > + > > + if (!rpf->entity.pipe) { > > + rpf->entity.pipe = pipe; > > + list_add_tail(&rpf->entity.list_pipe, &pipe->entities); > > + } > > + > > + bru->inputs[i].rpf = rpf; > > + rpf->bru_input = i; > > + rpf->entity.sink = pipe->bru; > > + rpf->entity.sink_pad = i; > > + > > + dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n", > > + __func__, rpf->entity.index, BRU_NAME(pipe->bru), i); > > + > > + ret = vsp1_du_pipeline_setup_rpf(vsp1, pipe, rpf, i); > > + if (ret < 0) { > > + dev_err(vsp1->dev, > > + "%s: failed to setup RPF.%u\n", > > + __func__, rpf->entity.index); > > + return ret; > > + } > > + } > > + > > + return 0; > > +} > > + > > > > /* Configure all entities in the pipeline. */ > > static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe) > > { > > > > @@ -396,111 +575,6 @@ int vsp1_du_atomic_update(struct device *dev, > > unsigned int pipe_index,> > > } > > EXPORT_SYMBOL_GPL(vsp1_du_atomic_update); > > > > -static int vsp1_du_setup_rpf_pipe(struct vsp1_device *vsp1, > > - struct vsp1_pipeline *pipe, > > - struct vsp1_rwpf *rpf, unsigned int bru_input) > > -{ > > - struct v4l2_subdev_selection sel; > > - struct v4l2_subdev_format format; > > - const struct v4l2_rect *crop; > > - int ret; > > - > > - /* > > - * Configure the format on the RPF sink pad and propagate it up to the > > - * BRU sink pad. > > - */ > > - crop = &vsp1->drm->inputs[rpf->entity.index].crop; > > - > > - memset(&format, 0, sizeof(format)); > > - format.which = V4L2_SUBDEV_FORMAT_ACTIVE; > > - format.pad = RWPF_PAD_SINK; > > - format.format.width = crop->width + crop->left; > > - format.format.height = crop->height + crop->top; > > - format.format.code = rpf->fmtinfo->mbus; > > - format.format.field = V4L2_FIELD_NONE; > > - > > - ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, > > - &format); > > - if (ret < 0) > > - return ret; > > - > > - dev_dbg(vsp1->dev, > > - "%s: set format %ux%u (%x) on RPF%u sink\n", > > - __func__, format.format.width, format.format.height, > > - format.format.code, rpf->entity.index); > > - > > - memset(&sel, 0, sizeof(sel)); > > - sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; > > - sel.pad = RWPF_PAD_SINK; > > - sel.target = V4L2_SEL_TGT_CROP; > > - sel.r = *crop; > > - > > - ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_selection, NULL, > > - &sel); > > - if (ret < 0) > > - return ret; > > - > > - dev_dbg(vsp1->dev, > > - "%s: set selection (%u,%u)/%ux%u on RPF%u sink\n", > > - __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height, > > - rpf->entity.index); > > - > > - /* > > - * RPF source, hardcode the format to ARGB8888 to turn on format > > - * conversion if needed. > > - */ > > - format.pad = RWPF_PAD_SOURCE; > > - > > - ret = v4l2_subdev_call(&rpf->entity.subdev, pad, get_fmt, NULL, > > - &format); > > - if (ret < 0) > > - return ret; > > - > > - dev_dbg(vsp1->dev, > > - "%s: got format %ux%u (%x) on RPF%u source\n", > > - __func__, format.format.width, format.format.height, > > - format.format.code, rpf->entity.index); > > - > > - format.format.code = MEDIA_BUS_FMT_ARGB8888_1X32; > > - > > - ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, > > - &format); > > - if (ret < 0) > > - return ret; > > - > > - /* BRU sink, propagate the format from the RPF source. */ > > - format.pad = bru_input; > > - > > - ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL, > > - &format); > > - if (ret < 0) > > - return ret; > > - > > - dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n", > > - __func__, format.format.width, format.format.height, > > - format.format.code, BRU_NAME(pipe->bru), format.pad); > > - > > - sel.pad = bru_input; > > - sel.target = V4L2_SEL_TGT_COMPOSE; > > - sel.r = vsp1->drm->inputs[rpf->entity.index].compose; > > - > > - ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL, > > - &sel); > > - if (ret < 0) > > - return ret; > > - > > - dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n", > > - __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height, > > - BRU_NAME(pipe->bru), sel.pad); > > - > > - return 0; > > -} > > - > > -static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf > > *rpf) -{ > > - return vsp1->drm->inputs[rpf->entity.index].zpos; > > -} > > - > > > > /** > > > > * vsp1_du_atomic_flush - Commit an atomic update > > * @dev: the VSP device > > > > @@ -511,69 +585,8 @@ void vsp1_du_atomic_flush(struct device *dev, > > unsigned int pipe_index)> > > struct vsp1_device *vsp1 = dev_get_drvdata(dev); > > struct vsp1_drm_pipeline *drm_pipe = &vsp1->drm->pipe[pipe_index]; > > struct vsp1_pipeline *pipe = &drm_pipe->pipe; > > > > - struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, }; > > - struct vsp1_bru *bru = to_bru(&pipe->bru->subdev); > > - unsigned int i; > > - int ret; > > - > > - /* Count the number of enabled inputs and sort them by Z-order. */ > > - pipe->num_inputs = 0; > > - > > - for (i = 0; i < vsp1->info->rpf_count; ++i) { > > - struct vsp1_rwpf *rpf = vsp1->rpf[i]; > > - unsigned int j; > > - > > - /* > > - * Make sure we don't accept more inputs than the hardware can > > - * handle. This is a temporary fix to avoid display stall, we > > - * need to instead allocate the BRU or BRS to display pipelines > > - * dynamically based on the number of planes they each use. > > - */ > > - if (pipe->num_inputs >= pipe->bru->source_pad) > > - pipe->inputs[i] = NULL; > > - > > - if (!pipe->inputs[i]) > > - continue; > > - > > - /* Insert the RPF in the sorted RPFs array. */ > > - for (j = pipe->num_inputs++; j > 0; --j) { > > - if (rpf_zpos(vsp1, inputs[j-1]) <= rpf_zpos(vsp1, rpf)) > > - break; > > - inputs[j] = inputs[j-1]; > > - } > > - > > - inputs[j] = rpf; > > - } > > - > > - /* Setup the RPF input pipeline for every enabled input. */ > > - for (i = 0; i < pipe->bru->source_pad; ++i) { > > - struct vsp1_rwpf *rpf = inputs[i]; > > - > > - if (!rpf) { > > - bru->inputs[i].rpf = NULL; > > - continue; > > - } > > - > > - if (!rpf->entity.pipe) { > > - rpf->entity.pipe = pipe; > > - list_add_tail(&rpf->entity.list_pipe, &pipe->entities); > > - } > > - > > - bru->inputs[i].rpf = rpf; > > - rpf->bru_input = i; > > - rpf->entity.sink = pipe->bru; > > - rpf->entity.sink_pad = i; > > - > > - dev_dbg(vsp1->dev, "%s: connecting RPF.%u to %s:%u\n", > > - __func__, rpf->entity.index, BRU_NAME(pipe->bru), i); > > - > > - ret = vsp1_du_setup_rpf_pipe(vsp1, pipe, rpf, i); > > - if (ret < 0) > > - dev_err(vsp1->dev, > > - "%s: failed to setup RPF.%u\n", > > - __func__, rpf->entity.index); > > - } > > > > + vsp1_du_pipeline_setup_input(vsp1, pipe); > > > > vsp1_du_pipeline_configure(pipe); > > > > } > > EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush); -- Regards, Laurent Pinchart From mboxrd@z Thu Jan 1 00:00:00 1970 From: Laurent Pinchart Subject: Re: [PATCH 07/15] v4l: vsp1: Move DRM atomic commit pipeline setup to separate function Date: Thu, 29 Mar 2018 10:08:35 +0300 Message-ID: <2427732.6RX94pHpa3@avalon> References: <20180226214516.11559-1-laurent.pinchart+renesas@ideasonboard.com> <20180226214516.11559-8-laurent.pinchart+renesas@ideasonboard.com> <80250bdd-dda3-5a2f-02e8-1121197949f5@ideasonboard.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from galahad.ideasonboard.com (galahad.ideasonboard.com [185.26.127.97]) by gabe.freedesktop.org (Postfix) with ESMTPS id 324396E01F for ; Thu, 29 Mar 2018 07:08:35 +0000 (UTC) In-Reply-To: <80250bdd-dda3-5a2f-02e8-1121197949f5@ideasonboard.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Kieran Bingham Cc: linux-renesas-soc@vger.kernel.org, Laurent Pinchart , dri-devel@lists.freedesktop.org, linux-media@vger.kernel.org List-Id: dri-devel@lists.freedesktop.org SGkgS2llcmFuLAoKT24gV2VkbmVzZGF5LCAyOCBNYXJjaCAyMDE4IDE3OjQzOjEzIEVFU1QgS2ll cmFuIEJpbmdoYW0gd3JvdGU6Cj4gT24gMjYvMDIvMTggMjE6NDUsIExhdXJlbnQgUGluY2hhcnQg d3JvdGU6Cj4gPiBUaGUgRFJNIHBpcGVsaW5lIHNldHVwIGNvZGUgdXNlZCBhdCBhdG9taWMgY29t bWl0IHRpbWUgaXMgc2ltaWxhciB0byB0aGUKPiA+IHNldHVwIGNvZGUgdXNlZCB3aGVuIGVuYWJs aW5nIHRoZSBwaXBlbGluZS4gTW92ZSBpdCB0byBhIHNlcGFyYXRlCj4gPiBmdW5jdGlvbiBpbiBv cmRlciB0byBzaGFyZSBpdC4KPiA+IAo+ID4gU2lnbmVkLW9mZi1ieTogTGF1cmVudCBQaW5jaGFy dAo+ID4gPGxhdXJlbnQucGluY2hhcnQrcmVuZXNhc0BpZGVhc29uYm9hcmQuY29tPgo+IAo+IEFz c3VtaW5nIG5vIGhpZGRlbiBzZWNyZXQgY29kZSBhZGRpdGlvbiBpbiB0aGlzIGNvZGUgbW92ZSB0 aGF0IEkgaGF2ZW4ndAo+IHNlZW4uLgo+IAo+IE9ubHkgYSBtaW5vciBuaXQgYmVsb3cgYXNraW5n IGlmIHRoZSBmdW5jdGlvbiBzaG91bGQgYmUgcGx1cmFsaXNlZCAoX2lucHV0cywKPiByYXRoZXIg dGhhbiBfaW5wdXQpCgpJJ2xsIGZpeCB0aGF0IGluIHYyLCB0aGFua3MuCgo+IFJldmlld2VkLWJ5 OiBLaWVyYW4gQmluZ2hhbSA8a2llcmFuLmJpbmdoYW0rcmVuZXNhc0BpZGVhc29uYm9hcmQuY29t Pgo+IAo+ID4gLS0tCj4gPiAKPiA+ICBkcml2ZXJzL21lZGlhL3BsYXRmb3JtL3ZzcDEvdnNwMV9k cm0uYyB8IDM0Nwo+ID4gICsrKysrKysrKysrKysrKysrLS0tLS0tLS0tLS0tLS0tLSAxIGZpbGUg Y2hhbmdlZCwgMTgwIGluc2VydGlvbnMoKyksIDE2Nwo+ID4gIGRlbGV0aW9ucygtKQo+ID4gCj4g PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS92c3AxL3ZzcDFfZHJtLmMKPiA+ IGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS92c3AxL3ZzcDFfZHJtLmMgaW5kZXggOWEwNDNhOTE1 YzBiLi43YmY2OTdiYTc5NjkKPiA+IDEwMDY0NAo+ID4gLS0tIGEvZHJpdmVycy9tZWRpYS9wbGF0 Zm9ybS92c3AxL3ZzcDFfZHJtLmMKPiA+ICsrKyBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vdnNw MS92c3AxX2RybS5jCj4gPiBAQCAtNDYsNiArNDYsMTg1IEBAIHN0YXRpYyB2b2lkIHZzcDFfZHVf cGlwZWxpbmVfZnJhbWVfZW5kKHN0cnVjdAo+ID4gdnNwMV9waXBlbGluZSAqcGlwZSw+IAo+ID4g ICAqIFBpcGVsaW5lIENvbmZpZ3VyYXRpb24KPiA+ICAgKi8KPiA+IAo+ID4gKy8qIFNldHVwIG9u ZSBSUEYgYW5kIHRoZSBjb25uZWN0ZWQgQlJVIHNpbmsgcGFkLiAqLwo+ID4gK3N0YXRpYyBpbnQg dnNwMV9kdV9waXBlbGluZV9zZXR1cF9ycGYoc3RydWN0IHZzcDFfZGV2aWNlICp2c3AxLAo+ID4g KwkJCQkgICAgICBzdHJ1Y3QgdnNwMV9waXBlbGluZSAqcGlwZSwKPiA+ICsJCQkJICAgICAgc3Ry dWN0IHZzcDFfcndwZiAqcnBmLAo+ID4gKwkJCQkgICAgICB1bnNpZ25lZCBpbnQgYnJ1X2lucHV0 KQo+ID4gK3sKPiA+ICsJc3RydWN0IHY0bDJfc3ViZGV2X3NlbGVjdGlvbiBzZWw7Cj4gPiArCXN0 cnVjdCB2NGwyX3N1YmRldl9mb3JtYXQgZm9ybWF0Owo+ID4gKwljb25zdCBzdHJ1Y3QgdjRsMl9y ZWN0ICpjcm9wOwo+ID4gKwlpbnQgcmV0Owo+ID4gKwo+ID4gKwkvKgo+ID4gKwkgKiBDb25maWd1 cmUgdGhlIGZvcm1hdCBvbiB0aGUgUlBGIHNpbmsgcGFkIGFuZCBwcm9wYWdhdGUgaXQgdXAgdG8g dGhlCj4gPiArCSAqIEJSVSBzaW5rIHBhZC4KPiA+ICsJICovCj4gPiArCWNyb3AgPSAmdnNwMS0+ ZHJtLT5pbnB1dHNbcnBmLT5lbnRpdHkuaW5kZXhdLmNyb3A7Cj4gPiArCj4gPiArCW1lbXNldCgm Zm9ybWF0LCAwLCBzaXplb2YoZm9ybWF0KSk7Cj4gPiArCWZvcm1hdC53aGljaCA9IFY0TDJfU1VC REVWX0ZPUk1BVF9BQ1RJVkU7Cj4gPiArCWZvcm1hdC5wYWQgPSBSV1BGX1BBRF9TSU5LOwo+ID4g Kwlmb3JtYXQuZm9ybWF0LndpZHRoID0gY3JvcC0+d2lkdGggKyBjcm9wLT5sZWZ0Owo+ID4gKwlm b3JtYXQuZm9ybWF0LmhlaWdodCA9IGNyb3AtPmhlaWdodCArIGNyb3AtPnRvcDsKPiA+ICsJZm9y bWF0LmZvcm1hdC5jb2RlID0gcnBmLT5mbXRpbmZvLT5tYnVzOwo+ID4gKwlmb3JtYXQuZm9ybWF0 LmZpZWxkID0gVjRMMl9GSUVMRF9OT05FOwo+ID4gKwo+ID4gKwlyZXQgPSB2NGwyX3N1YmRldl9j YWxsKCZycGYtPmVudGl0eS5zdWJkZXYsIHBhZCwgc2V0X2ZtdCwgTlVMTCwKPiA+ICsJCQkgICAg ICAgJmZvcm1hdCk7Cj4gPiArCWlmIChyZXQgPCAwKQo+ID4gKwkJcmV0dXJuIHJldDsKPiA+ICsK PiA+ICsJZGV2X2RiZyh2c3AxLT5kZXYsCj4gPiArCQkiJXM6IHNldCBmb3JtYXQgJXV4JXUgKCV4 KSBvbiBSUEYldSBzaW5rXG4iLAo+ID4gKwkJX19mdW5jX18sIGZvcm1hdC5mb3JtYXQud2lkdGgs IGZvcm1hdC5mb3JtYXQuaGVpZ2h0LAo+ID4gKwkJZm9ybWF0LmZvcm1hdC5jb2RlLCBycGYtPmVu dGl0eS5pbmRleCk7Cj4gPiArCj4gPiArCW1lbXNldCgmc2VsLCAwLCBzaXplb2Yoc2VsKSk7Cj4g PiArCXNlbC53aGljaCA9IFY0TDJfU1VCREVWX0ZPUk1BVF9BQ1RJVkU7Cj4gPiArCXNlbC5wYWQg PSBSV1BGX1BBRF9TSU5LOwo+ID4gKwlzZWwudGFyZ2V0ID0gVjRMMl9TRUxfVEdUX0NST1A7Cj4g PiArCXNlbC5yID0gKmNyb3A7Cj4gPiArCj4gPiArCXJldCA9IHY0bDJfc3ViZGV2X2NhbGwoJnJw Zi0+ZW50aXR5LnN1YmRldiwgcGFkLCBzZXRfc2VsZWN0aW9uLCBOVUxMLAo+ID4gKwkJCSAgICAg ICAmc2VsKTsKPiA+ICsJaWYgKHJldCA8IDApCj4gPiArCQlyZXR1cm4gcmV0Owo+ID4gKwo+ID4g KwlkZXZfZGJnKHZzcDEtPmRldiwKPiA+ICsJCSIlczogc2V0IHNlbGVjdGlvbiAoJXUsJXUpLyV1 eCV1IG9uIFJQRiV1IHNpbmtcbiIsCj4gPiArCQlfX2Z1bmNfXywgc2VsLnIubGVmdCwgc2VsLnIu dG9wLCBzZWwuci53aWR0aCwgc2VsLnIuaGVpZ2h0LAo+ID4gKwkJcnBmLT5lbnRpdHkuaW5kZXgp Owo+ID4gKwo+ID4gKwkvKgo+ID4gKwkgKiBSUEYgc291cmNlLCBoYXJkY29kZSB0aGUgZm9ybWF0 IHRvIEFSR0I4ODg4IHRvIHR1cm4gb24gZm9ybWF0Cj4gPiArCSAqIGNvbnZlcnNpb24gaWYgbmVl ZGVkLgo+ID4gKwkgKi8KPiA+ICsJZm9ybWF0LnBhZCA9IFJXUEZfUEFEX1NPVVJDRTsKPiA+ICsK PiA+ICsJcmV0ID0gdjRsMl9zdWJkZXZfY2FsbCgmcnBmLT5lbnRpdHkuc3ViZGV2LCBwYWQsIGdl dF9mbXQsIE5VTEwsCj4gPiArCQkJICAgICAgICZmb3JtYXQpOwo+ID4gKwlpZiAocmV0IDwgMCkK PiA+ICsJCXJldHVybiByZXQ7Cj4gPiArCj4gPiArCWRldl9kYmcodnNwMS0+ZGV2LAo+ID4gKwkJ IiVzOiBnb3QgZm9ybWF0ICV1eCV1ICgleCkgb24gUlBGJXUgc291cmNlXG4iLAo+ID4gKwkJX19m dW5jX18sIGZvcm1hdC5mb3JtYXQud2lkdGgsIGZvcm1hdC5mb3JtYXQuaGVpZ2h0LAo+ID4gKwkJ Zm9ybWF0LmZvcm1hdC5jb2RlLCBycGYtPmVudGl0eS5pbmRleCk7Cj4gPiArCj4gPiArCWZvcm1h dC5mb3JtYXQuY29kZSA9IE1FRElBX0JVU19GTVRfQVJHQjg4ODhfMVgzMjsKPiA+ICsKPiA+ICsJ cmV0ID0gdjRsMl9zdWJkZXZfY2FsbCgmcnBmLT5lbnRpdHkuc3ViZGV2LCBwYWQsIHNldF9mbXQs IE5VTEwsCj4gPiArCQkJICAgICAgICZmb3JtYXQpOwo+ID4gKwlpZiAocmV0IDwgMCkKPiA+ICsJ CXJldHVybiByZXQ7Cj4gPiArCj4gPiArCS8qIEJSVSBzaW5rLCBwcm9wYWdhdGUgdGhlIGZvcm1h dCBmcm9tIHRoZSBSUEYgc291cmNlLiAqLwo+ID4gKwlmb3JtYXQucGFkID0gYnJ1X2lucHV0Owo+ ID4gKwo+ID4gKwlyZXQgPSB2NGwyX3N1YmRldl9jYWxsKCZwaXBlLT5icnUtPnN1YmRldiwgcGFk LCBzZXRfZm10LCBOVUxMLAo+ID4gKwkJCSAgICAgICAmZm9ybWF0KTsKPiA+ICsJaWYgKHJldCA8 IDApCj4gPiArCQlyZXR1cm4gcmV0Owo+ID4gKwo+ID4gKwlkZXZfZGJnKHZzcDEtPmRldiwgIiVz OiBzZXQgZm9ybWF0ICV1eCV1ICgleCkgb24gJXMgcGFkICV1XG4iLAo+ID4gKwkJX19mdW5jX18s IGZvcm1hdC5mb3JtYXQud2lkdGgsIGZvcm1hdC5mb3JtYXQuaGVpZ2h0LAo+ID4gKwkJZm9ybWF0 LmZvcm1hdC5jb2RlLCBCUlVfTkFNRShwaXBlLT5icnUpLCBmb3JtYXQucGFkKTsKPiA+ICsKPiA+ ICsJc2VsLnBhZCA9IGJydV9pbnB1dDsKPiA+ICsJc2VsLnRhcmdldCA9IFY0TDJfU0VMX1RHVF9D T01QT1NFOwo+ID4gKwlzZWwuciA9IHZzcDEtPmRybS0+aW5wdXRzW3JwZi0+ZW50aXR5LmluZGV4 XS5jb21wb3NlOwo+ID4gKwo+ID4gKwlyZXQgPSB2NGwyX3N1YmRldl9jYWxsKCZwaXBlLT5icnUt PnN1YmRldiwgcGFkLCBzZXRfc2VsZWN0aW9uLCBOVUxMLAo+ID4gKwkJCSAgICAgICAmc2VsKTsK PiA+ICsJaWYgKHJldCA8IDApCj4gPiArCQlyZXR1cm4gcmV0Owo+ID4gKwo+ID4gKwlkZXZfZGJn KHZzcDEtPmRldiwgIiVzOiBzZXQgc2VsZWN0aW9uICgldSwldSkvJXV4JXUgb24gJXMgcGFkICV1 XG4iLAo+ID4gKwkJX19mdW5jX18sIHNlbC5yLmxlZnQsIHNlbC5yLnRvcCwgc2VsLnIud2lkdGgs IHNlbC5yLmhlaWdodCwKPiA+ICsJCUJSVV9OQU1FKHBpcGUtPmJydSksIHNlbC5wYWQpOwo+ID4g Kwo+ID4gKwlyZXR1cm4gMDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIHVuc2lnbmVkIGludCBy cGZfenBvcyhzdHJ1Y3QgdnNwMV9kZXZpY2UgKnZzcDEsIHN0cnVjdCB2c3AxX3J3cGYKPiA+ICpy cGYpICt7Cj4gPiArCXJldHVybiB2c3AxLT5kcm0tPmlucHV0c1tycGYtPmVudGl0eS5pbmRleF0u enBvczsKPiA+ICt9Cj4gPiArCj4gPiArLyogU2V0dXAgdGhlIGlucHV0IHNpZGUgb2YgdGhlIHBp cGVsaW5lIChSUEZzIGFuZCBCUlUgc2luayBwYWRzKS4gKi8KPiA+ICtzdGF0aWMgaW50IHZzcDFf ZHVfcGlwZWxpbmVfc2V0dXBfaW5wdXQoc3RydWN0IHZzcDFfZGV2aWNlICp2c3AxLAo+IAo+IE1p bm9yIG5pdCAtIHNob3VsZG4ndCB0aGlzIGJlIF9zZXR1cF9pbnB1dHMoLi4pCj4gYXMgd2UgY291 bGQgaGF2ZSBtdWx0aXBsZSBpbnB1dHMsIGFuZCBpdCBjb25maWd1cmVzIHRoZW0gYWxsLgo+IAo+ ID4gKwkJCQkJc3RydWN0IHZzcDFfcGlwZWxpbmUgKnBpcGUpCj4gPiArewo+ID4gKwlzdHJ1Y3Qg dnNwMV9yd3BmICppbnB1dHNbVlNQMV9NQVhfUlBGXSA9IHsgTlVMTCwgfTsKPiA+ICsJc3RydWN0 IHZzcDFfYnJ1ICpicnUgPSB0b19icnUoJnBpcGUtPmJydS0+c3ViZGV2KTsKPiA+ICsJdW5zaWdu ZWQgaW50IGk7Cj4gPiArCWludCByZXQ7Cj4gPiArCj4gPiArCS8qIENvdW50IHRoZSBudW1iZXIg b2YgZW5hYmxlZCBpbnB1dHMgYW5kIHNvcnQgdGhlbSBieSBaLW9yZGVyLiAqLwo+ID4gKwlwaXBl LT5udW1faW5wdXRzID0gMDsKPiA+ICsKPiA+ICsJZm9yIChpID0gMDsgaSA8IHZzcDEtPmluZm8t PnJwZl9jb3VudDsgKytpKSB7Cj4gPiArCQlzdHJ1Y3QgdnNwMV9yd3BmICpycGYgPSB2c3AxLT5y cGZbaV07Cj4gPiArCQl1bnNpZ25lZCBpbnQgajsKPiA+ICsKPiA+ICsJCS8qCj4gPiArCQkgKiBN YWtlIHN1cmUgd2UgZG9uJ3QgYWNjZXB0IG1vcmUgaW5wdXRzIHRoYW4gdGhlIGhhcmR3YXJlIGNh bgo+ID4gKwkJICogaGFuZGxlLiBUaGlzIGlzIGEgdGVtcG9yYXJ5IGZpeCB0byBhdm9pZCBkaXNw bGF5IHN0YWxsLCB3ZQo+ID4gKwkJICogbmVlZCB0byBpbnN0ZWFkIGFsbG9jYXRlIHRoZSBCUlUg b3IgQlJTIHRvIGRpc3BsYXkgcGlwZWxpbmVzCj4gPiArCQkgKiBkeW5hbWljYWxseSBiYXNlZCBv biB0aGUgbnVtYmVyIG9mIHBsYW5lcyB0aGV5IGVhY2ggdXNlLgo+ID4gKwkJICovCj4gPiArCQlp ZiAocGlwZS0+bnVtX2lucHV0cyA+PSBwaXBlLT5icnUtPnNvdXJjZV9wYWQpCj4gPiArCQkJcGlw ZS0+aW5wdXRzW2ldID0gTlVMTDsKPiA+ICsKPiA+ICsJCWlmICghcGlwZS0+aW5wdXRzW2ldKQo+ ID4gKwkJCWNvbnRpbnVlOwo+ID4gKwo+ID4gKwkJLyogSW5zZXJ0IHRoZSBSUEYgaW4gdGhlIHNv cnRlZCBSUEZzIGFycmF5LiAqLwo+ID4gKwkJZm9yIChqID0gcGlwZS0+bnVtX2lucHV0cysrOyBq ID4gMDsgLS1qKSB7Cj4gPiArCQkJaWYgKHJwZl96cG9zKHZzcDEsIGlucHV0c1tqLTFdKSA8PSBy cGZfenBvcyh2c3AxLCBycGYpKQo+ID4gKwkJCQlicmVhazsKPiA+ICsJCQlpbnB1dHNbal0gPSBp bnB1dHNbai0xXTsKPiA+ICsJCX0KPiA+ICsKPiA+ICsJCWlucHV0c1tqXSA9IHJwZjsKPiA+ICsJ fQo+ID4gKwo+ID4gKwkvKiBTZXR1cCB0aGUgUlBGIGlucHV0IHBpcGVsaW5lIGZvciBldmVyeSBl bmFibGVkIGlucHV0LiAqLwo+ID4gKwlmb3IgKGkgPSAwOyBpIDwgcGlwZS0+YnJ1LT5zb3VyY2Vf cGFkOyArK2kpIHsKPiA+ICsJCXN0cnVjdCB2c3AxX3J3cGYgKnJwZiA9IGlucHV0c1tpXTsKPiA+ ICsKPiA+ICsJCWlmICghcnBmKSB7Cj4gPiArCQkJYnJ1LT5pbnB1dHNbaV0ucnBmID0gTlVMTDsK PiA+ICsJCQljb250aW51ZTsKPiA+ICsJCX0KPiA+ICsKPiA+ICsJCWlmICghcnBmLT5lbnRpdHku cGlwZSkgewo+ID4gKwkJCXJwZi0+ZW50aXR5LnBpcGUgPSBwaXBlOwo+ID4gKwkJCWxpc3RfYWRk X3RhaWwoJnJwZi0+ZW50aXR5Lmxpc3RfcGlwZSwgJnBpcGUtPmVudGl0aWVzKTsKPiA+ICsJCX0K PiA+ICsKPiA+ICsJCWJydS0+aW5wdXRzW2ldLnJwZiA9IHJwZjsKPiA+ICsJCXJwZi0+YnJ1X2lu cHV0ID0gaTsKPiA+ICsJCXJwZi0+ZW50aXR5LnNpbmsgPSBwaXBlLT5icnU7Cj4gPiArCQlycGYt PmVudGl0eS5zaW5rX3BhZCA9IGk7Cj4gPiArCj4gPiArCQlkZXZfZGJnKHZzcDEtPmRldiwgIiVz OiBjb25uZWN0aW5nIFJQRi4ldSB0byAlczoldVxuIiwKPiA+ICsJCQlfX2Z1bmNfXywgcnBmLT5l bnRpdHkuaW5kZXgsIEJSVV9OQU1FKHBpcGUtPmJydSksIGkpOwo+ID4gKwo+ID4gKwkJcmV0ID0g dnNwMV9kdV9waXBlbGluZV9zZXR1cF9ycGYodnNwMSwgcGlwZSwgcnBmLCBpKTsKPiA+ICsJCWlm IChyZXQgPCAwKSB7Cj4gPiArCQkJZGV2X2Vycih2c3AxLT5kZXYsCj4gPiArCQkJCSIlczogZmFp bGVkIHRvIHNldHVwIFJQRi4ldVxuIiwKPiA+ICsJCQkJX19mdW5jX18sIHJwZi0+ZW50aXR5Lmlu ZGV4KTsKPiA+ICsJCQlyZXR1cm4gcmV0Owo+ID4gKwkJfQo+ID4gKwl9Cj4gPiArCj4gPiArCXJl dHVybiAwOwo+ID4gK30KPiA+ICsKPiA+IAo+ID4gIC8qIENvbmZpZ3VyZSBhbGwgZW50aXRpZXMg aW4gdGhlIHBpcGVsaW5lLiAqLwo+ID4gIHN0YXRpYyB2b2lkIHZzcDFfZHVfcGlwZWxpbmVfY29u ZmlndXJlKHN0cnVjdCB2c3AxX3BpcGVsaW5lICpwaXBlKQo+ID4gIHsKPiA+IAo+ID4gQEAgLTM5 NiwxMTEgKzU3NSw2IEBAIGludCB2c3AxX2R1X2F0b21pY191cGRhdGUoc3RydWN0IGRldmljZSAq ZGV2LAo+ID4gdW5zaWduZWQgaW50IHBpcGVfaW5kZXgsPiAKPiA+ICB9Cj4gPiAgRVhQT1JUX1NZ TUJPTF9HUEwodnNwMV9kdV9hdG9taWNfdXBkYXRlKTsKPiA+IAo+ID4gLXN0YXRpYyBpbnQgdnNw MV9kdV9zZXR1cF9ycGZfcGlwZShzdHJ1Y3QgdnNwMV9kZXZpY2UgKnZzcDEsCj4gPiAtCQkJCSAg c3RydWN0IHZzcDFfcGlwZWxpbmUgKnBpcGUsCj4gPiAtCQkJCSAgc3RydWN0IHZzcDFfcndwZiAq cnBmLCB1bnNpZ25lZCBpbnQgYnJ1X2lucHV0KQo+ID4gLXsKPiA+IC0Jc3RydWN0IHY0bDJfc3Vi ZGV2X3NlbGVjdGlvbiBzZWw7Cj4gPiAtCXN0cnVjdCB2NGwyX3N1YmRldl9mb3JtYXQgZm9ybWF0 Owo+ID4gLQljb25zdCBzdHJ1Y3QgdjRsMl9yZWN0ICpjcm9wOwo+ID4gLQlpbnQgcmV0Owo+ID4g LQo+ID4gLQkvKgo+ID4gLQkgKiBDb25maWd1cmUgdGhlIGZvcm1hdCBvbiB0aGUgUlBGIHNpbmsg cGFkIGFuZCBwcm9wYWdhdGUgaXQgdXAgdG8gdGhlCj4gPiAtCSAqIEJSVSBzaW5rIHBhZC4KPiA+ IC0JICovCj4gPiAtCWNyb3AgPSAmdnNwMS0+ZHJtLT5pbnB1dHNbcnBmLT5lbnRpdHkuaW5kZXhd LmNyb3A7Cj4gPiAtCj4gPiAtCW1lbXNldCgmZm9ybWF0LCAwLCBzaXplb2YoZm9ybWF0KSk7Cj4g PiAtCWZvcm1hdC53aGljaCA9IFY0TDJfU1VCREVWX0ZPUk1BVF9BQ1RJVkU7Cj4gPiAtCWZvcm1h dC5wYWQgPSBSV1BGX1BBRF9TSU5LOwo+ID4gLQlmb3JtYXQuZm9ybWF0LndpZHRoID0gY3JvcC0+ d2lkdGggKyBjcm9wLT5sZWZ0Owo+ID4gLQlmb3JtYXQuZm9ybWF0LmhlaWdodCA9IGNyb3AtPmhl aWdodCArIGNyb3AtPnRvcDsKPiA+IC0JZm9ybWF0LmZvcm1hdC5jb2RlID0gcnBmLT5mbXRpbmZv LT5tYnVzOwo+ID4gLQlmb3JtYXQuZm9ybWF0LmZpZWxkID0gVjRMMl9GSUVMRF9OT05FOwo+ID4g LQo+ID4gLQlyZXQgPSB2NGwyX3N1YmRldl9jYWxsKCZycGYtPmVudGl0eS5zdWJkZXYsIHBhZCwg c2V0X2ZtdCwgTlVMTCwKPiA+IC0JCQkgICAgICAgJmZvcm1hdCk7Cj4gPiAtCWlmIChyZXQgPCAw KQo+ID4gLQkJcmV0dXJuIHJldDsKPiA+IC0KPiA+IC0JZGV2X2RiZyh2c3AxLT5kZXYsCj4gPiAt CQkiJXM6IHNldCBmb3JtYXQgJXV4JXUgKCV4KSBvbiBSUEYldSBzaW5rXG4iLAo+ID4gLQkJX19m dW5jX18sIGZvcm1hdC5mb3JtYXQud2lkdGgsIGZvcm1hdC5mb3JtYXQuaGVpZ2h0LAo+ID4gLQkJ Zm9ybWF0LmZvcm1hdC5jb2RlLCBycGYtPmVudGl0eS5pbmRleCk7Cj4gPiAtCj4gPiAtCW1lbXNl dCgmc2VsLCAwLCBzaXplb2Yoc2VsKSk7Cj4gPiAtCXNlbC53aGljaCA9IFY0TDJfU1VCREVWX0ZP Uk1BVF9BQ1RJVkU7Cj4gPiAtCXNlbC5wYWQgPSBSV1BGX1BBRF9TSU5LOwo+ID4gLQlzZWwudGFy Z2V0ID0gVjRMMl9TRUxfVEdUX0NST1A7Cj4gPiAtCXNlbC5yID0gKmNyb3A7Cj4gPiAtCj4gPiAt CXJldCA9IHY0bDJfc3ViZGV2X2NhbGwoJnJwZi0+ZW50aXR5LnN1YmRldiwgcGFkLCBzZXRfc2Vs ZWN0aW9uLCBOVUxMLAo+ID4gLQkJCSAgICAgICAmc2VsKTsKPiA+IC0JaWYgKHJldCA8IDApCj4g PiAtCQlyZXR1cm4gcmV0Owo+ID4gLQo+ID4gLQlkZXZfZGJnKHZzcDEtPmRldiwKPiA+IC0JCSIl czogc2V0IHNlbGVjdGlvbiAoJXUsJXUpLyV1eCV1IG9uIFJQRiV1IHNpbmtcbiIsCj4gPiAtCQlf X2Z1bmNfXywgc2VsLnIubGVmdCwgc2VsLnIudG9wLCBzZWwuci53aWR0aCwgc2VsLnIuaGVpZ2h0 LAo+ID4gLQkJcnBmLT5lbnRpdHkuaW5kZXgpOwo+ID4gLQo+ID4gLQkvKgo+ID4gLQkgKiBSUEYg c291cmNlLCBoYXJkY29kZSB0aGUgZm9ybWF0IHRvIEFSR0I4ODg4IHRvIHR1cm4gb24gZm9ybWF0 Cj4gPiAtCSAqIGNvbnZlcnNpb24gaWYgbmVlZGVkLgo+ID4gLQkgKi8KPiA+IC0JZm9ybWF0LnBh ZCA9IFJXUEZfUEFEX1NPVVJDRTsKPiA+IC0KPiA+IC0JcmV0ID0gdjRsMl9zdWJkZXZfY2FsbCgm cnBmLT5lbnRpdHkuc3ViZGV2LCBwYWQsIGdldF9mbXQsIE5VTEwsCj4gPiAtCQkJICAgICAgICZm b3JtYXQpOwo+ID4gLQlpZiAocmV0IDwgMCkKPiA+IC0JCXJldHVybiByZXQ7Cj4gPiAtCj4gPiAt CWRldl9kYmcodnNwMS0+ZGV2LAo+ID4gLQkJIiVzOiBnb3QgZm9ybWF0ICV1eCV1ICgleCkgb24g UlBGJXUgc291cmNlXG4iLAo+ID4gLQkJX19mdW5jX18sIGZvcm1hdC5mb3JtYXQud2lkdGgsIGZv cm1hdC5mb3JtYXQuaGVpZ2h0LAo+ID4gLQkJZm9ybWF0LmZvcm1hdC5jb2RlLCBycGYtPmVudGl0 eS5pbmRleCk7Cj4gPiAtCj4gPiAtCWZvcm1hdC5mb3JtYXQuY29kZSA9IE1FRElBX0JVU19GTVRf QVJHQjg4ODhfMVgzMjsKPiA+IC0KPiA+IC0JcmV0ID0gdjRsMl9zdWJkZXZfY2FsbCgmcnBmLT5l bnRpdHkuc3ViZGV2LCBwYWQsIHNldF9mbXQsIE5VTEwsCj4gPiAtCQkJICAgICAgICZmb3JtYXQp Owo+ID4gLQlpZiAocmV0IDwgMCkKPiA+IC0JCXJldHVybiByZXQ7Cj4gPiAtCj4gPiAtCS8qIEJS VSBzaW5rLCBwcm9wYWdhdGUgdGhlIGZvcm1hdCBmcm9tIHRoZSBSUEYgc291cmNlLiAqLwo+ID4g LQlmb3JtYXQucGFkID0gYnJ1X2lucHV0Owo+ID4gLQo+ID4gLQlyZXQgPSB2NGwyX3N1YmRldl9j YWxsKCZwaXBlLT5icnUtPnN1YmRldiwgcGFkLCBzZXRfZm10LCBOVUxMLAo+ID4gLQkJCSAgICAg ICAmZm9ybWF0KTsKPiA+IC0JaWYgKHJldCA8IDApCj4gPiAtCQlyZXR1cm4gcmV0Owo+ID4gLQo+ ID4gLQlkZXZfZGJnKHZzcDEtPmRldiwgIiVzOiBzZXQgZm9ybWF0ICV1eCV1ICgleCkgb24gJXMg cGFkICV1XG4iLAo+ID4gLQkJX19mdW5jX18sIGZvcm1hdC5mb3JtYXQud2lkdGgsIGZvcm1hdC5m b3JtYXQuaGVpZ2h0LAo+ID4gLQkJZm9ybWF0LmZvcm1hdC5jb2RlLCBCUlVfTkFNRShwaXBlLT5i cnUpLCBmb3JtYXQucGFkKTsKPiA+IC0KPiA+IC0Jc2VsLnBhZCA9IGJydV9pbnB1dDsKPiA+IC0J c2VsLnRhcmdldCA9IFY0TDJfU0VMX1RHVF9DT01QT1NFOwo+ID4gLQlzZWwuciA9IHZzcDEtPmRy bS0+aW5wdXRzW3JwZi0+ZW50aXR5LmluZGV4XS5jb21wb3NlOwo+ID4gLQo+ID4gLQlyZXQgPSB2 NGwyX3N1YmRldl9jYWxsKCZwaXBlLT5icnUtPnN1YmRldiwgcGFkLCBzZXRfc2VsZWN0aW9uLCBO VUxMLAo+ID4gLQkJCSAgICAgICAmc2VsKTsKPiA+IC0JaWYgKHJldCA8IDApCj4gPiAtCQlyZXR1 cm4gcmV0Owo+ID4gLQo+ID4gLQlkZXZfZGJnKHZzcDEtPmRldiwgIiVzOiBzZXQgc2VsZWN0aW9u ICgldSwldSkvJXV4JXUgb24gJXMgcGFkICV1XG4iLAo+ID4gLQkJX19mdW5jX18sIHNlbC5yLmxl ZnQsIHNlbC5yLnRvcCwgc2VsLnIud2lkdGgsIHNlbC5yLmhlaWdodCwKPiA+IC0JCUJSVV9OQU1F KHBpcGUtPmJydSksIHNlbC5wYWQpOwo+ID4gLQo+ID4gLQlyZXR1cm4gMDsKPiA+IC19Cj4gPiAt Cj4gPiAtc3RhdGljIHVuc2lnbmVkIGludCBycGZfenBvcyhzdHJ1Y3QgdnNwMV9kZXZpY2UgKnZz cDEsIHN0cnVjdCB2c3AxX3J3cGYKPiA+ICpycGYpIC17Cj4gPiAtCXJldHVybiB2c3AxLT5kcm0t PmlucHV0c1tycGYtPmVudGl0eS5pbmRleF0uenBvczsKPiA+IC19Cj4gPiAtCj4gPiAKPiA+ICAv KioKPiA+ICAKPiA+ICAgKiB2c3AxX2R1X2F0b21pY19mbHVzaCAtIENvbW1pdCBhbiBhdG9taWMg dXBkYXRlCj4gPiAgICogQGRldjogdGhlIFZTUCBkZXZpY2UKPiA+IAo+ID4gQEAgLTUxMSw2OSAr NTg1LDggQEAgdm9pZCB2c3AxX2R1X2F0b21pY19mbHVzaChzdHJ1Y3QgZGV2aWNlICpkZXYsCj4g PiB1bnNpZ25lZCBpbnQgcGlwZV9pbmRleCk+IAo+ID4gIAlzdHJ1Y3QgdnNwMV9kZXZpY2UgKnZz cDEgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiA+ICAJc3RydWN0IHZzcDFfZHJtX3BpcGVsaW5l ICpkcm1fcGlwZSA9ICZ2c3AxLT5kcm0tPnBpcGVbcGlwZV9pbmRleF07Cj4gPiAgCXN0cnVjdCB2 c3AxX3BpcGVsaW5lICpwaXBlID0gJmRybV9waXBlLT5waXBlOwo+ID4gCj4gPiAtCXN0cnVjdCB2 c3AxX3J3cGYgKmlucHV0c1tWU1AxX01BWF9SUEZdID0geyBOVUxMLCB9Owo+ID4gLQlzdHJ1Y3Qg dnNwMV9icnUgKmJydSA9IHRvX2JydSgmcGlwZS0+YnJ1LT5zdWJkZXYpOwo+ID4gLQl1bnNpZ25l ZCBpbnQgaTsKPiA+IC0JaW50IHJldDsKPiA+IC0KPiA+IC0JLyogQ291bnQgdGhlIG51bWJlciBv ZiBlbmFibGVkIGlucHV0cyBhbmQgc29ydCB0aGVtIGJ5IFotb3JkZXIuICovCj4gPiAtCXBpcGUt Pm51bV9pbnB1dHMgPSAwOwo+ID4gLQo+ID4gLQlmb3IgKGkgPSAwOyBpIDwgdnNwMS0+aW5mby0+ cnBmX2NvdW50OyArK2kpIHsKPiA+IC0JCXN0cnVjdCB2c3AxX3J3cGYgKnJwZiA9IHZzcDEtPnJw ZltpXTsKPiA+IC0JCXVuc2lnbmVkIGludCBqOwo+ID4gLQo+ID4gLQkJLyoKPiA+IC0JCSAqIE1h a2Ugc3VyZSB3ZSBkb24ndCBhY2NlcHQgbW9yZSBpbnB1dHMgdGhhbiB0aGUgaGFyZHdhcmUgY2Fu Cj4gPiAtCQkgKiBoYW5kbGUuIFRoaXMgaXMgYSB0ZW1wb3JhcnkgZml4IHRvIGF2b2lkIGRpc3Bs YXkgc3RhbGwsIHdlCj4gPiAtCQkgKiBuZWVkIHRvIGluc3RlYWQgYWxsb2NhdGUgdGhlIEJSVSBv ciBCUlMgdG8gZGlzcGxheSBwaXBlbGluZXMKPiA+IC0JCSAqIGR5bmFtaWNhbGx5IGJhc2VkIG9u IHRoZSBudW1iZXIgb2YgcGxhbmVzIHRoZXkgZWFjaCB1c2UuCj4gPiAtCQkgKi8KPiA+IC0JCWlm IChwaXBlLT5udW1faW5wdXRzID49IHBpcGUtPmJydS0+c291cmNlX3BhZCkKPiA+IC0JCQlwaXBl LT5pbnB1dHNbaV0gPSBOVUxMOwo+ID4gLQo+ID4gLQkJaWYgKCFwaXBlLT5pbnB1dHNbaV0pCj4g PiAtCQkJY29udGludWU7Cj4gPiAtCj4gPiAtCQkvKiBJbnNlcnQgdGhlIFJQRiBpbiB0aGUgc29y dGVkIFJQRnMgYXJyYXkuICovCj4gPiAtCQlmb3IgKGogPSBwaXBlLT5udW1faW5wdXRzKys7IGog PiAwOyAtLWopIHsKPiA+IC0JCQlpZiAocnBmX3pwb3ModnNwMSwgaW5wdXRzW2otMV0pIDw9IHJw Zl96cG9zKHZzcDEsIHJwZikpCj4gPiAtCQkJCWJyZWFrOwo+ID4gLQkJCWlucHV0c1tqXSA9IGlu cHV0c1tqLTFdOwo+ID4gLQkJfQo+ID4gLQo+ID4gLQkJaW5wdXRzW2pdID0gcnBmOwo+ID4gLQl9 Cj4gPiAtCj4gPiAtCS8qIFNldHVwIHRoZSBSUEYgaW5wdXQgcGlwZWxpbmUgZm9yIGV2ZXJ5IGVu YWJsZWQgaW5wdXQuICovCj4gPiAtCWZvciAoaSA9IDA7IGkgPCBwaXBlLT5icnUtPnNvdXJjZV9w YWQ7ICsraSkgewo+ID4gLQkJc3RydWN0IHZzcDFfcndwZiAqcnBmID0gaW5wdXRzW2ldOwo+ID4g LQo+ID4gLQkJaWYgKCFycGYpIHsKPiA+IC0JCQlicnUtPmlucHV0c1tpXS5ycGYgPSBOVUxMOwo+ ID4gLQkJCWNvbnRpbnVlOwo+ID4gLQkJfQo+ID4gLQo+ID4gLQkJaWYgKCFycGYtPmVudGl0eS5w aXBlKSB7Cj4gPiAtCQkJcnBmLT5lbnRpdHkucGlwZSA9IHBpcGU7Cj4gPiAtCQkJbGlzdF9hZGRf dGFpbCgmcnBmLT5lbnRpdHkubGlzdF9waXBlLCAmcGlwZS0+ZW50aXRpZXMpOwo+ID4gLQkJfQo+ ID4gLQo+ID4gLQkJYnJ1LT5pbnB1dHNbaV0ucnBmID0gcnBmOwo+ID4gLQkJcnBmLT5icnVfaW5w dXQgPSBpOwo+ID4gLQkJcnBmLT5lbnRpdHkuc2luayA9IHBpcGUtPmJydTsKPiA+IC0JCXJwZi0+ ZW50aXR5LnNpbmtfcGFkID0gaTsKPiA+IC0KPiA+IC0JCWRldl9kYmcodnNwMS0+ZGV2LCAiJXM6 IGNvbm5lY3RpbmcgUlBGLiV1IHRvICVzOiV1XG4iLAo+ID4gLQkJCV9fZnVuY19fLCBycGYtPmVu dGl0eS5pbmRleCwgQlJVX05BTUUocGlwZS0+YnJ1KSwgaSk7Cj4gPiAtCj4gPiAtCQlyZXQgPSB2 c3AxX2R1X3NldHVwX3JwZl9waXBlKHZzcDEsIHBpcGUsIHJwZiwgaSk7Cj4gPiAtCQlpZiAocmV0 IDwgMCkKPiA+IC0JCQlkZXZfZXJyKHZzcDEtPmRldiwKPiA+IC0JCQkJIiVzOiBmYWlsZWQgdG8g c2V0dXAgUlBGLiV1XG4iLAo+ID4gLQkJCQlfX2Z1bmNfXywgcnBmLT5lbnRpdHkuaW5kZXgpOwo+ ID4gLQl9Cj4gPiAKPiA+ICsJdnNwMV9kdV9waXBlbGluZV9zZXR1cF9pbnB1dCh2c3AxLCBwaXBl KTsKPiA+IAo+ID4gIAl2c3AxX2R1X3BpcGVsaW5lX2NvbmZpZ3VyZShwaXBlKTsKPiA+ICAKPiA+ ICB9Cj4gPiAgRVhQT1JUX1NZTUJPTF9HUEwodnNwMV9kdV9hdG9taWNfZmx1c2gpOwoKCi0tIApS ZWdhcmRzLAoKTGF1cmVudCBQaW5jaGFydAoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX18KZHJpLWRldmVsIG1haWxpbmcgbGlzdApkcmktZGV2ZWxAbGlzdHMu ZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlz dGluZm8vZHJpLWRldmVsCg==