From mboxrd@z Thu Jan 1 00:00:00 1970 From: Laurent Pinchart Date: Thu, 26 Nov 2015 18:26:49 +0000 Subject: Re: [PATCH] drm: rcar-du: Perform initialization/cleanup at probe/remove time Message-Id: <1672184.5pWpzmZmYm@avalon> List-Id: References: <1445295114-20921-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com> <2416796.7aKg1mPfX6@avalon> <20151021153945.GI16848@phenom.ffwll.local> In-Reply-To: <20151021153945.GI16848@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 Wednesday 21 October 2015 17:39:45 Daniel Vetter wrote: > On Wed, Oct 21, 2015 at 06:16:08PM +0300, Laurent Pinchart wrote: > > On Tuesday 20 October 2015 09:32:13 Daniel Vetter wrote: > >> On Tue, Oct 20, 2015 at 01:51:54AM +0300, Laurent Pinchart wrote: > >>> The drm driver .load() operation is prone to race conditions as it > >>> initializes the driver after registering the device nodes. Its usage > >>> is deprecated, inline it in the probe function and call > >>> drm_dev_alloc() and drm_dev_register() explicitly. > >>> > >>> For consistency inline the .unload() handler in the remove function as > >>> well. > >>> > >>> Signed-off-by: Laurent Pinchart > >>> > >>> --- > >>> > >>> drivers/gpu/drm/rcar-du/rcar_du_drv.c | 184 +++++++++++---------- > >>> drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c | 11 +- > >>> drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 11 +- > >>> drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 11 +- > >>> 4 files changed, 104 insertions(+), 113 deletions(-) > >>> > >>> diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > >>> b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index > >>> bebcc97db5e5..46d628752371 > >>> 100644 > >>> --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c > >>> +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c > > > > [snip] > > > >>> -static int rcar_du_remove(struct platform_device *pdev) > >>> +static int rcar_du_probe(struct platform_device *pdev) > >>> { > >>> - struct rcar_du_device *rcdu = platform_get_drvdata(pdev); > >>> + struct device_node *np = pdev->dev.of_node; > >>> + struct rcar_du_device *rcdu; > >>> + struct drm_connector *connector; > >>> + struct drm_device *ddev; > >>> + struct resource *mem; > >>> + int ret; > >>> + > >>> + if (np = NULL) { > >>> + dev_err(&pdev->dev, "no device tree node\n"); > >>> + return -ENODEV; > >>> + } > >>> + > >>> + /* Allocate and initialize the DRM and R-Car device structures. */ > >>> + rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL); > >>> + if (rcdu = NULL) > >>> + return -ENOMEM; > >>> + > >>> + init_waitqueue_head(&rcdu->commit.wait); > >>> > >>> - drm_put_dev(rcdu->ddev); > >>> + rcdu->dev = &pdev->dev; > >>> + rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data; > >>> + > >>> + ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev); > >>> + if (!ddev) > >>> + return -ENOMEM; > >>> + > >>> + rcdu->ddev = ddev; > >>> + ddev->dev_private = rcdu; > >>> + > >>> + platform_set_drvdata(pdev, rcdu); > >>> + > >>> + /* I/O resources */ > >>> + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); > >>> + rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem); > >>> + if (IS_ERR(rcdu->mmio)) { > >>> + ret = PTR_ERR(rcdu->mmio); > >>> + goto error; > >>> + } > >>> + > >>> + /* Initialize vertical blanking interrupts handling. Start with > >>> vblank > >>> + * disabled for all CRTCs. > >>> + */ > >>> + ret = drm_vblank_init(ddev, (1 << rcdu->info->num_crtcs) - 1); > >>> + if (ret < 0) { > >>> + dev_err(&pdev->dev, "failed to initialize vblank\n"); > >>> + goto error; > >>> + } > >>> + > >>> + /* DRM/KMS objects */ > >>> + ret = rcar_du_modeset_init(rcdu); > >>> + if (ret < 0) { > >>> + dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret); > >>> + goto error; > >>> + } > >>> + > >>> + ddev->irq_enabled = 1; > >>> + > >>> + /* Register the DRM device with the core and the connectors with > >>> + * sysfs. > >>> + */ > >>> + ret = drm_dev_register(ddev, 0); > >>> + if (ret) > >>> + goto error; > >>> + > >>> + mutex_lock(&ddev->mode_config.mutex); > >>> + drm_for_each_connector(connector, ddev) { > >>> + ret = drm_connector_register(connector); > >>> + if (ret < 0) > >>> + break; > >>> + } > >>> + mutex_unlock(&ddev->mode_config.mutex); > >> > >> I'm wondereding whether we shouldn't just wrap this up in a helper > >> somehow, like drm_dev_modeset_register. > > > > How about drm_connector_plug_all() to match the existing > > drm_connector_unplug_all() ? > > plug/unplug has for me a different meaning wrt connectors. And because of > the MST problem I'd just leave this along really. > > >> Only trouble is that we might be racing with adding MST connectors > >> already, and that's where I stopped thinking about it ;-) > > > > You'll have to brief me on the MST issue if you want my opinion on the > > matter :-) > > MST can hot-add connectors, and we can do that as soon as we process > hotplug events. Which is generally towards the end of the init sequence, > but decidedly before drm_dev_register(). > > So a function which walks all connectors (even when holding relevant > locks) could try to double-register a connector added through MST hotplug, > leading to slight unpleasantries. > > But since this is hard I didn't think up an idea for how to address this. > Since there's also the question whether the hotplug uevent will fare well > before the drm_dev_register() call ... We've more or less successfully avoided thinking about dynamic addition and removal of encoders and CRTCs so far, and support for dynamically added connectors is probably also not as generic as it could be. We won't be able to continue in this direction for much longer, so prepare yourself psychologically ;-) It's a bit ironic that all these needs for dynamic changes come mostly from the embedded world where everything was supposed to be static. > >> Anyway that aside aside: > >> > >> Acked-by: Daniel Vetter > > > > Thanks. I've just noticed that the driver can crash due to .set_busid being still set to drm_platform_set_busid. I'll send a v2 with that removed and an explicit call to drm_dev_set_unique added. You might want to watch for the same issue if you review similar changes in other drivers. > >>> + > >>> + if (ret < 0) > >>> + goto error; > >>> + > >>> + DRM_INFO("Device %s probed\n", dev_name(&pdev->dev)); > >>> return 0; > >>> + > >>> +error: > >>> + rcar_du_remove(pdev); > >>> + > >>> + return ret; > >>> } -- Regards, Laurent Pinchart From mboxrd@z Thu Jan 1 00:00:00 1970 From: Laurent Pinchart Subject: Re: [PATCH] drm: rcar-du: Perform initialization/cleanup at probe/remove time Date: Thu, 26 Nov 2015 20:26:49 +0200 Message-ID: <1672184.5pWpzmZmYm@avalon> References: <1445295114-20921-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com> <2416796.7aKg1mPfX6@avalon> <20151021153945.GI16848@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 D48756E147 for ; Thu, 26 Nov 2015 10:26:43 -0800 (PST) In-Reply-To: <20151021153945.GI16848@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 SGkgRGFuaWVsLAoKT24gV2VkbmVzZGF5IDIxIE9jdG9iZXIgMjAxNSAxNzozOTo0NSBEYW5pZWwg VmV0dGVyIHdyb3RlOgo+IE9uIFdlZCwgT2N0IDIxLCAyMDE1IGF0IDA2OjE2OjA4UE0gKzAzMDAs IExhdXJlbnQgUGluY2hhcnQgd3JvdGU6Cj4gPiBPbiBUdWVzZGF5IDIwIE9jdG9iZXIgMjAxNSAw OTozMjoxMyBEYW5pZWwgVmV0dGVyIHdyb3RlOgo+ID4+IE9uIFR1ZSwgT2N0IDIwLCAyMDE1IGF0 IDAxOjUxOjU0QU0gKzAzMDAsIExhdXJlbnQgUGluY2hhcnQgd3JvdGU6Cj4gPj4+IFRoZSBkcm0g ZHJpdmVyIC5sb2FkKCkgb3BlcmF0aW9uIGlzIHByb25lIHRvIHJhY2UgY29uZGl0aW9ucyBhcyBp dAo+ID4+PiBpbml0aWFsaXplcyB0aGUgZHJpdmVyIGFmdGVyIHJlZ2lzdGVyaW5nIHRoZSBkZXZp Y2Ugbm9kZXMuIEl0cyB1c2FnZQo+ID4+PiBpcyBkZXByZWNhdGVkLCBpbmxpbmUgaXQgaW4gdGhl IHByb2JlIGZ1bmN0aW9uIGFuZCBjYWxsCj4gPj4+IGRybV9kZXZfYWxsb2MoKSBhbmQgZHJtX2Rl dl9yZWdpc3RlcigpIGV4cGxpY2l0bHkuCj4gPj4+IAo+ID4+PiBGb3IgY29uc2lzdGVuY3kgaW5s aW5lIHRoZSAudW5sb2FkKCkgaGFuZGxlciBpbiB0aGUgcmVtb3ZlIGZ1bmN0aW9uIGFzCj4gPj4+ IHdlbGwuCj4gPj4+IAo+ID4+PiBTaWduZWQtb2ZmLWJ5OiBMYXVyZW50IFBpbmNoYXJ0Cj4gPj4+ IDxsYXVyZW50LnBpbmNoYXJ0K3JlbmVzYXNAaWRlYXNvbmJvYXJkLmNvbT4KPiA+Pj4gLS0tCj4g Pj4+IAo+ID4+PiAgZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9kcnYuYyAgICAgfCAx ODQgKysrKysrKysrKystLS0tLS0tLS0tCj4gPj4+ICBkcml2ZXJzL2dwdS9kcm0vcmNhci1kdS9y Y2FyX2R1X2hkbWljb24uYyB8ICAxMSArLQo+ID4+PiAgZHJpdmVycy9ncHUvZHJtL3JjYXItZHUv cmNhcl9kdV9sdmRzY29uLmMgfCAgMTEgKy0KPiA+Pj4gIGRyaXZlcnMvZ3B1L2RybS9yY2FyLWR1 L3JjYXJfZHVfdmdhY29uLmMgIHwgIDExICstCj4gPj4+ICA0IGZpbGVzIGNoYW5nZWQsIDEwNCBp bnNlcnRpb25zKCspLCAxMTMgZGVsZXRpb25zKC0pCj4gPj4+IAo+ID4+PiBkaWZmIC0tZ2l0IGEv ZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9kdV9kcnYuYwo+ID4+PiBiL2RyaXZlcnMvZ3B1 L2RybS9yY2FyLWR1L3JjYXJfZHVfZHJ2LmMgaW5kZXgKPiA+Pj4gYmViY2M5N2RiNWU1Li40NmQ2 Mjg3NTIzNzEKPiA+Pj4gMTAwNjQ0Cj4gPj4+IC0tLSBhL2RyaXZlcnMvZ3B1L2RybS9yY2FyLWR1 L3JjYXJfZHVfZHJ2LmMKPiA+Pj4gKysrIGIvZHJpdmVycy9ncHUvZHJtL3JjYXItZHUvcmNhcl9k dV9kcnYuYwo+ID4gCj4gPiBbc25pcF0KPiA+IAo+ID4+PiAtc3RhdGljIGludCByY2FyX2R1X3Jl bW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+ID4+PiArc3RhdGljIGludCByY2Fy X2R1X3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gPj4+ICB7Cj4gPj4+IC0J c3RydWN0IHJjYXJfZHVfZGV2aWNlICpyY2R1ID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7 Cj4gPj4+ICsJc3RydWN0IGRldmljZV9ub2RlICpucCA9IHBkZXYtPmRldi5vZl9ub2RlOwo+ID4+ PiArCXN0cnVjdCByY2FyX2R1X2RldmljZSAqcmNkdTsKPiA+Pj4gKwlzdHJ1Y3QgZHJtX2Nvbm5l Y3RvciAqY29ubmVjdG9yOwo+ID4+PiArCXN0cnVjdCBkcm1fZGV2aWNlICpkZGV2Owo+ID4+PiAr CXN0cnVjdCByZXNvdXJjZSAqbWVtOwo+ID4+PiArCWludCByZXQ7Cj4gPj4+ICsKPiA+Pj4gKwlp ZiAobnAgPT0gTlVMTCkgewo+ID4+PiArCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJubyBkZXZpY2Ug dHJlZSBub2RlXG4iKTsKPiA+Pj4gKwkJcmV0dXJuIC1FTk9ERVY7Cj4gPj4+ICsJfQo+ID4+PiAr Cj4gPj4+ICsJLyogQWxsb2NhdGUgYW5kIGluaXRpYWxpemUgdGhlIERSTSBhbmQgUi1DYXIgZGV2 aWNlIHN0cnVjdHVyZXMuICovCj4gPj4+ICsJcmNkdSA9IGRldm1fa3phbGxvYygmcGRldi0+ZGV2 LCBzaXplb2YoKnJjZHUpLCBHRlBfS0VSTkVMKTsKPiA+Pj4gKwlpZiAocmNkdSA9PSBOVUxMKQo+ ID4+PiArCQlyZXR1cm4gLUVOT01FTTsKPiA+Pj4gKwo+ID4+PiArCWluaXRfd2FpdHF1ZXVlX2hl YWQoJnJjZHUtPmNvbW1pdC53YWl0KTsKPiA+Pj4gCj4gPj4+IC0JZHJtX3B1dF9kZXYocmNkdS0+ ZGRldik7Cj4gPj4+ICsJcmNkdS0+ZGV2ID0gJnBkZXYtPmRldjsKPiA+Pj4gKwlyY2R1LT5pbmZv ID0gb2ZfbWF0Y2hfZGV2aWNlKHJjYXJfZHVfb2ZfdGFibGUsIHJjZHUtPmRldiktPmRhdGE7Cj4g Pj4+ICsKPiA+Pj4gKwlkZGV2ID0gZHJtX2Rldl9hbGxvYygmcmNhcl9kdV9kcml2ZXIsICZwZGV2 LT5kZXYpOwo+ID4+PiArCWlmICghZGRldikKPiA+Pj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gPj4+ ICsKPiA+Pj4gKwlyY2R1LT5kZGV2ID0gZGRldjsKPiA+Pj4gKwlkZGV2LT5kZXZfcHJpdmF0ZSA9 IHJjZHU7Cj4gPj4+ICsKPiA+Pj4gKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2LCByY2R1KTsK PiA+Pj4gKwo+ID4+PiArCS8qIEkvTyByZXNvdXJjZXMgKi8KPiA+Pj4gKwltZW0gPSBwbGF0Zm9y bV9nZXRfcmVzb3VyY2UocGRldiwgSU9SRVNPVVJDRV9NRU0sIDApOwo+ID4+PiArCXJjZHUtPm1t aW8gPSBkZXZtX2lvcmVtYXBfcmVzb3VyY2UoJnBkZXYtPmRldiwgbWVtKTsKPiA+Pj4gKwlpZiAo SVNfRVJSKHJjZHUtPm1taW8pKSB7Cj4gPj4+ICsJCXJldCA9IFBUUl9FUlIocmNkdS0+bW1pbyk7 Cj4gPj4+ICsJCWdvdG8gZXJyb3I7Cj4gPj4+ICsJfQo+ID4+PiArCj4gPj4+ICsJLyogSW5pdGlh bGl6ZSB2ZXJ0aWNhbCBibGFua2luZyBpbnRlcnJ1cHRzIGhhbmRsaW5nLiBTdGFydCB3aXRoIAo+ ID4+PiB2YmxhbmsKPiA+Pj4gKwkgKiBkaXNhYmxlZCBmb3IgYWxsIENSVENzLgo+ID4+PiArCSAq Lwo+ID4+PiArCXJldCA9IGRybV92YmxhbmtfaW5pdChkZGV2LCAoMSA8PCByY2R1LT5pbmZvLT5u dW1fY3J0Y3MpIC0gMSk7Cj4gPj4+ICsJaWYgKHJldCA8IDApIHsKPiA+Pj4gKwkJZGV2X2Vycigm cGRldi0+ZGV2LCAiZmFpbGVkIHRvIGluaXRpYWxpemUgdmJsYW5rXG4iKTsKPiA+Pj4gKwkJZ290 byBlcnJvcjsKPiA+Pj4gKwl9Cj4gPj4+ICsKPiA+Pj4gKwkvKiBEUk0vS01TIG9iamVjdHMgKi8K PiA+Pj4gKwlyZXQgPSByY2FyX2R1X21vZGVzZXRfaW5pdChyY2R1KTsKPiA+Pj4gKwlpZiAocmV0 IDwgMCkgewo+ID4+PiArCQlkZXZfZXJyKCZwZGV2LT5kZXYsICJmYWlsZWQgdG8gaW5pdGlhbGl6 ZSBEUk0vS01TICglZClcbiIsIHJldCk7Cj4gPj4+ICsJCWdvdG8gZXJyb3I7Cj4gPj4+ICsJfQo+ ID4+PiArCj4gPj4+ICsJZGRldi0+aXJxX2VuYWJsZWQgPSAxOwo+ID4+PiArCj4gPj4+ICsJLyog UmVnaXN0ZXIgdGhlIERSTSBkZXZpY2Ugd2l0aCB0aGUgY29yZSBhbmQgdGhlIGNvbm5lY3RvcnMg d2l0aAo+ID4+PiArCSAqIHN5c2ZzLgo+ID4+PiArCSAqLwo+ID4+PiArCXJldCA9IGRybV9kZXZf cmVnaXN0ZXIoZGRldiwgMCk7Cj4gPj4+ICsJaWYgKHJldCkKPiA+Pj4gKwkJZ290byBlcnJvcjsK PiA+Pj4gKwo+ID4+PiArCW11dGV4X2xvY2soJmRkZXYtPm1vZGVfY29uZmlnLm11dGV4KTsKPiA+ Pj4gKwlkcm1fZm9yX2VhY2hfY29ubmVjdG9yKGNvbm5lY3RvciwgZGRldikgewo+ID4+PiArCQly ZXQgPSBkcm1fY29ubmVjdG9yX3JlZ2lzdGVyKGNvbm5lY3Rvcik7Cj4gPj4+ICsJCWlmIChyZXQg PCAwKQo+ID4+PiArCQkJYnJlYWs7Cj4gPj4+ICsJfQo+ID4+PiArCW11dGV4X3VubG9jaygmZGRl di0+bW9kZV9jb25maWcubXV0ZXgpOwo+ID4+IAo+ID4+IEknbSB3b25kZXJlZGluZyB3aGV0aGVy IHdlIHNob3VsZG4ndCBqdXN0IHdyYXAgdGhpcyB1cCBpbiBhIGhlbHBlcgo+ID4+IHNvbWVob3cs IGxpa2UgZHJtX2Rldl9tb2Rlc2V0X3JlZ2lzdGVyLgo+ID4gCj4gPiBIb3cgYWJvdXQgZHJtX2Nv bm5lY3Rvcl9wbHVnX2FsbCgpIHRvIG1hdGNoIHRoZSBleGlzdGluZwo+ID4gZHJtX2Nvbm5lY3Rv cl91bnBsdWdfYWxsKCkgPwo+IAo+IHBsdWcvdW5wbHVnIGhhcyBmb3IgbWUgYSBkaWZmZXJlbnQg bWVhbmluZyB3cnQgY29ubmVjdG9ycy4gQW5kIGJlY2F1c2Ugb2YKPiB0aGUgTVNUIHByb2JsZW0g SSdkIGp1c3QgbGVhdmUgdGhpcyBhbG9uZyByZWFsbHkuCj4gCj4gPj4gT25seSB0cm91YmxlIGlz IHRoYXQgd2UgbWlnaHQgYmUgcmFjaW5nIHdpdGggYWRkaW5nIE1TVCBjb25uZWN0b3JzCj4gPj4g YWxyZWFkeSwgYW5kIHRoYXQncyB3aGVyZSBJIHN0b3BwZWQgdGhpbmtpbmcgYWJvdXQgaXQgOy0p Cj4gPiAKPiA+IFlvdSdsbCBoYXZlIHRvIGJyaWVmIG1lIG9uIHRoZSBNU1QgaXNzdWUgaWYgeW91 IHdhbnQgbXkgb3BpbmlvbiBvbiB0aGUKPiA+IG1hdHRlciA6LSkKPiAKPiBNU1QgY2FuIGhvdC1h ZGQgY29ubmVjdG9ycywgYW5kIHdlIGNhbiBkbyB0aGF0IGFzIHNvb24gYXMgd2UgcHJvY2Vzcwo+ IGhvdHBsdWcgZXZlbnRzLiBXaGljaCBpcyBnZW5lcmFsbHkgdG93YXJkcyB0aGUgZW5kIG9mIHRo ZSBpbml0IHNlcXVlbmNlLAo+IGJ1dCBkZWNpZGVkbHkgYmVmb3JlIGRybV9kZXZfcmVnaXN0ZXIo KS4KPiAKPiBTbyBhIGZ1bmN0aW9uIHdoaWNoIHdhbGtzIGFsbCBjb25uZWN0b3JzIChldmVuIHdo ZW4gaG9sZGluZyByZWxldmFudAo+IGxvY2tzKSBjb3VsZCB0cnkgdG8gZG91YmxlLXJlZ2lzdGVy IGEgY29ubmVjdG9yIGFkZGVkIHRocm91Z2ggTVNUIGhvdHBsdWcsCj4gbGVhZGluZyB0byBzbGln aHQgdW5wbGVhc2FudHJpZXMuCj4gCj4gQnV0IHNpbmNlIHRoaXMgaXMgaGFyZCBJIGRpZG4ndCB0 aGluayB1cCBhbiBpZGVhIGZvciBob3cgdG8gYWRkcmVzcyB0aGlzLgo+IFNpbmNlIHRoZXJlJ3Mg YWxzbyB0aGUgcXVlc3Rpb24gd2hldGhlciB0aGUgaG90cGx1ZyB1ZXZlbnQgd2lsbCBmYXJlIHdl bGwKPiBiZWZvcmUgdGhlIGRybV9kZXZfcmVnaXN0ZXIoKSBjYWxsIC4uLgoKV2UndmUgbW9yZSBv ciBsZXNzIHN1Y2Nlc3NmdWxseSBhdm9pZGVkIHRoaW5raW5nIGFib3V0IGR5bmFtaWMgYWRkaXRp b24gYW5kIApyZW1vdmFsIG9mIGVuY29kZXJzIGFuZCBDUlRDcyBzbyBmYXIsIGFuZCBzdXBwb3J0 IGZvciBkeW5hbWljYWxseSBhZGRlZCAKY29ubmVjdG9ycyBpcyBwcm9iYWJseSBhbHNvIG5vdCBh cyBnZW5lcmljIGFzIGl0IGNvdWxkIGJlLiBXZSB3b24ndCBiZSBhYmxlIHRvIApjb250aW51ZSBp biB0aGlzIGRpcmVjdGlvbiBmb3IgbXVjaCBsb25nZXIsIHNvIHByZXBhcmUgeW91cnNlbGYgCnBz eWNob2xvZ2ljYWxseSA7LSkgSXQncyBhIGJpdCBpcm9uaWMgdGhhdCBhbGwgdGhlc2UgbmVlZHMg Zm9yIGR5bmFtaWMgY2hhbmdlcyAKY29tZSBtb3N0bHkgZnJvbSB0aGUgZW1iZWRkZWQgd29ybGQg d2hlcmUgZXZlcnl0aGluZyB3YXMgc3VwcG9zZWQgdG8gYmUgCnN0YXRpYy4KCj4gPj4gQW55d2F5 IHRoYXQgYXNpZGUgYXNpZGU6Cj4gPj4gCj4gPj4gQWNrZWQtYnk6IERhbmllbCBWZXR0ZXIgPGRh bmllbC52ZXR0ZXJAZmZ3bGwuY2g+Cj4gPiAKPiA+IFRoYW5rcy4KCkkndmUganVzdCBub3RpY2Vk IHRoYXQgdGhlIGRyaXZlciBjYW4gY3Jhc2ggZHVlIHRvIC5zZXRfYnVzaWQgYmVpbmcgc3RpbGwg c2V0IAp0byBkcm1fcGxhdGZvcm1fc2V0X2J1c2lkLiBJJ2xsIHNlbmQgYSB2MiB3aXRoIHRoYXQg cmVtb3ZlZCBhbmQgYW4gZXhwbGljaXQgCmNhbGwgdG8gZHJtX2Rldl9zZXRfdW5pcXVlIGFkZGVk LiBZb3UgbWlnaHQgd2FudCB0byB3YXRjaCBmb3IgdGhlIHNhbWUgaXNzdWUgCmlmIHlvdSByZXZp ZXcgc2ltaWxhciBjaGFuZ2VzIGluIG90aGVyIGRyaXZlcnMuCgo+ID4+PiArCj4gPj4+ICsJaWYg KHJldCA8IDApCj4gPj4+ICsJCWdvdG8gZXJyb3I7Cj4gPj4+ICsKPiA+Pj4gKwlEUk1fSU5GTygi RGV2aWNlICVzIHByb2JlZFxuIiwgZGV2X25hbWUoJnBkZXYtPmRldikpOwo+ID4+PiAgCXJldHVy biAwOwo+ID4+PiArCj4gPj4+ICtlcnJvcjoKPiA+Pj4gKwlyY2FyX2R1X3JlbW92ZShwZGV2KTsK PiA+Pj4gKwo+ID4+PiArCXJldHVybiByZXQ7Cj4gPj4+ICB9CgotLSAKUmVnYXJkcywKCkxhdXJl bnQgUGluY2hhcnQKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fCmRyaS1kZXZlbCBtYWlsaW5nIGxpc3QKZHJpLWRldmVsQGxpc3RzLmZyZWVkZXNrdG9wLm9y ZwpodHRwOi8vbGlzdHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vZHJpLWRldmVs Cg==