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 E15F0C6FA99 for ; Sun, 5 Mar 2023 10:06:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229563AbjCEKGW (ORCPT ); Sun, 5 Mar 2023 05:06:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52502 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229500AbjCEKGV (ORCPT ); Sun, 5 Mar 2023 05:06:21 -0500 Received: from sin.source.kernel.org (sin.source.kernel.org [145.40.73.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 81F3A1115A; Sun, 5 Mar 2023 02:06:18 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id 14C67CE0025; Sun, 5 Mar 2023 10:06:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5C258C433EF; Sun, 5 Mar 2023 10:06:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1678010774; bh=kpBFMKEBqUkeGuB89D6wba5oBX6H0hX8DrHyUPB0KEg=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=HzkQqG9hdiWmcu7HwW0/Jt/UnZ5T8ng8Twb+8X65VXMwgG/KRAFFfCGkMa/UW5u3t zh/EQoHQTtCysNAcyISiOZl/G8GpZhEGyao7p8N7m4pD2G4gKEbllz9uaENuJJJlTK Xlh/eqvvkno7EsEQIjThOaaBsZ+1G2/TTQXseT1WTPQYL6VCbxwNbjy7ZMg2WPMb2x yOQ/ZywP1iLleH+KxKM8hyQ6KzULDrJ1eKalR1uc18Vf7A+IFrH6CKPJHcYNw+2GKo vA5dOURHpBSZ8m1CDT87XeXm5Xt6eUig5zcbjeaNincjnyZVD8h+pWRtpz36qrhlex W1xdhYvKiewuQ== Date: Sun, 5 Mar 2023 10:06:08 +0000 From: Lee Jones To: ChiaEn Wu Cc: corbet@lwn.net, pavel@ucw.cz, matthias.bgg@gmail.com, andriy.shevchenko@linux.intel.com, jacek.anaszewski@gmail.com, angelogioacchino.delregno@collabora.com, linux-doc@vger.kernel.org, peterwu.pub@gmail.com, cy_huang@richtek.com, linux-leds@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, szunichen@gmail.com, Alice Chen Subject: Re: [PATCH v17 RESEND 2/3] leds: flash: mt6370: Add MediaTek MT6370 flashlight support Message-ID: <20230305100608.GD2574592@google.com> References: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-doc@vger.kernel.org On Thu, 23 Feb 2023, ChiaEn Wu wrote: > From: ChiYuan Huang > > The MediaTek MT6370 is a highly-integrated smart power management IC, > which includes a single cell Li-Ion/Li-Polymer switching battery > charger, a USB Type-C & Power Delivery (PD) controller, dual Flash > LED current sources, a RGB LED driver, a backlight WLED driver, > a display bias driver and a general LDO for portable devices. > > Add support for the MT6370 Flash LED driver. Flash LED in MT6370 > has 2 channels and support torch/strobe mode. > > Acked-by: Jacek Anaszewski > Co-developed-by: Alice Chen > Signed-off-by: Alice Chen > Signed-off-by: ChiYuan Huang > Signed-off-by: ChiaEn Wu > --- > v17 > - Update the year of Copyright from 2022 to 2023 > > --- > drivers/leds/flash/Kconfig | 13 + > drivers/leds/flash/Makefile | 1 + > drivers/leds/flash/leds-mt6370-flash.c | 596 +++++++++++++++++++++++++++++++++ > 3 files changed, 610 insertions(+) > create mode 100644 drivers/leds/flash/leds-mt6370-flash.c Please unwrap to 100-chars throughout. > diff --git a/drivers/leds/flash/Kconfig b/drivers/leds/flash/Kconfig > index d3eb689..49d8922 100644 > --- a/drivers/leds/flash/Kconfig > +++ b/drivers/leds/flash/Kconfig > @@ -61,6 +61,19 @@ config LEDS_MT6360 > Independent current sources supply for each flash LED support torch > and strobe mode. > > +config LEDS_MT6370_FLASH > + tristate "Flash LED Support for MediaTek MT6370 PMIC" > + depends on LEDS_CLASS > + depends on V4L2_FLASH_LED_CLASS || !V4L2_FLASH_LED_CLASS > + depends on MFD_MT6370 > + help > + Support 2 channels and torch/strobe mode. > + Say Y here to enable support for > + MT6370_FLASH_LED device. > + > + This driver can also be built as a module. If so, the module > + will be called "leds-mt6370-flash". > + > config LEDS_RT4505 > tristate "LED support for RT4505 flashlight controller" > depends on I2C && OF > diff --git a/drivers/leds/flash/Makefile b/drivers/leds/flash/Makefile > index 0acbddc..4665e8e 100644 > --- a/drivers/leds/flash/Makefile > +++ b/drivers/leds/flash/Makefile > @@ -1,6 +1,7 @@ > # SPDX-License-Identifier: GPL-2.0 > > obj-$(CONFIG_LEDS_MT6360) += leds-mt6360.o > +obj-$(CONFIG_LEDS_MT6370_FLASH) += leds-mt6370-flash.o > obj-$(CONFIG_LEDS_AAT1290) += leds-aat1290.o > obj-$(CONFIG_LEDS_AS3645A) += leds-as3645a.o > obj-$(CONFIG_LEDS_KTD2692) += leds-ktd2692.o > diff --git a/drivers/leds/flash/leds-mt6370-flash.c b/drivers/leds/flash/leds-mt6370-flash.c > new file mode 100644 > index 00000000..b03617f > --- /dev/null > +++ b/drivers/leds/flash/leds-mt6370-flash.c > @@ -0,0 +1,596 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (C) 2023 Richtek Technology Corp. > + * > + * Authors: > + * Alice Chen > + * ChiYuan Huang > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +enum { > + MT6370_LED_FLASH1 = 0, > + MT6370_LED_FLASH2, > + MT6370_MAX_LEDS > +}; > + > +/* Virtual definition for multicolor */ > + > +#define MT6370_REG_FLEDEN 0x17E > +#define MT6370_REG_STRBTO 0x173 > +#define MT6370_REG_CHGSTAT2 0x1D1 > +#define MT6370_REG_FLEDSTAT1 0x1D9 > +#define MT6370_REG_FLEDISTRB(_id) (0x174 + 4 * (_id)) > +#define MT6370_REG_FLEDITOR(_id) (0x175 + 4 * (_id)) > +#define MT6370_ITORCH_MASK GENMASK(4, 0) > +#define MT6370_ISTROBE_MASK GENMASK(6, 0) > +#define MT6370_STRBTO_MASK GENMASK(6, 0) > +#define MT6370_TORCHEN_MASK BIT(3) > +#define MT6370_STROBEN_MASK BIT(2) > +#define MT6370_FLCSEN_MASK(_id) BIT(MT6370_LED_FLASH2 - (_id)) > +#define MT6370_FLCSEN_MASK_ALL GENMASK(1, 0) > +#define MT6370_FLEDCHGVINOVP_MASK BIT(3) > +#define MT6370_FLED1STRBTO_MASK BIT(11) > +#define MT6370_FLED2STRBTO_MASK BIT(10) > +#define MT6370_FLED1STRB_MASK BIT(9) > +#define MT6370_FLED2STRB_MASK BIT(8) > +#define MT6370_FLED1SHORT_MASK BIT(7) > +#define MT6370_FLED2SHORT_MASK BIT(6) > +#define MT6370_FLEDLVF_MASK BIT(3) > + > +#define MT6370_LED_JOINT 2 > +#define MT6370_RANGE_FLED_REG 4 > +#define MT6370_ITORCH_MIN_uA 25000 > +#define MT6370_ITORCH_STEP_uA 12500 > +#define MT6370_ITORCH_MAX_uA 400000 > +#define MT6370_ITORCH_DOUBLE_MAX_uA 800000 > +#define MT6370_ISTRB_MIN_uA 50000 > +#define MT6370_ISTRB_STEP_uA 12500 > +#define MT6370_ISTRB_MAX_uA 1500000 > +#define MT6370_ISTRB_DOUBLE_MAX_uA 3000000 > +#define MT6370_STRBTO_MIN_US 64000 > +#define MT6370_STRBTO_STEP_US 32000 > +#define MT6370_STRBTO_MAX_US 2432000 > + > +#define to_mt6370_led(ptr, member) container_of(ptr, struct mt6370_led, member) > + > +struct mt6370_led { > + struct led_classdev_flash flash; > + struct v4l2_flash *v4l2_flash; > + struct mt6370_priv *priv; > + u8 led_no; > +}; > + > +struct mt6370_priv { > + struct regmap *regmap; > + struct mutex lock; > + unsigned int fled_strobe_used; > + unsigned int fled_torch_used; > + unsigned int leds_active; > + unsigned int leds_count; > + struct mt6370_led leds[]; > +}; > + > +static int mt6370_torch_brightness_set(struct led_classdev *lcdev, > + enum led_brightness level) > +{ > + struct mt6370_led *led = to_mt6370_led(lcdev, flash.led_cdev); > + struct mt6370_priv *priv = led->priv; > + u32 led_enable_mask = led->led_no == MT6370_LED_JOINT ? > + MT6370_FLCSEN_MASK_ALL : > + MT6370_FLCSEN_MASK(led->led_no); > + u32 enable_mask = MT6370_TORCHEN_MASK | led_enable_mask; > + u32 val = level ? led_enable_mask : 0; > + u32 curr; > + int ret, i; > + > + mutex_lock(&priv->lock); > + > + /* > + * There is only one set of flash control logic, and this > + * flag is used to check if 'strobe' is currently being used. > + */ > + if (priv->fled_strobe_used) { > + dev_warn(lcdev->dev, "Please disable strobe first [%d]\n", > + priv->fled_strobe_used); > + ret = -EBUSY; > + goto unlock; > + } > + > + if (level) > + curr = priv->fled_torch_used | BIT(led->led_no); > + else > + curr = priv->fled_torch_used & ~BIT(led->led_no); > + > + if (curr) > + val |= MT6370_TORCHEN_MASK; > + > + if (level) { > + level -= 1; > + if (led->led_no == MT6370_LED_JOINT) { > + u32 flevel[MT6370_MAX_LEDS]; > + > + flevel[0] = level / 2; > + flevel[1] = level - flevel[0]; > + for (i = 0; i < MT6370_MAX_LEDS; i++) { > + ret = regmap_update_bits(priv->regmap, > + MT6370_REG_FLEDITOR(i), > + MT6370_ITORCH_MASK, flevel[i]); > + if (ret) > + goto unlock; > + } > + } else { > + ret = regmap_update_bits(priv->regmap, > + MT6370_REG_FLEDITOR(led->led_no), > + MT6370_ITORCH_MASK, level); > + if (ret) > + goto unlock; > + } > + } > + > + ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, > + enable_mask, val); > + if (ret) > + goto unlock; > + > + priv->fled_torch_used = curr; > + > +unlock: > + mutex_unlock(&priv->lock); > + return ret; > +} > + > +static int mt6370_flash_brightness_set(struct led_classdev_flash *fl_cdev, > + u32 brightness) > +{ > + /* > + * Because of the current spikes when turning on the flash, > + * the brightness should be kept by the LED framework. This > + * empty function is used to prevent checking failure when > + * led_classdev_flash registers ops. > + */ > + return 0; > +} > + > +static int _mt6370_flash_brightness_set(struct led_classdev_flash *fl_cdev, > + u32 brightness) > +{ > + struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); > + struct mt6370_priv *priv = led->priv; > + struct led_flash_setting *setting = &fl_cdev->brightness; > + u32 val = (brightness - setting->min) / setting->step; > + int ret, i; > + > + if (led->led_no == MT6370_LED_JOINT) { What is a "JOINT"? > + u32 flevel[MT6370_MAX_LEDS]; > + > + flevel[0] = val / 2; > + flevel[1] = val - flevel[0]; Please provide a comment describing what's going on here. > + for (i = 0; i < MT6370_MAX_LEDS; i++) { > + ret = regmap_update_bits(priv->regmap, > + MT6370_REG_FLEDISTRB(i), > + MT6370_ISTROBE_MASK, flevel[i]); > + if (ret) > + break; > + } > + } else > + ret = regmap_update_bits(priv->regmap, > + MT6370_REG_FLEDISTRB(led->led_no), > + MT6370_ISTROBE_MASK, val); > + > + return ret; > +} > + > +static int mt6370_strobe_set(struct led_classdev_flash *fl_cdev, bool state) > +{ > + struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); > + struct mt6370_priv *priv = led->priv; > + struct led_classdev *lcdev = &fl_cdev->led_cdev; > + struct led_flash_setting *s = &fl_cdev->brightness; > + u32 led_enable_mask = led->led_no == MT6370_LED_JOINT ? > + MT6370_FLCSEN_MASK_ALL : > + MT6370_FLCSEN_MASK(led->led_no); > + u32 enable_mask = MT6370_STROBEN_MASK | led_enable_mask; > + u32 val = state ? led_enable_mask : 0; > + u32 curr; > + int ret; > + > + mutex_lock(&priv->lock); > + > + /* > + * There is only one set of flash control logic, and this > + * flag is used to check if 'torch' is currently being used. > + */ > + if (priv->fled_torch_used) { > + dev_warn(lcdev->dev, "Please disable torch first [0x%x]\n", > + priv->fled_torch_used); > + ret = -EBUSY; > + goto unlock; > + } > + > + if (state) > + curr = priv->fled_strobe_used | BIT(led->led_no); > + else > + curr = priv->fled_strobe_used & ~BIT(led->led_no); > + > + if (curr) > + val |= MT6370_STROBEN_MASK; > + > + ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, enable_mask, > + val); > + if (ret) { > + dev_err(lcdev->dev, "[%d] control current source %d fail\n", > + led->led_no, state); > + goto unlock; > + } > + > + /* > + * If the flash needs to turn on, configure the flash current to > + * ramp up to the setting value. Otherwise, always revert to the > + * minimum one. > + */ > + ret = _mt6370_flash_brightness_set(fl_cdev, state ? s->val : s->min); > + if (ret) { > + dev_err(lcdev->dev, "[%d] Failed to set brightness\n", led->led_no); > + goto unlock; > + } > + > + /* > + * For the flash to turn on/off, we must wait for HW ramping > + * up/down time 5ms/500us to prevent the unexpected problem. > + */ > + if (!priv->fled_strobe_used && curr) > + usleep_range(5000, 6000); > + else if (priv->fled_strobe_used && !curr) > + usleep_range(500, 600); > + > + priv->fled_strobe_used = curr; > + > +unlock: > + mutex_unlock(&priv->lock); > + return ret; > +} > + > +static int mt6370_strobe_get(struct led_classdev_flash *fl_cdev, bool *state) > +{ > + struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); > + struct mt6370_priv *priv = led->priv; > + > + mutex_lock(&priv->lock); > + *state = !!(priv->fled_strobe_used & BIT(led->led_no)); > + mutex_unlock(&priv->lock); > + > + return 0; > +} > + > +static int mt6370_timeout_set(struct led_classdev_flash *fl_cdev, u32 timeout) > +{ > + struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); > + struct mt6370_priv *priv = led->priv; > + struct led_flash_setting *s = &fl_cdev->timeout; > + u32 val = (timeout - s->min) / s->step; > + > + return regmap_update_bits(priv->regmap, MT6370_REG_STRBTO, > + MT6370_STRBTO_MASK, val); > +} > + > +static int mt6370_fault_get(struct led_classdev_flash *fl_cdev, u32 *fault) > +{ > + struct mt6370_led *led = to_mt6370_led(fl_cdev, flash); > + struct mt6370_priv *priv = led->priv; > + u16 fled_stat; > + unsigned int chg_stat, strobe_timeout_mask, fled_short_mask; > + u32 rfault = 0; > + int ret; > + > + ret = regmap_read(priv->regmap, MT6370_REG_CHGSTAT2, &chg_stat); > + if (ret) > + return ret; > + > + ret = regmap_raw_read(priv->regmap, MT6370_REG_FLEDSTAT1, &fled_stat, > + sizeof(fled_stat)); > + if (ret) > + return ret; > + > + switch (led->led_no) { > + case MT6370_LED_FLASH1: > + strobe_timeout_mask = MT6370_FLED1STRBTO_MASK; > + fled_short_mask = MT6370_FLED1SHORT_MASK; > + break; > + > + case MT6370_LED_FLASH2: > + strobe_timeout_mask = MT6370_FLED2STRBTO_MASK; > + fled_short_mask = MT6370_FLED2SHORT_MASK; > + break; > + > + case MT6370_LED_JOINT: > + strobe_timeout_mask = MT6370_FLED1STRBTO_MASK | > + MT6370_FLED2STRBTO_MASK; > + fled_short_mask = MT6370_FLED1SHORT_MASK | > + MT6370_FLED2SHORT_MASK; > + break; > + default: > + return -EINVAL; > + } > + > + if (chg_stat & MT6370_FLEDCHGVINOVP_MASK) > + rfault |= LED_FAULT_INPUT_VOLTAGE; > + > + if (fled_stat & strobe_timeout_mask) > + rfault |= LED_FAULT_TIMEOUT; > + > + if (fled_stat & fled_short_mask) > + rfault |= LED_FAULT_SHORT_CIRCUIT; > + > + if (fled_stat & MT6370_FLEDLVF_MASK) > + rfault |= LED_FAULT_UNDER_VOLTAGE; > + > + *fault = rfault; > + return ret; > +} > + > +static const struct led_flash_ops mt6370_flash_ops = { > + .flash_brightness_set = mt6370_flash_brightness_set, > + .strobe_set = mt6370_strobe_set, > + .strobe_get = mt6370_strobe_get, > + .timeout_set = mt6370_timeout_set, > + .fault_get = mt6370_fault_get, > +}; > + > +#if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS) > +static int mt6370_flash_external_strobe_set(struct v4l2_flash *v4l2_flash, > + bool enable) > +{ > + struct led_classdev_flash *flash = v4l2_flash->fled_cdev; > + struct mt6370_led *led = to_mt6370_led(flash, flash); > + struct mt6370_priv *priv = led->priv; > + u32 mask = led->led_no == MT6370_LED_JOINT ? MT6370_FLCSEN_MASK_ALL : > + MT6370_FLCSEN_MASK(led->led_no); > + u32 val = enable ? mask : 0; > + int ret; > + > + mutex_lock(&priv->lock); > + > + ret = regmap_update_bits(priv->regmap, MT6370_REG_FLEDEN, mask, val); > + if (ret) > + goto unlock; > + > + if (enable) > + priv->fled_strobe_used |= BIT(led->led_no); > + else > + priv->fled_strobe_used &= ~BIT(led->led_no); > + > +unlock: > + mutex_unlock(&priv->lock); > + return ret; > +} > + > +static const struct v4l2_flash_ops v4l2_flash_ops = { > + .external_strobe_set = mt6370_flash_external_strobe_set, > +}; > + > +static void mt6370_init_v4l2_flash_config(struct mt6370_led *led, > + struct v4l2_flash_config *cfg) > +{ > + struct led_classdev *lcdev; > + struct led_flash_setting *s = &cfg->intensity; > + > + lcdev = &led->flash.led_cdev; > + > + s->min = MT6370_ITORCH_MIN_uA; > + s->step = MT6370_ITORCH_STEP_uA; > + s->val = s->max = s->min + (lcdev->max_brightness - 1) * s->step; > + > + cfg->has_external_strobe = 1; has_external_strobe is a bool. > + strscpy(cfg->dev_name, dev_name(lcdev->dev), sizeof(cfg->dev_name)); > + > + cfg->flash_faults = LED_FAULT_SHORT_CIRCUIT | LED_FAULT_TIMEOUT | > + LED_FAULT_INPUT_VOLTAGE | LED_FAULT_UNDER_VOLTAGE; > +} > +#else > +static const struct v4l2_flash_ops v4l2_flash_ops; > +static void mt6370_init_v4l2_flash_config(struct mt6370_led *led, > + struct v4l2_flash_config *cfg) > +{ > +} > +#endif > + > +static void mt6370_v4l2_flash_release(void *v4l2_flash) > +{ > + v4l2_flash_release(v4l2_flash); > +} > + > +static int mt6370_led_register(struct device *parent, struct mt6370_led *led, > + struct fwnode_handle *fwnode) > +{ > + struct led_init_data init_data = { .fwnode = fwnode }; > + struct v4l2_flash_config v4l2_config = {}; > + int ret; > + > + ret = devm_led_classdev_flash_register_ext(parent, &led->flash, > + &init_data); > + if (ret) > + return dev_err_probe(parent, ret, > + "Couldn't register flash %d\n", led->led_no); > + > + mt6370_init_v4l2_flash_config(led, &v4l2_config); > + led->v4l2_flash = v4l2_flash_init(parent, fwnode, &led->flash, > + &v4l2_flash_ops, &v4l2_config); > + if (IS_ERR(led->v4l2_flash)) > + return dev_err_probe(parent, PTR_ERR(led->v4l2_flash), > + "Failed to register %d v4l2 sd\n", led->led_no); > + > + return devm_add_action_or_reset(parent, mt6370_v4l2_flash_release, > + led->v4l2_flash); > +} > + > +static u32 mt6370_clamp(u32 val, u32 min, u32 max, u32 step) > +{ > + u32 retval; > + > + retval = clamp_val(val, min, max); > + if (step > 1) > + retval = rounddown(retval - min, step) + min; > + > + return retval; > +} > + > +static int mt6370_init_flash_properties(struct device *dev, > + struct mt6370_led *led, > + struct fwnode_handle *fwnode) > +{ > + struct led_classdev_flash *flash = &led->flash; > + struct led_classdev *lcdev = &flash->led_cdev; > + struct mt6370_priv *priv = led->priv; > + struct led_flash_setting *s; > + u32 sources[MT6370_MAX_LEDS]; > + u32 max_ua, val; > + int i, ret, num; > + > + num = fwnode_property_count_u32(fwnode, "led-sources"); > + if (num < 1) > + return dev_err_probe(dev, -EINVAL, > + "Not specified or wrong number of led-sources\n"); > + > + ret = fwnode_property_read_u32_array(fwnode, "led-sources", sources, num); > + if (ret) > + return ret; > + > + for (i = 0; i < num; i++) { > + if (sources[i] >= MT6370_MAX_LEDS) > + return -EINVAL; > + if (priv->leds_active & BIT(sources[i])) > + return -EINVAL; > + priv->leds_active |= BIT(sources[i]); > + } > + > + led->led_no = num == 2 ? MT6370_LED_JOINT : sources[0]; > + > + max_ua = num == 2 ? MT6370_ITORCH_DOUBLE_MAX_uA : MT6370_ITORCH_MAX_uA; > + val = MT6370_ITORCH_MIN_uA; In what scenario does this not get overwritten? > + ret = fwnode_property_read_u32(fwnode, "led-max-microamp", &val); > + if (!ret) > + val = mt6370_clamp(val, MT6370_ITORCH_MIN_uA, max_ua, > + MT6370_ITORCH_STEP_uA); > + > + lcdev->max_brightness = (val - MT6370_ITORCH_MIN_uA) / > + MT6370_ITORCH_STEP_uA + 1; > + lcdev->brightness_set_blocking = mt6370_torch_brightness_set; > + lcdev->flags |= LED_DEV_CAP_FLASH; > + > + max_ua = num == 2 ? MT6370_ISTRB_DOUBLE_MAX_uA : MT6370_ISTRB_MAX_uA; > + val = MT6370_ISTRB_MIN_uA; > + ret = fwnode_property_read_u32(fwnode, "flash-max-microamp", &val); > + if (!ret) > + val = mt6370_clamp(val, MT6370_ISTRB_MIN_uA, max_ua, > + MT6370_ISTRB_STEP_uA); > + > + s = &flash->brightness; > + s->min = MT6370_ISTRB_MIN_uA; > + s->step = MT6370_ISTRB_STEP_uA; > + s->val = s->max = val; > + > + /* > + * Always configure to the minimum level when > + * off to prevent flash current spikes. > + */ > + ret = _mt6370_flash_brightness_set(flash, s->min); > + if (ret) > + return ret; > + > + > + val = MT6370_STRBTO_MIN_US; As above. > + ret = fwnode_property_read_u32(fwnode, "flash-max-timeout-us", &val); > + if (!ret) > + val = mt6370_clamp(val, MT6370_STRBTO_MIN_US, > + MT6370_STRBTO_MAX_US, MT6370_STRBTO_STEP_US); > + > + s = &flash->timeout; > + s->min = MT6370_STRBTO_MIN_US; > + s->step = MT6370_STRBTO_STEP_US; > + s->val = s->max = val; > + > + flash->ops = &mt6370_flash_ops; > + > + return 0; > +} > + > +static int mt6370_led_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct mt6370_priv *priv; > + struct fwnode_handle *child; > + size_t count; > + int i = 0, ret; > + > + count = device_get_child_node_count(dev); > + if (!count || count > MT6370_MAX_LEDS) > + return dev_err_probe(dev, -EINVAL, > + "No child node or node count over max led number %zu\n", count); > + > + priv = devm_kzalloc(dev, struct_size(priv, leds, count), GFP_KERNEL); > + if (!priv) > + return -ENOMEM; > + > + priv->leds_count = count; > + mutex_init(&priv->lock); > + > + priv->regmap = dev_get_regmap(dev->parent, NULL); > + if (!priv->regmap) > + return dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n"); > + > + device_for_each_child_node(dev, child) { > + struct mt6370_led *led = priv->leds + i; > + > + led->priv = priv; > + > + ret = mt6370_init_flash_properties(dev, led, child); > + if (ret) { > + fwnode_handle_put(child); > + return ret; > + } > + > + ret = mt6370_led_register(dev, led, child); > + if (ret) { > + fwnode_handle_put(child); > + return ret; > + } > + > + i++; > + } > + > + return 0; > +} > + > +static const struct of_device_id mt6370_led_of_id[] = { > + { .compatible = "mediatek,mt6370-flashlight" }, > + { /* sentinel */ } Please remove this comment. We know how NULL terminators work. :) > +}; > +MODULE_DEVICE_TABLE(of, mt6370_led_of_id); > + > +static struct platform_driver mt6370_led_driver = { > + .driver = { > + .name = "mt6370-flashlight", > + .of_match_table = mt6370_led_of_id, > + }, > + .probe = mt6370_led_probe, > +}; > +module_platform_driver(mt6370_led_driver); > + > +MODULE_AUTHOR("Alice Chen "); > +MODULE_AUTHOR("ChiYuan Huang "); > +MODULE_DESCRIPTION("MT6370 FLASH LED Driver"); > +MODULE_LICENSE("GPL"); > -- > 2.7.4 > -- Lee Jones [李琼斯] 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 37A4AC61DA4 for ; Sun, 5 Mar 2023 10:07:35 +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=erE6Qpy0Gg7VE86gO7GsJVfpSV72lWxtc8LOxD9pm2k=; b=ylJOHXbaEKNp2y KMooiVT6b2Nu2o+xaYZcEH3I3+6D4ikKZjdVq17XsEMeRrxVdNAcZR0i6lsCk/pNiTzoYs2uo+JKA xfhfT++/vtHf407O0XkPr9RLKo4O9v+hqMEX4hr4B/LYX4sETUvmvJoOGv9b6SB4CxV/irMw/9JY6 2FE0Wxgx55PFpRudumIxCXuE+W21YmEC9pnFcVQodayzHvTDRhl07hU27HsvFo4DTH7YVk7G7ICxx 8hiB92PIuqtlHVbT9+oVpAJy5Myh0hL4a3gf3krCUuOGkqYSBQQ5ubYO3ZSEi7SNl48NNVLe+cAUx qkOVZ7YNOLHA0Lcad9dg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pYlFz-00A4JP-F2; Sun, 05 Mar 2023 10:06:19 +0000 Received: from dfw.source.kernel.org ([2604:1380:4641:c500::1]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1pYlFv-00A4Is-Lc; Sun, 05 Mar 2023 10:06:18 +0000 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id C68A560ADD; Sun, 5 Mar 2023 10:06:14 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5C258C433EF; Sun, 5 Mar 2023 10:06:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1678010774; bh=kpBFMKEBqUkeGuB89D6wba5oBX6H0hX8DrHyUPB0KEg=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=HzkQqG9hdiWmcu7HwW0/Jt/UnZ5T8ng8Twb+8X65VXMwgG/KRAFFfCGkMa/UW5u3t zh/EQoHQTtCysNAcyISiOZl/G8GpZhEGyao7p8N7m4pD2G4gKEbllz9uaENuJJJlTK Xlh/eqvvkno7EsEQIjThOaaBsZ+1G2/TTQXseT1WTPQYL6VCbxwNbjy7ZMg2WPMb2x yOQ/ZywP1iLleH+KxKM8hyQ6KzULDrJ1eKalR1uc18Vf7A+IFrH6CKPJHcYNw+2GKo vA5dOURHpBSZ8m1CDT87XeXm5Xt6eUig5zcbjeaNincjnyZVD8h+pWRtpz36qrhlex W1xdhYvKiewuQ== Date: Sun, 5 Mar 2023 10:06:08 +0000 From: Lee Jones To: ChiaEn Wu Cc: corbet@lwn.net, pavel@ucw.cz, matthias.bgg@gmail.com, andriy.shevchenko@linux.intel.com, jacek.anaszewski@gmail.com, angelogioacchino.delregno@collabora.com, linux-doc@vger.kernel.org, peterwu.pub@gmail.com, cy_huang@richtek.com, linux-leds@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, szunichen@gmail.com, Alice Chen Subject: Re: [PATCH v17 RESEND 2/3] leds: flash: mt6370: Add MediaTek MT6370 flashlight support Message-ID: <20230305100608.GD2574592@google.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230305_020615_848744_27A03BE7 X-CRM114-Status: GOOD ( 41.48 ) 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 T24gVGh1LCAyMyBGZWIgMjAyMywgQ2hpYUVuIFd1IHdyb3RlOgoKPiBGcm9tOiBDaGlZdWFuIEh1 YW5nIDxjeV9odWFuZ0ByaWNodGVrLmNvbT4KPiAKPiBUaGUgTWVkaWFUZWsgTVQ2MzcwIGlzIGEg aGlnaGx5LWludGVncmF0ZWQgc21hcnQgcG93ZXIgbWFuYWdlbWVudCBJQywKPiB3aGljaCBpbmNs dWRlcyBhIHNpbmdsZSBjZWxsIExpLUlvbi9MaS1Qb2x5bWVyIHN3aXRjaGluZyBiYXR0ZXJ5Cj4g Y2hhcmdlciwgYSBVU0IgVHlwZS1DICYgUG93ZXIgRGVsaXZlcnkgKFBEKSBjb250cm9sbGVyLCBk dWFsIEZsYXNoCj4gTEVEIGN1cnJlbnQgc291cmNlcywgYSBSR0IgTEVEIGRyaXZlciwgYSBiYWNr bGlnaHQgV0xFRCBkcml2ZXIsCj4gYSBkaXNwbGF5IGJpYXMgZHJpdmVyIGFuZCBhIGdlbmVyYWwg TERPIGZvciBwb3J0YWJsZSBkZXZpY2VzLgo+IAo+IEFkZCBzdXBwb3J0IGZvciB0aGUgTVQ2Mzcw IEZsYXNoIExFRCBkcml2ZXIuIEZsYXNoIExFRCBpbiBNVDYzNzAKPiBoYXMgMiBjaGFubmVscyBh bmQgc3VwcG9ydCB0b3JjaC9zdHJvYmUgbW9kZS4KPiAKPiBBY2tlZC1ieTogSmFjZWsgQW5hc3pl d3NraSA8amFjZWsuYW5hc3pld3NraUBnbWFpbC5jb20+Cj4gQ28tZGV2ZWxvcGVkLWJ5OiBBbGlj ZSBDaGVuIDxhbGljZV9jaGVuQHJpY2h0ZWsuY29tPgo+IFNpZ25lZC1vZmYtYnk6IEFsaWNlIENo ZW4gPGFsaWNlX2NoZW5AcmljaHRlay5jb20+Cj4gU2lnbmVkLW9mZi1ieTogQ2hpWXVhbiBIdWFu ZyA8Y3lfaHVhbmdAcmljaHRlay5jb20+Cj4gU2lnbmVkLW9mZi1ieTogQ2hpYUVuIFd1IDxjaGlh ZW5fd3VAcmljaHRlay5jb20+Cj4gLS0tCj4gdjE3Cj4gLSBVcGRhdGUgdGhlIHllYXIgb2YgQ29w eXJpZ2h0IGZyb20gMjAyMiB0byAyMDIzCj4gCj4gLS0tCj4gIGRyaXZlcnMvbGVkcy9mbGFzaC9L Y29uZmlnICAgICAgICAgICAgIHwgIDEzICsKPiAgZHJpdmVycy9sZWRzL2ZsYXNoL01ha2VmaWxl ICAgICAgICAgICAgfCAgIDEgKwo+ICBkcml2ZXJzL2xlZHMvZmxhc2gvbGVkcy1tdDYzNzAtZmxh c2guYyB8IDU5NiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKPiAgMyBmaWxlcyBj aGFuZ2VkLCA2MTAgaW5zZXJ0aW9ucygrKQo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9s ZWRzL2ZsYXNoL2xlZHMtbXQ2MzcwLWZsYXNoLmMKClBsZWFzZSB1bndyYXAgdG8gMTAwLWNoYXJz IHRocm91Z2hvdXQuCiAKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9sZWRzL2ZsYXNoL0tjb25maWcg Yi9kcml2ZXJzL2xlZHMvZmxhc2gvS2NvbmZpZwo+IGluZGV4IGQzZWI2ODkuLjQ5ZDg5MjIgMTAw NjQ0Cj4gLS0tIGEvZHJpdmVycy9sZWRzL2ZsYXNoL0tjb25maWcKPiArKysgYi9kcml2ZXJzL2xl ZHMvZmxhc2gvS2NvbmZpZwo+IEBAIC02MSw2ICs2MSwxOSBAQCBjb25maWcgTEVEU19NVDYzNjAK PiAgCSAgSW5kZXBlbmRlbnQgY3VycmVudCBzb3VyY2VzIHN1cHBseSBmb3IgZWFjaCBmbGFzaCBM RUQgc3VwcG9ydCB0b3JjaAo+ICAJICBhbmQgc3Ryb2JlIG1vZGUuCj4gIAo+ICtjb25maWcgTEVE U19NVDYzNzBfRkxBU0gKPiArCXRyaXN0YXRlICJGbGFzaCBMRUQgU3VwcG9ydCBmb3IgTWVkaWFU ZWsgTVQ2MzcwIFBNSUMiCj4gKwlkZXBlbmRzIG9uIExFRFNfQ0xBU1MKPiArCWRlcGVuZHMgb24g VjRMMl9GTEFTSF9MRURfQ0xBU1MgfHwgIVY0TDJfRkxBU0hfTEVEX0NMQVNTCj4gKwlkZXBlbmRz IG9uIE1GRF9NVDYzNzAKPiArCWhlbHAKPiArCSAgU3VwcG9ydCAyIGNoYW5uZWxzIGFuZCB0b3Jj aC9zdHJvYmUgbW9kZS4KPiArCSAgU2F5IFkgaGVyZSB0byBlbmFibGUgc3VwcG9ydCBmb3IKPiAr CSAgTVQ2MzcwX0ZMQVNIX0xFRCBkZXZpY2UuCj4gKwo+ICsJICBUaGlzIGRyaXZlciBjYW4gYWxz byBiZSBidWlsdCBhcyBhIG1vZHVsZS4gSWYgc28sIHRoZSBtb2R1bGUKPiArCSAgd2lsbCBiZSBj YWxsZWQgImxlZHMtbXQ2MzcwLWZsYXNoIi4KPiArCj4gIGNvbmZpZyBMRURTX1JUNDUwNQo+ICAJ dHJpc3RhdGUgIkxFRCBzdXBwb3J0IGZvciBSVDQ1MDUgZmxhc2hsaWdodCBjb250cm9sbGVyIgo+ ICAJZGVwZW5kcyBvbiBJMkMgJiYgT0YKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9sZWRzL2ZsYXNo L01ha2VmaWxlIGIvZHJpdmVycy9sZWRzL2ZsYXNoL01ha2VmaWxlCj4gaW5kZXggMGFjYmRkYy4u NDY2NWU4ZSAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL2xlZHMvZmxhc2gvTWFrZWZpbGUKPiArKysg Yi9kcml2ZXJzL2xlZHMvZmxhc2gvTWFrZWZpbGUKPiBAQCAtMSw2ICsxLDcgQEAKPiAgIyBTUERY LUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAo+ICAKPiAgb2JqLSQoQ09ORklHX0xFRFNfTVQ2 MzYwKQkrPSBsZWRzLW10NjM2MC5vCj4gK29iai0kKENPTkZJR19MRURTX01UNjM3MF9GTEFTSCkJ Kz0gbGVkcy1tdDYzNzAtZmxhc2gubwo+ICBvYmotJChDT05GSUdfTEVEU19BQVQxMjkwKQkrPSBs ZWRzLWFhdDEyOTAubwo+ICBvYmotJChDT05GSUdfTEVEU19BUzM2NDVBKQkrPSBsZWRzLWFzMzY0 NWEubwo+ICBvYmotJChDT05GSUdfTEVEU19LVEQyNjkyKQkrPSBsZWRzLWt0ZDI2OTIubwo+IGRp ZmYgLS1naXQgYS9kcml2ZXJzL2xlZHMvZmxhc2gvbGVkcy1tdDYzNzAtZmxhc2guYyBiL2RyaXZl cnMvbGVkcy9mbGFzaC9sZWRzLW10NjM3MC1mbGFzaC5jCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQK PiBpbmRleCAwMDAwMDAwMC4uYjAzNjE3Zgo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJz L2xlZHMvZmxhc2gvbGVkcy1tdDYzNzAtZmxhc2guYwo+IEBAIC0wLDAgKzEsNTk2IEBACj4gKy8v IFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wLW9ubHkKPiArLyoKPiArICogQ29weXJp Z2h0IChDKSAyMDIzIFJpY2h0ZWsgVGVjaG5vbG9neSBDb3JwLgo+ICsgKgo+ICsgKiBBdXRob3Jz Ogo+ICsgKiAgIEFsaWNlIENoZW4gPGFsaWNlX2NoZW5AcmljaHRlay5jb20+Cj4gKyAqICAgQ2hp WXVhbiBIdWFuZyA8Y3lfaHVhbmdAcmljaHRlay5jb20+Cj4gKyAqLwo+ICsKPiArI2luY2x1ZGUg PGxpbnV4L2JpdG9wcy5oPgo+ICsjaW5jbHVkZSA8bGludXgvZGVsYXkuaD4KPiArI2luY2x1ZGUg PGxpbnV4L2luaXQuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2ludGVycnVwdC5oPgo+ICsjaW5jbHVk ZSA8bGludXgva2VybmVsLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9sZWQtY2xhc3MtZmxhc2guaD4K PiArI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvbXV0ZXguaD4K PiArI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPgo+ICsjaW5jbHVkZSA8bGludXgv cHJvcGVydHkuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3JlZ21hcC5oPgo+ICsKPiArI2luY2x1ZGUg PG1lZGlhL3Y0bDItZmxhc2gtbGVkLWNsYXNzLmg+Cj4gKwo+ICtlbnVtIHsKPiArCU1UNjM3MF9M RURfRkxBU0gxID0gMCwKPiArCU1UNjM3MF9MRURfRkxBU0gyLAo+ICsJTVQ2MzcwX01BWF9MRURT Cj4gK307Cj4gKwo+ICsvKiBWaXJ0dWFsIGRlZmluaXRpb24gZm9yIG11bHRpY29sb3IgKi8KPiAr Cj4gKyNkZWZpbmUgTVQ2MzcwX1JFR19GTEVERU4JCTB4MTdFCj4gKyNkZWZpbmUgTVQ2MzcwX1JF R19TVFJCVE8JCTB4MTczCj4gKyNkZWZpbmUgTVQ2MzcwX1JFR19DSEdTVEFUMgkJMHgxRDEKPiAr I2RlZmluZSBNVDYzNzBfUkVHX0ZMRURTVEFUMQkJMHgxRDkKPiArI2RlZmluZSBNVDYzNzBfUkVH X0ZMRURJU1RSQihfaWQpCSgweDE3NCArIDQgKiAoX2lkKSkKPiArI2RlZmluZSBNVDYzNzBfUkVH X0ZMRURJVE9SKF9pZCkJKDB4MTc1ICsgNCAqIChfaWQpKQo+ICsjZGVmaW5lIE1UNjM3MF9JVE9S Q0hfTUFTSwkJR0VOTUFTSyg0LCAwKQo+ICsjZGVmaW5lIE1UNjM3MF9JU1RST0JFX01BU0sJCUdF Tk1BU0soNiwgMCkKPiArI2RlZmluZSBNVDYzNzBfU1RSQlRPX01BU0sJCUdFTk1BU0soNiwgMCkK PiArI2RlZmluZSBNVDYzNzBfVE9SQ0hFTl9NQVNLCQlCSVQoMykKPiArI2RlZmluZSBNVDYzNzBf U1RST0JFTl9NQVNLCQlCSVQoMikKPiArI2RlZmluZSBNVDYzNzBfRkxDU0VOX01BU0soX2lkKQkJ QklUKE1UNjM3MF9MRURfRkxBU0gyIC0gKF9pZCkpCj4gKyNkZWZpbmUgTVQ2MzcwX0ZMQ1NFTl9N QVNLX0FMTAkJR0VOTUFTSygxLCAwKQo+ICsjZGVmaW5lIE1UNjM3MF9GTEVEQ0hHVklOT1ZQX01B U0sJQklUKDMpCj4gKyNkZWZpbmUgTVQ2MzcwX0ZMRUQxU1RSQlRPX01BU0sJCUJJVCgxMSkKPiAr I2RlZmluZSBNVDYzNzBfRkxFRDJTVFJCVE9fTUFTSwkJQklUKDEwKQo+ICsjZGVmaW5lIE1UNjM3 MF9GTEVEMVNUUkJfTUFTSwkJQklUKDkpCj4gKyNkZWZpbmUgTVQ2MzcwX0ZMRUQyU1RSQl9NQVNL CQlCSVQoOCkKPiArI2RlZmluZSBNVDYzNzBfRkxFRDFTSE9SVF9NQVNLCQlCSVQoNykKPiArI2Rl ZmluZSBNVDYzNzBfRkxFRDJTSE9SVF9NQVNLCQlCSVQoNikKPiArI2RlZmluZSBNVDYzNzBfRkxF RExWRl9NQVNLCQlCSVQoMykKPiArCj4gKyNkZWZpbmUgTVQ2MzcwX0xFRF9KT0lOVAkJMgo+ICsj ZGVmaW5lIE1UNjM3MF9SQU5HRV9GTEVEX1JFRwkJNAo+ICsjZGVmaW5lIE1UNjM3MF9JVE9SQ0hf TUlOX3VBCQkyNTAwMAo+ICsjZGVmaW5lIE1UNjM3MF9JVE9SQ0hfU1RFUF91QQkJMTI1MDAKPiAr I2RlZmluZSBNVDYzNzBfSVRPUkNIX01BWF91QQkJNDAwMDAwCj4gKyNkZWZpbmUgTVQ2MzcwX0lU T1JDSF9ET1VCTEVfTUFYX3VBCTgwMDAwMAo+ICsjZGVmaW5lIE1UNjM3MF9JU1RSQl9NSU5fdUEJ CTUwMDAwCj4gKyNkZWZpbmUgTVQ2MzcwX0lTVFJCX1NURVBfdUEJCTEyNTAwCj4gKyNkZWZpbmUg TVQ2MzcwX0lTVFJCX01BWF91QQkJMTUwMDAwMAo+ICsjZGVmaW5lIE1UNjM3MF9JU1RSQl9ET1VC TEVfTUFYX3VBCTMwMDAwMDAKPiArI2RlZmluZSBNVDYzNzBfU1RSQlRPX01JTl9VUwkJNjQwMDAK PiArI2RlZmluZSBNVDYzNzBfU1RSQlRPX1NURVBfVVMJCTMyMDAwCj4gKyNkZWZpbmUgTVQ2Mzcw X1NUUkJUT19NQVhfVVMJCTI0MzIwMDAKPiArCj4gKyNkZWZpbmUgdG9fbXQ2MzcwX2xlZChwdHIs IG1lbWJlcikgY29udGFpbmVyX29mKHB0ciwgc3RydWN0IG10NjM3MF9sZWQsIG1lbWJlcikKPiAr Cj4gK3N0cnVjdCBtdDYzNzBfbGVkIHsKPiArCXN0cnVjdCBsZWRfY2xhc3NkZXZfZmxhc2ggZmxh c2g7Cj4gKwlzdHJ1Y3QgdjRsMl9mbGFzaCAqdjRsMl9mbGFzaDsKPiArCXN0cnVjdCBtdDYzNzBf cHJpdiAqcHJpdjsKPiArCXU4IGxlZF9ubzsKPiArfTsKPiArCj4gK3N0cnVjdCBtdDYzNzBfcHJp diB7Cj4gKwlzdHJ1Y3QgcmVnbWFwICpyZWdtYXA7Cj4gKwlzdHJ1Y3QgbXV0ZXggbG9jazsKPiAr CXVuc2lnbmVkIGludCBmbGVkX3N0cm9iZV91c2VkOwo+ICsJdW5zaWduZWQgaW50IGZsZWRfdG9y Y2hfdXNlZDsKPiArCXVuc2lnbmVkIGludCBsZWRzX2FjdGl2ZTsKPiArCXVuc2lnbmVkIGludCBs ZWRzX2NvdW50Owo+ICsJc3RydWN0IG10NjM3MF9sZWQgbGVkc1tdOwo+ICt9Owo+ICsKPiArc3Rh dGljIGludCBtdDYzNzBfdG9yY2hfYnJpZ2h0bmVzc19zZXQoc3RydWN0IGxlZF9jbGFzc2RldiAq bGNkZXYsCj4gKwkJCQkgICAgICAgZW51bSBsZWRfYnJpZ2h0bmVzcyBsZXZlbCkKPiArewo+ICsJ c3RydWN0IG10NjM3MF9sZWQgKmxlZCA9IHRvX210NjM3MF9sZWQobGNkZXYsIGZsYXNoLmxlZF9j ZGV2KTsKPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9IGxlZC0+cHJpdjsKPiArCXUzMiBs ZWRfZW5hYmxlX21hc2sgPSBsZWQtPmxlZF9ubyA9PSBNVDYzNzBfTEVEX0pPSU5UID8KPiArCQkJ ICAgICAgTVQ2MzcwX0ZMQ1NFTl9NQVNLX0FMTCA6Cj4gKwkJCSAgICAgIE1UNjM3MF9GTENTRU5f TUFTSyhsZWQtPmxlZF9ubyk7Cj4gKwl1MzIgZW5hYmxlX21hc2sgPSBNVDYzNzBfVE9SQ0hFTl9N QVNLIHwgbGVkX2VuYWJsZV9tYXNrOwo+ICsJdTMyIHZhbCA9IGxldmVsID8gbGVkX2VuYWJsZV9t YXNrIDogMDsKPiArCXUzMiBjdXJyOwo+ICsJaW50IHJldCwgaTsKPiArCj4gKwltdXRleF9sb2Nr KCZwcml2LT5sb2NrKTsKPiArCj4gKwkvKgo+ICsJICogVGhlcmUgaXMgb25seSBvbmUgc2V0IG9m IGZsYXNoIGNvbnRyb2wgbG9naWMsIGFuZCB0aGlzCj4gKwkgKiBmbGFnIGlzIHVzZWQgdG8gY2hl Y2sgaWYgJ3N0cm9iZScgaXMgY3VycmVudGx5IGJlaW5nIHVzZWQuCj4gKwkgKi8KPiArCWlmIChw cml2LT5mbGVkX3N0cm9iZV91c2VkKSB7Cj4gKwkJZGV2X3dhcm4obGNkZXYtPmRldiwgIlBsZWFz ZSBkaXNhYmxlIHN0cm9iZSBmaXJzdCBbJWRdXG4iLAo+ICsJCQkgcHJpdi0+ZmxlZF9zdHJvYmVf dXNlZCk7Cj4gKwkJcmV0ID0gLUVCVVNZOwo+ICsJCWdvdG8gdW5sb2NrOwo+ICsJfQo+ICsKPiAr CWlmIChsZXZlbCkKPiArCQljdXJyID0gcHJpdi0+ZmxlZF90b3JjaF91c2VkIHwgQklUKGxlZC0+ bGVkX25vKTsKPiArCWVsc2UKPiArCQljdXJyID0gcHJpdi0+ZmxlZF90b3JjaF91c2VkICYgfkJJ VChsZWQtPmxlZF9ubyk7Cj4gKwo+ICsJaWYgKGN1cnIpCj4gKwkJdmFsIHw9IE1UNjM3MF9UT1JD SEVOX01BU0s7Cj4gKwo+ICsJaWYgKGxldmVsKSB7Cj4gKwkJbGV2ZWwgLT0gMTsKPiArCQlpZiAo bGVkLT5sZWRfbm8gPT0gTVQ2MzcwX0xFRF9KT0lOVCkgewo+ICsJCQl1MzIgZmxldmVsW01UNjM3 MF9NQVhfTEVEU107Cj4gKwo+ICsJCQlmbGV2ZWxbMF0gPSBsZXZlbCAvIDI7Cj4gKwkJCWZsZXZl bFsxXSA9IGxldmVsIC0gZmxldmVsWzBdOwo+ICsJCQlmb3IgKGkgPSAwOyBpIDwgTVQ2MzcwX01B WF9MRURTOyBpKyspIHsKPiArCQkJCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhwcml2LT5yZWdt YXAsCj4gKwkJCQkJCU1UNjM3MF9SRUdfRkxFRElUT1IoaSksCj4gKwkJCQkJCU1UNjM3MF9JVE9S Q0hfTUFTSywgZmxldmVsW2ldKTsKPiArCQkJCWlmIChyZXQpCj4gKwkJCQkJZ290byB1bmxvY2s7 Cj4gKwkJCX0KPiArCQl9IGVsc2Ugewo+ICsJCQlyZXQgPSByZWdtYXBfdXBkYXRlX2JpdHMocHJp di0+cmVnbWFwLAo+ICsJCQkJCU1UNjM3MF9SRUdfRkxFRElUT1IobGVkLT5sZWRfbm8pLAo+ICsJ CQkJCU1UNjM3MF9JVE9SQ0hfTUFTSywgbGV2ZWwpOwo+ICsJCQlpZiAocmV0KQo+ICsJCQkJZ290 byB1bmxvY2s7Cj4gKwkJfQo+ICsJfQo+ICsKPiArCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhw cml2LT5yZWdtYXAsIE1UNjM3MF9SRUdfRkxFREVOLAo+ICsJCQkJIGVuYWJsZV9tYXNrLCB2YWwp Owo+ICsJaWYgKHJldCkKPiArCQlnb3RvIHVubG9jazsKPiArCj4gKwlwcml2LT5mbGVkX3RvcmNo X3VzZWQgPSBjdXJyOwo+ICsKPiArdW5sb2NrOgo+ICsJbXV0ZXhfdW5sb2NrKCZwcml2LT5sb2Nr KTsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgbXQ2MzcwX2ZsYXNoX2Jy aWdodG5lc3Nfc2V0KHN0cnVjdCBsZWRfY2xhc3NkZXZfZmxhc2ggKmZsX2NkZXYsCj4gKwkJCQkg ICAgICAgdTMyIGJyaWdodG5lc3MpCj4gK3sKPiArCS8qCj4gKwkgKiBCZWNhdXNlIG9mIHRoZSBj dXJyZW50IHNwaWtlcyB3aGVuIHR1cm5pbmcgb24gdGhlIGZsYXNoLAo+ICsJICogdGhlIGJyaWdo dG5lc3Mgc2hvdWxkIGJlIGtlcHQgYnkgdGhlIExFRCBmcmFtZXdvcmsuIFRoaXMKPiArCSAqIGVt cHR5IGZ1bmN0aW9uIGlzIHVzZWQgdG8gcHJldmVudCBjaGVja2luZyBmYWlsdXJlIHdoZW4KPiAr CSAqIGxlZF9jbGFzc2Rldl9mbGFzaCByZWdpc3RlcnMgb3BzLgo+ICsJICovCj4gKwlyZXR1cm4g MDsKPiArfQo+ICsKPiArc3RhdGljIGludCBfbXQ2MzcwX2ZsYXNoX2JyaWdodG5lc3Nfc2V0KHN0 cnVjdCBsZWRfY2xhc3NkZXZfZmxhc2ggKmZsX2NkZXYsCj4gKwkJCQkJdTMyIGJyaWdodG5lc3Mp Cj4gK3sKPiArCXN0cnVjdCBtdDYzNzBfbGVkICpsZWQgPSB0b19tdDYzNzBfbGVkKGZsX2NkZXYs IGZsYXNoKTsKPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9IGxlZC0+cHJpdjsKPiArCXN0 cnVjdCBsZWRfZmxhc2hfc2V0dGluZyAqc2V0dGluZyA9ICZmbF9jZGV2LT5icmlnaHRuZXNzOwo+ ICsJdTMyIHZhbCA9IChicmlnaHRuZXNzIC0gc2V0dGluZy0+bWluKSAvIHNldHRpbmctPnN0ZXA7 Cj4gKwlpbnQgcmV0LCBpOwo+ICsKPiArCWlmIChsZWQtPmxlZF9ubyA9PSBNVDYzNzBfTEVEX0pP SU5UKSB7CgpXaGF0IGlzIGEgIkpPSU5UIj8KCj4gKwkJdTMyIGZsZXZlbFtNVDYzNzBfTUFYX0xF RFNdOwo+ICsKPiArCQlmbGV2ZWxbMF0gPSB2YWwgLyAyOwo+ICsJCWZsZXZlbFsxXSA9IHZhbCAt IGZsZXZlbFswXTsKClBsZWFzZSBwcm92aWRlIGEgY29tbWVudCBkZXNjcmliaW5nIHdoYXQncyBn b2luZyBvbiBoZXJlLgoKPiArCQlmb3IgKGkgPSAwOyBpIDwgTVQ2MzcwX01BWF9MRURTOyBpKysp IHsKPiArCQkJcmV0ID0gcmVnbWFwX3VwZGF0ZV9iaXRzKHByaXYtPnJlZ21hcCwKPiArCQkJCQkJ IE1UNjM3MF9SRUdfRkxFRElTVFJCKGkpLAo+ICsJCQkJCQkgTVQ2MzcwX0lTVFJPQkVfTUFTSywg ZmxldmVsW2ldKTsKPiArCQkJaWYgKHJldCkKPiArCQkJCWJyZWFrOwo+ICsJCX0KPiArCX0gZWxz ZQo+ICsJCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhwcml2LT5yZWdtYXAsCj4gKwkJCQkJIE1U NjM3MF9SRUdfRkxFRElTVFJCKGxlZC0+bGVkX25vKSwKPiArCQkJCQkgTVQ2MzcwX0lTVFJPQkVf TUFTSywgdmFsKTsKPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IG10 NjM3MF9zdHJvYmVfc2V0KHN0cnVjdCBsZWRfY2xhc3NkZXZfZmxhc2ggKmZsX2NkZXYsIGJvb2wg c3RhdGUpCj4gK3sKPiArCXN0cnVjdCBtdDYzNzBfbGVkICpsZWQgPSB0b19tdDYzNzBfbGVkKGZs X2NkZXYsIGZsYXNoKTsKPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9IGxlZC0+cHJpdjsK PiArCXN0cnVjdCBsZWRfY2xhc3NkZXYgKmxjZGV2ID0gJmZsX2NkZXYtPmxlZF9jZGV2Owo+ICsJ c3RydWN0IGxlZF9mbGFzaF9zZXR0aW5nICpzID0gJmZsX2NkZXYtPmJyaWdodG5lc3M7Cj4gKwl1 MzIgbGVkX2VuYWJsZV9tYXNrID0gbGVkLT5sZWRfbm8gPT0gTVQ2MzcwX0xFRF9KT0lOVCA/Cj4g KwkJCSAgICAgIE1UNjM3MF9GTENTRU5fTUFTS19BTEwgOgo+ICsJCQkgICAgICBNVDYzNzBfRkxD U0VOX01BU0sobGVkLT5sZWRfbm8pOwo+ICsJdTMyIGVuYWJsZV9tYXNrID0gTVQ2MzcwX1NUUk9C RU5fTUFTSyB8IGxlZF9lbmFibGVfbWFzazsKPiArCXUzMiB2YWwgPSBzdGF0ZSA/IGxlZF9lbmFi bGVfbWFzayA6IDA7Cj4gKwl1MzIgY3VycjsKPiArCWludCByZXQ7Cj4gKwo+ICsJbXV0ZXhfbG9j aygmcHJpdi0+bG9jayk7Cj4gKwo+ICsJLyoKPiArCSAqIFRoZXJlIGlzIG9ubHkgb25lIHNldCBv ZiBmbGFzaCBjb250cm9sIGxvZ2ljLCBhbmQgdGhpcwo+ICsJICogZmxhZyBpcyB1c2VkIHRvIGNo ZWNrIGlmICd0b3JjaCcgaXMgY3VycmVudGx5IGJlaW5nIHVzZWQuCj4gKwkgKi8KPiArCWlmIChw cml2LT5mbGVkX3RvcmNoX3VzZWQpIHsKPiArCQlkZXZfd2FybihsY2Rldi0+ZGV2LCAiUGxlYXNl IGRpc2FibGUgdG9yY2ggZmlyc3QgWzB4JXhdXG4iLAo+ICsJCQkJICAgICAgcHJpdi0+ZmxlZF90 b3JjaF91c2VkKTsKPiArCQlyZXQgPSAtRUJVU1k7Cj4gKwkJZ290byB1bmxvY2s7Cj4gKwl9Cj4g Kwo+ICsJaWYgKHN0YXRlKQo+ICsJCWN1cnIgPSBwcml2LT5mbGVkX3N0cm9iZV91c2VkIHwgQklU KGxlZC0+bGVkX25vKTsKPiArCWVsc2UKPiArCQljdXJyID0gcHJpdi0+ZmxlZF9zdHJvYmVfdXNl ZCAmIH5CSVQobGVkLT5sZWRfbm8pOwo+ICsKPiArCWlmIChjdXJyKQo+ICsJCXZhbCB8PSBNVDYz NzBfU1RST0JFTl9NQVNLOwo+ICsKPiArCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhwcml2LT5y ZWdtYXAsIE1UNjM3MF9SRUdfRkxFREVOLCBlbmFibGVfbWFzaywKPiArCQkJCSB2YWwpOwo+ICsJ aWYgKHJldCkgewo+ICsJCWRldl9lcnIobGNkZXYtPmRldiwgIlslZF0gY29udHJvbCBjdXJyZW50 IHNvdXJjZSAlZCBmYWlsXG4iLAo+ICsJCQkJICAgICBsZWQtPmxlZF9ubywgc3RhdGUpOwo+ICsJ CWdvdG8gdW5sb2NrOwo+ICsJfQo+ICsKPiArCS8qCj4gKwkgKiBJZiB0aGUgZmxhc2ggbmVlZHMg dG8gdHVybiBvbiwgY29uZmlndXJlIHRoZSBmbGFzaCBjdXJyZW50IHRvCj4gKwkgKiByYW1wIHVw IHRvIHRoZSBzZXR0aW5nIHZhbHVlLiBPdGhlcndpc2UsIGFsd2F5cyByZXZlcnQgdG8gdGhlCj4g KwkgKiBtaW5pbXVtIG9uZS4KPiArCSAqLwo+ICsJcmV0ID0gX210NjM3MF9mbGFzaF9icmlnaHRu ZXNzX3NldChmbF9jZGV2LCBzdGF0ZSA/IHMtPnZhbCA6IHMtPm1pbik7Cj4gKwlpZiAocmV0KSB7 Cj4gKwkJZGV2X2VycihsY2Rldi0+ZGV2LCAiWyVkXSBGYWlsZWQgdG8gc2V0IGJyaWdodG5lc3Nc biIsIGxlZC0+bGVkX25vKTsKPiArCQlnb3RvIHVubG9jazsKPiArCX0KPiArCj4gKwkvKgo+ICsJ ICogRm9yIHRoZSBmbGFzaCB0byB0dXJuIG9uL29mZiwgd2UgbXVzdCB3YWl0IGZvciBIVyByYW1w aW5nCj4gKwkgKiB1cC9kb3duIHRpbWUgNW1zLzUwMHVzIHRvIHByZXZlbnQgdGhlIHVuZXhwZWN0 ZWQgcHJvYmxlbS4KPiArCSAqLwo+ICsJaWYgKCFwcml2LT5mbGVkX3N0cm9iZV91c2VkICYmIGN1 cnIpCj4gKwkJdXNsZWVwX3JhbmdlKDUwMDAsIDYwMDApOwo+ICsJZWxzZSBpZiAocHJpdi0+Zmxl ZF9zdHJvYmVfdXNlZCAmJiAhY3VycikKPiArCQl1c2xlZXBfcmFuZ2UoNTAwLCA2MDApOwo+ICsK PiArCXByaXYtPmZsZWRfc3Ryb2JlX3VzZWQgPSBjdXJyOwo+ICsKPiArdW5sb2NrOgo+ICsJbXV0 ZXhfdW5sb2NrKCZwcml2LT5sb2NrKTsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRp YyBpbnQgbXQ2MzcwX3N0cm9iZV9nZXQoc3RydWN0IGxlZF9jbGFzc2Rldl9mbGFzaCAqZmxfY2Rl diwgYm9vbCAqc3RhdGUpCj4gK3sKPiArCXN0cnVjdCBtdDYzNzBfbGVkICpsZWQgPSB0b19tdDYz NzBfbGVkKGZsX2NkZXYsIGZsYXNoKTsKPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9IGxl ZC0+cHJpdjsKPiArCj4gKwltdXRleF9sb2NrKCZwcml2LT5sb2NrKTsKPiArCSpzdGF0ZSA9ICEh KHByaXYtPmZsZWRfc3Ryb2JlX3VzZWQgJiBCSVQobGVkLT5sZWRfbm8pKTsKPiArCW11dGV4X3Vu bG9jaygmcHJpdi0+bG9jayk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBp bnQgbXQ2MzcwX3RpbWVvdXRfc2V0KHN0cnVjdCBsZWRfY2xhc3NkZXZfZmxhc2ggKmZsX2NkZXYs IHUzMiB0aW1lb3V0KQo+ICt7Cj4gKwlzdHJ1Y3QgbXQ2MzcwX2xlZCAqbGVkID0gdG9fbXQ2Mzcw X2xlZChmbF9jZGV2LCBmbGFzaCk7Cj4gKwlzdHJ1Y3QgbXQ2MzcwX3ByaXYgKnByaXYgPSBsZWQt PnByaXY7Cj4gKwlzdHJ1Y3QgbGVkX2ZsYXNoX3NldHRpbmcgKnMgPSAmZmxfY2Rldi0+dGltZW91 dDsKPiArCXUzMiB2YWwgPSAodGltZW91dCAtIHMtPm1pbikgLyBzLT5zdGVwOwo+ICsKPiArCXJl dHVybiByZWdtYXBfdXBkYXRlX2JpdHMocHJpdi0+cmVnbWFwLCBNVDYzNzBfUkVHX1NUUkJUTywK PiArCQkJCSAgTVQ2MzcwX1NUUkJUT19NQVNLLCB2YWwpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50 IG10NjM3MF9mYXVsdF9nZXQoc3RydWN0IGxlZF9jbGFzc2Rldl9mbGFzaCAqZmxfY2RldiwgdTMy ICpmYXVsdCkKPiArewo+ICsJc3RydWN0IG10NjM3MF9sZWQgKmxlZCA9IHRvX210NjM3MF9sZWQo ZmxfY2RldiwgZmxhc2gpOwo+ICsJc3RydWN0IG10NjM3MF9wcml2ICpwcml2ID0gbGVkLT5wcml2 Owo+ICsJdTE2IGZsZWRfc3RhdDsKPiArCXVuc2lnbmVkIGludCBjaGdfc3RhdCwgc3Ryb2JlX3Rp bWVvdXRfbWFzaywgZmxlZF9zaG9ydF9tYXNrOwo+ICsJdTMyIHJmYXVsdCA9IDA7Cj4gKwlpbnQg cmV0Owo+ICsKPiArCXJldCA9IHJlZ21hcF9yZWFkKHByaXYtPnJlZ21hcCwgTVQ2MzcwX1JFR19D SEdTVEFUMiwgJmNoZ19zdGF0KTsKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4g KwlyZXQgPSByZWdtYXBfcmF3X3JlYWQocHJpdi0+cmVnbWFwLCBNVDYzNzBfUkVHX0ZMRURTVEFU MSwgJmZsZWRfc3RhdCwKPiArCQkJICAgICAgc2l6ZW9mKGZsZWRfc3RhdCkpOwo+ICsJaWYgKHJl dCkKPiArCQlyZXR1cm4gcmV0Owo+ICsKPiArCXN3aXRjaCAobGVkLT5sZWRfbm8pIHsKPiArCWNh c2UgTVQ2MzcwX0xFRF9GTEFTSDE6Cj4gKwkJc3Ryb2JlX3RpbWVvdXRfbWFzayA9IE1UNjM3MF9G TEVEMVNUUkJUT19NQVNLOwo+ICsJCWZsZWRfc2hvcnRfbWFzayA9IE1UNjM3MF9GTEVEMVNIT1JU X01BU0s7Cj4gKwkJYnJlYWs7Cj4gKwo+ICsJY2FzZSBNVDYzNzBfTEVEX0ZMQVNIMjoKPiArCQlz dHJvYmVfdGltZW91dF9tYXNrID0gTVQ2MzcwX0ZMRUQyU1RSQlRPX01BU0s7Cj4gKwkJZmxlZF9z aG9ydF9tYXNrID0gTVQ2MzcwX0ZMRUQyU0hPUlRfTUFTSzsKPiArCQlicmVhazsKPiArCj4gKwlj YXNlIE1UNjM3MF9MRURfSk9JTlQ6Cj4gKwkJc3Ryb2JlX3RpbWVvdXRfbWFzayA9IE1UNjM3MF9G TEVEMVNUUkJUT19NQVNLIHwKPiArCQkJCSAgICAgIE1UNjM3MF9GTEVEMlNUUkJUT19NQVNLOwo+ ICsJCWZsZWRfc2hvcnRfbWFzayA9IE1UNjM3MF9GTEVEMVNIT1JUX01BU0sgfAo+ICsJCQkJICBN VDYzNzBfRkxFRDJTSE9SVF9NQVNLOwo+ICsJCWJyZWFrOwo+ICsJZGVmYXVsdDoKPiArCQlyZXR1 cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlpZiAoY2hnX3N0YXQgJiBNVDYzNzBfRkxFRENIR1ZJ Tk9WUF9NQVNLKQo+ICsJCXJmYXVsdCB8PSBMRURfRkFVTFRfSU5QVVRfVk9MVEFHRTsKPiArCj4g KwlpZiAoZmxlZF9zdGF0ICYgc3Ryb2JlX3RpbWVvdXRfbWFzaykKPiArCQlyZmF1bHQgfD0gTEVE X0ZBVUxUX1RJTUVPVVQ7Cj4gKwo+ICsJaWYgKGZsZWRfc3RhdCAmIGZsZWRfc2hvcnRfbWFzaykK PiArCQlyZmF1bHQgfD0gTEVEX0ZBVUxUX1NIT1JUX0NJUkNVSVQ7Cj4gKwo+ICsJaWYgKGZsZWRf c3RhdCAmIE1UNjM3MF9GTEVETFZGX01BU0spCj4gKwkJcmZhdWx0IHw9IExFRF9GQVVMVF9VTkRF Ul9WT0xUQUdFOwo+ICsKPiArCSpmYXVsdCA9IHJmYXVsdDsKPiArCXJldHVybiByZXQ7Cj4gK30K PiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgbGVkX2ZsYXNoX29wcyBtdDYzNzBfZmxhc2hfb3Bz ID0gewo+ICsJLmZsYXNoX2JyaWdodG5lc3Nfc2V0ID0gbXQ2MzcwX2ZsYXNoX2JyaWdodG5lc3Nf c2V0LAo+ICsJLnN0cm9iZV9zZXQgPSBtdDYzNzBfc3Ryb2JlX3NldCwKPiArCS5zdHJvYmVfZ2V0 ID0gbXQ2MzcwX3N0cm9iZV9nZXQsCj4gKwkudGltZW91dF9zZXQgPSBtdDYzNzBfdGltZW91dF9z ZXQsCj4gKwkuZmF1bHRfZ2V0ID0gbXQ2MzcwX2ZhdWx0X2dldCwKPiArfTsKPiArCj4gKyNpZiBJ U19FTkFCTEVEKENPTkZJR19WNEwyX0ZMQVNIX0xFRF9DTEFTUykKPiArc3RhdGljIGludCBtdDYz NzBfZmxhc2hfZXh0ZXJuYWxfc3Ryb2JlX3NldChzdHJ1Y3QgdjRsMl9mbGFzaCAqdjRsMl9mbGFz aCwKPiArCQkJCQkgICAgYm9vbCBlbmFibGUpCj4gK3sKPiArCXN0cnVjdCBsZWRfY2xhc3NkZXZf Zmxhc2ggKmZsYXNoID0gdjRsMl9mbGFzaC0+ZmxlZF9jZGV2Owo+ICsJc3RydWN0IG10NjM3MF9s ZWQgKmxlZCA9IHRvX210NjM3MF9sZWQoZmxhc2gsIGZsYXNoKTsKPiArCXN0cnVjdCBtdDYzNzBf cHJpdiAqcHJpdiA9IGxlZC0+cHJpdjsKPiArCXUzMiBtYXNrID0gbGVkLT5sZWRfbm8gPT0gTVQ2 MzcwX0xFRF9KT0lOVCA/IE1UNjM3MF9GTENTRU5fTUFTS19BTEwgOgo+ICsJCSAgIE1UNjM3MF9G TENTRU5fTUFTSyhsZWQtPmxlZF9ubyk7Cj4gKwl1MzIgdmFsID0gZW5hYmxlID8gbWFzayA6IDA7 Cj4gKwlpbnQgcmV0Owo+ICsKPiArCW11dGV4X2xvY2soJnByaXYtPmxvY2spOwo+ICsKPiArCXJl dCA9IHJlZ21hcF91cGRhdGVfYml0cyhwcml2LT5yZWdtYXAsIE1UNjM3MF9SRUdfRkxFREVOLCBt YXNrLCB2YWwpOwo+ICsJaWYgKHJldCkKPiArCQlnb3RvIHVubG9jazsKPiArCj4gKwlpZiAoZW5h YmxlKQo+ICsJCXByaXYtPmZsZWRfc3Ryb2JlX3VzZWQgfD0gQklUKGxlZC0+bGVkX25vKTsKPiAr CWVsc2UKPiArCQlwcml2LT5mbGVkX3N0cm9iZV91c2VkICY9IH5CSVQobGVkLT5sZWRfbm8pOwo+ ICsKPiArdW5sb2NrOgo+ICsJbXV0ZXhfdW5sb2NrKCZwcml2LT5sb2NrKTsKPiArCXJldHVybiBy ZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgdjRsMl9mbGFzaF9vcHMgdjRsMl9m bGFzaF9vcHMgPSB7Cj4gKwkuZXh0ZXJuYWxfc3Ryb2JlX3NldCA9IG10NjM3MF9mbGFzaF9leHRl cm5hbF9zdHJvYmVfc2V0LAo+ICt9Owo+ICsKPiArc3RhdGljIHZvaWQgbXQ2MzcwX2luaXRfdjRs Ml9mbGFzaF9jb25maWcoc3RydWN0IG10NjM3MF9sZWQgKmxlZCwKPiArCQkJCQkgIHN0cnVjdCB2 NGwyX2ZsYXNoX2NvbmZpZyAqY2ZnKQo+ICt7Cj4gKwlzdHJ1Y3QgbGVkX2NsYXNzZGV2ICpsY2Rl djsKPiArCXN0cnVjdCBsZWRfZmxhc2hfc2V0dGluZyAqcyA9ICZjZmctPmludGVuc2l0eTsKPiAr Cj4gKwlsY2RldiA9ICZsZWQtPmZsYXNoLmxlZF9jZGV2Owo+ICsKPiArCXMtPm1pbiA9IE1UNjM3 MF9JVE9SQ0hfTUlOX3VBOwo+ICsJcy0+c3RlcCA9IE1UNjM3MF9JVE9SQ0hfU1RFUF91QTsKPiAr CXMtPnZhbCA9IHMtPm1heCA9IHMtPm1pbiArIChsY2Rldi0+bWF4X2JyaWdodG5lc3MgLSAxKSAq IHMtPnN0ZXA7Cj4gKwo+ICsJY2ZnLT5oYXNfZXh0ZXJuYWxfc3Ryb2JlID0gMTsKCmhhc19leHRl cm5hbF9zdHJvYmUgaXMgYSBib29sLgoKPiArCXN0cnNjcHkoY2ZnLT5kZXZfbmFtZSwgZGV2X25h bWUobGNkZXYtPmRldiksIHNpemVvZihjZmctPmRldl9uYW1lKSk7Cj4gKwo+ICsJY2ZnLT5mbGFz aF9mYXVsdHMgPSBMRURfRkFVTFRfU0hPUlRfQ0lSQ1VJVCB8IExFRF9GQVVMVF9USU1FT1VUIHwK PiArCQkJICAgIExFRF9GQVVMVF9JTlBVVF9WT0xUQUdFIHwgTEVEX0ZBVUxUX1VOREVSX1ZPTFRB R0U7Cj4gK30KPiArI2Vsc2UKPiArc3RhdGljIGNvbnN0IHN0cnVjdCB2NGwyX2ZsYXNoX29wcyB2 NGwyX2ZsYXNoX29wczsKPiArc3RhdGljIHZvaWQgbXQ2MzcwX2luaXRfdjRsMl9mbGFzaF9jb25m aWcoc3RydWN0IG10NjM3MF9sZWQgKmxlZCwKPiArCQkJCQkgIHN0cnVjdCB2NGwyX2ZsYXNoX2Nv bmZpZyAqY2ZnKQo+ICt7Cj4gK30KPiArI2VuZGlmCj4gKwo+ICtzdGF0aWMgdm9pZCBtdDYzNzBf djRsMl9mbGFzaF9yZWxlYXNlKHZvaWQgKnY0bDJfZmxhc2gpCj4gK3sKPiArCXY0bDJfZmxhc2hf cmVsZWFzZSh2NGwyX2ZsYXNoKTsKPiArfQo+ICsKPiArc3RhdGljIGludCBtdDYzNzBfbGVkX3Jl Z2lzdGVyKHN0cnVjdCBkZXZpY2UgKnBhcmVudCwgc3RydWN0IG10NjM3MF9sZWQgKmxlZCwKPiAr CQkJCXN0cnVjdCBmd25vZGVfaGFuZGxlICpmd25vZGUpCj4gK3sKPiArCXN0cnVjdCBsZWRfaW5p dF9kYXRhIGluaXRfZGF0YSA9IHsgLmZ3bm9kZSA9IGZ3bm9kZSB9Owo+ICsJc3RydWN0IHY0bDJf Zmxhc2hfY29uZmlnIHY0bDJfY29uZmlnID0ge307Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXJldCA9 IGRldm1fbGVkX2NsYXNzZGV2X2ZsYXNoX3JlZ2lzdGVyX2V4dChwYXJlbnQsICZsZWQtPmZsYXNo LAo+ICsJCQkJCQkgICAmaW5pdF9kYXRhKTsKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIGRldl9l cnJfcHJvYmUocGFyZW50LCByZXQsCj4gKwkJCQkgICAgICJDb3VsZG4ndCByZWdpc3RlciBmbGFz aCAlZFxuIiwgbGVkLT5sZWRfbm8pOwo+ICsKPiArCW10NjM3MF9pbml0X3Y0bDJfZmxhc2hfY29u ZmlnKGxlZCwgJnY0bDJfY29uZmlnKTsKPiArCWxlZC0+djRsMl9mbGFzaCA9IHY0bDJfZmxhc2hf aW5pdChwYXJlbnQsIGZ3bm9kZSwgJmxlZC0+Zmxhc2gsCj4gKwkJCQkJICAmdjRsMl9mbGFzaF9v cHMsICZ2NGwyX2NvbmZpZyk7Cj4gKwlpZiAoSVNfRVJSKGxlZC0+djRsMl9mbGFzaCkpCj4gKwkJ cmV0dXJuIGRldl9lcnJfcHJvYmUocGFyZW50LCBQVFJfRVJSKGxlZC0+djRsMl9mbGFzaCksCj4g KwkJCQkgICAgICJGYWlsZWQgdG8gcmVnaXN0ZXIgJWQgdjRsMiBzZFxuIiwgbGVkLT5sZWRfbm8p Owo+ICsKPiArCXJldHVybiBkZXZtX2FkZF9hY3Rpb25fb3JfcmVzZXQocGFyZW50LCBtdDYzNzBf djRsMl9mbGFzaF9yZWxlYXNlLAo+ICsJCQkJCWxlZC0+djRsMl9mbGFzaCk7Cj4gK30KPiArCj4g K3N0YXRpYyB1MzIgbXQ2MzcwX2NsYW1wKHUzMiB2YWwsIHUzMiBtaW4sIHUzMiBtYXgsIHUzMiBz dGVwKQo+ICt7Cj4gKwl1MzIgcmV0dmFsOwo+ICsKPiArCXJldHZhbCA9IGNsYW1wX3ZhbCh2YWws IG1pbiwgbWF4KTsKPiArCWlmIChzdGVwID4gMSkKPiArCQlyZXR2YWwgPSByb3VuZGRvd24ocmV0 dmFsIC0gbWluLCBzdGVwKSArIG1pbjsKPiArCj4gKwlyZXR1cm4gcmV0dmFsOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgaW50IG10NjM3MF9pbml0X2ZsYXNoX3Byb3BlcnRpZXMoc3RydWN0IGRldmljZSAq ZGV2LAo+ICsJCQkJCXN0cnVjdCBtdDYzNzBfbGVkICpsZWQsCj4gKwkJCQkJc3RydWN0IGZ3bm9k ZV9oYW5kbGUgKmZ3bm9kZSkKPiArewo+ICsJc3RydWN0IGxlZF9jbGFzc2Rldl9mbGFzaCAqZmxh c2ggPSAmbGVkLT5mbGFzaDsKPiArCXN0cnVjdCBsZWRfY2xhc3NkZXYgKmxjZGV2ID0gJmZsYXNo LT5sZWRfY2RldjsKPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9IGxlZC0+cHJpdjsKPiAr CXN0cnVjdCBsZWRfZmxhc2hfc2V0dGluZyAqczsKPiArCXUzMiBzb3VyY2VzW01UNjM3MF9NQVhf TEVEU107Cj4gKwl1MzIgbWF4X3VhLCB2YWw7Cj4gKwlpbnQgaSwgcmV0LCBudW07Cj4gKwo+ICsJ bnVtID0gZndub2RlX3Byb3BlcnR5X2NvdW50X3UzMihmd25vZGUsICJsZWQtc291cmNlcyIpOwo+ ICsJaWYgKG51bSA8IDEpCj4gKwkJcmV0dXJuIGRldl9lcnJfcHJvYmUoZGV2LCAtRUlOVkFMLAo+ ICsJCQkJICAgICAiTm90IHNwZWNpZmllZCBvciB3cm9uZyBudW1iZXIgb2YgbGVkLXNvdXJjZXNc biIpOwo+ICsKPiArCXJldCA9IGZ3bm9kZV9wcm9wZXJ0eV9yZWFkX3UzMl9hcnJheShmd25vZGUs ICJsZWQtc291cmNlcyIsIHNvdXJjZXMsIG51bSk7Cj4gKwlpZiAocmV0KQo+ICsJCXJldHVybiBy ZXQ7Cj4gKwo+ICsJZm9yIChpID0gMDsgaSA8IG51bTsgaSsrKSB7Cj4gKwkJaWYgKHNvdXJjZXNb aV0gPj0gTVQ2MzcwX01BWF9MRURTKQo+ICsJCQlyZXR1cm4gLUVJTlZBTDsKPiArCQlpZiAocHJp di0+bGVkc19hY3RpdmUgJiBCSVQoc291cmNlc1tpXSkpCj4gKwkJCXJldHVybiAtRUlOVkFMOwo+ ICsJCXByaXYtPmxlZHNfYWN0aXZlIHw9IEJJVChzb3VyY2VzW2ldKTsKPiArCX0KPiArCj4gKwls ZWQtPmxlZF9ubyA9IG51bSA9PSAyID8gTVQ2MzcwX0xFRF9KT0lOVCA6IHNvdXJjZXNbMF07Cj4g Kwo+ICsJbWF4X3VhID0gbnVtID09IDIgPyBNVDYzNzBfSVRPUkNIX0RPVUJMRV9NQVhfdUEgOiBN VDYzNzBfSVRPUkNIX01BWF91QTsKPiArCXZhbCA9IE1UNjM3MF9JVE9SQ0hfTUlOX3VBOwoKSW4g d2hhdCBzY2VuYXJpbyBkb2VzIHRoaXMgbm90IGdldCBvdmVyd3JpdHRlbj8KCj4gKwlyZXQgPSBm d25vZGVfcHJvcGVydHlfcmVhZF91MzIoZndub2RlLCAibGVkLW1heC1taWNyb2FtcCIsICZ2YWwp Owo+ICsJaWYgKCFyZXQpCj4gKwkJdmFsID0gbXQ2MzcwX2NsYW1wKHZhbCwgTVQ2MzcwX0lUT1JD SF9NSU5fdUEsIG1heF91YSwKPiArCQkJCSAgIE1UNjM3MF9JVE9SQ0hfU1RFUF91QSk7Cj4gKwo+ ICsJbGNkZXYtPm1heF9icmlnaHRuZXNzID0gKHZhbCAtIE1UNjM3MF9JVE9SQ0hfTUlOX3VBKSAv Cj4gKwkJCQkgTVQ2MzcwX0lUT1JDSF9TVEVQX3VBICsgMTsKPiArCWxjZGV2LT5icmlnaHRuZXNz X3NldF9ibG9ja2luZyA9IG10NjM3MF90b3JjaF9icmlnaHRuZXNzX3NldDsKPiArCWxjZGV2LT5m bGFncyB8PSBMRURfREVWX0NBUF9GTEFTSDsKPiArCj4gKwltYXhfdWEgPSBudW0gPT0gMiA/IE1U NjM3MF9JU1RSQl9ET1VCTEVfTUFYX3VBIDogTVQ2MzcwX0lTVFJCX01BWF91QTsKPiArCXZhbCA9 IE1UNjM3MF9JU1RSQl9NSU5fdUE7Cj4gKwlyZXQgPSBmd25vZGVfcHJvcGVydHlfcmVhZF91MzIo Zndub2RlLCAiZmxhc2gtbWF4LW1pY3JvYW1wIiwgJnZhbCk7Cj4gKwlpZiAoIXJldCkKPiArCQl2 YWwgPSBtdDYzNzBfY2xhbXAodmFsLCBNVDYzNzBfSVNUUkJfTUlOX3VBLCBtYXhfdWEsCj4gKwkJ CQkgICBNVDYzNzBfSVNUUkJfU1RFUF91QSk7Cj4gKwo+ICsJcyA9ICZmbGFzaC0+YnJpZ2h0bmVz czsKPiArCXMtPm1pbiA9IE1UNjM3MF9JU1RSQl9NSU5fdUE7Cj4gKwlzLT5zdGVwID0gTVQ2Mzcw X0lTVFJCX1NURVBfdUE7Cj4gKwlzLT52YWwgPSBzLT5tYXggPSB2YWw7Cj4gKwo+ICsJLyoKPiAr CSAqIEFsd2F5cyBjb25maWd1cmUgdG8gdGhlIG1pbmltdW0gbGV2ZWwgd2hlbgo+ICsJICogb2Zm IHRvIHByZXZlbnQgZmxhc2ggY3VycmVudCBzcGlrZXMuCj4gKwkgKi8KPiArCXJldCA9IF9tdDYz NzBfZmxhc2hfYnJpZ2h0bmVzc19zZXQoZmxhc2gsIHMtPm1pbik7Cj4gKwlpZiAocmV0KQo+ICsJ CXJldHVybiByZXQ7Cj4gKwo+ICsKPiArCXZhbCA9IE1UNjM3MF9TVFJCVE9fTUlOX1VTOwoKQXMg YWJvdmUuCgo+ICsJcmV0ID0gZndub2RlX3Byb3BlcnR5X3JlYWRfdTMyKGZ3bm9kZSwgImZsYXNo LW1heC10aW1lb3V0LXVzIiwgJnZhbCk7Cj4gKwlpZiAoIXJldCkKPiArCQl2YWwgPSBtdDYzNzBf Y2xhbXAodmFsLCBNVDYzNzBfU1RSQlRPX01JTl9VUywKPiArCQkJCSAgIE1UNjM3MF9TVFJCVE9f TUFYX1VTLCBNVDYzNzBfU1RSQlRPX1NURVBfVVMpOwo+ICsKPiArCXMgPSAmZmxhc2gtPnRpbWVv dXQ7Cj4gKwlzLT5taW4gPSBNVDYzNzBfU1RSQlRPX01JTl9VUzsKPiArCXMtPnN0ZXAgPSBNVDYz NzBfU1RSQlRPX1NURVBfVVM7Cj4gKwlzLT52YWwgPSBzLT5tYXggPSB2YWw7Cj4gKwo+ICsJZmxh c2gtPm9wcyA9ICZtdDYzNzBfZmxhc2hfb3BzOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgaW50IG10NjM3MF9sZWRfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRl dikKPiArewo+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRldjsKPiArCXN0cnVjdCBt dDYzNzBfcHJpdiAqcHJpdjsKPiArCXN0cnVjdCBmd25vZGVfaGFuZGxlICpjaGlsZDsKPiArCXNp emVfdCBjb3VudDsKPiArCWludCBpID0gMCwgcmV0Owo+ICsKPiArCWNvdW50ID0gZGV2aWNlX2dl dF9jaGlsZF9ub2RlX2NvdW50KGRldik7Cj4gKwlpZiAoIWNvdW50IHx8IGNvdW50ID4gTVQ2Mzcw X01BWF9MRURTKQo+ICsJCXJldHVybiBkZXZfZXJyX3Byb2JlKGRldiwgLUVJTlZBTCwKPiArCQkg ICAgICAgIk5vIGNoaWxkIG5vZGUgb3Igbm9kZSBjb3VudCBvdmVyIG1heCBsZWQgbnVtYmVyICV6 dVxuIiwgY291bnQpOwo+ICsKPiArCXByaXYgPSBkZXZtX2t6YWxsb2MoZGV2LCBzdHJ1Y3Rfc2l6 ZShwcml2LCBsZWRzLCBjb3VudCksIEdGUF9LRVJORUwpOwo+ICsJaWYgKCFwcml2KQo+ICsJCXJl dHVybiAtRU5PTUVNOwo+ICsKPiArCXByaXYtPmxlZHNfY291bnQgPSBjb3VudDsKPiArCW11dGV4 X2luaXQoJnByaXYtPmxvY2spOwo+ICsKPiArCXByaXYtPnJlZ21hcCA9IGRldl9nZXRfcmVnbWFw KGRldi0+cGFyZW50LCBOVUxMKTsKPiArCWlmICghcHJpdi0+cmVnbWFwKQo+ICsJCXJldHVybiBk ZXZfZXJyX3Byb2JlKGRldiwgLUVOT0RFViwgIkZhaWxlZCB0byBnZXQgcGFyZW50IHJlZ21hcFxu Iik7Cj4gKwo+ICsJZGV2aWNlX2Zvcl9lYWNoX2NoaWxkX25vZGUoZGV2LCBjaGlsZCkgewo+ICsJ CXN0cnVjdCBtdDYzNzBfbGVkICpsZWQgPSBwcml2LT5sZWRzICsgaTsKPiArCj4gKwkJbGVkLT5w cml2ID0gcHJpdjsKPiArCj4gKwkJcmV0ID0gbXQ2MzcwX2luaXRfZmxhc2hfcHJvcGVydGllcyhk ZXYsIGxlZCwgY2hpbGQpOwo+ICsJCWlmIChyZXQpIHsKPiArCQkJZndub2RlX2hhbmRsZV9wdXQo Y2hpbGQpOwo+ICsJCQlyZXR1cm4gcmV0Owo+ICsJCX0KPiArCj4gKwkJcmV0ID0gbXQ2MzcwX2xl ZF9yZWdpc3RlcihkZXYsIGxlZCwgY2hpbGQpOwo+ICsJCWlmIChyZXQpIHsKPiArCQkJZndub2Rl X2hhbmRsZV9wdXQoY2hpbGQpOwo+ICsJCQlyZXR1cm4gcmV0Owo+ICsJCX0KPiArCj4gKwkJaSsr Owo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0 IG9mX2RldmljZV9pZCBtdDYzNzBfbGVkX29mX2lkW10gPSB7Cj4gKwl7IC5jb21wYXRpYmxlID0g Im1lZGlhdGVrLG10NjM3MC1mbGFzaGxpZ2h0IiB9LAo+ICsJeyAvKiBzZW50aW5lbCAqLyB9CgpQ bGVhc2UgcmVtb3ZlIHRoaXMgY29tbWVudC4gIFdlIGtub3cgaG93IE5VTEwgdGVybWluYXRvcnMg d29yay4gOikKCj4gK307Cj4gK01PRFVMRV9ERVZJQ0VfVEFCTEUob2YsIG10NjM3MF9sZWRfb2Zf aWQpOwo+ICsKPiArc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgbXQ2MzcwX2xlZF9kcml2 ZXIgPSB7Cj4gKwkuZHJpdmVyID0gewo+ICsJCS5uYW1lID0gIm10NjM3MC1mbGFzaGxpZ2h0IiwK PiArCQkub2ZfbWF0Y2hfdGFibGUgPSBtdDYzNzBfbGVkX29mX2lkLAo+ICsJfSwKPiArCS5wcm9i ZSA9IG10NjM3MF9sZWRfcHJvYmUsCj4gK307Cj4gK21vZHVsZV9wbGF0Zm9ybV9kcml2ZXIobXQ2 MzcwX2xlZF9kcml2ZXIpOwo+ICsKPiArTU9EVUxFX0FVVEhPUigiQWxpY2UgQ2hlbiA8YWxpY2Vf Y2hlbkByaWNodGVrLmNvbT4iKTsKPiArTU9EVUxFX0FVVEhPUigiQ2hpWXVhbiBIdWFuZyA8Y3lf aHVhbmdAcmljaHRlay5jb20+Iik7Cj4gK01PRFVMRV9ERVNDUklQVElPTigiTVQ2MzcwIEZMQVNI IExFRCBEcml2ZXIiKTsKPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwo+IC0tIAo+IDIuNy40Cj4g CgotLSAKTGVlIEpvbmVzIFvmnY7nkLzmlq9dCgpfX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fXwpsaW51eC1hcm0ta2VybmVsIG1haWxpbmcgbGlzdApsaW51eC1h cm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmluZnJhZGVhZC5vcmcv bWFpbG1hbi9saXN0aW5mby9saW51eC1hcm0ta2VybmVsCg==