From mboxrd@z Thu Jan 1 00:00:00 1970 From: thomas.petazzoni@bootlin.com (Thomas Petazzoni) Date: Wed, 2 May 2018 11:17:44 +0200 Subject: [PATCH 10/17] irqchip/irq-mvebu-sei: add new driver for Marvell SEI In-Reply-To: <20180421135537.24716-11-miquel.raynal@bootlin.com> References: <20180421135537.24716-1-miquel.raynal@bootlin.com> <20180421135537.24716-11-miquel.raynal@bootlin.com> Message-ID: <20180502111744.5391afff@windsurf.home> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Hello, On Sat, 21 Apr 2018 15:55:30 +0200, Miquel Raynal wrote: > diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile > index 5ed465ab1c76..6b5b75cb4694 100644 > --- a/drivers/irqchip/Makefile > +++ b/drivers/irqchip/Makefile > @@ -73,6 +73,7 @@ obj-$(CONFIG_IMX_GPCV2) += irq-imx-gpcv2.o > obj-$(CONFIG_PIC32_EVIC) += irq-pic32-evic.o > obj-$(CONFIG_MSCC_OCELOT_IRQ) += irq-mscc-ocelot.o > obj-$(CONFIG_MVEBU_GICP) += irq-mvebu-gicp.o > +obj-$(CONFIG_MVEBU_SEI) += irq-mvebu-sei.o > obj-$(CONFIG_MVEBU_ICU) += irq-mvebu-icu.o > obj-$(CONFIG_MVEBU_ODMI) += irq-mvebu-odmi.o > obj-$(CONFIG_MVEBU_PIC) += irq-mvebu-pic.o Alphabetic ordering would put SEI after PIC I guess :) > diff --git a/drivers/irqchip/irq-mvebu-sei.c b/drivers/irqchip/irq-mvebu-sei.c > new file mode 100644 > index 000000000000..5c12c74e3f09 > --- /dev/null > +++ b/drivers/irqchip/irq-mvebu-sei.c > @@ -0,0 +1,449 @@ > +// SPDX-License-Identifier: GPL-2.0 OR X11 License for code is GPL-2.0 only. We use GPL-2.0 OR X11 for Device Trees. > +#define pr_fmt(fmt) "mvebu-sei: " fmt > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#define GICP_SET_SEI_OFFSET 0x30 > +#define GICP_CLR_SEI_OFFSET GICP_SET_SEI_OFFSET Why do you have this concept of set/clr if there is only one register ? I assume that if there is only a "set" register, it means that SEI interrupts can only be edge triggered, contrary to NSR interrupts, which have separate set/clr to support level-triggered interrupts. Having only a "set" offset means that we can rely on the existing "struct msi_msg" to convey both the MSI doorbell address and payload, and we don't need the mvebu_gicp_get_doorbells() hack. > +/* Cause register */ > +#define GICP_SECR(idx) (0x0 + (idx * 0x4)) > +/* Mask register */ > +#define GICP_SEMR(idx) (0x20 + (idx * 0x4)) Minor nit: order register definitions by order of increasing offset, i.e the GICP_SET_SEI_OFFSET should be defined here. > +#define SEI_IRQ_NB_PER_REG 32 > +#define SEI_IRQ_REG_NB 2 s/NB/COUNT/ > +#define SEI_IRQ_NB (SEI_IRQ_NB_PER_REG * SEI_IRQ_REG_NB) Ditto. > +#define SEI_IRQ_REG_IDX(irq_id) (irq_id / SEI_IRQ_NB_PER_REG) > +#define SEI_IRQ_REG_BIT(irq_id) (irq_id % SEI_IRQ_NB_PER_REG) > + > +struct mvebu_sei_interrupt_range { > + u32 first; > + u32 number; > +}; > + > +struct mvebu_sei { > + struct device *dev; > + void __iomem *base; > + struct resource *res; > + struct irq_domain *ap_domain; > + struct irq_domain *cp_domain; > + struct mvebu_sei_interrupt_range ap_interrupts; > + struct mvebu_sei_interrupt_range cp_interrupts; > + /* Lock on MSI allocations/releases */ > + spinlock_t cp_msi_lock; > + DECLARE_BITMAP(cp_msi_bitmap, SEI_IRQ_NB); > +}; > + > +static int mvebu_sei_domain_to_sei_irq(struct mvebu_sei *sei, > + struct irq_domain *domain, > + irq_hw_number_t hwirq) > +{ > + if (domain == sei->ap_domain) > + return sei->ap_interrupts.first + hwirq; > + else > + return sei->cp_interrupts.first + hwirq; I am not entirely clear whether we need subnodes or not in this binding, but I guess we do because we have one subset of the interrupts that are wired interrupts, and another part that are MSI triggered. Perhaps this is one aspect on which Marc Zyngier can comment ? > +static void mvebu_sei_reset(struct mvebu_sei *sei) > +{ > + u32 reg_idx; > + > + for (reg_idx = 0; reg_idx < SEI_IRQ_REG_NB; reg_idx++) { > + /* Clear all cause bits */ > + writel(0xFFFFFFFF, sei->base + GICP_SECR(reg_idx)); > + /* Enable all interrupts */ > + writel(0, sei->base + GICP_SEMR(reg_idx)); Enabling interrupts by default ? This looks weird. They should only be enabled... when enabled. > +int mvebu_sei_get_doorbells(struct device_node *dn, phys_addr_t *set, > + phys_addr_t *clr) > +{ > + struct platform_device *pdev; > + struct mvebu_sei *sei; > + > + pdev = of_find_device_by_node(dn->parent); > + if (!pdev) > + return -ENODEV; > + > + sei = platform_get_drvdata(pdev); > + if (!sei) > + return -ENODEV; > + > + *set = (phys_addr_t)(sei->res->start + GICP_SET_SEI_OFFSET); > + *clr = (phys_addr_t)(sei->res->start + GICP_CLR_SEI_OFFSET); > + > + return 0; > +} As I said above, I believe this hack is not needed, because SEIs are edge-triggered, and we have a single SET_SEI_OFFSET MSI doorbell address to convey, which makes "struct msi_msg" as it is today sufficient. > +static void mvebu_sei_mask_irq(struct irq_data *d) > +{ > + struct mvebu_sei *sei = irq_data_get_irq_chip_data(d); > + u32 reg_idx = SEI_IRQ_REG_IDX(d->hwirq); This doesn't look right. The d->hwirq is relative to the beginning of the domain, while you should use sei_irq here. For example, the SEI n?32 (first interrupt in the second register) will have d->hwirq = 11, because it is the 11th SEI interrupt for the CP. So here, you will conclude that reg_idx = 0, while it should be reg_idx = 1. > + u32 sei_irq = mvebu_sei_domain_to_sei_irq(sei, d->domain, d->hwirq); > + u32 irq_mask = BIT(SEI_IRQ_REG_BIT(sei_irq)); > + u32 reg; > + > + /* 1 disables the interrupt */ > + reg = readl(sei->base + GICP_SEMR(reg_idx)); > + writel(reg | irq_mask, sei->base + GICP_SEMR(reg_idx)); Personal taste here, but I prefer: reg = readl(sei->base + GICP_SEMR(reg_idx)); reg |= BIT(SEI_IRQ_REG_BIT(sei_irq)); writel(reg, sei->base + GICP_SEMR(reg_idx)); > +static void mvebu_sei_unmask_irq(struct irq_data *d) > +{ > + struct mvebu_sei *sei = irq_data_get_irq_chip_data(d); > + u32 reg_idx = SEI_IRQ_REG_IDX(d->hwirq); Same mistake as above I believe. > + u32 sei_irq = mvebu_sei_domain_to_sei_irq(sei, d->domain, d->hwirq); > + u32 irq_mask = BIT(SEI_IRQ_REG_BIT(sei_irq)); > + u32 reg; > + > + /* 0 enables the interrupt */ > + reg = readl(sei->base + GICP_SEMR(reg_idx)); > + writel(reg & ~irq_mask, sei->base + GICP_SEMR(reg_idx)); And same nitpick comment :-) > +static int mvebu_sei_irq_domain_alloc(struct irq_domain *domain, > + unsigned int virq, unsigned int nr_irqs, > + void *args) I think the coding style says that arguments should be aligned, no ? > +{ > + struct mvebu_sei *sei = domain->host_data; > + struct irq_fwspec *fwspec = args; > + struct irq_chip *irq_chip; > + int sei_hwirq, hwirq; > + int ret; > + > + /* Software only supports single allocations for now */ > + if (nr_irqs != 1) > + return -ENOTSUPP; > + > + if (domain == sei->ap_domain) { > + irq_chip = &mvebu_sei_ap_wired_irq_chip; > + hwirq = fwspec->param[0]; > + } else { > + irq_chip = &mvebu_sei_cp_msi_irq_chip; > + spin_lock(&sei->cp_msi_lock); > + hwirq = bitmap_find_free_region(sei->cp_msi_bitmap, SEI_IRQ_NB, > + 0); > + spin_unlock(&sei->cp_msi_lock); > + if (hwirq < 0) > + return -ENOSPC; > + } > + > + sei_hwirq = mvebu_sei_domain_to_sei_irq(sei, domain, hwirq); > + > + fwspec->fwnode = domain->parent->fwnode; > + fwspec->param_count = 3; > + fwspec->param[0] = GIC_SPI; > + fwspec->param[1] = sei_hwirq; > + fwspec->param[2] = IRQ_TYPE_EDGE_RISING; Maybe it's me being confused, but I thought all SEI interrupts were muxed together to a single SPI for the parent GIC. But here, you allocate different SPIs at the GIC level. Intuitively, this doesn't look good. Haven't you copy/pasted too much from the gicp driver, where we have a 1:1 mapping between interrupts coming into the GICP and interrupts signaled by the GICP to the GIC, while here we have a N:1 mapping, with N interrupts coming into the GICP_SEI, and only one interrupt leaving the GICP_SEI to the GIC ? > +static const struct irq_domain_ops mvebu_sei_ap_domain_ops = { > + .xlate = irq_domain_xlate_onecell, > + .alloc = mvebu_sei_irq_domain_alloc, > + .free = mvebu_sei_irq_domain_free, > +}; > + > +static const struct irq_domain_ops mvebu_sei_cp_domain_ops = { > + .xlate = irq_domain_xlate_twocell, > + .alloc = mvebu_sei_irq_domain_alloc, > + .free = mvebu_sei_irq_domain_free, > +}; Why do you need two cells for the interrupts coming from the CP and only one cell for the interrupts coming from the AP ? For thermal in the AP, you do: + interrupt-parent = <&sei_wired_controller>; + interrupts = <18>; i.e, you don't specify an interrupt type. For thermal in the CP, you do: + interrupts-extended = + <&CP110_LABEL(icu_sei) 116 IRQ_TYPE_LEVEL_HIGH>; here you specify an interrupt type. I'm not sure why you have this difference. Even more so because I think a SEI level interrupt is not possible, since you only have a "SET" register and no "CLR" register. Some guidance from Marc here might be useful perhaps. > +static int mvebu_sei_probe(struct platform_device *pdev) > +{ > + struct device_node *node = pdev->dev.of_node, *parent, *child; > + struct irq_domain *parent_domain, *plat_domain; > + struct mvebu_sei *sei; > + const __be32 *property; > + u32 top_level_spi, size; > + int ret; > + > + sei = devm_kzalloc(&pdev->dev, sizeof(*sei), GFP_KERNEL); > + if (!sei) > + return -ENOMEM; > + > + sei->dev = &pdev->dev; > + > + spin_lock_init(&sei->cp_msi_lock); > + > + sei->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!sei->res) { > + dev_err(sei->dev, "Failed to retrieve SEI resource\n"); > + return -ENODEV; > + } > + > + sei->base = devm_ioremap(sei->dev, sei->res->start, > + resource_size(sei->res)); > + if (!sei->base) { > + dev_err(sei->dev, "Failed to remap SEI resource\n"); > + return -ENODEV; > + } Use devm_ioremap_resource() here, and remove the error handling of platform_get_resource(), because it's already taken care of by devm_ioremap_resource(). > + /* > + * Reserve the single (top-level) parent SPI IRQ from which all the > + * interrupts handled by this driver will be signaled. > + */ > + top_level_spi = irq_of_parse_and_map(node, 0); > + if (top_level_spi <= 0) { > + dev_err(sei->dev, "Failed to retrieve top-level SPI IRQ\n"); > + return -ENODEV; > + } Rather than top_level_spi, something like parent_irq would make more sense to me. > + irq_set_chained_handler(top_level_spi, mvebu_sei_handle_cascade_irq); > + irq_set_handler_data(top_level_spi, sei); > + > + /* > + * SEIs in the range [ 0; 20] are wired and come from the AP. > + * SEIs in the range [21; 63] are CP SEI and are triggered through MSIs. > + * > + * Each SEI 'domain' is represented as a subnode. > + */ > + > + /* Get a reference to the parent domain to create a hierarchy */ > + parent = of_irq_find_parent(node); > + if (!parent) { > + dev_err(sei->dev, "Failed to find parent IRQ node\n"); > + ret = -ENODEV; > + goto dispose_irq; > + } > + > + parent_domain = irq_find_host(parent); > + if (!parent_domain) { > + dev_err(sei->dev, "Failed to find parent IRQ domain\n"); > + ret = -ENODEV; > + goto dispose_irq; > + } > + > + /* Create the 'wired' hierarchy */ > + child = of_find_node_by_name(node, "sei-wired-controller"); > + if (!child) { > + dev_err(sei->dev, "Missing 'sei-wired-controller' subnode\n"); > + ret = -ENODEV; > + goto dispose_irq; > + } Don't forget to of_node_put(child) once you're done using this DT node reference. > + > + property = of_get_property(child, "reg", &size); > + if (!property || size != (2 * sizeof(u32))) { > + dev_err(sei->dev, "Missing subnode 'reg' property\n"); > + ret = -ENODEV; > + goto dispose_irq; > + } As Rob said, I don't think the "reg" property is appropriate for this usage. > + sei->ap_interrupts.first = be32_to_cpu(property[0]); > + sei->ap_interrupts.number = be32_to_cpu(property[1]); > + sei->ap_domain = irq_domain_create_hierarchy(parent_domain, 0, > + sei->ap_interrupts.number, > + of_node_to_fwnode(child), > + &mvebu_sei_ap_domain_ops, > + sei); > + if (!sei->ap_domain) { > + dev_err(sei->dev, "Failed to create AP IRQ domain\n"); > + ret = -ENOMEM; > + goto dispose_irq; > + } > + > + /* Create the 'MSI' hierarchy */ > + child = of_find_node_by_name(node, "sei-msi-controller"); > + if (!child) { > + dev_err(sei->dev, "Missing 'sei-msi-controller' subnode\n"); > + ret = -ENODEV; > + goto remove_ap_domain; > + } Ditto: missing of_node_put(child) somewhere below to balance of_find_node_by_name(). > + property = of_get_property(child, "reg", &size); > + if (!property || size != (2 * sizeof(u32))) { > + dev_err(sei->dev, "Missing subnode 'reg' property\n"); > + ret = -ENODEV; > + goto remove_ap_domain; > + } > + > + sei->cp_interrupts.first = be32_to_cpu(property[0]); > + sei->cp_interrupts.number = be32_to_cpu(property[1]); > + sei->cp_domain = irq_domain_create_hierarchy(parent_domain, 0, > + sei->cp_interrupts.number, > + of_node_to_fwnode(child), > + &mvebu_sei_cp_domain_ops, > + sei); > + if (!sei->cp_domain) { > + pr_err("Failed to create CPs IRQ domain\n"); > + ret = -ENOMEM; > + goto remove_ap_domain; > + } > + > + plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(child), > + &mvebu_sei_msi_domain_info, > + sei->cp_domain); > + if (!plat_domain) { > + pr_err("Failed to create CPs MSI domain\n"); > + ret = -ENOMEM; > + goto remove_cp_domain; > + } > + > + platform_set_drvdata(pdev, sei); > + > + mvebu_sei_reset(sei); Please do the reset *before* registering the IRQ domains, it's more logical to have the HW ready and then expose it to Linux rather than the opposite. It would be nice to have the review from Marc on this driver, especially on whether the SEI is properly modeled in terms of IRQ domains; > diff --git a/drivers/irqchip/irq-mvebu-sei.h b/drivers/irqchip/irq-mvebu-sei.h > new file mode 100644 > index 000000000000..f0c12a441923 > --- /dev/null > +++ b/drivers/irqchip/irq-mvebu-sei.h > @@ -0,0 +1,12 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +#ifndef __MVEBU_SEI_H__ > +#define __MVEBU_SEI_H__ > + > +#include > + > +struct device_node; > + > +int mvebu_sei_get_doorbells(struct device_node *dn, phys_addr_t *set, > + phys_addr_t *clr); > + > +#endif /* __MVEBU_SEI_H__ */ This header file can be removed if you drop mvebu_sei_get_doorbells(), as suggested above. Best regards, Thomas -- Thomas Petazzoni, CTO, Bootlin (formerly Free Electrons) Embedded Linux and Kernel engineering https://bootlin.com From mboxrd@z Thu Jan 1 00:00:00 1970 From: Thomas Petazzoni Subject: Re: [PATCH 10/17] irqchip/irq-mvebu-sei: add new driver for Marvell SEI Date: Wed, 2 May 2018 11:17:44 +0200 Message-ID: <20180502111744.5391afff@windsurf.home> References: <20180421135537.24716-1-miquel.raynal@bootlin.com> <20180421135537.24716-11-miquel.raynal@bootlin.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <20180421135537.24716-11-miquel.raynal@bootlin.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org To: Miquel Raynal Cc: Mark Rutland , Andrew Lunn , Jason Cooper , devicetree@vger.kernel.org, Marc Zyngier , Catalin Marinas , Gregory Clement , Haim Boot , Will Deacon , Maxime Chevallier , Nadav Haklai , Antoine Tenart , Rob Herring , Thomas Gleixner , Hanna Hawa , linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth List-Id: devicetree@vger.kernel.org SGVsbG8sCgpPbiBTYXQsIDIxIEFwciAyMDE4IDE1OjU1OjMwICswMjAwLCBNaXF1ZWwgUmF5bmFs IHdyb3RlOgoKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9pcnFjaGlwL01ha2VmaWxlIGIvZHJpdmVy cy9pcnFjaGlwL01ha2VmaWxlCj4gaW5kZXggNWVkNDY1YWIxYzc2Li42YjViNzVjYjQ2OTQgMTAw NjQ0Cj4gLS0tIGEvZHJpdmVycy9pcnFjaGlwL01ha2VmaWxlCj4gKysrIGIvZHJpdmVycy9pcnFj aGlwL01ha2VmaWxlCj4gQEAgLTczLDYgKzczLDcgQEAgb2JqLSQoQ09ORklHX0lNWF9HUENWMikJ CQkrPSBpcnEtaW14LWdwY3YyLm8KPiAgb2JqLSQoQ09ORklHX1BJQzMyX0VWSUMpCQkrPSBpcnEt cGljMzItZXZpYy5vCj4gIG9iai0kKENPTkZJR19NU0NDX09DRUxPVF9JUlEpCQkrPSBpcnEtbXNj Yy1vY2Vsb3Qubwo+ICBvYmotJChDT05GSUdfTVZFQlVfR0lDUCkJCSs9IGlycS1tdmVidS1naWNw Lm8KPiArb2JqLSQoQ09ORklHX01WRUJVX1NFSSkJCQkrPSBpcnEtbXZlYnUtc2VpLm8KPiAgb2Jq LSQoQ09ORklHX01WRUJVX0lDVSkJCQkrPSBpcnEtbXZlYnUtaWN1Lm8KPiAgb2JqLSQoQ09ORklH X01WRUJVX09ETUkpCQkrPSBpcnEtbXZlYnUtb2RtaS5vCj4gIG9iai0kKENPTkZJR19NVkVCVV9Q SUMpCQkJKz0gaXJxLW12ZWJ1LXBpYy5vCgpBbHBoYWJldGljIG9yZGVyaW5nIHdvdWxkIHB1dCBT RUkgYWZ0ZXIgUElDIEkgZ3Vlc3MgOikKCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvaXJxY2hpcC9p cnEtbXZlYnUtc2VpLmMgYi9kcml2ZXJzL2lycWNoaXAvaXJxLW12ZWJ1LXNlaS5jCj4gbmV3IGZp bGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAwMDAuLjVjMTJjNzRlM2YwOQo+IC0tLSAv ZGV2L251bGwKPiArKysgYi9kcml2ZXJzL2lycWNoaXAvaXJxLW12ZWJ1LXNlaS5jCj4gQEAgLTAs MCArMSw0NDkgQEAKPiArLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAgT1IgWDEx CgpMaWNlbnNlIGZvciBjb2RlIGlzIEdQTC0yLjAgb25seS4gV2UgdXNlIEdQTC0yLjAgT1IgWDEx IGZvciBEZXZpY2UKVHJlZXMuCgo+ICsjZGVmaW5lIHByX2ZtdChmbXQpICJtdmVidS1zZWk6ICIg Zm10Cj4gKwo+ICsjaW5jbHVkZSA8bGludXgvaXJxLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9pbnRl cnJ1cHQuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2lycWNoaXAvY2hhaW5lZF9pcnEuaD4KPiArI2lu Y2x1ZGUgPGxpbnV4L2lycWRvbWFpbi5oPgo+ICsjaW5jbHVkZSA8bGludXgva2VybmVsLmg+Cj4g KyNpbmNsdWRlIDxsaW51eC9vZl9hZGRyZXNzLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9vZl9pcnEu aD4KPiArI2luY2x1ZGUgPGxpbnV4L29mX3BsYXRmb3JtLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9t c2kuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPgo+ICsjaW5jbHVkZSA8 bGludXgvaXJxY2hpcC5oPgo+ICsKPiArI2luY2x1ZGUgPGR0LWJpbmRpbmdzL2ludGVycnVwdC1j b250cm9sbGVyL2FybS1naWMuaD4KPiArCj4gKyNkZWZpbmUgR0lDUF9TRVRfU0VJX09GRlNFVAkw eDMwCj4gKyNkZWZpbmUgR0lDUF9DTFJfU0VJX09GRlNFVAlHSUNQX1NFVF9TRUlfT0ZGU0VUCgpX aHkgZG8geW91IGhhdmUgdGhpcyBjb25jZXB0IG9mIHNldC9jbHIgaWYgdGhlcmUgaXMgb25seSBv bmUgcmVnaXN0ZXIgPwpJIGFzc3VtZSB0aGF0IGlmIHRoZXJlIGlzIG9ubHkgYSAic2V0IiByZWdp c3RlciwgaXQgbWVhbnMgdGhhdCBTRUkKaW50ZXJydXB0cyBjYW4gb25seSBiZSBlZGdlIHRyaWdn ZXJlZCwgY29udHJhcnkgdG8gTlNSIGludGVycnVwdHMsCndoaWNoIGhhdmUgc2VwYXJhdGUgc2V0 L2NsciB0byBzdXBwb3J0IGxldmVsLXRyaWdnZXJlZCBpbnRlcnJ1cHRzLgoKSGF2aW5nIG9ubHkg YSAic2V0IiBvZmZzZXQgbWVhbnMgdGhhdCB3ZSBjYW4gcmVseSBvbiB0aGUgZXhpc3RpbmcKInN0 cnVjdCBtc2lfbXNnIiB0byBjb252ZXkgYm90aCB0aGUgTVNJIGRvb3JiZWxsIGFkZHJlc3MgYW5k IHBheWxvYWQsCmFuZCB3ZSBkb24ndCBuZWVkIHRoZSBtdmVidV9naWNwX2dldF9kb29yYmVsbHMo KSBoYWNrLgoKPiArLyogQ2F1c2UgcmVnaXN0ZXIgKi8KPiArI2RlZmluZSBHSUNQX1NFQ1IoaWR4 KQkJKDB4MCAgKyAoaWR4ICogMHg0KSkKPiArLyogTWFzayByZWdpc3RlciAqLwo+ICsjZGVmaW5l IEdJQ1BfU0VNUihpZHgpCQkoMHgyMCArIChpZHggKiAweDQpKQoKTWlub3Igbml0OiBvcmRlciBy ZWdpc3RlciBkZWZpbml0aW9ucyBieSBvcmRlciBvZiBpbmNyZWFzaW5nIG9mZnNldCwKaS5lIHRo ZSBHSUNQX1NFVF9TRUlfT0ZGU0VUIHNob3VsZCBiZSBkZWZpbmVkIGhlcmUuCgo+ICsjZGVmaW5l IFNFSV9JUlFfTkJfUEVSX1JFRwkzMgo+ICsjZGVmaW5lIFNFSV9JUlFfUkVHX05CCQkyCgpzL05C L0NPVU5ULwoKPiArI2RlZmluZSBTRUlfSVJRX05CCQkoU0VJX0lSUV9OQl9QRVJfUkVHICogU0VJ X0lSUV9SRUdfTkIpCgpEaXR0by4KCj4gKyNkZWZpbmUgU0VJX0lSUV9SRUdfSURYKGlycV9pZCkJ KGlycV9pZCAvIFNFSV9JUlFfTkJfUEVSX1JFRykKPiArI2RlZmluZSBTRUlfSVJRX1JFR19CSVQo aXJxX2lkKQkoaXJxX2lkICUgU0VJX0lSUV9OQl9QRVJfUkVHKQo+ICsKPiArc3RydWN0IG12ZWJ1 X3NlaV9pbnRlcnJ1cHRfcmFuZ2Ugewo+ICsJdTMyIGZpcnN0Owo+ICsJdTMyIG51bWJlcjsKPiAr fTsKPiArCj4gK3N0cnVjdCBtdmVidV9zZWkgewo+ICsJc3RydWN0IGRldmljZSAqZGV2Owo+ICsJ dm9pZCBfX2lvbWVtICpiYXNlOwo+ICsJc3RydWN0IHJlc291cmNlICpyZXM7Cj4gKwlzdHJ1Y3Qg aXJxX2RvbWFpbiAqYXBfZG9tYWluOwo+ICsJc3RydWN0IGlycV9kb21haW4gKmNwX2RvbWFpbjsK PiArCXN0cnVjdCBtdmVidV9zZWlfaW50ZXJydXB0X3JhbmdlIGFwX2ludGVycnVwdHM7Cj4gKwlz dHJ1Y3QgbXZlYnVfc2VpX2ludGVycnVwdF9yYW5nZSBjcF9pbnRlcnJ1cHRzOwo+ICsJLyogTG9j ayBvbiBNU0kgYWxsb2NhdGlvbnMvcmVsZWFzZXMgKi8KPiArCXNwaW5sb2NrX3QgY3BfbXNpX2xv Y2s7Cj4gKwlERUNMQVJFX0JJVE1BUChjcF9tc2lfYml0bWFwLCBTRUlfSVJRX05CKTsKPiArfTsK PiArCj4gK3N0YXRpYyBpbnQgbXZlYnVfc2VpX2RvbWFpbl90b19zZWlfaXJxKHN0cnVjdCBtdmVi dV9zZWkgKnNlaSwKPiArCQkJCSAgICAgICBzdHJ1Y3QgaXJxX2RvbWFpbiAqZG9tYWluLAo+ICsJ CQkJICAgICAgIGlycV9od19udW1iZXJfdCBod2lycSkKPiArewo+ICsJaWYgKGRvbWFpbiA9PSBz ZWktPmFwX2RvbWFpbikKPiArCQlyZXR1cm4gc2VpLT5hcF9pbnRlcnJ1cHRzLmZpcnN0ICsgaHdp cnE7Cj4gKwllbHNlCj4gKwkJcmV0dXJuIHNlaS0+Y3BfaW50ZXJydXB0cy5maXJzdCArIGh3aXJx OwoKSSBhbSBub3QgZW50aXJlbHkgY2xlYXIgd2hldGhlciB3ZSBuZWVkIHN1Ym5vZGVzIG9yIG5v dCBpbiB0aGlzCmJpbmRpbmcsIGJ1dCBJIGd1ZXNzIHdlIGRvIGJlY2F1c2Ugd2UgaGF2ZSBvbmUg c3Vic2V0IG9mIHRoZSBpbnRlcnJ1cHRzCnRoYXQgYXJlIHdpcmVkIGludGVycnVwdHMsIGFuZCBh bm90aGVyIHBhcnQgdGhhdCBhcmUgTVNJIHRyaWdnZXJlZC4KClBlcmhhcHMgdGhpcyBpcyBvbmUg YXNwZWN0IG9uIHdoaWNoIE1hcmMgWnluZ2llciBjYW4gY29tbWVudCA/Cgo+ICtzdGF0aWMgdm9p ZCBtdmVidV9zZWlfcmVzZXQoc3RydWN0IG12ZWJ1X3NlaSAqc2VpKQo+ICt7Cj4gKwl1MzIgcmVn X2lkeDsKPiArCj4gKwlmb3IgKHJlZ19pZHggPSAwOyByZWdfaWR4IDwgU0VJX0lSUV9SRUdfTkI7 IHJlZ19pZHgrKykgewo+ICsJCS8qIENsZWFyIGFsbCBjYXVzZSBiaXRzICovCj4gKwkJd3JpdGVs KDB4RkZGRkZGRkYsIHNlaS0+YmFzZSArIEdJQ1BfU0VDUihyZWdfaWR4KSk7Cj4gKwkJLyogRW5h YmxlIGFsbCBpbnRlcnJ1cHRzICovCj4gKwkJd3JpdGVsKDAsIHNlaS0+YmFzZSArIEdJQ1BfU0VN UihyZWdfaWR4KSk7CgpFbmFibGluZyBpbnRlcnJ1cHRzIGJ5IGRlZmF1bHQgPyBUaGlzIGxvb2tz IHdlaXJkLiBUaGV5IHNob3VsZCBvbmx5IGJlCmVuYWJsZWQuLi4gd2hlbiBlbmFibGVkLgoKPiAr aW50IG12ZWJ1X3NlaV9nZXRfZG9vcmJlbGxzKHN0cnVjdCBkZXZpY2Vfbm9kZSAqZG4sIHBoeXNf YWRkcl90ICpzZXQsCj4gKwkJCSAgICBwaHlzX2FkZHJfdCAqY2xyKQo+ICt7Cj4gKwlzdHJ1Y3Qg cGxhdGZvcm1fZGV2aWNlICpwZGV2Owo+ICsJc3RydWN0IG12ZWJ1X3NlaSAqc2VpOwo+ICsKPiAr CXBkZXYgPSBvZl9maW5kX2RldmljZV9ieV9ub2RlKGRuLT5wYXJlbnQpOwo+ICsJaWYgKCFwZGV2 KQo+ICsJCXJldHVybiAtRU5PREVWOwo+ICsKPiArCXNlaSA9IHBsYXRmb3JtX2dldF9kcnZkYXRh KHBkZXYpOwo+ICsJaWYgKCFzZWkpCj4gKwkJcmV0dXJuIC1FTk9ERVY7Cj4gKwo+ICsJKnNldCA9 IChwaHlzX2FkZHJfdCkoc2VpLT5yZXMtPnN0YXJ0ICsgR0lDUF9TRVRfU0VJX09GRlNFVCk7Cj4g KwkqY2xyID0gKHBoeXNfYWRkcl90KShzZWktPnJlcy0+c3RhcnQgKyBHSUNQX0NMUl9TRUlfT0ZG U0VUKTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQoKQXMgSSBzYWlkIGFib3ZlLCBJIGJlbGlldmUg dGhpcyBoYWNrIGlzIG5vdCBuZWVkZWQsIGJlY2F1c2UgU0VJcyBhcmUKZWRnZS10cmlnZ2VyZWQs IGFuZCB3ZSBoYXZlIGEgc2luZ2xlIFNFVF9TRUlfT0ZGU0VUIE1TSSBkb29yYmVsbAphZGRyZXNz IHRvIGNvbnZleSwgd2hpY2ggbWFrZXMgInN0cnVjdCBtc2lfbXNnIiBhcyBpdCBpcyB0b2RheQpz dWZmaWNpZW50LgoKPiArc3RhdGljIHZvaWQgbXZlYnVfc2VpX21hc2tfaXJxKHN0cnVjdCBpcnFf ZGF0YSAqZCkKPiArewo+ICsJc3RydWN0IG12ZWJ1X3NlaSAqc2VpID0gaXJxX2RhdGFfZ2V0X2ly cV9jaGlwX2RhdGEoZCk7Cj4gKwl1MzIgcmVnX2lkeCA9IFNFSV9JUlFfUkVHX0lEWChkLT5od2ly cSk7CgpUaGlzIGRvZXNuJ3QgbG9vayByaWdodC4gVGhlIGQtPmh3aXJxIGlzIHJlbGF0aXZlIHRv IHRoZSBiZWdpbm5pbmcgb2YKdGhlIGRvbWFpbiwgd2hpbGUgeW91IHNob3VsZCB1c2Ugc2VpX2ly cSBoZXJlLiBGb3IgZXhhbXBsZSwgdGhlIFNFSQpuwrAzMiAoZmlyc3QgaW50ZXJydXB0IGluIHRo ZSBzZWNvbmQgcmVnaXN0ZXIpIHdpbGwgaGF2ZSBkLT5od2lycSA9IDExLApiZWNhdXNlIGl0IGlz IHRoZSAxMXRoIFNFSSBpbnRlcnJ1cHQgZm9yIHRoZSBDUC4gU28gaGVyZSwgeW91IHdpbGwKY29u Y2x1ZGUgdGhhdCByZWdfaWR4ID0gMCwgd2hpbGUgaXQgc2hvdWxkIGJlIHJlZ19pZHggPSAxLgoK PiArCXUzMiBzZWlfaXJxID0gbXZlYnVfc2VpX2RvbWFpbl90b19zZWlfaXJxKHNlaSwgZC0+ZG9t YWluLCBkLT5od2lycSk7Cj4gKwl1MzIgaXJxX21hc2sgPSBCSVQoU0VJX0lSUV9SRUdfQklUKHNl aV9pcnEpKTsKPiArCXUzMiByZWc7Cj4gKwo+ICsJLyogMSBkaXNhYmxlcyB0aGUgaW50ZXJydXB0 ICovCj4gKwlyZWcgPSAgcmVhZGwoc2VpLT5iYXNlICsgR0lDUF9TRU1SKHJlZ19pZHgpKTsKPiAr CXdyaXRlbChyZWcgfCBpcnFfbWFzaywgc2VpLT5iYXNlICsgR0lDUF9TRU1SKHJlZ19pZHgpKTsK ClBlcnNvbmFsIHRhc3RlIGhlcmUsIGJ1dCBJIHByZWZlcjoKCglyZWcgPSAgcmVhZGwoc2VpLT5i YXNlICsgR0lDUF9TRU1SKHJlZ19pZHgpKTsKCXJlZyB8PSBCSVQoU0VJX0lSUV9SRUdfQklUKHNl aV9pcnEpKTsKCXdyaXRlbChyZWcsIHNlaS0+YmFzZSArIEdJQ1BfU0VNUihyZWdfaWR4KSk7Cgo+ ICtzdGF0aWMgdm9pZCBtdmVidV9zZWlfdW5tYXNrX2lycShzdHJ1Y3QgaXJxX2RhdGEgKmQpCj4g K3sKPiArCXN0cnVjdCBtdmVidV9zZWkgKnNlaSA9IGlycV9kYXRhX2dldF9pcnFfY2hpcF9kYXRh KGQpOwo+ICsJdTMyIHJlZ19pZHggPSBTRUlfSVJRX1JFR19JRFgoZC0+aHdpcnEpOwoKU2FtZSBt aXN0YWtlIGFzIGFib3ZlIEkgYmVsaWV2ZS4KCj4gKwl1MzIgc2VpX2lycSA9IG12ZWJ1X3NlaV9k b21haW5fdG9fc2VpX2lycShzZWksIGQtPmRvbWFpbiwgZC0+aHdpcnEpOwo+ICsJdTMyIGlycV9t YXNrID0gQklUKFNFSV9JUlFfUkVHX0JJVChzZWlfaXJxKSk7Cj4gKwl1MzIgcmVnOwo+ICsKPiAr CS8qIDAgZW5hYmxlcyB0aGUgaW50ZXJydXB0ICovCj4gKwlyZWcgPSByZWFkbChzZWktPmJhc2Ug KyBHSUNQX1NFTVIocmVnX2lkeCkpOwo+ICsJd3JpdGVsKHJlZyAmIH5pcnFfbWFzaywgc2VpLT5i YXNlICsgR0lDUF9TRU1SKHJlZ19pZHgpKTsKCkFuZCBzYW1lIG5pdHBpY2sgY29tbWVudCA6LSkK Cj4gK3N0YXRpYyBpbnQgbXZlYnVfc2VpX2lycV9kb21haW5fYWxsb2Moc3RydWN0IGlycV9kb21h aW4gKmRvbWFpbiwKPiArCQkJCSAgICAgIHVuc2lnbmVkIGludCB2aXJxLCB1bnNpZ25lZCBpbnQg bnJfaXJxcywKPiArCQkJCSAgICAgIHZvaWQgKmFyZ3MpCgpJIHRoaW5rIHRoZSBjb2Rpbmcgc3R5 bGUgc2F5cyB0aGF0IGFyZ3VtZW50cyBzaG91bGQgYmUgYWxpZ25lZCwgbm8gPwoKPiArewo+ICsJ c3RydWN0IG12ZWJ1X3NlaSAqc2VpID0gZG9tYWluLT5ob3N0X2RhdGE7Cj4gKwlzdHJ1Y3QgaXJx X2Z3c3BlYyAqZndzcGVjID0gYXJnczsKPiArCXN0cnVjdCBpcnFfY2hpcCAqaXJxX2NoaXA7Cj4g KwlpbnQgc2VpX2h3aXJxLCBod2lycTsKPiArCWludCByZXQ7Cj4gKwo+ICsJLyogU29mdHdhcmUg b25seSBzdXBwb3J0cyBzaW5nbGUgYWxsb2NhdGlvbnMgZm9yIG5vdyAqLwo+ICsJaWYgKG5yX2ly cXMgIT0gMSkKPiArCQlyZXR1cm4gLUVOT1RTVVBQOwo+ICsKPiArCWlmIChkb21haW4gPT0gc2Vp LT5hcF9kb21haW4pIHsKPiArCQlpcnFfY2hpcCA9ICZtdmVidV9zZWlfYXBfd2lyZWRfaXJxX2No aXA7Cj4gKwkJaHdpcnEgPSBmd3NwZWMtPnBhcmFtWzBdOwo+ICsJfSBlbHNlIHsKPiArCQlpcnFf Y2hpcCA9ICZtdmVidV9zZWlfY3BfbXNpX2lycV9jaGlwOwo+ICsJCXNwaW5fbG9jaygmc2VpLT5j cF9tc2lfbG9jayk7Cj4gKwkJaHdpcnEgPSBiaXRtYXBfZmluZF9mcmVlX3JlZ2lvbihzZWktPmNw X21zaV9iaXRtYXAsIFNFSV9JUlFfTkIsCj4gKwkJCQkJCTApOwo+ICsJCXNwaW5fdW5sb2NrKCZz ZWktPmNwX21zaV9sb2NrKTsKPiArCQlpZiAoaHdpcnEgPCAwKQo+ICsJCQlyZXR1cm4gLUVOT1NQ QzsKPiArCX0KPiArCj4gKwlzZWlfaHdpcnEgPSBtdmVidV9zZWlfZG9tYWluX3RvX3NlaV9pcnEo c2VpLCBkb21haW4sIGh3aXJxKTsKPiArCj4gKwlmd3NwZWMtPmZ3bm9kZSA9IGRvbWFpbi0+cGFy ZW50LT5md25vZGU7Cj4gKwlmd3NwZWMtPnBhcmFtX2NvdW50ID0gMzsKPiArCWZ3c3BlYy0+cGFy YW1bMF0gPSBHSUNfU1BJOwo+ICsJZndzcGVjLT5wYXJhbVsxXSA9IHNlaV9od2lycTsKPiArCWZ3 c3BlYy0+cGFyYW1bMl0gPSBJUlFfVFlQRV9FREdFX1JJU0lORzsKCk1heWJlIGl0J3MgbWUgYmVp bmcgY29uZnVzZWQsIGJ1dCBJIHRob3VnaHQgYWxsIFNFSSBpbnRlcnJ1cHRzIHdlcmUKbXV4ZWQg dG9nZXRoZXIgdG8gYSBzaW5nbGUgU1BJIGZvciB0aGUgcGFyZW50IEdJQy4gQnV0IGhlcmUsIHlv dQphbGxvY2F0ZSBkaWZmZXJlbnQgU1BJcyBhdCB0aGUgR0lDIGxldmVsLiBJbnR1aXRpdmVseSwg dGhpcyBkb2Vzbid0Cmxvb2sgZ29vZC4gSGF2ZW4ndCB5b3UgY29weS9wYXN0ZWQgdG9vIG11Y2gg ZnJvbSB0aGUgZ2ljcCBkcml2ZXIsIHdoZXJlCndlIGhhdmUgYSAxOjEgbWFwcGluZyBiZXR3ZWVu IGludGVycnVwdHMgY29taW5nIGludG8gdGhlIEdJQ1AgYW5kCmludGVycnVwdHMgc2lnbmFsZWQg YnkgdGhlIEdJQ1AgdG8gdGhlIEdJQywgd2hpbGUgaGVyZSB3ZSBoYXZlIGEgTjoxCm1hcHBpbmcs IHdpdGggTiBpbnRlcnJ1cHRzIGNvbWluZyBpbnRvIHRoZSBHSUNQX1NFSSwgYW5kIG9ubHkgb25l CmludGVycnVwdCBsZWF2aW5nIHRoZSBHSUNQX1NFSSB0byB0aGUgR0lDID8KCj4gK3N0YXRpYyBj b25zdCBzdHJ1Y3QgaXJxX2RvbWFpbl9vcHMgbXZlYnVfc2VpX2FwX2RvbWFpbl9vcHMgPSB7Cj4g KwkueGxhdGUgPSBpcnFfZG9tYWluX3hsYXRlX29uZWNlbGwsCj4gKwkuYWxsb2MgPSBtdmVidV9z ZWlfaXJxX2RvbWFpbl9hbGxvYywKPiArCS5mcmVlID0gbXZlYnVfc2VpX2lycV9kb21haW5fZnJl ZSwKPiArfTsKPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgaXJxX2RvbWFpbl9vcHMgbXZlYnVf c2VpX2NwX2RvbWFpbl9vcHMgPSB7Cj4gKwkueGxhdGUgPSBpcnFfZG9tYWluX3hsYXRlX3R3b2Nl bGwsCj4gKwkuYWxsb2MgPSBtdmVidV9zZWlfaXJxX2RvbWFpbl9hbGxvYywKPiArCS5mcmVlID0g bXZlYnVfc2VpX2lycV9kb21haW5fZnJlZSwKPiArfTsKCldoeSBkbyB5b3UgbmVlZCB0d28gY2Vs bHMgZm9yIHRoZSBpbnRlcnJ1cHRzIGNvbWluZyBmcm9tIHRoZSBDUCBhbmQKb25seSBvbmUgY2Vs bCBmb3IgdGhlIGludGVycnVwdHMgY29taW5nIGZyb20gdGhlIEFQID8KCkZvciB0aGVybWFsIGlu IHRoZSBBUCwgeW91IGRvOgoKKwkJCQkJaW50ZXJydXB0LXBhcmVudCA9IDwmc2VpX3dpcmVkX2Nv bnRyb2xsZXI+OworCQkJCQlpbnRlcnJ1cHRzID0gPDE4PjsKCmkuZSwgeW91IGRvbid0IHNwZWNp ZnkgYW4gaW50ZXJydXB0IHR5cGUuIEZvciB0aGVybWFsIGluIHRoZSBDUCwgeW91IGRvOgoKKwkJ CQlpbnRlcnJ1cHRzLWV4dGVuZGVkID0KKwkJCQkJPCZDUDExMF9MQUJFTChpY3Vfc2VpKSAxMTYg SVJRX1RZUEVfTEVWRUxfSElHSD47CgpoZXJlIHlvdSBzcGVjaWZ5IGFuIGludGVycnVwdCB0eXBl LiBJJ20gbm90IHN1cmUgd2h5IHlvdSBoYXZlIHRoaXMKZGlmZmVyZW5jZS4gRXZlbiBtb3JlIHNv IGJlY2F1c2UgSSB0aGluayBhIFNFSSBsZXZlbCBpbnRlcnJ1cHQgaXMgbm90CnBvc3NpYmxlLCBz aW5jZSB5b3Ugb25seSBoYXZlIGEgIlNFVCIgcmVnaXN0ZXIgYW5kIG5vICJDTFIiIHJlZ2lzdGVy LgoKU29tZSBndWlkYW5jZSBmcm9tIE1hcmMgaGVyZSBtaWdodCBiZSB1c2VmdWwgcGVyaGFwcy4K Cgo+ICtzdGF0aWMgaW50IG12ZWJ1X3NlaV9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpw ZGV2KQo+ICt7Cj4gKwlzdHJ1Y3QgZGV2aWNlX25vZGUgKm5vZGUgPSBwZGV2LT5kZXYub2Zfbm9k ZSwgKnBhcmVudCwgKmNoaWxkOwo+ICsJc3RydWN0IGlycV9kb21haW4gKnBhcmVudF9kb21haW4s ICpwbGF0X2RvbWFpbjsKPiArCXN0cnVjdCBtdmVidV9zZWkgKnNlaTsKPiArCWNvbnN0IF9fYmUz MiAqcHJvcGVydHk7Cj4gKwl1MzIgdG9wX2xldmVsX3NwaSwgc2l6ZTsKPiArCWludCByZXQ7Cj4g Kwo+ICsJc2VpID0gZGV2bV9remFsbG9jKCZwZGV2LT5kZXYsIHNpemVvZigqc2VpKSwgR0ZQX0tF Uk5FTCk7Cj4gKwlpZiAoIXNlaSkKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwlzZWktPmRl diA9ICZwZGV2LT5kZXY7Cj4gKwo+ICsJc3Bpbl9sb2NrX2luaXQoJnNlaS0+Y3BfbXNpX2xvY2sp Owo+ICsKPiArCXNlaS0+cmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlKHBkZXYsIElPUkVTT1VS Q0VfTUVNLCAwKTsKPiArCWlmICghc2VpLT5yZXMpIHsKPiArCQlkZXZfZXJyKHNlaS0+ZGV2LCAi RmFpbGVkIHRvIHJldHJpZXZlIFNFSSByZXNvdXJjZVxuIik7Cj4gKwkJcmV0dXJuIC1FTk9ERVY7 Cj4gKwl9Cj4gKwo+ICsJc2VpLT5iYXNlID0gZGV2bV9pb3JlbWFwKHNlaS0+ZGV2LCBzZWktPnJl cy0+c3RhcnQsCj4gKwkJCQkgcmVzb3VyY2Vfc2l6ZShzZWktPnJlcykpOwo+ICsJaWYgKCFzZWkt PmJhc2UpIHsKPiArCQlkZXZfZXJyKHNlaS0+ZGV2LCAiRmFpbGVkIHRvIHJlbWFwIFNFSSByZXNv dXJjZVxuIik7Cj4gKwkJcmV0dXJuIC1FTk9ERVY7Cj4gKwl9CgpVc2UgZGV2bV9pb3JlbWFwX3Jl c291cmNlKCkgaGVyZSwgYW5kIHJlbW92ZSB0aGUgZXJyb3IgaGFuZGxpbmcgb2YKcGxhdGZvcm1f Z2V0X3Jlc291cmNlKCksIGJlY2F1c2UgaXQncyBhbHJlYWR5IHRha2VuIGNhcmUgb2YgYnkKZGV2 bV9pb3JlbWFwX3Jlc291cmNlKCkuCgo+ICsJLyoKPiArCSAqIFJlc2VydmUgdGhlIHNpbmdsZSAo dG9wLWxldmVsKSBwYXJlbnQgU1BJIElSUSBmcm9tIHdoaWNoIGFsbCB0aGUKPiArCSAqIGludGVy cnVwdHMgaGFuZGxlZCBieSB0aGlzIGRyaXZlciB3aWxsIGJlIHNpZ25hbGVkLgo+ICsJICovCj4g Kwl0b3BfbGV2ZWxfc3BpID0gaXJxX29mX3BhcnNlX2FuZF9tYXAobm9kZSwgMCk7Cj4gKwlpZiAo dG9wX2xldmVsX3NwaSA8PSAwKSB7Cj4gKwkJZGV2X2VycihzZWktPmRldiwgIkZhaWxlZCB0byBy ZXRyaWV2ZSB0b3AtbGV2ZWwgU1BJIElSUVxuIik7Cj4gKwkJcmV0dXJuIC1FTk9ERVY7Cj4gKwl9 CgpSYXRoZXIgdGhhbiB0b3BfbGV2ZWxfc3BpLCBzb21ldGhpbmcgbGlrZSBwYXJlbnRfaXJxIHdv dWxkIG1ha2UgbW9yZQpzZW5zZSB0byBtZS4KCj4gKwlpcnFfc2V0X2NoYWluZWRfaGFuZGxlcih0 b3BfbGV2ZWxfc3BpLCBtdmVidV9zZWlfaGFuZGxlX2Nhc2NhZGVfaXJxKTsKPiArCWlycV9zZXRf aGFuZGxlcl9kYXRhKHRvcF9sZXZlbF9zcGksIHNlaSk7Cj4gKwo+ICsJLyoKPiArCSAqIFNFSXMg aW4gdGhlIHJhbmdlIFsgMDsgMjBdIGFyZSB3aXJlZCBhbmQgY29tZSBmcm9tIHRoZSBBUC4KPiAr CSAqIFNFSXMgaW4gdGhlIHJhbmdlIFsyMTsgNjNdIGFyZSBDUCBTRUkgYW5kIGFyZSB0cmlnZ2Vy ZWQgdGhyb3VnaCBNU0lzLgo+ICsJICoKPiArCSAqIEVhY2ggU0VJICdkb21haW4nIGlzIHJlcHJl c2VudGVkIGFzIGEgc3Vibm9kZS4KPiArCSAqLwo+ICsKPiArCS8qIEdldCBhIHJlZmVyZW5jZSB0 byB0aGUgcGFyZW50IGRvbWFpbiB0byBjcmVhdGUgYSBoaWVyYXJjaHkgKi8KPiArCXBhcmVudCA9 IG9mX2lycV9maW5kX3BhcmVudChub2RlKTsKPiArCWlmICghcGFyZW50KSB7Cj4gKwkJZGV2X2Vy cihzZWktPmRldiwgIkZhaWxlZCB0byBmaW5kIHBhcmVudCBJUlEgbm9kZVxuIik7Cj4gKwkJcmV0 ID0gLUVOT0RFVjsKPiArCQlnb3RvIGRpc3Bvc2VfaXJxOwo+ICsJfQo+ICsKPiArCXBhcmVudF9k b21haW4gPSBpcnFfZmluZF9ob3N0KHBhcmVudCk7Cj4gKwlpZiAoIXBhcmVudF9kb21haW4pIHsK PiArCQlkZXZfZXJyKHNlaS0+ZGV2LCAiRmFpbGVkIHRvIGZpbmQgcGFyZW50IElSUSBkb21haW5c biIpOwo+ICsJCXJldCA9IC1FTk9ERVY7Cj4gKwkJZ290byBkaXNwb3NlX2lycTsKPiArCX0KPiAr Cj4gKwkvKiBDcmVhdGUgdGhlICd3aXJlZCcgaGllcmFyY2h5ICovCj4gKwljaGlsZCA9IG9mX2Zp bmRfbm9kZV9ieV9uYW1lKG5vZGUsICJzZWktd2lyZWQtY29udHJvbGxlciIpOwo+ICsJaWYgKCFj aGlsZCkgewo+ICsJCWRldl9lcnIoc2VpLT5kZXYsICJNaXNzaW5nICdzZWktd2lyZWQtY29udHJv bGxlcicgc3Vibm9kZVxuIik7Cj4gKwkJcmV0ID0gLUVOT0RFVjsKPiArCQlnb3RvIGRpc3Bvc2Vf aXJxOwo+ICsJfQoKRG9uJ3QgZm9yZ2V0IHRvIG9mX25vZGVfcHV0KGNoaWxkKSBvbmNlIHlvdSdy ZSBkb25lIHVzaW5nIHRoaXMgRFQgbm9kZQpyZWZlcmVuY2UuCgo+ICsKPiArCXByb3BlcnR5ID0g b2ZfZ2V0X3Byb3BlcnR5KGNoaWxkLCAicmVnIiwgJnNpemUpOwo+ICsJaWYgKCFwcm9wZXJ0eSB8 fCBzaXplICE9ICgyICogc2l6ZW9mKHUzMikpKSB7Cj4gKwkJZGV2X2VycihzZWktPmRldiwgIk1p c3Npbmcgc3Vibm9kZSAncmVnJyBwcm9wZXJ0eVxuIik7Cj4gKwkJcmV0ID0gLUVOT0RFVjsKPiAr CQlnb3RvIGRpc3Bvc2VfaXJxOwo+ICsJfQoKQXMgUm9iIHNhaWQsIEkgZG9uJ3QgdGhpbmsgdGhl ICJyZWciIHByb3BlcnR5IGlzIGFwcHJvcHJpYXRlIGZvciB0aGlzCnVzYWdlLgoKPiArCXNlaS0+ YXBfaW50ZXJydXB0cy5maXJzdCA9IGJlMzJfdG9fY3B1KHByb3BlcnR5WzBdKTsKPiArCXNlaS0+ YXBfaW50ZXJydXB0cy5udW1iZXIgPSBiZTMyX3RvX2NwdShwcm9wZXJ0eVsxXSk7Cj4gKwlzZWkt PmFwX2RvbWFpbiA9IGlycV9kb21haW5fY3JlYXRlX2hpZXJhcmNoeShwYXJlbnRfZG9tYWluLCAw LAo+ICsJCQkJCQkgICAgIHNlaS0+YXBfaW50ZXJydXB0cy5udW1iZXIsCj4gKwkJCQkJCSAgICAg b2Zfbm9kZV90b19md25vZGUoY2hpbGQpLAo+ICsJCQkJCQkgICAgICZtdmVidV9zZWlfYXBfZG9t YWluX29wcywKPiArCQkJCQkJICAgICBzZWkpOwo+ICsJaWYgKCFzZWktPmFwX2RvbWFpbikgewo+ ICsJCWRldl9lcnIoc2VpLT5kZXYsICJGYWlsZWQgdG8gY3JlYXRlIEFQIElSUSBkb21haW5cbiIp Owo+ICsJCXJldCA9IC1FTk9NRU07Cj4gKwkJZ290byBkaXNwb3NlX2lycTsKPiArCX0KPiArCj4g KwkvKiBDcmVhdGUgdGhlICdNU0knIGhpZXJhcmNoeSAqLwo+ICsJY2hpbGQgPSBvZl9maW5kX25v ZGVfYnlfbmFtZShub2RlLCAic2VpLW1zaS1jb250cm9sbGVyIik7Cj4gKwlpZiAoIWNoaWxkKSB7 Cj4gKwkJZGV2X2VycihzZWktPmRldiwgIk1pc3NpbmcgJ3NlaS1tc2ktY29udHJvbGxlcicgc3Vi bm9kZVxuIik7Cj4gKwkJcmV0ID0gLUVOT0RFVjsKPiArCQlnb3RvIHJlbW92ZV9hcF9kb21haW47 Cj4gKwl9CgpEaXR0bzogbWlzc2luZyBvZl9ub2RlX3B1dChjaGlsZCkgc29tZXdoZXJlIGJlbG93 IHRvIGJhbGFuY2UKb2ZfZmluZF9ub2RlX2J5X25hbWUoKS4KCj4gKwlwcm9wZXJ0eSA9IG9mX2dl dF9wcm9wZXJ0eShjaGlsZCwgInJlZyIsICZzaXplKTsKPiArCWlmICghcHJvcGVydHkgfHwgc2l6 ZSAhPSAoMiAqIHNpemVvZih1MzIpKSkgewo+ICsJCWRldl9lcnIoc2VpLT5kZXYsICJNaXNzaW5n IHN1Ym5vZGUgJ3JlZycgcHJvcGVydHlcbiIpOwo+ICsJCXJldCA9IC1FTk9ERVY7Cj4gKwkJZ290 byByZW1vdmVfYXBfZG9tYWluOwo+ICsJfQo+ICsKPiArCXNlaS0+Y3BfaW50ZXJydXB0cy5maXJz dCA9IGJlMzJfdG9fY3B1KHByb3BlcnR5WzBdKTsKPiArCXNlaS0+Y3BfaW50ZXJydXB0cy5udW1i ZXIgPSBiZTMyX3RvX2NwdShwcm9wZXJ0eVsxXSk7Cj4gKwlzZWktPmNwX2RvbWFpbiA9IGlycV9k b21haW5fY3JlYXRlX2hpZXJhcmNoeShwYXJlbnRfZG9tYWluLCAwLAo+ICsJCQkJCQkgICAgIHNl aS0+Y3BfaW50ZXJydXB0cy5udW1iZXIsCj4gKwkJCQkJCSAgICAgb2Zfbm9kZV90b19md25vZGUo Y2hpbGQpLAo+ICsJCQkJCQkgICAgICZtdmVidV9zZWlfY3BfZG9tYWluX29wcywKPiArCQkJCQkJ ICAgICBzZWkpOwo+ICsJaWYgKCFzZWktPmNwX2RvbWFpbikgewo+ICsJCXByX2VycigiRmFpbGVk IHRvIGNyZWF0ZSBDUHMgSVJRIGRvbWFpblxuIik7Cj4gKwkJcmV0ID0gLUVOT01FTTsKPiArCQln b3RvIHJlbW92ZV9hcF9kb21haW47Cj4gKwl9Cj4gKwo+ICsJcGxhdF9kb21haW4gPSBwbGF0Zm9y bV9tc2lfY3JlYXRlX2lycV9kb21haW4ob2Zfbm9kZV90b19md25vZGUoY2hpbGQpLAo+ICsJCQkJ CQkgICAgICZtdmVidV9zZWlfbXNpX2RvbWFpbl9pbmZvLAo+ICsJCQkJCQkgICAgIHNlaS0+Y3Bf ZG9tYWluKTsKPiArCWlmICghcGxhdF9kb21haW4pIHsKPiArCQlwcl9lcnIoIkZhaWxlZCB0byBj cmVhdGUgQ1BzIE1TSSBkb21haW5cbiIpOwo+ICsJCXJldCA9IC1FTk9NRU07Cj4gKwkJZ290byBy ZW1vdmVfY3BfZG9tYWluOwo+ICsJfQoKCgo+ICsKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBk ZXYsIHNlaSk7Cj4gKwo+ICsJbXZlYnVfc2VpX3Jlc2V0KHNlaSk7CgpQbGVhc2UgZG8gdGhlIHJl c2V0ICpiZWZvcmUqIHJlZ2lzdGVyaW5nIHRoZSBJUlEgZG9tYWlucywgaXQncyBtb3JlCmxvZ2lj YWwgdG8gaGF2ZSB0aGUgSFcgcmVhZHkgYW5kIHRoZW4gZXhwb3NlIGl0IHRvIExpbnV4IHJhdGhl ciB0aGFuCnRoZSBvcHBvc2l0ZS4KCkl0IHdvdWxkIGJlIG5pY2UgdG8gaGF2ZSB0aGUgcmV2aWV3 IGZyb20gTWFyYyBvbiB0aGlzIGRyaXZlciwKZXNwZWNpYWxseSBvbiB3aGV0aGVyIHRoZSBTRUkg aXMgcHJvcGVybHkgbW9kZWxlZCBpbiB0ZXJtcyBvZiBJUlEKZG9tYWluczsKCj4gZGlmZiAtLWdp dCBhL2RyaXZlcnMvaXJxY2hpcC9pcnEtbXZlYnUtc2VpLmggYi9kcml2ZXJzL2lycWNoaXAvaXJx LW12ZWJ1LXNlaS5oCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAwMDAu LmYwYzEyYTQ0MTkyMwo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL2lycWNoaXAvaXJx LW12ZWJ1LXNlaS5oCj4gQEAgLTAsMCArMSwxMiBAQAo+ICsvKiBTUERYLUxpY2Vuc2UtSWRlbnRp ZmllcjogR1BMLTIuMCAqLwo+ICsjaWZuZGVmIF9fTVZFQlVfU0VJX0hfXwo+ICsjZGVmaW5lIF9f TVZFQlVfU0VJX0hfXwo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L3R5cGVzLmg+Cj4gKwo+ICtzdHJ1 Y3QgZGV2aWNlX25vZGU7Cj4gKwo+ICtpbnQgbXZlYnVfc2VpX2dldF9kb29yYmVsbHMoc3RydWN0 IGRldmljZV9ub2RlICpkbiwgcGh5c19hZGRyX3QgKnNldCwKPiArCQkJICAgIHBoeXNfYWRkcl90 ICpjbHIpOwo+ICsKPiArI2VuZGlmIC8qIF9fTVZFQlVfU0VJX0hfXyAqLwoKVGhpcyBoZWFkZXIg ZmlsZSBjYW4gYmUgcmVtb3ZlZCBpZiB5b3UgZHJvcCBtdmVidV9zZWlfZ2V0X2Rvb3JiZWxscygp LAphcyBzdWdnZXN0ZWQgYWJvdmUuCgpCZXN0IHJlZ2FyZHMsCgpUaG9tYXMKLS0gClRob21hcyBQ ZXRhenpvbmksIENUTywgQm9vdGxpbiAoZm9ybWVybHkgRnJlZSBFbGVjdHJvbnMpCkVtYmVkZGVk IExpbnV4IGFuZCBLZXJuZWwgZW5naW5lZXJpbmcKaHR0cHM6Ly9ib290bGluLmNvbQoKX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbGludXgtYXJtLWtlcm5l bCBtYWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6 Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtlcm5lbAo=