From mboxrd@z Thu Jan 1 00:00:00 1970 From: Laurent Pinchart Date: Sun, 27 Dec 2015 09:00:07 +0000 Subject: Re: [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes Message-Id: <3199261.oWaujEx9hz@avalon> List-Id: References: <1442184669-30990-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com> <2986707.83nd5NsHMZ@avalon> <20151217094151.GV30437@phenom.ffwll.local> In-Reply-To: <20151217094151.GV30437@phenom.ffwll.local> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: Daniel Vetter Cc: Laurent Pinchart , dri-devel@lists.freedesktop.org, linux-sh@vger.kernel.org Hi Daniel, On Thursday 17 December 2015 10:41:51 Daniel Vetter wrote: > On Thu, Dec 17, 2015 at 09:11:49AM +0200, Laurent Pinchart wrote: > > On Monday 14 September 2015 09:22:13 Daniel Vetter wrote: > >> On Mon, Sep 14, 2015 at 01:50:55AM +0300, Laurent Pinchart wrote: > >>> Plane sources are configured by the VSPS bit in the PnDDCR4 register. > >>> Although the datasheet states that the bit is updated during vertical > >>> blanking, it seems that updates only occur when the DU group is held > >>> in reset through the DSYSR.DRES bit. Restart the group if the source > >>> changes. > >>> > >>> Signed-off-by: Laurent Pinchart > >>> > >>> --- > >>> > >>> drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 4 ++++ > >>> drivers/gpu/drm/rcar-du/rcar_du_group.c | 2 ++ > >>> drivers/gpu/drm/rcar-du/rcar_du_group.h | 2 ++ > >>> drivers/gpu/drm/rcar-du/rcar_du_plane.c | 22 ++++++++++++++++++++-- > >>> 4 files changed, 28 insertions(+), 2 deletions(-) > >>> > >>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c > >>> b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index > >>> 48cb19949ca3..7e2f5c26d589 > >>> 100644 > >>> --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c > >>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c > >>> @@ -272,6 +272,10 @@ static void rcar_du_crtc_update_planes(struct > >>> rcar_du_crtc *rcrtc) > >>> rcar_du_group_restart(rcrtc->group); > >>> } > >>> > >>> + /* Restart the group if plane sources have changed. */ > >>> + if (rcrtc->group->need_restart) > >>> + rcar_du_group_restart(rcrtc->group); > >>> + > >>> mutex_unlock(&rcrtc->group->lock); > >>> > >>> rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, > >>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c > >>> b/drivers/gpu/drm/rcar-du/rcar_du_group.c index > >>> 4a44ddd51766..0e2b46dce563 100644 > >>> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c > >>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c > >>> @@ -162,6 +162,8 @@ void rcar_du_group_start_stop(struct rcar_du_group > >>> *rgrp, bool start) > >>> > >>> void rcar_du_group_restart(struct rcar_du_group *rgrp) > >>> { > >>> + rgrp->need_restart = false; > >>> + > >>> __rcar_du_group_start_stop(rgrp, false); > >>> __rcar_du_group_start_stop(rgrp, true); > >>> } > >>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h > >>> b/drivers/gpu/drm/rcar-du/rcar_du_group.h index > >>> 4b1952fd4e7d..5e3adc6b31b5 100644 > >>> --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h > >>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h > >>> @@ -32,6 +32,7 @@ struct rcar_du_device; > >>> * @dptsr_planes: bitmask of planes driven by dot-clock and timing > >>> generator 1 > >>> * @num_planes: number of planes in the group > >>> * @planes: planes handled by the group > >>> + * @need_restart: the group needs to be restarted due to a > >>> configuration change > >>> */ > >>> struct rcar_du_group { > >>> struct rcar_du_device *dev; > >>> @@ -47,6 +48,7 @@ struct rcar_du_group { > >>> unsigned int num_planes; > >>> struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES]; > >>> > >>> + bool need_restart; > >> > >> My recommendation is to keep any of these intermediate values in state > >> objects too. The reason is that eventually we want to also support real > >> queues of atomic commits, > > > > I like the idea :-) > > > >> and then anything stored globally (well, outside of the state objects) > >> won't work. And yes it's ok to push that kind of stuff into helper, > >> this isn't really any different than e.g. crtc_state->active_changed > >> and similar booleans indicating that something special needs to be done > >> when committing. > > > > I agree with you. There's still a couple of state variables I need to > > remove in the driver structures, and that's on my todo list (although not > > very high I'm afraid). > > > > The group state is a bit of an oddball. The DU groups CRTCs by two and > > shares resources inside a group. Implementing that resource sharing > > requires storing group state, which is very difficult without an atomic > > state object for the group. > > > > Am I missing an easy way to fix that ? And would it be fine to upstream > > this patch as-is in the meantime ? I'd like to get it in v4.6, it's been > > out for long enough and is blocking other people. > > Involves a bit of typing, but we allow drivers to subclass > drm_atomic_state and add whatever they want. I hadn't noticed it had been introduced, that's very nice. > The important part is to make sure you get the locking right, i.e. only ever > duplicate anything when you hold the right locks. For that you have about 3 > options: > - protect all group state with mode_config->connection_lock. Might > unecessarily serialize updates. > - create a per-group ww_mutex (atomic allows you to throw as many > additional ww_mutex locks encapsulated within a drm_modeset_lock as you > want). > - just grab the crtc states (plus locks) for all the crtcs in a group when > duplicating a group state > > I highly recommend you follow the patterns laid out in drm_atomic.c and > only allow your driver to get at the group state through a get_group_state > helper, like we have for plane/crtc/connector states. That can then take > care of the locking and everything. Thanks for the tip, I'll give it a try. > i915 uses this to keep track of shared resources like dpll and display > core clock. > > There should be kerneldoc for the individual functions, but I think we > lack an overview/example section ... hint, hint ;-) I'll first try to understand it by using it :-) -- Regards, Laurent Pinchart From mboxrd@z Thu Jan 1 00:00:00 1970 From: Laurent Pinchart Subject: Re: [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes Date: Sun, 27 Dec 2015 11:00:07 +0200 Message-ID: <3199261.oWaujEx9hz@avalon> References: <1442184669-30990-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com> <2986707.83nd5NsHMZ@avalon> <20151217094151.GV30437@phenom.ffwll.local> 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 762D089381 for ; Sun, 27 Dec 2015 01:00:13 -0800 (PST) In-Reply-To: <20151217094151.GV30437@phenom.ffwll.local> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Daniel Vetter Cc: Laurent Pinchart , dri-devel@lists.freedesktop.org, linux-sh@vger.kernel.org List-Id: dri-devel@lists.freedesktop.org SGkgRGFuaWVsLAoKT24gVGh1cnNkYXkgMTcgRGVjZW1iZXIgMjAxNSAxMDo0MTo1MSBEYW5pZWwg VmV0dGVyIHdyb3RlOgo+IE9uIFRodSwgRGVjIDE3LCAyMDE1IGF0IDA5OjExOjQ5QU0gKzAyMDAs IExhdXJlbnQgUGluY2hhcnQgd3JvdGU6Cj4gPiBPbiBNb25kYXkgMTQgU2VwdGVtYmVyIDIwMTUg MDk6MjI6MTMgRGFuaWVsIFZldHRlciB3cm90ZToKPiA+PiBPbiBNb24sIFNlcCAxNCwgMjAxNSBh dCAwMTo1MDo1NUFNICswMzAwLCBMYXVyZW50IFBpbmNoYXJ0IHdyb3RlOgo+ID4+PiBQbGFuZSBz b3VyY2VzIGFyZSBjb25maWd1cmVkIGJ5IHRoZSBWU1BTIGJpdCBpbiB0aGUgUG5ERENSNCByZWdp c3Rlci4KPiA+Pj4gQWx0aG91Z2ggdGhlIGRhdGFzaGVldCBzdGF0ZXMgdGhhdCB0aGUgYml0IGlz IHVwZGF0ZWQgZHVyaW5nIHZlcnRpY2FsCj4gPj4+IGJsYW5raW5nLCBpdCBzZWVtcyB0aGF0IHVw ZGF0ZXMgb25seSBvY2N1ciB3aGVuIHRoZSBEVSBncm91cCBpcyBoZWxkCj4gPj4+IGluIHJlc2V0 IHRocm91Z2ggdGhlIERTWVNSLkRSRVMgYml0LiBSZXN0YXJ0IHRoZSBncm91cCBpZiB0aGUgc291 cmNlCj4gPj4+IGNoYW5nZXMuCj4gPj4+IAo+ID4+PiBTaWduZWQtb2ZmLWJ5OiBMYXVyZW50IFBp bmNoYXJ0Cj4gPj4+IDxsYXVyZW50LnBpbmNoYXJ0K3JlbmVzYXNAaWRlYXNvbmJvYXJkLmNvbT4K PiA+Pj4gLS0tCj4gPj4+IAo+ID4+PiAgZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9j cnRjLmMgIHwgIDQgKysrKwo+ID4+PiAgZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9n cm91cC5jIHwgIDIgKysKPiA+Pj4gIGRyaXZlcnMvZ3B1L2RybS9yY2FyLWR1L3JjYXJfZHVfZ3Jv dXAuaCB8ICAyICsrCj4gPj4+ICBkcml2ZXJzL2dwdS9kcm0vcmNhci1kdS9yY2FyX2R1X3BsYW5l LmMgfCAyMiArKysrKysrKysrKysrKysrKysrKy0tCj4gPj4+ICA0IGZpbGVzIGNoYW5nZWQsIDI4 IGluc2VydGlvbnMoKyksIDIgZGVsZXRpb25zKC0pCj4gPj4+IAo+ID4+PiBkaWZmIC0tZ2l0IGEv ZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9jcnRjLmMKPiA+Pj4gYi9kcml2ZXJzL2dw dS9kcm0vcmNhci1kdS9yY2FyX2R1X2NydGMuYyBpbmRleAo+ID4+PiA0OGNiMTk5NDljYTMuLjdl MmY1YzI2ZDU4OQo+ID4+PiAxMDA2NDQKPiA+Pj4gLS0tIGEvZHJpdmVycy9ncHUvZHJtL3JjYXIt ZHUvcmNhcl9kdV9jcnRjLmMKPiA+Pj4gKysrIGIvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNh cl9kdV9jcnRjLmMKPiA+Pj4gQEAgLTI3Miw2ICsyNzIsMTAgQEAgc3RhdGljIHZvaWQgcmNhcl9k dV9jcnRjX3VwZGF0ZV9wbGFuZXMoc3RydWN0Cj4gPj4+IHJjYXJfZHVfY3J0YyAqcmNydGMpCj4g Pj4+ICAJCQlyY2FyX2R1X2dyb3VwX3Jlc3RhcnQocmNydGMtPmdyb3VwKTsKPiA+Pj4gIAl9Cj4g Pj4+IAo+ID4+PiArCS8qIFJlc3RhcnQgdGhlIGdyb3VwIGlmIHBsYW5lIHNvdXJjZXMgaGF2ZSBj aGFuZ2VkLiAqLwo+ID4+PiArCWlmIChyY3J0Yy0+Z3JvdXAtPm5lZWRfcmVzdGFydCkKPiA+Pj4g KwkJcmNhcl9kdV9ncm91cF9yZXN0YXJ0KHJjcnRjLT5ncm91cCk7Cj4gPj4+ICsKPiA+Pj4gIAlt dXRleF91bmxvY2soJnJjcnRjLT5ncm91cC0+bG9jayk7Cj4gPj4+ICAJCj4gPj4+ICAJcmNhcl9k dV9ncm91cF93cml0ZShyY3J0Yy0+Z3JvdXAsIHJjcnRjLT5pbmRleCAlIDIgPyBEUzJQUiA6IERT MVBSLAo+ID4+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9n cm91cC5jCj4gPj4+IGIvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9ncm91cC5jIGlu ZGV4Cj4gPj4+IDRhNDRkZGQ1MTc2Ni4uMGUyYjQ2ZGNlNTYzIDEwMDY0NAo+ID4+PiAtLS0gYS9k cml2ZXJzL2dwdS9kcm0vcmNhci1kdS9yY2FyX2R1X2dyb3VwLmMKPiA+Pj4gKysrIGIvZHJpdmVy cy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9ncm91cC5jCj4gPj4+IEBAIC0xNjIsNiArMTYyLDgg QEAgdm9pZCByY2FyX2R1X2dyb3VwX3N0YXJ0X3N0b3Aoc3RydWN0IHJjYXJfZHVfZ3JvdXAKPiA+ Pj4gKnJncnAsIGJvb2wgc3RhcnQpCj4gPj4+IAo+ID4+PiAgdm9pZCByY2FyX2R1X2dyb3VwX3Jl c3RhcnQoc3RydWN0IHJjYXJfZHVfZ3JvdXAgKnJncnApCj4gPj4+ICB7Cj4gPj4+ICsJcmdycC0+ bmVlZF9yZXN0YXJ0ID0gZmFsc2U7Cj4gPj4+ICsKPiA+Pj4gIAlfX3JjYXJfZHVfZ3JvdXBfc3Rh cnRfc3RvcChyZ3JwLCBmYWxzZSk7Cj4gPj4+ICAJX19yY2FyX2R1X2dyb3VwX3N0YXJ0X3N0b3Ao cmdycCwgdHJ1ZSk7Cj4gPj4+ICB9Cj4gPj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0v cmNhci1kdS9yY2FyX2R1X2dyb3VwLmgKPiA+Pj4gYi9kcml2ZXJzL2dwdS9kcm0vcmNhci1kdS9y Y2FyX2R1X2dyb3VwLmggaW5kZXgKPiA+Pj4gNGIxOTUyZmQ0ZTdkLi41ZTNhZGM2YjMxYjUgMTAw NjQ0Cj4gPj4+IC0tLSBhL2RyaXZlcnMvZ3B1L2RybS9yY2FyLWR1L3JjYXJfZHVfZ3JvdXAuaAo+ ID4+PiArKysgYi9kcml2ZXJzL2dwdS9kcm0vcmNhci1kdS9yY2FyX2R1X2dyb3VwLmgKPiA+Pj4g QEAgLTMyLDYgKzMyLDcgQEAgc3RydWN0IHJjYXJfZHVfZGV2aWNlOwo+ID4+PiAgICogQGRwdHNy X3BsYW5lczogYml0bWFzayBvZiBwbGFuZXMgZHJpdmVuIGJ5IGRvdC1jbG9jayBhbmQgdGltaW5n Cj4gPj4+ICAgZ2VuZXJhdG9yIDEKPiA+Pj4gICAqIEBudW1fcGxhbmVzOiBudW1iZXIgb2YgcGxh bmVzIGluIHRoZSBncm91cAo+ID4+PiAgICogQHBsYW5lczogcGxhbmVzIGhhbmRsZWQgYnkgdGhl IGdyb3VwCj4gPj4+ICsgKiBAbmVlZF9yZXN0YXJ0OiB0aGUgZ3JvdXAgbmVlZHMgdG8gYmUgcmVz dGFydGVkIGR1ZSB0byBhCj4gPj4+IGNvbmZpZ3VyYXRpb24gY2hhbmdlCj4gPj4+ICAgKi8KPiA+ Pj4gIHN0cnVjdCByY2FyX2R1X2dyb3VwIHsKPiA+Pj4gIAlzdHJ1Y3QgcmNhcl9kdV9kZXZpY2Ug KmRldjsKPiA+Pj4gQEAgLTQ3LDYgKzQ4LDcgQEAgc3RydWN0IHJjYXJfZHVfZ3JvdXAgewo+ID4+ PiAgCXVuc2lnbmVkIGludCBudW1fcGxhbmVzOwo+ID4+PiAgCXN0cnVjdCByY2FyX2R1X3BsYW5l IHBsYW5lc1tSQ0FSX0RVX05VTV9LTVNfUExBTkVTXTsKPiA+Pj4gCj4gPj4+ICsJYm9vbCBuZWVk X3Jlc3RhcnQ7Cj4gPj4gCj4gPj4gTXkgcmVjb21tZW5kYXRpb24gaXMgdG8ga2VlcCBhbnkgb2Yg dGhlc2UgaW50ZXJtZWRpYXRlIHZhbHVlcyBpbiBzdGF0ZQo+ID4+IG9iamVjdHMgdG9vLiBUaGUg cmVhc29uIGlzIHRoYXQgZXZlbnR1YWxseSB3ZSB3YW50IHRvIGFsc28gc3VwcG9ydCByZWFsCj4g Pj4gcXVldWVzIG9mIGF0b21pYyBjb21taXRzLAo+ID4gCj4gPiBJIGxpa2UgdGhlIGlkZWEgOi0p Cj4gPiAKPiA+PiBhbmQgdGhlbiBhbnl0aGluZyBzdG9yZWQgZ2xvYmFsbHkgKHdlbGwsIG91dHNp ZGUgb2YgdGhlIHN0YXRlIG9iamVjdHMpCj4gPj4gd29uJ3Qgd29yay4gQW5kIHllcyBpdCdzIG9r IHRvIHB1c2ggdGhhdCBraW5kIG9mIHN0dWZmIGludG8gaGVscGVyLAo+ID4+IHRoaXMgaXNuJ3Qg cmVhbGx5IGFueSBkaWZmZXJlbnQgdGhhbiBlLmcuIGNydGNfc3RhdGUtPmFjdGl2ZV9jaGFuZ2Vk Cj4gPj4gYW5kIHNpbWlsYXIgYm9vbGVhbnMgaW5kaWNhdGluZyB0aGF0IHNvbWV0aGluZyBzcGVj aWFsIG5lZWRzIHRvIGJlIGRvbmUKPiA+PiB3aGVuIGNvbW1pdHRpbmcuCj4gPgo+ID4gSSBhZ3Jl ZSB3aXRoIHlvdS4gVGhlcmUncyBzdGlsbCBhIGNvdXBsZSBvZiBzdGF0ZSB2YXJpYWJsZXMgSSBu ZWVkIHRvCj4gPiByZW1vdmUgaW4gdGhlIGRyaXZlciBzdHJ1Y3R1cmVzLCBhbmQgdGhhdCdzIG9u IG15IHRvZG8gbGlzdCAoYWx0aG91Z2ggbm90Cj4gPiB2ZXJ5IGhpZ2ggSSdtIGFmcmFpZCkuCj4g PiAKPiA+IFRoZSBncm91cCBzdGF0ZSBpcyBhIGJpdCBvZiBhbiBvZGRiYWxsLiBUaGUgRFUgZ3Jv dXBzIENSVENzIGJ5IHR3byBhbmQKPiA+IHNoYXJlcyByZXNvdXJjZXMgaW5zaWRlIGEgZ3JvdXAu IEltcGxlbWVudGluZyB0aGF0IHJlc291cmNlIHNoYXJpbmcKPiA+IHJlcXVpcmVzIHN0b3Jpbmcg Z3JvdXAgc3RhdGUsIHdoaWNoIGlzIHZlcnkgZGlmZmljdWx0IHdpdGhvdXQgYW4gYXRvbWljCj4g PiBzdGF0ZSBvYmplY3QgZm9yIHRoZSBncm91cC4KPiA+IAo+ID4gQW0gSSBtaXNzaW5nIGFuIGVh c3kgd2F5IHRvIGZpeCB0aGF0ID8gQW5kIHdvdWxkIGl0IGJlIGZpbmUgdG8gdXBzdHJlYW0KPiA+ IHRoaXMgcGF0Y2ggYXMtaXMgaW4gdGhlIG1lYW50aW1lID8gSSdkIGxpa2UgdG8gZ2V0IGl0IGlu IHY0LjYsIGl0J3MgYmVlbgo+ID4gb3V0IGZvciBsb25nIGVub3VnaCBhbmQgaXMgYmxvY2tpbmcg b3RoZXIgcGVvcGxlLgo+IAo+IEludm9sdmVzIGEgYml0IG9mIHR5cGluZywgYnV0IHdlIGFsbG93 IGRyaXZlcnMgdG8gc3ViY2xhc3MKPiBkcm1fYXRvbWljX3N0YXRlIGFuZCBhZGQgd2hhdGV2ZXIg dGhleSB3YW50LgoKSSBoYWRuJ3Qgbm90aWNlZCBpdCBoYWQgYmVlbiBpbnRyb2R1Y2VkLCB0aGF0 J3MgdmVyeSBuaWNlLgoKPiBUaGUgaW1wb3J0YW50IHBhcnQgaXMgdG8gbWFrZSBzdXJlIHlvdSBn ZXQgdGhlIGxvY2tpbmcgcmlnaHQsIGkuZS4gb25seSBldmVyCj4gZHVwbGljYXRlIGFueXRoaW5n IHdoZW4geW91IGhvbGQgdGhlIHJpZ2h0IGxvY2tzLiBGb3IgdGhhdCB5b3UgaGF2ZSBhYm91dCAz Cj4gb3B0aW9uczoKPiAtIHByb3RlY3QgYWxsIGdyb3VwIHN0YXRlIHdpdGggbW9kZV9jb25maWct PmNvbm5lY3Rpb25fbG9jay4gTWlnaHQKPiAgIHVuZWNlc3NhcmlseSBzZXJpYWxpemUgdXBkYXRl cy4KPiAtIGNyZWF0ZSBhIHBlci1ncm91cCB3d19tdXRleCAoYXRvbWljIGFsbG93cyB5b3UgdG8g dGhyb3cgYXMgbWFueQo+ICAgYWRkaXRpb25hbCB3d19tdXRleCBsb2NrcyBlbmNhcHN1bGF0ZWQg d2l0aGluIGEgZHJtX21vZGVzZXRfbG9jayBhcyB5b3UKPiAgIHdhbnQpLgo+IC0ganVzdCBncmFi IHRoZSBjcnRjIHN0YXRlcyAocGx1cyBsb2NrcykgZm9yIGFsbCB0aGUgY3J0Y3MgaW4gYSBncm91 cCB3aGVuCj4gICBkdXBsaWNhdGluZyBhIGdyb3VwIHN0YXRlCj4gCj4gSSBoaWdobHkgcmVjb21t ZW5kIHlvdSBmb2xsb3cgdGhlIHBhdHRlcm5zIGxhaWQgb3V0IGluIGRybV9hdG9taWMuYyBhbmQK PiBvbmx5IGFsbG93IHlvdXIgZHJpdmVyIHRvIGdldCBhdCB0aGUgZ3JvdXAgc3RhdGUgdGhyb3Vn aCBhIGdldF9ncm91cF9zdGF0ZQo+IGhlbHBlciwgbGlrZSB3ZSBoYXZlIGZvciBwbGFuZS9jcnRj L2Nvbm5lY3RvciBzdGF0ZXMuIFRoYXQgY2FuIHRoZW4gdGFrZQo+IGNhcmUgb2YgdGhlIGxvY2tp bmcgYW5kIGV2ZXJ5dGhpbmcuCgpUaGFua3MgZm9yIHRoZSB0aXAsIEknbGwgZ2l2ZSBpdCBhIHRy eS4KCj4gaTkxNSB1c2VzIHRoaXMgdG8ga2VlcCB0cmFjayBvZiBzaGFyZWQgcmVzb3VyY2VzIGxp a2UgZHBsbCBhbmQgZGlzcGxheQo+IGNvcmUgY2xvY2suCj4gCj4gVGhlcmUgc2hvdWxkIGJlIGtl cm5lbGRvYyBmb3IgdGhlIGluZGl2aWR1YWwgZnVuY3Rpb25zLCBidXQgSSB0aGluayB3ZQo+IGxh Y2sgYW4gb3ZlcnZpZXcvZXhhbXBsZSBzZWN0aW9uIC4uLiBoaW50LCBoaW50IDstKQoKSSdsbCBm aXJzdCB0cnkgdG8gdW5kZXJzdGFuZCBpdCBieSB1c2luZyBpdCA6LSkKCi0tIApSZWdhcmRzLAoK TGF1cmVudCBQaW5jaGFydAoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX18KZHJpLWRldmVsIG1haWxpbmcgbGlzdApkcmktZGV2ZWxAbGlzdHMuZnJlZWRlc2t0 b3Aub3JnCmh0dHA6Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0aW5mby9kcmkt ZGV2ZWwK