From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.9 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 47F97C5B57F for ; Sun, 30 Jun 2019 15:02:50 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1F5A820673 for ; Sun, 30 Jun 2019 15:02:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="fRHGr0NQ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726547AbfF3PCq (ORCPT ); Sun, 30 Jun 2019 11:02:46 -0400 Received: from mail-qk1-f193.google.com ([209.85.222.193]:43414 "EHLO mail-qk1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726500AbfF3PCq (ORCPT ); Sun, 30 Jun 2019 11:02:46 -0400 Received: by mail-qk1-f193.google.com with SMTP id m14so9019448qka.10; Sun, 30 Jun 2019 08:02:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=dc1ZOlpC7lAGBUCKs27bntMMiI+Lv0N6AfkWh/PXjOk=; b=fRHGr0NQRl6QvXdXDos0N3g4OnlcsrnOQydwKjK+U2IPKj0928RwVCgGi3IQaSs4qH zPnvOEb3KyEDJP8ctxwqL1pH2KxsDKBww8OhmSBtRf+rpS26HQHOvzUQjiLg5OAAGRwm XsG82J9zo8YnkJJxcZe1VI4GIepME7KctKg0TBO+EcFT8kGbfyb56T2bEiM1s2hUtJA6 qoD6XoT0J+kRNHp6YEtaXh7s2UVAXQ/bw9CfgufMCSHubvoFK2EuVBjtwZfdPSLiMwTZ aNkMziMnF4hCh4P+zLJcg+c8dKBysA4k/3VaxQrBB1kZMKecjWDZBRh48zPPkqdxlmZn e0vg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=dc1ZOlpC7lAGBUCKs27bntMMiI+Lv0N6AfkWh/PXjOk=; b=tmXw4pwLCcluUAXI/onrQySsT4VxF06JvA7q53NGm8Wg9BGfgJLH+94bAYweYujYc6 Tx3mkK4735S+Mj40iS0YYQUXZ0FcAZNOxesztaLQGUFm2hvGj/olqE8K0qxym6XtnMee gZJQRAT9eYNQ9OCFRsbT3MCODG2yYJiVSkimPE9XPbFijZSeMhHoRqw3sZ0ICXJWtgM0 0/h0AE0T136Q3Q2hGx9ZUIKtrPbYUgFnLS3qS5tZzE/E2Jp8dszn3c7UBnC2qI6XEVzw wwjZqmePOTevpM0HwEwVtnHuFM8vNV8v+1bnaGTAJvsZ3b1kF6YQUtCzydkL4v3LA17f FI/g== X-Gm-Message-State: APjAAAVaa8rb6Yv2Ea5wFsVJKtd2to/6O/k8U31Cr8n/I8Y9g4C9AJkB ZVs/K3MQQVkRowN5oVNZS04= X-Google-Smtp-Source: APXvYqyb4A8fxnJFGSVk29kqD4iLsI5nw1fUR6ng/0RGFELkKo5n83itxm+NC7Wif+yG0dLGI4k+bA== X-Received: by 2002:a37:795:: with SMTP id 143mr17084419qkh.140.1561906964588; Sun, 30 Jun 2019 08:02:44 -0700 (PDT) Received: from localhost ([2601:184:4780:7861:5010:5849:d76d:b714]) by smtp.gmail.com with ESMTPSA id s11sm4077384qte.49.2019.06.30.08.02.43 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Sun, 30 Jun 2019 08:02:44 -0700 (PDT) From: Rob Clark To: dri-devel@lists.freedesktop.org, linux-arm-msm@vger.kernel.org Cc: freedreno@lists.freedesktop.org, aarch64-laptops@lists.linaro.org, linux-clk@vger.kernel.org, linux-pm@vger.kernel.org, Rob Clark , Michael Turquette , Stephen Boyd , Andy Gross , linux-kernel@vger.kernel.org Subject: [PATCH 1/5] clk: inherit clocks enabled by bootloader Date: Sun, 30 Jun 2019 08:01:39 -0700 Message-Id: <20190630150230.7878-2-robdclark@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190630150230.7878-1-robdclark@gmail.com> References: <20190630150230.7878-1-robdclark@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org From: Rob Clark The goal here is to support inheriting a display setup by bootloader, although there may also be some non-display related use-cases. Rough idea is to add a flag for clks and power domains that might already be enabled when kernel starts, and which should not be disabled at late_initcall if the kernel thinks they are "unused". If bootloader is enabling display, and kernel is using efifb before real display driver is loaded (potentially from kernel module after userspace starts, in a typical distro kernel), we don't want to kill the clocks and power domains that are used by the display before userspace starts. Signed-off-by: Rob Clark --- drivers/clk/clk.c | 48 ++++++++++++++++++++++++++++++++ drivers/clk/qcom/common.c | 25 +++++++++++++++++ drivers/clk/qcom/dispcc-sdm845.c | 22 ++++++++------- drivers/clk/qcom/gcc-sdm845.c | 3 +- include/linux/clk-provider.h | 10 +++++++ 5 files changed, 97 insertions(+), 11 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index aa51756fd4d6..14460e87f508 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -66,6 +66,7 @@ struct clk_core { unsigned long flags; bool orphan; bool rpm_enabled; + bool inherit_enabled; /* clock was enabled by bootloader */ unsigned int enable_count; unsigned int prepare_count; unsigned int protect_count; @@ -1166,6 +1167,9 @@ static void clk_unprepare_unused_subtree(struct clk_core *core) hlist_for_each_entry(child, &core->children, child_node) clk_unprepare_unused_subtree(child); + if (core->inherit_enabled) + return; + if (core->prepare_count) return; @@ -1197,6 +1201,9 @@ static void clk_disable_unused_subtree(struct clk_core *core) hlist_for_each_entry(child, &core->children, child_node) clk_disable_unused_subtree(child); + if (core->inherit_enabled) + return; + if (core->flags & CLK_OPS_PARENT_ENABLE) clk_core_prepare_enable(core->parent); @@ -1270,6 +1277,45 @@ static int clk_disable_unused(void) } late_initcall_sync(clk_disable_unused); +/* Ignore CLK_INHERIT_BOOTLOADER clocks enabled by bootloader. This + * gives a debug knob to disable inheriting clks from bootloader, so + * that drivers that used to work, when loaded as a module, thanks + * to disabling "unused" clocks at late_initcall(), can continue to + * work. + * + * The proper solution is to fix the drivers. + */ +static bool clk_ignore_inherited; +static int __init clk_ignore_inherited_setup(char *__unused) +{ + clk_ignore_inherited = true; + return 1; +} +__setup("clk_ignore_inherited", clk_ignore_inherited_setup); + +/* clock and it's parents are already prepared/enabled from bootloader, + * so simply record the fact. + */ +static void __clk_inherit_enabled(struct clk_core *core) +{ + unsigned long parent_rate = 0; + core->inherit_enabled = true; + if (core->parent) { + __clk_inherit_enabled(core->parent); + parent_rate = core->parent->rate; + } + if (core->ops->recalc_rate) + core->rate = core->ops->recalc_rate(core->hw, parent_rate); +} + +void clk_inherit_enabled(struct clk *clk) +{ + if (clk_ignore_inherited) + return; + __clk_inherit_enabled(clk->core); +} +EXPORT_SYMBOL_GPL(clk_inherit_enabled); + static int clk_core_determine_round_nolock(struct clk_core *core, struct clk_rate_request *req) { @@ -3302,6 +3348,8 @@ static int __clk_core_init(struct clk_core *core) * are enabled during init but might not have a parent yet. */ if (parent) { + if (orphan->inherit_enabled) + __clk_inherit_enabled(parent); /* update the clk tree topology */ __clk_set_parent_before(orphan, parent); __clk_set_parent_after(orphan, parent, NULL); diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index a6b2f86112d8..0d542eeef9aa 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -290,6 +290,31 @@ int qcom_cc_really_probe(struct platform_device *pdev, if (ret) return ret; + /* + * Check which of clocks that we inherit state from bootloader + * are enabled, and fixup enable/prepare state (as well as that + * of it's parents). + */ + for (i = 0; i < num_clks; i++) { + struct clk_hw *hw; + + if (!rclks[i]) + continue; + + hw = &rclks[i]->hw; + + if (!(hw->init->flags & CLK_INHERIT_BOOTLOADER)) + continue; + + if (!clk_is_enabled_regmap(hw)) + continue; + + dev_dbg(dev, "%s is enabled from bootloader!\n", + hw->init->name); + + clk_inherit_enabled(hw->clk); + } + return 0; } EXPORT_SYMBOL_GPL(qcom_cc_really_probe); diff --git a/drivers/clk/qcom/dispcc-sdm845.c b/drivers/clk/qcom/dispcc-sdm845.c index 0cc4909b5dbe..40d7e0ab4340 100644 --- a/drivers/clk/qcom/dispcc-sdm845.c +++ b/drivers/clk/qcom/dispcc-sdm845.c @@ -263,6 +263,7 @@ static struct clk_branch disp_cc_mdss_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "disp_cc_mdss_ahb_clk", + .flags = CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -276,6 +277,7 @@ static struct clk_branch disp_cc_mdss_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "disp_cc_mdss_axi_clk", + .flags = CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -294,7 +296,7 @@ static struct clk_branch disp_cc_mdss_byte0_clk = { "disp_cc_mdss_byte0_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -330,7 +332,7 @@ static struct clk_branch disp_cc_mdss_byte0_intf_clk = { "disp_cc_mdss_byte0_div_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -349,7 +351,7 @@ static struct clk_branch disp_cc_mdss_byte1_clk = { "disp_cc_mdss_byte1_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -385,7 +387,7 @@ static struct clk_branch disp_cc_mdss_byte1_intf_clk = { "disp_cc_mdss_byte1_div_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -403,7 +405,7 @@ static struct clk_branch disp_cc_mdss_esc0_clk = { "disp_cc_mdss_esc0_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -421,7 +423,7 @@ static struct clk_branch disp_cc_mdss_esc1_clk = { "disp_cc_mdss_esc1_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -439,7 +441,7 @@ static struct clk_branch disp_cc_mdss_mdp_clk = { "disp_cc_mdss_mdp_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -475,7 +477,7 @@ static struct clk_branch disp_cc_mdss_pclk0_clk = { "disp_cc_mdss_pclk0_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -494,7 +496,7 @@ static struct clk_branch disp_cc_mdss_pclk1_clk = { "disp_cc_mdss_pclk1_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -561,7 +563,7 @@ static struct clk_branch disp_cc_mdss_vsync_clk = { "disp_cc_mdss_vsync_clk_src", }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c index 7131dcf9b060..fe2498be7bc7 100644 --- a/drivers/clk/qcom/gcc-sdm845.c +++ b/drivers/clk/qcom/gcc-sdm845.c @@ -1314,7 +1314,7 @@ static struct clk_branch gcc_disp_ahb_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_disp_ahb_clk", - .flags = CLK_IS_CRITICAL, + .flags = CLK_IS_CRITICAL | CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, @@ -1328,6 +1328,7 @@ static struct clk_branch gcc_disp_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_disp_axi_clk", + .flags = CLK_INHERIT_BOOTLOADER, .ops = &clk_branch2_ops, }, }, diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index bb6118f79784..41b951c8b92b 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -34,6 +34,7 @@ #define CLK_OPS_PARENT_ENABLE BIT(12) /* duty cycle call may be forwarded to the parent clock */ #define CLK_DUTY_CYCLE_PARENT BIT(13) +#define CLK_INHERIT_BOOTLOADER BIT(14) /* clk may be enabled from bootloader */ struct clk; struct clk_hw; @@ -349,6 +350,15 @@ void clk_hw_unregister_fixed_rate(struct clk_hw *hw); void of_fixed_clk_setup(struct device_node *np); +/** + * clk_inherit_enabled - update the enable/prepare count of a clock and it's + * parents for clock enabled by bootloader. + * + * Intended to be used by clock drivers to inform the clk core of a clock + * that is already running. + */ +void clk_inherit_enabled(struct clk *clk); + /** * struct clk_gate - gating clock * -- 2.20.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Rob Clark Subject: [PATCH 1/5] clk: inherit clocks enabled by bootloader Date: Sun, 30 Jun 2019 08:01:39 -0700 Message-ID: <20190630150230.7878-2-robdclark@gmail.com> References: <20190630150230.7878-1-robdclark@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <20190630150230.7878-1-robdclark-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: freedreno-bounces-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org Sender: "Freedreno" To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org, linux-arm-msm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Cc: Rob Clark , aarch64-laptops-cunTk1MwBs8s++Sfvej+rw@public.gmane.org, linux-pm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Stephen Boyd , Michael Turquette , linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Andy Gross , freedreno-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org, linux-clk-u79uwXL29TY76Z2rM5mHXA@public.gmane.org List-Id: dri-devel@lists.freedesktop.org RnJvbTogUm9iIENsYXJrIDxyb2JkY2xhcmtAY2hyb21pdW0ub3JnPgoKVGhlIGdvYWwgaGVyZSBp cyB0byBzdXBwb3J0IGluaGVyaXRpbmcgYSBkaXNwbGF5IHNldHVwIGJ5IGJvb3Rsb2FkZXIsCmFs dGhvdWdoIHRoZXJlIG1heSBhbHNvIGJlIHNvbWUgbm9uLWRpc3BsYXkgcmVsYXRlZCB1c2UtY2Fz ZXMuCgpSb3VnaCBpZGVhIGlzIHRvIGFkZCBhIGZsYWcgZm9yIGNsa3MgYW5kIHBvd2VyIGRvbWFp bnMgdGhhdCBtaWdodAphbHJlYWR5IGJlIGVuYWJsZWQgd2hlbiBrZXJuZWwgc3RhcnRzLCBhbmQg d2hpY2ggc2hvdWxkIG5vdCBiZQpkaXNhYmxlZCBhdCBsYXRlX2luaXRjYWxsIGlmIHRoZSBrZXJu ZWwgdGhpbmtzIHRoZXkgYXJlICJ1bnVzZWQiLgoKSWYgYm9vdGxvYWRlciBpcyBlbmFibGluZyBk aXNwbGF5LCBhbmQga2VybmVsIGlzIHVzaW5nIGVmaWZiIGJlZm9yZQpyZWFsIGRpc3BsYXkgZHJp dmVyIGlzIGxvYWRlZCAocG90ZW50aWFsbHkgZnJvbSBrZXJuZWwgbW9kdWxlIGFmdGVyCnVzZXJz cGFjZSBzdGFydHMsIGluIGEgdHlwaWNhbCBkaXN0cm8ga2VybmVsKSwgd2UgZG9uJ3Qgd2FudCB0 byBraWxsCnRoZSBjbG9ja3MgYW5kIHBvd2VyIGRvbWFpbnMgdGhhdCBhcmUgdXNlZCBieSB0aGUg ZGlzcGxheSBiZWZvcmUKdXNlcnNwYWNlIHN0YXJ0cy4KClNpZ25lZC1vZmYtYnk6IFJvYiBDbGFy ayA8cm9iZGNsYXJrQGNocm9taXVtLm9yZz4KLS0tCiBkcml2ZXJzL2Nsay9jbGsuYyAgICAgICAg ICAgICAgICB8IDQ4ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCiBkcml2ZXJzL2Ns ay9xY29tL2NvbW1vbi5jICAgICAgICB8IDI1ICsrKysrKysrKysrKysrKysrCiBkcml2ZXJzL2Ns ay9xY29tL2Rpc3BjYy1zZG04NDUuYyB8IDIyICsrKysrKysrLS0tLS0tLQogZHJpdmVycy9jbGsv cWNvbS9nY2Mtc2RtODQ1LmMgICAgfCAgMyArLQogaW5jbHVkZS9saW51eC9jbGstcHJvdmlkZXIu aCAgICAgfCAxMCArKysrKysrCiA1IGZpbGVzIGNoYW5nZWQsIDk3IGluc2VydGlvbnMoKyksIDEx IGRlbGV0aW9ucygtKQoKZGlmZiAtLWdpdCBhL2RyaXZlcnMvY2xrL2Nsay5jIGIvZHJpdmVycy9j bGsvY2xrLmMKaW5kZXggYWE1MTc1NmZkNGQ2Li4xNDQ2MGU4N2Y1MDggMTAwNjQ0Ci0tLSBhL2Ry aXZlcnMvY2xrL2Nsay5jCisrKyBiL2RyaXZlcnMvY2xrL2Nsay5jCkBAIC02Niw2ICs2Niw3IEBA IHN0cnVjdCBjbGtfY29yZSB7CiAJdW5zaWduZWQgbG9uZwkJZmxhZ3M7CiAJYm9vbAkJCW9ycGhh bjsKIAlib29sCQkJcnBtX2VuYWJsZWQ7CisJYm9vbAkJCWluaGVyaXRfZW5hYmxlZDsgLyogY2xv Y2sgd2FzIGVuYWJsZWQgYnkgYm9vdGxvYWRlciAqLwogCXVuc2lnbmVkIGludAkJZW5hYmxlX2Nv dW50OwogCXVuc2lnbmVkIGludAkJcHJlcGFyZV9jb3VudDsKIAl1bnNpZ25lZCBpbnQJCXByb3Rl Y3RfY291bnQ7CkBAIC0xMTY2LDYgKzExNjcsOSBAQCBzdGF0aWMgdm9pZCBjbGtfdW5wcmVwYXJl X3VudXNlZF9zdWJ0cmVlKHN0cnVjdCBjbGtfY29yZSAqY29yZSkKIAlobGlzdF9mb3JfZWFjaF9l bnRyeShjaGlsZCwgJmNvcmUtPmNoaWxkcmVuLCBjaGlsZF9ub2RlKQogCQljbGtfdW5wcmVwYXJl X3VudXNlZF9zdWJ0cmVlKGNoaWxkKTsKIAorCWlmIChjb3JlLT5pbmhlcml0X2VuYWJsZWQpCisJ CXJldHVybjsKKwogCWlmIChjb3JlLT5wcmVwYXJlX2NvdW50KQogCQlyZXR1cm47CiAKQEAgLTEx OTcsNiArMTIwMSw5IEBAIHN0YXRpYyB2b2lkIGNsa19kaXNhYmxlX3VudXNlZF9zdWJ0cmVlKHN0 cnVjdCBjbGtfY29yZSAqY29yZSkKIAlobGlzdF9mb3JfZWFjaF9lbnRyeShjaGlsZCwgJmNvcmUt PmNoaWxkcmVuLCBjaGlsZF9ub2RlKQogCQljbGtfZGlzYWJsZV91bnVzZWRfc3VidHJlZShjaGls ZCk7CiAKKwlpZiAoY29yZS0+aW5oZXJpdF9lbmFibGVkKQorCQlyZXR1cm47CisKIAlpZiAoY29y ZS0+ZmxhZ3MgJiBDTEtfT1BTX1BBUkVOVF9FTkFCTEUpCiAJCWNsa19jb3JlX3ByZXBhcmVfZW5h YmxlKGNvcmUtPnBhcmVudCk7CiAKQEAgLTEyNzAsNiArMTI3Nyw0NSBAQCBzdGF0aWMgaW50IGNs a19kaXNhYmxlX3VudXNlZCh2b2lkKQogfQogbGF0ZV9pbml0Y2FsbF9zeW5jKGNsa19kaXNhYmxl X3VudXNlZCk7CiAKKy8qIElnbm9yZSBDTEtfSU5IRVJJVF9CT09UTE9BREVSIGNsb2NrcyBlbmFi bGVkIGJ5IGJvb3Rsb2FkZXIuICBUaGlzCisgKiBnaXZlcyBhIGRlYnVnIGtub2IgdG8gZGlzYWJs ZSBpbmhlcml0aW5nIGNsa3MgZnJvbSBib290bG9hZGVyLCBzbworICogdGhhdCBkcml2ZXJzIHRo YXQgdXNlZCB0byB3b3JrLCB3aGVuIGxvYWRlZCBhcyBhIG1vZHVsZSwgdGhhbmtzCisgKiB0byBk aXNhYmxpbmcgInVudXNlZCIgY2xvY2tzIGF0IGxhdGVfaW5pdGNhbGwoKSwgY2FuIGNvbnRpbnVl IHRvCisgKiB3b3JrLgorICoKKyAqIFRoZSBwcm9wZXIgc29sdXRpb24gaXMgdG8gZml4IHRoZSBk cml2ZXJzLgorICovCitzdGF0aWMgYm9vbCBjbGtfaWdub3JlX2luaGVyaXRlZDsKK3N0YXRpYyBp bnQgX19pbml0IGNsa19pZ25vcmVfaW5oZXJpdGVkX3NldHVwKGNoYXIgKl9fdW51c2VkKQorewor CWNsa19pZ25vcmVfaW5oZXJpdGVkID0gdHJ1ZTsKKwlyZXR1cm4gMTsKK30KK19fc2V0dXAoImNs a19pZ25vcmVfaW5oZXJpdGVkIiwgY2xrX2lnbm9yZV9pbmhlcml0ZWRfc2V0dXApOworCisvKiBj bG9jayBhbmQgaXQncyBwYXJlbnRzIGFyZSBhbHJlYWR5IHByZXBhcmVkL2VuYWJsZWQgZnJvbSBi b290bG9hZGVyLAorICogc28gc2ltcGx5IHJlY29yZCB0aGUgZmFjdC4KKyAqLworc3RhdGljIHZv aWQgX19jbGtfaW5oZXJpdF9lbmFibGVkKHN0cnVjdCBjbGtfY29yZSAqY29yZSkKK3sKKwl1bnNp Z25lZCBsb25nIHBhcmVudF9yYXRlID0gMDsKKwljb3JlLT5pbmhlcml0X2VuYWJsZWQgPSB0cnVl OworCWlmIChjb3JlLT5wYXJlbnQpIHsKKwkJX19jbGtfaW5oZXJpdF9lbmFibGVkKGNvcmUtPnBh cmVudCk7CisJCXBhcmVudF9yYXRlID0gY29yZS0+cGFyZW50LT5yYXRlOworCX0KKwlpZiAoY29y ZS0+b3BzLT5yZWNhbGNfcmF0ZSkKKwkJY29yZS0+cmF0ZSA9IGNvcmUtPm9wcy0+cmVjYWxjX3Jh dGUoY29yZS0+aHcsIHBhcmVudF9yYXRlKTsKK30KKwordm9pZCBjbGtfaW5oZXJpdF9lbmFibGVk KHN0cnVjdCBjbGsgKmNsaykKK3sKKwlpZiAoY2xrX2lnbm9yZV9pbmhlcml0ZWQpCisJCXJldHVy bjsKKwlfX2Nsa19pbmhlcml0X2VuYWJsZWQoY2xrLT5jb3JlKTsKK30KK0VYUE9SVF9TWU1CT0xf R1BMKGNsa19pbmhlcml0X2VuYWJsZWQpOworCiBzdGF0aWMgaW50IGNsa19jb3JlX2RldGVybWlu ZV9yb3VuZF9ub2xvY2soc3RydWN0IGNsa19jb3JlICpjb3JlLAogCQkJCQkgICBzdHJ1Y3QgY2xr X3JhdGVfcmVxdWVzdCAqcmVxKQogewpAQCAtMzMwMiw2ICszMzQ4LDggQEAgc3RhdGljIGludCBf X2Nsa19jb3JlX2luaXQoc3RydWN0IGNsa19jb3JlICpjb3JlKQogCQkgKiBhcmUgZW5hYmxlZCBk dXJpbmcgaW5pdCBidXQgbWlnaHQgbm90IGhhdmUgYSBwYXJlbnQgeWV0LgogCQkgKi8KIAkJaWYg KHBhcmVudCkgeworCQkJaWYgKG9ycGhhbi0+aW5oZXJpdF9lbmFibGVkKQorCQkJCV9fY2xrX2lu aGVyaXRfZW5hYmxlZChwYXJlbnQpOwogCQkJLyogdXBkYXRlIHRoZSBjbGsgdHJlZSB0b3BvbG9n eSAqLwogCQkJX19jbGtfc2V0X3BhcmVudF9iZWZvcmUob3JwaGFuLCBwYXJlbnQpOwogCQkJX19j bGtfc2V0X3BhcmVudF9hZnRlcihvcnBoYW4sIHBhcmVudCwgTlVMTCk7CmRpZmYgLS1naXQgYS9k cml2ZXJzL2Nsay9xY29tL2NvbW1vbi5jIGIvZHJpdmVycy9jbGsvcWNvbS9jb21tb24uYwppbmRl eCBhNmIyZjg2MTEyZDguLjBkNTQyZWVlZjlhYSAxMDA2NDQKLS0tIGEvZHJpdmVycy9jbGsvcWNv bS9jb21tb24uYworKysgYi9kcml2ZXJzL2Nsay9xY29tL2NvbW1vbi5jCkBAIC0yOTAsNiArMjkw LDMxIEBAIGludCBxY29tX2NjX3JlYWxseV9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpw ZGV2LAogCWlmIChyZXQpCiAJCXJldHVybiByZXQ7CiAKKwkvKgorCSAqIENoZWNrIHdoaWNoIG9m IGNsb2NrcyB0aGF0IHdlIGluaGVyaXQgc3RhdGUgZnJvbSBib290bG9hZGVyCisJICogYXJlIGVu YWJsZWQsIGFuZCBmaXh1cCBlbmFibGUvcHJlcGFyZSBzdGF0ZSAoYXMgd2VsbCBhcyB0aGF0CisJ ICogb2YgaXQncyBwYXJlbnRzKS4KKwkgKi8KKwlmb3IgKGkgPSAwOyBpIDwgbnVtX2Nsa3M7IGkr KykgeworCQlzdHJ1Y3QgY2xrX2h3ICpodzsKKworCQlpZiAoIXJjbGtzW2ldKQorCQkJY29udGlu dWU7CisKKwkJaHcgPSAmcmNsa3NbaV0tPmh3OworCisJCWlmICghKGh3LT5pbml0LT5mbGFncyAm IENMS19JTkhFUklUX0JPT1RMT0FERVIpKQorCQkJY29udGludWU7CisKKwkJaWYgKCFjbGtfaXNf ZW5hYmxlZF9yZWdtYXAoaHcpKQorCQkJY29udGludWU7CisKKwkJZGV2X2RiZyhkZXYsICIlcyBp cyBlbmFibGVkIGZyb20gYm9vdGxvYWRlciFcbiIsCisJCQlody0+aW5pdC0+bmFtZSk7CisKKwkJ Y2xrX2luaGVyaXRfZW5hYmxlZChody0+Y2xrKTsKKwl9CisKIAlyZXR1cm4gMDsKIH0KIEVYUE9S VF9TWU1CT0xfR1BMKHFjb21fY2NfcmVhbGx5X3Byb2JlKTsKZGlmZiAtLWdpdCBhL2RyaXZlcnMv Y2xrL3Fjb20vZGlzcGNjLXNkbTg0NS5jIGIvZHJpdmVycy9jbGsvcWNvbS9kaXNwY2Mtc2RtODQ1 LmMKaW5kZXggMGNjNDkwOWI1ZGJlLi40MGQ3ZTBhYjQzNDAgMTAwNjQ0Ci0tLSBhL2RyaXZlcnMv Y2xrL3Fjb20vZGlzcGNjLXNkbTg0NS5jCisrKyBiL2RyaXZlcnMvY2xrL3Fjb20vZGlzcGNjLXNk bTg0NS5jCkBAIC0yNjMsNiArMjYzLDcgQEAgc3RhdGljIHN0cnVjdCBjbGtfYnJhbmNoIGRpc3Bf Y2NfbWRzc19haGJfY2xrID0gewogCQkuZW5hYmxlX21hc2sgPSBCSVQoMCksCiAJCS5ody5pbml0 ID0gJihzdHJ1Y3QgY2xrX2luaXRfZGF0YSl7CiAJCQkubmFtZSA9ICJkaXNwX2NjX21kc3NfYWhi X2NsayIsCisJCQkuZmxhZ3MgPSBDTEtfSU5IRVJJVF9CT09UTE9BREVSLAogCQkJLm9wcyA9ICZj bGtfYnJhbmNoMl9vcHMsCiAJCX0sCiAJfSwKQEAgLTI3Niw2ICsyNzcsNyBAQCBzdGF0aWMgc3Ry dWN0IGNsa19icmFuY2ggZGlzcF9jY19tZHNzX2F4aV9jbGsgPSB7CiAJCS5lbmFibGVfbWFzayA9 IEJJVCgwKSwKIAkJLmh3LmluaXQgPSAmKHN0cnVjdCBjbGtfaW5pdF9kYXRhKXsKIAkJCS5uYW1l ID0gImRpc3BfY2NfbWRzc19heGlfY2xrIiwKKwkJCS5mbGFncyA9IENMS19JTkhFUklUX0JPT1RM T0FERVIsCiAJCQkub3BzID0gJmNsa19icmFuY2gyX29wcywKIAkJfSwKIAl9LApAQCAtMjk0LDcg KzI5Niw3IEBAIHN0YXRpYyBzdHJ1Y3QgY2xrX2JyYW5jaCBkaXNwX2NjX21kc3NfYnl0ZTBfY2xr ID0gewogCQkJCSJkaXNwX2NjX21kc3NfYnl0ZTBfY2xrX3NyYyIsCiAJCQl9LAogCQkJLm51bV9w YXJlbnRzID0gMSwKLQkJCS5mbGFncyA9IENMS19TRVRfUkFURV9QQVJFTlQsCisJCQkuZmxhZ3Mg PSBDTEtfU0VUX1JBVEVfUEFSRU5UIHwgQ0xLX0lOSEVSSVRfQk9PVExPQURFUiwKIAkJCS5vcHMg PSAmY2xrX2JyYW5jaDJfb3BzLAogCQl9LAogCX0sCkBAIC0zMzAsNyArMzMyLDcgQEAgc3RhdGlj IHN0cnVjdCBjbGtfYnJhbmNoIGRpc3BfY2NfbWRzc19ieXRlMF9pbnRmX2NsayA9IHsKIAkJCQki ZGlzcF9jY19tZHNzX2J5dGUwX2Rpdl9jbGtfc3JjIiwKIAkJCX0sCiAJCQkubnVtX3BhcmVudHMg PSAxLAotCQkJLmZsYWdzID0gQ0xLX1NFVF9SQVRFX1BBUkVOVCwKKwkJCS5mbGFncyA9IENMS19T RVRfUkFURV9QQVJFTlQgfCBDTEtfSU5IRVJJVF9CT09UTE9BREVSLAogCQkJLm9wcyA9ICZjbGtf YnJhbmNoMl9vcHMsCiAJCX0sCiAJfSwKQEAgLTM0OSw3ICszNTEsNyBAQCBzdGF0aWMgc3RydWN0 IGNsa19icmFuY2ggZGlzcF9jY19tZHNzX2J5dGUxX2NsayA9IHsKIAkJCQkiZGlzcF9jY19tZHNz X2J5dGUxX2Nsa19zcmMiLAogCQkJfSwKIAkJCS5udW1fcGFyZW50cyA9IDEsCi0JCQkuZmxhZ3Mg PSBDTEtfU0VUX1JBVEVfUEFSRU5ULAorCQkJLmZsYWdzID0gQ0xLX1NFVF9SQVRFX1BBUkVOVCB8 IENMS19JTkhFUklUX0JPT1RMT0FERVIsCiAJCQkub3BzID0gJmNsa19icmFuY2gyX29wcywKIAkJ fSwKIAl9LApAQCAtMzg1LDcgKzM4Nyw3IEBAIHN0YXRpYyBzdHJ1Y3QgY2xrX2JyYW5jaCBkaXNw X2NjX21kc3NfYnl0ZTFfaW50Zl9jbGsgPSB7CiAJCQkJImRpc3BfY2NfbWRzc19ieXRlMV9kaXZf Y2xrX3NyYyIsCiAJCQl9LAogCQkJLm51bV9wYXJlbnRzID0gMSwKLQkJCS5mbGFncyA9IENMS19T RVRfUkFURV9QQVJFTlQsCisJCQkuZmxhZ3MgPSBDTEtfU0VUX1JBVEVfUEFSRU5UIHwgQ0xLX0lO SEVSSVRfQk9PVExPQURFUiwKIAkJCS5vcHMgPSAmY2xrX2JyYW5jaDJfb3BzLAogCQl9LAogCX0s CkBAIC00MDMsNyArNDA1LDcgQEAgc3RhdGljIHN0cnVjdCBjbGtfYnJhbmNoIGRpc3BfY2NfbWRz c19lc2MwX2NsayA9IHsKIAkJCQkiZGlzcF9jY19tZHNzX2VzYzBfY2xrX3NyYyIsCiAJCQl9LAog CQkJLm51bV9wYXJlbnRzID0gMSwKLQkJCS5mbGFncyA9IENMS19TRVRfUkFURV9QQVJFTlQsCisJ CQkuZmxhZ3MgPSBDTEtfU0VUX1JBVEVfUEFSRU5UIHwgQ0xLX0lOSEVSSVRfQk9PVExPQURFUiwK IAkJCS5vcHMgPSAmY2xrX2JyYW5jaDJfb3BzLAogCQl9LAogCX0sCkBAIC00MjEsNyArNDIzLDcg QEAgc3RhdGljIHN0cnVjdCBjbGtfYnJhbmNoIGRpc3BfY2NfbWRzc19lc2MxX2NsayA9IHsKIAkJ CQkiZGlzcF9jY19tZHNzX2VzYzFfY2xrX3NyYyIsCiAJCQl9LAogCQkJLm51bV9wYXJlbnRzID0g MSwKLQkJCS5mbGFncyA9IENMS19TRVRfUkFURV9QQVJFTlQsCisJCQkuZmxhZ3MgPSBDTEtfU0VU X1JBVEVfUEFSRU5UIHwgQ0xLX0lOSEVSSVRfQk9PVExPQURFUiwKIAkJCS5vcHMgPSAmY2xrX2Jy YW5jaDJfb3BzLAogCQl9LAogCX0sCkBAIC00MzksNyArNDQxLDcgQEAgc3RhdGljIHN0cnVjdCBj bGtfYnJhbmNoIGRpc3BfY2NfbWRzc19tZHBfY2xrID0gewogCQkJCSJkaXNwX2NjX21kc3NfbWRw X2Nsa19zcmMiLAogCQkJfSwKIAkJCS5udW1fcGFyZW50cyA9IDEsCi0JCQkuZmxhZ3MgPSBDTEtf U0VUX1JBVEVfUEFSRU5ULAorCQkJLmZsYWdzID0gQ0xLX1NFVF9SQVRFX1BBUkVOVCB8IENMS19J TkhFUklUX0JPT1RMT0FERVIsCiAJCQkub3BzID0gJmNsa19icmFuY2gyX29wcywKIAkJfSwKIAl9 LApAQCAtNDc1LDcgKzQ3Nyw3IEBAIHN0YXRpYyBzdHJ1Y3QgY2xrX2JyYW5jaCBkaXNwX2NjX21k c3NfcGNsazBfY2xrID0gewogCQkJCSJkaXNwX2NjX21kc3NfcGNsazBfY2xrX3NyYyIsCiAJCQl9 LAogCQkJLm51bV9wYXJlbnRzID0gMSwKLQkJCS5mbGFncyA9IENMS19TRVRfUkFURV9QQVJFTlQs CisJCQkuZmxhZ3MgPSBDTEtfU0VUX1JBVEVfUEFSRU5UIHwgQ0xLX0lOSEVSSVRfQk9PVExPQURF UiwKIAkJCS5vcHMgPSAmY2xrX2JyYW5jaDJfb3BzLAogCQl9LAogCX0sCkBAIC00OTQsNyArNDk2 LDcgQEAgc3RhdGljIHN0cnVjdCBjbGtfYnJhbmNoIGRpc3BfY2NfbWRzc19wY2xrMV9jbGsgPSB7 CiAJCQkJImRpc3BfY2NfbWRzc19wY2xrMV9jbGtfc3JjIiwKIAkJCX0sCiAJCQkubnVtX3BhcmVu dHMgPSAxLAotCQkJLmZsYWdzID0gQ0xLX1NFVF9SQVRFX1BBUkVOVCwKKwkJCS5mbGFncyA9IENM S19TRVRfUkFURV9QQVJFTlQgfCBDTEtfSU5IRVJJVF9CT09UTE9BREVSLAogCQkJLm9wcyA9ICZj bGtfYnJhbmNoMl9vcHMsCiAJCX0sCiAJfSwKQEAgLTU2MSw3ICs1NjMsNyBAQCBzdGF0aWMgc3Ry dWN0IGNsa19icmFuY2ggZGlzcF9jY19tZHNzX3ZzeW5jX2NsayA9IHsKIAkJCQkiZGlzcF9jY19t ZHNzX3ZzeW5jX2Nsa19zcmMiLAogCQkJfSwKIAkJCS5udW1fcGFyZW50cyA9IDEsCi0JCQkuZmxh Z3MgPSBDTEtfU0VUX1JBVEVfUEFSRU5ULAorCQkJLmZsYWdzID0gQ0xLX1NFVF9SQVRFX1BBUkVO VCB8IENMS19JTkhFUklUX0JPT1RMT0FERVIsCiAJCQkub3BzID0gJmNsa19icmFuY2gyX29wcywK IAkJfSwKIAl9LApkaWZmIC0tZ2l0IGEvZHJpdmVycy9jbGsvcWNvbS9nY2Mtc2RtODQ1LmMgYi9k cml2ZXJzL2Nsay9xY29tL2djYy1zZG04NDUuYwppbmRleCA3MTMxZGNmOWIwNjAuLmZlMjQ5OGJl N2JjNyAxMDA2NDQKLS0tIGEvZHJpdmVycy9jbGsvcWNvbS9nY2Mtc2RtODQ1LmMKKysrIGIvZHJp dmVycy9jbGsvcWNvbS9nY2Mtc2RtODQ1LmMKQEAgLTEzMTQsNyArMTMxNCw3IEBAIHN0YXRpYyBz dHJ1Y3QgY2xrX2JyYW5jaCBnY2NfZGlzcF9haGJfY2xrID0gewogCQkuZW5hYmxlX21hc2sgPSBC SVQoMCksCiAJCS5ody5pbml0ID0gJihzdHJ1Y3QgY2xrX2luaXRfZGF0YSl7CiAJCQkubmFtZSA9 ICJnY2NfZGlzcF9haGJfY2xrIiwKLQkJCS5mbGFncyA9IENMS19JU19DUklUSUNBTCwKKwkJCS5m bGFncyA9IENMS19JU19DUklUSUNBTCB8IENMS19JTkhFUklUX0JPT1RMT0FERVIsCiAJCQkub3Bz ID0gJmNsa19icmFuY2gyX29wcywKIAkJfSwKIAl9LApAQCAtMTMyOCw2ICsxMzI4LDcgQEAgc3Rh dGljIHN0cnVjdCBjbGtfYnJhbmNoIGdjY19kaXNwX2F4aV9jbGsgPSB7CiAJCS5lbmFibGVfbWFz ayA9IEJJVCgwKSwKIAkJLmh3LmluaXQgPSAmKHN0cnVjdCBjbGtfaW5pdF9kYXRhKXsKIAkJCS5u YW1lID0gImdjY19kaXNwX2F4aV9jbGsiLAorCQkJLmZsYWdzID0gQ0xLX0lOSEVSSVRfQk9PVExP QURFUiwKIAkJCS5vcHMgPSAmY2xrX2JyYW5jaDJfb3BzLAogCQl9LAogCX0sCmRpZmYgLS1naXQg YS9pbmNsdWRlL2xpbnV4L2Nsay1wcm92aWRlci5oIGIvaW5jbHVkZS9saW51eC9jbGstcHJvdmlk ZXIuaAppbmRleCBiYjYxMThmNzk3ODQuLjQxYjk1MWM4YjkyYiAxMDA2NDQKLS0tIGEvaW5jbHVk ZS9saW51eC9jbGstcHJvdmlkZXIuaAorKysgYi9pbmNsdWRlL2xpbnV4L2Nsay1wcm92aWRlci5o CkBAIC0zNCw2ICszNCw3IEBACiAjZGVmaW5lIENMS19PUFNfUEFSRU5UX0VOQUJMRQlCSVQoMTIp CiAvKiBkdXR5IGN5Y2xlIGNhbGwgbWF5IGJlIGZvcndhcmRlZCB0byB0aGUgcGFyZW50IGNsb2Nr ICovCiAjZGVmaW5lIENMS19EVVRZX0NZQ0xFX1BBUkVOVAlCSVQoMTMpCisjZGVmaW5lIENMS19J TkhFUklUX0JPT1RMT0FERVIJQklUKDE0KSAvKiBjbGsgbWF5IGJlIGVuYWJsZWQgZnJvbSBib290 bG9hZGVyICovCiAKIHN0cnVjdCBjbGs7CiBzdHJ1Y3QgY2xrX2h3OwpAQCAtMzQ5LDYgKzM1MCwx NSBAQCB2b2lkIGNsa19od191bnJlZ2lzdGVyX2ZpeGVkX3JhdGUoc3RydWN0IGNsa19odyAqaHcp OwogCiB2b2lkIG9mX2ZpeGVkX2Nsa19zZXR1cChzdHJ1Y3QgZGV2aWNlX25vZGUgKm5wKTsKIAor LyoqCisgKiBjbGtfaW5oZXJpdF9lbmFibGVkIC0gdXBkYXRlIHRoZSBlbmFibGUvcHJlcGFyZSBj b3VudCBvZiBhIGNsb2NrIGFuZCBpdCdzCisgKiBwYXJlbnRzIGZvciBjbG9jayBlbmFibGVkIGJ5 IGJvb3Rsb2FkZXIuCisgKgorICogSW50ZW5kZWQgdG8gYmUgdXNlZCBieSBjbG9jayBkcml2ZXJz IHRvIGluZm9ybSB0aGUgY2xrIGNvcmUgb2YgYSBjbG9jaworICogdGhhdCBpcyBhbHJlYWR5IHJ1 bm5pbmcuCisgKi8KK3ZvaWQgY2xrX2luaGVyaXRfZW5hYmxlZChzdHJ1Y3QgY2xrICpjbGspOwor CiAvKioKICAqIHN0cnVjdCBjbGtfZ2F0ZSAtIGdhdGluZyBjbG9jawogICoKLS0gCjIuMjAuMQoK X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KRnJlZWRyZW5v IG1haWxpbmcgbGlzdApGcmVlZHJlbm9AbGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlz dHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vZnJlZWRyZW5v