From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932968AbdADGzl (ORCPT ); Wed, 4 Jan 2017 01:55:41 -0500 Received: from mga02.intel.com ([134.134.136.20]:37895 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751763AbdADGzj (ORCPT ); Wed, 4 Jan 2017 01:55:39 -0500 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,458,1477983600"; d="scan'208";a="1078976555" From: "Xu, Even" To: "jikos@kernel.org" CC: "srinivas.pandruvada@linux.intel.com" , "linux-input@vger.kernel.org" , "benjamin.tissoires@redhat.com" , "linux-kernel@vger.kernel.org" , "gregkh@linuxfoundation.org" , "arnd@arndb.de" , "Shevchenko, Andriy" Subject: Re: [PATCH 7/7] misc: intel-ish-client: add intel ishtp clients driver Thread-Topic: [PATCH 7/7] misc: intel-ish-client: add intel ishtp clients driver Thread-Index: AQHSXLs45tV/nqOSWE+fURJiZa4VqKEmDwoAgAFcQ4A= Date: Wed, 4 Jan 2017 06:55:29 +0000 Message-ID: <1483512029.25176.7.camel@intel.com> References: <1482456149-4841-1-git-send-email-even.xu@intel.com> <1482456149-4841-7-git-send-email-even.xu@intel.com> In-Reply-To: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.154.100] Content-Type: text/plain; charset="utf-8" Content-ID: MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from base64 to 8bit by mail.home.local id v046tnSP006175 On 二, 2017-01-03 at 10:54 +0100, Jiri Kosina wrote: > On Fri, 23 Dec 2016, Even Xu wrote: > > [ ... snip ... ] > > > > +static ssize_t ishtp_cl_write(struct file *file, const char __user > > *ubuf, > > + size_t length, loff_t *offset) > > +{ > > + struct ishtp_cl_miscdev *ishtp_cl_misc = file- > > >private_data; > > + struct ishtp_cl *cl; > > + void *write_buf; > > + struct ishtp_device *dev; > > + int ret; > > + > > + /* Non-blocking semantics are not supported */ > > + if (file->f_flags & O_NONBLOCK) { > > + ret = -EINVAL; > > + goto out_unlock; > When taking the error path here you'd try to unlock  > ishtp_cl_misc->cl_mutex before actually acquiring it. > Thanks for your comments, Jiri, I update my patch below: =============================================================== Intel ISHFW supports many different clients, in hid/intel-ish-hid/ishtp bus driver, it creates following client devices: HID client: interface of sensor configure and sensor event report. SMHI client: interface of sensor calibration, ISHFW debug, ISHFW performance analysis and manufacture support. Trace client: interface of ISHFW debug log output. Trace configure client: interface of ISHFW debug log configuration, such as output port, log level, filter. ISHFW loader client: interface of customized ISHFW loader. HID client has been handle by hid/intel-ish-hid/intel-ishtp-hid client driver, and rest of the clients export interface using miscellaneous drivers. This interface is used by user space tools for debugging and calibration of sensors. Signed-off-by: Even Xu Reviewed-by: Andriy Shevchenko Reviewed-by: Srinivas Pandruvada ---  drivers/misc/Kconfig                               |   1 +  drivers/misc/Makefile                              |   1 +  drivers/misc/intel-ish-client/Kconfig              |  15 +  drivers/misc/intel-ish-client/Makefile             |   8 +  .../misc/intel-ish-client/intel-ishtp-clients.c    | 882 +++++++++++++++++++++  include/uapi/linux/intel-ishtp-clients.h           |  73 ++  6 files changed, 980 insertions(+)  create mode 100644 drivers/misc/intel-ish-client/Kconfig  create mode 100644 drivers/misc/intel-ish-client/Makefile  create mode 100644 drivers/misc/intel-ish-client/intel-ishtp-clients.c  create mode 100644 include/uapi/linux/intel-ishtp-clients.h diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 64971ba..a89849f 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -778,4 +778,5 @@ source "drivers/misc/mic/Kconfig"  source "drivers/misc/genwqe/Kconfig"  source "drivers/misc/echo/Kconfig"  source "drivers/misc/cxl/Kconfig" +source "drivers/misc/intel-ish-client/Kconfig"  endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 3198336..c54015d 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_ECHO) += echo/  obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o  obj-$(CONFIG_CXL_BASE) += cxl/  obj-$(CONFIG_PANEL)             += panel.o +obj-$(CONFIG_INTEL_ISH_CLIENT) += intel-ish-client/    lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o  lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o diff --git a/drivers/misc/intel-ish-client/Kconfig b/drivers/misc/intel-ish-client/Kconfig new file mode 100644 index 0000000..6fa9cc0 --- /dev/null +++ b/drivers/misc/intel-ish-client/Kconfig @@ -0,0 +1,15 @@ +menu "Intel ISH Client support" + depends on INTEL_ISH_HID + +config INTEL_ISH_CLIENT + tristate "Intel Integrated Sensor Hub Client" + help +   The Integrated Sensor Hub (ISH) supports many clients, Intel ISH client +   driver supports following clients: +   SMHI client: calibration & perfermance & menufacture tool interface +   trace configure client: ISHFW trace parameter configure interface +   trace tool client: ISHFW trace log output interface +   loader client: loading customized ISHFW interface + +   Say Y here if you want to support Intel ISH clients. If unsure, say N. +endmenu diff --git a/drivers/misc/intel-ish-client/Makefile b/drivers/misc/intel-ish-client/Makefile new file mode 100644 index 0000000..29a5461 --- /dev/null +++ b/drivers/misc/intel-ish-client/Makefile @@ -0,0 +1,8 @@ +# +# Makefile - Intel ISH client driver +# Copyright (c) 2014-2016, Intel Corporation. +# +# +obj-$(CONFIG_INTEL_ISH_CLIENT) += intel-ishtp-clients.o + +ccflags-y += -I$(srctree)/drivers/hid/intel-ish-hid/ishtp diff --git a/drivers/misc/intel-ish-client/intel-ishtp-clients.c b/drivers/misc/intel-ish-client/intel-ishtp-clients.c new file mode 100644 index 0000000..4ca3ab8 --- /dev/null +++ b/drivers/misc/intel-ish-client/intel-ishtp-clients.c @@ -0,0 +1,882 @@ +/* + * ISHTP clients driver + * + * Copyright (c) 2016, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ishtp-dev.h" +#include "client.h" + +/* + * ISH client misc driver structure + */ +struct ishtp_cl_miscdev { + struct miscdevice cl_miscdev; + struct ishtp_cl_device *cl_device; + struct ishtp_cl *cl; + + /* Wait queue for waiting ISHFW event/message */ + wait_queue_head_t read_wait; + /* Read buffer, will point to available ISHFW message */ + struct ishtp_cl_rb *read_rb; + + /* +  * cl member can be freed/changed by ISHFW reset and release() calling, +  * so must pay attention to protect cl while try to access it. This +  * mutex is used to protect cl member. +  */ + struct mutex cl_mutex; + + struct work_struct reset_work; +}; + +/* ISH client GUIDs */ +/* SMHI client UUID: bb579a2e-cc54-4450-b1d0-5e7520dcad25 */ +static const uuid_le ishtp_smhi_guid = + UUID_LE(0xbb579a2e, 0xcc54, 0x4450, + 0xb1, 0xd0, 0x5e, 0x75, 0x20, 0xdc, 0xad, 0x25); + +/* Trace log client UUID: c1cc78b9-b693-4e54-9191-5169cb027c25 */ +static const uuid_le ishtp_trace_guid = + UUID_LE(0xc1cc78b9, 0xb693, 0x4e54, + 0x91, 0x91, 0x51, 0x69, 0xcb, 0x02, 0x7c, 0x25); + +/* Trace config client UUID: 1f050626-d505-4e94-b189-535d7de19cf2 */ +static const uuid_le ishtp_traceconfig_guid = + UUID_LE(0x1f050626, 0xd505, 0x4e94, + 0xb1, 0x89, 0x53, 0x5d, 0x7d, 0xe1, 0x9c, 0xf2); + +/* ISHFW loader client UUID: c804d06a-55bd-4ea7-aded-1e31228c76dc */ +static const uuid_le ishtp_loader_guid = + UUID_LE(0xc804d06a, 0x55bd, 0x4ea7, + 0xad, 0xed, 0x1e, 0x31, 0x22, 0x8c, 0x76, 0xdc); + +static int ishtp_cl_open(struct inode *inode, struct file *file) +{ + struct miscdevice *misc = file->private_data; + struct ishtp_cl *cl; + struct ishtp_device *dev; + struct ishtp_cl_miscdev *ishtp_cl_misc; + int ret; + + /* Non-blocking semantics are not supported */ + if (file->f_flags & O_NONBLOCK) + return -EINVAL; + + ishtp_cl_misc = container_of(misc, + struct ishtp_cl_miscdev, cl_miscdev); + if (!ishtp_cl_misc || !ishtp_cl_misc->cl_device) + return -ENODEV; + + dev = ishtp_cl_misc->cl_device->ishtp_dev; + if (!dev) + return -ENODEV; + + mutex_lock(&ishtp_cl_misc->cl_mutex); + + /* +  * Every client only supports one opened instance +  * at the sametime. +  */ + if (ishtp_cl_misc->cl) { + ret = -EBUSY; + goto out_unlock; + } + + cl = ishtp_cl_allocate(dev); + if (!cl) { + ret = -ENOMEM; + goto out_free; + } + + if (dev->dev_state != ISHTP_DEV_ENABLED) { + ret = -ENODEV; + goto out_free; + } + + ret = ishtp_cl_link(cl, ISHTP_HOST_CLIENT_ID_ANY); + if (ret) + goto out_free; + + ishtp_cl_misc->cl = cl; + + file->private_data = ishtp_cl_misc; + + mutex_unlock(&ishtp_cl_misc->cl_mutex); + + return nonseekable_open(inode, file); + +out_free: + kfree(cl); +out_unlock: + mutex_unlock(&ishtp_cl_misc->cl_mutex); + return ret; +} + +#define WAIT_FOR_SEND_SLICE_MS 100 +#define WAIT_FOR_SEND_COUNT 10 + +static int ishtp_cl_release(struct inode *inode, struct file *file) +{ + struct ishtp_cl_miscdev *ishtp_cl_misc = file->private_data; + struct ishtp_cl *cl; + struct ishtp_cl_rb *rb; + struct ishtp_device *dev; + int try = WAIT_FOR_SEND_COUNT; + int ret; + + mutex_lock(&ishtp_cl_misc->cl_mutex); + + /* Wake up from waiting if anyone wait on it */ + wake_up_interruptible(&ishtp_cl_misc->read_wait); + + cl = ishtp_cl_misc->cl; + dev = cl->dev; + + /* +  * May happen if device sent FW reset or was intentionally +  * halted by host SW. The client is then invalid. +  */ + if ((dev->dev_state == ISHTP_DEV_ENABLED) && + (cl->state == ISHTP_CL_CONNECTED)) { + /* +  * Check and wait 1s for message in tx_list to be sent. +  */ + do { + if (!ishtp_cl_tx_empty(cl)) + msleep_interruptible(WAIT_FOR_SEND_SLICE_MS); + else + break; + } while (--try); + + cl->state = ISHTP_CL_DISCONNECTING; + ret = ishtp_cl_disconnect(cl); + } + + ishtp_cl_unlink(cl); + ishtp_cl_flush_queues(cl); + /* Disband and free all Tx and Rx client-level rings */ + ishtp_cl_free(cl); + + ishtp_cl_misc->cl = NULL; + + rb = ishtp_cl_misc->read_rb; + if (rb) { + ishtp_cl_io_rb_recycle(rb); + ishtp_cl_misc->read_rb = NULL; + } + + file->private_data = NULL; + + mutex_unlock(&ishtp_cl_misc->cl_mutex); + + return ret; +} + +static ssize_t ishtp_cl_read(struct file *file, char __user *ubuf, + size_t length, loff_t *offset) +{ + struct ishtp_cl_miscdev *ishtp_cl_misc = file->private_data; + struct ishtp_cl *cl; + struct ishtp_cl_rb *rb; + struct ishtp_device *dev; + int ret = 0; + + /* Non-blocking semantics are not supported */ + if (file->f_flags & O_NONBLOCK) + return -EINVAL; + + mutex_lock(&ishtp_cl_misc->cl_mutex); + + cl = ishtp_cl_misc->cl; + + /* +  * ISHFW reset will cause cl be freed and re-allocated. +  * So must make sure cl is re-allocated successfully. +  */ + if (!cl || !cl->dev) { + ret = -ENODEV; + goto out_unlock; + } + + dev = cl->dev; + if (dev->dev_state != ISHTP_DEV_ENABLED) { + ret = -ENODEV; + goto out_unlock; + } + + if (ishtp_cl_misc->read_rb) + goto get_rb; + + rb = ishtp_cl_rx_get_rb(cl); + if (rb) + goto copy_buffer; + + /* +  * Release mutex for other operation can be processed parallelly +  * during waiting. +  */ + mutex_unlock(&ishtp_cl_misc->cl_mutex); + + if (wait_event_interruptible(ishtp_cl_misc->read_wait, + ishtp_cl_misc->read_rb != NULL)) { + dev_err(&ishtp_cl_misc->cl_device->dev, + "Wake up not successful;" + "signal pending = %d signal = %08lX\n", + signal_pending(current), + current->pending.signal.sig[0]); + return -ERESTARTSYS; + } + + mutex_lock(&ishtp_cl_misc->cl_mutex); + + /* +  * waitqueue can be woken up in many cases, so must check +  * if dev and cl is still available. +  */ + if (dev->dev_state != ISHTP_DEV_ENABLED) { + ret = -ENODEV; + goto out_unlock; + } + + cl = ishtp_cl_misc->cl; + if (!cl) { + ret = -ENODEV; + goto out_unlock; + } + + if (cl->state == ISHTP_CL_INITIALIZING || + cl->state == ISHTP_CL_DISCONNECTED || + cl->state == ISHTP_CL_DISCONNECTING) { + ret = -EBUSY; + goto out_unlock; + } + +get_rb: + rb = ishtp_cl_misc->read_rb; + if (!rb) { + ret = -ENODEV; + goto out_unlock; + } + +copy_buffer: + /* Now copy the data to user space */ + if (!length || !ubuf || *offset > rb->buf_idx) { + ret = -EMSGSIZE; + goto out_unlock; + } + + /* +  * length is being truncated, however buf_idx may +  * point beyond that. +  */ + length = min_t(size_t, length, rb->buf_idx - *offset); + + if (copy_to_user(ubuf, rb->buffer.data + *offset, length)) { + ret = -EFAULT; + goto out_unlock; + } + + *offset += length; + if ((unsigned long)*offset < rb->buf_idx) + goto out_unlock; + + ishtp_cl_io_rb_recycle(rb); + ishtp_cl_misc->read_rb = NULL; + *offset = 0; + +out_unlock: + mutex_unlock(&ishtp_cl_misc->cl_mutex); + return ret < 0 ? ret : length; +} + +static ssize_t ishtp_cl_write(struct file *file, const char __user *ubuf, + size_t length, loff_t *offset) +{ + struct ishtp_cl_miscdev *ishtp_cl_misc = file->private_data; + struct ishtp_cl *cl; + void *write_buf; + struct ishtp_device *dev; + int ret; + + /* Non-blocking semantics are not supported */ + if (file->f_flags & O_NONBLOCK) + return -EINVAL; + + mutex_lock(&ishtp_cl_misc->cl_mutex); + + cl = ishtp_cl_misc->cl; + + /* +  * ISHFW reset will cause cl be freed and re-allocated. +  * So must make sure cl is re-allocated successfully. +  */ + if (!cl || !cl->dev) { + ret = -ENODEV; + goto out_unlock; + } + + dev = cl->dev; + + if (dev->dev_state != ISHTP_DEV_ENABLED) { + ret = -ENODEV; + goto out_unlock; + } + + if (cl->state != ISHTP_CL_CONNECTED) { + dev_err(&ishtp_cl_misc->cl_device->dev, + "host client = %d isn't connected to fw client = %d\n", + cl->host_client_id, cl->fw_client_id); + ret = -ENODEV; + goto out_unlock; + } + + if (length <= 0 || length > cl->device->fw_client->props.max_msg_length) { + ret = -EMSGSIZE; + goto out_unlock; + } + + write_buf = memdup_user(ubuf, length); + if (IS_ERR(write_buf)) { + ret = PTR_ERR(write_buf); + goto out_unlock; + } + + ret = ishtp_cl_send(cl, write_buf, length); + + kfree(write_buf); + +out_unlock: + mutex_unlock(&ishtp_cl_misc->cl_mutex); + + return ret < 0 ? ret : length; +} + +static int ishtp_cl_ioctl_connect_client(struct file *file, + struct ishtp_connect_client_data *data) +{ + struct ishtp_cl_miscdev *ishtp_cl_misc = file->private_data; + struct ishtp_device *dev; + struct ishtp_client *client; + struct ishtp_cl_device *cl_device; + struct ishtp_cl *cl = ishtp_cl_misc->cl; + struct ishtp_fw_client *fw_client; + + if (!cl || !cl->dev) + return -ENODEV; + + dev = cl->dev; + + if (dev->dev_state != ISHTP_DEV_ENABLED) + return -ENODEV; + + if (cl->state != ISHTP_CL_INITIALIZING && + cl->state != ISHTP_CL_DISCONNECTED) + return -EBUSY; + + cl_device = ishtp_cl_misc->cl_device; + + if (uuid_le_cmp(data->in_client_uuid, + cl_device->fw_client->props.protocol_name) != 0) { + dev_err(&ishtp_cl_misc->cl_device->dev, + "Required uuid don't match current client uuid\n"); + return -EFAULT; + } + + /* Find the fw client we're trying to connect to */ + fw_client = ishtp_fw_cl_get_client(dev, &data->in_client_uuid); + if (!fw_client) { + dev_err(&ishtp_cl_misc->cl_device->dev, + "Don't find current client uuid\n"); + return -ENOENT; + } + + cl->fw_client_id = fw_client->client_id; + cl->state = ISHTP_CL_CONNECTING; + + /* Prepare the output buffer */ + client = &data->out_client_properties; + client->max_msg_length = fw_client->props.max_msg_length; + client->protocol_version = fw_client->props.protocol_version; + + return ishtp_cl_connect(cl); +} + +static long ishtp_cl_ioctl(struct file *file, unsigned int cmd, + unsigned long data) +{ + struct ishtp_cl_miscdev *ishtp_cl_misc = file->private_data; + struct ishtp_cl *cl; + struct ishtp_device *dev; + struct ishtp_connect_client_data *connect_data; + char fw_stat_buf[20]; + unsigned int ring_size; + int ret = 0; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + mutex_lock(&ishtp_cl_misc->cl_mutex); + + cl = ishtp_cl_misc->cl; + + /* +  * ISHFW reset will cause cl be freed and re-allocated. +  * So must make sure cl is re-allocated successfully. +  */ + if (!cl || !cl->dev) { + mutex_unlock(&ishtp_cl_misc->cl_mutex); + return -ENODEV; + } + + dev = cl->dev; + + switch (cmd) { + case IOCTL_ISH_HW_RESET: + ret = ish_hw_reset(dev); + break; + + case IOCTL_ISHTP_SET_RX_FIFO_SIZE: + ring_size = data; + + if (ring_size > CL_MAX_RX_RING_SIZE) { + ret = -EINVAL; + break; + } + + if (cl->state != ISHTP_CL_INITIALIZING) { + ret = -EBUSY; + break; + } + + cl->rx_ring_size = ring_size; + break; + + case IOCTL_ISHTP_SET_TX_FIFO_SIZE: + ring_size = data; + + if (ring_size > CL_MAX_TX_RING_SIZE) { + ret = -EINVAL; + break; + } + + if (cl->state != ISHTP_CL_INITIALIZING) { + ret = -EBUSY; + break; + } + + cl->tx_ring_size = ring_size; + break; + + case IOCTL_ISH_GET_FW_STATUS: + if (!data) { + ret = -ENOMEM; + break; + } + + snprintf(fw_stat_buf, sizeof(fw_stat_buf), + "%08X\n", dev->ops->get_fw_status(dev)); + + if (copy_to_user((char __user *)data, fw_stat_buf, + strlen(fw_stat_buf))) { + ret = -EFAULT; + break; + } + + ret = strlen(fw_stat_buf); + break; + + case IOCTL_ISHTP_CONNECT_CLIENT: + if (dev->dev_state != ISHTP_DEV_ENABLED) { + ret = -ENODEV; + break; + } + + connect_data = memdup_user((char __user *)data, + sizeof(struct ishtp_connect_client_data)); + if (IS_ERR(connect_data)) { + ret = PTR_ERR(connect_data); + break; + } + + ret = ishtp_cl_ioctl_connect_client(file, connect_data); + if (ret) { + kfree(connect_data); + break; + } + + /* If all is ok, copying the data back to user. */ + if (copy_to_user((char __user *)data, connect_data, + sizeof(struct ishtp_connect_client_data))) + ret = -EFAULT; + + kfree(connect_data); + + break; + + default: + ret = -EINVAL; + break; + } + + mutex_unlock(&ishtp_cl_misc->cl_mutex); + + return ret; +} + +/* + * File operations structure will be used for ishtp client misc device. + */ +static const struct file_operations ishtp_cl_fops = { + .owner = THIS_MODULE, + .read = ishtp_cl_read, + .unlocked_ioctl = ishtp_cl_ioctl, + .open = ishtp_cl_open, + .release = ishtp_cl_release, + .write = ishtp_cl_write, + .llseek = no_llseek +}; + +/** + * ishtp_cl_event_cb() - ISHTP client driver event callback + * @cl_device: ISHTP client device instance + * + * This function gets called on related event recevied from ISHFW. + * It will remove event buffer exists on in_process list to related + * client device and wait up client driver to process. + */ +static void ishtp_cl_event_cb(struct ishtp_cl_device *cl_device) +{ + struct ishtp_cl_miscdev *ishtp_cl_misc; + struct ishtp_cl *cl; + struct ishtp_cl_rb *rb; + + ishtp_cl_misc = ishtp_get_drvdata(cl_device); + if (!ishtp_cl_misc) + return; + + mutex_lock(&ishtp_cl_misc->cl_mutex); + + /* +  * If this waitqueue is active, cl_mutex is locked by read(), it's safe +  * to access ishtp_cl_misc and cl. +  */ + if (waitqueue_active(&ishtp_cl_misc->read_wait)) { + + /* +  * If already has read_rb, wake up waitqueue directly. +  */ + if (ishtp_cl_misc->read_rb) { + mutex_unlock(&ishtp_cl_misc->cl_mutex); + wake_up_interruptible(&ishtp_cl_misc->read_wait); + return; + } + + cl = ishtp_cl_misc->cl; + + rb = ishtp_cl_rx_get_rb(cl); + if (rb) + ishtp_cl_misc->read_rb = rb; + + wake_up_interruptible(&ishtp_cl_misc->read_wait); + } + + mutex_unlock(&ishtp_cl_misc->cl_mutex); +} + +/** + * ishtp_cl_reset_handler() - ISHTP client driver reset work handler + * @work: work struct + * + * This function gets called on reset workqueue scheduled when ISHFW + * reset happen. It will disconnect and remove current ishtp_cl, then + * create a new ishtp_cl and re-connect again. + */ +static void ishtp_cl_reset_handler(struct work_struct *work) +{ + struct ishtp_cl_miscdev *ishtp_cl_misc; + struct ishtp_device *dev; + struct ishtp_cl_device *cl_device; + struct ishtp_cl *cl; + struct ishtp_fw_client *fw_client; + int ret = 0; + + ishtp_cl_misc = container_of(work, + struct ishtp_cl_miscdev, reset_work); + + dev = ishtp_cl_misc->cl_device->ishtp_dev; + if (!dev) { + dev_err(&ishtp_cl_misc->cl_device->dev, + "This cl_device not link to ishtp_dev\n"); + return; + } + + cl_device = ishtp_cl_misc->cl_device; + + mutex_lock(&ishtp_cl_misc->cl_mutex); + + /* Wake up from waiting if anyone wait on it */ + wake_up_interruptible(&ishtp_cl_misc->read_wait); + + cl = ishtp_cl_misc->cl; + if (cl) { + ishtp_cl_flush_queues(cl); + ishtp_cl_free(cl); + + cl = NULL; + + cl = ishtp_cl_allocate(dev); + if (!cl) { + dev_err(&ishtp_cl_misc->cl_device->dev, + "Allocate ishtp_cl failed\n"); + ret = -ENOMEM; + goto out_unlock; + } + + if (dev->dev_state != ISHTP_DEV_ENABLED) { + dev_err(&ishtp_cl_misc->cl_device->dev, + "Ishtp dev isn't enabled\n"); + ret = -ENODEV; + goto out_free; + } + + ret = ishtp_cl_link(cl, ISHTP_HOST_CLIENT_ID_ANY); + if (ret) { + dev_err(&ishtp_cl_misc->cl_device->dev, + "Can not link to ishtp\n"); + goto out_free; + } + + fw_client = ishtp_fw_cl_get_client(dev, + &cl_device->fw_client->props.protocol_name); + if (!fw_client) { + dev_err(&ishtp_cl_misc->cl_device->dev, + "Don't find related fw client\n"); + ret = -ENOENT; + goto out_free; + } + + cl->fw_client_id = fw_client->client_id; + cl->state = ISHTP_CL_CONNECTING; + + ret = ishtp_cl_connect(cl); + if (ret) { + dev_err(&ishtp_cl_misc->cl_device->dev, + "Connect to fw failed\n"); + goto out_free; + } + + ishtp_cl_misc->cl = cl; + } + + /* After reset, must register event callback again */ + ishtp_register_event_cb(cl_device, ishtp_cl_event_cb); + +out_free: + if (ret) { + ishtp_cl_free(cl); + ishtp_cl_misc->cl = NULL; + + dev_err(&ishtp_cl_misc->cl_device->dev, "Reset failed\n"); + } + +out_unlock: + mutex_unlock(&ishtp_cl_misc->cl_mutex); +} + +/** + * ishtp_cl_probe() - ISHTP client driver probe + * @cl_device: ISHTP client device instance + * + * This function gets called on device create on ISHTP bus + * + * Return: 0 on success, non zero on error + */ +static int ishtp_cl_probe(struct ishtp_cl_device *cl_device) +{ + struct ishtp_cl_miscdev *ishtp_cl_misc; + int ret; + + if (!cl_device) + return -ENODEV; + + ishtp_cl_misc = kzalloc(sizeof(struct ishtp_cl_miscdev), + GFP_KERNEL); + if (!ishtp_cl_misc) + return -ENOMEM; + + if (uuid_le_cmp(ishtp_smhi_guid, + cl_device->fw_client->props.protocol_name) == 0) { + ishtp_cl_misc->cl_miscdev.name = "ish-smhi"; + } else if (uuid_le_cmp(ishtp_trace_guid, + cl_device->fw_client->props.protocol_name) == 0) { + ishtp_cl_misc->cl_miscdev.name = "ish-trace"; + } else if (uuid_le_cmp(ishtp_traceconfig_guid, + cl_device->fw_client->props.protocol_name) == 0) { + ishtp_cl_misc->cl_miscdev.name = "ish-tracec"; + } else if (uuid_le_cmp(ishtp_loader_guid, + cl_device->fw_client->props.protocol_name) == 0) { + ishtp_cl_misc->cl_miscdev.name = "ish-loader"; + } else { + dev_err(&cl_device->dev, "Not supported client\n"); + ret = -ENODEV; + goto release_mem; + } + + ishtp_cl_misc->cl_miscdev.parent = &cl_device->dev; + ishtp_cl_misc->cl_miscdev.fops = &ishtp_cl_fops; + ishtp_cl_misc->cl_miscdev.minor = MISC_DYNAMIC_MINOR, + + ret = misc_register(&ishtp_cl_misc->cl_miscdev); + if (ret) { + dev_err(&cl_device->dev, "misc device register failed\n"); + goto release_mem; + } + + ishtp_cl_misc->cl_device = cl_device; + + init_waitqueue_head(&ishtp_cl_misc->read_wait); + + ishtp_set_drvdata(cl_device, ishtp_cl_misc); + + ishtp_get_device(cl_device); + + mutex_init(&ishtp_cl_misc->cl_mutex); + + INIT_WORK(&ishtp_cl_misc->reset_work, ishtp_cl_reset_handler); + + /* Register event callback */ + ishtp_register_event_cb(cl_device, ishtp_cl_event_cb); + + return 0; + +release_mem: + kfree(ishtp_cl_misc); + + return ret; +} + +/** + * ishtp_cl_remove() - ISHTP client driver remove + * @cl_device: ISHTP client device instance + * + * This function gets called on device remove on ISHTP bus + * + * Return: 0 + */ +static int ishtp_cl_remove(struct ishtp_cl_device *cl_device) +{ + struct ishtp_cl_miscdev *ishtp_cl_misc; + struct ishtp_cl *cl; + + ishtp_cl_misc = ishtp_get_drvdata(cl_device); + if (!ishtp_cl_misc) + return -ENODEV; + + if (!ishtp_cl_misc->cl_miscdev.parent) + return -ENODEV; + + /* Wake up from waiting if anyone wait on it */ + wake_up_interruptible(&ishtp_cl_misc->read_wait); + + mutex_lock(&ishtp_cl_misc->cl_mutex); + + cl = ishtp_cl_misc->cl; + if (cl) { + cl->state = ISHTP_CL_DISCONNECTING; + ishtp_cl_disconnect(cl); + ishtp_cl_unlink(cl); + ishtp_cl_flush_queues(cl); + ishtp_cl_free(cl); + ishtp_cl_misc->cl = NULL; + } + + mutex_unlock(&ishtp_cl_misc->cl_mutex); + + mutex_destroy(&ishtp_cl_misc->cl_mutex); + + misc_deregister(&ishtp_cl_misc->cl_miscdev); + + ishtp_put_device(cl_device); + + kfree(ishtp_cl_misc); + + return 0; +} + +/** + * ishtp_cl_reset() - ISHTP client driver reset + * @cl_device: ISHTP client device instance + * + * This function gets called on device reset on ISHTP bus. + * If client is connected, needs to disconnect client and + * reconnect again. + * + * Return: 0 + */ +static int ishtp_cl_reset(struct ishtp_cl_device *cl_device) +{ + struct ishtp_cl_miscdev *ishtp_cl_misc; + + ishtp_cl_misc = ishtp_get_drvdata(cl_device); + if (!ishtp_cl_misc) { + dev_err(&cl_device->dev, "Client driver not ready yet\n"); + return -ENODEV; + } + + schedule_work(&ishtp_cl_misc->reset_work); + + return 0; +} + +static struct ishtp_cl_driver ishtp_cl_driver = { + .name = "ishtp-client", + .probe = ishtp_cl_probe, + .remove = ishtp_cl_remove, + .reset = ishtp_cl_reset, +}; + +static int __init ishtp_client_init(void) +{ + /* Register ISHTP client device driver with ISHTP Bus */ + return ishtp_cl_driver_register(&ishtp_cl_driver); +} + +static void __exit ishtp_client_exit(void) +{ + ishtp_cl_driver_unregister(&ishtp_cl_driver); +} + +/* To make sure ISHTP bus driver loaded first */ +late_initcall(ishtp_client_init); +module_exit(ishtp_client_exit); + +MODULE_DESCRIPTION("ISH ISHTP client driver"); +MODULE_AUTHOR("Even Xu "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ishtp:*"); diff --git a/include/uapi/linux/intel-ishtp-clients.h b/include/uapi/linux/intel-ishtp-clients.h new file mode 100644 index 0000000..792500a --- /dev/null +++ b/include/uapi/linux/intel-ishtp-clients.h @@ -0,0 +1,73 @@ +/* + * Intel ISHTP Clients Interface Header + * + * Copyright (c) 2016, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#ifndef _INTEL_ISHTP_CLIENTS_H +#define _INTEL_ISHTP_CLIENTS_H + +#include +#include +#include +#include +#include + +/* + * This IOCTL is used to associate the current file descriptor with a + * FW Client (given by UUID). This opens a communication channel + * between a host client and a FW client. From this point every read and write + * will communicate with the associated FW client. + * Only in close() (file_operation release()) the communication between + * the clients is disconnected + * + * The IOCTL argument is a struct with a union that contains + * the input parameter and the output parameter for this IOCTL. + * + * The input parameter is UUID of the FW Client. + * The output parameter is the properties of the FW client + * (FW protocol version and max message size). + * + */ +#define IOCTL_ISHTP_CONNECT_CLIENT _IOWR('H', 0x81, \ + struct ishtp_connect_client_data) + +/* Configuration: set number of Rx/Tx buffers. Must be used before connection */ +#define IOCTL_ISHTP_SET_RX_FIFO_SIZE _IOWR('H', 0x82, long) +#define IOCTL_ISHTP_SET_TX_FIFO_SIZE _IOWR('H', 0x83, long) + +/* Get FW status */ +#define IOCTL_ISH_GET_FW_STATUS _IO('H', 0x84) + +#define IOCTL_ISH_HW_RESET _IO('H', 0x85) + +/* + * Intel ISHTP client information struct + */ +struct ishtp_client { + __u32 max_msg_length; + __u8 protocol_version; + __u8 reserved[3]; +}; + +/* + * IOCTL Connect client data structure + */ +struct ishtp_connect_client_data { + union { + uuid_le in_client_uuid; + struct ishtp_client  out_client_properties; + }; +}; + +#endif /* _INTEL_ISHTP_CLIENTS_H */ --  2.7.4 From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Xu, Even" Subject: Re: [PATCH 7/7] misc: intel-ish-client: add intel ishtp clients driver Date: Wed, 4 Jan 2017 06:55:29 +0000 Message-ID: <1483512029.25176.7.camel@intel.com> References: <1482456149-4841-1-git-send-email-even.xu@intel.com> <1482456149-4841-7-git-send-email-even.xu@intel.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 Content-ID: Sender: linux-kernel-owner@vger.kernel.org To: "jikos@kernel.org" Cc: "srinivas.pandruvada@linux.intel.com" , "linux-input@vger.kernel.org" , "benjamin.tissoires@redhat.com" , "linux-kernel@vger.kernel.org" , "gregkh@linuxfoundation.org" , "arnd@arndb.de" , "Shevchenko, Andriy" List-Id: linux-input@vger.kernel.org T24g5LqMLCAyMDE3LTAxLTAzIGF0IDEwOjU0ICswMTAwLCBKaXJpIEtvc2luYSB3cm90ZToNCj4g T24gRnJpLCAyMyBEZWMgMjAxNiwgRXZlbiBYdSB3cm90ZToNCj4gDQo+IFsgLi4uIHNuaXAgLi4u IF0NCj4gPiANCj4gPiArc3RhdGljIHNzaXplX3QgaXNodHBfY2xfd3JpdGUoc3RydWN0IGZpbGUg KmZpbGUsIGNvbnN0IGNoYXIgX191c2VyDQo+ID4gKnVidWYsDQo+ID4gKwlzaXplX3QgbGVuZ3Ro LCBsb2ZmX3QgKm9mZnNldCkNCj4gPiArew0KPiA+ICsJc3RydWN0IGlzaHRwX2NsX21pc2NkZXYg KmlzaHRwX2NsX21pc2MgPSBmaWxlLQ0KPiA+ID5wcml2YXRlX2RhdGE7DQo+ID4gKwlzdHJ1Y3Qg aXNodHBfY2wgKmNsOw0KPiA+ICsJdm9pZCAqd3JpdGVfYnVmOw0KPiA+ICsJc3RydWN0IGlzaHRw X2RldmljZSAqZGV2Ow0KPiA+ICsJaW50IHJldDsNCj4gPiArDQo+ID4gKwkvKiBOb24tYmxvY2tp bmcgc2VtYW50aWNzIGFyZSBub3Qgc3VwcG9ydGVkICovDQo+ID4gKwlpZiAoZmlsZS0+Zl9mbGFn cyAmIE9fTk9OQkxPQ0spIHsNCj4gPiArCQlyZXQgPSAtRUlOVkFMOw0KPiA+ICsJCWdvdG8gb3V0 X3VubG9jazsNCj4gV2hlbiB0YWtpbmcgdGhlIGVycm9yIHBhdGggaGVyZSB5b3UnZCB0cnkgdG8g dW5sb2NrwqANCj4gaXNodHBfY2xfbWlzYy0+Y2xfbXV0ZXggYmVmb3JlIGFjdHVhbGx5IGFjcXVp cmluZyBpdC4NCj4gDQoNClRoYW5rcyBmb3IgeW91ciBjb21tZW50cywgSmlyaSwgSSB1cGRhdGUg bXkgcGF0Y2ggYmVsb3c6DQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09PT0NCg0KSW50ZWwgSVNIRlcgc3VwcG9ydHMgbWFueSBkaWZm ZXJlbnQgY2xpZW50cywgaW4NCmhpZC9pbnRlbC1pc2gtaGlkL2lzaHRwIGJ1cyBkcml2ZXIsIGl0 IGNyZWF0ZXMgZm9sbG93aW5nIGNsaWVudCBkZXZpY2VzOg0KSElEIGNsaWVudDoNCglpbnRlcmZh Y2Ugb2Ygc2Vuc29yIGNvbmZpZ3VyZSBhbmQgc2Vuc29yIGV2ZW50IHJlcG9ydC4NClNNSEkgY2xp ZW50Og0KCWludGVyZmFjZSBvZiBzZW5zb3IgY2FsaWJyYXRpb24sIElTSEZXIGRlYnVnLCBJU0hG VyBwZXJmb3JtYW5jZQ0KCWFuYWx5c2lzIGFuZCBtYW51ZmFjdHVyZSBzdXBwb3J0Lg0KVHJhY2Ug Y2xpZW50Og0KCWludGVyZmFjZSBvZiBJU0hGVyBkZWJ1ZyBsb2cgb3V0cHV0Lg0KVHJhY2UgY29u ZmlndXJlIGNsaWVudDoNCglpbnRlcmZhY2Ugb2YgSVNIRlcgZGVidWcgbG9nIGNvbmZpZ3VyYXRp b24sIHN1Y2ggYXMgb3V0cHV0IHBvcnQsDQoJbG9nIGxldmVsLCBmaWx0ZXIuDQpJU0hGVyBsb2Fk ZXIgY2xpZW50Og0KCWludGVyZmFjZSBvZiBjdXN0b21pemVkIElTSEZXIGxvYWRlci4NCkhJRCBj bGllbnQgaGFzIGJlZW4gaGFuZGxlIGJ5IGhpZC9pbnRlbC1pc2gtaGlkL2ludGVsLWlzaHRwLWhp ZCBjbGllbnQNCmRyaXZlciwgYW5kIHJlc3Qgb2YgdGhlIGNsaWVudHMgZXhwb3J0IGludGVyZmFj ZSB1c2luZyBtaXNjZWxsYW5lb3VzDQpkcml2ZXJzLiBUaGlzIGludGVyZmFjZSBpcyB1c2VkIGJ5 IHVzZXIgc3BhY2UgdG9vbHMgZm9yIGRlYnVnZ2luZyBhbmQNCmNhbGlicmF0aW9uIG9mIHNlbnNv cnMuDQoNClNpZ25lZC1vZmYtYnk6IEV2ZW4gWHUgPGV2ZW4ueHVAaW50ZWwuY29tPg0KUmV2aWV3 ZWQtYnk6IEFuZHJpeSBTaGV2Y2hlbmtvIDxhbmRyaXkuc2hldmNoZW5rb0BpbnRlbC5jb20+DQpS ZXZpZXdlZC1ieTogU3Jpbml2YXMgUGFuZHJ1dmFkYSA8c3Jpbml2YXMucGFuZHJ1dmFkYUBsaW51 eC5pbnRlbC5jb20+DQotLS0NCsKgZHJpdmVycy9taXNjL0tjb25maWfCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgwqAxICsN CsKgZHJpdmVycy9taXNjL01ha2VmaWxlwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfMKgwqDCoDEgKw0KwqBkcml2ZXJzL21pc2MvaW50 ZWwtaXNoLWNsaWVudC9LY29uZmlnwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgMTUg Kw0KwqBkcml2ZXJzL21pc2MvaW50ZWwtaXNoLWNsaWVudC9NYWtlZmlsZcKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgfMKgwqDCoDggKw0KwqAuLi4vbWlzYy9pbnRlbC1pc2gtY2xpZW50L2ludGVs LWlzaHRwLWNsaWVudHMuY8KgwqDCoMKgfCA4ODIgKysrKysrKysrKysrKysrKysrKysrDQrCoGlu Y2x1ZGUvdWFwaS9saW51eC9pbnRlbC1pc2h0cC1jbGllbnRzLmjCoMKgwqDCoMKgwqDCoMKgwqDC oMKgfMKgwqA3MyArKw0KwqA2IGZpbGVzIGNoYW5nZWQsIDk4MCBpbnNlcnRpb25zKCspDQrCoGNy ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21pc2MvaW50ZWwtaXNoLWNsaWVudC9LY29uZmlnDQrC oGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21pc2MvaW50ZWwtaXNoLWNsaWVudC9NYWtlZmls ZQ0KwqBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy9taXNjL2ludGVsLWlzaC1jbGllbnQvaW50 ZWwtaXNodHAtY2xpZW50cy5jDQrCoGNyZWF0ZSBtb2RlIDEwMDY0NCBpbmNsdWRlL3VhcGkvbGlu dXgvaW50ZWwtaXNodHAtY2xpZW50cy5oDQoNCmRpZmYgLS1naXQgYS9kcml2ZXJzL21pc2MvS2Nv bmZpZyBiL2RyaXZlcnMvbWlzYy9LY29uZmlnDQppbmRleCA2NDk3MWJhLi5hODk4NDlmIDEwMDY0 NA0KLS0tIGEvZHJpdmVycy9taXNjL0tjb25maWcNCisrKyBiL2RyaXZlcnMvbWlzYy9LY29uZmln DQpAQCAtNzc4LDQgKzc3OCw1IEBAIHNvdXJjZSAiZHJpdmVycy9taXNjL21pYy9LY29uZmlnIg0K wqBzb3VyY2UgImRyaXZlcnMvbWlzYy9nZW53cWUvS2NvbmZpZyINCsKgc291cmNlICJkcml2ZXJz L21pc2MvZWNoby9LY29uZmlnIg0KwqBzb3VyY2UgImRyaXZlcnMvbWlzYy9jeGwvS2NvbmZpZyIN Citzb3VyY2UgImRyaXZlcnMvbWlzYy9pbnRlbC1pc2gtY2xpZW50L0tjb25maWciDQrCoGVuZG1l bnUNCmRpZmYgLS1naXQgYS9kcml2ZXJzL21pc2MvTWFrZWZpbGUgYi9kcml2ZXJzL21pc2MvTWFr ZWZpbGUNCmluZGV4IDMxOTgzMzYuLmM1NDAxNWQgMTAwNjQ0DQotLS0gYS9kcml2ZXJzL21pc2Mv TWFrZWZpbGUNCg0KKysrIGIvZHJpdmVycy9taXNjL01ha2VmaWxlDQpAQCAtNTMsNiArNTMsNyBA QCBvYmotJChDT05GSUdfRUNITykJCSs9IGVjaG8vDQrCoG9iai0kKENPTkZJR19WRVhQUkVTU19T WVNDRkcpCSs9IHZleHByZXNzLXN5c2NmZy5vDQrCoG9iai0kKENPTkZJR19DWExfQkFTRSkJCSs9 IGN4bC8NCsKgb2JqLSQoQ09ORklHX1BBTkVMKcKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgKz0g cGFuZWwubw0KK29iai0kKENPTkZJR19JTlRFTF9JU0hfQ0xJRU5UKQkrPSBpbnRlbC1pc2gtY2xp ZW50Lw0KwqANCsKgbGtkdG0tJChDT05GSUdfTEtEVE0pCQkrPSBsa2R0bV9jb3JlLm8NCsKgbGtk dG0tJChDT05GSUdfTEtEVE0pCQkrPSBsa2R0bV9idWdzLm8NCmRpZmYgLS1naXQgYS9kcml2ZXJz L21pc2MvaW50ZWwtaXNoLWNsaWVudC9LY29uZmlnIGIvZHJpdmVycy9taXNjL2ludGVsLWlzaC1j bGllbnQvS2NvbmZpZw0KbmV3IGZpbGUgbW9kZSAxMDA2NDQNCmluZGV4IDAwMDAwMDAuLjZmYTlj YzANCi0tLSAvZGV2L251bGwNCisrKyBiL2RyaXZlcnMvbWlzYy9pbnRlbC1pc2gtY2xpZW50L0tj b25maWcNCkBAIC0wLDAgKzEsMTUgQEANCittZW51ICJJbnRlbCBJU0ggQ2xpZW50IHN1cHBvcnQi DQorCWRlcGVuZHMgb24gSU5URUxfSVNIX0hJRA0KKw0KK2NvbmZpZyBJTlRFTF9JU0hfQ0xJRU5U DQorCXRyaXN0YXRlICJJbnRlbCBJbnRlZ3JhdGVkIFNlbnNvciBIdWIgQ2xpZW50Ig0KKwloZWxw DQorCcKgwqBUaGUgSW50ZWdyYXRlZCBTZW5zb3IgSHViIChJU0gpIHN1cHBvcnRzIG1hbnkgY2xp ZW50cywgSW50ZWwgSVNIIGNsaWVudA0KKwnCoMKgZHJpdmVyIHN1cHBvcnRzIGZvbGxvd2luZyBj bGllbnRzOg0KKwnCoMKgU01ISSBjbGllbnQ6IGNhbGlicmF0aW9uICYgcGVyZmVybWFuY2UgJiBt ZW51ZmFjdHVyZSB0b29sIGludGVyZmFjZQ0KKwnCoMKgdHJhY2UgY29uZmlndXJlIGNsaWVudDog SVNIRlcgdHJhY2UgcGFyYW1ldGVyIGNvbmZpZ3VyZSBpbnRlcmZhY2UNCisJwqDCoHRyYWNlIHRv b2wgY2xpZW50OiBJU0hGVyB0cmFjZSBsb2cgb3V0cHV0IGludGVyZmFjZQ0KKwnCoMKgbG9hZGVy IGNsaWVudDogbG9hZGluZyBjdXN0b21pemVkIElTSEZXIGludGVyZmFjZQ0KKw0KKwnCoMKgU2F5 IFkgaGVyZSBpZiB5b3Ugd2FudCB0byBzdXBwb3J0IEludGVsIElTSCBjbGllbnRzLiBJZiB1bnN1 cmUsIHNheSBOLg0KK2VuZG1lbnUNCmRpZmYgLS1naXQgYS9kcml2ZXJzL21pc2MvaW50ZWwtaXNo LWNsaWVudC9NYWtlZmlsZSBiL2RyaXZlcnMvbWlzYy9pbnRlbC1pc2gtY2xpZW50L01ha2VmaWxl DQpuZXcgZmlsZSBtb2RlIDEwMDY0NA0KaW5kZXggMDAwMDAwMC4uMjlhNTQ2MQ0KLS0tIC9kZXYv bnVsbA0KKysrIGIvZHJpdmVycy9taXNjL2ludGVsLWlzaC1jbGllbnQvTWFrZWZpbGUNCkBAIC0w LDAgKzEsOCBAQA0KKyMNCisjIE1ha2VmaWxlIC0gSW50ZWwgSVNIIGNsaWVudCBkcml2ZXINCisj IENvcHlyaWdodCAoYykgMjAxNC0yMDE2LCBJbnRlbCBDb3Jwb3JhdGlvbi4NCisjDQorIw0KK29i ai0kKENPTkZJR19JTlRFTF9JU0hfQ0xJRU5UKSArPSBpbnRlbC1pc2h0cC1jbGllbnRzLm8NCisN CitjY2ZsYWdzLXkgKz0gLUkkKHNyY3RyZWUpL2RyaXZlcnMvaGlkL2ludGVsLWlzaC1oaWQvaXNo dHANCmRpZmYgLS1naXQgYS9kcml2ZXJzL21pc2MvaW50ZWwtaXNoLWNsaWVudC9pbnRlbC1pc2h0 cC1jbGllbnRzLmMgYi9kcml2ZXJzL21pc2MvaW50ZWwtaXNoLWNsaWVudC9pbnRlbC1pc2h0cC1j bGllbnRzLmMNCm5ldyBmaWxlIG1vZGUgMTAwNjQ0DQppbmRleCAwMDAwMDAwLi40Y2EzYWI4DQot LS0gL2Rldi9udWxsDQorKysgYi9kcml2ZXJzL21pc2MvaW50ZWwtaXNoLWNsaWVudC9pbnRlbC1p c2h0cC1jbGllbnRzLmMNCkBAIC0wLDAgKzEsODgyIEBADQorLyoNCisgKiBJU0hUUCBjbGllbnRz IGRyaXZlcg0KKyAqDQorICogQ29weXJpZ2h0IChjKSAyMDE2LCBJbnRlbCBDb3Jwb3JhdGlvbi4N CisgKg0KKyAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJp YnV0ZSBpdCBhbmQvb3IgbW9kaWZ5IGl0DQorICogdW5kZXIgdGhlIHRlcm1zIGFuZCBjb25kaXRp b25zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSwNCisgKiB2ZXJzaW9uIDIsIGFz IHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLg0KKyAqDQorICogVGhp cyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIGl0IHdpbGwgYmUgdXNlZnVsLCBi dXQgV0lUSE9VVA0KKyAqIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdh cnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWSBvcg0KKyAqIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxB UiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvcg0KKyAqIG1v cmUgZGV0YWlscy4NCisgKi8NCisNCisjaW5jbHVkZSA8bGludXgvY2FwYWJpbGl0eS5oPg0KKyNp bmNsdWRlIDxsaW51eC9kZWxheS5oPg0KKyNpbmNsdWRlIDxsaW51eC9kZXZpY2UuaD4NCisjaW5j bHVkZSA8bGludXgvZXJybm8uaD4NCisjaW5jbHVkZSA8bGludXgvZnMuaD4NCisjaW5jbHVkZSA8 bGludXgvaW50ZXJydXB0Lmg+DQorI2luY2x1ZGUgPGxpbnV4L2ludGVsLWlzaHRwLWNsaWVudHMu aD4NCisjaW5jbHVkZSA8bGludXgvaW9jdGwuaD4NCisjaW5jbHVkZSA8bGludXgva2VybmVsLmg+ DQorI2luY2x1ZGUgPGxpbnV4L21pc2NkZXZpY2UuaD4NCisjaW5jbHVkZSA8bGludXgvbW9kdWxl Lmg+DQorI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4NCisjaW5jbHVkZSA8bGludXgvdHlwZXMuaD4N CisjaW5jbHVkZSA8bGludXgvdXVpZC5oPg0KKyNpbmNsdWRlIDxsaW51eC91YWNjZXNzLmg+DQor DQorI2luY2x1ZGUgImlzaHRwLWRldi5oIg0KKyNpbmNsdWRlICJjbGllbnQuaCINCisNCisvKg0K KyAqIElTSCBjbGllbnQgbWlzYyBkcml2ZXIgc3RydWN0dXJlDQorICovDQorc3RydWN0IGlzaHRw X2NsX21pc2NkZXYgew0KKwlzdHJ1Y3QgbWlzY2RldmljZSBjbF9taXNjZGV2Ow0KKwlzdHJ1Y3Qg aXNodHBfY2xfZGV2aWNlICpjbF9kZXZpY2U7DQorCXN0cnVjdCBpc2h0cF9jbCAqY2w7DQorDQor CS8qIFdhaXQgcXVldWUgZm9yIHdhaXRpbmcgSVNIRlcgZXZlbnQvbWVzc2FnZSAqLw0KKwl3YWl0 X3F1ZXVlX2hlYWRfdCByZWFkX3dhaXQ7DQorCS8qIFJlYWQgYnVmZmVyLCB3aWxsIHBvaW50IHRv IGF2YWlsYWJsZSBJU0hGVyBtZXNzYWdlICovDQorCXN0cnVjdCBpc2h0cF9jbF9yYiAqcmVhZF9y YjsNCisNCisJLyoNCisJwqAqIGNsIG1lbWJlciBjYW4gYmUgZnJlZWQvY2hhbmdlZCBieSBJU0hG VyByZXNldCBhbmQgcmVsZWFzZSgpIGNhbGxpbmcsDQorCcKgKiBzbyBtdXN0IHBheSBhdHRlbnRp b24gdG8gcHJvdGVjdCBjbCB3aGlsZSB0cnkgdG8gYWNjZXNzIGl0LiBUaGlzDQorCcKgKiBtdXRl eCBpcyB1c2VkIHRvIHByb3RlY3QgY2wgbWVtYmVyLg0KKwnCoCovDQorCXN0cnVjdCBtdXRleCBj bF9tdXRleDsNCisNCisJc3RydWN0IHdvcmtfc3RydWN0IHJlc2V0X3dvcms7DQorfTsNCisNCisv KiBJU0ggY2xpZW50IEdVSURzICovDQorLyogU01ISSBjbGllbnQgVVVJRDogYmI1NzlhMmUtY2M1 NC00NDUwLWIxZDAtNWU3NTIwZGNhZDI1ICovDQorc3RhdGljIGNvbnN0IHV1aWRfbGUgaXNodHBf c21oaV9ndWlkID0NCisJCQlVVUlEX0xFKDB4YmI1NzlhMmUsIDB4Y2M1NCwgMHg0NDUwLA0KKwkJ CQkweGIxLCAweGQwLCAweDVlLCAweDc1LCAweDIwLCAweGRjLCAweGFkLCAweDI1KTsNCisNCisv KiBUcmFjZSBsb2cgY2xpZW50IFVVSUQ6IGMxY2M3OGI5LWI2OTMtNGU1NC05MTkxLTUxNjljYjAy N2MyNSAqLw0KK3N0YXRpYyBjb25zdCB1dWlkX2xlIGlzaHRwX3RyYWNlX2d1aWQgPQ0KKwkJCVVV SURfTEUoMHhjMWNjNzhiOSwgMHhiNjkzLCAweDRlNTQsDQorCQkJCTB4OTEsIDB4OTEsIDB4NTEs IDB4NjksIDB4Y2IsIDB4MDIsIDB4N2MsIDB4MjUpOw0KKw0KKy8qIFRyYWNlIGNvbmZpZyBjbGll bnQgVVVJRDogMWYwNTA2MjYtZDUwNS00ZTk0LWIxODktNTM1ZDdkZTE5Y2YyICovDQorc3RhdGlj IGNvbnN0IHV1aWRfbGUgaXNodHBfdHJhY2Vjb25maWdfZ3VpZCA9DQorCQkJVVVJRF9MRSgweDFm MDUwNjI2LCAweGQ1MDUsIDB4NGU5NCwNCisJCQkJMHhiMSwgMHg4OSwgMHg1MywgMHg1ZCwgMHg3 ZCwgMHhlMSwgMHg5YywgMHhmMik7DQorDQorLyogSVNIRlcgbG9hZGVyIGNsaWVudCBVVUlEOiBj ODA0ZDA2YS01NWJkLTRlYTctYWRlZC0xZTMxMjI4Yzc2ZGMgKi8NCitzdGF0aWMgY29uc3QgdXVp ZF9sZSBpc2h0cF9sb2FkZXJfZ3VpZCA9DQorCQkJVVVJRF9MRSgweGM4MDRkMDZhLCAweDU1YmQs IDB4NGVhNywNCisJCQkJMHhhZCwgMHhlZCwgMHgxZSwgMHgzMSwgMHgyMiwgMHg4YywgMHg3Niwg MHhkYyk7DQorDQorc3RhdGljIGludCBpc2h0cF9jbF9vcGVuKHN0cnVjdCBpbm9kZSAqaW5vZGUs IHN0cnVjdCBmaWxlICpmaWxlKQ0KK3sNCisJc3RydWN0IG1pc2NkZXZpY2UgKm1pc2MgPSBmaWxl LT5wcml2YXRlX2RhdGE7DQorCXN0cnVjdCBpc2h0cF9jbCAqY2w7DQorCXN0cnVjdCBpc2h0cF9k ZXZpY2UgKmRldjsNCisJc3RydWN0IGlzaHRwX2NsX21pc2NkZXYgKmlzaHRwX2NsX21pc2M7DQor CWludCByZXQ7DQorDQorCS8qIE5vbi1ibG9ja2luZyBzZW1hbnRpY3MgYXJlIG5vdCBzdXBwb3J0 ZWQgKi8NCisJaWYgKGZpbGUtPmZfZmxhZ3MgJiBPX05PTkJMT0NLKQ0KKwkJcmV0dXJuIC1FSU5W QUw7DQorDQorCWlzaHRwX2NsX21pc2MgPSBjb250YWluZXJfb2YobWlzYywNCisJCQkJc3RydWN0 IGlzaHRwX2NsX21pc2NkZXYsIGNsX21pc2NkZXYpOw0KKwlpZiAoIWlzaHRwX2NsX21pc2MgfHwg IWlzaHRwX2NsX21pc2MtPmNsX2RldmljZSkNCisJCXJldHVybiAtRU5PREVWOw0KKw0KKwlkZXYg PSBpc2h0cF9jbF9taXNjLT5jbF9kZXZpY2UtPmlzaHRwX2RldjsNCisJaWYgKCFkZXYpDQorCQly ZXR1cm4gLUVOT0RFVjsNCisNCisJbXV0ZXhfbG9jaygmaXNodHBfY2xfbWlzYy0+Y2xfbXV0ZXgp Ow0KKw0KKwkvKg0KKwnCoCogRXZlcnkgY2xpZW50IG9ubHkgc3VwcG9ydHMgb25lIG9wZW5lZCBp bnN0YW5jZQ0KKwnCoCogYXQgdGhlIHNhbWV0aW1lLg0KKwnCoCovDQorCWlmIChpc2h0cF9jbF9t aXNjLT5jbCkgew0KKwkJcmV0ID0gLUVCVVNZOw0KKwkJZ290byBvdXRfdW5sb2NrOw0KKwl9DQor DQorCWNsID0gaXNodHBfY2xfYWxsb2NhdGUoZGV2KTsNCisJaWYgKCFjbCkgew0KKwkJcmV0ID0g LUVOT01FTTsNCisJCWdvdG8gb3V0X2ZyZWU7DQorCX0NCisNCisJaWYgKGRldi0+ZGV2X3N0YXRl ICE9IElTSFRQX0RFVl9FTkFCTEVEKSB7DQorCQlyZXQgPSAtRU5PREVWOw0KKwkJZ290byBvdXRf ZnJlZTsNCisJfQ0KKw0KKwlyZXQgPSBpc2h0cF9jbF9saW5rKGNsLCBJU0hUUF9IT1NUX0NMSUVO VF9JRF9BTlkpOw0KKwlpZiAocmV0KQ0KKwkJZ290byBvdXRfZnJlZTsNCisNCisJaXNodHBfY2xf bWlzYy0+Y2wgPSBjbDsNCisNCisJZmlsZS0+cHJpdmF0ZV9kYXRhID0gaXNodHBfY2xfbWlzYzsN CisNCisJbXV0ZXhfdW5sb2NrKCZpc2h0cF9jbF9taXNjLT5jbF9tdXRleCk7DQorDQorCXJldHVy biBub25zZWVrYWJsZV9vcGVuKGlub2RlLCBmaWxlKTsNCisNCitvdXRfZnJlZToNCisJa2ZyZWUo Y2wpOw0KK291dF91bmxvY2s6DQorCW11dGV4X3VubG9jaygmaXNodHBfY2xfbWlzYy0+Y2xfbXV0 ZXgpOw0KKwlyZXR1cm4gcmV0Ow0KK30NCisNCisjZGVmaW5lIFdBSVRfRk9SX1NFTkRfU0xJQ0Vf TVMJCTEwMA0KKyNkZWZpbmUgV0FJVF9GT1JfU0VORF9DT1VOVAkJMTANCisNCitzdGF0aWMgaW50 IGlzaHRwX2NsX3JlbGVhc2Uoc3RydWN0IGlub2RlICppbm9kZSwgc3RydWN0IGZpbGUgKmZpbGUp DQorew0KKwlzdHJ1Y3QgaXNodHBfY2xfbWlzY2RldiAqaXNodHBfY2xfbWlzYyA9IGZpbGUtPnBy aXZhdGVfZGF0YTsNCisJc3RydWN0IGlzaHRwX2NsICpjbDsNCisJc3RydWN0IGlzaHRwX2NsX3Ji ICpyYjsNCisJc3RydWN0IGlzaHRwX2RldmljZSAqZGV2Ow0KKwlpbnQgdHJ5ID0gV0FJVF9GT1Jf U0VORF9DT1VOVDsNCisJaW50IHJldDsNCisNCisJbXV0ZXhfbG9jaygmaXNodHBfY2xfbWlzYy0+ Y2xfbXV0ZXgpOw0KKw0KKwkvKiBXYWtlIHVwIGZyb20gd2FpdGluZyBpZiBhbnlvbmUgd2FpdCBv biBpdCAqLw0KKwl3YWtlX3VwX2ludGVycnVwdGlibGUoJmlzaHRwX2NsX21pc2MtPnJlYWRfd2Fp dCk7DQorDQorCWNsID0gaXNodHBfY2xfbWlzYy0+Y2w7DQorCWRldiA9IGNsLT5kZXY7DQorDQor CS8qDQorCcKgKiBNYXkgaGFwcGVuIGlmIGRldmljZSBzZW50IEZXIHJlc2V0IG9yIHdhcyBpbnRl bnRpb25hbGx5DQorCcKgKiBoYWx0ZWQgYnkgaG9zdCBTVy4gVGhlIGNsaWVudCBpcyB0aGVuIGlu dmFsaWQuDQorCcKgKi8NCisJaWYgKChkZXYtPmRldl9zdGF0ZSA9PSBJU0hUUF9ERVZfRU5BQkxF RCkgJiYNCisJCQkoY2wtPnN0YXRlID09IElTSFRQX0NMX0NPTk5FQ1RFRCkpIHsNCisJCS8qDQor CQnCoCogQ2hlY2sgYW5kIHdhaXQgMXMgZm9yIG1lc3NhZ2UgaW4gdHhfbGlzdCB0byBiZSBzZW50 Lg0KKwkJwqAqLw0KKwkJZG8gew0KKwkJCWlmICghaXNodHBfY2xfdHhfZW1wdHkoY2wpKQ0KKwkJ CQltc2xlZXBfaW50ZXJydXB0aWJsZShXQUlUX0ZPUl9TRU5EX1NMSUNFX01TKTsNCisJCQllbHNl DQorCQkJCWJyZWFrOw0KKwkJfSB3aGlsZSAoLS10cnkpOw0KKw0KKwkJY2wtPnN0YXRlID0gSVNI VFBfQ0xfRElTQ09OTkVDVElORzsNCisJCXJldCA9IGlzaHRwX2NsX2Rpc2Nvbm5lY3QoY2wpOw0K Kwl9DQorDQorCWlzaHRwX2NsX3VubGluayhjbCk7DQorCWlzaHRwX2NsX2ZsdXNoX3F1ZXVlcyhj bCk7DQorCS8qIERpc2JhbmQgYW5kIGZyZWUgYWxsIFR4IGFuZCBSeCBjbGllbnQtbGV2ZWwgcmlu Z3MgKi8NCisJaXNodHBfY2xfZnJlZShjbCk7DQorDQorCWlzaHRwX2NsX21pc2MtPmNsID0gTlVM TDsNCisNCisJcmIgPSBpc2h0cF9jbF9taXNjLT5yZWFkX3JiOw0KKwlpZiAocmIpIHsNCisJCWlz aHRwX2NsX2lvX3JiX3JlY3ljbGUocmIpOw0KKwkJaXNodHBfY2xfbWlzYy0+cmVhZF9yYiA9IE5V TEw7DQorCX0NCisNCisJZmlsZS0+cHJpdmF0ZV9kYXRhID0gTlVMTDsNCisNCisJbXV0ZXhfdW5s b2NrKCZpc2h0cF9jbF9taXNjLT5jbF9tdXRleCk7DQorDQorCXJldHVybiByZXQ7DQorfQ0KKw0K K3N0YXRpYyBzc2l6ZV90IGlzaHRwX2NsX3JlYWQoc3RydWN0IGZpbGUgKmZpbGUsIGNoYXIgX191 c2VyICp1YnVmLA0KKwkJCXNpemVfdCBsZW5ndGgsIGxvZmZfdCAqb2Zmc2V0KQ0KK3sNCisJc3Ry dWN0IGlzaHRwX2NsX21pc2NkZXYgKmlzaHRwX2NsX21pc2MgPSBmaWxlLT5wcml2YXRlX2RhdGE7 DQorCXN0cnVjdCBpc2h0cF9jbCAqY2w7DQorCXN0cnVjdCBpc2h0cF9jbF9yYiAqcmI7DQorCXN0 cnVjdCBpc2h0cF9kZXZpY2UgKmRldjsNCisJaW50IHJldCA9IDA7DQorDQorCS8qIE5vbi1ibG9j a2luZyBzZW1hbnRpY3MgYXJlIG5vdCBzdXBwb3J0ZWQgKi8NCisJaWYgKGZpbGUtPmZfZmxhZ3Mg JiBPX05PTkJMT0NLKQ0KKwkJcmV0dXJuIC1FSU5WQUw7DQorDQorCW11dGV4X2xvY2soJmlzaHRw X2NsX21pc2MtPmNsX211dGV4KTsNCisNCisJY2wgPSBpc2h0cF9jbF9taXNjLT5jbDsNCisNCisJ LyoNCisJwqAqIElTSEZXIHJlc2V0IHdpbGwgY2F1c2UgY2wgYmUgZnJlZWQgYW5kIHJlLWFsbG9j YXRlZC4NCisJwqAqIFNvIG11c3QgbWFrZSBzdXJlIGNsIGlzIHJlLWFsbG9jYXRlZCBzdWNjZXNz ZnVsbHkuDQorCcKgKi8NCisJaWYgKCFjbCB8fCAhY2wtPmRldikgew0KKwkJcmV0ID0gLUVOT0RF VjsNCisJCWdvdG8gb3V0X3VubG9jazsNCisJfQ0KKw0KKwlkZXYgPSBjbC0+ZGV2Ow0KKwlpZiAo ZGV2LT5kZXZfc3RhdGUgIT0gSVNIVFBfREVWX0VOQUJMRUQpIHsNCisJCXJldCA9IC1FTk9ERVY7 DQorCQlnb3RvIG91dF91bmxvY2s7DQorCX0NCisNCisJaWYgKGlzaHRwX2NsX21pc2MtPnJlYWRf cmIpDQorCQlnb3RvIGdldF9yYjsNCisNCisJcmIgPSBpc2h0cF9jbF9yeF9nZXRfcmIoY2wpOw0K KwlpZiAocmIpDQorCQlnb3RvIGNvcHlfYnVmZmVyOw0KKw0KKwkvKg0KKwnCoCogUmVsZWFzZSBt dXRleCBmb3Igb3RoZXIgb3BlcmF0aW9uIGNhbiBiZSBwcm9jZXNzZWQgcGFyYWxsZWxseQ0KKwnC oCogZHVyaW5nIHdhaXRpbmcuDQorCcKgKi8NCisJbXV0ZXhfdW5sb2NrKCZpc2h0cF9jbF9taXNj LT5jbF9tdXRleCk7DQorDQorCWlmICh3YWl0X2V2ZW50X2ludGVycnVwdGlibGUoaXNodHBfY2xf bWlzYy0+cmVhZF93YWl0LA0KKwkJCWlzaHRwX2NsX21pc2MtPnJlYWRfcmIgIT0gTlVMTCkpIHsN CisJCWRldl9lcnIoJmlzaHRwX2NsX21pc2MtPmNsX2RldmljZS0+ZGV2LA0KKwkJCSJXYWtlIHVw IG5vdCBzdWNjZXNzZnVsOyINCisJCQkic2lnbmFsIHBlbmRpbmcgPSAlZCBzaWduYWwgPSAlMDhs WFxuIiwNCisJCQlzaWduYWxfcGVuZGluZyhjdXJyZW50KSwNCisJCQljdXJyZW50LT5wZW5kaW5n LnNpZ25hbC5zaWdbMF0pOw0KKwkJcmV0dXJuIC1FUkVTVEFSVFNZUzsNCisJfQ0KKw0KKwltdXRl eF9sb2NrKCZpc2h0cF9jbF9taXNjLT5jbF9tdXRleCk7DQorDQorCS8qDQorCcKgKiB3YWl0cXVl dWUgY2FuIGJlIHdva2VuIHVwIGluIG1hbnkgY2FzZXMsIHNvIG11c3QgY2hlY2sNCisJwqAqIGlm IGRldiBhbmQgY2wgaXMgc3RpbGwgYXZhaWxhYmxlLg0KKwnCoCovDQorCWlmIChkZXYtPmRldl9z dGF0ZSAhPSBJU0hUUF9ERVZfRU5BQkxFRCkgew0KKwkJcmV0ID0gLUVOT0RFVjsNCisJCWdvdG8g b3V0X3VubG9jazsNCisJfQ0KKw0KKwljbCA9IGlzaHRwX2NsX21pc2MtPmNsOw0KKwlpZiAoIWNs KSB7DQorCQlyZXQgPSAtRU5PREVWOw0KKwkJZ290byBvdXRfdW5sb2NrOw0KKwl9DQorDQorCWlm IChjbC0+c3RhdGUgPT0gSVNIVFBfQ0xfSU5JVElBTElaSU5HIHx8DQorCQljbC0+c3RhdGUgPT0g SVNIVFBfQ0xfRElTQ09OTkVDVEVEIHx8DQorCQljbC0+c3RhdGUgPT0gSVNIVFBfQ0xfRElTQ09O TkVDVElORykgew0KKwkJcmV0ID0gLUVCVVNZOw0KKwkJZ290byBvdXRfdW5sb2NrOw0KKwl9DQor DQorZ2V0X3JiOg0KKwlyYiA9IGlzaHRwX2NsX21pc2MtPnJlYWRfcmI7DQorCWlmICghcmIpIHsN CisJCXJldCA9IC1FTk9ERVY7DQorCQlnb3RvIG91dF91bmxvY2s7DQorCX0NCisNCitjb3B5X2J1 ZmZlcjoNCisJLyogTm93IGNvcHkgdGhlIGRhdGEgdG8gdXNlciBzcGFjZSAqLw0KKwlpZiAoIWxl bmd0aCB8fCAhdWJ1ZiB8fCAqb2Zmc2V0ID4gcmItPmJ1Zl9pZHgpIHsNCisJCXJldCA9IC1FTVNH U0laRTsNCisJCWdvdG8gb3V0X3VubG9jazsNCisJfQ0KKw0KKwkvKg0KKwnCoCogbGVuZ3RoIGlz IGJlaW5nIHRydW5jYXRlZCwgaG93ZXZlciBidWZfaWR4IG1heQ0KKwnCoCogcG9pbnQgYmV5b25k IHRoYXQuDQorCcKgKi8NCisJbGVuZ3RoID0gbWluX3Qoc2l6ZV90LCBsZW5ndGgsIHJiLT5idWZf aWR4IC0gKm9mZnNldCk7DQorDQorCWlmIChjb3B5X3RvX3VzZXIodWJ1ZiwgcmItPmJ1ZmZlci5k YXRhICsgKm9mZnNldCwgbGVuZ3RoKSkgew0KKwkJcmV0ID0gLUVGQVVMVDsNCisJCWdvdG8gb3V0 X3VubG9jazsNCisJfQ0KKw0KKwkqb2Zmc2V0ICs9IGxlbmd0aDsNCisJaWYgKCh1bnNpZ25lZCBs b25nKSpvZmZzZXQgPCByYi0+YnVmX2lkeCkNCisJCWdvdG8gb3V0X3VubG9jazsNCisNCisJaXNo dHBfY2xfaW9fcmJfcmVjeWNsZShyYik7DQorCWlzaHRwX2NsX21pc2MtPnJlYWRfcmIgPSBOVUxM Ow0KKwkqb2Zmc2V0ID0gMDsNCisNCitvdXRfdW5sb2NrOg0KKwltdXRleF91bmxvY2soJmlzaHRw X2NsX21pc2MtPmNsX211dGV4KTsNCisJcmV0dXJuIHJldCA8IDAgPyByZXQgOiBsZW5ndGg7DQor fQ0KKw0KK3N0YXRpYyBzc2l6ZV90IGlzaHRwX2NsX3dyaXRlKHN0cnVjdCBmaWxlICpmaWxlLCBj b25zdCBjaGFyIF9fdXNlciAqdWJ1ZiwNCisJc2l6ZV90IGxlbmd0aCwgbG9mZl90ICpvZmZzZXQp DQorew0KKwlzdHJ1Y3QgaXNodHBfY2xfbWlzY2RldiAqaXNodHBfY2xfbWlzYyA9IGZpbGUtPnBy aXZhdGVfZGF0YTsNCisJc3RydWN0IGlzaHRwX2NsICpjbDsNCisJdm9pZCAqd3JpdGVfYnVmOw0K KwlzdHJ1Y3QgaXNodHBfZGV2aWNlICpkZXY7DQorCWludCByZXQ7DQorDQorCS8qIE5vbi1ibG9j a2luZyBzZW1hbnRpY3MgYXJlIG5vdCBzdXBwb3J0ZWQgKi8NCisJaWYgKGZpbGUtPmZfZmxhZ3Mg JiBPX05PTkJMT0NLKQ0KKwkJcmV0dXJuIC1FSU5WQUw7DQorDQorCW11dGV4X2xvY2soJmlzaHRw X2NsX21pc2MtPmNsX211dGV4KTsNCisNCisJY2wgPSBpc2h0cF9jbF9taXNjLT5jbDsNCisNCisJ LyoNCisJwqAqIElTSEZXIHJlc2V0IHdpbGwgY2F1c2UgY2wgYmUgZnJlZWQgYW5kIHJlLWFsbG9j YXRlZC4NCisJwqAqIFNvIG11c3QgbWFrZSBzdXJlIGNsIGlzIHJlLWFsbG9jYXRlZCBzdWNjZXNz ZnVsbHkuDQorCcKgKi8NCisJaWYgKCFjbCB8fCAhY2wtPmRldikgew0KKwkJcmV0ID0gLUVOT0RF VjsNCisJCWdvdG8gb3V0X3VubG9jazsNCisJfQ0KKw0KKwlkZXYgPSBjbC0+ZGV2Ow0KKw0KKwlp ZiAoZGV2LT5kZXZfc3RhdGUgIT0gSVNIVFBfREVWX0VOQUJMRUQpIHsNCisJCXJldCA9IC1FTk9E RVY7DQorCQlnb3RvIG91dF91bmxvY2s7DQorCX0NCisNCisJaWYgKGNsLT5zdGF0ZSAhPSBJU0hU UF9DTF9DT05ORUNURUQpIHsNCisJCWRldl9lcnIoJmlzaHRwX2NsX21pc2MtPmNsX2RldmljZS0+ ZGV2LA0KKwkJCSJob3N0IGNsaWVudCA9ICVkIGlzbid0IGNvbm5lY3RlZCB0byBmdyBjbGllbnQg PSAlZFxuIiwNCisJCQljbC0+aG9zdF9jbGllbnRfaWQsIGNsLT5md19jbGllbnRfaWQpOw0KKwkJ cmV0ID0gLUVOT0RFVjsNCisJCWdvdG8gb3V0X3VubG9jazsNCisJfQ0KKw0KKwlpZiAobGVuZ3Ro IDw9IDAgfHwgbGVuZ3RoID4gY2wtPmRldmljZS0+ZndfY2xpZW50LT5wcm9wcy5tYXhfbXNnX2xl bmd0aCkgew0KKwkJcmV0ID0gLUVNU0dTSVpFOw0KKwkJZ290byBvdXRfdW5sb2NrOw0KKwl9DQor DQorCXdyaXRlX2J1ZiA9IG1lbWR1cF91c2VyKHVidWYsIGxlbmd0aCk7DQorCWlmIChJU19FUlIo d3JpdGVfYnVmKSkgew0KKwkJcmV0ID0gUFRSX0VSUih3cml0ZV9idWYpOw0KKwkJZ290byBvdXRf dW5sb2NrOw0KKwl9DQorDQorCXJldCA9IGlzaHRwX2NsX3NlbmQoY2wsIHdyaXRlX2J1ZiwgbGVu Z3RoKTsNCisNCisJa2ZyZWUod3JpdGVfYnVmKTsNCisNCitvdXRfdW5sb2NrOg0KKwltdXRleF91 bmxvY2soJmlzaHRwX2NsX21pc2MtPmNsX211dGV4KTsNCisNCisJcmV0dXJuIHJldCA8IDAgPyBy ZXQgOiBsZW5ndGg7DQorfQ0KKw0KK3N0YXRpYyBpbnQgaXNodHBfY2xfaW9jdGxfY29ubmVjdF9j bGllbnQoc3RydWN0IGZpbGUgKmZpbGUsDQorCXN0cnVjdCBpc2h0cF9jb25uZWN0X2NsaWVudF9k YXRhICpkYXRhKQ0KK3sNCisJc3RydWN0IGlzaHRwX2NsX21pc2NkZXYgKmlzaHRwX2NsX21pc2Mg PSBmaWxlLT5wcml2YXRlX2RhdGE7DQorCXN0cnVjdCBpc2h0cF9kZXZpY2UgKmRldjsNCisJc3Ry dWN0IGlzaHRwX2NsaWVudCAqY2xpZW50Ow0KKwlzdHJ1Y3QgaXNodHBfY2xfZGV2aWNlICpjbF9k ZXZpY2U7DQorCXN0cnVjdCBpc2h0cF9jbCAqY2wgPSBpc2h0cF9jbF9taXNjLT5jbDsNCisJc3Ry dWN0IGlzaHRwX2Z3X2NsaWVudCAqZndfY2xpZW50Ow0KKw0KKwlpZiAoIWNsIHx8ICFjbC0+ZGV2 KQ0KKwkJcmV0dXJuIC1FTk9ERVY7DQorDQorCWRldiA9IGNsLT5kZXY7DQorDQorCWlmIChkZXYt PmRldl9zdGF0ZSAhPSBJU0hUUF9ERVZfRU5BQkxFRCkNCisJCXJldHVybiAtRU5PREVWOw0KKw0K KwlpZiAoY2wtPnN0YXRlICE9IElTSFRQX0NMX0lOSVRJQUxJWklORyAmJg0KKwkJCWNsLT5zdGF0 ZSAhPSBJU0hUUF9DTF9ESVNDT05ORUNURUQpDQorCQlyZXR1cm4gLUVCVVNZOw0KKw0KKwljbF9k ZXZpY2UgPSBpc2h0cF9jbF9taXNjLT5jbF9kZXZpY2U7DQorDQorCWlmICh1dWlkX2xlX2NtcChk YXRhLT5pbl9jbGllbnRfdXVpZCwNCisJCQljbF9kZXZpY2UtPmZ3X2NsaWVudC0+cHJvcHMucHJv dG9jb2xfbmFtZSkgIT0gMCkgew0KKwkJZGV2X2VycigmaXNodHBfY2xfbWlzYy0+Y2xfZGV2aWNl LT5kZXYsDQorCQkJIlJlcXVpcmVkIHV1aWQgZG9uJ3QgbWF0Y2ggY3VycmVudCBjbGllbnQgdXVp ZFxuIik7DQorCQlyZXR1cm4gLUVGQVVMVDsNCisJfQ0KKw0KKwkvKiBGaW5kIHRoZSBmdyBjbGll bnQgd2UncmUgdHJ5aW5nIHRvIGNvbm5lY3QgdG8gKi8NCisJZndfY2xpZW50ID0gaXNodHBfZndf Y2xfZ2V0X2NsaWVudChkZXYsICZkYXRhLT5pbl9jbGllbnRfdXVpZCk7DQorCWlmICghZndfY2xp ZW50KSB7DQorCQlkZXZfZXJyKCZpc2h0cF9jbF9taXNjLT5jbF9kZXZpY2UtPmRldiwNCisJCQki RG9uJ3QgZmluZCBjdXJyZW50IGNsaWVudCB1dWlkXG4iKTsNCisJCXJldHVybiAtRU5PRU5UOw0K Kwl9DQorDQorCWNsLT5md19jbGllbnRfaWQgPSBmd19jbGllbnQtPmNsaWVudF9pZDsNCisJY2wt PnN0YXRlID0gSVNIVFBfQ0xfQ09OTkVDVElORzsNCisNCisJLyogUHJlcGFyZSB0aGUgb3V0cHV0 IGJ1ZmZlciAqLw0KKwljbGllbnQgPSAmZGF0YS0+b3V0X2NsaWVudF9wcm9wZXJ0aWVzOw0KKwlj bGllbnQtPm1heF9tc2dfbGVuZ3RoID0gZndfY2xpZW50LT5wcm9wcy5tYXhfbXNnX2xlbmd0aDsN CisJY2xpZW50LT5wcm90b2NvbF92ZXJzaW9uID0gZndfY2xpZW50LT5wcm9wcy5wcm90b2NvbF92 ZXJzaW9uOw0KKw0KKwlyZXR1cm4gaXNodHBfY2xfY29ubmVjdChjbCk7DQorfQ0KKw0KK3N0YXRp YyBsb25nIGlzaHRwX2NsX2lvY3RsKHN0cnVjdCBmaWxlICpmaWxlLCB1bnNpZ25lZCBpbnQgY21k LA0KKwkJCXVuc2lnbmVkIGxvbmcgZGF0YSkNCit7DQorCXN0cnVjdCBpc2h0cF9jbF9taXNjZGV2 ICppc2h0cF9jbF9taXNjID0gZmlsZS0+cHJpdmF0ZV9kYXRhOw0KKwlzdHJ1Y3QgaXNodHBfY2wg KmNsOw0KKwlzdHJ1Y3QgaXNodHBfZGV2aWNlICpkZXY7DQorCXN0cnVjdCBpc2h0cF9jb25uZWN0 X2NsaWVudF9kYXRhICpjb25uZWN0X2RhdGE7DQorCWNoYXIgZndfc3RhdF9idWZbMjBdOw0KKwl1 bnNpZ25lZCBpbnQgcmluZ19zaXplOw0KKwlpbnQgcmV0ID0gMDsNCisNCisJaWYgKCFjYXBhYmxl KENBUF9TWVNfQURNSU4pKQ0KKwkJcmV0dXJuIC1FUEVSTTsNCisNCisJbXV0ZXhfbG9jaygmaXNo dHBfY2xfbWlzYy0+Y2xfbXV0ZXgpOw0KKw0KKwljbCA9IGlzaHRwX2NsX21pc2MtPmNsOw0KKw0K KwkvKg0KKwnCoCogSVNIRlcgcmVzZXQgd2lsbCBjYXVzZSBjbCBiZSBmcmVlZCBhbmQgcmUtYWxs b2NhdGVkLg0KKwnCoCogU28gbXVzdCBtYWtlIHN1cmUgY2wgaXMgcmUtYWxsb2NhdGVkIHN1Y2Nl c3NmdWxseS4NCisJwqAqLw0KKwlpZiAoIWNsIHx8ICFjbC0+ZGV2KSB7DQorCQltdXRleF91bmxv Y2soJmlzaHRwX2NsX21pc2MtPmNsX211dGV4KTsNCisJCXJldHVybiAtRU5PREVWOw0KKwl9DQor DQorCWRldiA9IGNsLT5kZXY7DQorDQorCXN3aXRjaCAoY21kKSB7DQorCWNhc2UgSU9DVExfSVNI X0hXX1JFU0VUOg0KKwkJcmV0ID0gaXNoX2h3X3Jlc2V0KGRldik7DQorCQlicmVhazsNCisNCisJ Y2FzZSBJT0NUTF9JU0hUUF9TRVRfUlhfRklGT19TSVpFOg0KKwkJcmluZ19zaXplID0gZGF0YTsN CisNCisJCWlmIChyaW5nX3NpemUgPiBDTF9NQVhfUlhfUklOR19TSVpFKSB7DQorCQkJcmV0ID0g LUVJTlZBTDsNCisJCQlicmVhazsNCisJCX0NCisNCisJCWlmIChjbC0+c3RhdGUgIT0gSVNIVFBf Q0xfSU5JVElBTElaSU5HKSB7DQorCQkJcmV0ID0gLUVCVVNZOw0KKwkJCWJyZWFrOw0KKwkJfQ0K Kw0KKwkJY2wtPnJ4X3Jpbmdfc2l6ZSA9IHJpbmdfc2l6ZTsNCisJCWJyZWFrOw0KKw0KKwljYXNl IElPQ1RMX0lTSFRQX1NFVF9UWF9GSUZPX1NJWkU6DQorCQlyaW5nX3NpemUgPSBkYXRhOw0KKw0K KwkJaWYgKHJpbmdfc2l6ZSA+IENMX01BWF9UWF9SSU5HX1NJWkUpIHsNCisJCQlyZXQgPSAtRUlO VkFMOw0KKwkJCWJyZWFrOw0KKwkJfQ0KKw0KKwkJaWYgKGNsLT5zdGF0ZSAhPSBJU0hUUF9DTF9J TklUSUFMSVpJTkcpIHsNCisJCQlyZXQgPSAtRUJVU1k7DQorCQkJYnJlYWs7DQorCQl9DQorDQor CQljbC0+dHhfcmluZ19zaXplID0gcmluZ19zaXplOw0KKwkJYnJlYWs7DQorDQorCWNhc2UgSU9D VExfSVNIX0dFVF9GV19TVEFUVVM6DQorCQlpZiAoIWRhdGEpIHsNCisJCQlyZXQgPSAtRU5PTUVN Ow0KKwkJCWJyZWFrOw0KKwkJfQ0KKw0KKwkJc25wcmludGYoZndfc3RhdF9idWYsIHNpemVvZihm d19zdGF0X2J1ZiksDQorCQkJIiUwOFhcbiIsIGRldi0+b3BzLT5nZXRfZndfc3RhdHVzKGRldikp Ow0KKw0KKwkJaWYgKGNvcHlfdG9fdXNlcigoY2hhciBfX3VzZXIgKilkYXRhLCBmd19zdGF0X2J1 ZiwNCisJCQkJc3RybGVuKGZ3X3N0YXRfYnVmKSkpIHsNCisJCQlyZXQgPSAtRUZBVUxUOw0KKwkJ CWJyZWFrOw0KKwkJfQ0KKw0KKwkJcmV0ID0gc3RybGVuKGZ3X3N0YXRfYnVmKTsNCisJCWJyZWFr Ow0KKw0KKwljYXNlIElPQ1RMX0lTSFRQX0NPTk5FQ1RfQ0xJRU5UOg0KKwkJaWYgKGRldi0+ZGV2 X3N0YXRlICE9IElTSFRQX0RFVl9FTkFCTEVEKSB7DQorCQkJcmV0ID0gLUVOT0RFVjsNCisJCQli cmVhazsNCisJCX0NCisNCisJCWNvbm5lY3RfZGF0YSA9IG1lbWR1cF91c2VyKChjaGFyIF9fdXNl ciAqKWRhdGEsDQorCQkJCQlzaXplb2Yoc3RydWN0IGlzaHRwX2Nvbm5lY3RfY2xpZW50X2RhdGEp KTsNCisJCWlmIChJU19FUlIoY29ubmVjdF9kYXRhKSkgew0KKwkJCXJldCA9IFBUUl9FUlIoY29u bmVjdF9kYXRhKTsNCisJCQlicmVhazsNCisJCX0NCisNCisJCXJldCA9IGlzaHRwX2NsX2lvY3Rs X2Nvbm5lY3RfY2xpZW50KGZpbGUsIGNvbm5lY3RfZGF0YSk7DQorCQlpZiAocmV0KSB7DQorCQkJ a2ZyZWUoY29ubmVjdF9kYXRhKTsNCisJCQlicmVhazsNCisJCX0NCisNCisJCS8qIElmIGFsbCBp cyBvaywgY29weWluZyB0aGUgZGF0YSBiYWNrIHRvIHVzZXIuICovDQorCQlpZiAoY29weV90b191 c2VyKChjaGFyIF9fdXNlciAqKWRhdGEsIGNvbm5lY3RfZGF0YSwNCisJCQkJc2l6ZW9mKHN0cnVj dCBpc2h0cF9jb25uZWN0X2NsaWVudF9kYXRhKSkpDQorCQkJcmV0ID0gLUVGQVVMVDsNCisNCisJ CWtmcmVlKGNvbm5lY3RfZGF0YSk7DQorDQorCQlicmVhazsNCisNCisJZGVmYXVsdDoNCisJCXJl dCA9IC1FSU5WQUw7DQorCQlicmVhazsNCisJfQ0KKw0KKwltdXRleF91bmxvY2soJmlzaHRwX2Ns X21pc2MtPmNsX211dGV4KTsNCisNCisJcmV0dXJuIHJldDsNCit9DQorDQorLyoNCisgKiBGaWxl IG9wZXJhdGlvbnMgc3RydWN0dXJlIHdpbGwgYmUgdXNlZCBmb3IgaXNodHAgY2xpZW50IG1pc2Mg ZGV2aWNlLg0KKyAqLw0KK3N0YXRpYyBjb25zdCBzdHJ1Y3QgZmlsZV9vcGVyYXRpb25zIGlzaHRw X2NsX2ZvcHMgPSB7DQorCS5vd25lciA9IFRISVNfTU9EVUxFLA0KKwkucmVhZCA9IGlzaHRwX2Ns X3JlYWQsDQorCS51bmxvY2tlZF9pb2N0bCA9IGlzaHRwX2NsX2lvY3RsLA0KKwkub3BlbiA9IGlz aHRwX2NsX29wZW4sDQorCS5yZWxlYXNlID0gaXNodHBfY2xfcmVsZWFzZSwNCisJLndyaXRlID0g aXNodHBfY2xfd3JpdGUsDQorCS5sbHNlZWsgPSBub19sbHNlZWsNCit9Ow0KKw0KKy8qKg0KKyAq IGlzaHRwX2NsX2V2ZW50X2NiKCkgLSBJU0hUUCBjbGllbnQgZHJpdmVyIGV2ZW50IGNhbGxiYWNr DQorICogQGNsX2RldmljZToJCUlTSFRQIGNsaWVudCBkZXZpY2UgaW5zdGFuY2UNCisgKg0KKyAq IFRoaXMgZnVuY3Rpb24gZ2V0cyBjYWxsZWQgb24gcmVsYXRlZCBldmVudCByZWNldmllZCBmcm9t IElTSEZXLg0KKyAqIEl0IHdpbGwgcmVtb3ZlIGV2ZW50IGJ1ZmZlciBleGlzdHMgb24gaW5fcHJv Y2VzcyBsaXN0IHRvIHJlbGF0ZWQNCisgKiBjbGllbnQgZGV2aWNlIGFuZCB3YWl0IHVwIGNsaWVu dCBkcml2ZXIgdG8gcHJvY2Vzcy4NCisgKi8NCitzdGF0aWMgdm9pZCBpc2h0cF9jbF9ldmVudF9j YihzdHJ1Y3QgaXNodHBfY2xfZGV2aWNlICpjbF9kZXZpY2UpDQorew0KKwlzdHJ1Y3QgaXNodHBf Y2xfbWlzY2RldiAqaXNodHBfY2xfbWlzYzsNCisJc3RydWN0IGlzaHRwX2NsICpjbDsNCisJc3Ry dWN0IGlzaHRwX2NsX3JiICpyYjsNCisNCisJaXNodHBfY2xfbWlzYyA9IGlzaHRwX2dldF9kcnZk YXRhKGNsX2RldmljZSk7DQorCWlmICghaXNodHBfY2xfbWlzYykNCisJCXJldHVybjsNCisNCisJ bXV0ZXhfbG9jaygmaXNodHBfY2xfbWlzYy0+Y2xfbXV0ZXgpOw0KKw0KKwkvKg0KKwnCoCogSWYg dGhpcyB3YWl0cXVldWUgaXMgYWN0aXZlLCBjbF9tdXRleCBpcyBsb2NrZWQgYnkgcmVhZCgpLCBp dCdzIHNhZmUNCisJwqAqIHRvIGFjY2VzcyBpc2h0cF9jbF9taXNjIGFuZCBjbC4NCisJwqAqLw0K KwlpZiAod2FpdHF1ZXVlX2FjdGl2ZSgmaXNodHBfY2xfbWlzYy0+cmVhZF93YWl0KSkgew0KKw0K KwkJLyoNCisJCcKgKiBJZiBhbHJlYWR5IGhhcyByZWFkX3JiLCB3YWtlIHVwIHdhaXRxdWV1ZSBk aXJlY3RseS4NCisJCcKgKi8NCisJCWlmIChpc2h0cF9jbF9taXNjLT5yZWFkX3JiKSB7DQorCQkJ bXV0ZXhfdW5sb2NrKCZpc2h0cF9jbF9taXNjLT5jbF9tdXRleCk7DQorCQkJd2FrZV91cF9pbnRl cnJ1cHRpYmxlKCZpc2h0cF9jbF9taXNjLT5yZWFkX3dhaXQpOw0KKwkJCXJldHVybjsNCisJCX0N CisNCisJCWNsID0gaXNodHBfY2xfbWlzYy0+Y2w7DQorDQorCQlyYiA9IGlzaHRwX2NsX3J4X2dl dF9yYihjbCk7DQorCQlpZiAocmIpDQorCQkJaXNodHBfY2xfbWlzYy0+cmVhZF9yYiA9IHJiOw0K Kw0KKwkJd2FrZV91cF9pbnRlcnJ1cHRpYmxlKCZpc2h0cF9jbF9taXNjLT5yZWFkX3dhaXQpOw0K Kwl9DQorDQorCW11dGV4X3VubG9jaygmaXNodHBfY2xfbWlzYy0+Y2xfbXV0ZXgpOw0KK30NCisN CisvKioNCisgKiBpc2h0cF9jbF9yZXNldF9oYW5kbGVyKCkgLSBJU0hUUCBjbGllbnQgZHJpdmVy IHJlc2V0IHdvcmsgaGFuZGxlcg0KKyAqIEB3b3JrOgkJd29yayBzdHJ1Y3QNCisgKg0KKyAqIFRo aXMgZnVuY3Rpb24gZ2V0cyBjYWxsZWQgb24gcmVzZXQgd29ya3F1ZXVlIHNjaGVkdWxlZCB3aGVu IElTSEZXDQorICogcmVzZXQgaGFwcGVuLiBJdCB3aWxsIGRpc2Nvbm5lY3QgYW5kIHJlbW92ZSBj dXJyZW50IGlzaHRwX2NsLCB0aGVuDQorICogY3JlYXRlIGEgbmV3IGlzaHRwX2NsIGFuZCByZS1j b25uZWN0IGFnYWluLg0KKyAqLw0KK3N0YXRpYyB2b2lkIGlzaHRwX2NsX3Jlc2V0X2hhbmRsZXIo c3RydWN0IHdvcmtfc3RydWN0ICp3b3JrKQ0KK3sNCisJc3RydWN0IGlzaHRwX2NsX21pc2NkZXYg KmlzaHRwX2NsX21pc2M7DQorCXN0cnVjdCBpc2h0cF9kZXZpY2UgKmRldjsNCisJc3RydWN0IGlz aHRwX2NsX2RldmljZSAqY2xfZGV2aWNlOw0KKwlzdHJ1Y3QgaXNodHBfY2wgKmNsOw0KKwlzdHJ1 Y3QgaXNodHBfZndfY2xpZW50ICpmd19jbGllbnQ7DQorCWludCByZXQgPSAwOw0KKw0KKwlpc2h0 cF9jbF9taXNjID0gY29udGFpbmVyX29mKHdvcmssDQorCQkJc3RydWN0IGlzaHRwX2NsX21pc2Nk ZXYsIHJlc2V0X3dvcmspOw0KKw0KKwlkZXYgPSBpc2h0cF9jbF9taXNjLT5jbF9kZXZpY2UtPmlz aHRwX2RldjsNCisJaWYgKCFkZXYpIHsNCisJCWRldl9lcnIoJmlzaHRwX2NsX21pc2MtPmNsX2Rl dmljZS0+ZGV2LA0KKwkJCSJUaGlzIGNsX2RldmljZSBub3QgbGluayB0byBpc2h0cF9kZXZcbiIp Ow0KKwkJcmV0dXJuOw0KKwl9DQorDQorCWNsX2RldmljZSA9IGlzaHRwX2NsX21pc2MtPmNsX2Rl dmljZTsNCisNCisJbXV0ZXhfbG9jaygmaXNodHBfY2xfbWlzYy0+Y2xfbXV0ZXgpOw0KKw0KKwkv KiBXYWtlIHVwIGZyb20gd2FpdGluZyBpZiBhbnlvbmUgd2FpdCBvbiBpdCAqLw0KKwl3YWtlX3Vw X2ludGVycnVwdGlibGUoJmlzaHRwX2NsX21pc2MtPnJlYWRfd2FpdCk7DQorDQorCWNsID0gaXNo dHBfY2xfbWlzYy0+Y2w7DQorCWlmIChjbCkgew0KKwkJaXNodHBfY2xfZmx1c2hfcXVldWVzKGNs KTsNCisJCWlzaHRwX2NsX2ZyZWUoY2wpOw0KKw0KKwkJY2wgPSBOVUxMOw0KKw0KKwkJY2wgPSBp c2h0cF9jbF9hbGxvY2F0ZShkZXYpOw0KKwkJaWYgKCFjbCkgew0KKwkJCWRldl9lcnIoJmlzaHRw X2NsX21pc2MtPmNsX2RldmljZS0+ZGV2LA0KKwkJCQkiQWxsb2NhdGUgaXNodHBfY2wgZmFpbGVk XG4iKTsNCisJCQlyZXQgPSAtRU5PTUVNOw0KKwkJCWdvdG8gb3V0X3VubG9jazsNCisJCX0NCisN CisJCWlmIChkZXYtPmRldl9zdGF0ZSAhPSBJU0hUUF9ERVZfRU5BQkxFRCkgew0KKwkJCWRldl9l cnIoJmlzaHRwX2NsX21pc2MtPmNsX2RldmljZS0+ZGV2LA0KKwkJCQkiSXNodHAgZGV2IGlzbid0 IGVuYWJsZWRcbiIpOw0KKwkJCXJldCA9IC1FTk9ERVY7DQorCQkJZ290byBvdXRfZnJlZTsNCisJ CX0NCisNCisJCXJldCA9IGlzaHRwX2NsX2xpbmsoY2wsIElTSFRQX0hPU1RfQ0xJRU5UX0lEX0FO WSk7DQorCQlpZiAocmV0KSB7DQorCQkJZGV2X2VycigmaXNodHBfY2xfbWlzYy0+Y2xfZGV2aWNl LT5kZXYsDQorCQkJCSJDYW4gbm90IGxpbmsgdG8gaXNodHBcbiIpOw0KKwkJCWdvdG8gb3V0X2Zy ZWU7DQorCQl9DQorDQorCQlmd19jbGllbnQgPSBpc2h0cF9md19jbF9nZXRfY2xpZW50KGRldiwN CisJCQkJJmNsX2RldmljZS0+ZndfY2xpZW50LT5wcm9wcy5wcm90b2NvbF9uYW1lKTsNCisJCWlm ICghZndfY2xpZW50KSB7DQorCQkJZGV2X2VycigmaXNodHBfY2xfbWlzYy0+Y2xfZGV2aWNlLT5k ZXYsDQorCQkJCSJEb24ndCBmaW5kIHJlbGF0ZWQgZncgY2xpZW50XG4iKTsNCisJCQlyZXQgPSAt RU5PRU5UOw0KKwkJCWdvdG8gb3V0X2ZyZWU7DQorCQl9DQorDQorCQljbC0+ZndfY2xpZW50X2lk ID0gZndfY2xpZW50LT5jbGllbnRfaWQ7DQorCQljbC0+c3RhdGUgPSBJU0hUUF9DTF9DT05ORUNU SU5HOw0KKw0KKwkJcmV0ID0gaXNodHBfY2xfY29ubmVjdChjbCk7DQorCQlpZiAocmV0KSB7DQor CQkJZGV2X2VycigmaXNodHBfY2xfbWlzYy0+Y2xfZGV2aWNlLT5kZXYsDQorCQkJCSJDb25uZWN0 IHRvIGZ3IGZhaWxlZFxuIik7DQorCQkJZ290byBvdXRfZnJlZTsNCisJCX0NCisNCisJCWlzaHRw X2NsX21pc2MtPmNsID0gY2w7DQorCX0NCisNCisJLyogQWZ0ZXIgcmVzZXQsIG11c3QgcmVnaXN0 ZXIgZXZlbnQgY2FsbGJhY2sgYWdhaW4gKi8NCisJaXNodHBfcmVnaXN0ZXJfZXZlbnRfY2IoY2xf ZGV2aWNlLCBpc2h0cF9jbF9ldmVudF9jYik7DQorDQorb3V0X2ZyZWU6DQorCWlmIChyZXQpIHsN CisJCWlzaHRwX2NsX2ZyZWUoY2wpOw0KKwkJaXNodHBfY2xfbWlzYy0+Y2wgPSBOVUxMOw0KKw0K KwkJZGV2X2VycigmaXNodHBfY2xfbWlzYy0+Y2xfZGV2aWNlLT5kZXYsICJSZXNldCBmYWlsZWRc biIpOw0KKwl9DQorDQorb3V0X3VubG9jazoNCisJbXV0ZXhfdW5sb2NrKCZpc2h0cF9jbF9taXNj LT5jbF9tdXRleCk7DQorfQ0KKw0KKy8qKg0KKyAqIGlzaHRwX2NsX3Byb2JlKCkgLSBJU0hUUCBj bGllbnQgZHJpdmVyIHByb2JlDQorICogQGNsX2RldmljZToJCUlTSFRQIGNsaWVudCBkZXZpY2Ug aW5zdGFuY2UNCisgKg0KKyAqIFRoaXMgZnVuY3Rpb24gZ2V0cyBjYWxsZWQgb24gZGV2aWNlIGNy ZWF0ZSBvbiBJU0hUUCBidXMNCisgKg0KKyAqIFJldHVybjogMCBvbiBzdWNjZXNzLCBub24gemVy byBvbiBlcnJvcg0KKyAqLw0KK3N0YXRpYyBpbnQgaXNodHBfY2xfcHJvYmUoc3RydWN0IGlzaHRw X2NsX2RldmljZSAqY2xfZGV2aWNlKQ0KK3sNCisJc3RydWN0IGlzaHRwX2NsX21pc2NkZXYgKmlz aHRwX2NsX21pc2M7DQorCWludCByZXQ7DQorDQorCWlmICghY2xfZGV2aWNlKQ0KKwkJcmV0dXJu IC1FTk9ERVY7DQorDQorCWlzaHRwX2NsX21pc2MgPSBremFsbG9jKHNpemVvZihzdHJ1Y3QgaXNo dHBfY2xfbWlzY2RldiksDQorCQkJCUdGUF9LRVJORUwpOw0KKwlpZiAoIWlzaHRwX2NsX21pc2Mp DQorCQlyZXR1cm4gLUVOT01FTTsNCisNCisJaWYgKHV1aWRfbGVfY21wKGlzaHRwX3NtaGlfZ3Vp ZCwNCisJCQljbF9kZXZpY2UtPmZ3X2NsaWVudC0+cHJvcHMucHJvdG9jb2xfbmFtZSkgPT0gMCkg ew0KKwkJaXNodHBfY2xfbWlzYy0+Y2xfbWlzY2Rldi5uYW1lID0gImlzaC1zbWhpIjsNCisJfSBl bHNlIGlmICh1dWlkX2xlX2NtcChpc2h0cF90cmFjZV9ndWlkLA0KKwkJCWNsX2RldmljZS0+Zndf Y2xpZW50LT5wcm9wcy5wcm90b2NvbF9uYW1lKSA9PSAwKSB7DQorCQlpc2h0cF9jbF9taXNjLT5j bF9taXNjZGV2Lm5hbWUgPSAiaXNoLXRyYWNlIjsNCisJfSBlbHNlIGlmICh1dWlkX2xlX2NtcChp c2h0cF90cmFjZWNvbmZpZ19ndWlkLA0KKwkJCWNsX2RldmljZS0+ZndfY2xpZW50LT5wcm9wcy5w cm90b2NvbF9uYW1lKSA9PSAwKSB7DQorCQlpc2h0cF9jbF9taXNjLT5jbF9taXNjZGV2Lm5hbWUg PSAiaXNoLXRyYWNlYyI7DQorCX0gZWxzZSBpZiAodXVpZF9sZV9jbXAoaXNodHBfbG9hZGVyX2d1 aWQsDQorCQkJY2xfZGV2aWNlLT5md19jbGllbnQtPnByb3BzLnByb3RvY29sX25hbWUpID09IDAp IHsNCisJCWlzaHRwX2NsX21pc2MtPmNsX21pc2NkZXYubmFtZSA9ICJpc2gtbG9hZGVyIjsNCisJ fSBlbHNlIHsNCisJCWRldl9lcnIoJmNsX2RldmljZS0+ZGV2LCAiTm90IHN1cHBvcnRlZCBjbGll bnRcbiIpOw0KKwkJcmV0ID0gLUVOT0RFVjsNCisJCWdvdG8gcmVsZWFzZV9tZW07DQorCX0NCisN CisJaXNodHBfY2xfbWlzYy0+Y2xfbWlzY2Rldi5wYXJlbnQgPSAmY2xfZGV2aWNlLT5kZXY7DQor CWlzaHRwX2NsX21pc2MtPmNsX21pc2NkZXYuZm9wcyA9ICZpc2h0cF9jbF9mb3BzOw0KKwlpc2h0 cF9jbF9taXNjLT5jbF9taXNjZGV2Lm1pbm9yID0gTUlTQ19EWU5BTUlDX01JTk9SLA0KKw0KKwly ZXQgPSBtaXNjX3JlZ2lzdGVyKCZpc2h0cF9jbF9taXNjLT5jbF9taXNjZGV2KTsNCisJaWYgKHJl dCkgew0KKwkJZGV2X2VycigmY2xfZGV2aWNlLT5kZXYsICJtaXNjIGRldmljZSByZWdpc3RlciBm YWlsZWRcbiIpOw0KKwkJZ290byByZWxlYXNlX21lbTsNCisJfQ0KKw0KKwlpc2h0cF9jbF9taXNj LT5jbF9kZXZpY2UgPSBjbF9kZXZpY2U7DQorDQorCWluaXRfd2FpdHF1ZXVlX2hlYWQoJmlzaHRw X2NsX21pc2MtPnJlYWRfd2FpdCk7DQorDQorCWlzaHRwX3NldF9kcnZkYXRhKGNsX2RldmljZSwg aXNodHBfY2xfbWlzYyk7DQorDQorCWlzaHRwX2dldF9kZXZpY2UoY2xfZGV2aWNlKTsNCisNCisJ bXV0ZXhfaW5pdCgmaXNodHBfY2xfbWlzYy0+Y2xfbXV0ZXgpOw0KKw0KKwlJTklUX1dPUksoJmlz aHRwX2NsX21pc2MtPnJlc2V0X3dvcmssIGlzaHRwX2NsX3Jlc2V0X2hhbmRsZXIpOw0KKw0KKwkv KiBSZWdpc3RlciBldmVudCBjYWxsYmFjayAqLw0KKwlpc2h0cF9yZWdpc3Rlcl9ldmVudF9jYihj bF9kZXZpY2UsIGlzaHRwX2NsX2V2ZW50X2NiKTsNCisNCisJcmV0dXJuIDA7DQorDQorcmVsZWFz ZV9tZW06DQorCWtmcmVlKGlzaHRwX2NsX21pc2MpOw0KKw0KKwlyZXR1cm4gcmV0Ow0KK30NCisN CisvKioNCisgKiBpc2h0cF9jbF9yZW1vdmUoKSAtIElTSFRQIGNsaWVudCBkcml2ZXIgcmVtb3Zl DQorICogQGNsX2RldmljZToJCUlTSFRQIGNsaWVudCBkZXZpY2UgaW5zdGFuY2UNCisgKg0KKyAq IFRoaXMgZnVuY3Rpb24gZ2V0cyBjYWxsZWQgb24gZGV2aWNlIHJlbW92ZSBvbiBJU0hUUCBidXMN CisgKg0KKyAqIFJldHVybjogMA0KKyAqLw0KK3N0YXRpYyBpbnQgaXNodHBfY2xfcmVtb3ZlKHN0 cnVjdCBpc2h0cF9jbF9kZXZpY2UgKmNsX2RldmljZSkNCit7DQorCXN0cnVjdCBpc2h0cF9jbF9t aXNjZGV2ICppc2h0cF9jbF9taXNjOw0KKwlzdHJ1Y3QgaXNodHBfY2wgKmNsOw0KKw0KKwlpc2h0 cF9jbF9taXNjID0gaXNodHBfZ2V0X2RydmRhdGEoY2xfZGV2aWNlKTsNCisJaWYgKCFpc2h0cF9j bF9taXNjKQ0KKwkJcmV0dXJuIC1FTk9ERVY7DQorDQorCWlmICghaXNodHBfY2xfbWlzYy0+Y2xf bWlzY2Rldi5wYXJlbnQpDQorCQlyZXR1cm4gLUVOT0RFVjsNCisNCisJLyogV2FrZSB1cCBmcm9t IHdhaXRpbmcgaWYgYW55b25lIHdhaXQgb24gaXQgKi8NCisJd2FrZV91cF9pbnRlcnJ1cHRpYmxl KCZpc2h0cF9jbF9taXNjLT5yZWFkX3dhaXQpOw0KKw0KKwltdXRleF9sb2NrKCZpc2h0cF9jbF9t aXNjLT5jbF9tdXRleCk7DQorDQorCWNsID0gaXNodHBfY2xfbWlzYy0+Y2w7DQorCWlmIChjbCkg ew0KKwkJY2wtPnN0YXRlID0gSVNIVFBfQ0xfRElTQ09OTkVDVElORzsNCisJCWlzaHRwX2NsX2Rp c2Nvbm5lY3QoY2wpOw0KKwkJaXNodHBfY2xfdW5saW5rKGNsKTsNCisJCWlzaHRwX2NsX2ZsdXNo X3F1ZXVlcyhjbCk7DQorCQlpc2h0cF9jbF9mcmVlKGNsKTsNCisJCWlzaHRwX2NsX21pc2MtPmNs ID0gTlVMTDsNCisJfQ0KKw0KKwltdXRleF91bmxvY2soJmlzaHRwX2NsX21pc2MtPmNsX211dGV4 KTsNCisNCisJbXV0ZXhfZGVzdHJveSgmaXNodHBfY2xfbWlzYy0+Y2xfbXV0ZXgpOw0KKw0KKwlt aXNjX2RlcmVnaXN0ZXIoJmlzaHRwX2NsX21pc2MtPmNsX21pc2NkZXYpOw0KKw0KKwlpc2h0cF9w dXRfZGV2aWNlKGNsX2RldmljZSk7DQorDQorCWtmcmVlKGlzaHRwX2NsX21pc2MpOw0KKw0KKwly ZXR1cm4gMDsNCit9DQorDQorLyoqDQorICogaXNodHBfY2xfcmVzZXQoKSAtIElTSFRQIGNsaWVu dCBkcml2ZXIgcmVzZXQNCisgKiBAY2xfZGV2aWNlOgkJSVNIVFAgY2xpZW50IGRldmljZSBpbnN0 YW5jZQ0KKyAqDQorICogVGhpcyBmdW5jdGlvbiBnZXRzIGNhbGxlZCBvbiBkZXZpY2UgcmVzZXQg b24gSVNIVFAgYnVzLg0KKyAqIElmIGNsaWVudCBpcyBjb25uZWN0ZWQsIG5lZWRzIHRvIGRpc2Nv bm5lY3QgY2xpZW50IGFuZA0KKyAqIHJlY29ubmVjdCBhZ2Fpbi4NCisgKg0KKyAqIFJldHVybjog MA0KKyAqLw0KK3N0YXRpYyBpbnQgaXNodHBfY2xfcmVzZXQoc3RydWN0IGlzaHRwX2NsX2Rldmlj ZSAqY2xfZGV2aWNlKQ0KK3sNCisJc3RydWN0IGlzaHRwX2NsX21pc2NkZXYgKmlzaHRwX2NsX21p c2M7DQorDQorCWlzaHRwX2NsX21pc2MgPSBpc2h0cF9nZXRfZHJ2ZGF0YShjbF9kZXZpY2UpOw0K KwlpZiAoIWlzaHRwX2NsX21pc2MpIHsNCisJCWRldl9lcnIoJmNsX2RldmljZS0+ZGV2LCAiQ2xp ZW50IGRyaXZlciBub3QgcmVhZHkgeWV0XG4iKTsNCisJCXJldHVybiAtRU5PREVWOw0KKwl9DQor DQorCXNjaGVkdWxlX3dvcmsoJmlzaHRwX2NsX21pc2MtPnJlc2V0X3dvcmspOw0KKw0KKwlyZXR1 cm4gMDsNCit9DQorDQorc3RhdGljIHN0cnVjdCBpc2h0cF9jbF9kcml2ZXIgaXNodHBfY2xfZHJp dmVyID0gew0KKwkubmFtZSA9ICJpc2h0cC1jbGllbnQiLA0KKwkucHJvYmUgPSBpc2h0cF9jbF9w cm9iZSwNCisJLnJlbW92ZSA9IGlzaHRwX2NsX3JlbW92ZSwNCisJLnJlc2V0ID0gaXNodHBfY2xf cmVzZXQsDQorfTsNCisNCitzdGF0aWMgaW50IF9faW5pdCBpc2h0cF9jbGllbnRfaW5pdCh2b2lk KQ0KK3sNCisJLyogUmVnaXN0ZXIgSVNIVFAgY2xpZW50IGRldmljZSBkcml2ZXIgd2l0aCBJU0hU UCBCdXMgKi8NCisJcmV0dXJuIGlzaHRwX2NsX2RyaXZlcl9yZWdpc3RlcigmaXNodHBfY2xfZHJp dmVyKTsNCit9DQorDQorc3RhdGljIHZvaWQgX19leGl0IGlzaHRwX2NsaWVudF9leGl0KHZvaWQp DQorew0KKwlpc2h0cF9jbF9kcml2ZXJfdW5yZWdpc3RlcigmaXNodHBfY2xfZHJpdmVyKTsNCit9 DQorDQorLyogVG8gbWFrZSBzdXJlIElTSFRQIGJ1cyBkcml2ZXIgbG9hZGVkIGZpcnN0ICovDQor bGF0ZV9pbml0Y2FsbChpc2h0cF9jbGllbnRfaW5pdCk7DQorbW9kdWxlX2V4aXQoaXNodHBfY2xp ZW50X2V4aXQpOw0KKw0KK01PRFVMRV9ERVNDUklQVElPTigiSVNIIElTSFRQIGNsaWVudCBkcml2 ZXIiKTsNCitNT0RVTEVfQVVUSE9SKCJFdmVuIFh1IDxldmVuLnh1QGludGVsLmNvbT4iKTsNCitN T0RVTEVfTElDRU5TRSgiR1BMIik7DQorTU9EVUxFX0FMSUFTKCJpc2h0cDoqIik7DQpkaWZmIC0t Z2l0IGEvaW5jbHVkZS91YXBpL2xpbnV4L2ludGVsLWlzaHRwLWNsaWVudHMuaCBiL2luY2x1ZGUv dWFwaS9saW51eC9pbnRlbC1pc2h0cC1jbGllbnRzLmgNCm5ldyBmaWxlIG1vZGUgMTAwNjQ0DQpp bmRleCAwMDAwMDAwLi43OTI1MDBhDQotLS0gL2Rldi9udWxsDQorKysgYi9pbmNsdWRlL3VhcGkv bGludXgvaW50ZWwtaXNodHAtY2xpZW50cy5oDQpAQCAtMCwwICsxLDczIEBADQorLyoNCisgKiBJ bnRlbCBJU0hUUCBDbGllbnRzIEludGVyZmFjZSBIZWFkZXINCisgKg0KKyAqIENvcHlyaWdodCAo YykgMjAxNiwgSW50ZWwgQ29ycG9yYXRpb24uDQorICoNCisgKiBUaGlzIHByb2dyYW0gaXMgZnJl ZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdA0KKyAq IHVuZGVyIHRoZSB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGlj IExpY2Vuc2UsDQorICogdmVyc2lvbiAyLCBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdh cmUgRm91bmRhdGlvbi4NCisgKg0KKyAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0 aGUgaG9wZSBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0IFdJVEhPVVQNCisgKiBBTlkgV0FSUkFOVFk7 IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFkgb3IN CisgKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgR2VuZXJh bCBQdWJsaWMgTGljZW5zZSBmb3INCisgKiBtb3JlIGRldGFpbHMuDQorICoNCisgKi8NCisNCisj aWZuZGVmIF9JTlRFTF9JU0hUUF9DTElFTlRTX0gNCisjZGVmaW5lIF9JTlRFTF9JU0hUUF9DTElF TlRTX0gNCisNCisjaW5jbHVkZSA8bGludXgvaW9jdGwuaD4NCisjaW5jbHVkZSA8bGludXgvbWlz Y2RldmljZS5oPg0KKyNpbmNsdWRlIDxsaW51eC9tdXRleC5oPg0KKyNpbmNsdWRlIDxsaW51eC90 eXBlcy5oPg0KKyNpbmNsdWRlIDxsaW51eC91dWlkLmg+DQorDQorLyoNCisgKiBUaGlzIElPQ1RM IGlzIHVzZWQgdG8gYXNzb2NpYXRlIHRoZSBjdXJyZW50IGZpbGUgZGVzY3JpcHRvciB3aXRoIGEN CisgKiBGVyBDbGllbnQgKGdpdmVuIGJ5IFVVSUQpLiBUaGlzIG9wZW5zIGEgY29tbXVuaWNhdGlv biBjaGFubmVsDQorICogYmV0d2VlbiBhIGhvc3QgY2xpZW50IGFuZCBhIEZXIGNsaWVudC4gRnJv bSB0aGlzIHBvaW50IGV2ZXJ5IHJlYWQgYW5kIHdyaXRlDQorICogd2lsbCBjb21tdW5pY2F0ZSB3 aXRoIHRoZSBhc3NvY2lhdGVkIEZXIGNsaWVudC4NCisgKiBPbmx5IGluIGNsb3NlKCkgKGZpbGVf b3BlcmF0aW9uIHJlbGVhc2UoKSkgdGhlIGNvbW11bmljYXRpb24gYmV0d2Vlbg0KKyAqIHRoZSBj bGllbnRzIGlzIGRpc2Nvbm5lY3RlZA0KKyAqDQorICogVGhlIElPQ1RMIGFyZ3VtZW50IGlzIGEg c3RydWN0IHdpdGggYSB1bmlvbiB0aGF0IGNvbnRhaW5zDQorICogdGhlIGlucHV0IHBhcmFtZXRl ciBhbmQgdGhlIG91dHB1dCBwYXJhbWV0ZXIgZm9yIHRoaXMgSU9DVEwuDQorICoNCisgKiBUaGUg aW5wdXQgcGFyYW1ldGVyIGlzIFVVSUQgb2YgdGhlIEZXIENsaWVudC4NCisgKiBUaGUgb3V0cHV0 IHBhcmFtZXRlciBpcyB0aGUgcHJvcGVydGllcyBvZiB0aGUgRlcgY2xpZW50DQorICogKEZXIHBy b3RvY29sIHZlcnNpb24gYW5kIG1heCBtZXNzYWdlIHNpemUpLg0KKyAqDQorICovDQorI2RlZmlu ZSBJT0NUTF9JU0hUUF9DT05ORUNUX0NMSUVOVAlfSU9XUignSCcsIDB4ODEsCVwNCisJCQkJc3Ry dWN0IGlzaHRwX2Nvbm5lY3RfY2xpZW50X2RhdGEpDQorDQorLyogQ29uZmlndXJhdGlvbjogc2V0 IG51bWJlciBvZiBSeC9UeCBidWZmZXJzLiBNdXN0IGJlIHVzZWQgYmVmb3JlIGNvbm5lY3Rpb24g Ki8NCisjZGVmaW5lIElPQ1RMX0lTSFRQX1NFVF9SWF9GSUZPX1NJWkUJX0lPV1IoJ0gnLCAweDgy LCBsb25nKQ0KKyNkZWZpbmUgSU9DVExfSVNIVFBfU0VUX1RYX0ZJRk9fU0laRQlfSU9XUignSCcs IDB4ODMsIGxvbmcpDQorDQorLyogR2V0IEZXIHN0YXR1cyAqLw0KKyNkZWZpbmUgSU9DVExfSVNI X0dFVF9GV19TVEFUVVMJX0lPKCdIJywgMHg4NCkNCisNCisjZGVmaW5lIElPQ1RMX0lTSF9IV19S RVNFVAlfSU8oJ0gnLCAweDg1KQ0KKw0KKy8qDQorICogSW50ZWwgSVNIVFAgY2xpZW50IGluZm9y bWF0aW9uIHN0cnVjdA0KKyAqLw0KK3N0cnVjdCBpc2h0cF9jbGllbnQgew0KKwlfX3UzMiBtYXhf bXNnX2xlbmd0aDsNCisJX191OCBwcm90b2NvbF92ZXJzaW9uOw0KKwlfX3U4IHJlc2VydmVkWzNd Ow0KK307DQorDQorLyoNCisgKiBJT0NUTCBDb25uZWN0IGNsaWVudCBkYXRhIHN0cnVjdHVyZQ0K KyAqLw0KK3N0cnVjdCBpc2h0cF9jb25uZWN0X2NsaWVudF9kYXRhIHsNCisJdW5pb24gew0KKwkJ dXVpZF9sZQkJCWluX2NsaWVudF91dWlkOw0KKwkJc3RydWN0IGlzaHRwX2NsaWVudMKgCW91dF9j bGllbnRfcHJvcGVydGllczsNCisJfTsNCit9Ow0KKw0KKyNlbmRpZiAvKiBfSU5URUxfSVNIVFBf Q0xJRU5UU19IICovDQotLcKgDQoyLjcuNA==