From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752715AbeEOIK2 (ORCPT ); Tue, 15 May 2018 04:10:28 -0400 Received: from lb2-smtp-cloud9.xs4all.net ([194.109.24.26]:41214 "EHLO lb2-smtp-cloud9.xs4all.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752443AbeEOIKW (ORCPT ); Tue, 15 May 2018 04:10:22 -0400 Subject: Re: [RFC PATCH 5/5] media: platform: Add Chrome OS EC CEC driver To: Neil Armstrong , airlied@linux.ie, hans.verkuil@cisco.com, lee.jones@linaro.org, olof@lixom.net, seanpaul@google.com Cc: sadolfsson@google.com, felixe@google.com, bleung@google.com, darekm@google.com, marcheu@chromium.org, fparent@baylibre.com, dri-devel@lists.freedesktop.org, linux-media@vger.kernel.org, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org References: <1526337639-3568-1-git-send-email-narmstrong@baylibre.com> <1526337639-3568-6-git-send-email-narmstrong@baylibre.com> From: Hans Verkuil Message-ID: <331d45a4-e496-d0f0-5a0b-ead2cc66da6f@xs4all.nl> Date: Tue, 15 May 2018 10:10:14 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-CMAE-Envelope: MS4wfAG+0tkO8BQPTqxwH4xYiVRkfsZYUnHoZIAvYBKpekjwC5Pj7zddXXZ4q3eEIMclPT+uPtLL86QiNBdBzDUZcu3y+ldi9oIToEVHlc/+DX6hZtlW7has qTMKKxu6b5KA6U3uUN+YEPNV/aoB8pzMmMod3YJUXEhbhCDDBQYpbIG661Lh3OYkSNdY8s2R6xyrJP5PbsyBR2EZVAdCXLalZAfxZoDjMWbLlLfKumMI6TR/ yGDMMXjalKQU5JlDP5+thiIwzg42TLj67cM6Uys9CfY/VhE4Rmm69C2JBddArjs4nV5OYEMvKFnxRHccaM9roHGumiAyJip1ruoWoxGpGhiUSPoc8uzPEIAR cD2215w7iW7yW8W4AY33WPdw96YR3kxQoZhqB59hRo5vmSmfyh3WwzoV98ZkDTxIM3sUrXLN+X9gc+6ACmK0vcDZeGHs3wZyUjCTE51S3cNOGlW/RlC8T8RW jo/zknNuPc5PMjWdfdZclwDF0KIhUDNSDdMa0J/bzJypOgEqQu6wzkUYc51NVjubMyv7woCJofUQ/RTmOFrFPy3xLb1y/z4N/+pO2Xsv39rqWi+/Ewa3XG23 MWUPEEZIs+qV7LLbHESQaOFTa58xiBO51CS9LjJ1uy0+Zs2PXBKQYX59v1xk9n0W/sz4tALTQfV5hLqq3jduqp90L/yQ6emBdrYGToahyhlxWjpgO8/G/sr0 /pGmxhnPRVKTWOQWRNhRM+4JHy9U5F/rcWRiQRAI02W+zMf8QWX16AoqJa626A59cYOQhcaswqpBYKcnMYHYaXHtzKonWdeGjOge4qFIqKBjD1Y/MZIUYw== Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 05/15/18 09:25, Neil Armstrong wrote: > Hi Hans, > > Thanks for the extensive review. > > On 15/05/2018 08:58, Hans Verkuil wrote: >> On 05/15/2018 12:40 AM, Neil Armstrong wrote: >>> The Chrome OS Embedded Controller can expose a CEC bus, this patch add the >>> driver for such feature of the Embedded Controller. >>> >>> This driver is part of the cros-ec MFD and will be add as a sub-device when >>> the feature bit is exposed by the EC. >>> >>> The controller will only handle a single logical address and handles >>> all the messages retries and will only expose Success or Error. >>> >>> When the logical address is invalid, the controller will act as a CEC sniffer >>> and transfer all messages on the bus. >> >> I did not see any support for this. If this works as you state here, then adding >> support for CEC_CAP_MONITOR_ALL is highly recommended. > > Oops, I forgot to remove this phrase, the FW will maybe support it, but it has been > dropped for the first revision. > >> >>> >>> Signed-off-by: Neil Armstrong >>> --- >>> drivers/media/platform/Kconfig | 11 + >>> drivers/media/platform/Makefile | 2 + >>> drivers/media/platform/cros-ec/Makefile | 1 + >>> drivers/media/platform/cros-ec/cros-ec-cec.c | 331 +++++++++++++++++++++++++++ >>> 4 files changed, 345 insertions(+) >>> create mode 100644 drivers/media/platform/cros-ec/Makefile >>> create mode 100644 drivers/media/platform/cros-ec/cros-ec-cec.c >> >> Shouldn't the directory be called cros-ec-cec? >> >>> >>> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig >>> index c7a1cf8..e55a8ed2 100644 >>> --- a/drivers/media/platform/Kconfig >>> +++ b/drivers/media/platform/Kconfig >>> @@ -546,6 +546,17 @@ menuconfig CEC_PLATFORM_DRIVERS >>> >>> if CEC_PLATFORM_DRIVERS >>> >>> +config VIDEO_CROS_EC_CEC >>> + tristate "Chrome OS EC CEC driver" >>> + depends on MFD_CROS_EC || COMPILE_TEST >>> + select CEC_CORE >>> + select CEC_NOTIFIER >>> + ---help--- >>> + If you say yes here you will get support for the >>> + Chrome OS Embedded Controller's CEC. >>> + The CEC bus is present in the HDMI connector and enables communication >>> + between compatible devices. >>> + >>> config VIDEO_MESON_AO_CEC >>> tristate "Amlogic Meson AO CEC driver" >>> depends on ARCH_MESON || COMPILE_TEST >>> diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile >>> index 932515d..0e0582e 100644 >>> --- a/drivers/media/platform/Makefile >>> +++ b/drivers/media/platform/Makefile >>> @@ -92,3 +92,5 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom/camss-8x16/ >>> obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/ >>> >>> obj-y += meson/ >>> + >>> +obj-y += cros-ec/ >>> diff --git a/drivers/media/platform/cros-ec/Makefile b/drivers/media/platform/cros-ec/Makefile >>> new file mode 100644 >>> index 0000000..9ce97f9 >>> --- /dev/null >>> +++ b/drivers/media/platform/cros-ec/Makefile >>> @@ -0,0 +1 @@ >>> +obj-$(CONFIG_VIDEO_CROS_EC_CEC) += cros-ec-cec.o >>> diff --git a/drivers/media/platform/cros-ec/cros-ec-cec.c b/drivers/media/platform/cros-ec/cros-ec-cec.c >>> new file mode 100644 >>> index 0000000..fea90da >>> --- /dev/null >>> +++ b/drivers/media/platform/cros-ec/cros-ec-cec.c >>> @@ -0,0 +1,331 @@ >>> +// SPDX-License-Identifier: GPL-2.0+ >>> +/* >>> + * CEC driver for Chrome OS Embedded Controller >>> + * >>> + * Copyright (c) 2018 BayLibre, SAS >>> + * Author: Neil Armstrong >>> + */ >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#define DRV_NAME "cros-ec-cec" >>> + >>> +/** >>> + * struct cros_ec_cec - Driver data for EC CEC >>> + * >>> + * @cros_ec: Pointer to EC device >>> + * @notifier: Notifier info for responding to EC events >>> + * @adap: CEC adapter >>> + * @notify: CEC notifier pointer >>> + * @rc_msg: storage for a received message >>> + */ >>> +struct cros_ec_cec { >>> + struct cros_ec_device *cros_ec; >>> + struct notifier_block notifier; >>> + struct cec_adapter *adap; >>> + struct cec_notifier *notify; >>> + struct cec_msg rx_msg; >>> +}; >>> + >>> +static void handle_cec_message(struct cros_ec_cec *cros_ec_cec) >>> +{ >>> + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; >>> + uint8_t *cec_message = cros_ec->event_data.data.cec_message; >>> + unsigned int len = cros_ec->event_size; >>> + >>> + cros_ec_cec->rx_msg.len = len; >> >> How robust is the underlying code and hardware? What happens if a >> CEC message with more than 16 bytes is received? >> >> Hard to test unless you have an RPi3 set up as a CEC debugger. See >> last section in https://hverkuil.home.xs4all.nl/cec-status.txt. >> >> Since you worked with CEC for a while now I recommend you set up such >> a system. It's cheap and very useful. > > I will definitely setup this kind of system, I tried using am Amlogic SoC, but it really can't monitor the bus.... > > But I also have an ST STM32F0 Development board with double HDMI connector to develop CEC, I'll maybe try to use it for that purpose. You really want a setup that uses the cec-gpio driver since that allows you to do CEC error injection. If you can hook up the CEC pin to a GPIO on the stm32 board, than that should work just as well as with the RPi3. > >> >>> + memcpy(cros_ec_cec->rx_msg.msg, cec_message, len); >>> + >>> + cec_received_msg(cros_ec_cec->adap, &cros_ec_cec->rx_msg); >>> +} >>> + >>> +static void handle_cec_event(struct cros_ec_cec *cros_ec_cec) >>> +{ >>> + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; >>> + uint32_t events = cros_ec->event_data.data.cec_events; >>> + >>> + if (events & EC_MKBP_CEC_SEND_OK) >>> + cec_transmit_attempt_done(cros_ec_cec->adap, >>> + CEC_TX_STATUS_OK); >>> + >>> + if (events & EC_MKBP_CEC_SEND_FAILED) >>> + cec_transmit_attempt_done(cros_ec_cec->adap, >>> + CEC_TX_STATUS_ERROR); >> >> You said above that the HW takes care of all the message retries. >> If that's the case, then you need to use cec_transmit_done here >> and pass in status CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_NACK. >> The MAX_RETRIES flag tells the cec core that it shouldn't attempt >> to retry the message because the HW already did that. >> >> NACK is better than ERROR if the hardware supports only an OK/FAIL >> result. > > Ok, we were unsure about this, thanks for the clarification. > >> >>> +} >>> + >>> +static int cros_ec_cec_event(struct notifier_block *nb, >>> + unsigned long queued_during_suspend, void *_notify) >>> +{ >>> + struct cros_ec_cec *cros_ec_cec; >>> + struct cros_ec_device *cros_ec; >>> + >>> + cros_ec_cec = container_of(nb, struct cros_ec_cec, notifier); >>> + cros_ec = cros_ec_cec->cros_ec; >>> + >>> + if (cros_ec->event_data.event_type == EC_MKBP_CEC_EVENT) { >>> + handle_cec_event(cros_ec_cec); >>> + return NOTIFY_OK; >>> + } >>> + >>> + if (cros_ec->event_data.event_type == EC_MKBP_EVENT_CEC_MESSAGE) { >>> + handle_cec_message(cros_ec_cec); >>> + return NOTIFY_OK; >>> + } >>> + >>> + return NOTIFY_DONE; >>> +} >>> + >>> +static int cros_ec_cec_set_log_addr(struct cec_adapter *adap, u8 logical_addr) >>> +{ >>> + struct cros_ec_cec *cros_ec_cec = adap->priv; >>> + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; >>> + struct { >>> + struct cros_ec_command msg; >>> + struct ec_params_cec_set data; >>> + } __packed msg; >> >> Just say: ... msg = {}; >> >>> + int ret = 0; >>> + >>> + if (logical_addr == CEC_LOG_ADDR_INVALID) >>> + return 0; >> >> This looks weird. If I had configured a LA before, then this should unconfigure >> it. But it just keeps the existing LA, so any poll messages to us will still >> be Acked. Or am I missing something? Did you miss this comment? It's weird what is happening here. >> >>> + >>> + memset(&msg, 0, sizeof(msg)); >> >> and you can drop this memset. > > I always forget this trick. > >> >>> + msg.msg.command = EC_CMD_CEC_SET; >>> + msg.msg.outsize = sizeof(msg.data); >>> + msg.data.cmd = CEC_CMD_LOGICAL_ADDRESS; >>> + msg.data.address = logical_addr; >>> + >>> + ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); >>> + if (ret < 0) { >>> + dev_err(cros_ec->dev, >>> + "error setting CEC logical address on EC: %d\n", ret); >>> + return ret; >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +static int cros_ec_cec_transmit(struct cec_adapter *adap, u8 attempts, >>> + u32 signal_free_time, struct cec_msg *cec_msg) >>> +{ >>> + struct cros_ec_cec *cros_ec_cec = adap->priv; >>> + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; >>> + struct { >>> + struct cros_ec_command msg; >>> + struct ec_params_cec_write data; >>> + } __packed msg; >> >> ... msg = {}; >> >>> + int ret = 0; >>> + >>> + if (cec_msg->len > MAX_CEC_MSG_LEN) >>> + return -EINVAL; >> >> No need, can never happen. > > Forgor to remove it, the API changed in the meantime, now it can never happen ! > >> >>> + >>> + memset(&msg, 0, sizeof(msg)); >> >> and drop this. >> >>> + msg.msg.command = EC_CMD_CEC_WRITE_MSG; >>> + msg.msg.outsize = cec_msg->len; >>> + memcpy(msg.data.msg, cec_msg->msg, cec_msg->len); >>> + >>> + ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); >>> + if (ret < 0) { >>> + dev_err(cros_ec->dev, >>> + "error writting CEC msg on EC: %d\n", ret); >>> + return ret; >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +static int cros_ec_cec_adap_enable(struct cec_adapter *adap, bool enable) >>> +{ >>> + struct cros_ec_cec *cros_ec_cec = adap->priv; >>> + struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec; >>> + struct { >>> + struct cros_ec_command msg; >>> + struct ec_params_cec_set data; >>> + } __packed msg; >>> + int ret = 0; >>> + >>> + memset(&msg, 0, sizeof(msg)); >>> + msg.msg.command = EC_CMD_CEC_SET; >>> + msg.msg.outsize = sizeof(msg.data); >>> + msg.data.cmd = CEC_CMD_ENABLE; >>> + msg.data.enable = enable; >>> + >>> + ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg); >>> + if (ret < 0) { >>> + dev_err(cros_ec->dev, >>> + "error %sabling CEC on EC: %d\n", >>> + (enable ? "en" : "dis"), ret); >>> + return ret; >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +static const struct cec_adap_ops cros_ec_cec_ops = { >>> + .adap_enable = cros_ec_cec_adap_enable, >>> + .adap_log_addr = cros_ec_cec_set_log_addr, >>> + .adap_transmit = cros_ec_cec_transmit, >>> +}; >>> + >>> +#ifdef CONFIG_PM_SLEEP >>> +static int cros_ec_cec_suspend(struct device *dev) >>> +{ >>> + struct platform_device *pdev = to_platform_device(dev); >>> + struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev); >>> + >>> + if (device_may_wakeup(dev)) >>> + enable_irq_wake(cros_ec_cec->cros_ec->irq); >>> + >>> + return 0; >>> +} >>> + >>> +static int cros_ec_cec_resume(struct device *dev) >>> +{ >>> + struct platform_device *pdev = to_platform_device(dev); >>> + struct cros_ec_cec *cros_ec_cec = dev_get_drvdata(&pdev->dev); >>> + >>> + if (device_may_wakeup(dev)) >>> + disable_irq_wake(cros_ec_cec->cros_ec->irq); >>> + >>> + return 0; >>> +} >>> +#endif >>> + >>> +static SIMPLE_DEV_PM_OPS(cros_ec_cec_pm_ops, >>> + cros_ec_cec_suspend, cros_ec_cec_resume); >>> + >>> + >>> +struct cec_dmi_match { >>> + char *sys_vendor; >>> + char *product_name; >>> + char *devname; >>> + char *conn; >>> +}; >>> + >>> +static const struct cec_dmi_match cec_dmi_match_table[] = { >>> + /* Google Fizz */ >>> + { "Google", "Fizz", "0000:00:02.0", "HDMI-A-1" }, >>> +}; >>> + >>> +static int cros_ec_cec_get_notifier(struct cec_notifier **notify) >>> +{ >>> + int i; >>> + >>> + for (i = 0 ; i < ARRAY_SIZE(cec_dmi_match_table) ; ++i) { >>> + const struct cec_dmi_match *m = &cec_dmi_match_table[i]; >>> + >>> + if (dmi_match(DMI_SYS_VENDOR, m->sys_vendor) && >>> + dmi_match(DMI_PRODUCT_NAME, m->product_name)) { >>> + *notify = cec_notifier_get_byname(m->devname, m->conn); >> >> See my comments for patch 2/5. > > I will change with you comment, looks way cleaner. > >> >>> + return 0; >>> + } >>> + } >>> + >>> + return -EINVAL; >>> +} >>> + >>> +static int cros_ec_cec_probe(struct platform_device *pdev) >>> +{ >>> + struct cros_ec_dev *ec_dev = dev_get_drvdata(pdev->dev.parent); >>> + struct cros_ec_device *cros_ec = ec_dev->ec_dev; >>> + struct cros_ec_cec *cros_ec_cec; >>> + unsigned int cec_caps = CEC_CAP_DEFAULTS; >> >> Does this need CEC_CAP_NEEDS_HPD? Can it still use CEC if there is no HPD >> signal? > > No, Yes, the EC FW is independent of the HPD status > >> >>> + int ret; >>> + >>> + cros_ec_cec = devm_kzalloc(&pdev->dev, sizeof(*cros_ec_cec), >>> + GFP_KERNEL); >>> + if (!cros_ec_cec) >>> + return -ENOMEM; >>> + >>> + platform_set_drvdata(pdev, cros_ec_cec); >>> + cros_ec_cec->cros_ec = cros_ec; >>> + >>> + ret = cros_ec_cec_get_notifier(&cros_ec_cec->notify); >>> + if (ret) { >>> + dev_warn(&pdev->dev, "no CEC notifier available\n"); >>> + cec_caps |= CEC_CAP_PHYS_ADDR; >> >> Can this happen? What hardware has this? I am strongly opposed to CEC drivers >> using this capability unless there is no other option. It's a pain for userspace. > > It's in case an HW having a CEC capable FW but not in the cec_dmi_match_table, in this case > it won't fail but still enable the CEC interface without a notifier. I don't think that's a good idea. CAP_PHYS_ADDR should *only* be used in situations where it is truly impossible to tell which output is connected to the CEC adapter. That's the case with e.g. USB CEC dongles where you have no idea how the user connected the HDMI cables. But I assume that in this case it just means that the cec_dmi_match_table needs to be updated, i.e. it is a driver bug. Another thing: this driver assumes that there is only one CEC adapter for only one HDMI output. But what if there are more HDMI outputs? Will there be one CEC adapter for each output? Or does the hardware have no provisions for that? Something should be mentioned about this in a comment. Regards, Hans > >> >>> + } else if (!cros_ec_cec->notify) { >>> + return -EPROBE_DEFER; >>> + } >>> + >>> + ret = device_init_wakeup(&pdev->dev, 1); >>> + if (ret) { >>> + dev_err(&pdev->dev, "failed to initialize wakeup\n"); >>> + return ret; >>> + } >>> + >>> + cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec, >>> + DRV_NAME, cec_caps, 1); >>> + if (IS_ERR(cros_ec_cec->adap)) >>> + return PTR_ERR(cros_ec_cec->adap); >>> + >>> + cros_ec_cec->adap->owner = THIS_MODULE; >> >> This can be dropped, cec_register_adapter() sets this already. > > Noted. > >> >>> + >>> + /* Get CEC events from the EC. */ >>> + cros_ec_cec->notifier.notifier_call = cros_ec_cec_event; >>> + ret = blocking_notifier_chain_register(&cros_ec->event_notifier, >>> + &cros_ec_cec->notifier); >>> + if (ret) { >>> + dev_err(&pdev->dev, "failed to register notifier\n"); >>> + cec_delete_adapter(cros_ec_cec->adap); >>> + return ret; >>> + } >>> + >>> + ret = cec_register_adapter(cros_ec_cec->adap, &pdev->dev); >>> + if (ret < 0) { >>> + cec_delete_adapter(cros_ec_cec->adap); >>> + return ret; >>> + } >>> + >>> + cec_register_cec_notifier(cros_ec_cec->adap, cros_ec_cec->notify); >>> + >>> + return 0; >>> +} >>> + >>> +static int cros_ec_cec_remove(struct platform_device *pdev) >>> +{ >>> + struct cros_ec_cec *cros_ec_cec = platform_get_drvdata(pdev); >>> + struct device *dev = &pdev->dev; >>> + int ret; >>> + >>> + ret = blocking_notifier_chain_unregister( >>> + &cros_ec_cec->cros_ec->event_notifier, >>> + &cros_ec_cec->notifier); >>> + >>> + if (ret) { >>> + dev_err(dev, "failed to unregister notifier\n"); >>> + return ret; >>> + } >>> + >>> + cec_unregister_adapter(cros_ec_cec->adap); >>> + >>> + if (cros_ec_cec->notify) >>> + cec_notifier_put(cros_ec_cec->notify); >>> + >>> + return 0; >>> +} >>> + >>> +static struct platform_driver cros_ec_cec_driver = { >>> + .probe = cros_ec_cec_probe, >>> + .remove = cros_ec_cec_remove, >>> + .driver = { >>> + .name = DRV_NAME, >>> + .pm = &cros_ec_cec_pm_ops, >>> + }, >>> +}; >>> + >>> +module_platform_driver(cros_ec_cec_driver); >>> + >>> +MODULE_DESCRIPTION("CEC driver for Chrome OS ECs"); >>> +MODULE_AUTHOR("Neil Armstrong "); >>> +MODULE_LICENSE("GPL"); >>> +MODULE_ALIAS("platform:" DRV_NAME); >>> >> >> Regards, >> >> Hans >> > > Thanks, > Neil > From mboxrd@z Thu Jan 1 00:00:00 1970 From: Hans Verkuil Subject: Re: [RFC PATCH 5/5] media: platform: Add Chrome OS EC CEC driver Date: Tue, 15 May 2018 10:10:14 +0200 Message-ID: <331d45a4-e496-d0f0-5a0b-ead2cc66da6f@xs4all.nl> References: <1526337639-3568-1-git-send-email-narmstrong@baylibre.com> <1526337639-3568-6-git-send-email-narmstrong@baylibre.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: Content-Language: en-US List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" To: Neil Armstrong , airlied@linux.ie, hans.verkuil@cisco.com, lee.jones@linaro.org, olof@lixom.net, seanpaul@google.com Cc: sadolfsson@google.com, intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, fparent@baylibre.com, felixe@google.com, bleung@google.com, darekm@google.com, linux-media@vger.kernel.org List-Id: dri-devel@lists.freedesktop.org T24gMDUvMTUvMTggMDk6MjUsIE5laWwgQXJtc3Ryb25nIHdyb3RlOgo+IEhpIEhhbnMsCj4gCj4g VGhhbmtzIGZvciB0aGUgZXh0ZW5zaXZlIHJldmlldy4KPiAKPiBPbiAxNS8wNS8yMDE4IDA4OjU4 LCBIYW5zIFZlcmt1aWwgd3JvdGU6Cj4+IE9uIDA1LzE1LzIwMTggMTI6NDAgQU0sIE5laWwgQXJt c3Ryb25nIHdyb3RlOgo+Pj4gVGhlIENocm9tZSBPUyBFbWJlZGRlZCBDb250cm9sbGVyIGNhbiBl eHBvc2UgYSBDRUMgYnVzLCB0aGlzIHBhdGNoIGFkZCB0aGUKPj4+IGRyaXZlciBmb3Igc3VjaCBm ZWF0dXJlIG9mIHRoZSBFbWJlZGRlZCBDb250cm9sbGVyLgo+Pj4KPj4+IFRoaXMgZHJpdmVyIGlz IHBhcnQgb2YgdGhlIGNyb3MtZWMgTUZEIGFuZCB3aWxsIGJlIGFkZCBhcyBhIHN1Yi1kZXZpY2Ug d2hlbgo+Pj4gdGhlIGZlYXR1cmUgYml0IGlzIGV4cG9zZWQgYnkgdGhlIEVDLgo+Pj4KPj4+IFRo ZSBjb250cm9sbGVyIHdpbGwgb25seSBoYW5kbGUgYSBzaW5nbGUgbG9naWNhbCBhZGRyZXNzIGFu ZCBoYW5kbGVzCj4+PiBhbGwgdGhlIG1lc3NhZ2VzIHJldHJpZXMgYW5kIHdpbGwgb25seSBleHBv c2UgU3VjY2VzcyBvciBFcnJvci4KPj4+Cj4+PiBXaGVuIHRoZSBsb2dpY2FsIGFkZHJlc3MgaXMg aW52YWxpZCwgdGhlIGNvbnRyb2xsZXIgd2lsbCBhY3QgYXMgYSBDRUMgc25pZmZlcgo+Pj4gYW5k IHRyYW5zZmVyIGFsbCBtZXNzYWdlcyBvbiB0aGUgYnVzLgo+Pgo+PiBJIGRpZCBub3Qgc2VlIGFu eSBzdXBwb3J0IGZvciB0aGlzLiBJZiB0aGlzIHdvcmtzIGFzIHlvdSBzdGF0ZSBoZXJlLCB0aGVu IGFkZGluZwo+PiBzdXBwb3J0IGZvciBDRUNfQ0FQX01PTklUT1JfQUxMIGlzIGhpZ2hseSByZWNv bW1lbmRlZC4KPiAKPiBPb3BzLCBJIGZvcmdvdCB0byByZW1vdmUgdGhpcyBwaHJhc2UsIHRoZSBG VyB3aWxsIG1heWJlIHN1cHBvcnQgaXQsIGJ1dCBpdCBoYXMgYmVlbgo+IGRyb3BwZWQgZm9yIHRo ZSBmaXJzdCByZXZpc2lvbi4KPiAKPj4KPj4+Cj4+PiBTaWduZWQtb2ZmLWJ5OiBOZWlsIEFybXN0 cm9uZyA8bmFybXN0cm9uZ0BiYXlsaWJyZS5jb20+Cj4+PiAtLS0KPj4+ICBkcml2ZXJzL21lZGlh L3BsYXRmb3JtL0tjb25maWcgICAgICAgICAgICAgICB8ICAxMSArCj4+PiAgZHJpdmVycy9tZWRp YS9wbGF0Zm9ybS9NYWtlZmlsZSAgICAgICAgICAgICAgfCAgIDIgKwo+Pj4gIGRyaXZlcnMvbWVk aWEvcGxhdGZvcm0vY3Jvcy1lYy9NYWtlZmlsZSAgICAgIHwgICAxICsKPj4+ICBkcml2ZXJzL21l ZGlhL3BsYXRmb3JtL2Nyb3MtZWMvY3Jvcy1lYy1jZWMuYyB8IDMzMSArKysrKysrKysrKysrKysr KysrKysrKysrKysKPj4+ICA0IGZpbGVzIGNoYW5nZWQsIDM0NSBpbnNlcnRpb25zKCspCj4+PiAg Y3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvbWVkaWEvcGxhdGZvcm0vY3Jvcy1lYy9NYWtlZmls ZQo+Pj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21lZGlhL3BsYXRmb3JtL2Nyb3MtZWMv Y3Jvcy1lYy1jZWMuYwo+Pgo+PiBTaG91bGRuJ3QgdGhlIGRpcmVjdG9yeSBiZSBjYWxsZWQgY3Jv cy1lYy1jZWM/Cj4+Cj4+Pgo+Pj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0v S2NvbmZpZyBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vS2NvbmZpZwo+Pj4gaW5kZXggYzdhMWNm OC4uZTU1YThlZDIgMTAwNjQ0Cj4+PiAtLS0gYS9kcml2ZXJzL21lZGlhL3BsYXRmb3JtL0tjb25m aWcKPj4+ICsrKyBiL2RyaXZlcnMvbWVkaWEvcGxhdGZvcm0vS2NvbmZpZwo+Pj4gQEAgLTU0Niw2 ICs1NDYsMTcgQEAgbWVudWNvbmZpZyBDRUNfUExBVEZPUk1fRFJJVkVSUwo+Pj4gIAo+Pj4gIGlm IENFQ19QTEFURk9STV9EUklWRVJTCj4+PiAgCj4+PiArY29uZmlnIFZJREVPX0NST1NfRUNfQ0VD Cj4+PiArCXRyaXN0YXRlICJDaHJvbWUgT1MgRUMgQ0VDIGRyaXZlciIKPj4+ICsJZGVwZW5kcyBv biBNRkRfQ1JPU19FQyB8fCBDT01QSUxFX1RFU1QKPj4+ICsJc2VsZWN0IENFQ19DT1JFCj4+PiAr CXNlbGVjdCBDRUNfTk9USUZJRVIKPj4+ICsJLS0taGVscC0tLQo+Pj4gKwkgIElmIHlvdSBzYXkg eWVzIGhlcmUgeW91IHdpbGwgZ2V0IHN1cHBvcnQgZm9yIHRoZQo+Pj4gKwkgIENocm9tZSBPUyBF bWJlZGRlZCBDb250cm9sbGVyJ3MgQ0VDLgo+Pj4gKwkgIFRoZSBDRUMgYnVzIGlzIHByZXNlbnQg aW4gdGhlIEhETUkgY29ubmVjdG9yIGFuZCBlbmFibGVzIGNvbW11bmljYXRpb24KPj4+ICsJICBi ZXR3ZWVuIGNvbXBhdGlibGUgZGV2aWNlcy4KPj4+ICsKPj4+ICBjb25maWcgVklERU9fTUVTT05f QU9fQ0VDCj4+PiAgCXRyaXN0YXRlICJBbWxvZ2ljIE1lc29uIEFPIENFQyBkcml2ZXIiCj4+PiAg CWRlcGVuZHMgb24gQVJDSF9NRVNPTiB8fCBDT01QSUxFX1RFU1QKPj4+IGRpZmYgLS1naXQgYS9k cml2ZXJzL21lZGlhL3BsYXRmb3JtL01ha2VmaWxlIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9N YWtlZmlsZQo+Pj4gaW5kZXggOTMyNTE1ZC4uMGUwNTgyZSAxMDA2NDQKPj4+IC0tLSBhL2RyaXZl cnMvbWVkaWEvcGxhdGZvcm0vTWFrZWZpbGUKPj4+ICsrKyBiL2RyaXZlcnMvbWVkaWEvcGxhdGZv cm0vTWFrZWZpbGUKPj4+IEBAIC05MiwzICs5Miw1IEBAIG9iai0kKENPTkZJR19WSURFT19RQ09N X0NBTVNTKQkJKz0gcWNvbS9jYW1zcy04eDE2Lwo+Pj4gIG9iai0kKENPTkZJR19WSURFT19RQ09N X1ZFTlVTKQkJKz0gcWNvbS92ZW51cy8KPj4+ICAKPj4+ICBvYmoteQkJCQkJKz0gbWVzb24vCj4+ PiArCj4+PiArb2JqLXkJCQkJCSs9IGNyb3MtZWMvCj4+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9t ZWRpYS9wbGF0Zm9ybS9jcm9zLWVjL01ha2VmaWxlIGIvZHJpdmVycy9tZWRpYS9wbGF0Zm9ybS9j cm9zLWVjL01ha2VmaWxlCj4+PiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+Pj4gaW5kZXggMDAwMDAw MC4uOWNlOTdmOQo+Pj4gLS0tIC9kZXYvbnVsbAo+Pj4gKysrIGIvZHJpdmVycy9tZWRpYS9wbGF0 Zm9ybS9jcm9zLWVjL01ha2VmaWxlCj4+PiBAQCAtMCwwICsxIEBACj4+PiArb2JqLSQoQ09ORklH X1ZJREVPX0NST1NfRUNfQ0VDKSArPSBjcm9zLWVjLWNlYy5vCj4+PiBkaWZmIC0tZ2l0IGEvZHJp dmVycy9tZWRpYS9wbGF0Zm9ybS9jcm9zLWVjL2Nyb3MtZWMtY2VjLmMgYi9kcml2ZXJzL21lZGlh L3BsYXRmb3JtL2Nyb3MtZWMvY3Jvcy1lYy1jZWMuYwo+Pj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQK Pj4+IGluZGV4IDAwMDAwMDAuLmZlYTkwZGEKPj4+IC0tLSAvZGV2L251bGwKPj4+ICsrKyBiL2Ry aXZlcnMvbWVkaWEvcGxhdGZvcm0vY3Jvcy1lYy9jcm9zLWVjLWNlYy5jCj4+PiBAQCAtMCwwICsx LDMzMSBAQAo+Pj4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wKwo+Pj4gKy8q Cj4+PiArICogQ0VDIGRyaXZlciBmb3IgQ2hyb21lIE9TIEVtYmVkZGVkIENvbnRyb2xsZXIKPj4+ ICsgKgo+Pj4gKyAqIENvcHlyaWdodCAoYykgMjAxOCBCYXlMaWJyZSwgU0FTCj4+PiArICogQXV0 aG9yOiBOZWlsIEFybXN0cm9uZyA8bmFybXN0cm9uZ0BiYXlsaWJyZS5jb20+Cj4+PiArICovCj4+ PiArCj4+PiArI2luY2x1ZGUgPGxpbnV4L2tlcm5lbC5oPgo+Pj4gKyNpbmNsdWRlIDxsaW51eC9t b2R1bGUuaD4KPj4+ICsjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+Cj4+PiArI2lu Y2x1ZGUgPGxpbnV4L2RtaS5oPgo+Pj4gKyNpbmNsdWRlIDxsaW51eC9jZWMuaD4KPj4+ICsjaW5j bHVkZSA8bGludXgvc2xhYi5oPgo+Pj4gKyNpbmNsdWRlIDxsaW51eC9pbnRlcnJ1cHQuaD4KPj4+ ICsjaW5jbHVkZSA8bWVkaWEvY2VjLmg+Cj4+PiArI2luY2x1ZGUgPG1lZGlhL2NlYy1ub3RpZmll ci5oPgo+Pj4gKyNpbmNsdWRlIDxsaW51eC9tZmQvY3Jvc19lYy5oPgo+Pj4gKyNpbmNsdWRlIDxs aW51eC9tZmQvY3Jvc19lY19jb21tYW5kcy5oPgo+Pj4gKwo+Pj4gKyNkZWZpbmUgRFJWX05BTUUJ ImNyb3MtZWMtY2VjIgo+Pj4gKwo+Pj4gKy8qKgo+Pj4gKyAqIHN0cnVjdCBjcm9zX2VjX2NlYyAt IERyaXZlciBkYXRhIGZvciBFQyBDRUMKPj4+ICsgKgo+Pj4gKyAqIEBjcm9zX2VjOiBQb2ludGVy IHRvIEVDIGRldmljZQo+Pj4gKyAqIEBub3RpZmllcjogTm90aWZpZXIgaW5mbyBmb3IgcmVzcG9u ZGluZyB0byBFQyBldmVudHMKPj4+ICsgKiBAYWRhcDogQ0VDIGFkYXB0ZXIKPj4+ICsgKiBAbm90 aWZ5OiBDRUMgbm90aWZpZXIgcG9pbnRlcgo+Pj4gKyAqIEByY19tc2c6IHN0b3JhZ2UgZm9yIGEg cmVjZWl2ZWQgbWVzc2FnZQo+Pj4gKyAqLwo+Pj4gK3N0cnVjdCBjcm9zX2VjX2NlYyB7Cj4+PiAr CXN0cnVjdCBjcm9zX2VjX2RldmljZSAqY3Jvc19lYzsKPj4+ICsJc3RydWN0IG5vdGlmaWVyX2Js b2NrIG5vdGlmaWVyOwo+Pj4gKwlzdHJ1Y3QgY2VjX2FkYXB0ZXIgKmFkYXA7Cj4+PiArCXN0cnVj dCBjZWNfbm90aWZpZXIgKm5vdGlmeTsKPj4+ICsJc3RydWN0IGNlY19tc2cgcnhfbXNnOwo+Pj4g K307Cj4+PiArCj4+PiArc3RhdGljIHZvaWQgaGFuZGxlX2NlY19tZXNzYWdlKHN0cnVjdCBjcm9z X2VjX2NlYyAqY3Jvc19lY19jZWMpCj4+PiArewo+Pj4gKwlzdHJ1Y3QgY3Jvc19lY19kZXZpY2Ug KmNyb3NfZWMgPSBjcm9zX2VjX2NlYy0+Y3Jvc19lYzsKPj4+ICsJdWludDhfdCAqY2VjX21lc3Nh Z2UgPSBjcm9zX2VjLT5ldmVudF9kYXRhLmRhdGEuY2VjX21lc3NhZ2U7Cj4+PiArCXVuc2lnbmVk IGludCBsZW4gPSBjcm9zX2VjLT5ldmVudF9zaXplOwo+Pj4gKwo+Pj4gKwljcm9zX2VjX2NlYy0+ cnhfbXNnLmxlbiA9IGxlbjsKPj4KPj4gSG93IHJvYnVzdCBpcyB0aGUgdW5kZXJseWluZyBjb2Rl IGFuZCBoYXJkd2FyZT8gV2hhdCBoYXBwZW5zIGlmIGEKPj4gQ0VDIG1lc3NhZ2Ugd2l0aCBtb3Jl IHRoYW4gMTYgYnl0ZXMgaXMgcmVjZWl2ZWQ/Cj4+Cj4+IEhhcmQgdG8gdGVzdCB1bmxlc3MgeW91 IGhhdmUgYW4gUlBpMyBzZXQgdXAgYXMgYSBDRUMgZGVidWdnZXIuIFNlZQo+PiBsYXN0IHNlY3Rp b24gaW4gaHR0cHM6Ly9odmVya3VpbC5ob21lLnhzNGFsbC5ubC9jZWMtc3RhdHVzLnR4dC4KPj4K Pj4gU2luY2UgeW91IHdvcmtlZCB3aXRoIENFQyBmb3IgYSB3aGlsZSBub3cgSSByZWNvbW1lbmQg eW91IHNldCB1cCBzdWNoCj4+IGEgc3lzdGVtLiBJdCdzIGNoZWFwIGFuZCB2ZXJ5IHVzZWZ1bC4K PiAKPiBJIHdpbGwgZGVmaW5pdGVseSBzZXR1cCB0aGlzIGtpbmQgb2Ygc3lzdGVtLCBJIHRyaWVk IHVzaW5nIGFtIEFtbG9naWMgU29DLCBidXQgaXQgcmVhbGx5IGNhbid0IG1vbml0b3IgdGhlIGJ1 cy4uLi4KPiAKPiBCdXQgSSBhbHNvIGhhdmUgYW4gU1QgU1RNMzJGMCBEZXZlbG9wbWVudCBib2Fy ZCB3aXRoIGRvdWJsZSBIRE1JIGNvbm5lY3RvciB0byBkZXZlbG9wIENFQywgSSdsbCBtYXliZSB0 cnkgdG8gdXNlIGl0IGZvciB0aGF0IHB1cnBvc2UuCgpZb3UgcmVhbGx5IHdhbnQgYSBzZXR1cCB0 aGF0IHVzZXMgdGhlIGNlYy1ncGlvIGRyaXZlciBzaW5jZSB0aGF0IGFsbG93cwp5b3UgdG8gZG8g Q0VDIGVycm9yIGluamVjdGlvbi4gSWYgeW91IGNhbiBob29rIHVwIHRoZSBDRUMgcGluIHRvIGEg R1BJTwpvbiB0aGUgc3RtMzIgYm9hcmQsIHRoYW4gdGhhdCBzaG91bGQgd29yayBqdXN0IGFzIHdl bGwgYXMgd2l0aCB0aGUgUlBpMy4KCj4gCj4+Cj4+PiArCW1lbWNweShjcm9zX2VjX2NlYy0+cnhf bXNnLm1zZywgY2VjX21lc3NhZ2UsIGxlbik7Cj4+PiArCj4+PiArCWNlY19yZWNlaXZlZF9tc2co Y3Jvc19lY19jZWMtPmFkYXAsICZjcm9zX2VjX2NlYy0+cnhfbXNnKTsKPj4+ICt9Cj4+PiArCj4+ PiArc3RhdGljIHZvaWQgaGFuZGxlX2NlY19ldmVudChzdHJ1Y3QgY3Jvc19lY19jZWMgKmNyb3Nf ZWNfY2VjKQo+Pj4gK3sKPj4+ICsJc3RydWN0IGNyb3NfZWNfZGV2aWNlICpjcm9zX2VjID0gY3Jv c19lY19jZWMtPmNyb3NfZWM7Cj4+PiArCXVpbnQzMl90IGV2ZW50cyA9IGNyb3NfZWMtPmV2ZW50 X2RhdGEuZGF0YS5jZWNfZXZlbnRzOwo+Pj4gKwo+Pj4gKwlpZiAoZXZlbnRzICYgRUNfTUtCUF9D RUNfU0VORF9PSykKPj4+ICsJCWNlY190cmFuc21pdF9hdHRlbXB0X2RvbmUoY3Jvc19lY19jZWMt PmFkYXAsCj4+PiArCQkJCQkgIENFQ19UWF9TVEFUVVNfT0spOwo+Pj4gKwo+Pj4gKwlpZiAoZXZl bnRzICYgRUNfTUtCUF9DRUNfU0VORF9GQUlMRUQpCj4+PiArCQljZWNfdHJhbnNtaXRfYXR0ZW1w dF9kb25lKGNyb3NfZWNfY2VjLT5hZGFwLAo+Pj4gKwkJCQkJICBDRUNfVFhfU1RBVFVTX0VSUk9S KTsKPj4KPj4gWW91IHNhaWQgYWJvdmUgdGhhdCB0aGUgSFcgdGFrZXMgY2FyZSBvZiBhbGwgdGhl IG1lc3NhZ2UgcmV0cmllcy4KPj4gSWYgdGhhdCdzIHRoZSBjYXNlLCB0aGVuIHlvdSBuZWVkIHRv IHVzZSBjZWNfdHJhbnNtaXRfZG9uZSBoZXJlCj4+IGFuZCBwYXNzIGluIHN0YXR1cyBDRUNfVFhf U1RBVFVTX01BWF9SRVRSSUVTIHwgQ0VDX1RYX1NUQVRVU19OQUNLLgo+PiBUaGUgTUFYX1JFVFJJ RVMgZmxhZyB0ZWxscyB0aGUgY2VjIGNvcmUgdGhhdCBpdCBzaG91bGRuJ3QgYXR0ZW1wdAo+PiB0 byByZXRyeSB0aGUgbWVzc2FnZSBiZWNhdXNlIHRoZSBIVyBhbHJlYWR5IGRpZCB0aGF0Lgo+Pgo+ PiBOQUNLIGlzIGJldHRlciB0aGFuIEVSUk9SIGlmIHRoZSBoYXJkd2FyZSBzdXBwb3J0cyBvbmx5 IGFuIE9LL0ZBSUwKPj4gcmVzdWx0Lgo+IAo+IE9rLCB3ZSB3ZXJlIHVuc3VyZSBhYm91dCB0aGlz LCB0aGFua3MgZm9yIHRoZSBjbGFyaWZpY2F0aW9uLgo+IAo+Pgo+Pj4gK30KPj4+ICsKPj4+ICtz dGF0aWMgaW50IGNyb3NfZWNfY2VjX2V2ZW50KHN0cnVjdCBub3RpZmllcl9ibG9jayAqbmIsCj4+ PiArCXVuc2lnbmVkIGxvbmcgcXVldWVkX2R1cmluZ19zdXNwZW5kLCB2b2lkICpfbm90aWZ5KQo+ Pj4gK3sKPj4+ICsJc3RydWN0IGNyb3NfZWNfY2VjICpjcm9zX2VjX2NlYzsKPj4+ICsJc3RydWN0 IGNyb3NfZWNfZGV2aWNlICpjcm9zX2VjOwo+Pj4gKwo+Pj4gKwljcm9zX2VjX2NlYyA9IGNvbnRh aW5lcl9vZihuYiwgc3RydWN0IGNyb3NfZWNfY2VjLCBub3RpZmllcik7Cj4+PiArCWNyb3NfZWMg PSBjcm9zX2VjX2NlYy0+Y3Jvc19lYzsKPj4+ICsKPj4+ICsJaWYgKGNyb3NfZWMtPmV2ZW50X2Rh dGEuZXZlbnRfdHlwZSA9PSBFQ19NS0JQX0NFQ19FVkVOVCkgewo+Pj4gKwkJaGFuZGxlX2NlY19l dmVudChjcm9zX2VjX2NlYyk7Cj4+PiArCQlyZXR1cm4gTk9USUZZX09LOwo+Pj4gKwl9Cj4+PiAr Cj4+PiArCWlmIChjcm9zX2VjLT5ldmVudF9kYXRhLmV2ZW50X3R5cGUgPT0gRUNfTUtCUF9FVkVO VF9DRUNfTUVTU0FHRSkgewo+Pj4gKwkJaGFuZGxlX2NlY19tZXNzYWdlKGNyb3NfZWNfY2VjKTsK Pj4+ICsJCXJldHVybiBOT1RJRllfT0s7Cj4+PiArCX0KPj4+ICsKPj4+ICsJcmV0dXJuIE5PVElG WV9ET05FOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgaW50IGNyb3NfZWNfY2VjX3NldF9sb2df YWRkcihzdHJ1Y3QgY2VjX2FkYXB0ZXIgKmFkYXAsIHU4IGxvZ2ljYWxfYWRkcikKPj4+ICt7Cj4+ PiArCXN0cnVjdCBjcm9zX2VjX2NlYyAqY3Jvc19lY19jZWMgPSBhZGFwLT5wcml2Owo+Pj4gKwlz dHJ1Y3QgY3Jvc19lY19kZXZpY2UgKmNyb3NfZWMgPSBjcm9zX2VjX2NlYy0+Y3Jvc19lYzsKPj4+ ICsJc3RydWN0IHsKPj4+ICsJCXN0cnVjdCBjcm9zX2VjX2NvbW1hbmQgbXNnOwo+Pj4gKwkJc3Ry dWN0IGVjX3BhcmFtc19jZWNfc2V0IGRhdGE7Cj4+PiArCX0gX19wYWNrZWQgbXNnOwo+Pgo+PiBK dXN0IHNheTogLi4uIG1zZyA9IHt9Owo+Pgo+Pj4gKwlpbnQgcmV0ID0gMDsKPj4+ICsKPj4+ICsJ aWYgKGxvZ2ljYWxfYWRkciA9PSBDRUNfTE9HX0FERFJfSU5WQUxJRCkKPj4+ICsJCXJldHVybiAw Owo+Pgo+PiBUaGlzIGxvb2tzIHdlaXJkLiBJZiBJIGhhZCBjb25maWd1cmVkIGEgTEEgYmVmb3Jl LCB0aGVuIHRoaXMgc2hvdWxkIHVuY29uZmlndXJlCj4+IGl0LiBCdXQgaXQganVzdCBrZWVwcyB0 aGUgZXhpc3RpbmcgTEEsIHNvIGFueSBwb2xsIG1lc3NhZ2VzIHRvIHVzIHdpbGwgc3RpbGwKPj4g YmUgQWNrZWQuIE9yIGFtIEkgbWlzc2luZyBzb21ldGhpbmc/CgpEaWQgeW91IG1pc3MgdGhpcyBj b21tZW50PyBJdCdzIHdlaXJkIHdoYXQgaXMgaGFwcGVuaW5nIGhlcmUuCgo+Pgo+Pj4gKwo+Pj4g KwltZW1zZXQoJm1zZywgMCwgc2l6ZW9mKG1zZykpOwo+Pgo+PiBhbmQgeW91IGNhbiBkcm9wIHRo aXMgbWVtc2V0Lgo+IAo+IEkgYWx3YXlzIGZvcmdldCB0aGlzIHRyaWNrLgo+IAo+Pgo+Pj4gKwlt c2cubXNnLmNvbW1hbmQgPSBFQ19DTURfQ0VDX1NFVDsKPj4+ICsJbXNnLm1zZy5vdXRzaXplID0g c2l6ZW9mKG1zZy5kYXRhKTsKPj4+ICsJbXNnLmRhdGEuY21kID0gQ0VDX0NNRF9MT0dJQ0FMX0FE RFJFU1M7Cj4+PiArCW1zZy5kYXRhLmFkZHJlc3MgPSBsb2dpY2FsX2FkZHI7Cj4+PiArCj4+PiAr CXJldCA9IGNyb3NfZWNfY21kX3hmZXJfc3RhdHVzKGNyb3NfZWMsICZtc2cubXNnKTsKPj4+ICsJ aWYgKHJldCA8IDApIHsKPj4+ICsJCWRldl9lcnIoY3Jvc19lYy0+ZGV2LAo+Pj4gKwkJCSJlcnJv ciBzZXR0aW5nIENFQyBsb2dpY2FsIGFkZHJlc3Mgb24gRUM6ICVkXG4iLCByZXQpOwo+Pj4gKwkJ cmV0dXJuIHJldDsKPj4+ICsJfQo+Pj4gKwo+Pj4gKwlyZXR1cm4gMDsKPj4+ICt9Cj4+PiArCj4+ PiArc3RhdGljIGludCBjcm9zX2VjX2NlY190cmFuc21pdChzdHJ1Y3QgY2VjX2FkYXB0ZXIgKmFk YXAsIHU4IGF0dGVtcHRzLAo+Pj4gKwkJCQl1MzIgc2lnbmFsX2ZyZWVfdGltZSwgc3RydWN0IGNl Y19tc2cgKmNlY19tc2cpCj4+PiArewo+Pj4gKwlzdHJ1Y3QgY3Jvc19lY19jZWMgKmNyb3NfZWNf Y2VjID0gYWRhcC0+cHJpdjsKPj4+ICsJc3RydWN0IGNyb3NfZWNfZGV2aWNlICpjcm9zX2VjID0g Y3Jvc19lY19jZWMtPmNyb3NfZWM7Cj4+PiArCXN0cnVjdCB7Cj4+PiArCQlzdHJ1Y3QgY3Jvc19l Y19jb21tYW5kIG1zZzsKPj4+ICsJCXN0cnVjdCBlY19wYXJhbXNfY2VjX3dyaXRlIGRhdGE7Cj4+ PiArCX0gX19wYWNrZWQgbXNnOwo+Pgo+PiAuLi4gbXNnID0ge307Cj4+Cj4+PiArCWludCByZXQg PSAwOwo+Pj4gKwo+Pj4gKwlpZiAoY2VjX21zZy0+bGVuID4gTUFYX0NFQ19NU0dfTEVOKQo+Pj4g KwkJcmV0dXJuIC1FSU5WQUw7Cj4+Cj4+IE5vIG5lZWQsIGNhbiBuZXZlciBoYXBwZW4uCj4gCj4g Rm9yZ29yIHRvIHJlbW92ZSBpdCwgdGhlIEFQSSBjaGFuZ2VkIGluIHRoZSBtZWFudGltZSwgbm93 IGl0IGNhbiBuZXZlciBoYXBwZW4gIQo+IAo+Pgo+Pj4gKwo+Pj4gKwltZW1zZXQoJm1zZywgMCwg c2l6ZW9mKG1zZykpOwo+Pgo+PiBhbmQgZHJvcCB0aGlzLgo+Pgo+Pj4gKwltc2cubXNnLmNvbW1h bmQgPSBFQ19DTURfQ0VDX1dSSVRFX01TRzsKPj4+ICsJbXNnLm1zZy5vdXRzaXplID0gY2VjX21z Zy0+bGVuOwo+Pj4gKwltZW1jcHkobXNnLmRhdGEubXNnLCBjZWNfbXNnLT5tc2csIGNlY19tc2ct Pmxlbik7Cj4+PiArCj4+PiArCXJldCA9IGNyb3NfZWNfY21kX3hmZXJfc3RhdHVzKGNyb3NfZWMs ICZtc2cubXNnKTsKPj4+ICsJaWYgKHJldCA8IDApIHsKPj4+ICsJCWRldl9lcnIoY3Jvc19lYy0+ ZGV2LAo+Pj4gKwkJCSJlcnJvciB3cml0dGluZyBDRUMgbXNnIG9uIEVDOiAlZFxuIiwgcmV0KTsK Pj4+ICsJCXJldHVybiByZXQ7Cj4+PiArCX0KPj4+ICsKPj4+ICsJcmV0dXJuIDA7Cj4+PiArfQo+ Pj4gKwo+Pj4gK3N0YXRpYyBpbnQgY3Jvc19lY19jZWNfYWRhcF9lbmFibGUoc3RydWN0IGNlY19h ZGFwdGVyICphZGFwLCBib29sIGVuYWJsZSkKPj4+ICt7Cj4+PiArCXN0cnVjdCBjcm9zX2VjX2Nl YyAqY3Jvc19lY19jZWMgPSBhZGFwLT5wcml2Owo+Pj4gKwlzdHJ1Y3QgY3Jvc19lY19kZXZpY2Ug KmNyb3NfZWMgPSBjcm9zX2VjX2NlYy0+Y3Jvc19lYzsKPj4+ICsJc3RydWN0IHsKPj4+ICsJCXN0 cnVjdCBjcm9zX2VjX2NvbW1hbmQgbXNnOwo+Pj4gKwkJc3RydWN0IGVjX3BhcmFtc19jZWNfc2V0 IGRhdGE7Cj4+PiArCX0gX19wYWNrZWQgbXNnOwo+Pj4gKwlpbnQgcmV0ID0gMDsKPj4+ICsKPj4+ ICsJbWVtc2V0KCZtc2csIDAsIHNpemVvZihtc2cpKTsKPj4+ICsJbXNnLm1zZy5jb21tYW5kID0g RUNfQ01EX0NFQ19TRVQ7Cj4+PiArCW1zZy5tc2cub3V0c2l6ZSA9IHNpemVvZihtc2cuZGF0YSk7 Cj4+PiArCW1zZy5kYXRhLmNtZCA9IENFQ19DTURfRU5BQkxFOwo+Pj4gKwltc2cuZGF0YS5lbmFi bGUgPSBlbmFibGU7Cj4+PiArCj4+PiArCXJldCA9IGNyb3NfZWNfY21kX3hmZXJfc3RhdHVzKGNy b3NfZWMsICZtc2cubXNnKTsKPj4+ICsJaWYgKHJldCA8IDApIHsKPj4+ICsJCWRldl9lcnIoY3Jv c19lYy0+ZGV2LAo+Pj4gKwkJCSJlcnJvciAlc2FibGluZyBDRUMgb24gRUM6ICVkXG4iLAo+Pj4g KwkJCShlbmFibGUgPyAiZW4iIDogImRpcyIpLCByZXQpOwo+Pj4gKwkJcmV0dXJuIHJldDsKPj4+ ICsJfQo+Pj4gKwo+Pj4gKwlyZXR1cm4gMDsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIGNvbnN0 IHN0cnVjdCBjZWNfYWRhcF9vcHMgY3Jvc19lY19jZWNfb3BzID0gewo+Pj4gKwkuYWRhcF9lbmFi bGUgPSBjcm9zX2VjX2NlY19hZGFwX2VuYWJsZSwKPj4+ICsJLmFkYXBfbG9nX2FkZHIgPSBjcm9z X2VjX2NlY19zZXRfbG9nX2FkZHIsCj4+PiArCS5hZGFwX3RyYW5zbWl0ID0gY3Jvc19lY19jZWNf dHJhbnNtaXQsCj4+PiArfTsKPj4+ICsKPj4+ICsjaWZkZWYgQ09ORklHX1BNX1NMRUVQCj4+PiAr c3RhdGljIGludCBjcm9zX2VjX2NlY19zdXNwZW5kKHN0cnVjdCBkZXZpY2UgKmRldikKPj4+ICt7 Cj4+PiArCXN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYgPSB0b19wbGF0Zm9ybV9kZXZpY2Uo ZGV2KTsKPj4+ICsJc3RydWN0IGNyb3NfZWNfY2VjICpjcm9zX2VjX2NlYyA9IGRldl9nZXRfZHJ2 ZGF0YSgmcGRldi0+ZGV2KTsKPj4+ICsKPj4+ICsJaWYgKGRldmljZV9tYXlfd2FrZXVwKGRldikp Cj4+PiArCQllbmFibGVfaXJxX3dha2UoY3Jvc19lY19jZWMtPmNyb3NfZWMtPmlycSk7Cj4+PiAr Cj4+PiArCXJldHVybiAwOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgaW50IGNyb3NfZWNfY2Vj X3Jlc3VtZShzdHJ1Y3QgZGV2aWNlICpkZXYpCj4+PiArewo+Pj4gKwlzdHJ1Y3QgcGxhdGZvcm1f ZGV2aWNlICpwZGV2ID0gdG9fcGxhdGZvcm1fZGV2aWNlKGRldik7Cj4+PiArCXN0cnVjdCBjcm9z X2VjX2NlYyAqY3Jvc19lY19jZWMgPSBkZXZfZ2V0X2RydmRhdGEoJnBkZXYtPmRldik7Cj4+PiAr Cj4+PiArCWlmIChkZXZpY2VfbWF5X3dha2V1cChkZXYpKQo+Pj4gKwkJZGlzYWJsZV9pcnFfd2Fr ZShjcm9zX2VjX2NlYy0+Y3Jvc19lYy0+aXJxKTsKPj4+ICsKPj4+ICsJcmV0dXJuIDA7Cj4+PiAr fQo+Pj4gKyNlbmRpZgo+Pj4gKwo+Pj4gK3N0YXRpYyBTSU1QTEVfREVWX1BNX09QUyhjcm9zX2Vj X2NlY19wbV9vcHMsCj4+PiArCWNyb3NfZWNfY2VjX3N1c3BlbmQsIGNyb3NfZWNfY2VjX3Jlc3Vt ZSk7Cj4+PiArCj4+PiArCj4+PiArc3RydWN0IGNlY19kbWlfbWF0Y2ggewo+Pj4gKwljaGFyICpz eXNfdmVuZG9yOwo+Pj4gKwljaGFyICpwcm9kdWN0X25hbWU7Cj4+PiArCWNoYXIgKmRldm5hbWU7 Cj4+PiArCWNoYXIgKmNvbm47Cj4+PiArfTsKPj4+ICsKPj4+ICtzdGF0aWMgY29uc3Qgc3RydWN0 IGNlY19kbWlfbWF0Y2ggY2VjX2RtaV9tYXRjaF90YWJsZVtdID0gewo+Pj4gKwkvKiBHb29nbGUg Rml6eiAqLwo+Pj4gKwl7ICJHb29nbGUiLCAiRml6eiIsICIwMDAwOjAwOjAyLjAiLCAiSERNSS1B LTEiIH0sCj4+PiArfTsKPj4+ICsKPj4+ICtzdGF0aWMgaW50IGNyb3NfZWNfY2VjX2dldF9ub3Rp ZmllcihzdHJ1Y3QgY2VjX25vdGlmaWVyICoqbm90aWZ5KQo+Pj4gK3sKPj4+ICsJaW50IGk7Cj4+ PiArCj4+PiArCWZvciAoaSA9IDAgOyBpIDwgQVJSQVlfU0laRShjZWNfZG1pX21hdGNoX3RhYmxl KSA7ICsraSkgewo+Pj4gKwkJY29uc3Qgc3RydWN0IGNlY19kbWlfbWF0Y2ggKm0gPSAmY2VjX2Rt aV9tYXRjaF90YWJsZVtpXTsKPj4+ICsKPj4+ICsJCWlmIChkbWlfbWF0Y2goRE1JX1NZU19WRU5E T1IsIG0tPnN5c192ZW5kb3IpICYmCj4+PiArCQkgICAgZG1pX21hdGNoKERNSV9QUk9EVUNUX05B TUUsIG0tPnByb2R1Y3RfbmFtZSkpIHsKPj4+ICsJCQkqbm90aWZ5ID0gY2VjX25vdGlmaWVyX2dl dF9ieW5hbWUobS0+ZGV2bmFtZSwgbS0+Y29ubik7Cj4+Cj4+IFNlZSBteSBjb21tZW50cyBmb3Ig cGF0Y2ggMi81Lgo+IAo+IEkgd2lsbCBjaGFuZ2Ugd2l0aCB5b3UgY29tbWVudCwgbG9va3Mgd2F5 IGNsZWFuZXIuCj4gCj4+Cj4+PiArCQkJcmV0dXJuIDA7Cj4+PiArCQl9Cj4+PiArCX0KPj4+ICsK Pj4+ICsJcmV0dXJuIC1FSU5WQUw7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyBpbnQgY3Jvc19l Y19jZWNfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikKPj4+ICt7Cj4+PiArCXN0 cnVjdCBjcm9zX2VjX2RldiAqZWNfZGV2ID0gZGV2X2dldF9kcnZkYXRhKHBkZXYtPmRldi5wYXJl bnQpOwo+Pj4gKwlzdHJ1Y3QgY3Jvc19lY19kZXZpY2UgKmNyb3NfZWMgPSBlY19kZXYtPmVjX2Rl djsKPj4+ICsJc3RydWN0IGNyb3NfZWNfY2VjICpjcm9zX2VjX2NlYzsKPj4+ICsJdW5zaWduZWQg aW50IGNlY19jYXBzID0gQ0VDX0NBUF9ERUZBVUxUUzsKPj4KPj4gRG9lcyB0aGlzIG5lZWQgQ0VD X0NBUF9ORUVEU19IUEQ/IENhbiBpdCBzdGlsbCB1c2UgQ0VDIGlmIHRoZXJlIGlzIG5vIEhQRAo+ PiBzaWduYWw/Cj4gCj4gTm8sIFllcywgdGhlIEVDIEZXIGlzIGluZGVwZW5kZW50IG9mIHRoZSBI UEQgc3RhdHVzCj4gCj4+Cj4+PiArCWludCByZXQ7Cj4+PiArCj4+PiArCWNyb3NfZWNfY2VjID0g ZGV2bV9remFsbG9jKCZwZGV2LT5kZXYsIHNpemVvZigqY3Jvc19lY19jZWMpLAo+Pj4gKwkJCQkg ICBHRlBfS0VSTkVMKTsKPj4+ICsJaWYgKCFjcm9zX2VjX2NlYykKPj4+ICsJCXJldHVybiAtRU5P TUVNOwo+Pj4gKwo+Pj4gKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0YShwZGV2LCBjcm9zX2VjX2NlYyk7 Cj4+PiArCWNyb3NfZWNfY2VjLT5jcm9zX2VjID0gY3Jvc19lYzsKPj4+ICsKPj4+ICsJcmV0ID0g Y3Jvc19lY19jZWNfZ2V0X25vdGlmaWVyKCZjcm9zX2VjX2NlYy0+bm90aWZ5KTsKPj4+ICsJaWYg KHJldCkgewo+Pj4gKwkJZGV2X3dhcm4oJnBkZXYtPmRldiwgIm5vIENFQyBub3RpZmllciBhdmFp bGFibGVcbiIpOwo+Pj4gKwkJY2VjX2NhcHMgfD0gQ0VDX0NBUF9QSFlTX0FERFI7Cj4+Cj4+IENh biB0aGlzIGhhcHBlbj8gV2hhdCBoYXJkd2FyZSBoYXMgdGhpcz8gSSBhbSBzdHJvbmdseSBvcHBv c2VkIHRvIENFQyBkcml2ZXJzCj4+IHVzaW5nIHRoaXMgY2FwYWJpbGl0eSB1bmxlc3MgdGhlcmUg aXMgbm8gb3RoZXIgb3B0aW9uLiBJdCdzIGEgcGFpbiBmb3IgdXNlcnNwYWNlLgo+IAo+IEl0J3Mg aW4gY2FzZSBhbiBIVyBoYXZpbmcgYSBDRUMgY2FwYWJsZSBGVyBidXQgbm90IGluIHRoZSBjZWNf ZG1pX21hdGNoX3RhYmxlLCBpbiB0aGlzIGNhc2UKPiBpdCB3b24ndCBmYWlsIGJ1dCBzdGlsbCBl bmFibGUgdGhlIENFQyBpbnRlcmZhY2Ugd2l0aG91dCBhIG5vdGlmaWVyLgoKSSBkb24ndCB0aGlu ayB0aGF0J3MgYSBnb29kIGlkZWEuIENBUF9QSFlTX0FERFIgc2hvdWxkICpvbmx5KiBiZSB1c2Vk IGluIHNpdHVhdGlvbnMKd2hlcmUgaXQgaXMgdHJ1bHkgaW1wb3NzaWJsZSB0byB0ZWxsIHdoaWNo IG91dHB1dCBpcyBjb25uZWN0ZWQgdG8gdGhlIENFQyBhZGFwdGVyLgpUaGF0J3MgdGhlIGNhc2Ug d2l0aCBlLmcuIFVTQiBDRUMgZG9uZ2xlcyB3aGVyZSB5b3UgaGF2ZSBubyBpZGVhIGhvdyB0aGUg dXNlcgpjb25uZWN0ZWQgdGhlIEhETUkgY2FibGVzLgoKQnV0IEkgYXNzdW1lIHRoYXQgaW4gdGhp cyBjYXNlIGl0IGp1c3QgbWVhbnMgdGhhdCB0aGUgY2VjX2RtaV9tYXRjaF90YWJsZSBuZWVkcwp0 byBiZSB1cGRhdGVkLCBpLmUuIGl0IGlzIGEgZHJpdmVyIGJ1Zy4KCkFub3RoZXIgdGhpbmc6IHRo aXMgZHJpdmVyIGFzc3VtZXMgdGhhdCB0aGVyZSBpcyBvbmx5IG9uZSBDRUMgYWRhcHRlciBmb3Ig b25seQpvbmUgSERNSSBvdXRwdXQuIEJ1dCB3aGF0IGlmIHRoZXJlIGFyZSBtb3JlIEhETUkgb3V0 cHV0cz8gV2lsbCB0aGVyZSBiZSBvbmUKQ0VDIGFkYXB0ZXIgZm9yIGVhY2ggb3V0cHV0PyBPciBk b2VzIHRoZSBoYXJkd2FyZSBoYXZlIG5vIHByb3Zpc2lvbnMgZm9yIHRoYXQ/CgpTb21ldGhpbmcg c2hvdWxkIGJlIG1lbnRpb25lZCBhYm91dCB0aGlzIGluIGEgY29tbWVudC4KClJlZ2FyZHMsCgoJ SGFucwoKPiAKPj4KPj4+ICsJfSBlbHNlIGlmICghY3Jvc19lY19jZWMtPm5vdGlmeSkgewo+Pj4g KwkJcmV0dXJuIC1FUFJPQkVfREVGRVI7Cj4+PiArCX0KPj4+ICsKPj4+ICsJcmV0ID0gZGV2aWNl X2luaXRfd2FrZXVwKCZwZGV2LT5kZXYsIDEpOwo+Pj4gKwlpZiAocmV0KSB7Cj4+PiArCQlkZXZf ZXJyKCZwZGV2LT5kZXYsICJmYWlsZWQgdG8gaW5pdGlhbGl6ZSB3YWtldXBcbiIpOwo+Pj4gKwkJ cmV0dXJuIHJldDsKPj4+ICsJfQo+Pj4gKwo+Pj4gKwljcm9zX2VjX2NlYy0+YWRhcCA9IGNlY19h bGxvY2F0ZV9hZGFwdGVyKCZjcm9zX2VjX2NlY19vcHMsIGNyb3NfZWNfY2VjLAo+Pj4gKwkJCQkJ CSBEUlZfTkFNRSwgY2VjX2NhcHMsIDEpOwo+Pj4gKwlpZiAoSVNfRVJSKGNyb3NfZWNfY2VjLT5h ZGFwKSkKPj4+ICsJCXJldHVybiBQVFJfRVJSKGNyb3NfZWNfY2VjLT5hZGFwKTsKPj4+ICsKPj4+ ICsJY3Jvc19lY19jZWMtPmFkYXAtPm93bmVyID0gVEhJU19NT0RVTEU7Cj4+Cj4+IFRoaXMgY2Fu IGJlIGRyb3BwZWQsIGNlY19yZWdpc3Rlcl9hZGFwdGVyKCkgc2V0cyB0aGlzIGFscmVhZHkuCj4g Cj4gTm90ZWQuCj4gCj4+Cj4+PiArCj4+PiArCS8qIEdldCBDRUMgZXZlbnRzIGZyb20gdGhlIEVD LiAqLwo+Pj4gKwljcm9zX2VjX2NlYy0+bm90aWZpZXIubm90aWZpZXJfY2FsbCA9IGNyb3NfZWNf Y2VjX2V2ZW50Owo+Pj4gKwlyZXQgPSBibG9ja2luZ19ub3RpZmllcl9jaGFpbl9yZWdpc3Rlcigm Y3Jvc19lYy0+ZXZlbnRfbm90aWZpZXIsCj4+PiArCQkJCQkgICAgICAgJmNyb3NfZWNfY2VjLT5u b3RpZmllcik7Cj4+PiArCWlmIChyZXQpIHsKPj4+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgImZh aWxlZCB0byByZWdpc3RlciBub3RpZmllclxuIik7Cj4+PiArCQljZWNfZGVsZXRlX2FkYXB0ZXIo Y3Jvc19lY19jZWMtPmFkYXApOwo+Pj4gKwkJcmV0dXJuIHJldDsKPj4+ICsJfQo+Pj4gKwo+Pj4g KwlyZXQgPSBjZWNfcmVnaXN0ZXJfYWRhcHRlcihjcm9zX2VjX2NlYy0+YWRhcCwgJnBkZXYtPmRl dik7Cj4+PiArCWlmIChyZXQgPCAwKSB7Cj4+PiArCQljZWNfZGVsZXRlX2FkYXB0ZXIoY3Jvc19l Y19jZWMtPmFkYXApOwo+Pj4gKwkJcmV0dXJuIHJldDsKPj4+ICsJfQo+Pj4gKwo+Pj4gKwljZWNf cmVnaXN0ZXJfY2VjX25vdGlmaWVyKGNyb3NfZWNfY2VjLT5hZGFwLCBjcm9zX2VjX2NlYy0+bm90 aWZ5KTsKPj4+ICsKPj4+ICsJcmV0dXJuIDA7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyBpbnQg Y3Jvc19lY19jZWNfcmVtb3ZlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpCj4+PiArewo+ Pj4gKwlzdHJ1Y3QgY3Jvc19lY19jZWMgKmNyb3NfZWNfY2VjID0gcGxhdGZvcm1fZ2V0X2RydmRh dGEocGRldik7Cj4+PiArCXN0cnVjdCBkZXZpY2UgKmRldiA9ICZwZGV2LT5kZXY7Cj4+PiArCWlu dCByZXQ7Cj4+PiArCj4+PiArCXJldCA9IGJsb2NraW5nX25vdGlmaWVyX2NoYWluX3VucmVnaXN0 ZXIoCj4+PiArCQkJJmNyb3NfZWNfY2VjLT5jcm9zX2VjLT5ldmVudF9ub3RpZmllciwKPj4+ICsJ CQkmY3Jvc19lY19jZWMtPm5vdGlmaWVyKTsKPj4+ICsKPj4+ICsJaWYgKHJldCkgewo+Pj4gKwkJ ZGV2X2VycihkZXYsICJmYWlsZWQgdG8gdW5yZWdpc3RlciBub3RpZmllclxuIik7Cj4+PiArCQly ZXR1cm4gcmV0Owo+Pj4gKwl9Cj4+PiArCj4+PiArCWNlY191bnJlZ2lzdGVyX2FkYXB0ZXIoY3Jv c19lY19jZWMtPmFkYXApOwo+Pj4gKwo+Pj4gKwlpZiAoY3Jvc19lY19jZWMtPm5vdGlmeSkKPj4+ ICsJCWNlY19ub3RpZmllcl9wdXQoY3Jvc19lY19jZWMtPm5vdGlmeSk7Cj4+PiArCj4+PiArCXJl dHVybiAwOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBj cm9zX2VjX2NlY19kcml2ZXIgPSB7Cj4+PiArCS5wcm9iZSA9IGNyb3NfZWNfY2VjX3Byb2JlLAo+ Pj4gKwkucmVtb3ZlICA9IGNyb3NfZWNfY2VjX3JlbW92ZSwKPj4+ICsJLmRyaXZlciA9IHsKPj4+ ICsJCS5uYW1lID0gRFJWX05BTUUsCj4+PiArCQkucG0gPSAmY3Jvc19lY19jZWNfcG1fb3BzLAo+ Pj4gKwl9LAo+Pj4gK307Cj4+PiArCj4+PiArbW9kdWxlX3BsYXRmb3JtX2RyaXZlcihjcm9zX2Vj X2NlY19kcml2ZXIpOwo+Pj4gKwo+Pj4gK01PRFVMRV9ERVNDUklQVElPTigiQ0VDIGRyaXZlciBm b3IgQ2hyb21lIE9TIEVDcyIpOwo+Pj4gK01PRFVMRV9BVVRIT1IoIk5laWwgQXJtc3Ryb25nIDxu YXJtc3Ryb25nQGJheWxpYnJlLmNvbT4iKTsKPj4+ICtNT0RVTEVfTElDRU5TRSgiR1BMIik7Cj4+ PiArTU9EVUxFX0FMSUFTKCJwbGF0Zm9ybToiIERSVl9OQU1FKTsKPj4+Cj4+Cj4+IFJlZ2FyZHMs Cj4+Cj4+IAlIYW5zCj4+Cj4gCj4gVGhhbmtzLAo+IE5laWwKPiAKCl9fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCkludGVsLWdmeCBtYWlsaW5nIGxpc3QKSW50 ZWwtZ2Z4QGxpc3RzLmZyZWVkZXNrdG9wLm9yZwpodHRwczovL2xpc3RzLmZyZWVkZXNrdG9wLm9y Zy9tYWlsbWFuL2xpc3RpbmZvL2ludGVsLWdmeAo=