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 DC089C61DA4 for ; Tue, 7 Mar 2023 02:23:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229893AbjCGCXw (ORCPT ); Mon, 6 Mar 2023 21:23:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52088 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229817AbjCGCXv (ORCPT ); Mon, 6 Mar 2023 21:23:51 -0500 Received: from mg.richtek.com (mg.richtek.com [220.130.44.152]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 5A5272596D; Mon, 6 Mar 2023 18:23:44 -0800 (PST) X-MailGates: (flag:4,DYNAMIC,BADHELO,RELAY,NOHOST:PASS)(compute_score:DE LIVER,40,3) Received: from 192.168.10.47 by mg.richtek.com with MailGates ESMTP Server V5.0(22260:0:AUTH_RELAY) (envelope-from ); Tue, 07 Mar 2023 10:23:03 +0800 (CST) Received: from ex3.rt.l (192.168.10.46) by ex4.rt.l (192.168.10.47) 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 10:23:03 +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 10:23:02 +0800 Date: Tue, 7 Mar 2023 10:23:02 +0800 From: ChiYuan Huang To: Lee Jones CC: ChiaEn Wu , , , , , , , , , , , , , , Alice Chen Subject: Re: [PATCH v17 RESEND 1/3] leds: rgb: mt6370: Add MediaTek MT6370 current sink type LED Indicator support Message-ID: <20230307022302.GA4930@linuxcarl2.richtek.com> References: <8f139c773de274311c8ca63a47d6b207c30913e2.1677150607.git.chiaen_wu@richtek.com> <20230305085533.GC2574592@google.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20230305085533.GC2574592@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: Thanks's for the reviewing. To prevent the misunderstanding, reply as below. No reply means will do. On Sun, Mar 05, 2023 at 08:55:33AM +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 MediaTek MT6370 Current Sink Type LED Indicator > > driver. It can control four channels current-sink RGB LEDs with 3 modes: > > constant current, PWM, and breath 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/rgb/Kconfig | 13 + > > drivers/leds/rgb/Makefile | 1 + > > drivers/leds/rgb/leds-mt6370-rgb.c | 1009 ++++++++++++++++++++++++++++++++++++ > > 3 files changed, 1023 insertions(+) > > create mode 100644 drivers/leds/rgb/leds-mt6370-rgb.c > > In generally, this is really nicely done. Great job. > > Just a few niggles, then you'll be good to go. > > > diff --git a/drivers/leds/rgb/Kconfig b/drivers/leds/rgb/Kconfig > > index 204cf47..7d86bb2 100644 > > --- a/drivers/leds/rgb/Kconfig > > +++ b/drivers/leds/rgb/Kconfig > > @@ -26,4 +26,17 @@ config LEDS_QCOM_LPG > > > > If compiled as a module, the module will be named leds-qcom-lpg. > > > > +config LEDS_MT6370_RGB > > + tristate "LED Support for MediaTek MT6370 PMIC" > > + depends on MFD_MT6370 > > + select LINEAR_RANGE > > + help > > + Say Y here to enable support for MT6370_RGB LED device. > > + In MT6370, there are four channel current-sink LED drivers that > > + support hardware pattern for constant current, PWM, and breath mode. > > + Isink4 channel can also be used as a CHG_VIN power good indicator. > > + > > + This driver can also be built as a module. If so, the module > > + will be called "leds-mt6370-rgb". > > + > > endif # LEDS_CLASS_MULTICOLOR > > diff --git a/drivers/leds/rgb/Makefile b/drivers/leds/rgb/Makefile > > index 0675bc0..8c01daf 100644 > > --- a/drivers/leds/rgb/Makefile > > +++ b/drivers/leds/rgb/Makefile > > @@ -2,3 +2,4 @@ > > > > obj-$(CONFIG_LEDS_PWM_MULTICOLOR) += leds-pwm-multicolor.o > > obj-$(CONFIG_LEDS_QCOM_LPG) += leds-qcom-lpg.o > > +obj-$(CONFIG_LEDS_MT6370_RGB) += leds-mt6370-rgb.o > > diff --git a/drivers/leds/rgb/leds-mt6370-rgb.c b/drivers/leds/rgb/leds-mt6370-rgb.c > > new file mode 100644 > > index 00000000..185d5d7 > > --- /dev/null > > +++ b/drivers/leds/rgb/leds-mt6370-rgb.c > > @@ -0,0 +1,1009 @@ > > +// SPDX-License-Identifier: GPL-2.0-only > > +/* > > + * Copyright (C) 2023 Richtek Technology Corp. > > + * > > + * Authors: > > + * ChiYuan Huang > > + * Alice Chen > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > + > > +enum { > > + MT6370_LED_ISNK1 = 0, > > + MT6370_LED_ISNK2, > > + MT6370_LED_ISNK3, > > + MT6370_LED_ISNK4, > > + MT6370_MAX_LEDS > > +}; > > + > > +enum mt6370_led_mode { > > + MT6370_LED_PWM_MODE = 0, > > + MT6370_LED_BREATH_MODE, > > + MT6370_LED_REG_MODE, > > + MT6370_LED_MAX_MODE > > +}; > > + > > +enum mt6370_led_field { > > + F_RGB_EN = 0, > > + F_CHGIND_EN, > > + F_LED1_CURR, > > + F_LED2_CURR, > > + F_LED3_CURR, > > + F_LED4_CURR, > > + F_LED1_MODE, > > + F_LED2_MODE, > > + F_LED3_MODE, > > + F_LED4_MODE, > > + F_LED1_DUTY, > > + F_LED2_DUTY, > > + F_LED3_DUTY, > > + F_LED4_DUTY, > > + F_LED1_FREQ, > > + F_LED2_FREQ, > > + F_LED3_FREQ, > > + F_LED4_FREQ, > > + F_MAX_FIELDS > > +}; > > + > > +enum mt6370_led_ranges { > > + R_LED123_CURR = 0, > > + R_LED4_CURR, > > + R_LED_TRFON, > > + R_LED_TOFF, > > + R_MAX_RANGES > > +}; > > + > > +enum mt6370_pattern { > > + P_LED_TR1 = 0, > > + P_LED_TR2, > > + P_LED_TF1, > > + P_LED_TF2, > > + P_LED_TON, > > + P_LED_TOFF, > > + P_MAX_PATTERNS > > +}; > > + > > +#define MT6370_REG_DEV_INFO 0x100 > > +#define MT6370_REG_RGB1_DIM 0x182 > > +#define MT6370_REG_RGB2_DIM 0x183 > > +#define MT6370_REG_RGB3_DIM 0x184 > > +#define MT6370_REG_RGB_EN 0x185 > > +#define MT6370_REG_RGB1_ISNK 0x186 > > +#define MT6370_REG_RGB2_ISNK 0x187 > > +#define MT6370_REG_RGB3_ISNK 0x188 > > +#define MT6370_REG_RGB1_TR 0x189 > > +#define MT6370_REG_RGB_CHRIND_DIM 0x192 > > +#define MT6370_REG_RGB_CHRIND_CTRL 0x193 > > +#define MT6370_REG_RGB_CHRIND_TR 0x194 > > + > > +#define MT6372_REG_RGB_EN 0x182 > > +#define MT6372_REG_RGB1_ISNK 0x183 > > +#define MT6372_REG_RGB2_ISNK 0x184 > > +#define MT6372_REG_RGB3_ISNK 0x185 > > +#define MT6372_REG_RGB4_ISNK 0x186 > > +#define MT6372_REG_RGB1_DIM 0x187 > > +#define MT6372_REG_RGB2_DIM 0x188 > > +#define MT6372_REG_RGB3_DIM 0x189 > > +#define MT6372_REG_RGB4_DIM 0x18A > > +#define MT6372_REG_RGB12_FREQ 0x18B > > +#define MT6372_REG_RGB34_FREQ 0x18C > > +#define MT6372_REG_RGB1_TR 0x18D > > + > > +#define MT6370_VENID_MASK GENMASK(7, 4) > > Vendor? Defines should be self documenting. > > What does this save over "VENDOR_ID"? > So 'MT6370_VENDOR_ID_MASK'? And will define all used VENDOR_ID. > > +#define MT6370_CHEN_BIT(id) BIT(MT6370_LED_ISNK4 - id) > > +#define MT6370_VIRTUAL_MULTICOLOR 5 > > +#define MC_CHANNEL_NUM 3 > > +#define MT6370_PWM_DUTY (BIT(5) - 1) > > +#define MT6372_PWM_DUTY (BIT(8) - 1) > > + > > +struct mt6370_led { > > + /* > > + * If the color of the LED in DT is set to > > + * - 'LED_COLOR_ID_RGB' > > + * - 'LED_COLOR_ID_MULTI' > > + * The member 'index' of this struct will be set to > > + * 'MT6370_VIRTUAL_MULTICOLOR'. > > + * If so, this LED will choose 'struct led_classdev_mc mc' to use. > > + * Instead, if the member 'index' of this struct is set to > > + * 'MT6370_LED_ISNK1' ~ 'MT6370_LED_ISNK4', then this LED will choose > > + * 'struct led_classdev isink' to use. > > + */ > > + union { > > + struct led_classdev isink; > > + struct led_classdev_mc mc; > > + }; > > + struct mt6370_priv *priv; > > + enum led_default_state default_state; > > + u32 index; > > +}; > > + > > +struct mt6370_pdata { > > + const unsigned int *tfreq; > > + unsigned int tfreq_len; > > + u16 reg_rgb1_tr; > > + s16 reg_rgb_chrind_tr; > > + u8 pwm_duty; > > +}; > > + > > +struct mt6370_priv { > > + /* Per LED access lock */ > > + struct mutex lock; > > + struct regmap *regmap; > > + struct regmap_field *fields[F_MAX_FIELDS]; > > + const struct reg_field *reg_fields; > > + const struct linear_range *ranges; > > + struct reg_cfg *reg_cfgs; > > + const struct mt6370_pdata *pdata; > > + unsigned int leds_count; > > + unsigned int leds_active; > > + struct mt6370_led leds[]; > > +}; > > + > > +static const struct reg_field common_reg_fields[F_MAX_FIELDS] = { > > + [F_RGB_EN] = REG_FIELD(MT6370_REG_RGB_EN, 4, 7), > > + [F_CHGIND_EN] = REG_FIELD(MT6370_REG_RGB_CHRIND_DIM, 7, 7), > > + [F_LED1_CURR] = REG_FIELD(MT6370_REG_RGB1_ISNK, 0, 2), > > + [F_LED2_CURR] = REG_FIELD(MT6370_REG_RGB2_ISNK, 0, 2), > > + [F_LED3_CURR] = REG_FIELD(MT6370_REG_RGB3_ISNK, 0, 2), > > + [F_LED4_CURR] = REG_FIELD(MT6370_REG_RGB_CHRIND_CTRL, 0, 1), > > + [F_LED1_MODE] = REG_FIELD(MT6370_REG_RGB1_DIM, 5, 6), > > + [F_LED2_MODE] = REG_FIELD(MT6370_REG_RGB2_DIM, 5, 6), > > + [F_LED3_MODE] = REG_FIELD(MT6370_REG_RGB3_DIM, 5, 6), > > + [F_LED4_MODE] = REG_FIELD(MT6370_REG_RGB_CHRIND_DIM, 5, 6), > > + [F_LED1_DUTY] = REG_FIELD(MT6370_REG_RGB1_DIM, 0, 4), > > + [F_LED2_DUTY] = REG_FIELD(MT6370_REG_RGB2_DIM, 0, 4), > > + [F_LED3_DUTY] = REG_FIELD(MT6370_REG_RGB3_DIM, 0, 4), > > + [F_LED4_DUTY] = REG_FIELD(MT6370_REG_RGB_CHRIND_DIM, 0, 4), > > + [F_LED1_FREQ] = REG_FIELD(MT6370_REG_RGB1_ISNK, 3, 5), > > + [F_LED2_FREQ] = REG_FIELD(MT6370_REG_RGB2_ISNK, 3, 5), > > + [F_LED3_FREQ] = REG_FIELD(MT6370_REG_RGB3_ISNK, 3, 5), > > + [F_LED4_FREQ] = REG_FIELD(MT6370_REG_RGB_CHRIND_CTRL, 2, 4), > > +}; > > + > > +static const struct reg_field mt6372_reg_fields[F_MAX_FIELDS] = { > > + [F_RGB_EN] = REG_FIELD(MT6372_REG_RGB_EN, 4, 7), > > + [F_CHGIND_EN] = REG_FIELD(MT6372_REG_RGB_EN, 3, 3), > > + [F_LED1_CURR] = REG_FIELD(MT6372_REG_RGB1_ISNK, 0, 3), > > + [F_LED2_CURR] = REG_FIELD(MT6372_REG_RGB2_ISNK, 0, 3), > > + [F_LED3_CURR] = REG_FIELD(MT6372_REG_RGB3_ISNK, 0, 3), > > + [F_LED4_CURR] = REG_FIELD(MT6372_REG_RGB4_ISNK, 0, 3), > > + [F_LED1_MODE] = REG_FIELD(MT6372_REG_RGB1_ISNK, 6, 7), > > + [F_LED2_MODE] = REG_FIELD(MT6372_REG_RGB2_ISNK, 6, 7), > > + [F_LED3_MODE] = REG_FIELD(MT6372_REG_RGB3_ISNK, 6, 7), > > + [F_LED4_MODE] = REG_FIELD(MT6372_REG_RGB4_ISNK, 6, 7), > > + [F_LED1_DUTY] = REG_FIELD(MT6372_REG_RGB1_DIM, 0, 7), > > + [F_LED2_DUTY] = REG_FIELD(MT6372_REG_RGB2_DIM, 0, 7), > > + [F_LED3_DUTY] = REG_FIELD(MT6372_REG_RGB3_DIM, 0, 7), > > + [F_LED4_DUTY] = REG_FIELD(MT6372_REG_RGB4_DIM, 0, 7), > > + [F_LED1_FREQ] = REG_FIELD(MT6372_REG_RGB12_FREQ, 5, 7), > > + [F_LED2_FREQ] = REG_FIELD(MT6372_REG_RGB12_FREQ, 2, 4), > > + [F_LED3_FREQ] = REG_FIELD(MT6372_REG_RGB34_FREQ, 5, 7), > > + [F_LED4_FREQ] = REG_FIELD(MT6372_REG_RGB34_FREQ, 2, 4), > > +}; > > + > > +/* Current unit: microamp, time unit: millisecond */ > > +static const struct linear_range common_led_ranges[R_MAX_RANGES] = { > > + [R_LED123_CURR] = { 4000, 1, 6, 4000 }, > > + [R_LED4_CURR] = { 2000, 1, 3, 2000 }, > > + [R_LED_TRFON] = { 125, 0, 15, 200 }, > > + [R_LED_TOFF] = { 250, 0, 15, 400 }, > > +}; > > + > > +static const struct linear_range mt6372_led_ranges[R_MAX_RANGES] = { > > + [R_LED123_CURR] = { 2000, 1, 14, 2000 }, > > + [R_LED4_CURR] = { 2000, 1, 14, 2000 }, > > + [R_LED_TRFON] = { 125, 0, 15, 250 }, > > + [R_LED_TOFF] = { 250, 0, 15, 500 }, > > +}; > > + > > +static const unsigned int common_tfreqs[] = { > > + 10000, 5000, 2000, 1000, 500, 200, 5, 1, > > +}; > > + > > +static const unsigned int mt6372_tfreqs[] = { > > + 8000, 4000, 2000, 1000, 500, 250, 8, 4, > > +}; > > + > > +static const struct mt6370_pdata common_pdata = { > > + .tfreq = common_tfreqs, > > + .tfreq_len = ARRAY_SIZE(common_tfreqs), > > + .pwm_duty = MT6370_PWM_DUTY, > > + .reg_rgb1_tr = MT6370_REG_RGB1_TR, > > + .reg_rgb_chrind_tr = MT6370_REG_RGB_CHRIND_TR, > > +}; > > + > > +static const struct mt6370_pdata mt6372_pdata = { > > + .tfreq = mt6372_tfreqs, > > + .tfreq_len = ARRAY_SIZE(mt6372_tfreqs), > > + .pwm_duty = MT6372_PWM_DUTY, > > + .reg_rgb1_tr = MT6372_REG_RGB1_TR, > > + .reg_rgb_chrind_tr = -1, > > +}; > > + > > +static enum mt6370_led_field mt6370_get_led_current_field(unsigned int led_no) > > +{ > > + switch (led_no) { > > + case MT6370_LED_ISNK1: > > + return F_LED1_CURR; > > + case MT6370_LED_ISNK2: > > + return F_LED2_CURR; > > + case MT6370_LED_ISNK3: > > + return F_LED3_CURR; > > + default: > > + return F_LED4_CURR; > > + } > > +} > > + > > +static int mt6370_set_led_brightness(struct mt6370_priv *priv, > > + unsigned int led_no, unsigned int level) > > +{ > > + enum mt6370_led_field sel_field; > > + > > + sel_field = mt6370_get_led_current_field(led_no); > > + > > + return regmap_field_write(priv->fields[sel_field], level); > > +} > > + > > +static int mt6370_get_led_brightness(struct mt6370_priv *priv, > > + unsigned int led_no, unsigned int *level) > > +{ > > + enum mt6370_led_field sel_field; > > + > > + sel_field = mt6370_get_led_current_field(led_no); > > + > > + return regmap_field_read(priv->fields[sel_field], level); > > +} > > + > > +static int mt6370_set_led_duty(struct mt6370_priv *priv, unsigned int led_no, > > + unsigned int ton, unsigned int toff) > > +{ > > + const struct mt6370_pdata *pdata = priv->pdata; > > + enum mt6370_led_field sel_field; > > + unsigned int divisor, ratio; > > + > > + divisor = pdata->pwm_duty; > > + ratio = ton * divisor / (ton + toff); > > + > > + switch (led_no) { > > + case MT6370_LED_ISNK1: > > + sel_field = F_LED1_DUTY; > > + break; > > + case MT6370_LED_ISNK2: > > + sel_field = F_LED2_DUTY; > > + break; > > + case MT6370_LED_ISNK3: > > + sel_field = F_LED3_DUTY; > > + break; > > + default: > > + sel_field = F_LED4_DUTY; > > + break; > > + } > > + > > + return regmap_field_write(priv->fields[sel_field], ratio); > > +} > > + > > +static int mt6370_set_led_freq(struct mt6370_priv *priv, unsigned int led_no, > > + unsigned int ton, unsigned int toff) > > +{ > > + const struct mt6370_pdata *pdata = priv->pdata; > > + enum mt6370_led_field sel_field; > > + unsigned int tfreq_len = pdata->tfreq_len; > > + unsigned int tsum, sel; > > + > > + tsum = ton + toff; > > + > > + if (tsum > pdata->tfreq[0] || tsum < pdata->tfreq[tfreq_len - 1]) > > + return -EOPNOTSUPP; > > + > > + sel = find_closest_descending(tsum, pdata->tfreq, tfreq_len); > > + > > + switch (led_no) { > > + case MT6370_LED_ISNK1: > > + sel_field = F_LED1_FREQ; > > + break; > > + case MT6370_LED_ISNK2: > > + sel_field = F_LED2_FREQ; > > + break; > > + case MT6370_LED_ISNK3: > > + sel_field = F_LED3_FREQ; > > + break; > > + default: > > + sel_field = F_LED4_FREQ; > > + break; > > + } > > + > > + return regmap_field_write(priv->fields[sel_field], sel); > > +} > > + > > +static void mt6370_get_breath_reg_base(struct mt6370_priv *priv, > > + unsigned int led_no, unsigned int *base) > > +{ > > + const struct mt6370_pdata *pdata = priv->pdata; > > + > > + if (pdata->reg_rgb_chrind_tr < 0) { > > + *base = pdata->reg_rgb1_tr + led_no * 3; > > + return; > > + } > > + > > + switch (led_no) { > > + case MT6370_LED_ISNK1: > > + case MT6370_LED_ISNK2: > > + case MT6370_LED_ISNK3: > > + *base = pdata->reg_rgb1_tr + led_no * 3; > > + break; > > + default: > > + *base = pdata->reg_rgb_chrind_tr; > > + break; > > + } > > +} > > + > > +static int mt6370_gen_breath_pattern(struct mt6370_priv *priv, > > + struct led_pattern *pattern, u32 len, > > + u8 *pattern_val, u32 val_len) > > +{ > > + enum mt6370_led_ranges sel_range; > > + struct led_pattern *curr; > > + unsigned int sel; > > + u32 val = 0; > > + int i; > > + > > + if (len < P_MAX_PATTERNS && val_len < P_MAX_PATTERNS / 2) > > + return -EINVAL; > > + > > + /* > > + * Pattern list > > + * tr1: byte 0, b'[7: 4] > > Perhaps this is standard formatting and I'm just not aware of it, but > the space is throwing me and making me think twice. Does this mean bits > 7 through 4, so b'11110000? > Yes. like as you said. Sorry for the redudant space make you confused. I'm not sure whether it's a standard formating or not. Sometimes, in datasheet, we'll use this format to represent the bitfield for functions. Your format is also good for it. And which one is preferable? > > + * tr2: byte 0, b'[3: 0] > > + * tf1: byte 1, b'[7: 4] > > + * tf2: byte 1, b'[3: 0] > > + * ton: byte 2, b'[7: 4] > > + * toff: byte 2, b'[3: 0] > > + */ > > + for (i = 0; i < P_MAX_PATTERNS; i++) { > > + curr = pattern + i; > > + > > + sel_range = i == P_LED_TOFF ? R_LED_TOFF : R_LED_TRFON; > > + > > + linear_range_get_selector_within(priv->ranges + sel_range, > > + curr->delta_t, &sel); > > + > > + if (i % 2) { > > + val |= sel; > > + } else { > > + val <<= 8; > > + val |= sel << 4; > > + } > > + } > > + > > + put_unaligned_be24(val, pattern_val); > > + > > + return 0; > > +} > > + > > +static int mt6370_set_led_mode(struct mt6370_priv *priv, unsigned int led_no, > > + enum mt6370_led_mode mode) > > +{ > > + enum mt6370_led_field sel_field; > > + > > + switch (led_no) { > > + case MT6370_LED_ISNK1: > > + sel_field = F_LED1_MODE; > > + break; > > + case MT6370_LED_ISNK2: > > + sel_field = F_LED2_MODE; > > + break; > > + case MT6370_LED_ISNK3: > > + sel_field = F_LED3_MODE; > > + break; > > + default: > > + sel_field = F_LED4_MODE; > > + break; > > + } > > + > > + return regmap_field_write(priv->fields[sel_field], mode); > > +} > > + > > +static int mt6370_mc_brightness_set(struct led_classdev *lcdev, > > + enum led_brightness level) > > +{ > > + struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev); > > + struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc); > > + struct mt6370_priv *priv = led->priv; > > + struct mc_subled *subled; > > + unsigned int enable, disable; > > + int i, ret; > > + > > + mutex_lock(&priv->lock); > > + > > + led_mc_calc_color_components(mccdev, level); > > + > > + ret = regmap_field_read(priv->fields[F_RGB_EN], &enable); > > + if (ret) > > + goto out_unlock; > > + > > + disable = enable; > > + > > + for (i = 0; i < mccdev->num_colors; i++) { > > + u32 brightness; > > + > > + subled = mccdev->subled_info + i; > > + brightness = min(subled->brightness, lcdev->max_brightness); > > + disable &= ~MT6370_CHEN_BIT(subled->channel); > > + > > + if (level == 0) { > > + enable &= ~MT6370_CHEN_BIT(subled->channel); > > + > > + ret = mt6370_set_led_mode(priv, subled->channel, > > + MT6370_LED_REG_MODE); > > Please unify your line-wrap strategy. In some places you are using the > full 100-chars allowable and in many others, you line-wrap early. Please > go through the entire file and unwrap to 100-chars where appropriate. > > You'll see what I mean as you re-read the file with this in mind. > > > + if (ret) > > + goto out_unlock; > > + > > + continue; > > + } > > + > > + if (brightness == 0) { > > + enable &= ~MT6370_CHEN_BIT(subled->channel); > > + continue; > > + } > > + > > + enable |= MT6370_CHEN_BIT(subled->channel); > > + > > + ret = mt6370_set_led_brightness(priv, subled->channel, > > + brightness); > > + if (ret) > > + goto out_unlock; > > + } > > + > > + ret = regmap_field_write(priv->fields[F_RGB_EN], disable); > > + if (ret) > > + goto out_unlock; > > + > > + ret = regmap_field_write(priv->fields[F_RGB_EN], enable); > > + > > +out_unlock: > > + mutex_unlock(&priv->lock); > > + > > + return ret; > > +} > > + > > +static int mt6370_mc_blink_set(struct led_classdev *lcdev, > > + unsigned long *delay_on, > > + unsigned long *delay_off) > > +{ > > + struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev); > > + struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc); > > + struct mt6370_priv *priv = led->priv; > > + struct mc_subled *subled; > > + unsigned int enable, disable; > > + int i, ret; > > + > > + mutex_lock(&priv->lock); > > + > > + if (!*delay_on && !*delay_off) > > + *delay_on = *delay_off = 500; > > + > > + ret = regmap_field_read(priv->fields[F_RGB_EN], &enable); > > + if (ret) > > + goto out_unlock; > > + > > + disable = enable; > > + > > + for (i = 0; i < mccdev->num_colors; i++) { > > + subled = mccdev->subled_info + i; > > + > > + disable &= ~MT6370_CHEN_BIT(subled->channel); > > + > > + ret = mt6370_set_led_duty(priv, subled->channel, *delay_on, > > + *delay_off); > > + if (ret) > > + goto out_unlock; > > + > > + ret = mt6370_set_led_freq(priv, subled->channel, *delay_on, > > + *delay_off); > > + if (ret) > > + goto out_unlock; > > + > > + ret = mt6370_set_led_mode(priv, subled->channel, > > + MT6370_LED_PWM_MODE); > > + if (ret) > > + goto out_unlock; > > + } > > + > > + /* Toggle to make pattern timing the same */ > > + ret = regmap_field_write(priv->fields[F_RGB_EN], disable); > > + if (ret) > > + goto out_unlock; > > + > > + ret = regmap_field_write(priv->fields[F_RGB_EN], enable); > > + > > +out_unlock: > > + mutex_unlock(&priv->lock); > > + > > + return ret; > > +} > > + > > +static int mt6370_mc_pattern_set(struct led_classdev *lcdev, > > + struct led_pattern *pattern, u32 len, int repeat) > > +{ > > + struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev); > > + struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc); > > + struct mt6370_priv *priv = led->priv; > > + struct mc_subled *subled; > > + unsigned int reg_base, enable, disable; > > + u8 params[P_MAX_PATTERNS / 2]; > > + int i, ret; > > + > > + mutex_lock(&priv->lock); > > + > > + ret = mt6370_gen_breath_pattern(priv, pattern, len, params, > > + sizeof(params)); > > + if (ret) > > + goto out_unlock; > > + > > + ret = regmap_field_read(priv->fields[F_RGB_EN], &enable); > > + if (ret) > > + goto out_unlock; > > + > > + disable = enable; > > + > > + for (i = 0; i < mccdev->num_colors; i++) { > > + subled = mccdev->subled_info + i; > > + > > + mt6370_get_breath_reg_base(priv, subled->channel, ®_base); > > + disable &= ~MT6370_CHEN_BIT(subled->channel); > > + > > + ret = regmap_raw_write(priv->regmap, reg_base, params, > > + sizeof(params)); > > + if (ret) > > + goto out_unlock; > > + > > + ret = mt6370_set_led_mode(priv, subled->channel, > > + MT6370_LED_BREATH_MODE); > > + if (ret) > > + goto out_unlock; > > + } > > + > > + /* Toggle to make pattern timing be the same */ > > + ret = regmap_field_write(priv->fields[F_RGB_EN], disable); > > + if (ret) > > + goto out_unlock; > > + > > + ret = regmap_field_write(priv->fields[F_RGB_EN], enable); > > + > > +out_unlock: > > + mutex_unlock(&priv->lock); > > + > > + return ret; > > +} > > + > > +static inline int mt6370_mc_pattern_clear(struct led_classdev *lcdev) > > +{ > > + struct led_classdev_mc *mccdev = lcdev_to_mccdev(lcdev); > > + struct mt6370_led *led = container_of(mccdev, struct mt6370_led, mc); > > + struct mt6370_priv *priv = led->priv; > > + struct mc_subled *subled; > > + int i, ret; > > + > > + mutex_lock(&led->priv->lock); > > + > > + for (i = 0; i < mccdev->num_colors; i++) { > > + subled = mccdev->subled_info + i; > > + > > + ret = mt6370_set_led_mode(priv, subled->channel, > > + MT6370_LED_REG_MODE); > > + if (ret) > > + break; > > + } > > + > > + mutex_unlock(&led->priv->lock); > > + > > + return ret; > > +} > > + > > +static int mt6370_isnk_brightness_set(struct led_classdev *lcdev, > > + enum led_brightness level) > > +{ > > + struct mt6370_led *led = container_of(lcdev, struct mt6370_led, isink); > > + struct mt6370_priv *priv = led->priv; > > + unsigned int enable; > > + int ret; > > + > > + mutex_lock(&priv->lock); > > + > > + ret = regmap_field_read(priv->fields[F_RGB_EN], &enable); > > + if (ret) > > + goto out_unlock; > > + > > + if (level == 0) { > > + enable &= ~MT6370_CHEN_BIT(led->index); > > + > > + ret = mt6370_set_led_mode(priv, led->index, > > + MT6370_LED_REG_MODE); > > + if (ret) > > + goto out_unlock; > > + } else { > > + enable |= MT6370_CHEN_BIT(led->index); > > + > > + ret = mt6370_set_led_brightness(priv, led->index, level); > > + if (ret) > > + goto out_unlock; > > + } > > + > > + ret = regmap_field_write(priv->fields[F_RGB_EN], enable); > > + > > +out_unlock: > > + mutex_unlock(&priv->lock); > > + > > + return ret; > > +} > > + > > +static int mt6370_isnk_blink_set(struct led_classdev *lcdev, > > + unsigned long *delay_on, > > + unsigned long *delay_off) > > +{ > > + struct mt6370_led *led = container_of(lcdev, struct mt6370_led, isink); > > + struct mt6370_priv *priv = led->priv; > > + int ret; > > + > > + mutex_lock(&priv->lock); > > + > > + if (!*delay_on && !*delay_off) > > + *delay_on = *delay_off = 500; > > + > > + ret = mt6370_set_led_duty(priv, led->index, *delay_on, *delay_off); > > + if (ret) > > + goto out_unlock; > > + > > + ret = mt6370_set_led_freq(priv, led->index, *delay_on, *delay_off); > > + if (ret) > > + goto out_unlock; > > + > > + ret = mt6370_set_led_mode(priv, led->index, MT6370_LED_PWM_MODE); > > + > > +out_unlock: > > + mutex_unlock(&priv->lock); > > + > > + return ret; > > +} > > + > > +static int mt6370_isnk_pattern_set(struct led_classdev *lcdev, > > + struct led_pattern *pattern, u32 len, > > + int repeat) > > +{ > > + struct mt6370_led *led = container_of(lcdev, struct mt6370_led, isink); > > + struct mt6370_priv *priv = led->priv; > > + unsigned int reg_base; > > + u8 params[P_MAX_PATTERNS / 2]; > > + int ret; > > + > > + mutex_lock(&priv->lock); > > + > > + ret = mt6370_gen_breath_pattern(priv, pattern, len, params, > > + sizeof(params)); > > + if (ret) > > + goto out_unlock; > > + > > + mt6370_get_breath_reg_base(priv, led->index, ®_base); > > + > > + ret = regmap_raw_write(priv->regmap, reg_base, params, sizeof(params)); > > + if (ret) > > + goto out_unlock; > > + > > + ret = mt6370_set_led_mode(priv, led->index, MT6370_LED_BREATH_MODE); > > + > > +out_unlock: > > + mutex_unlock(&priv->lock); > > + > > + return ret; > > +} > > + > > +static inline int mt6370_isnk_pattern_clear(struct led_classdev *lcdev) > > +{ > > + struct mt6370_led *led = container_of(lcdev, struct mt6370_led, isink); > > + struct mt6370_priv *priv = led->priv; > > + int ret; > > + > > + mutex_lock(&led->priv->lock); > > + ret = mt6370_set_led_mode(priv, led->index, MT6370_LED_REG_MODE); > > + mutex_unlock(&led->priv->lock); > > + > > + return ret; > > +} > > + > > +static int mt6370_init_led_properties(struct device *dev, > > + struct mt6370_led *led, > > + struct led_init_data *init_data) > > +{ > > + struct mt6370_priv *priv = led->priv; > > + struct led_classdev *lcdev; > > + struct fwnode_handle *child; > > + enum mt6370_led_ranges sel_range; > > + u32 max_uA, max_level; > > + int ret; > > + > > + if (led->index == MT6370_VIRTUAL_MULTICOLOR) { > > Rather than having these huge if-else statements, please consider using > a sub-function. > I'll rewrite this as a sub function 'mt6370_assign_multicolor_info'. start... > > + struct mc_subled *sub_led; > > + u32 num_color = 0; > > + > > + sub_led = devm_kcalloc(dev, MC_CHANNEL_NUM, sizeof(*sub_led), > > + GFP_KERNEL); > > + if (!sub_led) > > + return -ENOMEM; > > + > > + fwnode_for_each_child_node(init_data->fwnode, child) { > > + u32 reg, color; > > + > > + ret = fwnode_property_read_u32(child, "reg", ®); > > + if (ret || reg > MT6370_LED_ISNK3 || > > + priv->leds_active & BIT(reg)) { > > + fwnode_handle_put(child); > > + return -EINVAL; > > + } > > + > > + ret = fwnode_property_read_u32(child, "color", &color); > > + if (ret) { > > + fwnode_handle_put(child); > > + return dev_err_probe(dev, ret, "LED %d, no color specified\n", > > + led->index); > > + } > > + > > + priv->leds_active |= BIT(reg); > > + sub_led[num_color].color_index = color; > > + sub_led[num_color].channel = reg; > > + sub_led[num_color].intensity = 0; > > + num_color++; > > + } > > + > > + if (num_color < 2) > > + return dev_err_probe(dev, -EINVAL, > > + "Multicolor must include 2 or more LED channels\n"); > > + > > + led->mc.num_colors = num_color; > > + led->mc.subled_info = sub_led; > > + ...end > > + lcdev = &led->mc.led_cdev; > > + lcdev->brightness_set_blocking = mt6370_mc_brightness_set; > > + lcdev->blink_set = mt6370_mc_blink_set; > > + lcdev->pattern_set = mt6370_mc_pattern_set; > > + lcdev->pattern_clear = mt6370_mc_pattern_clear; > > + } else { > > + lcdev = &led->isink; > > + lcdev->brightness_set_blocking = mt6370_isnk_brightness_set; > > + lcdev->blink_set = mt6370_isnk_blink_set; > > + lcdev->pattern_set = mt6370_isnk_pattern_set; > > + lcdev->pattern_clear = mt6370_isnk_pattern_clear; > > + } > > + > > + ret = fwnode_property_read_u32(init_data->fwnode, "led-max-microamp", > > + &max_uA); > > + if (ret) { > > + dev_warn(dev, "Not specified led-max-microamp, config to the minimum\n"); > > + max_uA = 0; > > + } > > + > > + if (led->index == MT6370_LED_ISNK4) > > + sel_range = R_LED4_CURR; > > + else > > + sel_range = R_LED123_CURR; > > + > > + linear_range_get_selector_within(priv->ranges + sel_range, max_uA, > > + &max_level); > > + > > + lcdev->max_brightness = max_level; > > + > > + led->default_state = led_init_default_state_get(init_data->fwnode); > > + > > + return 0; > > +} > > + > > +static int mt6370_isnk_init_default_state(struct mt6370_led *led) > > +{ > > + struct mt6370_priv *priv = led->priv; > > + unsigned int enable, level; > > + int ret; > > + > > + ret = mt6370_get_led_brightness(priv, led->index, &level); > > + if (ret) > > + return ret; > > + > > + ret = regmap_field_read(priv->fields[F_RGB_EN], &enable); > > + if (ret) > > + return ret; > > + > > + if (!(enable & MT6370_CHEN_BIT(led->index))) > > + level = 0; > > + > > + switch (led->default_state) { > > + case LEDS_DEFSTATE_ON: > > + led->isink.brightness = led->isink.max_brightness; > > + break; > > + case LEDS_DEFSTATE_KEEP: > > + led->isink.brightness = min(level, led->isink.max_brightness); > > + break; > > + default: > > + led->isink.brightness = 0; > > + break; > > + } > > + > > + return mt6370_isnk_brightness_set(&led->isink, led->isink.brightness); > > +} > > + > > +static int mt6370_led_register(struct device *dev, struct mt6370_led *led, > > + struct led_init_data *init_data) > > +{ > > + struct mt6370_priv *priv = led->priv; > > + int ret; > > + > > + if (led->index == MT6370_VIRTUAL_MULTICOLOR) { > > This too could be split into separate functions to tidy things up a > little. > Like as below? if (led->index == MT6370_VIRTUAL_MULTICOLOR) return mt6370_multicolor_led_register(....) if (led->index == MT6370_LED_ISNK4) { ..... } ret = mt6370_init_isnk_default_state(...) Since the multilor case directly return from the sub-function, else can be removed. > > + ret = mt6370_mc_brightness_set(&led->mc.led_cdev, 0); > > + if (ret) > > + return dev_err_probe(dev, ret, "Couldn't set multicolor brightness\n"); > > + > > + ret = devm_led_classdev_multicolor_register_ext(dev, &led->mc, > > + init_data); > > + if (ret) > > + return dev_err_probe(dev, ret, "Couldn't register multicolor\n"); > > + } else { > > + if (led->index == MT6370_LED_ISNK4) { > > + ret = regmap_field_write(priv->fields[F_CHGIND_EN], 1); > > + if (ret) > > + return dev_err_probe(dev, ret, "Failed to set CHRIND to SW\n"); > > + } > > + > > + ret = mt6370_isnk_init_default_state(led); > > + if (ret) > > + return dev_err_probe(dev, ret, "Failed to init %d isnk state\n", > > + led->index); > > + > > + ret = devm_led_classdev_register_ext(dev, &led->isink, > > + init_data); > > + if (ret) > > + return dev_err_probe(dev, ret, "Couldn't register isink %d\n", led->index); > > + } > > + > > + return 0; > > +} > > + > > +static int mt6370_check_vendor_info(struct mt6370_priv *priv) > > +{ > > + unsigned int devinfo, vid; > > + int ret; > > + > > + ret = regmap_read(priv->regmap, MT6370_REG_DEV_INFO, &devinfo); > > + if (ret) > > + return ret; > > + > > + vid = FIELD_GET(MT6370_VENID_MASK, devinfo); > > + if (vid == 0x9 || vid == 0xb) { > > Are there nice human readable associates of these (vendor?) IDS? > For clearly understanding, I'll define these two as 'MT6372_VENDOR_ID' and 'MT6372C_VENDOR_ID'. > > + priv->reg_fields = mt6372_reg_fields; > > + priv->ranges = mt6372_led_ranges; > > + priv->pdata = &mt6372_pdata; > > + } else { > > + /* Common for MT6370/71 */ > > + priv->reg_fields = common_reg_fields; > > + priv->ranges = common_led_ranges; > > + priv->pdata = &common_pdata; > > + } > > + > > + return 0; > > +} > > + > > +static int mt6370_leds_probe(struct platform_device *pdev) > > +{ > > + struct device *dev = &pdev->dev; > > + struct mt6370_priv *priv; > > + struct fwnode_handle *child; > > + size_t count; > > + unsigned int i = 0; > > + int 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"); > > + > > + ret = mt6370_check_vendor_info(priv); > > + if (ret) > > + return dev_err_probe(dev, ret, "Failed to check vendor info\n"); > > + > > + ret = devm_regmap_field_bulk_alloc(dev, priv->regmap, priv->fields, > > + priv->reg_fields, F_MAX_FIELDS); > > + if (ret) > > + return dev_err_probe(dev, ret, "Failed to allocate regmap field\n"); > > + > > + device_for_each_child_node(dev, child) { > > + struct mt6370_led *led = priv->leds + i++; > > + struct led_init_data init_data = { .fwnode = child }; > > + u32 reg, color; > > + > > + ret = fwnode_property_read_u32(child, "reg", ®); > > + if (ret) { > > + fwnode_handle_put(child); > > + return dev_err_probe(dev, ret, "Failed to parse reg property\n"); > > + } > > + > > + if (reg >= MT6370_MAX_LEDS) { > > + fwnode_handle_put(child); > > + return dev_err_probe(dev, -EINVAL, "Error reg property number\n"); > > + } > > + > > + ret = fwnode_property_read_u32(child, "color", &color); > > + if (ret) { > > + fwnode_handle_put(child); > > + return dev_err_probe(dev, ret, "Failed to parse color property\n"); > > + } > > + > > + if (color == LED_COLOR_ID_RGB || color == LED_COLOR_ID_MULTI) > > + reg = MT6370_VIRTUAL_MULTICOLOR; > > + > > + if (priv->leds_active & BIT(reg)) { > > + fwnode_handle_put(child); > > + return dev_err_probe(dev, -EINVAL, "Duplicate reg property\n"); > > + } > > + > > + priv->leds_active |= BIT(reg); > > + > > + led->index = reg; > > + led->priv = priv; > > + > > + ret = mt6370_init_led_properties(dev, led, &init_data); > > + if (ret) { > > + fwnode_handle_put(child); > > I count 6 calls to fwnode_handle_put() here. > > Please use a goto to divert the error handling to the bottom of the > function where you call fwnode_handle_put() just once. > > > + return ret; > > + } > > + > > + ret = mt6370_led_register(dev, led, &init_data); > > + if (ret) { > > + fwnode_handle_put(child); > > + return ret; > > + } > > + } > > + > > + return 0; > > +} > > + > > +static const struct of_device_id mt6370_rgbled_device_table[] = { > > + { .compatible = "mediatek,mt6370-indicator" }, > > + {} > > +}; > > +MODULE_DEVICE_TABLE(of, mt6370_rgbled_device_table); > > + > > +static struct platform_driver mt6370_rgbled_driver = { > > + .driver = { > > + .name = "mt6370-indicator", > > + .of_match_table = mt6370_rgbled_device_table, > > + }, > > + .probe = mt6370_leds_probe, > > +}; > > +module_platform_driver(mt6370_rgbled_driver); > > + > > +MODULE_AUTHOR("Alice Chen "); > > +MODULE_AUTHOR("ChiYuan Huang "); > > +MODULE_DESCRIPTION("MediaTek MT6370 RGB 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 342D0C64EC4 for ; Tue, 7 Mar 2023 02:26:10 +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=Topbo/q6TcglO0JZ72AWeopaVNuTrQN5o1lO8olBauI=; b=E+Q++oTmoHKelV VMoWAimxxhHiePkMfkxGAddnLqlQwa7tXKjrtTBLAPLMLK3T5hDAxRhxZE3LCM2ku/bqmIjNFsCu6 fC/VV7wnfHzh+3TdBpQBGJuqlo1kXCpqHcMi4QUnhJaRD79/jgGwlxAQM8FzHuxV9eRbogdfLEIZj 7o4baOZf0OccNClNQd2GTDZYQ6z+it0H6QY/VE39hbEa+GtMUfDYei2K1/bgSxY+aoI0hXUH+UKE+ UCQ2PG0Y1zMENHGi0U22HLQbQz5yBiwHEjgI6eYg6mDG4nz4AIV3JrFHj46rz2K0FRv+U6G4tZHvg uSRINVDcW40LOJS9AAmw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1pZMzs-00FrGn-5x; Tue, 07 Mar 2023 02:24:12 +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 1pZMzi-00FrB6-5r; Tue, 07 Mar 2023 02:24:07 +0000 X-MailGates: (flag:4,DYNAMIC,BADHELO,RELAY,NOHOST:PASS)(compute_score:DE LIVER,40,3) Received: from 192.168.10.47 by mg.richtek.com with MailGates ESMTP Server V5.0(22260:0:AUTH_RELAY) (envelope-from ); Tue, 07 Mar 2023 10:23:03 +0800 (CST) Received: from ex3.rt.l (192.168.10.46) by ex4.rt.l (192.168.10.47) 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 10:23:03 +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 10:23:02 +0800 Date: Tue, 7 Mar 2023 10:23:02 +0800 From: ChiYuan Huang To: Lee Jones CC: ChiaEn Wu , , , , , , , , , , , , , , Alice Chen Subject: Re: [PATCH v17 RESEND 1/3] leds: rgb: mt6370: Add MediaTek MT6370 current sink type LED Indicator support Message-ID: <20230307022302.GA4930@linuxcarl2.richtek.com> References: <8f139c773de274311c8ca63a47d6b207c30913e2.1677150607.git.chiaen_wu@richtek.com> <20230305085533.GC2574592@google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20230305085533.GC2574592@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_182402_921294_2C4E520D X-CRM114-Status: GOOD ( 36.99 ) 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 SGksIExlZToKClRoYW5rcydzIGZvciB0aGUgcmV2aWV3aW5nLgpUbyBwcmV2ZW50IHRoZSBtaXN1 bmRlcnN0YW5kaW5nLCByZXBseSBhcyBiZWxvdy4KTm8gcmVwbHkgbWVhbnMgd2lsbCBkby4KCk9u IFN1biwgTWFyIDA1LCAyMDIzIGF0IDA4OjU1OjMzQU0gKzAwMDAsIExlZSBKb25lcyB3cm90ZToK PiBPbiBUaHUsIDIzIEZlYiAyMDIzLCBDaGlhRW4gV3Ugd3JvdGU6Cj4gCj4gPiBGcm9tOiBDaGlZ dWFuIEh1YW5nIDxjeV9odWFuZ0ByaWNodGVrLmNvbT4KPiA+IAo+ID4gVGhlIE1lZGlhVGVrIE1U NjM3MCBpcyBhIGhpZ2hseS1pbnRlZ3JhdGVkIHNtYXJ0IHBvd2VyIG1hbmFnZW1lbnQgSUMsCj4g PiB3aGljaCBpbmNsdWRlcyBhIHNpbmdsZSBjZWxsIExpLUlvbi9MaS1Qb2x5bWVyIHN3aXRjaGlu ZyBiYXR0ZXJ5Cj4gPiBjaGFyZ2VyLCBhIFVTQiBUeXBlLUMgJiBQb3dlciBEZWxpdmVyeSAoUEQp IGNvbnRyb2xsZXIsIGR1YWwKPiA+IEZsYXNoIExFRCBjdXJyZW50IHNvdXJjZXMsIGEgUkdCIExF RCBkcml2ZXIsIGEgYmFja2xpZ2h0IFdMRUQgZHJpdmVyLAo+ID4gYSBkaXNwbGF5IGJpYXMgZHJp dmVyIGFuZCBhIGdlbmVyYWwgTERPIGZvciBwb3J0YWJsZSBkZXZpY2VzLgo+ID4gCj4gPiBBZGQg c3VwcG9ydCBmb3IgdGhlIE1lZGlhVGVrIE1UNjM3MCBDdXJyZW50IFNpbmsgVHlwZSBMRUQgSW5k aWNhdG9yCj4gPiBkcml2ZXIuIEl0IGNhbiBjb250cm9sIGZvdXIgY2hhbm5lbHMgY3VycmVudC1z aW5rIFJHQiBMRURzIHdpdGggMyBtb2RlczoKPiA+IGNvbnN0YW50IGN1cnJlbnQsIFBXTSwgYW5k IGJyZWF0aCBtb2RlLgo+ID4gCj4gPiBBY2tlZC1ieTogSmFjZWsgQW5hc3pld3NraSA8amFjZWsu YW5hc3pld3NraUBnbWFpbC5jb20+Cj4gPiBDby1kZXZlbG9wZWQtYnk6IEFsaWNlIENoZW4gPGFs aWNlX2NoZW5AcmljaHRlay5jb20+Cj4gPiBTaWduZWQtb2ZmLWJ5OiBBbGljZSBDaGVuIDxhbGlj ZV9jaGVuQHJpY2h0ZWsuY29tPgo+ID4gU2lnbmVkLW9mZi1ieTogQ2hpWXVhbiBIdWFuZyA8Y3lf aHVhbmdAcmljaHRlay5jb20+Cj4gPiBTaWduZWQtb2ZmLWJ5OiBDaGlhRW4gV3UgPGNoaWFlbl93 dUByaWNodGVrLmNvbT4KPiA+IC0tLQo+ID4gdjE3Cj4gPiAtIFVwZGF0ZSB0aGUgeWVhciBvZiBD b3B5cmlnaHQgZnJvbSAyMDIyIHRvIDIwMjMKPiA+IAo+ID4gLS0tCj4gPiAgZHJpdmVycy9sZWRz L3JnYi9LY29uZmlnICAgICAgICAgICB8ICAgMTMgKwo+ID4gIGRyaXZlcnMvbGVkcy9yZ2IvTWFr ZWZpbGUgICAgICAgICAgfCAgICAxICsKPiA+ICBkcml2ZXJzL2xlZHMvcmdiL2xlZHMtbXQ2Mzcw LXJnYi5jIHwgMTAwOSArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysKPiA+ICAz IGZpbGVzIGNoYW5nZWQsIDEwMjMgaW5zZXJ0aW9ucygrKQo+ID4gIGNyZWF0ZSBtb2RlIDEwMDY0 NCBkcml2ZXJzL2xlZHMvcmdiL2xlZHMtbXQ2MzcwLXJnYi5jCj4gCj4gSW4gZ2VuZXJhbGx5LCB0 aGlzIGlzIHJlYWxseSBuaWNlbHkgZG9uZS4gIEdyZWF0IGpvYi4KPiAKPiBKdXN0IGEgZmV3IG5p Z2dsZXMsIHRoZW4geW91J2xsIGJlIGdvb2QgdG8gZ28uCj4gIAo+ID4gZGlmZiAtLWdpdCBhL2Ry aXZlcnMvbGVkcy9yZ2IvS2NvbmZpZyBiL2RyaXZlcnMvbGVkcy9yZ2IvS2NvbmZpZwo+ID4gaW5k ZXggMjA0Y2Y0Ny4uN2Q4NmJiMiAxMDA2NDQKPiA+IC0tLSBhL2RyaXZlcnMvbGVkcy9yZ2IvS2Nv bmZpZwo+ID4gKysrIGIvZHJpdmVycy9sZWRzL3JnYi9LY29uZmlnCj4gPiBAQCAtMjYsNCArMjYs MTcgQEAgY29uZmlnIExFRFNfUUNPTV9MUEcKPiA+ICAKPiA+ICAJICBJZiBjb21waWxlZCBhcyBh IG1vZHVsZSwgdGhlIG1vZHVsZSB3aWxsIGJlIG5hbWVkIGxlZHMtcWNvbS1scGcuCj4gPiAgCj4g PiArY29uZmlnIExFRFNfTVQ2MzcwX1JHQgo+ID4gKwl0cmlzdGF0ZSAiTEVEIFN1cHBvcnQgZm9y IE1lZGlhVGVrIE1UNjM3MCBQTUlDIgo+ID4gKwlkZXBlbmRzIG9uIE1GRF9NVDYzNzAKPiA+ICsJ c2VsZWN0IExJTkVBUl9SQU5HRQo+ID4gKwloZWxwCj4gPiArCSAgU2F5IFkgaGVyZSB0byBlbmFi bGUgc3VwcG9ydCBmb3IgTVQ2MzcwX1JHQiBMRUQgZGV2aWNlLgo+ID4gKwkgIEluIE1UNjM3MCwg dGhlcmUgYXJlIGZvdXIgY2hhbm5lbCBjdXJyZW50LXNpbmsgTEVEIGRyaXZlcnMgdGhhdAo+ID4g KwkgIHN1cHBvcnQgaGFyZHdhcmUgcGF0dGVybiBmb3IgY29uc3RhbnQgY3VycmVudCwgUFdNLCBh bmQgYnJlYXRoIG1vZGUuCj4gPiArCSAgSXNpbms0IGNoYW5uZWwgY2FuIGFsc28gYmUgdXNlZCBh cyBhIENIR19WSU4gcG93ZXIgZ29vZCBpbmRpY2F0b3IuCj4gPiArCj4gPiArCSAgVGhpcyBkcml2 ZXIgY2FuIGFsc28gYmUgYnVpbHQgYXMgYSBtb2R1bGUuIElmIHNvLCB0aGUgbW9kdWxlCj4gPiAr CSAgd2lsbCBiZSBjYWxsZWQgImxlZHMtbXQ2MzcwLXJnYiIuCj4gPiArCj4gPiAgZW5kaWYgIyBM RURTX0NMQVNTX01VTFRJQ09MT1IKPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2xlZHMvcmdiL01h a2VmaWxlIGIvZHJpdmVycy9sZWRzL3JnYi9NYWtlZmlsZQo+ID4gaW5kZXggMDY3NWJjMC4uOGMw MWRhZiAxMDA2NDQKPiA+IC0tLSBhL2RyaXZlcnMvbGVkcy9yZ2IvTWFrZWZpbGUKPiA+ICsrKyBi L2RyaXZlcnMvbGVkcy9yZ2IvTWFrZWZpbGUKPiA+IEBAIC0yLDMgKzIsNCBAQAo+ID4gIAo+ID4g IG9iai0kKENPTkZJR19MRURTX1BXTV9NVUxUSUNPTE9SKQkrPSBsZWRzLXB3bS1tdWx0aWNvbG9y Lm8KPiA+ICBvYmotJChDT05GSUdfTEVEU19RQ09NX0xQRykJCSs9IGxlZHMtcWNvbS1scGcubwo+ ID4gK29iai0kKENPTkZJR19MRURTX01UNjM3MF9SR0IpCQkrPSBsZWRzLW10NjM3MC1yZ2Iubwo+ ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbGVkcy9yZ2IvbGVkcy1tdDYzNzAtcmdiLmMgYi9kcml2 ZXJzL2xlZHMvcmdiL2xlZHMtbXQ2MzcwLXJnYi5jCj4gPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+ ID4gaW5kZXggMDAwMDAwMDAuLjE4NWQ1ZDcKPiA+IC0tLSAvZGV2L251bGwKPiA+ICsrKyBiL2Ry aXZlcnMvbGVkcy9yZ2IvbGVkcy1tdDYzNzAtcmdiLmMKPiA+IEBAIC0wLDAgKzEsMTAwOSBAQAo+ ID4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wLW9ubHkKPiA+ICsvKgo+ID4g KyAqIENvcHlyaWdodCAoQykgMjAyMyBSaWNodGVrIFRlY2hub2xvZ3kgQ29ycC4KPiA+ICsgKgo+ ID4gKyAqIEF1dGhvcnM6Cj4gPiArICogICBDaGlZdWFuIEh1YW5nIDxjeV9odWFuZ0ByaWNodGVr LmNvbT4KPiA+ICsgKiAgIEFsaWNlIENoZW4gPGFsaWNlX2NoZW5AcmljaHRlay5jb20+Cj4gPiAr ICovCj4gPiArCj4gPiArI2luY2x1ZGUgPGxpbnV4L2JpdG9wcy5oPgo+ID4gKyNpbmNsdWRlIDxs aW51eC9rZXJuZWwuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgvbGVkcy5oPgo+ID4gKyNpbmNsdWRl IDxsaW51eC9sZWQtY2xhc3MtbXVsdGljb2xvci5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9saW5l YXJfcmFuZ2UuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgvbW9kX2RldmljZXRhYmxlLmg+Cj4gPiAr I2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9tdXRleC5oPgo+ ID4gKyNpbmNsdWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZpY2UuaD4KPiA+ICsjaW5jbHVkZSA8bGlu dXgvcHJvcGVydHkuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgvcmVnbWFwLmg+Cj4gPiArI2luY2x1 ZGUgPGxpbnV4L3V0aWxfbWFjcm9zLmg+Cj4gPiArCj4gPiArI2luY2x1ZGUgPGFzbS91bmFsaWdu ZWQuaD4KPiA+ICsKPiA+ICtlbnVtIHsKPiA+ICsJTVQ2MzcwX0xFRF9JU05LMSA9IDAsCj4gPiAr CU1UNjM3MF9MRURfSVNOSzIsCj4gPiArCU1UNjM3MF9MRURfSVNOSzMsCj4gPiArCU1UNjM3MF9M RURfSVNOSzQsCj4gPiArCU1UNjM3MF9NQVhfTEVEUwo+ID4gK307Cj4gPiArCj4gPiArZW51bSBt dDYzNzBfbGVkX21vZGUgewo+ID4gKwlNVDYzNzBfTEVEX1BXTV9NT0RFID0gMCwKPiA+ICsJTVQ2 MzcwX0xFRF9CUkVBVEhfTU9ERSwKPiA+ICsJTVQ2MzcwX0xFRF9SRUdfTU9ERSwKPiA+ICsJTVQ2 MzcwX0xFRF9NQVhfTU9ERQo+ID4gK307Cj4gPiArCj4gPiArZW51bSBtdDYzNzBfbGVkX2ZpZWxk IHsKPiA+ICsJRl9SR0JfRU4gPSAwLAo+ID4gKwlGX0NIR0lORF9FTiwKPiA+ICsJRl9MRUQxX0NV UlIsCj4gPiArCUZfTEVEMl9DVVJSLAo+ID4gKwlGX0xFRDNfQ1VSUiwKPiA+ICsJRl9MRUQ0X0NV UlIsCj4gPiArCUZfTEVEMV9NT0RFLAo+ID4gKwlGX0xFRDJfTU9ERSwKPiA+ICsJRl9MRUQzX01P REUsCj4gPiArCUZfTEVENF9NT0RFLAo+ID4gKwlGX0xFRDFfRFVUWSwKPiA+ICsJRl9MRUQyX0RV VFksCj4gPiArCUZfTEVEM19EVVRZLAo+ID4gKwlGX0xFRDRfRFVUWSwKPiA+ICsJRl9MRUQxX0ZS RVEsCj4gPiArCUZfTEVEMl9GUkVRLAo+ID4gKwlGX0xFRDNfRlJFUSwKPiA+ICsJRl9MRUQ0X0ZS RVEsCj4gPiArCUZfTUFYX0ZJRUxEUwo+ID4gK307Cj4gPiArCj4gPiArZW51bSBtdDYzNzBfbGVk X3JhbmdlcyB7Cj4gPiArCVJfTEVEMTIzX0NVUlIgPSAwLAo+ID4gKwlSX0xFRDRfQ1VSUiwKPiA+ ICsJUl9MRURfVFJGT04sCj4gPiArCVJfTEVEX1RPRkYsCj4gPiArCVJfTUFYX1JBTkdFUwo+ID4g K307Cj4gPiArCj4gPiArZW51bSBtdDYzNzBfcGF0dGVybiB7Cj4gPiArCVBfTEVEX1RSMSA9IDAs Cj4gPiArCVBfTEVEX1RSMiwKPiA+ICsJUF9MRURfVEYxLAo+ID4gKwlQX0xFRF9URjIsCj4gPiAr CVBfTEVEX1RPTiwKPiA+ICsJUF9MRURfVE9GRiwKPiA+ICsJUF9NQVhfUEFUVEVSTlMKPiA+ICt9 Owo+ID4gKwo+ID4gKyNkZWZpbmUgTVQ2MzcwX1JFR19ERVZfSU5GTwkJCTB4MTAwCj4gPiArI2Rl ZmluZSBNVDYzNzBfUkVHX1JHQjFfRElNCQkJMHgxODIKPiA+ICsjZGVmaW5lIE1UNjM3MF9SRUdf UkdCMl9ESU0JCQkweDE4Mwo+ID4gKyNkZWZpbmUgTVQ2MzcwX1JFR19SR0IzX0RJTQkJCTB4MTg0 Cj4gPiArI2RlZmluZSBNVDYzNzBfUkVHX1JHQl9FTgkJCTB4MTg1Cj4gPiArI2RlZmluZSBNVDYz NzBfUkVHX1JHQjFfSVNOSwkJCTB4MTg2Cj4gPiArI2RlZmluZSBNVDYzNzBfUkVHX1JHQjJfSVNO SwkJCTB4MTg3Cj4gPiArI2RlZmluZSBNVDYzNzBfUkVHX1JHQjNfSVNOSwkJCTB4MTg4Cj4gPiAr I2RlZmluZSBNVDYzNzBfUkVHX1JHQjFfVFIJCQkweDE4OQo+ID4gKyNkZWZpbmUgTVQ2MzcwX1JF R19SR0JfQ0hSSU5EX0RJTQkJMHgxOTIKPiA+ICsjZGVmaW5lIE1UNjM3MF9SRUdfUkdCX0NIUklO RF9DVFJMCQkweDE5Mwo+ID4gKyNkZWZpbmUgTVQ2MzcwX1JFR19SR0JfQ0hSSU5EX1RSCQkweDE5 NAo+ID4gKwo+ID4gKyNkZWZpbmUgTVQ2MzcyX1JFR19SR0JfRU4JCQkweDE4Mgo+ID4gKyNkZWZp bmUgTVQ2MzcyX1JFR19SR0IxX0lTTksJCQkweDE4Mwo+ID4gKyNkZWZpbmUgTVQ2MzcyX1JFR19S R0IyX0lTTksJCQkweDE4NAo+ID4gKyNkZWZpbmUgTVQ2MzcyX1JFR19SR0IzX0lTTksJCQkweDE4 NQo+ID4gKyNkZWZpbmUgTVQ2MzcyX1JFR19SR0I0X0lTTksJCQkweDE4Ngo+ID4gKyNkZWZpbmUg TVQ2MzcyX1JFR19SR0IxX0RJTQkJCTB4MTg3Cj4gPiArI2RlZmluZSBNVDYzNzJfUkVHX1JHQjJf RElNCQkJMHgxODgKPiA+ICsjZGVmaW5lIE1UNjM3Ml9SRUdfUkdCM19ESU0JCQkweDE4OQo+ID4g KyNkZWZpbmUgTVQ2MzcyX1JFR19SR0I0X0RJTQkJCTB4MThBCj4gPiArI2RlZmluZSBNVDYzNzJf UkVHX1JHQjEyX0ZSRVEJCQkweDE4Qgo+ID4gKyNkZWZpbmUgTVQ2MzcyX1JFR19SR0IzNF9GUkVR CQkJMHgxOEMKPiA+ICsjZGVmaW5lIE1UNjM3Ml9SRUdfUkdCMV9UUgkJCTB4MThECj4gPiArCj4g PiArI2RlZmluZSBNVDYzNzBfVkVOSURfTUFTSwkJCUdFTk1BU0soNywgNCkKPiAKPiBWZW5kb3I/ ICBEZWZpbmVzIHNob3VsZCBiZSBzZWxmIGRvY3VtZW50aW5nLgo+IAo+IFdoYXQgZG9lcyB0aGlz IHNhdmUgb3ZlciAiVkVORE9SX0lEIj8KPgpTbyAnTVQ2MzcwX1ZFTkRPUl9JRF9NQVNLJz8gQW5k IHdpbGwgZGVmaW5lIGFsbCB1c2VkIFZFTkRPUl9JRC4KPiA+ICsjZGVmaW5lIE1UNjM3MF9DSEVO X0JJVChpZCkJCQlCSVQoTVQ2MzcwX0xFRF9JU05LNCAtIGlkKQo+ID4gKyNkZWZpbmUgTVQ2Mzcw X1ZJUlRVQUxfTVVMVElDT0xPUgkJNQo+ID4gKyNkZWZpbmUgTUNfQ0hBTk5FTF9OVU0JCQkJMwo+ ID4gKyNkZWZpbmUgTVQ2MzcwX1BXTV9EVVRZCQkJCShCSVQoNSkgLSAxKQo+ID4gKyNkZWZpbmUg TVQ2MzcyX1BXTV9EVVRZCQkJCShCSVQoOCkgLSAxKQo+ID4gKwo+ID4gK3N0cnVjdCBtdDYzNzBf bGVkIHsKPiA+ICsJLyoKPiA+ICsJICogSWYgdGhlIGNvbG9yIG9mIHRoZSBMRUQgaW4gRFQgaXMg c2V0IHRvCj4gPiArCSAqICAgLSAnTEVEX0NPTE9SX0lEX1JHQicKPiA+ICsJICogICAtICdMRURf Q09MT1JfSURfTVVMVEknCj4gPiArCSAqIFRoZSBtZW1iZXIgJ2luZGV4JyBvZiB0aGlzIHN0cnVj dCB3aWxsIGJlIHNldCB0bwo+ID4gKwkgKiAnTVQ2MzcwX1ZJUlRVQUxfTVVMVElDT0xPUicuCj4g PiArCSAqIElmIHNvLCB0aGlzIExFRCB3aWxsIGNob29zZSAnc3RydWN0IGxlZF9jbGFzc2Rldl9t YyBtYycgdG8gdXNlLgo+ID4gKwkgKiBJbnN0ZWFkLCBpZiB0aGUgbWVtYmVyICdpbmRleCcgb2Yg dGhpcyBzdHJ1Y3QgaXMgc2V0IHRvCj4gPiArCSAqICdNVDYzNzBfTEVEX0lTTksxJyB+ICdNVDYz NzBfTEVEX0lTTks0JywgdGhlbiB0aGlzIExFRCB3aWxsIGNob29zZQo+ID4gKwkgKiAnc3RydWN0 IGxlZF9jbGFzc2RldiBpc2luaycgdG8gdXNlLgo+ID4gKwkgKi8KPiA+ICsJdW5pb24gewo+ID4g KwkJc3RydWN0IGxlZF9jbGFzc2RldiBpc2luazsKPiA+ICsJCXN0cnVjdCBsZWRfY2xhc3NkZXZf bWMgbWM7Cj4gPiArCX07Cj4gPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdjsKPiA+ICsJZW51 bSBsZWRfZGVmYXVsdF9zdGF0ZSBkZWZhdWx0X3N0YXRlOwo+ID4gKwl1MzIgaW5kZXg7Cj4gPiAr fTsKPiA+ICsKPiA+ICtzdHJ1Y3QgbXQ2MzcwX3BkYXRhIHsKPiA+ICsJY29uc3QgdW5zaWduZWQg aW50ICp0ZnJlcTsKPiA+ICsJdW5zaWduZWQgaW50IHRmcmVxX2xlbjsKPiA+ICsJdTE2IHJlZ19y Z2IxX3RyOwo+ID4gKwlzMTYgcmVnX3JnYl9jaHJpbmRfdHI7Cj4gPiArCXU4IHB3bV9kdXR5Owo+ ID4gK307Cj4gPiArCj4gPiArc3RydWN0IG10NjM3MF9wcml2IHsKPiA+ICsJLyogUGVyIExFRCBh Y2Nlc3MgbG9jayAqLwo+ID4gKwlzdHJ1Y3QgbXV0ZXggbG9jazsKPiA+ICsJc3RydWN0IHJlZ21h cCAqcmVnbWFwOwo+ID4gKwlzdHJ1Y3QgcmVnbWFwX2ZpZWxkICpmaWVsZHNbRl9NQVhfRklFTERT XTsKPiA+ICsJY29uc3Qgc3RydWN0IHJlZ19maWVsZCAqcmVnX2ZpZWxkczsKPiA+ICsJY29uc3Qg c3RydWN0IGxpbmVhcl9yYW5nZSAqcmFuZ2VzOwo+ID4gKwlzdHJ1Y3QgcmVnX2NmZyAqcmVnX2Nm Z3M7Cj4gPiArCWNvbnN0IHN0cnVjdCBtdDYzNzBfcGRhdGEgKnBkYXRhOwo+ID4gKwl1bnNpZ25l ZCBpbnQgbGVkc19jb3VudDsKPiA+ICsJdW5zaWduZWQgaW50IGxlZHNfYWN0aXZlOwo+ID4gKwlz dHJ1Y3QgbXQ2MzcwX2xlZCBsZWRzW107Cj4gPiArfTsKPiA+ICsKPiA+ICtzdGF0aWMgY29uc3Qg c3RydWN0IHJlZ19maWVsZCBjb21tb25fcmVnX2ZpZWxkc1tGX01BWF9GSUVMRFNdID0gewo+ID4g KwlbRl9SR0JfRU5dCT0gUkVHX0ZJRUxEKE1UNjM3MF9SRUdfUkdCX0VOLCA0LCA3KSwKPiA+ICsJ W0ZfQ0hHSU5EX0VOXQk9IFJFR19GSUVMRChNVDYzNzBfUkVHX1JHQl9DSFJJTkRfRElNLCA3LCA3 KSwKPiA+ICsJW0ZfTEVEMV9DVVJSXQk9IFJFR19GSUVMRChNVDYzNzBfUkVHX1JHQjFfSVNOSywg MCwgMiksCj4gPiArCVtGX0xFRDJfQ1VSUl0JPSBSRUdfRklFTEQoTVQ2MzcwX1JFR19SR0IyX0lT TkssIDAsIDIpLAo+ID4gKwlbRl9MRUQzX0NVUlJdCT0gUkVHX0ZJRUxEKE1UNjM3MF9SRUdfUkdC M19JU05LLCAwLCAyKSwKPiA+ICsJW0ZfTEVENF9DVVJSXQk9IFJFR19GSUVMRChNVDYzNzBfUkVH X1JHQl9DSFJJTkRfQ1RSTCwgMCwgMSksCj4gPiArCVtGX0xFRDFfTU9ERV0JPSBSRUdfRklFTEQo TVQ2MzcwX1JFR19SR0IxX0RJTSwgNSwgNiksCj4gPiArCVtGX0xFRDJfTU9ERV0JPSBSRUdfRklF TEQoTVQ2MzcwX1JFR19SR0IyX0RJTSwgNSwgNiksCj4gPiArCVtGX0xFRDNfTU9ERV0JPSBSRUdf RklFTEQoTVQ2MzcwX1JFR19SR0IzX0RJTSwgNSwgNiksCj4gPiArCVtGX0xFRDRfTU9ERV0JPSBS RUdfRklFTEQoTVQ2MzcwX1JFR19SR0JfQ0hSSU5EX0RJTSwgNSwgNiksCj4gPiArCVtGX0xFRDFf RFVUWV0JPSBSRUdfRklFTEQoTVQ2MzcwX1JFR19SR0IxX0RJTSwgMCwgNCksCj4gPiArCVtGX0xF RDJfRFVUWV0JPSBSRUdfRklFTEQoTVQ2MzcwX1JFR19SR0IyX0RJTSwgMCwgNCksCj4gPiArCVtG X0xFRDNfRFVUWV0JPSBSRUdfRklFTEQoTVQ2MzcwX1JFR19SR0IzX0RJTSwgMCwgNCksCj4gPiAr CVtGX0xFRDRfRFVUWV0JPSBSRUdfRklFTEQoTVQ2MzcwX1JFR19SR0JfQ0hSSU5EX0RJTSwgMCwg NCksCj4gPiArCVtGX0xFRDFfRlJFUV0JPSBSRUdfRklFTEQoTVQ2MzcwX1JFR19SR0IxX0lTTkss IDMsIDUpLAo+ID4gKwlbRl9MRUQyX0ZSRVFdCT0gUkVHX0ZJRUxEKE1UNjM3MF9SRUdfUkdCMl9J U05LLCAzLCA1KSwKPiA+ICsJW0ZfTEVEM19GUkVRXQk9IFJFR19GSUVMRChNVDYzNzBfUkVHX1JH QjNfSVNOSywgMywgNSksCj4gPiArCVtGX0xFRDRfRlJFUV0JPSBSRUdfRklFTEQoTVQ2MzcwX1JF R19SR0JfQ0hSSU5EX0NUUkwsIDIsIDQpLAo+ID4gK307Cj4gPiArCj4gPiArc3RhdGljIGNvbnN0 IHN0cnVjdCByZWdfZmllbGQgbXQ2MzcyX3JlZ19maWVsZHNbRl9NQVhfRklFTERTXSA9IHsKPiA+ ICsJW0ZfUkdCX0VOXQk9IFJFR19GSUVMRChNVDYzNzJfUkVHX1JHQl9FTiwgNCwgNyksCj4gPiAr CVtGX0NIR0lORF9FTl0JPSBSRUdfRklFTEQoTVQ2MzcyX1JFR19SR0JfRU4sIDMsIDMpLAo+ID4g KwlbRl9MRUQxX0NVUlJdCT0gUkVHX0ZJRUxEKE1UNjM3Ml9SRUdfUkdCMV9JU05LLCAwLCAzKSwK PiA+ICsJW0ZfTEVEMl9DVVJSXQk9IFJFR19GSUVMRChNVDYzNzJfUkVHX1JHQjJfSVNOSywgMCwg MyksCj4gPiArCVtGX0xFRDNfQ1VSUl0JPSBSRUdfRklFTEQoTVQ2MzcyX1JFR19SR0IzX0lTTkss IDAsIDMpLAo+ID4gKwlbRl9MRUQ0X0NVUlJdCT0gUkVHX0ZJRUxEKE1UNjM3Ml9SRUdfUkdCNF9J U05LLCAwLCAzKSwKPiA+ICsJW0ZfTEVEMV9NT0RFXQk9IFJFR19GSUVMRChNVDYzNzJfUkVHX1JH QjFfSVNOSywgNiwgNyksCj4gPiArCVtGX0xFRDJfTU9ERV0JPSBSRUdfRklFTEQoTVQ2MzcyX1JF R19SR0IyX0lTTkssIDYsIDcpLAo+ID4gKwlbRl9MRUQzX01PREVdCT0gUkVHX0ZJRUxEKE1UNjM3 Ml9SRUdfUkdCM19JU05LLCA2LCA3KSwKPiA+ICsJW0ZfTEVENF9NT0RFXQk9IFJFR19GSUVMRChN VDYzNzJfUkVHX1JHQjRfSVNOSywgNiwgNyksCj4gPiArCVtGX0xFRDFfRFVUWV0JPSBSRUdfRklF TEQoTVQ2MzcyX1JFR19SR0IxX0RJTSwgMCwgNyksCj4gPiArCVtGX0xFRDJfRFVUWV0JPSBSRUdf RklFTEQoTVQ2MzcyX1JFR19SR0IyX0RJTSwgMCwgNyksCj4gPiArCVtGX0xFRDNfRFVUWV0JPSBS RUdfRklFTEQoTVQ2MzcyX1JFR19SR0IzX0RJTSwgMCwgNyksCj4gPiArCVtGX0xFRDRfRFVUWV0J PSBSRUdfRklFTEQoTVQ2MzcyX1JFR19SR0I0X0RJTSwgMCwgNyksCj4gPiArCVtGX0xFRDFfRlJF UV0JPSBSRUdfRklFTEQoTVQ2MzcyX1JFR19SR0IxMl9GUkVRLCA1LCA3KSwKPiA+ICsJW0ZfTEVE Ml9GUkVRXQk9IFJFR19GSUVMRChNVDYzNzJfUkVHX1JHQjEyX0ZSRVEsIDIsIDQpLAo+ID4gKwlb Rl9MRUQzX0ZSRVFdCT0gUkVHX0ZJRUxEKE1UNjM3Ml9SRUdfUkdCMzRfRlJFUSwgNSwgNyksCj4g PiArCVtGX0xFRDRfRlJFUV0JPSBSRUdfRklFTEQoTVQ2MzcyX1JFR19SR0IzNF9GUkVRLCAyLCA0 KSwKPiA+ICt9Owo+ID4gKwo+ID4gKy8qIEN1cnJlbnQgdW5pdDogbWljcm9hbXAsIHRpbWUgdW5p dDogbWlsbGlzZWNvbmQgKi8KPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGxpbmVhcl9yYW5nZSBj b21tb25fbGVkX3Jhbmdlc1tSX01BWF9SQU5HRVNdID0gewo+ID4gKwlbUl9MRUQxMjNfQ1VSUl0J PSB7IDQwMDAsIDEsIDYsIDQwMDAgfSwKPiA+ICsJW1JfTEVENF9DVVJSXQk9IHsgMjAwMCwgMSwg MywgMjAwMCB9LAo+ID4gKwlbUl9MRURfVFJGT05dCT0geyAxMjUsIDAsIDE1LCAyMDAgfSwKPiA+ ICsJW1JfTEVEX1RPRkZdCT0geyAyNTAsIDAsIDE1LCA0MDAgfSwKPiA+ICt9Owo+ID4gKwo+ID4g K3N0YXRpYyBjb25zdCBzdHJ1Y3QgbGluZWFyX3JhbmdlIG10NjM3Ml9sZWRfcmFuZ2VzW1JfTUFY X1JBTkdFU10gPSB7Cj4gPiArCVtSX0xFRDEyM19DVVJSXQk9IHsgMjAwMCwgMSwgMTQsIDIwMDAg fSwKPiA+ICsJW1JfTEVENF9DVVJSXQk9IHsgMjAwMCwgMSwgMTQsIDIwMDAgfSwKPiA+ICsJW1Jf TEVEX1RSRk9OXQk9IHsgMTI1LCAwLCAxNSwgMjUwIH0sCj4gPiArCVtSX0xFRF9UT0ZGXQk9IHsg MjUwLCAwLCAxNSwgNTAwIH0sCj4gPiArfTsKPiA+ICsKPiA+ICtzdGF0aWMgY29uc3QgdW5zaWdu ZWQgaW50IGNvbW1vbl90ZnJlcXNbXSA9IHsKPiA+ICsJMTAwMDAsIDUwMDAsIDIwMDAsIDEwMDAs IDUwMCwgMjAwLCA1LCAxLAo+ID4gK307Cj4gPiArCj4gPiArc3RhdGljIGNvbnN0IHVuc2lnbmVk IGludCBtdDYzNzJfdGZyZXFzW10gPSB7Cj4gPiArCTgwMDAsIDQwMDAsIDIwMDAsIDEwMDAsIDUw MCwgMjUwLCA4LCA0LAo+ID4gK307Cj4gPiArCj4gPiArc3RhdGljIGNvbnN0IHN0cnVjdCBtdDYz NzBfcGRhdGEgY29tbW9uX3BkYXRhID0gewo+ID4gKwkudGZyZXEgPSBjb21tb25fdGZyZXFzLAo+ ID4gKwkudGZyZXFfbGVuID0gQVJSQVlfU0laRShjb21tb25fdGZyZXFzKSwKPiA+ICsJLnB3bV9k dXR5ID0gTVQ2MzcwX1BXTV9EVVRZLAo+ID4gKwkucmVnX3JnYjFfdHIgPSBNVDYzNzBfUkVHX1JH QjFfVFIsCj4gPiArCS5yZWdfcmdiX2NocmluZF90ciA9IE1UNjM3MF9SRUdfUkdCX0NIUklORF9U UiwKPiA+ICt9Owo+ID4gKwo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgbXQ2MzcwX3BkYXRhIG10 NjM3Ml9wZGF0YSA9IHsKPiA+ICsJLnRmcmVxID0gbXQ2MzcyX3RmcmVxcywKPiA+ICsJLnRmcmVx X2xlbiA9IEFSUkFZX1NJWkUobXQ2MzcyX3RmcmVxcyksCj4gPiArCS5wd21fZHV0eSA9IE1UNjM3 Ml9QV01fRFVUWSwKPiA+ICsJLnJlZ19yZ2IxX3RyID0gTVQ2MzcyX1JFR19SR0IxX1RSLAo+ID4g KwkucmVnX3JnYl9jaHJpbmRfdHIgPSAtMSwKPiA+ICt9Owo+ID4gKwo+ID4gK3N0YXRpYyBlbnVt IG10NjM3MF9sZWRfZmllbGQgbXQ2MzcwX2dldF9sZWRfY3VycmVudF9maWVsZCh1bnNpZ25lZCBp bnQgbGVkX25vKQo+ID4gK3sKPiA+ICsJc3dpdGNoIChsZWRfbm8pIHsKPiA+ICsJY2FzZSBNVDYz NzBfTEVEX0lTTksxOgo+ID4gKwkJcmV0dXJuIEZfTEVEMV9DVVJSOwo+ID4gKwljYXNlIE1UNjM3 MF9MRURfSVNOSzI6Cj4gPiArCQlyZXR1cm4gRl9MRUQyX0NVUlI7Cj4gPiArCWNhc2UgTVQ2Mzcw X0xFRF9JU05LMzoKPiA+ICsJCXJldHVybiBGX0xFRDNfQ1VSUjsKPiA+ICsJZGVmYXVsdDoKPiA+ ICsJCXJldHVybiBGX0xFRDRfQ1VSUjsKPiA+ICsJfQo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMg aW50IG10NjM3MF9zZXRfbGVkX2JyaWdodG5lc3Moc3RydWN0IG10NjM3MF9wcml2ICpwcml2LAo+ ID4gKwkJCQkgICAgIHVuc2lnbmVkIGludCBsZWRfbm8sIHVuc2lnbmVkIGludCBsZXZlbCkKPiA+ ICt7Cj4gPiArCWVudW0gbXQ2MzcwX2xlZF9maWVsZCBzZWxfZmllbGQ7Cj4gPiArCj4gPiArCXNl bF9maWVsZCA9IG10NjM3MF9nZXRfbGVkX2N1cnJlbnRfZmllbGQobGVkX25vKTsKPiA+ICsKPiA+ ICsJcmV0dXJuIHJlZ21hcF9maWVsZF93cml0ZShwcml2LT5maWVsZHNbc2VsX2ZpZWxkXSwgbGV2 ZWwpOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50IG10NjM3MF9nZXRfbGVkX2JyaWdodG5l c3Moc3RydWN0IG10NjM3MF9wcml2ICpwcml2LAo+ID4gKwkJCQkgICAgIHVuc2lnbmVkIGludCBs ZWRfbm8sIHVuc2lnbmVkIGludCAqbGV2ZWwpCj4gPiArewo+ID4gKwllbnVtIG10NjM3MF9sZWRf ZmllbGQgc2VsX2ZpZWxkOwo+ID4gKwo+ID4gKwlzZWxfZmllbGQgPSBtdDYzNzBfZ2V0X2xlZF9j dXJyZW50X2ZpZWxkKGxlZF9ubyk7Cj4gPiArCj4gPiArCXJldHVybiByZWdtYXBfZmllbGRfcmVh ZChwcml2LT5maWVsZHNbc2VsX2ZpZWxkXSwgbGV2ZWwpOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0 aWMgaW50IG10NjM3MF9zZXRfbGVkX2R1dHkoc3RydWN0IG10NjM3MF9wcml2ICpwcml2LCB1bnNp Z25lZCBpbnQgbGVkX25vLAo+ID4gKwkJCSAgICAgICB1bnNpZ25lZCBpbnQgdG9uLCB1bnNpZ25l ZCBpbnQgdG9mZikKPiA+ICt7Cj4gPiArCWNvbnN0IHN0cnVjdCBtdDYzNzBfcGRhdGEgKnBkYXRh ID0gcHJpdi0+cGRhdGE7Cj4gPiArCWVudW0gbXQ2MzcwX2xlZF9maWVsZCBzZWxfZmllbGQ7Cj4g PiArCXVuc2lnbmVkIGludCBkaXZpc29yLCByYXRpbzsKPiA+ICsKPiA+ICsJZGl2aXNvciA9IHBk YXRhLT5wd21fZHV0eTsKPiA+ICsJcmF0aW8gPSB0b24gKiBkaXZpc29yIC8gKHRvbiArIHRvZmYp Owo+ID4gKwo+ID4gKwlzd2l0Y2ggKGxlZF9ubykgewo+ID4gKwljYXNlIE1UNjM3MF9MRURfSVNO SzE6Cj4gPiArCQlzZWxfZmllbGQgPSBGX0xFRDFfRFVUWTsKPiA+ICsJCWJyZWFrOwo+ID4gKwlj YXNlIE1UNjM3MF9MRURfSVNOSzI6Cj4gPiArCQlzZWxfZmllbGQgPSBGX0xFRDJfRFVUWTsKPiA+ ICsJCWJyZWFrOwo+ID4gKwljYXNlIE1UNjM3MF9MRURfSVNOSzM6Cj4gPiArCQlzZWxfZmllbGQg PSBGX0xFRDNfRFVUWTsKPiA+ICsJCWJyZWFrOwo+ID4gKwlkZWZhdWx0Ogo+ID4gKwkJc2VsX2Zp ZWxkID0gRl9MRUQ0X0RVVFk7Cj4gPiArCQlicmVhazsKPiA+ICsJfQo+ID4gKwo+ID4gKwlyZXR1 cm4gcmVnbWFwX2ZpZWxkX3dyaXRlKHByaXYtPmZpZWxkc1tzZWxfZmllbGRdLCByYXRpbyk7Cj4g PiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgbXQ2MzcwX3NldF9sZWRfZnJlcShzdHJ1Y3QgbXQ2 MzcwX3ByaXYgKnByaXYsIHVuc2lnbmVkIGludCBsZWRfbm8sCj4gPiArCQkJICAgICAgIHVuc2ln bmVkIGludCB0b24sIHVuc2lnbmVkIGludCB0b2ZmKQo+ID4gK3sKPiA+ICsJY29uc3Qgc3RydWN0 IG10NjM3MF9wZGF0YSAqcGRhdGEgPSBwcml2LT5wZGF0YTsKPiA+ICsJZW51bSBtdDYzNzBfbGVk X2ZpZWxkIHNlbF9maWVsZDsKPiA+ICsJdW5zaWduZWQgaW50IHRmcmVxX2xlbiA9IHBkYXRhLT50 ZnJlcV9sZW47Cj4gPiArCXVuc2lnbmVkIGludCB0c3VtLCBzZWw7Cj4gPiArCj4gPiArCXRzdW0g PSB0b24gKyB0b2ZmOwo+ID4gKwo+ID4gKwlpZiAodHN1bSA+IHBkYXRhLT50ZnJlcVswXSB8fCB0 c3VtIDwgcGRhdGEtPnRmcmVxW3RmcmVxX2xlbiAtIDFdKQo+ID4gKwkJcmV0dXJuIC1FT1BOT1RT VVBQOwo+ID4gKwo+ID4gKwlzZWwgPSBmaW5kX2Nsb3Nlc3RfZGVzY2VuZGluZyh0c3VtLCBwZGF0 YS0+dGZyZXEsIHRmcmVxX2xlbik7Cj4gPiArCj4gPiArCXN3aXRjaCAobGVkX25vKSB7Cj4gPiAr CWNhc2UgTVQ2MzcwX0xFRF9JU05LMToKPiA+ICsJCXNlbF9maWVsZCA9IEZfTEVEMV9GUkVROwo+ ID4gKwkJYnJlYWs7Cj4gPiArCWNhc2UgTVQ2MzcwX0xFRF9JU05LMjoKPiA+ICsJCXNlbF9maWVs ZCA9IEZfTEVEMl9GUkVROwo+ID4gKwkJYnJlYWs7Cj4gPiArCWNhc2UgTVQ2MzcwX0xFRF9JU05L MzoKPiA+ICsJCXNlbF9maWVsZCA9IEZfTEVEM19GUkVROwo+ID4gKwkJYnJlYWs7Cj4gPiArCWRl ZmF1bHQ6Cj4gPiArCQlzZWxfZmllbGQgPSBGX0xFRDRfRlJFUTsKPiA+ICsJCWJyZWFrOwo+ID4g Kwl9Cj4gPiArCj4gPiArCXJldHVybiByZWdtYXBfZmllbGRfd3JpdGUocHJpdi0+ZmllbGRzW3Nl bF9maWVsZF0sIHNlbCk7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyB2b2lkIG10NjM3MF9nZXRf YnJlYXRoX3JlZ19iYXNlKHN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiwKPiA+ICsJCQkJICAgICAg IHVuc2lnbmVkIGludCBsZWRfbm8sIHVuc2lnbmVkIGludCAqYmFzZSkKPiA+ICt7Cj4gPiArCWNv bnN0IHN0cnVjdCBtdDYzNzBfcGRhdGEgKnBkYXRhID0gcHJpdi0+cGRhdGE7Cj4gPiArCj4gPiAr CWlmIChwZGF0YS0+cmVnX3JnYl9jaHJpbmRfdHIgPCAwKSB7Cj4gPiArCQkqYmFzZSA9IHBkYXRh LT5yZWdfcmdiMV90ciArIGxlZF9ubyAqIDM7Cj4gPiArCQlyZXR1cm47Cj4gPiArCX0KPiA+ICsK PiA+ICsJc3dpdGNoIChsZWRfbm8pIHsKPiA+ICsJY2FzZSBNVDYzNzBfTEVEX0lTTksxOgo+ID4g KwljYXNlIE1UNjM3MF9MRURfSVNOSzI6Cj4gPiArCWNhc2UgTVQ2MzcwX0xFRF9JU05LMzoKPiA+ ICsJCSpiYXNlID0gcGRhdGEtPnJlZ19yZ2IxX3RyICsgbGVkX25vICogMzsKPiA+ICsJCWJyZWFr Owo+ID4gKwlkZWZhdWx0Ogo+ID4gKwkJKmJhc2UgPSBwZGF0YS0+cmVnX3JnYl9jaHJpbmRfdHI7 Cj4gPiArCQlicmVhazsKPiA+ICsJfQo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50IG10NjM3 MF9nZW5fYnJlYXRoX3BhdHRlcm4oc3RydWN0IG10NjM3MF9wcml2ICpwcml2LAo+ID4gKwkJCQkg ICAgIHN0cnVjdCBsZWRfcGF0dGVybiAqcGF0dGVybiwgdTMyIGxlbiwKPiA+ICsJCQkJICAgICB1 OCAqcGF0dGVybl92YWwsIHUzMiB2YWxfbGVuKQo+ID4gK3sKPiA+ICsJZW51bSBtdDYzNzBfbGVk X3JhbmdlcyBzZWxfcmFuZ2U7Cj4gPiArCXN0cnVjdCBsZWRfcGF0dGVybiAqY3VycjsKPiA+ICsJ dW5zaWduZWQgaW50IHNlbDsKPiA+ICsJdTMyIHZhbCA9IDA7Cj4gPiArCWludCBpOwo+ID4gKwo+ ID4gKwlpZiAobGVuIDwgUF9NQVhfUEFUVEVSTlMgJiYgdmFsX2xlbiA8IFBfTUFYX1BBVFRFUk5T IC8gMikKPiA+ICsJCXJldHVybiAtRUlOVkFMOwo+ID4gKwo+ID4gKwkvKgo+ID4gKwkgKiBQYXR0 ZXJuIGxpc3QKPiA+ICsJICogdHIxOgkgYnl0ZSAwLCBiJ1s3OiA0XQo+IAo+IFBlcmhhcHMgdGhp cyBpcyBzdGFuZGFyZCBmb3JtYXR0aW5nIGFuZCBJJ20ganVzdCBub3QgYXdhcmUgb2YgaXQsIGJ1 dAo+IHRoZSBzcGFjZSBpcyB0aHJvd2luZyBtZSBhbmQgbWFraW5nIG1lIHRoaW5rIHR3aWNlLiAg RG9lcyB0aGlzIG1lYW4gYml0cwo+IDcgdGhyb3VnaCA0LCBzbyBiJzExMTEwMDAwPwo+Clllcy4g bGlrZSBhcyB5b3Ugc2FpZC4gU29ycnkgZm9yIHRoZSByZWR1ZGFudCBzcGFjZSBtYWtlIHlvdSBj b25mdXNlZC4KSSdtIG5vdCBzdXJlIHdoZXRoZXIgaXQncyBhIHN0YW5kYXJkIGZvcm1hdGluZyBv ciBub3QuClNvbWV0aW1lcywgaW4gZGF0YXNoZWV0LCB3ZSdsbCB1c2UgdGhpcyBmb3JtYXQgdG8g cmVwcmVzZW50IHRoZSBiaXRmaWVsZCBmb3IgZnVuY3Rpb25zLgpZb3VyIGZvcm1hdCBpcyBhbHNv IGdvb2QgZm9yIGl0LgpBbmQgd2hpY2ggb25lIGlzIHByZWZlcmFibGU/Cj4gPiArCSAqIHRyMjoJ IGJ5dGUgMCwgYidbMzogMF0KPiA+ICsJICogdGYxOgkgYnl0ZSAxLCBiJ1s3OiA0XQo+ID4gKwkg KiB0ZjI6CSBieXRlIDEsIGInWzM6IDBdCj4gPiArCSAqIHRvbjoJIGJ5dGUgMiwgYidbNzogNF0K PiA+ICsJICogdG9mZjogYnl0ZSAyLCBiJ1szOiAwXQo+ID4gKwkgKi8KPiA+ICsJZm9yIChpID0g MDsgaSA8IFBfTUFYX1BBVFRFUk5TOyBpKyspIHsKPiA+ICsJCWN1cnIgPSBwYXR0ZXJuICsgaTsK PiA+ICsKPiA+ICsJCXNlbF9yYW5nZSA9IGkgPT0gUF9MRURfVE9GRiA/IFJfTEVEX1RPRkYgOiBS X0xFRF9UUkZPTjsKPiA+ICsKPiA+ICsJCWxpbmVhcl9yYW5nZV9nZXRfc2VsZWN0b3Jfd2l0aGlu KHByaXYtPnJhbmdlcyArIHNlbF9yYW5nZSwKPiA+ICsJCQkJCQkgY3Vyci0+ZGVsdGFfdCwgJnNl bCk7Cj4gPiArCj4gPiArCQlpZiAoaSAlIDIpIHsKPiA+ICsJCQl2YWwgfD0gc2VsOwo+ID4gKwkJ fSBlbHNlIHsKPiA+ICsJCQl2YWwgPDw9IDg7Cj4gPiArCQkJdmFsIHw9IHNlbCA8PCA0Owo+ID4g KwkJfQo+ID4gKwl9Cj4gPiArCj4gPiArCXB1dF91bmFsaWduZWRfYmUyNCh2YWwsIHBhdHRlcm5f dmFsKTsKPiA+ICsKPiA+ICsJcmV0dXJuIDA7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQg bXQ2MzcwX3NldF9sZWRfbW9kZShzdHJ1Y3QgbXQ2MzcwX3ByaXYgKnByaXYsIHVuc2lnbmVkIGlu dCBsZWRfbm8sCj4gPiArCQkJICAgICAgIGVudW0gbXQ2MzcwX2xlZF9tb2RlIG1vZGUpCj4gPiAr ewo+ID4gKwllbnVtIG10NjM3MF9sZWRfZmllbGQgc2VsX2ZpZWxkOwo+ID4gKwo+ID4gKwlzd2l0 Y2ggKGxlZF9ubykgewo+ID4gKwljYXNlIE1UNjM3MF9MRURfSVNOSzE6Cj4gPiArCQlzZWxfZmll bGQgPSBGX0xFRDFfTU9ERTsKPiA+ICsJCWJyZWFrOwo+ID4gKwljYXNlIE1UNjM3MF9MRURfSVNO SzI6Cj4gPiArCQlzZWxfZmllbGQgPSBGX0xFRDJfTU9ERTsKPiA+ICsJCWJyZWFrOwo+ID4gKwlj YXNlIE1UNjM3MF9MRURfSVNOSzM6Cj4gPiArCQlzZWxfZmllbGQgPSBGX0xFRDNfTU9ERTsKPiA+ ICsJCWJyZWFrOwo+ID4gKwlkZWZhdWx0Ogo+ID4gKwkJc2VsX2ZpZWxkID0gRl9MRUQ0X01PREU7 Cj4gPiArCQlicmVhazsKPiA+ICsJfQo+ID4gKwo+ID4gKwlyZXR1cm4gcmVnbWFwX2ZpZWxkX3dy aXRlKHByaXYtPmZpZWxkc1tzZWxfZmllbGRdLCBtb2RlKTsKPiA+ICt9Cj4gPiArCj4gPiArc3Rh dGljIGludCBtdDYzNzBfbWNfYnJpZ2h0bmVzc19zZXQoc3RydWN0IGxlZF9jbGFzc2RldiAqbGNk ZXYsCj4gPiArCQkJCSAgICBlbnVtIGxlZF9icmlnaHRuZXNzIGxldmVsKQo+ID4gK3sKPiA+ICsJ c3RydWN0IGxlZF9jbGFzc2Rldl9tYyAqbWNjZGV2ID0gbGNkZXZfdG9fbWNjZGV2KGxjZGV2KTsK PiA+ICsJc3RydWN0IG10NjM3MF9sZWQgKmxlZCA9IGNvbnRhaW5lcl9vZihtY2NkZXYsIHN0cnVj dCBtdDYzNzBfbGVkLCBtYyk7Cj4gPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9IGxlZC0+ cHJpdjsKPiA+ICsJc3RydWN0IG1jX3N1YmxlZCAqc3VibGVkOwo+ID4gKwl1bnNpZ25lZCBpbnQg ZW5hYmxlLCBkaXNhYmxlOwo+ID4gKwlpbnQgaSwgcmV0Owo+ID4gKwo+ID4gKwltdXRleF9sb2Nr KCZwcml2LT5sb2NrKTsKPiA+ICsKPiA+ICsJbGVkX21jX2NhbGNfY29sb3JfY29tcG9uZW50cyht Y2NkZXYsIGxldmVsKTsKPiA+ICsKPiA+ICsJcmV0ID0gcmVnbWFwX2ZpZWxkX3JlYWQocHJpdi0+ ZmllbGRzW0ZfUkdCX0VOXSwgJmVuYWJsZSk7Cj4gPiArCWlmIChyZXQpCj4gPiArCQlnb3RvIG91 dF91bmxvY2s7Cj4gPiArCj4gPiArCWRpc2FibGUgPSBlbmFibGU7Cj4gPiArCj4gPiArCWZvciAo aSA9IDA7IGkgPCBtY2NkZXYtPm51bV9jb2xvcnM7IGkrKykgewo+ID4gKwkJdTMyIGJyaWdodG5l c3M7Cj4gPiArCj4gPiArCQlzdWJsZWQgPSBtY2NkZXYtPnN1YmxlZF9pbmZvICsgaTsKPiA+ICsJ CWJyaWdodG5lc3MgPSBtaW4oc3VibGVkLT5icmlnaHRuZXNzLCBsY2Rldi0+bWF4X2JyaWdodG5l c3MpOwo+ID4gKwkJZGlzYWJsZSAmPSB+TVQ2MzcwX0NIRU5fQklUKHN1YmxlZC0+Y2hhbm5lbCk7 Cj4gPiArCj4gPiArCQlpZiAobGV2ZWwgPT0gMCkgewo+ID4gKwkJCWVuYWJsZSAmPSB+TVQ2Mzcw X0NIRU5fQklUKHN1YmxlZC0+Y2hhbm5lbCk7Cj4gPiArCj4gPiArCQkJcmV0ID0gbXQ2MzcwX3Nl dF9sZWRfbW9kZShwcml2LCBzdWJsZWQtPmNoYW5uZWwsCj4gPiArCQkJCQkJICBNVDYzNzBfTEVE X1JFR19NT0RFKTsKPiAKPiBQbGVhc2UgdW5pZnkgeW91ciBsaW5lLXdyYXAgc3RyYXRlZ3kuICBJ biBzb21lIHBsYWNlcyB5b3UgYXJlIHVzaW5nIHRoZQo+IGZ1bGwgMTAwLWNoYXJzIGFsbG93YWJs ZSBhbmQgaW4gbWFueSBvdGhlcnMsIHlvdSBsaW5lLXdyYXAgZWFybHkuICBQbGVhc2UKPiBnbyB0 aHJvdWdoIHRoZSBlbnRpcmUgZmlsZSBhbmQgdW53cmFwIHRvIDEwMC1jaGFycyB3aGVyZSBhcHBy b3ByaWF0ZS4KPiAKPiBZb3UnbGwgc2VlIHdoYXQgSSBtZWFuIGFzIHlvdSByZS1yZWFkIHRoZSBm aWxlIHdpdGggdGhpcyBpbiBtaW5kLgo+IAo+ID4gKwkJCWlmIChyZXQpCj4gPiArCQkJCWdvdG8g b3V0X3VubG9jazsKPiA+ICsKPiA+ICsJCQljb250aW51ZTsKPiA+ICsJCX0KPiA+ICsKPiA+ICsJ CWlmIChicmlnaHRuZXNzID09IDApIHsKPiA+ICsJCQllbmFibGUgJj0gfk1UNjM3MF9DSEVOX0JJ VChzdWJsZWQtPmNoYW5uZWwpOwo+ID4gKwkJCWNvbnRpbnVlOwo+ID4gKwkJfQo+ID4gKwo+ID4g KwkJZW5hYmxlIHw9IE1UNjM3MF9DSEVOX0JJVChzdWJsZWQtPmNoYW5uZWwpOwo+ID4gKwo+ID4g KwkJcmV0ID0gbXQ2MzcwX3NldF9sZWRfYnJpZ2h0bmVzcyhwcml2LCBzdWJsZWQtPmNoYW5uZWws Cj4gPiArCQkJCQkJYnJpZ2h0bmVzcyk7Cj4gPiArCQlpZiAocmV0KQo+ID4gKwkJCWdvdG8gb3V0 X3VubG9jazsKPiA+ICsJfQo+ID4gKwo+ID4gKwlyZXQgPSByZWdtYXBfZmllbGRfd3JpdGUocHJp di0+ZmllbGRzW0ZfUkdCX0VOXSwgZGlzYWJsZSk7Cj4gPiArCWlmIChyZXQpCj4gPiArCQlnb3Rv IG91dF91bmxvY2s7Cj4gPiArCj4gPiArCXJldCA9IHJlZ21hcF9maWVsZF93cml0ZShwcml2LT5m aWVsZHNbRl9SR0JfRU5dLCBlbmFibGUpOwo+ID4gKwo+ID4gK291dF91bmxvY2s6Cj4gPiArCW11 dGV4X3VubG9jaygmcHJpdi0+bG9jayk7Cj4gPiArCj4gPiArCXJldHVybiByZXQ7Cj4gPiArfQo+ ID4gKwo+ID4gK3N0YXRpYyBpbnQgbXQ2MzcwX21jX2JsaW5rX3NldChzdHJ1Y3QgbGVkX2NsYXNz ZGV2ICpsY2RldiwKPiA+ICsJCQkgICAgICAgdW5zaWduZWQgbG9uZyAqZGVsYXlfb24sCj4gPiAr CQkJICAgICAgIHVuc2lnbmVkIGxvbmcgKmRlbGF5X29mZikKPiA+ICt7Cj4gPiArCXN0cnVjdCBs ZWRfY2xhc3NkZXZfbWMgKm1jY2RldiA9IGxjZGV2X3RvX21jY2RldihsY2Rldik7Cj4gPiArCXN0 cnVjdCBtdDYzNzBfbGVkICpsZWQgPSBjb250YWluZXJfb2YobWNjZGV2LCBzdHJ1Y3QgbXQ2Mzcw X2xlZCwgbWMpOwo+ID4gKwlzdHJ1Y3QgbXQ2MzcwX3ByaXYgKnByaXYgPSBsZWQtPnByaXY7Cj4g PiArCXN0cnVjdCBtY19zdWJsZWQgKnN1YmxlZDsKPiA+ICsJdW5zaWduZWQgaW50IGVuYWJsZSwg ZGlzYWJsZTsKPiA+ICsJaW50IGksIHJldDsKPiA+ICsKPiA+ICsJbXV0ZXhfbG9jaygmcHJpdi0+ bG9jayk7Cj4gPiArCj4gPiArCWlmICghKmRlbGF5X29uICYmICEqZGVsYXlfb2ZmKQo+ID4gKwkJ KmRlbGF5X29uID0gKmRlbGF5X29mZiA9IDUwMDsKPiA+ICsKPiA+ICsJcmV0ID0gcmVnbWFwX2Zp ZWxkX3JlYWQocHJpdi0+ZmllbGRzW0ZfUkdCX0VOXSwgJmVuYWJsZSk7Cj4gPiArCWlmIChyZXQp Cj4gPiArCQlnb3RvIG91dF91bmxvY2s7Cj4gPiArCj4gPiArCWRpc2FibGUgPSBlbmFibGU7Cj4g PiArCj4gPiArCWZvciAoaSA9IDA7IGkgPCBtY2NkZXYtPm51bV9jb2xvcnM7IGkrKykgewo+ID4g KwkJc3VibGVkID0gbWNjZGV2LT5zdWJsZWRfaW5mbyArIGk7Cj4gPiArCj4gPiArCQlkaXNhYmxl ICY9IH5NVDYzNzBfQ0hFTl9CSVQoc3VibGVkLT5jaGFubmVsKTsKPiA+ICsKPiA+ICsJCXJldCA9 IG10NjM3MF9zZXRfbGVkX2R1dHkocHJpdiwgc3VibGVkLT5jaGFubmVsLCAqZGVsYXlfb24sCj4g PiArCQkJCQkgICpkZWxheV9vZmYpOwo+ID4gKwkJaWYgKHJldCkKPiA+ICsJCQlnb3RvIG91dF91 bmxvY2s7Cj4gPiArCj4gPiArCQlyZXQgPSBtdDYzNzBfc2V0X2xlZF9mcmVxKHByaXYsIHN1Ymxl ZC0+Y2hhbm5lbCwgKmRlbGF5X29uLAo+ID4gKwkJCQkJICAqZGVsYXlfb2ZmKTsKPiA+ICsJCWlm IChyZXQpCj4gPiArCQkJZ290byBvdXRfdW5sb2NrOwo+ID4gKwo+ID4gKwkJcmV0ID0gbXQ2Mzcw X3NldF9sZWRfbW9kZShwcml2LCBzdWJsZWQtPmNoYW5uZWwsCj4gPiArCQkJCQkgIE1UNjM3MF9M RURfUFdNX01PREUpOwo+ID4gKwkJaWYgKHJldCkKPiA+ICsJCQlnb3RvIG91dF91bmxvY2s7Cj4g PiArCX0KPiA+ICsKPiA+ICsJLyogVG9nZ2xlIHRvIG1ha2UgcGF0dGVybiB0aW1pbmcgdGhlIHNh bWUgKi8KPiA+ICsJcmV0ID0gcmVnbWFwX2ZpZWxkX3dyaXRlKHByaXYtPmZpZWxkc1tGX1JHQl9F Tl0sIGRpc2FibGUpOwo+ID4gKwlpZiAocmV0KQo+ID4gKwkJZ290byBvdXRfdW5sb2NrOwo+ID4g Kwo+ID4gKwlyZXQgPSByZWdtYXBfZmllbGRfd3JpdGUocHJpdi0+ZmllbGRzW0ZfUkdCX0VOXSwg ZW5hYmxlKTsKPiA+ICsKPiA+ICtvdXRfdW5sb2NrOgo+ID4gKwltdXRleF91bmxvY2soJnByaXYt PmxvY2spOwo+ID4gKwo+ID4gKwlyZXR1cm4gcmV0Owo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMg aW50IG10NjM3MF9tY19wYXR0ZXJuX3NldChzdHJ1Y3QgbGVkX2NsYXNzZGV2ICpsY2RldiwKPiA+ ICsJCQlzdHJ1Y3QgbGVkX3BhdHRlcm4gKnBhdHRlcm4sIHUzMiBsZW4sIGludCByZXBlYXQpCj4g PiArewo+ID4gKwlzdHJ1Y3QgbGVkX2NsYXNzZGV2X21jICptY2NkZXYgPSBsY2Rldl90b19tY2Nk ZXYobGNkZXYpOwo+ID4gKwlzdHJ1Y3QgbXQ2MzcwX2xlZCAqbGVkID0gY29udGFpbmVyX29mKG1j Y2Rldiwgc3RydWN0IG10NjM3MF9sZWQsIG1jKTsKPiA+ICsJc3RydWN0IG10NjM3MF9wcml2ICpw cml2ID0gbGVkLT5wcml2Owo+ID4gKwlzdHJ1Y3QgbWNfc3VibGVkICpzdWJsZWQ7Cj4gPiArCXVu c2lnbmVkIGludCByZWdfYmFzZSwgZW5hYmxlLCBkaXNhYmxlOwo+ID4gKwl1OCBwYXJhbXNbUF9N QVhfUEFUVEVSTlMgLyAyXTsKPiA+ICsJaW50IGksIHJldDsKPiA+ICsKPiA+ICsJbXV0ZXhfbG9j aygmcHJpdi0+bG9jayk7Cj4gPiArCj4gPiArCXJldCA9IG10NjM3MF9nZW5fYnJlYXRoX3BhdHRl cm4ocHJpdiwgcGF0dGVybiwgbGVuLCBwYXJhbXMsCj4gPiArCQkJCQlzaXplb2YocGFyYW1zKSk7 Cj4gPiArCWlmIChyZXQpCj4gPiArCQlnb3RvIG91dF91bmxvY2s7Cj4gPiArCj4gPiArCXJldCA9 IHJlZ21hcF9maWVsZF9yZWFkKHByaXYtPmZpZWxkc1tGX1JHQl9FTl0sICZlbmFibGUpOwo+ID4g KwlpZiAocmV0KQo+ID4gKwkJZ290byBvdXRfdW5sb2NrOwo+ID4gKwo+ID4gKwlkaXNhYmxlID0g ZW5hYmxlOwo+ID4gKwo+ID4gKwlmb3IgKGkgPSAwOyBpIDwgbWNjZGV2LT5udW1fY29sb3JzOyBp KyspIHsKPiA+ICsJCXN1YmxlZCA9IG1jY2Rldi0+c3VibGVkX2luZm8gKyBpOwo+ID4gKwo+ID4g KwkJbXQ2MzcwX2dldF9icmVhdGhfcmVnX2Jhc2UocHJpdiwgc3VibGVkLT5jaGFubmVsLCAmcmVn X2Jhc2UpOwo+ID4gKwkJZGlzYWJsZSAmPSB+TVQ2MzcwX0NIRU5fQklUKHN1YmxlZC0+Y2hhbm5l bCk7Cj4gPiArCj4gPiArCQlyZXQgPSByZWdtYXBfcmF3X3dyaXRlKHByaXYtPnJlZ21hcCwgcmVn X2Jhc2UsIHBhcmFtcywKPiA+ICsJCQkJICAgICAgIHNpemVvZihwYXJhbXMpKTsKPiA+ICsJCWlm IChyZXQpCj4gPiArCQkJZ290byBvdXRfdW5sb2NrOwo+ID4gKwo+ID4gKwkJcmV0ID0gbXQ2Mzcw X3NldF9sZWRfbW9kZShwcml2LCBzdWJsZWQtPmNoYW5uZWwsCj4gPiArCQkJCQkgIE1UNjM3MF9M RURfQlJFQVRIX01PREUpOwo+ID4gKwkJaWYgKHJldCkKPiA+ICsJCQlnb3RvIG91dF91bmxvY2s7 Cj4gPiArCX0KPiA+ICsKPiA+ICsJLyogVG9nZ2xlIHRvIG1ha2UgcGF0dGVybiB0aW1pbmcgYmUg dGhlIHNhbWUgKi8KPiA+ICsJcmV0ID0gcmVnbWFwX2ZpZWxkX3dyaXRlKHByaXYtPmZpZWxkc1tG X1JHQl9FTl0sIGRpc2FibGUpOwo+ID4gKwlpZiAocmV0KQo+ID4gKwkJZ290byBvdXRfdW5sb2Nr Owo+ID4gKwo+ID4gKwlyZXQgPSByZWdtYXBfZmllbGRfd3JpdGUocHJpdi0+ZmllbGRzW0ZfUkdC X0VOXSwgZW5hYmxlKTsKPiA+ICsKPiA+ICtvdXRfdW5sb2NrOgo+ID4gKwltdXRleF91bmxvY2so JnByaXYtPmxvY2spOwo+ID4gKwo+ID4gKwlyZXR1cm4gcmV0Owo+ID4gK30KPiA+ICsKPiA+ICtz dGF0aWMgaW5saW5lIGludCBtdDYzNzBfbWNfcGF0dGVybl9jbGVhcihzdHJ1Y3QgbGVkX2NsYXNz ZGV2ICpsY2RldikKPiA+ICt7Cj4gPiArCXN0cnVjdCBsZWRfY2xhc3NkZXZfbWMgKm1jY2RldiA9 IGxjZGV2X3RvX21jY2RldihsY2Rldik7Cj4gPiArCXN0cnVjdCBtdDYzNzBfbGVkICpsZWQgPSBj b250YWluZXJfb2YobWNjZGV2LCBzdHJ1Y3QgbXQ2MzcwX2xlZCwgbWMpOwo+ID4gKwlzdHJ1Y3Qg bXQ2MzcwX3ByaXYgKnByaXYgPSBsZWQtPnByaXY7Cj4gPiArCXN0cnVjdCBtY19zdWJsZWQgKnN1 YmxlZDsKPiA+ICsJaW50IGksIHJldDsKPiA+ICsKPiA+ICsJbXV0ZXhfbG9jaygmbGVkLT5wcml2 LT5sb2NrKTsKPiA+ICsKPiA+ICsJZm9yIChpID0gMDsgaSA8IG1jY2Rldi0+bnVtX2NvbG9yczsg aSsrKSB7Cj4gPiArCQlzdWJsZWQgPSBtY2NkZXYtPnN1YmxlZF9pbmZvICsgaTsKPiA+ICsKPiA+ ICsJCXJldCA9IG10NjM3MF9zZXRfbGVkX21vZGUocHJpdiwgc3VibGVkLT5jaGFubmVsLAo+ID4g KwkJCQkJICBNVDYzNzBfTEVEX1JFR19NT0RFKTsKPiA+ICsJCWlmIChyZXQpCj4gPiArCQkJYnJl YWs7Cj4gPiArCX0KPiA+ICsKPiA+ICsJbXV0ZXhfdW5sb2NrKCZsZWQtPnByaXYtPmxvY2spOwo+ ID4gKwo+ID4gKwlyZXR1cm4gcmV0Owo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50IG10NjM3 MF9pc25rX2JyaWdodG5lc3Nfc2V0KHN0cnVjdCBsZWRfY2xhc3NkZXYgKmxjZGV2LAo+ID4gKwkJ CQkgICAgICBlbnVtIGxlZF9icmlnaHRuZXNzIGxldmVsKQo+ID4gK3sKPiA+ICsJc3RydWN0IG10 NjM3MF9sZWQgKmxlZCA9IGNvbnRhaW5lcl9vZihsY2Rldiwgc3RydWN0IG10NjM3MF9sZWQsIGlz aW5rKTsKPiA+ICsJc3RydWN0IG10NjM3MF9wcml2ICpwcml2ID0gbGVkLT5wcml2Owo+ID4gKwl1 bnNpZ25lZCBpbnQgZW5hYmxlOwo+ID4gKwlpbnQgcmV0Owo+ID4gKwo+ID4gKwltdXRleF9sb2Nr KCZwcml2LT5sb2NrKTsKPiA+ICsKPiA+ICsJcmV0ID0gcmVnbWFwX2ZpZWxkX3JlYWQocHJpdi0+ ZmllbGRzW0ZfUkdCX0VOXSwgJmVuYWJsZSk7Cj4gPiArCWlmIChyZXQpCj4gPiArCQlnb3RvIG91 dF91bmxvY2s7Cj4gPiArCj4gPiArCWlmIChsZXZlbCA9PSAwKSB7Cj4gPiArCQllbmFibGUgJj0g fk1UNjM3MF9DSEVOX0JJVChsZWQtPmluZGV4KTsKPiA+ICsKPiA+ICsJCXJldCA9IG10NjM3MF9z ZXRfbGVkX21vZGUocHJpdiwgbGVkLT5pbmRleCwKPiA+ICsJCQkJCSAgTVQ2MzcwX0xFRF9SRUdf TU9ERSk7Cj4gPiArCQlpZiAocmV0KQo+ID4gKwkJCWdvdG8gb3V0X3VubG9jazsKPiA+ICsJfSBl bHNlIHsKPiA+ICsJCWVuYWJsZSB8PSBNVDYzNzBfQ0hFTl9CSVQobGVkLT5pbmRleCk7Cj4gPiAr Cj4gPiArCQlyZXQgPSBtdDYzNzBfc2V0X2xlZF9icmlnaHRuZXNzKHByaXYsIGxlZC0+aW5kZXgs IGxldmVsKTsKPiA+ICsJCWlmIChyZXQpCj4gPiArCQkJZ290byBvdXRfdW5sb2NrOwo+ID4gKwl9 Cj4gPiArCj4gPiArCXJldCA9IHJlZ21hcF9maWVsZF93cml0ZShwcml2LT5maWVsZHNbRl9SR0Jf RU5dLCBlbmFibGUpOwo+ID4gKwo+ID4gK291dF91bmxvY2s6Cj4gPiArCW11dGV4X3VubG9jaygm cHJpdi0+bG9jayk7Cj4gPiArCj4gPiArCXJldHVybiByZXQ7Cj4gPiArfQo+ID4gKwo+ID4gK3N0 YXRpYyBpbnQgbXQ2MzcwX2lzbmtfYmxpbmtfc2V0KHN0cnVjdCBsZWRfY2xhc3NkZXYgKmxjZGV2 LAo+ID4gKwkJCQkgdW5zaWduZWQgbG9uZyAqZGVsYXlfb24sCj4gPiArCQkJCSB1bnNpZ25lZCBs b25nICpkZWxheV9vZmYpCj4gPiArewo+ID4gKwlzdHJ1Y3QgbXQ2MzcwX2xlZCAqbGVkID0gY29u dGFpbmVyX29mKGxjZGV2LCBzdHJ1Y3QgbXQ2MzcwX2xlZCwgaXNpbmspOwo+ID4gKwlzdHJ1Y3Qg bXQ2MzcwX3ByaXYgKnByaXYgPSBsZWQtPnByaXY7Cj4gPiArCWludCByZXQ7Cj4gPiArCj4gPiAr CW11dGV4X2xvY2soJnByaXYtPmxvY2spOwo+ID4gKwo+ID4gKwlpZiAoISpkZWxheV9vbiAmJiAh KmRlbGF5X29mZikKPiA+ICsJCSpkZWxheV9vbiA9ICpkZWxheV9vZmYgPSA1MDA7Cj4gPiArCj4g PiArCXJldCA9IG10NjM3MF9zZXRfbGVkX2R1dHkocHJpdiwgbGVkLT5pbmRleCwgKmRlbGF5X29u LCAqZGVsYXlfb2ZmKTsKPiA+ICsJaWYgKHJldCkKPiA+ICsJCWdvdG8gb3V0X3VubG9jazsKPiA+ ICsKPiA+ICsJcmV0ID0gbXQ2MzcwX3NldF9sZWRfZnJlcShwcml2LCBsZWQtPmluZGV4LCAqZGVs YXlfb24sICpkZWxheV9vZmYpOwo+ID4gKwlpZiAocmV0KQo+ID4gKwkJZ290byBvdXRfdW5sb2Nr Owo+ID4gKwo+ID4gKwlyZXQgPSBtdDYzNzBfc2V0X2xlZF9tb2RlKHByaXYsIGxlZC0+aW5kZXgs IE1UNjM3MF9MRURfUFdNX01PREUpOwo+ID4gKwo+ID4gK291dF91bmxvY2s6Cj4gPiArCW11dGV4 X3VubG9jaygmcHJpdi0+bG9jayk7Cj4gPiArCj4gPiArCXJldHVybiByZXQ7Cj4gPiArfQo+ID4g Kwo+ID4gK3N0YXRpYyBpbnQgbXQ2MzcwX2lzbmtfcGF0dGVybl9zZXQoc3RydWN0IGxlZF9jbGFz c2RldiAqbGNkZXYsCj4gPiArCQkJCSAgIHN0cnVjdCBsZWRfcGF0dGVybiAqcGF0dGVybiwgdTMy IGxlbiwKPiA+ICsJCQkJICAgaW50IHJlcGVhdCkKPiA+ICt7Cj4gPiArCXN0cnVjdCBtdDYzNzBf bGVkICpsZWQgPSBjb250YWluZXJfb2YobGNkZXYsIHN0cnVjdCBtdDYzNzBfbGVkLCBpc2luayk7 Cj4gPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9IGxlZC0+cHJpdjsKPiA+ICsJdW5zaWdu ZWQgaW50IHJlZ19iYXNlOwo+ID4gKwl1OCBwYXJhbXNbUF9NQVhfUEFUVEVSTlMgLyAyXTsKPiA+ ICsJaW50IHJldDsKPiA+ICsKPiA+ICsJbXV0ZXhfbG9jaygmcHJpdi0+bG9jayk7Cj4gPiArCj4g PiArCXJldCA9IG10NjM3MF9nZW5fYnJlYXRoX3BhdHRlcm4ocHJpdiwgcGF0dGVybiwgbGVuLCBw YXJhbXMsCj4gPiArCQkJCQlzaXplb2YocGFyYW1zKSk7Cj4gPiArCWlmIChyZXQpCj4gPiArCQln b3RvIG91dF91bmxvY2s7Cj4gPiArCj4gPiArCW10NjM3MF9nZXRfYnJlYXRoX3JlZ19iYXNlKHBy aXYsIGxlZC0+aW5kZXgsICZyZWdfYmFzZSk7Cj4gPiArCj4gPiArCXJldCA9IHJlZ21hcF9yYXdf d3JpdGUocHJpdi0+cmVnbWFwLCByZWdfYmFzZSwgcGFyYW1zLCBzaXplb2YocGFyYW1zKSk7Cj4g PiArCWlmIChyZXQpCj4gPiArCQlnb3RvIG91dF91bmxvY2s7Cj4gPiArCj4gPiArCXJldCA9IG10 NjM3MF9zZXRfbGVkX21vZGUocHJpdiwgbGVkLT5pbmRleCwgTVQ2MzcwX0xFRF9CUkVBVEhfTU9E RSk7Cj4gPiArCj4gPiArb3V0X3VubG9jazoKPiA+ICsJbXV0ZXhfdW5sb2NrKCZwcml2LT5sb2Nr KTsKPiA+ICsKPiA+ICsJcmV0dXJuIHJldDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGlubGlu ZSBpbnQgbXQ2MzcwX2lzbmtfcGF0dGVybl9jbGVhcihzdHJ1Y3QgbGVkX2NsYXNzZGV2ICpsY2Rl dikKPiA+ICt7Cj4gPiArCXN0cnVjdCBtdDYzNzBfbGVkICpsZWQgPSBjb250YWluZXJfb2YobGNk ZXYsIHN0cnVjdCBtdDYzNzBfbGVkLCBpc2luayk7Cj4gPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAq cHJpdiA9IGxlZC0+cHJpdjsKPiA+ICsJaW50IHJldDsKPiA+ICsKPiA+ICsJbXV0ZXhfbG9jaygm bGVkLT5wcml2LT5sb2NrKTsKPiA+ICsJcmV0ID0gbXQ2MzcwX3NldF9sZWRfbW9kZShwcml2LCBs ZWQtPmluZGV4LCBNVDYzNzBfTEVEX1JFR19NT0RFKTsKPiA+ICsJbXV0ZXhfdW5sb2NrKCZsZWQt PnByaXYtPmxvY2spOwo+ID4gKwo+ID4gKwlyZXR1cm4gcmV0Owo+ID4gK30KPiA+ICsKPiA+ICtz dGF0aWMgaW50IG10NjM3MF9pbml0X2xlZF9wcm9wZXJ0aWVzKHN0cnVjdCBkZXZpY2UgKmRldiwK PiA+ICsJCQkJICAgICAgc3RydWN0IG10NjM3MF9sZWQgKmxlZCwKPiA+ICsJCQkJICAgICAgc3Ry dWN0IGxlZF9pbml0X2RhdGEgKmluaXRfZGF0YSkKPiA+ICt7Cj4gPiArCXN0cnVjdCBtdDYzNzBf cHJpdiAqcHJpdiA9IGxlZC0+cHJpdjsKPiA+ICsJc3RydWN0IGxlZF9jbGFzc2RldiAqbGNkZXY7 Cj4gPiArCXN0cnVjdCBmd25vZGVfaGFuZGxlICpjaGlsZDsKPiA+ICsJZW51bSBtdDYzNzBfbGVk X3JhbmdlcyBzZWxfcmFuZ2U7Cj4gPiArCXUzMiBtYXhfdUEsIG1heF9sZXZlbDsKPiA+ICsJaW50 IHJldDsKPiA+ICsKPiA+ICsJaWYgKGxlZC0+aW5kZXggPT0gTVQ2MzcwX1ZJUlRVQUxfTVVMVElD T0xPUikgewo+IAo+IFJhdGhlciB0aGFuIGhhdmluZyB0aGVzZSBodWdlIGlmLWVsc2Ugc3RhdGVt ZW50cywgcGxlYXNlIGNvbnNpZGVyIHVzaW5nCj4gYSBzdWItZnVuY3Rpb24uCj4gCkknbGwgcmV3 cml0ZSB0aGlzIGFzIGEgc3ViIGZ1bmN0aW9uICdtdDYzNzBfYXNzaWduX211bHRpY29sb3JfaW5m bycuCnN0YXJ0Li4uCj4gPiArCQlzdHJ1Y3QgbWNfc3VibGVkICpzdWJfbGVkOwo+ID4gKwkJdTMy IG51bV9jb2xvciA9IDA7Cj4gPiArCj4gPiArCQlzdWJfbGVkID0gZGV2bV9rY2FsbG9jKGRldiwg TUNfQ0hBTk5FTF9OVU0sIHNpemVvZigqc3ViX2xlZCksCj4gPiArCQkJCSAgICAgICBHRlBfS0VS TkVMKTsKPiA+ICsJCWlmICghc3ViX2xlZCkKPiA+ICsJCQlyZXR1cm4gLUVOT01FTTsKPiA+ICsK PiA+ICsJCWZ3bm9kZV9mb3JfZWFjaF9jaGlsZF9ub2RlKGluaXRfZGF0YS0+Zndub2RlLCBjaGls ZCkgewo+ID4gKwkJCXUzMiByZWcsIGNvbG9yOwo+ID4gKwo+ID4gKwkJCXJldCA9IGZ3bm9kZV9w cm9wZXJ0eV9yZWFkX3UzMihjaGlsZCwgInJlZyIsICZyZWcpOwo+ID4gKwkJCWlmIChyZXQgfHwg cmVnID4gTVQ2MzcwX0xFRF9JU05LMyB8fAo+ID4gKwkJCSAgICBwcml2LT5sZWRzX2FjdGl2ZSAm IEJJVChyZWcpKSB7Cj4gPiArCQkJCWZ3bm9kZV9oYW5kbGVfcHV0KGNoaWxkKTsKPiA+ICsJCQkJ cmV0dXJuIC1FSU5WQUw7Cj4gPiArCQkJfQo+ID4gKwo+ID4gKwkJCXJldCA9IGZ3bm9kZV9wcm9w ZXJ0eV9yZWFkX3UzMihjaGlsZCwgImNvbG9yIiwgJmNvbG9yKTsKPiA+ICsJCQlpZiAocmV0KSB7 Cj4gPiArCQkJCWZ3bm9kZV9oYW5kbGVfcHV0KGNoaWxkKTsKPiA+ICsJCQkJcmV0dXJuIGRldl9l cnJfcHJvYmUoZGV2LCByZXQsICJMRUQgJWQsIG5vIGNvbG9yIHNwZWNpZmllZFxuIiwKPiA+ICsJ CQkJCQkgICAgIGxlZC0+aW5kZXgpOwo+ID4gKwkJCX0KPiA+ICsKPiA+ICsJCQlwcml2LT5sZWRz X2FjdGl2ZSB8PSBCSVQocmVnKTsKPiA+ICsJCQlzdWJfbGVkW251bV9jb2xvcl0uY29sb3JfaW5k ZXggPSBjb2xvcjsKPiA+ICsJCQlzdWJfbGVkW251bV9jb2xvcl0uY2hhbm5lbCA9IHJlZzsKPiA+ ICsJCQlzdWJfbGVkW251bV9jb2xvcl0uaW50ZW5zaXR5ID0gMDsKPiA+ICsJCQludW1fY29sb3Ir KzsKPiA+ICsJCX0KPiA+ICsKPiA+ICsJCWlmIChudW1fY29sb3IgPCAyKQo+ID4gKwkJCXJldHVy biBkZXZfZXJyX3Byb2JlKGRldiwgLUVJTlZBTCwKPiA+ICsJCQkJCSAgICAgIk11bHRpY29sb3Ig bXVzdCBpbmNsdWRlIDIgb3IgbW9yZSBMRUQgY2hhbm5lbHNcbiIpOwo+ID4gKwo+ID4gKwkJbGVk LT5tYy5udW1fY29sb3JzID0gbnVtX2NvbG9yOwo+ID4gKwkJbGVkLT5tYy5zdWJsZWRfaW5mbyA9 IHN1Yl9sZWQ7Cj4gPiArCi4uLmVuZAo+ID4gKwkJbGNkZXYgPSAmbGVkLT5tYy5sZWRfY2RldjsK PiA+ICsJCWxjZGV2LT5icmlnaHRuZXNzX3NldF9ibG9ja2luZyA9IG10NjM3MF9tY19icmlnaHRu ZXNzX3NldDsKPiA+ICsJCWxjZGV2LT5ibGlua19zZXQgPSBtdDYzNzBfbWNfYmxpbmtfc2V0Owo+ ID4gKwkJbGNkZXYtPnBhdHRlcm5fc2V0ID0gbXQ2MzcwX21jX3BhdHRlcm5fc2V0Owo+ID4gKwkJ bGNkZXYtPnBhdHRlcm5fY2xlYXIgPSBtdDYzNzBfbWNfcGF0dGVybl9jbGVhcjsKPiA+ICsJfSBl bHNlIHsKPiA+ICsJCWxjZGV2ID0gJmxlZC0+aXNpbms7Cj4gPiArCQlsY2Rldi0+YnJpZ2h0bmVz c19zZXRfYmxvY2tpbmcgPSBtdDYzNzBfaXNua19icmlnaHRuZXNzX3NldDsKPiA+ICsJCWxjZGV2 LT5ibGlua19zZXQgPSBtdDYzNzBfaXNua19ibGlua19zZXQ7Cj4gPiArCQlsY2Rldi0+cGF0dGVy bl9zZXQgPSBtdDYzNzBfaXNua19wYXR0ZXJuX3NldDsKPiA+ICsJCWxjZGV2LT5wYXR0ZXJuX2Ns ZWFyID0gbXQ2MzcwX2lzbmtfcGF0dGVybl9jbGVhcjsKPiA+ICsJfQo+ID4gKwo+ID4gKwlyZXQg PSBmd25vZGVfcHJvcGVydHlfcmVhZF91MzIoaW5pdF9kYXRhLT5md25vZGUsICJsZWQtbWF4LW1p Y3JvYW1wIiwKPiA+ICsJCQkJICAgICAgICZtYXhfdUEpOwo+ID4gKwlpZiAocmV0KSB7Cj4gPiAr CQlkZXZfd2FybihkZXYsICJOb3Qgc3BlY2lmaWVkIGxlZC1tYXgtbWljcm9hbXAsIGNvbmZpZyB0 byB0aGUgbWluaW11bVxuIik7Cj4gPiArCQltYXhfdUEgPSAwOwo+ID4gKwl9Cj4gPiArCj4gPiAr CWlmIChsZWQtPmluZGV4ID09IE1UNjM3MF9MRURfSVNOSzQpCj4gPiArCQlzZWxfcmFuZ2UgPSBS X0xFRDRfQ1VSUjsKPiA+ICsJZWxzZQo+ID4gKwkJc2VsX3JhbmdlID0gUl9MRUQxMjNfQ1VSUjsK PiA+ICsKPiA+ICsJbGluZWFyX3JhbmdlX2dldF9zZWxlY3Rvcl93aXRoaW4ocHJpdi0+cmFuZ2Vz ICsgc2VsX3JhbmdlLCBtYXhfdUEsCj4gPiArCQkJCQkgJm1heF9sZXZlbCk7Cj4gPiArCj4gPiAr CWxjZGV2LT5tYXhfYnJpZ2h0bmVzcyA9IG1heF9sZXZlbDsKPiA+ICsKPiA+ICsJbGVkLT5kZWZh dWx0X3N0YXRlID0gbGVkX2luaXRfZGVmYXVsdF9zdGF0ZV9nZXQoaW5pdF9kYXRhLT5md25vZGUp Owo+ID4gKwo+ID4gKwlyZXR1cm4gMDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGludCBtdDYz NzBfaXNua19pbml0X2RlZmF1bHRfc3RhdGUoc3RydWN0IG10NjM3MF9sZWQgKmxlZCkKPiA+ICt7 Cj4gPiArCXN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdiA9IGxlZC0+cHJpdjsKPiA+ICsJdW5zaWdu ZWQgaW50IGVuYWJsZSwgbGV2ZWw7Cj4gPiArCWludCByZXQ7Cj4gPiArCj4gPiArCXJldCA9IG10 NjM3MF9nZXRfbGVkX2JyaWdodG5lc3MocHJpdiwgbGVkLT5pbmRleCwgJmxldmVsKTsKPiA+ICsJ aWYgKHJldCkKPiA+ICsJCXJldHVybiByZXQ7Cj4gPiArCj4gPiArCXJldCA9IHJlZ21hcF9maWVs ZF9yZWFkKHByaXYtPmZpZWxkc1tGX1JHQl9FTl0sICZlbmFibGUpOwo+ID4gKwlpZiAocmV0KQo+ ID4gKwkJcmV0dXJuIHJldDsKPiA+ICsKPiA+ICsJaWYgKCEoZW5hYmxlICYgTVQ2MzcwX0NIRU5f QklUKGxlZC0+aW5kZXgpKSkKPiA+ICsJCWxldmVsID0gMDsKPiA+ICsKPiA+ICsJc3dpdGNoIChs ZWQtPmRlZmF1bHRfc3RhdGUpIHsKPiA+ICsJY2FzZSBMRURTX0RFRlNUQVRFX09OOgo+ID4gKwkJ bGVkLT5pc2luay5icmlnaHRuZXNzID0gbGVkLT5pc2luay5tYXhfYnJpZ2h0bmVzczsKPiA+ICsJ CWJyZWFrOwo+ID4gKwljYXNlIExFRFNfREVGU1RBVEVfS0VFUDoKPiA+ICsJCWxlZC0+aXNpbmsu YnJpZ2h0bmVzcyA9IG1pbihsZXZlbCwgbGVkLT5pc2luay5tYXhfYnJpZ2h0bmVzcyk7Cj4gPiAr CQlicmVhazsKPiA+ICsJZGVmYXVsdDoKPiA+ICsJCWxlZC0+aXNpbmsuYnJpZ2h0bmVzcyA9IDA7 Cj4gPiArCQlicmVhazsKPiA+ICsJfQo+ID4gKwo+ID4gKwlyZXR1cm4gbXQ2MzcwX2lzbmtfYnJp Z2h0bmVzc19zZXQoJmxlZC0+aXNpbmssIGxlZC0+aXNpbmsuYnJpZ2h0bmVzcyk7Cj4gPiArfQo+ ID4gKwo+ID4gK3N0YXRpYyBpbnQgbXQ2MzcwX2xlZF9yZWdpc3RlcihzdHJ1Y3QgZGV2aWNlICpk ZXYsIHN0cnVjdCBtdDYzNzBfbGVkICpsZWQsCj4gPiArCQkJICAgICAgIHN0cnVjdCBsZWRfaW5p dF9kYXRhICppbml0X2RhdGEpCj4gPiArewo+ID4gKwlzdHJ1Y3QgbXQ2MzcwX3ByaXYgKnByaXYg PSBsZWQtPnByaXY7Cj4gPiArCWludCByZXQ7Cj4gPiArCj4gPiArCWlmIChsZWQtPmluZGV4ID09 IE1UNjM3MF9WSVJUVUFMX01VTFRJQ09MT1IpIHsKPiAKPiBUaGlzIHRvbyBjb3VsZCBiZSBzcGxp dCBpbnRvIHNlcGFyYXRlIGZ1bmN0aW9ucyB0byB0aWR5IHRoaW5ncyB1cCBhCj4gbGl0dGxlLgo+ Ckxpa2UgYXMgYmVsb3c/CgppZiAobGVkLT5pbmRleCA9PSBNVDYzNzBfVklSVFVBTF9NVUxUSUNP TE9SKQogICByZXR1cm4gbXQ2MzcwX211bHRpY29sb3JfbGVkX3JlZ2lzdGVyKC4uLi4pCgppZiAo bGVkLT5pbmRleCA9PSBNVDYzNzBfTEVEX0lTTks0KSB7CiAgICAuLi4uLgp9CgpyZXQgPSBtdDYz NzBfaW5pdF9pc25rX2RlZmF1bHRfc3RhdGUoLi4uKQoKU2luY2UgdGhlIG11bHRpbG9yIGNhc2Ug ZGlyZWN0bHkgcmV0dXJuIGZyb20gdGhlIHN1Yi1mdW5jdGlvbiwgZWxzZSBjYW4gYmUgcmVtb3Zl ZC4KPiA+ICsJCXJldCA9IG10NjM3MF9tY19icmlnaHRuZXNzX3NldCgmbGVkLT5tYy5sZWRfY2Rl diwgMCk7Cj4gPiArCQlpZiAocmV0KQo+ID4gKwkJCXJldHVybiBkZXZfZXJyX3Byb2JlKGRldiwg cmV0LCAiQ291bGRuJ3Qgc2V0IG11bHRpY29sb3IgYnJpZ2h0bmVzc1xuIik7Cj4gPiArCj4gPiAr CQlyZXQgPSBkZXZtX2xlZF9jbGFzc2Rldl9tdWx0aWNvbG9yX3JlZ2lzdGVyX2V4dChkZXYsICZs ZWQtPm1jLAo+ID4gKwkJCQkJCQkJaW5pdF9kYXRhKTsKPiA+ICsJCWlmIChyZXQpCj4gPiArCQkJ cmV0dXJuIGRldl9lcnJfcHJvYmUoZGV2LCByZXQsICJDb3VsZG4ndCByZWdpc3RlciBtdWx0aWNv bG9yXG4iKTsKPiA+ICsJfSBlbHNlIHsKPiA+ICsJCWlmIChsZWQtPmluZGV4ID09IE1UNjM3MF9M RURfSVNOSzQpIHsKPiA+ICsJCQlyZXQgPSByZWdtYXBfZmllbGRfd3JpdGUocHJpdi0+ZmllbGRz W0ZfQ0hHSU5EX0VOXSwgMSk7Cj4gPiArCQkJaWYgKHJldCkKPiA+ICsJCQkJcmV0dXJuIGRldl9l cnJfcHJvYmUoZGV2LCByZXQsICJGYWlsZWQgdG8gc2V0IENIUklORCB0byBTV1xuIik7Cj4gPiAr CQl9Cj4gPiArCj4gPiArCQlyZXQgPSBtdDYzNzBfaXNua19pbml0X2RlZmF1bHRfc3RhdGUobGVk KTsKPiA+ICsJCWlmIChyZXQpCj4gPiArCQkJcmV0dXJuIGRldl9lcnJfcHJvYmUoZGV2LCByZXQs ICJGYWlsZWQgdG8gaW5pdCAlZCBpc25rIHN0YXRlXG4iLAo+ID4gKwkJCQkJICAgICBsZWQtPmlu ZGV4KTsKPiA+ICsKPiA+ICsJCXJldCA9IGRldm1fbGVkX2NsYXNzZGV2X3JlZ2lzdGVyX2V4dChk ZXYsICZsZWQtPmlzaW5rLAo+ID4gKwkJCQkJCSAgICAgaW5pdF9kYXRhKTsKPiA+ICsJCWlmIChy ZXQpCj4gPiArCQkJcmV0dXJuIGRldl9lcnJfcHJvYmUoZGV2LCByZXQsICJDb3VsZG4ndCByZWdp c3RlciBpc2luayAlZFxuIiwgbGVkLT5pbmRleCk7Cj4gPiArCX0KPiA+ICsKPiA+ICsJcmV0dXJu IDA7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgbXQ2MzcwX2NoZWNrX3ZlbmRvcl9pbmZv KHN0cnVjdCBtdDYzNzBfcHJpdiAqcHJpdikKPiA+ICt7Cj4gPiArCXVuc2lnbmVkIGludCBkZXZp bmZvLCB2aWQ7Cj4gPiArCWludCByZXQ7Cj4gPiArCj4gPiArCXJldCA9IHJlZ21hcF9yZWFkKHBy aXYtPnJlZ21hcCwgTVQ2MzcwX1JFR19ERVZfSU5GTywgJmRldmluZm8pOwo+ID4gKwlpZiAocmV0 KQo+ID4gKwkJcmV0dXJuIHJldDsKPiA+ICsKPiA+ICsJdmlkID0gRklFTERfR0VUKE1UNjM3MF9W RU5JRF9NQVNLLCBkZXZpbmZvKTsKPiA+ICsJaWYgKHZpZCA9PSAweDkgfHwgdmlkID09IDB4Yikg ewo+IAo+IEFyZSB0aGVyZSBuaWNlIGh1bWFuIHJlYWRhYmxlIGFzc29jaWF0ZXMgb2YgdGhlc2Ug KHZlbmRvcj8pIElEUz8KPgpGb3IgY2xlYXJseSB1bmRlcnN0YW5kaW5nLCBJJ2xsIGRlZmluZSB0 aGVzZSB0d28gYXMgJ01UNjM3Ml9WRU5ET1JfSUQnIGFuZCAnTVQ2MzcyQ19WRU5ET1JfSUQnLgog Cj4gPiArCQlwcml2LT5yZWdfZmllbGRzID0gbXQ2MzcyX3JlZ19maWVsZHM7Cj4gPiArCQlwcml2 LT5yYW5nZXMgPSBtdDYzNzJfbGVkX3JhbmdlczsKPiA+ICsJCXByaXYtPnBkYXRhID0gJm10NjM3 Ml9wZGF0YTsKPiA+ICsJfSBlbHNlIHsKPiA+ICsJCS8qIENvbW1vbiBmb3IgTVQ2MzcwLzcxICov Cj4gPiArCQlwcml2LT5yZWdfZmllbGRzID0gY29tbW9uX3JlZ19maWVsZHM7Cj4gPiArCQlwcml2 LT5yYW5nZXMgPSBjb21tb25fbGVkX3JhbmdlczsKPiA+ICsJCXByaXYtPnBkYXRhID0gJmNvbW1v bl9wZGF0YTsKPiA+ICsJfQo+ID4gKwo+ID4gKwlyZXR1cm4gMDsKPiA+ICt9Cj4gPiArCj4gPiAr c3RhdGljIGludCBtdDYzNzBfbGVkc19wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2 KQo+ID4gK3sKPiA+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gJnBkZXYtPmRldjsKPiA+ICsJc3Ry dWN0IG10NjM3MF9wcml2ICpwcml2Owo+ID4gKwlzdHJ1Y3QgZndub2RlX2hhbmRsZSAqY2hpbGQ7 Cj4gPiArCXNpemVfdCBjb3VudDsKPiA+ICsJdW5zaWduZWQgaW50IGkgPSAwOwo+ID4gKwlpbnQg cmV0Owo+ID4gKwo+ID4gKwljb3VudCA9IGRldmljZV9nZXRfY2hpbGRfbm9kZV9jb3VudChkZXYp Owo+ID4gKwlpZiAoIWNvdW50IHx8IGNvdW50ID4gTVQ2MzcwX01BWF9MRURTKQo+ID4gKwkJcmV0 dXJuIGRldl9lcnJfcHJvYmUoZGV2LCAtRUlOVkFMLAo+ID4gKwkJCQkgICAgICJObyBjaGlsZCBu b2RlIG9yIG5vZGUgY291bnQgb3ZlciBtYXggTEVEIG51bWJlciAlenVcbiIsCj4gPiArCQkJCSAg ICAgIGNvdW50KTsKPiA+ICsKPiA+ICsJcHJpdiA9IGRldm1fa3phbGxvYyhkZXYsIHN0cnVjdF9z aXplKHByaXYsIGxlZHMsIGNvdW50KSwgR0ZQX0tFUk5FTCk7Cj4gPiArCWlmICghcHJpdikKPiA+ ICsJCXJldHVybiAtRU5PTUVNOwo+ID4gKwo+ID4gKwlwcml2LT5sZWRzX2NvdW50ID0gY291bnQ7 Cj4gPiArCW11dGV4X2luaXQoJnByaXYtPmxvY2spOwo+ID4gKwo+ID4gKwlwcml2LT5yZWdtYXAg PSBkZXZfZ2V0X3JlZ21hcChkZXYtPnBhcmVudCwgTlVMTCk7Cj4gPiArCWlmICghcHJpdi0+cmVn bWFwKQo+ID4gKwkJcmV0dXJuIGRldl9lcnJfcHJvYmUoZGV2LCAtRU5PREVWLCAiRmFpbGVkIHRv IGdldCBwYXJlbnQgcmVnbWFwXG4iKTsKPiA+ICsKPiA+ICsJcmV0ID0gbXQ2MzcwX2NoZWNrX3Zl bmRvcl9pbmZvKHByaXYpOwo+ID4gKwlpZiAocmV0KQo+ID4gKwkJcmV0dXJuIGRldl9lcnJfcHJv YmUoZGV2LCByZXQsICJGYWlsZWQgdG8gY2hlY2sgdmVuZG9yIGluZm9cbiIpOwo+ID4gKwo+ID4g KwlyZXQgPSBkZXZtX3JlZ21hcF9maWVsZF9idWxrX2FsbG9jKGRldiwgcHJpdi0+cmVnbWFwLCBw cml2LT5maWVsZHMsCj4gPiArCQkJCQkgICBwcml2LT5yZWdfZmllbGRzLCBGX01BWF9GSUVMRFMp Owo+ID4gKwlpZiAocmV0KQo+ID4gKwkJcmV0dXJuIGRldl9lcnJfcHJvYmUoZGV2LCByZXQsICJG YWlsZWQgdG8gYWxsb2NhdGUgcmVnbWFwIGZpZWxkXG4iKTsKPiA+ICsKPiA+ICsJZGV2aWNlX2Zv cl9lYWNoX2NoaWxkX25vZGUoZGV2LCBjaGlsZCkgewo+ID4gKwkJc3RydWN0IG10NjM3MF9sZWQg KmxlZCA9IHByaXYtPmxlZHMgKyBpKys7Cj4gPiArCQlzdHJ1Y3QgbGVkX2luaXRfZGF0YSBpbml0 X2RhdGEgPSB7IC5md25vZGUgPSBjaGlsZCB9Owo+ID4gKwkJdTMyIHJlZywgY29sb3I7Cj4gPiAr Cj4gPiArCQlyZXQgPSBmd25vZGVfcHJvcGVydHlfcmVhZF91MzIoY2hpbGQsICJyZWciLCAmcmVn KTsKPiA+ICsJCWlmIChyZXQpIHsKPiA+ICsJCQlmd25vZGVfaGFuZGxlX3B1dChjaGlsZCk7Cj4g PiArCQkJcmV0dXJuIGRldl9lcnJfcHJvYmUoZGV2LCByZXQsICJGYWlsZWQgdG8gcGFyc2UgcmVn IHByb3BlcnR5XG4iKTsKPiA+ICsJCX0KPiA+ICsKPiA+ICsJCWlmIChyZWcgPj0gTVQ2MzcwX01B WF9MRURTKSB7Cj4gPiArCQkJZndub2RlX2hhbmRsZV9wdXQoY2hpbGQpOwo+ID4gKwkJCXJldHVy biBkZXZfZXJyX3Byb2JlKGRldiwgLUVJTlZBTCwgIkVycm9yIHJlZyBwcm9wZXJ0eSBudW1iZXJc biIpOwo+ID4gKwkJfQo+ID4gKwo+ID4gKwkJcmV0ID0gZndub2RlX3Byb3BlcnR5X3JlYWRfdTMy KGNoaWxkLCAiY29sb3IiLCAmY29sb3IpOwo+ID4gKwkJaWYgKHJldCkgewo+ID4gKwkJCWZ3bm9k ZV9oYW5kbGVfcHV0KGNoaWxkKTsKPiA+ICsJCQlyZXR1cm4gZGV2X2Vycl9wcm9iZShkZXYsIHJl dCwgIkZhaWxlZCB0byBwYXJzZSBjb2xvciBwcm9wZXJ0eVxuIik7Cj4gPiArCQl9Cj4gPiArCj4g PiArCQlpZiAoY29sb3IgPT0gTEVEX0NPTE9SX0lEX1JHQiB8fCBjb2xvciA9PSBMRURfQ09MT1Jf SURfTVVMVEkpCj4gPiArCQkJcmVnID0gTVQ2MzcwX1ZJUlRVQUxfTVVMVElDT0xPUjsKPiA+ICsK PiA+ICsJCWlmIChwcml2LT5sZWRzX2FjdGl2ZSAmIEJJVChyZWcpKSB7Cj4gPiArCQkJZndub2Rl X2hhbmRsZV9wdXQoY2hpbGQpOwo+ID4gKwkJCXJldHVybiBkZXZfZXJyX3Byb2JlKGRldiwgLUVJ TlZBTCwgIkR1cGxpY2F0ZSByZWcgcHJvcGVydHlcbiIpOwo+ID4gKwkJfQo+ID4gKwo+ID4gKwkJ cHJpdi0+bGVkc19hY3RpdmUgfD0gQklUKHJlZyk7Cj4gPiArCj4gPiArCQlsZWQtPmluZGV4ID0g cmVnOwo+ID4gKwkJbGVkLT5wcml2ID0gcHJpdjsKPiA+ICsKPiA+ICsJCXJldCA9IG10NjM3MF9p bml0X2xlZF9wcm9wZXJ0aWVzKGRldiwgbGVkLCAmaW5pdF9kYXRhKTsKPiA+ICsJCWlmIChyZXQp IHsKPiA+ICsJCQlmd25vZGVfaGFuZGxlX3B1dChjaGlsZCk7Cj4gCj4gSSBjb3VudCA2IGNhbGxz IHRvIGZ3bm9kZV9oYW5kbGVfcHV0KCkgaGVyZS4KPiAKPiBQbGVhc2UgdXNlIGEgZ290byB0byBk aXZlcnQgdGhlIGVycm9yIGhhbmRsaW5nIHRvIHRoZSBib3R0b20gb2YgdGhlCj4gZnVuY3Rpb24g d2hlcmUgeW91IGNhbGwgZndub2RlX2hhbmRsZV9wdXQoKSBqdXN0IG9uY2UuCj4gCj4gPiArCQkJ cmV0dXJuIHJldDsKPiA+ICsJCX0KPiA+ICsKPiA+ICsJCXJldCA9IG10NjM3MF9sZWRfcmVnaXN0 ZXIoZGV2LCBsZWQsICZpbml0X2RhdGEpOwo+ID4gKwkJaWYgKHJldCkgewo+ID4gKwkJCWZ3bm9k ZV9oYW5kbGVfcHV0KGNoaWxkKTsKPiA+ICsJCQlyZXR1cm4gcmV0Owo+ID4gKwkJfQo+ID4gKwl9 Cj4gPiArCj4gPiArCXJldHVybiAwOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgY29uc3Qgc3Ry dWN0IG9mX2RldmljZV9pZCBtdDYzNzBfcmdibGVkX2RldmljZV90YWJsZVtdID0gewo+ID4gKwl7 IC5jb21wYXRpYmxlID0gIm1lZGlhdGVrLG10NjM3MC1pbmRpY2F0b3IiIH0sCj4gPiArCXt9Cj4g PiArfTsKPiA+ICtNT0RVTEVfREVWSUNFX1RBQkxFKG9mLCBtdDYzNzBfcmdibGVkX2RldmljZV90 YWJsZSk7Cj4gPiArCj4gPiArc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgbXQ2MzcwX3Jn YmxlZF9kcml2ZXIgPSB7Cj4gPiArCS5kcml2ZXIgPSB7Cj4gPiArCQkubmFtZSA9ICJtdDYzNzAt aW5kaWNhdG9yIiwKPiA+ICsJCS5vZl9tYXRjaF90YWJsZSA9IG10NjM3MF9yZ2JsZWRfZGV2aWNl X3RhYmxlLAo+ID4gKwl9LAo+ID4gKwkucHJvYmUgPSBtdDYzNzBfbGVkc19wcm9iZSwKPiA+ICt9 Owo+ID4gK21vZHVsZV9wbGF0Zm9ybV9kcml2ZXIobXQ2MzcwX3JnYmxlZF9kcml2ZXIpOwo+ID4g Kwo+ID4gK01PRFVMRV9BVVRIT1IoIkFsaWNlIENoZW4gPGFsaWNlX2NoZW5AcmljaHRlay5jb20+ Iik7Cj4gPiArTU9EVUxFX0FVVEhPUigiQ2hpWXVhbiBIdWFuZyA8Y3lfaHVhbmdAcmljaHRlay5j b20+Iik7Cj4gPiArTU9EVUxFX0RFU0NSSVBUSU9OKCJNZWRpYVRlayBNVDYzNzAgUkdCIExFRCBE cml2ZXIiKTsKPiA+ICtNT0RVTEVfTElDRU5TRSgiR1BMIik7Cj4gPiAtLSAKPiA+IDIuNy40Cj4g PiAKPiAKPiAtLSAKPiBMZWUgSm9uZXMgW+adjueQvOaWr10KCl9fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fCmxpbnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0 CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFkZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFk ZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4LWFybS1rZXJuZWwK