From mboxrd@z Thu Jan 1 00:00:00 1970 From: Hao Zhang Subject: Re: [PATCH v3 6/6] ARM: PWM: add allwinner sun8i R40/T3/V40 PWM support. Date: Tue, 12 Mar 2019 13:42:57 +0800 Message-ID: References: <20181125162319.GA5422@arx-s1> <20181220175750.GG9408@ulmo> Reply-To: hao5781286-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Return-path: Sender: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org In-Reply-To: <20181220175750.GG9408@ulmo> List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , To: Thierry Reding Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, Mark Rutland , Maxime Ripard , Chen-Yu Tsai , Michael Turquette , sboyd-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, linux-gpio-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, open list , "open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS" , "moderated list:ARM/Allwinner sunXi SoC support" , linux-pwm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-sunxi-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org List-Id: linux-gpio@vger.kernel.org Thierry Reding =E4=BA=8E2018=E5=B9=B412=E6=9C=88= 21=E6=97=A5=E5=91=A8=E4=BA=94 =E4=B8=8A=E5=8D=881:57=E5=86=99=E9=81=93=EF= =BC=9A > > On Mon, Nov 26, 2018 at 12:23:19AM +0800, Hao Zhang wrote: > > The sun8i R40/T3/V40 PWM has 8 PWM channals and divides to 4 PWM pairs, > > each PWM pair built-in 1 clock module, 2 timer logic module and 1 > > programmable dead-time generator, it also support waveform capture. > > It has 2 clock sources OSC24M and APB1, it is different with the > > sun4i-pwm driver, Therefore add a new driver for it. > > > > Signed-off-by: Hao Zhang > > --- > > drivers/pwm/Kconfig | 12 +- > > drivers/pwm/Makefile | 1 + > > drivers/pwm/pwm-sun8i.c | 418 ++++++++++++++++++++++++++++++++++++++++= ++++++++ > > 3 files changed, 430 insertions(+), 1 deletion(-) > > create mode 100644 drivers/pwm/pwm-sun8i.c > > > > diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig > > index 504d252..6105ac8 100644 > > --- a/drivers/pwm/Kconfig > > +++ b/drivers/pwm/Kconfig > > @@ -426,7 +426,7 @@ config PWM_STMPE > > expanders. > > > > config PWM_SUN4I > > - tristate "Allwinner PWM support" > > + tristate "Allwinner SUN4I PWM support" > > depends on ARCH_SUNXI || COMPILE_TEST > > depends on HAS_IOMEM && COMMON_CLK > > help > > @@ -435,6 +435,16 @@ config PWM_SUN4I > > To compile this driver as a module, choose M here: the module > > will be called pwm-sun4i. > > > > +config PWM_SUN8I > > + tristate "Allwinner SUN8I (R40/V40/T3) PWM support" > > + depends on ARCH_SUNXI || COMPILE_TEST > > + depends on HAS_IOMEM && COMMON_CLK > > + help > > + Generic PWM framework driver for Allwinner R40/V40/T3 SoCs. > > + > > + To compile this driver as a module, choose M here: the module > > + will be called pwm-sun8i. > > + > > config PWM_TEGRA > > tristate "NVIDIA Tegra PWM support" > > depends on ARCH_TEGRA > > diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile > > index 9c676a0..32c8d2d 100644 > > --- a/drivers/pwm/Makefile > > +++ b/drivers/pwm/Makefile > > @@ -43,6 +43,7 @@ obj-$(CONFIG_PWM_STM32) +=3D pwm-stm32.o > > obj-$(CONFIG_PWM_STM32_LP) +=3D pwm-stm32-lp.o > > obj-$(CONFIG_PWM_STMPE) +=3D pwm-stmpe.o > > obj-$(CONFIG_PWM_SUN4I) +=3D pwm-sun4i.o > > +obj-$(CONFIG_PWM_SUN8I) +=3D pwm-sun8i.o > > obj-$(CONFIG_PWM_TEGRA) +=3D pwm-tegra.o > > obj-$(CONFIG_PWM_TIECAP) +=3D pwm-tiecap.o > > obj-$(CONFIG_PWM_TIEHRPWM) +=3D pwm-tiehrpwm.o > > diff --git a/drivers/pwm/pwm-sun8i.c b/drivers/pwm/pwm-sun8i.c > > new file mode 100644 > > index 0000000..d8597e4 > > --- /dev/null > > +++ b/drivers/pwm/pwm-sun8i.c > > @@ -0,0 +1,418 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +// Copyright (C) 2018 Hao Zhang > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define PWM_IRQ_ENABLE_REG 0x0000 > > +#define PCIE(ch) BIT(ch) > > + > > +#define PWM_IRQ_STATUS_REG 0x0004 > > +#define PIS(ch) BIT(ch) > > + > > +#define CAPTURE_IRQ_ENABLE_REG 0x0010 > > +#define CRIE(ch) BIT((ch) * 2) > > +#define CFIE(ch) BIT((ch) * 2 + 1) > > + > > +#define CAPTURE_IRQ_STATUS_REG 0x0014 > > +#define CRIS(ch) BIT((ch) * 2) > > +#define CFIS(ch) BIT((ch) * 2 + 1) > > + > > +#define CLK_CFG_REG(ch) (0x0020 + ((ch) >> 1) * 4) > > +#define CLK_SRC_SEL GENMASK(8, 7) > > +#define CLK_SRC_BYPASS_SEC BIT(6) > > +#define CLK_SRC_BYPASS_FIR BIT(5) > > +#define CLK_GATING BIT(4) > > +#define CLK_DIV_M GENMASK(3, 0) > > + > > +#define PWM_DZ_CTR_REG(ch) (0x0030 + ((ch) >> 1) * 4) > > +#define PWM_DZ_INTV GENMASK(15, 8) > > +#define PWM_DZ_EN BIT(0) > > + > > +#define PWM_ENABLE_REG 0x0040 > > +#define PWM_EN(ch) BIT(ch) > > + > > +#define CAPTURE_ENABLE_REG 0x0044 > > +#define CAP_EN(ch) BIT(ch) > > + > > +#define PWM_CTR_REG(ch) (0x0060 + (ch) * 0x20) > > +#define PWM_PERIOD_RDY BIT(11) > > +#define PWM_PUL_START BIT(10) > > +#define PWM_MODE BIT(9) > > +#define PWM_ACT_STA BIT(8) > > +#define PWM_PRESCAL_K GENMASK(7, 0) > > + > > +#define PWM_PERIOD_REG(ch) (0x0064 + (ch) * 0x20) > > +#define PWM_ENTIRE_CYCLE GENMASK(31, 16) > > +#define PWM_ACT_CYCLE GENMASK(15, 0) > > + > > +#define PWM_CNT_REG(ch) (0x0068 + (ch) * 0x20) > > +#define PWM_CNT_VAL GENMASK(15, 0) > > + > > +#define CAPTURE_CTR_REG(ch) (0x006c + (ch) * 0x20) > > +#define CAPTURE_CRLF BIT(2) > > +#define CAPTURE_CFLF BIT(1) > > +#define CAPINV BIT(0) > > + > > +#define CAPTURE_RISE_REG(ch) (0x0070 + (ch) * 0x20) > > +#define CAPTURE_CRLR GENMASK(15, 0) > > + > > +#define CAPTURE_FALL_REG(ch) (0x0074 + (ch) * 0x20) > > +#define CAPTURE_CFLR GENMASK(15, 0) > > + > > +struct sun8i_pwm_chip { > > + struct pwm_chip chip; > > + struct clk *clk; > > + void __iomem *base; > > + const struct sun8i_pwm_data *data; > > + struct regmap *regmap; > > +}; > > + > > +static struct sun8i_pwm_chip *to_sun8i_pwm_chip(struct pwm_chip *chip) > > +{ > > + return container_of(chip, struct sun8i_pwm_chip, chip); > > +} > > + > > +static u32 sun8i_pwm_read(struct sun8i_pwm_chip *sun8i_pwm, > > + unsigned long offset) > > +{ > > + u32 val; > > + > > + regmap_read(sun8i_pwm->regmap, offset, &val); > > + return val; > > +} > > + > > +static void sun8i_pwm_set_bit(struct sun8i_pwm_chip *sun8i_pwm, > > + unsigned long reg, u32 bit) > > +{ > > + regmap_update_bits(sun8i_pwm->regmap, reg, bit, bit); > > +} > > + > > +static void sun8i_pwm_clear_bit(struct sun8i_pwm_chip *sun8i_pwm, > > + unsigned long reg, u32 bit) > > +{ > > + regmap_update_bits(sun8i_pwm->regmap, reg, bit, 0); > > +} > > + > > +static void sun8i_pwm_set_value(struct sun8i_pwm_chip *sun8i_pwm, > > + unsigned long reg, u32 mask, u32 val) > > +{ > > + regmap_update_bits(sun8i_pwm->regmap, reg, mask, val); > > +} > > + > > +static void sun8i_pwm_set_polarity(struct sun8i_pwm_chip *chip, u32 ch= , > > + enum pwm_polarity polarity) > > +{ > > + if (polarity =3D=3D PWM_POLARITY_NORMAL) > > + sun8i_pwm_set_bit(chip, PWM_CTR_REG(ch), PWM_ACT_STA); > > + else > > + sun8i_pwm_clear_bit(chip, PWM_CTR_REG(ch), PWM_ACT_STA); > > +} > > + > > +static int sun8i_pwm_config(struct sun8i_pwm_chip *sun8i_pwm, u8 ch, > > + struct pwm_state *state) > > +{ > > + u64 clk_rate, clk_div, val; > > + u16 prescaler =3D 0; > > + u16 div_id =3D 0; > > + struct clk *clk; > > + bool is_clk; > > + int ret; > > + > > + clk_rate =3D clk_get_rate(sun8i_pwm->clk); > > + > > + /* check period and select clock source */ > > + val =3D state->period * clk_rate; > > + do_div(val, NSEC_PER_SEC); > > + is_clk =3D devm_clk_name_match(sun8i_pwm->clk, "mux-0"); > > + if (val <=3D 1 && is_clk) { > > + clk =3D devm_clk_get(sun8i_pwm->chip.dev, "mux-1"); > > + if (IS_ERR(clk)) { > > + dev_err(sun8i_pwm->chip.dev, > > + "Period expects a larger value\n"); > > + return -EINVAL; > > + } > > You should never try to get resources at this point. You should have > requested them already at ->probe() time. Otherwise, how are you going > to handle failures here? > Something wrong here, i will fix it, thanks :) > > + > > + clk_rate =3D clk_get_rate(clk); > > + val =3D state->period * clk_rate; > > + do_div(val, NSEC_PER_SEC); > > + if (val <=3D 1) { > > + dev_err(sun8i_pwm->chip.dev, > > + "Period expects a larger value\n"); > > + return -EINVAL; > > + } > > + > > + /* change clock source to "mux-1" */ > > + clk_disable_unprepare(sun8i_pwm->clk); > > + devm_clk_put(sun8i_pwm->chip.dev, sun8i_pwm->clk); > > + sun8i_pwm->clk =3D clk; > > + > > + ret =3D clk_prepare_enable(sun8i_pwm->clk); > > + if (ret) { > > + dev_err(sun8i_pwm->chip.dev, > > + "Failed to enable PWM clock\n"); > > + return ret; > > + } > > + > > + } else { > > + dev_err(sun8i_pwm->chip.dev, > > + "Period expects a larger value\n"); > > + return -EINVAL; > > + } > > + > > + is_clk =3D devm_clk_name_match(sun8i_pwm->clk, "mux-0"); > > + if (is_clk) > > + sun8i_pwm_set_value(sun8i_pwm, CLK_CFG_REG(ch), > > + CLK_SRC_SEL, 0 << 7); > > + else > > + sun8i_pwm_set_value(sun8i_pwm, CLK_CFG_REG(ch), > > + CLK_SRC_SEL, 1 << 7); > > + > > + dev_info(sun8i_pwm->chip.dev, "clock source freq:%lldHz\n", clk_r= ate); > > + > > + /* calculate and set prescaler, div table, PWM entire cycle */ > > + clk_div =3D val; > > + while (clk_div > 65535) { > > + prescaler++; > > + clk_div =3D val; > > + do_div(clk_div, 1U << div_id); > > + do_div(clk_div, prescaler + 1); > > + > > + if (prescaler =3D=3D 255) { > > + prescaler =3D 0; > > + div_id++; > > + if (div_id =3D=3D 9) { > > + dev_err(sun8i_pwm->chip.dev, > > + "unsupport period value\n"); > > + return -EINVAL; > > + } > > + } > > + } > > + > > + sun8i_pwm_set_value(sun8i_pwm, PWM_PERIOD_REG(ch), > > + PWM_ENTIRE_CYCLE, clk_div << 16); > > + sun8i_pwm_set_value(sun8i_pwm, PWM_CTR_REG(ch), > > + PWM_PRESCAL_K, prescaler << 0); > > + sun8i_pwm_set_value(sun8i_pwm, CLK_CFG_REG(ch), > > + CLK_DIV_M, div_id << 0); > > + > > + /* set duty cycle */ > > + val =3D state->period; > > + do_div(val, clk_div); > > + clk_div =3D state->duty_cycle; > > + do_div(clk_div, val); > > + if (clk_div > 65535) > > + clk_div =3D 65535; > > + > > + sun8i_pwm_set_value(sun8i_pwm, PWM_PERIOD_REG(ch), > > + PWM_ACT_CYCLE, clk_div << 0); > > + > > + return 0; > > +} > > + > > +static int sun8i_pwm_apply(struct pwm_chip *chip, struct pwm_device *p= wm, > > + struct pwm_state *state) > > +{ > > + int ret; > > + struct sun8i_pwm_chip *sun8i_pwm =3D to_sun8i_pwm_chip(chip); > > + struct pwm_state cstate; > > + > > + pwm_get_state(pwm, &cstate); > > + if (!cstate.enabled) { > > + ret =3D clk_prepare_enable(sun8i_pwm->clk); > > + if (ret) { > > + dev_err(chip->dev, "Failed to enable PWM clock\n"= ); > > + return ret; > > + } > > + } > > + > > + if ((cstate.period !=3D state->period) || > > + (cstate.duty_cycle !=3D state->duty_cycle)) { > > + ret =3D sun8i_pwm_config(sun8i_pwm, pwm->hwpwm, state); > > + if (ret) { > > + dev_err(chip->dev, "Failed to config PWM\n"); > > + return ret; > > + } > > + } > > So this isn't really how atomic is supposed to work. The whole point of > the single callback is to allow the driver to apply the changes in an > atomic way, which means that either everything is applied or nothing is > applied. > > That's not what you do here. In the above you can end up with an enabled > clock but the settings not being applied. Similarly sun8i_pwm_config() > can abort in a number of places, which would leave you with a half- > configured PWM channel. > > Instead, what you should be doing is precompute everything and check > that the configuration can be applied before touching any registers or > enabling clocks. Once you've validate the new state, you need to write > everything and there should be no more risk of failure. > Got it, it is useful for me ! > Thierry > -----BEGIN PGP SIGNATURE----- > > iQIzBAABCAAdFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAlwb2B4ACgkQ3SOs138+ > s6GmgRAAwvTyhaFa0jWmUftz+0FS5JTXADm9VusyhbSlmHV7UNkqkQuLnaT1WoGi > gGW5ZMLA+wSPWrXqGsw1HuzLc57c1/eDQdxLmlqBz0Lwribn75+0kisEvV3CRCEL > P9UiTgMualhTe0DGKZmcHJvV56sEhx7b2WQ81sOn5nZvCP/iFTURp5WSyk+phAyb > ss9i5bjwuxC34wLC0wCVNvr2XlpdD7CTy0R/nap1Za2nf6Cm0TnzGGPIYki1/gM2 > fUtYT/zCvfGp+JG5+R2755XdomXzj0vmXD7Omv75eKzMb+HivolmLPJEfUiP8c+x > SElT/F/jIkwvdBzyeQ/sA8ybh4N0DVapnUxBjrUBLOMlrNDlh+ApjUOOpwylQBXQ > 6JKmjoHoBg31lK9QEPxoIoNP0FdZBr6+lAaZeQNx95PeICxD21IvPtuLEp4ksbX7 > fJsOxbkBzbIMpKuxLM3vkl89/O9IhPbVoyvMASCPMmdwAIH+LSy3SvIFWbGQ0nXS > gwjTzN4r1AWmdXIN+faT6khnNY64WoPd896AyJSQ5mQsl42IMKRi42kpfeN3/f8y > x4d07WSTCRB4v+OehJEVP2WJNsbI3EvtClbngn66xSac7kGSbg4cpbW0NzkrFj+T > dOG2p9wUMibPBXzS+V7JzTsDgR9JG2fzxG8PhEesaG/Bt32Hg0Y=3D > =3DS1Wz > -----END PGP SIGNATURE----- --=20 You received this message because you are subscribed to the Google Groups "= linux-sunxi" group. To unsubscribe from this group and stop receiving emails from it, send an e= mail to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit https://groups.google.com/d/optout. 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 X-Spam-Level: X-Spam-Status: No, score=-4.0 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_PASS,UNWANTED_LANGUAGE_BODY autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3CEDCC43381 for ; Tue, 12 Mar 2019 05:43:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E92B62084F for ; Tue, 12 Mar 2019 05:43:13 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gW2oFbFJ" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727161AbfCLFnN (ORCPT ); Tue, 12 Mar 2019 01:43:13 -0400 Received: from mail-wr1-f68.google.com ([209.85.221.68]:44945 "EHLO mail-wr1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726545AbfCLFnM (ORCPT ); Tue, 12 Mar 2019 01:43:12 -0400 Received: by mail-wr1-f68.google.com with SMTP id w2so1203273wrt.11; Mon, 11 Mar 2019 22:43:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=DCFWrKMkPSlIxd7n635HoPYKiNDnEatlKvCsU2Ma/vo=; b=gW2oFbFJiXv6vuFijUvsp/yKB63LRlwtrZNse9xVVgXS6K3xRD9EtaxY85q9BJwcDi 19tht/DzSRC/h2j/YpoaF+Ygeyu2tW7dwgqkyazpN7Z6FhHPuuSiJrkyUB2gmRXcijOb F1+u5eSOThzmlrXW/ZKWIE9aJ2mutvuFAVr+tTSDFTm+vzMS/fMF9HM+EyZJyqhOU9+1 E4yKWTRl+LE8295Fv02J6/WHHBbBWenQKrG6kG2vZEtG+bB7OEXwP9Qznv16oYRtz+nZ J/kVuDrWKpAKVH9LwWEXH/04lCW74+KqDAiQ1gtYQDEVy3sL/CUaMFOyALXyxQXNEBYZ Tzkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=DCFWrKMkPSlIxd7n635HoPYKiNDnEatlKvCsU2Ma/vo=; b=i2XAd61GDWqNZbFxFIPbLYH7OUbu4xpcH9YHZA71A5t6ABhifi9MuaWjn48wAUjimy MU7W9b5e22pUYuuhxfOE+4d7LUI1ucev0r+zdXghpQsJpTYTZfpWpovpoqqkkua10wSL 1wa98a7Zs83XB76PCBgYYj2/eyZYFsk6dhMhuWiu07Ak828pIdzLcq63L+miVJ7oEF/L t2JlzOOo0DxFSAhzDivK9auD1c96ncpSrPLwueVRhWM016h0+KFP/hCJKxLTAUXNpHbE gKPUJInys840cVX2tTQw0hoknhjZ3CRVxwBcIBDtiFMXCnQ5AsqNy/3etsUYTvO1hwFO 4eqg== X-Gm-Message-State: APjAAAXxsccSLEBxeenWWHB/Wqhh6yhPYkdD/xVUlkHLNsYNIyHljDH/ NFlArW0ZeulmAhDCYYQaqGDvjzM1O47vxuuRMdg= X-Google-Smtp-Source: APXvYqxaAnODKnkR7pMW4waqvVLw/V1KAEoesB1t2uFmIx1Z5MgQ8jkd6sS7iD3QSiJ1s9wOTMWxMovzrPVEhDPeWPM= X-Received: by 2002:adf:e4c9:: with SMTP id v9mr9437633wrm.209.1552369389065; Mon, 11 Mar 2019 22:43:09 -0700 (PDT) MIME-Version: 1.0 References: <20181125162319.GA5422@arx-s1> <20181220175750.GG9408@ulmo> In-Reply-To: <20181220175750.GG9408@ulmo> From: Hao Zhang Date: Tue, 12 Mar 2019 13:42:57 +0800 Message-ID: Subject: Re: [PATCH v3 6/6] ARM: PWM: add allwinner sun8i R40/T3/V40 PWM support. To: Thierry Reding Cc: robh+dt@kernel.org, Mark Rutland , Maxime Ripard , Chen-Yu Tsai , Michael Turquette , sboyd@kernel.org, linux-gpio@vger.kernel.org, open list , "open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS" , "moderated list:ARM/Allwinner sunXi SoC support" , linux-pwm@vger.kernel.org, linux-sunxi@googlegroups.com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Thierry Reding =E4=BA=8E2018=E5=B9=B412=E6=9C=88= 21=E6=97=A5=E5=91=A8=E4=BA=94 =E4=B8=8A=E5=8D=881:57=E5=86=99=E9=81=93=EF= =BC=9A > > On Mon, Nov 26, 2018 at 12:23:19AM +0800, Hao Zhang wrote: > > The sun8i R40/T3/V40 PWM has 8 PWM channals and divides to 4 PWM pairs, > > each PWM pair built-in 1 clock module, 2 timer logic module and 1 > > programmable dead-time generator, it also support waveform capture. > > It has 2 clock sources OSC24M and APB1, it is different with the > > sun4i-pwm driver, Therefore add a new driver for it. > > > > Signed-off-by: Hao Zhang > > --- > > drivers/pwm/Kconfig | 12 +- > > drivers/pwm/Makefile | 1 + > > drivers/pwm/pwm-sun8i.c | 418 ++++++++++++++++++++++++++++++++++++++++= ++++++++ > > 3 files changed, 430 insertions(+), 1 deletion(-) > > create mode 100644 drivers/pwm/pwm-sun8i.c > > > > diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig > > index 504d252..6105ac8 100644 > > --- a/drivers/pwm/Kconfig > > +++ b/drivers/pwm/Kconfig > > @@ -426,7 +426,7 @@ config PWM_STMPE > > expanders. > > > > config PWM_SUN4I > > - tristate "Allwinner PWM support" > > + tristate "Allwinner SUN4I PWM support" > > depends on ARCH_SUNXI || COMPILE_TEST > > depends on HAS_IOMEM && COMMON_CLK > > help > > @@ -435,6 +435,16 @@ config PWM_SUN4I > > To compile this driver as a module, choose M here: the module > > will be called pwm-sun4i. > > > > +config PWM_SUN8I > > + tristate "Allwinner SUN8I (R40/V40/T3) PWM support" > > + depends on ARCH_SUNXI || COMPILE_TEST > > + depends on HAS_IOMEM && COMMON_CLK > > + help > > + Generic PWM framework driver for Allwinner R40/V40/T3 SoCs. > > + > > + To compile this driver as a module, choose M here: the module > > + will be called pwm-sun8i. > > + > > config PWM_TEGRA > > tristate "NVIDIA Tegra PWM support" > > depends on ARCH_TEGRA > > diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile > > index 9c676a0..32c8d2d 100644 > > --- a/drivers/pwm/Makefile > > +++ b/drivers/pwm/Makefile > > @@ -43,6 +43,7 @@ obj-$(CONFIG_PWM_STM32) +=3D pwm-stm32.o > > obj-$(CONFIG_PWM_STM32_LP) +=3D pwm-stm32-lp.o > > obj-$(CONFIG_PWM_STMPE) +=3D pwm-stmpe.o > > obj-$(CONFIG_PWM_SUN4I) +=3D pwm-sun4i.o > > +obj-$(CONFIG_PWM_SUN8I) +=3D pwm-sun8i.o > > obj-$(CONFIG_PWM_TEGRA) +=3D pwm-tegra.o > > obj-$(CONFIG_PWM_TIECAP) +=3D pwm-tiecap.o > > obj-$(CONFIG_PWM_TIEHRPWM) +=3D pwm-tiehrpwm.o > > diff --git a/drivers/pwm/pwm-sun8i.c b/drivers/pwm/pwm-sun8i.c > > new file mode 100644 > > index 0000000..d8597e4 > > --- /dev/null > > +++ b/drivers/pwm/pwm-sun8i.c > > @@ -0,0 +1,418 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +// Copyright (C) 2018 Hao Zhang > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define PWM_IRQ_ENABLE_REG 0x0000 > > +#define PCIE(ch) BIT(ch) > > + > > +#define PWM_IRQ_STATUS_REG 0x0004 > > +#define PIS(ch) BIT(ch) > > + > > +#define CAPTURE_IRQ_ENABLE_REG 0x0010 > > +#define CRIE(ch) BIT((ch) * 2) > > +#define CFIE(ch) BIT((ch) * 2 + 1) > > + > > +#define CAPTURE_IRQ_STATUS_REG 0x0014 > > +#define CRIS(ch) BIT((ch) * 2) > > +#define CFIS(ch) BIT((ch) * 2 + 1) > > + > > +#define CLK_CFG_REG(ch) (0x0020 + ((ch) >> 1) * 4) > > +#define CLK_SRC_SEL GENMASK(8, 7) > > +#define CLK_SRC_BYPASS_SEC BIT(6) > > +#define CLK_SRC_BYPASS_FIR BIT(5) > > +#define CLK_GATING BIT(4) > > +#define CLK_DIV_M GENMASK(3, 0) > > + > > +#define PWM_DZ_CTR_REG(ch) (0x0030 + ((ch) >> 1) * 4) > > +#define PWM_DZ_INTV GENMASK(15, 8) > > +#define PWM_DZ_EN BIT(0) > > + > > +#define PWM_ENABLE_REG 0x0040 > > +#define PWM_EN(ch) BIT(ch) > > + > > +#define CAPTURE_ENABLE_REG 0x0044 > > +#define CAP_EN(ch) BIT(ch) > > + > > +#define PWM_CTR_REG(ch) (0x0060 + (ch) * 0x20) > > +#define PWM_PERIOD_RDY BIT(11) > > +#define PWM_PUL_START BIT(10) > > +#define PWM_MODE BIT(9) > > +#define PWM_ACT_STA BIT(8) > > +#define PWM_PRESCAL_K GENMASK(7, 0) > > + > > +#define PWM_PERIOD_REG(ch) (0x0064 + (ch) * 0x20) > > +#define PWM_ENTIRE_CYCLE GENMASK(31, 16) > > +#define PWM_ACT_CYCLE GENMASK(15, 0) > > + > > +#define PWM_CNT_REG(ch) (0x0068 + (ch) * 0x20) > > +#define PWM_CNT_VAL GENMASK(15, 0) > > + > > +#define CAPTURE_CTR_REG(ch) (0x006c + (ch) * 0x20) > > +#define CAPTURE_CRLF BIT(2) > > +#define CAPTURE_CFLF BIT(1) > > +#define CAPINV BIT(0) > > + > > +#define CAPTURE_RISE_REG(ch) (0x0070 + (ch) * 0x20) > > +#define CAPTURE_CRLR GENMASK(15, 0) > > + > > +#define CAPTURE_FALL_REG(ch) (0x0074 + (ch) * 0x20) > > +#define CAPTURE_CFLR GENMASK(15, 0) > > + > > +struct sun8i_pwm_chip { > > + struct pwm_chip chip; > > + struct clk *clk; > > + void __iomem *base; > > + const struct sun8i_pwm_data *data; > > + struct regmap *regmap; > > +}; > > + > > +static struct sun8i_pwm_chip *to_sun8i_pwm_chip(struct pwm_chip *chip) > > +{ > > + return container_of(chip, struct sun8i_pwm_chip, chip); > > +} > > + > > +static u32 sun8i_pwm_read(struct sun8i_pwm_chip *sun8i_pwm, > > + unsigned long offset) > > +{ > > + u32 val; > > + > > + regmap_read(sun8i_pwm->regmap, offset, &val); > > + return val; > > +} > > + > > +static void sun8i_pwm_set_bit(struct sun8i_pwm_chip *sun8i_pwm, > > + unsigned long reg, u32 bit) > > +{ > > + regmap_update_bits(sun8i_pwm->regmap, reg, bit, bit); > > +} > > + > > +static void sun8i_pwm_clear_bit(struct sun8i_pwm_chip *sun8i_pwm, > > + unsigned long reg, u32 bit) > > +{ > > + regmap_update_bits(sun8i_pwm->regmap, reg, bit, 0); > > +} > > + > > +static void sun8i_pwm_set_value(struct sun8i_pwm_chip *sun8i_pwm, > > + unsigned long reg, u32 mask, u32 val) > > +{ > > + regmap_update_bits(sun8i_pwm->regmap, reg, mask, val); > > +} > > + > > +static void sun8i_pwm_set_polarity(struct sun8i_pwm_chip *chip, u32 ch= , > > + enum pwm_polarity polarity) > > +{ > > + if (polarity =3D=3D PWM_POLARITY_NORMAL) > > + sun8i_pwm_set_bit(chip, PWM_CTR_REG(ch), PWM_ACT_STA); > > + else > > + sun8i_pwm_clear_bit(chip, PWM_CTR_REG(ch), PWM_ACT_STA); > > +} > > + > > +static int sun8i_pwm_config(struct sun8i_pwm_chip *sun8i_pwm, u8 ch, > > + struct pwm_state *state) > > +{ > > + u64 clk_rate, clk_div, val; > > + u16 prescaler =3D 0; > > + u16 div_id =3D 0; > > + struct clk *clk; > > + bool is_clk; > > + int ret; > > + > > + clk_rate =3D clk_get_rate(sun8i_pwm->clk); > > + > > + /* check period and select clock source */ > > + val =3D state->period * clk_rate; > > + do_div(val, NSEC_PER_SEC); > > + is_clk =3D devm_clk_name_match(sun8i_pwm->clk, "mux-0"); > > + if (val <=3D 1 && is_clk) { > > + clk =3D devm_clk_get(sun8i_pwm->chip.dev, "mux-1"); > > + if (IS_ERR(clk)) { > > + dev_err(sun8i_pwm->chip.dev, > > + "Period expects a larger value\n"); > > + return -EINVAL; > > + } > > You should never try to get resources at this point. You should have > requested them already at ->probe() time. Otherwise, how are you going > to handle failures here? > Something wrong here, i will fix it, thanks :) > > + > > + clk_rate =3D clk_get_rate(clk); > > + val =3D state->period * clk_rate; > > + do_div(val, NSEC_PER_SEC); > > + if (val <=3D 1) { > > + dev_err(sun8i_pwm->chip.dev, > > + "Period expects a larger value\n"); > > + return -EINVAL; > > + } > > + > > + /* change clock source to "mux-1" */ > > + clk_disable_unprepare(sun8i_pwm->clk); > > + devm_clk_put(sun8i_pwm->chip.dev, sun8i_pwm->clk); > > + sun8i_pwm->clk =3D clk; > > + > > + ret =3D clk_prepare_enable(sun8i_pwm->clk); > > + if (ret) { > > + dev_err(sun8i_pwm->chip.dev, > > + "Failed to enable PWM clock\n"); > > + return ret; > > + } > > + > > + } else { > > + dev_err(sun8i_pwm->chip.dev, > > + "Period expects a larger value\n"); > > + return -EINVAL; > > + } > > + > > + is_clk =3D devm_clk_name_match(sun8i_pwm->clk, "mux-0"); > > + if (is_clk) > > + sun8i_pwm_set_value(sun8i_pwm, CLK_CFG_REG(ch), > > + CLK_SRC_SEL, 0 << 7); > > + else > > + sun8i_pwm_set_value(sun8i_pwm, CLK_CFG_REG(ch), > > + CLK_SRC_SEL, 1 << 7); > > + > > + dev_info(sun8i_pwm->chip.dev, "clock source freq:%lldHz\n", clk_r= ate); > > + > > + /* calculate and set prescaler, div table, PWM entire cycle */ > > + clk_div =3D val; > > + while (clk_div > 65535) { > > + prescaler++; > > + clk_div =3D val; > > + do_div(clk_div, 1U << div_id); > > + do_div(clk_div, prescaler + 1); > > + > > + if (prescaler =3D=3D 255) { > > + prescaler =3D 0; > > + div_id++; > > + if (div_id =3D=3D 9) { > > + dev_err(sun8i_pwm->chip.dev, > > + "unsupport period value\n"); > > + return -EINVAL; > > + } > > + } > > + } > > + > > + sun8i_pwm_set_value(sun8i_pwm, PWM_PERIOD_REG(ch), > > + PWM_ENTIRE_CYCLE, clk_div << 16); > > + sun8i_pwm_set_value(sun8i_pwm, PWM_CTR_REG(ch), > > + PWM_PRESCAL_K, prescaler << 0); > > + sun8i_pwm_set_value(sun8i_pwm, CLK_CFG_REG(ch), > > + CLK_DIV_M, div_id << 0); > > + > > + /* set duty cycle */ > > + val =3D state->period; > > + do_div(val, clk_div); > > + clk_div =3D state->duty_cycle; > > + do_div(clk_div, val); > > + if (clk_div > 65535) > > + clk_div =3D 65535; > > + > > + sun8i_pwm_set_value(sun8i_pwm, PWM_PERIOD_REG(ch), > > + PWM_ACT_CYCLE, clk_div << 0); > > + > > + return 0; > > +} > > + > > +static int sun8i_pwm_apply(struct pwm_chip *chip, struct pwm_device *p= wm, > > + struct pwm_state *state) > > +{ > > + int ret; > > + struct sun8i_pwm_chip *sun8i_pwm =3D to_sun8i_pwm_chip(chip); > > + struct pwm_state cstate; > > + > > + pwm_get_state(pwm, &cstate); > > + if (!cstate.enabled) { > > + ret =3D clk_prepare_enable(sun8i_pwm->clk); > > + if (ret) { > > + dev_err(chip->dev, "Failed to enable PWM clock\n"= ); > > + return ret; > > + } > > + } > > + > > + if ((cstate.period !=3D state->period) || > > + (cstate.duty_cycle !=3D state->duty_cycle)) { > > + ret =3D sun8i_pwm_config(sun8i_pwm, pwm->hwpwm, state); > > + if (ret) { > > + dev_err(chip->dev, "Failed to config PWM\n"); > > + return ret; > > + } > > + } > > So this isn't really how atomic is supposed to work. The whole point of > the single callback is to allow the driver to apply the changes in an > atomic way, which means that either everything is applied or nothing is > applied. > > That's not what you do here. In the above you can end up with an enabled > clock but the settings not being applied. Similarly sun8i_pwm_config() > can abort in a number of places, which would leave you with a half- > configured PWM channel. > > Instead, what you should be doing is precompute everything and check > that the configuration can be applied before touching any registers or > enabling clocks. Once you've validate the new state, you need to write > everything and there should be no more risk of failure. > Got it, it is useful for me ! > Thierry > -----BEGIN PGP SIGNATURE----- > > iQIzBAABCAAdFiEEiOrDCAFJzPfAjcif3SOs138+s6EFAlwb2B4ACgkQ3SOs138+ > s6GmgRAAwvTyhaFa0jWmUftz+0FS5JTXADm9VusyhbSlmHV7UNkqkQuLnaT1WoGi > gGW5ZMLA+wSPWrXqGsw1HuzLc57c1/eDQdxLmlqBz0Lwribn75+0kisEvV3CRCEL > P9UiTgMualhTe0DGKZmcHJvV56sEhx7b2WQ81sOn5nZvCP/iFTURp5WSyk+phAyb > ss9i5bjwuxC34wLC0wCVNvr2XlpdD7CTy0R/nap1Za2nf6Cm0TnzGGPIYki1/gM2 > fUtYT/zCvfGp+JG5+R2755XdomXzj0vmXD7Omv75eKzMb+HivolmLPJEfUiP8c+x > SElT/F/jIkwvdBzyeQ/sA8ybh4N0DVapnUxBjrUBLOMlrNDlh+ApjUOOpwylQBXQ > 6JKmjoHoBg31lK9QEPxoIoNP0FdZBr6+lAaZeQNx95PeICxD21IvPtuLEp4ksbX7 > fJsOxbkBzbIMpKuxLM3vkl89/O9IhPbVoyvMASCPMmdwAIH+LSy3SvIFWbGQ0nXS > gwjTzN4r1AWmdXIN+faT6khnNY64WoPd896AyJSQ5mQsl42IMKRi42kpfeN3/f8y > x4d07WSTCRB4v+OehJEVP2WJNsbI3EvtClbngn66xSac7kGSbg4cpbW0NzkrFj+T > dOG2p9wUMibPBXzS+V7JzTsDgR9JG2fzxG8PhEesaG/Bt32Hg0Y=3D > =3DS1Wz > -----END PGP SIGNATURE----- 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 X-Spam-Level: X-Spam-Status: No, score=-3.9 required=3.0 tests=DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,DKIM_VALID,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_PASS,UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 450EEC43381 for ; Tue, 12 Mar 2019 05:43:20 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 14B1D2084F for ; Tue, 12 Mar 2019 05:43:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="argOQi/x"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gW2oFbFJ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 14B1D2084F Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:To:Subject:Message-ID:Date:From: In-Reply-To:References:MIME-Version:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=yCcVuI/LZYjk448xW/7If91uWrDJ7kqjHHK6y5enSPs=; b=argOQi/xOkyH7T Opl8aog+mQi/7z9h24Bp2HmtfGFA21N15QOPrrlkLn1GR3Q0GUvKV2VMae3FpN2dAOnNQKHau+3PC Rn6ION4hIuaSjbRjaD1SsMzVq5d7jlTtKzLL1vVqhI4K19xN97Wp+JEGA9gyYkq/Lc01cu0evOXBK XQtKrERmc6atJEIj1toc5G0G6P5udr7VFN9myQsKXm6tqAhFfuEel26k6grZ58/hIdf0DTcOQymrQ wti2S7PebMKasiUdH/kLpT+gtywDU3iV8zyuw3oh8RBBtCsX0JjXuWoGk5l3xzMsgulbASIwohJxh zPH2sF5/bhCVPdwjr/1A==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h3aC2-0001Qo-8u; Tue, 12 Mar 2019 05:43:14 +0000 Received: from mail-wr1-x444.google.com ([2a00:1450:4864:20::444]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1h3aBy-0001QO-Kz for linux-arm-kernel@lists.infradead.org; Tue, 12 Mar 2019 05:43:12 +0000 Received: by mail-wr1-x444.google.com with SMTP id g18so1248977wru.3 for ; Mon, 11 Mar 2019 22:43:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc:content-transfer-encoding; bh=DCFWrKMkPSlIxd7n635HoPYKiNDnEatlKvCsU2Ma/vo=; b=gW2oFbFJiXv6vuFijUvsp/yKB63LRlwtrZNse9xVVgXS6K3xRD9EtaxY85q9BJwcDi 19tht/DzSRC/h2j/YpoaF+Ygeyu2tW7dwgqkyazpN7Z6FhHPuuSiJrkyUB2gmRXcijOb F1+u5eSOThzmlrXW/ZKWIE9aJ2mutvuFAVr+tTSDFTm+vzMS/fMF9HM+EyZJyqhOU9+1 E4yKWTRl+LE8295Fv02J6/WHHBbBWenQKrG6kG2vZEtG+bB7OEXwP9Qznv16oYRtz+nZ J/kVuDrWKpAKVH9LwWEXH/04lCW74+KqDAiQ1gtYQDEVy3sL/CUaMFOyALXyxQXNEBYZ Tzkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=DCFWrKMkPSlIxd7n635HoPYKiNDnEatlKvCsU2Ma/vo=; b=VQrmlC9Uqn2E7uNANznflYdfFn4sKAMvWljdJP5yMFW6oEs32vvaV3cucK/VXdf+UC IzKosxP7nUfJABG3fwwdtE6ijKVv8VNhC1h4TZye3KIAS7CLMPCWejW+499dq9AG5JTJ g0MmEgi9c8oiBIAxKyoQtAOVsTulgk6Mke1BDSXp+C+xJXErOfqc4WkMdSrGzt7o3AHO 0UIpf1HV+T5jtdwvc1gAggTe+I85paL1k2L6dXLptgolxOVyJ9Iaym1I911dssbl9u6I 2wjd6kIeVIX0JXzlvXuW87cxqiYnDbNPSEO3EFLHqs2oB75NgX8Kk3d91D8MsTXxnRM/ gwKw== X-Gm-Message-State: APjAAAXsrccL9TVsW6EXVtRi9Uhdl79qWxSTrlhLjoBP4hYZPhbKUQeJ sxaMlVeA+xRsceZnBgQ6cK0x87tOvGnknxwto2U= X-Google-Smtp-Source: APXvYqxaAnODKnkR7pMW4waqvVLw/V1KAEoesB1t2uFmIx1Z5MgQ8jkd6sS7iD3QSiJ1s9wOTMWxMovzrPVEhDPeWPM= X-Received: by 2002:adf:e4c9:: with SMTP id v9mr9437633wrm.209.1552369389065; Mon, 11 Mar 2019 22:43:09 -0700 (PDT) MIME-Version: 1.0 References: <20181125162319.GA5422@arx-s1> <20181220175750.GG9408@ulmo> In-Reply-To: <20181220175750.GG9408@ulmo> From: Hao Zhang Date: Tue, 12 Mar 2019 13:42:57 +0800 Message-ID: Subject: Re: [PATCH v3 6/6] ARM: PWM: add allwinner sun8i R40/T3/V40 PWM support. To: Thierry Reding X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190311_224310_746606_B0030C83 X-CRM114-Status: GOOD ( 29.18 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , "open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS" , linux-gpio@vger.kernel.org, Maxime Ripard , Michael Turquette , linux-sunxi@googlegroups.com, open list , linux-pwm@vger.kernel.org, sboyd@kernel.org, Chen-Yu Tsai , robh+dt@kernel.org, "moderated list:ARM/Allwinner sunXi SoC support" Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org VGhpZXJyeSBSZWRpbmcgPHRoaWVycnkucmVkaW5nQGdtYWlsLmNvbT4g5LqOMjAxOOW5tDEy5pyI MjHml6XlkajkupQg5LiK5Y2IMTo1N+WGmemBk++8mgo+Cj4gT24gTW9uLCBOb3YgMjYsIDIwMTgg YXQgMTI6MjM6MTlBTSArMDgwMCwgSGFvIFpoYW5nIHdyb3RlOgo+ID4gVGhlIHN1bjhpIFI0MC9U My9WNDAgUFdNIGhhcyA4IFBXTSBjaGFubmFscyBhbmQgZGl2aWRlcyB0byA0IFBXTSBwYWlycywK PiA+IGVhY2ggUFdNIHBhaXIgYnVpbHQtaW4gMSBjbG9jayBtb2R1bGUsIDIgdGltZXIgbG9naWMg bW9kdWxlIGFuZCAxCj4gPiBwcm9ncmFtbWFibGUgZGVhZC10aW1lIGdlbmVyYXRvciwgaXQgYWxz byBzdXBwb3J0IHdhdmVmb3JtIGNhcHR1cmUuCj4gPiBJdCBoYXMgMiBjbG9jayBzb3VyY2VzIE9T QzI0TSBhbmQgQVBCMSwgaXQgaXMgZGlmZmVyZW50IHdpdGggdGhlCj4gPiBzdW40aS1wd20gZHJp dmVyLCBUaGVyZWZvcmUgYWRkIGEgbmV3IGRyaXZlciBmb3IgaXQuCj4gPgo+ID4gU2lnbmVkLW9m Zi1ieTogSGFvIFpoYW5nIDxoYW81NzgxMjg2QGdtYWlsLmNvbT4KPiA+IC0tLQo+ID4gIGRyaXZl cnMvcHdtL0tjb25maWcgICAgIHwgIDEyICstCj4gPiAgZHJpdmVycy9wd20vTWFrZWZpbGUgICAg fCAgIDEgKwo+ID4gIGRyaXZlcnMvcHdtL3B3bS1zdW44aS5jIHwgNDE4ICsrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwo+ID4gIDMgZmlsZXMgY2hhbmdlZCwg NDMwIGluc2VydGlvbnMoKyksIDEgZGVsZXRpb24oLSkKPiA+ICBjcmVhdGUgbW9kZSAxMDA2NDQg ZHJpdmVycy9wd20vcHdtLXN1bjhpLmMKPiA+Cj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9wd20v S2NvbmZpZyBiL2RyaXZlcnMvcHdtL0tjb25maWcKPiA+IGluZGV4IDUwNGQyNTIuLjYxMDVhYzgg MTAwNjQ0Cj4gPiAtLS0gYS9kcml2ZXJzL3B3bS9LY29uZmlnCj4gPiArKysgYi9kcml2ZXJzL3B3 bS9LY29uZmlnCj4gPiBAQCAtNDI2LDcgKzQyNiw3IEBAIGNvbmZpZyBQV01fU1RNUEUKPiA+ICAg ICAgICAgZXhwYW5kZXJzLgo+ID4KPiA+ICBjb25maWcgUFdNX1NVTjRJCj4gPiAtICAgICB0cmlz dGF0ZSAiQWxsd2lubmVyIFBXTSBzdXBwb3J0Igo+ID4gKyAgICAgdHJpc3RhdGUgIkFsbHdpbm5l ciBTVU40SSBQV00gc3VwcG9ydCIKPiA+ICAgICAgIGRlcGVuZHMgb24gQVJDSF9TVU5YSSB8fCBD T01QSUxFX1RFU1QKPiA+ICAgICAgIGRlcGVuZHMgb24gSEFTX0lPTUVNICYmIENPTU1PTl9DTEsK PiA+ICAgICAgIGhlbHAKPiA+IEBAIC00MzUsNiArNDM1LDE2IEBAIGNvbmZpZyBQV01fU1VONEkK PiA+ICAgICAgICAgVG8gY29tcGlsZSB0aGlzIGRyaXZlciBhcyBhIG1vZHVsZSwgY2hvb3NlIE0g aGVyZTogdGhlIG1vZHVsZQo+ID4gICAgICAgICB3aWxsIGJlIGNhbGxlZCBwd20tc3VuNGkuCj4g Pgo+ID4gK2NvbmZpZyBQV01fU1VOOEkKPiA+ICsgICAgIHRyaXN0YXRlICJBbGx3aW5uZXIgU1VO OEkgKFI0MC9WNDAvVDMpIFBXTSBzdXBwb3J0Igo+ID4gKyAgICAgZGVwZW5kcyBvbiBBUkNIX1NV TlhJIHx8IENPTVBJTEVfVEVTVAo+ID4gKyAgICAgZGVwZW5kcyBvbiBIQVNfSU9NRU0gJiYgQ09N TU9OX0NMSwo+ID4gKyAgICAgaGVscAo+ID4gKyAgICAgICBHZW5lcmljIFBXTSBmcmFtZXdvcmsg ZHJpdmVyIGZvciBBbGx3aW5uZXIgUjQwL1Y0MC9UMyBTb0NzLgo+ID4gKwo+ID4gKyAgICAgICBU byBjb21waWxlIHRoaXMgZHJpdmVyIGFzIGEgbW9kdWxlLCBjaG9vc2UgTSBoZXJlOiB0aGUgbW9k dWxlCj4gPiArICAgICAgIHdpbGwgYmUgY2FsbGVkIHB3bS1zdW44aS4KPiA+ICsKPiA+ICBjb25m aWcgUFdNX1RFR1JBCj4gPiAgICAgICB0cmlzdGF0ZSAiTlZJRElBIFRlZ3JhIFBXTSBzdXBwb3J0 Igo+ID4gICAgICAgZGVwZW5kcyBvbiBBUkNIX1RFR1JBCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVy cy9wd20vTWFrZWZpbGUgYi9kcml2ZXJzL3B3bS9NYWtlZmlsZQo+ID4gaW5kZXggOWM2NzZhMC4u MzJjOGQyZCAxMDA2NDQKPiA+IC0tLSBhL2RyaXZlcnMvcHdtL01ha2VmaWxlCj4gPiArKysgYi9k cml2ZXJzL3B3bS9NYWtlZmlsZQo+ID4gQEAgLTQzLDYgKzQzLDcgQEAgb2JqLSQoQ09ORklHX1BX TV9TVE0zMikgICAgICAgICAgICAgKz0gcHdtLXN0bTMyLm8KPiA+ICBvYmotJChDT05GSUdfUFdN X1NUTTMyX0xQKSAgICs9IHB3bS1zdG0zMi1scC5vCj4gPiAgb2JqLSQoQ09ORklHX1BXTV9TVE1Q RSkgICAgICAgICAgICAgICs9IHB3bS1zdG1wZS5vCj4gPiAgb2JqLSQoQ09ORklHX1BXTV9TVU40 SSkgICAgICAgICAgICAgICs9IHB3bS1zdW40aS5vCj4gPiArb2JqLSQoQ09ORklHX1BXTV9TVU44 SSkgICAgICAgICAgICAgICs9IHB3bS1zdW44aS5vCj4gPiAgb2JqLSQoQ09ORklHX1BXTV9URUdS QSkgICAgICAgICAgICAgICs9IHB3bS10ZWdyYS5vCj4gPiAgb2JqLSQoQ09ORklHX1BXTV9USUVD QVApICAgICArPSBwd20tdGllY2FwLm8KPiA+ICBvYmotJChDT05GSUdfUFdNX1RJRUhSUFdNKSAg ICs9IHB3bS10aWVocnB3bS5vCj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9wd20vcHdtLXN1bjhp LmMgYi9kcml2ZXJzL3B3bS9wd20tc3VuOGkuYwo+ID4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiA+ IGluZGV4IDAwMDAwMDAuLmQ4NTk3ZTQKPiA+IC0tLSAvZGV2L251bGwKPiA+ICsrKyBiL2RyaXZl cnMvcHdtL3B3bS1zdW44aS5jCj4gPiBAQCAtMCwwICsxLDQxOCBAQAo+ID4gKy8vIFNQRFgtTGlj ZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wCj4gPiArLy8gQ29weXJpZ2h0IChDKSAyMDE4IEhhbyBa aGFuZyA8aGFvNTc4MTI4NkBnbWFpbC5jb20+Cj4gPiArCj4gPiArI2luY2x1ZGUgPGxpbnV4L2Jp dG9wcy5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9jbGsuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgv Y2xrLXByb3ZpZGVyLmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L2RlbGF5Lmg+Cj4gPiArI2luY2x1 ZGUgPGxpbnV4L2Vyci5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9pby5oPgo+ID4gKyNpbmNsdWRl IDxsaW51eC9tb2R1bGUuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgvb2YuaD4KPiA+ICsjaW5jbHVk ZSA8bGludXgvb2ZfZGV2aWNlLmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2Rldmlj ZS5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9wd20uaD4KPiA+ICsjaW5jbHVkZSA8bGludXgvc2xh Yi5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9zcGlubG9jay5oPgo+ID4gKyNpbmNsdWRlIDxsaW51 eC90aW1lLmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L3JlZ21hcC5oPgo+ID4gKwo+ID4gKyNkZWZp bmUgUFdNX0lSUV9FTkFCTEVfUkVHICAgMHgwMDAwCj4gPiArI2RlZmluZSBQQ0lFKGNoKSAgICAg ICAgICAgICBCSVQoY2gpCj4gPiArCj4gPiArI2RlZmluZSBQV01fSVJRX1NUQVRVU19SRUcgICAw eDAwMDQKPiA+ICsjZGVmaW5lIFBJUyhjaCkgICAgICAgICAgICAgICAgICAgICAgQklUKGNoKQo+ ID4gKwo+ID4gKyNkZWZpbmUgQ0FQVFVSRV9JUlFfRU5BQkxFX1JFRyAgICAgICAweDAwMTAKPiA+ ICsjZGVmaW5lIENSSUUoY2gpICAgICAgICAgICAgIEJJVCgoY2gpICogMikKPiA+ICsjZGVmaW5l IENGSUUoY2gpICAgICAgICAgICAgIEJJVCgoY2gpICogMiArIDEpCj4gPiArCj4gPiArI2RlZmlu ZSBDQVBUVVJFX0lSUV9TVEFUVVNfUkVHICAgICAgIDB4MDAxNAo+ID4gKyNkZWZpbmUgQ1JJUyhj aCkgICAgICAgICAgICAgQklUKChjaCkgKiAyKQo+ID4gKyNkZWZpbmUgQ0ZJUyhjaCkgICAgICAg ICAgICAgQklUKChjaCkgKiAyICsgMSkKPiA+ICsKPiA+ICsjZGVmaW5lIENMS19DRkdfUkVHKGNo KSAgICAgICAgICAgICAgKDB4MDAyMCArICgoY2gpID4+IDEpICogNCkKPiA+ICsjZGVmaW5lIENM S19TUkNfU0VMICAgICAgICAgIEdFTk1BU0soOCwgNykKPiA+ICsjZGVmaW5lIENMS19TUkNfQllQ QVNTX1NFQyAgIEJJVCg2KQo+ID4gKyNkZWZpbmUgQ0xLX1NSQ19CWVBBU1NfRklSICAgQklUKDUp Cj4gPiArI2RlZmluZSBDTEtfR0FUSU5HICAgICAgICAgICBCSVQoNCkKPiA+ICsjZGVmaW5lIENM S19ESVZfTSAgICAgICAgICAgIEdFTk1BU0soMywgMCkKPiA+ICsKPiA+ICsjZGVmaW5lIFBXTV9E Wl9DVFJfUkVHKGNoKSAgICgweDAwMzAgKyAoKGNoKSA+PiAxKSAqIDQpCj4gPiArI2RlZmluZSBQ V01fRFpfSU5UViAgICAgICAgICBHRU5NQVNLKDE1LCA4KQo+ID4gKyNkZWZpbmUgUFdNX0RaX0VO ICAgICAgICAgICAgQklUKDApCj4gPiArCj4gPiArI2RlZmluZSBQV01fRU5BQkxFX1JFRyAgICAg ICAgICAgICAgIDB4MDA0MAo+ID4gKyNkZWZpbmUgUFdNX0VOKGNoKSAgICAgICAgICAgQklUKGNo KQo+ID4gKwo+ID4gKyNkZWZpbmUgQ0FQVFVSRV9FTkFCTEVfUkVHICAgMHgwMDQ0Cj4gPiArI2Rl ZmluZSBDQVBfRU4oY2gpICAgICAgICAgICBCSVQoY2gpCj4gPiArCj4gPiArI2RlZmluZSBQV01f Q1RSX1JFRyhjaCkgICAgICAgICAgICAgICgweDAwNjAgKyAoY2gpICogMHgyMCkKPiA+ICsjZGVm aW5lIFBXTV9QRVJJT0RfUkRZICAgICAgICAgICAgICAgQklUKDExKQo+ID4gKyNkZWZpbmUgUFdN X1BVTF9TVEFSVCAgICAgICAgICAgICAgICBCSVQoMTApCj4gPiArI2RlZmluZSBQV01fTU9ERSAg ICAgICAgICAgICBCSVQoOSkKPiA+ICsjZGVmaW5lIFBXTV9BQ1RfU1RBICAgICAgICAgIEJJVCg4 KQo+ID4gKyNkZWZpbmUgUFdNX1BSRVNDQUxfSyAgICAgICAgICAgICAgICBHRU5NQVNLKDcsIDAp Cj4gPiArCj4gPiArI2RlZmluZSBQV01fUEVSSU9EX1JFRyhjaCkgICAoMHgwMDY0ICsgKGNoKSAq IDB4MjApCj4gPiArI2RlZmluZSBQV01fRU5USVJFX0NZQ0xFICAgICBHRU5NQVNLKDMxLCAxNikK PiA+ICsjZGVmaW5lIFBXTV9BQ1RfQ1lDTEUgICAgICAgICAgICAgICAgR0VOTUFTSygxNSwgMCkK PiA+ICsKPiA+ICsjZGVmaW5lIFBXTV9DTlRfUkVHKGNoKSAgICAgICAgICAgICAgKDB4MDA2OCAr IChjaCkgKiAweDIwKQo+ID4gKyNkZWZpbmUgUFdNX0NOVF9WQUwgICAgICAgICAgR0VOTUFTSygx NSwgMCkKPiA+ICsKPiA+ICsjZGVmaW5lIENBUFRVUkVfQ1RSX1JFRyhjaCkgICgweDAwNmMgKyAo Y2gpICogMHgyMCkKPiA+ICsjZGVmaW5lIENBUFRVUkVfQ1JMRiAgICAgICAgIEJJVCgyKQo+ID4g KyNkZWZpbmUgQ0FQVFVSRV9DRkxGICAgICAgICAgQklUKDEpCj4gPiArI2RlZmluZSBDQVBJTlYg ICAgICAgICAgICAgICAgICAgICAgIEJJVCgwKQo+ID4gKwo+ID4gKyNkZWZpbmUgQ0FQVFVSRV9S SVNFX1JFRyhjaCkgKDB4MDA3MCArIChjaCkgKiAweDIwKQo+ID4gKyNkZWZpbmUgQ0FQVFVSRV9D UkxSICAgICAgICAgR0VOTUFTSygxNSwgMCkKPiA+ICsKPiA+ICsjZGVmaW5lIENBUFRVUkVfRkFM TF9SRUcoY2gpICgweDAwNzQgKyAoY2gpICogMHgyMCkKPiA+ICsjZGVmaW5lIENBUFRVUkVfQ0ZM UiAgICAgICAgIEdFTk1BU0soMTUsIDApCj4gPiArCj4gPiArc3RydWN0IHN1bjhpX3B3bV9jaGlw IHsKPiA+ICsgICAgIHN0cnVjdCBwd21fY2hpcCBjaGlwOwo+ID4gKyAgICAgc3RydWN0IGNsayAq Y2xrOwo+ID4gKyAgICAgdm9pZCBfX2lvbWVtICpiYXNlOwo+ID4gKyAgICAgY29uc3Qgc3RydWN0 IHN1bjhpX3B3bV9kYXRhICpkYXRhOwo+ID4gKyAgICAgc3RydWN0IHJlZ21hcCAqcmVnbWFwOwo+ ID4gK307Cj4gPiArCj4gPiArc3RhdGljIHN0cnVjdCBzdW44aV9wd21fY2hpcCAqdG9fc3VuOGlf cHdtX2NoaXAoc3RydWN0IHB3bV9jaGlwICpjaGlwKQo+ID4gK3sKPiA+ICsgICAgIHJldHVybiBj b250YWluZXJfb2YoY2hpcCwgc3RydWN0IHN1bjhpX3B3bV9jaGlwLCBjaGlwKTsKPiA+ICt9Cj4g PiArCj4gPiArc3RhdGljIHUzMiBzdW44aV9wd21fcmVhZChzdHJ1Y3Qgc3VuOGlfcHdtX2NoaXAg KnN1bjhpX3B3bSwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgIHVuc2lnbmVkIGxvbmcgb2Zm c2V0KQo+ID4gK3sKPiA+ICsgICAgIHUzMiB2YWw7Cj4gPiArCj4gPiArICAgICByZWdtYXBfcmVh ZChzdW44aV9wd20tPnJlZ21hcCwgb2Zmc2V0LCAmdmFsKTsKPiA+ICsgICAgIHJldHVybiB2YWw7 Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyB2b2lkIHN1bjhpX3B3bV9zZXRfYml0KHN0cnVjdCBz dW44aV9wd21fY2hpcCAqc3VuOGlfcHdtLAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAg IHVuc2lnbmVkIGxvbmcgcmVnLCB1MzIgYml0KQo+ID4gK3sKPiA+ICsgICAgIHJlZ21hcF91cGRh dGVfYml0cyhzdW44aV9wd20tPnJlZ21hcCwgcmVnLCBiaXQsIGJpdCk7Cj4gPiArfQo+ID4gKwo+ ID4gK3N0YXRpYyB2b2lkIHN1bjhpX3B3bV9jbGVhcl9iaXQoc3RydWN0IHN1bjhpX3B3bV9jaGlw ICpzdW44aV9wd20sCj4gPiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bnNpZ25lZCBs b25nIHJlZywgdTMyIGJpdCkKPiA+ICt7Cj4gPiArICAgICByZWdtYXBfdXBkYXRlX2JpdHMoc3Vu OGlfcHdtLT5yZWdtYXAsIHJlZywgYml0LCAwKTsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIHZv aWQgc3VuOGlfcHdtX3NldF92YWx1ZShzdHJ1Y3Qgc3VuOGlfcHdtX2NoaXAgKnN1bjhpX3B3bSwK PiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuc2lnbmVkIGxvbmcgcmVnLCB1MzIg bWFzaywgdTMyIHZhbCkKPiA+ICt7Cj4gPiArICAgICByZWdtYXBfdXBkYXRlX2JpdHMoc3VuOGlf cHdtLT5yZWdtYXAsIHJlZywgbWFzaywgdmFsKTsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIHZv aWQgc3VuOGlfcHdtX3NldF9wb2xhcml0eShzdHJ1Y3Qgc3VuOGlfcHdtX2NoaXAgKmNoaXAsIHUz MiBjaCwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVudW0gcHdtX3BvbGFy aXR5IHBvbGFyaXR5KQo+ID4gK3sKPiA+ICsgICAgIGlmIChwb2xhcml0eSA9PSBQV01fUE9MQVJJ VFlfTk9STUFMKQo+ID4gKyAgICAgICAgICAgICBzdW44aV9wd21fc2V0X2JpdChjaGlwLCBQV01f Q1RSX1JFRyhjaCksIFBXTV9BQ1RfU1RBKTsKPiA+ICsgICAgIGVsc2UKPiA+ICsgICAgICAgICAg ICAgc3VuOGlfcHdtX2NsZWFyX2JpdChjaGlwLCBQV01fQ1RSX1JFRyhjaCksIFBXTV9BQ1RfU1RB KTsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIGludCBzdW44aV9wd21fY29uZmlnKHN0cnVjdCBz dW44aV9wd21fY2hpcCAqc3VuOGlfcHdtLCB1OCBjaCwKPiA+ICsgICAgICAgICAgICAgICAgICAg ICAgICAgc3RydWN0IHB3bV9zdGF0ZSAqc3RhdGUpCj4gPiArewo+ID4gKyAgICAgdTY0IGNsa19y YXRlLCBjbGtfZGl2LCB2YWw7Cj4gPiArICAgICB1MTYgcHJlc2NhbGVyID0gMDsKPiA+ICsgICAg IHUxNiBkaXZfaWQgPSAwOwo+ID4gKyAgICAgc3RydWN0IGNsayAqY2xrOwo+ID4gKyAgICAgYm9v bCBpc19jbGs7Cj4gPiArICAgICBpbnQgcmV0Owo+ID4gKwo+ID4gKyAgICAgY2xrX3JhdGUgPSBj bGtfZ2V0X3JhdGUoc3VuOGlfcHdtLT5jbGspOwo+ID4gKwo+ID4gKyAgICAgLyogY2hlY2sgcGVy aW9kIGFuZCBzZWxlY3QgY2xvY2sgc291cmNlICovCj4gPiArICAgICB2YWwgPSBzdGF0ZS0+cGVy aW9kICogY2xrX3JhdGU7Cj4gPiArICAgICBkb19kaXYodmFsLCBOU0VDX1BFUl9TRUMpOwo+ID4g KyAgICAgaXNfY2xrID0gZGV2bV9jbGtfbmFtZV9tYXRjaChzdW44aV9wd20tPmNsaywgIm11eC0w Iik7Cj4gPiArICAgICBpZiAodmFsIDw9IDEgJiYgaXNfY2xrKSB7Cj4gPiArICAgICAgICAgICAg IGNsayA9IGRldm1fY2xrX2dldChzdW44aV9wd20tPmNoaXAuZGV2LCAibXV4LTEiKTsKPiA+ICsg ICAgICAgICAgICAgaWYgKElTX0VSUihjbGspKSB7Cj4gPiArICAgICAgICAgICAgICAgICAgICAg ZGV2X2VycihzdW44aV9wd20tPmNoaXAuZGV2LAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIlBlcmlvZCBleHBlY3RzIGEgbGFyZ2VyIHZhbHVlXG4iKTsKPiA+ICsgICAgICAgICAg ICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsKPiA+ICsgICAgICAgICAgICAgfQo+Cj4gWW91IHNo b3VsZCBuZXZlciB0cnkgdG8gZ2V0IHJlc291cmNlcyBhdCB0aGlzIHBvaW50LiBZb3Ugc2hvdWxk IGhhdmUKPiByZXF1ZXN0ZWQgdGhlbSBhbHJlYWR5IGF0IC0+cHJvYmUoKSB0aW1lLiBPdGhlcndp c2UsIGhvdyBhcmUgeW91IGdvaW5nCj4gdG8gaGFuZGxlIGZhaWx1cmVzIGhlcmU/Cj4KClNvbWV0 aGluZyB3cm9uZyBoZXJlLCBpIHdpbGwgZml4IGl0LCB0aGFua3MgOikKCj4gPiArCj4gPiArICAg ICAgICAgICAgIGNsa19yYXRlID0gY2xrX2dldF9yYXRlKGNsayk7Cj4gPiArICAgICAgICAgICAg IHZhbCA9IHN0YXRlLT5wZXJpb2QgKiBjbGtfcmF0ZTsKPiA+ICsgICAgICAgICAgICAgZG9fZGl2 KHZhbCwgTlNFQ19QRVJfU0VDKTsKPiA+ICsgICAgICAgICAgICAgaWYgKHZhbCA8PSAxKSB7Cj4g PiArICAgICAgICAgICAgICAgICAgICAgZGV2X2VycihzdW44aV9wd20tPmNoaXAuZGV2LAo+ID4g KyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBlcmlvZCBleHBlY3RzIGEgbGFyZ2VyIHZh bHVlXG4iKTsKPiA+ICsgICAgICAgICAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsKPiA+ICsg ICAgICAgICAgICAgfQo+ID4gKwo+ID4gKyAgICAgICAgICAgICAvKiBjaGFuZ2UgY2xvY2sgc291 cmNlIHRvICJtdXgtMSIgKi8KPiA+ICsgICAgICAgICAgICAgY2xrX2Rpc2FibGVfdW5wcmVwYXJl KHN1bjhpX3B3bS0+Y2xrKTsKPiA+ICsgICAgICAgICAgICAgZGV2bV9jbGtfcHV0KHN1bjhpX3B3 bS0+Y2hpcC5kZXYsIHN1bjhpX3B3bS0+Y2xrKTsKPiA+ICsgICAgICAgICAgICAgc3VuOGlfcHdt LT5jbGsgPSBjbGs7Cj4gPiArCj4gPiArICAgICAgICAgICAgIHJldCA9IGNsa19wcmVwYXJlX2Vu YWJsZShzdW44aV9wd20tPmNsayk7Cj4gPiArICAgICAgICAgICAgIGlmIChyZXQpIHsKPiA+ICsg ICAgICAgICAgICAgICAgICAgICBkZXZfZXJyKHN1bjhpX3B3bS0+Y2hpcC5kZXYsCj4gPiArICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAiRmFpbGVkIHRvIGVuYWJsZSBQV00gY2xvY2tcbiIp Owo+ID4gKyAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXQ7Cj4gPiArICAgICAgICAgICAg IH0KPiA+ICsKPiA+ICsgICAgIH0gZWxzZSB7Cj4gPiArICAgICAgICAgICAgIGRldl9lcnIoc3Vu OGlfcHdtLT5jaGlwLmRldiwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAiUGVyaW9kIGV4cGVj dHMgYSBsYXJnZXIgdmFsdWVcbiIpOwo+ID4gKyAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsK PiA+ICsgICAgIH0KPiA+ICsKPiA+ICsgICAgIGlzX2NsayA9IGRldm1fY2xrX25hbWVfbWF0Y2go c3VuOGlfcHdtLT5jbGssICJtdXgtMCIpOwo+ID4gKyAgICAgaWYgKGlzX2NsaykKPiA+ICsgICAg ICAgICAgICAgc3VuOGlfcHdtX3NldF92YWx1ZShzdW44aV9wd20sIENMS19DRkdfUkVHKGNoKSwK PiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDTEtfU1JDX1NFTCwgMCA8PCA3 KTsKPiA+ICsgICAgIGVsc2UKPiA+ICsgICAgICAgICAgICAgc3VuOGlfcHdtX3NldF92YWx1ZShz dW44aV9wd20sIENMS19DRkdfUkVHKGNoKSwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICBDTEtfU1JDX1NFTCwgMSA8PCA3KTsKPiA+ICsKPiA+ICsgICAgIGRldl9pbmZvKHN1 bjhpX3B3bS0+Y2hpcC5kZXYsICJjbG9jayBzb3VyY2UgZnJlcTolbGxkSHpcbiIsIGNsa19yYXRl KTsKPiA+ICsKPiA+ICsgICAgIC8qIGNhbGN1bGF0ZSBhbmQgc2V0IHByZXNjYWxlciwgZGl2IHRh YmxlLCBQV00gZW50aXJlIGN5Y2xlICovCj4gPiArICAgICBjbGtfZGl2ID0gdmFsOwo+ID4gKyAg ICAgd2hpbGUgKGNsa19kaXYgPiA2NTUzNSkgewo+ID4gKyAgICAgICAgICAgICBwcmVzY2FsZXIr KzsKPiA+ICsgICAgICAgICAgICAgY2xrX2RpdiA9IHZhbDsKPiA+ICsgICAgICAgICAgICAgZG9f ZGl2KGNsa19kaXYsIDFVIDw8IGRpdl9pZCk7Cj4gPiArICAgICAgICAgICAgIGRvX2RpdihjbGtf ZGl2LCBwcmVzY2FsZXIgKyAxKTsKPiA+ICsKPiA+ICsgICAgICAgICAgICAgaWYgKHByZXNjYWxl ciA9PSAyNTUpIHsKPiA+ICsgICAgICAgICAgICAgICAgICAgICBwcmVzY2FsZXIgPSAwOwo+ID4g KyAgICAgICAgICAgICAgICAgICAgIGRpdl9pZCsrOwo+ID4gKyAgICAgICAgICAgICAgICAgICAg IGlmIChkaXZfaWQgPT0gOSkgewo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2 X2VycihzdW44aV9wd20tPmNoaXAuZGV2LAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAidW5zdXBwb3J0IHBlcmlvZCB2YWx1ZVxuIik7Cj4gPiArICAgICAgICAgICAg ICAgICAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsKPiA+ICsgICAgICAgICAgICAgICAgICAg ICB9Cj4gPiArICAgICAgICAgICAgIH0KPiA+ICsgICAgIH0KPiA+ICsKPiA+ICsgICAgIHN1bjhp X3B3bV9zZXRfdmFsdWUoc3VuOGlfcHdtLCBQV01fUEVSSU9EX1JFRyhjaCksCj4gPiArICAgICAg ICAgICAgICAgICAgICAgICAgIFBXTV9FTlRJUkVfQ1lDTEUsIGNsa19kaXYgPDwgMTYpOwo+ID4g KyAgICAgc3VuOGlfcHdtX3NldF92YWx1ZShzdW44aV9wd20sIFBXTV9DVFJfUkVHKGNoKSwKPiA+ ICsgICAgICAgICAgICAgICAgICAgICAgICAgUFdNX1BSRVNDQUxfSywgcHJlc2NhbGVyIDw8IDAp Owo+ID4gKyAgICAgc3VuOGlfcHdtX3NldF92YWx1ZShzdW44aV9wd20sIENMS19DRkdfUkVHKGNo KSwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgQ0xLX0RJVl9NLCBkaXZfaWQgPDwgMCk7 Cj4gPiArCj4gPiArICAgICAvKiBzZXQgZHV0eSBjeWNsZSAqLwo+ID4gKyAgICAgdmFsID0gc3Rh dGUtPnBlcmlvZDsKPiA+ICsgICAgIGRvX2Rpdih2YWwsIGNsa19kaXYpOwo+ID4gKyAgICAgY2xr X2RpdiA9IHN0YXRlLT5kdXR5X2N5Y2xlOwo+ID4gKyAgICAgZG9fZGl2KGNsa19kaXYsIHZhbCk7 Cj4gPiArICAgICBpZiAoY2xrX2RpdiA+IDY1NTM1KQo+ID4gKyAgICAgICAgICAgICBjbGtfZGl2 ID0gNjU1MzU7Cj4gPiArCj4gPiArICAgICBzdW44aV9wd21fc2V0X3ZhbHVlKHN1bjhpX3B3bSwg UFdNX1BFUklPRF9SRUcoY2gpLAo+ID4gKyAgICAgICAgICAgICAgICAgICAgICAgICBQV01fQUNU X0NZQ0xFLCBjbGtfZGl2IDw8IDApOwo+ID4gKwo+ID4gKyAgICAgcmV0dXJuIDA7Cj4gPiArfQo+ ID4gKwo+ID4gK3N0YXRpYyBpbnQgc3VuOGlfcHdtX2FwcGx5KHN0cnVjdCBwd21fY2hpcCAqY2hp cCwgc3RydWN0IHB3bV9kZXZpY2UgKnB3bSwKPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICBz dHJ1Y3QgcHdtX3N0YXRlICpzdGF0ZSkKPiA+ICt7Cj4gPiArICAgICBpbnQgcmV0Owo+ID4gKyAg ICAgc3RydWN0IHN1bjhpX3B3bV9jaGlwICpzdW44aV9wd20gPSB0b19zdW44aV9wd21fY2hpcChj aGlwKTsKPiA+ICsgICAgIHN0cnVjdCBwd21fc3RhdGUgY3N0YXRlOwo+ID4gKwo+ID4gKyAgICAg cHdtX2dldF9zdGF0ZShwd20sICZjc3RhdGUpOwo+ID4gKyAgICAgaWYgKCFjc3RhdGUuZW5hYmxl ZCkgewo+ID4gKyAgICAgICAgICAgICByZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoc3VuOGlfcHdt LT5jbGspOwo+ID4gKyAgICAgICAgICAgICBpZiAocmV0KSB7Cj4gPiArICAgICAgICAgICAgICAg ICAgICAgZGV2X2VycihjaGlwLT5kZXYsICJGYWlsZWQgdG8gZW5hYmxlIFBXTSBjbG9ja1xuIik7 Cj4gPiArICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJldDsKPiA+ICsgICAgICAgICAgICAg fQo+ID4gKyAgICAgfQo+ID4gKwo+ID4gKyAgICAgaWYgKChjc3RhdGUucGVyaW9kICE9IHN0YXRl LT5wZXJpb2QpIHx8Cj4gPiArICAgICAgICAgKGNzdGF0ZS5kdXR5X2N5Y2xlICE9IHN0YXRlLT5k dXR5X2N5Y2xlKSkgewo+ID4gKyAgICAgICAgICAgICByZXQgPSBzdW44aV9wd21fY29uZmlnKHN1 bjhpX3B3bSwgcHdtLT5od3B3bSwgc3RhdGUpOwo+ID4gKyAgICAgICAgICAgICBpZiAocmV0KSB7 Cj4gPiArICAgICAgICAgICAgICAgICAgICAgZGV2X2VycihjaGlwLT5kZXYsICJGYWlsZWQgdG8g Y29uZmlnIFBXTVxuIik7Cj4gPiArICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJldDsKPiA+ ICsgICAgICAgICAgICAgfQo+ID4gKyAgICAgfQo+Cj4gU28gdGhpcyBpc24ndCByZWFsbHkgaG93 IGF0b21pYyBpcyBzdXBwb3NlZCB0byB3b3JrLiBUaGUgd2hvbGUgcG9pbnQgb2YKPiB0aGUgc2lu Z2xlIGNhbGxiYWNrIGlzIHRvIGFsbG93IHRoZSBkcml2ZXIgdG8gYXBwbHkgdGhlIGNoYW5nZXMg aW4gYW4KPiBhdG9taWMgd2F5LCB3aGljaCBtZWFucyB0aGF0IGVpdGhlciBldmVyeXRoaW5nIGlz IGFwcGxpZWQgb3Igbm90aGluZyBpcwo+IGFwcGxpZWQuCj4KPiBUaGF0J3Mgbm90IHdoYXQgeW91 IGRvIGhlcmUuIEluIHRoZSBhYm92ZSB5b3UgY2FuIGVuZCB1cCB3aXRoIGFuIGVuYWJsZWQKPiBj bG9jayBidXQgdGhlIHNldHRpbmdzIG5vdCBiZWluZyBhcHBsaWVkLiBTaW1pbGFybHkgc3VuOGlf cHdtX2NvbmZpZygpCj4gY2FuIGFib3J0IGluIGEgbnVtYmVyIG9mIHBsYWNlcywgd2hpY2ggd291 bGQgbGVhdmUgeW91IHdpdGggYSBoYWxmLQo+IGNvbmZpZ3VyZWQgUFdNIGNoYW5uZWwuCj4KPiBJ bnN0ZWFkLCB3aGF0IHlvdSBzaG91bGQgYmUgZG9pbmcgaXMgcHJlY29tcHV0ZSBldmVyeXRoaW5n IGFuZCBjaGVjawo+IHRoYXQgdGhlIGNvbmZpZ3VyYXRpb24gY2FuIGJlIGFwcGxpZWQgYmVmb3Jl IHRvdWNoaW5nIGFueSByZWdpc3RlcnMgb3IKPiBlbmFibGluZyBjbG9ja3MuIE9uY2UgeW91J3Zl IHZhbGlkYXRlIHRoZSBuZXcgc3RhdGUsIHlvdSBuZWVkIHRvIHdyaXRlCj4gZXZlcnl0aGluZyBh bmQgdGhlcmUgc2hvdWxkIGJlIG5vIG1vcmUgcmlzayBvZiBmYWlsdXJlLgo+CgpHb3QgaXQsIGl0 IGlzIHVzZWZ1bCBmb3IgbWUgIQoKPiBUaGllcnJ5Cj4gLS0tLS1CRUdJTiBQR1AgU0lHTkFUVVJF LS0tLS0KPgo+IGlRSXpCQUFCQ0FBZEZpRUVpT3JEQ0FGSnpQZkFqY2lmM1NPczEzOCtzNkVGQWx3 YjJCNEFDZ2tRM1NPczEzOCsKPiBzNkdtZ1JBQXd2VHloYUZhMGpXbVVmdHorMEZTNUpUWEFEbTlW dXN5aGJTbG1IVjdVTmtxa1F1TG5hVDFXb0dpCj4gZ0dXNVpNTEErd1NQV3JYcUdzdzFIdXpMYzU3 YzEvZURRZHhMbWxxQnowTHdyaWJuNzUrMGtpc0V2VjNDUkNFTAo+IFA5VWlUZ011YWxoVGUwREdL Wm1jSEp2VjU2c0VoeDdiMldRODFzT241blp2Q1AvaUZUVVJwNVdTeWsrcGhBeWIKPiBzczlpNWJq d3V4QzM0d0xDMHdDVk52cjJYbHBkRDdDVHkwUi9uYXAxWmEybmY2Q20wVG56R0dQSVlraTEvZ00y Cj4gZlV0WVQvekN2ZkdwK0pHNStSMjc1NVhkb21Yemowdm1YRDdPbXY3NWVLek1iK0hpdm9sbUxQ SkVmVWlQOGMreAo+IFNFbFQvRi9qSWt3dmRCenllUS9zQTh5Ymg0TjBEVmFwblV4QmpyVUJMT01s ck5EbGgrQXBqVU9PcHd5bFFCWFEKPiA2Skttam9Ib0JnMzFsSzlRRVB4b0lvTlAwRmRaQnI2K2xB YVplUU54OTVQZUlDeEQyMUl2UHR1TEVwNGtzYlg3Cj4gZkpzT3hia0J6YklNcEt1eExNM3ZrbDg5 L085SWhQYlZveXZNQVNDUE1tZHdBSUgrTFN5M1N2SUZXYkdRMG5YUwo+IGd3alR6TjRyMUFXbWRY SU4rZmFUNmtobk5ZNjRXb1BkODk2QXlKU1E1bVFzbDQySU1LUmk0MmtwZmVOMy9mOHkKPiB4NGQw N1dTVENSQjR2K09laEpFVlAyV0pOc2JJM0V2dENsYm5nbjY2eFNhYzdrR1NiZzRjcGJXME56a3JG aitUCj4gZE9HMnA5d1VNaWJQQlh6UytWN0p6VHNEZ1I5SkcyZnp4RzhQaEVlc2FHL0J0MzJIZzBZ PQo+ID1TMVd6Cj4gLS0tLS1FTkQgUEdQIFNJR05BVFVSRS0tLS0tCgpfX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpsaW51eC1hcm0ta2VybmVsIG1haWxpbmcg bGlzdApsaW51eC1hcm0ta2VybmVsQGxpc3RzLmluZnJhZGVhZC5vcmcKaHR0cDovL2xpc3RzLmlu ZnJhZGVhZC5vcmcvbWFpbG1hbi9saXN0aW5mby9saW51eC1hcm0ta2VybmVsCg==