From mboxrd@z Thu Jan 1 00:00:00 1970 From: l.stach@pengutronix.de (Lucas Stach) Date: Mon, 23 Jul 2018 19:19:40 +0200 Subject: [PATCH v6 5/5] mailbox: Add support for i.MX7D messaging unit In-Reply-To: <20180722063923.30222-6-o.rempel@pengutronix.de> References: <20180722063923.30222-1-o.rempel@pengutronix.de> <20180722063923.30222-6-o.rempel@pengutronix.de> Message-ID: <1532366380.3163.109.camel@pengutronix.de> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Am Sonntag, den 22.07.2018, 08:39 +0200 schrieb Oleksij Rempel: > The Mailbox controller is able to send messages (up to 4 32 bit words) > between the endpoints. > > This driver was tested using the mailbox-test driver sending messages > between the Cortex-A7 and the Cortex-M4. > > > Reviewed-by: Dong Aisheng > > Signed-off-by: Oleksij Rempel > --- > ?drivers/mailbox/Kconfig???????|???6 + > ?drivers/mailbox/Makefile??????|???2 + > ?drivers/mailbox/imx-mailbox.c | 273 ++++++++++++++++++++++++++++++++++ > ?3 files changed, 281 insertions(+) > ?create mode 100644 drivers/mailbox/imx-mailbox.c > > diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig > index a2bb27446dce..79060ddc380d 100644 > --- a/drivers/mailbox/Kconfig > +++ b/drivers/mailbox/Kconfig > @@ -15,6 +15,12 @@ config ARM_MHU > > ? ??The controller has 3 mailbox channels, the last of which can be > > ? ??used in Secure mode only. > ? > +config IMX_MBOX > > + tristate "i.MX Mailbox" > > + depends on ARCH_MXC || COMPILE_TEST > > + help > > + ??Mailbox implementation for i.MX Messaging Unit (MU). > + > ?config PLATFORM_MHU > > ? tristate "Platform MHU Mailbox" > > ? depends on OF > diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile > index cc23c3a43fcd..ba2fe1b6dd62 100644 > --- a/drivers/mailbox/Makefile > +++ b/drivers/mailbox/Makefile > > @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST) += mailbox-test.o > ? > > ?obj-$(CONFIG_ARM_MHU) += arm_mhu.o > ? > > +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o > + > > ?obj-$(CONFIG_PLATFORM_MHU) += platform_mhu.o > ? > > ?obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o > diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c > new file mode 100644 > index 000000000000..29cf2876db01 > --- /dev/null > +++ b/drivers/mailbox/imx-mailbox.c > @@ -0,0 +1,273 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2018 Pengutronix, Oleksij Rempel > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* Transmit Register */ > > +#define IMX_MU_xTRn(x) (0x00 + 4 * (x)) > +/* Receive Register */ > > +#define IMX_MU_xRRn(x) (0x10 + 4 * (x)) > +/* Status Register */ > > +#define IMX_MU_xSR 0x20 > > +#define IMX_MU_xSR_TEn(x) BIT(20 + (3 - (x))) > > +#define IMX_MU_xSR_RFn(x) BIT(24 + (3 - (x))) > > +#define IMX_MU_xSR_BRDIP BIT(9) > + > +/* Control Register */ > > +#define IMX_MU_xCR 0x24 > +/* Transmit Interrupt Enable */ > > +#define IMX_MU_xCR_TIEn(x) BIT(20 + (3 - (x))) > +/* Receive Interrupt Enable */ > > +#define IMX_MU_xCR_RIEn(x) BIT(24 + (3 - (x))) > + > > +#define IMX_MU_CHANS 4u > + > +struct imx_mu_con_priv { > > > + int irq; > > > + unsigned int idx; > > > + char *irq_desc; > +}; > + > +struct imx_mu_priv { > > > + struct device *dev; > > > + void __iomem *base; > + > > > + struct mbox_controller mbox; > > > + struct mbox_chan mbox_chans[IMX_MU_CHANS]; > + > > + struct imx_mu_con_priv??con_priv[IMX_MU_CHANS]; > > > + struct clk *clk; > + > > > + bool side_b; > +}; > + > +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox) > +{ > > + return container_of(mbox, struct imx_mu_priv, mbox); > +} > + > +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs) > +{ > + iowrite32(val, priv->base + offs); This driver is never going to be used on a device with port based IO, so iowrite doesn't make much sense here, just use writel. Same comment applies to the below read function. Also, given that those functions are not really shortening the code in the user they may also be removed completely IMHO. > +} > + > +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs) > +{ > > + return ioread32(priv->base + offs); > +} > + > +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr) > +{ > > + u32 val; > + > > + val = imx_mu_read(priv, offs); > > + val &= ~clr; > > + val |= set; > > + imx_mu_write(priv, val, offs); > + > > + return val; > +} > + > +static irqreturn_t imx_mu_isr(int irq, void *p) > +{ > > + struct mbox_chan *chan = p; > > + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox); > > + struct imx_mu_con_priv *cp = chan->con_priv; > > + u32 val, ctrl, dat; > + > > + ctrl = imx_mu_read(priv, IMX_MU_xCR); > > + val = imx_mu_read(priv, IMX_MU_xSR); > > + val &= IMX_MU_xSR_TEn(cp->idx) | IMX_MU_xSR_RFn(cp->idx); > > + val &= ctrl & (IMX_MU_xCR_TIEn(cp->idx) | IMX_MU_xCR_RIEn(cp->idx)); > > + if (!val) > > + return IRQ_NONE; > + > > + if (val & IMX_MU_xSR_TEn(cp->idx)) { > > + imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->idx)); > > + mbox_chan_txdone(chan, 0); > > + } > + > > + if (val & IMX_MU_xSR_RFn(cp->idx)) { > > + dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx)); > > + mbox_chan_received_data(chan, (void *)&dat); > > + } > + > > + return IRQ_HANDLED; > +} > + > +static bool imx_mu_last_tx_done(struct mbox_chan *chan) > +{ > > + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox); > > + struct imx_mu_con_priv *cp = chan->con_priv; > > + u32 val; > + > > + val = imx_mu_read(priv, IMX_MU_xSR); > > + /* test if transmit register is empty */ > + return val & IMX_MU_xSR_TEn(cp->idx); I guess "return imx_mu_read(priv, IMX_MU_xSR) & IMX_MU_xSR_TEn(cp->idx);" is shorter and equally well understood. > +} > + > +static int imx_mu_send_data(struct mbox_chan *chan, void *data) > +{ > > + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox); > > + struct imx_mu_con_priv *cp = chan->con_priv; > > + u32 *arg = data; > + > > + if (!imx_mu_last_tx_done(chan)) > > + return -EBUSY; > + > > + imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx)); > + imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->idx), 0); In multi-channel mode this RMW cycle needs some kind of locking. As this register is also changed from the irq handler, this probably needs to be a irqsave spinlock. > + > > + return 0; > +} > + > +static int imx_mu_startup(struct mbox_chan *chan) > +{ > > + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox); > > + struct imx_mu_con_priv *cp = chan->con_priv; > > + int ret; > + > > + cp->irq_desc = devm_kasprintf(priv->dev, GFP_KERNEL, "imx_mu_chan[%i]", > > + ??????cp->idx); > > + if (!cp->irq_desc) > > + return -ENOMEM; > + > > + ret = devm_request_irq(priv->dev, cp->irq, imx_mu_isr, > + ???????IRQF_SHARED, cp->irq_desc, chan); Using the devm_ variants of those functions doesn't make sense when the resources aren't tied to the device lifetime. As you are tearing them down manually in imx_mu_shutdown anyways, just use the raw variants of those functions. > + if (ret) { > > + dev_err(priv->dev, > > + "Unable to acquire IRQ %d\n", cp->irq); > > + return ret; > > + } > + > > + imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->idx), 0); > + > > + return 0; > +} > + > +static void imx_mu_shutdown(struct mbox_chan *chan) > +{ > > + struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox); > > + struct imx_mu_con_priv *cp = chan->con_priv; > + > > + imx_mu_rmw(priv, IMX_MU_xCR, 0, > > + ???IMX_MU_xCR_TIEn(cp->idx) | IMX_MU_xCR_RIEn(cp->idx)); > + > > + devm_free_irq(priv->dev, cp->irq, chan); > > + devm_kfree(priv->dev, cp->irq_desc); > +} > + > +static const struct mbox_chan_ops imx_mu_ops = { > > + .send_data = imx_mu_send_data, > > + .startup = imx_mu_startup, > > + .shutdown = imx_mu_shutdown, > +}; > + > +static void imx_mu_init_generic(struct imx_mu_priv *priv) > +{ > > + if (priv->side_b) > > + return; > + > > + /* Set default MU configuration */ > > + imx_mu_write(priv, 0, IMX_MU_xCR); > +} > + > +static int imx_mu_probe(struct platform_device *pdev) > +{ > > + struct device *dev = &pdev->dev; > > + struct device_node *np = dev->of_node; > > + struct resource *iomem; > > + struct imx_mu_priv *priv; > > + unsigned int i; > > + int irq, ret; > + > > + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); > > + if (!priv) > > + return -ENOMEM; > + > > + priv->dev = dev; > + > > + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); > > + priv->base = devm_ioremap_resource(&pdev->dev, iomem); > > + if (IS_ERR(priv->base)) > > + return PTR_ERR(priv->base); > + > > + irq = platform_get_irq(pdev, 0); > > + if (irq < 0) > > + return irq; > + > > + priv->clk = devm_clk_get(dev, NULL); > > + if (IS_ERR(priv->clk)) { > > + if (PTR_ERR(priv->clk) != -ENOENT) > > + return PTR_ERR(priv->clk); > + > > + priv->clk = NULL; > > + } > + > > + ret = clk_prepare_enable(priv->clk); > > + if (ret) { > > + dev_err(dev, "Failed to enable clock\n"); > > + return ret; > > + } > + > > + for (i = 0; i < IMX_MU_CHANS; i++) { > > + struct imx_mu_con_priv *cp = &priv->con_priv[i]; > + > > + cp->idx = i; > > + cp->irq = irq; > > + priv->mbox_chans[i].con_priv = cp; > > + } > + > > + if (of_property_read_bool(np, "fsl,mu-side-b")) > + priv->side_b = true; No need for the if clause here. Just assign the return value from of_property_read_bool to priv->side_b. > + > > + priv->mbox.dev = dev; > > + priv->mbox.ops = &imx_mu_ops; > > + priv->mbox.chans = priv->mbox_chans; > > + priv->mbox.num_chans = IMX_MU_CHANS; > > + priv->mbox.txdone_irq = true; > + > > + platform_set_drvdata(pdev, priv); > + > > + imx_mu_init_generic(priv); > + > > + return mbox_controller_register(&priv->mbox); > +} > + > +static int imx_mu_remove(struct platform_device *pdev) > +{ > > + struct imx_mu_priv *priv = platform_get_drvdata(pdev); > + > > + mbox_controller_unregister(&priv->mbox); > > + clk_disable_unprepare(priv->clk); > + > > + return 0; > +} > + > +static const struct of_device_id imx_mu_dt_ids[] = { > > + { .compatible = "fsl,imx6sx-mu" }, > > + { }, > +}; > +MODULE_DEVICE_TABLE(of, imx_mu_dt_ids); > + > +static struct platform_driver imx_mu_driver = { > > > + .probe = imx_mu_probe, > > > + .remove = imx_mu_remove, > > + .driver = { > > > + .name = "imx_mu", > > + .of_match_table = imx_mu_dt_ids, > > + }, > +}; > +module_platform_driver(imx_mu_driver); > + > > +MODULE_AUTHOR("Oleksij Rempel "); > +MODULE_DESCRIPTION("Message Unit driver for i.MX"); > +MODULE_LICENSE("GPL v2"); From mboxrd@z Thu Jan 1 00:00:00 1970 From: Lucas Stach Subject: Re: [PATCH v6 5/5] mailbox: Add support for i.MX7D messaging unit Date: Mon, 23 Jul 2018 19:19:40 +0200 Message-ID: <1532366380.3163.109.camel@pengutronix.de> References: <20180722063923.30222-1-o.rempel@pengutronix.de> <20180722063923.30222-6-o.rempel@pengutronix.de> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <20180722063923.30222-6-o.rempel@pengutronix.de> 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: Oleksij Rempel , Shawn Guo , Fabio Estevam , Rob Herring , Mark Rutland , "A.s. Dong" , Vladimir Zapolskiy Cc: kernel@pengutronix.de, devicetree@vger.kernel.org, dl-linux-imx , linux-arm-kernel@lists.infradead.org List-Id: devicetree@vger.kernel.org QW0gU29ubnRhZywgZGVuIDIyLjA3LjIwMTgsIDA4OjM5ICswMjAwIHNjaHJpZWIgT2xla3NpaiBS ZW1wZWw6Cj4gVGhlIE1haWxib3ggY29udHJvbGxlciBpcyBhYmxlIHRvIHNlbmQgbWVzc2FnZXMg KHVwIHRvIDQgMzIgYml0IHdvcmRzKQo+IGJldHdlZW4gdGhlIGVuZHBvaW50cy4KPiAKPiBUaGlz IGRyaXZlciB3YXMgdGVzdGVkIHVzaW5nIHRoZSBtYWlsYm94LXRlc3QgZHJpdmVyIHNlbmRpbmcg bWVzc2FnZXMKPiBiZXR3ZWVuIHRoZSBDb3J0ZXgtQTcgYW5kIHRoZSBDb3J0ZXgtTTQuCj4gCj4g PiBSZXZpZXdlZC1ieTogRG9uZyBBaXNoZW5nIDxhaXNoZW5nLmRvbmdAbnhwLmNvbT4KPiA+IFNp Z25lZC1vZmYtYnk6IE9sZWtzaWogUmVtcGVsIDxvLnJlbXBlbEBwZW5ndXRyb25peC5kZT4KPiAt LS0KPiDCoGRyaXZlcnMvbWFpbGJveC9LY29uZmlnwqDCoMKgwqDCoMKgwqB8wqDCoMKgNiArCj4g wqBkcml2ZXJzL21haWxib3gvTWFrZWZpbGXCoMKgwqDCoMKgwqB8wqDCoMKgMiArCj4gwqBkcml2 ZXJzL21haWxib3gvaW14LW1haWxib3guYyB8IDI3MyArKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrCj4gwqAzIGZpbGVzIGNoYW5nZWQsIDI4MSBpbnNlcnRpb25zKCspCj4gwqBjcmVh dGUgbW9kZSAxMDA2NDQgZHJpdmVycy9tYWlsYm94L2lteC1tYWlsYm94LmMKPiAKPiBkaWZmIC0t Z2l0IGEvZHJpdmVycy9tYWlsYm94L0tjb25maWcgYi9kcml2ZXJzL21haWxib3gvS2NvbmZpZwo+ IGluZGV4IGEyYmIyNzQ0NmRjZS4uNzkwNjBkZGMzODBkIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMv bWFpbGJveC9LY29uZmlnCj4gKysrIGIvZHJpdmVycy9tYWlsYm94L0tjb25maWcKPiBAQCAtMTUs NiArMTUsMTIgQEAgY29uZmlnIEFSTV9NSFUKPiA+IMKgCcKgwqBUaGUgY29udHJvbGxlciBoYXMg MyBtYWlsYm94IGNoYW5uZWxzLCB0aGUgbGFzdCBvZiB3aGljaCBjYW4gYmUKPiA+IMKgCcKgwqB1 c2VkIGluIFNlY3VyZSBtb2RlIG9ubHkuCj4gwqAKPiArY29uZmlnIElNWF9NQk9YCj4gPiArCXRy aXN0YXRlICJpLk1YIE1haWxib3giCj4gPiArCWRlcGVuZHMgb24gQVJDSF9NWEMgfHwgQ09NUElM RV9URVNUCj4gPiArCWhlbHAKPiA+ICsJwqDCoE1haWxib3ggaW1wbGVtZW50YXRpb24gZm9yIGku TVggTWVzc2FnaW5nIFVuaXQgKE1VKS4KPiArCj4gwqBjb25maWcgUExBVEZPUk1fTUhVCj4gPiDC oAl0cmlzdGF0ZSAiUGxhdGZvcm0gTUhVIE1haWxib3giCj4gPiDCoAlkZXBlbmRzIG9uIE9GCj4g ZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWFpbGJveC9NYWtlZmlsZSBiL2RyaXZlcnMvbWFpbGJveC9N YWtlZmlsZQo+IGluZGV4IGNjMjNjM2E0M2ZjZC4uYmEyZmUxYjZkZDYyIDEwMDY0NAo+IC0tLSBh L2RyaXZlcnMvbWFpbGJveC9NYWtlZmlsZQo+ICsrKyBiL2RyaXZlcnMvbWFpbGJveC9NYWtlZmls ZQo+ID4gQEAgLTcsNiArNyw4IEBAIG9iai0kKENPTkZJR19NQUlMQk9YX1RFU1QpCSs9IG1haWxi b3gtdGVzdC5vCj4gwqAKPiA+IMKgb2JqLSQoQ09ORklHX0FSTV9NSFUpCSs9IGFybV9taHUubwo+ IMKgCj4gPiArb2JqLSQoQ09ORklHX0lNWF9NQk9YKQkrPSBpbXgtbWFpbGJveC5vCj4gKwo+ID4g wqBvYmotJChDT05GSUdfUExBVEZPUk1fTUhVKQkrPSBwbGF0Zm9ybV9taHUubwo+IMKgCj4gPiDC oG9iai0kKENPTkZJR19QTDMyMF9NQk9YKQkrPSBwbDMyMC1pcGMubwo+IGRpZmYgLS1naXQgYS9k cml2ZXJzL21haWxib3gvaW14LW1haWxib3guYyBiL2RyaXZlcnMvbWFpbGJveC9pbXgtbWFpbGJv eC5jCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAwMDAuLjI5Y2YyODc2 ZGIwMQo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL21haWxib3gvaW14LW1haWxib3gu Ywo+IEBAIC0wLDAgKzEsMjczIEBACj4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwt Mi4wCj4gKy8qCj4gKyAqIENvcHlyaWdodCAoYykgMjAxOCBQZW5ndXRyb25peCwgT2xla3NpaiBS ZW1wZWwgPG8ucmVtcGVsQHBlbmd1dHJvbml4LmRlPgo+ICsgKi8KPiArCj4gKyNpbmNsdWRlIDxs aW51eC9jbGsuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2ludGVycnVwdC5oPgo+ICsjaW5jbHVkZSA8 bGludXgvaW8uaD4KPiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgo+ICsjaW5jbHVkZSA8bGlu dXgvbWFpbGJveF9jb250cm9sbGVyLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KPiAr I2luY2x1ZGUgPGxpbnV4L29mX2RldmljZS5oPgo+ICsKPiArLyogVHJhbnNtaXQgUmVnaXN0ZXIg Ki8KPiA+ICsjZGVmaW5lIElNWF9NVV94VFJuKHgpCQkoMHgwMCArIDQgKiAoeCkpCj4gKy8qIFJl Y2VpdmUgUmVnaXN0ZXIgKi8KPiA+ICsjZGVmaW5lIElNWF9NVV94UlJuKHgpCQkoMHgxMCArIDQg KiAoeCkpCj4gKy8qIFN0YXR1cyBSZWdpc3RlciAqLwo+ID4gKyNkZWZpbmUgSU1YX01VX3hTUgkJ MHgyMAo+ID4gKyNkZWZpbmUgSU1YX01VX3hTUl9URW4oeCkJQklUKDIwICsgKDMgLSAoeCkpKQo+ ID4gKyNkZWZpbmUgSU1YX01VX3hTUl9SRm4oeCkJQklUKDI0ICsgKDMgLSAoeCkpKQo+ID4gKyNk ZWZpbmUgSU1YX01VX3hTUl9CUkRJUAlCSVQoOSkKPiArCj4gKy8qIENvbnRyb2wgUmVnaXN0ZXIg Ki8KPiA+ICsjZGVmaW5lIElNWF9NVV94Q1IJCTB4MjQKPiArLyogVHJhbnNtaXQgSW50ZXJydXB0 IEVuYWJsZSAqLwo+ID4gKyNkZWZpbmUgSU1YX01VX3hDUl9USUVuKHgpCUJJVCgyMCArICgzIC0g KHgpKSkKPiArLyogUmVjZWl2ZSBJbnRlcnJ1cHQgRW5hYmxlICovCj4gPiArI2RlZmluZSBJTVhf TVVfeENSX1JJRW4oeCkJQklUKDI0ICsgKDMgLSAoeCkpKQo+ICsKPiA+ICsjZGVmaW5lIElNWF9N VV9DSEFOUwk0dQo+ICsKPiArc3RydWN0IGlteF9tdV9jb25fcHJpdiB7Cj4gPiA+ICsJaW50CQkJ aXJxOwo+ID4gPiArCXVuc2lnbmVkIGludAkJaWR4Owo+ID4gPiArCWNoYXIJCQkqaXJxX2Rlc2M7 Cj4gK307Cj4gKwo+ICtzdHJ1Y3QgaW14X211X3ByaXYgewo+ID4gPiArCXN0cnVjdCBkZXZpY2UJ CSpkZXY7Cj4gPiA+ICsJdm9pZCBfX2lvbWVtCQkqYmFzZTsKPiArCj4gPiA+ICsJc3RydWN0IG1i b3hfY29udHJvbGxlcgltYm94Owo+ID4gPiArCXN0cnVjdCBtYm94X2NoYW4JbWJveF9jaGFuc1tJ TVhfTVVfQ0hBTlNdOwo+ICsKPiA+ICsJc3RydWN0IGlteF9tdV9jb25fcHJpdsKgwqBjb25fcHJp dltJTVhfTVVfQ0hBTlNdOwo+ID4gPiArCXN0cnVjdCBjbGsJCSpjbGs7Cj4gKwo+ID4gPiArCWJv b2wJCQlzaWRlX2I7Cj4gK307Cj4gKwo+ICtzdGF0aWMgc3RydWN0IGlteF9tdV9wcml2ICp0b19p bXhfbXVfcHJpdihzdHJ1Y3QgbWJveF9jb250cm9sbGVyICptYm94KQo+ICt7Cj4gPiArCXJldHVy biBjb250YWluZXJfb2YobWJveCwgc3RydWN0IGlteF9tdV9wcml2LCBtYm94KTsKPiArfQo+ICsK PiArc3RhdGljIHZvaWQgaW14X211X3dyaXRlKHN0cnVjdCBpbXhfbXVfcHJpdiAqcHJpdiwgdTMy IHZhbCwgdTMyIG9mZnMpCj4gK3sKPiArCWlvd3JpdGUzMih2YWwsIHByaXYtPmJhc2UgKyBvZmZz KTsKClRoaXMgZHJpdmVyIGlzIG5ldmVyIGdvaW5nIHRvIGJlIHVzZWQgb24gYSBkZXZpY2Ugd2l0 aCBwb3J0IGJhc2VkIElPLApzbyBpb3dyaXRlIGRvZXNuJ3QgbWFrZSBtdWNoIHNlbnNlIGhlcmUs IGp1c3QgdXNlIHdyaXRlbC4gU2FtZSBjb21tZW50CmFwcGxpZXMgdG8gdGhlIGJlbG93IHJlYWQg ZnVuY3Rpb24uCgpBbHNvLCBnaXZlbiB0aGF0IHRob3NlIGZ1bmN0aW9ucyBhcmUgbm90IHJlYWxs eSBzaG9ydGVuaW5nIHRoZSBjb2RlIGluCnRoZSB1c2VyIHRoZXkgbWF5IGFsc28gYmUgcmVtb3Zl ZCBjb21wbGV0ZWx5IElNSE8uCiAgCj4gK30KPiArCj4gK3N0YXRpYyB1MzIgaW14X211X3JlYWQo c3RydWN0IGlteF9tdV9wcml2ICpwcml2LCB1MzIgb2ZmcykKPiArewo+ID4gKwlyZXR1cm4gaW9y ZWFkMzIocHJpdi0+YmFzZSArIG9mZnMpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdTMyIGlteF9tdV9y bXcoc3RydWN0IGlteF9tdV9wcml2ICpwcml2LCB1MzIgb2ZmcywgdTMyIHNldCwgdTMyIGNscikK PiArewo+ID4gKwl1MzIgdmFsOwo+ICsKPiA+ICsJdmFsID0gaW14X211X3JlYWQocHJpdiwgb2Zm cyk7Cj4gPiArCXZhbCAmPSB+Y2xyOwo+ID4gKwl2YWwgfD0gc2V0Owo+ID4gKwlpbXhfbXVfd3Jp dGUocHJpdiwgdmFsLCBvZmZzKTsKPiArCj4gPiArCXJldHVybiB2YWw7Cj4gK30KPiArCj4gK3N0 YXRpYyBpcnFyZXR1cm5fdCBpbXhfbXVfaXNyKGludCBpcnEsIHZvaWQgKnApCj4gK3sKPiA+ICsJ c3RydWN0IG1ib3hfY2hhbiAqY2hhbiA9IHA7Cj4gPiArCXN0cnVjdCBpbXhfbXVfcHJpdiAqcHJp diA9IHRvX2lteF9tdV9wcml2KGNoYW4tPm1ib3gpOwo+ID4gKwlzdHJ1Y3QgaW14X211X2Nvbl9w cml2ICpjcCA9IGNoYW4tPmNvbl9wcml2Owo+ID4gKwl1MzIgdmFsLCBjdHJsLCBkYXQ7Cj4gKwo+ ID4gKwljdHJsID0gaW14X211X3JlYWQocHJpdiwgSU1YX01VX3hDUik7Cj4gPiArCXZhbCA9IGlt eF9tdV9yZWFkKHByaXYsIElNWF9NVV94U1IpOwo+ID4gKwl2YWwgJj0gSU1YX01VX3hTUl9URW4o Y3AtPmlkeCkgfCBJTVhfTVVfeFNSX1JGbihjcC0+aWR4KTsKPiA+ICsJdmFsICY9IGN0cmwgJiAo SU1YX01VX3hDUl9USUVuKGNwLT5pZHgpIHwgSU1YX01VX3hDUl9SSUVuKGNwLT5pZHgpKTsKPiA+ ICsJaWYgKCF2YWwpCj4gPiArCQlyZXR1cm4gSVJRX05PTkU7Cj4gKwo+ID4gKwlpZiAodmFsICYg SU1YX01VX3hTUl9URW4oY3AtPmlkeCkpIHsKPiA+ICsJCWlteF9tdV9ybXcocHJpdiwgSU1YX01V X3hDUiwgMCwgSU1YX01VX3hDUl9USUVuKGNwLT5pZHgpKTsKPiA+ICsJCW1ib3hfY2hhbl90eGRv bmUoY2hhbiwgMCk7Cj4gPiArCX0KPiArCj4gPiArCWlmICh2YWwgJiBJTVhfTVVfeFNSX1JGbihj cC0+aWR4KSkgewo+ID4gKwkJZGF0ID0gaW14X211X3JlYWQocHJpdiwgSU1YX01VX3hSUm4oY3At PmlkeCkpOwo+ID4gKwkJbWJveF9jaGFuX3JlY2VpdmVkX2RhdGEoY2hhbiwgKHZvaWQgKikmZGF0 KTsKPiA+ICsJfQo+ICsKPiA+ICsJcmV0dXJuIElSUV9IQU5ETEVEOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgYm9vbCBpbXhfbXVfbGFzdF90eF9kb25lKHN0cnVjdCBtYm94X2NoYW4gKmNoYW4pCj4gK3sK PiA+ICsJc3RydWN0IGlteF9tdV9wcml2ICpwcml2ID0gdG9faW14X211X3ByaXYoY2hhbi0+bWJv eCk7Cj4gPiArCXN0cnVjdCBpbXhfbXVfY29uX3ByaXYgKmNwID0gY2hhbi0+Y29uX3ByaXY7Cj4g PiArCXUzMiB2YWw7Cj4gKwo+ID4gKwl2YWwgPSBpbXhfbXVfcmVhZChwcml2LCBJTVhfTVVfeFNS KTsKPiA+ICsJLyogdGVzdCBpZiB0cmFuc21pdCByZWdpc3RlciBpcyBlbXB0eSAqLwo+ICsJcmV0 dXJuIHZhbCAmIElNWF9NVV94U1JfVEVuKGNwLT5pZHgpOwoKSSBndWVzcwoicmV0dXJuIGlteF9t dV9yZWFkKHByaXYsIElNWF9NVV94U1IpICYgSU1YX01VX3hTUl9URW4oY3AtPmlkeCk7IiBpcwpz aG9ydGVyIGFuZCBlcXVhbGx5IHdlbGwgdW5kZXJzdG9vZC4KCj4gK30KPiArCj4gK3N0YXRpYyBp bnQgaW14X211X3NlbmRfZGF0YShzdHJ1Y3QgbWJveF9jaGFuICpjaGFuLCB2b2lkICpkYXRhKQo+ ICt7Cj4gPiArCXN0cnVjdCBpbXhfbXVfcHJpdiAqcHJpdiA9IHRvX2lteF9tdV9wcml2KGNoYW4t Pm1ib3gpOwo+ID4gKwlzdHJ1Y3QgaW14X211X2Nvbl9wcml2ICpjcCA9IGNoYW4tPmNvbl9wcml2 Owo+ID4gKwl1MzIgKmFyZyA9IGRhdGE7Cj4gKwo+ID4gKwlpZiAoIWlteF9tdV9sYXN0X3R4X2Rv bmUoY2hhbikpCj4gPiArCQlyZXR1cm4gLUVCVVNZOwo+ICsKPiA+ICsJaW14X211X3dyaXRlKHBy aXYsICphcmcsIElNWF9NVV94VFJuKGNwLT5pZHgpKTsKPiArCWlteF9tdV9ybXcocHJpdiwgSU1Y X01VX3hDUiwgSU1YX01VX3hTUl9URW4oY3AtPmlkeCksIDApOwoKSW4gbXVsdGktY2hhbm5lbCBt b2RlIHRoaXMgUk1XIGN5Y2xlIG5lZWRzIHNvbWUga2luZCBvZiBsb2NraW5nLiBBcwp0aGlzIHJl Z2lzdGVyIGlzIGFsc28gY2hhbmdlZCBmcm9tIHRoZSBpcnEgaGFuZGxlciwgdGhpcyBwcm9iYWJs eSBuZWVkcwp0byBiZSBhIGlycXNhdmUgc3BpbmxvY2suCgo+ICsKPiA+ICsJcmV0dXJuIDA7Cj4g K30KPiArCj4gK3N0YXRpYyBpbnQgaW14X211X3N0YXJ0dXAoc3RydWN0IG1ib3hfY2hhbiAqY2hh bikKPiArewo+ID4gKwlzdHJ1Y3QgaW14X211X3ByaXYgKnByaXYgPSB0b19pbXhfbXVfcHJpdihj aGFuLT5tYm94KTsKPiA+ICsJc3RydWN0IGlteF9tdV9jb25fcHJpdiAqY3AgPSBjaGFuLT5jb25f cHJpdjsKPiA+ICsJaW50IHJldDsKPiArCj4gPiArCWNwLT5pcnFfZGVzYyA9IGRldm1fa2FzcHJp bnRmKHByaXYtPmRldiwgR0ZQX0tFUk5FTCwgImlteF9tdV9jaGFuWyVpXSIsCj4gPiArCQkJCcKg wqDCoMKgwqDCoGNwLT5pZHgpOwo+ID4gKwlpZiAoIWNwLT5pcnFfZGVzYykKPiA+ICsJCXJldHVy biAtRU5PTUVNOwo+ICsKPiA+ICsJcmV0ID0gZGV2bV9yZXF1ZXN0X2lycShwcml2LT5kZXYsIGNw LT5pcnEsIGlteF9tdV9pc3IsCj4gKwkJCcKgwqDCoMKgwqDCoMKgSVJRRl9TSEFSRUQsIGNwLT5p cnFfZGVzYywgY2hhbik7CgpVc2luZyB0aGUgZGV2bV8gdmFyaWFudHMgb2YgdGhvc2UgZnVuY3Rp b25zIGRvZXNuJ3QgbWFrZSBzZW5zZSB3aGVuIHRoZQpyZXNvdXJjZXMgYXJlbid0IHRpZWQgdG8g dGhlIGRldmljZSBsaWZldGltZS4gQXMgeW91IGFyZSB0ZWFyaW5nIHRoZW0KZG93biBtYW51YWxs eSBpbiBpbXhfbXVfc2h1dGRvd24gYW55d2F5cywganVzdCB1c2UgdGhlIHJhdyB2YXJpYW50cyBv Zgp0aG9zZSBmdW5jdGlvbnMuCgo+ICsJaWYgKHJldCkgewo+ID4gKwkJZGV2X2Vycihwcml2LT5k ZXYsCj4gPiArCQkJIlVuYWJsZSB0byBhY3F1aXJlIElSUSAlZFxuIiwgY3AtPmlycSk7Cj4gPiAr CQlyZXR1cm4gcmV0Owo+ID4gKwl9Cj4gKwo+ID4gKwlpbXhfbXVfcm13KHByaXYsIElNWF9NVV94 Q1IsIElNWF9NVV94Q1JfUklFbihjcC0+aWR4KSwgMCk7Cj4gKwo+ID4gKwlyZXR1cm4gMDsKPiAr fQo+ICsKPiArc3RhdGljIHZvaWQgaW14X211X3NodXRkb3duKHN0cnVjdCBtYm94X2NoYW4gKmNo YW4pCj4gK3sKPiA+ICsJc3RydWN0IGlteF9tdV9wcml2ICpwcml2ID0gdG9faW14X211X3ByaXYo Y2hhbi0+bWJveCk7Cj4gPiArCXN0cnVjdCBpbXhfbXVfY29uX3ByaXYgKmNwID0gY2hhbi0+Y29u X3ByaXY7Cj4gKwo+ID4gKwlpbXhfbXVfcm13KHByaXYsIElNWF9NVV94Q1IsIDAsCj4gPiArCQnC oMKgwqBJTVhfTVVfeENSX1RJRW4oY3AtPmlkeCkgfCBJTVhfTVVfeENSX1JJRW4oY3AtPmlkeCkp Owo+ICsKPiA+ICsJZGV2bV9mcmVlX2lycShwcml2LT5kZXYsIGNwLT5pcnEsIGNoYW4pOwo+ID4g KwlkZXZtX2tmcmVlKHByaXYtPmRldiwgY3AtPmlycV9kZXNjKTsKPiArfQo+ICsKPiArc3RhdGlj IGNvbnN0IHN0cnVjdCBtYm94X2NoYW5fb3BzIGlteF9tdV9vcHMgPSB7Cj4gPiArCS5zZW5kX2Rh dGEgPSBpbXhfbXVfc2VuZF9kYXRhLAo+ID4gKwkuc3RhcnR1cCA9IGlteF9tdV9zdGFydHVwLAo+ ID4gKwkuc2h1dGRvd24gPSBpbXhfbXVfc2h1dGRvd24sCj4gK307Cj4gKwo+ICtzdGF0aWMgdm9p ZCBpbXhfbXVfaW5pdF9nZW5lcmljKHN0cnVjdCBpbXhfbXVfcHJpdiAqcHJpdikKPiArewo+ID4g KwlpZiAocHJpdi0+c2lkZV9iKQo+ID4gKwkJcmV0dXJuOwo+ICsKPiA+ICsJLyogU2V0IGRlZmF1 bHQgTVUgY29uZmlndXJhdGlvbiAqLwo+ID4gKwlpbXhfbXVfd3JpdGUocHJpdiwgMCwgSU1YX01V X3hDUik7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgaW14X211X3Byb2JlKHN0cnVjdCBwbGF0Zm9y bV9kZXZpY2UgKnBkZXYpCj4gK3sKPiA+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRl djsKPiA+ICsJc3RydWN0IGRldmljZV9ub2RlICpucCA9IGRldi0+b2Zfbm9kZTsKPiA+ICsJc3Ry dWN0IHJlc291cmNlICppb21lbTsKPiA+ICsJc3RydWN0IGlteF9tdV9wcml2ICpwcml2Owo+ID4g Kwl1bnNpZ25lZCBpbnQgaTsKPiA+ICsJaW50IGlycSwgcmV0Owo+ICsKPiA+ICsJcHJpdiA9IGRl dm1fa3phbGxvYyhkZXYsIHNpemVvZigqcHJpdiksIEdGUF9LRVJORUwpOwo+ID4gKwlpZiAoIXBy aXYpCj4gPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gPiArCXByaXYtPmRldiA9IGRldjsKPiAr Cj4gPiArCWlvbWVtID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlKHBkZXYsIElPUkVTT1VSQ0VfTUVN LCAwKTsKPiA+ICsJcHJpdi0+YmFzZSA9IGRldm1faW9yZW1hcF9yZXNvdXJjZSgmcGRldi0+ZGV2 LCBpb21lbSk7Cj4gPiArCWlmIChJU19FUlIocHJpdi0+YmFzZSkpCj4gPiArCQlyZXR1cm4gUFRS X0VSUihwcml2LT5iYXNlKTsKPiArCj4gPiArCWlycSA9IHBsYXRmb3JtX2dldF9pcnEocGRldiwg MCk7Cj4gPiArCWlmIChpcnEgPCAwKQo+ID4gKwkJcmV0dXJuIGlycTsKPiArCj4gPiArCXByaXYt PmNsayA9IGRldm1fY2xrX2dldChkZXYsIE5VTEwpOwo+ID4gKwlpZiAoSVNfRVJSKHByaXYtPmNs aykpIHsKPiA+ICsJCWlmIChQVFJfRVJSKHByaXYtPmNsaykgIT0gLUVOT0VOVCkKPiA+ICsJCQly ZXR1cm4gUFRSX0VSUihwcml2LT5jbGspOwo+ICsKPiA+ICsJCXByaXYtPmNsayA9IE5VTEw7Cj4g PiArCX0KPiArCj4gPiArCXJldCA9IGNsa19wcmVwYXJlX2VuYWJsZShwcml2LT5jbGspOwo+ID4g KwlpZiAocmV0KSB7Cj4gPiArCQlkZXZfZXJyKGRldiwgIkZhaWxlZCB0byBlbmFibGUgY2xvY2tc biIpOwo+ID4gKwkJcmV0dXJuIHJldDsKPiA+ICsJfQo+ICsKPiA+ICsJZm9yIChpID0gMDsgaSA8 IElNWF9NVV9DSEFOUzsgaSsrKSB7Cj4gPiArCQlzdHJ1Y3QgaW14X211X2Nvbl9wcml2ICpjcCA9 ICZwcml2LT5jb25fcHJpdltpXTsKPiArCj4gPiArCQljcC0+aWR4ID0gaTsKPiA+ICsJCWNwLT5p cnEgPSBpcnE7Cj4gPiArCQlwcml2LT5tYm94X2NoYW5zW2ldLmNvbl9wcml2ID0gY3A7Cj4gPiAr CX0KPiArCj4gPiArCWlmIChvZl9wcm9wZXJ0eV9yZWFkX2Jvb2wobnAsICJmc2wsbXUtc2lkZS1i IikpCj4gKwkJcHJpdi0+c2lkZV9iID0gdHJ1ZTsKCk5vIG5lZWQgZm9yIHRoZSBpZiBjbGF1c2Ug aGVyZS4gSnVzdCBhc3NpZ24gdGhlIHJldHVybiB2YWx1ZSBmcm9tCm9mX3Byb3BlcnR5X3JlYWRf Ym9vbCB0byBwcml2LT5zaWRlX2IuCgo+ICsKPiA+ICsJcHJpdi0+bWJveC5kZXYgPSBkZXY7Cj4g PiArCXByaXYtPm1ib3gub3BzID0gJmlteF9tdV9vcHM7Cj4gPiArCXByaXYtPm1ib3guY2hhbnMg PSBwcml2LT5tYm94X2NoYW5zOwo+ID4gKwlwcml2LT5tYm94Lm51bV9jaGFucyA9IElNWF9NVV9D SEFOUzsKPiA+ICsJcHJpdi0+bWJveC50eGRvbmVfaXJxID0gdHJ1ZTsKPiArCj4gPiArCXBsYXRm b3JtX3NldF9kcnZkYXRhKHBkZXYsIHByaXYpOwo+ICsKPiA+ICsJaW14X211X2luaXRfZ2VuZXJp Yyhwcml2KTsKPiArCj4gPiArCXJldHVybiBtYm94X2NvbnRyb2xsZXJfcmVnaXN0ZXIoJnByaXYt Pm1ib3gpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IGlteF9tdV9yZW1vdmUoc3RydWN0IHBsYXRm b3JtX2RldmljZSAqcGRldikKPiArewo+ID4gKwlzdHJ1Y3QgaW14X211X3ByaXYgKnByaXYgPSBw bGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKPiArCj4gPiArCW1ib3hfY29udHJvbGxlcl91bnJl Z2lzdGVyKCZwcml2LT5tYm94KTsKPiA+ICsJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKHByaXYtPmNs ayk7Cj4gKwo+ID4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBv Zl9kZXZpY2VfaWQgaW14X211X2R0X2lkc1tdID0gewo+ID4gKwl7IC5jb21wYXRpYmxlID0gImZz bCxpbXg2c3gtbXUiIH0sCj4gPiArCXsgfSwKPiArfTsKPiArTU9EVUxFX0RFVklDRV9UQUJMRShv ZiwgaW14X211X2R0X2lkcyk7Cj4gKwo+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBp bXhfbXVfZHJpdmVyID0gewo+ID4gPiArCS5wcm9iZQkJPSBpbXhfbXVfcHJvYmUsCj4gPiA+ICsJ LnJlbW92ZQkJPSBpbXhfbXVfcmVtb3ZlLAo+ID4gKwkuZHJpdmVyID0gewo+ID4gPiArCQkubmFt ZQk9ICJpbXhfbXUiLAo+ID4gKwkJLm9mX21hdGNoX3RhYmxlID0gaW14X211X2R0X2lkcywKPiA+ ICsJfSwKPiArfTsKPiArbW9kdWxlX3BsYXRmb3JtX2RyaXZlcihpbXhfbXVfZHJpdmVyKTsKPiAr Cj4gPiArTU9EVUxFX0FVVEhPUigiT2xla3NpaiBSZW1wZWwgPG8ucmVtcGVsQHBlbmd1dHJvbml4 LmRlPiIpOwo+ICtNT0RVTEVfREVTQ1JJUFRJT04oIk1lc3NhZ2UgVW5pdCBkcml2ZXIgZm9yIGku TVgiKTsKPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCB2MiIpOwoKX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX18KbGludXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QK bGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRl YWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtlcm5lbAo=