From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.6 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS,USER_AGENT_MUTT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 821A1C4360F for ; Thu, 14 Mar 2019 12:09:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 477F221852 for ; Thu, 14 Mar 2019 12:09:53 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="q4tdjhGv" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726829AbfCNMJw (ORCPT ); Thu, 14 Mar 2019 08:09:52 -0400 Received: from perceval.ideasonboard.com ([213.167.242.64]:49620 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726617AbfCNMJw (ORCPT ); Thu, 14 Mar 2019 08:09:52 -0400 Received: from pendragon.ideasonboard.com (dfj612yhrgyx302h3jwwy-3.rev.dnainternet.fi [IPv6:2001:14ba:21f5:5b00:ce28:277f:58d7:3ca4]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id F014B31C; Thu, 14 Mar 2019 13:09:47 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1552565388; bh=csHL9WT69OTBj1ejPw07ThEoquCk/pqxq+o+VJr45lk=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=q4tdjhGvjse2pnQVAJ0973yJNT3RKqi34P35H/B/JrMB5ZgTGqmlYrdFypByestCL TyF0qGNQT1PtDemH1iFvXS669JI/56LKhZkJxMxjiZ0LWzQJVbPPzNTVSW1s86+OtL TI3ycdQFu+PAuA5ESdfeeIEjLi8QiSvlQN/elqgI= Date: Thu, 14 Mar 2019 14:09:41 +0200 From: Laurent Pinchart To: Kieran Bingham Cc: Laurent Pinchart , dri-devel@lists.freedesktop.org, linux-media@vger.kernel.org, linux-renesas-soc@vger.kernel.org, Liviu Dudau , Brian Starkey Subject: Re: [PATCH v6 11/18] media: vsp1: drm: Implement writeback support Message-ID: <20190314120941.GC5455@pendragon.ideasonboard.com> References: <20190313000532.7087-1-laurent.pinchart+renesas@ideasonboard.com> <20190313000532.7087-12-laurent.pinchart+renesas@ideasonboard.com> <20190313155606.GF4722@pendragon.ideasonboard.com> <2fe9b232-36be-bb0d-6c33-91d0050b35c1@ideasonboard.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <2fe9b232-36be-bb0d-6c33-91d0050b35c1@ideasonboard.com> User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org Hi Kieran, On Thu, Mar 14, 2019 at 08:28:27AM +0000, Kieran Bingham wrote: > On 13/03/2019 15:56, Laurent Pinchart wrote: > > On Wed, Mar 13, 2019 at 11:42:34AM +0000, Kieran Bingham wrote: > >> On 13/03/2019 00:05, Laurent Pinchart wrote: > >>> Extend the vsp1_du_atomic_flush() API with writeback support by adding > >>> format, pitch and memory addresses of the writeback framebuffer. > >>> Writeback completion is reported through the existing frame completion > >>> callback with a new VSP1_DU_STATUS_WRITEBACK status flag. > >>> > >>> Signed-off-by: Laurent Pinchart > > My concerns have been addressed here: > > Reviewed-by: Kieran Bingham > > >>> --- > >>> drivers/media/platform/vsp1/vsp1_dl.c | 14 ++++++++++++++ > >>> drivers/media/platform/vsp1/vsp1_dl.h | 3 ++- > >>> drivers/media/platform/vsp1/vsp1_drm.c | 25 ++++++++++++++++++++++++- > >>> include/media/vsp1.h | 15 +++++++++++++++ > >>> 4 files changed, 55 insertions(+), 2 deletions(-) > >>> > >>> diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c > >>> index ed7cda4130f2..104b6f514536 100644 > >>> --- a/drivers/media/platform/vsp1/vsp1_dl.c > >>> +++ b/drivers/media/platform/vsp1/vsp1_dl.c > >>> @@ -958,6 +958,9 @@ void vsp1_dl_list_commit(struct vsp1_dl_list *dl, unsigned int dl_flags) > >>> * > >>> * The VSP1_DL_FRAME_END_INTERNAL flag indicates that the display list that just > >>> * became active had been queued with the internal notification flag. > >>> + * > >>> + * The VSP1_DL_FRAME_END_WRITEBACK flag indicates that the previously active > >>> + * display list had been queued with the writeback flag. > >> > >> How does this interact with the possibility of the writeback being > >> disabled by the WPF in the event of it failing to get a DL. > >> > >> It's only a small corner case, but will the 'writeback' report back as > >> though it succeeded? (without writing to memory, and thus giving an > >> unmodified buffer back?) > > > > Wrteback completion will never be reported in that case. This shouldn't > > happen as we should never fail to get a display list. Do you think it > > would be better to fake completion ? > > Would this lack of completion cause a hang while DRM waits for the > completion to occur? I guess this would timeout after some period. Not in the kernel as far as I can tell, but userspace could then wait forever. > I'm not sure what's worse. To hang / block for a timeout - or just > return a 'bad buffer'. We would know in the VSP that the completion has > failed, so we could signal a failure, but I think as the rest of the DRM > model goes with a timeout if the flip_done fails to complete for > example, we should follow that. > > So leave this as is, and perhaps lets make sure the core writeback > framework will report a warning if it hits a time out. There's no timeout handling for writeback in the core. > If we ever fail to get a display list - we will have bigger issues which > will propogate elsewhere :) Yes, I think so too. This should really never happen. > >>> */ > >>> unsigned int vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) > >>> { > >>> @@ -995,6 +998,17 @@ unsigned int vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) > >>> if (status & VI6_STATUS_FLD_STD(dlm->index)) > >>> goto done; > >>> > >>> + /* > >>> + * If the active display list has the writeback flag set, the frame > >>> + * completion marks the end of the writeback capture. Return the > >>> + * VSP1_DL_FRAME_END_WRITEBACK flag and reset the display list's > >>> + * writeback flag. > >>> + */ > >>> + if (dlm->active && (dlm->active->flags & VSP1_DL_FRAME_END_WRITEBACK)) { > >>> + flags |= VSP1_DL_FRAME_END_WRITEBACK; > >>> + dlm->active->flags &= ~VSP1_DL_FRAME_END_WRITEBACK; > >>> + } > >>> + > >>> /* > >>> * The device starts processing the queued display list right after the > >>> * frame end interrupt. The display list thus becomes active. > >>> diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h > >>> index e0fdb145e6ed..4d7bcfdc9bd9 100644 > >>> --- a/drivers/media/platform/vsp1/vsp1_dl.h > >>> +++ b/drivers/media/platform/vsp1/vsp1_dl.h > >>> @@ -18,7 +18,8 @@ struct vsp1_dl_list; > >>> struct vsp1_dl_manager; > >>> > >>> #define VSP1_DL_FRAME_END_COMPLETED BIT(0) > >>> -#define VSP1_DL_FRAME_END_INTERNAL BIT(1) > >>> +#define VSP1_DL_FRAME_END_WRITEBACK BIT(1) > >> > >> So below BIT(2) (code above) the flags match the externally exposed > >> bitfield for the VSP1_DU_STATUS_ > >> > >> While above (code below), are 'private' bitfields. > >> > >> Should this requirement be documented here somehow? especially the > >> mapping of FRAME_END_{COMPLETED,WRITEBACK} to > >> DU_STATUS_{COMPLETED,WRITEBACK}. > > > > I've added a comment here, as explained in my reply to your review of > > 10/18, to document this. > > Great. > > >>> +#define VSP1_DL_FRAME_END_INTERNAL BIT(2) > >>> > >>> /** > >>> * struct vsp1_dl_ext_cmd - Extended Display command > >>> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c > >>> index 0367f88135bf..16826bf184c7 100644 > >>> --- a/drivers/media/platform/vsp1/vsp1_drm.c > >>> +++ b/drivers/media/platform/vsp1/vsp1_drm.c > >>> @@ -37,7 +37,9 @@ static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe, > >>> > >>> if (drm_pipe->du_complete) { > >>> struct vsp1_entity *uif = drm_pipe->uif; > >>> - unsigned int status = completion & VSP1_DU_STATUS_COMPLETE; > >>> + unsigned int status = completion > >>> + & (VSP1_DU_STATUS_COMPLETE | > >>> + VSP1_DU_STATUS_WRITEBACK); > >>> u32 crc; > >>> > >>> crc = uif ? vsp1_uif_get_crc(to_uif(&uif->subdev)) : 0; > >>> @@ -541,6 +543,8 @@ static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe) > >>> > >>> if (drm_pipe->force_brx_release) > >>> dl_flags |= VSP1_DL_FRAME_END_INTERNAL; > >>> + if (pipe->output->writeback) > >>> + dl_flags |= VSP1_DL_FRAME_END_WRITEBACK; > >>> > >>> dl = vsp1_dl_list_get(pipe->output->dlm); > >>> dlb = vsp1_dl_list_get_body0(dl); > >>> @@ -870,12 +874,31 @@ 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; > >>> + int ret; > >>> > >>> drm_pipe->crc = cfg->crc; > >>> > >>> mutex_lock(&vsp1->drm->lock); > >>> + > >>> + if (pipe->output->has_writeback && cfg->writeback.pixelformat) { > >> > >> Is pipe->output->has_writeback necessary here? Can > >> cfg->writeback.pixelformat be set if pipe->output->has_writeback is false? > >> > >> Hrm ... actually - Perhaps it is useful. It validates both sides of the > >> system. > >> > >> pipe->output->has_writeback is a capability of the VSP, where as > >> cfg->writeback.pixelformat is a 'request' from the DU. > > > > Correct, I think it's best to check both, to ensure we don't try to > > queue a writeback request on a system that doesn't support writeback. On > > the other hand this shouldn't happen as the DU driver shouldn't expose > > writeback to userspace in that case, so if you don't think the check is > > worth it I can remove the has_writeback field completely. > > It's a cheap check, I don't think it is too much of an issue - but I > agree (if we don't already) then we should make sure userspace does not > see a writeback functionality if it is not supported through the whole > pipeline (i.e. including the capability in the VSP1). > > That would make me lean towards removing this check here - *iff* we > guarantee that the VSP will only be asked to do write back when it's > possible. Unless there's a bug in the DU side, we have such a guarantee. I'll remove the check. > >>> + const struct vsp1_du_writeback_config *wb_cfg = &cfg->writeback; > >>> + > >>> + ret = vsp1_du_pipeline_set_rwpf_format(vsp1, pipe->output, > >>> + wb_cfg->pixelformat, > >>> + wb_cfg->pitch); > >>> + if (WARN_ON(ret < 0)) > >>> + goto done; > >>> + > >>> + pipe->output->mem.addr[0] = wb_cfg->mem[0]; > >>> + pipe->output->mem.addr[1] = wb_cfg->mem[1]; > >>> + pipe->output->mem.addr[2] = wb_cfg->mem[2]; > >>> + pipe->output->writeback = true; > >>> + } > >>> + > >>> vsp1_du_pipeline_setup_inputs(vsp1, pipe); > >>> vsp1_du_pipeline_configure(pipe); > >>> + > >>> +done: > >>> mutex_unlock(&vsp1->drm->lock); > >>> } > >>> EXPORT_SYMBOL_GPL(vsp1_du_atomic_flush); > >>> diff --git a/include/media/vsp1.h b/include/media/vsp1.h > >>> index 877496936487..cc1b0d42ce95 100644 > >>> --- a/include/media/vsp1.h > >>> +++ b/include/media/vsp1.h > >>> @@ -18,6 +18,7 @@ struct device; > >>> int vsp1_du_init(struct device *dev); > >>> > >>> #define VSP1_DU_STATUS_COMPLETE BIT(0) > >>> +#define VSP1_DU_STATUS_WRITEBACK BIT(1) > >>> > >>> /** > >>> * struct vsp1_du_lif_config - VSP LIF configuration > >>> @@ -83,12 +84,26 @@ struct vsp1_du_crc_config { > >>> unsigned int index; > >>> }; > >>> > >>> +/** > >>> + * struct vsp1_du_writeback_config - VSP writeback configuration parameters > >>> + * @pixelformat: plane pixel format (V4L2 4CC) > >>> + * @pitch: line pitch in bytes for the first plane > >>> + * @mem: DMA memory address for each plane of the frame buffer > >>> + */ > >>> +struct vsp1_du_writeback_config { > >>> + u32 pixelformat; > >>> + unsigned int pitch; > >>> + dma_addr_t mem[3]; > >>> +}; > >>> + > >>> /** > >>> * struct vsp1_du_atomic_pipe_config - VSP atomic pipe configuration parameters > >>> * @crc: CRC computation configuration > >>> + * @writeback: writeback configuration > >>> */ > >>> struct vsp1_du_atomic_pipe_config { > >>> struct vsp1_du_crc_config crc; > >>> + struct vsp1_du_writeback_config writeback; > >>> }; > >>> > >>> void vsp1_du_atomic_begin(struct device *dev, unsigned int pipe_index); > > > > -- > Regards > -- > Kieran -- Regards, Laurent Pinchart From mboxrd@z Thu Jan 1 00:00:00 1970 From: Laurent Pinchart Subject: Re: [PATCH v6 11/18] media: vsp1: drm: Implement writeback support Date: Thu, 14 Mar 2019 14:09:41 +0200 Message-ID: <20190314120941.GC5455@pendragon.ideasonboard.com> References: <20190313000532.7087-1-laurent.pinchart+renesas@ideasonboard.com> <20190313000532.7087-12-laurent.pinchart+renesas@ideasonboard.com> <20190313155606.GF4722@pendragon.ideasonboard.com> <2fe9b232-36be-bb0d-6c33-91d0050b35c1@ideasonboard.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7B61A6E0A9 for ; Thu, 14 Mar 2019 12:09:50 +0000 (UTC) Content-Disposition: inline In-Reply-To: <2fe9b232-36be-bb0d-6c33-91d0050b35c1@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: Laurent Pinchart , Liviu Dudau , dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org, linux-media@vger.kernel.org List-Id: dri-devel@lists.freedesktop.org SGkgS2llcmFuLAoKT24gVGh1LCBNYXIgMTQsIDIwMTkgYXQgMDg6Mjg6MjdBTSArMDAwMCwgS2ll cmFuIEJpbmdoYW0gd3JvdGU6Cj4gT24gMTMvMDMvMjAxOSAxNTo1NiwgTGF1cmVudCBQaW5jaGFy dCB3cm90ZToKPiA+IE9uIFdlZCwgTWFyIDEzLCAyMDE5IGF0IDExOjQyOjM0QU0gKzAwMDAsIEtp ZXJhbiBCaW5naGFtIHdyb3RlOgo+ID4+IE9uIDEzLzAzLzIwMTkgMDA6MDUsIExhdXJlbnQgUGlu Y2hhcnQgd3JvdGU6Cj4gPj4+IEV4dGVuZCB0aGUgdnNwMV9kdV9hdG9taWNfZmx1c2goKSBBUEkg d2l0aCB3cml0ZWJhY2sgc3VwcG9ydCBieSBhZGRpbmcKPiA+Pj4gZm9ybWF0LCBwaXRjaCBhbmQg bWVtb3J5IGFkZHJlc3NlcyBvZiB0aGUgd3JpdGViYWNrIGZyYW1lYnVmZmVyLgo+ID4+PiBXcml0 ZWJhY2sgY29tcGxldGlvbiBpcyByZXBvcnRlZCB0aHJvdWdoIHRoZSBleGlzdGluZyBmcmFtZSBj b21wbGV0aW9uCj4gPj4+IGNhbGxiYWNrIHdpdGggYSBuZXcgVlNQMV9EVV9TVEFUVVNfV1JJVEVC QUNLIHN0YXR1cyBmbGFnLgo+ID4+Pgo+ID4+PiBTaWduZWQtb2ZmLWJ5OiBMYXVyZW50IFBpbmNo YXJ0IDxsYXVyZW50LnBpbmNoYXJ0K3JlbmVzYXNAaWRlYXNvbmJvYXJkLmNvbT4KPiAKPiBNeSBj b25jZXJucyBoYXZlIGJlZW4gYWRkcmVzc2VkIGhlcmU6Cj4gCj4gUmV2aWV3ZWQtYnk6IEtpZXJh biBCaW5naGFtIDxraWVyYW4uYmluZ2hhbStyZW5lc2FzQGlkZWFzb25ib2FyZC5jb20+Cj4gCj4g Pj4+IC0tLQo+ID4+PiAgZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS92c3AxL3ZzcDFfZGwuYyAgfCAx NCArKysrKysrKysrKysrKwo+ID4+PiAgZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS92c3AxL3ZzcDFf ZGwuaCAgfCAgMyArKy0KPiA+Pj4gIGRyaXZlcnMvbWVkaWEvcGxhdGZvcm0vdnNwMS92c3AxX2Ry bS5jIHwgMjUgKysrKysrKysrKysrKysrKysrKysrKysrLQo+ID4+PiAgaW5jbHVkZS9tZWRpYS92 c3AxLmggICAgICAgICAgICAgICAgICAgfCAxNSArKysrKysrKysrKysrKysKPiA+Pj4gIDQgZmls ZXMgY2hhbmdlZCwgNTUgaW5zZXJ0aW9ucygrKSwgMiBkZWxldGlvbnMoLSkKPiA+Pj4KPiA+Pj4g ZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vdnNwMS92c3AxX2RsLmMgYi9kcml2 ZXJzL21lZGlhL3BsYXRmb3JtL3ZzcDEvdnNwMV9kbC5jCj4gPj4+IGluZGV4IGVkN2NkYTQxMzBm Mi4uMTA0YjZmNTE0NTM2IDEwMDY0NAo+ID4+PiAtLS0gYS9kcml2ZXJzL21lZGlhL3BsYXRmb3Jt L3ZzcDEvdnNwMV9kbC5jCj4gPj4+ICsrKyBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vdnNwMS92 c3AxX2RsLmMKPiA+Pj4gQEAgLTk1OCw2ICs5NTgsOSBAQCB2b2lkIHZzcDFfZGxfbGlzdF9jb21t aXQoc3RydWN0IHZzcDFfZGxfbGlzdCAqZGwsIHVuc2lnbmVkIGludCBkbF9mbGFncykKPiA+Pj4g ICAqCj4gPj4+ICAgKiBUaGUgVlNQMV9ETF9GUkFNRV9FTkRfSU5URVJOQUwgZmxhZyBpbmRpY2F0 ZXMgdGhhdCB0aGUgZGlzcGxheSBsaXN0IHRoYXQganVzdAo+ID4+PiAgICogYmVjYW1lIGFjdGl2 ZSBoYWQgYmVlbiBxdWV1ZWQgd2l0aCB0aGUgaW50ZXJuYWwgbm90aWZpY2F0aW9uIGZsYWcuCj4g Pj4+ICsgKgo+ID4+PiArICogVGhlIFZTUDFfRExfRlJBTUVfRU5EX1dSSVRFQkFDSyBmbGFnIGlu ZGljYXRlcyB0aGF0IHRoZSBwcmV2aW91c2x5IGFjdGl2ZQo+ID4+PiArICogZGlzcGxheSBsaXN0 IGhhZCBiZWVuIHF1ZXVlZCB3aXRoIHRoZSB3cml0ZWJhY2sgZmxhZy4KPiA+Pgo+ID4+IEhvdyBk b2VzIHRoaXMgaW50ZXJhY3Qgd2l0aCB0aGUgcG9zc2liaWxpdHkgb2YgdGhlIHdyaXRlYmFjayBi ZWluZwo+ID4+IGRpc2FibGVkIGJ5IHRoZSBXUEYgaW4gdGhlIGV2ZW50IG9mIGl0IGZhaWxpbmcg dG8gZ2V0IGEgREwuCj4gPj4KPiA+PiBJdCdzIG9ubHkgYSBzbWFsbCBjb3JuZXIgY2FzZSwgYnV0 IHdpbGwgdGhlICd3cml0ZWJhY2snIHJlcG9ydCBiYWNrIGFzCj4gPj4gdGhvdWdoIGl0IHN1Y2Nl ZWRlZD8gKHdpdGhvdXQgd3JpdGluZyB0byBtZW1vcnksIGFuZCB0aHVzIGdpdmluZyBhbgo+ID4+ IHVubW9kaWZpZWQgYnVmZmVyIGJhY2s/KQo+ID4gCj4gPiBXcnRlYmFjayBjb21wbGV0aW9uIHdp bGwgbmV2ZXIgYmUgcmVwb3J0ZWQgaW4gdGhhdCBjYXNlLiBUaGlzIHNob3VsZG4ndAo+ID4gaGFw cGVuIGFzIHdlIHNob3VsZCBuZXZlciBmYWlsIHRvIGdldCBhIGRpc3BsYXkgbGlzdC4gRG8geW91 IHRoaW5rIGl0Cj4gPiB3b3VsZCBiZSBiZXR0ZXIgdG8gZmFrZSBjb21wbGV0aW9uID8KPiAKPiBX b3VsZCB0aGlzIGxhY2sgb2YgY29tcGxldGlvbiBjYXVzZSBhIGhhbmcgd2hpbGUgRFJNIHdhaXRz IGZvciB0aGUKPiBjb21wbGV0aW9uIHRvIG9jY3VyPyBJIGd1ZXNzIHRoaXMgd291bGQgdGltZW91 dCBhZnRlciBzb21lIHBlcmlvZC4KCk5vdCBpbiB0aGUga2VybmVsIGFzIGZhciBhcyBJIGNhbiB0 ZWxsLCBidXQgdXNlcnNwYWNlIGNvdWxkIHRoZW4gd2FpdApmb3JldmVyLgoKPiBJJ20gbm90IHN1 cmUgd2hhdCdzIHdvcnNlLiBUbyBoYW5nIC8gYmxvY2sgZm9yIGEgdGltZW91dCAtIG9yIGp1c3QK PiByZXR1cm4gYSAnYmFkIGJ1ZmZlcicuIFdlIHdvdWxkIGtub3cgaW4gdGhlIFZTUCB0aGF0IHRo ZSBjb21wbGV0aW9uIGhhcwo+IGZhaWxlZCwgc28gd2UgY291bGQgc2lnbmFsIGEgZmFpbHVyZSwg YnV0IEkgdGhpbmsgYXMgdGhlIHJlc3Qgb2YgdGhlIERSTQo+IG1vZGVsIGdvZXMgd2l0aCBhIHRp bWVvdXQgaWYgdGhlIGZsaXBfZG9uZSBmYWlscyB0byBjb21wbGV0ZSBmb3IKPiBleGFtcGxlLCB3 ZSBzaG91bGQgZm9sbG93IHRoYXQuCj4gCj4gU28gbGVhdmUgdGhpcyBhcyBpcywgYW5kIHBlcmhh cHMgbGV0cyBtYWtlIHN1cmUgdGhlIGNvcmUgd3JpdGViYWNrCj4gZnJhbWV3b3JrIHdpbGwgcmVw b3J0IGEgd2FybmluZyBpZiBpdCBoaXRzIGEgdGltZSBvdXQuCgpUaGVyZSdzIG5vIHRpbWVvdXQg aGFuZGxpbmcgZm9yIHdyaXRlYmFjayBpbiB0aGUgY29yZS4KCj4gSWYgd2UgZXZlciBmYWlsIHRv IGdldCBhIGRpc3BsYXkgbGlzdCAtIHdlIHdpbGwgaGF2ZSBiaWdnZXIgaXNzdWVzIHdoaWNoCj4g d2lsbCBwcm9wb2dhdGUgZWxzZXdoZXJlIDopCgpZZXMsIEkgdGhpbmsgc28gdG9vLiBUaGlzIHNo b3VsZCByZWFsbHkgbmV2ZXIgaGFwcGVuLgoKPiA+Pj4gICAqLwo+ID4+PiAgdW5zaWduZWQgaW50 IHZzcDFfZGxtX2lycV9mcmFtZV9lbmQoc3RydWN0IHZzcDFfZGxfbWFuYWdlciAqZGxtKQo+ID4+ PiAgewo+ID4+PiBAQCAtOTk1LDYgKzk5OCwxNyBAQCB1bnNpZ25lZCBpbnQgdnNwMV9kbG1faXJx X2ZyYW1lX2VuZChzdHJ1Y3QgdnNwMV9kbF9tYW5hZ2VyICpkbG0pCj4gPj4+ICAJaWYgKHN0YXR1 cyAmIFZJNl9TVEFUVVNfRkxEX1NURChkbG0tPmluZGV4KSkKPiA+Pj4gIAkJZ290byBkb25lOwo+ ID4+PiAgCj4gPj4+ICsJLyoKPiA+Pj4gKwkgKiBJZiB0aGUgYWN0aXZlIGRpc3BsYXkgbGlzdCBo YXMgdGhlIHdyaXRlYmFjayBmbGFnIHNldCwgdGhlIGZyYW1lCj4gPj4+ICsJICogY29tcGxldGlv biBtYXJrcyB0aGUgZW5kIG9mIHRoZSB3cml0ZWJhY2sgY2FwdHVyZS4gUmV0dXJuIHRoZQo+ID4+ PiArCSAqIFZTUDFfRExfRlJBTUVfRU5EX1dSSVRFQkFDSyBmbGFnIGFuZCByZXNldCB0aGUgZGlz cGxheSBsaXN0J3MKPiA+Pj4gKwkgKiB3cml0ZWJhY2sgZmxhZy4KPiA+Pj4gKwkgKi8KPiA+Pj4g KwlpZiAoZGxtLT5hY3RpdmUgJiYgKGRsbS0+YWN0aXZlLT5mbGFncyAmIFZTUDFfRExfRlJBTUVf RU5EX1dSSVRFQkFDSykpIHsKPiA+Pj4gKwkJZmxhZ3MgfD0gVlNQMV9ETF9GUkFNRV9FTkRfV1JJ VEVCQUNLOwo+ID4+PiArCQlkbG0tPmFjdGl2ZS0+ZmxhZ3MgJj0gflZTUDFfRExfRlJBTUVfRU5E X1dSSVRFQkFDSzsKPiA+Pj4gKwl9Cj4gPj4+ICsKPiA+Pj4gIAkvKgo+ID4+PiAgCSAqIFRoZSBk ZXZpY2Ugc3RhcnRzIHByb2Nlc3NpbmcgdGhlIHF1ZXVlZCBkaXNwbGF5IGxpc3QgcmlnaHQgYWZ0 ZXIgdGhlCj4gPj4+ICAJICogZnJhbWUgZW5kIGludGVycnVwdC4gVGhlIGRpc3BsYXkgbGlzdCB0 aHVzIGJlY29tZXMgYWN0aXZlLgo+ID4+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9tZWRpYS9wbGF0 Zm9ybS92c3AxL3ZzcDFfZGwuaCBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vdnNwMS92c3AxX2Rs LmgKPiA+Pj4gaW5kZXggZTBmZGIxNDVlNmVkLi40ZDdiY2ZkYzliZDkgMTAwNjQ0Cj4gPj4+IC0t LSBhL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vdnNwMS92c3AxX2RsLmgKPiA+Pj4gKysrIGIvZHJp dmVycy9tZWRpYS9wbGF0Zm9ybS92c3AxL3ZzcDFfZGwuaAo+ID4+PiBAQCAtMTgsNyArMTgsOCBA QCBzdHJ1Y3QgdnNwMV9kbF9saXN0Owo+ID4+PiAgc3RydWN0IHZzcDFfZGxfbWFuYWdlcjsKPiA+ Pj4gIAo+ID4+PiAgI2RlZmluZSBWU1AxX0RMX0ZSQU1FX0VORF9DT01QTEVURUQJCUJJVCgwKQo+ ID4+PiAtI2RlZmluZSBWU1AxX0RMX0ZSQU1FX0VORF9JTlRFUk5BTAkJQklUKDEpCj4gPj4+ICsj ZGVmaW5lIFZTUDFfRExfRlJBTUVfRU5EX1dSSVRFQkFDSwkJQklUKDEpCj4gPj4KPiA+PiBTbyBi ZWxvdyBCSVQoMikgKGNvZGUgYWJvdmUpIHRoZSBmbGFncyBtYXRjaCB0aGUgZXh0ZXJuYWxseSBl eHBvc2VkCj4gPj4gYml0ZmllbGQgZm9yIHRoZSBWU1AxX0RVX1NUQVRVU18KPiA+Pgo+ID4+IFdo aWxlIGFib3ZlIChjb2RlIGJlbG93KSwgYXJlICdwcml2YXRlJyBiaXRmaWVsZHMuCj4gPj4KPiA+ PiBTaG91bGQgdGhpcyByZXF1aXJlbWVudCBiZSBkb2N1bWVudGVkIGhlcmUgc29tZWhvdz8gZXNw ZWNpYWxseSB0aGUKPiA+PiBtYXBwaW5nIG9mIEZSQU1FX0VORF97Q09NUExFVEVELFdSSVRFQkFD S30gdG8KPiA+PiBEVV9TVEFUVVNfe0NPTVBMRVRFRCxXUklURUJBQ0t9Lgo+ID4gCj4gPiBJJ3Zl IGFkZGVkIGEgY29tbWVudCBoZXJlLCBhcyBleHBsYWluZWQgaW4gbXkgcmVwbHkgdG8geW91ciBy ZXZpZXcgb2YKPiA+IDEwLzE4LCB0byBkb2N1bWVudCB0aGlzLgo+IAo+IEdyZWF0Lgo+IAo+ID4+ PiArI2RlZmluZSBWU1AxX0RMX0ZSQU1FX0VORF9JTlRFUk5BTAkJQklUKDIpCj4gPj4+ICAKPiA+ Pj4gIC8qKgo+ID4+PiAgICogc3RydWN0IHZzcDFfZGxfZXh0X2NtZCAtIEV4dGVuZGVkIERpc3Bs YXkgY29tbWFuZAo+ID4+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS92c3Ax L3ZzcDFfZHJtLmMgYi9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL3ZzcDEvdnNwMV9kcm0uYwo+ID4+ PiBpbmRleCAwMzY3Zjg4MTM1YmYuLjE2ODI2YmYxODRjNyAxMDA2NDQKPiA+Pj4gLS0tIGEvZHJp dmVycy9tZWRpYS9wbGF0Zm9ybS92c3AxL3ZzcDFfZHJtLmMKPiA+Pj4gKysrIGIvZHJpdmVycy9t ZWRpYS9wbGF0Zm9ybS92c3AxL3ZzcDFfZHJtLmMKPiA+Pj4gQEAgLTM3LDcgKzM3LDkgQEAgc3Rh dGljIHZvaWQgdnNwMV9kdV9waXBlbGluZV9mcmFtZV9lbmQoc3RydWN0IHZzcDFfcGlwZWxpbmUg KnBpcGUsCj4gPj4+ICAKPiA+Pj4gIAlpZiAoZHJtX3BpcGUtPmR1X2NvbXBsZXRlKSB7Cj4gPj4+ ICAJCXN0cnVjdCB2c3AxX2VudGl0eSAqdWlmID0gZHJtX3BpcGUtPnVpZjsKPiA+Pj4gLQkJdW5z aWduZWQgaW50IHN0YXR1cyA9IGNvbXBsZXRpb24gJiBWU1AxX0RVX1NUQVRVU19DT01QTEVURTsK PiA+Pj4gKwkJdW5zaWduZWQgaW50IHN0YXR1cyA9IGNvbXBsZXRpb24KPiA+Pj4gKwkJCQkgICAg JiAoVlNQMV9EVV9TVEFUVVNfQ09NUExFVEUgfAo+ID4+PiArCQkJCSAgICAgICBWU1AxX0RVX1NU QVRVU19XUklURUJBQ0spOwo+ID4+PiAgCQl1MzIgY3JjOwo+ID4+PiAgCj4gPj4+ICAJCWNyYyA9 IHVpZiA/IHZzcDFfdWlmX2dldF9jcmModG9fdWlmKCZ1aWYtPnN1YmRldikpIDogMDsKPiA+Pj4g QEAgLTU0MSw2ICs1NDMsOCBAQCBzdGF0aWMgdm9pZCB2c3AxX2R1X3BpcGVsaW5lX2NvbmZpZ3Vy ZShzdHJ1Y3QgdnNwMV9waXBlbGluZSAqcGlwZSkKPiA+Pj4gIAo+ID4+PiAgCWlmIChkcm1fcGlw ZS0+Zm9yY2VfYnJ4X3JlbGVhc2UpCj4gPj4+ICAJCWRsX2ZsYWdzIHw9IFZTUDFfRExfRlJBTUVf RU5EX0lOVEVSTkFMOwo+ID4+PiArCWlmIChwaXBlLT5vdXRwdXQtPndyaXRlYmFjaykKPiA+Pj4g KwkJZGxfZmxhZ3MgfD0gVlNQMV9ETF9GUkFNRV9FTkRfV1JJVEVCQUNLOwo+ID4+PiAgCj4gPj4+ ICAJZGwgPSB2c3AxX2RsX2xpc3RfZ2V0KHBpcGUtPm91dHB1dC0+ZGxtKTsKPiA+Pj4gIAlkbGIg PSB2c3AxX2RsX2xpc3RfZ2V0X2JvZHkwKGRsKTsKPiA+Pj4gQEAgLTg3MCwxMiArODc0LDMxIEBA IHZvaWQgdnNwMV9kdV9hdG9taWNfZmx1c2goc3RydWN0IGRldmljZSAqZGV2LCB1bnNpZ25lZCBp bnQgcGlwZV9pbmRleCwKPiA+Pj4gIAlzdHJ1Y3QgdnNwMV9kZXZpY2UgKnZzcDEgPSBkZXZfZ2V0 X2RydmRhdGEoZGV2KTsKPiA+Pj4gIAlzdHJ1Y3QgdnNwMV9kcm1fcGlwZWxpbmUgKmRybV9waXBl ID0gJnZzcDEtPmRybS0+cGlwZVtwaXBlX2luZGV4XTsKPiA+Pj4gIAlzdHJ1Y3QgdnNwMV9waXBl bGluZSAqcGlwZSA9ICZkcm1fcGlwZS0+cGlwZTsKPiA+Pj4gKwlpbnQgcmV0Owo+ID4+PiAgCj4g Pj4+ICAJZHJtX3BpcGUtPmNyYyA9IGNmZy0+Y3JjOwo+ID4+PiAgCj4gPj4+ICAJbXV0ZXhfbG9j aygmdnNwMS0+ZHJtLT5sb2NrKTsKPiA+Pj4gKwo+ID4+PiArCWlmIChwaXBlLT5vdXRwdXQtPmhh c193cml0ZWJhY2sgJiYgY2ZnLT53cml0ZWJhY2sucGl4ZWxmb3JtYXQpIHsKPiA+Pgo+ID4+IElz IHBpcGUtPm91dHB1dC0+aGFzX3dyaXRlYmFjayBuZWNlc3NhcnkgaGVyZT8gQ2FuCj4gPj4gY2Zn LT53cml0ZWJhY2sucGl4ZWxmb3JtYXQgYmUgc2V0IGlmIHBpcGUtPm91dHB1dC0+aGFzX3dyaXRl YmFjayBpcyBmYWxzZT8KPiA+Pgo+ID4+IEhybSAuLi4gYWN0dWFsbHkgLSBQZXJoYXBzIGl0IGlz IHVzZWZ1bC4gSXQgdmFsaWRhdGVzIGJvdGggc2lkZXMgb2YgdGhlCj4gPj4gc3lzdGVtLgo+ID4+ Cj4gPj4gcGlwZS0+b3V0cHV0LT5oYXNfd3JpdGViYWNrIGlzIGEgY2FwYWJpbGl0eSBvZiB0aGUg VlNQLCB3aGVyZSBhcwo+ID4+IGNmZy0+d3JpdGViYWNrLnBpeGVsZm9ybWF0IGlzIGEgJ3JlcXVl c3QnIGZyb20gdGhlIERVLgo+ID4gCj4gPiBDb3JyZWN0LCBJIHRoaW5rIGl0J3MgYmVzdCB0byBj aGVjayBib3RoLCB0byBlbnN1cmUgd2UgZG9uJ3QgdHJ5IHRvCj4gPiBxdWV1ZSBhIHdyaXRlYmFj ayByZXF1ZXN0IG9uIGEgc3lzdGVtIHRoYXQgZG9lc24ndCBzdXBwb3J0IHdyaXRlYmFjay4gT24K PiA+IHRoZSBvdGhlciBoYW5kIHRoaXMgc2hvdWxkbid0IGhhcHBlbiBhcyB0aGUgRFUgZHJpdmVy IHNob3VsZG4ndCBleHBvc2UKPiA+IHdyaXRlYmFjayB0byB1c2Vyc3BhY2UgaW4gdGhhdCBjYXNl LCBzbyBpZiB5b3UgZG9uJ3QgdGhpbmsgdGhlIGNoZWNrIGlzCj4gPiB3b3J0aCBpdCBJIGNhbiBy ZW1vdmUgdGhlIGhhc193cml0ZWJhY2sgZmllbGQgY29tcGxldGVseS4KPiAKPiBJdCdzIGEgY2hl YXAgY2hlY2ssIEkgZG9uJ3QgdGhpbmsgaXQgaXMgdG9vIG11Y2ggb2YgYW4gaXNzdWUgLSBidXQg SQo+IGFncmVlIChpZiB3ZSBkb24ndCBhbHJlYWR5KSB0aGVuIHdlIHNob3VsZCBtYWtlIHN1cmUg dXNlcnNwYWNlIGRvZXMgbm90Cj4gc2VlIGEgd3JpdGViYWNrIGZ1bmN0aW9uYWxpdHkgaWYgaXQg aXMgbm90IHN1cHBvcnRlZCB0aHJvdWdoIHRoZSB3aG9sZQo+IHBpcGVsaW5lIChpLmUuIGluY2x1 ZGluZyB0aGUgY2FwYWJpbGl0eSBpbiB0aGUgVlNQMSkuCj4gCj4gVGhhdCB3b3VsZCBtYWtlIG1l IGxlYW4gdG93YXJkcyByZW1vdmluZyB0aGlzIGNoZWNrIGhlcmUgLSAqaWZmKiB3ZQo+IGd1YXJh bnRlZSB0aGF0IHRoZSBWU1Agd2lsbCBvbmx5IGJlIGFza2VkIHRvIGRvIHdyaXRlIGJhY2sgd2hl biBpdCdzCj4gcG9zc2libGUuCgpVbmxlc3MgdGhlcmUncyBhIGJ1ZyBpbiB0aGUgRFUgc2lkZSwg d2UgaGF2ZSBzdWNoIGEgZ3VhcmFudGVlLiBJJ2xsCnJlbW92ZSB0aGUgY2hlY2suCgo+ID4+PiAr CQljb25zdCBzdHJ1Y3QgdnNwMV9kdV93cml0ZWJhY2tfY29uZmlnICp3Yl9jZmcgPSAmY2ZnLT53 cml0ZWJhY2s7Cj4gPj4+ICsKPiA+Pj4gKwkJcmV0ID0gdnNwMV9kdV9waXBlbGluZV9zZXRfcndw Zl9mb3JtYXQodnNwMSwgcGlwZS0+b3V0cHV0LAo+ID4+PiArCQkJCQkJICAgICAgIHdiX2NmZy0+ cGl4ZWxmb3JtYXQsCj4gPj4+ICsJCQkJCQkgICAgICAgd2JfY2ZnLT5waXRjaCk7Cj4gPj4+ICsJ CWlmIChXQVJOX09OKHJldCA8IDApKQo+ID4+PiArCQkJZ290byBkb25lOwo+ID4+PiArCj4gPj4+ ICsJCXBpcGUtPm91dHB1dC0+bWVtLmFkZHJbMF0gPSB3Yl9jZmctPm1lbVswXTsKPiA+Pj4gKwkJ cGlwZS0+b3V0cHV0LT5tZW0uYWRkclsxXSA9IHdiX2NmZy0+bWVtWzFdOwo+ID4+PiArCQlwaXBl LT5vdXRwdXQtPm1lbS5hZGRyWzJdID0gd2JfY2ZnLT5tZW1bMl07Cj4gPj4+ICsJCXBpcGUtPm91 dHB1dC0+d3JpdGViYWNrID0gdHJ1ZTsKPiA+Pj4gKwl9Cj4gPj4+ICsKPiA+Pj4gIAl2c3AxX2R1 X3BpcGVsaW5lX3NldHVwX2lucHV0cyh2c3AxLCBwaXBlKTsKPiA+Pj4gIAl2c3AxX2R1X3BpcGVs aW5lX2NvbmZpZ3VyZShwaXBlKTsKPiA+Pj4gKwo+ID4+PiArZG9uZToKPiA+Pj4gIAltdXRleF91 bmxvY2soJnZzcDEtPmRybS0+bG9jayk7Cj4gPj4+ICB9Cj4gPj4+ICBFWFBPUlRfU1lNQk9MX0dQ TCh2c3AxX2R1X2F0b21pY19mbHVzaCk7Cj4gPj4+IGRpZmYgLS1naXQgYS9pbmNsdWRlL21lZGlh L3ZzcDEuaCBiL2luY2x1ZGUvbWVkaWEvdnNwMS5oCj4gPj4+IGluZGV4IDg3NzQ5NjkzNjQ4Ny4u Y2MxYjBkNDJjZTk1IDEwMDY0NAo+ID4+PiAtLS0gYS9pbmNsdWRlL21lZGlhL3ZzcDEuaAo+ID4+ PiArKysgYi9pbmNsdWRlL21lZGlhL3ZzcDEuaAo+ID4+PiBAQCAtMTgsNiArMTgsNyBAQCBzdHJ1 Y3QgZGV2aWNlOwo+ID4+PiAgaW50IHZzcDFfZHVfaW5pdChzdHJ1Y3QgZGV2aWNlICpkZXYpOwo+ ID4+PiAgCj4gPj4+ICAjZGVmaW5lIFZTUDFfRFVfU1RBVFVTX0NPTVBMRVRFCQlCSVQoMCkKPiA+ Pj4gKyNkZWZpbmUgVlNQMV9EVV9TVEFUVVNfV1JJVEVCQUNLCUJJVCgxKQo+ID4+PiAgCj4gPj4+ ICAvKioKPiA+Pj4gICAqIHN0cnVjdCB2c3AxX2R1X2xpZl9jb25maWcgLSBWU1AgTElGIGNvbmZp Z3VyYXRpb24KPiA+Pj4gQEAgLTgzLDEyICs4NCwyNiBAQCBzdHJ1Y3QgdnNwMV9kdV9jcmNfY29u ZmlnIHsKPiA+Pj4gIAl1bnNpZ25lZCBpbnQgaW5kZXg7Cj4gPj4+ICB9Owo+ID4+PiAgCj4gPj4+ ICsvKioKPiA+Pj4gKyAqIHN0cnVjdCB2c3AxX2R1X3dyaXRlYmFja19jb25maWcgLSBWU1Agd3Jp dGViYWNrIGNvbmZpZ3VyYXRpb24gcGFyYW1ldGVycwo+ID4+PiArICogQHBpeGVsZm9ybWF0OiBw bGFuZSBwaXhlbCBmb3JtYXQgKFY0TDIgNENDKQo+ID4+PiArICogQHBpdGNoOiBsaW5lIHBpdGNo IGluIGJ5dGVzIGZvciB0aGUgZmlyc3QgcGxhbmUKPiA+Pj4gKyAqIEBtZW06IERNQSBtZW1vcnkg YWRkcmVzcyBmb3IgZWFjaCBwbGFuZSBvZiB0aGUgZnJhbWUgYnVmZmVyCj4gPj4+ICsgKi8KPiA+ Pj4gK3N0cnVjdCB2c3AxX2R1X3dyaXRlYmFja19jb25maWcgewo+ID4+PiArCXUzMiBwaXhlbGZv cm1hdDsKPiA+Pj4gKwl1bnNpZ25lZCBpbnQgcGl0Y2g7Cj4gPj4+ICsJZG1hX2FkZHJfdCBtZW1b M107Cj4gPj4+ICt9Owo+ID4+PiArCj4gPj4+ICAvKioKPiA+Pj4gICAqIHN0cnVjdCB2c3AxX2R1 X2F0b21pY19waXBlX2NvbmZpZyAtIFZTUCBhdG9taWMgcGlwZSBjb25maWd1cmF0aW9uIHBhcmFt ZXRlcnMKPiA+Pj4gICAqIEBjcmM6IENSQyBjb21wdXRhdGlvbiBjb25maWd1cmF0aW9uCj4gPj4+ ICsgKiBAd3JpdGViYWNrOiB3cml0ZWJhY2sgY29uZmlndXJhdGlvbgo+ID4+PiAgICovCj4gPj4+ ICBzdHJ1Y3QgdnNwMV9kdV9hdG9taWNfcGlwZV9jb25maWcgewo+ID4+PiAgCXN0cnVjdCB2c3Ax X2R1X2NyY19jb25maWcgY3JjOwo+ID4+PiArCXN0cnVjdCB2c3AxX2R1X3dyaXRlYmFja19jb25m aWcgd3JpdGViYWNrOwo+ID4+PiAgfTsKPiA+Pj4gIAo+ID4+PiAgdm9pZCB2c3AxX2R1X2F0b21p Y19iZWdpbihzdHJ1Y3QgZGV2aWNlICpkZXYsIHVuc2lnbmVkIGludCBwaXBlX2luZGV4KTsKPiA+ IAo+IAo+IC0tIAo+IFJlZ2FyZHMKPiAtLQo+IEtpZXJhbgoKLS0gClJlZ2FyZHMsCgpMYXVyZW50 IFBpbmNoYXJ0Cl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f CmRyaS1kZXZlbCBtYWlsaW5nIGxpc3QKZHJpLWRldmVsQGxpc3RzLmZyZWVkZXNrdG9wLm9yZwpo dHRwczovL2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2RyaS1kZXZlbA==