From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from galahad.ideasonboard.com ([185.26.127.97]:33874 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753508AbeCTM7C (ORCPT ); Tue, 20 Mar 2018 08:59:02 -0400 From: Laurent Pinchart To: Jacopo Mondi Cc: architt@codeaurora.org, a.hajda@samsung.com, airlied@linux.ie, horms@verge.net.au, magnus.damm@gmail.com, geert@linux-m68k.org, niklas.soderlund@ragnatech.se, sergei.shtylyov@cogentembedded.com, robh+dt@kernel.org, mark.rutland@arm.com, dri-devel@lists.freedesktop.org, linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v6 2/3] drm: bridge: Add thc63lvd1024 LVDS decoder driver Date: Tue, 20 Mar 2018 15:00:06 +0200 Message-ID: <2013431.yq1szSm9OZ@avalon> In-Reply-To: <1521213399-31947-3-git-send-email-jacopo+renesas@jmondi.org> References: <1521213399-31947-1-git-send-email-jacopo+renesas@jmondi.org> <1521213399-31947-3-git-send-email-jacopo+renesas@jmondi.org> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="iso-8859-1" Sender: linux-renesas-soc-owner@vger.kernel.org List-ID: Hi Jacopo, Thank you for the patch. On Friday, 16 March 2018 17:16:38 EET Jacopo Mondi wrote: > Add DRM bridge driver for Thine THC63LVD1024 LVDS to digital parallel > output converter. >=20 > Signed-off-by: Jacopo Mondi > Reviewed-by: Andrzej Hajda > Reviewed-by: Niklas S=F6derlund > --- > drivers/gpu/drm/bridge/Kconfig | 6 + > drivers/gpu/drm/bridge/Makefile | 1 + > drivers/gpu/drm/bridge/thc63lvd1024.c | 255 ++++++++++++++++++++++++++++= +++ > 3 files changed, 262 insertions(+) > create mode 100644 drivers/gpu/drm/bridge/thc63lvd1024.c I'm aware that you started with a generic driver and then moved to a chip- specific driver and that it caused issues. I however believe it was a good= =20 design, but we can make the driver generic later when a second similar chip= =20 will need to be supported. > diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kcon= fig > index 3b99d5a..5815a20 100644 > --- a/drivers/gpu/drm/bridge/Kconfig > +++ b/drivers/gpu/drm/bridge/Kconfig > @@ -92,6 +92,12 @@ config DRM_SII9234 > It is an I2C driver, that detects connection of MHL bridge > and starts encapsulation of HDMI signal. >=20 > +config DRM_THINE_THC63LVD1024 > + tristate "Thine THC63LVD1024 LVDS decoder bridge" > + depends on OF > + ---help--- > + Thine THC63LVD1024 LVDS/parallel converter driver. > + > config DRM_TOSHIBA_TC358767 > tristate "Toshiba TC358767 eDP bridge" > depends on OF > diff --git a/drivers/gpu/drm/bridge/Makefile > b/drivers/gpu/drm/bridge/Makefile index 373eb28..fd90b16 100644 > --- a/drivers/gpu/drm/bridge/Makefile > +++ b/drivers/gpu/drm/bridge/Makefile > @@ -8,6 +8,7 @@ obj-$(CONFIG_DRM_PARADE_PS8622) +=3D parade-ps8622.o > obj-$(CONFIG_DRM_SIL_SII8620) +=3D sil-sii8620.o > obj-$(CONFIG_DRM_SII902X) +=3D sii902x.o > obj-$(CONFIG_DRM_SII9234) +=3D sii9234.o > +obj-$(CONFIG_DRM_THINE_THC63LVD1024) +=3D thc63lvd1024.o > obj-$(CONFIG_DRM_TOSHIBA_TC358767) +=3D tc358767.o > obj-$(CONFIG_DRM_ANALOGIX_DP) +=3D analogix/ > obj-$(CONFIG_DRM_I2C_ADV7511) +=3D adv7511/ > diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c > b/drivers/gpu/drm/bridge/thc63lvd1024.c new file mode 100644 > index 0000000..02a54c2 > --- /dev/null > +++ b/drivers/gpu/drm/bridge/thc63lvd1024.c > @@ -0,0 +1,255 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * THC63LVD1024 LVDS to parallel data DRM bridge driver. > + * > + * Copyright (C) 2018 Jacopo Mondi > + */ > + > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +enum { Please name the enumeration. > + THC63_LVDS_IN0, > + THC63_LVDS_IN1, > + THC63_DIGITAL_OUT0, > + THC63_DIGITAL_OUT1, Strictly speaking LVDS is digital too. Maybe THC63_RGB_OUT* ? > +}; > + > +static const char * const thc63_reg_names[] =3D { > + "vcc", "lvcc", "pvcc", "cvcc", > +}; > + > +struct thc63_dev { > + struct device *dev; > + > + struct regulator *vccs[ARRAY_SIZE(thc63_reg_names)]; > + > + struct gpio_desc *pdwn; > + struct gpio_desc *oe; > + > + struct drm_bridge bridge; > + struct drm_bridge *next; > +}; > + > +static inline struct thc63_dev *to_thc63(struct drm_bridge *bridge) > +{ > + return container_of(bridge, struct thc63_dev, bridge); > +} > + > +static int thc63_attach(struct drm_bridge *bridge) > +{ > + struct thc63_dev *thc63 =3D to_thc63(bridge); > + > + return drm_bridge_attach(bridge->encoder, thc63->next, bridge); > +} > + > +static void thc63_enable(struct drm_bridge *bridge) > +{ > + struct thc63_dev *thc63 =3D to_thc63(bridge); > + struct regulator *vcc; > + int i; > +=20 > + for (i =3D 0; i < ARRAY_SIZE(thc63->vccs); i++) { > + vcc =3D thc63->vccs[i]; > + if (!vcc) > + continue; > + > + if (regulator_enable(vcc)) You can operate on thc63->vccs[i] directly without a local variable, here a= nd=20 below in the functions that handle regulators. > + goto error_vcc_enable; > + } I thought about proposing usage of the regulators bulk API but it doesn't=20 support optional regulators :-( If you agree with my proposal to make all=20 regulators mandatory, please consider the bulk API to simplify power supply= =20 handling. If on the other hand you agree with my proposal to keep the vcc=20 supply only, it won't matter. > + if (thc63->pdwn) > + gpiod_set_value(thc63->pdwn, 0); > + > + if (thc63->oe) > + gpiod_set_value(thc63->oe, 1); > + > + return; > + > +error_vcc_enable: > + dev_err(thc63->dev, "Failed to enable regulator %s\n", > + thc63_reg_names[i]); I'd move the error message right before the goto. > + for (i =3D i - 1; i >=3D 0; i--) { > + vcc =3D thc63->vccs[i]; > + if (!vcc) > + continue; > + > + regulator_disable(vcc); > + } > +} > + > +static void thc63_disable(struct drm_bridge *bridge) > +{ > + struct thc63_dev *thc63 =3D to_thc63(bridge); > + struct regulator *vcc; > + int i; > + > + if (thc63->oe) > + gpiod_set_value(thc63->oe, 0); > + > + if (thc63->pdwn) > + gpiod_set_value(thc63->pdwn, 1); > + > + for (i =3D ARRAY_SIZE(thc63->vccs) - 1; i >=3D 0; i--) { > + vcc =3D thc63->vccs[i]; > + if (!vcc) > + continue; > + > + if (regulator_disable(vcc)) > + dev_dbg(thc63->dev, > + "Failed to disable regulator %s\n", > + thc63_reg_names[i]); > + } > +} > + > +struct drm_bridge_funcs thc63_bridge_func =3D { static const > + .attach =3D thc63_attach, > + .enable =3D thc63_enable, > + .disable =3D thc63_disable, > +}; > + > +static int thc63_parse_dt(struct thc63_dev *thc63) > +{ > + struct device_node *thc63_out; > + struct device_node *remote; > + int ret =3D 0; > + > + thc63_out =3D of_graph_get_endpoint_by_regs(thc63->dev->of_node, > + THC63_DIGITAL_OUT0, -1); > + if (!thc63_out) { > + dev_err(thc63->dev, "Missing endpoint in Port@%u\n", > + THC63_DIGITAL_OUT0); > + return -ENODEV; > + } > + > + remote =3D of_graph_get_remote_port_parent(thc63_out); of_node_put(thc63_out); here, it will simplify error handling. > + if (!remote) { > + dev_err(thc63->dev, "Endpoint in Port@%u unconnected\n", > + THC63_DIGITAL_OUT0); > + ret =3D -ENODEV; > + goto error_put_out_node; > + } > + > + if (!of_device_is_available(remote)) { > + dev_err(thc63->dev, "Port@%u remote endpoint is disabled\n", > + THC63_DIGITAL_OUT0); > + ret =3D -ENODEV; > + goto error_put_remote_node; > + } > + > + thc63->next =3D of_drm_find_bridge(remote); > + if (!thc63->next) > + ret =3D -EPROBE_DEFER; You can add a return 0 here (and a goto in the previous check. Going throug= h=20 error labels in the non-error case is confusing. As a result you can avoid= =20 initializing ret to 0. > +error_put_remote_node: > + of_node_put(remote); > +error_put_out_node: > + of_node_put(thc63_out); > + > + return ret; > +} > + > +static int thc63_gpio_init(struct thc63_dev *thc63) > +{ > + thc63->oe =3D devm_gpiod_get_optional(thc63->dev, "oe", GPIOD_OUT_LOW); > + if (IS_ERR(thc63->oe)) { > + dev_err(thc63->dev, "Unable to get \"oe-gpios\"\n"); You can add the error code to the message, it could be helpful. > + return PTR_ERR(thc63->oe); > + } > + > + thc63->pdwn =3D devm_gpiod_get_optional(thc63->dev, "pdwn", > + GPIOD_OUT_HIGH); > + if (IS_ERR(thc63->pdwn)) { > + dev_err(thc63->dev, "Unable to get \"pdwn-gpios\"\n"); Same here. > + return PTR_ERR(thc63->pdwn); > + } > + > + return 0; > +} > + > +static int thc63_regulator_init(struct thc63_dev *thc63) > +{ > + struct regulator **reg; > + int i; i is never negative, you can make it an unsigned int. > + reg =3D &thc63->vccs[0]; > + for (i =3D 0; i < ARRAY_SIZE(thc63->vccs); i++, reg++) { > + *reg =3D devm_regulator_get_optional(thc63->dev, > + thc63_reg_names[i]); > + if (IS_ERR(*reg)) { > + if (PTR_ERR(*reg) =3D=3D -EPROBE_DEFER) > + return -EPROBE_DEFER; > + *reg =3D NULL; > + } > + } Wouldn't the following be simpler ? for (i =3D 0; i < ARRAY_SIZE(thc63->vccs); i++) { struct regulator *reg; reg =3D devm_regulator_get_optional(thc63->dev, thc63_reg_names[i]); if (IS_ERR(reg)) { if (PTR_ERR(reg) =3D=3D -EPROBE_DEFER) return -EPROBE_DEFER; reg =3D NULL; } thc63->vccs[i] =3D reg; } > + return 0; > +} > + > +static int thc63_probe(struct platform_device *pdev) > +{ > + struct thc63_dev *thc63; > + int ret; > + > + thc63 =3D devm_kzalloc(&pdev->dev, sizeof(*thc63), GFP_KERNEL); > + if (!thc63) > + return -ENOMEM; > + > + thc63->dev =3D &pdev->dev; > + platform_set_drvdata(pdev, thc63); > + > + ret =3D thc63_regulator_init(thc63); > + if (ret) > + return ret; > + > + ret =3D thc63_gpio_init(thc63); > + if (ret) > + return ret; > + > + ret =3D thc63_parse_dt(thc63); > + if (ret) > + return ret; > + > + thc63->bridge.driver_private =3D thc63; > + thc63->bridge.of_node =3D pdev->dev.of_node; > + thc63->bridge.funcs =3D &thc63_bridge_func; > + > + drm_bridge_add(&thc63->bridge); > + > + return 0; > +} > + > +static int thc63_remove(struct platform_device *pdev) > +{ > + struct thc63_dev *thc63 =3D platform_get_drvdata(pdev); > + > + drm_bridge_remove(&thc63->bridge); > + > + return 0; > +} > + > +static const struct of_device_id thc63_match[] =3D { > + { .compatible =3D "thine,thc63lvd1024", }, > + { }, > +}; > +MODULE_DEVICE_TABLE(of, thc63_match); > + > +static struct platform_driver thc63_driver =3D { > + .probe =3D thc63_probe, > + .remove =3D thc63_remove, > + .driver =3D { > + .name =3D "thc63lvd1024", > + .of_match_table =3D thc63_match, > + }, > +}; > +module_platform_driver(thc63_driver); > + > +MODULE_AUTHOR("Jacopo Mondi "); > +MODULE_DESCRIPTION("Thine THC63LVD1024 LVDS decoder DRM bridge driver"); > +MODULE_LICENSE("GPL v2"); =2D-=20 Regards, Laurent Pinchart From mboxrd@z Thu Jan 1 00:00:00 1970 From: Laurent Pinchart Subject: Re: [PATCH v6 2/3] drm: bridge: Add thc63lvd1024 LVDS decoder driver Date: Tue, 20 Mar 2018 15:00:06 +0200 Message-ID: <2013431.yq1szSm9OZ@avalon> References: <1521213399-31947-1-git-send-email-jacopo+renesas@jmondi.org> <1521213399-31947-3-git-send-email-jacopo+renesas@jmondi.org> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <1521213399-31947-3-git-send-email-jacopo+renesas@jmondi.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: Jacopo Mondi Cc: mark.rutland@arm.com, devicetree@vger.kernel.org, sergei.shtylyov@cogentembedded.com, airlied@linux.ie, magnus.damm@gmail.com, linux-kernel@vger.kernel.org, robh+dt@kernel.org, linux-renesas-soc@vger.kernel.org, horms@verge.net.au, geert@linux-m68k.org, dri-devel@lists.freedesktop.org, niklas.soderlund@ragnatech.se List-Id: devicetree@vger.kernel.org SGkgSmFjb3BvLAoKVGhhbmsgeW91IGZvciB0aGUgcGF0Y2guCgpPbiBGcmlkYXksIDE2IE1hcmNo IDIwMTggMTc6MTY6MzggRUVUIEphY29wbyBNb25kaSB3cm90ZToKPiBBZGQgRFJNIGJyaWRnZSBk cml2ZXIgZm9yIFRoaW5lIFRIQzYzTFZEMTAyNCBMVkRTIHRvIGRpZ2l0YWwgcGFyYWxsZWwKPiBv dXRwdXQgY29udmVydGVyLgo+IAo+IFNpZ25lZC1vZmYtYnk6IEphY29wbyBNb25kaSA8amFjb3Bv K3JlbmVzYXNAam1vbmRpLm9yZz4KPiBSZXZpZXdlZC1ieTogQW5kcnplaiBIYWpkYSA8YS5oYWpk YUBzYW1zdW5nLmNvbT4KPiBSZXZpZXdlZC1ieTogTmlrbGFzIFPDtmRlcmx1bmQgPG5pa2xhcy5z b2Rlcmx1bmQrcmVuZXNhc0ByYWduYXRlY2guc2U+Cj4gLS0tCj4gIGRyaXZlcnMvZ3B1L2RybS9i cmlkZ2UvS2NvbmZpZyAgICAgICAgfCAgIDYgKwo+ICBkcml2ZXJzL2dwdS9kcm0vYnJpZGdlL01h a2VmaWxlICAgICAgIHwgICAxICsKPiAgZHJpdmVycy9ncHUvZHJtL2JyaWRnZS90aGM2M2x2ZDEw MjQuYyB8IDI1NSArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrCj4gIDMgZmlsZXMgY2hh bmdlZCwgMjYyIGluc2VydGlvbnMoKykKPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvZ3B1 L2RybS9icmlkZ2UvdGhjNjNsdmQxMDI0LmMKCkknbSBhd2FyZSB0aGF0IHlvdSBzdGFydGVkIHdp dGggYSBnZW5lcmljIGRyaXZlciBhbmQgdGhlbiBtb3ZlZCB0byBhIGNoaXAtCnNwZWNpZmljIGRy aXZlciBhbmQgdGhhdCBpdCBjYXVzZWQgaXNzdWVzLiBJIGhvd2V2ZXIgYmVsaWV2ZSBpdCB3YXMg YSBnb29kIApkZXNpZ24sIGJ1dCB3ZSBjYW4gbWFrZSB0aGUgZHJpdmVyIGdlbmVyaWMgbGF0ZXIg d2hlbiBhIHNlY29uZCBzaW1pbGFyIGNoaXAgCndpbGwgbmVlZCB0byBiZSBzdXBwb3J0ZWQuCgo+ IGRpZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vYnJpZGdlL0tjb25maWcgYi9kcml2ZXJzL2dw dS9kcm0vYnJpZGdlL0tjb25maWcKPiBpbmRleCAzYjk5ZDVhLi41ODE1YTIwIDEwMDY0NAo+IC0t LSBhL2RyaXZlcnMvZ3B1L2RybS9icmlkZ2UvS2NvbmZpZwo+ICsrKyBiL2RyaXZlcnMvZ3B1L2Ry bS9icmlkZ2UvS2NvbmZpZwo+IEBAIC05Miw2ICs5MiwxMiBAQCBjb25maWcgRFJNX1NJSTkyMzQK PiAgCSAgSXQgaXMgYW4gSTJDIGRyaXZlciwgdGhhdCBkZXRlY3RzIGNvbm5lY3Rpb24gb2YgTUhM IGJyaWRnZQo+ICAJICBhbmQgc3RhcnRzIGVuY2Fwc3VsYXRpb24gb2YgSERNSSBzaWduYWwuCj4g Cj4gK2NvbmZpZyBEUk1fVEhJTkVfVEhDNjNMVkQxMDI0Cj4gKwl0cmlzdGF0ZSAiVGhpbmUgVEhD NjNMVkQxMDI0IExWRFMgZGVjb2RlciBicmlkZ2UiCj4gKwlkZXBlbmRzIG9uIE9GCj4gKwktLS1o ZWxwLS0tCj4gKwkgIFRoaW5lIFRIQzYzTFZEMTAyNCBMVkRTL3BhcmFsbGVsIGNvbnZlcnRlciBk cml2ZXIuCj4gKwo+ICBjb25maWcgRFJNX1RPU0hJQkFfVEMzNTg3NjcKPiAgCXRyaXN0YXRlICJU b3NoaWJhIFRDMzU4NzY3IGVEUCBicmlkZ2UiCj4gIAlkZXBlbmRzIG9uIE9GCj4gZGlmZiAtLWdp dCBhL2RyaXZlcnMvZ3B1L2RybS9icmlkZ2UvTWFrZWZpbGUKPiBiL2RyaXZlcnMvZ3B1L2RybS9i cmlkZ2UvTWFrZWZpbGUgaW5kZXggMzczZWIyOC4uZmQ5MGIxNiAxMDA2NDQKPiAtLS0gYS9kcml2 ZXJzL2dwdS9kcm0vYnJpZGdlL01ha2VmaWxlCj4gKysrIGIvZHJpdmVycy9ncHUvZHJtL2JyaWRn ZS9NYWtlZmlsZQo+IEBAIC04LDYgKzgsNyBAQCBvYmotJChDT05GSUdfRFJNX1BBUkFERV9QUzg2 MjIpICs9IHBhcmFkZS1wczg2MjIubwo+ICBvYmotJChDT05GSUdfRFJNX1NJTF9TSUk4NjIwKSAr PSBzaWwtc2lpODYyMC5vCj4gIG9iai0kKENPTkZJR19EUk1fU0lJOTAyWCkgKz0gc2lpOTAyeC5v Cj4gIG9iai0kKENPTkZJR19EUk1fU0lJOTIzNCkgKz0gc2lpOTIzNC5vCj4gK29iai0kKENPTkZJ R19EUk1fVEhJTkVfVEhDNjNMVkQxMDI0KSArPSB0aGM2M2x2ZDEwMjQubwo+ICBvYmotJChDT05G SUdfRFJNX1RPU0hJQkFfVEMzNTg3NjcpICs9IHRjMzU4NzY3Lm8KPiAgb2JqLSQoQ09ORklHX0RS TV9BTkFMT0dJWF9EUCkgKz0gYW5hbG9naXgvCj4gIG9iai0kKENPTkZJR19EUk1fSTJDX0FEVjc1 MTEpICs9IGFkdjc1MTEvCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS9icmlkZ2UvdGhj NjNsdmQxMDI0LmMKPiBiL2RyaXZlcnMvZ3B1L2RybS9icmlkZ2UvdGhjNjNsdmQxMDI0LmMgbmV3 IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwLi4wMmE1NGMyCj4gLS0tIC9kZXYvbnVs bAo+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9icmlkZ2UvdGhjNjNsdmQxMDI0LmMKPiBAQCAtMCww ICsxLDI1NSBAQAo+ICsvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAo+ICsvKgo+ ICsgKiBUSEM2M0xWRDEwMjQgTFZEUyB0byBwYXJhbGxlbCBkYXRhIERSTSBicmlkZ2UgZHJpdmVy Lgo+ICsgKgo+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMTggSmFjb3BvIE1vbmRpIDxqYWNvcG8rcmVu ZXNhc0BqbW9uZGkub3JnPgo+ICsgKi8KPiArCj4gKyNpbmNsdWRlIDxkcm0vZHJtUC5oPgo+ICsj aW5jbHVkZSA8ZHJtL2RybV9icmlkZ2UuaD4KPiArI2luY2x1ZGUgPGRybS9kcm1fcGFuZWwuaD4K PiArCj4gKyNpbmNsdWRlIDxsaW51eC9ncGlvL2NvbnN1bWVyLmg+Cj4gKyNpbmNsdWRlIDxsaW51 eC9vZl9ncmFwaC5oPgo+ICsjaW5jbHVkZSA8bGludXgvcmVndWxhdG9yL2NvbnN1bWVyLmg+Cj4g Kwo+ICtlbnVtIHsKClBsZWFzZSBuYW1lIHRoZSBlbnVtZXJhdGlvbi4KCj4gKwlUSEM2M19MVkRT X0lOMCwKPiArCVRIQzYzX0xWRFNfSU4xLAo+ICsJVEhDNjNfRElHSVRBTF9PVVQwLAo+ICsJVEhD NjNfRElHSVRBTF9PVVQxLAoKU3RyaWN0bHkgc3BlYWtpbmcgTFZEUyBpcyBkaWdpdGFsIHRvby4g TWF5YmUgVEhDNjNfUkdCX09VVCogPwoKPiArfTsKPiArCj4gK3N0YXRpYyBjb25zdCBjaGFyICog Y29uc3QgdGhjNjNfcmVnX25hbWVzW10gPSB7Cj4gKwkidmNjIiwgImx2Y2MiLCAicHZjYyIsICJj dmNjIiwKPiArfTsKPiArCj4gK3N0cnVjdCB0aGM2M19kZXYgewo+ICsJc3RydWN0IGRldmljZSAq ZGV2Owo+ICsKPiArCXN0cnVjdCByZWd1bGF0b3IgKnZjY3NbQVJSQVlfU0laRSh0aGM2M19yZWdf bmFtZXMpXTsKPiArCj4gKwlzdHJ1Y3QgZ3Bpb19kZXNjICpwZHduOwo+ICsJc3RydWN0IGdwaW9f ZGVzYyAqb2U7Cj4gKwo+ICsJc3RydWN0IGRybV9icmlkZ2UgYnJpZGdlOwo+ICsJc3RydWN0IGRy bV9icmlkZ2UgKm5leHQ7Cj4gK307Cj4gKwo+ICtzdGF0aWMgaW5saW5lIHN0cnVjdCB0aGM2M19k ZXYgKnRvX3RoYzYzKHN0cnVjdCBkcm1fYnJpZGdlICpicmlkZ2UpCj4gK3sKPiArCXJldHVybiBj b250YWluZXJfb2YoYnJpZGdlLCBzdHJ1Y3QgdGhjNjNfZGV2LCBicmlkZ2UpOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgaW50IHRoYzYzX2F0dGFjaChzdHJ1Y3QgZHJtX2JyaWRnZSAqYnJpZGdlKQo+ICt7 Cj4gKwlzdHJ1Y3QgdGhjNjNfZGV2ICp0aGM2MyA9IHRvX3RoYzYzKGJyaWRnZSk7Cj4gKwo+ICsJ cmV0dXJuIGRybV9icmlkZ2VfYXR0YWNoKGJyaWRnZS0+ZW5jb2RlciwgdGhjNjMtPm5leHQsIGJy aWRnZSk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHRoYzYzX2VuYWJsZShzdHJ1Y3QgZHJtX2Jy aWRnZSAqYnJpZGdlKQo+ICt7Cj4gKwlzdHJ1Y3QgdGhjNjNfZGV2ICp0aGM2MyA9IHRvX3RoYzYz KGJyaWRnZSk7Cj4gKwlzdHJ1Y3QgcmVndWxhdG9yICp2Y2M7Cj4gKwlpbnQgaTsKPiArIAo+ICsJ Zm9yIChpID0gMDsgaSA8IEFSUkFZX1NJWkUodGhjNjMtPnZjY3MpOyBpKyspIHsKPiArCQl2Y2Mg PSB0aGM2My0+dmNjc1tpXTsKPiArCQlpZiAoIXZjYykKPiArCQkJY29udGludWU7Cj4gKwo+ICsJ CWlmIChyZWd1bGF0b3JfZW5hYmxlKHZjYykpCgpZb3UgY2FuIG9wZXJhdGUgb24gdGhjNjMtPnZj Y3NbaV0gZGlyZWN0bHkgd2l0aG91dCBhIGxvY2FsIHZhcmlhYmxlLCBoZXJlIGFuZCAKYmVsb3cg aW4gdGhlIGZ1bmN0aW9ucyB0aGF0IGhhbmRsZSByZWd1bGF0b3JzLgoKPiArCQkJZ290byBlcnJv cl92Y2NfZW5hYmxlOwo+ICsJfQoKSSB0aG91Z2h0IGFib3V0IHByb3Bvc2luZyB1c2FnZSBvZiB0 aGUgcmVndWxhdG9ycyBidWxrIEFQSSBidXQgaXQgZG9lc24ndCAKc3VwcG9ydCBvcHRpb25hbCBy ZWd1bGF0b3JzIDotKCBJZiB5b3UgYWdyZWUgd2l0aCBteSBwcm9wb3NhbCB0byBtYWtlIGFsbCAK cmVndWxhdG9ycyBtYW5kYXRvcnksIHBsZWFzZSBjb25zaWRlciB0aGUgYnVsayBBUEkgdG8gc2lt cGxpZnkgcG93ZXIgc3VwcGx5IApoYW5kbGluZy4gSWYgb24gdGhlIG90aGVyIGhhbmQgeW91IGFn cmVlIHdpdGggbXkgcHJvcG9zYWwgdG8ga2VlcCB0aGUgdmNjIApzdXBwbHkgb25seSwgaXQgd29u J3QgbWF0dGVyLgoKPiArCWlmICh0aGM2My0+cGR3bikKPiArCQlncGlvZF9zZXRfdmFsdWUodGhj NjMtPnBkd24sIDApOwo+ICsKPiArCWlmICh0aGM2My0+b2UpCj4gKwkJZ3Bpb2Rfc2V0X3ZhbHVl KHRoYzYzLT5vZSwgMSk7Cj4gKwo+ICsJcmV0dXJuOwo+ICsKPiArZXJyb3JfdmNjX2VuYWJsZToK PiArCWRldl9lcnIodGhjNjMtPmRldiwgIkZhaWxlZCB0byBlbmFibGUgcmVndWxhdG9yICVzXG4i LAo+ICsJCXRoYzYzX3JlZ19uYW1lc1tpXSk7CgpJJ2QgbW92ZSB0aGUgZXJyb3IgbWVzc2FnZSBy aWdodCBiZWZvcmUgdGhlIGdvdG8uCgo+ICsJZm9yIChpID0gaSAtIDE7IGkgPj0gMDsgaS0tKSB7 Cj4gKwkJdmNjID0gdGhjNjMtPnZjY3NbaV07Cj4gKwkJaWYgKCF2Y2MpCj4gKwkJCWNvbnRpbnVl Owo+ICsKPiArCQlyZWd1bGF0b3JfZGlzYWJsZSh2Y2MpOwo+ICsJfQo+ICt9Cj4gKwo+ICtzdGF0 aWMgdm9pZCB0aGM2M19kaXNhYmxlKHN0cnVjdCBkcm1fYnJpZGdlICpicmlkZ2UpCj4gK3sKPiAr CXN0cnVjdCB0aGM2M19kZXYgKnRoYzYzID0gdG9fdGhjNjMoYnJpZGdlKTsKPiArCXN0cnVjdCBy ZWd1bGF0b3IgKnZjYzsKPiArCWludCBpOwo+ICsKPiArCWlmICh0aGM2My0+b2UpCj4gKwkJZ3Bp b2Rfc2V0X3ZhbHVlKHRoYzYzLT5vZSwgMCk7Cj4gKwo+ICsJaWYgKHRoYzYzLT5wZHduKQo+ICsJ CWdwaW9kX3NldF92YWx1ZSh0aGM2My0+cGR3biwgMSk7Cj4gKwo+ICsJZm9yIChpID0gQVJSQVlf U0laRSh0aGM2My0+dmNjcykgLSAxOyBpID49IDA7IGktLSkgewo+ICsJCXZjYyA9IHRoYzYzLT52 Y2NzW2ldOwo+ICsJCWlmICghdmNjKQo+ICsJCQljb250aW51ZTsKPiArCj4gKwkJaWYgKHJlZ3Vs YXRvcl9kaXNhYmxlKHZjYykpCj4gKwkJCWRldl9kYmcodGhjNjMtPmRldiwKPiArCQkJCSJGYWls ZWQgdG8gZGlzYWJsZSByZWd1bGF0b3IgJXNcbiIsCj4gKwkJCQl0aGM2M19yZWdfbmFtZXNbaV0p Owo+ICsJfQo+ICt9Cj4gKwo+ICtzdHJ1Y3QgZHJtX2JyaWRnZV9mdW5jcyB0aGM2M19icmlkZ2Vf ZnVuYyA9IHsKCnN0YXRpYyBjb25zdAoKPiArCS5hdHRhY2gJPSB0aGM2M19hdHRhY2gsCj4gKwku ZW5hYmxlID0gdGhjNjNfZW5hYmxlLAo+ICsJLmRpc2FibGUgPSB0aGM2M19kaXNhYmxlLAo+ICt9 Owo+ICsKPiArc3RhdGljIGludCB0aGM2M19wYXJzZV9kdChzdHJ1Y3QgdGhjNjNfZGV2ICp0aGM2 MykKPiArewo+ICsJc3RydWN0IGRldmljZV9ub2RlICp0aGM2M19vdXQ7Cj4gKwlzdHJ1Y3QgZGV2 aWNlX25vZGUgKnJlbW90ZTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCXRoYzYzX291dCA9IG9m X2dyYXBoX2dldF9lbmRwb2ludF9ieV9yZWdzKHRoYzYzLT5kZXYtPm9mX25vZGUsCj4gKwkJCQkJ CSAgVEhDNjNfRElHSVRBTF9PVVQwLCAtMSk7Cj4gKwlpZiAoIXRoYzYzX291dCkgewo+ICsJCWRl dl9lcnIodGhjNjMtPmRldiwgIk1pc3NpbmcgZW5kcG9pbnQgaW4gUG9ydEAldVxuIiwKPiArCQkJ VEhDNjNfRElHSVRBTF9PVVQwKTsKPiArCQlyZXR1cm4gLUVOT0RFVjsKPiArCX0KPiArCj4gKwly ZW1vdGUgPSBvZl9ncmFwaF9nZXRfcmVtb3RlX3BvcnRfcGFyZW50KHRoYzYzX291dCk7CgoJb2Zf bm9kZV9wdXQodGhjNjNfb3V0KTsKCmhlcmUsIGl0IHdpbGwgc2ltcGxpZnkgZXJyb3IgaGFuZGxp bmcuCgo+ICsJaWYgKCFyZW1vdGUpIHsKPiArCQlkZXZfZXJyKHRoYzYzLT5kZXYsICJFbmRwb2lu dCBpbiBQb3J0QCV1IHVuY29ubmVjdGVkXG4iLAo+ICsJCQlUSEM2M19ESUdJVEFMX09VVDApOwo+ ICsJCXJldCA9IC1FTk9ERVY7Cj4gKwkJZ290byBlcnJvcl9wdXRfb3V0X25vZGU7Cj4gKwl9Cj4g Kwo+ICsJaWYgKCFvZl9kZXZpY2VfaXNfYXZhaWxhYmxlKHJlbW90ZSkpIHsKPiArCQlkZXZfZXJy KHRoYzYzLT5kZXYsICJQb3J0QCV1IHJlbW90ZSBlbmRwb2ludCBpcyBkaXNhYmxlZFxuIiwKPiAr CQkJVEhDNjNfRElHSVRBTF9PVVQwKTsKPiArCQlyZXQgPSAtRU5PREVWOwo+ICsJCWdvdG8gZXJy b3JfcHV0X3JlbW90ZV9ub2RlOwo+ICsJfQo+ICsKPiArCXRoYzYzLT5uZXh0ID0gb2ZfZHJtX2Zp bmRfYnJpZGdlKHJlbW90ZSk7Cj4gKwlpZiAoIXRoYzYzLT5uZXh0KQo+ICsJCXJldCA9IC1FUFJP QkVfREVGRVI7CgpZb3UgY2FuIGFkZCBhIHJldHVybiAwIGhlcmUgKGFuZCBhIGdvdG8gaW4gdGhl IHByZXZpb3VzIGNoZWNrLiBHb2luZyB0aHJvdWdoIAplcnJvciBsYWJlbHMgaW4gdGhlIG5vbi1l cnJvciBjYXNlIGlzIGNvbmZ1c2luZy4gQXMgYSByZXN1bHQgeW91IGNhbiBhdm9pZCAKaW5pdGlh bGl6aW5nIHJldCB0byAwLgoKPiArZXJyb3JfcHV0X3JlbW90ZV9ub2RlOgo+ICsJb2Zfbm9kZV9w dXQocmVtb3RlKTsKPiArZXJyb3JfcHV0X291dF9ub2RlOgo+ICsJb2Zfbm9kZV9wdXQodGhjNjNf b3V0KTsKPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHRoYzYzX2dw aW9faW5pdChzdHJ1Y3QgdGhjNjNfZGV2ICp0aGM2MykKPiArewo+ICsJdGhjNjMtPm9lID0gZGV2 bV9ncGlvZF9nZXRfb3B0aW9uYWwodGhjNjMtPmRldiwgIm9lIiwgR1BJT0RfT1VUX0xPVyk7Cj4g KwlpZiAoSVNfRVJSKHRoYzYzLT5vZSkpIHsKPiArCQlkZXZfZXJyKHRoYzYzLT5kZXYsICJVbmFi bGUgdG8gZ2V0IFwib2UtZ3Bpb3NcIlxuIik7CgpZb3UgY2FuIGFkZCB0aGUgZXJyb3IgY29kZSB0 byB0aGUgbWVzc2FnZSwgaXQgY291bGQgYmUgaGVscGZ1bC4KCj4gKwkJcmV0dXJuIFBUUl9FUlIo dGhjNjMtPm9lKTsKPiArCX0KPiArCj4gKwl0aGM2My0+cGR3biA9IGRldm1fZ3Bpb2RfZ2V0X29w dGlvbmFsKHRoYzYzLT5kZXYsICJwZHduIiwKPiArCQkJCQkgICAgICBHUElPRF9PVVRfSElHSCk7 Cj4gKwlpZiAoSVNfRVJSKHRoYzYzLT5wZHduKSkgewo+ICsJCWRldl9lcnIodGhjNjMtPmRldiwg IlVuYWJsZSB0byBnZXQgXCJwZHduLWdwaW9zXCJcbiIpOwoKU2FtZSBoZXJlLgoKPiArCQlyZXR1 cm4gUFRSX0VSUih0aGM2My0+cGR3bik7Cj4gKwl9Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiAr Cj4gK3N0YXRpYyBpbnQgdGhjNjNfcmVndWxhdG9yX2luaXQoc3RydWN0IHRoYzYzX2RldiAqdGhj NjMpCj4gK3sKPiArCXN0cnVjdCByZWd1bGF0b3IgKipyZWc7Cj4gKwlpbnQgaTsKCmkgaXMgbmV2 ZXIgbmVnYXRpdmUsIHlvdSBjYW4gbWFrZSBpdCBhbiB1bnNpZ25lZCBpbnQuCgo+ICsJcmVnID0g JnRoYzYzLT52Y2NzWzBdOwo+ICsJZm9yIChpID0gMDsgaSA8IEFSUkFZX1NJWkUodGhjNjMtPnZj Y3MpOyBpKyssIHJlZysrKSB7Cj4gKwkJKnJlZyA9IGRldm1fcmVndWxhdG9yX2dldF9vcHRpb25h bCh0aGM2My0+ZGV2LAo+ICsJCQkJCQkgICB0aGM2M19yZWdfbmFtZXNbaV0pOwo+ICsJCWlmIChJ U19FUlIoKnJlZykpIHsKPiArCQkJaWYgKFBUUl9FUlIoKnJlZykgPT0gLUVQUk9CRV9ERUZFUikK PiArCQkJCXJldHVybiAtRVBST0JFX0RFRkVSOwo+ICsJCQkqcmVnID0gTlVMTDsKPiArCQl9Cj4g Kwl9CgpXb3VsZG4ndCB0aGUgZm9sbG93aW5nIGJlIHNpbXBsZXIgPwoKCWZvciAoaSA9IDA7IGkg PCBBUlJBWV9TSVpFKHRoYzYzLT52Y2NzKTsgaSsrKSB7CgkJc3RydWN0IHJlZ3VsYXRvciAqcmVn OwoKCQlyZWcgPSBkZXZtX3JlZ3VsYXRvcl9nZXRfb3B0aW9uYWwodGhjNjMtPmRldiwKCQkJCQkJ ICAgdGhjNjNfcmVnX25hbWVzW2ldKTsKCQlpZiAoSVNfRVJSKHJlZykpIHsKCQkJaWYgKFBUUl9F UlIocmVnKSA9PSAtRVBST0JFX0RFRkVSKQoJCQkJcmV0dXJuIC1FUFJPQkVfREVGRVI7CgkJCXJl ZyA9IE5VTEw7CgkJfQoKCQl0aGM2My0+dmNjc1tpXSA9IHJlZzsKCX0KCj4gKwlyZXR1cm4gMDsK PiArfQo+ICsKPiArc3RhdGljIGludCB0aGM2M19wcm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNl ICpwZGV2KQo+ICt7Cj4gKwlzdHJ1Y3QgdGhjNjNfZGV2ICp0aGM2MzsKPiArCWludCByZXQ7Cj4g Kwo+ICsJdGhjNjMgPSBkZXZtX2t6YWxsb2MoJnBkZXYtPmRldiwgc2l6ZW9mKCp0aGM2MyksIEdG UF9LRVJORUwpOwo+ICsJaWYgKCF0aGM2MykKPiArCQlyZXR1cm4gLUVOT01FTTsKPiArCj4gKwl0 aGM2My0+ZGV2ID0gJnBkZXYtPmRldjsKPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIHRo YzYzKTsKPiArCj4gKwlyZXQgPSB0aGM2M19yZWd1bGF0b3JfaW5pdCh0aGM2Myk7Cj4gKwlpZiAo cmV0KQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJcmV0ID0gdGhjNjNfZ3Bpb19pbml0KHRoYzYz KTsKPiArCWlmIChyZXQpCj4gKwkJcmV0dXJuIHJldDsKPiArCj4gKwlyZXQgPSB0aGM2M19wYXJz ZV9kdCh0aGM2Myk7Cj4gKwlpZiAocmV0KQo+ICsJCXJldHVybiByZXQ7Cj4gKwo+ICsJdGhjNjMt PmJyaWRnZS5kcml2ZXJfcHJpdmF0ZSA9IHRoYzYzOwo+ICsJdGhjNjMtPmJyaWRnZS5vZl9ub2Rl ID0gcGRldi0+ZGV2Lm9mX25vZGU7Cj4gKwl0aGM2My0+YnJpZGdlLmZ1bmNzID0gJnRoYzYzX2Jy aWRnZV9mdW5jOwo+ICsKPiArCWRybV9icmlkZ2VfYWRkKCZ0aGM2My0+YnJpZGdlKTsKPiArCj4g KwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCB0aGM2M19yZW1vdmUoc3RydWN0IHBs YXRmb3JtX2RldmljZSAqcGRldikKPiArewo+ICsJc3RydWN0IHRoYzYzX2RldiAqdGhjNjMgPSBw bGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsKPiArCj4gKwlkcm1fYnJpZGdlX3JlbW92ZSgmdGhj NjMtPmJyaWRnZSk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyBjb25zdCBz dHJ1Y3Qgb2ZfZGV2aWNlX2lkIHRoYzYzX21hdGNoW10gPSB7Cj4gKwl7IC5jb21wYXRpYmxlID0g InRoaW5lLHRoYzYzbHZkMTAyNCIsIH0sCj4gKwl7IH0sCj4gK307Cj4gK01PRFVMRV9ERVZJQ0Vf VEFCTEUob2YsIHRoYzYzX21hdGNoKTsKPiArCj4gK3N0YXRpYyBzdHJ1Y3QgcGxhdGZvcm1fZHJp dmVyIHRoYzYzX2RyaXZlciA9IHsKPiArCS5wcm9iZQk9IHRoYzYzX3Byb2JlLAo+ICsJLnJlbW92 ZQk9IHRoYzYzX3JlbW92ZSwKPiArCS5kcml2ZXIJPSB7Cj4gKwkJLm5hbWUJCT0gInRoYzYzbHZk MTAyNCIsCj4gKwkJLm9mX21hdGNoX3RhYmxlCT0gdGhjNjNfbWF0Y2gsCj4gKwl9LAo+ICt9Owo+ ICttb2R1bGVfcGxhdGZvcm1fZHJpdmVyKHRoYzYzX2RyaXZlcik7Cj4gKwo+ICtNT0RVTEVfQVVU SE9SKCJKYWNvcG8gTW9uZGkgPGphY29wb0BqbW9uZGkub3JnPiIpOwo+ICtNT0RVTEVfREVTQ1JJ UFRJT04oIlRoaW5lIFRIQzYzTFZEMTAyNCBMVkRTIGRlY29kZXIgRFJNIGJyaWRnZSBkcml2ZXIi KTsKPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCB2MiIpOwoKLS0gClJlZ2FyZHMsCgpMYXVyZW50IFBp bmNoYXJ0CgpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpk cmktZGV2ZWwgbWFpbGluZyBsaXN0CmRyaS1kZXZlbEBsaXN0cy5mcmVlZGVza3RvcC5vcmcKaHR0 cHM6Ly9saXN0cy5mcmVlZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0aW5mby9kcmktZGV2ZWwK