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 04894C54EAA for ; Fri, 27 Jan 2023 10:20:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230035AbjA0KUj (ORCPT ); Fri, 27 Jan 2023 05:20:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60494 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232305AbjA0KUg (ORCPT ); Fri, 27 Jan 2023 05:20:36 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6503E8A6D; Fri, 27 Jan 2023 02:20:22 -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 ams.source.kernel.org (Postfix) with ESMTPS id DA7F2B82012; Fri, 27 Jan 2023 10:20:20 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4485EC433EF; Fri, 27 Jan 2023 10:20:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1674814819; bh=2wxu7ntwMi6ZNQWRoK77fbDuMKV9hnY+XYvRBl8shbw=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=tDUguWG8Fcm081aJA6EOtz2krl12ICOPl6VIPX8iO5iEdtMMdvjiuwLd4PTCkzPGY 639VDZDBrO5NmRTGP131WnIHnNi/RCowy2d4MKXxI2cwOt+IP874i+ZcYNvkL0/6u3 svsZ+hgsjOujJ8QNhKrVT0EaUs4/LxKKRyc75/dYpwxlfc1cyg3prnV0soxFgKv4rf LplM8u8mtt98xZRwSAP9qsQvtNLYdhuxewpCMRCvsQ4lHsqKvlAPZWi/ZlogIMeXtH yMgk8YT1sLw5qI/S/vYfe7/0Atny7k6jOLKzyuu+XrwAqQz3a42hsrCjcRoJpNAwXl l28EB8K+J4tGA== Date: Fri, 27 Jan 2023 10:20:12 +0000 From: Lee Jones To: ChiaEn Wu , Jacek Anaszewski Cc: pavel@ucw.cz, matthias.bgg@gmail.com, andriy.shevchenko@linux.intel.com, 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 , ChiaEn Wu Subject: Re: [PATCH v16 2/2] leds: flash: mt6370: Add MediaTek MT6370 flashlight support Message-ID: References: <7a6ac0051789831a7a53c2f3b66010fc0f1e5395.1673886245.git.chiaen_wu@richtek.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <7a6ac0051789831a7a53c2f3b66010fc0f1e5395.1673886245.git.chiaen_wu@richtek.com> Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org Jacek, Andy, On Tue, 17 Jan 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. > > Co-developed-by: Alice Chen > Signed-off-by: Alice Chen > Signed-off-by: ChiYuan Huang > Signed-off-by: ChiaEn Wu > --- > > v16 > - Remove blank line in the head text. > - For enum, declared the first element as 0 > - Remove unusd default state and state define. > - For mt6370_priv, 'dev' member only be used once. Remove it. > - Refine assign operator for '?:', no need to use brackets for the > judgement. > - Refine '_mt6370_flash_brightness_set' function for else case. > - Modify 'struct led_flash_setting *setting' to 'struct > led_flash_setting *s'. This can reduce line count. > - Remove the revert logic in 'mt6370_strobe_set' function. > No need to do it. > - Remove mutex usage in timeout_set and fault_get. > Regmap lock already protect it. > - Add default label for switch case in fault_get. > - Directly assign fwnode as the parameter for 'mt6370_led_register' and > 'mt6370_init_flash_config'. > - Due to struct mt6370_priv 'dev' member removed, pass 'dev' as the > input parameter for 'mt6370_init_flash_config'. > - For some if judgement, remove 'num > MT6370_MAX_LEDS'. > There's no need to check it. The below code already protect it. > - Group mt6360 and mt6370 in Makefile. > - SPDX already declared as 'GPL v2-only', change MODULE_LICENSE to > 'GPL'. > - Add one more author for ChiYuan Huang. > --- > 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 I see that you guys have been super helpful reviewing this in the past. Have your queries now been addressed? > 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..e5c4c94 > --- /dev/null > +++ b/drivers/leds/flash/leds-mt6370-flash.c > @@ -0,0 +1,596 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (C) 2022 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) { > + u32 flevel[MT6370_MAX_LEDS]; > + > + flevel[0] = val / 2; > + flevel[1] = val - flevel[0]; > + 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; > + 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; > + 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; > + 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 */ } > +}; > +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 3C7FBC54EAA for ; Fri, 27 Jan 2023 10:21:39 +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=/uAZSqsCUr8sYHKUqB482rrSX+PH7OLcrrErvm+IPxg=; b=ayPWF7z9aIOwJG +1iSJDqsM+/XWvFqcnnWV2WwAzU11pbGtxv/VmyjTh/Q7s8Euq62DyUosoJCmTg4mXLknrrlB2y1h rjywWaIoWK8MVVwlSmg7J6/IylCAXiadNrR/VeyFX1pBx/xlWbyFRi5CplykUCET99trAagPVkNVt nmnZUSpQxPlKmQoz7tCRtVoJwAXRXvo7nU0Em6MWfBNqiR0oAXatlKD3jJTDvliVesIN3vF8G7Lha 01Y6IAzyXZ4oG6oJvBxrd415WUi+YqkMoKcILpoUZjRGvivLVeC7axJvxGJU4xf1k7bCmj/42K5Pj nMnYMEYyqMrdMeGZ64PA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pLLqT-00DuSe-8f; Fri, 27 Jan 2023 10:20:33 +0000 Received: from ams.source.kernel.org ([2604:1380:4601:e00::1]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1pLLqI-00DuNN-Fj; Fri, 27 Jan 2023 10:20:29 +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 ams.source.kernel.org (Postfix) with ESMTPS id CF92AB8200B; Fri, 27 Jan 2023 10:20:20 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4485EC433EF; Fri, 27 Jan 2023 10:20:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1674814819; bh=2wxu7ntwMi6ZNQWRoK77fbDuMKV9hnY+XYvRBl8shbw=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=tDUguWG8Fcm081aJA6EOtz2krl12ICOPl6VIPX8iO5iEdtMMdvjiuwLd4PTCkzPGY 639VDZDBrO5NmRTGP131WnIHnNi/RCowy2d4MKXxI2cwOt+IP874i+ZcYNvkL0/6u3 svsZ+hgsjOujJ8QNhKrVT0EaUs4/LxKKRyc75/dYpwxlfc1cyg3prnV0soxFgKv4rf LplM8u8mtt98xZRwSAP9qsQvtNLYdhuxewpCMRCvsQ4lHsqKvlAPZWi/ZlogIMeXtH yMgk8YT1sLw5qI/S/vYfe7/0Atny7k6jOLKzyuu+XrwAqQz3a42hsrCjcRoJpNAwXl l28EB8K+J4tGA== Date: Fri, 27 Jan 2023 10:20:12 +0000 From: Lee Jones To: ChiaEn Wu , Jacek Anaszewski Cc: pavel@ucw.cz, matthias.bgg@gmail.com, andriy.shevchenko@linux.intel.com, 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 , ChiaEn Wu Subject: Re: [PATCH v16 2/2] leds: flash: mt6370: Add MediaTek MT6370 flashlight support Message-ID: References: <7a6ac0051789831a7a53c2f3b66010fc0f1e5395.1673886245.git.chiaen_wu@richtek.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <7a6ac0051789831a7a53c2f3b66010fc0f1e5395.1673886245.git.chiaen_wu@richtek.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20230127_022022_887838_94B226C3 X-CRM114-Status: GOOD ( 45.53 ) 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 SmFjZWssIEFuZHksCgpPbiBUdWUsIDE3IEphbiAyMDIzLCBDaGlhRW4gV3Ugd3JvdGU6Cgo+IEZy b206IENoaVl1YW4gSHVhbmcgPGN5X2h1YW5nQHJpY2h0ZWsuY29tPgo+IAo+IFRoZSBNZWRpYVRl ayBNVDYzNzAgaXMgYSBoaWdobHktaW50ZWdyYXRlZCBzbWFydCBwb3dlciBtYW5hZ2VtZW50IElD LAo+IHdoaWNoIGluY2x1ZGVzIGEgc2luZ2xlIGNlbGwgTGktSW9uL0xpLVBvbHltZXIgc3dpdGNo aW5nIGJhdHRlcnkKPiBjaGFyZ2VyLCBhIFVTQiBUeXBlLUMgJiBQb3dlciBEZWxpdmVyeSAoUEQp IGNvbnRyb2xsZXIsIGR1YWwgRmxhc2gKPiBMRUQgY3VycmVudCBzb3VyY2VzLCBhIFJHQiBMRUQg ZHJpdmVyLCBhIGJhY2tsaWdodCBXTEVEIGRyaXZlciwKPiBhIGRpc3BsYXkgYmlhcyBkcml2ZXIg YW5kIGEgZ2VuZXJhbCBMRE8gZm9yIHBvcnRhYmxlIGRldmljZXMuCj4gCj4gQWRkIHN1cHBvcnQg Zm9yIHRoZSBNVDYzNzAgRmxhc2ggTEVEIGRyaXZlci4gRmxhc2ggTEVEIGluIE1UNjM3MAo+IGhh cyAyIGNoYW5uZWxzIGFuZCBzdXBwb3J0IHRvcmNoL3N0cm9iZSBtb2RlLgo+IAo+IENvLWRldmVs b3BlZC1ieTogQWxpY2UgQ2hlbiA8YWxpY2VfY2hlbkByaWNodGVrLmNvbT4KPiBTaWduZWQtb2Zm LWJ5OiBBbGljZSBDaGVuIDxhbGljZV9jaGVuQHJpY2h0ZWsuY29tPgo+IFNpZ25lZC1vZmYtYnk6 IENoaVl1YW4gSHVhbmcgPGN5X2h1YW5nQHJpY2h0ZWsuY29tPgo+IFNpZ25lZC1vZmYtYnk6IENo aWFFbiBXdSA8Y2hpYWVuX3d1QHJpY2h0ZWsuY29tPgo+IC0tLQo+IAo+IHYxNgo+IC0gUmVtb3Zl IGJsYW5rIGxpbmUgaW4gdGhlIGhlYWQgdGV4dC4KPiAtIEZvciBlbnVtLCBkZWNsYXJlZCB0aGUg Zmlyc3QgZWxlbWVudCBhcyAwCj4gLSBSZW1vdmUgdW51c2QgZGVmYXVsdCBzdGF0ZSBhbmQgc3Rh dGUgZGVmaW5lLgo+IC0gRm9yIG10NjM3MF9wcml2LCAnZGV2JyBtZW1iZXIgb25seSBiZSB1c2Vk IG9uY2UuIFJlbW92ZSBpdC4KPiAtIFJlZmluZSBhc3NpZ24gb3BlcmF0b3IgZm9yICc/OicsIG5v IG5lZWQgdG8gdXNlIGJyYWNrZXRzIGZvciB0aGUKPiAgIGp1ZGdlbWVudC4KPiAtIFJlZmluZSAn X210NjM3MF9mbGFzaF9icmlnaHRuZXNzX3NldCcgZnVuY3Rpb24gZm9yIGVsc2UgY2FzZS4KPiAt IE1vZGlmeSAnc3RydWN0IGxlZF9mbGFzaF9zZXR0aW5nICpzZXR0aW5nJyB0byAnc3RydWN0Cj4g ICBsZWRfZmxhc2hfc2V0dGluZyAqcycuIFRoaXMgY2FuIHJlZHVjZSBsaW5lIGNvdW50Lgo+IC0g UmVtb3ZlIHRoZSByZXZlcnQgbG9naWMgaW4gJ210NjM3MF9zdHJvYmVfc2V0JyBmdW5jdGlvbi4K PiAgIE5vIG5lZWQgdG8gZG8gaXQuCj4gLSBSZW1vdmUgbXV0ZXggdXNhZ2UgaW4gdGltZW91dF9z ZXQgYW5kIGZhdWx0X2dldC4KPiAgIFJlZ21hcCBsb2NrIGFscmVhZHkgcHJvdGVjdCBpdC4KPiAt IEFkZCBkZWZhdWx0IGxhYmVsIGZvciBzd2l0Y2ggY2FzZSBpbiBmYXVsdF9nZXQuCj4gLSBEaXJl Y3RseSBhc3NpZ24gZndub2RlIGFzIHRoZSBwYXJhbWV0ZXIgZm9yICdtdDYzNzBfbGVkX3JlZ2lz dGVyJyBhbmQKPiAgICdtdDYzNzBfaW5pdF9mbGFzaF9jb25maWcnLgo+IC0gRHVlIHRvIHN0cnVj dCBtdDYzNzBfcHJpdiAnZGV2JyBtZW1iZXIgcmVtb3ZlZCwgcGFzcyAnZGV2JyBhcyB0aGUKPiAg IGlucHV0IHBhcmFtZXRlciBmb3IgJ210NjM3MF9pbml0X2ZsYXNoX2NvbmZpZycuCj4gLSBGb3Ig c29tZSBpZiBqdWRnZW1lbnQsIHJlbW92ZSAnbnVtID4gTVQ2MzcwX01BWF9MRURTJy4KPiAgIFRo ZXJlJ3Mgbm8gbmVlZCB0byBjaGVjayBpdC4gVGhlIGJlbG93IGNvZGUgYWxyZWFkeSBwcm90ZWN0 IGl0Lgo+IC0gR3JvdXAgbXQ2MzYwIGFuZCBtdDYzNzAgaW4gTWFrZWZpbGUuCj4gLSBTUERYIGFs cmVhZHkgZGVjbGFyZWQgYXMgJ0dQTCB2Mi1vbmx5JywgY2hhbmdlIE1PRFVMRV9MSUNFTlNFIHRv Cj4gICAnR1BMJy4KPiAtIEFkZCBvbmUgbW9yZSBhdXRob3IgZm9yIENoaVl1YW4gSHVhbmcuCj4g LS0tCj4gIGRyaXZlcnMvbGVkcy9mbGFzaC9LY29uZmlnICAgICAgICAgICAgIHwgIDEzICsKPiAg ZHJpdmVycy9sZWRzL2ZsYXNoL01ha2VmaWxlICAgICAgICAgICAgfCAgIDEgKwo+ICBkcml2ZXJz L2xlZHMvZmxhc2gvbGVkcy1tdDYzNzAtZmxhc2guYyB8IDU5NiArKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysKPiAgMyBmaWxlcyBjaGFuZ2VkLCA2MTAgaW5zZXJ0aW9ucygrKQo+ICBj cmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9sZWRzL2ZsYXNoL2xlZHMtbXQ2MzcwLWZsYXNoLmMK Ckkgc2VlIHRoYXQgeW91IGd1eXMgaGF2ZSBiZWVuIHN1cGVyIGhlbHBmdWwgcmV2aWV3aW5nIHRo aXMgaW4gdGhlIHBhc3QuCgpIYXZlIHlvdXIgcXVlcmllcyBub3cgYmVlbiBhZGRyZXNzZWQ/CiAK PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9sZWRzL2ZsYXNoL0tjb25maWcgYi9kcml2ZXJzL2xlZHMv Zmxhc2gvS2NvbmZpZwo+IGluZGV4IGQzZWI2ODkuLjQ5ZDg5MjIgMTAwNjQ0Cj4gLS0tIGEvZHJp dmVycy9sZWRzL2ZsYXNoL0tjb25maWcKPiArKysgYi9kcml2ZXJzL2xlZHMvZmxhc2gvS2NvbmZp Zwo+IEBAIC02MSw2ICs2MSwxOSBAQCBjb25maWcgTEVEU19NVDYzNjAKPiAgCSAgSW5kZXBlbmRl bnQgY3VycmVudCBzb3VyY2VzIHN1cHBseSBmb3IgZWFjaCBmbGFzaCBMRUQgc3VwcG9ydCB0b3Jj aAo+ICAJICBhbmQgc3Ryb2JlIG1vZGUuCj4gIAo+ICtjb25maWcgTEVEU19NVDYzNzBfRkxBU0gK PiArCXRyaXN0YXRlICJGbGFzaCBMRUQgU3VwcG9ydCBmb3IgTWVkaWFUZWsgTVQ2MzcwIFBNSUMi Cj4gKwlkZXBlbmRzIG9uIExFRFNfQ0xBU1MKPiArCWRlcGVuZHMgb24gVjRMMl9GTEFTSF9MRURf Q0xBU1MgfHwgIVY0TDJfRkxBU0hfTEVEX0NMQVNTCj4gKwlkZXBlbmRzIG9uIE1GRF9NVDYzNzAK PiArCWhlbHAKPiArCSAgU3VwcG9ydCAyIGNoYW5uZWxzIGFuZCB0b3JjaC9zdHJvYmUgbW9kZS4K PiArCSAgU2F5IFkgaGVyZSB0byBlbmFibGUgc3VwcG9ydCBmb3IKPiArCSAgTVQ2MzcwX0ZMQVNI X0xFRCBkZXZpY2UuCj4gKwo+ICsJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBh IG1vZHVsZS4gSWYgc28sIHRoZSBtb2R1bGUKPiArCSAgd2lsbCBiZSBjYWxsZWQgImxlZHMtbXQ2 MzcwLWZsYXNoIi4KPiArCj4gIGNvbmZpZyBMRURTX1JUNDUwNQo+ICAJdHJpc3RhdGUgIkxFRCBz dXBwb3J0IGZvciBSVDQ1MDUgZmxhc2hsaWdodCBjb250cm9sbGVyIgo+ICAJZGVwZW5kcyBvbiBJ MkMgJiYgT0YKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9sZWRzL2ZsYXNoL01ha2VmaWxlIGIvZHJp dmVycy9sZWRzL2ZsYXNoL01ha2VmaWxlCj4gaW5kZXggMGFjYmRkYy4uNDY2NWU4ZSAxMDA2NDQK PiAtLS0gYS9kcml2ZXJzL2xlZHMvZmxhc2gvTWFrZWZpbGUKPiArKysgYi9kcml2ZXJzL2xlZHMv Zmxhc2gvTWFrZWZpbGUKPiBAQCAtMSw2ICsxLDcgQEAKPiAgIyBTUERYLUxpY2Vuc2UtSWRlbnRp ZmllcjogR1BMLTIuMAo+ICAKPiAgb2JqLSQoQ09ORklHX0xFRFNfTVQ2MzYwKQkrPSBsZWRzLW10 NjM2MC5vCj4gK29iai0kKENPTkZJR19MRURTX01UNjM3MF9GTEFTSCkJKz0gbGVkcy1tdDYzNzAt Zmxhc2gubwo+ICBvYmotJChDT05GSUdfTEVEU19BQVQxMjkwKQkrPSBsZWRzLWFhdDEyOTAubwo+ ICBvYmotJChDT05GSUdfTEVEU19BUzM2NDVBKQkrPSBsZWRzLWFzMzY0NWEubwo+ICBvYmotJChD T05GSUdfTEVEU19LVEQyNjkyKQkrPSBsZWRzLWt0ZDI2OTIubwo+IGRpZmYgLS1naXQgYS9kcml2 ZXJzL2xlZHMvZmxhc2gvbGVkcy1tdDYzNzAtZmxhc2guYyBiL2RyaXZlcnMvbGVkcy9mbGFzaC9s ZWRzLW10NjM3MC1mbGFzaC5jCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAw MC4uZTVjNGM5NAo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL2xlZHMvZmxhc2gvbGVk cy1tdDYzNzAtZmxhc2guYwo+IEBAIC0wLDAgKzEsNTk2IEBACj4gKy8vIFNQRFgtTGljZW5zZS1J ZGVudGlmaWVyOiBHUEwtMi4wLW9ubHkKPiArLyoKPiArICogQ29weXJpZ2h0IChDKSAyMDIyIFJp Y2h0ZWsgVGVjaG5vbG9neSBDb3JwLgo+ICsgKgo+ICsgKiBBdXRob3JzOgo+ICsgKiAgIEFsaWNl IENoZW4gPGFsaWNlX2NoZW5AcmljaHRlay5jb20+Cj4gKyAqICAgQ2hpWXVhbiBIdWFuZyA8Y3lf aHVhbmdAcmljaHRlay5jb20+Cj4gKyAqLwo+ICsKPiArI2luY2x1ZGUgPGxpbnV4L2JpdG9wcy5o Pgo+ICsjaW5jbHVkZSA8bGludXgvZGVsYXkuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2luaXQuaD4K PiArI2luY2x1ZGUgPGxpbnV4L2ludGVycnVwdC5oPgo+ICsjaW5jbHVkZSA8bGludXgva2VybmVs Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9sZWQtY2xhc3MtZmxhc2guaD4KPiArI2luY2x1ZGUgPGxp bnV4L21vZHVsZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvbXV0ZXguaD4KPiArI2luY2x1ZGUgPGxp bnV4L3BsYXRmb3JtX2RldmljZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvcHJvcGVydHkuaD4KPiAr I2luY2x1ZGUgPGxpbnV4L3JlZ21hcC5oPgo+ICsKPiArI2luY2x1ZGUgPG1lZGlhL3Y0bDItZmxh c2gtbGVkLWNsYXNzLmg+Cj4gKwo+ICtlbnVtIHsKPiArCU1UNjM3MF9MRURfRkxBU0gxID0gMCwK PiArCU1UNjM3MF9MRURfRkxBU0gyLAo+ICsJTVQ2MzcwX01BWF9MRURTCj4gK307Cj4gKwo+ICsv KiBWaXJ0dWFsIGRlZmluaXRpb24gZm9yIG11bHRpY29sb3IgKi8KPiArCj4gKyNkZWZpbmUgTVQ2 MzcwX1JFR19GTEVERU4JCTB4MTdFCj4gKyNkZWZpbmUgTVQ2MzcwX1JFR19TVFJCVE8JCTB4MTcz Cj4gKyNkZWZpbmUgTVQ2MzcwX1JFR19DSEdTVEFUMgkJMHgxRDEKPiArI2RlZmluZSBNVDYzNzBf UkVHX0ZMRURTVEFUMQkJMHgxRDkKPiArI2RlZmluZSBNVDYzNzBfUkVHX0ZMRURJU1RSQihfaWQp CSgweDE3NCArIDQgKiAoX2lkKSkKPiArI2RlZmluZSBNVDYzNzBfUkVHX0ZMRURJVE9SKF9pZCkJ KDB4MTc1ICsgNCAqIChfaWQpKQo+ICsjZGVmaW5lIE1UNjM3MF9JVE9SQ0hfTUFTSwkJR0VOTUFT Syg0LCAwKQo+ICsjZGVmaW5lIE1UNjM3MF9JU1RST0JFX01BU0sJCUdFTk1BU0soNiwgMCkKPiAr I2RlZmluZSBNVDYzNzBfU1RSQlRPX01BU0sJCUdFTk1BU0soNiwgMCkKPiArI2RlZmluZSBNVDYz NzBfVE9SQ0hFTl9NQVNLCQlCSVQoMykKPiArI2RlZmluZSBNVDYzNzBfU1RST0JFTl9NQVNLCQlC SVQoMikKPiArI2RlZmluZSBNVDYzNzBfRkxDU0VOX01BU0soX2lkKQkJQklUKE1UNjM3MF9MRURf RkxBU0gyIC0gKF9pZCkpCj4gKyNkZWZpbmUgTVQ2MzcwX0ZMQ1NFTl9NQVNLX0FMTAkJR0VOTUFT SygxLCAwKQo+ICsjZGVmaW5lIE1UNjM3MF9GTEVEQ0hHVklOT1ZQX01BU0sJQklUKDMpCj4gKyNk ZWZpbmUgTVQ2MzcwX0ZMRUQxU1RSQlRPX01BU0sJCUJJVCgxMSkKPiArI2RlZmluZSBNVDYzNzBf RkxFRDJTVFJCVE9fTUFTSwkJQklUKDEwKQo+ICsjZGVmaW5lIE1UNjM3MF9GTEVEMVNUUkJfTUFT SwkJQklUKDkpCj4gKyNkZWZpbmUgTVQ2MzcwX0ZMRUQyU1RSQl9NQVNLCQlCSVQoOCkKPiArI2Rl ZmluZSBNVDYzNzBfRkxFRDFTSE9SVF9NQVNLCQlCSVQoNykKPiArI2RlZmluZSBNVDYzNzBfRkxF RDJTSE9SVF9NQVNLCQlCSVQoNikKPiArI2RlZmluZSBNVDYzNzBfRkxFRExWRl9NQVNLCQlCSVQo MykKPiArCj4gKyNkZWZpbmUgTVQ2MzcwX0xFRF9KT0lOVAkJMgo+ICsjZGVmaW5lIE1UNjM3MF9S QU5HRV9GTEVEX1JFRwkJNAo+ICsjZGVmaW5lIE1UNjM3MF9JVE9SQ0hfTUlOX3VBCQkyNTAwMAo+ ICsjZGVmaW5lIE1UNjM3MF9JVE9SQ0hfU1RFUF91QQkJMTI1MDAKPiArI2RlZmluZSBNVDYzNzBf SVRPUkNIX01BWF91QQkJNDAwMDAwCj4gKyNkZWZpbmUgTVQ2MzcwX0lUT1JDSF9ET1VCTEVfTUFY X3VBCTgwMDAwMAo+ICsjZGVmaW5lIE1UNjM3MF9JU1RSQl9NSU5fdUEJCTUwMDAwCj4gKyNkZWZp bmUgTVQ2MzcwX0lTVFJCX1NURVBfdUEJCTEyNTAwCj4gKyNkZWZpbmUgTVQ2MzcwX0lTVFJCX01B WF91QQkJMTUwMDAwMAo+ICsjZGVmaW5lIE1UNjM3MF9JU1RSQl9ET1VCTEVfTUFYX3VBCTMwMDAw MDAKPiArI2RlZmluZSBNVDYzNzBfU1RSQlRPX01JTl9VUwkJNjQwMDAKPiArI2RlZmluZSBNVDYz NzBfU1RSQlRPX1NURVBfVVMJCTMyMDAwCj4gKyNkZWZpbmUgTVQ2MzcwX1NUUkJUT19NQVhfVVMJ CTI0MzIwMDAKPiArCj4gKyNkZWZpbmUgdG9fbXQ2MzcwX2xlZChwdHIsIG1lbWJlcikgY29udGFp bmVyX29mKHB0ciwgc3RydWN0IG10NjM3MF9sZWQsIG1lbWJlcikKPiArCj4gK3N0cnVjdCBtdDYz NzBfbGVkIHsKPiArCXN0cnVjdCBsZWRfY2xhc3NkZXZfZmxhc2ggZmxhc2g7Cj4gKwlzdHJ1Y3Qg djRsMl9mbGFzaCAqdjRsMl9mbGFzaDsKPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdjsKPiAr CXU4IGxlZF9ubzsKPiArfTsKPiArCj4gK3N0cnVjdCBtdDYzNzBfcHJpdiB7Cj4gKwlzdHJ1Y3Qg cmVnbWFwICpyZWdtYXA7Cj4gKwlzdHJ1Y3QgbXV0ZXggbG9jazsKPiArCXVuc2lnbmVkIGludCBm bGVkX3N0cm9iZV91c2VkOwo+ICsJdW5zaWduZWQgaW50IGZsZWRfdG9yY2hfdXNlZDsKPiArCXVu c2lnbmVkIGludCBsZWRzX2FjdGl2ZTsKPiArCXVuc2lnbmVkIGludCBsZWRzX2NvdW50Owo+ICsJ c3RydWN0IG10NjM3MF9sZWQgbGVkc1tdOwo+ICt9Owo+ICsKPiArc3RhdGljIGludCBtdDYzNzBf dG9yY2hfYnJpZ2h0bmVzc19zZXQoc3RydWN0IGxlZF9jbGFzc2RldiAqbGNkZXYsCj4gKwkJCQkg ICAgICAgZW51bSBsZWRfYnJpZ2h0bmVzcyBsZXZlbCkKPiArewo+ICsJc3RydWN0IG10NjM3MF9s ZWQgKmxlZCA9IHRvX210NjM3MF9sZWQobGNkZXYsIGZsYXNoLmxlZF9jZGV2KTsKPiArCXN0cnVj dCBtdDYzNzBfcHJpdiAqcHJpdiA9IGxlZC0+cHJpdjsKPiArCXUzMiBsZWRfZW5hYmxlX21hc2sg PSBsZWQtPmxlZF9ubyA9PSBNVDYzNzBfTEVEX0pPSU5UID8KPiArCQkJICAgICAgTVQ2MzcwX0ZM Q1NFTl9NQVNLX0FMTCA6Cj4gKwkJCSAgICAgIE1UNjM3MF9GTENTRU5fTUFTSyhsZWQtPmxlZF9u byk7Cj4gKwl1MzIgZW5hYmxlX21hc2sgPSBNVDYzNzBfVE9SQ0hFTl9NQVNLIHwgbGVkX2VuYWJs ZV9tYXNrOwo+ICsJdTMyIHZhbCA9IGxldmVsID8gbGVkX2VuYWJsZV9tYXNrIDogMDsKPiArCXUz MiBjdXJyOwo+ICsJaW50IHJldCwgaTsKPiArCj4gKwltdXRleF9sb2NrKCZwcml2LT5sb2NrKTsK PiArCj4gKwkvKgo+ICsJICogVGhlcmUgaXMgb25seSBvbmUgc2V0IG9mIGZsYXNoIGNvbnRyb2wg bG9naWMsIGFuZCB0aGlzCj4gKwkgKiBmbGFnIGlzIHVzZWQgdG8gY2hlY2sgaWYgJ3N0cm9iZScg aXMgY3VycmVudGx5IGJlaW5nIHVzZWQuCj4gKwkgKi8KPiArCWlmIChwcml2LT5mbGVkX3N0cm9i ZV91c2VkKSB7Cj4gKwkJZGV2X3dhcm4obGNkZXYtPmRldiwgIlBsZWFzZSBkaXNhYmxlIHN0cm9i ZSBmaXJzdCBbJWRdXG4iLAo+ICsJCQkgcHJpdi0+ZmxlZF9zdHJvYmVfdXNlZCk7Cj4gKwkJcmV0 ID0gLUVCVVNZOwo+ICsJCWdvdG8gdW5sb2NrOwo+ICsJfQo+ICsKPiArCWlmIChsZXZlbCkKPiAr CQljdXJyID0gcHJpdi0+ZmxlZF90b3JjaF91c2VkIHwgQklUKGxlZC0+bGVkX25vKTsKPiArCWVs c2UKPiArCQljdXJyID0gcHJpdi0+ZmxlZF90b3JjaF91c2VkICYgfkJJVChsZWQtPmxlZF9ubyk7 Cj4gKwo+ICsJaWYgKGN1cnIpCj4gKwkJdmFsIHw9IE1UNjM3MF9UT1JDSEVOX01BU0s7Cj4gKwo+ ICsJaWYgKGxldmVsKSB7Cj4gKwkJbGV2ZWwgLT0gMTsKPiArCQlpZiAobGVkLT5sZWRfbm8gPT0g TVQ2MzcwX0xFRF9KT0lOVCkgewo+ICsJCQl1MzIgZmxldmVsW01UNjM3MF9NQVhfTEVEU107Cj4g Kwo+ICsJCQlmbGV2ZWxbMF0gPSBsZXZlbCAvIDI7Cj4gKwkJCWZsZXZlbFsxXSA9IGxldmVsIC0g ZmxldmVsWzBdOwo+ICsJCQlmb3IgKGkgPSAwOyBpIDwgTVQ2MzcwX01BWF9MRURTOyBpKyspIHsK PiArCQkJCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhwcml2LT5yZWdtYXAsCj4gKwkJCQkJCU1U NjM3MF9SRUdfRkxFRElUT1IoaSksCj4gKwkJCQkJCU1UNjM3MF9JVE9SQ0hfTUFTSywgZmxldmVs W2ldKTsKPiArCQkJCWlmIChyZXQpCj4gKwkJCQkJZ290byB1bmxvY2s7Cj4gKwkJCX0KPiArCQl9 IGVsc2Ugewo+ICsJCQlyZXQgPSByZWdtYXBfdXBkYXRlX2JpdHMocHJpdi0+cmVnbWFwLAo+ICsJ CQkJCU1UNjM3MF9SRUdfRkxFRElUT1IobGVkLT5sZWRfbm8pLAo+ICsJCQkJCU1UNjM3MF9JVE9S Q0hfTUFTSywgbGV2ZWwpOwo+ICsJCQlpZiAocmV0KQo+ICsJCQkJZ290byB1bmxvY2s7Cj4gKwkJ fQo+ICsJfQo+ICsKPiArCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhwcml2LT5yZWdtYXAsIE1U NjM3MF9SRUdfRkxFREVOLAo+ICsJCQkJIGVuYWJsZV9tYXNrLCB2YWwpOwo+ICsJaWYgKHJldCkK PiArCQlnb3RvIHVubG9jazsKPiArCj4gKwlwcml2LT5mbGVkX3RvcmNoX3VzZWQgPSBjdXJyOwo+ ICsKPiArdW5sb2NrOgo+ICsJbXV0ZXhfdW5sb2NrKCZwcml2LT5sb2NrKTsKPiArCXJldHVybiBy ZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgbXQ2MzcwX2ZsYXNoX2JyaWdodG5lc3Nfc2V0KHN0 cnVjdCBsZWRfY2xhc3NkZXZfZmxhc2ggKmZsX2NkZXYsCj4gKwkJCQkgICAgICAgdTMyIGJyaWdo dG5lc3MpCj4gK3sKPiArCS8qCj4gKwkgKiBCZWNhdXNlIG9mIHRoZSBjdXJyZW50IHNwaWtlcyB3 aGVuIHR1cm5pbmcgb24gdGhlIGZsYXNoLAo+ICsJICogdGhlIGJyaWdodG5lc3Mgc2hvdWxkIGJl IGtlcHQgYnkgdGhlIExFRCBmcmFtZXdvcmsuIFRoaXMKPiArCSAqIGVtcHR5IGZ1bmN0aW9uIGlz IHVzZWQgdG8gcHJldmVudCBjaGVja2luZyBmYWlsdXJlIHdoZW4KPiArCSAqIGxlZF9jbGFzc2Rl dl9mbGFzaCByZWdpc3RlcnMgb3BzLgo+ICsJICovCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiAr c3RhdGljIGludCBfbXQ2MzcwX2ZsYXNoX2JyaWdodG5lc3Nfc2V0KHN0cnVjdCBsZWRfY2xhc3Nk ZXZfZmxhc2ggKmZsX2NkZXYsCj4gKwkJCQkJdTMyIGJyaWdodG5lc3MpCj4gK3sKPiArCXN0cnVj dCBtdDYzNzBfbGVkICpsZWQgPSB0b19tdDYzNzBfbGVkKGZsX2NkZXYsIGZsYXNoKTsKPiArCXN0 cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9IGxlZC0+cHJpdjsKPiArCXN0cnVjdCBsZWRfZmxhc2hf c2V0dGluZyAqc2V0dGluZyA9ICZmbF9jZGV2LT5icmlnaHRuZXNzOwo+ICsJdTMyIHZhbCA9IChi cmlnaHRuZXNzIC0gc2V0dGluZy0+bWluKSAvIHNldHRpbmctPnN0ZXA7Cj4gKwlpbnQgcmV0LCBp Owo+ICsKPiArCWlmIChsZWQtPmxlZF9ubyA9PSBNVDYzNzBfTEVEX0pPSU5UKSB7Cj4gKwkJdTMy IGZsZXZlbFtNVDYzNzBfTUFYX0xFRFNdOwo+ICsKPiArCQlmbGV2ZWxbMF0gPSB2YWwgLyAyOwo+ ICsJCWZsZXZlbFsxXSA9IHZhbCAtIGZsZXZlbFswXTsKPiArCQlmb3IgKGkgPSAwOyBpIDwgTVQ2 MzcwX01BWF9MRURTOyBpKyspIHsKPiArCQkJcmV0ID0gcmVnbWFwX3VwZGF0ZV9iaXRzKHByaXYt PnJlZ21hcCwKPiArCQkJCQkJIE1UNjM3MF9SRUdfRkxFRElTVFJCKGkpLAo+ICsJCQkJCQkgTVQ2 MzcwX0lTVFJPQkVfTUFTSywgZmxldmVsW2ldKTsKPiArCQkJaWYgKHJldCkKPiArCQkJCWJyZWFr Owo+ICsJCX0KPiArCX0gZWxzZQo+ICsJCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhwcml2LT5y ZWdtYXAsCj4gKwkJCQkJIE1UNjM3MF9SRUdfRkxFRElTVFJCKGxlZC0+bGVkX25vKSwKPiArCQkJ CQkgTVQ2MzcwX0lTVFJPQkVfTUFTSywgdmFsKTsKPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4g Kwo+ICtzdGF0aWMgaW50IG10NjM3MF9zdHJvYmVfc2V0KHN0cnVjdCBsZWRfY2xhc3NkZXZfZmxh c2ggKmZsX2NkZXYsIGJvb2wgc3RhdGUpCj4gK3sKPiArCXN0cnVjdCBtdDYzNzBfbGVkICpsZWQg PSB0b19tdDYzNzBfbGVkKGZsX2NkZXYsIGZsYXNoKTsKPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAq cHJpdiA9IGxlZC0+cHJpdjsKPiArCXN0cnVjdCBsZWRfY2xhc3NkZXYgKmxjZGV2ID0gJmZsX2Nk ZXYtPmxlZF9jZGV2Owo+ICsJc3RydWN0IGxlZF9mbGFzaF9zZXR0aW5nICpzID0gJmZsX2NkZXYt PmJyaWdodG5lc3M7Cj4gKwl1MzIgbGVkX2VuYWJsZV9tYXNrID0gbGVkLT5sZWRfbm8gPT0gTVQ2 MzcwX0xFRF9KT0lOVCA/Cj4gKwkJCSAgICAgIE1UNjM3MF9GTENTRU5fTUFTS19BTEwgOgo+ICsJ CQkgICAgICBNVDYzNzBfRkxDU0VOX01BU0sobGVkLT5sZWRfbm8pOwo+ICsJdTMyIGVuYWJsZV9t YXNrID0gTVQ2MzcwX1NUUk9CRU5fTUFTSyB8IGxlZF9lbmFibGVfbWFzazsKPiArCXUzMiB2YWwg PSBzdGF0ZSA/IGxlZF9lbmFibGVfbWFzayA6IDA7Cj4gKwl1MzIgY3VycjsKPiArCWludCByZXQ7 Cj4gKwo+ICsJbXV0ZXhfbG9jaygmcHJpdi0+bG9jayk7Cj4gKwo+ICsJLyoKPiArCSAqIFRoZXJl IGlzIG9ubHkgb25lIHNldCBvZiBmbGFzaCBjb250cm9sIGxvZ2ljLCBhbmQgdGhpcwo+ICsJICog ZmxhZyBpcyB1c2VkIHRvIGNoZWNrIGlmICd0b3JjaCcgaXMgY3VycmVudGx5IGJlaW5nIHVzZWQu Cj4gKwkgKi8KPiArCWlmIChwcml2LT5mbGVkX3RvcmNoX3VzZWQpIHsKPiArCQlkZXZfd2Fybihs Y2Rldi0+ZGV2LCAiUGxlYXNlIGRpc2FibGUgdG9yY2ggZmlyc3QgWzB4JXhdXG4iLAo+ICsJCQkJ ICAgICAgcHJpdi0+ZmxlZF90b3JjaF91c2VkKTsKPiArCQlyZXQgPSAtRUJVU1k7Cj4gKwkJZ290 byB1bmxvY2s7Cj4gKwl9Cj4gKwo+ICsJaWYgKHN0YXRlKQo+ICsJCWN1cnIgPSBwcml2LT5mbGVk X3N0cm9iZV91c2VkIHwgQklUKGxlZC0+bGVkX25vKTsKPiArCWVsc2UKPiArCQljdXJyID0gcHJp di0+ZmxlZF9zdHJvYmVfdXNlZCAmIH5CSVQobGVkLT5sZWRfbm8pOwo+ICsKPiArCWlmIChjdXJy KQo+ICsJCXZhbCB8PSBNVDYzNzBfU1RST0JFTl9NQVNLOwo+ICsKPiArCXJldCA9IHJlZ21hcF91 cGRhdGVfYml0cyhwcml2LT5yZWdtYXAsIE1UNjM3MF9SRUdfRkxFREVOLCBlbmFibGVfbWFzaywK PiArCQkJCSB2YWwpOwo+ICsJaWYgKHJldCkgewo+ICsJCWRldl9lcnIobGNkZXYtPmRldiwgIlsl ZF0gY29udHJvbCBjdXJyZW50IHNvdXJjZSAlZCBmYWlsXG4iLAo+ICsJCQkJICAgICBsZWQtPmxl ZF9ubywgc3RhdGUpOwo+ICsJCWdvdG8gdW5sb2NrOwo+ICsJfQo+ICsKPiArCS8qCj4gKwkgKiBJ ZiB0aGUgZmxhc2ggbmVlZHMgdG8gdHVybiBvbiwgY29uZmlndXJlIHRoZSBmbGFzaCBjdXJyZW50 IHRvCj4gKwkgKiByYW1wIHVwIHRvIHRoZSBzZXR0aW5nIHZhbHVlLiBPdGhlcndpc2UsIGFsd2F5 cyByZXZlcnQgdG8gdGhlCj4gKwkgKiBtaW5pbXVtIG9uZS4KPiArCSAqLwo+ICsJcmV0ID0gX210 NjM3MF9mbGFzaF9icmlnaHRuZXNzX3NldChmbF9jZGV2LCBzdGF0ZSA/IHMtPnZhbCA6IHMtPm1p bik7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZGV2X2VycihsY2Rldi0+ZGV2LCAiWyVkXSBGYWlsZWQg dG8gc2V0IGJyaWdodG5lc3NcbiIsIGxlZC0+bGVkX25vKTsKPiArCQlnb3RvIHVubG9jazsKPiAr CX0KPiArCj4gKwkvKgo+ICsJICogRm9yIHRoZSBmbGFzaCB0byB0dXJuIG9uL29mZiwgd2UgbXVz dCB3YWl0IGZvciBIVyByYW1waW5nCj4gKwkgKiB1cC9kb3duIHRpbWUgNW1zLzUwMHVzIHRvIHBy ZXZlbnQgdGhlIHVuZXhwZWN0ZWQgcHJvYmxlbS4KPiArCSAqLwo+ICsJaWYgKCFwcml2LT5mbGVk X3N0cm9iZV91c2VkICYmIGN1cnIpCj4gKwkJdXNsZWVwX3JhbmdlKDUwMDAsIDYwMDApOwo+ICsJ ZWxzZSBpZiAocHJpdi0+ZmxlZF9zdHJvYmVfdXNlZCAmJiAhY3VycikKPiArCQl1c2xlZXBfcmFu Z2UoNTAwLCA2MDApOwo+ICsKPiArCXByaXYtPmZsZWRfc3Ryb2JlX3VzZWQgPSBjdXJyOwo+ICsK PiArdW5sb2NrOgo+ICsJbXV0ZXhfdW5sb2NrKCZwcml2LT5sb2NrKTsKPiArCXJldHVybiByZXQ7 Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgbXQ2MzcwX3N0cm9iZV9nZXQoc3RydWN0IGxlZF9jbGFz c2Rldl9mbGFzaCAqZmxfY2RldiwgYm9vbCAqc3RhdGUpCj4gK3sKPiArCXN0cnVjdCBtdDYzNzBf bGVkICpsZWQgPSB0b19tdDYzNzBfbGVkKGZsX2NkZXYsIGZsYXNoKTsKPiArCXN0cnVjdCBtdDYz NzBfcHJpdiAqcHJpdiA9IGxlZC0+cHJpdjsKPiArCj4gKwltdXRleF9sb2NrKCZwcml2LT5sb2Nr KTsKPiArCSpzdGF0ZSA9ICEhKHByaXYtPmZsZWRfc3Ryb2JlX3VzZWQgJiBCSVQobGVkLT5sZWRf bm8pKTsKPiArCW11dGV4X3VubG9jaygmcHJpdi0+bG9jayk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4g K30KPiArCj4gK3N0YXRpYyBpbnQgbXQ2MzcwX3RpbWVvdXRfc2V0KHN0cnVjdCBsZWRfY2xhc3Nk ZXZfZmxhc2ggKmZsX2NkZXYsIHUzMiB0aW1lb3V0KQo+ICt7Cj4gKwlzdHJ1Y3QgbXQ2MzcwX2xl ZCAqbGVkID0gdG9fbXQ2MzcwX2xlZChmbF9jZGV2LCBmbGFzaCk7Cj4gKwlzdHJ1Y3QgbXQ2Mzcw X3ByaXYgKnByaXYgPSBsZWQtPnByaXY7Cj4gKwlzdHJ1Y3QgbGVkX2ZsYXNoX3NldHRpbmcgKnMg PSAmZmxfY2Rldi0+dGltZW91dDsKPiArCXUzMiB2YWwgPSAodGltZW91dCAtIHMtPm1pbikgLyBz LT5zdGVwOwo+ICsKPiArCXJldHVybiByZWdtYXBfdXBkYXRlX2JpdHMocHJpdi0+cmVnbWFwLCBN VDYzNzBfUkVHX1NUUkJUTywKPiArCQkJCSAgTVQ2MzcwX1NUUkJUT19NQVNLLCB2YWwpOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW50IG10NjM3MF9mYXVsdF9nZXQoc3RydWN0IGxlZF9jbGFzc2Rldl9m bGFzaCAqZmxfY2RldiwgdTMyICpmYXVsdCkKPiArewo+ICsJc3RydWN0IG10NjM3MF9sZWQgKmxl ZCA9IHRvX210NjM3MF9sZWQoZmxfY2RldiwgZmxhc2gpOwo+ICsJc3RydWN0IG10NjM3MF9wcml2 ICpwcml2ID0gbGVkLT5wcml2Owo+ICsJdTE2IGZsZWRfc3RhdDsKPiArCXVuc2lnbmVkIGludCBj aGdfc3RhdCwgc3Ryb2JlX3RpbWVvdXRfbWFzaywgZmxlZF9zaG9ydF9tYXNrOwo+ICsJdTMyIHJm YXVsdCA9IDA7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXJldCA9IHJlZ21hcF9yZWFkKHByaXYtPnJl Z21hcCwgTVQ2MzcwX1JFR19DSEdTVEFUMiwgJmNoZ19zdGF0KTsKPiArCWlmIChyZXQpCj4gKwkJ cmV0dXJuIHJldDsKPiArCj4gKwlyZXQgPSByZWdtYXBfcmF3X3JlYWQocHJpdi0+cmVnbWFwLCBN VDYzNzBfUkVHX0ZMRURTVEFUMSwgJmZsZWRfc3RhdCwKPiArCQkJICAgICAgc2l6ZW9mKGZsZWRf c3RhdCkpOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1cm4gcmV0Owo+ICsKPiArCXN3aXRjaCAobGVk LT5sZWRfbm8pIHsKPiArCWNhc2UgTVQ2MzcwX0xFRF9GTEFTSDE6Cj4gKwkJc3Ryb2JlX3RpbWVv dXRfbWFzayA9IE1UNjM3MF9GTEVEMVNUUkJUT19NQVNLOwo+ICsJCWZsZWRfc2hvcnRfbWFzayA9 IE1UNjM3MF9GTEVEMVNIT1JUX01BU0s7Cj4gKwkJYnJlYWs7Cj4gKwo+ICsJY2FzZSBNVDYzNzBf TEVEX0ZMQVNIMjoKPiArCQlzdHJvYmVfdGltZW91dF9tYXNrID0gTVQ2MzcwX0ZMRUQyU1RSQlRP X01BU0s7Cj4gKwkJZmxlZF9zaG9ydF9tYXNrID0gTVQ2MzcwX0ZMRUQyU0hPUlRfTUFTSzsKPiAr CQlicmVhazsKPiArCj4gKwljYXNlIE1UNjM3MF9MRURfSk9JTlQ6Cj4gKwkJc3Ryb2JlX3RpbWVv dXRfbWFzayA9IE1UNjM3MF9GTEVEMVNUUkJUT19NQVNLIHwKPiArCQkJCSAgICAgIE1UNjM3MF9G TEVEMlNUUkJUT19NQVNLOwo+ICsJCWZsZWRfc2hvcnRfbWFzayA9IE1UNjM3MF9GTEVEMVNIT1JU X01BU0sgfAo+ICsJCQkJICBNVDYzNzBfRkxFRDJTSE9SVF9NQVNLOwo+ICsJCWJyZWFrOwo+ICsJ ZGVmYXVsdDoKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlpZiAoY2hnX3N0YXQg JiBNVDYzNzBfRkxFRENIR1ZJTk9WUF9NQVNLKQo+ICsJCXJmYXVsdCB8PSBMRURfRkFVTFRfSU5Q VVRfVk9MVEFHRTsKPiArCj4gKwlpZiAoZmxlZF9zdGF0ICYgc3Ryb2JlX3RpbWVvdXRfbWFzaykK PiArCQlyZmF1bHQgfD0gTEVEX0ZBVUxUX1RJTUVPVVQ7Cj4gKwo+ICsJaWYgKGZsZWRfc3RhdCAm IGZsZWRfc2hvcnRfbWFzaykKPiArCQlyZmF1bHQgfD0gTEVEX0ZBVUxUX1NIT1JUX0NJUkNVSVQ7 Cj4gKwo+ICsJaWYgKGZsZWRfc3RhdCAmIE1UNjM3MF9GTEVETFZGX01BU0spCj4gKwkJcmZhdWx0 IHw9IExFRF9GQVVMVF9VTkRFUl9WT0xUQUdFOwo+ICsKPiArCSpmYXVsdCA9IHJmYXVsdDsKPiAr CXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgbGVkX2ZsYXNoX29w cyBtdDYzNzBfZmxhc2hfb3BzID0gewo+ICsJLmZsYXNoX2JyaWdodG5lc3Nfc2V0ID0gbXQ2Mzcw X2ZsYXNoX2JyaWdodG5lc3Nfc2V0LAo+ICsJLnN0cm9iZV9zZXQgPSBtdDYzNzBfc3Ryb2JlX3Nl dCwKPiArCS5zdHJvYmVfZ2V0ID0gbXQ2MzcwX3N0cm9iZV9nZXQsCj4gKwkudGltZW91dF9zZXQg PSBtdDYzNzBfdGltZW91dF9zZXQsCj4gKwkuZmF1bHRfZ2V0ID0gbXQ2MzcwX2ZhdWx0X2dldCwK PiArfTsKPiArCj4gKyNpZiBJU19FTkFCTEVEKENPTkZJR19WNEwyX0ZMQVNIX0xFRF9DTEFTUykK PiArc3RhdGljIGludCBtdDYzNzBfZmxhc2hfZXh0ZXJuYWxfc3Ryb2JlX3NldChzdHJ1Y3QgdjRs Ml9mbGFzaCAqdjRsMl9mbGFzaCwKPiArCQkJCQkgICAgYm9vbCBlbmFibGUpCj4gK3sKPiArCXN0 cnVjdCBsZWRfY2xhc3NkZXZfZmxhc2ggKmZsYXNoID0gdjRsMl9mbGFzaC0+ZmxlZF9jZGV2Owo+ ICsJc3RydWN0IG10NjM3MF9sZWQgKmxlZCA9IHRvX210NjM3MF9sZWQoZmxhc2gsIGZsYXNoKTsK PiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9IGxlZC0+cHJpdjsKPiArCXUzMiBtYXNrID0g bGVkLT5sZWRfbm8gPT0gTVQ2MzcwX0xFRF9KT0lOVCA/IE1UNjM3MF9GTENTRU5fTUFTS19BTEwg Ogo+ICsJCSAgIE1UNjM3MF9GTENTRU5fTUFTSyhsZWQtPmxlZF9ubyk7Cj4gKwl1MzIgdmFsID0g ZW5hYmxlID8gbWFzayA6IDA7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCW11dGV4X2xvY2soJnByaXYt PmxvY2spOwo+ICsKPiArCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhwcml2LT5yZWdtYXAsIE1U NjM3MF9SRUdfRkxFREVOLCBtYXNrLCB2YWwpOwo+ICsJaWYgKHJldCkKPiArCQlnb3RvIHVubG9j azsKPiArCj4gKwlpZiAoZW5hYmxlKQo+ICsJCXByaXYtPmZsZWRfc3Ryb2JlX3VzZWQgfD0gQklU KGxlZC0+bGVkX25vKTsKPiArCWVsc2UKPiArCQlwcml2LT5mbGVkX3N0cm9iZV91c2VkICY9IH5C SVQobGVkLT5sZWRfbm8pOwo+ICsKPiArdW5sb2NrOgo+ICsJbXV0ZXhfdW5sb2NrKCZwcml2LT5s b2NrKTsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgdjRs Ml9mbGFzaF9vcHMgdjRsMl9mbGFzaF9vcHMgPSB7Cj4gKwkuZXh0ZXJuYWxfc3Ryb2JlX3NldCA9 IG10NjM3MF9mbGFzaF9leHRlcm5hbF9zdHJvYmVfc2V0LAo+ICt9Owo+ICsKPiArc3RhdGljIHZv aWQgbXQ2MzcwX2luaXRfdjRsMl9mbGFzaF9jb25maWcoc3RydWN0IG10NjM3MF9sZWQgKmxlZCwK PiArCQkJCQkgIHN0cnVjdCB2NGwyX2ZsYXNoX2NvbmZpZyAqY2ZnKQo+ICt7Cj4gKwlzdHJ1Y3Qg bGVkX2NsYXNzZGV2ICpsY2RldjsKPiArCXN0cnVjdCBsZWRfZmxhc2hfc2V0dGluZyAqcyA9ICZj ZmctPmludGVuc2l0eTsKPiArCj4gKwlsY2RldiA9ICZsZWQtPmZsYXNoLmxlZF9jZGV2Owo+ICsK PiArCXMtPm1pbiA9IE1UNjM3MF9JVE9SQ0hfTUlOX3VBOwo+ICsJcy0+c3RlcCA9IE1UNjM3MF9J VE9SQ0hfU1RFUF91QTsKPiArCXMtPnZhbCA9IHMtPm1heCA9IHMtPm1pbiArIChsY2Rldi0+bWF4 X2JyaWdodG5lc3MgLSAxKSAqIHMtPnN0ZXA7Cj4gKwo+ICsJY2ZnLT5oYXNfZXh0ZXJuYWxfc3Ry b2JlID0gMTsKPiArCXN0cnNjcHkoY2ZnLT5kZXZfbmFtZSwgZGV2X25hbWUobGNkZXYtPmRldiks IHNpemVvZihjZmctPmRldl9uYW1lKSk7Cj4gKwo+ICsJY2ZnLT5mbGFzaF9mYXVsdHMgPSBMRURf RkFVTFRfU0hPUlRfQ0lSQ1VJVCB8IExFRF9GQVVMVF9USU1FT1VUIHwKPiArCQkJICAgIExFRF9G QVVMVF9JTlBVVF9WT0xUQUdFIHwgTEVEX0ZBVUxUX1VOREVSX1ZPTFRBR0U7Cj4gK30KPiArI2Vs c2UKPiArc3RhdGljIGNvbnN0IHN0cnVjdCB2NGwyX2ZsYXNoX29wcyB2NGwyX2ZsYXNoX29wczsK PiArc3RhdGljIHZvaWQgbXQ2MzcwX2luaXRfdjRsMl9mbGFzaF9jb25maWcoc3RydWN0IG10NjM3 MF9sZWQgKmxlZCwKPiArCQkJCQkgIHN0cnVjdCB2NGwyX2ZsYXNoX2NvbmZpZyAqY2ZnKQo+ICt7 Cj4gK30KPiArI2VuZGlmCj4gKwo+ICtzdGF0aWMgdm9pZCBtdDYzNzBfdjRsMl9mbGFzaF9yZWxl YXNlKHZvaWQgKnY0bDJfZmxhc2gpCj4gK3sKPiArCXY0bDJfZmxhc2hfcmVsZWFzZSh2NGwyX2Zs YXNoKTsKPiArfQo+ICsKPiArc3RhdGljIGludCBtdDYzNzBfbGVkX3JlZ2lzdGVyKHN0cnVjdCBk ZXZpY2UgKnBhcmVudCwgc3RydWN0IG10NjM3MF9sZWQgKmxlZCwKPiArCQkJCXN0cnVjdCBmd25v ZGVfaGFuZGxlICpmd25vZGUpCj4gK3sKPiArCXN0cnVjdCBsZWRfaW5pdF9kYXRhIGluaXRfZGF0 YSA9IHsgLmZ3bm9kZSA9IGZ3bm9kZSB9Owo+ICsJc3RydWN0IHY0bDJfZmxhc2hfY29uZmlnIHY0 bDJfY29uZmlnID0ge307Cj4gKwlpbnQgcmV0Owo+ICsKPiArCXJldCA9IGRldm1fbGVkX2NsYXNz ZGV2X2ZsYXNoX3JlZ2lzdGVyX2V4dChwYXJlbnQsICZsZWQtPmZsYXNoLAo+ICsJCQkJCQkgICAm aW5pdF9kYXRhKTsKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIGRldl9lcnJfcHJvYmUocGFyZW50 LCByZXQsCj4gKwkJCQkgICAgICJDb3VsZG4ndCByZWdpc3RlciBmbGFzaCAlZFxuIiwgbGVkLT5s ZWRfbm8pOwo+ICsKPiArCW10NjM3MF9pbml0X3Y0bDJfZmxhc2hfY29uZmlnKGxlZCwgJnY0bDJf Y29uZmlnKTsKPiArCWxlZC0+djRsMl9mbGFzaCA9IHY0bDJfZmxhc2hfaW5pdChwYXJlbnQsIGZ3 bm9kZSwgJmxlZC0+Zmxhc2gsCj4gKwkJCQkJICAmdjRsMl9mbGFzaF9vcHMsICZ2NGwyX2NvbmZp Zyk7Cj4gKwlpZiAoSVNfRVJSKGxlZC0+djRsMl9mbGFzaCkpCj4gKwkJcmV0dXJuIGRldl9lcnJf cHJvYmUocGFyZW50LCBQVFJfRVJSKGxlZC0+djRsMl9mbGFzaCksCj4gKwkJCQkgICAgICJGYWls ZWQgdG8gcmVnaXN0ZXIgJWQgdjRsMiBzZFxuIiwgbGVkLT5sZWRfbm8pOwo+ICsKPiArCXJldHVy biBkZXZtX2FkZF9hY3Rpb25fb3JfcmVzZXQocGFyZW50LCBtdDYzNzBfdjRsMl9mbGFzaF9yZWxl YXNlLAo+ICsJCQkJCWxlZC0+djRsMl9mbGFzaCk7Cj4gK30KPiArCj4gK3N0YXRpYyB1MzIgbXQ2 MzcwX2NsYW1wKHUzMiB2YWwsIHUzMiBtaW4sIHUzMiBtYXgsIHUzMiBzdGVwKQo+ICt7Cj4gKwl1 MzIgcmV0dmFsOwo+ICsKPiArCXJldHZhbCA9IGNsYW1wX3ZhbCh2YWwsIG1pbiwgbWF4KTsKPiAr CWlmIChzdGVwID4gMSkKPiArCQlyZXR2YWwgPSByb3VuZGRvd24ocmV0dmFsIC0gbWluLCBzdGVw KSArIG1pbjsKPiArCj4gKwlyZXR1cm4gcmV0dmFsOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IG10 NjM3MF9pbml0X2ZsYXNoX3Byb3BlcnRpZXMoc3RydWN0IGRldmljZSAqZGV2LAo+ICsJCQkJCXN0 cnVjdCBtdDYzNzBfbGVkICpsZWQsCj4gKwkJCQkJc3RydWN0IGZ3bm9kZV9oYW5kbGUgKmZ3bm9k ZSkKPiArewo+ICsJc3RydWN0IGxlZF9jbGFzc2Rldl9mbGFzaCAqZmxhc2ggPSAmbGVkLT5mbGFz aDsKPiArCXN0cnVjdCBsZWRfY2xhc3NkZXYgKmxjZGV2ID0gJmZsYXNoLT5sZWRfY2RldjsKPiAr CXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9IGxlZC0+cHJpdjsKPiArCXN0cnVjdCBsZWRfZmxh c2hfc2V0dGluZyAqczsKPiArCXUzMiBzb3VyY2VzW01UNjM3MF9NQVhfTEVEU107Cj4gKwl1MzIg bWF4X3VhLCB2YWw7Cj4gKwlpbnQgaSwgcmV0LCBudW07Cj4gKwo+ICsJbnVtID0gZndub2RlX3By b3BlcnR5X2NvdW50X3UzMihmd25vZGUsICJsZWQtc291cmNlcyIpOwo+ICsJaWYgKG51bSA8IDEp Cj4gKwkJcmV0dXJuIGRldl9lcnJfcHJvYmUoZGV2LCAtRUlOVkFMLAo+ICsJCQkJICAgICAiTm90 IHNwZWNpZmllZCBvciB3cm9uZyBudW1iZXIgb2YgbGVkLXNvdXJjZXNcbiIpOwo+ICsKPiArCXJl dCA9IGZ3bm9kZV9wcm9wZXJ0eV9yZWFkX3UzMl9hcnJheShmd25vZGUsICJsZWQtc291cmNlcyIs IHNvdXJjZXMsIG51bSk7Cj4gKwlpZiAocmV0KQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJZm9y IChpID0gMDsgaSA8IG51bTsgaSsrKSB7Cj4gKwkJaWYgKHNvdXJjZXNbaV0gPj0gTVQ2MzcwX01B WF9MRURTKQo+ICsJCQlyZXR1cm4gLUVJTlZBTDsKPiArCQlpZiAocHJpdi0+bGVkc19hY3RpdmUg JiBCSVQoc291cmNlc1tpXSkpCj4gKwkJCXJldHVybiAtRUlOVkFMOwo+ICsJCXByaXYtPmxlZHNf YWN0aXZlIHw9IEJJVChzb3VyY2VzW2ldKTsKPiArCX0KPiArCj4gKwlsZWQtPmxlZF9ubyA9IG51 bSA9PSAyID8gTVQ2MzcwX0xFRF9KT0lOVCA6IHNvdXJjZXNbMF07Cj4gKwo+ICsJbWF4X3VhID0g bnVtID09IDIgPyBNVDYzNzBfSVRPUkNIX0RPVUJMRV9NQVhfdUEgOiBNVDYzNzBfSVRPUkNIX01B WF91QTsKPiArCXZhbCA9IE1UNjM3MF9JVE9SQ0hfTUlOX3VBOwo+ICsJcmV0ID0gZndub2RlX3By b3BlcnR5X3JlYWRfdTMyKGZ3bm9kZSwgImxlZC1tYXgtbWljcm9hbXAiLCAmdmFsKTsKPiArCWlm ICghcmV0KQo+ICsJCXZhbCA9IG10NjM3MF9jbGFtcCh2YWwsIE1UNjM3MF9JVE9SQ0hfTUlOX3VB LCBtYXhfdWEsCj4gKwkJCQkgICBNVDYzNzBfSVRPUkNIX1NURVBfdUEpOwo+ICsKPiArCWxjZGV2 LT5tYXhfYnJpZ2h0bmVzcyA9ICh2YWwgLSBNVDYzNzBfSVRPUkNIX01JTl91QSkgLwo+ICsJCQkJ IE1UNjM3MF9JVE9SQ0hfU1RFUF91QSArIDE7Cj4gKwlsY2Rldi0+YnJpZ2h0bmVzc19zZXRfYmxv Y2tpbmcgPSBtdDYzNzBfdG9yY2hfYnJpZ2h0bmVzc19zZXQ7Cj4gKwlsY2Rldi0+ZmxhZ3MgfD0g TEVEX0RFVl9DQVBfRkxBU0g7Cj4gKwo+ICsJbWF4X3VhID0gbnVtID09IDIgPyBNVDYzNzBfSVNU UkJfRE9VQkxFX01BWF91QSA6IE1UNjM3MF9JU1RSQl9NQVhfdUE7Cj4gKwl2YWwgPSBNVDYzNzBf SVNUUkJfTUlOX3VBOwo+ICsJcmV0ID0gZndub2RlX3Byb3BlcnR5X3JlYWRfdTMyKGZ3bm9kZSwg ImZsYXNoLW1heC1taWNyb2FtcCIsICZ2YWwpOwo+ICsJaWYgKCFyZXQpCj4gKwkJdmFsID0gbXQ2 MzcwX2NsYW1wKHZhbCwgTVQ2MzcwX0lTVFJCX01JTl91QSwgbWF4X3VhLAo+ICsJCQkJICAgTVQ2 MzcwX0lTVFJCX1NURVBfdUEpOwo+ICsKPiArCXMgPSAmZmxhc2gtPmJyaWdodG5lc3M7Cj4gKwlz LT5taW4gPSBNVDYzNzBfSVNUUkJfTUlOX3VBOwo+ICsJcy0+c3RlcCA9IE1UNjM3MF9JU1RSQl9T VEVQX3VBOwo+ICsJcy0+dmFsID0gcy0+bWF4ID0gdmFsOwo+ICsKPiArCS8qCj4gKwkgKiBBbHdh eXMgY29uZmlndXJlIHRvIHRoZSBtaW5pbXVtIGxldmVsIHdoZW4KPiArCSAqIG9mZiB0byBwcmV2 ZW50IGZsYXNoIGN1cnJlbnQgc3Bpa2VzLgo+ICsJICovCj4gKwlyZXQgPSBfbXQ2MzcwX2ZsYXNo X2JyaWdodG5lc3Nfc2V0KGZsYXNoLCBzLT5taW4pOwo+ICsJaWYgKHJldCkKPiArCQlyZXR1cm4g cmV0Owo+ICsKPiArCj4gKwl2YWwgPSBNVDYzNzBfU1RSQlRPX01JTl9VUzsKPiArCXJldCA9IGZ3 bm9kZV9wcm9wZXJ0eV9yZWFkX3UzMihmd25vZGUsICJmbGFzaC1tYXgtdGltZW91dC11cyIsICZ2 YWwpOwo+ICsJaWYgKCFyZXQpCj4gKwkJdmFsID0gbXQ2MzcwX2NsYW1wKHZhbCwgTVQ2MzcwX1NU UkJUT19NSU5fVVMsCj4gKwkJCQkgICBNVDYzNzBfU1RSQlRPX01BWF9VUywgTVQ2MzcwX1NUUkJU T19TVEVQX1VTKTsKPiArCj4gKwlzID0gJmZsYXNoLT50aW1lb3V0Owo+ICsJcy0+bWluID0gTVQ2 MzcwX1NUUkJUT19NSU5fVVM7Cj4gKwlzLT5zdGVwID0gTVQ2MzcwX1NUUkJUT19TVEVQX1VTOwo+ ICsJcy0+dmFsID0gcy0+bWF4ID0gdmFsOwo+ICsKPiArCWZsYXNoLT5vcHMgPSAmbXQ2MzcwX2Zs YXNoX29wczsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBtdDYzNzBf bGVkX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4gK3sKPiArCXN0cnVjdCBk ZXZpY2UgKmRldiA9ICZwZGV2LT5kZXY7Cj4gKwlzdHJ1Y3QgbXQ2MzcwX3ByaXYgKnByaXY7Cj4g KwlzdHJ1Y3QgZndub2RlX2hhbmRsZSAqY2hpbGQ7Cj4gKwlzaXplX3QgY291bnQ7Cj4gKwlpbnQg aSA9IDAsIHJldDsKPiArCj4gKwljb3VudCA9IGRldmljZV9nZXRfY2hpbGRfbm9kZV9jb3VudChk ZXYpOwo+ICsJaWYgKCFjb3VudCB8fCBjb3VudCA+IE1UNjM3MF9NQVhfTEVEUykKPiArCQlyZXR1 cm4gZGV2X2Vycl9wcm9iZShkZXYsIC1FSU5WQUwsCj4gKwkJICAgICAgICJObyBjaGlsZCBub2Rl IG9yIG5vZGUgY291bnQgb3ZlciBtYXggbGVkIG51bWJlciAlenVcbiIsIGNvdW50KTsKPiArCj4g Kwlwcml2ID0gZGV2bV9remFsbG9jKGRldiwgc3RydWN0X3NpemUocHJpdiwgbGVkcywgY291bnQp LCBHRlBfS0VSTkVMKTsKPiArCWlmICghcHJpdikKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4g Kwlwcml2LT5sZWRzX2NvdW50ID0gY291bnQ7Cj4gKwltdXRleF9pbml0KCZwcml2LT5sb2NrKTsK PiArCj4gKwlwcml2LT5yZWdtYXAgPSBkZXZfZ2V0X3JlZ21hcChkZXYtPnBhcmVudCwgTlVMTCk7 Cj4gKwlpZiAoIXByaXYtPnJlZ21hcCkKPiArCQlyZXR1cm4gZGV2X2Vycl9wcm9iZShkZXYsIC1F Tk9ERVYsICJGYWlsZWQgdG8gZ2V0IHBhcmVudCByZWdtYXBcbiIpOwo+ICsKPiArCWRldmljZV9m b3JfZWFjaF9jaGlsZF9ub2RlKGRldiwgY2hpbGQpIHsKPiArCQlzdHJ1Y3QgbXQ2MzcwX2xlZCAq bGVkID0gcHJpdi0+bGVkcyArIGk7Cj4gKwo+ICsJCWxlZC0+cHJpdiA9IHByaXY7Cj4gKwo+ICsJ CXJldCA9IG10NjM3MF9pbml0X2ZsYXNoX3Byb3BlcnRpZXMoZGV2LCBsZWQsIGNoaWxkKTsKPiAr CQlpZiAocmV0KSB7Cj4gKwkJCWZ3bm9kZV9oYW5kbGVfcHV0KGNoaWxkKTsKPiArCQkJcmV0dXJu IHJldDsKPiArCQl9Cj4gKwo+ICsJCXJldCA9IG10NjM3MF9sZWRfcmVnaXN0ZXIoZGV2LCBsZWQs IGNoaWxkKTsKPiArCQlpZiAocmV0KSB7Cj4gKwkJCWZ3bm9kZV9oYW5kbGVfcHV0KGNoaWxkKTsK PiArCQkJcmV0dXJuIHJldDsKPiArCQl9Cj4gKwo+ICsJCWkrKzsKPiArCX0KPiArCj4gKwlyZXR1 cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgbXQ2Mzcw X2xlZF9vZl9pZFtdID0gewo+ICsJeyAuY29tcGF0aWJsZSA9ICJtZWRpYXRlayxtdDYzNzAtZmxh c2hsaWdodCIgfSwKPiArCXsgLyogc2VudGluZWwgKi8gfQo+ICt9Owo+ICtNT0RVTEVfREVWSUNF X1RBQkxFKG9mLCBtdDYzNzBfbGVkX29mX2lkKTsKPiArCj4gK3N0YXRpYyBzdHJ1Y3QgcGxhdGZv cm1fZHJpdmVyIG10NjM3MF9sZWRfZHJpdmVyID0gewo+ICsJLmRyaXZlciA9IHsKPiArCQkubmFt ZSA9ICJtdDYzNzAtZmxhc2hsaWdodCIsCj4gKwkJLm9mX21hdGNoX3RhYmxlID0gbXQ2MzcwX2xl ZF9vZl9pZCwKPiArCX0sCj4gKwkucHJvYmUgPSBtdDYzNzBfbGVkX3Byb2JlLAo+ICt9Owo+ICtt b2R1bGVfcGxhdGZvcm1fZHJpdmVyKG10NjM3MF9sZWRfZHJpdmVyKTsKPiArCj4gK01PRFVMRV9B VVRIT1IoIkFsaWNlIENoZW4gPGFsaWNlX2NoZW5AcmljaHRlay5jb20+Iik7Cj4gK01PRFVMRV9B VVRIT1IoIkNoaVl1YW4gSHVhbmcgPGN5X2h1YW5nQHJpY2h0ZWsuY29tPiIpOwo+ICtNT0RVTEVf REVTQ1JJUFRJT04oIk1UNjM3MCBGTEFTSCBMRUQgRHJpdmVyIik7Cj4gK01PRFVMRV9MSUNFTlNF KCJHUEwiKTsKPiAtLSAKPiAyLjcuNAo+IAoKLS0gCkxlZSBKb25lcyBb5p2O55C85pavXQoKX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbGludXgtYXJtLWtl cm5lbCBtYWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3JnCmh0 dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtlcm5l bAo=