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 B09D3C433EF for ; Mon, 31 Jan 2022 09:29:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237275AbiAaJ3j (ORCPT ); Mon, 31 Jan 2022 04:29:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50466 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231160AbiAaJ3j (ORCPT ); Mon, 31 Jan 2022 04:29:39 -0500 Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BB5DDC06173D for ; Mon, 31 Jan 2022 01:29:38 -0800 (PST) Received: by mail-wm1-x32f.google.com with SMTP id v123so9730068wme.2 for ; Mon, 31 Jan 2022 01:29:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=+K6CVITrnsRUky+BLWhSxF5egzLJ88cWLKIMCc6XEbQ=; b=loqmf1qlcbSW+eis/GTE7x15gBHA728qXoxkIgL8gUHEnvZSJ9td6+gyLUdgEXlAbb Dq1OPDsv78flVFaRHc6xEORePa+qtlfom/UPARjImwMHnnku2qwK31AaFZ42BrRe2VOW BmgqOhNd+hpoqeRH7I0OEToNl5H3HDsjMePYwvCU6SB3RNFAEFrWL6UlnouS70Ikd9zu V+5W4wkck2O0VZqUNVLDmswtoYLO12vOkO/KsAPYWgdg8w+V8fDrjeaROS781CXg9K1E yxHt0GOJVeVBGaFKHQe2B9+YLV21veluJdNG283Or2kb1JDlvmJ+zQ/SK8LA3SSZZ1MU KUaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=+K6CVITrnsRUky+BLWhSxF5egzLJ88cWLKIMCc6XEbQ=; b=yY2aDw6jxPx0sECxgsDNWtHHnBVoNMIvMU5zwAn3o9tVyZbwXOf6zlkEy2bFVdkLFj QFX9ETERDKo0eljRQt8H9IRR+70fMxvKalMynajMDrIfntb/EO6wglbjH7RxUtvHtPLH cn3jjL6ckMhMrGoiMxgz8bTyNDQj9MKo3blaybpPMZ3TOhj6WkRxD/VLHtHMI4Oh0304 fDN7C7X8URvIItJC4CA/iHNWIwJtTdhttbvP+MPE9pbKUjv8NUQsGY40wnxcghzWYKsY +bndha8ZLiZgs2jvXi6rQNSfxEj5C5V8ZfjlARFrrJFj/EzpdmgTrdeIffCbl4MReoty 5TcQ== X-Gm-Message-State: AOAM53092CaqTxK0BfDaoaLpu+uSFgyeS62ze2Knl19vdzAzMwm0h6y3 ydA6SbuJUfPt+NHVM/Vj5uxung== X-Google-Smtp-Source: ABdhPJyEsZVSsVBdRUL6qYAq3IIxILI7cX6VjnOLwoIO4iTz4HDgV0oyZ60c2oxQoYjiDUEXhLLgcA== X-Received: by 2002:a05:600c:3641:: with SMTP id y1mr17274997wmq.53.1643621376995; Mon, 31 Jan 2022 01:29:36 -0800 (PST) Received: from google.com (cpc106310-bagu17-2-0-cust853.1-3.cable.virginm.net. [86.15.223.86]) by smtp.gmail.com with ESMTPSA id s17sm11188184wrm.62.2022.01.31.01.29.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 31 Jan 2022 01:29:36 -0800 (PST) Date: Mon, 31 Jan 2022 09:29:34 +0000 From: Lee Jones To: Colin Foster Cc: linux-arm-kernel@lists.infradead.org, linux-gpio@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Steen Hegelund , Lars Povlsen , Linus Walleij , Russell King , Heiner Kallweit , Jakub Kicinski , "David S. Miller" , Florian Fainelli , Vivien Didelot , Andrew Lunn , UNGLinuxDriver@microchip.com, Alexandre Belloni , Claudiu Manoil , Vladimir Oltean , katie.morris@in-advantage.com Subject: Re: [RFC v6 net-next 6/9] mfd: ocelot: add support for external mfd control over SPI for the VSC7512 Message-ID: References: <20220129220221.2823127-1-colin.foster@in-advantage.com> <20220129220221.2823127-7-colin.foster@in-advantage.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20220129220221.2823127-7-colin.foster@in-advantage.com> Precedence: bulk List-ID: X-Mailing-List: linux-gpio@vger.kernel.org On Sat, 29 Jan 2022, Colin Foster wrote: > Create a single SPI MFD ocelot device that manages the SPI bus on the > external chip and can handle requests for regmaps. This should allow any > ocelot driver (pinctrl, miim, etc.) to be used externally, provided they > utilize regmaps. > > Signed-off-by: Colin Foster > --- > drivers/mfd/Kconfig | 19 ++ > drivers/mfd/Makefile | 3 + > drivers/mfd/ocelot-core.c | 165 +++++++++++ > drivers/mfd/ocelot-spi.c | 325 ++++++++++++++++++++++ > drivers/mfd/ocelot.h | 36 +++ > drivers/net/mdio/mdio-mscc-miim.c | 21 +- > drivers/pinctrl/pinctrl-microchip-sgpio.c | 22 +- > drivers/pinctrl/pinctrl-ocelot.c | 29 +- > include/soc/mscc/ocelot.h | 11 + Please avoid mixing subsystems in patches if at all avoidable. If there are not build time dependencies/breakages, I'd suggest firstly applying support for this into MFD *then* utilising that support in subsequent patches. > 9 files changed, 614 insertions(+), 17 deletions(-) > create mode 100644 drivers/mfd/ocelot-core.c > create mode 100644 drivers/mfd/ocelot-spi.c > create mode 100644 drivers/mfd/ocelot.h > > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig > index ba0b3eb131f1..57bbf2d11324 100644 > --- a/drivers/mfd/Kconfig > +++ b/drivers/mfd/Kconfig > @@ -948,6 +948,25 @@ config MFD_MENF21BMC > This driver can also be built as a module. If so the module > will be called menf21bmc. > > +config MFD_OCELOT > + tristate "Microsemi Ocelot External Control Support" Please explain exactly what an ECS is in the help below. > + select MFD_CORE > + help > + Say yes here to add support for Ocelot chips (VSC7511, VSC7512, > + VSC7513, VSC7514) controlled externally. > + > + All four of these chips can be controlled internally (MMIO) or > + externally via SPI, I2C, PCIe. This enables control of these chips > + over one or more of these buses. > + > +config MFD_OCELOT_SPI > + tristate "Microsemi Ocelot SPI interface" > + depends on MFD_OCELOT > + depends on SPI_MASTER > + select REGMAP_SPI > + help > + Say yes here to add control to the MFD_OCELOT chips via SPI. > + > config EZX_PCAP > bool "Motorola EZXPCAP Support" > depends on SPI_MASTER > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile > index df1ecc4a4c95..12513843067a 100644 > --- a/drivers/mfd/Makefile > +++ b/drivers/mfd/Makefile > @@ -120,6 +120,9 @@ obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o > > obj-$(CONFIG_MFD_CORE) += mfd-core.o > > +obj-$(CONFIG_MFD_OCELOT) += ocelot-core.o > +obj-$(CONFIG_MFD_OCELOT_SPI) += ocelot-spi.o > + These do not look lined-up with the remainder of the file. > obj-$(CONFIG_EZX_PCAP) += ezx-pcap.o > obj-$(CONFIG_MFD_CPCAP) += motorola-cpcap.o > > diff --git a/drivers/mfd/ocelot-core.c b/drivers/mfd/ocelot-core.c > new file mode 100644 > index 000000000000..590489481b8c > --- /dev/null > +++ b/drivers/mfd/ocelot-core.c > @@ -0,0 +1,165 @@ > +// SPDX-License-Identifier: (GPL-2.0 OR MIT) > +/* > + * MFD core driver for the Ocelot chip family. > + * > + * The VSC7511, 7512, 7513, and 7514 can be controlled internally via an > + * on-chip MIPS processor, or externally via SPI, I2C, PCIe. This core driver is > + * intended to be the bus-agnostic glue between, for example, the SPI bus and > + * the MFD children. > + * > + * Copyright 2021 Innovative Advantage Inc. > + * > + * Author: Colin Foster > + */ > + > +#include > +#include > +#include > + > +#include > + > +#include "ocelot.h" > + > +#define GCB_SOFT_RST (0x0008) Why the brackets? > +#define SOFT_CHIP_RST (0x1) As above. > +static const struct resource vsc7512_gcb_resource = { > + .start = 0x71070000, > + .end = 0x7107022b, Please define these somewhere. > + .name = "devcpu_gcb", > +}; There is a macro you can use for these. Grep for "DEFINE_RES_" > +static int ocelot_reset(struct ocelot_core *core) > +{ > + int ret; > + > + /* > + * Reset the entire chip here to put it into a completely known state. > + * Other drivers may want to reset their own subsystems. The register > + * self-clears, so one write is all that is needed > + */ > + ret = regmap_write(core->gcb_regmap, GCB_SOFT_RST, SOFT_CHIP_RST); > + if (ret) > + return ret; > + > + msleep(100); > + > + /* > + * A chip reset will clear the SPI configuration, so it needs to be done > + * again before we can access any more registers > + */ > + ret = ocelot_spi_initialize(core); > + > + return ret; > +} > + > +static struct regmap *ocelot_devm_regmap_init(struct ocelot_core *core, > + struct device *dev, > + const struct resource *res) > +{ > + struct regmap *regmap; > + > + regmap = dev_get_regmap(dev, res->name); > + if (!regmap) > + regmap = ocelot_spi_devm_get_regmap(core, dev, res); Why are you making SPI specific calls from the Core driver? > + return regmap; > +} > + > +struct regmap *ocelot_get_regmap_from_resource(struct device *dev, > + const struct resource *res) > +{ > + struct ocelot_core *core = dev_get_drvdata(dev); > + > + return ocelot_devm_regmap_init(core, dev, res); > +} > +EXPORT_SYMBOL(ocelot_get_regmap_from_resource); Why don't you always call ocelot_devm_regmap_init() with the 'core' parameter dropped and just do dev_get_drvdata() inside of there? You're passing 'dev' anyway. > +static const struct resource vsc7512_miim1_resources[] = { > + { > + .start = 0x710700c0, > + .end = 0x710700e3, > + .name = "gcb_miim1", > + .flags = IORESOURCE_MEM, > + }, > +}; > + > +static const struct resource vsc7512_pinctrl_resources[] = { > + { > + .start = 0x71070034, > + .end = 0x7107009f, > + .name = "gcb_gpio", > + .flags = IORESOURCE_MEM, > + }, > +}; > + > +static const struct resource vsc7512_sgpio_resources[] = { > + { > + .start = 0x710700f8, > + .end = 0x710701f7, > + .name = "gcb_sio", > + .flags = IORESOURCE_MEM, > + }, > +}; > + > +static const struct mfd_cell vsc7512_devs[] = { > + { > + .name = "pinctrl-ocelot", - "ocelot-pinctrl" > + .of_compatible = "mscc,ocelot-pinctrl", > + .num_resources = ARRAY_SIZE(vsc7512_pinctrl_resources), > + .resources = vsc7512_pinctrl_resources, > + }, > + { Same line please. > + .name = "pinctrl-sgpio", "ocelot-sgpio" > + .of_compatible = "mscc,ocelot-sgpio", > + .num_resources = ARRAY_SIZE(vsc7512_sgpio_resources), > + .resources = vsc7512_sgpio_resources, > + }, > + { > + .name = "ocelot-miim1", > + .of_compatible = "mscc,ocelot-miim", > + .num_resources = ARRAY_SIZE(vsc7512_miim1_resources), > + .resources = vsc7512_miim1_resources, > + }, > +}; > + > +int ocelot_core_init(struct ocelot_core *core) > +{ > + struct device *dev = core->dev; > + int ret; > + > + dev_set_drvdata(dev, core); > + > + core->gcb_regmap = ocelot_devm_regmap_init(core, dev, > + &vsc7512_gcb_resource); > + if (!core->gcb_regmap) And if an error is returned? > + return -ENOMEM; > + > + /* Prepare the chip */ Does it prepare or reset the chip? If the former, then the following call is misnamed. if the latter, then there is no need for this comment. > + ret = ocelot_reset(core); > + if (ret) { > + dev_err(dev, "ocelot mfd reset failed with code %d\n", ret); Isn't the device called 'ocelot'? If so, you just repeated yourself. "Failed to reset device: %d\n" > + return ret; > + } > + > + ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, vsc7512_devs, Why NONE? > + ARRAY_SIZE(vsc7512_devs), NULL, 0, NULL); > + if (ret) { > + dev_err(dev, "error adding mfd devices\n"); "Failed to add sub-devices" > + return ret; > + } > + > + return 0; > +} > +EXPORT_SYMBOL(ocelot_core_init); > + > +int ocelot_remove(struct ocelot_core *core) > +{ > + return 0; > +} > +EXPORT_SYMBOL(ocelot_remove); What's the propose of this? > +MODULE_DESCRIPTION("Ocelot Chip MFD driver"); No such thing as an MFD driver. > +MODULE_AUTHOR("Colin Foster "); > +MODULE_LICENSE("GPL v2"); > diff --git a/drivers/mfd/ocelot-spi.c b/drivers/mfd/ocelot-spi.c > new file mode 100644 > index 000000000000..1e268a4dfa17 > --- /dev/null > +++ b/drivers/mfd/ocelot-spi.c > @@ -0,0 +1,325 @@ > +// SPDX-License-Identifier: (GPL-2.0 OR MIT) > +/* > + * SPI core driver for the Ocelot chip family. > + * > + * This driver will handle everything necessary to allow for communication over > + * SPI to the VSC7511, VSC7512, VSC7513 and VSC7514 chips. The main functions > + * are to prepare the chip's SPI interface for a specific bus speed, and a host > + * processor's endianness. This will create and distribute regmaps for any MFD > + * children. > + * > + * Copyright 2021 Innovative Advantage Inc. > + * > + * Author: Colin Foster > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#include "ocelot.h" > + > +struct ocelot_spi { > + int spi_padding_bytes; > + struct spi_device *spi; > + struct ocelot_core core; > + struct regmap *cpuorg_regmap; > +}; > + > +#define DEV_CPUORG_IF_CTRL (0x0000) > +#define DEV_CPUORG_IF_CFGSTAT (0x0004) > + > +static const struct resource vsc7512_dev_cpuorg_resource = { > + .start = 0x71000000, > + .end = 0x710002ff, > + .name = "devcpu_org", > +}; > + > +#define VSC7512_BYTE_ORDER_LE 0x00000000 > +#define VSC7512_BYTE_ORDER_BE 0x81818181 > +#define VSC7512_BIT_ORDER_MSB 0x00000000 > +#define VSC7512_BIT_ORDER_LSB 0x42424242 > + > +static struct ocelot_spi *core_to_ocelot_spi(struct ocelot_core *core) > +{ > + return container_of(core, struct ocelot_spi, core); > +} See my comments in the header file. > +static int ocelot_spi_init_bus(struct ocelot_spi *ocelot_spi) > +{ > + struct spi_device *spi; > + struct device *dev; > + u32 val, check; > + int err; > + > + spi = ocelot_spi->spi; > + dev = &spi->dev; > + > +#ifdef __LITTLE_ENDIAN > + val = VSC7512_BYTE_ORDER_LE; > +#else > + val = VSC7512_BYTE_ORDER_BE; > +#endif > + > + err = regmap_write(ocelot_spi->cpuorg_regmap, DEV_CPUORG_IF_CTRL, val); > + if (err) > + return err; > + > + val = ocelot_spi->spi_padding_bytes; > + err = regmap_write(ocelot_spi->cpuorg_regmap, DEV_CPUORG_IF_CFGSTAT, > + val); > + if (err) > + return err; > + > + check = val | 0x02000000; Either define or comment magic numbers (I prefer the former). > + err = regmap_read(ocelot_spi->cpuorg_regmap, DEV_CPUORG_IF_CFGSTAT, > + &val); > + if (err) > + return err; Comments needed for what you're actually doing here. > + if (check != val) > + return -ENODEV; > + > + return 0; > +} > + > +int ocelot_spi_initialize(struct ocelot_core *core) > +{ > + struct ocelot_spi *ocelot_spi = core_to_ocelot_spi(core); > + > + return ocelot_spi_init_bus(ocelot_spi); > +} > +EXPORT_SYMBOL(ocelot_spi_initialize); See my comments in the header file. > +static unsigned int ocelot_spi_translate_address(unsigned int reg) > +{ > + return cpu_to_be32((reg & 0xffffff) >> 2); > +} Comment. > +struct ocelot_spi_regmap_context { > + u32 base; > + struct ocelot_spi *ocelot_spi; > +}; See my comments in the header file. > +static int ocelot_spi_reg_read(void *context, unsigned int reg, > + unsigned int *val) > +{ > + struct ocelot_spi_regmap_context *regmap_context = context; > + struct ocelot_spi *ocelot_spi = regmap_context->ocelot_spi; > + struct spi_transfer tx, padding, rx; > + struct spi_message msg; > + struct spi_device *spi; > + unsigned int addr; > + u8 *tx_buf; > + > + WARN_ON(!val); Is this possible? > + spi = ocelot_spi->spi; > + > + addr = ocelot_spi_translate_address(reg + regmap_context->base); > + tx_buf = (u8 *)&addr; > + > + spi_message_init(&msg); > + > + memset(&tx, 0, sizeof(struct spi_transfer)); > + > + /* Ignore the first byte for the 24-bit address */ > + tx.tx_buf = &tx_buf[1]; > + tx.len = 3; > + > + spi_message_add_tail(&tx, &msg); > + > + if (ocelot_spi->spi_padding_bytes > 0) { > + u8 dummy_buf[16] = {0}; > + > + memset(&padding, 0, sizeof(struct spi_transfer)); > + > + /* Just toggle the clock for padding bytes */ > + padding.len = ocelot_spi->spi_padding_bytes; > + padding.tx_buf = dummy_buf; > + padding.dummy_data = 1; > + > + spi_message_add_tail(&padding, &msg); > + } > + > + memset(&rx, 0, sizeof(struct spi_transfer)); sizeof(*rx) > + rx.rx_buf = val; > + rx.len = 4; > + > + spi_message_add_tail(&rx, &msg); > + > + return spi_sync(spi, &msg); > +} > + > +static int ocelot_spi_reg_write(void *context, unsigned int reg, > + unsigned int val) > +{ > + struct ocelot_spi_regmap_context *regmap_context = context; > + struct ocelot_spi *ocelot_spi = regmap_context->ocelot_spi; > + struct spi_transfer tx[2] = {0}; > + struct spi_message msg; > + struct spi_device *spi; > + unsigned int addr; > + u8 *tx_buf; > + > + spi = ocelot_spi->spi; > + > + addr = ocelot_spi_translate_address(reg + regmap_context->base); > + tx_buf = (u8 *)&addr; > + > + spi_message_init(&msg); > + > + /* Ignore the first byte for the 24-bit address and set the write bit */ > + tx_buf[1] |= BIT(7); > + tx[0].tx_buf = &tx_buf[1]; > + tx[0].len = 3; > + > + spi_message_add_tail(&tx[0], &msg); > + > + memset(&tx[1], 0, sizeof(struct spi_transfer)); > + tx[1].tx_buf = &val; > + tx[1].len = 4; > + > + spi_message_add_tail(&tx[1], &msg); > + > + return spi_sync(spi, &msg); > +} > + > +static const struct regmap_config ocelot_spi_regmap_config = { > + .reg_bits = 24, > + .reg_stride = 4, > + .val_bits = 32, > + > + .reg_read = ocelot_spi_reg_read, > + .reg_write = ocelot_spi_reg_write, > + > + .max_register = 0xffffffff, > + .use_single_write = true, > + .use_single_read = true, > + .can_multi_write = false, > + > + .reg_format_endian = REGMAP_ENDIAN_BIG, > + .val_format_endian = REGMAP_ENDIAN_NATIVE, > +}; > + > +struct regmap * > +ocelot_spi_devm_get_regmap(struct ocelot_core *core, struct device *dev, > + const struct resource *res) > +{ > + struct ocelot_spi *ocelot_spi = core_to_ocelot_spi(core); > + struct ocelot_spi_regmap_context *context; > + struct regmap_config regmap_config; > + struct regmap *regmap; > + > + context = devm_kzalloc(dev, sizeof(*context), GFP_KERNEL); > + if (IS_ERR(context)) > + return ERR_CAST(context); > + > + context->base = res->start; > + context->ocelot_spi = ocelot_spi; > + > + memcpy(®map_config, &ocelot_spi_regmap_config, > + sizeof(ocelot_spi_regmap_config)); > + > + regmap_config.name = res->name; > + regmap_config.max_register = res->end - res->start; > + > + regmap = devm_regmap_init(dev, NULL, context, ®map_config); > + if (IS_ERR(regmap)) > + return ERR_CAST(regmap); > + > + return regmap; > +} > + > +static int ocelot_spi_probe(struct spi_device *spi) > +{ > + struct device *dev = &spi->dev; > + struct ocelot_spi *ocelot_spi; > + int err; > + > + ocelot_spi = devm_kzalloc(dev, sizeof(*ocelot_spi), GFP_KERNEL); > + > + if (!ocelot_spi) > + return -ENOMEM; > + > + if (spi->max_speed_hz <= 500000) { > + ocelot_spi->spi_padding_bytes = 0; > + } else { > + /* > + * Calculation taken from the manual for IF_CFGSTAT:IF_CFG. > + * Register access time is 1us, so we need to configure and send > + * out enough padding bytes between the read request and data > + * transmission that lasts at least 1 microsecond. > + */ > + ocelot_spi->spi_padding_bytes = 1 + > + (spi->max_speed_hz / 1000000 + 2) / 8; > + } > + > + ocelot_spi->spi = spi; > + > + spi->bits_per_word = 8; > + > + err = spi_setup(spi); > + if (err < 0) { > + dev_err(&spi->dev, "Error %d initializing SPI\n", err); > + return err; > + } > + > + ocelot_spi->cpuorg_regmap = > + ocelot_spi_devm_get_regmap(&ocelot_spi->core, dev, > + &vsc7512_dev_cpuorg_resource); > + if (!ocelot_spi->cpuorg_regmap) And if an error is returned? > + return -ENOMEM; > + > + ocelot_spi->core.dev = dev; > + > + /* > + * The chip must be set up for SPI before it gets initialized and reset. > + * This must be done before calling init, and after a chip reset is > + * performed. > + */ > + err = ocelot_spi_init_bus(ocelot_spi); > + if (err) { > + dev_err(dev, "Error %d initializing Ocelot SPI bus\n", err); > + return err; > + } > + > + err = ocelot_core_init(&ocelot_spi->core); > + if (err < 0) { > + dev_err(dev, "Error %d initializing Ocelot MFD\n", err); > + return err; > + } > + > + return 0; > +} > + > +static int ocelot_spi_remove(struct spi_device *spi) > +{ > + return 0; > +} > + > +const struct of_device_id ocelot_spi_of_match[] = { > + { .compatible = "mscc,vsc7512_mfd_spi" }, > + { }, > +}; > +MODULE_DEVICE_TABLE(of, ocelot_spi_of_match); > + > +static struct spi_driver ocelot_spi_driver = { > + .driver = { > + .name = "ocelot_mfd_spi", > + .of_match_table = of_match_ptr(ocelot_spi_of_match), > + }, > + .probe = ocelot_spi_probe, > + .remove = ocelot_spi_remove, > +}; > +module_spi_driver(ocelot_spi_driver); > + > +MODULE_DESCRIPTION("Ocelot Chip MFD SPI driver"); > +MODULE_AUTHOR("Colin Foster "); > +MODULE_LICENSE("Dual MIT/GPL"); > diff --git a/drivers/mfd/ocelot.h b/drivers/mfd/ocelot.h > new file mode 100644 > index 000000000000..8bb2b57002be > --- /dev/null > +++ b/drivers/mfd/ocelot.h > @@ -0,0 +1,36 @@ > +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ > +/* > + * Copyright 2021 Innovative Advantage Inc. > + */ > + > +#include > +#include > + > +struct ocelot_core { > + struct device *dev; > + struct regmap *gcb_regmap; > +}; Please drop this over-complicated 'core' and 'spi' stuff. You spend too much effort converting between 'dev', 'core' and 'spi'. I suggest you just pass 'dev' around as your key parameter. Any additional attributes you *need" to carry around can do in: struct ocelot *ddata; > +void ocelot_get_resource_name(char *name, const struct resource *res, > + int size); > +int ocelot_core_init(struct ocelot_core *core); > +int ocelot_remove(struct ocelot_core *core); > + > +#if IS_ENABLED(CONFIG_MFD_OCELOT_SPI) > +struct regmap *ocelot_spi_devm_get_regmap(struct ocelot_core *core, > + struct device *dev, > + const struct resource *res); > +int ocelot_spi_initialize(struct ocelot_core *core); > +#else > +static inline struct regmap *ocelot_spi_devm_get_regmap( > + struct ocelot_core *core, struct device *dev, > + const struct resource *res) > +{ > + return NULL; > +} > + > +static inline int ocelot_spi_initialize(struct ocelot_core *core) > +{ > + return -EOPNOTSUPP; > +} > +#endif > diff --git a/drivers/net/mdio/mdio-mscc-miim.c b/drivers/net/mdio/mdio-mscc-miim.c > index 07baf8390744..8e54bde06fd5 100644 > --- a/drivers/net/mdio/mdio-mscc-miim.c > +++ b/drivers/net/mdio/mdio-mscc-miim.c > @@ -11,11 +11,13 @@ > #include > #include > #include > +#include > #include > #include > #include > #include > #include > +#include > > #define MSCC_MIIM_REG_STATUS 0x0 > #define MSCC_MIIM_STATUS_STAT_PENDING BIT(2) > @@ -230,13 +232,20 @@ static int mscc_miim_probe(struct platform_device *pdev) > struct mii_bus *bus; > int ret; > > - regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); > - if (IS_ERR(regs)) { > - dev_err(dev, "Unable to map MIIM registers\n"); > - return PTR_ERR(regs); > - } > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + > + if (!device_is_mfd(pdev)) { > + regs = devm_ioremap_resource(dev, res); > + if (IS_ERR(regs)) { > + dev_err(dev, "Unable to map MIIM registers\n"); > + return PTR_ERR(regs); > + } > > - mii_regmap = devm_regmap_init_mmio(dev, regs, &mscc_miim_regmap_config); > + mii_regmap = devm_regmap_init_mmio(dev, regs, > + &mscc_miim_regmap_config); These tabs look wrong. Doesn't checkpatch.pl warn about stuff like this? > + } else { > + mii_regmap = ocelot_get_regmap_from_resource(dev->parent, res); > + } You need a comment to explain why you're calling both of these. > if (IS_ERR(mii_regmap)) { > dev_err(dev, "Unable to create MIIM regmap\n"); > diff --git a/drivers/pinctrl/pinctrl-microchip-sgpio.c b/drivers/pinctrl/pinctrl-microchip-sgpio.c > index 8db3caf15cf2..53df095b33e0 100644 > --- a/drivers/pinctrl/pinctrl-microchip-sgpio.c > +++ b/drivers/pinctrl/pinctrl-microchip-sgpio.c > @@ -12,6 +12,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -19,6 +20,7 @@ > #include > #include > #include > +#include > > #include "core.h" > #include "pinconf.h" > @@ -137,7 +139,9 @@ static inline int sgpio_addr_to_pin(struct sgpio_priv *priv, int port, int bit) > > static inline u32 sgpio_get_addr(struct sgpio_priv *priv, u32 rno, u32 off) > { > - return priv->properties->regoff[rno] + off; > + int stride = regmap_get_reg_stride(priv->regs); > + > + return (priv->properties->regoff[rno] + off) * stride; > } > > static u32 sgpio_readl(struct sgpio_priv *priv, u32 rno, u32 off) > @@ -818,6 +822,7 @@ static int microchip_sgpio_probe(struct platform_device *pdev) > struct fwnode_handle *fwnode; > struct reset_control *reset; > struct sgpio_priv *priv; > + struct resource *res; > struct clk *clk; > u32 __iomem *regs; > u32 val; > @@ -850,11 +855,18 @@ static int microchip_sgpio_probe(struct platform_device *pdev) > return -EINVAL; > } > > - regs = devm_platform_ioremap_resource(pdev, 0); > - if (IS_ERR(regs)) > - return PTR_ERR(regs); > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + > + if (!device_is_mfd(pdev)) { > + regs = devm_ioremap_resource(dev, res); What happens if you call this if the device was registered via MFD? > + if (IS_ERR(regs)) > + return PTR_ERR(regs); > + > + priv->regs = devm_regmap_init_mmio(dev, regs, ®map_config); > + } else { > + priv->regs = ocelot_get_regmap_from_resource(dev->parent, res); > + } > > - priv->regs = devm_regmap_init_mmio(dev, regs, ®map_config); > if (IS_ERR(priv->regs)) > return PTR_ERR(priv->regs); > > diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c > index b6ad3ffb4596..d5485c6a0e20 100644 > --- a/drivers/pinctrl/pinctrl-ocelot.c > +++ b/drivers/pinctrl/pinctrl-ocelot.c > @@ -10,6 +10,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -20,6 +21,7 @@ > #include > #include > #include > +#include > > #include "core.h" > #include "pinconf.h" > @@ -1123,6 +1125,9 @@ static int lan966x_pinmux_set_mux(struct pinctrl_dev *pctldev, > return 0; > } > > +#if defined(REG) > +#undef REG > +#endif > #define REG(r, info, p) ((r) * (info)->stride + (4 * ((p) / 32))) > > static int ocelot_gpio_set_direction(struct pinctrl_dev *pctldev, > @@ -1805,6 +1810,7 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev) > struct device *dev = &pdev->dev; > struct ocelot_pinctrl *info; > struct regmap *pincfg; > + struct resource *res; > void __iomem *base; > int ret; > struct regmap_config regmap_config = { > @@ -1819,16 +1825,27 @@ static int ocelot_pinctrl_probe(struct platform_device *pdev) > > info->desc = (struct pinctrl_desc *)device_get_match_data(dev); > > - base = devm_ioremap_resource(dev, > - platform_get_resource(pdev, IORESOURCE_MEM, 0)); > - if (IS_ERR(base)) > - return PTR_ERR(base); > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (IS_ERR(res)) { > + dev_err(dev, "Failed to get resource\n"); > + return PTR_ERR(res); > + } > > info->stride = 1 + (info->desc->npins - 1) / 32; > > - regmap_config.max_register = OCELOT_GPIO_SD_MAP * info->stride + 15 * 4; > + if (!device_is_mfd(pdev)) { > + base = devm_ioremap_resource(dev, res); > + if (IS_ERR(base)) > + return PTR_ERR(base); > + > + regmap_config.max_register = > + OCELOT_GPIO_SD_MAP * info->stride + 15 * 4; > + > + info->map = devm_regmap_init_mmio(dev, base, ®map_config); > + } else { > + info->map = ocelot_get_regmap_from_resource(dev->parent, res); > + } > > - info->map = devm_regmap_init_mmio(dev, base, ®map_config); > if (IS_ERR(info->map)) { > dev_err(dev, "Failed to create regmap\n"); > return PTR_ERR(info->map); > diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h > index 5c3a3597f1d2..70fae9c8b649 100644 > --- a/include/soc/mscc/ocelot.h > +++ b/include/soc/mscc/ocelot.h > @@ -969,4 +969,15 @@ ocelot_mrp_del_ring_role(struct ocelot *ocelot, int port, > } > #endif > > +#if IS_ENABLED(CONFIG_MFD_OCELOT) > +struct regmap *ocelot_get_regmap_from_resource(struct device *dev, > + const struct resource *res); > +#else > +static inline struct regmap * > +ocelot_get_regmap_from_resource(struct device *dev, const struct resource *res) > +{ > + return NULL; > +} > +#endif > + > #endif -- Lee Jones [李琼斯] Principal Technical Lead - Developer Services Linaro.org │ Open source software for Arm SoCs Follow Linaro: Facebook | Twitter | Blog 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 91DC5C433F5 for ; Mon, 31 Jan 2022 09:31:21 +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:In-Reply-To:MIME-Version:References: Message-ID:Subject:Cc:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Ld6iAqqXAT4mhkgE1iG3FaH1CyKQwu/N1lqlS2PuJCM=; b=454fwB00kK9ZEu s2Azxb6j6+kReiU6kYj0ZUkOiPpHt4CQqBKKQ0zrbPz2ZVIYMXcfcpuBqFQw2zQGrSWqbEM/OFkSK wopNHzCE8JVR2TMDskO49+UwoXtlhWLGcqXjA+d6EHDljgrSNYgpNu/tHxyBe5/Zyw/y2Fnlw5z+R Zdehy0OtZd599WMiQOYCn6Is/q5XPE+BDLVrS5Xt/Phm5cOQhpZ0aw0zgWi8KDX8M4VH2d7ZXsxkb 9oFQUL3DTI2bBHVBuTnw70Vg6Y6iNRpoOysCpdpLdfuiyzb8pdgPivGlvHl9AL0BPZX0CZCRkSxVR JgbmB2gX29F1h4ojOtWQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nET0L-008eOK-7n; Mon, 31 Jan 2022 09:29:45 +0000 Received: from mail-wm1-x32a.google.com ([2a00:1450:4864:20::32a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nET0F-008eM0-2r for linux-arm-kernel@lists.infradead.org; Mon, 31 Jan 2022 09:29:42 +0000 Received: by mail-wm1-x32a.google.com with SMTP id n12-20020a05600c3b8c00b0034eb13edb8eso7144980wms.0 for ; Mon, 31 Jan 2022 01:29:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to; bh=+K6CVITrnsRUky+BLWhSxF5egzLJ88cWLKIMCc6XEbQ=; b=loqmf1qlcbSW+eis/GTE7x15gBHA728qXoxkIgL8gUHEnvZSJ9td6+gyLUdgEXlAbb Dq1OPDsv78flVFaRHc6xEORePa+qtlfom/UPARjImwMHnnku2qwK31AaFZ42BrRe2VOW BmgqOhNd+hpoqeRH7I0OEToNl5H3HDsjMePYwvCU6SB3RNFAEFrWL6UlnouS70Ikd9zu V+5W4wkck2O0VZqUNVLDmswtoYLO12vOkO/KsAPYWgdg8w+V8fDrjeaROS781CXg9K1E yxHt0GOJVeVBGaFKHQe2B9+YLV21veluJdNG283Or2kb1JDlvmJ+zQ/SK8LA3SSZZ1MU KUaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to; bh=+K6CVITrnsRUky+BLWhSxF5egzLJ88cWLKIMCc6XEbQ=; b=sj9Z+DXmRyRgSRu5dT8QE1U5N3t9T417hyoBzHgigdXLK5C1pUClGKVdvoTHvgPOqD aRsvHlcgNSY7InjYVcG7Ao1c4hpogj5t55QaR8afrNt7PZ4qpi+wOA5PuZ7EPbLRmtcO oCQ04/Y2wnM9ZKf65Ho1IwkQppDHvPcSWpCCIvLOGq3tZHehy9oycAuN6UFAhWMBCzVe KxKUyJbw+t8yIiINNi2sRKlanS3g96St9SAskZmlQRbdu6bg9Oxbp0YpABUNpNbevbP+ bFmAdjTA+imMtxm1UJID0ZGS6lYusRV9E2pMduZliPcTbulrEjE9HPZ9h7LP1D9ED+RV EJoA== X-Gm-Message-State: AOAM531F9cpfF/iBE3ewRYmfObivK9PzVfre0wkge/oBa1ffMN57ghma 0N5ryQW0l1zOGcyPUq+Gf8AiHQ== X-Google-Smtp-Source: ABdhPJyEsZVSsVBdRUL6qYAq3IIxILI7cX6VjnOLwoIO4iTz4HDgV0oyZ60c2oxQoYjiDUEXhLLgcA== X-Received: by 2002:a05:600c:3641:: with SMTP id y1mr17274997wmq.53.1643621376995; Mon, 31 Jan 2022 01:29:36 -0800 (PST) Received: from google.com (cpc106310-bagu17-2-0-cust853.1-3.cable.virginm.net. [86.15.223.86]) by smtp.gmail.com with ESMTPSA id s17sm11188184wrm.62.2022.01.31.01.29.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 31 Jan 2022 01:29:36 -0800 (PST) Date: Mon, 31 Jan 2022 09:29:34 +0000 From: Lee Jones To: Colin Foster Cc: linux-arm-kernel@lists.infradead.org, linux-gpio@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Steen Hegelund , Lars Povlsen , Linus Walleij , Russell King , Heiner Kallweit , Jakub Kicinski , "David S. Miller" , Florian Fainelli , Vivien Didelot , Andrew Lunn , UNGLinuxDriver@microchip.com, Alexandre Belloni , Claudiu Manoil , Vladimir Oltean , katie.morris@in-advantage.com Subject: Re: [RFC v6 net-next 6/9] mfd: ocelot: add support for external mfd control over SPI for the VSC7512 Message-ID: References: <20220129220221.2823127-1-colin.foster@in-advantage.com> <20220129220221.2823127-7-colin.foster@in-advantage.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20220129220221.2823127-7-colin.foster@in-advantage.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220131_012939_234848_6C1D9928 X-CRM114-Status: GOOD ( 45.81 ) 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 T24gU2F0LCAyOSBKYW4gMjAyMiwgQ29saW4gRm9zdGVyIHdyb3RlOgoKPiBDcmVhdGUgYSBzaW5n bGUgU1BJIE1GRCBvY2Vsb3QgZGV2aWNlIHRoYXQgbWFuYWdlcyB0aGUgU1BJIGJ1cyBvbiB0aGUK PiBleHRlcm5hbCBjaGlwIGFuZCBjYW4gaGFuZGxlIHJlcXVlc3RzIGZvciByZWdtYXBzLiBUaGlz IHNob3VsZCBhbGxvdyBhbnkKPiBvY2Vsb3QgZHJpdmVyIChwaW5jdHJsLCBtaWltLCBldGMuKSB0 byBiZSB1c2VkIGV4dGVybmFsbHksIHByb3ZpZGVkIHRoZXkKPiB1dGlsaXplIHJlZ21hcHMuCj4g Cj4gU2lnbmVkLW9mZi1ieTogQ29saW4gRm9zdGVyIDxjb2xpbi5mb3N0ZXJAaW4tYWR2YW50YWdl LmNvbT4KPiAtLS0KPiAgZHJpdmVycy9tZmQvS2NvbmZpZyAgICAgICAgICAgICAgICAgICAgICAg fCAgMTkgKysKPiAgZHJpdmVycy9tZmQvTWFrZWZpbGUgICAgICAgICAgICAgICAgICAgICAgfCAg IDMgKwo+ICBkcml2ZXJzL21mZC9vY2Vsb3QtY29yZS5jICAgICAgICAgICAgICAgICB8IDE2NSAr KysrKysrKysrKwo+ICBkcml2ZXJzL21mZC9vY2Vsb3Qtc3BpLmMgICAgICAgICAgICAgICAgICB8 IDMyNSArKysrKysrKysrKysrKysrKysrKysrCj4gIGRyaXZlcnMvbWZkL29jZWxvdC5oICAgICAg ICAgICAgICAgICAgICAgIHwgIDM2ICsrKwoKPiAgZHJpdmVycy9uZXQvbWRpby9tZGlvLW1zY2Mt bWlpbS5jICAgICAgICAgfCAgMjEgKy0KPiAgZHJpdmVycy9waW5jdHJsL3BpbmN0cmwtbWljcm9j aGlwLXNncGlvLmMgfCAgMjIgKy0KPiAgZHJpdmVycy9waW5jdHJsL3BpbmN0cmwtb2NlbG90LmMg ICAgICAgICAgfCAgMjkgKy0KPiAgaW5jbHVkZS9zb2MvbXNjYy9vY2Vsb3QuaCAgICAgICAgICAg ICAgICAgfCAgMTEgKwoKUGxlYXNlIGF2b2lkIG1peGluZyBzdWJzeXN0ZW1zIGluIHBhdGNoZXMg aWYgYXQgYWxsIGF2b2lkYWJsZS4KCklmIHRoZXJlIGFyZSBub3QgYnVpbGQgdGltZSBkZXBlbmRl bmNpZXMvYnJlYWthZ2VzLCBJJ2Qgc3VnZ2VzdApmaXJzdGx5IGFwcGx5aW5nIHN1cHBvcnQgZm9y IHRoaXMgaW50byBNRkQgKnRoZW4qIHV0aWxpc2luZyB0aGF0CnN1cHBvcnQgaW4gc3Vic2VxdWVu dCBwYXRjaGVzLgoKPiAgOSBmaWxlcyBjaGFuZ2VkLCA2MTQgaW5zZXJ0aW9ucygrKSwgMTcgZGVs ZXRpb25zKC0pCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21mZC9vY2Vsb3QtY29yZS5j Cj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21mZC9vY2Vsb3Qtc3BpLmMKPiAgY3JlYXRl IG1vZGUgMTAwNjQ0IGRyaXZlcnMvbWZkL29jZWxvdC5oCj4gCj4gZGlmZiAtLWdpdCBhL2RyaXZl cnMvbWZkL0tjb25maWcgYi9kcml2ZXJzL21mZC9LY29uZmlnCj4gaW5kZXggYmEwYjNlYjEzMWYx Li41N2JiZjJkMTEzMjQgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy9tZmQvS2NvbmZpZwo+ICsrKyBi L2RyaXZlcnMvbWZkL0tjb25maWcKPiBAQCAtOTQ4LDYgKzk0OCwyNSBAQCBjb25maWcgTUZEX01F TkYyMUJNQwo+ICAJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1vZHVsZS4g SWYgc28gdGhlIG1vZHVsZQo+ICAJICB3aWxsIGJlIGNhbGxlZCBtZW5mMjFibWMuCj4gIAo+ICtj b25maWcgTUZEX09DRUxPVAo+ICsJdHJpc3RhdGUgIk1pY3Jvc2VtaSBPY2Vsb3QgRXh0ZXJuYWwg Q29udHJvbCBTdXBwb3J0IgoKUGxlYXNlIGV4cGxhaW4gZXhhY3RseSB3aGF0IGFuIEVDUyBpcyBp biB0aGUgaGVscCBiZWxvdy4KCj4gKwlzZWxlY3QgTUZEX0NPUkUKPiArCWhlbHAKPiArCSAgU2F5 IHllcyBoZXJlIHRvIGFkZCBzdXBwb3J0IGZvciBPY2Vsb3QgY2hpcHMgKFZTQzc1MTEsIFZTQzc1 MTIsCj4gKwkgIFZTQzc1MTMsIFZTQzc1MTQpIGNvbnRyb2xsZWQgZXh0ZXJuYWxseS4KPiArCj4g KwkgIEFsbCBmb3VyIG9mIHRoZXNlIGNoaXBzIGNhbiBiZSBjb250cm9sbGVkIGludGVybmFsbHkg KE1NSU8pIG9yCj4gKwkgIGV4dGVybmFsbHkgdmlhIFNQSSwgSTJDLCBQQ0llLiBUaGlzIGVuYWJs ZXMgY29udHJvbCBvZiB0aGVzZSBjaGlwcwo+ICsJICBvdmVyIG9uZSBvciBtb3JlIG9mIHRoZXNl IGJ1c2VzLgo+ICsKPiArY29uZmlnIE1GRF9PQ0VMT1RfU1BJCj4gKwl0cmlzdGF0ZSAiTWljcm9z ZW1pIE9jZWxvdCBTUEkgaW50ZXJmYWNlIgo+ICsJZGVwZW5kcyBvbiBNRkRfT0NFTE9UCj4gKwlk ZXBlbmRzIG9uIFNQSV9NQVNURVIKPiArCXNlbGVjdCBSRUdNQVBfU1BJCj4gKwloZWxwCj4gKwkg IFNheSB5ZXMgaGVyZSB0byBhZGQgY29udHJvbCB0byB0aGUgTUZEX09DRUxPVCBjaGlwcyB2aWEg U1BJLgo+ICsKPiAgY29uZmlnIEVaWF9QQ0FQCj4gIAlib29sICJNb3Rvcm9sYSBFWlhQQ0FQIFN1 cHBvcnQiCj4gIAlkZXBlbmRzIG9uIFNQSV9NQVNURVIKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9t ZmQvTWFrZWZpbGUgYi9kcml2ZXJzL21mZC9NYWtlZmlsZQo+IGluZGV4IGRmMWVjYzRhNGM5NS4u MTI1MTM4NDMwNjdhIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvbWZkL01ha2VmaWxlCj4gKysrIGIv ZHJpdmVycy9tZmQvTWFrZWZpbGUKPiBAQCAtMTIwLDYgKzEyMCw5IEBAIG9iai0kKENPTkZJR19N RkRfTUMxM1hYWF9JMkMpCSs9IG1jMTN4eHgtaTJjLm8KPiAgCj4gIG9iai0kKENPTkZJR19NRkRf Q09SRSkJCSs9IG1mZC1jb3JlLm8KPiAgCj4gK29iai0kKENPTkZJR19NRkRfT0NFTE9UKQkrPSBv Y2Vsb3QtY29yZS5vCj4gK29iai0kKENPTkZJR19NRkRfT0NFTE9UX1NQSSkJKz0gb2NlbG90LXNw aS5vCj4gKwoKVGhlc2UgZG8gbm90IGxvb2sgbGluZWQtdXAgd2l0aCB0aGUgcmVtYWluZGVyIG9m IHRoZSBmaWxlLgoKPiAgb2JqLSQoQ09ORklHX0VaWF9QQ0FQKQkJKz0gZXp4LXBjYXAubwo+ICBv YmotJChDT05GSUdfTUZEX0NQQ0FQKQkJKz0gbW90b3JvbGEtY3BjYXAubwo+ICAKPiBkaWZmIC0t Z2l0IGEvZHJpdmVycy9tZmQvb2NlbG90LWNvcmUuYyBiL2RyaXZlcnMvbWZkL29jZWxvdC1jb3Jl LmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAwMDAwMC4uNTkwNDg5NDgx YjhjCj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2RyaXZlcnMvbWZkL29jZWxvdC1jb3JlLmMKPiBA QCAtMCwwICsxLDE2NSBAQAo+ICsvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogKEdQTC0yLjAg T1IgTUlUKQo+ICsvKgo+ICsgKiBNRkQgY29yZSBkcml2ZXIgZm9yIHRoZSBPY2Vsb3QgY2hpcCBm YW1pbHkuCj4gKyAqCj4gKyAqIFRoZSBWU0M3NTExLCA3NTEyLCA3NTEzLCBhbmQgNzUxNCBjYW4g YmUgY29udHJvbGxlZCBpbnRlcm5hbGx5IHZpYSBhbgo+ICsgKiBvbi1jaGlwIE1JUFMgcHJvY2Vz c29yLCBvciBleHRlcm5hbGx5IHZpYSBTUEksIEkyQywgUENJZS4gVGhpcyBjb3JlIGRyaXZlciBp cwo+ICsgKiBpbnRlbmRlZCB0byBiZSB0aGUgYnVzLWFnbm9zdGljIGdsdWUgYmV0d2VlbiwgZm9y IGV4YW1wbGUsIHRoZSBTUEkgYnVzIGFuZAo+ICsgKiB0aGUgTUZEIGNoaWxkcmVuLgo+ICsgKgo+ ICsgKiBDb3B5cmlnaHQgMjAyMSBJbm5vdmF0aXZlIEFkdmFudGFnZSBJbmMuCj4gKyAqCj4gKyAq IEF1dGhvcjogQ29saW4gRm9zdGVyIDxjb2xpbi5mb3N0ZXJAaW4tYWR2YW50YWdlLmNvbT4KPiAr ICovCj4gKwo+ICsjaW5jbHVkZSA8bGludXgvbWZkL2NvcmUuaD4KPiArI2luY2x1ZGUgPGxpbnV4 L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvcmVnbWFwLmg+Cj4gKwo+ICsjaW5jbHVkZSA8 YXNtL2J5dGVvcmRlci5oPgo+ICsKPiArI2luY2x1ZGUgIm9jZWxvdC5oIgo+ICsKPiArI2RlZmlu ZSBHQ0JfU09GVF9SU1QgKDB4MDAwOCkKCldoeSB0aGUgYnJhY2tldHM/Cgo+ICsjZGVmaW5lIFNP RlRfQ0hJUF9SU1QgKDB4MSkKCkFzIGFib3ZlLgoKPiArc3RhdGljIGNvbnN0IHN0cnVjdCByZXNv dXJjZSB2c2M3NTEyX2djYl9yZXNvdXJjZSA9IHsKPiArCS5zdGFydAk9IDB4NzEwNzAwMDAsCj4g KwkuZW5kCT0gMHg3MTA3MDIyYiwKClBsZWFzZSBkZWZpbmUgdGhlc2Ugc29tZXdoZXJlLgoKPiAr CS5uYW1lCT0gImRldmNwdV9nY2IiLAo+ICt9OwoKVGhlcmUgaXMgYSBtYWNybyB5b3UgY2FuIHVz ZSBmb3IgdGhlc2UuCgpHcmVwIGZvciAiREVGSU5FX1JFU18iCgo+ICtzdGF0aWMgaW50IG9jZWxv dF9yZXNldChzdHJ1Y3Qgb2NlbG90X2NvcmUgKmNvcmUpCj4gK3sKPiArCWludCByZXQ7Cj4gKwo+ ICsJLyoKPiArCSAqIFJlc2V0IHRoZSBlbnRpcmUgY2hpcCBoZXJlIHRvIHB1dCBpdCBpbnRvIGEg Y29tcGxldGVseSBrbm93biBzdGF0ZS4KPiArCSAqIE90aGVyIGRyaXZlcnMgbWF5IHdhbnQgdG8g cmVzZXQgdGhlaXIgb3duIHN1YnN5c3RlbXMuIFRoZSByZWdpc3Rlcgo+ICsJICogc2VsZi1jbGVh cnMsIHNvIG9uZSB3cml0ZSBpcyBhbGwgdGhhdCBpcyBuZWVkZWQKPiArCSAqLwo+ICsJcmV0ID0g cmVnbWFwX3dyaXRlKGNvcmUtPmdjYl9yZWdtYXAsIEdDQl9TT0ZUX1JTVCwgU09GVF9DSElQX1JT VCk7Cj4gKwlpZiAocmV0KQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJbXNsZWVwKDEwMCk7Cj4g Kwo+ICsJLyoKPiArCSAqIEEgY2hpcCByZXNldCB3aWxsIGNsZWFyIHRoZSBTUEkgY29uZmlndXJh dGlvbiwgc28gaXQgbmVlZHMgdG8gYmUgZG9uZQo+ICsJICogYWdhaW4gYmVmb3JlIHdlIGNhbiBh Y2Nlc3MgYW55IG1vcmUgcmVnaXN0ZXJzCj4gKwkgKi8KPiArCXJldCA9IG9jZWxvdF9zcGlfaW5p dGlhbGl6ZShjb3JlKTsKPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgc3Ry dWN0IHJlZ21hcCAqb2NlbG90X2Rldm1fcmVnbWFwX2luaXQoc3RydWN0IG9jZWxvdF9jb3JlICpj b3JlLAo+ICsJCQkJCSAgICAgIHN0cnVjdCBkZXZpY2UgKmRldiwKPiArCQkJCQkgICAgICBjb25z dCBzdHJ1Y3QgcmVzb3VyY2UgKnJlcykKPiArewo+ICsJc3RydWN0IHJlZ21hcCAqcmVnbWFwOwo+ ICsKPiArCXJlZ21hcCA9IGRldl9nZXRfcmVnbWFwKGRldiwgcmVzLT5uYW1lKTsKPiArCWlmICgh cmVnbWFwKQo+ICsJCXJlZ21hcCA9IG9jZWxvdF9zcGlfZGV2bV9nZXRfcmVnbWFwKGNvcmUsIGRl diwgcmVzKTsKCldoeSBhcmUgeW91IG1ha2luZyBTUEkgc3BlY2lmaWMgY2FsbHMgZnJvbSB0aGUg Q29yZSBkcml2ZXI/Cgo+ICsJcmV0dXJuIHJlZ21hcDsKPiArfQo+ICsKPiArc3RydWN0IHJlZ21h cCAqb2NlbG90X2dldF9yZWdtYXBfZnJvbV9yZXNvdXJjZShzdHJ1Y3QgZGV2aWNlICpkZXYsCj4g KwkJCQkJICAgICAgIGNvbnN0IHN0cnVjdCByZXNvdXJjZSAqcmVzKQo+ICt7Cj4gKwlzdHJ1Y3Qg b2NlbG90X2NvcmUgKmNvcmUgPSBkZXZfZ2V0X2RydmRhdGEoZGV2KTsKPiArCj4gKwlyZXR1cm4g b2NlbG90X2Rldm1fcmVnbWFwX2luaXQoY29yZSwgZGV2LCByZXMpOwo+ICt9Cj4gK0VYUE9SVF9T WU1CT0wob2NlbG90X2dldF9yZWdtYXBfZnJvbV9yZXNvdXJjZSk7CgpXaHkgZG9uJ3QgeW91IGFs d2F5cyBjYWxsIG9jZWxvdF9kZXZtX3JlZ21hcF9pbml0KCkgd2l0aCB0aGUgJ2NvcmUnCnBhcmFt ZXRlciBkcm9wcGVkIGFuZCBqdXN0IGRvIGRldl9nZXRfZHJ2ZGF0YSgpIGluc2lkZSBvZiB0aGVy ZT8KCllvdSdyZSBwYXNzaW5nICdkZXYnIGFueXdheS4KCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qg cmVzb3VyY2UgdnNjNzUxMl9taWltMV9yZXNvdXJjZXNbXSA9IHsKPiArCXsKPiArCQkuc3RhcnQg PSAweDcxMDcwMGMwLAo+ICsJCS5lbmQgPSAweDcxMDcwMGUzLAo+ICsJCS5uYW1lID0gImdjYl9t aWltMSIsCj4gKwkJLmZsYWdzID0gSU9SRVNPVVJDRV9NRU0sCj4gKwl9LAo+ICt9Owo+ICsKPiAr c3RhdGljIGNvbnN0IHN0cnVjdCByZXNvdXJjZSB2c2M3NTEyX3BpbmN0cmxfcmVzb3VyY2VzW10g PSB7Cj4gKwl7Cj4gKwkJLnN0YXJ0ID0gMHg3MTA3MDAzNCwKPiArCQkuZW5kID0gMHg3MTA3MDA5 ZiwKPiArCQkubmFtZSA9ICJnY2JfZ3BpbyIsCj4gKwkJLmZsYWdzID0gSU9SRVNPVVJDRV9NRU0s Cj4gKwl9LAo+ICt9Owo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCByZXNvdXJjZSB2c2M3NTEy X3NncGlvX3Jlc291cmNlc1tdID0gewo+ICsJewo+ICsJCS5zdGFydCA9IDB4NzEwNzAwZjgsCj4g KwkJLmVuZCA9IDB4NzEwNzAxZjcsCj4gKwkJLm5hbWUgPSAiZ2NiX3NpbyIsCj4gKwkJLmZsYWdz ID0gSU9SRVNPVVJDRV9NRU0sCj4gKwl9LAo+ICt9Owo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVj dCBtZmRfY2VsbCB2c2M3NTEyX2RldnNbXSA9IHsKPiArCXsKPiArCQkubmFtZSA9ICJwaW5jdHJs LW9jZWxvdCIsCgo8ZGV2aWNlPi08c3ViLWRldmljZT4KCiJvY2Vsb3QtcGluY3RybCIKCj4gKwkJ Lm9mX2NvbXBhdGlibGUgPSAibXNjYyxvY2Vsb3QtcGluY3RybCIsCj4gKwkJLm51bV9yZXNvdXJj ZXMgPSBBUlJBWV9TSVpFKHZzYzc1MTJfcGluY3RybF9yZXNvdXJjZXMpLAo+ICsJCS5yZXNvdXJj ZXMgPSB2c2M3NTEyX3BpbmN0cmxfcmVzb3VyY2VzLAo+ICsJfSwKPiArCXsKClNhbWUgbGluZSBw bGVhc2UuCgo+ICsJCS5uYW1lID0gInBpbmN0cmwtc2dwaW8iLAoKIm9jZWxvdC1zZ3BpbyIKCj4g KwkJLm9mX2NvbXBhdGlibGUgPSAibXNjYyxvY2Vsb3Qtc2dwaW8iLAo+ICsJCS5udW1fcmVzb3Vy Y2VzID0gQVJSQVlfU0laRSh2c2M3NTEyX3NncGlvX3Jlc291cmNlcyksCj4gKwkJLnJlc291cmNl cyA9IHZzYzc1MTJfc2dwaW9fcmVzb3VyY2VzLAo+ICsJfSwKPiArCXsKPiArCQkubmFtZSA9ICJv Y2Vsb3QtbWlpbTEiLAo+ICsJCS5vZl9jb21wYXRpYmxlID0gIm1zY2Msb2NlbG90LW1paW0iLAo+ ICsJCS5udW1fcmVzb3VyY2VzID0gQVJSQVlfU0laRSh2c2M3NTEyX21paW0xX3Jlc291cmNlcyks Cj4gKwkJLnJlc291cmNlcyA9IHZzYzc1MTJfbWlpbTFfcmVzb3VyY2VzLAo+ICsJfSwKPiArfTsK PiArCj4gK2ludCBvY2Vsb3RfY29yZV9pbml0KHN0cnVjdCBvY2Vsb3RfY29yZSAqY29yZSkKPiAr ewo+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gY29yZS0+ZGV2Owo+ICsJaW50IHJldDsKPiArCj4g KwlkZXZfc2V0X2RydmRhdGEoZGV2LCBjb3JlKTsKPiArCj4gKwljb3JlLT5nY2JfcmVnbWFwID0g b2NlbG90X2Rldm1fcmVnbWFwX2luaXQoY29yZSwgZGV2LAo+ICsJCQkJCQkgICAmdnNjNzUxMl9n Y2JfcmVzb3VyY2UpOwo+ICsJaWYgKCFjb3JlLT5nY2JfcmVnbWFwKQoKQW5kIGlmIGFuIGVycm9y IGlzIHJldHVybmVkPwoKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwkvKiBQcmVwYXJlIHRo ZSBjaGlwICovCgpEb2VzIGl0IHByZXBhcmUgb3IgcmVzZXQgdGhlIGNoaXA/CgpJZiB0aGUgZm9y bWVyLCB0aGVuIHRoZSBmb2xsb3dpbmcgY2FsbCBpcyBtaXNuYW1lZC4KCmlmIHRoZSBsYXR0ZXIs IHRoZW4gdGhlcmUgaXMgbm8gbmVlZCBmb3IgdGhpcyBjb21tZW50LgoKPiArCXJldCA9IG9jZWxv dF9yZXNldChjb3JlKTsKPiArCWlmIChyZXQpIHsKPiArCQlkZXZfZXJyKGRldiwgIm9jZWxvdCBt ZmQgcmVzZXQgZmFpbGVkIHdpdGggY29kZSAlZFxuIiwgcmV0KTsKCklzbid0IHRoZSBkZXZpY2Ug Y2FsbGVkICdvY2Vsb3QnPyAgSWYgc28sIHlvdSBqdXN0IHJlcGVhdGVkIHlvdXJzZWxmLgoKIkZh aWxlZCB0byByZXNldCBkZXZpY2U6ICVkXG4iCgo+ICsJCXJldHVybiByZXQ7Cj4gKwl9Cj4gKwo+ ICsJcmV0ID0gZGV2bV9tZmRfYWRkX2RldmljZXMoZGV2LCBQTEFURk9STV9ERVZJRF9OT05FLCB2 c2M3NTEyX2RldnMsCgpXaHkgTk9ORT8KCj4gKwkJCQkgICBBUlJBWV9TSVpFKHZzYzc1MTJfZGV2 cyksIE5VTEwsIDAsIE5VTEwpOwo+ICsJaWYgKHJldCkgewo+ICsJCWRldl9lcnIoZGV2LCAiZXJy b3IgYWRkaW5nIG1mZCBkZXZpY2VzXG4iKTsKCiJGYWlsZWQgdG8gYWRkIHN1Yi1kZXZpY2VzIgoK PiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gK0VYUE9SVF9T WU1CT0wob2NlbG90X2NvcmVfaW5pdCk7Cj4gKwo+ICtpbnQgb2NlbG90X3JlbW92ZShzdHJ1Y3Qg b2NlbG90X2NvcmUgKmNvcmUpCj4gK3sKPiArCXJldHVybiAwOwo+ICt9Cj4gK0VYUE9SVF9TWU1C T0wob2NlbG90X3JlbW92ZSk7CgpXaGF0J3MgdGhlIHByb3Bvc2Ugb2YgdGhpcz8KCj4gK01PRFVM RV9ERVNDUklQVElPTigiT2NlbG90IENoaXAgTUZEIGRyaXZlciIpOwoKTm8gc3VjaCB0aGluZyBh cyBhbiBNRkQgZHJpdmVyLgoKPiArTU9EVUxFX0FVVEhPUigiQ29saW4gRm9zdGVyIDxjb2xpbi5m b3N0ZXJAaW4tYWR2YW50YWdlLmNvbT4iKTsKPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCB2MiIpOwo+ IGRpZmYgLS1naXQgYS9kcml2ZXJzL21mZC9vY2Vsb3Qtc3BpLmMgYi9kcml2ZXJzL21mZC9vY2Vs b3Qtc3BpLmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAwMDAwMC4uMWUy NjhhNGRmYTE3Cj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2RyaXZlcnMvbWZkL29jZWxvdC1zcGku Ywo+IEBAIC0wLDAgKzEsMzI1IEBACj4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiAoR1BM LTIuMCBPUiBNSVQpCj4gKy8qCj4gKyAqIFNQSSBjb3JlIGRyaXZlciBmb3IgdGhlIE9jZWxvdCBj aGlwIGZhbWlseS4KPiArICoKPiArICogVGhpcyBkcml2ZXIgd2lsbCBoYW5kbGUgZXZlcnl0aGlu ZyBuZWNlc3NhcnkgdG8gYWxsb3cgZm9yIGNvbW11bmljYXRpb24gb3Zlcgo+ICsgKiBTUEkgdG8g dGhlIFZTQzc1MTEsIFZTQzc1MTIsIFZTQzc1MTMgYW5kIFZTQzc1MTQgY2hpcHMuIFRoZSBtYWlu IGZ1bmN0aW9ucwo+ICsgKiBhcmUgdG8gcHJlcGFyZSB0aGUgY2hpcCdzIFNQSSBpbnRlcmZhY2Ug Zm9yIGEgc3BlY2lmaWMgYnVzIHNwZWVkLCBhbmQgYSBob3N0Cj4gKyAqIHByb2Nlc3NvcidzIGVu ZGlhbm5lc3MuIFRoaXMgd2lsbCBjcmVhdGUgYW5kIGRpc3RyaWJ1dGUgcmVnbWFwcyBmb3IgYW55 IE1GRAo+ICsgKiBjaGlsZHJlbi4KPiArICoKPiArICogQ29weXJpZ2h0IDIwMjEgSW5ub3ZhdGl2 ZSBBZHZhbnRhZ2UgSW5jLgo+ICsgKgo+ICsgKiBBdXRob3I6IENvbGluIEZvc3RlciA8Y29saW4u Zm9zdGVyQGluLWFkdmFudGFnZS5jb20+Cj4gKyAqLwo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L2lv cG9sbC5oPgo+ICsjaW5jbHVkZSA8bGludXgva2NvbmZpZy5oPgo+ICsjaW5jbHVkZSA8bGludXgv bW9kdWxlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9vZi5oPgo+ICsjaW5jbHVkZSA8bGludXgvcmVn bWFwLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9zcGkvc3BpLmg+Cj4gKwo+ICsjaW5jbHVkZSA8YXNt L2J5dGVvcmRlci5oPgo+ICsKPiArI2luY2x1ZGUgIm9jZWxvdC5oIgo+ICsKPiArc3RydWN0IG9j ZWxvdF9zcGkgewo+ICsJaW50IHNwaV9wYWRkaW5nX2J5dGVzOwo+ICsJc3RydWN0IHNwaV9kZXZp Y2UgKnNwaTsKPiArCXN0cnVjdCBvY2Vsb3RfY29yZSBjb3JlOwo+ICsJc3RydWN0IHJlZ21hcCAq Y3B1b3JnX3JlZ21hcDsKPiArfTsKPiArCj4gKyNkZWZpbmUgREVWX0NQVU9SR19JRl9DVFJMCSgw eDAwMDApCj4gKyNkZWZpbmUgREVWX0NQVU9SR19JRl9DRkdTVEFUCSgweDAwMDQpCj4gKwo+ICtz dGF0aWMgY29uc3Qgc3RydWN0IHJlc291cmNlIHZzYzc1MTJfZGV2X2NwdW9yZ19yZXNvdXJjZSA9 IHsKPiArCS5zdGFydAk9IDB4NzEwMDAwMDAsCj4gKwkuZW5kCT0gMHg3MTAwMDJmZiwKPiArCS5u YW1lCT0gImRldmNwdV9vcmciLAo+ICt9Owo+ICsKPiArI2RlZmluZSBWU0M3NTEyX0JZVEVfT1JE RVJfTEUgMHgwMDAwMDAwMAo+ICsjZGVmaW5lIFZTQzc1MTJfQllURV9PUkRFUl9CRSAweDgxODE4 MTgxCj4gKyNkZWZpbmUgVlNDNzUxMl9CSVRfT1JERVJfTVNCIDB4MDAwMDAwMDAKPiArI2RlZmlu ZSBWU0M3NTEyX0JJVF9PUkRFUl9MU0IgMHg0MjQyNDI0Mgo+ICsKPiArc3RhdGljIHN0cnVjdCBv Y2Vsb3Rfc3BpICpjb3JlX3RvX29jZWxvdF9zcGkoc3RydWN0IG9jZWxvdF9jb3JlICpjb3JlKQo+ ICt7Cj4gKwlyZXR1cm4gY29udGFpbmVyX29mKGNvcmUsIHN0cnVjdCBvY2Vsb3Rfc3BpLCBjb3Jl KTsKPiArfQoKU2VlIG15IGNvbW1lbnRzIGluIHRoZSBoZWFkZXIgZmlsZS4KCj4gK3N0YXRpYyBp bnQgb2NlbG90X3NwaV9pbml0X2J1cyhzdHJ1Y3Qgb2NlbG90X3NwaSAqb2NlbG90X3NwaSkKPiAr ewo+ICsJc3RydWN0IHNwaV9kZXZpY2UgKnNwaTsKPiArCXN0cnVjdCBkZXZpY2UgKmRldjsKPiAr CXUzMiB2YWwsIGNoZWNrOwo+ICsJaW50IGVycjsKPiArCj4gKwlzcGkgPSBvY2Vsb3Rfc3BpLT5z cGk7Cj4gKwlkZXYgPSAmc3BpLT5kZXY7Cj4gKwo+ICsjaWZkZWYgX19MSVRUTEVfRU5ESUFOCj4g Kwl2YWwgPSBWU0M3NTEyX0JZVEVfT1JERVJfTEU7Cj4gKyNlbHNlCj4gKwl2YWwgPSBWU0M3NTEy X0JZVEVfT1JERVJfQkU7Cj4gKyNlbmRpZgo+ICsKPiArCWVyciA9IHJlZ21hcF93cml0ZShvY2Vs b3Rfc3BpLT5jcHVvcmdfcmVnbWFwLCBERVZfQ1BVT1JHX0lGX0NUUkwsIHZhbCk7Cj4gKwlpZiAo ZXJyKQo+ICsJCXJldHVybiBlcnI7Cj4gKwo+ICsJdmFsID0gb2NlbG90X3NwaS0+c3BpX3BhZGRp bmdfYnl0ZXM7Cj4gKwllcnIgPSByZWdtYXBfd3JpdGUob2NlbG90X3NwaS0+Y3B1b3JnX3JlZ21h cCwgREVWX0NQVU9SR19JRl9DRkdTVEFULAo+ICsJCQkgICB2YWwpOwo+ICsJaWYgKGVycikKPiAr CQlyZXR1cm4gZXJyOwo+ICsKPiArCWNoZWNrID0gdmFsIHwgMHgwMjAwMDAwMDsKCkVpdGhlciBk ZWZpbmUgb3IgY29tbWVudCBtYWdpYyBudW1iZXJzIChJIHByZWZlciB0aGUgZm9ybWVyKS4KCj4g KwllcnIgPSByZWdtYXBfcmVhZChvY2Vsb3Rfc3BpLT5jcHVvcmdfcmVnbWFwLCBERVZfQ1BVT1JH X0lGX0NGR1NUQVQsCj4gKwkJCSAgJnZhbCk7Cj4gKwlpZiAoZXJyKQo+ICsJCXJldHVybiBlcnI7 CgpDb21tZW50cyBuZWVkZWQgZm9yIHdoYXQgeW91J3JlIGFjdHVhbGx5IGRvaW5nIGhlcmUuCgo+ ICsJaWYgKGNoZWNrICE9IHZhbCkKPiArCQlyZXR1cm4gLUVOT0RFVjsKPiArCj4gKwlyZXR1cm4g MDsKPiArfQo+ICsKPiAraW50IG9jZWxvdF9zcGlfaW5pdGlhbGl6ZShzdHJ1Y3Qgb2NlbG90X2Nv cmUgKmNvcmUpCj4gK3sKPiArCXN0cnVjdCBvY2Vsb3Rfc3BpICpvY2Vsb3Rfc3BpID0gY29yZV90 b19vY2Vsb3Rfc3BpKGNvcmUpOwo+ICsKPiArCXJldHVybiBvY2Vsb3Rfc3BpX2luaXRfYnVzKG9j ZWxvdF9zcGkpOwo+ICt9Cj4gK0VYUE9SVF9TWU1CT0wob2NlbG90X3NwaV9pbml0aWFsaXplKTsK ClNlZSBteSBjb21tZW50cyBpbiB0aGUgaGVhZGVyIGZpbGUuCgo+ICtzdGF0aWMgdW5zaWduZWQg aW50IG9jZWxvdF9zcGlfdHJhbnNsYXRlX2FkZHJlc3ModW5zaWduZWQgaW50IHJlZykKPiArewo+ ICsJcmV0dXJuIGNwdV90b19iZTMyKChyZWcgJiAweGZmZmZmZikgPj4gMik7Cj4gK30KCkNvbW1l bnQuCgo+ICtzdHJ1Y3Qgb2NlbG90X3NwaV9yZWdtYXBfY29udGV4dCB7Cj4gKwl1MzIgYmFzZTsK PiArCXN0cnVjdCBvY2Vsb3Rfc3BpICpvY2Vsb3Rfc3BpOwo+ICt9OwoKU2VlIG15IGNvbW1lbnRz IGluIHRoZSBoZWFkZXIgZmlsZS4KCj4gK3N0YXRpYyBpbnQgb2NlbG90X3NwaV9yZWdfcmVhZCh2 b2lkICpjb250ZXh0LCB1bnNpZ25lZCBpbnQgcmVnLAo+ICsJCQkgICAgICAgdW5zaWduZWQgaW50 ICp2YWwpCj4gK3sKPiArCXN0cnVjdCBvY2Vsb3Rfc3BpX3JlZ21hcF9jb250ZXh0ICpyZWdtYXBf Y29udGV4dCA9IGNvbnRleHQ7Cj4gKwlzdHJ1Y3Qgb2NlbG90X3NwaSAqb2NlbG90X3NwaSA9IHJl Z21hcF9jb250ZXh0LT5vY2Vsb3Rfc3BpOwo+ICsJc3RydWN0IHNwaV90cmFuc2ZlciB0eCwgcGFk ZGluZywgcng7Cj4gKwlzdHJ1Y3Qgc3BpX21lc3NhZ2UgbXNnOwo+ICsJc3RydWN0IHNwaV9kZXZp Y2UgKnNwaTsKPiArCXVuc2lnbmVkIGludCBhZGRyOwo+ICsJdTggKnR4X2J1ZjsKPiArCj4gKwlX QVJOX09OKCF2YWwpOwoKSXMgdGhpcyBwb3NzaWJsZT8KCj4gKwlzcGkgPSBvY2Vsb3Rfc3BpLT5z cGk7Cj4gKwo+ICsJYWRkciA9IG9jZWxvdF9zcGlfdHJhbnNsYXRlX2FkZHJlc3MocmVnICsgcmVn bWFwX2NvbnRleHQtPmJhc2UpOwo+ICsJdHhfYnVmID0gKHU4ICopJmFkZHI7Cj4gKwo+ICsJc3Bp X21lc3NhZ2VfaW5pdCgmbXNnKTsKPiArCj4gKwltZW1zZXQoJnR4LCAwLCBzaXplb2Yoc3RydWN0 IHNwaV90cmFuc2ZlcikpOwo+ICsKPiArCS8qIElnbm9yZSB0aGUgZmlyc3QgYnl0ZSBmb3IgdGhl IDI0LWJpdCBhZGRyZXNzICovCj4gKwl0eC50eF9idWYgPSAmdHhfYnVmWzFdOwo+ICsJdHgubGVu ID0gMzsKPiArCj4gKwlzcGlfbWVzc2FnZV9hZGRfdGFpbCgmdHgsICZtc2cpOwo+ICsKPiArCWlm IChvY2Vsb3Rfc3BpLT5zcGlfcGFkZGluZ19ieXRlcyA+IDApIHsKPiArCQl1OCBkdW1teV9idWZb MTZdID0gezB9Owo+ICsKPiArCQltZW1zZXQoJnBhZGRpbmcsIDAsIHNpemVvZihzdHJ1Y3Qgc3Bp X3RyYW5zZmVyKSk7Cj4gKwo+ICsJCS8qIEp1c3QgdG9nZ2xlIHRoZSBjbG9jayBmb3IgcGFkZGlu ZyBieXRlcyAqLwo+ICsJCXBhZGRpbmcubGVuID0gb2NlbG90X3NwaS0+c3BpX3BhZGRpbmdfYnl0 ZXM7Cj4gKwkJcGFkZGluZy50eF9idWYgPSBkdW1teV9idWY7Cj4gKwkJcGFkZGluZy5kdW1teV9k YXRhID0gMTsKPiArCj4gKwkJc3BpX21lc3NhZ2VfYWRkX3RhaWwoJnBhZGRpbmcsICZtc2cpOwo+ ICsJfQo+ICsKPiArCW1lbXNldCgmcngsIDAsIHNpemVvZihzdHJ1Y3Qgc3BpX3RyYW5zZmVyKSk7 CgpzaXplb2YoKnJ4KQoKPiArCXJ4LnJ4X2J1ZiA9IHZhbDsKPiArCXJ4LmxlbiA9IDQ7Cj4gKwo+ ICsJc3BpX21lc3NhZ2VfYWRkX3RhaWwoJnJ4LCAmbXNnKTsKPiArCj4gKwlyZXR1cm4gc3BpX3N5 bmMoc3BpLCAmbXNnKTsKPiArfQo+ICsKPiArc3RhdGljIGludCBvY2Vsb3Rfc3BpX3JlZ193cml0 ZSh2b2lkICpjb250ZXh0LCB1bnNpZ25lZCBpbnQgcmVnLAo+ICsJCQkJdW5zaWduZWQgaW50IHZh bCkKPiArewo+ICsJc3RydWN0IG9jZWxvdF9zcGlfcmVnbWFwX2NvbnRleHQgKnJlZ21hcF9jb250 ZXh0ID0gY29udGV4dDsKPiArCXN0cnVjdCBvY2Vsb3Rfc3BpICpvY2Vsb3Rfc3BpID0gcmVnbWFw X2NvbnRleHQtPm9jZWxvdF9zcGk7Cj4gKwlzdHJ1Y3Qgc3BpX3RyYW5zZmVyIHR4WzJdID0gezB9 Owo+ICsJc3RydWN0IHNwaV9tZXNzYWdlIG1zZzsKPiArCXN0cnVjdCBzcGlfZGV2aWNlICpzcGk7 Cj4gKwl1bnNpZ25lZCBpbnQgYWRkcjsKPiArCXU4ICp0eF9idWY7Cj4gKwo+ICsJc3BpID0gb2Nl bG90X3NwaS0+c3BpOwo+ICsKPiArCWFkZHIgPSBvY2Vsb3Rfc3BpX3RyYW5zbGF0ZV9hZGRyZXNz KHJlZyArIHJlZ21hcF9jb250ZXh0LT5iYXNlKTsKPiArCXR4X2J1ZiA9ICh1OCAqKSZhZGRyOwo+ ICsKPiArCXNwaV9tZXNzYWdlX2luaXQoJm1zZyk7Cj4gKwo+ICsJLyogSWdub3JlIHRoZSBmaXJz dCBieXRlIGZvciB0aGUgMjQtYml0IGFkZHJlc3MgYW5kIHNldCB0aGUgd3JpdGUgYml0ICovCj4g Kwl0eF9idWZbMV0gfD0gQklUKDcpOwo+ICsJdHhbMF0udHhfYnVmID0gJnR4X2J1ZlsxXTsKPiAr CXR4WzBdLmxlbiA9IDM7Cj4gKwo+ICsJc3BpX21lc3NhZ2VfYWRkX3RhaWwoJnR4WzBdLCAmbXNn KTsKPiArCj4gKwltZW1zZXQoJnR4WzFdLCAwLCBzaXplb2Yoc3RydWN0IHNwaV90cmFuc2Zlcikp Owo+ICsJdHhbMV0udHhfYnVmID0gJnZhbDsKPiArCXR4WzFdLmxlbiA9IDQ7Cj4gKwo+ICsJc3Bp X21lc3NhZ2VfYWRkX3RhaWwoJnR4WzFdLCAmbXNnKTsKPiArCj4gKwlyZXR1cm4gc3BpX3N5bmMo c3BpLCAmbXNnKTsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCByZWdtYXBfY29uZmln IG9jZWxvdF9zcGlfcmVnbWFwX2NvbmZpZyA9IHsKPiArCS5yZWdfYml0cyA9IDI0LAo+ICsJLnJl Z19zdHJpZGUgPSA0LAo+ICsJLnZhbF9iaXRzID0gMzIsCj4gKwo+ICsJLnJlZ19yZWFkID0gb2Nl bG90X3NwaV9yZWdfcmVhZCwKPiArCS5yZWdfd3JpdGUgPSBvY2Vsb3Rfc3BpX3JlZ193cml0ZSwK PiArCj4gKwkubWF4X3JlZ2lzdGVyID0gMHhmZmZmZmZmZiwKPiArCS51c2Vfc2luZ2xlX3dyaXRl ID0gdHJ1ZSwKPiArCS51c2Vfc2luZ2xlX3JlYWQgPSB0cnVlLAo+ICsJLmNhbl9tdWx0aV93cml0 ZSA9IGZhbHNlLAo+ICsKPiArCS5yZWdfZm9ybWF0X2VuZGlhbiA9IFJFR01BUF9FTkRJQU5fQklH LAo+ICsJLnZhbF9mb3JtYXRfZW5kaWFuID0gUkVHTUFQX0VORElBTl9OQVRJVkUsCj4gK307Cj4g Kwo+ICtzdHJ1Y3QgcmVnbWFwICoKPiArb2NlbG90X3NwaV9kZXZtX2dldF9yZWdtYXAoc3RydWN0 IG9jZWxvdF9jb3JlICpjb3JlLCBzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJCSAgIGNvbnN0IHN0 cnVjdCByZXNvdXJjZSAqcmVzKQo+ICt7Cj4gKwlzdHJ1Y3Qgb2NlbG90X3NwaSAqb2NlbG90X3Nw aSA9IGNvcmVfdG9fb2NlbG90X3NwaShjb3JlKTsKPiArCXN0cnVjdCBvY2Vsb3Rfc3BpX3JlZ21h cF9jb250ZXh0ICpjb250ZXh0Owo+ICsJc3RydWN0IHJlZ21hcF9jb25maWcgcmVnbWFwX2NvbmZp ZzsKPiArCXN0cnVjdCByZWdtYXAgKnJlZ21hcDsKPiArCj4gKwljb250ZXh0ID0gZGV2bV9remFs bG9jKGRldiwgc2l6ZW9mKCpjb250ZXh0KSwgR0ZQX0tFUk5FTCk7Cj4gKwlpZiAoSVNfRVJSKGNv bnRleHQpKQo+ICsJCXJldHVybiBFUlJfQ0FTVChjb250ZXh0KTsKPiArCj4gKwljb250ZXh0LT5i YXNlID0gcmVzLT5zdGFydDsKPiArCWNvbnRleHQtPm9jZWxvdF9zcGkgPSBvY2Vsb3Rfc3BpOwo+ ICsKPiArCW1lbWNweSgmcmVnbWFwX2NvbmZpZywgJm9jZWxvdF9zcGlfcmVnbWFwX2NvbmZpZywK PiArCSAgICAgICBzaXplb2Yob2NlbG90X3NwaV9yZWdtYXBfY29uZmlnKSk7Cj4gKwo+ICsJcmVn bWFwX2NvbmZpZy5uYW1lID0gcmVzLT5uYW1lOwo+ICsJcmVnbWFwX2NvbmZpZy5tYXhfcmVnaXN0 ZXIgPSByZXMtPmVuZCAtIHJlcy0+c3RhcnQ7Cj4gKwo+ICsJcmVnbWFwID0gZGV2bV9yZWdtYXBf aW5pdChkZXYsIE5VTEwsIGNvbnRleHQsICZyZWdtYXBfY29uZmlnKTsKPiArCWlmIChJU19FUlIo cmVnbWFwKSkKPiArCQlyZXR1cm4gRVJSX0NBU1QocmVnbWFwKTsKPiArCj4gKwlyZXR1cm4gcmVn bWFwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IG9jZWxvdF9zcGlfcHJvYmUoc3RydWN0IHNwaV9k ZXZpY2UgKnNwaSkKPiArewo+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gJnNwaS0+ZGV2Owo+ICsJ c3RydWN0IG9jZWxvdF9zcGkgKm9jZWxvdF9zcGk7Cj4gKwlpbnQgZXJyOwo+ICsKPiArCW9jZWxv dF9zcGkgPSBkZXZtX2t6YWxsb2MoZGV2LCBzaXplb2YoKm9jZWxvdF9zcGkpLCBHRlBfS0VSTkVM KTsKPiArCj4gKwlpZiAoIW9jZWxvdF9zcGkpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwo+ICsJ aWYgKHNwaS0+bWF4X3NwZWVkX2h6IDw9IDUwMDAwMCkgewo+ICsJCW9jZWxvdF9zcGktPnNwaV9w YWRkaW5nX2J5dGVzID0gMDsKPiArCX0gZWxzZSB7Cj4gKwkJLyoKPiArCQkgKiBDYWxjdWxhdGlv biB0YWtlbiBmcm9tIHRoZSBtYW51YWwgZm9yIElGX0NGR1NUQVQ6SUZfQ0ZHLgo+ICsJCSAqIFJl Z2lzdGVyIGFjY2VzcyB0aW1lIGlzIDF1cywgc28gd2UgbmVlZCB0byBjb25maWd1cmUgYW5kIHNl bmQKPiArCQkgKiBvdXQgZW5vdWdoIHBhZGRpbmcgYnl0ZXMgYmV0d2VlbiB0aGUgcmVhZCByZXF1 ZXN0IGFuZCBkYXRhCj4gKwkJICogdHJhbnNtaXNzaW9uIHRoYXQgbGFzdHMgYXQgbGVhc3QgMSBt aWNyb3NlY29uZC4KPiArCQkgKi8KPiArCQlvY2Vsb3Rfc3BpLT5zcGlfcGFkZGluZ19ieXRlcyA9 IDEgKwo+ICsJCQkoc3BpLT5tYXhfc3BlZWRfaHogLyAxMDAwMDAwICsgMikgLyA4Owo+ICsJfQo+ ICsKPiArCW9jZWxvdF9zcGktPnNwaSA9IHNwaTsKPiArCj4gKwlzcGktPmJpdHNfcGVyX3dvcmQg PSA4Owo+ICsKPiArCWVyciA9IHNwaV9zZXR1cChzcGkpOwo+ICsJaWYgKGVyciA8IDApIHsKPiAr CQlkZXZfZXJyKCZzcGktPmRldiwgIkVycm9yICVkIGluaXRpYWxpemluZyBTUElcbiIsIGVycik7 Cj4gKwkJcmV0dXJuIGVycjsKPiArCX0KPiArCj4gKwlvY2Vsb3Rfc3BpLT5jcHVvcmdfcmVnbWFw ID0KPiArCQlvY2Vsb3Rfc3BpX2Rldm1fZ2V0X3JlZ21hcCgmb2NlbG90X3NwaS0+Y29yZSwgZGV2 LAo+ICsJCQkJCSAgICZ2c2M3NTEyX2Rldl9jcHVvcmdfcmVzb3VyY2UpOwo+ICsJaWYgKCFvY2Vs b3Rfc3BpLT5jcHVvcmdfcmVnbWFwKQoKQW5kIGlmIGFuIGVycm9yIGlzIHJldHVybmVkPwoKPiAr CQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwlvY2Vsb3Rfc3BpLT5jb3JlLmRldiA9IGRldjsKPiAr Cj4gKwkvKgo+ICsJICogVGhlIGNoaXAgbXVzdCBiZSBzZXQgdXAgZm9yIFNQSSBiZWZvcmUgaXQg Z2V0cyBpbml0aWFsaXplZCBhbmQgcmVzZXQuCj4gKwkgKiBUaGlzIG11c3QgYmUgZG9uZSBiZWZv cmUgY2FsbGluZyBpbml0LCBhbmQgYWZ0ZXIgYSBjaGlwIHJlc2V0IGlzCj4gKwkgKiBwZXJmb3Jt ZWQuCj4gKwkgKi8KPiArCWVyciA9IG9jZWxvdF9zcGlfaW5pdF9idXMob2NlbG90X3NwaSk7Cj4g KwlpZiAoZXJyKSB7Cj4gKwkJZGV2X2VycihkZXYsICJFcnJvciAlZCBpbml0aWFsaXppbmcgT2Nl bG90IFNQSSBidXNcbiIsIGVycik7Cj4gKwkJcmV0dXJuIGVycjsKPiArCX0KPiArCj4gKwllcnIg PSBvY2Vsb3RfY29yZV9pbml0KCZvY2Vsb3Rfc3BpLT5jb3JlKTsKPiArCWlmIChlcnIgPCAwKSB7 Cj4gKwkJZGV2X2VycihkZXYsICJFcnJvciAlZCBpbml0aWFsaXppbmcgT2NlbG90IE1GRFxuIiwg ZXJyKTsKPiArCQlyZXR1cm4gZXJyOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgaW50IG9jZWxvdF9zcGlfcmVtb3ZlKHN0cnVjdCBzcGlfZGV2aWNlICpzcGkpCj4g K3sKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtjb25zdCBzdHJ1Y3Qgb2ZfZGV2aWNlX2lkIG9j ZWxvdF9zcGlfb2ZfbWF0Y2hbXSA9IHsKPiArCXsgLmNvbXBhdGlibGUgPSAibXNjYyx2c2M3NTEy X21mZF9zcGkiIH0sCj4gKwl7IH0sCj4gK307Cj4gK01PRFVMRV9ERVZJQ0VfVEFCTEUob2YsIG9j ZWxvdF9zcGlfb2ZfbWF0Y2gpOwo+ICsKPiArc3RhdGljIHN0cnVjdCBzcGlfZHJpdmVyIG9jZWxv dF9zcGlfZHJpdmVyID0gewo+ICsJLmRyaXZlciA9IHsKPiArCQkubmFtZSA9ICJvY2Vsb3RfbWZk X3NwaSIsCj4gKwkJLm9mX21hdGNoX3RhYmxlID0gb2ZfbWF0Y2hfcHRyKG9jZWxvdF9zcGlfb2Zf bWF0Y2gpLAo+ICsJfSwKPiArCS5wcm9iZSA9IG9jZWxvdF9zcGlfcHJvYmUsCj4gKwkucmVtb3Zl ID0gb2NlbG90X3NwaV9yZW1vdmUsCj4gK307Cj4gK21vZHVsZV9zcGlfZHJpdmVyKG9jZWxvdF9z cGlfZHJpdmVyKTsKPiArCj4gK01PRFVMRV9ERVNDUklQVElPTigiT2NlbG90IENoaXAgTUZEIFNQ SSBkcml2ZXIiKTsKPiArTU9EVUxFX0FVVEhPUigiQ29saW4gRm9zdGVyIDxjb2xpbi5mb3N0ZXJA aW4tYWR2YW50YWdlLmNvbT4iKTsKPiArTU9EVUxFX0xJQ0VOU0UoIkR1YWwgTUlUL0dQTCIpOwo+ IGRpZmYgLS1naXQgYS9kcml2ZXJzL21mZC9vY2Vsb3QuaCBiL2RyaXZlcnMvbWZkL29jZWxvdC5o Cj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAwMDAuLjhiYjJiNTcwMDJi ZQo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL21mZC9vY2Vsb3QuaAo+IEBAIC0wLDAg KzEsMzYgQEAKPiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAgT1IgTUlUICov Cj4gKy8qCj4gKyAqIENvcHlyaWdodCAyMDIxIElubm92YXRpdmUgQWR2YW50YWdlIEluYy4KPiAr ICovCj4gKwo+ICsjaW5jbHVkZSA8bGludXgva2NvbmZpZy5oPgo+ICsjaW5jbHVkZSA8bGludXgv cmVnbWFwLmg+Cj4gKwo+ICtzdHJ1Y3Qgb2NlbG90X2NvcmUgewo+ICsJc3RydWN0IGRldmljZSAq ZGV2Owo+ICsJc3RydWN0IHJlZ21hcCAqZ2NiX3JlZ21hcDsKPiArfTsKClBsZWFzZSBkcm9wIHRo aXMgb3Zlci1jb21wbGljYXRlZCAnY29yZScgYW5kICdzcGknIHN0dWZmLgoKWW91IHNwZW5kIHRv byBtdWNoIGVmZm9ydCBjb252ZXJ0aW5nIGJldHdlZW4gJ2RldicsICdjb3JlJyBhbmQgJ3NwaScu CgpJIHN1Z2dlc3QgeW91IGp1c3QgcGFzcyAnZGV2JyBhcm91bmQgYXMgeW91ciBrZXkgcGFyYW1l dGVyLgoKQW55IGFkZGl0aW9uYWwgYXR0cmlidXRlcyB5b3UgKm5lZWQiIHRvIGNhcnJ5IGFyb3Vu ZCBjYW4gZG8gaW46CgogIHN0cnVjdCBvY2Vsb3QgKmRkYXRhOwoKPiArdm9pZCBvY2Vsb3RfZ2V0 X3Jlc291cmNlX25hbWUoY2hhciAqbmFtZSwgY29uc3Qgc3RydWN0IHJlc291cmNlICpyZXMsCj4g KwkJCSAgICAgIGludCBzaXplKTsKPiAraW50IG9jZWxvdF9jb3JlX2luaXQoc3RydWN0IG9jZWxv dF9jb3JlICpjb3JlKTsKPiAraW50IG9jZWxvdF9yZW1vdmUoc3RydWN0IG9jZWxvdF9jb3JlICpj b3JlKTsKPiArCj4gKyNpZiBJU19FTkFCTEVEKENPTkZJR19NRkRfT0NFTE9UX1NQSSkKPiArc3Ry dWN0IHJlZ21hcCAqb2NlbG90X3NwaV9kZXZtX2dldF9yZWdtYXAoc3RydWN0IG9jZWxvdF9jb3Jl ICpjb3JlLAo+ICsJCQkJCSAgc3RydWN0IGRldmljZSAqZGV2LAo+ICsJCQkJCSAgY29uc3Qgc3Ry dWN0IHJlc291cmNlICpyZXMpOwo+ICtpbnQgb2NlbG90X3NwaV9pbml0aWFsaXplKHN0cnVjdCBv Y2Vsb3RfY29yZSAqY29yZSk7Cj4gKyNlbHNlCj4gK3N0YXRpYyBpbmxpbmUgc3RydWN0IHJlZ21h cCAqb2NlbG90X3NwaV9kZXZtX2dldF9yZWdtYXAoCj4gKwkJc3RydWN0IG9jZWxvdF9jb3JlICpj b3JlLCBzdHJ1Y3QgZGV2aWNlICpkZXYsCj4gKwkJY29uc3Qgc3RydWN0IHJlc291cmNlICpyZXMp Cj4gK3sKPiArCXJldHVybiBOVUxMOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIGludCBvY2Vs b3Rfc3BpX2luaXRpYWxpemUoc3RydWN0IG9jZWxvdF9jb3JlICpjb3JlKQo+ICt7Cj4gKwlyZXR1 cm4gLUVPUE5PVFNVUFA7Cj4gK30KPiArI2VuZGlmCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbmV0 L21kaW8vbWRpby1tc2NjLW1paW0uYyBiL2RyaXZlcnMvbmV0L21kaW8vbWRpby1tc2NjLW1paW0u Ywo+IGluZGV4IDA3YmFmODM5MDc0NC4uOGU1NGJkZTA2ZmQ1IDEwMDY0NAo+IC0tLSBhL2RyaXZl cnMvbmV0L21kaW8vbWRpby1tc2NjLW1paW0uYwo+ICsrKyBiL2RyaXZlcnMvbmV0L21kaW8vbWRp by1tc2NjLW1paW0uYwo+IEBAIC0xMSwxMSArMTEsMTMgQEAKPiAgI2luY2x1ZGUgPGxpbnV4L2lv cG9sbC5oPgo+ICAjaW5jbHVkZSA8bGludXgva2VybmVsLmg+Cj4gICNpbmNsdWRlIDxsaW51eC9t ZGlvL21kaW8tbXNjYy1taWltLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9tZmQvY29yZS5oPgo+ICAj aW5jbHVkZSA8bGludXgvbW9kdWxlLmg+Cj4gICNpbmNsdWRlIDxsaW51eC9vZl9tZGlvLmg+Cj4g ICNpbmNsdWRlIDxsaW51eC9waHkuaD4KPiAgI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2Rldmlj ZS5oPgo+ICAjaW5jbHVkZSA8bGludXgvcmVnbWFwLmg+Cj4gKyNpbmNsdWRlIDxzb2MvbXNjYy9v Y2Vsb3QuaD4KPiAgCj4gICNkZWZpbmUgTVNDQ19NSUlNX1JFR19TVEFUVVMJCTB4MAo+ICAjZGVm aW5lCQlNU0NDX01JSU1fU1RBVFVTX1NUQVRfUEVORElORwlCSVQoMikKPiBAQCAtMjMwLDEzICsy MzIsMjAgQEAgc3RhdGljIGludCBtc2NjX21paW1fcHJvYmUoc3RydWN0IHBsYXRmb3JtX2Rldmlj ZSAqcGRldikKPiAgCXN0cnVjdCBtaWlfYnVzICpidXM7Cj4gIAlpbnQgcmV0Owo+ICAKPiAtCXJl Z3MgPSBkZXZtX3BsYXRmb3JtX2dldF9hbmRfaW9yZW1hcF9yZXNvdXJjZShwZGV2LCAwLCBOVUxM KTsKPiAtCWlmIChJU19FUlIocmVncykpIHsKPiAtCQlkZXZfZXJyKGRldiwgIlVuYWJsZSB0byBt YXAgTUlJTSByZWdpc3RlcnNcbiIpOwo+IC0JCXJldHVybiBQVFJfRVJSKHJlZ3MpOwo+IC0JfQo+ ICsJcmVzID0gcGxhdGZvcm1fZ2V0X3Jlc291cmNlKHBkZXYsIElPUkVTT1VSQ0VfTUVNLCAwKTsK PiArCj4gKwlpZiAoIWRldmljZV9pc19tZmQocGRldikpIHsKPiArCQlyZWdzID0gZGV2bV9pb3Jl bWFwX3Jlc291cmNlKGRldiwgcmVzKTsKPiArCQlpZiAoSVNfRVJSKHJlZ3MpKSB7Cj4gKwkJCWRl dl9lcnIoZGV2LCAiVW5hYmxlIHRvIG1hcCBNSUlNIHJlZ2lzdGVyc1xuIik7Cj4gKwkJCXJldHVy biBQVFJfRVJSKHJlZ3MpOwo+ICsJCX0KPiAgCj4gLQltaWlfcmVnbWFwID0gZGV2bV9yZWdtYXBf aW5pdF9tbWlvKGRldiwgcmVncywgJm1zY2NfbWlpbV9yZWdtYXBfY29uZmlnKTsKPiArCQltaWlf cmVnbWFwID0gZGV2bV9yZWdtYXBfaW5pdF9tbWlvKGRldiwgcmVncywKPiArCQkJCQkJICAgJm1z Y2NfbWlpbV9yZWdtYXBfY29uZmlnKTsKClRoZXNlIHRhYnMgbG9vayB3cm9uZy4KCkRvZXNuJ3Qg Y2hlY2twYXRjaC5wbCB3YXJuIGFib3V0IHN0dWZmIGxpa2UgdGhpcz8KPiArCX0gZWxzZSB7Cj4g KwkJbWlpX3JlZ21hcCA9IG9jZWxvdF9nZXRfcmVnbWFwX2Zyb21fcmVzb3VyY2UoZGV2LT5wYXJl bnQsIHJlcyk7Cj4gKwl9CgpZb3UgbmVlZCBhIGNvbW1lbnQgdG8gZXhwbGFpbiB3aHkgeW91J3Jl IGNhbGxpbmcgYm90aCBvZiB0aGVzZS4KCj4gIAlpZiAoSVNfRVJSKG1paV9yZWdtYXApKSB7Cj4g IAkJZGV2X2VycihkZXYsICJVbmFibGUgdG8gY3JlYXRlIE1JSU0gcmVnbWFwXG4iKTsKPiBkaWZm IC0tZ2l0IGEvZHJpdmVycy9waW5jdHJsL3BpbmN0cmwtbWljcm9jaGlwLXNncGlvLmMgYi9kcml2 ZXJzL3BpbmN0cmwvcGluY3RybC1taWNyb2NoaXAtc2dwaW8uYwo+IGluZGV4IDhkYjNjYWYxNWNm Mi4uNTNkZjA5NWIzM2UwIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvcGluY3RybC9waW5jdHJsLW1p Y3JvY2hpcC1zZ3Bpby5jCj4gKysrIGIvZHJpdmVycy9waW5jdHJsL3BpbmN0cmwtbWljcm9jaGlw LXNncGlvLmMKPiBAQCAtMTIsNiArMTIsNyBAQAo+ICAjaW5jbHVkZSA8bGludXgvY2xrLmg+Cj4g ICNpbmNsdWRlIDxsaW51eC9ncGlvL2RyaXZlci5oPgo+ICAjaW5jbHVkZSA8bGludXgvaW8uaD4K PiArI2luY2x1ZGUgPGxpbnV4L21mZC9jb3JlLmg+Cj4gICNpbmNsdWRlIDxsaW51eC9tb2RfZGV2 aWNldGFibGUuaD4KPiAgI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+ICAjaW5jbHVkZSA8bGlu dXgvcGluY3RybC9waW5tdXguaD4KPiBAQCAtMTksNiArMjAsNyBAQAo+ICAjaW5jbHVkZSA8bGlu dXgvcHJvcGVydHkuaD4KPiAgI2luY2x1ZGUgPGxpbnV4L3JlZ21hcC5oPgo+ICAjaW5jbHVkZSA8 bGludXgvcmVzZXQuaD4KPiArI2luY2x1ZGUgPHNvYy9tc2NjL29jZWxvdC5oPgo+ICAKPiAgI2lu Y2x1ZGUgImNvcmUuaCIKPiAgI2luY2x1ZGUgInBpbmNvbmYuaCIKPiBAQCAtMTM3LDcgKzEzOSw5 IEBAIHN0YXRpYyBpbmxpbmUgaW50IHNncGlvX2FkZHJfdG9fcGluKHN0cnVjdCBzZ3Bpb19wcml2 ICpwcml2LCBpbnQgcG9ydCwgaW50IGJpdCkKPiAgCj4gIHN0YXRpYyBpbmxpbmUgdTMyIHNncGlv X2dldF9hZGRyKHN0cnVjdCBzZ3Bpb19wcml2ICpwcml2LCB1MzIgcm5vLCB1MzIgb2ZmKQo+ICB7 Cj4gLQlyZXR1cm4gcHJpdi0+cHJvcGVydGllcy0+cmVnb2ZmW3Jub10gKyBvZmY7Cj4gKwlpbnQg c3RyaWRlID0gcmVnbWFwX2dldF9yZWdfc3RyaWRlKHByaXYtPnJlZ3MpOwo+ICsKPiArCXJldHVy biAocHJpdi0+cHJvcGVydGllcy0+cmVnb2ZmW3Jub10gKyBvZmYpICogc3RyaWRlOwo+ICB9Cj4g IAo+ICBzdGF0aWMgdTMyIHNncGlvX3JlYWRsKHN0cnVjdCBzZ3Bpb19wcml2ICpwcml2LCB1MzIg cm5vLCB1MzIgb2ZmKQo+IEBAIC04MTgsNiArODIyLDcgQEAgc3RhdGljIGludCBtaWNyb2NoaXBf c2dwaW9fcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKPiAgCXN0cnVjdCBmd25v ZGVfaGFuZGxlICpmd25vZGU7Cj4gIAlzdHJ1Y3QgcmVzZXRfY29udHJvbCAqcmVzZXQ7Cj4gIAlz dHJ1Y3Qgc2dwaW9fcHJpdiAqcHJpdjsKPiArCXN0cnVjdCByZXNvdXJjZSAqcmVzOwo+ICAJc3Ry dWN0IGNsayAqY2xrOwo+ICAJdTMyIF9faW9tZW0gKnJlZ3M7Cj4gIAl1MzIgdmFsOwo+IEBAIC04 NTAsMTEgKzg1NSwxOCBAQCBzdGF0aWMgaW50IG1pY3JvY2hpcF9zZ3Bpb19wcm9iZShzdHJ1Y3Qg cGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+ICAJCXJldHVybiAtRUlOVkFMOwo+ICAJfQo+ICAKPiAt CXJlZ3MgPSBkZXZtX3BsYXRmb3JtX2lvcmVtYXBfcmVzb3VyY2UocGRldiwgMCk7Cj4gLQlpZiAo SVNfRVJSKHJlZ3MpKQo+IC0JCXJldHVybiBQVFJfRVJSKHJlZ3MpOwo+ICsJcmVzID0gcGxhdGZv cm1fZ2V0X3Jlc291cmNlKHBkZXYsIElPUkVTT1VSQ0VfTUVNLCAwKTsKPiArCj4gKwlpZiAoIWRl dmljZV9pc19tZmQocGRldikpIHsKPiArCQlyZWdzID0gZGV2bV9pb3JlbWFwX3Jlc291cmNlKGRl diwgcmVzKTsKCldoYXQgaGFwcGVucyBpZiB5b3UgY2FsbCB0aGlzIGlmIHRoZSBkZXZpY2Ugd2Fz IHJlZ2lzdGVyZWQgdmlhIE1GRD8KCj4gKwkJaWYgKElTX0VSUihyZWdzKSkKPiArCQkJcmV0dXJu IFBUUl9FUlIocmVncyk7Cj4gKwo+ICsJCXByaXYtPnJlZ3MgPSBkZXZtX3JlZ21hcF9pbml0X21t aW8oZGV2LCByZWdzLCAmcmVnbWFwX2NvbmZpZyk7Cj4gKwl9IGVsc2Ugewo+ICsJCXByaXYtPnJl Z3MgPSBvY2Vsb3RfZ2V0X3JlZ21hcF9mcm9tX3Jlc291cmNlKGRldi0+cGFyZW50LCByZXMpOwo+ ICsJfQo+ICAKPiAtCXByaXYtPnJlZ3MgPSBkZXZtX3JlZ21hcF9pbml0X21taW8oZGV2LCByZWdz LCAmcmVnbWFwX2NvbmZpZyk7Cj4gIAlpZiAoSVNfRVJSKHByaXYtPnJlZ3MpKQo+ICAJCXJldHVy biBQVFJfRVJSKHByaXYtPnJlZ3MpOwo+ICAKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9waW5jdHJs L3BpbmN0cmwtb2NlbG90LmMgYi9kcml2ZXJzL3BpbmN0cmwvcGluY3RybC1vY2Vsb3QuYwo+IGlu ZGV4IGI2YWQzZmZiNDU5Ni4uZDU0ODVjNmEwZTIwIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvcGlu Y3RybC9waW5jdHJsLW9jZWxvdC5jCj4gKysrIGIvZHJpdmVycy9waW5jdHJsL3BpbmN0cmwtb2Nl bG90LmMKPiBAQCAtMTAsNiArMTAsNyBAQAo+ICAjaW5jbHVkZSA8bGludXgvZ3Bpby9kcml2ZXIu aD4KPiAgI2luY2x1ZGUgPGxpbnV4L2ludGVycnVwdC5oPgo+ICAjaW5jbHVkZSA8bGludXgvaW8u aD4KPiArI2luY2x1ZGUgPGxpbnV4L21mZC9jb3JlLmg+Cj4gICNpbmNsdWRlIDxsaW51eC9vZl9k ZXZpY2UuaD4KPiAgI2luY2x1ZGUgPGxpbnV4L29mX2lycS5oPgo+ICAjaW5jbHVkZSA8bGludXgv b2ZfcGxhdGZvcm0uaD4KPiBAQCAtMjAsNiArMjEsNyBAQAo+ICAjaW5jbHVkZSA8bGludXgvcGxh dGZvcm1fZGV2aWNlLmg+Cj4gICNpbmNsdWRlIDxsaW51eC9yZWdtYXAuaD4KPiAgI2luY2x1ZGUg PGxpbnV4L3NsYWIuaD4KPiArI2luY2x1ZGUgPHNvYy9tc2NjL29jZWxvdC5oPgo+ICAKPiAgI2lu Y2x1ZGUgImNvcmUuaCIKPiAgI2luY2x1ZGUgInBpbmNvbmYuaCIKPiBAQCAtMTEyMyw2ICsxMTI1 LDkgQEAgc3RhdGljIGludCBsYW45NjZ4X3Bpbm11eF9zZXRfbXV4KHN0cnVjdCBwaW5jdHJsX2Rl diAqcGN0bGRldiwKPiAgCXJldHVybiAwOwo+ICB9Cj4gIAo+ICsjaWYgZGVmaW5lZChSRUcpCj4g KyN1bmRlZiBSRUcKPiArI2VuZGlmCj4gICNkZWZpbmUgUkVHKHIsIGluZm8sIHApICgocikgKiAo aW5mbyktPnN0cmlkZSArICg0ICogKChwKSAvIDMyKSkpCj4gIAo+ICBzdGF0aWMgaW50IG9jZWxv dF9ncGlvX3NldF9kaXJlY3Rpb24oc3RydWN0IHBpbmN0cmxfZGV2ICpwY3RsZGV2LAo+IEBAIC0x ODA1LDYgKzE4MTAsNyBAQCBzdGF0aWMgaW50IG9jZWxvdF9waW5jdHJsX3Byb2JlKHN0cnVjdCBw bGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gIAlzdHJ1Y3QgZGV2aWNlICpkZXYgPSAmcGRldi0+ZGV2 Owo+ICAJc3RydWN0IG9jZWxvdF9waW5jdHJsICppbmZvOwo+ICAJc3RydWN0IHJlZ21hcCAqcGlu Y2ZnOwo+ICsJc3RydWN0IHJlc291cmNlICpyZXM7Cj4gIAl2b2lkIF9faW9tZW0gKmJhc2U7Cj4g IAlpbnQgcmV0Owo+ICAJc3RydWN0IHJlZ21hcF9jb25maWcgcmVnbWFwX2NvbmZpZyA9IHsKPiBA QCAtMTgxOSwxNiArMTgyNSwyNyBAQCBzdGF0aWMgaW50IG9jZWxvdF9waW5jdHJsX3Byb2JlKHN0 cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gIAo+ICAJaW5mby0+ZGVzYyA9IChzdHJ1Y3Qg cGluY3RybF9kZXNjICopZGV2aWNlX2dldF9tYXRjaF9kYXRhKGRldik7Cj4gIAo+IC0JYmFzZSA9 IGRldm1faW9yZW1hcF9yZXNvdXJjZShkZXYsCj4gLQkJCXBsYXRmb3JtX2dldF9yZXNvdXJjZShw ZGV2LCBJT1JFU09VUkNFX01FTSwgMCkpOwo+IC0JaWYgKElTX0VSUihiYXNlKSkKPiAtCQlyZXR1 cm4gUFRSX0VSUihiYXNlKTsKPiArCXJlcyA9IHBsYXRmb3JtX2dldF9yZXNvdXJjZShwZGV2LCBJ T1JFU09VUkNFX01FTSwgMCk7Cj4gKwlpZiAoSVNfRVJSKHJlcykpIHsKPiArCQlkZXZfZXJyKGRl diwgIkZhaWxlZCB0byBnZXQgcmVzb3VyY2VcbiIpOwo+ICsJCXJldHVybiBQVFJfRVJSKHJlcyk7 Cj4gKwl9Cj4gIAo+ICAJaW5mby0+c3RyaWRlID0gMSArIChpbmZvLT5kZXNjLT5ucGlucyAtIDEp IC8gMzI7Cj4gIAo+IC0JcmVnbWFwX2NvbmZpZy5tYXhfcmVnaXN0ZXIgPSBPQ0VMT1RfR1BJT19T RF9NQVAgKiBpbmZvLT5zdHJpZGUgKyAxNSAqIDQ7Cj4gKwlpZiAoIWRldmljZV9pc19tZmQocGRl dikpIHsKPiArCQliYXNlID0gZGV2bV9pb3JlbWFwX3Jlc291cmNlKGRldiwgcmVzKTsKPiArCQlp ZiAoSVNfRVJSKGJhc2UpKQo+ICsJCQlyZXR1cm4gUFRSX0VSUihiYXNlKTsKPiArCj4gKwkJcmVn bWFwX2NvbmZpZy5tYXhfcmVnaXN0ZXIgPQo+ICsJCQlPQ0VMT1RfR1BJT19TRF9NQVAgKiBpbmZv LT5zdHJpZGUgKyAxNSAqIDQ7Cj4gKwo+ICsJCWluZm8tPm1hcCA9IGRldm1fcmVnbWFwX2luaXRf bW1pbyhkZXYsIGJhc2UsICZyZWdtYXBfY29uZmlnKTsKPiArCX0gZWxzZSB7Cj4gKwkJaW5mby0+ bWFwID0gb2NlbG90X2dldF9yZWdtYXBfZnJvbV9yZXNvdXJjZShkZXYtPnBhcmVudCwgcmVzKTsK PiArCX0KPiAgCj4gLQlpbmZvLT5tYXAgPSBkZXZtX3JlZ21hcF9pbml0X21taW8oZGV2LCBiYXNl LCAmcmVnbWFwX2NvbmZpZyk7Cj4gIAlpZiAoSVNfRVJSKGluZm8tPm1hcCkpIHsKPiAgCQlkZXZf ZXJyKGRldiwgIkZhaWxlZCB0byBjcmVhdGUgcmVnbWFwXG4iKTsKPiAgCQlyZXR1cm4gUFRSX0VS UihpbmZvLT5tYXApOwo+IGRpZmYgLS1naXQgYS9pbmNsdWRlL3NvYy9tc2NjL29jZWxvdC5oIGIv aW5jbHVkZS9zb2MvbXNjYy9vY2Vsb3QuaAo+IGluZGV4IDVjM2EzNTk3ZjFkMi4uNzBmYWU5Yzhi NjQ5IDEwMDY0NAo+IC0tLSBhL2luY2x1ZGUvc29jL21zY2Mvb2NlbG90LmgKPiArKysgYi9pbmNs dWRlL3NvYy9tc2NjL29jZWxvdC5oCj4gQEAgLTk2OSw0ICs5NjksMTUgQEAgb2NlbG90X21ycF9k ZWxfcmluZ19yb2xlKHN0cnVjdCBvY2Vsb3QgKm9jZWxvdCwgaW50IHBvcnQsCj4gIH0KPiAgI2Vu ZGlmCj4gIAo+ICsjaWYgSVNfRU5BQkxFRChDT05GSUdfTUZEX09DRUxPVCkKPiArc3RydWN0IHJl Z21hcCAqb2NlbG90X2dldF9yZWdtYXBfZnJvbV9yZXNvdXJjZShzdHJ1Y3QgZGV2aWNlICpkZXYs Cj4gKwkJCQkJICAgICAgIGNvbnN0IHN0cnVjdCByZXNvdXJjZSAqcmVzKTsKPiArI2Vsc2UKPiAr c3RhdGljIGlubGluZSBzdHJ1Y3QgcmVnbWFwICoKPiArb2NlbG90X2dldF9yZWdtYXBfZnJvbV9y ZXNvdXJjZShzdHJ1Y3QgZGV2aWNlICpkZXYsIGNvbnN0IHN0cnVjdCByZXNvdXJjZSAqcmVzKQo+ ICt7Cj4gKwlyZXR1cm4gTlVMTDsKPiArfQo+ICsjZW5kaWYKPiArCj4gICNlbmRpZgoKLS0gCkxl ZSBKb25lcyBb5p2O55C85pavXQpQcmluY2lwYWwgVGVjaG5pY2FsIExlYWQgLSBEZXZlbG9wZXIg U2VydmljZXMKTGluYXJvLm9yZyDilIIgT3BlbiBzb3VyY2Ugc29mdHdhcmUgZm9yIEFybSBTb0Nz CkZvbGxvdyBMaW5hcm86IEZhY2Vib29rIHwgVHdpdHRlciB8IEJsb2cKCl9fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGlu ZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMu aW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK