From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from galahad.ideasonboard.com ([185.26.127.97]:47864 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750806AbdKNDeG (ORCPT ); Mon, 13 Nov 2017 22:34:06 -0500 From: Laurent Pinchart To: Liviu Dudau Cc: Laurent Pinchart , dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org, Kieran Bingham , Daniel Vetter Subject: Re: [PATCH/RFC 2/2] drm: rcar-du: Allow importing non-contiguous dma-buf with VSP Date: Tue, 14 Nov 2017 05:34:14 +0200 Message-ID: <1687766.IjFbpRoOl0@avalon> In-Reply-To: <20171113115314.GB26389@e110455-lin.cambridge.arm.com> References: <20171113103228.23312-1-laurent.pinchart+renesas@ideasonboard.com> <20171113103228.23312-3-laurent.pinchart+renesas@ideasonboard.com> <20171113115314.GB26389@e110455-lin.cambridge.arm.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 Liviu, On Monday, 13 November 2017 13:53:14 EET Liviu Dudau wrote: > On Mon, Nov 13, 2017 at 12:32:28PM +0200, Laurent Pinchart wrote: > > When the DU sources its frames from a VSP, it performs no memory access > > and thus has no requirements on imported dma-buf memory types. In > > particular the DU could import a physically non-contiguous buffer that > > would later be mapped contiguously through the VSP IOMMU. > > > > This use case isn't supported at the moment as the GEM CMA helpers will > > reject any non-contiguous buffer, and the DU isn't connected to an IOMMU > > that can make the buffer contiguous for DMA. Fix this by implementing a > > custom .gem_prime_import_sg_table() operation that accepts all imported > > dma-buf regardless of the number of scatterlist entries. > > This patch raises the question of why use CMA at all if you can accept > any kind of buffers. Both the DU and VSP require DMA contiguous memory. On R-Car Gen2 the DU performs DMA, and thus uses the GEM CMA helpers. On Gen3 it delegates DMA to the external VSP composer, and still uses the GEM CMA helpers to ensure that memory will be DMA contiguous for the VSP. The problem arises when physically non-contiguous dma-buf buffers are imported, they can be mapped contiguously to the VSP (assuming an IOMMU is present) but not to the DU (as there's no IOMMU). The situation is particularly messy due to the fact that I have one VSP instance per CRTC, each connected to its own IOMMU channel. The driver thus doesn't know when allocating GEM objects to which struct device they need to be mapped. The DRM helpers don't support delayed mapping of memory. I'd like to know whether that's something I should fix properly (which would likely involve major reworking of the helpers) or hack around it in the DU driver. > > Signed-off-by: Laurent Pinchart > > > > --- > > > > drivers/gpu/drm/rcar-du/rcar_du_drv.c | 2 +- > > drivers/gpu/drm/rcar-du/rcar_du_kms.c | 39 ++++++++++++++++++++++++++++++ > > drivers/gpu/drm/rcar-du/rcar_du_kms.h | 7 +++++++ > > 3 files changed, 47 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > > b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 48c166f925a3..d999231f98c7 > > 100644 > > --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > > +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c > > @@ -289,7 +289,7 @@ static struct drm_driver rcar_du_driver = { > > .gem_prime_import = drm_gem_prime_import, > > .gem_prime_export = drm_gem_prime_export, > > .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, > > - .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, > > + .gem_prime_import_sg_table = rcar_du_gem_prime_import_sg_table, > > .gem_prime_vmap = drm_gem_cma_prime_vmap, > > .gem_prime_vunmap = drm_gem_cma_prime_vunmap, > > .gem_prime_mmap = drm_gem_cma_prime_mmap, > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c > > b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 566d1a948c8f..2dd0c2ba047d > > 100644 > > --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c > > +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c [snip] > > +struct drm_gem_object *rcar_du_gem_prime_import_sg_table(struct > > drm_device *dev, > > + struct dma_buf_attachment *attach, > > + struct sg_table *sgt) > > +{ > > + struct rcar_du_device *rcdu = dev->dev_private; > > + struct drm_gem_cma_object *cma_obj; > > + struct drm_gem_object *gem_obj; > > + int ret; > > + > > + if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) > > + return drm_gem_cma_prime_import_sg_table(dev, attach, sgt); > > + > > + /* Create a CMA GEM buffer. */ > > + cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL); > > + if (!cma_obj) > > + return ERR_PTR(-ENOMEM); > > + gem_obj = &cma_obj->base; > > + > > + ret = drm_gem_object_init(dev, gem_obj, attach->dmabuf->size); > > + if (ret) > > + goto error; > > + > > + ret = drm_gem_create_mmap_offset(gem_obj); > > + if (ret) { > > + drm_gem_object_release(gem_obj); > > + goto error; > > + } > > + > > + cma_obj->paddr = 0; > > This is going to break drm_gem_cma_describe() if you are using it As far as I can tell drm_gem_cma_describe() will just print paddr = 0, it won't crash. > plus the rcar_du_plane_setup_scanout() unless I'm missing something besides > familiarity with the RCAR driver code :) rcar_du_plane_setup_scanout() is only called when !rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE) (that is on Gen3 hardware, or on Gen2 when I artificially disable all DMA from the DU and use external composers to emulate Gen3 behaviour for testing purpose), in which case this function calls drm_gem_cma_prime_import_sg_table(). > This function looks very similar to what I tried to do for mali-dp to > allow the import of contiguous DMA buffers that have more than 1 sgt > entries. In the end I gave up as I kept finding issues and went for the > drm_gem_cma_prime_import_sg_table() changes. Maybe you need to do a > similar change in the function to bypass some requirements if the driver > signals that it can accept relaxed requirements? As explained above I've considered reworking the helpers (to do it properly I think I'll likely need to rework drm_prime.c too), but I'd first like to know whether there's an interest for that. > > + cma_obj->sgt = sgt; > > + > > + return gem_obj; > > + > > +error: > > + kfree(cma_obj); > > + return ERR_PTR(ret); > > +} [snip] -- Regards, Laurent Pinchart From mboxrd@z Thu Jan 1 00:00:00 1970 From: Laurent Pinchart Subject: Re: [PATCH/RFC 2/2] drm: rcar-du: Allow importing non-contiguous dma-buf with VSP Date: Tue, 14 Nov 2017 05:34:14 +0200 Message-ID: <1687766.IjFbpRoOl0@avalon> References: <20171113103228.23312-1-laurent.pinchart+renesas@ideasonboard.com> <20171113103228.23312-3-laurent.pinchart+renesas@ideasonboard.com> <20171113115314.GB26389@e110455-lin.cambridge.arm.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 EF1E06E807 for ; Tue, 14 Nov 2017 03:34:05 +0000 (UTC) In-Reply-To: <20171113115314.GB26389@e110455-lin.cambridge.arm.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Liviu Dudau Cc: linux-renesas-soc@vger.kernel.org, Daniel Vetter , Laurent Pinchart , Kieran Bingham , dri-devel@lists.freedesktop.org List-Id: dri-devel@lists.freedesktop.org SGkgTGl2aXUsCgpPbiBNb25kYXksIDEzIE5vdmVtYmVyIDIwMTcgMTM6NTM6MTQgRUVUIExpdml1 IER1ZGF1IHdyb3RlOgo+IE9uIE1vbiwgTm92IDEzLCAyMDE3IGF0IDEyOjMyOjI4UE0gKzAyMDAs IExhdXJlbnQgUGluY2hhcnQgd3JvdGU6Cj4gPiBXaGVuIHRoZSBEVSBzb3VyY2VzIGl0cyBmcmFt ZXMgZnJvbSBhIFZTUCwgaXQgcGVyZm9ybXMgbm8gbWVtb3J5IGFjY2Vzcwo+ID4gYW5kIHRodXMg aGFzIG5vIHJlcXVpcmVtZW50cyBvbiBpbXBvcnRlZCBkbWEtYnVmIG1lbW9yeSB0eXBlcy4gSW4K PiA+IHBhcnRpY3VsYXIgdGhlIERVIGNvdWxkIGltcG9ydCBhIHBoeXNpY2FsbHkgbm9uLWNvbnRp Z3VvdXMgYnVmZmVyIHRoYXQKPiA+IHdvdWxkIGxhdGVyIGJlIG1hcHBlZCBjb250aWd1b3VzbHkg dGhyb3VnaCB0aGUgVlNQIElPTU1VLgo+ID4gCj4gPiBUaGlzIHVzZSBjYXNlIGlzbid0IHN1cHBv cnRlZCBhdCB0aGUgbW9tZW50IGFzIHRoZSBHRU0gQ01BIGhlbHBlcnMgd2lsbAo+ID4gcmVqZWN0 IGFueSBub24tY29udGlndW91cyBidWZmZXIsIGFuZCB0aGUgRFUgaXNuJ3QgY29ubmVjdGVkIHRv IGFuIElPTU1VCj4gPiB0aGF0IGNhbiBtYWtlIHRoZSBidWZmZXIgY29udGlndW91cyBmb3IgRE1B LiBGaXggdGhpcyBieSBpbXBsZW1lbnRpbmcgYQo+ID4gY3VzdG9tIC5nZW1fcHJpbWVfaW1wb3J0 X3NnX3RhYmxlKCkgb3BlcmF0aW9uIHRoYXQgYWNjZXB0cyBhbGwgaW1wb3J0ZWQKPiA+IGRtYS1i dWYgcmVnYXJkbGVzcyBvZiB0aGUgbnVtYmVyIG9mIHNjYXR0ZXJsaXN0IGVudHJpZXMuCj4gCj4g VGhpcyBwYXRjaCByYWlzZXMgdGhlIHF1ZXN0aW9uIG9mIHdoeSB1c2UgQ01BIGF0IGFsbCBpZiB5 b3UgY2FuIGFjY2VwdAo+IGFueSBraW5kIG9mIGJ1ZmZlcnMuCgpCb3RoIHRoZSBEVSBhbmQgVlNQ IHJlcXVpcmUgRE1BIGNvbnRpZ3VvdXMgbWVtb3J5LiBPbiBSLUNhciBHZW4yIHRoZSBEVSAKcGVy Zm9ybXMgRE1BLCBhbmQgdGh1cyB1c2VzIHRoZSBHRU0gQ01BIGhlbHBlcnMuIE9uIEdlbjMgaXQg ZGVsZWdhdGVzIERNQSB0byAKdGhlIGV4dGVybmFsIFZTUCBjb21wb3NlciwgYW5kIHN0aWxsIHVz ZXMgdGhlIEdFTSBDTUEgaGVscGVycyB0byBlbnN1cmUgdGhhdCAKbWVtb3J5IHdpbGwgYmUgRE1B IGNvbnRpZ3VvdXMgZm9yIHRoZSBWU1AuIFRoZSBwcm9ibGVtIGFyaXNlcyB3aGVuIHBoeXNpY2Fs bHkgCm5vbi1jb250aWd1b3VzIGRtYS1idWYgYnVmZmVycyBhcmUgaW1wb3J0ZWQsIHRoZXkgY2Fu IGJlIG1hcHBlZCBjb250aWd1b3VzbHkgCnRvIHRoZSBWU1AgKGFzc3VtaW5nIGFuIElPTU1VIGlz IHByZXNlbnQpIGJ1dCBub3QgdG8gdGhlIERVIChhcyB0aGVyZSdzIG5vIApJT01NVSkuCgpUaGUg c2l0dWF0aW9uIGlzIHBhcnRpY3VsYXJseSBtZXNzeSBkdWUgdG8gdGhlIGZhY3QgdGhhdCBJIGhh dmUgb25lIFZTUCAKaW5zdGFuY2UgcGVyIENSVEMsIGVhY2ggY29ubmVjdGVkIHRvIGl0cyBvd24g SU9NTVUgY2hhbm5lbC4gVGhlIGRyaXZlciB0aHVzIApkb2Vzbid0IGtub3cgd2hlbiBhbGxvY2F0 aW5nIEdFTSBvYmplY3RzIHRvIHdoaWNoIHN0cnVjdCBkZXZpY2UgdGhleSBuZWVkIHRvIApiZSBt YXBwZWQuIFRoZSBEUk0gaGVscGVycyBkb24ndCBzdXBwb3J0IGRlbGF5ZWQgbWFwcGluZyBvZiBt ZW1vcnkuIEknZCBsaWtlIAp0byBrbm93IHdoZXRoZXIgdGhhdCdzIHNvbWV0aGluZyBJIHNob3Vs ZCBmaXggcHJvcGVybHkgKHdoaWNoIHdvdWxkIGxpa2VseSAKaW52b2x2ZSBtYWpvciByZXdvcmtp bmcgb2YgdGhlIGhlbHBlcnMpIG9yIGhhY2sgYXJvdW5kIGl0IGluIHRoZSBEVSBkcml2ZXIuCgo+ ID4gU2lnbmVkLW9mZi1ieTogTGF1cmVudCBQaW5jaGFydAo+ID4gPGxhdXJlbnQucGluY2hhcnQr cmVuZXNhc0BpZGVhc29uYm9hcmQuY29tPgo+ID4gLS0tCj4gPiAKPiA+ICBkcml2ZXJzL2dwdS9k cm0vcmNhci1kdS9yY2FyX2R1X2Rydi5jIHwgIDIgKy0KPiA+ICBkcml2ZXJzL2dwdS9kcm0vcmNh ci1kdS9yY2FyX2R1X2ttcy5jIHwgMzkgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCj4g PiAgZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9rbXMuaCB8ICA3ICsrKysrKysKPiA+ ICAzIGZpbGVzIGNoYW5nZWQsIDQ3IGluc2VydGlvbnMoKyksIDEgZGVsZXRpb24oLSkKPiA+IAo+ ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9yY2FyLWR1L3JjYXJfZHVfZHJ2LmMKPiA+ IGIvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9kcnYuYyBpbmRleCA0OGMxNjZmOTI1 YTMuLmQ5OTkyMzFmOThjNwo+ID4gMTAwNjQ0Cj4gPiAtLS0gYS9kcml2ZXJzL2dwdS9kcm0vcmNh ci1kdS9yY2FyX2R1X2Rydi5jCj4gPiArKysgYi9kcml2ZXJzL2dwdS9kcm0vcmNhci1kdS9yY2Fy X2R1X2Rydi5jCj4gPiBAQCAtMjg5LDcgKzI4OSw3IEBAIHN0YXRpYyBzdHJ1Y3QgZHJtX2RyaXZl ciByY2FyX2R1X2RyaXZlciA9IHsKPiA+ICAJLmdlbV9wcmltZV9pbXBvcnQJPSBkcm1fZ2VtX3By aW1lX2ltcG9ydCwKPiA+ICAJLmdlbV9wcmltZV9leHBvcnQJPSBkcm1fZ2VtX3ByaW1lX2V4cG9y dCwKPiA+ICAJLmdlbV9wcmltZV9nZXRfc2dfdGFibGUJPSBkcm1fZ2VtX2NtYV9wcmltZV9nZXRf c2dfdGFibGUsCj4gPiAtCS5nZW1fcHJpbWVfaW1wb3J0X3NnX3RhYmxlID0gZHJtX2dlbV9jbWFf cHJpbWVfaW1wb3J0X3NnX3RhYmxlLAo+ID4gKwkuZ2VtX3ByaW1lX2ltcG9ydF9zZ190YWJsZSA9 IHJjYXJfZHVfZ2VtX3ByaW1lX2ltcG9ydF9zZ190YWJsZSwKPiA+ICAJLmdlbV9wcmltZV92bWFw CQk9IGRybV9nZW1fY21hX3ByaW1lX3ZtYXAsCj4gPiAgCS5nZW1fcHJpbWVfdnVubWFwCT0gZHJt X2dlbV9jbWFfcHJpbWVfdnVubWFwLAo+ID4gIAkuZ2VtX3ByaW1lX21tYXAJCT0gZHJtX2dlbV9j bWFfcHJpbWVfbW1hcCwKPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vcmNhci1kdS9y Y2FyX2R1X2ttcy5jCj4gPiBiL2RyaXZlcnMvZ3B1L2RybS9yY2FyLWR1L3JjYXJfZHVfa21zLmMg aW5kZXggNTY2ZDFhOTQ4YzhmLi4yZGQwYzJiYTA0N2QKPiA+IDEwMDY0NAo+ID4gLS0tIGEvZHJp dmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9rbXMuYwo+ID4gKysrIGIvZHJpdmVycy9ncHUv ZHJtL3JjYXItZHUvcmNhcl9kdV9rbXMuYwoKW3NuaXBdCgo+ID4gK3N0cnVjdCBkcm1fZ2VtX29i amVjdCAqcmNhcl9kdV9nZW1fcHJpbWVfaW1wb3J0X3NnX3RhYmxlKHN0cnVjdAo+ID4gZHJtX2Rl dmljZSAqZGV2LAo+ID4gKwkJCQlzdHJ1Y3QgZG1hX2J1Zl9hdHRhY2htZW50ICphdHRhY2gsCj4g PiArCQkJCXN0cnVjdCBzZ190YWJsZSAqc2d0KQo+ID4gK3sKPiA+ICsJc3RydWN0IHJjYXJfZHVf ZGV2aWNlICpyY2R1ID0gZGV2LT5kZXZfcHJpdmF0ZTsKPiA+ICsJc3RydWN0IGRybV9nZW1fY21h X29iamVjdCAqY21hX29iajsKPiA+ICsJc3RydWN0IGRybV9nZW1fb2JqZWN0ICpnZW1fb2JqOwo+ ID4gKwlpbnQgcmV0Owo+ID4gKwo+ID4gKwlpZiAoIXJjYXJfZHVfaGFzKHJjZHUsIFJDQVJfRFVf RkVBVFVSRV9WU1AxX1NPVVJDRSkpCj4gPiArCQlyZXR1cm4gZHJtX2dlbV9jbWFfcHJpbWVfaW1w b3J0X3NnX3RhYmxlKGRldiwgYXR0YWNoLCBzZ3QpOwo+ID4gKwo+ID4gKwkvKiBDcmVhdGUgYSBD TUEgR0VNIGJ1ZmZlci4gKi8KPiA+ICsJY21hX29iaiA9IGt6YWxsb2Moc2l6ZW9mKCpjbWFfb2Jq KSwgR0ZQX0tFUk5FTCk7Cj4gPiArCWlmICghY21hX29iaikKPiA+ICsJCXJldHVybiBFUlJfUFRS KC1FTk9NRU0pOwo+ID4gKwlnZW1fb2JqID0gJmNtYV9vYmotPmJhc2U7Cj4gPiArCj4gPiArCXJl dCA9IGRybV9nZW1fb2JqZWN0X2luaXQoZGV2LCBnZW1fb2JqLCBhdHRhY2gtPmRtYWJ1Zi0+c2l6 ZSk7Cj4gPiArCWlmIChyZXQpCj4gPiArCQlnb3RvIGVycm9yOwo+ID4gKwo+ID4gKwlyZXQgPSBk cm1fZ2VtX2NyZWF0ZV9tbWFwX29mZnNldChnZW1fb2JqKTsKPiA+ICsJaWYgKHJldCkgewo+ID4g KwkJZHJtX2dlbV9vYmplY3RfcmVsZWFzZShnZW1fb2JqKTsKPiA+ICsJCWdvdG8gZXJyb3I7Cj4g PiArCX0KPiA+ICsKPiA+ICsJY21hX29iai0+cGFkZHIgPSAwOwo+IAo+IFRoaXMgaXMgZ29pbmcg dG8gYnJlYWsgZHJtX2dlbV9jbWFfZGVzY3JpYmUoKSBpZiB5b3UgYXJlIHVzaW5nIGl0CgpBcyBm YXIgYXMgSSBjYW4gdGVsbCBkcm1fZ2VtX2NtYV9kZXNjcmliZSgpIHdpbGwganVzdCBwcmludCBw YWRkciA9IDAsIGl0IAp3b24ndCBjcmFzaC4KCj4gcGx1cyB0aGUgcmNhcl9kdV9wbGFuZV9zZXR1 cF9zY2Fub3V0KCkgdW5sZXNzIEknbSBtaXNzaW5nIHNvbWV0aGluZyBiZXNpZGVzCj4gZmFtaWxp YXJpdHkgd2l0aCB0aGUgUkNBUiBkcml2ZXIgY29kZSA6KQoKcmNhcl9kdV9wbGFuZV9zZXR1cF9z Y2Fub3V0KCkgaXMgb25seSBjYWxsZWQgd2hlbiAhcmNhcl9kdV9oYXMocmNkdSwgClJDQVJfRFVf RkVBVFVSRV9WU1AxX1NPVVJDRSkgKHRoYXQgaXMgb24gR2VuMyBoYXJkd2FyZSwgb3Igb24gR2Vu MiB3aGVuIEkgCmFydGlmaWNpYWxseSBkaXNhYmxlIGFsbCBETUEgZnJvbSB0aGUgRFUgYW5kIHVz ZSBleHRlcm5hbCBjb21wb3NlcnMgdG8gZW11bGF0ZSAKR2VuMyBiZWhhdmlvdXIgZm9yIHRlc3Rp bmcgcHVycG9zZSksIGluIHdoaWNoIGNhc2UgdGhpcyBmdW5jdGlvbiBjYWxscyAKZHJtX2dlbV9j bWFfcHJpbWVfaW1wb3J0X3NnX3RhYmxlKCkuCgo+IFRoaXMgZnVuY3Rpb24gbG9va3MgdmVyeSBz aW1pbGFyIHRvIHdoYXQgSSB0cmllZCB0byBkbyBmb3IgbWFsaS1kcCB0bwo+IGFsbG93IHRoZSBp bXBvcnQgb2YgY29udGlndW91cyBETUEgYnVmZmVycyB0aGF0IGhhdmUgbW9yZSB0aGFuIDEgc2d0 Cj4gZW50cmllcy4gSW4gdGhlIGVuZCBJIGdhdmUgdXAgYXMgSSBrZXB0IGZpbmRpbmcgaXNzdWVz IGFuZCB3ZW50IGZvciB0aGUKPiBkcm1fZ2VtX2NtYV9wcmltZV9pbXBvcnRfc2dfdGFibGUoKSBj aGFuZ2VzLiBNYXliZSB5b3UgbmVlZCB0byBkbyBhCj4gc2ltaWxhciBjaGFuZ2UgaW4gdGhlIGZ1 bmN0aW9uIHRvIGJ5cGFzcyBzb21lIHJlcXVpcmVtZW50cyBpZiB0aGUgZHJpdmVyCj4gc2lnbmFs cyB0aGF0IGl0IGNhbiBhY2NlcHQgcmVsYXhlZCByZXF1aXJlbWVudHM/CgpBcyBleHBsYWluZWQg YWJvdmUgSSd2ZSBjb25zaWRlcmVkIHJld29ya2luZyB0aGUgaGVscGVycyAodG8gZG8gaXQgcHJv cGVybHkgSSAKdGhpbmsgSSdsbCBsaWtlbHkgbmVlZCB0byByZXdvcmsgZHJtX3ByaW1lLmMgdG9v KSwgYnV0IEknZCBmaXJzdCBsaWtlIHRvIGtub3cgCndoZXRoZXIgdGhlcmUncyBhbiBpbnRlcmVz dCBmb3IgdGhhdC4KCj4gPiArCWNtYV9vYmotPnNndCA9IHNndDsKPiA+ICsKPiA+ICsJcmV0dXJu IGdlbV9vYmo7Cj4gPiArCj4gPiArZXJyb3I6Cj4gPiArCWtmcmVlKGNtYV9vYmopOwo+ID4gKwly ZXR1cm4gRVJSX1BUUihyZXQpOwo+ID4gK30KCltzbmlwXQoKLS0gClJlZ2FyZHMsCgpMYXVyZW50 IFBpbmNoYXJ0CgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f XwpkcmktZGV2ZWwgbWFpbGluZyBsaXN0CmRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3RvcC5vcmcK aHR0cHM6Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0aW5mby9kcmktZGV2ZWwK