From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Vetter Date: Thu, 17 Dec 2015 09:41:51 +0000 Subject: Re: [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes Message-Id: <20151217094151.GV30437@phenom.ffwll.local> List-Id: References: <1442184669-30990-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com> <1442184669-30990-9-git-send-email-laurent.pinchart+renesas@ideasonboard.com> <20150914072213.GC3383@phenom.ffwll.local> <2986707.83nd5NsHMZ@avalon> In-Reply-To: <2986707.83nd5NsHMZ@avalon> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: Laurent Pinchart Cc: Laurent Pinchart , dri-devel@lists.freedesktop.org, linux-sh@vger.kernel.org On Thu, Dec 17, 2015 at 09:11:49AM +0200, Laurent Pinchart wrote: > Hi Daniel, > > 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. 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. 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 ;-) Cheers, Daniel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch From mboxrd@z Thu Jan 1 00:00:00 1970 From: Daniel Vetter Subject: Re: [PATCH 08/22] drm: rcar-du: Restart the DU group when a plane source changes Date: Thu, 17 Dec 2015 10:41:51 +0100 Message-ID: <20151217094151.GV30437@phenom.ffwll.local> References: <1442184669-30990-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com> <1442184669-30990-9-git-send-email-laurent.pinchart+renesas@ideasonboard.com> <20150914072213.GC3383@phenom.ffwll.local> <2986707.83nd5NsHMZ@avalon> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from mail-wm0-f52.google.com (mail-wm0-f52.google.com [74.125.82.52]) by gabe.freedesktop.org (Postfix) with ESMTPS id BA65B6E970 for ; Thu, 17 Dec 2015 01:41:54 -0800 (PST) Received: by mail-wm0-f52.google.com with SMTP id p187so12783708wmp.0 for ; Thu, 17 Dec 2015 01:41:54 -0800 (PST) Content-Disposition: inline In-Reply-To: <2986707.83nd5NsHMZ@avalon> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Laurent Pinchart Cc: Laurent Pinchart , dri-devel@lists.freedesktop.org, linux-sh@vger.kernel.org List-Id: dri-devel@lists.freedesktop.org T24gVGh1LCBEZWMgMTcsIDIwMTUgYXQgMDk6MTE6NDlBTSArMDIwMCwgTGF1cmVudCBQaW5jaGFy dCB3cm90ZToKPiBIaSBEYW5pZWwsCj4gCj4gT24gTW9uZGF5IDE0IFNlcHRlbWJlciAyMDE1IDA5 OjIyOjEzIERhbmllbCBWZXR0ZXIgd3JvdGU6Cj4gPiBPbiBNb24sIFNlcCAxNCwgMjAxNSBhdCAw MTo1MDo1NUFNICswMzAwLCBMYXVyZW50IFBpbmNoYXJ0IHdyb3RlOgo+ID4gPiBQbGFuZSBzb3Vy Y2VzIGFyZSBjb25maWd1cmVkIGJ5IHRoZSBWU1BTIGJpdCBpbiB0aGUgUG5ERENSNCByZWdpc3Rl ci4KPiA+ID4gQWx0aG91Z2ggdGhlIGRhdGFzaGVldCBzdGF0ZXMgdGhhdCB0aGUgYml0IGlzIHVw ZGF0ZWQgZHVyaW5nIHZlcnRpY2FsCj4gPiA+IGJsYW5raW5nLCBpdCBzZWVtcyB0aGF0IHVwZGF0 ZXMgb25seSBvY2N1ciB3aGVuIHRoZSBEVSBncm91cCBpcyBoZWxkIGluCj4gPiA+IHJlc2V0IHRo cm91Z2ggdGhlIERTWVNSLkRSRVMgYml0LiBSZXN0YXJ0IHRoZSBncm91cCBpZiB0aGUgc291cmNl Cj4gPiA+IGNoYW5nZXMuCj4gPiA+IAo+ID4gPiBTaWduZWQtb2ZmLWJ5OiBMYXVyZW50IFBpbmNo YXJ0Cj4gPiA+IDxsYXVyZW50LnBpbmNoYXJ0K3JlbmVzYXNAaWRlYXNvbmJvYXJkLmNvbT4KPiA+ ID4gLS0tCj4gPiA+IAo+ID4gPiAgZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9jcnRj LmMgIHwgIDQgKysrKwo+ID4gPiAgZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9ncm91 cC5jIHwgIDIgKysKPiA+ID4gIGRyaXZlcnMvZ3B1L2RybS9yY2FyLWR1L3JjYXJfZHVfZ3JvdXAu aCB8ICAyICsrCj4gPiA+ICBkcml2ZXJzL2dwdS9kcm0vcmNhci1kdS9yY2FyX2R1X3BsYW5lLmMg fCAyMiArKysrKysrKysrKysrKysrKysrKy0tCj4gPiA+ICA0IGZpbGVzIGNoYW5nZWQsIDI4IGlu c2VydGlvbnMoKyksIDIgZGVsZXRpb25zKC0pCj4gPiA+IAo+ID4gPiBkaWZmIC0tZ2l0IGEvZHJp dmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9jcnRjLmMKPiA+ID4gYi9kcml2ZXJzL2dwdS9k cm0vcmNhci1kdS9yY2FyX2R1X2NydGMuYyBpbmRleCA0OGNiMTk5NDljYTMuLjdlMmY1YzI2ZDU4 OQo+ID4gPiAxMDA2NDQKPiA+ID4gLS0tIGEvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9k dV9jcnRjLmMKPiA+ID4gKysrIGIvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9jcnRj LmMKPiA+ID4gQEAgLTI3Miw2ICsyNzIsMTAgQEAgc3RhdGljIHZvaWQgcmNhcl9kdV9jcnRjX3Vw ZGF0ZV9wbGFuZXMoc3RydWN0Cj4gPiA+IHJjYXJfZHVfY3J0YyAqcmNydGMpCj4gPiA+ICAJCQly Y2FyX2R1X2dyb3VwX3Jlc3RhcnQocmNydGMtPmdyb3VwKTsKPiA+ID4gIAl9Cj4gPiA+IAo+ID4g PiArCS8qIFJlc3RhcnQgdGhlIGdyb3VwIGlmIHBsYW5lIHNvdXJjZXMgaGF2ZSBjaGFuZ2VkLiAq Lwo+ID4gPiArCWlmIChyY3J0Yy0+Z3JvdXAtPm5lZWRfcmVzdGFydCkKPiA+ID4gKwkJcmNhcl9k dV9ncm91cF9yZXN0YXJ0KHJjcnRjLT5ncm91cCk7Cj4gPiA+ICsKPiA+ID4gIAltdXRleF91bmxv Y2soJnJjcnRjLT5ncm91cC0+bG9jayk7Cj4gPiA+ICAJCj4gPiA+ICAJcmNhcl9kdV9ncm91cF93 cml0ZShyY3J0Yy0+Z3JvdXAsIHJjcnRjLT5pbmRleCAlIDIgPyBEUzJQUiA6IERTMVBSLAo+ID4g PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9ncm91cC5jCj4g PiA+IGIvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9ncm91cC5jIGluZGV4Cj4gPiA+ IDRhNDRkZGQ1MTc2Ni4uMGUyYjQ2ZGNlNTYzIDEwMDY0NAo+ID4gPiAtLS0gYS9kcml2ZXJzL2dw dS9kcm0vcmNhci1kdS9yY2FyX2R1X2dyb3VwLmMKPiA+ID4gKysrIGIvZHJpdmVycy9ncHUvZHJt L3JjYXItZHUvcmNhcl9kdV9ncm91cC5jCj4gPiA+IEBAIC0xNjIsNiArMTYyLDggQEAgdm9pZCBy Y2FyX2R1X2dyb3VwX3N0YXJ0X3N0b3Aoc3RydWN0IHJjYXJfZHVfZ3JvdXAKPiA+ID4gKnJncnAs IGJvb2wgc3RhcnQpCj4gPiA+IAo+ID4gPiAgdm9pZCByY2FyX2R1X2dyb3VwX3Jlc3RhcnQoc3Ry dWN0IHJjYXJfZHVfZ3JvdXAgKnJncnApCj4gPiA+ICB7Cj4gPiA+ICsJcmdycC0+bmVlZF9yZXN0 YXJ0ID0gZmFsc2U7Cj4gPiA+ICsKPiA+ID4gIAlfX3JjYXJfZHVfZ3JvdXBfc3RhcnRfc3RvcChy Z3JwLCBmYWxzZSk7Cj4gPiA+ICAJX19yY2FyX2R1X2dyb3VwX3N0YXJ0X3N0b3AocmdycCwgdHJ1 ZSk7Cj4gPiA+ICB9Cj4gPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vcmNhci1kdS9y Y2FyX2R1X2dyb3VwLmgKPiA+ID4gYi9kcml2ZXJzL2dwdS9kcm0vcmNhci1kdS9yY2FyX2R1X2dy b3VwLmggaW5kZXgKPiA+ID4gNGIxOTUyZmQ0ZTdkLi41ZTNhZGM2YjMxYjUgMTAwNjQ0Cj4gPiA+ IC0tLSBhL2RyaXZlcnMvZ3B1L2RybS9yY2FyLWR1L3JjYXJfZHVfZ3JvdXAuaAo+ID4gPiArKysg Yi9kcml2ZXJzL2dwdS9kcm0vcmNhci1kdS9yY2FyX2R1X2dyb3VwLmgKPiA+ID4gQEAgLTMyLDYg KzMyLDcgQEAgc3RydWN0IHJjYXJfZHVfZGV2aWNlOwo+ID4gPiAgICogQGRwdHNyX3BsYW5lczog Yml0bWFzayBvZiBwbGFuZXMgZHJpdmVuIGJ5IGRvdC1jbG9jayBhbmQgdGltaW5nCj4gPiA+ICAg Z2VuZXJhdG9yIDEKPiA+ID4gICAqIEBudW1fcGxhbmVzOiBudW1iZXIgb2YgcGxhbmVzIGluIHRo ZSBncm91cAo+ID4gPiAgICogQHBsYW5lczogcGxhbmVzIGhhbmRsZWQgYnkgdGhlIGdyb3VwCj4g PiA+ICsgKiBAbmVlZF9yZXN0YXJ0OiB0aGUgZ3JvdXAgbmVlZHMgdG8gYmUgcmVzdGFydGVkIGR1 ZSB0byBhIGNvbmZpZ3VyYXRpb24KPiA+ID4gY2hhbmdlCj4gPiA+ICAgKi8KPiA+ID4gIHN0cnVj dCByY2FyX2R1X2dyb3VwIHsKPiA+ID4gIAlzdHJ1Y3QgcmNhcl9kdV9kZXZpY2UgKmRldjsKPiA+ ID4gQEAgLTQ3LDYgKzQ4LDcgQEAgc3RydWN0IHJjYXJfZHVfZ3JvdXAgewo+ID4gPiAgCXVuc2ln bmVkIGludCBudW1fcGxhbmVzOwo+ID4gPiAgCXN0cnVjdCByY2FyX2R1X3BsYW5lIHBsYW5lc1tS Q0FSX0RVX05VTV9LTVNfUExBTkVTXTsKPiA+ID4gCj4gPiA+ICsJYm9vbCBuZWVkX3Jlc3RhcnQ7 Cj4gPiAKPiA+IE15IHJlY29tbWVuZGF0aW9uIGlzIHRvIGtlZXAgYW55IG9mIHRoZXNlIGludGVy bWVkaWF0ZSB2YWx1ZXMgaW4gc3RhdGUKPiA+IG9iamVjdHMgdG9vLiBUaGUgcmVhc29uIGlzIHRo YXQgZXZlbnR1YWxseSB3ZSB3YW50IHRvIGFsc28gc3VwcG9ydCByZWFsCj4gPiBxdWV1ZXMgb2Yg YXRvbWljIGNvbW1pdHMsCj4gCj4gSSBsaWtlIHRoZSBpZGVhIDotKQo+IAo+ID4gYW5kIHRoZW4g YW55dGhpbmcgc3RvcmVkIGdsb2JhbGx5ICh3ZWxsLCBvdXRzaWRlIG9mIHRoZSBzdGF0ZSBvYmpl Y3RzKSB3b24ndAo+ID4gd29yay4gQW5kIHllcyBpdCdzIG9rIHRvIHB1c2ggdGhhdCBraW5kIG9m IHN0dWZmIGludG8gaGVscGVyLCB0aGlzIGlzbid0Cj4gPiByZWFsbHkgYW55IGRpZmZlcmVudCB0 aGFuIGUuZy4gY3J0Y19zdGF0ZS0+YWN0aXZlX2NoYW5nZWQgYW5kIHNpbWlsYXIKPiA+IGJvb2xl YW5zIGluZGljYXRpbmcgdGhhdCBzb21ldGhpbmcgc3BlY2lhbCBuZWVkcyB0byBiZSBkb25lIHdo ZW4gY29tbWl0dGluZy4KPiAKPiBJIGFncmVlIHdpdGggeW91LiBUaGVyZSdzIHN0aWxsIGEgY291 cGxlIG9mIHN0YXRlIHZhcmlhYmxlcyBJIG5lZWQgdG8gcmVtb3ZlIAo+IGluIHRoZSBkcml2ZXIg c3RydWN0dXJlcywgYW5kIHRoYXQncyBvbiBteSB0b2RvIGxpc3QgKGFsdGhvdWdoIG5vdCB2ZXJ5 IGhpZ2ggCj4gSSdtIGFmcmFpZCkuCj4gCj4gVGhlIGdyb3VwIHN0YXRlIGlzIGEgYml0IG9mIGFu IG9kZGJhbGwuIFRoZSBEVSBncm91cHMgQ1JUQ3MgYnkgdHdvIGFuZCBzaGFyZXMgCj4gcmVzb3Vy Y2VzIGluc2lkZSBhIGdyb3VwLiBJbXBsZW1lbnRpbmcgdGhhdCByZXNvdXJjZSBzaGFyaW5nIHJl cXVpcmVzIHN0b3JpbmcgCj4gZ3JvdXAgc3RhdGUsIHdoaWNoIGlzIHZlcnkgZGlmZmljdWx0IHdp dGhvdXQgYW4gYXRvbWljIHN0YXRlIG9iamVjdCBmb3IgdGhlIAo+IGdyb3VwLgo+IAo+IEFtIEkg bWlzc2luZyBhbiBlYXN5IHdheSB0byBmaXggdGhhdCA/IEFuZCB3b3VsZCBpdCBiZSBmaW5lIHRv IHVwc3RyZWFtIHRoaXMgCj4gcGF0Y2ggYXMtaXMgaW4gdGhlIG1lYW50aW1lID8gSSdkIGxpa2Ug dG8gZ2V0IGl0IGluIHY0LjYsIGl0J3MgYmVlbiBvdXQgZm9yIAo+IGxvbmcgZW5vdWdoIGFuZCBp cyBibG9ja2luZyBvdGhlciBwZW9wbGUuCgpJbnZvbHZlcyBhIGJpdCBvZiB0eXBpbmcsIGJ1dCB3 ZSBhbGxvdyBkcml2ZXJzIHRvIHN1YmNsYXNzCmRybV9hdG9taWNfc3RhdGUgYW5kIGFkZCB3aGF0 ZXZlciB0aGV5IHdhbnQuIFRoZSBpbXBvcnRhbnQgcGFydCBpcyB0byBtYWtlCnN1cmUgeW91IGdl dCB0aGUgbG9ja2luZyByaWdodCwgaS5lLiBvbmx5IGV2ZXIgZHVwbGljYXRlIGFueXRoaW5nIHdo ZW4geW91CmhvbGQgdGhlIHJpZ2h0IGxvY2tzLiBGb3IgdGhhdCB5b3UgaGF2ZSBhYm91dCAzIG9w dGlvbnM6Ci0gcHJvdGVjdCBhbGwgZ3JvdXAgc3RhdGUgd2l0aCBtb2RlX2NvbmZpZy0+Y29ubmVj dGlvbl9sb2NrLiBNaWdodAogIHVuZWNlc3NhcmlseSBzZXJpYWxpemUgdXBkYXRlcy4KLSBjcmVh dGUgYSBwZXItZ3JvdXAgd3dfbXV0ZXggKGF0b21pYyBhbGxvd3MgeW91IHRvIHRocm93IGFzIG1h bnkKICBhZGRpdGlvbmFsIHd3X211dGV4IGxvY2tzIGVuY2Fwc3VsYXRlZCB3aXRoaW4gYSBkcm1f bW9kZXNldF9sb2NrIGFzIHlvdQogIHdhbnQpLgotIGp1c3QgZ3JhYiB0aGUgY3J0YyBzdGF0ZXMg KHBsdXMgbG9ja3MpIGZvciBhbGwgdGhlIGNydGNzIGluIGEgZ3JvdXAgd2hlbgogIGR1cGxpY2F0 aW5nIGEgZ3JvdXAgc3RhdGUKCkkgaGlnaGx5IHJlY29tbWVuZCB5b3UgZm9sbG93IHRoZSBwYXR0 ZXJucyBsYWlkIG91dCBpbiBkcm1fYXRvbWljLmMgYW5kCm9ubHkgYWxsb3cgeW91ciBkcml2ZXIg dG8gZ2V0IGF0IHRoZSBncm91cCBzdGF0ZSB0aHJvdWdoIGEgZ2V0X2dyb3VwX3N0YXRlCmhlbHBl ciwgbGlrZSB3ZSBoYXZlIGZvciBwbGFuZS9jcnRjL2Nvbm5lY3RvciBzdGF0ZXMuIFRoYXQgY2Fu IHRoZW4gdGFrZQpjYXJlIG9mIHRoZSBsb2NraW5nIGFuZCBldmVyeXRoaW5nLgoKaTkxNSB1c2Vz IHRoaXMgdG8ga2VlcCB0cmFjayBvZiBzaGFyZWQgcmVzb3VyY2VzIGxpa2UgZHBsbCBhbmQgZGlz cGxheQpjb3JlIGNsb2NrLgoKVGhlcmUgc2hvdWxkIGJlIGtlcm5lbGRvYyBmb3IgdGhlIGluZGl2 aWR1YWwgZnVuY3Rpb25zLCBidXQgSSB0aGluayB3ZQpsYWNrIGFuIG92ZXJ2aWV3L2V4YW1wbGUg c2VjdGlvbiAuLi4gaGludCwgaGludCA7LSkKCkNoZWVycywgRGFuaWVsCi0tIApEYW5pZWwgVmV0 dGVyClNvZnR3YXJlIEVuZ2luZWVyLCBJbnRlbCBDb3Jwb3JhdGlvbgpodHRwOi8vYmxvZy5mZnds bC5jaApfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpkcmkt ZGV2ZWwgbWFpbGluZyBsaXN0CmRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3RvcC5vcmcKaHR0cDov L2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2RyaS1kZXZlbAo=