From mboxrd@z Thu Jan 1 00:00:00 1970 From: linus.walleij@linaro.org (Linus Walleij) Date: Wed, 2 May 2018 15:47:19 +0200 Subject: [PATCH 2/2 v5] drm/pl111: Enable device-specific assigned memory In-Reply-To: <20180502134719.8388-1-linus.walleij@linaro.org> References: <20180502134719.8388-1-linus.walleij@linaro.org> Message-ID: <20180502134719.8388-2-linus.walleij@linaro.org> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org The Versatile Express has 8 MB of dedicated video RAM (VRAM) on the motherboard, which is what we should be using for the PL111 if available. On this platform, the memory backplane is constructed so that only this memory will work properly with the CLCD on the motherboard, using any other memory area just gives random snow on the display. The CA9 Versatile Express also has a PL111 instance on its core tile that can address all memory, and this does not have the restriction. The memory is assigned to the device using the memory-region device tree property and a "shared-dma-pool" reserved memory pool like this: reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; vram: vram at 48000000 { compatible = "shared-dma-pool"; reg = <0x48000000 0x00800000>; no-map; }; }; clcd at 1f000 { compatible = "arm,pl111", "arm,primecell"; (...) memory-region = <&vram>; }?; Cc: Liviu Dudau Cc: Mali DP Maintainers Reviewed-by: Eric Anholt Tested-by: Robin Murphy Signed-off-by: Linus Walleij --- ChangeLog v4->v5: - Collect Robin's Tested-by ChangeLog v4->v5: - Make the GEM sg import function static. ChangeLog v3->v4: - Collect Eric's review-tag. ChangeLog v2->v3: - Fix error path so we uref the memory properly. - Augment the GEM buffer import to return an error pointer if we try to import a buffer when using device-assigned memory: we can only scan out the special memory and the GEM buffers are not copied but referenced by pointer. ChangeLog v1->v2: - Make sure to also call of_reserved_mem_device_release() at remove() and errorpath. --- drivers/gpu/drm/pl111/pl111_drm.h | 1 + drivers/gpu/drm/pl111/pl111_drv.c | 34 +++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/gpu/drm/pl111/pl111_drm.h index 8639b2d4ddf7..ce4501d0ab48 100644 --- a/drivers/gpu/drm/pl111/pl111_drm.h +++ b/drivers/gpu/drm/pl111/pl111_drm.h @@ -79,6 +79,7 @@ struct pl111_drm_dev_private { const struct pl111_variant_data *variant; void (*variant_display_enable) (struct drm_device *drm, u32 format); void (*variant_display_disable) (struct drm_device *drm); + bool use_device_memory; }; int pl111_display_init(struct drm_device *dev); diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c index 4621259d5387..454ff0804642 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -60,6 +60,7 @@ #include #include #include +#include #include #include @@ -207,6 +208,24 @@ static int pl111_modeset_init(struct drm_device *dev) return ret; } +static struct drm_gem_object * +pl111_gem_import_sg_table(struct drm_device *dev, + struct dma_buf_attachment *attach, + struct sg_table *sgt) +{ + struct pl111_drm_dev_private *priv = dev->dev_private; + + /* + * When using device-specific reserved memory we can't import + * DMA buffers: those are passed by reference in any global + * memory and we can only handle a specific range of memory. + */ + if (priv->use_device_memory) + return ERR_PTR(-EINVAL); + + return drm_gem_cma_prime_import_sg_table(dev, attach, sgt); +} + DEFINE_DRM_GEM_CMA_FOPS(drm_fops); static struct drm_driver pl111_drm_driver = { @@ -227,7 +246,7 @@ static struct drm_driver pl111_drm_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_import = drm_gem_prime_import, - .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, + .gem_prime_import_sg_table = pl111_gem_import_sg_table, .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, @@ -257,6 +276,12 @@ static int pl111_amba_probe(struct amba_device *amba_dev, drm->dev_private = priv; priv->variant = variant; + ret = of_reserved_mem_device_init(dev); + if (!ret) { + dev_info(dev, "using device-specific reserved memory\n"); + priv->use_device_memory = true; + } + if (of_property_read_u32(dev->of_node, "max-memory-bandwidth", &priv->memory_bw)) { dev_info(dev, "no max memory bandwidth specified, assume unlimited\n"); @@ -275,7 +300,8 @@ static int pl111_amba_probe(struct amba_device *amba_dev, priv->regs = devm_ioremap_resource(dev, &amba_dev->res); if (IS_ERR(priv->regs)) { dev_err(dev, "%s failed mmio\n", __func__); - return PTR_ERR(priv->regs); + ret = PTR_ERR(priv->regs); + goto dev_unref; } /* This may override some variant settings */ @@ -305,11 +331,14 @@ static int pl111_amba_probe(struct amba_device *amba_dev, dev_unref: drm_dev_unref(drm); + of_reserved_mem_device_release(dev); + return ret; } static int pl111_amba_remove(struct amba_device *amba_dev) { + struct device *dev = &amba_dev->dev; struct drm_device *drm = amba_get_drvdata(amba_dev); struct pl111_drm_dev_private *priv = drm->dev_private; @@ -319,6 +348,7 @@ static int pl111_amba_remove(struct amba_device *amba_dev) drm_panel_bridge_remove(priv->bridge); drm_mode_config_cleanup(drm); drm_dev_unref(drm); + of_reserved_mem_device_release(dev); return 0; } -- 2.17.0 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Linus Walleij Subject: [PATCH 2/2 v5] drm/pl111: Enable device-specific assigned memory Date: Wed, 2 May 2018 15:47:19 +0200 Message-ID: <20180502134719.8388-2-linus.walleij@linaro.org> References: <20180502134719.8388-1-linus.walleij@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from mail-lf0-x243.google.com (mail-lf0-x243.google.com [IPv6:2a00:1450:4010:c07::243]) by gabe.freedesktop.org (Postfix) with ESMTPS id 85C5C6E429 for ; Wed, 2 May 2018 13:47:26 +0000 (UTC) Received: by mail-lf0-x243.google.com with SMTP id m18-v6so20960895lfb.0 for ; Wed, 02 May 2018 06:47:26 -0700 (PDT) In-Reply-To: <20180502134719.8388-1-linus.walleij@linaro.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Gustavo Padovan , Maarten Lankhorst , Sean Paul , Eric Anholt , Liviu Dudau Cc: Mali DP Maintainers , linux-arm-kernel@lists.infradead.org, dri-devel@lists.freedesktop.org List-Id: dri-devel@lists.freedesktop.org VGhlIFZlcnNhdGlsZSBFeHByZXNzIGhhcyA4IE1CIG9mIGRlZGljYXRlZCB2aWRlbyBSQU0gKFZS QU0pCm9uIHRoZSBtb3RoZXJib2FyZCwgd2hpY2ggaXMgd2hhdCB3ZSBzaG91bGQgYmUgdXNpbmcg Zm9yIHRoZQpQTDExMSBpZiBhdmFpbGFibGUuIE9uIHRoaXMgcGxhdGZvcm0sIHRoZSBtZW1vcnkg YmFja3BsYW5lCmlzIGNvbnN0cnVjdGVkIHNvIHRoYXQgb25seSB0aGlzIG1lbW9yeSB3aWxsIHdv cmsgcHJvcGVybHkKd2l0aCB0aGUgQ0xDRCBvbiB0aGUgbW90aGVyYm9hcmQsIHVzaW5nIGFueSBv dGhlciBtZW1vcnkKYXJlYSBqdXN0IGdpdmVzIHJhbmRvbSBzbm93IG9uIHRoZSBkaXNwbGF5LgoK VGhlIENBOSBWZXJzYXRpbGUgRXhwcmVzcyBhbHNvIGhhcyBhIFBMMTExIGluc3RhbmNlIG9uIGl0 cwpjb3JlIHRpbGUgdGhhdCBjYW4gYWRkcmVzcyBhbGwgbWVtb3J5LCBhbmQgdGhpcyBkb2VzIG5v dApoYXZlIHRoZSByZXN0cmljdGlvbi4KClRoZSBtZW1vcnkgaXMgYXNzaWduZWQgdG8gdGhlIGRl dmljZSB1c2luZyB0aGUgbWVtb3J5LXJlZ2lvbgpkZXZpY2UgdHJlZSBwcm9wZXJ0eSBhbmQgYSAi c2hhcmVkLWRtYS1wb29sIiByZXNlcnZlZAptZW1vcnkgcG9vbCBsaWtlIHRoaXM6CgpyZXNlcnZl ZC1tZW1vcnkgewogICAgICAgICNhZGRyZXNzLWNlbGxzID0gPDE+OwogICAgICAgICNzaXplLWNl bGxzID0gPDE+OwogICAgICAgIHJhbmdlczsKCiAgICAgICAgdnJhbTogdnJhbUA0ODAwMDAwMCB7 CiAgICAgICAgICAgICAgICBjb21wYXRpYmxlID0gInNoYXJlZC1kbWEtcG9vbCI7CiAgICAgICAg ICAgICAgICByZWcgPSA8MHg0ODAwMDAwMCAweDAwODAwMDAwPjsKICAgICAgICAgICAgICAgIG5v LW1hcDsKICAgICAgICB9Owp9OwoKY2xjZEAxZjAwMCB7CiAgICAgICAgY29tcGF0aWJsZSA9ICJh cm0scGwxMTEiLCAiYXJtLHByaW1lY2VsbCI7CgkoLi4uKQogICAgICAgIG1lbW9yeS1yZWdpb24g PSA8JnZyYW0+Owp9wrc7CgpDYzogTGl2aXUgRHVkYXUgPGxpdml1LmR1ZGF1QGFybS5jb20+CkNj OiBNYWxpIERQIE1haW50YWluZXJzIDxtYWxpZHBAZm9zcy5hcm0uY29tPgpSZXZpZXdlZC1ieTog RXJpYyBBbmhvbHQgPGVyaWNAYW5ob2x0Lm5ldD4KVGVzdGVkLWJ5OiBSb2JpbiBNdXJwaHkgPHJv YmluLm11cnBoeUBhcm0uY29tPgpTaWduZWQtb2ZmLWJ5OiBMaW51cyBXYWxsZWlqIDxsaW51cy53 YWxsZWlqQGxpbmFyby5vcmc+Ci0tLQpDaGFuZ2VMb2cgdjQtPnY1OgotIENvbGxlY3QgUm9iaW4n cyBUZXN0ZWQtYnkKQ2hhbmdlTG9nIHY0LT52NToKLSBNYWtlIHRoZSBHRU0gc2cgaW1wb3J0IGZ1 bmN0aW9uIHN0YXRpYy4KQ2hhbmdlTG9nIHYzLT52NDoKLSBDb2xsZWN0IEVyaWMncyByZXZpZXct dGFnLgpDaGFuZ2VMb2cgdjItPnYzOgotIEZpeCBlcnJvciBwYXRoIHNvIHdlIHVyZWYgdGhlIG1l bW9yeSBwcm9wZXJseS4KLSBBdWdtZW50IHRoZSBHRU0gYnVmZmVyIGltcG9ydCB0byByZXR1cm4g YW4gZXJyb3IgcG9pbnRlcgogIGlmIHdlIHRyeSB0byBpbXBvcnQgYSBidWZmZXIgd2hlbiB1c2lu ZyBkZXZpY2UtYXNzaWduZWQKICBtZW1vcnk6IHdlIGNhbiBvbmx5IHNjYW4gb3V0IHRoZSBzcGVj aWFsIG1lbW9yeSBhbmQgdGhlCiAgR0VNIGJ1ZmZlcnMgYXJlIG5vdCBjb3BpZWQgYnV0IHJlZmVy ZW5jZWQgYnkgcG9pbnRlci4KQ2hhbmdlTG9nIHYxLT52MjoKLSBNYWtlIHN1cmUgdG8gYWxzbyBj YWxsIG9mX3Jlc2VydmVkX21lbV9kZXZpY2VfcmVsZWFzZSgpIGF0CiAgcmVtb3ZlKCkgYW5kIGVy cm9ycGF0aC4KLS0tCiBkcml2ZXJzL2dwdS9kcm0vcGwxMTEvcGwxMTFfZHJtLmggfCAgMSArCiBk cml2ZXJzL2dwdS9kcm0vcGwxMTEvcGwxMTFfZHJ2LmMgfCAzNCArKysrKysrKysrKysrKysrKysr KysrKysrKysrKy0tCiAyIGZpbGVzIGNoYW5nZWQsIDMzIGluc2VydGlvbnMoKyksIDIgZGVsZXRp b25zKC0pCgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL3BsMTExL3BsMTExX2RybS5oIGIv ZHJpdmVycy9ncHUvZHJtL3BsMTExL3BsMTExX2RybS5oCmluZGV4IDg2MzliMmQ0ZGRmNy4uY2U0 NTAxZDBhYjQ4IDEwMDY0NAotLS0gYS9kcml2ZXJzL2dwdS9kcm0vcGwxMTEvcGwxMTFfZHJtLmgK KysrIGIvZHJpdmVycy9ncHUvZHJtL3BsMTExL3BsMTExX2RybS5oCkBAIC03OSw2ICs3OSw3IEBA IHN0cnVjdCBwbDExMV9kcm1fZGV2X3ByaXZhdGUgewogCWNvbnN0IHN0cnVjdCBwbDExMV92YXJp YW50X2RhdGEgKnZhcmlhbnQ7CiAJdm9pZCAoKnZhcmlhbnRfZGlzcGxheV9lbmFibGUpIChzdHJ1 Y3QgZHJtX2RldmljZSAqZHJtLCB1MzIgZm9ybWF0KTsKIAl2b2lkICgqdmFyaWFudF9kaXNwbGF5 X2Rpc2FibGUpIChzdHJ1Y3QgZHJtX2RldmljZSAqZHJtKTsKKwlib29sIHVzZV9kZXZpY2VfbWVt b3J5OwogfTsKIAogaW50IHBsMTExX2Rpc3BsYXlfaW5pdChzdHJ1Y3QgZHJtX2RldmljZSAqZGV2 KTsKZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9wbDExMS9wbDExMV9kcnYuYyBiL2RyaXZl cnMvZ3B1L2RybS9wbDExMS9wbDExMV9kcnYuYwppbmRleCA0NjIxMjU5ZDUzODcuLjQ1NGZmMDgw NDY0MiAxMDA2NDQKLS0tIGEvZHJpdmVycy9ncHUvZHJtL3BsMTExL3BsMTExX2Rydi5jCisrKyBi L2RyaXZlcnMvZ3B1L2RybS9wbDExMS9wbDExMV9kcnYuYwpAQCAtNjAsNiArNjAsNyBAQAogI2lu Y2x1ZGUgPGxpbnV4L3NsYWIuaD4KICNpbmNsdWRlIDxsaW51eC9vZi5oPgogI2luY2x1ZGUgPGxp bnV4L29mX2dyYXBoLmg+CisjaW5jbHVkZSA8bGludXgvb2ZfcmVzZXJ2ZWRfbWVtLmg+CiAKICNp bmNsdWRlIDxkcm0vZHJtUC5oPgogI2luY2x1ZGUgPGRybS9kcm1fYXRvbWljX2hlbHBlci5oPgpA QCAtMjA3LDYgKzIwOCwyNCBAQCBzdGF0aWMgaW50IHBsMTExX21vZGVzZXRfaW5pdChzdHJ1Y3Qg ZHJtX2RldmljZSAqZGV2KQogCXJldHVybiByZXQ7CiB9CiAKK3N0YXRpYyBzdHJ1Y3QgZHJtX2dl bV9vYmplY3QgKgorcGwxMTFfZ2VtX2ltcG9ydF9zZ190YWJsZShzdHJ1Y3QgZHJtX2RldmljZSAq ZGV2LAorCQkJICBzdHJ1Y3QgZG1hX2J1Zl9hdHRhY2htZW50ICphdHRhY2gsCisJCQkgIHN0cnVj dCBzZ190YWJsZSAqc2d0KQoreworCXN0cnVjdCBwbDExMV9kcm1fZGV2X3ByaXZhdGUgKnByaXYg PSBkZXYtPmRldl9wcml2YXRlOworCisJLyoKKwkgKiBXaGVuIHVzaW5nIGRldmljZS1zcGVjaWZp YyByZXNlcnZlZCBtZW1vcnkgd2UgY2FuJ3QgaW1wb3J0CisJICogRE1BIGJ1ZmZlcnM6IHRob3Nl IGFyZSBwYXNzZWQgYnkgcmVmZXJlbmNlIGluIGFueSBnbG9iYWwKKwkgKiBtZW1vcnkgYW5kIHdl IGNhbiBvbmx5IGhhbmRsZSBhIHNwZWNpZmljIHJhbmdlIG9mIG1lbW9yeS4KKwkgKi8KKwlpZiAo cHJpdi0+dXNlX2RldmljZV9tZW1vcnkpCisJCXJldHVybiBFUlJfUFRSKC1FSU5WQUwpOworCisJ cmV0dXJuIGRybV9nZW1fY21hX3ByaW1lX2ltcG9ydF9zZ190YWJsZShkZXYsIGF0dGFjaCwgc2d0 KTsKK30KKwogREVGSU5FX0RSTV9HRU1fQ01BX0ZPUFMoZHJtX2ZvcHMpOwogCiBzdGF0aWMgc3Ry dWN0IGRybV9kcml2ZXIgcGwxMTFfZHJtX2RyaXZlciA9IHsKQEAgLTIyNyw3ICsyNDYsNyBAQCBz dGF0aWMgc3RydWN0IGRybV9kcml2ZXIgcGwxMTFfZHJtX2RyaXZlciA9IHsKIAkucHJpbWVfaGFu ZGxlX3RvX2ZkID0gZHJtX2dlbV9wcmltZV9oYW5kbGVfdG9fZmQsCiAJLnByaW1lX2ZkX3RvX2hh bmRsZSA9IGRybV9nZW1fcHJpbWVfZmRfdG9faGFuZGxlLAogCS5nZW1fcHJpbWVfaW1wb3J0ID0g ZHJtX2dlbV9wcmltZV9pbXBvcnQsCi0JLmdlbV9wcmltZV9pbXBvcnRfc2dfdGFibGUgPSBkcm1f Z2VtX2NtYV9wcmltZV9pbXBvcnRfc2dfdGFibGUsCisJLmdlbV9wcmltZV9pbXBvcnRfc2dfdGFi bGUgPSBwbDExMV9nZW1faW1wb3J0X3NnX3RhYmxlLAogCS5nZW1fcHJpbWVfZXhwb3J0ID0gZHJt X2dlbV9wcmltZV9leHBvcnQsCiAJLmdlbV9wcmltZV9nZXRfc2dfdGFibGUJPSBkcm1fZ2VtX2Nt YV9wcmltZV9nZXRfc2dfdGFibGUsCiAKQEAgLTI1Nyw2ICsyNzYsMTIgQEAgc3RhdGljIGludCBw bDExMV9hbWJhX3Byb2JlKHN0cnVjdCBhbWJhX2RldmljZSAqYW1iYV9kZXYsCiAJZHJtLT5kZXZf cHJpdmF0ZSA9IHByaXY7CiAJcHJpdi0+dmFyaWFudCA9IHZhcmlhbnQ7CiAKKwlyZXQgPSBvZl9y ZXNlcnZlZF9tZW1fZGV2aWNlX2luaXQoZGV2KTsKKwlpZiAoIXJldCkgeworCQlkZXZfaW5mbyhk ZXYsICJ1c2luZyBkZXZpY2Utc3BlY2lmaWMgcmVzZXJ2ZWQgbWVtb3J5XG4iKTsKKwkJcHJpdi0+ dXNlX2RldmljZV9tZW1vcnkgPSB0cnVlOworCX0KKwogCWlmIChvZl9wcm9wZXJ0eV9yZWFkX3Uz MihkZXYtPm9mX25vZGUsICJtYXgtbWVtb3J5LWJhbmR3aWR0aCIsCiAJCQkJICZwcml2LT5tZW1v cnlfYncpKSB7CiAJCWRldl9pbmZvKGRldiwgIm5vIG1heCBtZW1vcnkgYmFuZHdpZHRoIHNwZWNp ZmllZCwgYXNzdW1lIHVubGltaXRlZFxuIik7CkBAIC0yNzUsNyArMzAwLDggQEAgc3RhdGljIGlu dCBwbDExMV9hbWJhX3Byb2JlKHN0cnVjdCBhbWJhX2RldmljZSAqYW1iYV9kZXYsCiAJcHJpdi0+ cmVncyA9IGRldm1faW9yZW1hcF9yZXNvdXJjZShkZXYsICZhbWJhX2Rldi0+cmVzKTsKIAlpZiAo SVNfRVJSKHByaXYtPnJlZ3MpKSB7CiAJCWRldl9lcnIoZGV2LCAiJXMgZmFpbGVkIG1taW9cbiIs IF9fZnVuY19fKTsKLQkJcmV0dXJuIFBUUl9FUlIocHJpdi0+cmVncyk7CisJCXJldCA9IFBUUl9F UlIocHJpdi0+cmVncyk7CisJCWdvdG8gZGV2X3VucmVmOwogCX0KIAogCS8qIFRoaXMgbWF5IG92 ZXJyaWRlIHNvbWUgdmFyaWFudCBzZXR0aW5ncyAqLwpAQCAtMzA1LDExICszMzEsMTQgQEAgc3Rh dGljIGludCBwbDExMV9hbWJhX3Byb2JlKHN0cnVjdCBhbWJhX2RldmljZSAqYW1iYV9kZXYsCiAK IGRldl91bnJlZjoKIAlkcm1fZGV2X3VucmVmKGRybSk7CisJb2ZfcmVzZXJ2ZWRfbWVtX2Rldmlj ZV9yZWxlYXNlKGRldik7CisKIAlyZXR1cm4gcmV0OwogfQogCiBzdGF0aWMgaW50IHBsMTExX2Ft YmFfcmVtb3ZlKHN0cnVjdCBhbWJhX2RldmljZSAqYW1iYV9kZXYpCiB7CisJc3RydWN0IGRldmlj ZSAqZGV2ID0gJmFtYmFfZGV2LT5kZXY7CiAJc3RydWN0IGRybV9kZXZpY2UgKmRybSA9IGFtYmFf Z2V0X2RydmRhdGEoYW1iYV9kZXYpOwogCXN0cnVjdCBwbDExMV9kcm1fZGV2X3ByaXZhdGUgKnBy aXYgPSBkcm0tPmRldl9wcml2YXRlOwogCkBAIC0zMTksNiArMzQ4LDcgQEAgc3RhdGljIGludCBw bDExMV9hbWJhX3JlbW92ZShzdHJ1Y3QgYW1iYV9kZXZpY2UgKmFtYmFfZGV2KQogCQlkcm1fcGFu ZWxfYnJpZGdlX3JlbW92ZShwcml2LT5icmlkZ2UpOwogCWRybV9tb2RlX2NvbmZpZ19jbGVhbnVw KGRybSk7CiAJZHJtX2Rldl91bnJlZihkcm0pOworCW9mX3Jlc2VydmVkX21lbV9kZXZpY2VfcmVs ZWFzZShkZXYpOwogCiAJcmV0dXJuIDA7CiB9Ci0tIAoyLjE3LjAKCl9fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmRyaS1kZXZlbCBtYWlsaW5nIGxpc3QKZHJp LWRldmVsQGxpc3RzLmZyZWVkZXNrdG9wLm9yZwpodHRwczovL2xpc3RzLmZyZWVkZXNrdG9wLm9y Zy9tYWlsbWFuL2xpc3RpbmZvL2RyaS1kZXZlbAo=