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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 20016C43217 for ; Wed, 12 Jan 2022 15:18:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1354527AbiALPSu (ORCPT ); Wed, 12 Jan 2022 10:18:50 -0500 Received: from ams.source.kernel.org ([145.40.68.75]:35378 "EHLO ams.source.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243741AbiALPSq (ORCPT ); Wed, 12 Jan 2022 10:18:46 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 5E955B81F6F; Wed, 12 Jan 2022 15:18:45 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D3368C36AEA; Wed, 12 Jan 2022 15:18:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1642000724; bh=NMtXD9XGfSjQw24lmJI+lMXHAN8OHl/EPTCgYLivcC8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lYYGtr81QTCzI4iU2gu8MRONhgV0GKuluNVzdqUHxxkhxGAC8h97/x5QXSdNeM18W PXtDjFnnKuE4mriuDrtJcu+r8lyKSobcMyB02tTuNuBrW87alNAmHnr1f3VghKr/i2 +0qqPmZcoI7Wv2soeQFkZBRilsyPMB+D8+ufU8WQA7/xPI28+ZnLlo4Oi5bWfFHvaD 3TPiyEpf2hckHYPUnvgdqcIWL50nGyCT8Wl+RLWn1+aAcSWKY0ELekVd8hpRCSd9O3 qD/+2pUPLaWiaTrBcmWdXxs2ghGXq010C1i52l/eMY7oyxc7EtJrvyjASSRKJvtouk dMMW0yNpS6NkA== Received: by pali.im (Postfix) id 8A943768; Wed, 12 Jan 2022 16:18:43 +0100 (CET) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Lorenzo Pieralisi , Bjorn Helgaas , Rob Herring , Thomas Petazzoni , =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Russell King , Marc Zyngier Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts Date: Wed, 12 Jan 2022 16:18:13 +0100 Message-Id: <20220112151814.24361-11-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220112151814.24361-1-pali@kernel.org> References: <20220105150239.9628-1-pali@kernel.org> <20220112151814.24361-1-pali@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org This adds support for legacy INTx interrupts received from other PCIe devices and which are reported by a new INTx irq chip. With this change, kernel can distinguish between INTA, INTB, INTC and INTD interrupts. Note that for this support, device tree files has to be properly adjusted to provide "interrupts" or "interrupts-extended" property with intx interrupt source, "interrupt-names" property with "intx" string and also 'interrupt-controller' subnode must be defined. If device tree files do not provide these nodes then driver would work as before. Signed-off-by: Pali Rohár --- drivers/pci/controller/pci-mvebu.c | 185 +++++++++++++++++++++++++++-- 1 file changed, 177 insertions(+), 8 deletions(-) diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c index 1e90ab888075..dbb6ecb4cb70 100644 --- a/drivers/pci/controller/pci-mvebu.c +++ b/drivers/pci/controller/pci-mvebu.c @@ -54,9 +54,10 @@ PCIE_CONF_ADDR_EN) #define PCIE_CONF_DATA_OFF 0x18fc #define PCIE_INT_CAUSE_OFF 0x1900 +#define PCIE_INT_UNMASK_OFF 0x1910 +#define PCIE_INT_INTX(i) BIT(24+i) #define PCIE_INT_PM_PME BIT(28) -#define PCIE_MASK_OFF 0x1910 -#define PCIE_MASK_ENABLE_INTS 0x0f000000 +#define PCIE_INT_ALL_MASK GENMASK(31, 0) #define PCIE_CTRL_OFF 0x1a00 #define PCIE_CTRL_X1_MODE 0x0001 #define PCIE_CTRL_RC_MODE BIT(1) @@ -110,6 +111,9 @@ struct mvebu_pcie_port { struct mvebu_pcie_window iowin; u32 saved_pcie_stat; struct resource regs; + struct irq_domain *intx_irq_domain; + raw_spinlock_t irq_lock; + int intx_irq; }; static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg) @@ -235,7 +239,7 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port) static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) { - u32 ctrl, lnkcap, cmd, dev_rev, mask; + u32 ctrl, lnkcap, cmd, dev_rev, unmask; /* Setup PCIe controller to Root Complex mode. */ ctrl = mvebu_readl(port, PCIE_CTRL_OFF); @@ -288,10 +292,30 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) /* Point PCIe unit MBUS decode windows to DRAM space. */ mvebu_pcie_setup_wins(port); - /* Enable interrupt lines A-D. */ - mask = mvebu_readl(port, PCIE_MASK_OFF); - mask |= PCIE_MASK_ENABLE_INTS; - mvebu_writel(port, mask, PCIE_MASK_OFF); + /* Mask all interrupt sources. */ + mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF); + + /* Clear all interrupt causes. */ + mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF); + + if (port->intx_irq <= 0) { + /* + * When neither "summary" interrupt, nor "intx" interrupt was + * specified in DT then unmask all legacy INTx interrupts as in + * this case driver does not provide a way for masking and + * unmasking of individual legacy INTx interrupts. In this case + * all interrupts, including legacy INTx are reported via one + * shared GIC source and therefore kernel cannot distinguish + * which individual legacy INTx was triggered. These interrupts + * are shared, so it should not cause any issue. Just + * performance penalty as every PCIe interrupt handler needs to + * be called when some interrupt is triggered. + */ + unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF); + unmask |= PCIE_INT_INTX(0) | PCIE_INT_INTX(1) | + PCIE_INT_INTX(2) | PCIE_INT_INTX(3); + mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF); + } } static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie, @@ -924,6 +948,108 @@ static struct pci_ops mvebu_pcie_ops = { .write = mvebu_pcie_wr_conf, }; +static void mvebu_pcie_intx_irq_mask(struct irq_data *d) +{ + struct mvebu_pcie_port *port = d->domain->host_data; + irq_hw_number_t hwirq = irqd_to_hwirq(d); + unsigned long flags; + u32 unmask; + + raw_spin_lock_irqsave(&port->irq_lock, flags); + unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF); + unmask &= ~PCIE_INT_INTX(hwirq); + mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF); + raw_spin_unlock_irqrestore(&port->irq_lock, flags); +} + +static void mvebu_pcie_intx_irq_unmask(struct irq_data *d) +{ + struct mvebu_pcie_port *port = d->domain->host_data; + irq_hw_number_t hwirq = irqd_to_hwirq(d); + unsigned long flags; + u32 unmask; + + raw_spin_lock_irqsave(&port->irq_lock, flags); + unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF); + unmask |= PCIE_INT_INTX(hwirq); + mvebu_writel(port, unmask, PCIE_INT_UNMASK_OFF); + raw_spin_unlock_irqrestore(&port->irq_lock, flags); +} + +static struct irq_chip intx_irq_chip = { + .name = "mvebu-INTx", + .irq_mask = mvebu_pcie_intx_irq_mask, + .irq_unmask = mvebu_pcie_intx_irq_unmask, +}; + +static int mvebu_pcie_intx_irq_map(struct irq_domain *h, + unsigned int virq, irq_hw_number_t hwirq) +{ + struct mvebu_pcie_port *port = h->host_data; + + irq_set_status_flags(virq, IRQ_LEVEL); + irq_set_chip_and_handler(virq, &intx_irq_chip, handle_level_irq); + irq_set_chip_data(virq, port); + + return 0; +} + +static const struct irq_domain_ops mvebu_pcie_intx_irq_domain_ops = { + .map = mvebu_pcie_intx_irq_map, + .xlate = irq_domain_xlate_onecell, +}; + +static int mvebu_pcie_init_irq_domain(struct mvebu_pcie_port *port) +{ + struct device *dev = &port->pcie->pdev->dev; + struct device_node *pcie_intc_node; + + raw_spin_lock_init(&port->irq_lock); + + pcie_intc_node = of_get_next_child(port->dn, NULL); + if (!pcie_intc_node) { + dev_err(dev, "No PCIe Intc node found for %s\n", port->name); + return -ENODEV; + } + + port->intx_irq_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX, + &mvebu_pcie_intx_irq_domain_ops, + port); + of_node_put(pcie_intc_node); + if (!port->intx_irq_domain) { + dev_err(dev, "Failed to get INTx IRQ domain for %s\n", port->name); + return -ENOMEM; + } + + return 0; +} + +static void mvebu_pcie_irq_handler(struct irq_desc *desc) +{ + struct mvebu_pcie_port *port = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + struct device *dev = &port->pcie->pdev->dev; + u32 cause, unmask, status; + int i; + + chained_irq_enter(chip, desc); + + cause = mvebu_readl(port, PCIE_INT_CAUSE_OFF); + unmask = mvebu_readl(port, PCIE_INT_UNMASK_OFF); + status = cause & unmask; + + /* Process legacy INTx interrupts */ + for (i = 0; i < PCI_NUM_INTX; i++) { + if (!(status & PCIE_INT_INTX(i))) + continue; + + if (generic_handle_domain_irq(port->intx_irq_domain, i) == -EINVAL) + dev_err_ratelimited(dev, "unexpected INT%c IRQ\n", (char)i+'A'); + } + + chained_irq_exit(chip, desc); +} + static int mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { /* Interrupt support on mvebu emulated bridges is not implemented yet */ @@ -1121,6 +1247,21 @@ static int mvebu_pcie_parse_port(struct mvebu_pcie *pcie, port->io_attr = -1; } + /* + * Old DT bindings do not contain "intx" interrupt + * so do not fail probing driver when interrupt does not exist. + */ + port->intx_irq = of_irq_get_byname(child, "intx"); + if (port->intx_irq == -EPROBE_DEFER) { + ret = port->intx_irq; + goto err; + } + if (port->intx_irq <= 0) { + dev_warn(dev, "%s: legacy INTx interrupts cannot be masked individually, " + "%pOF does not contain intx interrupt\n", + port->name, child); + } + reset_gpio = of_get_named_gpio_flags(child, "reset-gpios", 0, &flags); if (reset_gpio == -EPROBE_DEFER) { ret = reset_gpio; @@ -1317,6 +1458,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev) for (i = 0; i < pcie->nports; i++) { struct mvebu_pcie_port *port = &pcie->ports[i]; + int irq = port->intx_irq; child = port->dn; if (!child) @@ -1344,6 +1486,22 @@ static int mvebu_pcie_probe(struct platform_device *pdev) continue; } + if (irq > 0) { + ret = mvebu_pcie_init_irq_domain(port); + if (ret) { + dev_err(dev, "%s: cannot init irq domain\n", + port->name); + pci_bridge_emul_cleanup(&port->bridge); + devm_iounmap(dev, port->base); + port->base = NULL; + mvebu_pcie_powerdown(port); + continue; + } + irq_set_chained_handler_and_data(irq, + mvebu_pcie_irq_handler, + port); + } + /* * PCIe topology exported by mvebu hw is quite complicated. In * reality has something like N fully independent host bridges @@ -1448,6 +1606,7 @@ static int mvebu_pcie_remove(struct platform_device *pdev) for (i = 0; i < pcie->nports; i++) { struct mvebu_pcie_port *port = &pcie->ports[i]; + int irq = port->intx_irq; if (!port->base) continue; @@ -1458,7 +1617,17 @@ static int mvebu_pcie_remove(struct platform_device *pdev) mvebu_writel(port, cmd, PCIE_CMD_OFF); /* Mask all interrupt sources. */ - mvebu_writel(port, 0, PCIE_MASK_OFF); + mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_UNMASK_OFF); + + /* Clear all interrupt causes. */ + mvebu_writel(port, ~PCIE_INT_ALL_MASK, PCIE_INT_CAUSE_OFF); + + if (irq > 0) + irq_set_chained_handler_and_data(irq, NULL, NULL); + + /* Remove IRQ domains. */ + if (port->intx_irq_domain) + irq_domain_remove(port->intx_irq_domain); /* Free config space for emulated root bridge. */ pci_bridge_emul_cleanup(&port->bridge); -- 2.20.1 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 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4DCACC433EF for ; Wed, 12 Jan 2022 15:25:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=XMjfee0pLvwkcXsma6caf02qRjG+OwrqcwPFNO4gBIA=; b=TGzx2L4y54AUZJ 6Tf+vzjvtEobocywEG6qxC+kS6c2OMGtl/yy3BvDmNkM196m289Zp0VkR7lyhhSCmK7IADyzSIoxd xEbE9hlOyycxHrwqNHyrDnpn6dPZQ1J5/iGlXg6/N1i6NQ2D1gdHbIHBLxKz1e8bUH/tc+JmU/szV Bqq6dB7Lsdnp12/7bHGwssO2+WWPoF1o7HNw80Jc2BWc33Wgtzc4wOJVfheooCYQv/zwzGeajgSAB EK90spHIqWIp+xBbQVy8evvmiSY53Og8hfu6ZsqmoZS/ou4Gr+xeRZCNETgKZwcFrTCkD6w8cOJ3M wg8W+o6tsp1iTenqq5EQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1n7fU9-002sw3-Jd; Wed, 12 Jan 2022 15:24:26 +0000 Received: from dfw.source.kernel.org ([139.178.84.217]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1n7fOf-002qWC-0T for linux-arm-kernel@lists.infradead.org; Wed, 12 Jan 2022 15:18:47 +0000 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id B82D761910; Wed, 12 Jan 2022 15:18:44 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id D3368C36AEA; Wed, 12 Jan 2022 15:18:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1642000724; bh=NMtXD9XGfSjQw24lmJI+lMXHAN8OHl/EPTCgYLivcC8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lYYGtr81QTCzI4iU2gu8MRONhgV0GKuluNVzdqUHxxkhxGAC8h97/x5QXSdNeM18W PXtDjFnnKuE4mriuDrtJcu+r8lyKSobcMyB02tTuNuBrW87alNAmHnr1f3VghKr/i2 +0qqPmZcoI7Wv2soeQFkZBRilsyPMB+D8+ufU8WQA7/xPI28+ZnLlo4Oi5bWfFHvaD 3TPiyEpf2hckHYPUnvgdqcIWL50nGyCT8Wl+RLWn1+aAcSWKY0ELekVd8hpRCSd9O3 qD/+2pUPLaWiaTrBcmWdXxs2ghGXq010C1i52l/eMY7oyxc7EtJrvyjASSRKJvtouk dMMW0yNpS6NkA== Received: by pali.im (Postfix) id 8A943768; Wed, 12 Jan 2022 16:18:43 +0100 (CET) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Lorenzo Pieralisi , Bjorn Helgaas , Rob Herring , Thomas Petazzoni , =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Russell King , Marc Zyngier Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 10/11] PCI: mvebu: Implement support for legacy INTx interrupts Date: Wed, 12 Jan 2022 16:18:13 +0100 Message-Id: <20220112151814.24361-11-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220112151814.24361-1-pali@kernel.org> References: <20220105150239.9628-1-pali@kernel.org> <20220112151814.24361-1-pali@kernel.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220112_071845_185458_4DCA6697 X-CRM114-Status: GOOD ( 28.90 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org VGhpcyBhZGRzIHN1cHBvcnQgZm9yIGxlZ2FjeSBJTlR4IGludGVycnVwdHMgcmVjZWl2ZWQgZnJv bSBvdGhlciBQQ0llCmRldmljZXMgYW5kIHdoaWNoIGFyZSByZXBvcnRlZCBieSBhIG5ldyBJTlR4 IGlycSBjaGlwLgoKV2l0aCB0aGlzIGNoYW5nZSwga2VybmVsIGNhbiBkaXN0aW5ndWlzaCBiZXR3 ZWVuIElOVEEsIElOVEIsIElOVEMgYW5kIElOVEQKaW50ZXJydXB0cy4KCk5vdGUgdGhhdCBmb3Ig dGhpcyBzdXBwb3J0LCBkZXZpY2UgdHJlZSBmaWxlcyBoYXMgdG8gYmUgcHJvcGVybHkgYWRqdXN0 ZWQKdG8gcHJvdmlkZSAiaW50ZXJydXB0cyIgb3IgImludGVycnVwdHMtZXh0ZW5kZWQiIHByb3Bl cnR5IHdpdGggaW50eAppbnRlcnJ1cHQgc291cmNlLCAiaW50ZXJydXB0LW5hbWVzIiBwcm9wZXJ0 eSB3aXRoICJpbnR4IiBzdHJpbmcgYW5kIGFsc28KJ2ludGVycnVwdC1jb250cm9sbGVyJyBzdWJu b2RlIG11c3QgYmUgZGVmaW5lZC4KCklmIGRldmljZSB0cmVlIGZpbGVzIGRvIG5vdCBwcm92aWRl IHRoZXNlIG5vZGVzIHRoZW4gZHJpdmVyIHdvdWxkIHdvcmsgYXMKYmVmb3JlLgoKU2lnbmVkLW9m Zi1ieTogUGFsaSBSb2jDoXIgPHBhbGlAa2VybmVsLm9yZz4KLS0tCiBkcml2ZXJzL3BjaS9jb250 cm9sbGVyL3BjaS1tdmVidS5jIHwgMTg1ICsrKysrKysrKysrKysrKysrKysrKysrKysrKy0tCiAx IGZpbGUgY2hhbmdlZCwgMTc3IGluc2VydGlvbnMoKyksIDggZGVsZXRpb25zKC0pCgpkaWZmIC0t Z2l0IGEvZHJpdmVycy9wY2kvY29udHJvbGxlci9wY2ktbXZlYnUuYyBiL2RyaXZlcnMvcGNpL2Nv bnRyb2xsZXIvcGNpLW12ZWJ1LmMKaW5kZXggMWU5MGFiODg4MDc1Li5kYmI2ZWNiNGNiNzAgMTAw NjQ0Ci0tLSBhL2RyaXZlcnMvcGNpL2NvbnRyb2xsZXIvcGNpLW12ZWJ1LmMKKysrIGIvZHJpdmVy cy9wY2kvY29udHJvbGxlci9wY2ktbXZlYnUuYwpAQCAtNTQsOSArNTQsMTAgQEAKIAkgUENJRV9D T05GX0FERFJfRU4pCiAjZGVmaW5lIFBDSUVfQ09ORl9EQVRBX09GRgkweDE4ZmMKICNkZWZpbmUg UENJRV9JTlRfQ0FVU0VfT0ZGCTB4MTkwMAorI2RlZmluZSBQQ0lFX0lOVF9VTk1BU0tfT0ZGCTB4 MTkxMAorI2RlZmluZSAgUENJRV9JTlRfSU5UWChpKQkJQklUKDI0K2kpCiAjZGVmaW5lICBQQ0lF X0lOVF9QTV9QTUUJCUJJVCgyOCkKLSNkZWZpbmUgUENJRV9NQVNLX09GRgkJMHgxOTEwCi0jZGVm aW5lICBQQ0lFX01BU0tfRU5BQkxFX0lOVFMgICAgICAgICAgMHgwZjAwMDAwMAorI2RlZmluZSAg UENJRV9JTlRfQUxMX01BU0sJCUdFTk1BU0soMzEsIDApCiAjZGVmaW5lIFBDSUVfQ1RSTF9PRkYJ CTB4MWEwMAogI2RlZmluZSAgUENJRV9DVFJMX1gxX01PREUJCTB4MDAwMQogI2RlZmluZSAgUENJ RV9DVFJMX1JDX01PREUJCUJJVCgxKQpAQCAtMTEwLDYgKzExMSw5IEBAIHN0cnVjdCBtdmVidV9w Y2llX3BvcnQgewogCXN0cnVjdCBtdmVidV9wY2llX3dpbmRvdyBpb3dpbjsKIAl1MzIgc2F2ZWRf cGNpZV9zdGF0OwogCXN0cnVjdCByZXNvdXJjZSByZWdzOworCXN0cnVjdCBpcnFfZG9tYWluICpp bnR4X2lycV9kb21haW47CisJcmF3X3NwaW5sb2NrX3QgaXJxX2xvY2s7CisJaW50IGludHhfaXJx OwogfTsKIAogc3RhdGljIGlubGluZSB2b2lkIG12ZWJ1X3dyaXRlbChzdHJ1Y3QgbXZlYnVfcGNp ZV9wb3J0ICpwb3J0LCB1MzIgdmFsLCB1MzIgcmVnKQpAQCAtMjM1LDcgKzIzOSw3IEBAIHN0YXRp YyB2b2lkIG12ZWJ1X3BjaWVfc2V0dXBfd2lucyhzdHJ1Y3QgbXZlYnVfcGNpZV9wb3J0ICpwb3J0 KQogCiBzdGF0aWMgdm9pZCBtdmVidV9wY2llX3NldHVwX2h3KHN0cnVjdCBtdmVidV9wY2llX3Bv cnQgKnBvcnQpCiB7Ci0JdTMyIGN0cmwsIGxua2NhcCwgY21kLCBkZXZfcmV2LCBtYXNrOworCXUz MiBjdHJsLCBsbmtjYXAsIGNtZCwgZGV2X3JldiwgdW5tYXNrOwogCiAJLyogU2V0dXAgUENJZSBj b250cm9sbGVyIHRvIFJvb3QgQ29tcGxleCBtb2RlLiAqLwogCWN0cmwgPSBtdmVidV9yZWFkbChw b3J0LCBQQ0lFX0NUUkxfT0ZGKTsKQEAgLTI4OCwxMCArMjkyLDMwIEBAIHN0YXRpYyB2b2lkIG12 ZWJ1X3BjaWVfc2V0dXBfaHcoc3RydWN0IG12ZWJ1X3BjaWVfcG9ydCAqcG9ydCkKIAkvKiBQb2lu dCBQQ0llIHVuaXQgTUJVUyBkZWNvZGUgd2luZG93cyB0byBEUkFNIHNwYWNlLiAqLwogCW12ZWJ1 X3BjaWVfc2V0dXBfd2lucyhwb3J0KTsKIAotCS8qIEVuYWJsZSBpbnRlcnJ1cHQgbGluZXMgQS1E LiAqLwotCW1hc2sgPSBtdmVidV9yZWFkbChwb3J0LCBQQ0lFX01BU0tfT0ZGKTsKLQltYXNrIHw9 IFBDSUVfTUFTS19FTkFCTEVfSU5UUzsKLQltdmVidV93cml0ZWwocG9ydCwgbWFzaywgUENJRV9N QVNLX09GRik7CisJLyogTWFzayBhbGwgaW50ZXJydXB0IHNvdXJjZXMuICovCisJbXZlYnVfd3Jp dGVsKHBvcnQsIH5QQ0lFX0lOVF9BTExfTUFTSywgUENJRV9JTlRfVU5NQVNLX09GRik7CisKKwkv KiBDbGVhciBhbGwgaW50ZXJydXB0IGNhdXNlcy4gKi8KKwltdmVidV93cml0ZWwocG9ydCwgflBD SUVfSU5UX0FMTF9NQVNLLCBQQ0lFX0lOVF9DQVVTRV9PRkYpOworCisJaWYgKHBvcnQtPmludHhf aXJxIDw9IDApIHsKKwkJLyoKKwkJICogV2hlbiBuZWl0aGVyICJzdW1tYXJ5IiBpbnRlcnJ1cHQs IG5vciAiaW50eCIgaW50ZXJydXB0IHdhcworCQkgKiBzcGVjaWZpZWQgaW4gRFQgdGhlbiB1bm1h c2sgYWxsIGxlZ2FjeSBJTlR4IGludGVycnVwdHMgYXMgaW4KKwkJICogdGhpcyBjYXNlIGRyaXZl ciBkb2VzIG5vdCBwcm92aWRlIGEgd2F5IGZvciBtYXNraW5nIGFuZAorCQkgKiB1bm1hc2tpbmcg b2YgaW5kaXZpZHVhbCBsZWdhY3kgSU5UeCBpbnRlcnJ1cHRzLiBJbiB0aGlzIGNhc2UKKwkJICog YWxsIGludGVycnVwdHMsIGluY2x1ZGluZyBsZWdhY3kgSU5UeCBhcmUgcmVwb3J0ZWQgdmlhIG9u ZQorCQkgKiBzaGFyZWQgR0lDIHNvdXJjZSBhbmQgdGhlcmVmb3JlIGtlcm5lbCBjYW5ub3QgZGlz dGluZ3Vpc2gKKwkJICogd2hpY2ggaW5kaXZpZHVhbCBsZWdhY3kgSU5UeCB3YXMgdHJpZ2dlcmVk LiBUaGVzZSBpbnRlcnJ1cHRzCisJCSAqIGFyZSBzaGFyZWQsIHNvIGl0IHNob3VsZCBub3QgY2F1 c2UgYW55IGlzc3VlLiBKdXN0CisJCSAqIHBlcmZvcm1hbmNlIHBlbmFsdHkgYXMgZXZlcnkgUENJ ZSBpbnRlcnJ1cHQgaGFuZGxlciBuZWVkcyB0bworCQkgKiBiZSBjYWxsZWQgd2hlbiBzb21lIGlu dGVycnVwdCBpcyB0cmlnZ2VyZWQuCisJCSAqLworCQl1bm1hc2sgPSBtdmVidV9yZWFkbChwb3J0 LCBQQ0lFX0lOVF9VTk1BU0tfT0ZGKTsKKwkJdW5tYXNrIHw9IFBDSUVfSU5UX0lOVFgoMCkgfCBQ Q0lFX0lOVF9JTlRYKDEpIHwKKwkJCSAgUENJRV9JTlRfSU5UWCgyKSB8IFBDSUVfSU5UX0lOVFgo Myk7CisJCW12ZWJ1X3dyaXRlbChwb3J0LCB1bm1hc2ssIFBDSUVfSU5UX1VOTUFTS19PRkYpOwor CX0KIH0KIAogc3RhdGljIHN0cnVjdCBtdmVidV9wY2llX3BvcnQgKm12ZWJ1X3BjaWVfZmluZF9w b3J0KHN0cnVjdCBtdmVidV9wY2llICpwY2llLApAQCAtOTI0LDYgKzk0OCwxMDggQEAgc3RhdGlj IHN0cnVjdCBwY2lfb3BzIG12ZWJ1X3BjaWVfb3BzID0gewogCS53cml0ZSA9IG12ZWJ1X3BjaWVf d3JfY29uZiwKIH07CiAKK3N0YXRpYyB2b2lkIG12ZWJ1X3BjaWVfaW50eF9pcnFfbWFzayhzdHJ1 Y3QgaXJxX2RhdGEgKmQpCit7CisJc3RydWN0IG12ZWJ1X3BjaWVfcG9ydCAqcG9ydCA9IGQtPmRv bWFpbi0+aG9zdF9kYXRhOworCWlycV9od19udW1iZXJfdCBod2lycSA9IGlycWRfdG9faHdpcnEo ZCk7CisJdW5zaWduZWQgbG9uZyBmbGFnczsKKwl1MzIgdW5tYXNrOworCisJcmF3X3NwaW5fbG9j a19pcnFzYXZlKCZwb3J0LT5pcnFfbG9jaywgZmxhZ3MpOworCXVubWFzayA9IG12ZWJ1X3JlYWRs KHBvcnQsIFBDSUVfSU5UX1VOTUFTS19PRkYpOworCXVubWFzayAmPSB+UENJRV9JTlRfSU5UWCho d2lycSk7CisJbXZlYnVfd3JpdGVsKHBvcnQsIHVubWFzaywgUENJRV9JTlRfVU5NQVNLX09GRik7 CisJcmF3X3NwaW5fdW5sb2NrX2lycXJlc3RvcmUoJnBvcnQtPmlycV9sb2NrLCBmbGFncyk7Cit9 CisKK3N0YXRpYyB2b2lkIG12ZWJ1X3BjaWVfaW50eF9pcnFfdW5tYXNrKHN0cnVjdCBpcnFfZGF0 YSAqZCkKK3sKKwlzdHJ1Y3QgbXZlYnVfcGNpZV9wb3J0ICpwb3J0ID0gZC0+ZG9tYWluLT5ob3N0 X2RhdGE7CisJaXJxX2h3X251bWJlcl90IGh3aXJxID0gaXJxZF90b19od2lycShkKTsKKwl1bnNp Z25lZCBsb25nIGZsYWdzOworCXUzMiB1bm1hc2s7CisKKwlyYXdfc3Bpbl9sb2NrX2lycXNhdmUo JnBvcnQtPmlycV9sb2NrLCBmbGFncyk7CisJdW5tYXNrID0gbXZlYnVfcmVhZGwocG9ydCwgUENJ RV9JTlRfVU5NQVNLX09GRik7CisJdW5tYXNrIHw9IFBDSUVfSU5UX0lOVFgoaHdpcnEpOworCW12 ZWJ1X3dyaXRlbChwb3J0LCB1bm1hc2ssIFBDSUVfSU5UX1VOTUFTS19PRkYpOworCXJhd19zcGlu X3VubG9ja19pcnFyZXN0b3JlKCZwb3J0LT5pcnFfbG9jaywgZmxhZ3MpOworfQorCitzdGF0aWMg c3RydWN0IGlycV9jaGlwIGludHhfaXJxX2NoaXAgPSB7CisJLm5hbWUgPSAibXZlYnUtSU5UeCIs CisJLmlycV9tYXNrID0gbXZlYnVfcGNpZV9pbnR4X2lycV9tYXNrLAorCS5pcnFfdW5tYXNrID0g bXZlYnVfcGNpZV9pbnR4X2lycV91bm1hc2ssCit9OworCitzdGF0aWMgaW50IG12ZWJ1X3BjaWVf aW50eF9pcnFfbWFwKHN0cnVjdCBpcnFfZG9tYWluICpoLAorCQkJCSAgIHVuc2lnbmVkIGludCB2 aXJxLCBpcnFfaHdfbnVtYmVyX3QgaHdpcnEpCit7CisJc3RydWN0IG12ZWJ1X3BjaWVfcG9ydCAq cG9ydCA9IGgtPmhvc3RfZGF0YTsKKworCWlycV9zZXRfc3RhdHVzX2ZsYWdzKHZpcnEsIElSUV9M RVZFTCk7CisJaXJxX3NldF9jaGlwX2FuZF9oYW5kbGVyKHZpcnEsICZpbnR4X2lycV9jaGlwLCBo YW5kbGVfbGV2ZWxfaXJxKTsKKwlpcnFfc2V0X2NoaXBfZGF0YSh2aXJxLCBwb3J0KTsKKworCXJl dHVybiAwOworfQorCitzdGF0aWMgY29uc3Qgc3RydWN0IGlycV9kb21haW5fb3BzIG12ZWJ1X3Bj aWVfaW50eF9pcnFfZG9tYWluX29wcyA9IHsKKwkubWFwID0gbXZlYnVfcGNpZV9pbnR4X2lycV9t YXAsCisJLnhsYXRlID0gaXJxX2RvbWFpbl94bGF0ZV9vbmVjZWxsLAorfTsKKworc3RhdGljIGlu dCBtdmVidV9wY2llX2luaXRfaXJxX2RvbWFpbihzdHJ1Y3QgbXZlYnVfcGNpZV9wb3J0ICpwb3J0 KQoreworCXN0cnVjdCBkZXZpY2UgKmRldiA9ICZwb3J0LT5wY2llLT5wZGV2LT5kZXY7CisJc3Ry dWN0IGRldmljZV9ub2RlICpwY2llX2ludGNfbm9kZTsKKworCXJhd19zcGluX2xvY2tfaW5pdCgm cG9ydC0+aXJxX2xvY2spOworCisJcGNpZV9pbnRjX25vZGUgPSBvZl9nZXRfbmV4dF9jaGlsZChw b3J0LT5kbiwgTlVMTCk7CisJaWYgKCFwY2llX2ludGNfbm9kZSkgeworCQlkZXZfZXJyKGRldiwg Ik5vIFBDSWUgSW50YyBub2RlIGZvdW5kIGZvciAlc1xuIiwgcG9ydC0+bmFtZSk7CisJCXJldHVy biAtRU5PREVWOworCX0KKworCXBvcnQtPmludHhfaXJxX2RvbWFpbiA9IGlycV9kb21haW5fYWRk X2xpbmVhcihwY2llX2ludGNfbm9kZSwgUENJX05VTV9JTlRYLAorCQkJCQkJICAgICAgJm12ZWJ1 X3BjaWVfaW50eF9pcnFfZG9tYWluX29wcywKKwkJCQkJCSAgICAgIHBvcnQpOworCW9mX25vZGVf cHV0KHBjaWVfaW50Y19ub2RlKTsKKwlpZiAoIXBvcnQtPmludHhfaXJxX2RvbWFpbikgeworCQlk ZXZfZXJyKGRldiwgIkZhaWxlZCB0byBnZXQgSU5UeCBJUlEgZG9tYWluIGZvciAlc1xuIiwgcG9y dC0+bmFtZSk7CisJCXJldHVybiAtRU5PTUVNOworCX0KKworCXJldHVybiAwOworfQorCitzdGF0 aWMgdm9pZCBtdmVidV9wY2llX2lycV9oYW5kbGVyKHN0cnVjdCBpcnFfZGVzYyAqZGVzYykKK3sK KwlzdHJ1Y3QgbXZlYnVfcGNpZV9wb3J0ICpwb3J0ID0gaXJxX2Rlc2NfZ2V0X2hhbmRsZXJfZGF0 YShkZXNjKTsKKwlzdHJ1Y3QgaXJxX2NoaXAgKmNoaXAgPSBpcnFfZGVzY19nZXRfY2hpcChkZXNj KTsKKwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSAmcG9ydC0+cGNpZS0+cGRldi0+ZGV2OworCXUzMiBj YXVzZSwgdW5tYXNrLCBzdGF0dXM7CisJaW50IGk7CisKKwljaGFpbmVkX2lycV9lbnRlcihjaGlw LCBkZXNjKTsKKworCWNhdXNlID0gbXZlYnVfcmVhZGwocG9ydCwgUENJRV9JTlRfQ0FVU0VfT0ZG KTsKKwl1bm1hc2sgPSBtdmVidV9yZWFkbChwb3J0LCBQQ0lFX0lOVF9VTk1BU0tfT0ZGKTsKKwlz dGF0dXMgPSBjYXVzZSAmIHVubWFzazsKKworCS8qIFByb2Nlc3MgbGVnYWN5IElOVHggaW50ZXJy dXB0cyAqLworCWZvciAoaSA9IDA7IGkgPCBQQ0lfTlVNX0lOVFg7IGkrKykgeworCQlpZiAoIShz dGF0dXMgJiBQQ0lFX0lOVF9JTlRYKGkpKSkKKwkJCWNvbnRpbnVlOworCisJCWlmIChnZW5lcmlj X2hhbmRsZV9kb21haW5faXJxKHBvcnQtPmludHhfaXJxX2RvbWFpbiwgaSkgPT0gLUVJTlZBTCkK KwkJCWRldl9lcnJfcmF0ZWxpbWl0ZWQoZGV2LCAidW5leHBlY3RlZCBJTlQlYyBJUlFcbiIsIChj aGFyKWkrJ0EnKTsKKwl9CisKKwljaGFpbmVkX2lycV9leGl0KGNoaXAsIGRlc2MpOworfQorCiBz dGF0aWMgaW50IG12ZWJ1X3BjaWVfbWFwX2lycShjb25zdCBzdHJ1Y3QgcGNpX2RldiAqZGV2LCB1 OCBzbG90LCB1OCBwaW4pCiB7CiAJLyogSW50ZXJydXB0IHN1cHBvcnQgb24gbXZlYnUgZW11bGF0 ZWQgYnJpZGdlcyBpcyBub3QgaW1wbGVtZW50ZWQgeWV0ICovCkBAIC0xMTIxLDYgKzEyNDcsMjEg QEAgc3RhdGljIGludCBtdmVidV9wY2llX3BhcnNlX3BvcnQoc3RydWN0IG12ZWJ1X3BjaWUgKnBj aWUsCiAJCXBvcnQtPmlvX2F0dHIgPSAtMTsKIAl9CiAKKwkvKgorCSAqIE9sZCBEVCBiaW5kaW5n cyBkbyBub3QgY29udGFpbiAiaW50eCIgaW50ZXJydXB0CisJICogc28gZG8gbm90IGZhaWwgcHJv YmluZyBkcml2ZXIgd2hlbiBpbnRlcnJ1cHQgZG9lcyBub3QgZXhpc3QuCisJICovCisJcG9ydC0+ aW50eF9pcnEgPSBvZl9pcnFfZ2V0X2J5bmFtZShjaGlsZCwgImludHgiKTsKKwlpZiAocG9ydC0+ aW50eF9pcnEgPT0gLUVQUk9CRV9ERUZFUikgeworCQlyZXQgPSBwb3J0LT5pbnR4X2lycTsKKwkJ Z290byBlcnI7CisJfQorCWlmIChwb3J0LT5pbnR4X2lycSA8PSAwKSB7CisJCWRldl93YXJuKGRl diwgIiVzOiBsZWdhY3kgSU5UeCBpbnRlcnJ1cHRzIGNhbm5vdCBiZSBtYXNrZWQgaW5kaXZpZHVh bGx5LCAiCisJCQkgICAgICAiJXBPRiBkb2VzIG5vdCBjb250YWluIGludHggaW50ZXJydXB0XG4i LAorCQkJIHBvcnQtPm5hbWUsIGNoaWxkKTsKKwl9CisKIAlyZXNldF9ncGlvID0gb2ZfZ2V0X25h bWVkX2dwaW9fZmxhZ3MoY2hpbGQsICJyZXNldC1ncGlvcyIsIDAsICZmbGFncyk7CiAJaWYgKHJl c2V0X2dwaW8gPT0gLUVQUk9CRV9ERUZFUikgewogCQlyZXQgPSByZXNldF9ncGlvOwpAQCAtMTMx Nyw2ICsxNDU4LDcgQEAgc3RhdGljIGludCBtdmVidV9wY2llX3Byb2JlKHN0cnVjdCBwbGF0Zm9y bV9kZXZpY2UgKnBkZXYpCiAKIAlmb3IgKGkgPSAwOyBpIDwgcGNpZS0+bnBvcnRzOyBpKyspIHsK IAkJc3RydWN0IG12ZWJ1X3BjaWVfcG9ydCAqcG9ydCA9ICZwY2llLT5wb3J0c1tpXTsKKwkJaW50 IGlycSA9IHBvcnQtPmludHhfaXJxOwogCiAJCWNoaWxkID0gcG9ydC0+ZG47CiAJCWlmICghY2hp bGQpCkBAIC0xMzQ0LDYgKzE0ODYsMjIgQEAgc3RhdGljIGludCBtdmVidV9wY2llX3Byb2JlKHN0 cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCiAJCQljb250aW51ZTsKIAkJfQogCisJCWlmIChp cnEgPiAwKSB7CisJCQlyZXQgPSBtdmVidV9wY2llX2luaXRfaXJxX2RvbWFpbihwb3J0KTsKKwkJ CWlmIChyZXQpIHsKKwkJCQlkZXZfZXJyKGRldiwgIiVzOiBjYW5ub3QgaW5pdCBpcnEgZG9tYWlu XG4iLAorCQkJCQlwb3J0LT5uYW1lKTsKKwkJCQlwY2lfYnJpZGdlX2VtdWxfY2xlYW51cCgmcG9y dC0+YnJpZGdlKTsKKwkJCQlkZXZtX2lvdW5tYXAoZGV2LCBwb3J0LT5iYXNlKTsKKwkJCQlwb3J0 LT5iYXNlID0gTlVMTDsKKwkJCQltdmVidV9wY2llX3Bvd2VyZG93bihwb3J0KTsKKwkJCQljb250 aW51ZTsKKwkJCX0KKwkJCWlycV9zZXRfY2hhaW5lZF9oYW5kbGVyX2FuZF9kYXRhKGlycSwKKwkJ CQkJCQkgbXZlYnVfcGNpZV9pcnFfaGFuZGxlciwKKwkJCQkJCQkgcG9ydCk7CisJCX0KKwogCQkv KgogCQkgKiBQQ0llIHRvcG9sb2d5IGV4cG9ydGVkIGJ5IG12ZWJ1IGh3IGlzIHF1aXRlIGNvbXBs aWNhdGVkLiBJbgogCQkgKiByZWFsaXR5IGhhcyBzb21ldGhpbmcgbGlrZSBOIGZ1bGx5IGluZGVw ZW5kZW50IGhvc3QgYnJpZGdlcwpAQCAtMTQ0OCw2ICsxNjA2LDcgQEAgc3RhdGljIGludCBtdmVi dV9wY2llX3JlbW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQogCiAJZm9yIChpID0g MDsgaSA8IHBjaWUtPm5wb3J0czsgaSsrKSB7CiAJCXN0cnVjdCBtdmVidV9wY2llX3BvcnQgKnBv cnQgPSAmcGNpZS0+cG9ydHNbaV07CisJCWludCBpcnEgPSBwb3J0LT5pbnR4X2lycTsKIAogCQlp ZiAoIXBvcnQtPmJhc2UpCiAJCQljb250aW51ZTsKQEAgLTE0NTgsNyArMTYxNywxNyBAQCBzdGF0 aWMgaW50IG12ZWJ1X3BjaWVfcmVtb3ZlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCiAJ CW12ZWJ1X3dyaXRlbChwb3J0LCBjbWQsIFBDSUVfQ01EX09GRik7CiAKIAkJLyogTWFzayBhbGwg aW50ZXJydXB0IHNvdXJjZXMuICovCi0JCW12ZWJ1X3dyaXRlbChwb3J0LCAwLCBQQ0lFX01BU0tf T0ZGKTsKKwkJbXZlYnVfd3JpdGVsKHBvcnQsIH5QQ0lFX0lOVF9BTExfTUFTSywgUENJRV9JTlRf VU5NQVNLX09GRik7CisKKwkJLyogQ2xlYXIgYWxsIGludGVycnVwdCBjYXVzZXMuICovCisJCW12 ZWJ1X3dyaXRlbChwb3J0LCB+UENJRV9JTlRfQUxMX01BU0ssIFBDSUVfSU5UX0NBVVNFX09GRik7 CisKKwkJaWYgKGlycSA+IDApCisJCQlpcnFfc2V0X2NoYWluZWRfaGFuZGxlcl9hbmRfZGF0YShp cnEsIE5VTEwsIE5VTEwpOworCisJCS8qIFJlbW92ZSBJUlEgZG9tYWlucy4gKi8KKwkJaWYgKHBv cnQtPmludHhfaXJxX2RvbWFpbikKKwkJCWlycV9kb21haW5fcmVtb3ZlKHBvcnQtPmludHhfaXJx X2RvbWFpbik7CiAKIAkJLyogRnJlZSBjb25maWcgc3BhY2UgZm9yIGVtdWxhdGVkIHJvb3QgYnJp ZGdlLiAqLwogCQlwY2lfYnJpZGdlX2VtdWxfY2xlYW51cCgmcG9ydC0+YnJpZGdlKTsKLS0gCjIu MjAuMQoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxp bnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFk ZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4 LWFybS1rZXJuZWwK