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 92611C6FA99 for ; Tue, 7 Mar 2023 03:45:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229743AbjCGDpK (ORCPT ); Mon, 6 Mar 2023 22:45:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36398 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229619AbjCGDpJ (ORCPT ); Mon, 6 Mar 2023 22:45:09 -0500 Received: from mg.richtek.com (mg.richtek.com [220.130.44.152]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id DFEB329415; Mon, 6 Mar 2023 19:45:03 -0800 (PST) X-MailGates: (flag:4,DYNAMIC,BADHELO,RELAY,NOHOST:PASS)(compute_score:DE LIVER,40,3) Received: from 192.168.10.46 by mg.richtek.com with MailGates ESMTP Server V5.0(22251:0:AUTH_RELAY) (envelope-from ); Tue, 07 Mar 2023 11:44:33 +0800 (CST) Received: from ex3.rt.l (192.168.10.46) by ex3.rt.l (192.168.10.46) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.25; Tue, 7 Mar 2023 11:44:33 +0800 Received: from linuxcarl2.richtek.com (192.168.10.154) by ex3.rt.l (192.168.10.45) with Microsoft SMTP Server id 15.2.1118.25 via Frontend Transport; Tue, 7 Mar 2023 11:44:33 +0800 Date: Tue, 7 Mar 2023 11:44:33 +0800 From: ChiYuan Huang To: Lee Jones CC: ChiaEn Wu , , , , , , , , , , , , , Subject: Re: [PATCH v17 RESEND 2/3] leds: flash: mt6370: Add MediaTek MT6370 flashlight support Message-ID: <20230307034433.GA10739@linuxcarl2.richtek.com> References: <20230305100608.GD2574592@google.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20230305100608.GD2574592@google.com> User-Agent: Mutt/1.5.21 (2010-09-15) Precedence: bulk List-ID: X-Mailing-List: linux-doc@vger.kernel.org Hi, Lee: Reply below the comments. On Sun, Mar 05, 2023 at 10:06:08AM +0000, Lee Jones wrote: > 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"? > Since MT6370 has two flash led channels. Per channel can drive the current up to 1.5A. 'JOINT' case is used if 1.5A driving current is not enough, like as flash current 2A. They can use two channels to drive 'one' flash led by the HW application. This will make the driving current larger than the capability of one channel. > > + 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. > I checked the define, 'has_external_strobe' is a 1-bit bitfield of 'unsigned int'. To assign as '1' seems more reasonable than 'true'. > > + 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? > Only if the property is missing. This will make the value keep in minimum. > > + 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 C69B3C6FA99 for ; Tue, 7 Mar 2023 03:46:31 +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=m60tks1ukzDwWpUdiuCDHd6dji29hKfIn/qyRgrGxXo=; b=H26U4JN7tJk4GW tW5mbKF9UVlU/9XkvFcGAsRlH9dX8q82KQ4r/GjguZBB2CoIcIS+gt1GM0fb0ldACKcbJGoqZPi8K AmMLL3sglDKBCOM+ow+78Ib0Qgc/GaeC+UKpyF998wB+OW9bAcHM4NZupgzjNCNtfKI6/ezTRwY2b AOCW/bfYLYi4011icGAdsd0LS6pSIHZXR/BsviUoa8biGUePvauvXi1Y6qdxyuf1upu6dTizERB7A LcIaPPO2DT82i7JQeWzvGDVLrFSLeoikz9lMhP/me9ISEGW6hJPNFJCyxkvEpKS5QQWbIDWzx9tFn n2UAaNxBiE6kjsUV2GdQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pZOGT-00G4Pk-9N; Tue, 07 Mar 2023 03:45:25 +0000 Received: from mg.richtek.com ([220.130.44.152]) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pZOGK-00G4Lx-TO; Tue, 07 Mar 2023 03:45:23 +0000 X-MailGates: (flag:4,DYNAMIC,BADHELO,RELAY,NOHOST:PASS)(compute_score:DE LIVER,40,3) Received: from 192.168.10.46 by mg.richtek.com with MailGates ESMTP Server V5.0(22251:0:AUTH_RELAY) (envelope-from ); Tue, 07 Mar 2023 11:44:33 +0800 (CST) Received: from ex3.rt.l (192.168.10.46) by ex3.rt.l (192.168.10.46) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.25; Tue, 7 Mar 2023 11:44:33 +0800 Received: from linuxcarl2.richtek.com (192.168.10.154) by ex3.rt.l (192.168.10.45) with Microsoft SMTP Server id 15.2.1118.25 via Frontend Transport; Tue, 7 Mar 2023 11:44:33 +0800 Date: Tue, 7 Mar 2023 11:44:33 +0800 From: ChiYuan Huang To: Lee Jones CC: ChiaEn Wu , , , , , , , , , , , , , Subject: Re: [PATCH v17 RESEND 2/3] leds: flash: mt6370: Add MediaTek MT6370 flashlight support Message-ID: <20230307034433.GA10739@linuxcarl2.richtek.com> References: <20230305100608.GD2574592@google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20230305100608.GD2574592@google.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230306_194517_629471_1FD8EFB8 X-CRM114-Status: GOOD ( 44.91 ) 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 SGksIExlZToKICAgUmVwbHkgYmVsb3cgdGhlIGNvbW1lbnRzLgoKT24gU3VuLCBNYXIgMDUsIDIw MjMgYXQgMTA6MDY6MDhBTSArMDAwMCwgTGVlIEpvbmVzIHdyb3RlOgo+IE9uIFRodSwgMjMgRmVi IDIwMjMsIENoaWFFbiBXdSB3cm90ZToKPiAKPiA+IEZyb206IENoaVl1YW4gSHVhbmcgPGN5X2h1 YW5nQHJpY2h0ZWsuY29tPgo+ID4gCj4gPiBUaGUgTWVkaWFUZWsgTVQ2MzcwIGlzIGEgaGlnaGx5 LWludGVncmF0ZWQgc21hcnQgcG93ZXIgbWFuYWdlbWVudCBJQywKPiA+IHdoaWNoIGluY2x1ZGVz IGEgc2luZ2xlIGNlbGwgTGktSW9uL0xpLVBvbHltZXIgc3dpdGNoaW5nIGJhdHRlcnkKPiA+IGNo YXJnZXIsIGEgVVNCIFR5cGUtQyAmIFBvd2VyIERlbGl2ZXJ5IChQRCkgY29udHJvbGxlciwgZHVh bCBGbGFzaAo+ID4gTEVEIGN1cnJlbnQgc291cmNlcywgYSBSR0IgTEVEIGRyaXZlciwgYSBiYWNr bGlnaHQgV0xFRCBkcml2ZXIsCj4gPiBhIGRpc3BsYXkgYmlhcyBkcml2ZXIgYW5kIGEgZ2VuZXJh bCBMRE8gZm9yIHBvcnRhYmxlIGRldmljZXMuCj4gPiAKPiA+IEFkZCBzdXBwb3J0IGZvciB0aGUg TVQ2MzcwIEZsYXNoIExFRCBkcml2ZXIuIEZsYXNoIExFRCBpbiBNVDYzNzAKPiA+IGhhcyAyIGNo YW5uZWxzIGFuZCBzdXBwb3J0IHRvcmNoL3N0cm9iZSBtb2RlLgo+ID4gCj4gPiBBY2tlZC1ieTog SmFjZWsgQW5hc3pld3NraSA8amFjZWsuYW5hc3pld3NraUBnbWFpbC5jb20+Cj4gPiBDby1kZXZl bG9wZWQtYnk6IEFsaWNlIENoZW4gPGFsaWNlX2NoZW5AcmljaHRlay5jb20+Cj4gPiBTaWduZWQt b2ZmLWJ5OiBBbGljZSBDaGVuIDxhbGljZV9jaGVuQHJpY2h0ZWsuY29tPgo+ID4gU2lnbmVkLW9m Zi1ieTogQ2hpWXVhbiBIdWFuZyA8Y3lfaHVhbmdAcmljaHRlay5jb20+Cj4gPiBTaWduZWQtb2Zm LWJ5OiBDaGlhRW4gV3UgPGNoaWFlbl93dUByaWNodGVrLmNvbT4KPiA+IC0tLQo+ID4gdjE3Cj4g PiAtIFVwZGF0ZSB0aGUgeWVhciBvZiBDb3B5cmlnaHQgZnJvbSAyMDIyIHRvIDIwMjMKPiA+IAo+ ID4gLS0tCj4gPiAgZHJpdmVycy9sZWRzL2ZsYXNoL0tjb25maWcgICAgICAgICAgICAgfCAgMTMg Kwo+ID4gIGRyaXZlcnMvbGVkcy9mbGFzaC9NYWtlZmlsZSAgICAgICAgICAgIHwgICAxICsKPiA+ ICBkcml2ZXJzL2xlZHMvZmxhc2gvbGVkcy1tdDYzNzAtZmxhc2guYyB8IDU5NiArKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysKPiA+ICAzIGZpbGVzIGNoYW5nZWQsIDYxMCBpbnNlcnRp b25zKCspCj4gPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvbGVkcy9mbGFzaC9sZWRzLW10 NjM3MC1mbGFzaC5jCj4gCj4gUGxlYXNlIHVud3JhcCB0byAxMDAtY2hhcnMgdGhyb3VnaG91dC4K PiAgCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9sZWRzL2ZsYXNoL0tjb25maWcgYi9kcml2ZXJz L2xlZHMvZmxhc2gvS2NvbmZpZwo+ID4gaW5kZXggZDNlYjY4OS4uNDlkODkyMiAxMDA2NDQKPiA+ IC0tLSBhL2RyaXZlcnMvbGVkcy9mbGFzaC9LY29uZmlnCj4gPiArKysgYi9kcml2ZXJzL2xlZHMv Zmxhc2gvS2NvbmZpZwo+ID4gQEAgLTYxLDYgKzYxLDE5IEBAIGNvbmZpZyBMRURTX01UNjM2MAo+ ID4gIAkgIEluZGVwZW5kZW50IGN1cnJlbnQgc291cmNlcyBzdXBwbHkgZm9yIGVhY2ggZmxhc2gg TEVEIHN1cHBvcnQgdG9yY2gKPiA+ICAJICBhbmQgc3Ryb2JlIG1vZGUuCj4gPiAgCj4gPiArY29u ZmlnIExFRFNfTVQ2MzcwX0ZMQVNICj4gPiArCXRyaXN0YXRlICJGbGFzaCBMRUQgU3VwcG9ydCBm b3IgTWVkaWFUZWsgTVQ2MzcwIFBNSUMiCj4gPiArCWRlcGVuZHMgb24gTEVEU19DTEFTUwo+ID4g KwlkZXBlbmRzIG9uIFY0TDJfRkxBU0hfTEVEX0NMQVNTIHx8ICFWNEwyX0ZMQVNIX0xFRF9DTEFT Uwo+ID4gKwlkZXBlbmRzIG9uIE1GRF9NVDYzNzAKPiA+ICsJaGVscAo+ID4gKwkgIFN1cHBvcnQg MiBjaGFubmVscyBhbmQgdG9yY2gvc3Ryb2JlIG1vZGUuCj4gPiArCSAgU2F5IFkgaGVyZSB0byBl bmFibGUgc3VwcG9ydCBmb3IKPiA+ICsJICBNVDYzNzBfRkxBU0hfTEVEIGRldmljZS4KPiA+ICsK PiA+ICsJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1vZHVsZS4gSWYgc28s IHRoZSBtb2R1bGUKPiA+ICsJICB3aWxsIGJlIGNhbGxlZCAibGVkcy1tdDYzNzAtZmxhc2giLgo+ ID4gKwo+ID4gIGNvbmZpZyBMRURTX1JUNDUwNQo+ID4gIAl0cmlzdGF0ZSAiTEVEIHN1cHBvcnQg Zm9yIFJUNDUwNSBmbGFzaGxpZ2h0IGNvbnRyb2xsZXIiCj4gPiAgCWRlcGVuZHMgb24gSTJDICYm IE9GCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9sZWRzL2ZsYXNoL01ha2VmaWxlIGIvZHJpdmVy cy9sZWRzL2ZsYXNoL01ha2VmaWxlCj4gPiBpbmRleCAwYWNiZGRjLi40NjY1ZThlIDEwMDY0NAo+ ID4gLS0tIGEvZHJpdmVycy9sZWRzL2ZsYXNoL01ha2VmaWxlCj4gPiArKysgYi9kcml2ZXJzL2xl ZHMvZmxhc2gvTWFrZWZpbGUKPiA+IEBAIC0xLDYgKzEsNyBAQAo+ID4gICMgU1BEWC1MaWNlbnNl LUlkZW50aWZpZXI6IEdQTC0yLjAKPiA+ICAKPiA+ICBvYmotJChDT05GSUdfTEVEU19NVDYzNjAp CSs9IGxlZHMtbXQ2MzYwLm8KPiA+ICtvYmotJChDT05GSUdfTEVEU19NVDYzNzBfRkxBU0gpCSs9 IGxlZHMtbXQ2MzcwLWZsYXNoLm8KPiA+ICBvYmotJChDT05GSUdfTEVEU19BQVQxMjkwKQkrPSBs ZWRzLWFhdDEyOTAubwo+ID4gIG9iai0kKENPTkZJR19MRURTX0FTMzY0NUEpCSs9IGxlZHMtYXMz NjQ1YS5vCj4gPiAgb2JqLSQoQ09ORklHX0xFRFNfS1REMjY5MikJKz0gbGVkcy1rdGQyNjkyLm8K PiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2xlZHMvZmxhc2gvbGVkcy1tdDYzNzAtZmxhc2guYyBi L2RyaXZlcnMvbGVkcy9mbGFzaC9sZWRzLW10NjM3MC1mbGFzaC5jCj4gPiBuZXcgZmlsZSBtb2Rl IDEwMDY0NAo+ID4gaW5kZXggMDAwMDAwMDAuLmIwMzYxN2YKPiA+IC0tLSAvZGV2L251bGwKPiA+ ICsrKyBiL2RyaXZlcnMvbGVkcy9mbGFzaC9sZWRzLW10NjM3MC1mbGFzaC5jCj4gPiBAQCAtMCww ICsxLDU5NiBAQAo+ID4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wLW9ubHkK PiA+ICsvKgo+ID4gKyAqIENvcHlyaWdodCAoQykgMjAyMyBSaWNodGVrIFRlY2hub2xvZ3kgQ29y cC4KPiA+ICsgKgo+ID4gKyAqIEF1dGhvcnM6Cj4gPiArICogICBBbGljZSBDaGVuIDxhbGljZV9j aGVuQHJpY2h0ZWsuY29tPgo+ID4gKyAqICAgQ2hpWXVhbiBIdWFuZyA8Y3lfaHVhbmdAcmljaHRl ay5jb20+Cj4gPiArICovCj4gPiArCj4gPiArI2luY2x1ZGUgPGxpbnV4L2JpdG9wcy5oPgo+ID4g KyNpbmNsdWRlIDxsaW51eC9kZWxheS5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9pbml0Lmg+Cj4g PiArI2luY2x1ZGUgPGxpbnV4L2ludGVycnVwdC5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9rZXJu ZWwuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgvbGVkLWNsYXNzLWZsYXNoLmg+Cj4gPiArI2luY2x1 ZGUgPGxpbnV4L21vZHVsZS5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9tdXRleC5oPgo+ID4gKyNp bmNsdWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZpY2UuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgvcHJv cGVydHkuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgvcmVnbWFwLmg+Cj4gPiArCj4gPiArI2luY2x1 ZGUgPG1lZGlhL3Y0bDItZmxhc2gtbGVkLWNsYXNzLmg+Cj4gPiArCj4gPiArZW51bSB7Cj4gPiAr CU1UNjM3MF9MRURfRkxBU0gxID0gMCwKPiA+ICsJTVQ2MzcwX0xFRF9GTEFTSDIsCj4gPiArCU1U NjM3MF9NQVhfTEVEUwo+ID4gK307Cj4gPiArCj4gPiArLyogVmlydHVhbCBkZWZpbml0aW9uIGZv ciBtdWx0aWNvbG9yICovCj4gPiArCj4gPiArI2RlZmluZSBNVDYzNzBfUkVHX0ZMRURFTgkJMHgx N0UKPiA+ICsjZGVmaW5lIE1UNjM3MF9SRUdfU1RSQlRPCQkweDE3Mwo+ID4gKyNkZWZpbmUgTVQ2 MzcwX1JFR19DSEdTVEFUMgkJMHgxRDEKPiA+ICsjZGVmaW5lIE1UNjM3MF9SRUdfRkxFRFNUQVQx CQkweDFEOQo+ID4gKyNkZWZpbmUgTVQ2MzcwX1JFR19GTEVESVNUUkIoX2lkKQkoMHgxNzQgKyA0 ICogKF9pZCkpCj4gPiArI2RlZmluZSBNVDYzNzBfUkVHX0ZMRURJVE9SKF9pZCkJKDB4MTc1ICsg NCAqIChfaWQpKQo+ID4gKyNkZWZpbmUgTVQ2MzcwX0lUT1JDSF9NQVNLCQlHRU5NQVNLKDQsIDAp Cj4gPiArI2RlZmluZSBNVDYzNzBfSVNUUk9CRV9NQVNLCQlHRU5NQVNLKDYsIDApCj4gPiArI2Rl ZmluZSBNVDYzNzBfU1RSQlRPX01BU0sJCUdFTk1BU0soNiwgMCkKPiA+ICsjZGVmaW5lIE1UNjM3 MF9UT1JDSEVOX01BU0sJCUJJVCgzKQo+ID4gKyNkZWZpbmUgTVQ2MzcwX1NUUk9CRU5fTUFTSwkJ QklUKDIpCj4gPiArI2RlZmluZSBNVDYzNzBfRkxDU0VOX01BU0soX2lkKQkJQklUKE1UNjM3MF9M RURfRkxBU0gyIC0gKF9pZCkpCj4gPiArI2RlZmluZSBNVDYzNzBfRkxDU0VOX01BU0tfQUxMCQlH RU5NQVNLKDEsIDApCj4gPiArI2RlZmluZSBNVDYzNzBfRkxFRENIR1ZJTk9WUF9NQVNLCUJJVCgz KQo+ID4gKyNkZWZpbmUgTVQ2MzcwX0ZMRUQxU1RSQlRPX01BU0sJCUJJVCgxMSkKPiA+ICsjZGVm aW5lIE1UNjM3MF9GTEVEMlNUUkJUT19NQVNLCQlCSVQoMTApCj4gPiArI2RlZmluZSBNVDYzNzBf RkxFRDFTVFJCX01BU0sJCUJJVCg5KQo+ID4gKyNkZWZpbmUgTVQ2MzcwX0ZMRUQyU1RSQl9NQVNL CQlCSVQoOCkKPiA+ICsjZGVmaW5lIE1UNjM3MF9GTEVEMVNIT1JUX01BU0sJCUJJVCg3KQo+ID4g KyNkZWZpbmUgTVQ2MzcwX0ZMRUQyU0hPUlRfTUFTSwkJQklUKDYpCj4gPiArI2RlZmluZSBNVDYz NzBfRkxFRExWRl9NQVNLCQlCSVQoMykKPiA+ICsKPiA+ICsjZGVmaW5lIE1UNjM3MF9MRURfSk9J TlQJCTIKPiA+ICsjZGVmaW5lIE1UNjM3MF9SQU5HRV9GTEVEX1JFRwkJNAo+ID4gKyNkZWZpbmUg TVQ2MzcwX0lUT1JDSF9NSU5fdUEJCTI1MDAwCj4gPiArI2RlZmluZSBNVDYzNzBfSVRPUkNIX1NU RVBfdUEJCTEyNTAwCj4gPiArI2RlZmluZSBNVDYzNzBfSVRPUkNIX01BWF91QQkJNDAwMDAwCj4g PiArI2RlZmluZSBNVDYzNzBfSVRPUkNIX0RPVUJMRV9NQVhfdUEJODAwMDAwCj4gPiArI2RlZmlu ZSBNVDYzNzBfSVNUUkJfTUlOX3VBCQk1MDAwMAo+ID4gKyNkZWZpbmUgTVQ2MzcwX0lTVFJCX1NU RVBfdUEJCTEyNTAwCj4gPiArI2RlZmluZSBNVDYzNzBfSVNUUkJfTUFYX3VBCQkxNTAwMDAwCj4g PiArI2RlZmluZSBNVDYzNzBfSVNUUkJfRE9VQkxFX01BWF91QQkzMDAwMDAwCj4gPiArI2RlZmlu ZSBNVDYzNzBfU1RSQlRPX01JTl9VUwkJNjQwMDAKPiA+ICsjZGVmaW5lIE1UNjM3MF9TVFJCVE9f U1RFUF9VUwkJMzIwMDAKPiA+ICsjZGVmaW5lIE1UNjM3MF9TVFJCVE9fTUFYX1VTCQkyNDMyMDAw Cj4gPiArCj4gPiArI2RlZmluZSB0b19tdDYzNzBfbGVkKHB0ciwgbWVtYmVyKSBjb250YWluZXJf b2YocHRyLCBzdHJ1Y3QgbXQ2MzcwX2xlZCwgbWVtYmVyKQo+ID4gKwo+ID4gK3N0cnVjdCBtdDYz NzBfbGVkIHsKPiA+ICsJc3RydWN0IGxlZF9jbGFzc2Rldl9mbGFzaCBmbGFzaDsKPiA+ICsJc3Ry dWN0IHY0bDJfZmxhc2ggKnY0bDJfZmxhc2g7Cj4gPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJp djsKPiA+ICsJdTggbGVkX25vOwo+ID4gK307Cj4gPiArCj4gPiArc3RydWN0IG10NjM3MF9wcml2 IHsKPiA+ICsJc3RydWN0IHJlZ21hcCAqcmVnbWFwOwo+ID4gKwlzdHJ1Y3QgbXV0ZXggbG9jazsK PiA+ICsJdW5zaWduZWQgaW50IGZsZWRfc3Ryb2JlX3VzZWQ7Cj4gPiArCXVuc2lnbmVkIGludCBm bGVkX3RvcmNoX3VzZWQ7Cj4gPiArCXVuc2lnbmVkIGludCBsZWRzX2FjdGl2ZTsKPiA+ICsJdW5z aWduZWQgaW50IGxlZHNfY291bnQ7Cj4gPiArCXN0cnVjdCBtdDYzNzBfbGVkIGxlZHNbXTsKPiA+ ICt9Owo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgbXQ2MzcwX3RvcmNoX2JyaWdodG5lc3Nfc2V0KHN0 cnVjdCBsZWRfY2xhc3NkZXYgKmxjZGV2LAo+ID4gKwkJCQkgICAgICAgZW51bSBsZWRfYnJpZ2h0 bmVzcyBsZXZlbCkKPiA+ICt7Cj4gPiArCXN0cnVjdCBtdDYzNzBfbGVkICpsZWQgPSB0b19tdDYz NzBfbGVkKGxjZGV2LCBmbGFzaC5sZWRfY2Rldik7Cj4gPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAq cHJpdiA9IGxlZC0+cHJpdjsKPiA+ICsJdTMyIGxlZF9lbmFibGVfbWFzayA9IGxlZC0+bGVkX25v ID09IE1UNjM3MF9MRURfSk9JTlQgPwo+ID4gKwkJCSAgICAgIE1UNjM3MF9GTENTRU5fTUFTS19B TEwgOgo+ID4gKwkJCSAgICAgIE1UNjM3MF9GTENTRU5fTUFTSyhsZWQtPmxlZF9ubyk7Cj4gPiAr CXUzMiBlbmFibGVfbWFzayA9IE1UNjM3MF9UT1JDSEVOX01BU0sgfCBsZWRfZW5hYmxlX21hc2s7 Cj4gPiArCXUzMiB2YWwgPSBsZXZlbCA/IGxlZF9lbmFibGVfbWFzayA6IDA7Cj4gPiArCXUzMiBj dXJyOwo+ID4gKwlpbnQgcmV0LCBpOwo+ID4gKwo+ID4gKwltdXRleF9sb2NrKCZwcml2LT5sb2Nr KTsKPiA+ICsKPiA+ICsJLyoKPiA+ICsJICogVGhlcmUgaXMgb25seSBvbmUgc2V0IG9mIGZsYXNo IGNvbnRyb2wgbG9naWMsIGFuZCB0aGlzCj4gPiArCSAqIGZsYWcgaXMgdXNlZCB0byBjaGVjayBp ZiAnc3Ryb2JlJyBpcyBjdXJyZW50bHkgYmVpbmcgdXNlZC4KPiA+ICsJICovCj4gPiArCWlmIChw cml2LT5mbGVkX3N0cm9iZV91c2VkKSB7Cj4gPiArCQlkZXZfd2FybihsY2Rldi0+ZGV2LCAiUGxl YXNlIGRpc2FibGUgc3Ryb2JlIGZpcnN0IFslZF1cbiIsCj4gPiArCQkJIHByaXYtPmZsZWRfc3Ry b2JlX3VzZWQpOwo+ID4gKwkJcmV0ID0gLUVCVVNZOwo+ID4gKwkJZ290byB1bmxvY2s7Cj4gPiAr CX0KPiA+ICsKPiA+ICsJaWYgKGxldmVsKQo+ID4gKwkJY3VyciA9IHByaXYtPmZsZWRfdG9yY2hf dXNlZCB8IEJJVChsZWQtPmxlZF9ubyk7Cj4gPiArCWVsc2UKPiA+ICsJCWN1cnIgPSBwcml2LT5m bGVkX3RvcmNoX3VzZWQgJiB+QklUKGxlZC0+bGVkX25vKTsKPiA+ICsKPiA+ICsJaWYgKGN1cnIp Cj4gPiArCQl2YWwgfD0gTVQ2MzcwX1RPUkNIRU5fTUFTSzsKPiA+ICsKPiA+ICsJaWYgKGxldmVs KSB7Cj4gPiArCQlsZXZlbCAtPSAxOwo+ID4gKwkJaWYgKGxlZC0+bGVkX25vID09IE1UNjM3MF9M RURfSk9JTlQpIHsKPiA+ICsJCQl1MzIgZmxldmVsW01UNjM3MF9NQVhfTEVEU107Cj4gPiArCj4g PiArCQkJZmxldmVsWzBdID0gbGV2ZWwgLyAyOwo+ID4gKwkJCWZsZXZlbFsxXSA9IGxldmVsIC0g ZmxldmVsWzBdOwo+ID4gKwkJCWZvciAoaSA9IDA7IGkgPCBNVDYzNzBfTUFYX0xFRFM7IGkrKykg ewo+ID4gKwkJCQlyZXQgPSByZWdtYXBfdXBkYXRlX2JpdHMocHJpdi0+cmVnbWFwLAo+ID4gKwkJ CQkJCU1UNjM3MF9SRUdfRkxFRElUT1IoaSksCj4gPiArCQkJCQkJTVQ2MzcwX0lUT1JDSF9NQVNL LCBmbGV2ZWxbaV0pOwo+ID4gKwkJCQlpZiAocmV0KQo+ID4gKwkJCQkJZ290byB1bmxvY2s7Cj4g PiArCQkJfQo+ID4gKwkJfSBlbHNlIHsKPiA+ICsJCQlyZXQgPSByZWdtYXBfdXBkYXRlX2JpdHMo cHJpdi0+cmVnbWFwLAo+ID4gKwkJCQkJTVQ2MzcwX1JFR19GTEVESVRPUihsZWQtPmxlZF9ubyks Cj4gPiArCQkJCQlNVDYzNzBfSVRPUkNIX01BU0ssIGxldmVsKTsKPiA+ICsJCQlpZiAocmV0KQo+ ID4gKwkJCQlnb3RvIHVubG9jazsKPiA+ICsJCX0KPiA+ICsJfQo+ID4gKwo+ID4gKwlyZXQgPSBy ZWdtYXBfdXBkYXRlX2JpdHMocHJpdi0+cmVnbWFwLCBNVDYzNzBfUkVHX0ZMRURFTiwKPiA+ICsJ CQkJIGVuYWJsZV9tYXNrLCB2YWwpOwo+ID4gKwlpZiAocmV0KQo+ID4gKwkJZ290byB1bmxvY2s7 Cj4gPiArCj4gPiArCXByaXYtPmZsZWRfdG9yY2hfdXNlZCA9IGN1cnI7Cj4gPiArCj4gPiArdW5s b2NrOgo+ID4gKwltdXRleF91bmxvY2soJnByaXYtPmxvY2spOwo+ID4gKwlyZXR1cm4gcmV0Owo+ ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50IG10NjM3MF9mbGFzaF9icmlnaHRuZXNzX3NldChz dHJ1Y3QgbGVkX2NsYXNzZGV2X2ZsYXNoICpmbF9jZGV2LAo+ID4gKwkJCQkgICAgICAgdTMyIGJy aWdodG5lc3MpCj4gPiArewo+ID4gKwkvKgo+ID4gKwkgKiBCZWNhdXNlIG9mIHRoZSBjdXJyZW50 IHNwaWtlcyB3aGVuIHR1cm5pbmcgb24gdGhlIGZsYXNoLAo+ID4gKwkgKiB0aGUgYnJpZ2h0bmVz cyBzaG91bGQgYmUga2VwdCBieSB0aGUgTEVEIGZyYW1ld29yay4gVGhpcwo+ID4gKwkgKiBlbXB0 eSBmdW5jdGlvbiBpcyB1c2VkIHRvIHByZXZlbnQgY2hlY2tpbmcgZmFpbHVyZSB3aGVuCj4gPiAr CSAqIGxlZF9jbGFzc2Rldl9mbGFzaCByZWdpc3RlcnMgb3BzLgo+ID4gKwkgKi8KPiA+ICsJcmV0 dXJuIDA7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgX210NjM3MF9mbGFzaF9icmlnaHRu ZXNzX3NldChzdHJ1Y3QgbGVkX2NsYXNzZGV2X2ZsYXNoICpmbF9jZGV2LAo+ID4gKwkJCQkJdTMy IGJyaWdodG5lc3MpCj4gPiArewo+ID4gKwlzdHJ1Y3QgbXQ2MzcwX2xlZCAqbGVkID0gdG9fbXQ2 MzcwX2xlZChmbF9jZGV2LCBmbGFzaCk7Cj4gPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9 IGxlZC0+cHJpdjsKPiA+ICsJc3RydWN0IGxlZF9mbGFzaF9zZXR0aW5nICpzZXR0aW5nID0gJmZs X2NkZXYtPmJyaWdodG5lc3M7Cj4gPiArCXUzMiB2YWwgPSAoYnJpZ2h0bmVzcyAtIHNldHRpbmct Pm1pbikgLyBzZXR0aW5nLT5zdGVwOwo+ID4gKwlpbnQgcmV0LCBpOwo+ID4gKwo+ID4gKwlpZiAo bGVkLT5sZWRfbm8gPT0gTVQ2MzcwX0xFRF9KT0lOVCkgewo+IAo+IFdoYXQgaXMgYSAiSk9JTlQi Pwo+ClNpbmNlIE1UNjM3MCBoYXMgdHdvIGZsYXNoIGxlZCBjaGFubmVscy4gUGVyIGNoYW5uZWwg Y2FuIGRyaXZlIHRoZSBjdXJyZW50IHVwIHRvIDEuNUEuCidKT0lOVCcgY2FzZSBpcyB1c2VkIGlm IDEuNUEgZHJpdmluZyBjdXJyZW50IGlzIG5vdCBlbm91Z2gsIGxpa2UgYXMgZmxhc2ggY3VycmVu dCAyQS4KVGhleSBjYW4gdXNlIHR3byBjaGFubmVscyB0byBkcml2ZSAnb25lJyBmbGFzaCBsZWQg YnkgdGhlIEhXIGFwcGxpY2F0aW9uLgpUaGlzIHdpbGwgbWFrZSB0aGUgZHJpdmluZyBjdXJyZW50 IGxhcmdlciB0aGFuIHRoZSBjYXBhYmlsaXR5IG9mIG9uZSBjaGFubmVsLgoKPiA+ICsJCXUzMiBm bGV2ZWxbTVQ2MzcwX01BWF9MRURTXTsKPiA+ICsKPiA+ICsJCWZsZXZlbFswXSA9IHZhbCAvIDI7 Cj4gPiArCQlmbGV2ZWxbMV0gPSB2YWwgLSBmbGV2ZWxbMF07Cj4gCj4gUGxlYXNlIHByb3ZpZGUg YSBjb21tZW50IGRlc2NyaWJpbmcgd2hhdCdzIGdvaW5nIG9uIGhlcmUuCj4gCj4gPiArCQlmb3Ig KGkgPSAwOyBpIDwgTVQ2MzcwX01BWF9MRURTOyBpKyspIHsKPiA+ICsJCQlyZXQgPSByZWdtYXBf dXBkYXRlX2JpdHMocHJpdi0+cmVnbWFwLAo+ID4gKwkJCQkJCSBNVDYzNzBfUkVHX0ZMRURJU1RS QihpKSwKPiA+ICsJCQkJCQkgTVQ2MzcwX0lTVFJPQkVfTUFTSywgZmxldmVsW2ldKTsKPiA+ICsJ CQlpZiAocmV0KQo+ID4gKwkJCQlicmVhazsKPiA+ICsJCX0KPiA+ICsJfSBlbHNlCj4gPiArCQly ZXQgPSByZWdtYXBfdXBkYXRlX2JpdHMocHJpdi0+cmVnbWFwLAo+ID4gKwkJCQkJIE1UNjM3MF9S RUdfRkxFRElTVFJCKGxlZC0+bGVkX25vKSwKPiA+ICsJCQkJCSBNVDYzNzBfSVNUUk9CRV9NQVNL LCB2YWwpOwo+ID4gKwo+ID4gKwlyZXR1cm4gcmV0Owo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMg aW50IG10NjM3MF9zdHJvYmVfc2V0KHN0cnVjdCBsZWRfY2xhc3NkZXZfZmxhc2ggKmZsX2NkZXYs IGJvb2wgc3RhdGUpCj4gPiArewo+ID4gKwlzdHJ1Y3QgbXQ2MzcwX2xlZCAqbGVkID0gdG9fbXQ2 MzcwX2xlZChmbF9jZGV2LCBmbGFzaCk7Cj4gPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9 IGxlZC0+cHJpdjsKPiA+ICsJc3RydWN0IGxlZF9jbGFzc2RldiAqbGNkZXYgPSAmZmxfY2Rldi0+ bGVkX2NkZXY7Cj4gPiArCXN0cnVjdCBsZWRfZmxhc2hfc2V0dGluZyAqcyA9ICZmbF9jZGV2LT5i cmlnaHRuZXNzOwo+ID4gKwl1MzIgbGVkX2VuYWJsZV9tYXNrID0gbGVkLT5sZWRfbm8gPT0gTVQ2 MzcwX0xFRF9KT0lOVCA/Cj4gPiArCQkJICAgICAgTVQ2MzcwX0ZMQ1NFTl9NQVNLX0FMTCA6Cj4g PiArCQkJICAgICAgTVQ2MzcwX0ZMQ1NFTl9NQVNLKGxlZC0+bGVkX25vKTsKPiA+ICsJdTMyIGVu YWJsZV9tYXNrID0gTVQ2MzcwX1NUUk9CRU5fTUFTSyB8IGxlZF9lbmFibGVfbWFzazsKPiA+ICsJ dTMyIHZhbCA9IHN0YXRlID8gbGVkX2VuYWJsZV9tYXNrIDogMDsKPiA+ICsJdTMyIGN1cnI7Cj4g PiArCWludCByZXQ7Cj4gPiArCj4gPiArCW11dGV4X2xvY2soJnByaXYtPmxvY2spOwo+ID4gKwo+ ID4gKwkvKgo+ID4gKwkgKiBUaGVyZSBpcyBvbmx5IG9uZSBzZXQgb2YgZmxhc2ggY29udHJvbCBs b2dpYywgYW5kIHRoaXMKPiA+ICsJICogZmxhZyBpcyB1c2VkIHRvIGNoZWNrIGlmICd0b3JjaCcg aXMgY3VycmVudGx5IGJlaW5nIHVzZWQuCj4gPiArCSAqLwo+ID4gKwlpZiAocHJpdi0+ZmxlZF90 b3JjaF91c2VkKSB7Cj4gPiArCQlkZXZfd2FybihsY2Rldi0+ZGV2LCAiUGxlYXNlIGRpc2FibGUg dG9yY2ggZmlyc3QgWzB4JXhdXG4iLAo+ID4gKwkJCQkgICAgICBwcml2LT5mbGVkX3RvcmNoX3Vz ZWQpOwo+ID4gKwkJcmV0ID0gLUVCVVNZOwo+ID4gKwkJZ290byB1bmxvY2s7Cj4gPiArCX0KPiA+ ICsKPiA+ICsJaWYgKHN0YXRlKQo+ID4gKwkJY3VyciA9IHByaXYtPmZsZWRfc3Ryb2JlX3VzZWQg fCBCSVQobGVkLT5sZWRfbm8pOwo+ID4gKwllbHNlCj4gPiArCQljdXJyID0gcHJpdi0+ZmxlZF9z dHJvYmVfdXNlZCAmIH5CSVQobGVkLT5sZWRfbm8pOwo+ID4gKwo+ID4gKwlpZiAoY3VycikKPiA+ ICsJCXZhbCB8PSBNVDYzNzBfU1RST0JFTl9NQVNLOwo+ID4gKwo+ID4gKwlyZXQgPSByZWdtYXBf dXBkYXRlX2JpdHMocHJpdi0+cmVnbWFwLCBNVDYzNzBfUkVHX0ZMRURFTiwgZW5hYmxlX21hc2ss Cj4gPiArCQkJCSB2YWwpOwo+ID4gKwlpZiAocmV0KSB7Cj4gPiArCQlkZXZfZXJyKGxjZGV2LT5k ZXYsICJbJWRdIGNvbnRyb2wgY3VycmVudCBzb3VyY2UgJWQgZmFpbFxuIiwKPiA+ICsJCQkJICAg ICBsZWQtPmxlZF9ubywgc3RhdGUpOwo+ID4gKwkJZ290byB1bmxvY2s7Cj4gPiArCX0KPiA+ICsK PiA+ICsJLyoKPiA+ICsJICogSWYgdGhlIGZsYXNoIG5lZWRzIHRvIHR1cm4gb24sIGNvbmZpZ3Vy ZSB0aGUgZmxhc2ggY3VycmVudCB0bwo+ID4gKwkgKiByYW1wIHVwIHRvIHRoZSBzZXR0aW5nIHZh bHVlLiBPdGhlcndpc2UsIGFsd2F5cyByZXZlcnQgdG8gdGhlCj4gPiArCSAqIG1pbmltdW0gb25l Lgo+ID4gKwkgKi8KPiA+ICsJcmV0ID0gX210NjM3MF9mbGFzaF9icmlnaHRuZXNzX3NldChmbF9j ZGV2LCBzdGF0ZSA/IHMtPnZhbCA6IHMtPm1pbik7Cj4gPiArCWlmIChyZXQpIHsKPiA+ICsJCWRl dl9lcnIobGNkZXYtPmRldiwgIlslZF0gRmFpbGVkIHRvIHNldCBicmlnaHRuZXNzXG4iLCBsZWQt PmxlZF9ubyk7Cj4gPiArCQlnb3RvIHVubG9jazsKPiA+ICsJfQo+ID4gKwo+ID4gKwkvKgo+ID4g KwkgKiBGb3IgdGhlIGZsYXNoIHRvIHR1cm4gb24vb2ZmLCB3ZSBtdXN0IHdhaXQgZm9yIEhXIHJh bXBpbmcKPiA+ICsJICogdXAvZG93biB0aW1lIDVtcy81MDB1cyB0byBwcmV2ZW50IHRoZSB1bmV4 cGVjdGVkIHByb2JsZW0uCj4gPiArCSAqLwo+ID4gKwlpZiAoIXByaXYtPmZsZWRfc3Ryb2JlX3Vz ZWQgJiYgY3VycikKPiA+ICsJCXVzbGVlcF9yYW5nZSg1MDAwLCA2MDAwKTsKPiA+ICsJZWxzZSBp ZiAocHJpdi0+ZmxlZF9zdHJvYmVfdXNlZCAmJiAhY3VycikKPiA+ICsJCXVzbGVlcF9yYW5nZSg1 MDAsIDYwMCk7Cj4gPiArCj4gPiArCXByaXYtPmZsZWRfc3Ryb2JlX3VzZWQgPSBjdXJyOwo+ID4g Kwo+ID4gK3VubG9jazoKPiA+ICsJbXV0ZXhfdW5sb2NrKCZwcml2LT5sb2NrKTsKPiA+ICsJcmV0 dXJuIHJldDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGludCBtdDYzNzBfc3Ryb2JlX2dldChz dHJ1Y3QgbGVkX2NsYXNzZGV2X2ZsYXNoICpmbF9jZGV2LCBib29sICpzdGF0ZSkKPiA+ICt7Cj4g PiArCXN0cnVjdCBtdDYzNzBfbGVkICpsZWQgPSB0b19tdDYzNzBfbGVkKGZsX2NkZXYsIGZsYXNo KTsKPiA+ICsJc3RydWN0IG10NjM3MF9wcml2ICpwcml2ID0gbGVkLT5wcml2Owo+ID4gKwo+ID4g KwltdXRleF9sb2NrKCZwcml2LT5sb2NrKTsKPiA+ICsJKnN0YXRlID0gISEocHJpdi0+ZmxlZF9z dHJvYmVfdXNlZCAmIEJJVChsZWQtPmxlZF9ubykpOwo+ID4gKwltdXRleF91bmxvY2soJnByaXYt PmxvY2spOwo+ID4gKwo+ID4gKwlyZXR1cm4gMDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGlu dCBtdDYzNzBfdGltZW91dF9zZXQoc3RydWN0IGxlZF9jbGFzc2Rldl9mbGFzaCAqZmxfY2Rldiwg dTMyIHRpbWVvdXQpCj4gPiArewo+ID4gKwlzdHJ1Y3QgbXQ2MzcwX2xlZCAqbGVkID0gdG9fbXQ2 MzcwX2xlZChmbF9jZGV2LCBmbGFzaCk7Cj4gPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9 IGxlZC0+cHJpdjsKPiA+ICsJc3RydWN0IGxlZF9mbGFzaF9zZXR0aW5nICpzID0gJmZsX2NkZXYt PnRpbWVvdXQ7Cj4gPiArCXUzMiB2YWwgPSAodGltZW91dCAtIHMtPm1pbikgLyBzLT5zdGVwOwo+ ID4gKwo+ID4gKwlyZXR1cm4gcmVnbWFwX3VwZGF0ZV9iaXRzKHByaXYtPnJlZ21hcCwgTVQ2Mzcw X1JFR19TVFJCVE8sCj4gPiArCQkJCSAgTVQ2MzcwX1NUUkJUT19NQVNLLCB2YWwpOwo+ID4gK30K PiA+ICsKPiA+ICtzdGF0aWMgaW50IG10NjM3MF9mYXVsdF9nZXQoc3RydWN0IGxlZF9jbGFzc2Rl dl9mbGFzaCAqZmxfY2RldiwgdTMyICpmYXVsdCkKPiA+ICt7Cj4gPiArCXN0cnVjdCBtdDYzNzBf bGVkICpsZWQgPSB0b19tdDYzNzBfbGVkKGZsX2NkZXYsIGZsYXNoKTsKPiA+ICsJc3RydWN0IG10 NjM3MF9wcml2ICpwcml2ID0gbGVkLT5wcml2Owo+ID4gKwl1MTYgZmxlZF9zdGF0Owo+ID4gKwl1 bnNpZ25lZCBpbnQgY2hnX3N0YXQsIHN0cm9iZV90aW1lb3V0X21hc2ssIGZsZWRfc2hvcnRfbWFz azsKPiA+ICsJdTMyIHJmYXVsdCA9IDA7Cj4gPiArCWludCByZXQ7Cj4gPiArCj4gPiArCXJldCA9 IHJlZ21hcF9yZWFkKHByaXYtPnJlZ21hcCwgTVQ2MzcwX1JFR19DSEdTVEFUMiwgJmNoZ19zdGF0 KTsKPiA+ICsJaWYgKHJldCkKPiA+ICsJCXJldHVybiByZXQ7Cj4gPiArCj4gPiArCXJldCA9IHJl Z21hcF9yYXdfcmVhZChwcml2LT5yZWdtYXAsIE1UNjM3MF9SRUdfRkxFRFNUQVQxLCAmZmxlZF9z dGF0LAo+ID4gKwkJCSAgICAgIHNpemVvZihmbGVkX3N0YXQpKTsKPiA+ICsJaWYgKHJldCkKPiA+ ICsJCXJldHVybiByZXQ7Cj4gPiArCj4gPiArCXN3aXRjaCAobGVkLT5sZWRfbm8pIHsKPiA+ICsJ Y2FzZSBNVDYzNzBfTEVEX0ZMQVNIMToKPiA+ICsJCXN0cm9iZV90aW1lb3V0X21hc2sgPSBNVDYz NzBfRkxFRDFTVFJCVE9fTUFTSzsKPiA+ICsJCWZsZWRfc2hvcnRfbWFzayA9IE1UNjM3MF9GTEVE MVNIT1JUX01BU0s7Cj4gPiArCQlicmVhazsKPiA+ICsKPiA+ICsJY2FzZSBNVDYzNzBfTEVEX0ZM QVNIMjoKPiA+ICsJCXN0cm9iZV90aW1lb3V0X21hc2sgPSBNVDYzNzBfRkxFRDJTVFJCVE9fTUFT SzsKPiA+ICsJCWZsZWRfc2hvcnRfbWFzayA9IE1UNjM3MF9GTEVEMlNIT1JUX01BU0s7Cj4gPiAr CQlicmVhazsKPiA+ICsKPiA+ICsJY2FzZSBNVDYzNzBfTEVEX0pPSU5UOgo+ID4gKwkJc3Ryb2Jl X3RpbWVvdXRfbWFzayA9IE1UNjM3MF9GTEVEMVNUUkJUT19NQVNLIHwKPiA+ICsJCQkJICAgICAg TVQ2MzcwX0ZMRUQyU1RSQlRPX01BU0s7Cj4gPiArCQlmbGVkX3Nob3J0X21hc2sgPSBNVDYzNzBf RkxFRDFTSE9SVF9NQVNLIHwKPiA+ICsJCQkJICBNVDYzNzBfRkxFRDJTSE9SVF9NQVNLOwo+ID4g KwkJYnJlYWs7Cj4gPiArCWRlZmF1bHQ6Cj4gPiArCQlyZXR1cm4gLUVJTlZBTDsKPiA+ICsJfQo+ ID4gKwo+ID4gKwlpZiAoY2hnX3N0YXQgJiBNVDYzNzBfRkxFRENIR1ZJTk9WUF9NQVNLKQo+ID4g KwkJcmZhdWx0IHw9IExFRF9GQVVMVF9JTlBVVF9WT0xUQUdFOwo+ID4gKwo+ID4gKwlpZiAoZmxl ZF9zdGF0ICYgc3Ryb2JlX3RpbWVvdXRfbWFzaykKPiA+ICsJCXJmYXVsdCB8PSBMRURfRkFVTFRf VElNRU9VVDsKPiA+ICsKPiA+ICsJaWYgKGZsZWRfc3RhdCAmIGZsZWRfc2hvcnRfbWFzaykKPiA+ ICsJCXJmYXVsdCB8PSBMRURfRkFVTFRfU0hPUlRfQ0lSQ1VJVDsKPiA+ICsKPiA+ICsJaWYgKGZs ZWRfc3RhdCAmIE1UNjM3MF9GTEVETFZGX01BU0spCj4gPiArCQlyZmF1bHQgfD0gTEVEX0ZBVUxU X1VOREVSX1ZPTFRBR0U7Cj4gPiArCj4gPiArCSpmYXVsdCA9IHJmYXVsdDsKPiA+ICsJcmV0dXJu IHJldDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBsZWRfZmxhc2hfb3Bz IG10NjM3MF9mbGFzaF9vcHMgPSB7Cj4gPiArCS5mbGFzaF9icmlnaHRuZXNzX3NldCA9IG10NjM3 MF9mbGFzaF9icmlnaHRuZXNzX3NldCwKPiA+ICsJLnN0cm9iZV9zZXQgPSBtdDYzNzBfc3Ryb2Jl X3NldCwKPiA+ICsJLnN0cm9iZV9nZXQgPSBtdDYzNzBfc3Ryb2JlX2dldCwKPiA+ICsJLnRpbWVv dXRfc2V0ID0gbXQ2MzcwX3RpbWVvdXRfc2V0LAo+ID4gKwkuZmF1bHRfZ2V0ID0gbXQ2MzcwX2Zh dWx0X2dldCwKPiA+ICt9Owo+ID4gKwo+ID4gKyNpZiBJU19FTkFCTEVEKENPTkZJR19WNEwyX0ZM QVNIX0xFRF9DTEFTUykKPiA+ICtzdGF0aWMgaW50IG10NjM3MF9mbGFzaF9leHRlcm5hbF9zdHJv YmVfc2V0KHN0cnVjdCB2NGwyX2ZsYXNoICp2NGwyX2ZsYXNoLAo+ID4gKwkJCQkJICAgIGJvb2wg ZW5hYmxlKQo+ID4gK3sKPiA+ICsJc3RydWN0IGxlZF9jbGFzc2Rldl9mbGFzaCAqZmxhc2ggPSB2 NGwyX2ZsYXNoLT5mbGVkX2NkZXY7Cj4gPiArCXN0cnVjdCBtdDYzNzBfbGVkICpsZWQgPSB0b19t dDYzNzBfbGVkKGZsYXNoLCBmbGFzaCk7Cj4gPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9 IGxlZC0+cHJpdjsKPiA+ICsJdTMyIG1hc2sgPSBsZWQtPmxlZF9ubyA9PSBNVDYzNzBfTEVEX0pP SU5UID8gTVQ2MzcwX0ZMQ1NFTl9NQVNLX0FMTCA6Cj4gPiArCQkgICBNVDYzNzBfRkxDU0VOX01B U0sobGVkLT5sZWRfbm8pOwo+ID4gKwl1MzIgdmFsID0gZW5hYmxlID8gbWFzayA6IDA7Cj4gPiAr CWludCByZXQ7Cj4gPiArCj4gPiArCW11dGV4X2xvY2soJnByaXYtPmxvY2spOwo+ID4gKwo+ID4g KwlyZXQgPSByZWdtYXBfdXBkYXRlX2JpdHMocHJpdi0+cmVnbWFwLCBNVDYzNzBfUkVHX0ZMRURF TiwgbWFzaywgdmFsKTsKPiA+ICsJaWYgKHJldCkKPiA+ICsJCWdvdG8gdW5sb2NrOwo+ID4gKwo+ ID4gKwlpZiAoZW5hYmxlKQo+ID4gKwkJcHJpdi0+ZmxlZF9zdHJvYmVfdXNlZCB8PSBCSVQobGVk LT5sZWRfbm8pOwo+ID4gKwllbHNlCj4gPiArCQlwcml2LT5mbGVkX3N0cm9iZV91c2VkICY9IH5C SVQobGVkLT5sZWRfbm8pOwo+ID4gKwo+ID4gK3VubG9jazoKPiA+ICsJbXV0ZXhfdW5sb2NrKCZw cml2LT5sb2NrKTsKPiA+ICsJcmV0dXJuIHJldDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGNv bnN0IHN0cnVjdCB2NGwyX2ZsYXNoX29wcyB2NGwyX2ZsYXNoX29wcyA9IHsKPiA+ICsJLmV4dGVy bmFsX3N0cm9iZV9zZXQgPSBtdDYzNzBfZmxhc2hfZXh0ZXJuYWxfc3Ryb2JlX3NldCwKPiA+ICt9 Owo+ID4gKwo+ID4gK3N0YXRpYyB2b2lkIG10NjM3MF9pbml0X3Y0bDJfZmxhc2hfY29uZmlnKHN0 cnVjdCBtdDYzNzBfbGVkICpsZWQsCj4gPiArCQkJCQkgIHN0cnVjdCB2NGwyX2ZsYXNoX2NvbmZp ZyAqY2ZnKQo+ID4gK3sKPiA+ICsJc3RydWN0IGxlZF9jbGFzc2RldiAqbGNkZXY7Cj4gPiArCXN0 cnVjdCBsZWRfZmxhc2hfc2V0dGluZyAqcyA9ICZjZmctPmludGVuc2l0eTsKPiA+ICsKPiA+ICsJ bGNkZXYgPSAmbGVkLT5mbGFzaC5sZWRfY2RldjsKPiA+ICsKPiA+ICsJcy0+bWluID0gTVQ2Mzcw X0lUT1JDSF9NSU5fdUE7Cj4gPiArCXMtPnN0ZXAgPSBNVDYzNzBfSVRPUkNIX1NURVBfdUE7Cj4g PiArCXMtPnZhbCA9IHMtPm1heCA9IHMtPm1pbiArIChsY2Rldi0+bWF4X2JyaWdodG5lc3MgLSAx KSAqIHMtPnN0ZXA7Cj4gPiArCj4gPiArCWNmZy0+aGFzX2V4dGVybmFsX3N0cm9iZSA9IDE7Cj4g Cj4gaGFzX2V4dGVybmFsX3N0cm9iZSBpcyBhIGJvb2wuCj4KSSBjaGVja2VkIHRoZSBkZWZpbmUs ICdoYXNfZXh0ZXJuYWxfc3Ryb2JlJyBpcyBhIDEtYml0IGJpdGZpZWxkIG9mICd1bnNpZ25lZCBp bnQnLgpUbyBhc3NpZ24gYXMgJzEnIHNlZW1zIG1vcmUgcmVhc29uYWJsZSB0aGFuICd0cnVlJy4K Cj4gPiArCXN0cnNjcHkoY2ZnLT5kZXZfbmFtZSwgZGV2X25hbWUobGNkZXYtPmRldiksIHNpemVv ZihjZmctPmRldl9uYW1lKSk7Cj4gPiArCj4gPiArCWNmZy0+Zmxhc2hfZmF1bHRzID0gTEVEX0ZB VUxUX1NIT1JUX0NJUkNVSVQgfCBMRURfRkFVTFRfVElNRU9VVCB8Cj4gPiArCQkJICAgIExFRF9G QVVMVF9JTlBVVF9WT0xUQUdFIHwgTEVEX0ZBVUxUX1VOREVSX1ZPTFRBR0U7Cj4gPiArfQo+ID4g KyNlbHNlCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCB2NGwyX2ZsYXNoX29wcyB2NGwyX2ZsYXNo X29wczsKPiA+ICtzdGF0aWMgdm9pZCBtdDYzNzBfaW5pdF92NGwyX2ZsYXNoX2NvbmZpZyhzdHJ1 Y3QgbXQ2MzcwX2xlZCAqbGVkLAo+ID4gKwkJCQkJICBzdHJ1Y3QgdjRsMl9mbGFzaF9jb25maWcg KmNmZykKPiA+ICt7Cj4gPiArfQo+ID4gKyNlbmRpZgo+ID4gKwo+ID4gK3N0YXRpYyB2b2lkIG10 NjM3MF92NGwyX2ZsYXNoX3JlbGVhc2Uodm9pZCAqdjRsMl9mbGFzaCkKPiA+ICt7Cj4gPiArCXY0 bDJfZmxhc2hfcmVsZWFzZSh2NGwyX2ZsYXNoKTsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGlu dCBtdDYzNzBfbGVkX3JlZ2lzdGVyKHN0cnVjdCBkZXZpY2UgKnBhcmVudCwgc3RydWN0IG10NjM3 MF9sZWQgKmxlZCwKPiA+ICsJCQkJc3RydWN0IGZ3bm9kZV9oYW5kbGUgKmZ3bm9kZSkKPiA+ICt7 Cj4gPiArCXN0cnVjdCBsZWRfaW5pdF9kYXRhIGluaXRfZGF0YSA9IHsgLmZ3bm9kZSA9IGZ3bm9k ZSB9Owo+ID4gKwlzdHJ1Y3QgdjRsMl9mbGFzaF9jb25maWcgdjRsMl9jb25maWcgPSB7fTsKPiA+ ICsJaW50IHJldDsKPiA+ICsKPiA+ICsJcmV0ID0gZGV2bV9sZWRfY2xhc3NkZXZfZmxhc2hfcmVn aXN0ZXJfZXh0KHBhcmVudCwgJmxlZC0+Zmxhc2gsCj4gPiArCQkJCQkJICAgJmluaXRfZGF0YSk7 Cj4gPiArCWlmIChyZXQpCj4gPiArCQlyZXR1cm4gZGV2X2Vycl9wcm9iZShwYXJlbnQsIHJldCwK PiA+ICsJCQkJICAgICAiQ291bGRuJ3QgcmVnaXN0ZXIgZmxhc2ggJWRcbiIsIGxlZC0+bGVkX25v KTsKPiA+ICsKPiA+ICsJbXQ2MzcwX2luaXRfdjRsMl9mbGFzaF9jb25maWcobGVkLCAmdjRsMl9j b25maWcpOwo+ID4gKwlsZWQtPnY0bDJfZmxhc2ggPSB2NGwyX2ZsYXNoX2luaXQocGFyZW50LCBm d25vZGUsICZsZWQtPmZsYXNoLAo+ID4gKwkJCQkJICAmdjRsMl9mbGFzaF9vcHMsICZ2NGwyX2Nv bmZpZyk7Cj4gPiArCWlmIChJU19FUlIobGVkLT52NGwyX2ZsYXNoKSkKPiA+ICsJCXJldHVybiBk ZXZfZXJyX3Byb2JlKHBhcmVudCwgUFRSX0VSUihsZWQtPnY0bDJfZmxhc2gpLAo+ID4gKwkJCQkg ICAgICJGYWlsZWQgdG8gcmVnaXN0ZXIgJWQgdjRsMiBzZFxuIiwgbGVkLT5sZWRfbm8pOwo+ID4g Kwo+ID4gKwlyZXR1cm4gZGV2bV9hZGRfYWN0aW9uX29yX3Jlc2V0KHBhcmVudCwgbXQ2MzcwX3Y0 bDJfZmxhc2hfcmVsZWFzZSwKPiA+ICsJCQkJCWxlZC0+djRsMl9mbGFzaCk7Cj4gPiArfQo+ID4g Kwo+ID4gK3N0YXRpYyB1MzIgbXQ2MzcwX2NsYW1wKHUzMiB2YWwsIHUzMiBtaW4sIHUzMiBtYXgs IHUzMiBzdGVwKQo+ID4gK3sKPiA+ICsJdTMyIHJldHZhbDsKPiA+ICsKPiA+ICsJcmV0dmFsID0g Y2xhbXBfdmFsKHZhbCwgbWluLCBtYXgpOwo+ID4gKwlpZiAoc3RlcCA+IDEpCj4gPiArCQlyZXR2 YWwgPSByb3VuZGRvd24ocmV0dmFsIC0gbWluLCBzdGVwKSArIG1pbjsKPiA+ICsKPiA+ICsJcmV0 dXJuIHJldHZhbDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGludCBtdDYzNzBfaW5pdF9mbGFz aF9wcm9wZXJ0aWVzKHN0cnVjdCBkZXZpY2UgKmRldiwKPiA+ICsJCQkJCXN0cnVjdCBtdDYzNzBf bGVkICpsZWQsCj4gPiArCQkJCQlzdHJ1Y3QgZndub2RlX2hhbmRsZSAqZndub2RlKQo+ID4gK3sK PiA+ICsJc3RydWN0IGxlZF9jbGFzc2Rldl9mbGFzaCAqZmxhc2ggPSAmbGVkLT5mbGFzaDsKPiA+ ICsJc3RydWN0IGxlZF9jbGFzc2RldiAqbGNkZXYgPSAmZmxhc2gtPmxlZF9jZGV2Owo+ID4gKwlz dHJ1Y3QgbXQ2MzcwX3ByaXYgKnByaXYgPSBsZWQtPnByaXY7Cj4gPiArCXN0cnVjdCBsZWRfZmxh c2hfc2V0dGluZyAqczsKPiA+ICsJdTMyIHNvdXJjZXNbTVQ2MzcwX01BWF9MRURTXTsKPiA+ICsJ dTMyIG1heF91YSwgdmFsOwo+ID4gKwlpbnQgaSwgcmV0LCBudW07Cj4gPiArCj4gPiArCW51bSA9 IGZ3bm9kZV9wcm9wZXJ0eV9jb3VudF91MzIoZndub2RlLCAibGVkLXNvdXJjZXMiKTsKPiA+ICsJ aWYgKG51bSA8IDEpCj4gPiArCQlyZXR1cm4gZGV2X2Vycl9wcm9iZShkZXYsIC1FSU5WQUwsCj4g PiArCQkJCSAgICAgIk5vdCBzcGVjaWZpZWQgb3Igd3JvbmcgbnVtYmVyIG9mIGxlZC1zb3VyY2Vz XG4iKTsKPiA+ICsKPiA+ICsJcmV0ID0gZndub2RlX3Byb3BlcnR5X3JlYWRfdTMyX2FycmF5KGZ3 bm9kZSwgImxlZC1zb3VyY2VzIiwgc291cmNlcywgbnVtKTsKPiA+ICsJaWYgKHJldCkKPiA+ICsJ CXJldHVybiByZXQ7Cj4gPiArCj4gPiArCWZvciAoaSA9IDA7IGkgPCBudW07IGkrKykgewo+ID4g KwkJaWYgKHNvdXJjZXNbaV0gPj0gTVQ2MzcwX01BWF9MRURTKQo+ID4gKwkJCXJldHVybiAtRUlO VkFMOwo+ID4gKwkJaWYgKHByaXYtPmxlZHNfYWN0aXZlICYgQklUKHNvdXJjZXNbaV0pKQo+ID4g KwkJCXJldHVybiAtRUlOVkFMOwo+ID4gKwkJcHJpdi0+bGVkc19hY3RpdmUgfD0gQklUKHNvdXJj ZXNbaV0pOwo+ID4gKwl9Cj4gPiArCj4gPiArCWxlZC0+bGVkX25vID0gbnVtID09IDIgPyBNVDYz NzBfTEVEX0pPSU5UIDogc291cmNlc1swXTsKPiA+ICsKPiA+ICsJbWF4X3VhID0gbnVtID09IDIg PyBNVDYzNzBfSVRPUkNIX0RPVUJMRV9NQVhfdUEgOiBNVDYzNzBfSVRPUkNIX01BWF91QTsKPiA+ ICsJdmFsID0gTVQ2MzcwX0lUT1JDSF9NSU5fdUE7Cj4gCj4gSW4gd2hhdCBzY2VuYXJpbyBkb2Vz IHRoaXMgbm90IGdldCBvdmVyd3JpdHRlbj8KPiAKT25seSBpZiB0aGUgcHJvcGVydHkgaXMgbWlz c2luZy4gVGhpcyB3aWxsIG1ha2UgdGhlIHZhbHVlIGtlZXAgaW4gbWluaW11bS4KPiA+ICsJcmV0 ID0gZndub2RlX3Byb3BlcnR5X3JlYWRfdTMyKGZ3bm9kZSwgImxlZC1tYXgtbWljcm9hbXAiLCAm dmFsKTsKPiA+ICsJaWYgKCFyZXQpCj4gPiArCQl2YWwgPSBtdDYzNzBfY2xhbXAodmFsLCBNVDYz NzBfSVRPUkNIX01JTl91QSwgbWF4X3VhLAo+ID4gKwkJCQkgICBNVDYzNzBfSVRPUkNIX1NURVBf dUEpOwo+ID4gKwo+ID4gKwlsY2Rldi0+bWF4X2JyaWdodG5lc3MgPSAodmFsIC0gTVQ2MzcwX0lU T1JDSF9NSU5fdUEpIC8KPiA+ICsJCQkJIE1UNjM3MF9JVE9SQ0hfU1RFUF91QSArIDE7Cj4gPiAr CWxjZGV2LT5icmlnaHRuZXNzX3NldF9ibG9ja2luZyA9IG10NjM3MF90b3JjaF9icmlnaHRuZXNz X3NldDsKPiA+ICsJbGNkZXYtPmZsYWdzIHw9IExFRF9ERVZfQ0FQX0ZMQVNIOwo+ID4gKwo+ID4g KwltYXhfdWEgPSBudW0gPT0gMiA/IE1UNjM3MF9JU1RSQl9ET1VCTEVfTUFYX3VBIDogTVQ2Mzcw X0lTVFJCX01BWF91QTsKPiA+ICsJdmFsID0gTVQ2MzcwX0lTVFJCX01JTl91QTsKPiA+ICsJcmV0 ID0gZndub2RlX3Byb3BlcnR5X3JlYWRfdTMyKGZ3bm9kZSwgImZsYXNoLW1heC1taWNyb2FtcCIs ICZ2YWwpOwo+ID4gKwlpZiAoIXJldCkKPiA+ICsJCXZhbCA9IG10NjM3MF9jbGFtcCh2YWwsIE1U NjM3MF9JU1RSQl9NSU5fdUEsIG1heF91YSwKPiA+ICsJCQkJICAgTVQ2MzcwX0lTVFJCX1NURVBf dUEpOwo+ID4gKwo+ID4gKwlzID0gJmZsYXNoLT5icmlnaHRuZXNzOwo+ID4gKwlzLT5taW4gPSBN VDYzNzBfSVNUUkJfTUlOX3VBOwo+ID4gKwlzLT5zdGVwID0gTVQ2MzcwX0lTVFJCX1NURVBfdUE7 Cj4gPiArCXMtPnZhbCA9IHMtPm1heCA9IHZhbDsKPiA+ICsKPiA+ICsJLyoKPiA+ICsJICogQWx3 YXlzIGNvbmZpZ3VyZSB0byB0aGUgbWluaW11bSBsZXZlbCB3aGVuCj4gPiArCSAqIG9mZiB0byBw cmV2ZW50IGZsYXNoIGN1cnJlbnQgc3Bpa2VzLgo+ID4gKwkgKi8KPiA+ICsJcmV0ID0gX210NjM3 MF9mbGFzaF9icmlnaHRuZXNzX3NldChmbGFzaCwgcy0+bWluKTsKPiA+ICsJaWYgKHJldCkKPiA+ ICsJCXJldHVybiByZXQ7Cj4gPiArCj4gPiArCj4gPiArCXZhbCA9IE1UNjM3MF9TVFJCVE9fTUlO X1VTOwo+IAo+IEFzIGFib3ZlLgo+IAo+ID4gKwlyZXQgPSBmd25vZGVfcHJvcGVydHlfcmVhZF91 MzIoZndub2RlLCAiZmxhc2gtbWF4LXRpbWVvdXQtdXMiLCAmdmFsKTsKPiA+ICsJaWYgKCFyZXQp Cj4gPiArCQl2YWwgPSBtdDYzNzBfY2xhbXAodmFsLCBNVDYzNzBfU1RSQlRPX01JTl9VUywKPiA+ ICsJCQkJICAgTVQ2MzcwX1NUUkJUT19NQVhfVVMsIE1UNjM3MF9TVFJCVE9fU1RFUF9VUyk7Cj4g PiArCj4gPiArCXMgPSAmZmxhc2gtPnRpbWVvdXQ7Cj4gPiArCXMtPm1pbiA9IE1UNjM3MF9TVFJC VE9fTUlOX1VTOwo+ID4gKwlzLT5zdGVwID0gTVQ2MzcwX1NUUkJUT19TVEVQX1VTOwo+ID4gKwlz LT52YWwgPSBzLT5tYXggPSB2YWw7Cj4gPiArCj4gPiArCWZsYXNoLT5vcHMgPSAmbXQ2MzcwX2Zs YXNoX29wczsKPiA+ICsKPiA+ICsJcmV0dXJuIDA7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBp bnQgbXQ2MzcwX2xlZF9wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQo+ID4gK3sK PiA+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRldjsKPiA+ICsJc3RydWN0IG10NjM3 MF9wcml2ICpwcml2Owo+ID4gKwlzdHJ1Y3QgZndub2RlX2hhbmRsZSAqY2hpbGQ7Cj4gPiArCXNp emVfdCBjb3VudDsKPiA+ICsJaW50IGkgPSAwLCByZXQ7Cj4gPiArCj4gPiArCWNvdW50ID0gZGV2 aWNlX2dldF9jaGlsZF9ub2RlX2NvdW50KGRldik7Cj4gPiArCWlmICghY291bnQgfHwgY291bnQg PiBNVDYzNzBfTUFYX0xFRFMpCj4gPiArCQlyZXR1cm4gZGV2X2Vycl9wcm9iZShkZXYsIC1FSU5W QUwsCj4gPiArCQkgICAgICAgIk5vIGNoaWxkIG5vZGUgb3Igbm9kZSBjb3VudCBvdmVyIG1heCBs ZWQgbnVtYmVyICV6dVxuIiwgY291bnQpOwo+ID4gKwo+ID4gKwlwcml2ID0gZGV2bV9remFsbG9j KGRldiwgc3RydWN0X3NpemUocHJpdiwgbGVkcywgY291bnQpLCBHRlBfS0VSTkVMKTsKPiA+ICsJ aWYgKCFwcml2KQo+ID4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gPiArCj4gPiArCXByaXYtPmxlZHNf Y291bnQgPSBjb3VudDsKPiA+ICsJbXV0ZXhfaW5pdCgmcHJpdi0+bG9jayk7Cj4gPiArCj4gPiAr CXByaXYtPnJlZ21hcCA9IGRldl9nZXRfcmVnbWFwKGRldi0+cGFyZW50LCBOVUxMKTsKPiA+ICsJ aWYgKCFwcml2LT5yZWdtYXApCj4gPiArCQlyZXR1cm4gZGV2X2Vycl9wcm9iZShkZXYsIC1FTk9E RVYsICJGYWlsZWQgdG8gZ2V0IHBhcmVudCByZWdtYXBcbiIpOwo+ID4gKwo+ID4gKwlkZXZpY2Vf Zm9yX2VhY2hfY2hpbGRfbm9kZShkZXYsIGNoaWxkKSB7Cj4gPiArCQlzdHJ1Y3QgbXQ2MzcwX2xl ZCAqbGVkID0gcHJpdi0+bGVkcyArIGk7Cj4gPiArCj4gPiArCQlsZWQtPnByaXYgPSBwcml2Owo+ ID4gKwo+ID4gKwkJcmV0ID0gbXQ2MzcwX2luaXRfZmxhc2hfcHJvcGVydGllcyhkZXYsIGxlZCwg Y2hpbGQpOwo+ID4gKwkJaWYgKHJldCkgewo+ID4gKwkJCWZ3bm9kZV9oYW5kbGVfcHV0KGNoaWxk KTsKPiA+ICsJCQlyZXR1cm4gcmV0Owo+ID4gKwkJfQo+ID4gKwo+ID4gKwkJcmV0ID0gbXQ2Mzcw X2xlZF9yZWdpc3RlcihkZXYsIGxlZCwgY2hpbGQpOwo+ID4gKwkJaWYgKHJldCkgewo+ID4gKwkJ CWZ3bm9kZV9oYW5kbGVfcHV0KGNoaWxkKTsKPiA+ICsJCQlyZXR1cm4gcmV0Owo+ID4gKwkJfQo+ ID4gKwo+ID4gKwkJaSsrOwo+ID4gKwl9Cj4gPiArCj4gPiArCXJldHVybiAwOwo+ID4gK30KPiA+ ICsKPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IG9mX2RldmljZV9pZCBtdDYzNzBfbGVkX29mX2lk W10gPSB7Cj4gPiArCXsgLmNvbXBhdGlibGUgPSAibWVkaWF0ZWssbXQ2MzcwLWZsYXNobGlnaHQi IH0sCj4gPiArCXsgLyogc2VudGluZWwgKi8gfQo+IAo+IFBsZWFzZSByZW1vdmUgdGhpcyBjb21t ZW50LiAgV2Uga25vdyBob3cgTlVMTCB0ZXJtaW5hdG9ycyB3b3JrLiA6KQo+IAo+ID4gK307Cj4g PiArTU9EVUxFX0RFVklDRV9UQUJMRShvZiwgbXQ2MzcwX2xlZF9vZl9pZCk7Cj4gPiArCj4gPiAr c3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgbXQ2MzcwX2xlZF9kcml2ZXIgPSB7Cj4gPiAr CS5kcml2ZXIgPSB7Cj4gPiArCQkubmFtZSA9ICJtdDYzNzAtZmxhc2hsaWdodCIsCj4gPiArCQku b2ZfbWF0Y2hfdGFibGUgPSBtdDYzNzBfbGVkX29mX2lkLAo+ID4gKwl9LAo+ID4gKwkucHJvYmUg PSBtdDYzNzBfbGVkX3Byb2JlLAo+ID4gK307Cj4gPiArbW9kdWxlX3BsYXRmb3JtX2RyaXZlciht dDYzNzBfbGVkX2RyaXZlcik7Cj4gPiArCj4gPiArTU9EVUxFX0FVVEhPUigiQWxpY2UgQ2hlbiA8 YWxpY2VfY2hlbkByaWNodGVrLmNvbT4iKTsKPiA+ICtNT0RVTEVfQVVUSE9SKCJDaGlZdWFuIEh1 YW5nIDxjeV9odWFuZ0ByaWNodGVrLmNvbT4iKTsKPiA+ICtNT0RVTEVfREVTQ1JJUFRJT04oIk1U NjM3MCBGTEFTSCBMRUQgRHJpdmVyIik7Cj4gPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOwo+ID4g LS0gCj4gPiAyLjcuNAo+ID4gCj4gCj4gLS0gCj4gTGVlIEpvbmVzIFvmnY7nkLzmlq9dCgpfX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsaW51eC1hcm0ta2Vy bmVsIG1haWxpbmcgbGlzdApsaW51eC1hcm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0 cDovL2xpc3RzLmluZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1hcm0ta2VybmVs Cg==